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

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

trunk: Merged in qt 4.6.2 sources.

File size: 192.3 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/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#include "qmainwindow.h"
114
115QT_BEGIN_NAMESPACE
116
117#define XCOORD_MAX 16383
118#define WRECT_MAX 8191
119
120#ifndef QT_MAC_USE_COCOA
121
122extern "C" {
123 extern OSStatus _HIViewScrollRectWithOptions(HIViewRef, const HIRect *, CGFloat, CGFloat,
124 OptionBits) __attribute__ ((weak));
125}
126#define kHIViewScrollRectAdjustInvalid 1
127#define kHIViewScrollRectDontInvalidateRevealedArea 2
128#endif
129
130
131/*****************************************************************************
132 QWidget debug facilities
133 *****************************************************************************/
134//#define DEBUG_WINDOW_RGNS
135//#define DEBUG_WINDOW_CREATE
136//#define DEBUG_WINDOW_STATE
137//#define DEBUG_WIDGET_PAINT
138
139/*****************************************************************************
140 QWidget globals
141 *****************************************************************************/
142#ifndef QT_MAC_USE_COCOA
143typedef QHash<Qt::WindowFlags, WindowGroupRef> WindowGroupHash;
144Q_GLOBAL_STATIC(WindowGroupHash, qt_mac_window_groups)
145const UInt32 kWidgetCreatorQt = kEventClassQt;
146enum {
147 kWidgetPropertyQWidget = 'QWId' //QWidget *
148};
149#endif
150
151static bool qt_mac_raise_process = true;
152static OSWindowRef qt_root_win = 0;
153QWidget *mac_mouse_grabber = 0;
154QWidget *mac_keyboard_grabber = 0;
155
156#ifndef QT_MAC_USE_COCOA
157#ifdef QT_NAMESPACE
158
159// produce the string "com.trolltech.qt-namespace.widget", where "namespace" is the contents of QT_NAMESPACE.
160#define SS(x) #x
161#define S0(x) SS(x)
162#define S "com.trolltech.qt-" S0(QT_NAMESPACE) ".widget"
163
164static CFStringRef kObjectQWidget = CFSTR(S);
165
166#undef SS
167#undef S0
168#undef S
169
170#else
171static CFStringRef kObjectQWidget = CFSTR("com.trolltech.qt.widget");
172#endif // QT_NAMESPACE
173#endif // QT_MAC_USE_COCOA
174
175/*****************************************************************************
176 Externals
177 *****************************************************************************/
178extern QWidget *qt_mac_modal_blocked(QWidget *); //qapplication_mac.mm
179extern void qt_event_request_activate(QWidget *); //qapplication_mac.mm
180extern bool qt_event_remove_activate(); //qapplication_mac.mm
181extern void qt_mac_event_release(QWidget *w); //qapplication_mac.mm
182extern void qt_event_request_showsheet(QWidget *); //qapplication_mac.mm
183extern void qt_event_request_window_change(QWidget *); //qapplication_mac.mm
184extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm
185extern IconRef qt_mac_create_iconref(const QPixmap &); //qpixmap_mac.cpp
186extern void qt_mac_set_cursor(const QCursor *, const QPoint &); //qcursor_mac.mm
187extern void qt_mac_update_cursor(); //qcursor_mac.mm
188extern bool qt_nograb();
189extern CGImageRef qt_mac_create_cgimage(const QPixmap &, bool); //qpixmap_mac.cpp
190extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp
191extern QRegion qt_mac_convert_mac_region(RgnHandle rgn); //qregion_mac.cpp
192
193/*****************************************************************************
194 QWidget utility functions
195 *****************************************************************************/
196void Q_GUI_EXPORT qt_mac_set_raise_process(bool b) { qt_mac_raise_process = b; }
197static QSize qt_mac_desktopSize()
198{
199 int w = 0, h = 0;
200 CGDisplayCount cg_count;
201 CGGetActiveDisplayList(0, 0, &cg_count);
202 QVector<CGDirectDisplayID> displays(cg_count);
203 CGGetActiveDisplayList(cg_count, displays.data(), &cg_count);
204 Q_ASSERT(cg_count == (CGDisplayCount)displays.size());
205 for(int i = 0; i < (int)cg_count; ++i) {
206 CGRect r = CGDisplayBounds(displays.at(i));
207 w = qMax<int>(w, qRound(r.origin.x + r.size.width));
208 h = qMax<int>(h, qRound(r.origin.y + r.size.height));
209 }
210 return QSize(w, h);
211}
212
213#ifdef QT_MAC_USE_COCOA
214static NSDrawer *qt_mac_drawer_for(const QWidget *widget)
215{
216 // This only goes one level below the content view so start with the window.
217 // This works fine for straight Qt stuff, but runs into problems if we are
218 // embedding, but if that's the case, they probably want to be using
219 // NSDrawer directly.
220 NSView *widgetView = reinterpret_cast<NSView *>(widget->window()->winId());
221 NSArray *windows = [NSApp windows];
222 for (NSWindow *window in windows) {
223 NSArray *drawers = [window drawers];
224 for (NSDrawer *drawer in drawers) {
225 NSArray *views = [[drawer contentView] subviews];
226 for (NSView *view in views) {
227 if (view == widgetView)
228 return drawer;
229 }
230 }
231 }
232 return 0;
233}
234#endif
235
236static void qt_mac_destructView(OSViewRef view)
237{
238#ifdef QT_MAC_USE_COCOA
239 [view removeFromSuperview];
240 [view release];
241#else
242 HIViewRemoveFromSuperview(view);
243 CFRelease(view);
244#endif
245}
246
247static void qt_mac_destructWindow(OSWindowRef window)
248{
249#ifdef QT_MAC_USE_COCOA
250 if ([window isVisible] && [window isSheet]){
251 [NSApp endSheet:window];
252 [window orderOut:window];
253 }
254
255 [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForWindow:window];
256 [window release];
257#else
258 // Remove property to clean up memory:
259 RemoveWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget);
260 CFRelease(window);
261#endif
262}
263
264static void qt_mac_destructDrawer(NSDrawer *drawer)
265{
266#ifdef QT_MAC_USE_COCOA
267 [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForDrawer:drawer];
268 [drawer release];
269#else
270 Q_UNUSED(drawer);
271#endif
272}
273
274bool qt_mac_can_clickThrough(const QWidget *w)
275{
276 static int qt_mac_carbon_clickthrough = -1;
277 if (qt_mac_carbon_clickthrough < 0)
278 qt_mac_carbon_clickthrough = !qgetenv("QT_MAC_NO_COCOA_CLICKTHROUGH").isEmpty();
279 bool ret = !qt_mac_carbon_clickthrough;
280 for ( ; w; w = w->parentWidget()) {
281 if (w->testAttribute(Qt::WA_MacNoClickThrough)) {
282 ret = false;
283 break;
284 }
285 }
286 return ret;
287}
288
289bool qt_mac_is_macsheet(const QWidget *w)
290{
291 if (!w)
292 return false;
293
294 Qt::WindowModality modality = w->windowModality();
295 if (modality == Qt::ApplicationModal)
296 return false;
297 return w->parentWidget() && (modality == Qt::WindowModal || w->windowType() == Qt::Sheet);
298}
299
300bool qt_mac_is_macdrawer(const QWidget *w)
301{
302 return (w && w->parentWidget() && w->windowType() == Qt::Drawer);
303}
304
305bool qt_mac_insideKeyWindow(const QWidget *w)
306{
307#ifdef QT_MAC_USE_COCOA
308 return [[reinterpret_cast<NSView *>(w->winId()) window] isKeyWindow];
309#else
310 Q_UNUSED(w);
311#endif
312 return false;
313}
314
315bool qt_mac_set_drawer_preferred_edge(QWidget *w, Qt::DockWidgetArea where) //users of Qt for Mac OS X can use this..
316{
317 if(!qt_mac_is_macdrawer(w))
318 return false;
319
320#if QT_MAC_USE_COCOA
321 NSDrawer *drawer = qt_mac_drawer_for(w);
322 if (!drawer)
323 return false;
324 NSRectEdge edge;
325 if (where & Qt::LeftDockWidgetArea)
326 edge = NSMinXEdge;
327 else if (where & Qt::RightDockWidgetArea)
328 edge = NSMaxXEdge;
329 else if (where & Qt::TopDockWidgetArea)
330 edge = NSMaxYEdge;
331 else if (where & Qt::BottomDockWidgetArea)
332 edge = NSMinYEdge;
333 else
334 return false;
335
336 if (edge == [drawer preferredEdge]) //no-op
337 return false;
338
339 if (w->isVisible()) {
340 [drawer close];
341 [drawer openOnEdge:edge];
342 }
343 [drawer setPreferredEdge:edge];
344#else
345 OSWindowRef window = qt_mac_window_for(w);
346 OptionBits edge;
347 if(where & Qt::LeftDockWidgetArea)
348 edge = kWindowEdgeLeft;
349 else if(where & Qt::RightDockWidgetArea)
350 edge = kWindowEdgeRight;
351 else if(where & Qt::TopDockWidgetArea)
352 edge = kWindowEdgeTop;
353 else if(where & Qt::BottomDockWidgetArea)
354 edge = kWindowEdgeBottom;
355 else
356 return false;
357
358 if(edge == GetDrawerPreferredEdge(window)) //no-op
359 return false;
360
361 //do it
362 SetDrawerPreferredEdge(window, edge);
363 if(w->isVisible()) {
364 CloseDrawer(window, false);
365 OpenDrawer(window, edge, true);
366 }
367#endif
368 return true;
369}
370
371#ifndef QT_MAC_USE_COCOA
372Q_GUI_EXPORT
373#endif
374QPoint qt_mac_posInWindow(const QWidget *w)
375{
376 QPoint ret = w->data->wrect.topLeft();
377 while(w && !w->isWindow()) {
378 ret += w->pos();
379 w = w->parentWidget();
380 }
381 return ret;
382}
383
384//find a QWidget from a OSWindowRef
385QWidget *qt_mac_find_window(OSWindowRef window)
386{
387#ifdef QT_MAC_USE_COCOA
388 return [window QT_MANGLE_NAMESPACE(qt_qwidget)];
389#else
390 if(!window)
391 return 0;
392
393 QWidget *ret;
394 if(GetWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(ret), 0, &ret) == noErr)
395 return ret;
396 return 0;
397#endif
398}
399
400inline static void qt_mac_set_fullscreen_mode(bool b)
401{
402 extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
403 if(qt_mac_app_fullscreen == b)
404 return;
405 qt_mac_app_fullscreen = b;
406 if (b) {
407 SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
408 } else {
409 SetSystemUIMode(kUIModeNormal, 0);
410 }
411}
412
413Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w)
414{
415 return reinterpret_cast<OSViewRef>(w->data->winid);
416}
417
418Q_GUI_EXPORT OSViewRef qt_mac_get_contentview_for(OSWindowRef w)
419{
420#ifdef QT_MAC_USE_COCOA
421 return [w contentView];
422#else
423 HIViewRef contentView = 0;
424 OSStatus err = GetRootControl(w, &contentView); // Returns the window's content view (Apple QA1214)
425 if (err == errUnknownControl) {
426 contentView = HIViewGetRoot(w);
427 } else if (err != noErr) {
428 qWarning("Qt:Could not get content or root view of window! %s:%d [%ld]",
429 __FILE__, __LINE__, err);
430 }
431 return contentView;
432#endif
433}
434
435bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref)
436{
437 return widget->macEvent(0, ref);
438}
439
440Q_GUI_EXPORT OSWindowRef qt_mac_window_for(OSViewRef view)
441{
442#ifdef QT_MAC_USE_COCOA
443 if (view)
444 return [view window];
445 return 0;
446#else
447 return HIViewGetWindow(view);
448#endif
449}
450
451static bool qt_isGenuineQWidget(OSViewRef ref)
452{
453#ifdef QT_MAC_USE_COCOA
454 return [ref isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]];
455#else
456 return HIObjectIsOfClass(HIObjectRef(ref), kObjectQWidget);
457#endif
458}
459
460bool qt_isGenuineQWidget(const QWidget *window)
461{
462 return window && qt_isGenuineQWidget(OSViewRef(window->winId()));
463}
464
465Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w)
466{
467 OSViewRef hiview = qt_mac_nativeview_for(w);
468 if (hiview){
469 OSWindowRef window = qt_mac_window_for(hiview);
470 if (!window && qt_isGenuineQWidget(hiview)) {
471 QWidget *myWindow = w->window();
472 // This is a workaround for NSToolbar. When a widget is hidden
473 // by clicking the toolbar button, Cocoa reparents the widgets
474 // to another window (but Qt doesn't know about it).
475 // When we start showing them, it reparents back,
476 // but at this point it's window is nil, but the window it's being brought
477 // into (the Qt one) is for sure created.
478 // This stops the hierarchy moving under our feet.
479 if (myWindow != w && qt_mac_window_for(qt_mac_nativeview_for(myWindow)))
480 return qt_mac_window_for(qt_mac_nativeview_for(myWindow));
481
482 myWindow->d_func()->createWindow_sys();
483 // Reget the hiview since the "create window could potentially move the view (I guess).
484 hiview = qt_mac_nativeview_for(w);
485 window = qt_mac_window_for(hiview);
486 }
487 return window;
488 }
489 return 0;
490}
491#ifndef QT_MAC_USE_COCOA
492/* Checks if the current group is a 'stay on top' group. If so, the
493 group gets removed from the hash table */
494static void qt_mac_release_stays_on_top_group(WindowGroupRef group)
495{
496 for (WindowGroupHash::iterator it = qt_mac_window_groups()->begin(); it != qt_mac_window_groups()->end(); ++it) {
497 if (it.value() == group) {
498 qt_mac_window_groups()->remove(it.key());
499 return;
500 }
501 }
502}
503
504/* Use this function instead of ReleaseWindowGroup, this will be sure to release the
505 stays on top window group (created with qt_mac_get_stays_on_top_group below) */
506static void qt_mac_release_window_group(WindowGroupRef group)
507{
508 ReleaseWindowGroup(group);
509 if (GetWindowGroupRetainCount(group) == 0)
510 qt_mac_release_stays_on_top_group(group);
511}
512#define ReleaseWindowGroup(x) Are you sure you wanted to do that? (you wanted qt_mac_release_window_group)
513
514SInt32 qt_mac_get_group_level(WindowClass wclass)
515{
516 SInt32 group_level;
517 CGWindowLevel tmpLevel;
518 GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel);
519 group_level = tmpLevel;
520 return group_level;
521}
522#endif
523
524#ifndef QT_MAC_USE_COCOA
525static void qt_mac_set_window_group(OSWindowRef window, Qt::WindowFlags flags, int level)
526{
527 WindowGroupRef group = 0;
528 if (qt_mac_window_groups()->contains(flags)) {
529 group = qt_mac_window_groups()->value(flags);
530 RetainWindowGroup(group);
531 } else {
532 CreateWindowGroup(kWindowActivationScopeNone, &group);
533 SetWindowGroupLevel(group, level);
534 SetWindowGroupParent(group, GetWindowGroupOfClass(kAllWindowClasses));
535 qt_mac_window_groups()->insert(flags, group);
536 }
537 SetWindowGroup(window, group);
538}
539
540inline static void qt_mac_set_window_group_to_stays_on_top(OSWindowRef window, Qt::WindowType type)
541{
542 // We create one static stays on top window group so that
543 // all stays on top (aka popups) will fall into the same
544 // group and be able to be raise()'d with releation to one another (from
545 // within the same window group).
546 qt_mac_set_window_group(window, type|Qt::WindowStaysOnTopHint, qt_mac_get_group_level(kOverlayWindowClass));
547}
548
549inline static void qt_mac_set_window_group_to_tooltip(OSWindowRef window)
550{
551 // Since new groups are created for 'stays on top' windows, the
552 // same must be done for tooltips. Otherwise, tooltips would be drawn
553 // below 'stays on top' widgets even tough they are on the same level.
554 // Also, add 'two' to the group level to make sure they also get on top of popups.
555 qt_mac_set_window_group(window, Qt::ToolTip, qt_mac_get_group_level(kHelpWindowClass)+2);
556}
557
558inline static void qt_mac_set_window_group_to_popup(OSWindowRef window)
559{
560 // In Qt, a popup is seen as a 'stay on top' window.
561 // Since new groups are created for 'stays on top' windows, the
562 // same must be done for popups. Otherwise, popups would be drawn
563 // below 'stays on top' windows. Add 1 to get above pure stay-on-top windows.
564 qt_mac_set_window_group(window, Qt::Popup, qt_mac_get_group_level(kOverlayWindowClass)+1);
565}
566#endif
567
568inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRect &rect)
569{
570 if (!widget)
571 return false;
572
573#ifndef QT_NO_GRAPHICSVIEW
574 QWidget *tlw = widget->window();
575 QWExtra *extra = qt_widget_private(tlw)->extra;
576 if (extra && extra->proxyWidget) {
577 extra->proxyWidget->update(rect.translated(widget->mapTo(tlw, QPoint())));
578 return true;
579 }
580#endif
581
582 return false;
583}
584
585inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRegion &rgn)
586{
587 if (!widget)
588 return false;
589
590#ifndef QT_NO_GRAPHICSVIEW
591 QWidget *tlw = widget->window();
592 QWExtra *extra = qt_widget_private(tlw)->extra;
593 if (extra && extra->proxyWidget) {
594 const QPoint offset(widget->mapTo(tlw, QPoint()));
595 const QVector<QRect> rects = rgn.rects();
596 for (int i = 0; i < rects.size(); ++i)
597 extra->proxyWidget->update(rects.at(i).translated(offset));
598 return true;
599 }
600#endif
601
602 return false;
603}
604
605void QWidgetPrivate::macUpdateIsOpaque()
606{
607 Q_Q(QWidget);
608 if (!q->testAttribute(Qt::WA_WState_Created))
609 return;
610#ifndef QT_MAC_USE_COCOA
611 HIViewFeatures bits;
612 HIViewRef hiview = qt_mac_nativeview_for(q);
613 HIViewGetFeatures(hiview, &bits);
614 if ((bits & kHIViewIsOpaque) == isOpaque)
615 return;
616 if (isOpaque) {
617 HIViewChangeFeatures(hiview, kHIViewIsOpaque, 0);
618 } else {
619 HIViewChangeFeatures(hiview, 0, kHIViewIsOpaque);
620 }
621 if (q->isVisible())
622 HIViewReshapeStructure(qt_mac_nativeview_for(q));
623#else
624 if (isRealWindow() && !q->testAttribute(Qt::WA_MacBrushedMetal)) {
625 bool opaque = isOpaque;
626 if (extra && extra->imageMask)
627 opaque = false; // we are never opaque when we have a mask.
628 [qt_mac_window_for(q) setOpaque:opaque];
629 }
630#endif
631}
632#ifdef QT_MAC_USE_COCOA
633static OSWindowRef qt_mac_create_window(QWidget *widget, WindowClass wclass,
634 NSUInteger wattr, const QRect &crect)
635{
636 // Determine if we need to add in our "custom window" attribute. Cocoa is rather clever
637 // in deciding if we need the maximize button or not (i.e., it's resizeable, so you
638 // must need a maximize button). So, the only buttons we have control over are the
639 // close and minimize buttons. If someone wants to customize and NOT have the maximize
640 // button, then we have to do our hack. We only do it for these cases because otherwise
641 // the window looks different when activated. This "QtMacCustomizeWindow" attribute is
642 // intruding on a public space and WILL BREAK in the future.
643 // One can hope that there is a more public API available by that time.
644 Qt::WindowFlags flags = widget ? widget->windowFlags() : Qt::WindowFlags(0);
645 if ((flags & Qt::CustomizeWindowHint)) {
646 if ((flags & (Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint
647 | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint))
648 && !(flags & Qt::WindowMaximizeButtonHint))
649 wattr |= QtMacCustomizeWindow;
650 }
651
652 // If we haven't created the desktop widget, you have to pass the rectangle
653 // in "cocoa coordinates" (i.e., top points to the lower left coordinate).
654 // Otherwise, we do the conversion for you. Since we are the only ones that
655 // create the desktop widget, this is OK (but confusing).
656 NSRect geo = NSMakeRect(crect.left(),
657 (qt_root_win != 0) ? flipYCoordinate(crect.bottom() + 1) : crect.top(),
658 crect.width(), crect.height());
659 QMacCocoaAutoReleasePool pool;
660 OSWindowRef window;
661 switch (wclass) {
662 case kMovableModalWindowClass:
663 case kModalWindowClass:
664 case kSheetWindowClass:
665 case kFloatingWindowClass:
666 case kOverlayWindowClass:
667 case kHelpWindowClass: {
668 NSPanel *panel;
669 BOOL needFloating = NO;
670 BOOL worksWhenModal = widget && (widget->windowType() == Qt::Popup);
671 // Add in the extra flags if necessary.
672 switch (wclass) {
673 case kSheetWindowClass:
674 wattr |= NSDocModalWindowMask;
675 break;
676 case kFloatingWindowClass:
677 case kHelpWindowClass:
678 needFloating = YES;
679 wattr |= NSUtilityWindowMask;
680 break;
681 default:
682 break;
683 }
684 panel = [[QT_MANGLE_NAMESPACE(QCocoaPanel) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr];
685 [panel setFloatingPanel:needFloating];
686 [panel setWorksWhenModal:worksWhenModal];
687 window = panel;
688 break;
689 }
690 case kDrawerWindowClass: {
691 NSDrawer *drawer = [[NSDrawer alloc] initWithContentSize:geo.size preferredEdge:NSMinXEdge];
692 [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] becomeDelegateForDrawer:drawer widget:widget];
693 QWidget *parentWidget = widget->parentWidget();
694 if (parentWidget)
695 [drawer setParentWindow:qt_mac_window_for(parentWidget)];
696 [drawer setLeadingOffset:0.0];
697 [drawer setTrailingOffset:25.0];
698 window = [[drawer contentView] window]; // Just to make sure we actually return a window
699 break;
700 }
701 default:
702 window = [[QT_MANGLE_NAMESPACE(QCocoaWindow) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr];
703 break;
704 }
705 qt_syncCocoaTitleBarButtons(window, widget);
706 return window;
707}
708#else
709static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAttributes wattr,
710 const QRect &crect)
711{
712 OSWindowRef window;
713 Rect geo;
714 SetRect(&geo, crect.left(), crect.top(), crect.right() + 1, crect.bottom() + 1);
715 OSStatus err;
716 if(geo.right <= geo.left) geo.right = geo.left + 1;
717 if(geo.bottom <= geo.top) geo.bottom = geo.top + 1;
718 Rect null_rect;
719 SetRect(&null_rect, 0, 0, 1, 1);
720 err = CreateNewWindow(wclass, wattr, &null_rect, &window);
721 if(err == noErr) {
722 err = SetWindowBounds(window, kWindowContentRgn, &geo);
723 if(err != noErr)
724 qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__);
725 }
726 return window;
727}
728
729#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
730/* We build the release package against the 10.4 SDK.
731 So, to enable gestures for applications running on
732 10.6+, we define the missing constants here: */
733enum {
734 kEventClassGesture = 'gest',
735 kEventGestureStarted = 1,
736 kEventGestureEnded = 2,
737 kEventGestureMagnify = 4,
738 kEventGestureSwipe = 5,
739 kEventGestureRotate = 6,
740 kEventParamRotationAmount = 'rota',
741 kEventParamSwipeDirection = 'swip',
742 kEventParamMagnificationAmount = 'magn'
743};
744#endif
745
746// window events
747static EventTypeSpec window_events[] = {
748 { kEventClassWindow, kEventWindowClose },
749 { kEventClassWindow, kEventWindowExpanded },
750 { kEventClassWindow, kEventWindowHidden },
751 { kEventClassWindow, kEventWindowZoom },
752 { kEventClassWindow, kEventWindowZoomed },
753 { kEventClassWindow, kEventWindowCollapsed },
754 { kEventClassWindow, kEventWindowToolbarSwitchMode },
755 { kEventClassWindow, kEventWindowProxyBeginDrag },
756 { kEventClassWindow, kEventWindowProxyEndDrag },
757 { kEventClassWindow, kEventWindowResizeCompleted },
758 { kEventClassWindow, kEventWindowBoundsChanging },
759 { kEventClassWindow, kEventWindowGetRegion },
760 { kEventClassWindow, kEventWindowGetClickModality },
761 { kEventClassWindow, kEventWindowTransitionCompleted },
762 { kEventClassGesture, kEventGestureStarted },
763 { kEventClassGesture, kEventGestureEnded },
764 { kEventClassGesture, kEventGestureMagnify },
765 { kEventClassGesture, kEventGestureSwipe },
766 { kEventClassGesture, kEventGestureRotate },
767 { kEventClassMouse, kEventMouseDown }
768};
769static EventHandlerUPP mac_win_eventUPP = 0;
770static void cleanup_win_eventUPP()
771{
772 DisposeEventHandlerUPP(mac_win_eventUPP);
773 mac_win_eventUPP = 0;
774}
775static const EventHandlerUPP make_win_eventUPP()
776{
777 if(mac_win_eventUPP)
778 return mac_win_eventUPP;
779 qAddPostRoutine(cleanup_win_eventUPP);
780 return mac_win_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_window_event);
781}
782OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, void *)
783{
784 QScopedLoopLevelCounter loopLevelCounter(qApp->d_func()->threadData);
785 bool handled_event = true;
786 UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
787 switch(eclass) {
788 case kEventClassWindow: {
789 WindowRef wid = 0;
790 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
791 sizeof(WindowRef), 0, &wid);
792 QWidget *widget = qt_mac_find_window(wid);
793 if(!widget) {
794 handled_event = false;
795 } else if(ekind == kEventWindowGetClickModality) {
796 // Carbon will send us kEventWindowGetClickModality before every
797 // mouse press / release event. By returning 'true', we tell Carbon
798 // that we would like the event target to receive the mouse event even
799 // if the target is modally shaddowed. In Qt, this makes sense when we
800 // e.g. have a popup showing, as the popup will grab the event
801 // and perhaps use it to close itself.
802 // By also setting the current modal window back into the event, we
803 // help Carbon determining which window is supposed to be raised.
804 handled_event = qApp->activePopupWidget() ? true : false;
805 } else if(ekind == kEventWindowClose) {
806 widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
807 QMenuBar::macUpdateMenuBar();
808 } else if (ekind == kEventWindowTransitionCompleted) {
809 WindowTransitionAction transitionAction;
810 GetEventParameter(event, kEventParamWindowTransitionAction, typeWindowTransitionAction,
811 0, sizeof(transitionAction), 0, &transitionAction);
812 if (transitionAction == kWindowHideTransitionAction)
813 widget->hide();
814 } else if(ekind == kEventWindowExpanded) {
815 Qt::WindowStates currState = Qt::WindowStates(widget->data->window_state);
816 Qt::WindowStates newState = currState;
817 if (currState & Qt::WindowMinimized)
818 newState &= ~Qt::WindowMinimized;
819 if (!(currState & Qt::WindowActive))
820 newState |= Qt::WindowActive;
821 if (newState != currState) {
822 // newState will differ from currState if the window
823 // was expanded after clicking on the jewels (as opposed
824 // to calling QWidget::setWindowState)
825 widget->data->window_state = newState;
826 QWindowStateChangeEvent e(currState);
827 QApplication::sendSpontaneousEvent(widget, &e);
828 }
829
830 QShowEvent qse;
831 QApplication::sendSpontaneousEvent(widget, &qse);
832 } else if(ekind == kEventWindowZoom) {
833 widget->d_func()->topData()->normalGeometry = widget->geometry();
834 handled_event = false;
835 } else if(ekind == kEventWindowZoomed) {
836 WindowPartCode windowPart;
837 GetEventParameter(event, kEventParamWindowPartCode,
838 typeWindowPartCode, 0, sizeof(windowPart), 0, &windowPart);
839 if(windowPart == inZoomIn && widget->isMaximized()) {
840
841 widget->data->window_state = widget->data->window_state & ~Qt::WindowMaximized;
842 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state | Qt::WindowMaximized));
843 QApplication::sendSpontaneousEvent(widget, &e);
844 } else if(windowPart == inZoomOut && !widget->isMaximized()) {
845 widget->data->window_state = widget->data->window_state | Qt::WindowMaximized;
846 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state
847 & ~Qt::WindowMaximized));
848 QApplication::sendSpontaneousEvent(widget, &e);
849 }
850 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
851 qt_button_down = 0;
852 } else if(ekind == kEventWindowCollapsed) {
853 if (!widget->isMinimized()) {
854 widget->data->window_state = widget->data->window_state | Qt::WindowMinimized;
855 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state & ~Qt::WindowMinimized));
856 QApplication::sendSpontaneousEvent(widget, &e);
857 }
858
859 // Deactivate this window:
860 if (widget->isActiveWindow() && !(widget->windowType() == Qt::Popup)) {
861 QWidget *w = 0;
862 if (widget->parentWidget())
863 w = widget->parentWidget()->window();
864 if (!w || (!w->isVisible() && !w->isMinimized())) {
865 for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true);
866 wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) {
867 if ((w = qt_mac_find_window(wp)))
868 break;
869 }
870 }
871 if(!(w && w->isVisible() && !w->isMinimized()))
872 qApp->setActiveWindow(0);
873 }
874
875 //we send a hide to be like X11/Windows
876 QEvent e(QEvent::Hide);
877 QApplication::sendSpontaneousEvent(widget, &e);
878 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
879 qt_button_down = 0;
880 } else if(ekind == kEventWindowToolbarSwitchMode) {
881 macSendToolbarChangeEvent(widget);
882 HIToolbarRef toolbar;
883 if (GetWindowToolbar(wid, &toolbar) == noErr) {
884 if (toolbar) {
885 // Let HIToolbar do its thang, but things like the OpenGL context
886 // needs to know about it.
887 CallNextEventHandler(er, event);
888 qt_event_request_window_change(widget);
889 widget->data->fstrut_dirty = true;
890 }
891 }
892 } else if(ekind == kEventWindowGetRegion) {
893 WindowRef window;
894 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
895 sizeof(window), 0, &window);
896 WindowRegionCode wcode;
897 GetEventParameter(event, kEventParamWindowRegionCode, typeWindowRegionCode, 0,
898 sizeof(wcode), 0, &wcode);
899 if (wcode != kWindowOpaqueRgn){
900 // If the region is kWindowOpaqueRgn, don't call next
901 // event handler cause this will make the shadow of
902 // masked windows become offset. Unfortunately, we're not sure why.
903 CallNextEventHandler(er, event);
904 }
905 RgnHandle rgn;
906 GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0,
907 sizeof(rgn), 0, &rgn);
908
909 if(QWidgetPrivate::qt_widget_rgn(qt_mac_find_window(window), wcode, rgn, false))
910 SetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, sizeof(rgn), &rgn);
911 } else if(ekind == kEventWindowProxyBeginDrag) {
912 QIconDragEvent e;
913 QApplication::sendSpontaneousEvent(widget, &e);
914 } else if(ekind == kEventWindowResizeCompleted) {
915 // Create a mouse up event, since such an event is not send by carbon to the
916 // application event handler (while a mouse down <b>is</b> on kEventWindowResizeStarted)
917 EventRef mouseUpEvent;
918 CreateEvent(0, kEventClassMouse, kEventMouseUp, 0, kEventAttributeUserEvent, &mouseUpEvent);
919 UInt16 mbutton = kEventMouseButtonPrimary;
920 SetEventParameter(mouseUpEvent, kEventParamMouseButton, typeMouseButton, sizeof(mbutton), &mbutton);
921 WindowRef window;
922 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, sizeof(window), 0, &window);
923 Rect dragRect;
924 GetWindowBounds(window, kWindowGrowRgn, &dragRect);
925 Point pos = {dragRect.bottom, dragRect.right};
926 SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos);
927 SendEventToApplication(mouseUpEvent);
928 ReleaseEvent(mouseUpEvent);
929 } else if(ekind == kEventWindowBoundsChanging) {
930 UInt32 flags = 0;
931 GetEventParameter(event, kEventParamAttributes, typeUInt32, 0,
932 sizeof(flags), 0, &flags);
933 Rect nr;
934 GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0,
935 sizeof(nr), 0, &nr);
936
937 QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top);
938
939 QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData();
940 if (tlwExtra && tlwExtra->isSetGeometry == 1) {
941 widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove);
942 } else {
943 //implicitly removes the maximized bit
944 if((widget->data->window_state & Qt::WindowMaximized) &&
945 IsWindowInStandardState(wid, 0, 0)) {
946 widget->data->window_state &= ~Qt::WindowMaximized;
947 QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state
948 | Qt::WindowMaximized));
949 QApplication::sendSpontaneousEvent(widget, &e);
950
951 }
952
953 handled_event = false;
954 const QRect oldRect = widget->data->crect;
955 if((flags & kWindowBoundsChangeOriginChanged)) {
956 if(nr.left != oldRect.x() || nr.top != oldRect.y()) {
957 widget->data->crect.moveTo(nr.left, nr.top);
958 QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft());
959 QApplication::sendSpontaneousEvent(widget, &qme);
960 }
961 }
962 if((flags & kWindowBoundsChangeSizeChanged)) {
963 if (widget->isWindow()) {
964 QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size());
965 int dh = newSize.height() - newRect.height();
966 int dw = newSize.width() - newRect.width();
967 if (dw != 0 || dh != 0) {
968 handled_event = true; // We want to change the bounds, so we handle the event
969
970 // set the rect, so we can also do the resize down below (yes, we need to resize).
971 newRect.setBottom(newRect.bottom() + dh);
972 newRect.setRight(newRect.right() + dw);
973
974 nr.left = newRect.x();
975 nr.top = newRect.y();
976 nr.right = nr.left + newRect.width();
977 nr.bottom = nr.top + newRect.height();
978 SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr);
979 }
980 }
981
982 if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) {
983 widget->data->crect.setSize(newRect.size());
984 HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height());
985
986 // If the WA_StaticContents attribute is set we can optimize the resize
987 // by only repainting the newly exposed area. We do this by disabling
988 // painting when setting the size of the view. The OS will invalidate
989 // the newly exposed area for us.
990 const bool staticContents = widget->testAttribute(Qt::WA_StaticContents);
991 const HIViewRef view = qt_mac_nativeview_for(widget);
992 if (staticContents)
993 HIViewSetDrawingEnabled(view, false);
994 HIViewSetFrame(view, &bounds);
995 if (staticContents)
996 HIViewSetDrawingEnabled(view, true);
997
998 QResizeEvent qre(newRect.size(), oldRect.size());
999 QApplication::sendSpontaneousEvent(widget, &qre);
1000 qt_event_request_window_change(widget);
1001 }
1002 }
1003 }
1004 } else if (ekind == kEventWindowHidden) {
1005 // Make sure that we also hide any visible sheets on our window.
1006 // Cocoa does the right thing for us.
1007 const QObjectList children = widget->children();
1008 const int childCount = children.count();
1009 for (int i = 0; i < childCount; ++i) {
1010 QObject *obj = children.at(i);
1011 if (obj->isWidgetType()) {
1012 QWidget *widget = static_cast<QWidget *>(obj);
1013 if (qt_mac_is_macsheet(widget) && widget->isVisible())
1014 widget->hide();
1015 }
1016 }
1017 } else {
1018 handled_event = false;
1019 }
1020 break; }
1021 case kEventClassMouse: {
1022#if 0
1023 return SendEventToApplication(event);
1024#endif
1025
1026 bool send_to_app = false;
1027 {
1028 WindowPartCode wpc;
1029 if (GetEventParameter(event, kEventParamWindowPartCode, typeWindowPartCode, 0,
1030 sizeof(wpc), 0, &wpc) == noErr && wpc != inContent)
1031 send_to_app = true;
1032 }
1033 if(!send_to_app) {
1034 WindowRef window;
1035 if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0,
1036 sizeof(window), 0, &window) == noErr) {
1037 HIViewRef hiview;
1038 if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) {
1039 if(QWidget *w = QWidget::find((WId)hiview)) {
1040#if 0
1041 send_to_app = !w->isActiveWindow();
1042#else
1043 Q_UNUSED(w);
1044 send_to_app = true;
1045#endif
1046 }
1047 }
1048 }
1049 }
1050 if(send_to_app)
1051 return SendEventToApplication(event);
1052 handled_event = false;
1053 break; }
1054
1055 case kEventClassGesture: {
1056 // First, find the widget that was under
1057 // the mouse when the gesture happened:
1058 HIPoint screenLocation;
1059 if (GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0,
1060 sizeof(screenLocation), 0, &screenLocation) != noErr) {
1061 handled_event = false;
1062 break;
1063 }
1064 QWidget *widget = QApplication::widgetAt(screenLocation.x, screenLocation.y);
1065 if (!widget) {
1066 handled_event = false;
1067 break;
1068 }
1069
1070 QNativeGestureEvent qNGEvent;
1071 qNGEvent.position = QPoint(screenLocation.x, screenLocation.y);
1072
1073 switch (ekind) {
1074 case kEventGestureStarted:
1075 qNGEvent.gestureType = QNativeGestureEvent::GestureBegin;
1076 break;
1077 case kEventGestureEnded:
1078 qNGEvent.gestureType = QNativeGestureEvent::GestureEnd;
1079 break;
1080 case kEventGestureRotate: {
1081 CGFloat amount;
1082 if (GetEventParameter(event, kEventParamRotationAmount, 'cgfl', 0,
1083 sizeof(amount), 0, &amount) != noErr) {
1084 handled_event = false;
1085 break;
1086 }
1087 qNGEvent.gestureType = QNativeGestureEvent::Rotate;
1088 qNGEvent.percentage = float(-amount);
1089 break; }
1090 case kEventGestureSwipe: {
1091 HIPoint swipeDirection;
1092 if (GetEventParameter(event, kEventParamSwipeDirection, typeHIPoint, 0,
1093 sizeof(swipeDirection), 0, &swipeDirection) != noErr) {
1094 handled_event = false;
1095 break;
1096 }
1097 qNGEvent.gestureType = QNativeGestureEvent::Swipe;
1098 if (swipeDirection.x == 1)
1099 qNGEvent.angle = 180.0f;
1100 else if (swipeDirection.x == -1)
1101 qNGEvent.angle = 0.0f;
1102 else if (swipeDirection.y == 1)
1103 qNGEvent.angle = 90.0f;
1104 else if (swipeDirection.y == -1)
1105 qNGEvent.angle = 270.0f;
1106 break; }
1107 case kEventGestureMagnify: {
1108 CGFloat amount;
1109 if (GetEventParameter(event, kEventParamMagnificationAmount, 'cgfl', 0,
1110 sizeof(amount), 0, &amount) != noErr) {
1111 handled_event = false;
1112 break;
1113 }
1114 qNGEvent.gestureType = QNativeGestureEvent::Zoom;
1115 qNGEvent.percentage = float(amount);
1116 break; }
1117 }
1118
1119 QApplication::sendSpontaneousEvent(widget, &qNGEvent);
1120 break; }
1121
1122 default:
1123 handled_event = false;
1124 }
1125 if(!handled_event) //let the event go through
1126 return eventNotHandledErr;
1127 return noErr; //we eat the event
1128}
1129
1130// widget events
1131static HIObjectClassRef widget_class = 0;
1132static EventTypeSpec widget_events[] = {
1133 { kEventClassHIObject, kEventHIObjectConstruct },
1134 { kEventClassHIObject, kEventHIObjectDestruct },
1135
1136 { kEventClassControl, kEventControlDraw },
1137 { kEventClassControl, kEventControlInitialize },
1138 { kEventClassControl, kEventControlGetPartRegion },
1139 { kEventClassControl, kEventControlGetClickActivation },
1140 { kEventClassControl, kEventControlSetFocusPart },
1141 { kEventClassControl, kEventControlDragEnter },
1142 { kEventClassControl, kEventControlDragWithin },
1143 { kEventClassControl, kEventControlDragLeave },
1144 { kEventClassControl, kEventControlDragReceive },
1145 { kEventClassControl, kEventControlOwningWindowChanged },
1146 { kEventClassControl, kEventControlBoundsChanged },
1147 { kEventClassControl, kEventControlGetSizeConstraints },
1148 { kEventClassControl, kEventControlVisibilityChanged },
1149
1150 { kEventClassMouse, kEventMouseDown },
1151 { kEventClassMouse, kEventMouseUp },
1152 { kEventClassMouse, kEventMouseMoved },
1153 { kEventClassMouse, kEventMouseDragged }
1154};
1155static EventHandlerUPP mac_widget_eventUPP = 0;
1156static void cleanup_widget_eventUPP()
1157{
1158 DisposeEventHandlerUPP(mac_widget_eventUPP);
1159 mac_widget_eventUPP = 0;
1160}
1161static const EventHandlerUPP make_widget_eventUPP()
1162{
1163 if(mac_widget_eventUPP)
1164 return mac_widget_eventUPP;
1165 qAddPostRoutine(cleanup_widget_eventUPP);
1166 return mac_widget_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_widget_event);
1167}
1168OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, void *)
1169{
1170 QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData);
1171
1172 bool handled_event = true;
1173 UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
1174 switch(eclass) {
1175 case kEventClassHIObject: {
1176 HIViewRef view = 0;
1177 GetEventParameter(event, kEventParamHIObjectInstance, typeHIObjectRef,
1178 0, sizeof(view), 0, &view);
1179 if(ekind == kEventHIObjectConstruct) {
1180 if(view) {
1181 HIViewChangeFeatures(view, kHIViewAllowsSubviews, 0);
1182 SetEventParameter(event, kEventParamHIObjectInstance,
1183 typeVoidPtr, sizeof(view), &view);
1184 }
1185 } else if(ekind == kEventHIObjectDestruct) {
1186 //nothing to really do.. or is there?
1187 } else {
1188 handled_event = false;
1189 }
1190 break; }
1191 case kEventClassControl: {
1192 QWidget *widget = 0;
1193 HIViewRef hiview = 0;
1194 if(GetEventParameter(event, kEventParamDirectObject, typeControlRef,
1195 0, sizeof(hiview), 0, &hiview) == noErr)
1196 widget = QWidget::find((WId)hiview);
1197 if (widget && widget->macEvent(er, event))
1198 return noErr;
1199 if(ekind == kEventControlDraw) {
1200 if(widget && qt_isGenuineQWidget(hiview)) {
1201
1202 // if there is a window change event pending for any gl child wigets,
1203 // send it immediately. (required for flicker-free resizing)
1204 extern void qt_mac_send_posted_gl_updates(QWidget *widget);
1205 qt_mac_send_posted_gl_updates(widget);
1206
1207 if (QApplicationPrivate::graphicsSystem() && !widget->d_func()->paintOnScreen()) {
1208 widget->d_func()->syncBackingStore();
1209 widget->d_func()->dirtyOnWidget = QRegion();
1210 return noErr;
1211 }
1212
1213 //requested rgn
1214 RgnHandle rgn;
1215 GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0, sizeof(rgn), 0, &rgn);
1216 QRegion qrgn(qt_mac_convert_mac_region(rgn));
1217
1218 //update handles
1219 GrafPtr qd = 0;
1220 CGContextRef cg = 0;
1221 if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) {
1222 Q_ASSERT(false);
1223 }
1224 widget->d_func()->hd = cg;
1225 widget->d_func()->qd_hd = qd;
1226 CGContextSaveGState(cg);
1227
1228#ifdef DEBUG_WIDGET_PAINT
1229 const bool doDebug = true;
1230 if(doDebug) {
1231 qDebug("asked to draw %p[%p] [%s::%s] %p[%p] [%d] [%dx%d]", widget, hiview, widget->metaObject()->className(),
1232 widget->objectName().local8Bit().data(), widget->parentWidget(),
1233 (HIViewRef)(widget->parentWidget() ? qt_mac_nativeview_for(widget->parentWidget()) : (HIViewRef)0),
1234 HIViewIsCompositingEnabled(hiview), qt_mac_posInWindow(widget).x(), qt_mac_posInWindow(widget).y());
1235#if 0
1236 QVector<QRect> region_rects = qrgn.rects();
1237 qDebug("Region! %d", region_rects.count());
1238 for(int i = 0; i < region_rects.count(); i++)
1239 qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(),
1240 region_rects[i].width(), region_rects[i].height());
1241 region_rects = widget->d_func()->clp.rects();
1242 qDebug("Widget Region! %d", region_rects.count());
1243 for(int i = 0; i < region_rects.count(); i++)
1244 qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(),
1245 region_rects[i].width(), region_rects[i].height());
1246#endif
1247 }
1248#endif
1249 if (widget->isVisible() && widget->updatesEnabled()) { //process the actual paint event.
1250 if(widget->testAttribute(Qt::WA_WState_InPaintEvent))
1251 qWarning("QWidget::repaint: Recursive repaint detected");
1252
1253 QPoint redirectionOffset(0, 0);
1254 QWidget *tl = widget->window();
1255 if (tl) {
1256 Qt::WindowFlags flags = tl->windowFlags();
1257 if (flags & Qt::FramelessWindowHint
1258 || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint))) {
1259 if(tl->d_func()->extra && !tl->d_func()->extra->mask.isEmpty())
1260 redirectionOffset += tl->d_func()->extra->mask.boundingRect().topLeft();
1261 }
1262 }
1263
1264 //setup the context
1265 widget->setAttribute(Qt::WA_WState_InPaintEvent);
1266 QPaintEngine *engine = widget->paintEngine();
1267 if (engine)
1268 engine->setSystemClip(qrgn);
1269
1270 //handle the erase
1271 if (engine && (!widget->testAttribute(Qt::WA_NoSystemBackground)
1272 && (widget->isWindow() || widget->autoFillBackground())
1273 || widget->testAttribute(Qt::WA_TintedBackground)
1274 || widget->testAttribute(Qt::WA_StyledBackground))) {
1275#ifdef DEBUG_WIDGET_PAINT
1276 if(doDebug)
1277 qDebug(" Handling erase for [%s::%s]", widget->metaObject()->className(),
1278 widget->objectName().local8Bit().data());
1279#endif
1280 if (!redirectionOffset.isNull())
1281 widget->d_func()->setRedirected(widget, redirectionOffset);
1282
1283 bool was_unclipped = widget->testAttribute(Qt::WA_PaintUnclipped);
1284 widget->setAttribute(Qt::WA_PaintUnclipped, false);
1285 QPainter p(widget);
1286 p.setClipping(false);
1287 if(was_unclipped)
1288 widget->setAttribute(Qt::WA_PaintUnclipped);
1289 widget->d_func()->paintBackground(&p, qrgn, widget->isWindow() ? DrawAsRoot : 0);
1290 if (widget->testAttribute(Qt::WA_TintedBackground)) {
1291 QColor tint = widget->palette().window().color();
1292 tint.setAlphaF(.6);
1293 const QVector<QRect> &rects = qrgn.rects();
1294 for (int i = 0; i < rects.size(); ++i)
1295 p.fillRect(rects.at(i), tint);
1296 }
1297 p.end();
1298 if (!redirectionOffset.isNull())
1299 widget->d_func()->restoreRedirected();
1300 }
1301
1302 if (widget->isWindow() && !widget->d_func()->isOpaque
1303 && !widget->testAttribute(Qt::WA_MacBrushedMetal)) {
1304 QRect qrgnRect = qrgn.boundingRect();
1305 CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height()));
1306 }
1307
1308
1309 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
1310 CallNextEventHandler(er, event);
1311
1312 //send the paint
1313 redirectionOffset += widget->data->wrect.topLeft(); // Map from system to qt coordinates
1314 if (!redirectionOffset.isNull())
1315 widget->d_func()->setRedirected(widget, redirectionOffset);
1316 qrgn.translate(redirectionOffset);
1317 QPaintEvent e(qrgn);
1318 widget->d_func()->dirtyOnWidget = QRegion();
1319#ifdef QT3_SUPPORT
1320 e.setErased(true);
1321#endif
1322 QApplication::sendSpontaneousEvent(widget, &e);
1323 if (!redirectionOffset.isNull())
1324 widget->d_func()->restoreRedirected();
1325
1326 //cleanup
1327 if (engine)
1328 engine->setSystemClip(QRegion());
1329
1330 widget->setAttribute(Qt::WA_WState_InPaintEvent, false);
1331 if(!widget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && widget->paintingActive())
1332 qWarning("QWidget: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1333 }
1334
1335 widget->d_func()->hd = 0;
1336 widget->d_func()->qd_hd = 0;
1337 CGContextRestoreGState(cg);
1338 } else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) {
1339 CallNextEventHandler(er, event);
1340 }
1341 } else if(ekind == kEventControlInitialize) {
1342 if(HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) {
1343 UInt32 features = kControlSupportsDragAndDrop | kControlSupportsClickActivation | kControlSupportsFocus;
1344 SetEventParameter(event, kEventParamControlFeatures, typeUInt32, sizeof(features), &features);
1345 } else {
1346 handled_event = false;
1347 }
1348 } else if(ekind == kEventControlSetFocusPart) {
1349 if(widget) {
1350 ControlPartCode part;
1351 GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0,
1352 sizeof(part), 0, &part);
1353 if(part == kControlFocusNoPart){
1354 if (widget->hasFocus())
1355 QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
1356 } else
1357 widget->setFocus();
1358 }
1359 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
1360 CallNextEventHandler(er, event);
1361 } else if(ekind == kEventControlGetClickActivation) {
1362 ClickActivationResult clickT = kActivateAndIgnoreClick;
1363 SetEventParameter(event, kEventParamClickActivation, typeClickActivationResult,
1364 sizeof(clickT), &clickT);
1365 } else if(ekind == kEventControlGetPartRegion) {
1366 handled_event = false;
1367 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget) && CallNextEventHandler(er, event) == noErr) {
1368 handled_event = true;
1369 break;
1370 }
1371 if(widget && !widget->isWindow()) {
1372 ControlPartCode part;
1373 GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0,
1374 sizeof(part), 0, &part);
1375 if(part == kControlClickableMetaPart && widget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
1376 RgnHandle rgn;
1377 GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0,
1378 sizeof(rgn), 0, &rgn);
1379 SetEmptyRgn(rgn);
1380 handled_event = true;
1381 } else if(part == kControlStructureMetaPart || part == kControlClickableMetaPart) {
1382 RgnHandle rgn;
1383 GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0,
1384 sizeof(rgn), 0, &rgn);
1385 SetRectRgn(rgn, 0, 0, widget->width(), widget->height());
1386 if(QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false))
1387 handled_event = true;
1388 } else if(part == kControlOpaqueMetaPart) {
1389 if(widget->d_func()->isOpaque) {
1390 RgnHandle rgn;
1391 GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0,
1392 sizeof(RgnHandle), 0, &rgn);
1393 SetRectRgn(rgn, 0, 0, widget->width(), widget->height());
1394 QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false);
1395 SetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle,
1396 sizeof(RgnHandle), &rgn);
1397 handled_event = true;
1398 }
1399 }
1400 }
1401 } else if(ekind == kEventControlOwningWindowChanged) {
1402 if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
1403 CallNextEventHandler(er, event);
1404 if(widget && qt_mac_window_for(hiview)) {
1405 WindowRef foo = 0;
1406 GetEventParameter(event, kEventParamControlCurrentOwningWindow, typeWindowRef, 0,
1407 sizeof(foo), 0, &foo);
1408 widget->d_func()->initWindowPtr();
1409 }
1410 if (widget)
1411 qt_event_request_window_change(widget);
1412 } else if(ekind == kEventControlDragEnter || ekind == kEventControlDragWithin ||
1413 ekind == kEventControlDragLeave || ekind == kEventControlDragReceive) {
1414 // dnd are really handled in qdnd_mac.cpp,
1415 // just modularize the code a little...
1416 DragRef drag;
1417 GetEventParameter(event, kEventParamDragRef, typeDragRef, 0, sizeof(drag), 0, &drag);
1418 handled_event = false;
1419 bool drag_allowed = false;
1420
1421 QWidget *dropWidget = widget;
1422 if (qobject_cast<QFocusFrame *>(widget)){
1423 // We might shadow widgets underneath the focus
1424 // frame, so stay interrested, and let the dnd through
1425 drag_allowed = true;
1426 handled_event = true;
1427 Point where;
1428 GetDragMouse(drag, &where, 0);
1429 dropWidget = QApplication::widgetAt(QPoint(where.h, where.v));
1430
1431 if (dropWidget != QDragManager::self()->currentTarget()) {
1432 // We have to 'fake' enter and leave events for the shaddowed widgets:
1433 if (ekind == kEventControlDragEnter) {
1434 if (QDragManager::self()->currentTarget())
1435 QDragManager::self()->currentTarget()->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag);
1436 if (dropWidget) {
1437 dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragEnter, drag);
1438 }
1439 // Set dropWidget to zero, so qt_mac_dnd_event
1440 // doesn't get called a second time below:
1441 dropWidget = 0;
1442 } else if (ekind == kEventControlDragLeave) {
1443 dropWidget = QDragManager::self()->currentTarget();
1444 if (dropWidget) {
1445 dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag);
1446 }
1447 // Set dropWidget to zero, so qt_mac_dnd_event
1448 // doesn't get called a second time below:
1449 dropWidget = 0;
1450 }
1451 }
1452 }
1453
1454 // Send the dnd event to the widget:
1455 if (dropWidget && dropWidget->d_func()->qt_mac_dnd_event(ekind, drag)) {
1456 drag_allowed = true;
1457 handled_event = true;
1458 }
1459
1460 if (ekind == kEventControlDragEnter) {
1461 // If we don't accept the enter event, we will
1462 // receive no more drag events for this widget
1463 const Boolean wouldAccept = drag_allowed ? true : false;
1464 SetEventParameter(event, kEventParamControlWouldAcceptDrop, typeBoolean,
1465 sizeof(wouldAccept), &wouldAccept);
1466 }
1467 } else if (ekind == kEventControlBoundsChanged) {
1468 if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_Moved) || widget->testAttribute(Qt::WA_Resized)) {
1469 handled_event = false;
1470 } else {
1471 // Sync our view in case some other (non-Qt) view is controlling us.
1472 handled_event = true;
1473 Rect newBounds;
1474 GetEventParameter(event, kEventParamCurrentBounds,
1475 typeQDRectangle, 0, sizeof(Rect), 0, &newBounds);
1476 QRect rect(newBounds.left, newBounds.top,
1477 newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
1478
1479 bool moved = widget->testAttribute(Qt::WA_Moved);
1480 bool resized = widget->testAttribute(Qt::WA_Resized);
1481 widget->setGeometry(rect);
1482 widget->setAttribute(Qt::WA_Moved, moved);
1483 widget->setAttribute(Qt::WA_Resized, resized);
1484 qt_event_request_window_change(widget);
1485 }
1486 } else if (ekind == kEventControlGetSizeConstraints) {
1487 if (!widget || !qt_isGenuineQWidget(widget)) {
1488 handled_event = false;
1489 } else {
1490 handled_event = true;
1491 QWidgetItem item(widget);
1492 QSize size = item.minimumSize();
1493 HISize hisize = { size.width(), size.height() };
1494 SetEventParameter(event, kEventParamMinimumSize, typeHISize, sizeof(HISize), &hisize);
1495 size = item.maximumSize();
1496 hisize.width = size.width() + 2; // ### shouldn't have to add 2 (but it works).
1497 hisize.height = size.height();
1498 SetEventParameter(event, kEventParamMaximumSize, typeHISize, sizeof(HISize), &hisize);
1499 }
1500 } else if (ekind == kEventControlVisibilityChanged) {
1501 handled_event = false;
1502 if (widget) {
1503 qt_event_request_window_change(widget);
1504 if (!HIViewIsVisible(HIViewRef(widget->winId()))) {
1505 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
1506 if (widget == qt_button_down)
1507 qt_button_down = 0;
1508 }
1509 }
1510 }
1511 break; }
1512 case kEventClassMouse: {
1513 bool send_to_app = false;
1514 extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
1515 if(qt_button_down)
1516 send_to_app = true;
1517 if(send_to_app) {
1518 OSStatus err = SendEventToApplication(event);
1519 if(err != noErr)
1520 handled_event = false;
1521 } else {
1522 CallNextEventHandler(er, event);
1523 }
1524 break; }
1525 default:
1526 handled_event = false;
1527 break;
1528 }
1529 if(!handled_event) //let the event go through
1530 return eventNotHandledErr;
1531 return noErr; //we eat the event
1532}
1533#endif
1534
1535OSViewRef qt_mac_create_widget(QWidget *widget, QWidgetPrivate *widgetPrivate, OSViewRef parent)
1536{
1537#ifdef QT_MAC_USE_COCOA
1538 QMacCocoaAutoReleasePool pool;
1539 QT_MANGLE_NAMESPACE(QCocoaView) *view = [[QT_MANGLE_NAMESPACE(QCocoaView) alloc] initWithQWidget:widget widgetPrivate:widgetPrivate];
1540 if (view && parent)
1541 [parent addSubview:view];
1542 return view;
1543#else
1544 Q_UNUSED(widget);
1545 Q_UNUSED(widgetPrivate);
1546 if(!widget_class) {
1547 OSStatus err = HIObjectRegisterSubclass(kObjectQWidget, kHIViewClassID, 0, make_widget_eventUPP(),
1548 GetEventTypeCount(widget_events), widget_events,
1549 0, &widget_class);
1550 if (err && err != hiObjectClassExistsErr)
1551 qWarning("QWidget: Internal error (%d)", __LINE__);
1552 }
1553 HIViewRef ret = 0;
1554 if(HIObjectCreate(kObjectQWidget, 0, (HIObjectRef*)&ret) != noErr)
1555 qWarning("QWidget: Internal error (%d)", __LINE__);
1556 if(ret && parent)
1557 HIViewAddSubview(parent, ret);
1558 return ret;
1559#endif
1560}
1561
1562void qt_mac_unregister_widget()
1563{
1564#ifndef QT_MAC_USE_COCOA
1565 HIObjectUnregisterClass(widget_class);
1566 widget_class = 0;
1567#endif
1568}
1569
1570void QWidgetPrivate::toggleDrawers(bool visible)
1571{
1572 for (int i = 0; i < children.size(); ++i) {
1573 register QObject *object = children.at(i);
1574 if (!object->isWidgetType())
1575 continue;
1576 QWidget *widget = static_cast<QWidget*>(object);
1577 if(qt_mac_is_macdrawer(widget)) {
1578 if(visible) {
1579 if (!widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
1580 widget->show();
1581 } else {
1582 widget->hide();
1583 widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
1584 }
1585 }
1586 }
1587}
1588
1589/*****************************************************************************
1590 QWidgetPrivate member functions
1591 *****************************************************************************/
1592bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up)
1593{
1594 // I'm not sure what "up" is
1595 if(!w || !w->isWindow())
1596 return false;
1597
1598 QTLWExtra *topData = w->d_func()->topData();
1599 QWExtra *extraData = w->d_func()->extraData();
1600 // topData->resizer is only 4 bits, so subtracting -1 from zero causes bad stuff
1601 // to happen, prevent that here (you really want the thing hidden).
1602 if (up >= 0 || topData->resizer != 0)
1603 topData->resizer += up;
1604 OSWindowRef windowRef = qt_mac_window_for(OSViewRef(w->winId()));
1605 {
1606#ifndef QT_MAC_USE_COCOA
1607 WindowClass wclass;
1608 GetWindowClass(windowRef, &wclass);
1609 if(!(GetAvailableWindowAttributes(wclass) & kWindowResizableAttribute))
1610 return true;
1611#endif
1612 }
1613 bool remove_grip = (topData->resizer || (w->windowFlags() & Qt::FramelessWindowHint)
1614 || (extraData->maxw && extraData->maxh &&
1615 extraData->maxw == extraData->minw && extraData->maxh == extraData->minh));
1616#ifndef QT_MAC_USE_COCOA
1617 WindowAttributes attr;
1618 GetWindowAttributes(windowRef, &attr);
1619 if(remove_grip) {
1620 if(attr & kWindowResizableAttribute) {
1621 ChangeWindowAttributes(qt_mac_window_for(w), kWindowNoAttributes,
1622 kWindowResizableAttribute);
1623 ReshapeCustomWindow(qt_mac_window_for(w));
1624 }
1625 } else if(!(attr & kWindowResizableAttribute)) {
1626 ChangeWindowAttributes(windowRef, kWindowResizableAttribute,
1627 kWindowNoAttributes);
1628 ReshapeCustomWindow(windowRef);
1629 }
1630#else
1631 [windowRef setShowsResizeIndicator:!remove_grip];
1632#endif
1633 return true;
1634}
1635
1636void QWidgetPrivate::qt_clean_root_win()
1637{
1638#ifdef QT_MAC_USE_COCOA
1639 [qt_root_win release];
1640#else
1641 if(!qt_root_win)
1642 return;
1643 CFRelease(qt_root_win);
1644#endif
1645 qt_root_win = 0;
1646}
1647
1648bool QWidgetPrivate::qt_create_root_win()
1649{
1650 if(qt_root_win)
1651 return false;
1652 const QSize desktopSize = qt_mac_desktopSize();
1653 QRect desktopRect(QPoint(0, 0), desktopSize);
1654#ifdef QT_MAC_USE_COCOA
1655 qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, NSBorderlessWindowMask, desktopRect);
1656#else
1657 WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute);
1658 qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, wattr, desktopRect);
1659#endif
1660 if(!qt_root_win)
1661 return false;
1662 qAddPostRoutine(qt_clean_root_win);
1663 return true;
1664}
1665
1666bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false)
1667{
1668 bool ret = false;
1669#ifndef QT_MAC_USE_COCOA
1670 switch(wcode) {
1671 case kWindowStructureRgn: {
1672 if(widget) {
1673 if(widget->d_func()->extra && !widget->d_func()->extra->mask.isEmpty()) {
1674 QRegion rin = qt_mac_convert_mac_region(rgn);
1675 if(!rin.isEmpty()) {
1676 QPoint rin_tl = rin.boundingRect().topLeft(); //in offset
1677 rin.translate(-rin_tl.x(), -rin_tl.y()); //bring into same space as below
1678 QRegion mask = widget->d_func()->extra->mask;
1679 Qt::WindowFlags flags = widget->windowFlags();
1680 if(widget->isWindow()
1681 && !(flags & Qt::FramelessWindowHint
1682 || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint)))) {
1683 QRegion title;
1684 {
1685 QMacSmartQuickDrawRegion rgn(qt_mac_get_rgn());
1686 GetWindowRegion(qt_mac_window_for(widget), kWindowTitleBarRgn, rgn);
1687 title = qt_mac_convert_mac_region(rgn);
1688 }
1689 QRect br = title.boundingRect();
1690 mask.translate(0, br.height()); //put the mask 'under' the title bar..
1691 title.translate(-br.x(), -br.y());
1692 mask += title;
1693 }
1694
1695 QRegion cr = rin & mask;
1696 cr.translate(rin_tl.x(), rin_tl.y()); //translate back to incoming space
1697 CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn);
1698 }
1699 ret = true;
1700 } else if(force) {
1701 QRegion cr(widget->geometry());
1702 CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn);
1703 ret = true;
1704 }
1705 }
1706 break; }
1707 default: break;
1708 }
1709 //qDebug() << widget << ret << wcode << qt_mac_convert_mac_region(rgn);
1710#else
1711 Q_UNUSED(widget);
1712 Q_UNUSED(wcode);
1713 Q_UNUSED(rgn);
1714 Q_UNUSED(force);
1715#endif
1716 return ret;
1717}
1718
1719/*****************************************************************************
1720 QWidget member functions
1721 *****************************************************************************/
1722void QWidgetPrivate::determineWindowClass()
1723{
1724 Q_Q(QWidget);
1725#if !defined(QT_NO_MAINWINDOW) && !defined(QT_NO_TOOLBAR)
1726 // Make sure that QMainWindow has the MacWindowToolBarButtonHint when the
1727 // unifiedTitleAndToolBarOnMac property is ON. This is to avoid reentry of
1728 // setParent() triggered by the QToolBar::event(QEvent::ParentChange).
1729 QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q);
1730 if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) {
1731 data.window_flags |= Qt::MacWindowToolBarButtonHint;
1732 }
1733#endif
1734#ifndef QT_MAC_USE_COCOA
1735// ### COCOA:Interleave these better!
1736
1737 const Qt::WindowType type = q->windowType();
1738 Qt::WindowFlags &flags = data.window_flags;
1739 const bool popup = (type == Qt::Popup);
1740 if (type == Qt::ToolTip || type == Qt::SplashScreen || popup)
1741 flags |= Qt::FramelessWindowHint;
1742
1743 WindowClass wclass = kSheetWindowClass;
1744 if(qt_mac_is_macdrawer(q))
1745 wclass = kDrawerWindowClass;
1746 else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint)
1747 wclass = kDocumentWindowClass;
1748 else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen))
1749 wclass = kModalWindowClass;
1750 else if(q->testAttribute(Qt::WA_ShowModal))
1751 wclass = kMovableModalWindowClass;
1752 else if(type == Qt::ToolTip)
1753 wclass = kHelpWindowClass;
1754 else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5
1755 && type == Qt::SplashScreen))
1756 wclass = kFloatingWindowClass;
1757 else
1758 wclass = kDocumentWindowClass;
1759
1760 WindowGroupRef grp = 0;
1761 WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute);
1762 if (q->testAttribute(Qt::WA_MacFrameworkScaled))
1763 wattr |= kWindowFrameworkScaledAttribute;
1764 if(qt_mac_is_macsheet(q)) {
1765 //grp = GetWindowGroupOfClass(kMovableModalWindowClass);
1766 wclass = kSheetWindowClass;
1767 } else {
1768 grp = GetWindowGroupOfClass(wclass);
1769 // Shift things around a bit to get the correct window class based on the presence
1770 // (or lack) of the border.
1771 bool customize = flags & Qt::CustomizeWindowHint;
1772 bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint)));
1773 if (framelessWindow) {
1774 if(wclass == kDocumentWindowClass) {
1775 wattr |= kWindowNoTitleBarAttribute;
1776 } else if(wclass == kFloatingWindowClass) {
1777 wattr |= kWindowNoTitleBarAttribute;
1778 } else if (wclass == kMovableModalWindowClass) {
1779 wclass = kModalWindowClass;
1780 }
1781 } else {
1782 if(wclass != kModalWindowClass)
1783 wattr |= kWindowResizableAttribute;
1784 }
1785 // Only add extra decorations (well, buttons) for widgets that can have them
1786 // and have an actual border we can put them on.
1787 if(wclass != kModalWindowClass && wclass != kMovableModalWindowClass
1788 && wclass != kSheetWindowClass && wclass != kPlainWindowClass
1789 && !framelessWindow && wclass != kDrawerWindowClass
1790 && wclass != kHelpWindowClass) {
1791 if (flags & Qt::WindowMaximizeButtonHint)
1792 wattr |= kWindowFullZoomAttribute;
1793 if (flags & Qt::WindowMinimizeButtonHint)
1794 wattr |= kWindowCollapseBoxAttribute;
1795 if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint)
1796 wattr |= kWindowCloseBoxAttribute;
1797 if (flags & Qt::MacWindowToolBarButtonHint)
1798 wattr |= kWindowToolbarButtonAttribute;
1799 } else {
1800 // Clear these hints so that we aren't call them on invalid windows
1801 flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint
1802 | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
1803 }
1804 }
1805 if((popup || type == Qt::Tool) && !q->isModal())
1806 wattr |= kWindowHideOnSuspendAttribute;
1807 wattr |= kWindowLiveResizeAttribute;
1808
1809#ifdef DEBUG_WINDOW_CREATE
1810#define ADD_DEBUG_WINDOW_NAME(x) { x, #x }
1811 struct {
1812 UInt32 tag;
1813 const char *name;
1814 } known_attribs[] = {
1815 ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute),
1816 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1817 ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute),
1818 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1819 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1820 ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute),
1821 ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute),
1822 ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute),
1823 ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute),
1824 ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute),
1825 ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute),
1826 ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute),
1827 ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute),
1828 ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute),
1829 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1830 { 0, 0 }
1831 }, known_classes[] = {
1832 ADD_DEBUG_WINDOW_NAME(kHelpWindowClass),
1833 ADD_DEBUG_WINDOW_NAME(kPlainWindowClass),
1834 ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass),
1835 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1836 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1837 ADD_DEBUG_WINDOW_NAME(kSheetWindowClass),
1838 ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass),
1839 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1840 ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass),
1841 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1842 ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass),
1843 ADD_DEBUG_WINDOW_NAME(kModalWindowClass),
1844 { 0, 0 }
1845 };
1846 qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(),
1847 q->objectName().toLocal8Bit().constData());
1848 bool found_class = false;
1849 for(int i = 0; known_classes[i].name; i++) {
1850 if(wclass == known_classes[i].tag) {
1851 found_class = true;
1852 qDebug("Qt: internal: ** Class: %s", known_classes[i].name);
1853 break;
1854 }
1855 }
1856 if(!found_class)
1857 qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass);
1858 if(wattr) {
1859 WindowAttributes tmp_wattr = wattr;
1860 qDebug("Qt: internal: ** Attributes:");
1861 for(int i = 0; tmp_wattr && known_attribs[i].name; i++) {
1862 if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) {
1863 tmp_wattr ^= known_attribs[i].tag;
1864 qDebug("Qt: internal: * %s %s", known_attribs[i].name,
1865 (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)");
1866 }
1867 }
1868 if(tmp_wattr)
1869 qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr);
1870 }
1871#endif
1872
1873 /* Just to be extra careful we will change to the kUtilityWindowClass if the
1874 requested attributes cannot be used */
1875 if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) {
1876 WindowClass tmp_class = wclass;
1877 if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass)
1878 wclass = kFloatingWindowClass;
1879 if(tmp_class != wclass) {
1880 if(!grp)
1881 grp = GetWindowGroupOfClass(wclass);
1882 wclass = tmp_class;
1883 }
1884 }
1885 topData()->wclass = wclass;
1886 topData()->wattr = wattr;
1887#else
1888 const Qt::WindowType type = q->windowType();
1889 Qt::WindowFlags &flags = data.window_flags;
1890 const bool popup = (type == Qt::Popup);
1891 if (type == Qt::ToolTip || type == Qt::SplashScreen || popup)
1892 flags |= Qt::FramelessWindowHint;
1893
1894 WindowClass wclass = kSheetWindowClass;
1895 if(qt_mac_is_macdrawer(q))
1896 wclass = kDrawerWindowClass;
1897 else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint)
1898 wclass = kDocumentWindowClass;
1899 else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen))
1900 wclass = kModalWindowClass;
1901 else if(q->testAttribute(Qt::WA_ShowModal) || type == Qt::Dialog)
1902 wclass = kMovableModalWindowClass;
1903 else if(type == Qt::ToolTip)
1904 wclass = kHelpWindowClass;
1905 else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5
1906 && type == Qt::SplashScreen))
1907 wclass = kFloatingWindowClass;
1908 else
1909 wclass = kDocumentWindowClass;
1910
1911 WindowAttributes wattr = NSBorderlessWindowMask;
1912 if(qt_mac_is_macsheet(q)) {
1913 //grp = GetWindowGroupOfClass(kMovableModalWindowClass);
1914 wclass = kSheetWindowClass;
1915 wattr = NSTitledWindowMask | NSResizableWindowMask;
1916 } else {
1917#ifndef QT_MAC_USE_COCOA
1918 grp = GetWindowGroupOfClass(wclass);
1919#endif
1920 // Shift things around a bit to get the correct window class based on the presence
1921 // (or lack) of the border.
1922 bool customize = flags & Qt::CustomizeWindowHint;
1923 bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint)));
1924 if (framelessWindow) {
1925 if (wclass == kDocumentWindowClass) {
1926 wclass = kSimpleWindowClass;
1927 } else if (wclass == kFloatingWindowClass) {
1928 wclass = kToolbarWindowClass;
1929 } else if (wclass == kMovableModalWindowClass) {
1930 wclass = kModalWindowClass;
1931 }
1932 } else {
1933 wattr |= NSTitledWindowMask;
1934 if (wclass != kModalWindowClass)
1935 wattr |= NSResizableWindowMask;
1936 }
1937 // Only add extra decorations (well, buttons) for widgets that can have them
1938 // and have an actual border we can put them on.
1939 if (wclass != kModalWindowClass
1940 && wclass != kSheetWindowClass && wclass != kPlainWindowClass
1941 && !framelessWindow && wclass != kDrawerWindowClass
1942 && wclass != kHelpWindowClass) {
1943 if (flags & Qt::WindowMinimizeButtonHint)
1944 wattr |= NSMiniaturizableWindowMask;
1945 if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint)
1946 wattr |= NSClosableWindowMask;
1947 } else {
1948 // Clear these hints so that we aren't call them on invalid windows
1949 flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint
1950 | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
1951 }
1952 }
1953 if (q->testAttribute(Qt::WA_MacBrushedMetal))
1954 wattr |= NSTexturedBackgroundWindowMask;
1955
1956#ifdef DEBUG_WINDOW_CREATE
1957#define ADD_DEBUG_WINDOW_NAME(x) { x, #x }
1958 struct {
1959 UInt32 tag;
1960 const char *name;
1961 } known_attribs[] = {
1962 ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute),
1963 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1964 ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute),
1965 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1966 ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute),
1967 ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute),
1968 ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute),
1969 ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute),
1970 ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute),
1971 ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute),
1972 ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute),
1973 ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute),
1974 ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute),
1975 ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute),
1976 ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute),
1977 { 0, 0 }
1978 }, known_classes[] = {
1979 ADD_DEBUG_WINDOW_NAME(kHelpWindowClass),
1980 ADD_DEBUG_WINDOW_NAME(kPlainWindowClass),
1981 ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass),
1982 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1983 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1984 ADD_DEBUG_WINDOW_NAME(kSheetWindowClass),
1985 ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass),
1986 ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass),
1987 ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass),
1988 ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass),
1989 ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass),
1990 ADD_DEBUG_WINDOW_NAME(kModalWindowClass),
1991 { 0, 0 }
1992 };
1993 qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(),
1994 q->objectName().toLocal8Bit().constData());
1995 bool found_class = false;
1996 for(int i = 0; known_classes[i].name; i++) {
1997 if(wclass == known_classes[i].tag) {
1998 found_class = true;
1999 qDebug("Qt: internal: ** Class: %s", known_classes[i].name);
2000 break;
2001 }
2002 }
2003 if(!found_class)
2004 qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass);
2005 if(wattr) {
2006 WindowAttributes tmp_wattr = wattr;
2007 qDebug("Qt: internal: ** Attributes:");
2008 for(int i = 0; tmp_wattr && known_attribs[i].name; i++) {
2009 if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) {
2010 tmp_wattr ^= known_attribs[i].tag;
2011 qDebug("Qt: internal: * %s %s", known_attribs[i].name,
2012 (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)");
2013 }
2014 }
2015 if(tmp_wattr)
2016 qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr);
2017 }
2018#endif
2019
2020#ifndef QT_MAC_USE_COCOA
2021 /* Just to be extra careful we will change to the kUtilityWindowClass if the
2022 requested attributes cannot be used */
2023 if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) {
2024 WindowClass tmp_class = wclass;
2025 if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass)
2026 wclass = kFloatingWindowClass;
2027 if(tmp_class != wclass) {
2028 if(!grp)
2029 grp = GetWindowGroupOfClass(wclass);
2030 wclass = tmp_class;
2031 }
2032 }
2033#endif
2034#endif
2035 topData()->wclass = wclass;
2036 topData()->wattr = wattr;
2037}
2038
2039#ifndef QT_MAC_USE_COCOA // This is handled in Cocoa via our category.
2040void QWidgetPrivate::initWindowPtr()
2041{
2042 Q_Q(QWidget);
2043 OSWindowRef windowRef = qt_mac_window_for(qt_mac_nativeview_for(q)); //do not create!
2044 if(!windowRef)
2045 return;
2046 QWidget *window = q->window(), *oldWindow = 0;
2047 if(GetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(oldWindow), 0, &oldWindow) == noErr) {
2048 Q_ASSERT(window == oldWindow);
2049 return;
2050 }
2051
2052 if(SetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(window), &window) != noErr)
2053 qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__); //no real way to recover
2054 if(!q->windowType() != Qt::Desktop) { //setup an event callback handler on the window
2055 InstallWindowEventHandler(windowRef, make_win_eventUPP(), GetEventTypeCount(window_events),
2056 window_events, static_cast<void *>(qApp), &window_event);
2057 }
2058}
2059
2060void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef)
2061{
2062 Q_Q(QWidget);
2063 const Qt::WindowType type = q->windowType();
2064 Qt::WindowFlags &flags = data.window_flags;
2065 QWidget *parentWidget = q->parentWidget();
2066
2067 const bool desktop = (type == Qt::Desktop);
2068 const bool dialog = (type == Qt::Dialog
2069 || type == Qt::Sheet
2070 || type == Qt::Drawer
2071 || (flags & Qt::MSWindowsFixedSizeDialogHint));
2072 QTLWExtra *topExtra = topData();
2073 quint32 wattr = topExtra->wattr;
2074 if (!desktop)
2075 SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true);
2076 HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0);
2077 if (wattr & kWindowHideOnSuspendAttribute)
2078 HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0);
2079 else
2080 HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden);
2081 if ((flags & Qt::WindowStaysOnTopHint))
2082 ChangeWindowAttributes(windowRef, kWindowNoAttributes, kWindowHideOnSuspendAttribute);
2083 if (qt_mac_is_macdrawer(q) && parentWidget)
2084 SetDrawerParent(windowRef, qt_mac_window_for (parentWidget));
2085 if (topExtra->group) {
2086 qt_mac_release_window_group(topExtra->group);
2087 topExtra->group = 0;
2088 }
2089 if (type == Qt::ToolTip)
2090 qt_mac_set_window_group_to_tooltip(windowRef);
2091 else if (type == Qt::Popup && (flags & Qt::WindowStaysOnTopHint))
2092 qt_mac_set_window_group_to_popup(windowRef);
2093 else if (flags & Qt::WindowStaysOnTopHint)
2094 qt_mac_set_window_group_to_stays_on_top(windowRef, type);
2095 else if (dialog)
2096 SetWindowGroup(windowRef, GetWindowGroupOfClass(kMovableModalWindowClass));
2097
2098#ifdef DEBUG_WINDOW_CREATE
2099 if (WindowGroupRef grpf = GetWindowGroup(windowRef)) {
2100 QCFString cfname;
2101 CopyWindowGroupName(grpf, &cfname);
2102 SInt32 lvl;
2103 GetWindowGroupLevel(grpf, &lvl);
2104 const char *from = "Default";
2105 if (topExtra && grpf == topData()->group)
2106 from = "Created";
2107 else if (grpf == grp)
2108 from = "Copied";
2109 qDebug("Qt: internal: With window group '%s' [%p] @ %d: %s",
2110 static_cast<QString>(cfname).toLatin1().constData(), grpf, (int)lvl, from);
2111 } else {
2112 qDebug("Qt: internal: No window group!!!");
2113 }
2114 HIWindowAvailability hi_avail = 0;
2115 if (HIWindowGetAvailability(windowRef, &hi_avail) == noErr) {
2116 struct {
2117 UInt32 tag;
2118 const char *name;
2119 } known_avail[] = {
2120 ADD_DEBUG_WINDOW_NAME(kHIWindowExposeHidden),
2121 { 0, 0 }
2122 };
2123 qDebug("Qt: internal: ** HIWindowAvailibility:");
2124 for (int i = 0; hi_avail && known_avail[i].name; i++) {
2125 if ((hi_avail & known_avail[i].tag) == known_avail[i].tag) {
2126 hi_avail ^= known_avail[i].tag;
2127 qDebug("Qt: internal: * %s", known_avail[i].name);
2128 }
2129 }
2130 if (hi_avail)
2131 qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)hi_avail);
2132 }
2133#undef ADD_DEBUG_WINDOW_NAME
2134#endif
2135 if (extra && !extra->mask.isEmpty())
2136 ReshapeCustomWindow(windowRef);
2137 SetWindowModality(windowRef, kWindowModalityNone, 0);
2138 if (qt_mac_is_macdrawer(q))
2139 SetDrawerOffsets(windowRef, 0.0, 25.0);
2140 data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty
2141 HIViewRef hiview = (HIViewRef)data.winid;
2142 HIViewRef window_hiview = qt_mac_get_contentview_for(windowRef);
2143 if(!hiview) {
2144 hiview = qt_mac_create_widget(q, this, window_hiview);
2145 setWinId((WId)hiview);
2146 } else {
2147 HIViewAddSubview(window_hiview, hiview);
2148 }
2149 if (hiview) {
2150 Rect win_rect;
2151 GetWindowBounds(qt_mac_window_for (window_hiview), kWindowContentRgn, &win_rect);
2152 HIRect bounds = CGRectMake(0, 0, win_rect.right-win_rect.left, win_rect.bottom-win_rect.top);
2153 HIViewSetFrame(hiview, &bounds);
2154 HIViewSetVisible(hiview, true);
2155 if (q->testAttribute(Qt::WA_DropSiteRegistered))
2156 registerDropSite(true);
2157 transferChildren();
2158 }
2159 initWindowPtr();
2160
2161 if (topExtra->posFromMove) {
2162 updateFrameStrut();
2163 const QRect &fStrut = frameStrut();
2164 Rect r;
2165 SetRect(&r, data.crect.left(), data.crect.top(), data.crect.right() + 1, data.crect.bottom() + 1);
2166 SetRect(&r, r.left + fStrut.left(), r.top + fStrut.top(),
2167 (r.left + fStrut.left() + data.crect.width()) - fStrut.right(),
2168 (r.top + fStrut.top() + data.crect.height()) - fStrut.bottom());
2169 SetWindowBounds(windowRef, kWindowContentRgn, &r);
2170 topExtra->posFromMove = false;
2171 }
2172
2173 if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){
2174 q->setWindowOpacity(topExtra->opacity / 255.0f);
2175 } else if (qt_mac_is_macsheet(q)){
2176 SetThemeWindowBackground(qt_mac_window_for(q), kThemeBrushSheetBackgroundTransparent, true);
2177 CGFloat alpha = 0;
2178 GetWindowAlpha(qt_mac_window_for(q), &alpha);
2179 if (alpha == 1){
2180 // For some reason the 'SetThemeWindowBackground' does not seem
2181 // to work. So we do this little hack until it hopefully starts to
2182 // work in newer versions of mac OS.
2183 q->setWindowOpacity(0.95f);
2184 q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
2185 }
2186 } else{
2187 // If the window has been recreated after beeing e.g. a sheet,
2188 // make sure that we don't report a faulty opacity:
2189 q->setWindowOpacity(1.0f);
2190 q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
2191 }
2192
2193 // Since we only now have a window, sync our state.
2194 macUpdateHideOnSuspend();
2195 macUpdateOpaqueSizeGrip();
2196 macUpdateMetalAttribute();
2197 macUpdateIgnoreMouseEvents();
2198 setWindowTitle_helper(extra->topextra->caption);
2199 setWindowIconText_helper(extra->topextra->iconText);
2200 setWindowFilePath_helper(extra->topextra->filePath);
2201 setWindowModified_sys(q->isWindowModified());
2202 updateFrameStrut();
2203 qt_mac_update_sizer(q);
2204 applyMaxAndMinSizeOnWindow();
2205}
2206#else // QT_MAC_USE_COCOA
2207void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef)
2208{
2209 Q_Q(QWidget);
2210 QMacCocoaAutoReleasePool pool;
2211 NSWindow *windowRef = static_cast<NSWindow *>(voidWindowRef);
2212 const Qt::WindowType type = q->windowType();
2213 Qt::WindowFlags &flags = data.window_flags;
2214 QWidget *parentWidget = q->parentWidget();
2215
2216 const bool popup = (type == Qt::Popup);
2217 const bool dialog = (type == Qt::Dialog
2218 || type == Qt::Sheet
2219 || type == Qt::Drawer
2220 || (flags & Qt::MSWindowsFixedSizeDialogHint));
2221 QTLWExtra *topExtra = topData();
2222
2223 if ((popup || type == Qt::Tool || type == Qt::ToolTip) && !q->isModal()) {
2224 [windowRef setHidesOnDeactivate:YES];
2225 } else {
2226 [windowRef setHidesOnDeactivate:NO];
2227 }
2228 [windowRef setHasShadow:YES];
2229 Q_UNUSED(parentWidget);
2230 Q_UNUSED(dialog);
2231
2232 data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty
2233 OSViewRef nsview = (OSViewRef)data.winid;
2234 OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef);
2235 if (!nsview) {
2236 nsview = qt_mac_create_widget(q, this, window_contentview);
2237 setWinId(WId(nsview));
2238 } else {
2239 [window_contentview addSubview:nsview];
2240 }
2241 if (nsview) {
2242 NSRect bounds = [window_contentview bounds];
2243 [nsview setFrame:bounds];
2244 [nsview setHidden:NO];
2245 if (q->testAttribute(Qt::WA_DropSiteRegistered))
2246 registerDropSite(true);
2247 transferChildren();
2248 }
2249
2250 if (topExtra->posFromMove) {
2251 updateFrameStrut();
2252
2253 const QRect &fStrut = frameStrut();
2254 const QRect &crect = data.crect;
2255 const QRect frameRect(QPoint(crect.left(), crect.top()),
2256 QSize(fStrut.left() + fStrut.right() + crect.width(),
2257 fStrut.top() + fStrut.bottom() + crect.height()));
2258 NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1),
2259 frameRect.width(), frameRect.height());
2260 [windowRef setFrame:cocoaFrameRect display:NO];
2261 topExtra->posFromMove = false;
2262 }
2263
2264 if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){
2265 q->setWindowOpacity(topExtra->opacity / 255.0f);
2266 } else if (qt_mac_is_macsheet(q)){
2267 CGFloat alpha = [qt_mac_window_for(q) alphaValue];
2268 if (alpha >= 1.0) {
2269 q->setWindowOpacity(0.95f);
2270 q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
2271 }
2272 } else{
2273 // If the window has been recreated after beeing e.g. a sheet,
2274 // make sure that we don't report a faulty opacity:
2275 q->setWindowOpacity(1.0f);
2276 q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
2277 }
2278
2279 macUpdateHideOnSuspend();
2280 macUpdateOpaqueSizeGrip();
2281 macUpdateIgnoreMouseEvents();
2282 setWindowTitle_helper(extra->topextra->caption);
2283 setWindowIconText_helper(extra->topextra->iconText);
2284 setWindowModified_sys(q->isWindowModified());
2285 updateFrameStrut();
2286 syncCocoaMask();
2287 macUpdateIsOpaque();
2288 qt_mac_update_sizer(q);
2289 applyMaxAndMinSizeOnWindow();
2290}
2291
2292#endif // QT_MAC_USE_COCOA
2293
2294/*
2295 Recreates widget window. Useful if immutable
2296 properties for it has changed.
2297 */
2298void QWidgetPrivate::recreateMacWindow()
2299{
2300 Q_Q(QWidget);
2301 OSViewRef myView = qt_mac_nativeview_for(q);
2302 OSWindowRef oldWindow = qt_mac_window_for(myView);
2303#ifndef QT_MAC_USE_COCOA
2304 HIViewRemoveFromSuperview(myView);
2305 determineWindowClass();
2306 createWindow_sys();
2307 if (QMainWindowLayout *mwl = qobject_cast<QMainWindowLayout *>(q->layout())) {
2308 mwl->updateHIToolBarStatus();
2309 }
2310
2311 if (IsWindowVisible(oldWindow))
2312 show_sys();
2313#else
2314 QMacCocoaAutoReleasePool pool;
2315 [myView removeFromSuperview];
2316 determineWindowClass();
2317 createWindow_sys();
2318 if (NSToolbar *toolbar = [oldWindow toolbar]) {
2319 OSWindowRef newWindow = qt_mac_window_for(myView);
2320 [newWindow setToolbar:toolbar];
2321 [toolbar setVisible:[toolbar isVisible]];
2322 }
2323 if ([oldWindow isVisible]){
2324 if ([oldWindow isSheet])
2325 [NSApp endSheet:oldWindow];
2326 [oldWindow orderOut:oldWindow];
2327 show_sys();
2328 }
2329#endif // QT_MAC_USE_COCOA
2330
2331 // Release the window after creating the new window, because releasing it early
2332 // may cause the app to quit ("close on last window closed attribute")
2333 qt_mac_destructWindow(oldWindow);
2334}
2335
2336void QWidgetPrivate::createWindow_sys()
2337{
2338 Q_Q(QWidget);
2339 Qt::WindowFlags &flags = data.window_flags;
2340 QWidget *parentWidget = q->parentWidget();
2341
2342 QTLWExtra *topExtra = topData();
2343 if (topExtra->embedded)
2344 return; // Simply return because this view "is" the top window.
2345 quint32 wattr = topExtra->wattr;
2346
2347 if(parentWidget && (parentWidget->window()->windowFlags() & Qt::WindowStaysOnTopHint)) // If our parent has Qt::WStyle_StaysOnTop, so must we
2348 flags |= Qt::WindowStaysOnTopHint;
2349
2350 data.fstrut_dirty = true;
2351
2352 OSWindowRef windowRef = qt_mac_create_window(q, topExtra->wclass, wattr, data.crect);
2353 if (windowRef == 0)
2354 qWarning("QWidget: Internal error: %s:%d: If you reach this error please contact Qt Support and include the\n"
2355 " WidgetFlags used in creating the widget.", __FILE__, __LINE__);
2356#ifndef QT_MAC_USE_COCOA
2357 finishCreateWindow_sys_Carbon(windowRef);
2358#else
2359 finishCreateWindow_sys_Cocoa(windowRef);
2360#endif
2361}
2362
2363void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
2364{
2365 Q_Q(QWidget);
2366 OSViewRef destroyid = 0;
2367#ifndef QT_MAC_USE_COCOA
2368 window_event = 0;
2369#endif
2370
2371 Qt::WindowType type = q->windowType();
2372 Qt::WindowFlags flags = data.window_flags;
2373 QWidget *parentWidget = q->parentWidget();
2374
2375 bool topLevel = (flags & Qt::Window);
2376 bool popup = (type == Qt::Popup);
2377 bool dialog = (type == Qt::Dialog
2378 || type == Qt::Sheet
2379 || type == Qt::Drawer
2380 || (flags & Qt::MSWindowsFixedSizeDialogHint));
2381 bool desktop = (type == Qt::Desktop);
2382
2383 // Determine this early for top-levels so, we can use it later.
2384 if (topLevel)
2385 determineWindowClass();
2386
2387 if (desktop) {
2388 QSize desktopSize = qt_mac_desktopSize();
2389 q->setAttribute(Qt::WA_WState_Visible);
2390 data.crect.setRect(0, 0, desktopSize.width(), desktopSize.height());
2391 dialog = popup = false; // force these flags off
2392 } else {
2393 q->setAttribute(Qt::WA_WState_Visible, false);
2394
2395 if (topLevel && (type != Qt::Drawer)) {
2396 if (QDesktopWidget *dsk = QApplication::desktop()) { // calc pos/size from screen
2397 const bool wasResized = q->testAttribute(Qt::WA_Resized);
2398 const bool wasMoved = q->testAttribute(Qt::WA_Moved);
2399 int deskn = dsk->primaryScreen();
2400 if (parentWidget && parentWidget->windowType() != Qt::Desktop)
2401 deskn = dsk->screenNumber(parentWidget);
2402 QRect screenGeo = dsk->screenGeometry(deskn);
2403 if (!wasResized) {
2404#ifndef QT_MAC_USE_COCOA
2405 data.crect.setSize(QSize(screenGeo.width()/2, 4*screenGeo.height()/10));
2406#else
2407 NSRect newRect = [NSWindow frameRectForContentRect:NSMakeRect(0, 0,
2408 screenGeo.width() / 2.,
2409 4 * screenGeo.height() / 10.)
2410 styleMask:topData()->wattr];
2411 data.crect.setSize(QSize(newRect.size.width, newRect.size.height));
2412#endif
2413 // Constrain to minimums and maximums we've set
2414 if (extra->minw > 0)
2415 data.crect.setWidth(qMax(extra->minw, data.crect.width()));
2416 if (extra->minh > 0)
2417 data.crect.setHeight(qMax(extra->minh, data.crect.height()));
2418 if (extra->maxw > 0)
2419 data.crect.setWidth(qMin(extra->maxw, data.crect.width()));
2420 if (extra->maxh > 0)
2421 data.crect.setHeight(qMin(extra->maxh, data.crect.height()));
2422 }
2423 if (!wasMoved && !q->testAttribute(Qt::WA_DontShowOnScreen))
2424 data.crect.moveTopLeft(QPoint(screenGeo.width()/4,
2425 3 * screenGeo.height() / 10));
2426 }
2427 }
2428 }
2429
2430
2431 if(!window) // always initialize
2432 initializeWindow=true;
2433
2434 hd = 0;
2435 if(window) { // override the old window (with a new NSView)
2436 OSViewRef nativeView = OSViewRef(window);
2437 OSViewRef parent = 0;
2438#ifndef QT_MAC_USE_COCOA
2439 CFRetain(nativeView);
2440#else
2441 [nativeView retain];
2442#endif
2443 if (destroyOldWindow)
2444 destroyid = qt_mac_nativeview_for(q);
2445 bool transfer = false;
2446 setWinId((WId)nativeView);
2447#ifndef QT_MAC_USE_COCOA
2448#ifndef HIViewInstallEventHandler
2449 // Macro taken from the CarbonEvents Header on Tiger
2450#define HIViewInstallEventHandler( target, handler, numTypes, list, userData, outHandlerRef ) \
2451 InstallEventHandler( HIObjectGetEventTarget( (HIObjectRef) (target) ), (handler), (numTypes), (list), (userData), (outHandlerRef) )
2452#endif
2453 HIViewInstallEventHandler(nativeView, make_widget_eventUPP(), GetEventTypeCount(widget_events), widget_events, 0, 0);
2454#endif
2455 if(topLevel) {
2456 for(int i = 0; i < 2; ++i) {
2457 if(i == 1) {
2458 if(!initializeWindow)
2459 break;
2460 createWindow_sys();
2461 }
2462 if(OSWindowRef windowref = qt_mac_window_for(nativeView)) {
2463#ifndef QT_MAC_USE_COCOA
2464 CFRetain(windowref);
2465#else
2466 [windowref retain];
2467#endif
2468 if (initializeWindow) {
2469 parent = qt_mac_get_contentview_for(windowref);
2470 } else {
2471#ifndef QT_MAC_USE_COCOA
2472 parent = HIViewGetSuperview(nativeView);
2473#else
2474 parent = [nativeView superview];
2475#endif
2476 }
2477 break;
2478 }
2479 }
2480 if(!parent)
2481 transfer = true;
2482 } else if (parentWidget) {
2483 // I need to be added to my parent, therefore my parent needs an NSView
2484 parentWidget->createWinId();
2485 parent = qt_mac_nativeview_for(parentWidget);
2486 }
2487 if(parent != nativeView && parent) {
2488#ifndef QT_MAC_USE_COCOA
2489 HIViewAddSubview(parent, nativeView);
2490#else
2491 [parent addSubview:nativeView];
2492#endif
2493 }
2494 if(transfer)
2495 transferChildren();
2496 data.fstrut_dirty = true; // we'll re calculate this later
2497 q->setAttribute(Qt::WA_WState_Visible,
2498#ifndef QT_MAC_USE_COCOA
2499 HIViewIsVisible(nativeView)
2500#else
2501 ![nativeView isHidden]
2502#endif
2503 );
2504 if(initializeWindow) {
2505#ifndef QT_MAC_USE_COCOA
2506 HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
2507 HIViewSetFrame(nativeView, &bounds);
2508 q->setAttribute(Qt::WA_WState_Visible, HIViewIsVisible(nativeView));
2509#else
2510 NSRect bounds = NSMakeRect(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
2511 [nativeView setFrame:bounds];
2512 q->setAttribute(Qt::WA_WState_Visible, [nativeView isHidden]);
2513#endif
2514 }
2515#ifndef QT_MAC_USE_COCOA
2516 initWindowPtr();
2517#endif
2518 } else if (desktop) { // desktop widget
2519 if (!qt_root_win)
2520 QWidgetPrivate::qt_create_root_win();
2521 Q_ASSERT(qt_root_win);
2522 WId rootWinID = 0;
2523#ifndef QT_MAC_USE_COCOA
2524 CFRetain(qt_root_win);
2525 if(HIViewRef rootContentView = HIViewGetRoot(qt_root_win)) {
2526 rootWinID = (WId)rootContentView;
2527 CFRetain(rootContentView);
2528 }
2529#else
2530 [qt_root_win retain];
2531 if (OSViewRef rootContentView = [qt_root_win contentView]) {
2532 rootWinID = (WId)rootContentView;
2533 [rootContentView retain];
2534 }
2535#endif
2536 setWinId(rootWinID);
2537 } else if (topLevel) {
2538 determineWindowClass();
2539 if(OSViewRef osview = qt_mac_create_widget(q, this, 0)) {
2540#ifndef QT_MAC_USE_COCOA
2541 HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(),
2542 data.crect.width(), data.crect.height());
2543 HIViewSetFrame(osview, &bounds);
2544#else
2545 NSRect bounds = NSMakeRect(data.crect.x(), flipYCoordinate(data.crect.y()),
2546 data.crect.width(), data.crect.height());
2547 [osview setFrame:bounds];
2548#endif
2549 setWinId((WId)osview);
2550 }
2551 } else {
2552 data.fstrut_dirty = false; // non-toplevel widgets don't have a frame, so no need to update the strut
2553 if(OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
2554#ifndef QT_MAC_USE_COCOA
2555 HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
2556 HIViewSetFrame(osview, &bounds);
2557 setWinId((WId)osview);
2558#else
2559 NSRect bounds = NSMakeRect(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
2560 [osview setFrame:bounds];
2561 setWinId((WId)osview);
2562#endif
2563 if (q->testAttribute(Qt::WA_DropSiteRegistered))
2564 registerDropSite(true);
2565 }
2566 }
2567
2568 updateIsOpaque();
2569 if (q->hasFocus())
2570 setFocus_sys();
2571 if (!topLevel && initializeWindow)
2572 setWSGeometry();
2573 if (destroyid)
2574 qt_mac_destructView(destroyid);
2575 if (q->testAttribute(Qt::WA_AcceptTouchEvents))
2576 registerTouchWindow();
2577}
2578
2579/*!
2580 Returns the QuickDraw handle of the widget. Use of this function is not
2581 portable. This function will return 0 if QuickDraw is not supported, or
2582 if the handle could not be created.
2583
2584 \warning This function is only available on Mac OS X.
2585*/
2586
2587Qt::HANDLE
2588QWidget::macQDHandle() const
2589{
2590#ifndef QT_MAC_USE_COCOA
2591 return d_func()->qd_hd;
2592#else
2593 return 0;
2594#endif
2595}
2596
2597/*!
2598 Returns the CoreGraphics handle of the widget. Use of this function is
2599 not portable. This function will return 0 if no painter context can be
2600 established, or if the handle could not be created.
2601
2602 \warning This function is only available on Mac OS X.
2603*/
2604Qt::HANDLE
2605QWidget::macCGHandle() const
2606{
2607 return handle();
2608}
2609
2610void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
2611{
2612 Q_D(QWidget);
2613 if (!isWindow() && parentWidget())
2614 parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
2615 d->deactivateWidgetCleanup();
2616 qt_mac_event_release(this);
2617 if(testAttribute(Qt::WA_WState_Created)) {
2618 QMacCocoaAutoReleasePool pool;
2619 setAttribute(Qt::WA_WState_Created, false);
2620 QObjectList chldrn = children();
2621 for(int i = 0; i < chldrn.size(); i++) { // destroy all widget children
2622 QObject *obj = chldrn.at(i);
2623 if(obj->isWidgetType())
2624 static_cast<QWidget*>(obj)->destroy(destroySubWindows, destroySubWindows);
2625 }
2626 if(mac_mouse_grabber == this)
2627 releaseMouse();
2628 if(mac_keyboard_grabber == this)
2629 releaseKeyboard();
2630
2631 if(testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal
2632 QApplicationPrivate::leaveModal(this);
2633 else if((windowType() == Qt::Popup))
2634 qApp->d_func()->closePopup(this);
2635 if (destroyWindow) {
2636 if(OSViewRef hiview = qt_mac_nativeview_for(this)) {
2637 OSWindowRef window = 0;
2638 NSDrawer *drawer = nil;
2639#ifdef QT_MAC_USE_COCOA
2640 if (qt_mac_is_macdrawer(this)) {
2641 drawer = qt_mac_drawer_for(this);
2642 } else
2643#endif
2644 if (isWindow())
2645 window = qt_mac_window_for(hiview);
2646
2647 // Because of how "destruct" works, we have to do just a normal release for the root_win.
2648 if (window && window == qt_root_win) {
2649#ifndef QT_MAC_USE_COCOA
2650 CFRelease(hiview);
2651#else
2652 [hiview release];
2653#endif
2654 } else {
2655 qt_mac_destructView(hiview);
2656 }
2657 if (drawer)
2658 qt_mac_destructDrawer(drawer);
2659 if (window)
2660 qt_mac_destructWindow(window);
2661 }
2662 }
2663 QT_TRY {
2664 d->setWinId(0);
2665 } QT_CATCH (const std::bad_alloc &) {
2666 // swallow - destructors must not throw
2667 }
2668 }
2669}
2670
2671void QWidgetPrivate::transferChildren()
2672{
2673 Q_Q(QWidget);
2674 if (!q->testAttribute(Qt::WA_WState_Created))
2675 return; // Can't add any views anyway
2676
2677 QObjectList chlist = q->children();
2678 for (int i = 0; i < chlist.size(); ++i) {
2679 QObject *obj = chlist.at(i);
2680 if (obj->isWidgetType()) {
2681 QWidget *w = (QWidget *)obj;
2682 if (!w->isWindow()) {
2683 // This seems weird, no need to call it in a loop right?
2684 if (!topData()->caption.isEmpty())
2685 setWindowTitle_helper(extra->topextra->caption);
2686 if (w->testAttribute(Qt::WA_WState_Created)) {
2687#ifndef QT_MAC_USE_COCOA
2688 HIViewAddSubview(qt_mac_nativeview_for(q), qt_mac_nativeview_for(w));
2689#else
2690 // New NSWindows get an extra reference when drops are
2691 // registered (at least in 10.5) which means that we may
2692 // access the window later and get a crash (becasue our
2693 // widget is dead). Work around this be having the drop
2694 // site disabled until it is part of the new hierarchy.
2695 bool oldRegistered = w->testAttribute(Qt::WA_DropSiteRegistered);
2696 w->setAttribute(Qt::WA_DropSiteRegistered, false);
2697 [qt_mac_nativeview_for(w) retain];
2698 [qt_mac_nativeview_for(w) removeFromSuperview];
2699 [qt_mac_nativeview_for(q) addSubview:qt_mac_nativeview_for(w)];
2700 [qt_mac_nativeview_for(w) release];
2701 w->setAttribute(Qt::WA_DropSiteRegistered, oldRegistered);
2702#endif
2703 }
2704 }
2705 }
2706 }
2707}
2708
2709void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
2710{
2711 Q_Q(QWidget);
2712 QMacCocoaAutoReleasePool pool;
2713 QTLWExtra *topData = maybeTopData();
2714 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
2715#ifdef QT_MAC_USE_COCOA
2716 bool wasWindow = q->isWindow();
2717#endif
2718 OSViewRef old_id = 0;
2719
2720 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
2721 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
2722
2723 // Maintain the glWidgets list on parent change: remove "our" gl widgets
2724 // from the list on the old parent and grandparents.
2725 if (glWidgets.isEmpty() == false) {
2726 QWidget *current = q->parentWidget();
2727 while (current) {
2728 for (QList<QWidgetPrivate::GlWidgetInfo>::const_iterator it = glWidgets.constBegin();
2729 it != glWidgets.constEnd(); ++it)
2730 current->d_func()->glWidgets.removeAll(*it);
2731
2732 if (current->isWindow())
2733 break;
2734 current = current->parentWidget();
2735 }
2736 }
2737
2738#ifndef QT_MAC_USE_COCOA
2739 EventHandlerRef old_window_event = 0;
2740#else
2741 bool oldToolbarVisible = false;
2742 NSDrawer *oldDrawer = nil;
2743 NSToolbar *oldToolbar = 0;
2744#endif
2745 if (wasCreated && !(q->windowType() == Qt::Desktop)) {
2746 old_id = qt_mac_nativeview_for(q);
2747#ifndef QT_MAC_USE_COCOA
2748 old_window_event = window_event;
2749#else
2750 OSWindowRef oldWindow = qt_mac_window_for(old_id);
2751 if (qt_mac_is_macdrawer(q)) {
2752 oldDrawer = qt_mac_drawer_for(q);
2753 }
2754 if (wasWindow) {
2755 oldToolbar = [oldWindow toolbar];
2756 [oldToolbar retain];
2757 oldToolbarVisible = [oldToolbar isVisible];
2758 [oldWindow setToolbar:nil];
2759 }
2760#endif
2761 }
2762 QWidget* oldtlw = q->window();
2763
2764 if (q->testAttribute(Qt::WA_DropSiteRegistered))
2765 q->setAttribute(Qt::WA_DropSiteRegistered, false);
2766
2767 //recreate and setup flags
2768 QObjectPrivate::setParent_helper(parent);
2769 QPoint pt = q->pos();
2770 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
2771 if (wasCreated && !qt_isGenuineQWidget(q))
2772 return;
2773
2774 if ((data.window_flags & Qt::Sheet) && topData && topData->opacity == 242)
2775 q->setWindowOpacity(1.0f);
2776
2777 setWinId(0); //do after the above because they may want the id
2778
2779 data.window_flags = f;
2780 q->setAttribute(Qt::WA_WState_Created, false);
2781 q->setAttribute(Qt::WA_WState_Visible, false);
2782 q->setAttribute(Qt::WA_WState_Hidden, false);
2783 adjustFlags(data.window_flags, q);
2784 // keep compatibility with previous versions, we need to preserve the created state
2785 // (but we recreate the winId for the widget being reparented, again for compatibility)
2786 if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) {
2787 createWinId();
2788 if (q->isWindow()) {
2789#ifndef QT_MAC_USE_COCOA
2790 // We do this down below for wasCreated, so avoid doing this twice
2791 // (only for performance, it gets called a lot anyway).
2792 if (!wasCreated) {
2793 if (QMainWindowLayout *mwl = qobject_cast<QMainWindowLayout *>(q->layout())) {
2794 mwl->updateHIToolBarStatus();
2795 }
2796 }
2797#else
2798 // Simply transfer our toolbar over. Everything should stay put, unlike in Carbon.
2799 if (oldToolbar && !(f & Qt::FramelessWindowHint)) {
2800 OSWindowRef newWindow = qt_mac_window_for(q);
2801 [newWindow setToolbar:oldToolbar];
2802 [oldToolbar release];
2803 [oldToolbar setVisible:oldToolbarVisible];
2804 }
2805#endif
2806 }
2807 }
2808 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
2809 q->setAttribute(Qt::WA_WState_Hidden);
2810 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
2811
2812 if (wasCreated) {
2813 transferChildren();
2814#ifndef QT_MAC_USE_COCOA
2815 // If we were a unified window, We just transfered our toolbars out of the unified toolbar.
2816 // So redo the status one more time. It apparently is not an issue with Cocoa.
2817 if (q->isWindow()) {
2818 if (QMainWindowLayout *mwl = qobject_cast<QMainWindowLayout *>(q->layout())) {
2819 mwl->updateHIToolBarStatus();
2820 }
2821 }
2822#endif
2823
2824 if (topData &&
2825 (!topData->caption.isEmpty() || !topData->filePath.isEmpty()))
2826 setWindowTitle_helper(q->windowTitle());
2827 }
2828
2829 if (q->testAttribute(Qt::WA_AcceptDrops)
2830 || (!q->isWindow() && q->parentWidget()
2831 && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
2832 q->setAttribute(Qt::WA_DropSiteRegistered, true);
2833
2834 //cleanup
2835#ifndef QT_MAC_USE_COCOA
2836 if (old_window_event)
2837 RemoveEventHandler(old_window_event);
2838#endif
2839 if (old_id) { //don't need old window anymore
2840 OSWindowRef window = (oldtlw == q) ? qt_mac_window_for(old_id) : 0;
2841 qt_mac_destructView(old_id);
2842
2843#ifdef QT_MAC_USE_COCOA
2844 if (oldDrawer) {
2845 qt_mac_destructDrawer(oldDrawer);
2846 } else
2847#endif
2848 if (window)
2849 qt_mac_destructWindow(window);
2850 }
2851
2852 // Maintain the glWidgets list on parent change: add "our" gl widgets
2853 // to the list on the new parent and grandparents.
2854 if (glWidgets.isEmpty() == false) {
2855 QWidget *current = q->parentWidget();
2856 while (current) {
2857 current->d_func()->glWidgets += glWidgets;
2858 if (current->isWindow())
2859 break;
2860 current = current->parentWidget();
2861 }
2862 }
2863
2864 invalidateBuffer(q->rect());
2865 qt_event_request_window_change(q);
2866}
2867
2868QPoint QWidget::mapToGlobal(const QPoint &pos) const
2869{
2870 Q_D(const QWidget);
2871 if (!testAttribute(Qt::WA_WState_Created)) {
2872 QPoint p = pos + data->crect.topLeft();
2873 return isWindow() ? p : parentWidget()->mapToGlobal(p);
2874 }
2875#ifndef QT_MAC_USE_COCOA
2876 QPoint tmp = d->mapToWS(pos);
2877 HIPoint hi_pos = CGPointMake(tmp.x(), tmp.y());
2878 HIViewConvertPoint(&hi_pos, qt_mac_nativeview_for(this), 0);
2879 Rect win_rect;
2880 GetWindowBounds(qt_mac_window_for(this), kWindowStructureRgn, &win_rect);
2881 return QPoint((int)hi_pos.x+win_rect.left, (int)hi_pos.y+win_rect.top);
2882#else
2883 QPoint tmp = d->mapToWS(pos);
2884 NSPoint hi_pos = NSMakePoint(tmp.x(), tmp.y());
2885 hi_pos = [qt_mac_nativeview_for(this) convertPoint:hi_pos toView:nil];
2886 NSRect win_rect = [qt_mac_window_for(this) frame];
2887 hi_pos.x += win_rect.origin.x;
2888 hi_pos.y += win_rect.origin.y;
2889 // If we aren't the desktop we need to flip, if you flip the desktop on itself, you get the other problem.
2890 return ((window()->windowFlags() & Qt::Desktop) == Qt::Desktop) ? QPointF(hi_pos.x, hi_pos.y).toPoint()
2891 : flipPoint(hi_pos).toPoint();
2892#endif
2893}
2894
2895QPoint QWidget::mapFromGlobal(const QPoint &pos) const
2896{
2897 Q_D(const QWidget);
2898 if (!testAttribute(Qt::WA_WState_Created)) {
2899 QPoint p = isWindow() ? pos : parentWidget()->mapFromGlobal(pos);
2900 return p - data->crect.topLeft();
2901 }
2902#ifndef QT_MAC_USE_COCOA
2903 Rect win_rect;
2904 GetWindowBounds(qt_mac_window_for(this), kWindowStructureRgn, &win_rect);
2905 HIPoint hi_pos = CGPointMake(pos.x()-win_rect.left, pos.y()-win_rect.top);
2906 HIViewConvertPoint(&hi_pos, 0, qt_mac_nativeview_for(this));
2907 return d->mapFromWS(QPoint((int)hi_pos.x, (int)hi_pos.y));
2908#else
2909 NSRect win_rect = [qt_mac_window_for(this) frame];
2910 // The Window point is in "Cocoa coordinates," but the view is in "Qt coordinates"
2911 // so make sure to keep them in sync.
2912 NSPoint hi_pos = NSMakePoint(pos.x()-win_rect.origin.x,
2913 flipYCoordinate(pos.y())-win_rect.origin.y);
2914 hi_pos = [qt_mac_nativeview_for(this) convertPoint:hi_pos fromView:0];
2915 return d->mapFromWS(QPoint(qRound(hi_pos.x), qRound(hi_pos.y)));
2916#endif
2917}
2918
2919void QWidgetPrivate::updateSystemBackground()
2920{
2921}
2922
2923void QWidgetPrivate::setCursor_sys(const QCursor &)
2924{
2925#ifndef QT_MAC_USE_COCOA
2926 qt_mac_update_cursor();
2927#else
2928 Q_Q(QWidget);
2929 if (q->testAttribute(Qt::WA_WState_Created)) {
2930 QMacCocoaAutoReleasePool pool;
2931 [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)];
2932 }
2933#endif
2934}
2935
2936void QWidgetPrivate::unsetCursor_sys()
2937{
2938#ifndef QT_MAC_USE_COCOA
2939 qt_mac_update_cursor();
2940#else
2941 Q_Q(QWidget);
2942 if (q->testAttribute(Qt::WA_WState_Created)) {
2943 QMacCocoaAutoReleasePool pool;
2944 [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)];
2945 }
2946#endif
2947}
2948
2949void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
2950{
2951 Q_Q(QWidget);
2952 if (q->isWindow()) {
2953#ifndef QT_MAC_USE_COCOA
2954 SetWindowTitleWithCFString(qt_mac_window_for(q), QCFString(caption));
2955#else
2956 QMacCocoaAutoReleasePool pool;
2957 [qt_mac_window_for(q) setTitle:qt_mac_QStringToNSString(caption)];
2958#endif
2959 }
2960}
2961
2962void QWidgetPrivate::setWindowModified_sys(bool mod)
2963{
2964 Q_Q(QWidget);
2965 if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) {
2966#ifndef QT_MAC_USE_COCOA
2967 SetWindowModified(qt_mac_window_for(q), mod);
2968#else
2969 [qt_mac_window_for(q) setDocumentEdited:mod];
2970#endif
2971 }
2972}
2973
2974void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
2975{
2976 Q_Q(QWidget);
2977#ifdef QT_MAC_USE_COCOA
2978 QMacCocoaAutoReleasePool pool;
2979 QFileInfo fi(filePath);
2980 [qt_mac_window_for(q) setRepresentedFilename:fi.exists() ? qt_mac_QStringToNSString(filePath) : @""];
2981#else
2982 bool validRef = false;
2983 FSRef ref;
2984 bzero(&ref, sizeof(ref));
2985 OSStatus status;
2986
2987 if (!filePath.isEmpty()) {
2988 status = FSPathMakeRef(reinterpret_cast<const UInt8 *>(filePath.toUtf8().constData()), &ref, 0);
2989 validRef = (status == noErr);
2990 }
2991 // Set the proxy regardless, since this is our way of clearing it as well, but ignore the
2992 // return value as well.
2993 if (validRef) {
2994 status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref);
2995 } else {
2996 status = RemoveWindowProxy(qt_mac_window_for(q));
2997 }
2998 if (status != noErr)
2999 qWarning("QWidget::setWindowFilePath: Error setting proxyicon for path (%s):%ld",
3000 qPrintable(filePath), status);
3001#endif
3002}
3003
3004void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
3005{
3006 Q_Q(QWidget);
3007
3008 if (!q->testAttribute(Qt::WA_WState_Created))
3009 return;
3010
3011 QTLWExtra *topData = this->topData();
3012 if (topData->iconPixmap && !forceReset) // already set
3013 return;
3014
3015 QIcon icon = q->windowIcon();
3016 QPixmap *pm = 0;
3017 if (!icon.isNull()) {
3018 // now create the extra
3019 if (!topData->iconPixmap) {
3020 pm = new QPixmap(icon.pixmap(QSize(22, 22)));
3021 topData->iconPixmap = pm;
3022 } else {
3023 pm = topData->iconPixmap;
3024 }
3025 }
3026 if (q->isWindow()) {
3027#ifndef QT_MAC_USE_COCOA
3028 IconRef previousIcon = 0;
3029 if (icon.isNull()) {
3030 RemoveWindowProxy(qt_mac_window_for(q));
3031 previousIcon = topData->windowIcon;
3032 topData->windowIcon = 0;
3033 } else {
3034 WindowClass wclass;
3035 GetWindowClass(qt_mac_window_for(q), &wclass);
3036
3037 if (wclass == kDocumentWindowClass) {
3038 IconRef newIcon = qt_mac_create_iconref(*pm);
3039 previousIcon = topData->windowIcon;
3040 topData->windowIcon = newIcon;
3041 SetWindowProxyIcon(qt_mac_window_for(q), newIcon);
3042 }
3043 }
3044
3045 // Release the previous icon if it was set by this function.
3046 if (previousIcon != 0)
3047 ReleaseIconRef(previousIcon);
3048#else
3049 QMacCocoaAutoReleasePool pool;
3050 NSButton *iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton];
3051 if (iconButton == nil) {
3052 QCFString string(q->windowTitle());
3053 const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
3054 [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:tmpString]];
3055 iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton];
3056 }
3057 if (icon.isNull()) {
3058 [iconButton setImage:nil];
3059 } else {
3060 QPixmap scaled = pm->scaled(QSize(16,16), Qt::KeepAspectRatio, Qt::SmoothTransformation);
3061 NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(scaled));
3062 [iconButton setImage:image];
3063 [image release];
3064 }
3065#endif
3066 }
3067}
3068
3069void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
3070{
3071 Q_Q(QWidget);
3072 if(q->isWindow() && !iconText.isEmpty()) {
3073#ifndef QT_MAC_USE_COCOA
3074 SetWindowAlternateTitle(qt_mac_window_for(q), QCFString(iconText));
3075#else
3076 QMacCocoaAutoReleasePool pool;
3077 [qt_mac_window_for(q) setMiniwindowTitle:qt_mac_QStringToNSString(iconText)];
3078#endif
3079 }
3080}
3081
3082void QWidget::grabMouse()
3083{
3084 if(isVisible() && !qt_nograb()) {
3085 if(mac_mouse_grabber)
3086 mac_mouse_grabber->releaseMouse();
3087 mac_mouse_grabber=this;
3088 }
3089}
3090
3091#ifndef QT_NO_CURSOR
3092void QWidget::grabMouse(const QCursor &)
3093{
3094 if(isVisible() && !qt_nograb()) {
3095 if(mac_mouse_grabber)
3096 mac_mouse_grabber->releaseMouse();
3097 mac_mouse_grabber=this;
3098 }
3099}
3100#endif
3101
3102void QWidget::releaseMouse()
3103{
3104 if(!qt_nograb() && mac_mouse_grabber == this)
3105 mac_mouse_grabber = 0;
3106}
3107
3108void QWidget::grabKeyboard()
3109{
3110 if(!qt_nograb()) {
3111 if(mac_keyboard_grabber)
3112 mac_keyboard_grabber->releaseKeyboard();
3113 mac_keyboard_grabber = this;
3114 }
3115}
3116
3117void QWidget::releaseKeyboard()
3118{
3119 if(!qt_nograb() && mac_keyboard_grabber == this)
3120 mac_keyboard_grabber = 0;
3121}
3122
3123QWidget *QWidget::mouseGrabber()
3124{
3125 return mac_mouse_grabber;
3126}
3127
3128QWidget *QWidget::keyboardGrabber()
3129{
3130 return mac_keyboard_grabber;
3131}
3132
3133void QWidget::activateWindow()
3134{
3135 QWidget *tlw = window();
3136 if(!tlw->isVisible() || !tlw->isWindow() || (tlw->windowType() == Qt::Desktop))
3137 return;
3138 qt_event_remove_activate();
3139
3140 QWidget *fullScreenWidget = tlw;
3141 QWidget *parentW = tlw;
3142 // Find the oldest parent or the parent with fullscreen, whichever comes first.
3143 while (parentW) {
3144 fullScreenWidget = parentW->window();
3145 if (fullScreenWidget->windowState() & Qt::WindowFullScreen)
3146 break;
3147 parentW = fullScreenWidget->parentWidget();
3148 }
3149
3150 if (fullScreenWidget->windowType() != Qt::ToolTip) {
3151 qt_mac_set_fullscreen_mode((fullScreenWidget->windowState() & Qt::WindowFullScreen) &&
3152 qApp->desktop()->screenNumber(this) == 0);
3153 }
3154
3155 bool windowActive;
3156 OSWindowRef win = qt_mac_window_for(tlw);
3157#ifndef QT_MAC_USE_COCOA
3158 windowActive = IsWindowActive(win);
3159#else
3160 QMacCocoaAutoReleasePool pool;
3161 windowActive = [win isKeyWindow];
3162#endif
3163 if ((tlw->windowType() == Qt::Popup)
3164 || (tlw->windowType() == Qt::Tool)
3165 || qt_mac_is_macdrawer(tlw)
3166 || windowActive) {
3167#ifndef QT_MAC_USE_COCOA
3168 ActivateWindow(win, true);
3169#else
3170 [win makeKeyWindow];
3171#endif
3172 qApp->setActiveWindow(tlw);
3173 } else if(!isMinimized()) {
3174#ifndef QT_MAC_USE_COCOA
3175 SelectWindow(win);
3176#else
3177 [win makeKeyAndOrderFront:win];
3178#endif
3179 }
3180}
3181
3182QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
3183{
3184 return new QMacWindowSurface(q_func());
3185}
3186
3187void QWidgetPrivate::update_sys(const QRect &r)
3188{
3189 Q_Q(QWidget);
3190 if (r == q->rect()) {
3191 if (updateRedirectedToGraphicsProxyWidget(q, r))
3192 return;
3193 dirtyOnWidget += r;
3194#ifndef QT_MAC_USE_COCOA
3195 HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true);
3196#else
3197 [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
3198#endif
3199 return;
3200 }
3201
3202 int x = r.x(), y = r.y(), w = r.width(), h = r.height();
3203 if (w < 0)
3204 w = q->data->crect.width() - x;
3205 if (h < 0)
3206 h = q->data->crect.height() - y;
3207 if (w && h) {
3208 const QRect updateRect = QRect(x, y, w, h);
3209 if (updateRedirectedToGraphicsProxyWidget(q, updateRect))
3210 return;
3211#ifndef QT_MAC_USE_COCOA
3212 dirtyOnWidget += updateRect;
3213 HIRect r = CGRectMake(x, y, w, h);
3214 HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true);
3215#else
3216 [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(x, y, w, h)];
3217#endif
3218 }
3219}
3220
3221void QWidgetPrivate::update_sys(const QRegion &rgn)
3222{
3223 Q_Q(QWidget);
3224 if (updateRedirectedToGraphicsProxyWidget(q, rgn))
3225 return;
3226 dirtyOnWidget += rgn;
3227#ifndef QT_MAC_USE_COCOA
3228 RgnHandle rgnHandle = rgn.toQDRgnForUpdate_sys();
3229 if (rgnHandle)
3230 HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true);
3231 else {
3232 HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow.
3233 }
3234#else
3235 // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect.
3236 const QRect &boundingRect = rgn.boundingRect();
3237 [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(boundingRect.x(),
3238 boundingRect.y(), boundingRect.width(),
3239 boundingRect.height())];
3240#endif
3241}
3242
3243bool QWidgetPrivate::isRealWindow() const
3244{
3245 return q_func()->isWindow() && !topData()->embedded;
3246}
3247
3248void QWidgetPrivate::show_sys()
3249{
3250 Q_Q(QWidget);
3251 if ((q->windowType() == Qt::Desktop)) //desktop is always visible
3252 return;
3253
3254 invalidateBuffer(q->rect());
3255 if (q->testAttribute(Qt::WA_OutsideWSRange))
3256 return;
3257 QMacCocoaAutoReleasePool pool;
3258 q->setAttribute(Qt::WA_Mapped);
3259 if (q->testAttribute(Qt::WA_DontShowOnScreen))
3260 return;
3261
3262 bool realWindow = isRealWindow();
3263 if (realWindow && !q->testAttribute(Qt::WA_Moved)) {
3264 q->createWinId();
3265 if (QWidget *p = q->parentWidget()) {
3266 p->createWinId();
3267#ifndef QT_MAC_USE_COCOA
3268 RepositionWindow(qt_mac_window_for(q), qt_mac_window_for(p), kWindowCenterOnParentWindow);
3269#else
3270 CGRect parentFrame = NSRectToCGRect([qt_mac_window_for(p) frame]);
3271 OSWindowRef windowRef = qt_mac_window_for(q);
3272 NSRect windowFrame = [windowRef frame];
3273 NSPoint parentCenter = NSMakePoint(CGRectGetMidX(parentFrame), CGRectGetMidY(parentFrame));
3274 [windowRef setFrameTopLeftPoint:NSMakePoint(parentCenter.x - (windowFrame.size.width / 2),
3275 (parentCenter.y + (windowFrame.size.height / 2)))];
3276#endif
3277 } else {
3278#ifndef QT_MAC_USE_COCOA
3279 RepositionWindow(qt_mac_window_for(q), 0, kWindowCenterOnMainScreen);
3280#else
3281 // Ideally we would do a "center" here, but NSWindow's center is more equivalent to
3282 // kWindowAlertPositionOnMainScreen instead of kWindowCenterOnMainScreen.
3283 QRect availGeo = QApplication::desktop()->availableGeometry(q);
3284 // Center the content only.
3285 data.crect.moveCenter(availGeo.center());
3286 QRect fStrut = frameStrut();
3287 QRect frameRect(data.crect.x() - fStrut.left(), data.crect.y() - fStrut.top(),
3288 fStrut.left() + fStrut.right() + data.crect.width(),
3289 fStrut.top() + fStrut.bottom() + data.crect.height());
3290 NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), frameRect.width(), frameRect.height());
3291 [qt_mac_window_for(q) setFrame:cocoaFrameRect display:NO];
3292#endif
3293 }
3294 }
3295 data.fstrut_dirty = true;
3296 if (realWindow) {
3297 // Delegates can change window state, so record some things earlier.
3298 bool isCurrentlyMinimized = (q->windowState() & Qt::WindowMinimized);
3299 setModal_sys();
3300 OSWindowRef window = qt_mac_window_for(q);
3301#ifndef QT_MAC_USE_COCOA
3302 SizeWindow(window, q->width(), q->height(), true);
3303#endif
3304
3305#ifdef QT_MAC_USE_COCOA
3306 // Make sure that we end up sending a repaint event to
3307 // the widget if the window has been visible one before:
3308 [qt_mac_get_contentview_for(window) setNeedsDisplay:YES];
3309#endif
3310 if(qt_mac_is_macsheet(q)) {
3311 qt_event_request_showsheet(q);
3312 } else if(qt_mac_is_macdrawer(q)) {
3313#ifndef QT_MAC_USE_COCOA
3314 OpenDrawer(window, kWindowEdgeDefault, false);
3315#else
3316 NSDrawer *drawer = qt_mac_drawer_for(q);
3317 [drawer openOnEdge:[drawer preferredEdge]];
3318#endif
3319 } else {
3320#ifndef QT_MAC_USE_COCOA
3321 ShowHide(window, true);
3322#else
3323 // sync the opacity value back (in case of a fade).
3324 [window setAlphaValue:q->windowOpacity()];
3325 [window makeKeyAndOrderFront:window];
3326
3327 // If this window is app modal, we need to start spinning
3328 // a modal session for it. Interrupting
3329 // the event dispatcher will make this happend:
3330 if (data.window_modality == Qt::ApplicationModal)
3331 QEventDispatcherMac::instance()->interrupt();
3332#endif
3333 if (q->windowType() == Qt::Popup) {
3334 if (q->focusWidget())
3335 q->focusWidget()->d_func()->setFocus_sys();
3336 else
3337 setFocus_sys();
3338 }
3339 toggleDrawers(true);
3340 }
3341 if (isCurrentlyMinimized) { //show in collapsed state
3342#ifndef QT_MAC_USE_COCOA
3343 CollapseWindow(window, true);
3344#else
3345 [window miniaturize:window];
3346#endif
3347 } else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) {
3348#ifndef QT_MAC_USE_COCOA
3349 qt_event_request_activate(q);
3350#else
3351 [qt_mac_window_for(q) makeKeyWindow];
3352#endif
3353 }
3354 } else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) {
3355#ifndef QT_MAC_USE_COCOA
3356 HIViewSetVisible(qt_mac_nativeview_for(q), true);
3357#else
3358 [qt_mac_nativeview_for(q) setHidden:NO];
3359
3360#endif
3361 }
3362
3363 if (!QWidget::mouseGrabber()){
3364 QWidget *enterWidget = QApplication::widgetAt(QCursor::pos());
3365 QApplicationPrivate::dispatchEnterLeave(enterWidget, qt_mouseover);
3366 qt_mouseover = enterWidget;
3367 }
3368
3369 qt_event_request_window_change(q);
3370}
3371
3372
3373QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt)
3374{
3375#ifndef QT_MAC_USE_COCOA
3376 CGPoint nativePoint = CGPointMake(pt.x(), pt.y());
3377 HIViewConvertPoint(&nativePoint, qt_mac_nativeview_for(child->parentWidget()),
3378 qt_mac_nativeview_for(child));
3379#else
3380 NSPoint nativePoint = [qt_mac_nativeview_for(child) convertPoint:NSMakePoint(pt.x(), pt.y()) fromView:qt_mac_nativeview_for(child->parentWidget())];
3381#endif
3382 return QPoint(nativePoint.x, nativePoint.y);
3383}
3384
3385
3386void QWidgetPrivate::hide_sys()
3387{
3388 Q_Q(QWidget);
3389 if((q->windowType() == Qt::Desktop)) //you can't hide the desktop!
3390 return;
3391
3392 QMacCocoaAutoReleasePool pool;
3393 if(q->isWindow()) {
3394 OSWindowRef window = qt_mac_window_for(q);
3395 if(qt_mac_is_macsheet(q)) {
3396#ifndef QT_MAC_USE_COCOA
3397 WindowRef parent = 0;
3398 if(GetSheetWindowParent(window, &parent) != noErr || !parent)
3399 ShowHide(window, false);
3400 else
3401 HideSheetWindow(window);
3402#else
3403 [NSApp endSheet:window];
3404 [window orderOut:window];
3405#endif
3406 } else if(qt_mac_is_macdrawer(q)) {
3407#ifndef QT_MAC_USE_COCOA
3408 CloseDrawer(window, false);
3409#else
3410 [qt_mac_drawer_for(q) close];
3411#endif
3412 } else {
3413#ifndef QT_MAC_USE_COCOA
3414 ShowHide(window, false);
3415#else
3416 [window orderOut:window];
3417 // Unfortunately it is not as easy as just hiding the window, we need
3418 // to find out if we were in full screen mode. If we were and this is
3419 // the last window in full screen mode then we need to unset the full screen
3420 // mode. If this is not the last visible window in full screen mode then we
3421 // don't change the full screen mode.
3422 if(q->isFullScreen())
3423 {
3424 bool keepFullScreen = false;
3425 QWidgetList windowList = qApp->topLevelWidgets();
3426 int windowCount = windowList.count();
3427 for(int i = 0; i < windowCount; i++)
3428 {
3429 QWidget *w = windowList[i];
3430 // If it is the same window, we don't need to check :-)
3431 if(q == w)
3432 continue;
3433 // If they are not visible or if they are minimized then
3434 // we just ignore them.
3435 if(!w->isVisible() || w->isMinimized())
3436 continue;
3437 // Is it full screen?
3438 // Notice that if there is one window in full screen mode then we
3439 // cannot switch the full screen mode off, therefore we just abort.
3440 if(w->isFullScreen()) {
3441 keepFullScreen = true;
3442 break;
3443 }
3444 }
3445 // No windows in full screen mode, so let just unset that flag.
3446 if(!keepFullScreen)
3447 qt_mac_set_fullscreen_mode(false);
3448 }
3449#endif
3450 toggleDrawers(false);
3451#ifndef QT_MAC_USE_COCOA
3452 // Clear modality (because it seems something that we've always done).
3453 if (data.window_modality != Qt::NonModal) {
3454 SetWindowModality(window, kWindowModalityNone,
3455 q->parentWidget() ? qt_mac_window_for(q->parentWidget()->window()) : 0);
3456 }
3457#endif
3458 }
3459 if(q->isActiveWindow() && !(q->windowType() == Qt::Popup)) {
3460 QWidget *w = 0;
3461 if(q->parentWidget())
3462 w = q->parentWidget()->window();
3463 if(!w || (!w->isVisible() && !w->isMinimized())) {
3464#ifndef QT_MAC_USE_COCOA
3465 for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true);
3466 wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) {
3467 if((w = qt_mac_find_window(wp)))
3468 break;
3469 }
3470 if (!w){
3471 for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true);
3472 wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) {
3473 if((w = qt_mac_find_window(wp)))
3474 break;
3475 }
3476 }
3477 if (!w){
3478 for(WindowPtr wp = GetFrontWindowOfClass(kSimpleWindowClass, true);
3479 wp; wp = GetNextWindowOfClass(wp, kSimpleWindowClass, true)) {
3480 if((w = qt_mac_find_window(wp)))
3481 break;
3482 }
3483 }
3484#else
3485 NSArray *windows = [NSApp windows];
3486 NSUInteger totalWindows = [windows count];
3487 for (NSUInteger i = 0; i < totalWindows; ++i) {
3488 OSWindowRef wp = [windows objectAtIndex:i];
3489 if ((w = qt_mac_find_window(wp)))
3490 break;
3491 }
3492#endif
3493 }
3494 if(w && w->isVisible() && !w->isMinimized()) {
3495#ifndef QT_MAC_USE_COCOA
3496 qt_event_request_activate(w);
3497#else
3498 [qt_mac_window_for(w) makeKeyWindow];
3499#endif
3500 }
3501 }
3502 } else {
3503 invalidateBuffer(q->rect());
3504#ifndef QT_MAC_USE_COCOA
3505 HIViewSetVisible(qt_mac_nativeview_for(q), false);
3506#else
3507 [qt_mac_nativeview_for(q) setHidden:YES];
3508#endif
3509 }
3510
3511 if (!QWidget::mouseGrabber()){
3512 QWidget *enterWidget = QApplication::widgetAt(QCursor::pos());
3513 QApplicationPrivate::dispatchEnterLeave(enterWidget, qt_mouseover);
3514 qt_mouseover = enterWidget;
3515 }
3516
3517 qt_event_request_window_change(q);
3518 deactivateWidgetCleanup();
3519 qt_mac_event_release(q);
3520}
3521
3522void QWidget::setWindowState(Qt::WindowStates newstate)
3523{
3524 Q_D(QWidget);
3525 bool needShow = false;
3526 Qt::WindowStates oldstate = windowState();
3527 if (oldstate == newstate)
3528 return;
3529
3530#ifdef QT_MAC_USE_COCOA
3531 QMacCocoaAutoReleasePool pool;
3532#endif
3533 bool needSendStateChange = true;
3534 if(isWindow()) {
3535 if((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
3536 if(newstate & Qt::WindowFullScreen) {
3537 if(QTLWExtra *tlextra = d->topData()) {
3538 if(tlextra->normalGeometry.width() < 0) {
3539 if(!testAttribute(Qt::WA_Resized))
3540 adjustSize();
3541 tlextra->normalGeometry = geometry();
3542 }
3543 tlextra->savedFlags = windowFlags();
3544 }
3545 needShow = isVisible();
3546 const QRect fullscreen(qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(this)));
3547 setParent(parentWidget(), Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); //save
3548 setGeometry(fullscreen);
3549 if(!qApp->desktop()->screenNumber(this))
3550 qt_mac_set_fullscreen_mode(true);
3551 } else {
3552 needShow = isVisible();
3553 if(!qApp->desktop()->screenNumber(this))
3554 qt_mac_set_fullscreen_mode(false);
3555 setParent(parentWidget(), d->topData()->savedFlags);
3556 setGeometry(d->topData()->normalGeometry);
3557 d->topData()->normalGeometry.setRect(0, 0, -1, -1);
3558 }
3559 }
3560
3561 d->createWinId();
3562
3563 OSWindowRef window = qt_mac_window_for(this);
3564 if((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
3565 if (newstate & Qt::WindowMinimized) {
3566#ifndef QT_MAC_USE_COCOA
3567 CollapseWindow(window, true);
3568#else
3569 [window miniaturize:window];
3570#endif
3571 } else {
3572#ifndef QT_MAC_USE_COCOA
3573 CollapseWindow(window, false);
3574#else
3575 [window deminiaturize:window];
3576#endif
3577 }
3578 needSendStateChange = oldstate == windowState(); // Collapse didn't change our flags.
3579 }
3580
3581 if((newstate & Qt::WindowMaximized) && !((newstate & Qt::WindowFullScreen))) {
3582 if(QTLWExtra *tlextra = d->topData()) {
3583 if(tlextra->normalGeometry.width() < 0) {
3584 if(!testAttribute(Qt::WA_Resized))
3585 adjustSize();
3586 tlextra->normalGeometry = geometry();
3587 }
3588 }
3589 } else if(!(newstate & Qt::WindowFullScreen)) {
3590// d->topData()->normalGeometry = QRect(0, 0, -1, -1);
3591 }
3592
3593#ifdef DEBUG_WINDOW_STATE
3594#define WSTATE(x) qDebug("%s -- %s --> %s", #x, (oldstate & x) ? "true" : "false", (newstate & x) ? "true" : "false")
3595 WSTATE(Qt::WindowMinimized);
3596 WSTATE(Qt::WindowMaximized);
3597 WSTATE(Qt::WindowFullScreen);
3598#undef WSTATE
3599#endif
3600 if(!(newstate & (Qt::WindowMinimized|Qt::WindowFullScreen)) &&
3601 ((oldstate & Qt::WindowFullScreen) || (oldstate & Qt::WindowMinimized) ||
3602 (oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized))) {
3603 if(newstate & Qt::WindowMaximized) {
3604 data->fstrut_dirty = true;
3605#ifndef QT_MAC_USE_COCOA
3606 HIToolbarRef toolbarRef;
3607 if (GetWindowToolbar(window, &toolbarRef) == noErr && toolbarRef
3608 && !isVisible() && !IsWindowToolbarVisible(window)) {
3609 // HIToolbar, needs to be shown so that it's in the structure window
3610 // Typically this is part of a main window and will get shown
3611 // during the show, but it's will make the maximize all wrong.
3612 ShowHideWindowToolbar(window, true, false);
3613 d->updateFrameStrut(); // In theory the dirty would work, but it's optimized out if the window is not visible :(
3614 }
3615 Rect bounds;
3616 QDesktopWidget *dsk = QApplication::desktop();
3617 QRect avail = dsk->availableGeometry(dsk->screenNumber(this));
3618 SetRect(&bounds, avail.x(), avail.y(), avail.x() + avail.width(), avail.y() + avail.height());
3619 if(QWExtra *extra = d->extraData()) {
3620 if(bounds.right - bounds.left > extra->maxw)
3621 bounds.right = bounds.left + extra->maxw;
3622 if(bounds.bottom - bounds.top > extra->maxh)
3623 bounds.bottom = bounds.top + extra->maxh;
3624 }
3625 if(d->topData()) {
3626 QRect fs = d->frameStrut();
3627 bounds.left += fs.left();
3628 if(bounds.right < avail.x()+avail.width())
3629 bounds.right = qMin<short>((uint)avail.x()+avail.width(), bounds.right+fs.left());
3630 if(bounds.bottom < avail.y()+avail.height())
3631 bounds.bottom = qMin<short>((uint)avail.y()+avail.height(), bounds.bottom+fs.top());
3632 bounds.top += fs.top();
3633 bounds.right -= fs.right();
3634 bounds.bottom -= fs.bottom();
3635 }
3636 QRect orect(geometry().x(), geometry().y(), width(), height()),
3637 nrect(bounds.left, bounds.top, bounds.right - bounds.left,
3638 bounds.bottom - bounds.top);
3639 if(orect != nrect) { // the new rect differ from the old
3640 Point idealSize = { nrect.height(), nrect.width() };
3641 ZoomWindowIdeal(window, inZoomOut, &idealSize);
3642 }
3643#else
3644 NSToolbar *toolbarRef = [window toolbar];
3645 if (toolbarRef && !isVisible() && ![toolbarRef isVisible]) {
3646 // HIToolbar, needs to be shown so that it's in the structure window
3647 // Typically this is part of a main window and will get shown
3648 // during the show, but it's will make the maximize all wrong.
3649 // ### Not sure this is right for NSToolbar...
3650 [toolbarRef setVisible:true];
3651// ShowHideWindowToolbar(window, true, false);
3652 d->updateFrameStrut(); // In theory the dirty would work, but it's optimized out if the window is not visible :(
3653 }
3654 // Everything should be handled by Cocoa.
3655 [window zoom:window];
3656#endif
3657 needSendStateChange = oldstate == windowState(); // Zoom didn't change flags.
3658 } else if(oldstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen)) {
3659#ifndef QT_MAC_USE_COCOA
3660 Point idealSize;
3661 ZoomWindowIdeal(window, inZoomIn, &idealSize);
3662#else
3663 [window zoom:window];
3664#endif
3665 if(QTLWExtra *tlextra = d->topData()) {
3666 setGeometry(tlextra->normalGeometry);
3667 tlextra->normalGeometry.setRect(0, 0, -1, -1);
3668 }
3669 }
3670 }
3671 }
3672
3673 data->window_state = newstate;
3674
3675 if(needShow)
3676 show();
3677
3678 if(newstate & Qt::WindowActive)
3679 activateWindow();
3680
3681 qt_event_request_window_change(this);
3682 if (needSendStateChange) {
3683 QWindowStateChangeEvent e(oldstate);
3684 QApplication::sendEvent(this, &e);
3685 }
3686}
3687
3688void QWidgetPrivate::setFocus_sys()
3689{
3690 Q_Q(QWidget);
3691 if (q->testAttribute(Qt::WA_WState_Created)) {
3692#ifdef QT_MAC_USE_COCOA
3693 QMacCocoaAutoReleasePool pool;
3694 NSView *view = qt_mac_nativeview_for(q);
3695 [[view window] makeFirstResponder:view];
3696#else
3697 SetKeyboardFocus(qt_mac_window_for(q), qt_mac_nativeview_for(q), 1);
3698#endif
3699 }
3700}
3701
3702NSComparisonResult compareViews2Raise(id view1, id view2, void *context)
3703{
3704 id topView = reinterpret_cast<id>(context);
3705 if (view1 == topView)
3706 return NSOrderedDescending;
3707 if (view2 == topView)
3708 return NSOrderedAscending;
3709 return NSOrderedSame;
3710}
3711
3712void QWidgetPrivate::raise_sys()
3713{
3714 Q_Q(QWidget);
3715 if((q->windowType() == Qt::Desktop))
3716 return;
3717
3718#if QT_MAC_USE_COCOA
3719 QMacCocoaAutoReleasePool pool;
3720 if (isRealWindow()) {
3721 // Calling orderFront shows the window on Cocoa too.
3722 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) {
3723 [qt_mac_window_for(q) orderFront:qt_mac_window_for(q)];
3724 }
3725 if (qt_mac_raise_process) { //we get to be the active process now
3726 ProcessSerialNumber psn;
3727 GetCurrentProcess(&psn);
3728 SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
3729 }
3730 } else {
3731 NSView *view = qt_mac_nativeview_for(q);
3732 NSView *parentView = [view superview];
3733 [parentView sortSubviewsUsingFunction:compareViews2Raise context:reinterpret_cast<void *>(view)];
3734 }
3735#else
3736 if(q->isWindow()) {
3737 //raise this window
3738 BringToFront(qt_mac_window_for(q));
3739 if(qt_mac_raise_process) { //we get to be the active process now
3740 ProcessSerialNumber psn;
3741 GetCurrentProcess(&psn);
3742 SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
3743 }
3744 } else if(q->parentWidget()) {
3745 HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderAbove, 0);
3746 qt_event_request_window_change(q);
3747 }
3748#endif
3749}
3750
3751NSComparisonResult compareViews2Lower(id view1, id view2, void *context)
3752{
3753 id topView = reinterpret_cast<id>(context);
3754 if (view1 == topView)
3755 return NSOrderedAscending;
3756 if (view2 == topView)
3757 return NSOrderedDescending;
3758 return NSOrderedSame;
3759}
3760
3761void QWidgetPrivate::lower_sys()
3762{
3763 Q_Q(QWidget);
3764 if((q->windowType() == Qt::Desktop))
3765 return;
3766#ifdef QT_MAC_USE_COCOA
3767 if (isRealWindow()) {
3768 OSWindowRef window = qt_mac_window_for(q);
3769 [window orderBack:window];
3770 } else {
3771 NSView *view = qt_mac_nativeview_for(q);
3772 NSView *parentView = [view superview];
3773 [parentView sortSubviewsUsingFunction:compareViews2Lower context:reinterpret_cast<void *>(view)];
3774 }
3775#else
3776 if(q->isWindow()) {
3777 SendBehind(qt_mac_window_for(q), 0);
3778 } else if(q->parentWidget()) {
3779 invalidateBuffer(q->rect());
3780 HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderBelow, 0);
3781 qt_event_request_window_change(q);
3782 }
3783#endif
3784}
3785
3786NSComparisonResult compareViews2StackUnder(id view1, id view2, void *context)
3787{
3788 const QHash<NSView *, int> &viewOrder = *reinterpret_cast<QHash<NSView *, int> *>(context);
3789 if (viewOrder[view1] < viewOrder[view2])
3790 return NSOrderedAscending;
3791 if (viewOrder[view1] > viewOrder[view2])
3792 return NSOrderedDescending;
3793 return NSOrderedSame;
3794}
3795
3796void QWidgetPrivate::stackUnder_sys(QWidget *w)
3797{
3798 // stackUnder
3799 Q_Q(QWidget);
3800 if(!w || q->isWindow() || (q->windowType() == Qt::Desktop))
3801 return;
3802#ifdef QT_MAC_USE_COCOA
3803 // Do the same trick as lower_sys() and put this widget before the widget passed in.
3804 NSView *myView = qt_mac_nativeview_for(q);
3805 NSView *wView = qt_mac_nativeview_for(w);
3806
3807 QHash<NSView *, int> viewOrder;
3808 NSView *parentView = [myView superview];
3809 NSArray *subviews = [parentView subviews];
3810 NSUInteger index = 1;
3811 // make a hash of view->zorderindex and make sure z-value is always odd,
3812 // so that when we modify the order we create a new (even) z-value which
3813 // will not interfere with others.
3814 for (NSView *subview in subviews) {
3815 viewOrder.insert(subview, index * 2);
3816 ++index;
3817 }
3818 viewOrder[myView] = viewOrder[wView] - 1;
3819
3820 [parentView sortSubviewsUsingFunction:compareViews2StackUnder context:reinterpret_cast<void *>(&viewOrder)];
3821#else
3822 QWidget *p = q->parentWidget();
3823 if(!p || p != w->parentWidget())
3824 return;
3825 invalidateBuffer(q->rect());
3826 HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderBelow, qt_mac_nativeview_for(w));
3827 qt_event_request_window_change(q);
3828#endif
3829}
3830
3831/*
3832 Modifies the bounds for a widgets backing HIView during moves and resizes. Also updates the
3833 widget, either by scrolling its contents or repainting, depending on the WA_StaticContents
3834 flag
3835*/
3836static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newRect)
3837{
3838#ifndef QT_MAC_USE_COCOA
3839 HIRect bounds = CGRectMake(newRect.x(), newRect.y(),
3840 newRect.width(), newRect.height());
3841
3842 const HIViewRef view = qt_mac_nativeview_for(q);
3843 const bool isMove = (oldRect.topLeft() != newRect.topLeft());
3844 const bool isResize = (oldRect.size() != newRect.size());
3845
3846// qDebug() << oldRect << newRect << isMove << isResize << q->testAttribute(Qt::WA_OpaquePaintEvent) << q->testAttribute(Qt::WA_StaticContents);
3847 QWidgetPrivate *qd = qt_widget_private(q);
3848
3849 // Perform a normal (complete repaint) update in some cases:
3850 if (
3851 // always repaint on move.
3852 (isMove) ||
3853
3854 // limited update on resize requires WA_StaticContents.
3855 (isResize && q->testAttribute(Qt::WA_StaticContents) == false) ||
3856
3857 // one of the rects are invalid
3858 (oldRect.isValid() == false || newRect.isValid() == false) ||
3859
3860 // the position update is a part of a drag-and-drop operation
3861 QDragManager::self()->object ||
3862
3863 // we are on Panther (no HIViewSetNeedsDisplayInRect)
3864 QSysInfo::MacintoshVersion < QSysInfo::MV_10_4
3865 ){
3866 HIViewSetFrame(view, &bounds);
3867 return;
3868 }
3869
3870 const int dx = newRect.x() - oldRect.x();
3871 const int dy = newRect.y() - oldRect.y();
3872
3873 if (isMove) {
3874 // HIViewScrollRect silently fails if we try to scroll anything under the grow box.
3875 // Check if there's one present within the widget rect, and if there is fall back
3876 // to repainting the entire widget.
3877 QWidget const * const parentWidget = q->parentWidget();
3878 const HIViewRef parentView = qt_mac_nativeview_for(parentWidget);
3879 HIViewRef nativeSizeGrip = 0;
3880 if (q->testAttribute(Qt::WA_WState_Created))
3881 HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(q->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip);
3882 if (nativeSizeGrip) {
3883 QWidget * const window = q->window();
3884
3885 const int sizeGripSize = 20;
3886 const QRect oldWidgetRect = QRect(q->mapTo(window, QPoint(0, 0)), QSize(oldRect.width(), oldRect.height()));
3887 const QRect newWidgetRect = QRect(q->mapTo(window, QPoint(0, 0)), QSize(newRect.width(), newRect.height()));
3888 const QRect sizeGripRect = QRect(window->rect().bottomRight() - QPoint(sizeGripSize, sizeGripSize),
3889 window->rect().bottomRight());
3890
3891 if (sizeGripRect.intersects(oldWidgetRect) || sizeGripRect.intersects(newWidgetRect)) {
3892 HIViewSetFrame(view, &bounds);
3893 return;
3894 }
3895 }
3896
3897 // Don't scroll anything outside the parent widget rect.
3898 const QRect scrollRect = (oldRect | newRect) & parentWidget->rect();
3899 const HIRect scrollBounds =
3900 CGRectMake(scrollRect.x(), scrollRect.y(), scrollRect.width(), scrollRect.height());
3901
3902 // We cannot scroll when the widget has a mask as that would
3903 // scroll the masked out areas too
3904 if (qd->extra && qd->extra->hasMask) {
3905 HIViewMoveBy(view, dx, dy);
3906 return;
3907 }
3908
3909 OSStatus err = HIViewScrollRect(parentView, &scrollBounds, dx, dy);
3910 if (err != noErr) {
3911 HIViewSetNeedsDisplay(view, true);
3912 qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__);
3913 }
3914 }
3915 // Set the view bounds with drawing disabled to prevent repaints.
3916 HIViewSetDrawingEnabled(view, false);
3917 HIViewSetFrame(view, &bounds);
3918 HIViewSetDrawingEnabled(view, true);
3919
3920 // Update any newly exposed areas due to resizing.
3921 const int startx = oldRect.width();
3922 const int stopx = newRect.width();
3923 const int starty = oldRect.height();
3924 const int stopy = newRect.height();
3925
3926 const HIRect verticalSlice = CGRectMake(startx, 0, stopx , stopy);
3927 HIViewSetNeedsDisplayInRect(view, &verticalSlice, true);
3928 const HIRect horizontalSlice = CGRectMake(0, starty, startx, stopy);
3929 HIViewSetNeedsDisplayInRect(view, &horizontalSlice, true);
3930#else
3931 Q_UNUSED(oldRect);
3932 NSRect bounds = NSMakeRect(newRect.x(), newRect.y(),
3933 newRect.width(), newRect.height());
3934 [qt_mac_nativeview_for(q) setFrame:bounds];
3935#endif
3936}
3937
3938/*
3939 Helper function for non-toplevel widgets. Helps to map Qt's 32bit
3940 coordinate system to OS X's 16bit coordinate system.
3941
3942 Sets the geometry of the widget to data.crect, but clipped to sizes
3943 that OS X can handle. Unmaps widgets that are completely outside the
3944 valid range.
3945
3946 Maintains data.wrect, which is the geometry of the OS X widget,
3947 measured in this widget's coordinate system.
3948
3949 if the parent is not clipped, parentWRect is empty, otherwise
3950 parentWRect is the geometry of the parent's OS X rect, measured in
3951 parent's coord sys
3952*/
3953void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
3954{
3955 Q_Q(QWidget);
3956 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
3957 Q_UNUSED(oldRect);
3958 /*
3959 There are up to four different coordinate systems here:
3960 Qt coordinate system for this widget.
3961 X coordinate system for this widget (relative to wrect).
3962 Qt coordinate system for parent
3963 X coordinate system for parent (relative to parent's wrect).
3964 */
3965 QRect wrect;
3966 //xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys)
3967 QRect xrect = data.crect;
3968
3969 QRect parentWRect;
3970 if (q->isWindow() && topData()->embedded) {
3971#ifndef QT_MAC_USE_COCOA
3972 HIViewRef parentView = HIViewGetSuperview(qt_mac_nativeview_for(q));
3973#else
3974 NSView *parentView = [qt_mac_nativeview_for(q) superview];
3975#endif
3976 if (parentView) {
3977#ifndef QT_MAC_USE_COCOA
3978 HIRect tmpRect;
3979 HIViewGetFrame(parentView, &tmpRect);
3980#else
3981 NSRect tmpRect = [parentView frame];
3982#endif
3983 parentWRect = QRect(tmpRect.origin.x, tmpRect.origin.y,
3984 tmpRect.size.width, tmpRect.size.height);
3985 } else {
3986 const QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
3987 parentWRect = wrectRange;
3988 }
3989 } else {
3990 parentWRect = q->parentWidget()->data->wrect;
3991 }
3992
3993 if (parentWRect.isValid()) {
3994 // parent is clipped, and we have to clip to the same limit as parent
3995 if (!parentWRect.contains(xrect)) {
3996 xrect &= parentWRect;
3997 wrect = xrect;
3998 //translate from parent's to my Qt coord sys
3999 wrect.translate(-data.crect.topLeft());
4000 }
4001 //translate from parent's Qt coords to parent's X coords
4002 xrect.translate(-parentWRect.topLeft());
4003
4004 } else {
4005 // parent is not clipped, we may or may not have to clip
4006
4007 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
4008 // This is where the main optimization is: we are already
4009 // clipped, and if our clip is still valid, we can just
4010 // move our window, and do not need to move or clip
4011 // children
4012
4013 QRect vrect = xrect & q->parentWidget()->rect();
4014 vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
4015 if (data.wrect.contains(vrect)) {
4016 xrect = data.wrect;
4017 xrect.translate(data.crect.topLeft());
4018#ifndef QT_MAC_USE_COCOA
4019 HIRect bounds = CGRectMake(xrect.x(), xrect.y(),
4020 xrect.width(), xrect.height());
4021 HIViewSetFrame(qt_mac_nativeview_for(q), &bounds);
4022#else
4023 NSRect bounds = NSMakeRect(xrect.x(), xrect.y(),
4024 xrect.width(), xrect.height());
4025 [qt_mac_nativeview_for(q) setFrame:bounds];
4026#endif
4027 if (q->testAttribute(Qt::WA_OutsideWSRange)) {
4028 q->setAttribute(Qt::WA_OutsideWSRange, false);
4029 if (!dontShow) {
4030 q->setAttribute(Qt::WA_Mapped);
4031#ifndef QT_MAC_USE_COCOA
4032 HIViewSetVisible(qt_mac_nativeview_for(q), true);
4033#else
4034 [qt_mac_nativeview_for(q) setHidden:NO];
4035#endif
4036 }
4037 }
4038 return;
4039 }
4040 }
4041
4042 const QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
4043 if (!validRange.contains(xrect)) {
4044 // we are too big, and must clip
4045 QPoint screenOffset(0, 0); // offset of the part being on screen
4046 const QWidget *parentWidget = q->parentWidget();
4047 while (parentWidget && !parentWidget->isWindow()) {
4048 screenOffset -= parentWidget->data->crect.topLeft();
4049 parentWidget = parentWidget->parentWidget();
4050 }
4051 QRect cropRect(screenOffset.x() - WRECT_MAX,
4052 screenOffset.y() - WRECT_MAX,
4053 2*WRECT_MAX,
4054 2*WRECT_MAX);
4055
4056 xrect &=cropRect;
4057 wrect = xrect;
4058 wrect.translate(-data.crect.topLeft()); // translate wrect in my Qt coordinates
4059 }
4060 }
4061
4062 // unmap if we are outside the valid window system coord system
4063 bool outsideRange = !xrect.isValid();
4064 bool mapWindow = false;
4065 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
4066 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
4067 if (outsideRange) {
4068#ifndef QT_MAC_USE_COCOA
4069 HIViewSetVisible(qt_mac_nativeview_for(q), false);
4070#else
4071 [qt_mac_nativeview_for(q) setHidden:YES];
4072#endif
4073 q->setAttribute(Qt::WA_Mapped, false);
4074 } else if (!q->isHidden()) {
4075 mapWindow = true;
4076 }
4077 }
4078
4079 if (outsideRange)
4080 return;
4081
4082 bool jump = (data.wrect != wrect);
4083 data.wrect = wrect;
4084
4085
4086 // and now recursively for all children...
4087 // ### can be optimized
4088 for (int i = 0; i < children.size(); ++i) {
4089 QObject *object = children.at(i);
4090 if (object->isWidgetType()) {
4091 QWidget *w = static_cast<QWidget *>(object);
4092 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
4093 w->d_func()->setWSGeometry();
4094 }
4095 }
4096
4097 qt_mac_update_widget_posisiton(q, oldRect, xrect);
4098
4099 if (jump)
4100 q->update();
4101
4102 if (mapWindow && !dontShow) {
4103 q->setAttribute(Qt::WA_Mapped);
4104#ifndef QT_MAC_USE_COCOA
4105 HIViewSetVisible(qt_mac_nativeview_for(q), true);
4106#else
4107 [qt_mac_nativeview_for(q) setHidden:NO];
4108#endif
4109 }
4110}
4111
4112void QWidgetPrivate::adjustWithinMaxAndMinSize(int &w, int &h)
4113{
4114 if (QWExtra *extra = extraData()) {
4115 w = qMin(w, extra->maxw);
4116 h = qMin(h, extra->maxh);
4117 w = qMax(w, extra->minw);
4118 h = qMax(h, extra->minh);
4119
4120 // Deal with size increment
4121 if (QTLWExtra *top = topData()) {
4122 if(top->incw) {
4123 w = w/top->incw;
4124 w *= top->incw;
4125 }
4126 if(top->inch) {
4127 h = h/top->inch;
4128 h *= top->inch;
4129 }
4130 }
4131 }
4132
4133 if (isRealWindow()) {
4134 w = qMax(0, w);
4135 h = qMax(0, h);
4136 }
4137}
4138
4139void QWidgetPrivate::applyMaxAndMinSizeOnWindow()
4140{
4141 Q_Q(QWidget);
4142 const float max_f(20000);
4143#ifndef QT_MAC_USE_COCOA
4144#define SF(x) ((x > max_f) ? max_f : x)
4145 HISize max = CGSizeMake(SF(extra->maxw), SF(extra->maxh));
4146 HISize min = CGSizeMake(SF(extra->minw), SF(extra->minh));
4147#undef SF
4148 SetWindowResizeLimits(qt_mac_window_for(q), &min, &max);
4149#else
4150#define SF(x) ((x > max_f) ? max_f : x)
4151 NSSize max = NSMakeSize(SF(extra->maxw), SF(extra->maxh));
4152 NSSize min = NSMakeSize(SF(extra->minw), SF(extra->minh));
4153#undef SF
4154 [qt_mac_window_for(q) setContentMinSize:min];
4155 [qt_mac_window_for(q) setContentMaxSize:max];
4156#endif
4157}
4158
4159void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
4160{
4161 Q_Q(QWidget);
4162 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
4163
4164 if(q->windowType() == Qt::Desktop)
4165 return;
4166
4167 QMacCocoaAutoReleasePool pool;
4168 bool realWindow = isRealWindow();
4169
4170 if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen)){
4171 adjustWithinMaxAndMinSize(w, h);
4172#ifndef QT_MAC_USE_COCOA
4173 if (w != 0 && h != 0) {
4174 topData()->isSetGeometry = 1;
4175 topData()->isMove = isMove;
4176 Rect r; SetRect(&r, x, y, x + w, y + h);
4177 SetWindowBounds(qt_mac_window_for(q), kWindowContentRgn, &r);
4178 topData()->isSetGeometry = 0;
4179 } else {
4180 setGeometry_sys_helper(x, y, w, h, isMove);
4181 }
4182#else
4183 QSize olds = q->size();
4184 const bool isResize = (olds != QSize(w, h));
4185 NSWindow *window = qt_mac_window_for(q);
4186 const QRect &fStrut = frameStrut();
4187 const QRect frameRect(QPoint(x - fStrut.left(), y - fStrut.top()),
4188 QSize(fStrut.left() + fStrut.right() + w,
4189 fStrut.top() + fStrut.bottom() + h));
4190 NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1),
4191 frameRect.width(), frameRect.height());
4192 // The setFrame call will trigger a 'windowDidResize' notification for the corresponding
4193 // NSWindow. The pending flag is set, so that the resize event can be send as non-spontaneous.
4194 if (isResize)
4195 q->setAttribute(Qt::WA_PendingResizeEvent);
4196 QPoint currTopLeft = data.crect.topLeft();
4197 if (currTopLeft.x() == x && currTopLeft.y() == y
4198 && cocoaFrameRect.size.width != 0
4199 && cocoaFrameRect.size.height != 0) {
4200 [window setFrame:cocoaFrameRect display:NO];
4201 } else {
4202 // The window is moved and resized (or resized to zero).
4203 // Since Cocoa usually only sends us a resize callback after
4204 // setting a window frame, we issue an explicit move as
4205 // well. To stop Cocoa from optimize away the move (since the move
4206 // would have the same origin as the setFrame call) we shift the
4207 // window back and forth inbetween.
4208 cocoaFrameRect.origin.y += 1;
4209 [window setFrame:cocoaFrameRect display:NO];
4210 cocoaFrameRect.origin.y -= 1;
4211 [window setFrameOrigin:cocoaFrameRect.origin];
4212 }
4213#endif
4214 } else {
4215 setGeometry_sys_helper(x, y, w, h, isMove);
4216 }
4217}
4218
4219void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isMove)
4220{
4221 Q_Q(QWidget);
4222 bool realWindow = isRealWindow();
4223
4224 QPoint oldp = q->pos();
4225 QSize olds = q->size();
4226 const bool isResize = (olds != QSize(w, h));
4227
4228 if (!realWindow && !isResize && QPoint(x, y) == oldp)
4229 return;
4230
4231 if (isResize)
4232 data.window_state = data.window_state & ~Qt::WindowMaximized;
4233
4234 const bool visible = q->isVisible();
4235 data.crect = QRect(x, y, w, h);
4236
4237 if (realWindow) {
4238 adjustWithinMaxAndMinSize(w, h);
4239 qt_mac_update_sizer(q);
4240
4241#ifndef QT_MAC_USE_COCOA
4242 if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
4243 OSWindowRef window = qt_mac_window_for(q);
4244 if (extra->maxw && extra->maxh && extra->maxw == extra->minw
4245 && extra->maxh == extra->minh) {
4246 ChangeWindowAttributes(window, kWindowNoAttributes, kWindowFullZoomAttribute);
4247 } else {
4248 ChangeWindowAttributes(window, kWindowFullZoomAttribute, kWindowNoAttributes);
4249 }
4250 }
4251 HIRect bounds = CGRectMake(0, 0, w, h);
4252 HIViewSetFrame(qt_mac_nativeview_for(q), &bounds);
4253#else
4254 [qt_mac_nativeview_for(q) setFrame:NSMakeRect(0, 0, w, h)];
4255#endif
4256 } else {
4257 const QRect oldRect(oldp, olds);
4258 if (!isResize && QApplicationPrivate::graphicsSystem())
4259 moveRect(oldRect, x - oldp.x(), y - oldp.y());
4260 setWSGeometry(false, oldRect);
4261 if (isResize && QApplicationPrivate::graphicsSystem()) {
4262 invalidateBuffer(q->rect());
4263 if (extra && !graphicsEffect && !extra->mask.isEmpty()) {
4264 QRegion oldRegion(extra->mask.translated(oldp));
4265 oldRegion &= oldRect;
4266 q->parentWidget()->d_func()->invalidateBuffer(oldRegion);
4267 } else {
4268 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(oldRect));
4269 }
4270 }
4271 }
4272
4273 if(isMove || isResize) {
4274 if(!visible) {
4275 if(isMove && q->pos() != oldp)
4276 q->setAttribute(Qt::WA_PendingMoveEvent, true);
4277 if(isResize)
4278 q->setAttribute(Qt::WA_PendingResizeEvent, true);
4279 } else {
4280 if(isResize) { //send the resize event..
4281 QResizeEvent e(q->size(), olds);
4282 QApplication::sendEvent(q, &e);
4283 }
4284 if(isMove && q->pos() != oldp) { //send the move event..
4285 QMoveEvent e(q->pos(), oldp);
4286 QApplication::sendEvent(q, &e);
4287 }
4288 }
4289 }
4290 qt_event_request_window_change(q);
4291}
4292
4293void QWidgetPrivate::setConstraints_sys()
4294{
4295 updateMaximizeButton_sys();
4296 applyMaxAndMinSizeOnWindow();
4297}
4298
4299void QWidgetPrivate::updateMaximizeButton_sys()
4300{
4301 Q_Q(QWidget);
4302 if (q->data->window_flags & Qt::CustomizeWindowHint)
4303 return;
4304
4305 OSWindowRef window = qt_mac_window_for(q);
4306 QTLWExtra * tlwExtra = topData();
4307#ifdef QT_MAC_USE_COCOA
4308 QMacCocoaAutoReleasePool pool;
4309 NSButton *maximizeButton = [window standardWindowButton:NSWindowZoomButton];
4310#endif
4311 if (extra->maxw && extra->maxh
4312 && extra->maxw == extra->minw
4313 && extra->maxh == extra->minh) {
4314 // The window has a fixed size, so gray out the maximize button:
4315 if (!tlwExtra->savedWindowAttributesFromMaximized) {
4316#ifndef QT_MAC_USE_COCOA
4317 GetWindowAttributes(window,
4318 (WindowAttributes*)&extra->topextra->savedWindowAttributesFromMaximized);
4319
4320#else
4321 tlwExtra->savedWindowAttributesFromMaximized = (![maximizeButton isHidden] && [maximizeButton isEnabled]);
4322#endif
4323 }
4324#ifndef QT_MAC_USE_COCOA
4325 ChangeWindowAttributes(window, kWindowNoAttributes, kWindowFullZoomAttribute);
4326#else
4327 [maximizeButton setEnabled:NO];
4328#endif
4329
4330
4331 } else {
4332 if (tlwExtra->savedWindowAttributesFromMaximized) {
4333#ifndef QT_MAC_USE_COCOA
4334 ChangeWindowAttributes(window,
4335 extra->topextra->savedWindowAttributesFromMaximized,
4336 kWindowNoAttributes);
4337#else
4338 [maximizeButton setEnabled:YES];
4339#endif
4340 tlwExtra->savedWindowAttributesFromMaximized = 0;
4341 }
4342 }
4343
4344
4345}
4346
4347void QWidgetPrivate::scroll_sys(int dx, int dy)
4348{
4349 if (QApplicationPrivate::graphicsSystem() && !paintOnScreen()) {
4350 scrollChildren(dx, dy);
4351 scrollRect(q_func()->rect(), dx, dy);
4352 } else {
4353 scroll_sys(dx, dy, QRect());
4354 }
4355}
4356
4357void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
4358{
4359 Q_Q(QWidget);
4360
4361 if (QApplicationPrivate::graphicsSystem() && !paintOnScreen()) {
4362 scrollRect(r, dx, dy);
4363 return;
4364 }
4365
4366 const bool valid_rect = r.isValid();
4367 if (!q->updatesEnabled() && (valid_rect || q->children().isEmpty()))
4368 return;
4369
4370 qt_event_request_window_change(q);
4371
4372#ifdef QT_MAC_USE_COCOA
4373 QMacCocoaAutoReleasePool pool;
4374#endif
4375
4376 if(!valid_rect) { // scroll children
4377 QPoint pd(dx, dy);
4378 QWidgetList moved;
4379 QObjectList chldrn = q->children();
4380 for(int i = 0; i < chldrn.size(); i++) { //first move all children
4381 QObject *obj = chldrn.at(i);
4382 if(obj->isWidgetType()) {
4383 QWidget *w = (QWidget*)obj;
4384 if(!w->isWindow()) {
4385 w->data->crect = QRect(w->pos() + pd, w->size());
4386 if (w->testAttribute(Qt::WA_WState_Created)) {
4387#ifndef QT_MAC_USE_COCOA
4388 HIRect bounds = CGRectMake(w->data->crect.x(), w->data->crect.y(),
4389 w->data->crect.width(), w->data->crect.height());
4390 HIViewRef hiview = qt_mac_nativeview_for(w);
4391 const bool opaque = q->testAttribute(Qt::WA_OpaquePaintEvent);
4392
4393 if (opaque)
4394 HIViewSetDrawingEnabled(hiview, false);
4395 HIViewSetFrame(hiview, &bounds);
4396 if (opaque)
4397 HIViewSetDrawingEnabled(hiview, true);
4398#else
4399 [qt_mac_nativeview_for(w)
4400 setFrame:NSMakeRect(w->data->crect.x(), w->data->crect.y(),
4401 w->data->crect.width(), w->data->crect.height())];
4402#endif
4403 }
4404 moved.append(w);
4405 }
4406 }
4407 }
4408 //now send move events (do not do this in the above loop, breaks QAquaFocusWidget)
4409 for(int i = 0; i < moved.size(); i++) {
4410 QWidget *w = moved.at(i);
4411 QMoveEvent e(w->pos(), w->pos() - pd);
4412 QApplication::sendEvent(w, &e);
4413 }
4414 }
4415
4416 if (!q->testAttribute(Qt::WA_WState_Created) || !q->isVisible())
4417 return;
4418
4419 OSViewRef view = qt_mac_nativeview_for(q);
4420#ifndef QT_MAC_USE_COCOA
4421 HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height());
4422 OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid);
4423 if (err) {
4424 // The only parameter that can go wrong, is the rect.
4425 qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect");
4426 scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0),
4427 qMin(r.width(), q->width()), qMin(r.height(), q->height()));
4428 _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid);
4429 }
4430#else
4431 NSRect scrollRect = valid_rect ? NSMakeRect(r.x(), r.y(), r.width(), r.height())
4432 : NSMakeRect(0, 0, q->width(), q->height());
4433
4434
4435 // calc the updateRect
4436 NSRect deltaXRect = { {0, 0}, {0, 0} };
4437 NSRect deltaYRect = { {0, 0}, {0, 0} };
4438 if (dy != 0) {
4439 deltaYRect.size.width = scrollRect.size.width;
4440 if (dy > 0) {
4441 deltaYRect.size.height = dy;
4442 } else {
4443 deltaYRect.size.height = -dy;
4444 deltaYRect.origin.y = scrollRect.size.height + dy;
4445 }
4446 }
4447 if (dx != 0) {
4448 deltaXRect.size.height = scrollRect.size.height;
4449 if (dx > 0) {
4450 deltaXRect.size.width = dx;
4451 } else {
4452 deltaXRect.size.width = -dx;
4453 deltaXRect.origin.x = scrollRect.size.width + dx;
4454 }
4455 }
4456
4457 NSSize deltaSize = NSMakeSize(dx, dy);
4458 [view translateRectsNeedingDisplayInRect:scrollRect by:deltaSize];
4459 [view scrollRect:scrollRect by:deltaSize];
4460 [view setNeedsDisplayInRect:deltaXRect];
4461 [view setNeedsDisplayInRect:deltaYRect];
4462#endif // QT_MAC_USE_COCOA
4463}
4464
4465int QWidget::metric(PaintDeviceMetric m) const
4466{
4467 switch(m) {
4468 case PdmHeightMM:
4469 return qRound(metric(PdmHeight) * 25.4 / qreal(metric(PdmDpiY)));
4470 case PdmWidthMM:
4471 return qRound(metric(PdmWidth) * 25.4 / qreal(metric(PdmDpiX)));
4472 case PdmHeight:
4473 case PdmWidth: {
4474#ifndef QT_MAC_USE_COCOA
4475 HIRect rect;
4476 HIViewGetFrame(qt_mac_nativeview_for(this), &rect);
4477#else
4478 NSRect rect = [qt_mac_nativeview_for(this) frame];
4479#endif
4480 if(m == PdmWidth)
4481 return (int)rect.size.width;
4482 return (int)rect.size.height; }
4483 case PdmDepth:
4484 return 32;
4485 case PdmNumColors:
4486 return INT_MAX;
4487 case PdmDpiX:
4488 case PdmPhysicalDpiX: {
4489 Q_D(const QWidget);
4490 if (d->extra && d->extra->customDpiX)
4491 return d->extra->customDpiX;
4492 else if (d->parent)
4493 return static_cast<QWidget *>(d->parent)->metric(m);
4494 extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp
4495 return int(qt_mac_defaultDpi_x()); }
4496 case PdmDpiY:
4497 case PdmPhysicalDpiY: {
4498 Q_D(const QWidget);
4499 if (d->extra && d->extra->customDpiY)
4500 return d->extra->customDpiY;
4501 else if (d->parent)
4502 return static_cast<QWidget *>(d->parent)->metric(m);
4503 extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp
4504 return int(qt_mac_defaultDpi_y()); }
4505 default: //leave this so the compiler complains when new ones are added
4506 qWarning("QWidget::metric: Unhandled parameter %d", m);
4507 return QPaintDevice::metric(m);
4508 }
4509 return 0;
4510}
4511
4512void QWidgetPrivate::createSysExtra()
4513{
4514#ifdef QT_MAC_USE_COCOA
4515 extra->imageMask = 0;
4516#endif
4517}
4518
4519void QWidgetPrivate::deleteSysExtra()
4520{
4521#ifdef QT_MAC_USE_COCOA
4522 if (extra->imageMask)
4523 CFRelease(extra->imageMask);
4524#endif
4525}
4526
4527void QWidgetPrivate::createTLSysExtra()
4528{
4529 extra->topextra->resizer = 0;
4530 extra->topextra->isSetGeometry = 0;
4531 extra->topextra->isMove = 0;
4532 extra->topextra->wattr = 0;
4533 extra->topextra->wclass = 0;
4534 extra->topextra->group = 0;
4535 extra->topextra->windowIcon = 0;
4536 extra->topextra->savedWindowAttributesFromMaximized = 0;
4537}
4538
4539void QWidgetPrivate::deleteTLSysExtra()
4540{
4541#ifndef QT_MAC_USE_COCOA
4542 if (extra->topextra->group) {
4543 qt_mac_release_window_group(extra->topextra->group);
4544 extra->topextra->group = 0;
4545 }
4546 if (extra->topextra->windowIcon) {
4547 ReleaseIconRef(extra->topextra->windowIcon);
4548 extra->topextra->windowIcon = 0;
4549 }
4550#endif
4551}
4552
4553void QWidgetPrivate::updateFrameStrut()
4554{
4555 Q_Q(QWidget);
4556
4557 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
4558
4559 that->data.fstrut_dirty = false;
4560 QTLWExtra *top = that->topData();
4561
4562#if QT_MAC_USE_COCOA
4563 // 1 Get the window frame
4564 OSWindowRef oswnd = qt_mac_window_for(q);
4565 NSRect frameW = [oswnd frame];
4566 // 2 Get the content frame - so now
4567 NSRect frameC = [oswnd contentRectForFrameRect:frameW];
4568 top->frameStrut.setCoords(frameC.origin.x - frameW.origin.x,
4569 (frameW.origin.y + frameW.size.height) - (frameC.origin.y + frameC.size.height),
4570 (frameW.origin.x + frameW.size.width) - (frameC.origin.x + frameC.size.width),
4571 frameC.origin.y - frameW.origin.y);
4572#else
4573 Rect window_r;
4574 GetWindowStructureWidths(qt_mac_window_for(q), &window_r);
4575 top->frameStrut.setCoords(window_r.left, window_r.top, window_r.right, window_r.bottom);
4576#endif
4577}
4578
4579void QWidgetPrivate::registerDropSite(bool on)
4580{
4581 Q_Q(QWidget);
4582 if (!q->testAttribute(Qt::WA_WState_Created))
4583 return;
4584#ifndef QT_MAC_USE_COCOA
4585 SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on);
4586#else
4587 NSView *view = qt_mac_nativeview_for(q);
4588 if (on && [view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
4589 [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) registerDragTypes];
4590 }
4591#endif
4592}
4593
4594void QWidgetPrivate::registerTouchWindow()
4595{
4596#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
4597 if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
4598 return;
4599 Q_Q(QWidget);
4600 if (!q->testAttribute(Qt::WA_WState_Created))
4601 return;
4602#ifndef QT_MAC_USE_COCOA
4603 // Needs implementation!
4604#else
4605 NSView *view = qt_mac_nativeview_for(q);
4606 [view setAcceptsTouchEvents:YES];
4607#endif
4608#endif
4609}
4610
4611void QWidgetPrivate::setMask_sys(const QRegion &region)
4612{
4613 Q_UNUSED(region);
4614#ifndef QT_MAC_USE_COCOA
4615 Q_Q(QWidget);
4616 if (q->isWindow())
4617 ReshapeCustomWindow(qt_mac_window_for(q));
4618 else
4619 HIViewReshapeStructure(qt_mac_nativeview_for(q));
4620#else
4621 if (extra->mask.isEmpty()) {
4622 extra->maskBits = QImage();
4623 finishCocoaMaskSetup();
4624 } else {
4625 syncCocoaMask();
4626 }
4627
4628#endif
4629}
4630
4631void QWidgetPrivate::setWindowOpacity_sys(qreal level)
4632{
4633 Q_Q(QWidget);
4634
4635 if (!q->isWindow())
4636 return;
4637
4638 level = qBound(0.0, level, 1.0);
4639 topData()->opacity = (uchar)(level * 255);
4640 if (!q->testAttribute(Qt::WA_WState_Created))
4641 return;
4642
4643 OSWindowRef oswindow = qt_mac_window_for(q);
4644#if QT_MAC_USE_COCOA
4645 [oswindow setAlphaValue:level];
4646#else
4647 SetWindowAlpha(oswindow, level);
4648#endif
4649}
4650
4651#ifdef QT_MAC_USE_COCOA
4652void QWidgetPrivate::syncCocoaMask()
4653{
4654 Q_Q(QWidget);
4655 if (!q->testAttribute(Qt::WA_WState_Created) || !extra)
4656 return;
4657
4658 if (extra->hasMask && extra->maskBits.size() != q->size()) {
4659 extra->maskBits = QImage(q->size(), QImage::Format_Mono);
4660 extra->maskBits.fill(QColor(Qt::color1).rgba());
4661 extra->maskBits.setNumColors(2);
4662 extra->maskBits.setColor(0, QColor(Qt::color0).rgba());
4663 extra->maskBits.setColor(1, QColor(Qt::color1).rgba());
4664 QPainter painter(&extra->maskBits);
4665 painter.setBrush(Qt::color1);
4666 painter.setPen(Qt::NoPen);
4667 painter.drawRects(extra->mask.rects());
4668 painter.end();
4669 finishCocoaMaskSetup();
4670 }
4671}
4672
4673void QWidgetPrivate::finishCocoaMaskSetup()
4674{
4675 Q_Q(QWidget);
4676
4677 if (!q->testAttribute(Qt::WA_WState_Created) || !extra)
4678 return;
4679
4680 // Technically this is too late to release, because the data behind the image
4681 // has already been released. But it's more tidy to do it here.
4682 // If you are seeing a crash, consider doing a CFRelease before changing extra->maskBits.
4683 if (extra->imageMask) {
4684 CFRelease(extra->imageMask);
4685 extra->imageMask = 0;
4686 }
4687
4688 if (!extra->maskBits.isNull()) {
4689 QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0,
4690 extra->maskBits.bits(),
4691 extra->maskBits.numBytes(),
4692 0); // shouldn't need to release.
4693 CGFloat decode[2] = {1, 0};
4694 extra->imageMask = CGImageMaskCreate(extra->maskBits.width(), extra->maskBits.height(),
4695 1, 1, extra->maskBits.bytesPerLine(), dataProvider,
4696 decode, false);
4697 }
4698 if (q->isWindow()) {
4699 NSWindow *window = qt_mac_window_for(q);
4700 [window setOpaque:(extra->imageMask == 0)];
4701 [window invalidateShadow];
4702 }
4703 [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
4704}
4705#endif
4706
4707struct QPaintEngineCleanupHandler
4708{
4709 inline QPaintEngineCleanupHandler() : engine(0) {}
4710 inline ~QPaintEngineCleanupHandler() { delete engine; }
4711 QPaintEngine *engine;
4712};
4713
4714Q_GLOBAL_STATIC(QPaintEngineCleanupHandler, engineHandler)
4715
4716QPaintEngine *QWidget::paintEngine() const
4717{
4718 QPaintEngine *&pe = engineHandler()->engine;
4719 if (!pe)
4720 pe = new QCoreGraphicsPaintEngine();
4721 if (pe->isActive()) {
4722 QPaintEngine *engine = new QCoreGraphicsPaintEngine();
4723 engine->setAutoDestruct(true);
4724 return engine;
4725 }
4726 return pe;
4727}
4728
4729void QWidgetPrivate::setModal_sys()
4730{
4731 Q_Q(QWidget);
4732 if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow())
4733 return;
4734 const QWidget * const windowParent = q->window()->parentWidget();
4735 const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0;
4736 OSWindowRef windowRef = qt_mac_window_for(q);
4737
4738#ifdef QT_MAC_USE_COCOA
4739 QMacCocoaAutoReleasePool pool;
4740 bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask;
4741
4742 if (windowParent && q->windowModality() == Qt::WindowModal){
4743 // Window should be window-modal, which implies a sheet.
4744 if (!alreadySheet) {
4745 // NB: the following call will call setModal_sys recursivly:
4746 recreateMacWindow();
4747 windowRef = qt_mac_window_for(q);
4748 }
4749 if ([windowRef isKindOfClass:[NSPanel class]]){
4750 // If the primary window of the sheet parent is a child of a modal dialog,
4751 // the sheet parent should not be modally shaddowed.
4752 // This goes for the sheet as well:
4753 OSWindowRef ref = primaryWindow ? qt_mac_window_for(primaryWindow) : 0;
4754 bool isDialog = ref ? [ref isKindOfClass:[NSPanel class]] : false;
4755 bool worksWhenModal = isDialog ? [static_cast<NSPanel *>(ref) worksWhenModal] : false;
4756 if (worksWhenModal)
4757 [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
4758 }
4759 } else {
4760 // Window shold not be window-modal, and as such, not a sheet.
4761 if (alreadySheet){
4762 // NB: the following call will call setModal_sys recursivly:
4763 recreateMacWindow();
4764 windowRef = qt_mac_window_for(q);
4765 }
4766 if (q->windowModality() == Qt::ApplicationModal) {
4767 [windowRef setLevel:NSModalPanelWindowLevel];
4768 } else if (primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) {
4769 // INVARIANT: Our window is a dialog that has a dialog parent that is
4770 // application modal, or . This means that q is supposed to be on top of this
4771 // dialog and not be modally shaddowed:
4772 [windowRef setLevel:NSModalPanelWindowLevel];
4773 if ([windowRef isKindOfClass:[NSPanel class]])
4774 [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
4775 } else {
4776 // INVARIANT: q should not be modal.
4777 NSInteger winLevel = -1;
4778 if (q->windowType() == Qt::Popup) {
4779 winLevel = NSPopUpMenuWindowLevel;
4780 // Popup should be in at least the same level as its parent.
4781 if (primaryWindow) {
4782 OSWindowRef parentRef = qt_mac_window_for(primaryWindow);
4783 winLevel = qMax([parentRef level], winLevel);
4784 }
4785 } else if (q->windowType() == Qt::Tool) {
4786 winLevel = NSFloatingWindowLevel;
4787 } else if (q->windowType() == Qt::Dialog) {
4788 winLevel = NSModalPanelWindowLevel;
4789 }
4790
4791 // StayOnTop window should appear above Tool windows.
4792 if (data.window_flags & Qt::WindowStaysOnTopHint)
4793 winLevel = NSPopUpMenuWindowLevel;
4794 // Tooltips should appear above StayOnTop windows.
4795 if (q->windowType() == Qt::ToolTip)
4796 winLevel = NSScreenSaverWindowLevel;
4797 // All other types are Normal level.
4798 if (winLevel == -1)
4799 winLevel = NSNormalWindowLevel;
4800 [windowRef setLevel:winLevel];
4801 }
4802 }
4803
4804#else
4805 const bool primaryWindowModal = primaryWindow ? primaryWindow->testAttribute(Qt::WA_ShowModal) : false;
4806 const bool modal = q->testAttribute(Qt::WA_ShowModal);
4807
4808 WindowClass old_wclass;
4809 GetWindowClass(windowRef, &old_wclass);
4810
4811 if (modal || primaryWindowModal) {
4812 if (q->windowModality() == Qt::WindowModal
4813 || (primaryWindow && primaryWindow->windowModality() == Qt::WindowModal)){
4814 // Window should be window-modal (which implies a sheet).
4815 if (old_wclass != kSheetWindowClass){
4816 // We cannot convert a created window to a sheet.
4817 // So we recreate the window:
4818 recreateMacWindow();
4819 return;
4820 }
4821 } else {
4822 // Window should be application-modal (which implies NOT using a sheet).
4823 if (old_wclass == kSheetWindowClass){
4824 // We cannot convert a sheet to a window.
4825 // So we recreate the window:
4826 recreateMacWindow();
4827 return;
4828 } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) {
4829 if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){
4830 // Only change the class to kMovableModalWindowClass if the no explicit jewels
4831 // are set (kMovableModalWindowClass can't contain them), and the current window class
4832 // can be converted to modal (according to carbon doc). Mind the order of
4833 // HIWindowChangeClass and ChangeWindowAttributes.
4834 WindowGroupRef group = GetWindowGroup(windowRef);
4835 HIWindowChangeClass(windowRef, kMovableModalWindowClass);
4836 quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute;
4837 ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes);
4838 ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr);
4839 // If the window belongs to a qt-created group, set that group once more:
4840 if (data.window_flags & Qt::WindowStaysOnTopHint
4841 || q->windowType() == Qt::Popup
4842 || q->windowType() == Qt::ToolTip)
4843 SetWindowGroup(windowRef, group);
4844 }
4845 // Popups are usually handled "special" and are never modal.
4846 Qt::WindowType winType = q->windowType();
4847 if (winType != Qt::Popup && winType != Qt::ToolTip)
4848 SetWindowModality(windowRef, kWindowModalityAppModal, 0);
4849 }
4850 }
4851 } else if (windowRef) {
4852 if (old_wclass == kSheetWindowClass){
4853 // Converting a sheet to a window is complex. It's easier to recreate:
4854 recreateMacWindow();
4855 return;
4856 }
4857
4858 SetWindowModality(windowRef, kWindowModalityNone, 0);
4859 if (!(q->data->window_flags & Qt::CustomizeWindowHint)) {
4860 if (q->window()->d_func()->topData()->wattr |= kWindowCloseBoxAttribute)
4861 ChangeWindowAttributes(windowRef, kWindowCloseBoxAttribute, kWindowNoAttributes);
4862 if (q->window()->d_func()->topData()->wattr |= kWindowHorizontalZoomAttribute)
4863 ChangeWindowAttributes(windowRef, kWindowHorizontalZoomAttribute, kWindowNoAttributes);
4864 if (q->window()->d_func()->topData()->wattr |= kWindowCollapseBoxAttribute)
4865 ChangeWindowAttributes(windowRef, kWindowCollapseBoxAttribute, kWindowNoAttributes);
4866 }
4867
4868 WindowClass newClass = q->window()->d_func()->topData()->wclass;
4869 if (old_wclass != newClass && newClass != 0){
4870 WindowGroupRef group = GetWindowGroup(windowRef);
4871 HIWindowChangeClass(windowRef, newClass);
4872 // If the window belongs to a qt-created group, set that group once more:
4873 if (data.window_flags & Qt::WindowStaysOnTopHint
4874 || q->windowType() == Qt::Popup
4875 || q->windowType() == Qt::ToolTip)
4876 SetWindowGroup(windowRef, group);
4877 }
4878 }
4879
4880 // Make sure that HIWindowChangeClass didn't remove drag support
4881 // or reset the opaque size grip setting:
4882 SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true);
4883 macUpdateOpaqueSizeGrip();
4884#endif
4885}
4886
4887void QWidgetPrivate::macUpdateHideOnSuspend()
4888{
4889 Q_Q(QWidget);
4890 if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() || q->windowType() != Qt::Tool)
4891 return;
4892#ifndef QT_MAC_USE_COCOA
4893 if(q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
4894 ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowHideOnSuspendAttribute);
4895 else
4896 ChangeWindowAttributes(qt_mac_window_for(q), kWindowHideOnSuspendAttribute, 0);
4897#else
4898 if(q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
4899 [qt_mac_window_for(q) setHidesOnDeactivate:NO];
4900 else
4901 [qt_mac_window_for(q) setHidesOnDeactivate:YES];
4902#endif
4903}
4904
4905void QWidgetPrivate::macUpdateOpaqueSizeGrip()
4906{
4907 Q_Q(QWidget);
4908
4909 if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow())
4910 return;
4911
4912#ifndef QT_MAC_USE_COCOA // Growbox is always transparent on Cocoa. Can emulate with setting a QSizeGrip
4913 HIViewRef growBox;
4914 HIViewFindByID(HIViewGetRoot(qt_mac_window_for(q)), kHIViewWindowGrowBoxID, &growBox);
4915 if (!growBox)
4916 return;
4917 HIGrowBoxViewSetTransparent(growBox, !q->testAttribute(Qt::WA_MacOpaqueSizeGrip));
4918#endif
4919}
4920
4921void QWidgetPrivate::macUpdateSizeAttribute()
4922{
4923 Q_Q(QWidget);
4924 QEvent event(QEvent::MacSizeChange);
4925 QApplication::sendEvent(q, &event);
4926 for (int i = 0; i < children.size(); ++i) {
4927 QWidget *w = qobject_cast<QWidget *>(children.at(i));
4928 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
4929 && !q->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
4930 && !w->testAttribute(Qt::WA_MacSmallSize)
4931 && !w->testAttribute(Qt::WA_MacNormalSize))
4932 w->d_func()->macUpdateSizeAttribute();
4933 }
4934 resolveFont();
4935}
4936
4937void QWidgetPrivate::macUpdateIgnoreMouseEvents()
4938{
4939#ifndef QT_MAC_USE_COCOA // This is handled inside the mouse handler on Cocoa.
4940 Q_Q(QWidget);
4941 if (!q->testAttribute(Qt::WA_WState_Created))
4942 return;
4943
4944 if(q->isWindow())
4945 {
4946 if(q->testAttribute(Qt::WA_TransparentForMouseEvents))
4947 ChangeWindowAttributes(qt_mac_window_for(q), kWindowIgnoreClicksAttribute, 0);
4948 else
4949 ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowIgnoreClicksAttribute);
4950 ReshapeCustomWindow(qt_mac_window_for(q));
4951 } else {
4952#ifndef kHIViewFeatureIgnoresClicks
4953#define kHIViewFeatureIgnoresClicks kHIViewIgnoresClicks
4954#endif
4955 if(q->testAttribute(Qt::WA_TransparentForMouseEvents))
4956 HIViewChangeFeatures(qt_mac_nativeview_for(q), kHIViewFeatureIgnoresClicks, 0);
4957 else
4958 HIViewChangeFeatures(qt_mac_nativeview_for(q), 0, kHIViewFeatureIgnoresClicks);
4959 HIViewReshapeStructure(qt_mac_nativeview_for(q));
4960 }
4961#endif
4962}
4963
4964void QWidgetPrivate::macUpdateMetalAttribute()
4965{
4966 Q_Q(QWidget);
4967 bool realWindow = isRealWindow();
4968 if (!q->testAttribute(Qt::WA_WState_Created) || !realWindow)
4969 return;
4970
4971 if (realWindow) {
4972#if QT_MAC_USE_COCOA
4973 // Cocoa doesn't let us change the style mask once it's been changed
4974 // So, that means we need to recreate the window.
4975 OSWindowRef cocoaWindow = qt_mac_window_for(q);
4976 if ([cocoaWindow styleMask] & NSTexturedBackgroundWindowMask)
4977 return;
4978 recreateMacWindow();
4979#else
4980 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout *>(q->layout());
4981 if (q->testAttribute(Qt::WA_MacBrushedMetal)) {
4982 if (layout)
4983 layout->updateHIToolBarStatus();
4984 ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0);
4985 ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0);
4986 } else {
4987 ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute);
4988 ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalAttribute);
4989 if (layout)
4990 layout->updateHIToolBarStatus();
4991 }
4992#endif
4993 }
4994}
4995
4996void QWidgetPrivate::setEnabled_helper_sys(bool enable)
4997{
4998#ifdef QT_MAC_USE_COCOA
4999 Q_Q(QWidget);
5000 NSView *view = qt_mac_nativeview_for(q);
5001 if ([view isKindOfClass:[NSControl class]])
5002 [static_cast<NSControl *>(view) setEnabled:enable];
5003#else
5004 Q_UNUSED(enable);
5005#endif
5006}
5007
5008QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.