source: trunk/src/gui/kernel/qt_cocoa_helpers_mac.mm@ 668

Last change on this file since 668 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 47.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/****************************************************************************
43**
44** Copyright (c) 2007-2008, Apple, Inc.
45**
46** All rights reserved.
47**
48** Redistribution and use in source and binary forms, with or without
49** modification, are permitted provided that the following conditions are met:
50**
51** * Redistributions of source code must retain the above copyright notice,
52** this list of conditions and the following disclaimer.
53**
54** * Redistributions in binary form must reproduce the above copyright notice,
55** this list of conditions and the following disclaimer in the documentation
56** and/or other materials provided with the distribution.
57**
58** * Neither the name of Apple, Inc. nor the names of its contributors
59** may be used to endorse or promote products derived from this software
60** without specific prior written permission.
61**
62** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
63** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
64** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
65** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
66** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
67** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
68** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
69** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
70** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
71** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
72** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73**
74****************************************************************************/
75
76#include <private/qcore_mac_p.h>
77#include <qaction.h>
78#include <qwidget.h>
79#include <qdesktopwidget.h>
80#include <qevent.h>
81#include <qpixmapcache.h>
82#include <private/qevent_p.h>
83#include <private/qt_cocoa_helpers_mac_p.h>
84#include <private/qt_mac_p.h>
85#include <private/qapplication_p.h>
86#include <private/qcocoawindow_mac_p.h>
87#include <private/qcocoaview_mac_p.h>
88#include <private/qkeymapper_p.h>
89#include <private/qwidget_p.h>
90
91QT_BEGIN_NAMESPACE
92
93Q_GLOBAL_STATIC(QMacWindowFader, macwindowFader);
94
95QMacWindowFader::QMacWindowFader()
96 : m_duration(0.250)
97{
98}
99
100QMacWindowFader *QMacWindowFader::currentFader()
101{
102 return macwindowFader();
103}
104
105void QMacWindowFader::registerWindowToFade(QWidget *window)
106{
107 m_windowsToFade.append(window);
108}
109
110void QMacWindowFader::performFade()
111{
112 const QWidgetList myWidgetsToFade = m_windowsToFade;
113 const int widgetCount = myWidgetsToFade.count();
114#if QT_MAC_USE_COCOA
115 QMacCocoaAutoReleasePool pool;
116 [NSAnimationContext beginGrouping];
117 [[NSAnimationContext currentContext] setDuration:NSTimeInterval(m_duration)];
118#endif
119
120 for (int i = 0; i < widgetCount; ++i) {
121 QWidget *widget = m_windowsToFade.at(i);
122 OSWindowRef window = qt_mac_window_for(widget);
123#if QT_MAC_USE_COCOA
124 [[window animator] setAlphaValue:0.0];
125 QTimer::singleShot(qRound(m_duration * 1000), widget, SLOT(hide()));
126#else
127 TransitionWindowOptions options = {0, m_duration, 0, 0};
128 TransitionWindowWithOptions(window, kWindowFadeTransitionEffect, kWindowHideTransitionAction,
129 0, 1, &options);
130#endif
131 }
132#if QT_MAC_USE_COCOA
133 [NSAnimationContext endGrouping];
134#endif
135 m_duration = 0.250;
136 m_windowsToFade.clear();
137}
138
139extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
140extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
141extern QWidget * mac_mouse_grabber;
142extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
143
144void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
145{
146 OSWindowRef wnd = static_cast<OSWindowRef>(window);
147 if (wnd) {
148 QWidget *widget;
149#if QT_MAC_USE_COCOA
150 widget = [wnd QT_MANGLE_NAMESPACE(qt_qwidget)];
151#else
152 const UInt32 kWidgetCreatorQt = kEventClassQt;
153 enum {
154 kWidgetPropertyQWidget = 'QWId' //QWidget *
155 };
156 if (GetWindowProperty(static_cast<WindowRef>(window), kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(widget), 0, &widget) != noErr)
157 widget = 0;
158#endif
159 if (widget) {
160 QMacWindowFader::currentFader()->setFadeDuration(durationSeconds);
161 QMacWindowFader::currentFader()->registerWindowToFade(widget);
162 QMacWindowFader::currentFader()->performFade();
163 }
164 }
165}
166
167bool macWindowIsTextured( void * /*OSWindowRef*/ window )
168{
169 OSWindowRef wnd = static_cast<OSWindowRef>(window);
170#if QT_MAC_USE_COCOA
171 return ( [wnd styleMask] & NSTexturedBackgroundWindowMask ) ? true : false;
172#else
173 WindowAttributes currentAttributes;
174 GetWindowAttributes(wnd, &currentAttributes);
175 return (currentAttributes & kWindowMetalAttribute) ? true : false;
176#endif
177}
178
179void macWindowToolbarShow(const QWidget *widget, bool show )
180{
181 OSWindowRef wnd = qt_mac_window_for(widget);
182#if QT_MAC_USE_COCOA
183 if (NSToolbar *toolbar = [wnd toolbar]) {
184 QMacCocoaAutoReleasePool pool;
185 if (show != [toolbar isVisible]) {
186 [toolbar setVisible:show];
187 } else {
188 // The toolbar may be in sync, but we are not, update our framestrut.
189 qt_widget_private(const_cast<QWidget *>(widget))->updateFrameStrut();
190 }
191 }
192#else
193 ShowHideWindowToolbar(wnd, show, false);
194#endif
195}
196
197
198void macWindowToolbarSet( void * /*OSWindowRef*/ window, void *toolbarRef )
199{
200 OSWindowRef wnd = static_cast<OSWindowRef>(window);
201#if QT_MAC_USE_COCOA
202 [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)];
203#else
204 SetWindowToolbar(wnd, static_cast<HIToolbarRef>(toolbarRef));
205#endif
206}
207
208bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window )
209{
210 OSWindowRef wnd = static_cast<OSWindowRef>(window);
211#if QT_MAC_USE_COCOA
212 if (NSToolbar *toolbar = [wnd toolbar])
213 return [toolbar isVisible];
214 return false;
215#else
216 return IsWindowToolbarVisible(wnd);
217#endif
218}
219
220void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow )
221{
222 OSWindowRef wnd = static_cast<OSWindowRef>(window);
223#if QT_MAC_USE_COCOA
224 [wnd setHasShadow:BOOL(hasShadow)];
225#else
226 if (hasShadow)
227 ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute);
228 else
229 ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0);
230#endif
231}
232
233void macWindowFlush(void * /*OSWindowRef*/ window)
234{
235 OSWindowRef wnd = static_cast<OSWindowRef>(window);
236#if QT_MAC_USE_COCOA
237 [wnd flushWindowIfNeeded];
238#else
239 HIWindowFlush(wnd);
240#endif
241}
242
243void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm)
244{
245 QMacCocoaAutoReleasePool pool;
246 if(QCFType<CGImageRef> image = pm.toMacCGImageRef()) {
247 NSImage *newImage = 0;
248 NSRect imageRect = NSMakeRect(0.0, 0.0, CGImageGetWidth(image), CGImageGetHeight(image));
249 newImage = [[NSImage alloc] initWithSize:imageRect.size];
250 [newImage lockFocus];
251 {
252 CGContextRef imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
253 CGContextDrawImage(imageContext, *(CGRect*)&imageRect, image);
254 }
255 [newImage unlockFocus];
256 return newImage;
257 }
258 return 0;
259}
260
261void qt_mac_update_mouseTracking(QWidget *widget)
262{
263#ifdef QT_MAC_USE_COCOA
264 [qt_mac_nativeview_for(widget) updateTrackingAreas];
265#else
266 Q_UNUSED(widget);
267#endif
268}
269
270OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
271{
272 // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev)
273 OSStatus err = noErr;
274
275 require_action(inContext != NULL, InvalidContext, err = paramErr);
276 require_action(inBounds != NULL, InvalidBounds, err = paramErr);
277 require_action(inImage != NULL, InvalidImage, err = paramErr);
278
279 CGContextSaveGState( inContext );
280 CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds));
281 CGContextScaleCTM(inContext, 1, -1);
282
283 CGContextDrawImage(inContext, *inBounds, inImage);
284
285 CGContextRestoreGState(inContext);
286InvalidImage:
287InvalidBounds:
288InvalidContext:
289 return err;
290}
291
292bool qt_mac_checkForNativeSizeGrip(const QWidget *widget)
293{
294#ifndef QT_MAC_USE_COCOA
295 OSViewRef nativeSizeGrip = 0;
296 HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(widget->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip);
297 return (nativeSizeGrip != 0);
298#else
299 return [[reinterpret_cast<NSView *>(widget->winId()) window] showsResizeIndicator];
300#endif
301}
302struct qt_mac_enum_mapper
303{
304 int mac_code;
305 int qt_code;
306#if defined(DEBUG_MOUSE_MAPS)
307# define QT_MAC_MAP_ENUM(x) x, #x
308 const char *desc;
309#else
310# define QT_MAC_MAP_ENUM(x) x
311#endif
312};
313
314//mouse buttons
315static qt_mac_enum_mapper qt_mac_mouse_symbols[] = {
316{ kEventMouseButtonPrimary, QT_MAC_MAP_ENUM(Qt::LeftButton) },
317{ kEventMouseButtonSecondary, QT_MAC_MAP_ENUM(Qt::RightButton) },
318{ kEventMouseButtonTertiary, QT_MAC_MAP_ENUM(Qt::MidButton) },
319{ 4, QT_MAC_MAP_ENUM(Qt::XButton1) },
320{ 5, QT_MAC_MAP_ENUM(Qt::XButton2) },
321{ 0, QT_MAC_MAP_ENUM(0) }
322};
323Qt::MouseButtons qt_mac_get_buttons(int buttons)
324{
325#ifdef DEBUG_MOUSE_MAPS
326 qDebug("Qt: internal: **Mapping buttons: %d (0x%04x)", buttons, buttons);
327#endif
328 Qt::MouseButtons ret = Qt::NoButton;
329 for(int i = 0; qt_mac_mouse_symbols[i].qt_code; i++) {
330 if (buttons & (0x01<<(qt_mac_mouse_symbols[i].mac_code-1))) {
331#ifdef DEBUG_MOUSE_MAPS
332 qDebug("Qt: internal: got button: %s", qt_mac_mouse_symbols[i].desc);
333#endif
334 ret |= Qt::MouseButtons(qt_mac_mouse_symbols[i].qt_code);
335 }
336 }
337 return ret;
338}
339Qt::MouseButton qt_mac_get_button(EventMouseButton button)
340{
341#ifdef DEBUG_MOUSE_MAPS
342 qDebug("Qt: internal: **Mapping button: %d (0x%04x)", button, button);
343#endif
344 Qt::MouseButtons ret = 0;
345 for(int i = 0; qt_mac_mouse_symbols[i].qt_code; i++) {
346 if (button == qt_mac_mouse_symbols[i].mac_code) {
347#ifdef DEBUG_MOUSE_MAPS
348 qDebug("Qt: internal: got button: %s", qt_mac_mouse_symbols[i].desc);
349#endif
350 return Qt::MouseButton(qt_mac_mouse_symbols[i].qt_code);
351 }
352 }
353 return Qt::NoButton;
354}
355
356void macSendToolbarChangeEvent(QWidget *widget)
357{
358 QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey));
359 qt_sendSpontaneousEvent(widget, &ev);
360}
361
362Q_GLOBAL_STATIC(QMacTabletHash, tablet_hash)
363QMacTabletHash *qt_mac_tablet_hash()
364{
365 return tablet_hash();
366}
367
368#ifdef QT_MAC_USE_COCOA
369void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent)
370{
371 NSEvent *proximityEvent = static_cast<NSEvent *>(tabletEvent);
372 // simply construct a Carbon proximity record and handle it all in one spot.
373 TabletProximityRec carbonProximityRec = { [proximityEvent vendorID],
374 [proximityEvent tabletID],
375 [proximityEvent pointingDeviceID],
376 [proximityEvent deviceID],
377 [proximityEvent systemTabletID],
378 [proximityEvent vendorPointingDeviceType],
379 [proximityEvent pointingDeviceSerialNumber],
380 [proximityEvent uniqueID],
381 [proximityEvent capabilityMask],
382 [proximityEvent pointingDeviceType],
383 [proximityEvent isEnteringProximity] };
384 qt_dispatchTabletProximityEvent(carbonProximityRec);
385}
386#endif // QT_MAC_USE_COCOA
387
388void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec)
389{
390 QTabletDeviceData proximityDevice;
391 proximityDevice.tabletUniqueID = proxRec.uniqueID;
392 proximityDevice.capabilityMask = proxRec.capabilityMask;
393
394 switch (proxRec.pointerType) {
395 case NSUnknownPointingDevice:
396 default:
397 proximityDevice.tabletPointerType = QTabletEvent::UnknownPointer;
398 break;
399 case NSPenPointingDevice:
400 proximityDevice.tabletPointerType = QTabletEvent::Pen;
401 break;
402 case NSCursorPointingDevice:
403 proximityDevice.tabletPointerType = QTabletEvent::Cursor;
404 break;
405 case NSEraserPointingDevice:
406 proximityDevice.tabletPointerType = QTabletEvent::Eraser;
407 break;
408 }
409 uint bits = proxRec.vendorPointerType;
410 if (bits == 0 && proximityDevice.tabletUniqueID != 0) {
411 // Fallback. It seems that the driver doesn't always include all the information.
412 // High-End Wacom devices store their "type" in the uper bits of the Unique ID.
413 // I'm not sure how to handle it for consumer devices, but I'll test that in a bit.
414 bits = proximityDevice.tabletUniqueID >> 32;
415 }
416 // Defined in the "EN0056-NxtGenImpGuideX"
417 // on Wacom's Developer Website (www.wacomeng.com)
418 if (((bits & 0x0006) == 0x0002) && ((bits & 0x0F06) != 0x0902)) {
419 proximityDevice.tabletDeviceType = QTabletEvent::Stylus;
420 } else {
421 switch (bits & 0x0F06) {
422 case 0x0802:
423 proximityDevice.tabletDeviceType = QTabletEvent::Stylus;
424 break;
425 case 0x0902:
426 proximityDevice.tabletDeviceType = QTabletEvent::Airbrush;
427 break;
428 case 0x0004:
429 proximityDevice.tabletDeviceType = QTabletEvent::FourDMouse;
430 break;
431 case 0x0006:
432 proximityDevice.tabletDeviceType = QTabletEvent::Puck;
433 break;
434 case 0x0804:
435 proximityDevice.tabletDeviceType = QTabletEvent::RotationStylus;
436 break;
437 default:
438 proximityDevice.tabletDeviceType = QTabletEvent::NoDevice;
439 }
440 }
441 // The deviceID is "unique" while in the proximity, it's a key that we can use for
442 // linking up TabletDeviceData to an event (especially if there are two devices in action).
443 bool entering = proxRec.enterProximity;
444 if (entering) {
445 qt_mac_tablet_hash()->insert(proxRec.deviceID, proximityDevice);
446 } else {
447 qt_mac_tablet_hash()->remove(proxRec.deviceID);
448 }
449
450 QTabletEvent qtabletProximity(entering ? QEvent::TabletEnterProximity
451 : QEvent::TabletLeaveProximity,
452 QPoint(), QPoint(), QPointF(), proximityDevice.tabletDeviceType,
453 proximityDevice.tabletPointerType, 0., 0, 0, 0., 0., 0, 0,
454 proximityDevice.tabletUniqueID);
455
456 qt_sendSpontaneousEvent(qApp, &qtabletProximity);
457}
458
459#ifdef QT_MAC_USE_COCOA
460// Use this method to keep all the information in the TextSegment. As long as it is ordered
461// we are in OK shape, and we can influence that ourselves.
462struct KeyPair
463{
464 QChar cocoaKey;
465 Qt::Key qtKey;
466};
467
468bool operator==(const KeyPair &entry, QChar qchar)
469{
470 return entry.cocoaKey == qchar;
471}
472
473bool operator<(const KeyPair &entry, QChar qchar)
474{
475 return entry.cocoaKey < qchar;
476}
477
478bool operator<(QChar qchar, const KeyPair &entry)
479{
480 return qchar < entry.cocoaKey;
481}
482
483static Qt::Key cocoaKey2QtKey(QChar keyCode)
484{
485 static const int NumEntries = 57;
486 static const KeyPair entries[NumEntries] = {
487 { NSEnterCharacter, Qt::Key_Enter },
488 { NSTabCharacter, Qt::Key_Tab },
489 { NSCarriageReturnCharacter, Qt::Key_Return },
490 { NSBackTabCharacter, Qt::Key_Backtab },
491 { kEscapeCharCode, Qt::Key_Escape },
492 { NSDeleteCharacter, Qt::Key_Backspace },
493 { NSUpArrowFunctionKey, Qt::Key_Up },
494 { NSDownArrowFunctionKey, Qt::Key_Down },
495 { NSLeftArrowFunctionKey, Qt::Key_Left },
496 { NSRightArrowFunctionKey, Qt::Key_Right },
497 { NSF1FunctionKey, Qt::Key_F1 },
498 { NSF2FunctionKey, Qt::Key_F2 },
499 { NSF3FunctionKey, Qt::Key_F3 },
500 { NSF4FunctionKey, Qt::Key_F4 },
501 { NSF5FunctionKey, Qt::Key_F5 },
502 { NSF6FunctionKey, Qt::Key_F6 },
503 { NSF7FunctionKey, Qt::Key_F7 },
504 { NSF8FunctionKey, Qt::Key_F8 },
505 { NSF9FunctionKey, Qt::Key_F8 },
506 { NSF10FunctionKey, Qt::Key_F10 },
507 { NSF11FunctionKey, Qt::Key_F11 },
508 { NSF12FunctionKey, Qt::Key_F12 },
509 { NSF13FunctionKey, Qt::Key_F13 },
510 { NSF14FunctionKey, Qt::Key_F14 },
511 { NSF15FunctionKey, Qt::Key_F15 },
512 { NSF16FunctionKey, Qt::Key_F16 },
513 { NSF17FunctionKey, Qt::Key_F17 },
514 { NSF18FunctionKey, Qt::Key_F18 },
515 { NSF19FunctionKey, Qt::Key_F19 },
516 { NSF20FunctionKey, Qt::Key_F20 },
517 { NSF21FunctionKey, Qt::Key_F21 },
518 { NSF22FunctionKey, Qt::Key_F22 },
519 { NSF23FunctionKey, Qt::Key_F23 },
520 { NSF24FunctionKey, Qt::Key_F24 },
521 { NSF25FunctionKey, Qt::Key_F25 },
522 { NSF26FunctionKey, Qt::Key_F26 },
523 { NSF27FunctionKey, Qt::Key_F27 },
524 { NSF28FunctionKey, Qt::Key_F28 },
525 { NSF29FunctionKey, Qt::Key_F29 },
526 { NSF30FunctionKey, Qt::Key_F30 },
527 { NSF31FunctionKey, Qt::Key_F31 },
528 { NSF32FunctionKey, Qt::Key_F32 },
529 { NSF33FunctionKey, Qt::Key_F33 },
530 { NSF34FunctionKey, Qt::Key_F34 },
531 { NSF35FunctionKey, Qt::Key_F35 },
532 { NSInsertFunctionKey, Qt::Key_Insert },
533 { NSDeleteFunctionKey, Qt::Key_Delete },
534 { NSHomeFunctionKey, Qt::Key_Home },
535 { NSEndFunctionKey, Qt::Key_End },
536 { NSPageUpFunctionKey, Qt::Key_PageUp },
537 { NSPageDownFunctionKey, Qt::Key_PageDown },
538 { NSPrintScreenFunctionKey, Qt::Key_Print },
539 { NSScrollLockFunctionKey, Qt::Key_ScrollLock },
540 { NSPauseFunctionKey, Qt::Key_Pause },
541 { NSSysReqFunctionKey, Qt::Key_SysReq },
542 { NSMenuFunctionKey, Qt::Key_Menu },
543 { NSHelpFunctionKey, Qt::Key_Help },
544 };
545 static const KeyPair * const end = entries + NumEntries;
546 const KeyPair *i = qBinaryFind(entries, end, keyCode);
547 if (i == end)
548 return Qt::Key(keyCode.unicode());
549 return i->qtKey;
550}
551
552Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags)
553{
554 Qt::KeyboardModifiers qtMods =Qt::NoModifier;
555 if (modifierFlags & NSShiftKeyMask)
556 qtMods |= Qt::ShiftModifier;
557 if (modifierFlags & NSControlKeyMask)