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