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

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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