source: trunk/src/gui/kernel/qwidget_mac.mm@ 603

Last change on this file since 603 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 190.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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/qt_mac_p.h>
77#include <private/qeventdispatcher_mac_p.h>
78
79#include "qapplication.h"
80#include "qapplication_p.h"
81#include "qbitmap.h"
82#include "qcursor.h"
83#include "qdesktopwidget.h"
84#include "qevent.h"
85#include "qfileinfo.h"
86#include "qimage.h"
87#include "qlayout.h"
88#include "qmenubar.h"
89#include <private/qbackingstore_p.h>
90#include <private/qwindowsurface_mac_p.h>
91#include <private/qpaintengine_mac_p.h>
92#include "qpainter.h"
93#include "qstyle.h"
94#include "qtimer.h"
95#include "qfocusframe.h"
96#include "qdebug.h"
97#include <private/qmainwindowlayout_p.h>
98
99#include <private/qabstractscrollarea_p.h>
100#include <qabstractscrollarea.h>
101#include <ApplicationServices/ApplicationServices.h>
102#include <limits.h>
103#include <private/qt_cocoa_helpers_mac_p.h>
104#include <private/qcocoaview_mac_p.h>
105#include <private/qcocoawindow_mac_p.h>
106#include <private/qcocoawindowdelegate_mac_p.h>
107#include <private/qcocoapanel_mac_p.h>
108
109#include "qwidget_p.h"
110#include "qevent_p.h"
111#include "qdnd_p.h"
112#include <QtGui/qgraphicsproxywidget.h>
113
114QT_BEGIN_NAMESPACE
115
116#define XCOORD_MAX 16383
117#define WRECT_MAX 8191
118
119#ifndef QT_MAC_USE_COCOA
120
121extern "C" {
122 extern OSStatus _HIViewScrollRectWithOptions(HIViewRef, const HIRect *, CGFloat, CGFloat,
123 OptionBits) __attribute__ ((weak));
124}
125#define kHIViewScrollRectAdjustInvalid 1
126#define kHIViewScrollRectDontInvalidateRevealedArea 2
127#endif
128
129
130/*****************************************************************************
131 QWidget debug facilities
132 *****************************************************************************/
133//#define DEBUG_WINDOW_RGNS
134//#define DEBUG_WINDOW_CREATE
135//#define DEBUG_WINDOW_STATE
136//#define DEBUG_WIDGET_PAINT
137
138/*****************************************************************************
139 QWidget globals
140 *****************************************************************************/
141#ifndef QT_MAC_USE_COCOA
142typedef QHash<Qt::WindowFlags, WindowGroupRef> WindowGroupHash;
143Q_GLOBAL_STATIC(WindowGroupHash, qt_mac_window_groups)
144const UInt32 kWidgetCreatorQt = kEventClassQt;
145enum {
146 kWidgetPropertyQWidget = 'QWId' //QWidget *
147};
148#endif
149
150static bool qt_mac_raise_process = true;
151static OSWindowRef qt_root_win = 0;
152QWidget *mac_mouse_grabber = 0;
153QWidget *mac_keyboard_grabber = 0;
154
155#ifndef QT_MAC_USE_COCOA
156#ifdef QT_NAMESPACE
157
158// produce the string "com.trolltech.qt-namespace.widget", where "namespace" is the contents of QT_NAMESPACE.
159#define SS(x) #x
160#define S0(x) SS(x)
161#define S "com.trolltech.qt-" S0(QT_NAMESPACE) ".widget"
162
163static CFStringRef kObjectQWidget = CFSTR(S);
164
165#undef SS
166#undef S0
167#undef S
168
169#else
170static CFStringRef kObjectQWidget = CFSTR("com.trolltech.qt.widget");
171#endif // QT_NAMESPACE
172#endif // QT_MAC_USE_COCOA
173
174/*****************************************************************************
175 Externals
176 *****************************************************************************/
177extern QWidget *qt_mac_modal_blocked(QWidget *); //qapplication_mac.mm
178extern void qt_event_request_activate(QWidget *); //qapplication_mac.mm
179extern bool qt_event_remove_activate(); //qapplication_mac.mm
180extern void qt_mac_event_release(QWidget *w); //qapplication_mac.mm
181extern void qt_event_request_showsheet(QWidget *); //qapplication_mac.mm
182extern void qt_event_request_window_change(QWidget *); //qapplication_mac.mm
183extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm
184extern IconRef qt_mac_create_iconref(const QPixmap &); //qpixmap_mac.cpp
185extern void qt_mac_set_cursor(const QCursor *, const QPoint &); //qcursor_mac.mm
186extern void qt_mac_update_cursor(); //qcursor_mac.mm
187extern bool qt_nograb();
188extern CGImageRef qt_mac_create_cgimage(const QPixmap &, bool); //qpixmap_mac.cpp
189extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp
190extern QRegion qt_mac_convert_mac_region(RgnHandle rgn); //qregion_mac.cpp
191
192/*****************************************************************************
193 QWidget utility functions
194 *****************************************************************************/
195void Q_GUI_EXPORT qt_mac_set_raise_process(bool b) { qt_mac_raise_process = b; }
196static QSize qt_mac_desktopSize()
197{
198 int w = 0, h = 0;
199 CGDisplayCount cg_count;
200 CGGetActiveDisplayList(0, 0, &cg_count);
201 QVector<CGDirectDisplayID> displays(cg_count);
202 CGGetActiveDisplayList(cg_count, displays.data(), &cg_count);
203 Q_ASSERT(cg_count == (CGDisplayCount)displays.size());
204 for(int i = 0; i < (int)cg_count; ++i) {
205 CGRect r = CGDisplayBounds(displays.at(i));
206 w = qMax<int>(w, qRound(r.origin.x + r.size.width));
207 h = qMax<int>(h, qRound(r.origin.y + r.size.height));
208 }
209 return QSize(w, h);
210}
211
212#ifdef QT_MAC_USE_COCOA
213static NSDrawer *qt_mac_drawer_for(const QWidget *widget)
214{
215 // This only goes one level below the content view so start with the window.
216 // This works fine for straight Qt stuff, but runs into problems if we are
217 // embedding, but if that's the case, they probably want to be using
218 // NSDrawer directly.
219 NSView *widgetView = reinterpret_cast<NSView *>(widget->window()->winId());
220 NSArray *windows = [NSApp windows];
221 for (NSWindow *window in windows) {
222 NSArray *drawers = [window drawers];
223 for (NSDrawer *drawer in drawers) {
224 NSArray *views = [[drawer contentView] subviews];
225 for (NSView *view in views) {
226 if (view == widgetView)
227 return drawer;
228 }
229 }
230 }
231 return 0;
232}
233#endif
234
235static void qt_mac_destructView(OSViewRef view)
236{
237#ifdef QT_MAC_USE_COCOA
238 [view removeFromSuperview];
239 [view release];
240#else
241 HIViewRemoveFromSuperview(view);
242 CFRelease(view);
243#endif
244}
245
246static void qt_mac_destructWindow(OSWindowRef window)
247{
248#ifdef QT_MAC_USE_COCOA
249 if ([window isVisible] && [window isSheet]){
250 [NSApp endSheet:window];
251 [window orderOut:window];
252 }
253
254 [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForWindow:window];
255 [window release];
256#else
257 // Remove property to clean up memory:
258 RemoveWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget);
259 CFRelease(window);
260#endif
261}
262
263static void qt_mac_destructDrawer(NSDrawer *drawer)
264{
265#ifdef QT_MAC_USE_COCOA
266 [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForDrawer:drawer];
267 [drawer release];
268#else
269 Q_UNUSED(drawer);
270#endif
271}
272
273bool qt_mac_can_clickThrough(const QWidget *w)
274{
275 static int qt_mac_carbon_clickthrough = -1;
276 if (qt_mac_carbon_clickthrough < 0)
277 qt_mac_carbon_clickthrough = !qgetenv("QT_MAC_NO_COCOA_CLICKTHROUGH").isEmpty();
278 bool ret = !qt_mac_carbon_clickthrough;
279 for ( ; w; w = w->parentWidget()) {
280 if (w->testAttribute(Qt::WA_MacNoClickThrough)) {
281 ret = false;
282 break;
283 }
284 }
285 return ret;
286}
287
288bool qt_mac_is_macsheet(const QWidget *w)
289{
290 if (!w)
291 return false;
292
293 Qt::WindowModality modality = w->windowModality();
294 if (modality == Qt::ApplicationModal)
295 return false;
296 return w->parentWidget() && (modality == Qt::WindowModal || w->windowType() == Qt::Sheet);
297}
298
299bool qt_mac_is_macdrawer(const QWidget *w)
300{
301 return (w && w->parentWidget() && w->windowType() == Qt::Drawer);
302}
303
304bool qt_mac_insideKeyWindow(const QWidget *w)
305{
306#ifdef QT_MAC_USE_COCOA
307 return [[reinterpret_cast<NSView *>(w->winId()) window] isKeyWindow];
308#else
309 Q_UNUSED(w);
310#endif
311 return false;
312}
313
314bool qt_mac_set_drawer_preferred_edge(QWidget *w, Qt::DockWidgetArea where) //users of Qt for Mac OS X can use this..
315{
316 if(!qt_mac_is_macdrawer(w))
317 return false;
318
319#if QT_MAC_USE_COCOA
320 NSDrawer *drawer = qt_mac_drawer_for(w);
321 if (!drawer)
322 return false;
323 NSRectEdge edge;
324 if (where & Qt::LeftDockWidgetArea)
325 edge = NSMinXEdge;
326 else if (where & Qt::RightDockWidgetArea)
327 edge = NSMaxXEdge;
328 else if (where & Qt::TopDockWidgetArea)
329 edge = NSMaxYEdge;
330 else if (where & Qt::BottomDockWidgetArea)
331 edge = NSMinYEdge;
332 else
333 return false;
334
335 if (edge == [drawer preferredEdge]) //no-op
336 return false;
337
338 if (w->isVisible()) {
339 [drawer close];
340 [drawer openOnEdge:edge];
341 }
342 [drawer setPreferredEdge:edge];
343#else
344 OSWindowRef window = qt_mac_window_for(w);
345 OptionBits edge;
346 if(where & Qt::LeftDockWidgetArea)
347 edge = kWindowEdgeLeft;
348 else if(where & Qt::RightDockWidgetArea)
349 edge = kWindowEdgeRight;
350 else if(where & Qt::TopDockWidgetArea)
351 edge = kWindowEdgeTop;
352 else if(where & Qt::BottomDockWidgetArea)
353 edge = kWindowEdgeBottom;
354 else
355 return false;
356
357 if(edge == GetDrawerPreferredEdge(window)) //no-op
358 return false;
359
360 //do it
361 SetDrawerPreferredEdge(window, edge);
362 if(w->isVisible()) {
363 CloseDrawer(window, false);
364 OpenDrawer(window, edge, true);
365 }
366#endif
367 return true;
368}
369
370#ifndef QT_MAC_USE_COCOA
371Q_GUI_EXPORT
372#endif
373QPoint qt_mac_posInWindow(const QWidget *w)
374{
375 QPoint ret = w->data->wrect.topLeft();
376 while(w && !w->isWindow()) {
377 ret += w->pos();
378 w = w->parentWidget();
379 }
380 return ret;
381}
382
383//find a QWidget from a OSWindowRef
384QWidget *qt_mac_find_window(OSWindowRef window)
385{
386#ifdef QT_MAC_USE_COCOA
387 return [window QT_MANGLE_NAMESPACE(qt_qwidget)];
388#else
389 if(!window)
390 return 0;
391
392 QWidget *ret;
393 if(GetWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(ret), 0, &ret) == noErr)
394 return ret;
395 return 0;
396#endif
397}
398
399inline static void qt_mac_set_fullscreen_mode(bool b)
400{
401 extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
402 if(qt_mac_app_fullscreen == b)
403 return;
404 qt_mac_app_fullscreen = b;
405 if (b) {
406 SetSystemUIMode(kUIModeAllSuppressed, 0);
407 } else {
408 SetSystemUIMode(kUIModeNormal, 0);
409 }
410}
411
412Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w)
413{
414 return reinterpret_cast<OSViewRef>(w->data->winid);
415}
416
417Q_GUI_EXPORT OSViewRef qt_mac_get_contentview_for(OSWindowRef w)
418{
419#ifdef QT_MAC_USE_COCOA
420 return [w contentView];
421#else
422 HIViewRef contentView = 0;
423 OSStatus err = GetRootControl(w, &contentView); // Returns the window's content view (Apple QA1214)
424 if (err == errUnknownControl) {
425 contentView = HIViewGetRoot(w);
426 } else if (err != noErr) {
427 qWarning("Qt:Could not get content or root view of window! %s:%d [%ld]",
428 __FILE__, __LINE__, err);
429 }
430 return contentView;
431#endif
432}
433
434bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref)
435{
436 return widget->macEvent(0, ref);
437}
438
439Q_GUI_EXPORT OSWindowRef qt_mac_window_for(OSViewRef view)
440{
441#ifdef QT_MAC_USE_COCOA
442 if (view)
443 return [view window];
444 return 0;
445#else
446 return HIViewGetWindow(view);
447#endif
448}
449
450static bool qt_isGenuineQWidget(OSViewRef ref)
451{
452#ifdef QT_MAC_USE_COCOA
453 return [ref isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]];
454#else
455 return HIObjectIsOfClass(HIObjectRef(ref), kObjectQWidget);
456#endif
457}
458
459bool qt_isGenuineQWidget(const QWidget *window)
460{
461 return window && qt_isGenuineQWidget(OSViewRef(window->winId()));
462}
463
464Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w)
465{
466 OSViewRef hiview = qt_mac_nativeview_for(w);
467 if (hiview){
468 OSWindowRef window = qt_mac_window_for(hiview);
469 if (!window && qt_isGenuineQWidget(hiview)) {
470 QWidget *myWindow = w->window();
471 // This is a workaround for NSToolbar. When a widget is hidden
472 // by clicking the toolbar button, Cocoa reparents the widgets
473 // to another window (but Qt doesn't know about it).
474 // When we start showing them, it reparents back,
475 // but at this point it's window is nil, but the window it's being brought
476 // into (the Qt one) is for sure created.
477 // This stops the hierarchy moving under our feet.
478 if (myWindow != w && qt_mac_window_for(qt_mac_nativeview_for(myWindow)))
479 return qt_mac_window_for(qt_mac_nativeview_for(myWindow));
480
481 myWindow->d_func()->createWindow_sys();
482 // Reget the hiview since the "create window could potentially move the view (I guess).
483 hiview = qt_mac_nativeview_for(w);
484 window = qt_mac_window_for(hiview);
485 }
486 return window;
487 }
488 return 0;
489}
490#ifndef QT_MAC_USE_COCOA
491/* Checks if the current group is a 'stay on top' group. If so, the
492 group gets removed from the hash table */
493static void qt_mac_release_stays_on_top_group(WindowGroupRef group)
494{
495 for (WindowGroupHash::iterator it = qt_mac_window_groups()->begin(); it != qt_mac_window_groups()->end(); ++it) {
496 if (it.value() == group) {
497 qt_mac_window_groups()->remove(it.key());
498 return;
499 }
500 }
501}
502
503/* Use this function instead of ReleaseWindowGroup, this will be sure to release the
504 stays on top window group (created with qt_mac_get_stays_on_top_group below) */
505static void qt_mac_release_window_group(WindowGroupRef group)
506{
507 ReleaseWindowGroup(group);
508 if (GetWindowGroupRetainCount(group) == 0)
509 qt_mac_release_stays_on_top_group(group);
510}
511#define ReleaseWindowGroup(x) Are you sure you wanted to do that? (you wanted qt_mac_release_window_group)
512
513SInt32 qt_mac_get_group_level(WindowClass wclass)
514{
515 SInt32 group_level;
516 CGWindowLevel tmpLevel;
517 GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel);
518 group_level = tmpLevel;
519 return group_level;
520}
521#endif
522
523#ifndef QT_MAC_USE_COCOA
524static void qt_mac_set_window_group(OSWindowRef window, Qt::WindowFlags flags, int level)
525{
526 WindowGroupRef group = 0;
527 if (qt_mac_window_groups()->contains(flags)) {
528 group = qt_mac_window_groups()->value(flags);
529 RetainWindowGroup(group);
530 } else {
531 CreateWindowGroup(kWindowActivationScopeNone, &group);
532 SetWindowGroupLevel(group, level);
533 SetWindowGroupParent(group, GetWindowGroupOfClass(kAllWindowClasses));
534 qt_mac_window_groups()->insert(flags, group);
535 }
536 SetWindowGroup(window, group);
537}
538
539inline static void qt_mac_set_window_group_to_stays_on_top(OSWindowRef window, Qt::WindowType type)
540{
541 // We create one static stays on top window group so that
542 // all stays on top (aka popups) will fall into the same
543 // group and be able to be raise()'d with releation to one another (from
544 // within the same window group).
545 qt_mac_set_window_group(window, type|Qt::WindowStaysOnTopHint, qt_mac_get_group_level(kOverlayWindowClass));
546}
547
548inline static void qt_mac_set_window_group_to_tooltip(OSWindowRef window)
549{
550 // Since new groups are created for 'stays on top' windows, the
551 // same must be done for tooltips. Otherwise, tooltips would be drawn
552 // below 'stays on top' widgets even tough they are on the same level.
553 // Also, add 'two' to the group level to make sure they also get on top of popups.
554 qt_mac_set_window_group(window, Qt::ToolTip, qt_mac_get_group_level(kHelpWindowClass)+2);
555}
556
557inline static void qt_mac_set_window_group_to_popup(OSWindowRef window)
558{
559 // In Qt, a popup is seen as a 'stay on top' window.
560 // Since new groups are created for 'stays on top' windows, the
561 // same must be done for popups. Otherwise, popups would be drawn
562 // below 'stays on top' windows. Add 1 to get above pure stay-on-top windows.
563 qt_mac_set_window_group(window, Qt::Popup, qt_mac_get_group_level(kOverlayWindowClass)+1);
564}
565#endif
566
567inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRect &rect)
568{
569 if (!widget)
570 return false;
571
572#ifndef QT_NO_GRAPHICSVIEW
573 QWidget *tlw = widget->window();
574 QWExtra *extra = qt_widget_private(tlw)->extra;
575 if (extra && extra->proxyWidget) {
576 extra->proxyWidget->update(rect.translated(widget->mapTo(tlw, QPoint())));
577 return true;
578 }
579#endif
580
581 return false;
582}
583
584inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRegion &rgn)
585{
586 if (!widget)
587 return false;
588
589#ifndef QT_NO_GRAPHICSVIEW
590 QWidget *tlw = widget->window();
591 QWExtra *extra = qt_widget_private(tlw)->extra;
592 if (extra && extra->proxyWidget) {
593 const QPoint offset(widget->mapTo(tlw, QPoint()));
594 const QVector<QRect> rects = rgn.rects();
595 for (int i = 0; i < rects.size(); ++i)
596 extra->proxyWidget->update(rects.at(i).translated(offset));
597 return true;
598 }
599#endif
600
601 return false;
602}
603
604void QWidgetPrivate::macUpdateIsOpaque()
605{
606 Q_Q(QWidget);
607 if (!q->testAttribute(Qt::WA_WState_Created))
608 return;
609#ifndef QT_MAC_USE_COCOA
610 HIViewFeatures bits;
611 HIViewRef hiview = qt_mac_nativeview_for(q);
612 HIViewGetFeatures(hiview, &bits);
613 if ((bits & kHIViewIsOpaque) == isOpaque)
614 return;
615 if (isOpaque) {
616 HIViewChangeFeatures(hiview, kHIViewIsOpaque, 0);
617 } else {
618 HIViewChangeFeatures(hiview, 0, kHIViewIsOpaque);
619 }
620 if (q->isVisible())
621 HIViewReshapeStructure(qt_mac_nativeview_for(q));
622#else
623 if (isRealWindow() && !q->testAttribute(Qt::WA_MacBrushedMetal)) {
624 bool opaque = isOpaque;
625 if (extra && extra->imageMask)
626 opaque = false; // we are never opaque when we have a mask.
627 [qt_mac_window_for(q) setOpaque:opaque];
628 }
629#endif
630}
631#ifdef QT_MAC_USE_COCOA
632static OSWindowRef qt_mac_create_window(QWidget *widget, WindowClass wclass,
633 NSUInteger wattr, const QRect &crect)
634{
635 // Determine if we need to add in our "custom window" attribute. Cocoa is rather clever
636 // in deciding if we need the maximize button or not (i.e., it's resizeable, so you
637 // must need a maximize button). So, the only buttons we have control over are the
638 // close and minimize buttons. If someone wants to customize and NOT have the maximize
639 // button, then we have to do our hack. We only do it for these cases because otherwise
640 // the window looks different when activated. This "QtMacCustomizeWindow" attribute is
641 // intruding on a public space and WILL BREAK in the future.
642 // One can hope that there is a more public API available by that time.
643 Qt::WindowFlags flags = widget ? widget->windowFlags() : Qt::WindowFlags(0);
644 if ((flags & Qt::CustomizeWindowHint)) {
645 if ((flags & (Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint
646 | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint))
647 && !(flags & Qt::WindowMaximizeButtonHint))
648 wattr |= QtMacCustomizeWindow;
649 }
650
651 // If we haven't created the desktop widget, you have to pass the rectangle
652 // in "cocoa coordinates" (i.e., top points to the lower left coordinate).
653 // Otherwise, we do the conversion for you. Since we are the only ones that
654 // create the desktop widget, this is OK (but confusing).
655 NSRect geo = NSMakeRect(crect.left(),
656 (qt_root_win != 0) ? flipYCoordinate(crect.bottom() + 1) : crect.top(),
657 crect.width(), crect.height());
658 QMacCocoaAutoReleasePool pool;
659 OSWindowRef window;
660 switch (wclass) {
661 case kMovableModalWindowClass:
662 case kModalWindowClass:
663 case kSheetWindowClass:
664 case kFloatingWindowClass:
665 case kOverlayWindowClass:
666 case kHelpWindowClass: {
667 NSPanel *panel;
668 BOOL needFloating = NO;
669 BOOL worksWhenModal = widget && (widget->windowType() == Qt::Popup);
670 // Add in the extra flags if necessary.
671 switch (wclass) {
672 case kSheetWindowClass:
673 wattr |= NSDocModalWindowMask;
674 break;
675 case kFloatingWindowClass:
676 case kHelpWindowClass:
677 needFloating = YES;
678 wattr |= NSUtilityWindowMask;
679 break;
680 default:
681 break;
682 }
683 panel = [[QT_MANGLE_NAMESPACE(QCocoaPanel) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr];
684 [panel setFloatingPanel:needFloating];
685 [panel setWorksWhenModal:worksWhenModal];
686 window = panel;
687 break;
688 }
689 case kDrawerWindowClass: {
690 NSDrawer *drawer = [[NSDrawer alloc] initWithContentSize:geo.size preferredEdge:NSMinXEdge];
691 [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] becomeDelegateForDrawer:drawer widget:widget];
692 QWidget *parentWidget = widget->parentWidget();
693 if (parentWidget)
694 [drawer setParentWindow:qt_mac_window_for(parentWidget)];
695 [drawer setLeadingOffset:0.0];
696 [drawer setTrailingOffset:25.0];
697 window = [[drawer contentView] window]; // Just to make sure we actually return a window
698 break;
699 }
700 default:
701 window = [[QT_MANGLE_NAMESPACE(QCocoaWindow) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr];
702 break;
703 }
704 qt_syncCocoaTitleBarButtons(window, widget);
705 return window;
706}
707#else
708static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAttributes wattr,
709 const QRect &crect)
710{
711 OSWindowRef window;
712 Rect geo;
713 SetRect(&geo, crect.left(), crect.top(), crect.right() + 1, crect.bottom() + 1);
714 OSStatus err;
715 if(geo.right <= geo.left) geo.right = geo.left + 1;
716 if(geo.bottom <= geo.top) geo.bottom = geo.top + 1;
717 Rect null_rect;
718 SetRect(&null_rect, 0, 0, 1, 1);
719 err = CreateNewWindow(wclass, wattr, &null_rect, &window);
720 if(err == noErr) {
721 err = SetWindowBounds(window, kWindowContentRgn, &geo);
722 if(err != noErr)
723 qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__);
724 }
725 return window;
726}
727
728#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
729/* We build the release package against the 10.4 SDK.
730 So, to enable gestures for applications running on
731 10.6+, we define the missing constants here: */
732enum {
733 kEventClassGesture = 'gest',
734 kEventGestureStarted = 1,
735 kEventGestureEnded = 2,
736 kEventGestureMagnify = 4,
737 kEventGestureSwipe = 5,
738 kEventGestureRotate = 6,
739 kEventParamRotationAmount = 'rota',
740 kEventParamSwipeDirection = 'swip',
741 kEventParamMagnificationAmount = 'magn'
742};
743#endif
744
745// window events
746static EventTypeSpec window_events[] = {
747 { kEventClassWindow, kEventWindowClose },
748 { kEventClassWindow, kEventWindowExpanded },
749 { kEventClassWindow, kEventWindowHidden },
750 { kEventClassWindow, kEventWindowZoom },
751 { kEventClassWindow, kEventWindowZoomed },
752 { kEventClassWindow, kEventWindowCollapsed },
753 { kEventClassWindow, kEventWindowToolbarSwitchMode },
754 { kEventClassWindow, kEventWindowProxyBeginDrag },
755 { kEventClassWindow, kEventWindowProxyEndDrag },
756 { kEventClassWindow, kEventWindowResizeCompleted },
757 { kEventClassWindow, kEventWindowBoundsChanging },
758 { kEventClassWindow, kEventWindowGetRegion },
759 { kEventClassWindow, kEventWindowGetClickModality },
760 { kEventClassWindow, kEventWindowTransitionCompleted },
761 { kEventClassGesture, kEventGestureStarted },
762 { kEventClassGesture, kEventGestureEnded },
763 { kEventClassGesture, kEventGestureMagnify },
764 { kEventClassGesture, kEventGestureSwipe },
765 { kEventClassGesture, kEventGestureRotate },
766 { kEventClassMouse, kEventMouseDown }
767};
768static EventHandlerUPP mac_win_eventUPP = 0;
769static void cleanup_win_eventUPP()
770{
771 DisposeEventHandlerUPP(mac_win_eventUPP);
772 mac_win_eventUPP = 0;
773}
774static const EventHandlerUPP make_win_eventUPP()
775{
776 if(mac_win_eventUPP)
777 return mac_win_eventUPP;
778 qAddPostRoutine(cleanup_win_eventUPP);
779 return mac_win_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_window_event);
780}
781OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, void *)
782{
783 QScopedLoopLevelCounter loopLevelCounter(qApp->d_func()->threadData);
784 bool handled_event = true;
785 UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
786 switch(eclass) {
787 case kEventClassWindow: {
788 WindowRef wid = 0;
789 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
790 sizeof(WindowRef), 0, &wid);
791 QWidget *widget = qt_mac_find_window(wid);
792 if(!widget) {
793 handled_event = false;
794 } else if(ekind == kEventWindowGetClickModality) {
795 // Carbon will send us kEventWindowGetClickModality before every
796 // mouse press / release event. By returning 'true', we tell Carbon
797 // that we would like the event target to receive the mouse event even
798 // if the target is modally shaddowed. In Qt, this makes sense when we
799 // e.g. have a popup showing, as the popup will grab the event
800 // and perhaps use it to close itself.
801 // By also setting the current modal window back into the event, we
802 // help Carbon determining which window is supposed to be raised.
803 handled_event = qApp->activePopupWidget() ? true : false;
804 } else if(ekind == kEventWindowClose) {
805 widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
806 QMenuBar::macUpdateMenuBar();
807 } else if (ekind == kEventWindowTransitionCompleted) {
808 WindowTransitionAction transitionAction;
809 GetEventParameter(event, kEventParamWindowTransitionAction, typeWindowTransitionAction,
810 0, sizeof(transitionAction), 0, &transitionAction);
811 if (transitionAction == kWindowHideTransitionAction)
812 widget->hide();
813 } else if(ekind == kEventWindowExpanded) {
814 Qt::WindowStates currState = Qt::WindowStates(widget->data->window_state);
815 Qt::WindowStates newState = currState;
816 if (currState & Qt::WindowMinimized)
817 newState &= ~Qt::WindowMinimized;
818 if (!(currState & Qt::WindowActive))
819 newState |= Qt::WindowActive;
820 if (newState != currState) {
821 // newState will differ from currState if the window
822 // was expanded after clicking on the jewels (as opposed
823 // to calling QWidget::setWindowState)
824 widget->data->window_state = newState;
825 QWindowStateChangeEvent e(currState);
826 QApplication::sendSpontaneousEvent(widget, &e);
827 }
828
829 QShowEvent qse;
830 QApplication::sendSpontaneousEvent(widget, &qse);
831 } else if(ekind == kEventWindowZoom) {
832 widget->d_func()->topData()->normalGeometry = widget->geometry();
833 handled_event = false;
834 } else if(ekind == kEventWindowZoomed) {
835 WindowPartCode windowPart;
836 GetEventParameter(event, kEventParamWindowPartCode,
837 typeWindowPartCode, 0, sizeof(windowPart), 0, &windowPart);
838 if(windowPart == inZoomIn && widget->isMaximized()) {
839
840 widget->data->window_state = widget->data->window_state & ~Qt::WindowMaximized;
841 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state | Qt::WindowMaximized));
842 QApplication::sendSpontaneousEvent(widget, &e);
843 } else if(windowPart == inZoomOut && !widget->isMaximized()) {
844 widget->data->window_state = widget->data->window_state | Qt::WindowMaximized;
845 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state
846 & ~Qt::WindowMaximized));
847 QApplication::sendSpontaneousEvent(widget, &e);
848 }
849 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
850 qt_button_down = 0;
851 } else if(ekind == kEventWindowCollapsed) {
852 if (!widget->isMinimized()) {
853 widget->data->window_state = widget->data->window_state | Qt::WindowMinimized;
854 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state & ~Qt::WindowMinimized));
855 QApplication::sendSpontaneousEvent(widget, &e);
856 }
857
858 // Deactivate this window:
859 if (widget->isActiveWindow() && !(widget->windowType() == Qt::Popup)) {
860 QWidget *w = 0;
861 if (widget->parentWidget())
862 w = widget->parentWidget()->window();
863 if (!w || (!w->isVisible() && !w->isMinimized())) {
864 for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true);
865 wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) {
866 if ((w = qt_mac_find_window(wp)))
867 break;
868 }
869 }
870 if(!(w && w->isVisible() && !w->isMinimized()))
871 qApp->setActiveWindow(0);
872 }
873
874 //we send a hide to be like X11/Windows
875 QEvent e(QEvent::Hide);
876 QApplication::sendSpontaneousEvent(widget, &e);
877 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
878 qt_button_down = 0;
879 } else if(ekind == kEventWindowToolbarSwitchMode) {
880 macSendToolbarChangeEvent(widget);
881 HIToolbarRef toolbar;
882 if (GetWindowToolbar(wid, &toolbar) == noErr) {
883 if (toolbar) {
884 // Let HIToolbar do its thang, but things like the OpenGL context
885 // needs to know about it.
886 CallNextEventHandler(er, event);
887 qt_event_request_window_change(widget);
888 widget->data->fstrut_dirty = true;
889 }
890 }
891 } else if(ekind == kEventWindowGetRegion) {
892 WindowRef window;
893 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
894 sizeof(window), 0, &window);
895 WindowRegionCode wcode;
896 GetEventParameter(event, kEventParamWindowRegionCode, typeWindowRegionCode, 0,
897 sizeof(wcode), 0, &wcode);
898 if (wcode != kWindowOpaqueRgn){
899 // If the region is kWindowOpaqueRgn, don't call next
900 // event handler cause this will make the shadow of
901 // masked windows become offset. Unfortunately, we're not sure why.
902 CallNextEventHandler(er, event);
903 }
904 RgnHandle rgn;
905 GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0,
906 sizeof(rgn), 0, &rgn);
907
908 if(QWidgetPrivate::qt_widget_rgn(qt_mac_find_window(window), wcode, rgn, false))
909 SetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, sizeof(rgn), &rgn);
910 } else if(ekind == kEventWindowProxyBeginDrag) {
911 QIconDragEvent e;
912 QApplication::sendSpontaneousEvent(widget, &e);
913 } else if(ekind == kEventWindowResizeCompleted) {
914 // Create a mouse up event, since such an event is not send by carbon to the
915 // application event handler (while a mouse down <b>is</b> on kEventWindowResizeStarted)
916 EventRef mouseUpEvent;
917 CreateEvent(0, kEventClassMouse, kEventMouseUp, 0, kEventAttributeUserEvent, &mouseUpEvent);
918 UInt16 mbutton = kEventMouseButtonPrimary;
919 SetEventParameter(mouseUpEvent, kEventParamMouseButton, typeMouseButton, sizeof(mbutton), &mbutton);
920 WindowRef window;
921 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, sizeof(window), 0, &window);
922 Rect dragRect;
923 GetWindowBounds(window, kWindowGrowRgn, &dragRect);
924 Point pos = {dragRect.bottom, dragRect.right};
925 SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos);
926 SendEventToApplication(mouseUpEvent);
927 ReleaseEvent(mouseUpEvent);
928 } else if(ekind == kEventWindowBoundsChanging) {
929 UInt32 flags = 0;
930 GetEventParameter(event, kEventParamAttributes, typeUInt32, 0,
931 sizeof(flags), 0, &flags);
932 Rect nr;
933 GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0,
934 sizeof(nr), 0, &nr);
935
936 QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top);
937
938 QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData();
939 if (tlwExtra && tlwExtra->isSetGeometry == 1) {
940 widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove);
941 } else {
942 //implicitly removes the maximized bit
943 if((widget->data->window_state & Qt::WindowMaximized) &&
944 IsWindowInStandardState(wid, 0, 0)) {
945 widget->data->window_state &= ~Qt::WindowMaximized;
946 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state
947 | Qt::WindowMaximized));
948 QApplication::sendSpontaneousEvent(widget, &e);
949
950 }
951
952 handled_event = false;
953 const QRect oldRect = widget->data->crect;
954 if((flags & kWindowBoundsChangeOriginChanged)) {
955 if(nr.left != oldRect.x() || nr.top != oldRect.y()) {
956 widget->data->crect.moveTo(nr.left, nr.top);
957 QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft());
958 QApplication::sendSpontaneousEvent(widget, &qme);
959 }
960 }
961 if((flags & kWindowBoundsChangeSizeChanged)) {
962 if (widget->isWindow()) {
963 QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size());
964 int dh = newSize.height() - newRect.height();
965 int dw = newSize.width() - newRect.width();
966 if (dw != 0 || dh != 0) {
967 handled_event = true; // We want to change the bounds, so we handle the event
968
969 // set the rect, so we can also do the resize down below (yes, we need to resize).
970 newRect.setBottom(newRect.bottom() + dh);
971 newRect.setRight(newRect.right() + dw);
972
973 nr.left = newRect.x();
974 nr.top = newRect.y();
975 nr.right = nr.left + newRect.width();
976 nr.bottom = nr.top + newRect.height();
977 SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr);
978 }
979 }
980
981 if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) {
982 widget->data->crect.setSize(newRect.size());
983 HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height());
984
985 // If the WA_StaticContents attribute is set we can optimize the resize
986 // by only repainting the newly exposed area. We do this by disabling
987 // painting when setting the size of the view. The OS will invalidate
988 // the newly exposed area for us.
989 const bool staticContents = widget->testAttribute(Qt::WA_StaticContents);
990 const HIViewRef view = qt_mac_nativeview_for(widget);
991 if (staticContents)
992 HIViewSetDrawingEnabled(view, false);
993 HIViewSetFrame(view, &bounds);
994 if (staticContents)
995 HIViewSetDrawingEnabled(view, true);
996
997 QResizeEvent qre(newRect.size(), oldRect.size());
998 QApplication::sendSpontaneousEvent(widget, &qre);
999 qt_event_request_window_change(widget);
1000 }
1001 }
1002 }
1003 } else if (ekind == kEventWindowHidden) {
1004 // Make sure that we also hide any visible sheets on our window.
1005 // Cocoa does the right thing for us.
1006 const QObjectList children = widget->children();
1007 const int childCount = children.count();
1008 for (int i = 0; i < childCount; ++i) {
1009 QObject *obj = children.at(i);
1010 if (obj->isWidgetType()) {
1011 QWidget *widget = static_cast<QWidget *>(obj);
1012 if (qt_mac_is_macsheet(widget) && widget->isVisible())
1013 widget->hide();
1014 }
1015 }
1016 } else {
1017 handled_event = false;
1018 }
1019 break; }
1020 case kEventClassMouse: {
1021#if 0
1022 return SendEventToApplication(event);
1023#endif
1024
1025 bool send_to_app = false;
1026 {
1027 WindowPartCode wpc;
1028 if (GetEventParameter(event, kEventParamWindowPartCode, typeWindowPartCode, 0,
1029 sizeof(wpc), 0, &wpc) == noErr && wpc != inContent)
1030 send_to_app = true;
1031 }
1032 if(!send_to_app) {
1033 WindowRef window;
1034 if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0,
1035 sizeof(window), 0, &window) == noErr) {
1036 HIViewRef hiview;
1037 if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) {
1038 if(QWidget *w = QWidget::find((WId)hiview)) {
1039#if 0
1040 send_to_app = !w->isActiveWindow();
1041#else
1042 Q_UNUSED(w);
1043 send_to_app = true;
1044#endif
1045 }
1046 }
1047 }
1048 }
1049 if(send_to_app)
1050 return SendEventToApplication(event);
1051 handled_event = false;
1052 break; }
1053
1054 case kEventClassGesture: {
1055 // First, find the widget that was under
1056 // the mouse when the gesture happened:
1057 HIPoint screenLocation;
1058 if (GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0,
1059 sizeof(screenLocation), 0, &screenLocation) != noErr) {
1060 handled_event = false;
1061 break;
1062 }
1063 QWidget *widget = QApplication::widgetAt(screenLocation.x, screenLocation.y);
1064 if (!widget) {
1065 handled_event = false;
1066 break;
1067 }
1068
1069 QNativeGestureEvent qNGEvent;
1070 qNGEvent.position = QPoint(screenLocation.x, screenLocation.y);
1071
1072 switch (ekind) {
1073 case kEventGestureStarted:
1074 qNGEvent.gestureType = QNativeGestureEvent::GestureBegin;
1075 break;
1076 case kEventGestureEnded:
1077 qNGEvent.gestureType = QNativeGestureEvent::GestureEnd;
1078 break;
1079 case kEventGestureRotate: {
1080 CGFloat amount;
1081 if (GetEventParameter(event, kEventParamRotationAmount, 'cgfl', 0,
1082 sizeof(amount), 0, &amount) != noErr) {
1083 handled_event = false;
1084 break;
1085 }
1086 qNGEvent.gestureType = QNativeGestureEvent::Rotate;
1087 qNGEvent.percentage = float(-amount);
1088 break; }
1089 case kEventGestureSwipe: {
1090 HIPoint swipeDirection;
1091 if (GetEventParameter(event, kEventParamSwipeDirection, typeHIPoint, 0,
1092 sizeof(swipeDirection), 0, &swipeDirection) != noErr) {
1093 handled_event = false;
1094 break;
1095 }
1096 qNGEvent.gestureType = QNativeGestureEvent::Swipe;
1097 if (swipeDirection.x == 1)
1098 qNGEvent.angle = 180.0f;
1099 else if (swipeDirection.x == -1)
1100 qNGEvent.angle = 0.0f;
1101 else if (swipeDirection.y == 1)
1102 qNGEvent.angle = 90.0f;
1103 else if (swipeDirection.y == -1)
1104 qNGEvent.angle = 270.0f;
1105 break; }
1106 case kEventGestureMagnify: {
1107 CGFloat amount;
1108 if (GetEventParameter(event, kEventParamMagnificationAmount, 'cgfl', 0,
1109 sizeof(amount), 0, &amount) != noErr) {
1110 handled_event = false;
1111 break;
1112 }
1113 qNGEvent.gestureType = QNativeGestureEvent::Zoom;
1114 qNGEvent.percentage = float(amount);
1115 break; }
1116 }
1117
1118 QApplication::sendSpontaneousEvent(widget, &qNGEvent);
1119 break; }
1120
1121 default:
1122 handled_event = false;
1123 }
1124 if(!handled_event) //let the event go through
1125 return eventNotHandledErr;
1126 return noErr; //we eat the event
1127}
1128
1129// widget events
1130static HIObjectClassRef widget_class = 0;
1131static EventTypeSpec widget_events[] = {
1132 { kEventClassHIObject, kEventHIObjectConstruct },
1133 { kEventClassHIObject, kEventHIObjectDestruct },
1134
1135 { kEventClassControl, kEventControlDraw },
1136 { kEventClassControl, kEventControlInitialize },
1137 { kEventClassControl, kEventControlGetPartRegion },
1138 { kEventClassControl, kEventControlGetClickActivation },
1139 { kEventClassControl, kEventControlSetFocusPart },
1140 { kEventClassControl, kEventControlDragEnter },
1141 { kEventClassControl, kEventControlDragWithin },
1142 { kEventClassControl, kEventControlDragLeave },
1143 { kEventClassControl, kEventControlDragReceive },
1144 { kEventClassControl, kEventControlOwningWindowChanged },
1145 { kEventClassControl, kEventControlBoundsChanged },
1146 { kEventClassControl, kEventControlGetSizeConstraints },
1147 { kEventClassControl, kEventControlVisibilityChanged },
1148
1149 { kEventClassMouse, kEventMouseDown },
1150 { kEventClassMouse, kEventMouseUp },
1151 { kEventClassMouse, kEventMouseMoved },
1152 { kEventClassMouse, kEventMouseDragged }
1153};
1154static EventHandlerUPP mac_widget_eventUPP = 0;
1155static void cleanup_widget_eventUPP()
1156{
1157 DisposeEventHandlerUPP(mac_widget_eventUPP);
1158 mac_widget_eventUPP = 0;
1159}
1160static const EventHandlerUPP make_widget_eventUPP()
1161{
1162 if(mac_widget_eventUPP)
1163 return mac_widget_eventUPP;
1164 qAddPostRoutine(cleanup_widget_eventUPP);
1165 return mac_widget_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_widget_event);
1166}
1167OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, void *)
1168{
1169 QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData);
1170
1171 bool handled_event = true;
1172 UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
1173 switch(eclass) {
1174 case kEventClassHIObject: {
1175 HIViewRef view = 0;
1176 GetEventParameter(event, kEventParamHIObjectInstance, typeHIObjectRef,
1177 0, sizeof(view), 0, &view);
1178 if(ekind == kEventHIObjectConstruct) {
1179 if(view) {
1180 HIViewChangeFeatures(view, kHIViewAllowsSubviews, 0);
1181 SetEventParameter(event, kEventParamHIObjectInstance,
1182 typeVoidPtr, sizeof(view), &view);
1183 }
1184 } else if(ekind == kEventHIObjectDestruct) {
1185 //nothing to really do.. or is there?
1186 } else {
1187 handled_event = false;
1188 }
1189 break; }
1190 case kEventClassControl: {
1191 QWidget *widget = 0;
1192 HIViewRef hiview = 0;
1193 if(GetEventParameter(event, kEventParamDirectObject, typeControlRef,
1194 0, sizeof(hiview), 0, &hiview) == noErr)
1195 widget = QWidget::find((WId)hiview);
1196 if (widget && widget->macEvent(er, event))
1197 return noErr;
1198 if(ekind == kEventControlDraw) {
1199 if(widget && qt_isGenuineQWidget(hiview)) {
1200
1201 // if there is a window change event pending for any gl child wigets,
1202 // send it immediately. (required for flicker-free resizing)
1203 extern void qt_mac_send_posted_gl_updates(QWidget *widget);
1204 qt_mac_send_posted_gl_updates(widget);
1205
1206 if (QApplicationPrivate::graphicsSystem() && !widget->d_func()->paintOnScreen()) {
1207 widget->d_func()->syncBackingStore();
1208 widget->d_func()->dirtyOnWidget = QRegion();
1209 return noErr;
1210 }
1211
1212 //requested rgn
1213 RgnHandle rgn;
1214 GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0, sizeof(rgn), 0, &rgn);
1215 QRegion qrgn(qt_mac_convert_mac_region(rgn));
1216
1217 //update handles
1218 GrafPtr qd = 0;
1219 CGContextRef cg = 0;
1220 if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) {
1221 Q_ASSERT(false);
1222 }
1223 widget->d_func()->hd = cg;
1224 widget->d_func()->qd_hd = qd;
1225 CGContextSaveGState(cg);
1226
1227#ifdef DEBUG_WIDGET_PAINT
1228 const bool doDebug = true;
1229 if(doDebug) {
1230 qDebug("asked to draw %p[%p] [%s::%s] %p[%p] [%d] [%dx%d]", widget, hiview, widget->metaObject()->className(),
1231 widget->objectName().local8Bit().data(), widget->parentWidget(),
1232 (HIViewRef)(widget->parentWidget() ? qt_mac_nativeview_for(widget->parentWidget()) : (HIViewRef)0),
1233 HIViewIsCompositingEnabled(hiview), qt_mac_posInWindow(widget).x(), qt_mac_posInWindow(widget).y());
1234#if 0
1235 QVector<QRect> region_rects = qrgn.rects();
1236 qDebug("Region! %d", region_rects.count());
1237 for(int i = 0; i < region_rects.count(); i++)
1238 qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(),
1239 region_rects[i].width(), region_rects[i].height());
1240 region_rects = widget->d_func()->clp.rects();
1241 qDebug("Widget Region! %d", region_rects.count());
1242 for(int i = 0; i < region_rects.count(); i++)
1243 qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(),
1244 region_rects[i].width(), region_rects[i].height());
1245#endif
1246 }
1247#endif
1248 if (widget->isVisible() && widget->updatesEnabled()) { //process the actual paint event.
1249 if(widget->testAttribute(Qt::WA_WState_InPaintEvent))
1250 qWarning("QWidget::repaint: Recursive repaint detected");
1251
1252 QPoint redirectionOffset(0, 0);
1253 QWidget *tl = widget->window();
1254 if (tl) {
1255 Qt::WindowFlags flags = tl->windowFlags();
1256 if (flags & Qt::FramelessWindowHint
1257 || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint))) {
1258 if(tl->d_func()->extra && !tl->d_func()->extra->mask.isEmpty())
1259 redirectionOffset += tl->d_func()->extra->mask.boundingRect().topLeft();
1260 }
1261 }
1262
1263 //setup the context
1264 widget->setAttribute(Qt::WA_WState_InPaintEvent);
1265 QPaintEngine *engine = widget->paintEngine();
1266 if (engine)
1267 engine->setSystemClip(qrgn);
1268
1269 //handle the erase
1270 if (engine && (!widget->testAttribute(Qt::WA_NoSystemBackground)
1271 && (widget->isWindow() || widget->autoFillBackground())
1272 || widget->testAttribute(Qt::WA_TintedBackground)
1273 || widget->testAttribute(Qt::WA_StyledBackground))) {
1274#ifdef DEBUG_WIDGET_PAINT
1275 if(doDebug)
1276 qDebug(" Handling erase for [%s::%s]", widget->metaObject()->className(),
1277 widget->objectName().local8Bit().data());
1278#endif
1279 if (!redirectionOffset.isNull())
1280 widget->d_func()->setRedirected(widget, redirectionOffset);
1281
1282 bool was_unclipped = widget->testAttribute(Qt::WA_PaintUnclipped);
1283 widget->setAttribute(Qt::WA_PaintUnclipped, false);
1284 QPainter p(widget);
1285 p.setClipping(false);
1286 if(was_unclipped)
1287 widget->setAttribute(Qt::WA_PaintUnclipped);
1288 widget->d_func()->paintBackground(&p, qrgn, widget->isWindow() ? DrawAsRoot : 0);
1289 if (widget->testAttribute(Qt::WA_TintedBackground)) {
1290 QColor tint = widget->palette().window().color();
1291 tint.setAlphaF(.6);
1292 const QVector<QRect> &rects = qrgn.rects();
1293 for (int i = 0; i < rects.size(); ++i)
1294 p.fillRect(rects.at(i), tint);
1295 }
1296 p.end();
1297 if (!redirectionOffset.isNull())
1298 widget->d_func()->restoreRedirected();
1299 }
1300
1301 if (widget->isWindow() && !widget->d_func()->isOpaque
1302 && !widget->testAttribute(Qt::WA_MacBrushedMetal)) {
1303 QRect qrgnRect = qrgn.boundingRect();
1304 CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height()));
1305 }
1306
1307
1308 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
1309 CallNextEventHandler(er, event);
1310
1311 //send the paint
1312 redirectionOffset += widget->data->wrect.topLeft(); // Map from system to qt coordinates
1313 if (!redirectionOffset.isNull())
1314 widget->d_func()->setRedirected(widget, redirectionOffset);
1315 qrgn.translate(redirectionOffset);
1316 QPaintEvent e(qrgn);
1317 widget->d_func()->dirtyOnWidget = QRegion();
1318#ifdef QT3_SUPPORT
1319 e.setErased(true);
1320#endif
1321 QApplication::sendSpontaneousEvent(widget, &e);
1322 if (!redirectionOffset.isNull())
1323 widget->d_func()->restoreRedirected();
1324
1325 //cleanup
1326 if (engine)
1327 engine->setSystemClip(QRegion());
1328
1329 widget->setAttribute(Qt::WA_WState_InPaintEvent, false);
1330 if(!widget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && widget->paintingActive())
1331 qWarning("QWidget: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1332 }
1333
1334 widget->d_func()->hd = 0;
1335 widget->d_func()->qd_hd = 0;
1336 CGContextRestoreGState(cg);
1337 } else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) {
1338 CallNextEventHandler(er, event);
1339 }
1340 } else if(ekind == kEventControlInitialize) {
1341 if(HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) {
1342 UInt32 features = kControlSupportsDragAndDrop | kControlSupportsClickActivation | kControlSupportsFocus;
1343 SetEventParameter(event, kEventParamControlFeatures, typeUInt32, sizeof(features), &features);
1344 } else {
1345 handled_event = false;
1346 }
1347 } else if(ekind == kEventControlSetFocusPart) {
1348 if(widget) {
1349 ControlPartCode part;
1350 GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0,
1351 sizeof(part), 0, &part);
1352 if(part == kControlFocusNoPart){
1353 if (widget->hasFocus())
1354 QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
1355 } else
1356 widget->setFocus();
1357 }
1358 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
1359 CallNextEventHandler(er, event);
1360 } else if(ekind == kEventControlGetClickActivation) {
1361 ClickActivationResult clickT = kActivateAndIgnoreClick;
1362 SetEventParameter(event, kEventParamClickActivation, typeClickActivationResult,
1363 sizeof(clickT), &clickT);
1364 } else if(ekind == kEventControlGetPartRegion) {
1365 handled_event = false;
1366 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget) && CallNextEventHandler(er, event) == noErr) {
1367 handled_event = true;
1368 break;
1369 }
1370 if(widget && !widget->isWindow()) {
1371 ControlPartCode part;
1372 GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0,
1373 sizeof(part), 0, &part);
1374 if(part == kControlClickableMetaPart && widget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
1375 RgnHandle rgn;
1376 GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0,
1377 sizeof(rgn), 0, &rgn);
1378 SetEmptyRgn(rgn);
1379 handled_event = true;
1380 } else if(part == kControlStructureMetaPart || part == kControlClickableMetaPart) {
1381 RgnHandle rgn;
1382 GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0,
1383 sizeof(rgn), 0, &rgn);
1384 SetRectRgn(rgn, 0, 0, widget->width(), widget->height());
1385 if(QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false))
1386 handled_event = true;
1387 } else if(part == kControlOpaqueMetaPart) {
1388 if(widget->d_func()->isOpaque) {
1389 RgnHandle rgn;
1390 GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0,
1391 sizeof(RgnHandle), 0, &rgn);
1392 SetRectRgn(rgn, 0, 0, widget->width(), widget->height());
1393 QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false);
1394 SetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle,
1395 sizeof(RgnHandle), &rgn);
1396 handled_event = true;
1397 }
1398 }
1399 }
1400 } else if(ekind == kEventControlOwningWindowChanged) {
1401 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
1402 CallNextEventHandler(er, event);
1403 if(widget && qt_mac_window_for(hiview)) {
1404 WindowRef foo = 0;
1405 GetEventParameter(event, kEventParamControlCurrentOwningWindow, typeWindowRef, 0,
1406 sizeof(foo), 0, &foo);
1407 widget->d_func()->initWindowPtr();
1408 }
1409 if (widget)
1410 qt_event_request_window_change(widget);
1411 } else if(ekind == kEventControlDragEnter || ekind == kEventControlDragWithin ||
1412 ekind == kEventControlDragLeave || ekind == kEventControlDragReceive) {
1413 // dnd are really handled in qdnd_mac.cpp,
1414 // just modularize the code a little...
1415 DragRef drag;
1416 GetEventParameter(event, kEventParamDragRef, typeDragRef, 0, sizeof(drag), 0, &drag);
1417 handled_event = false;
1418 bool drag_allowed = false;
1419
1420 QWidget *dropWidget = widget;
1421 if (qobject_cast<QFocusFrame *>(widget)){
1422 // We might shadow widgets underneath the focus
1423 // frame, so stay interrested, and let the dnd through
1424 drag_allowed = true;
1425 handled_event = true;
1426 Point where;
1427 GetDragMouse(drag, &where, 0);
1428 dropWidget = QApplication::widgetAt(QPoint(where.h, where.v));
1429
1430 if (dropWidget != QDragManager::self()->currentTarget()) {
1431 // We have to 'fake' enter and leave events for the shaddowed widgets:
1432 if (ekind == kEventControlDragEnter) {
1433 if (QDragManager::self()->currentTarget())
1434 QDragManager::self()->currentTarget()->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag);
1435 if (dropWidget) {
1436 dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragEnter, drag);
1437 }
1438 // Set dropWidget to zero, so qt_mac_dnd_event
1439 // doesn't get called a second time below:
1440 dropWidget = 0;
1441 } else if (ekind == kEventControlDragLeave) {
1442 dropWidget = QDragManager::self()->currentTarget();
1443 if (dropWidget) {
1444 dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag);
1445 }
1446 // Set dropWidget to zero, so qt_mac_dnd_event
1447 // doesn't get called a second time below:
1448 dropWidget = 0;
1449 }
1450 }
1451 }
1452
1453 // Send the dnd event to the widget:
1454 if (dropWidget && dropWidget->d_func()->qt_mac_dnd_event(ekind, drag)) {
1455 drag_allowed = true;
1456 handled_event = true;
1457 }
1458
1459 if (ekind == kEventControlDragEnter) {
1460 // If we don't accept the enter event, we will
1461 // receive no more drag events for this widget
1462 const Boolean wouldAccept = drag_allowed ? true : false;
1463 SetEventParameter(event, kEventParamControlWouldAcceptDrop, typeBoolean,
1464 sizeof(wouldAccept), &wouldAccept);
1465 }
1466 } else if (ekind == kEventControlBoundsChanged) {
1467 if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_Moved) || widget->testAttribute(Qt::WA_Resized)) {
1468 handled_event = false;
1469 } else {
1470 // Sync our view in case some other (non-Qt) view is controlling us.
1471 handled_event = true;
1472 Rect newBounds;
1473 GetEventParameter(event, kEventParamCurrentBounds,
1474 typeQDRectangle, 0, sizeof(Rect), 0, &newBounds);
1475 QRect rect(newBounds.left, newBounds.top,
1476 newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
1477
1478 bool moved = widget->testAttribute(Qt::WA_Moved);
1479 bool resized = widget->testAttribute(Qt::WA_Resized);
1480 widget->setGeometry(rect);
1481 widget->setAttribute(Qt::WA_Moved, moved);
1482 widget->setAttribute(Qt::WA_Resized, resized);
1483 qt_event_request_window_change(widget);
1484 }
1485 } else if (ekind == kEventControlGetSizeConstraints) {
1486 if (!widget || !qt_isGenuineQWidget(widget)) {
1487 handled_event = false;
1488 } else {
1489 handled_event = true;
1490 QWidgetItem item(widget);
1491 QSize size = item.minimumSize();
1492 HISize hisize = { size.width(), size.height() };
1493 SetEventParameter(event, kEventParamMinimumSize, typeHISize, sizeof(HISize), &hisize);
1494 size = item.maximumSize();
1495 hisize.width = size.width() + 2; // ### shouldn't have to add 2 (but it works).
1496 hisize.height = size.height();
1497 SetEventParameter(event, kEventParamMaximumSize, typeHISize, sizeof(HISize), &hisize);
1498 }
1499 } else if (ekind == kEventControlVisibilityChanged) {
1500 handled_event = false;
1501 if (widget) {
1502 qt_event_request_window_change(widget);
1503 if (!HIViewIsVisible(HIViewRef(widget->winId()))) {
1504 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
1505 if (widget == qt_button_down)
1506 qt_button_down = 0;
1507 }
1508 }
1509 }
1510 break; }
1511 case kEventClassMouse: {
1512 bool send_to_app = false;
1513 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
1514 if(qt_button_down)
1515 send_to_app = true;
1516 if(send_to_app) {
1517 OSStatus err = SendEventToApplication(event);
1518 if(err != noErr)
1519 handled_event = false;
1520 } else {
1521 CallNextEventHandler(er, event);
1522 }
1523 break; }
1524 default:
1525 handled_event = false;
1526 break;
1527 }
1528 if(!handled_event) //let the event go through
1529 return eventNotHandledErr;
1530 return noErr; //we eat the event
1531}
1532#endif
1533
1534OSViewRef qt_mac_create_widget(QWidget *widget, QWidgetPrivate *widgetPrivate, OSViewRef parent)
1535{
1536#ifdef QT_MAC_USE_COCOA
1537 QMacCocoaAutoReleasePool pool;
1538 QT_MANGLE_NAMESPACE(QCocoaView) *view = [[QT_MANGLE_NAMESPACE(QCocoaView) alloc] initWithQWidget:widget widgetPrivate:widgetPrivate];
1539 if (view && parent)
1540 [parent addSubview:view];
1541 return view;
1542#else
1543 Q_UNUSED(widget);
1544 Q_UNUSED(widgetPrivate);
1545 if(!widget_class) {
1546 OSStatus err = HIObjectRegisterSubclass(kObjectQWidget, kHIViewClassID, 0, make_widget_eventUPP(),
1547 GetEventTypeCount(widget_events), widget_events,
1548 0, &widget_class);
1549 if (err && err != hiObjectClassExistsErr)
1550 qWarning("QWidget: Internal error (%d)", __LINE__);
1551 }
1552 HIViewRef ret = 0;
1553 if(HIObjectCreate(kObjectQWidget, 0, (HIObjectRef*)&ret) != noErr)
1554 qWarning("QWidget: Internal error (%d)", __LINE__);
1555 if(ret && parent)
1556 HIViewAddSubview(parent, ret);
1557 return ret;
1558#endif
1559}
1560
1561void qt_mac_unregister_widget()
1562{
1563#ifndef QT_MAC_USE_COCOA
1564 HIObjectUnregisterClass(widget_class);
1565 widget_class = 0;
1566#endif
1567}
1568
1569void QWidgetPrivate::toggleDrawers(bool visible)
1570{
1571 for (int i = 0; i < children.size(); ++i) {
1572 register QObject *object = children.at(i);
1573 if (!object->isWidgetType())
1574 continue;
1575 QWidget *widget = static_cast<QWidget*>(object);
1576 if(qt_mac_is_macdrawer(widget)) {
1577 if(visible) {
1578 if (!widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
1579 widget->show();
1580 } else {
1581 widget->hide();
1582 widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
1583 }
1584 }
1585 }
1586}
1587
1588/*****************************************************************************
1589 QWidgetPrivate member functions
1590 *****************************************************************************/
1591bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up)
1592{
1593 // I'm not sure what "up" is
1594 if(!w || !w->isWindow())
1595 return false;
1596
1597 QTLWExtra *topData = w->d_func()->topData();
1598 QWExtra *extraData = w->d_func()->extraData();
1599 // topData->resizer is only 4 bits, so subtracting -1 from zero causes bad stuff
1600 // to happen, prevent that here (you really want the thing hidden).
1601 if (up >= 0 || topData->resizer != 0)
1602 topData->resizer += up;
1603 OSWindowRef windowRef = qt_mac_window_for(OSViewRef(w->winId()));
1604 {
1605#ifndef QT_MAC_USE_COCOA
1606 WindowClass wclass;
1607 GetWindowClass(windowRef, &wclass);
1608 if(!(GetAvailableWindowAttributes(wclass) & kWindowResizableAttribute))
1609 return true;
1610#endif
1611 }
1612 bool remove_grip = (topData->resizer || (w->windowFlags() & Qt::FramelessWindowHint)
1613 || (extraData->maxw && extraData->maxh &&
1614 extraData->maxw == extraData->minw && extraData->maxh == extraData->minh));
1615#ifndef QT_MAC_USE_COCOA
1616 WindowAttributes attr;
1617 GetWindowAttributes(windowRef, &attr);
1618 if(remove_grip) {
1619 if(attr & kWindowResizableAttribute) {
1620 ChangeWindowAttributes(qt_mac_window_for(w), kWindowNoAttributes,
1621 kWindowResizableAttribute);
1622 ReshapeCustomWindow(qt_mac_window_for(w));
1623 }
1624 } else if(!(attr & kWindowResizableAttribute)) {
1625 ChangeWindowAttributes(windowRef, kWindowResizableAttribute,
1626 kWindowNoAttributes);
1627 ReshapeCustomWindow(windowRef);
1628 }
1629#else
1630 [windowRef setShowsResizeIndicator:!remove_grip];
1631#endif
1632 return true;
1633}
1634
1635void QWidgetPrivate::qt_clean_root_win()
1636{
1637#ifdef QT_MAC_USE_COCOA
1638 [qt_root_win release];
1639#else
1640 if(!qt_root_win)
1641 return;
1642 CFRelease(qt_root_win);
1643#endif
1644 qt_root_win = 0;
1645}
1646
1647bool QWidgetPrivate::qt_create_root_win()
1648{
1649 if(qt_root_win)
1650 return false;
1651 const QSize desktopSize = qt_mac_desktopSize();
1652 QRect desktopRect(QPoint(0, 0), desktopSize);
1653#ifdef QT_MAC_USE_COCOA
1654 qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, NSBorderlessWindowMask, desktopRect);
1655#else
1656 WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute);
1657 qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, wattr, desktopRect);
1658#endif
1659 if(!qt_root_win)
1660 return false;
1661 qAddPostRoutine(qt_clean_root_win);
1662 return true;
1663}
1664
1665bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false)
1666{
1667 bool ret = false;
1668#ifndef QT_MAC_USE_COCOA
1669 switch(wcode) {
1670 case kWindowStructureRgn: {
1671 if(widget) {
1672 if(widget->d_func()->extra && !widget->d_func()->extra->mask.isEmpty()) {
1673 QRegion rin = qt_mac_convert_mac_region(rgn);
1674 if(!rin.isEmpty()) {
1675 QPoint rin_tl = rin.boundingRect().topLeft(); //in offset
1676 rin.translate(-rin_tl.x(), -rin_tl.y()); //bring into same space as below
1677 QRegion mask = widget->d_func()->extra->mask;
1678 Qt::WindowFlags flags = widget->windowFlags();
1679 if(widget->isWindow()
1680 && !(flags & Qt::FramelessWindowHint
1681 || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint)))) {
1682 QRegion title;
1683 {
1684 QMacSmartQuickDrawRegion rgn(qt_mac_get_rgn());
1685 GetWindowRegion(qt_mac_window_for(widget), kWindowTitleBarRgn, rgn);
1686 title = qt_mac_convert_mac_region(rgn);
1687 }
1688 QRect br = title.boundingRect();
1689 mask.translate(0, br.height()); //put the mask 'under' the title bar..
1690 title.translate(-br.x(), -br.y());
1691 mask += title;
1692 }
1693
1694 QRegion cr = rin & mask;
1695 cr.translate(rin_tl.x(), rin_tl.y()); //translate back to incoming space
1696 CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn);
1697 }
1698 ret = true;
1699 } else if(force) {
1700 QRegion cr(widget->geometry());
1701 CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn);
1702 ret = true;
1703 }
1704 }
1705 break; }
1706 default: break;
1707 }
1708 //qDebug() << widget << ret << wcode << qt_mac_convert_mac_region(rgn);
1709#else
1710 Q_UNUSED(widget);
1711 Q_UNUSED(wcode);
1712 Q_UNUSED(rgn);
1713 Q_UNUSED(force);
1714#endif
1715 return ret;
1716}
1717
1718/*****************************************************************************
1719 QWidget member functions
1720 *****************************************************************************/
1721void QWidgetPrivate::determineWindowClass()
1722{
1723 Q_Q(QWidget);
1724#ifndef QT_MAC_USE_COCOA
1725// ### COCOA:Interleave these better!
1726
1727 const Qt::WindowType type = q->windowType();
1728 Qt::WindowFlags &flags = data.window_flags;
1729 const bool popup = (type == Qt::Popup);
1730 if (type == Qt::ToolTip || type == Qt::SplashScreen || popup)
1731 flags |= Qt::FramelessWindowHint;
1732
1733 WindowClass wclass = kSheetWindowClass;
1734 if(qt_mac_is_macdrawer(q))
1735 wclass = kDrawerWindowClass;
1736 else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint)
1737 wclass = kDocumentWindowClass;
1738 else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen))
1739 wclass = kModalWindowClass;
1740 else if(q->testAttribute(Qt::WA_ShowModal))
1741 wclass = kMovableModalWindowClass;
1742 else if(type == Qt::ToolTip)
1743 wclass = kHelpWindowClass;
1744 else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5
1745 && type == Qt::SplashScreen))
1746 wclass = kFloatingWindowClass;
1747 else
1748 wclass = kDocumentWindowClass;
1749
1750 WindowGroupRef grp = 0;
1751 WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute);
1752 if (q->testAttribute(Qt::WA_MacFrameworkScaled))
1753 wattr |= kWindowFrameworkScaledAttribute;
1754 if(qt_mac_is_macsheet(q)) {
1755 //grp = GetWindowGroupOfClass(kMovableModalWindowClass);
1756 wclass = kSheetWindowClass;
1757 } else {
1758 grp = GetWindowGroupOfClass(wclass);
1759 // Shift things around a bit to get the correct window class based on the presence
1760 // (or lack) of the border.
1761 bool customize = flags & Qt::CustomizeWindowHint;
1762 bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint)));
1763 if (framelessWindow) {
1764 if(wclass == kDocumentWindowClass) {
1765 wattr |= kWindowNoTitleBarAttribute;
1766 } else if(wclass == kFloatingWindowClass) {
1767 wattr |= kWindowNoTitleBarAttribute;
1768 } else if (wclass == kMovableModalWindowClass) {
1769 wclass = kModalWindowClass;
1770 }
1771 } else {
1772 if(wclass != kModalWindowClass)
1773 wattr |= kWindowResizableAttribute;
1774 }
1775 // Only add extra decorations (well, buttons) for widgets that can have them
1776 // and have an actual border we can put them on.
1777 if(wclass != kModalWindowClass && wclass != kMovableModalWindowClass
1778 && wclass != kSheetWindowClass && wclass != kPlainWindowClass
1779 && !framelessWindow && wclass != kDrawerWindowClass
1780 && wclass != kHelpWindowClass) {
1781 if (flags & Qt::WindowMaximizeButtonHint)
1782 wattr |= kWindowFullZoomAttribute;
1783 if (flags & Qt::WindowMinimizeButtonHint)
1784 wattr |= kWindowCollapseBoxAttribute;
1785 if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint)
1786 wattr |= kWindowCloseBoxAttribute;
1787 if (flags & Qt::MacWindowToolBarButtonHint)
1788 wattr |= kWindowToolbarButtonAttribute;
1789 } else {
1790 // Clear these hints so that we aren't call them on invalid windows
1791 flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint
1792 | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
1793 }
1794 }
1795 if((popup || type == Qt::Tool) && !q->isModal())
1796 wattr |= kWindowHideOnSuspendAttribute;
1797 wattr |= kWindowLiveResizeAttribute;
1798
1799#ifdef DEBUG_WINDOW_CREATE
1800#define ADD_DEBUG_WINDOW_NAME(x) { x, #x }
1801 struct {
1802 UInt32 tag;
1803 const char *name;
1804 } known_attribs[] = {
1805 ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute),
1806 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1807 ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute),
1808 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1809 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1810 ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute),
1811 ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute),
1812 ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute),
1813 ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute),
1814 ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute),
1815 ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute),
1816 ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute),
1817 ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute),
1818 ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute),
1819 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1820 { 0, 0 }
1821 }, known_classes[] = {
1822 ADD_DEBUG_WINDOW_NAME(kHelpWindowClass),
1823 ADD_DEBUG_WINDOW_NAME(kPlainWindowClass),
1824 ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass),
1825 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1826 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1827 ADD_DEBUG_WINDOW_NAME(kSheetWindowClass),
1828 ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass),
1829 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1830 ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass),
1831 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1832 ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass),
1833 ADD_DEBUG_WINDOW_NAME(kModalWindowClass),
1834 { 0, 0 }
1835 };
1836 qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(),
1837 q->objectName().toLocal8Bit().constData());
1838 bool found_class = false;
1839 for(int i = 0; known_classes[i].name; i++) {
1840 if(wclass == known_classes[i].tag) {
1841 found_class = true;
1842 qDebug("Qt: internal: ** Class: %s", known_classes[i].name);
1843 break;
1844 }
1845 }
1846 if(!found_class)
1847 qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass);
1848 if(wattr) {
1849 WindowAttributes tmp_wattr = wattr;
1850 qDebug("Qt: internal: ** Attributes:");
1851 for(int i = 0; tmp_wattr && known_attribs[i].name; i++) {
1852 if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) {
1853 tmp_wattr ^= known_attribs[i].tag;
1854 qDebug("Qt: internal: * %s %s", known_attribs[i].name,
1855 (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)");
1856 }
1857 }
1858 if(tmp_wattr)
1859 qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr);
1860 }
1861#endif
1862
1863 /* Just to be extra careful we will change to the kUtilityWindowClass if the
1864 requested attributes cannot be used */
1865 if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) {
1866 WindowClass tmp_class = wclass;
1867 if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass)
1868 wclass = kFloatingWindowClass;
1869 if(tmp_class != wclass) {
1870 if(!grp)
1871 grp = GetWindowGroupOfClass(wclass);
1872 wclass = tmp_class;
1873 }
1874 }
1875 topData()->wclass = wclass;
1876 topData()->wattr = wattr;
1877#else
1878 const Qt::WindowType type = q->windowType();
1879 Qt::WindowFlags &flags = data.window_flags;
1880 const bool popup = (type == Qt::Popup);
1881 if (type == Qt::ToolTip || type == Qt::SplashScreen || popup)
1882 flags |= Qt::FramelessWindowHint;
1883
1884 WindowClass wclass = kSheetWindowClass;
1885 if(qt_mac_is_macdrawer(q))
1886 wclass = kDrawerWindowClass;
1887 else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint)
1888 wclass = kDocumentWindowClass;
1889 else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen))
1890 wclass = kModalWindowClass;
1891 else if(q->testAttribute(Qt::WA_ShowModal) || type == Qt::Dialog)
1892 wclass = kMovableModalWindowClass;
1893 else if(type == Qt::ToolTip)
1894 wclass = kHelpWindowClass;
1895 else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5
1896 && type == Qt::SplashScreen))
1897 wclass = kFloatingWindowClass;
1898 else
1899 wclass = kDocumentWindowClass;
1900
1901 WindowAttributes wattr = NSBorderlessWindowMask;
1902 if(qt_mac_is_macsheet(q)) {
1903 //grp = GetWindowGroupOfClass(kMovableModalWindowClass);
1904 wclass = kSheetWindowClass;
1905 wattr = NSTitledWindowMask | NSResizableWindowMask;
1906 } else {
1907#ifndef QT_MAC_USE_COCOA
1908 grp = GetWindowGroupOfClass(wclass);
1909#endif
1910 // Shift things around a bit to get the correct window class based on the presence
1911 // (or lack) of the border.
1912 bool customize = flags & Qt::CustomizeWindowHint;
1913 bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint)));
1914 if (framelessWindow) {
1915 if (wclass == kDocumentWindowClass) {
1916 wclass = kSimpleWindowClass;
1917 } else if (wclass == kFloatingWindowClass) {
1918 wclass = kToolbarWindowClass;
1919 } else if (wclass == kMovableModalWindowClass) {
1920 wclass = kModalWindowClass;
1921 }
1922 } else {
1923 wattr |= NSTitledWindowMask;
1924 if (wclass != kModalWindowClass)
1925 wattr |= NSResizableWindowMask;
1926 }
1927 // Only add extra decorations (well, buttons) for widgets that can have them
1928 // and have an actual border we can put them on.
1929 if (wclass != kModalWindowClass
1930 && wclass != kSheetWindowClass && wclass != kPlainWindowClass
1931 && !framelessWindow && wclass != kDrawerWindowClass
1932 && wclass != kHelpWindowClass) {
1933 if (flags & Qt::WindowMinimizeButtonHint)
1934 wattr |= NSMiniaturizableWindowMask;
1935 if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint)
1936 wattr |= NSClosableWindowMask;
1937 } else {
1938 // Clear these hints so that we aren't call them on invalid windows
1939 flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint
1940 | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
1941 }
1942 }
1943 if (q->testAttribute(Qt::WA_MacBrushedMetal))
1944 wattr |= NSTexturedBackgroundWindowMask;
1945
1946#ifdef DEBUG_WINDOW_CREATE
1947#define ADD_DEBUG_WINDOW_NAME(x) { x, #x }
1948 struct {
1949 UInt32 tag;
1950 const char *name;
1951 } known_attribs[] = {
1952 ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute),
1953 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1954 ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute),
1955 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1956 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1957 ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute),
1958 ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute),
1959 ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute),
1960 ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute),
1961 ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute),
1962 ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute),
1963 ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute),
1964 ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute),
1965 ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute),
1966 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1967 { 0, 0 }
1968 }, known_classes[] = {
1969 ADD_DEBUG_WINDOW_NAME(kHelpWindowClass),
1970 ADD_DEBUG_WINDOW_NAME(kPlainWindowClass),
1971 ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass),
1972 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1973 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1974 ADD_DEBUG_WINDOW_NAME(kSheetWindowClass),
1975 ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass),
1976 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1977 ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass),
1978 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1979 ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass),
1980 ADD_DEBUG_WINDOW_NAME(kModalWindowClass),
1981 { 0, 0 }
1982 };
1983 qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(),
1984 q->objectName().toLocal8Bit().constData());
1985 bool found_class = false;
1986 for(int i = 0; known_classes[i].name; i++) {
1987 if(wclass == known_classes[i].tag) {
1988 found_class = true;
1989 qDebug("Qt: internal: ** Class: %s", known_classes[i].name);
1990 break;
1991 }
1992 }
1993 if(!found_class)
1994 qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass);
1995 if(wattr) {
1996 WindowAttributes tmp_wattr = wattr;
1997 qDebug("Qt: internal: ** Attributes:");
1998 for(int i = 0; tmp_wattr && known_attribs[i].name; i++) {
1999 if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) {
2000 tmp_wattr ^= known_attribs[i].tag;
2001 qDebug("Qt: internal: * %s %s", known_attribs[i].name,
2002 (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)");
2003 }
2004 }
2005 if(tmp_wattr)
2006 qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr);
2007 }
2008#endif
2009
2010#ifndef QT_MAC_USE_COCOA
2011 /* Just to be extra careful we will change to the kUtilityWindowClass if the
2012 requested attributes cannot be used */
2013 if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) {
2014 WindowClass tmp_class = wclass;
2015 if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass)
2016 wclass = kFloatingWindowClass;
2017 if(tmp_class != wclass) {
2018 if(!grp)
2019 grp = GetWindowGroupOfClass(wclass);
2020 wclass = tmp_class;
2021 }
2022 }
2023#endif
2024#endif
2025 topData()->wclass = wclass;
2026 topData()->wattr = wattr;
2027}
2028
2029#ifndef QT_MAC_USE_COCOA // This is handled in Cocoa via our category.
2030void QWidgetPrivate::initWindowPtr()
2031{
2032 Q_Q(QWidget);
2033 OSWindowRef windowRef = qt_mac_window_for(qt_mac_nativeview_for(q)); //do not create!
2034 if(!windowRef)
2035 return;
2036 QWidget *window = q->window(), *oldWindow = 0;
2037 if(GetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(oldWindow), 0, &oldWindow) == noErr) {
2038 Q_ASSERT(window == oldWindow);
2039 return;
2040 }
2041
2042 if(SetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(window), &window) != noErr)
2043 qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__); //no real way to recover
2044 if(!q->windowType() != Qt::Desktop) { //setup an event callback handler on the window
2045 InstallWindowEventHandler(windowRef, make_win_eventUPP(), GetEventTypeCount(window_events),
2046 window_events, static_cast<void *>(qApp), &window_event);
2047 }
2048}
2049
2050void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef)
2051{
2052 Q_Q(QWidget);
2053 const Qt::WindowType type = q->windowType();
2054 Qt::WindowFlags &flags = data.window_flags;
2055 QWidget *parentWidget = q->parentWidget();
2056
2057 const bool desktop = (type == Qt::Desktop);
2058 const bool dialog = (type == Qt::Dialog
2059 || type == Qt::Sheet
2060 || type == Qt::Drawer
2061 || (flags & Qt::MSWindowsFixedSizeDialogHint));
2062 QTLWExtra *topExtra = topData();
2063 quint32 wattr = topExtra->wattr;
2064 if (!desktop)
2065 SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true);
2066 HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0);
2067 if (wattr & kWindowHideOnSuspendAttribute)
2068 HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0);
2069 else
2070 HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden);
2071 if ((flags & Qt::WindowStaysOnTopHint))
2072 ChangeWindowAttributes(windowRef, kWindowNoAttributes, kWindowHideOnSuspendAttribute);
2073 if (qt_mac_is_macdrawer(q) && parentWidget)
2074 SetDrawerParent(windowRef, qt_mac_window_for (parentWidget));
2075 if (topExtra->group) {
2076 qt_mac_release_window_group(topExtra->group);
2077 topExtra->group = 0;
2078 }
2079 if (type == Qt::ToolTip)
2080 qt_mac_set_window_group_to_tooltip(windowRef);
2081 else if (type == Qt::Popup && (flags & Qt::WindowStaysOnTopHint))
2082 qt_mac_set_window_group_to_popup(windowRef);
2083 else if (flags & Qt::WindowStaysOnTopHint)
2084 qt_mac_set_window_group_to_stays_on_top(windowRef, type);
2085 else if (dialog)
2086 SetWindowGroup(windowRef, GetWindowGroupOfClass(kMovableModalWindowClass));
2087
2088#ifdef DEBUG_WINDOW_CREATE
2089 if (WindowGroupRef grpf = GetWindowGroup(windowRef)) {
2090 QCFString cfname;
2091 CopyWindowGroupName(grpf, &cfname);
2092 SInt32 lvl;
2093 GetWindowGroupLevel(grpf, &lvl);
2094 const char *from = "Default";
2095 if (topExtra && grpf == topData()->group)
2096 from = "Created";
2097 else if (grpf == grp)
2098 from = "Copied";
2099 qDebug("Qt: internal: With window group '%s' [%p] @ %d: %s",
2100 static_cast<QString>(cfname).toLatin1().constData(), grpf, (int)lvl, from);
2101 } else {
2102 qDebug("Qt: internal: No window group!!!");
2103 }
2104 HIWindowAvailability hi_avail = 0;
2105 if (HIWindowGetAvailability(windowRef, &hi_avail) == noErr) {
2106 struct {
2107 UInt32 tag;
2108 const char *name;
2109 } known_avail[] = {
2110 ADD_DEBUG_WINDOW_NAME(kHIWindowExposeHidden),
2111 { 0, 0 }
2112 };
2113 qDebug("Qt: internal: ** HIWindowAvailibility:");
2114 for (int i = 0; hi_avail && known_avail[i].name; i++) {
2115 if ((hi_avail & known_avail[i].tag) == known_avail[i].tag) {
2116 hi_avail ^= known_avail[i].tag;
2117 qDebug("Qt: internal: * %s", known_avail[i].name);
2118 }
2119 }
2120 if (hi_avail)
2121 qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)hi_avail);
2122 }
2123#undef ADD_DEBUG_WINDOW_NAME
2124#endif
2125 if (extra && !extra->mask.isEmpty())
2126 ReshapeCustomWindow(windowRef);
2127 SetWindowModality(windowRef, kWindowModalityNone, 0);
2128 if (qt_mac_is_macdrawer(q))
2129 SetDrawerOffsets(windowRef, 0.0, 25.0);
2130 data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty
2131 HIViewRef hiview = (HIViewRef)data.winid;
2132 HIViewRef window_hiview = qt_mac_get_contentview_for(windowRef);
2133 if(!hiview) {
2134 hiview = qt_mac_create_widget(q, this, window_hiview);
2135 setWinId((WId)hiview);
2136 } else {
2137 HIViewAddSubview(window_hiview, hiview);
2138 }
2139 if (hiview) {
2140 Rect win_rect;
2141 GetWindowBounds(qt_mac_window_for (window_hiview), kWindowContentRgn, &win_rect);
2142 HIRect bounds = CGRectMake(0, 0, win_rect.right-win_rect.left, win_rect.bottom-win_rect.top);
2143 HIViewSetFrame(hiview, &bounds);
2144 HIViewSetVisible(hiview, true);
2145 if (q->testAttribute(Qt::WA_DropSiteRegistered))
2146 registerDropSite(true);
2147 transferChildren();
2148 }
2149 initWindowPtr();
2150
2151 if (topExtra->posFromMove) {
2152 updateFrameStrut();
2153 const QRect &fStrut = frameStrut();
2154 Rect r;
2155 SetRect(&r, data.crect.left(), data.crect.top(), data.crect.right() + 1, data.crect.bottom() + 1);
2156 SetRect(&r, r.left + fStrut.left(), r.top + fStrut.top(),
2157 (r.left + fStrut.left() + data.crect.width()) - fStrut.right(),
2158 (r.top + fStrut.top() + data.crect.height()) - fStrut.bottom());
2159 SetWindowBounds(windowRef, kWindowContentRgn, &r);
2160 topExtra->posFromMove = false;
2161 }
2162
2163 if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){
2164 q->setWindowOpacity(topExtra->opacity / 255.0f);
2165 } else if (qt_mac_is_macsheet(q)){
2166 SetThemeWindowBackground(qt_mac_window_for(q), kThemeBrushSheetBackgroundTransparent, true);
2167 CGFloat alpha = 0;
2168 GetWindowAlpha(qt_mac_window_for(q), &alpha);
2169 if (alpha == 1){
2170 // For some reason the 'SetThemeWindowBackground' does not seem
2171 // to work. So we do this little hack until it hopefully starts to
2172 // work in newer versions of mac OS.
2173 q->setWindowOpacity(0.95f);
2174 q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
2175 }
2176 } else{
2177 // If the window has been recreated after beeing e.g. a sheet,
2178 // make sure that we don't report a faulty opacity:
2179 q->setWindowOpacity(1.0f);
2180 q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
2181 }
2182
2183 // Since we only now have a window, sync our state.
2184 macUpdateHideOnSuspend();
2185 macUpdateOpaqueSizeGrip();
2186 macUpdateMetalAttribute();
2187 macUpdateIgnoreMouseEvents();
2188 setWindowTitle_helper(extra->topextra->caption);
2189 setWindowIconText_helper(extra->topextra->iconText);
2190 setWindowFilePath_helper(extra->topextra->filePath);
2191 setWindowModified_sys(q->isWindowModified());
2192 updateFrameStrut();
2193 qt_mac_update_sizer(q);
2194 applyMaxAndMinSizeOnWindow();
2195}
2196#else // QT_MAC_USE_COCOA
2197void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef)
2198{
2199 Q_Q(QWidget);
2200 QMacCocoaAutoReleasePool pool;
2201 NSWindow *windowRef = static_cast<NSWindow *>(voidWindowRef);
2202 const Qt::WindowType type = q->windowType();
2203 Qt::WindowFlags &flags = data.window_flags;
2204 QWidget *parentWidget = q->parentWidget();
2205
2206 const bool popup = (type == Qt::Popup);
2207 const bool dialog = (type == Qt::Dialog
2208 || type == Qt::Sheet
2209 || type == Qt::Drawer
2210 || (flags & Qt::MSWindowsFixedSizeDialogHint));
2211 QTLWExtra *topExtra = topData();
2212
2213 if ((popup || type == Qt::Tool || type == Qt::ToolTip) && !q->isModal()) {
2214 [windowRef setHidesOnDeactivate:YES];
2215 } else {
2216 [windowRef setHidesOnDeactivate:NO];
2217 }
2218 [windowRef setHasShadow:YES];
2219 Q_UNUSED(parentWidget);
2220 Q_UNUSED(dialog);
2221
2222 data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty
2223 OSViewRef nsview = (OSViewRef)data.winid;
2224 OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef);