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

Last change on this file since 147 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}