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

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

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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