| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| ** |
| ** Copyright (c) 2007-2008, Apple, Inc. |
| ** |
| ** All rights reserved. |
| ** |
| ** Redistribution and use in source and binary forms, with or without |
| ** modification, are permitted provided that the following conditions are met: |
| ** |
| ** * Redistributions of source code must retain the above copyright notice, |
| ** this list of conditions and the following disclaimer. |
| ** |
| ** * Redistributions in binary form must reproduce the above copyright notice, |
| ** this list of conditions and the following disclaimer in the documentation |
| ** and/or other materials provided with the distribution. |
| ** |
| ** * Neither the name of Apple, Inc. nor the names of its contributors |
| ** may be used to endorse or promote products derived from this software |
| ** without specific prior written permission. |
| ** |
| ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| ** |
| ****************************************************************************/ |
| |
| #include <private/qt_mac_p.h> |
| #include <private/qeventdispatcher_mac_p.h> |
| |
| #include "qapplication.h" |
| #include "qapplication_p.h" |
| #include "qbitmap.h" |
| #include "qcursor.h" |
| #include "qdesktopwidget.h" |
| #include "qevent.h" |
| #include "qfileinfo.h" |
| #include "qimage.h" |
| #include "qlayout.h" |
| #include "qmenubar.h" |
| #include <private/qbackingstore_p.h> |
| #include <private/qwindowsurface_mac_p.h> |
| #include <private/qpaintengine_mac_p.h> |
| #include "qpainter.h" |
| #include "qstyle.h" |
| #include "qtimer.h" |
| #include "qfocusframe.h" |
| #include "qdebug.h" |
| #include <private/qmainwindowlayout_p.h> |
| |
| #include <private/qabstractscrollarea_p.h> |
| #include <qabstractscrollarea.h> |
| #include <ApplicationServices/ApplicationServices.h> |
| #include <limits.h> |
| #include <private/qt_cocoa_helpers_mac_p.h> |
| #include <private/qcocoaview_mac_p.h> |
| #include <private/qcocoawindow_mac_p.h> |
| #include <private/qcocoawindowdelegate_mac_p.h> |
| #include <private/qcocoapanel_mac_p.h> |
| |
| #include "qwidget_p.h" |
| #include "qevent_p.h" |
| #include "qdnd_p.h" |
| #include <QtGui/qgraphicsproxywidget.h> |
| #include "qmainwindow.h" |
| |
| QT_BEGIN_NAMESPACE |
| |
| // qmainwindow.cpp |
| extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window); |
| |
| #define XCOORD_MAX 16383 |
| #define WRECT_MAX 8191 |
| |
| #ifndef QT_MAC_USE_COCOA |
| |
| extern "C" { |
| extern OSStatus _HIViewScrollRectWithOptions(HIViewRef, const HIRect *, CGFloat, CGFloat, |
| OptionBits) __attribute__ ((weak)); |
| } |
| #define kHIViewScrollRectAdjustInvalid 1 |
| #define kHIViewScrollRectDontInvalidateRevealedArea 2 |
| #endif |
| |
| |
| /***************************************************************************** |
| QWidget debug facilities |
| *****************************************************************************/ |
| //#define DEBUG_WINDOW_RGNS |
| //#define DEBUG_WINDOW_CREATE |
| //#define DEBUG_WINDOW_STATE |
| //#define DEBUG_WIDGET_PAINT |
| |
| /***************************************************************************** |
| QWidget globals |
| *****************************************************************************/ |
| #ifndef QT_MAC_USE_COCOA |
| typedef QHash<Qt::WindowFlags, WindowGroupRef> WindowGroupHash; |
| Q_GLOBAL_STATIC(WindowGroupHash, qt_mac_window_groups) |
| const UInt32 kWidgetCreatorQt = kEventClassQt; |
| enum { |
| kWidgetPropertyQWidget = 'QWId' //QWidget * |
| }; |
| #endif |
| |
| static bool qt_mac_raise_process = true; |
| static OSWindowRef qt_root_win = 0; |
| QWidget *mac_mouse_grabber = 0; |
| QWidget *mac_keyboard_grabber = 0; |
| extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp |
| |
| #ifndef QT_MAC_USE_COCOA |
| #ifdef QT_NAMESPACE |
| |
| // produce the string "com.trolltech.qt-namespace.widget", where "namespace" is the contents of QT_NAMESPACE. |
| #define SS(x) #x |
| #define S0(x) SS(x) |
| #define S "com.trolltech.qt-" S0(QT_NAMESPACE) ".widget" |
| |
| static CFStringRef kObjectQWidget = CFSTR(S); |
| |
| #undef SS |
| #undef S0 |
| #undef S |
| |
| #else |
| static CFStringRef kObjectQWidget = CFSTR("com.trolltech.qt.widget"); |
| #endif // QT_NAMESPACE |
| #endif // QT_MAC_USE_COCOA |
| |
| /***************************************************************************** |
| Externals |
| *****************************************************************************/ |
| extern QWidget *qt_mac_modal_blocked(QWidget *); //qapplication_mac.mm |
| extern void qt_event_request_activate(QWidget *); //qapplication_mac.mm |
| extern bool qt_event_remove_activate(); //qapplication_mac.mm |
| extern void qt_mac_event_release(QWidget *w); //qapplication_mac.mm |
| extern void qt_event_request_showsheet(QWidget *); //qapplication_mac.mm |
| extern void qt_event_request_window_change(QWidget *); //qapplication_mac.mm |
| extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm |
| extern IconRef qt_mac_create_iconref(const QPixmap &); //qpixmap_mac.cpp |
| extern void qt_mac_set_cursor(const QCursor *, const QPoint &); //qcursor_mac.mm |
| extern void qt_mac_update_cursor(); //qcursor_mac.mm |
| extern bool qt_nograb(); |
| extern CGImageRef qt_mac_create_cgimage(const QPixmap &, bool); //qpixmap_mac.cpp |
| extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp |
| extern QRegion qt_mac_convert_mac_region(RgnHandle rgn); //qregion_mac.cpp |
| |
| /***************************************************************************** |
| QWidget utility functions |
| *****************************************************************************/ |
| void Q_GUI_EXPORT qt_mac_set_raise_process(bool b) { qt_mac_raise_process = b; } |
| static QSize qt_mac_desktopSize() |
| { |
| int w = 0, h = 0; |
| CGDisplayCount cg_count; |
| CGGetActiveDisplayList(0, 0, &cg_count); |
| QVector<CGDirectDisplayID> displays(cg_count); |
| CGGetActiveDisplayList(cg_count, displays.data(), &cg_count); |
| Q_ASSERT(cg_count == (CGDisplayCount)displays.size()); |
| for(int i = 0; i < (int)cg_count; ++i) { |
| CGRect r = CGDisplayBounds(displays.at(i)); |
| w = qMax<int>(w, qRound(r.origin.x + r.size.width)); |
| h = qMax<int>(h, qRound(r.origin.y + r.size.height)); |
| } |
| return QSize(w, h); |
| } |
| |
| #ifdef QT_MAC_USE_COCOA |
| static NSDrawer *qt_mac_drawer_for(const QWidget *widget) |
| { |
| // This only goes one level below the content view so start with the window. |
| // This works fine for straight Qt stuff, but runs into problems if we are |
| // embedding, but if that's the case, they probably want to be using |
| // NSDrawer directly. |
| NSView *widgetView = reinterpret_cast<NSView *>(widget->window()->winId()); |
| NSArray *windows = [NSApp windows]; |
| for (NSWindow *window in windows) { |
| NSArray *drawers = [window drawers]; |
| for (NSDrawer *drawer in drawers) { |
| NSArray *views = [[drawer contentView] subviews]; |
| for (NSView *view in views) { |
| if (view == widgetView) |
| return drawer; |
| } |
| } |
| } |
| return 0; |
| } |
| #endif |
| |
| static void qt_mac_destructView(OSViewRef view) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| [view removeFromSuperview]; |
| [view release]; |
| #else |
| HIViewRemoveFromSuperview(view); |
| CFRelease(view); |
| #endif |
| } |
| |
| static void qt_mac_destructWindow(OSWindowRef window) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| if ([window isVisible] && [window isSheet]){ |
| [NSApp endSheet:window]; |
| [window orderOut:window]; |
| } |
| |
| [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForWindow:window]; |
| [window release]; |
| #else |
| // Remove property to clean up memory: |
| RemoveWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget); |
| CFRelease(window); |
| #endif |
| } |
| |
| static void qt_mac_destructDrawer(NSDrawer *drawer) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForDrawer:drawer]; |
| [drawer release]; |
| #else |
| Q_UNUSED(drawer); |
| #endif |
| } |
| |
| bool qt_mac_can_clickThrough(const QWidget *w) |
| { |
| static int qt_mac_carbon_clickthrough = -1; |
| if (qt_mac_carbon_clickthrough < 0) |
| qt_mac_carbon_clickthrough = !qgetenv("QT_MAC_NO_COCOA_CLICKTHROUGH").isEmpty(); |
| bool ret = !qt_mac_carbon_clickthrough; |
| for ( ; w; w = w->parentWidget()) { |
| if (w->testAttribute(Qt::WA_MacNoClickThrough)) { |
| ret = false; |
| break; |
| } |
| } |
| return ret; |
| } |
| |
| bool qt_mac_is_macsheet(const QWidget *w) |
| { |
| if (!w) |
| return false; |
| |
| Qt::WindowModality modality = w->windowModality(); |
| if (modality == Qt::ApplicationModal) |
| return false; |
| return w->parentWidget() && (modality == Qt::WindowModal || w->windowType() == Qt::Sheet); |
| } |
| |
| bool qt_mac_is_macdrawer(const QWidget *w) |
| { |
| return (w && w->parentWidget() && w->windowType() == Qt::Drawer); |
| } |
| |
| bool qt_mac_insideKeyWindow(const QWidget *w) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| return [[reinterpret_cast<NSView *>(w->winId()) window] isKeyWindow]; |
| #else |
| Q_UNUSED(w); |
| #endif |
| return false; |
| } |
| |
| bool qt_mac_set_drawer_preferred_edge(QWidget *w, Qt::DockWidgetArea where) //users of Qt for Mac OS X can use this.. |
| { |
| if(!qt_mac_is_macdrawer(w)) |
| return false; |
| |
| #if QT_MAC_USE_COCOA |
| NSDrawer *drawer = qt_mac_drawer_for(w); |
| if (!drawer) |
| return false; |
| NSRectEdge edge; |
| if (where & Qt::LeftDockWidgetArea) |
| edge = NSMinXEdge; |
| else if (where & Qt::RightDockWidgetArea) |
| edge = NSMaxXEdge; |
| else if (where & Qt::TopDockWidgetArea) |
| edge = NSMaxYEdge; |
| else if (where & Qt::BottomDockWidgetArea) |
| edge = NSMinYEdge; |
| else |
| return false; |
| |
| if (edge == [drawer preferredEdge]) //no-op |
| return false; |
| |
| if (w->isVisible()) { |
| [drawer close]; |
| [drawer openOnEdge:edge]; |
| } |
| [drawer setPreferredEdge:edge]; |
| #else |
| OSWindowRef window = qt_mac_window_for(w); |
| OptionBits edge; |
| if(where & Qt::LeftDockWidgetArea) |
| edge = kWindowEdgeLeft; |
| else if(where & Qt::RightDockWidgetArea) |
| edge = kWindowEdgeRight; |
| else if(where & Qt::TopDockWidgetArea) |
| edge = kWindowEdgeTop; |
| else if(where & Qt::BottomDockWidgetArea) |
| edge = kWindowEdgeBottom; |
| else |
| return false; |
| |
| if(edge == GetDrawerPreferredEdge(window)) //no-op |
| return false; |
| |
| //do it |
| SetDrawerPreferredEdge(window, edge); |
| if(w->isVisible()) { |
| CloseDrawer(window, false); |
| OpenDrawer(window, edge, true); |
| } |
| #endif |
| return true; |
| } |
| |
| #ifndef QT_MAC_USE_COCOA |
| Q_GUI_EXPORT |
| #endif |
| QPoint qt_mac_posInWindow(const QWidget *w) |
| { |
| QPoint ret = w->data->wrect.topLeft(); |
| while(w && !w->isWindow()) { |
| ret += w->pos(); |
| w = w->parentWidget(); |
| } |
| return ret; |
| } |
| |
| //find a QWidget from a OSWindowRef |
| QWidget *qt_mac_find_window(OSWindowRef window) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| return [window QT_MANGLE_NAMESPACE(qt_qwidget)]; |
| #else |
| if(!window) |
| return 0; |
| |
| QWidget *ret; |
| if(GetWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(ret), 0, &ret) == noErr) |
| return ret; |
| return 0; |
| #endif |
| } |
| |
| inline static void qt_mac_set_fullscreen_mode(bool b) |
| { |
| extern bool qt_mac_app_fullscreen; //qapplication_mac.mm |
| if(qt_mac_app_fullscreen == b) |
| return; |
| qt_mac_app_fullscreen = b; |
| if (b) { |
| SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); |
| } else { |
| SetSystemUIMode(kUIModeNormal, 0); |
| } |
| } |
| |
| Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w) |
| { |
| return reinterpret_cast<OSViewRef>(w->data->winid); |
| } |
| |
| Q_GUI_EXPORT OSViewRef qt_mac_get_contentview_for(OSWindowRef w) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| return [w contentView]; |
| #else |
| HIViewRef contentView = 0; |
| OSStatus err = GetRootControl(w, &contentView); // Returns the window's content view (Apple QA1214) |
| if (err == errUnknownControl) { |
| contentView = HIViewGetRoot(w); |
| } else if (err != noErr) { |
| qWarning("Qt:Could not get content or root view of window! %s:%d [%ld]", |
| __FILE__, __LINE__, err); |
| } |
| return contentView; |
| #endif |
| } |
| |
| bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref) |
| { |
| return widget->macEvent(0, ref); |
| } |
| |
| Q_GUI_EXPORT OSWindowRef qt_mac_window_for(OSViewRef view) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| if (view) |
| return [view window]; |
| return 0; |
| #else |
| return HIViewGetWindow(view); |
| #endif |
| } |
| |
| static bool qt_isGenuineQWidget(OSViewRef ref) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| return [ref isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]; |
| #else |
| return HIObjectIsOfClass(HIObjectRef(ref), kObjectQWidget); |
| #endif |
| } |
| |
| bool qt_isGenuineQWidget(const QWidget *window) |
| { |
| if (!window) |
| return false; |
| |
| if (!window->internalWinId()) |
| return true; //alien |
| |
| return qt_isGenuineQWidget(OSViewRef(window->internalWinId())); |
| } |
| |
| Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w) |
| { |
| OSViewRef hiview = qt_mac_nativeview_for(w); |
| if (hiview){ |
| OSWindowRef window = qt_mac_window_for(hiview); |
| if (!window && qt_isGenuineQWidget(hiview)) { |
| QWidget *myWindow = w->window(); |
| // This is a workaround for NSToolbar. When a widget is hidden |
| // by clicking the toolbar button, Cocoa reparents the widgets |
| // to another window (but Qt doesn't know about it). |
| // When we start showing them, it reparents back, |
| // but at this point it's window is nil, but the window it's being brought |
| // into (the Qt one) is for sure created. |
| // This stops the hierarchy moving under our feet. |
| if (myWindow != w && qt_mac_window_for(qt_mac_nativeview_for(myWindow))) |
| return qt_mac_window_for(qt_mac_nativeview_for(myWindow)); |
| |
| myWindow->d_func()->createWindow_sys(); |
| // Reget the hiview since the "create window could potentially move the view (I guess). |
| hiview = qt_mac_nativeview_for(w); |
| window = qt_mac_window_for(hiview); |
| } |
| return window; |
| } |
| return 0; |
| } |
| #ifndef QT_MAC_USE_COCOA |
| /* Checks if the current group is a 'stay on top' group. If so, the |
| group gets removed from the hash table */ |
| static void qt_mac_release_stays_on_top_group(WindowGroupRef group) |
| { |
| for (WindowGroupHash::iterator it = qt_mac_window_groups()->begin(); it != qt_mac_window_groups()->end(); ++it) { |
| if (it.value() == group) { |
| qt_mac_window_groups()->remove(it.key()); |
| return; |
| } |
| } |
| } |
| |
| /* Use this function instead of ReleaseWindowGroup, this will be sure to release the |
| stays on top window group (created with qt_mac_get_stays_on_top_group below) */ |
| static void qt_mac_release_window_group(WindowGroupRef group) |
| { |
| ReleaseWindowGroup(group); |
| if (GetWindowGroupRetainCount(group) == 0) |
| qt_mac_release_stays_on_top_group(group); |
| } |
| #define ReleaseWindowGroup(x) Are you sure you wanted to do that? (you wanted qt_mac_release_window_group) |
| |
| SInt32 qt_mac_get_group_level(WindowClass wclass) |
| { |
| SInt32 group_level; |
| CGWindowLevel tmpLevel; |
| GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel); |
| group_level = tmpLevel; |
| return group_level; |
| } |
| #endif |
| |
| #ifndef QT_MAC_USE_COCOA |
| static void qt_mac_set_window_group(OSWindowRef window, Qt::WindowFlags flags, int level) |
| { |
| WindowGroupRef group = 0; |
| if (qt_mac_window_groups()->contains(flags)) { |
| group = qt_mac_window_groups()->value(flags); |
| RetainWindowGroup(group); |
| } else { |
| CreateWindowGroup(kWindowActivationScopeNone, &group); |
| SetWindowGroupLevel(group, level); |
| SetWindowGroupParent(group, GetWindowGroupOfClass(kAllWindowClasses)); |
| qt_mac_window_groups()->insert(flags, group); |
| } |
| SetWindowGroup(window, group); |
| } |
| |
| inline static void qt_mac_set_window_group_to_stays_on_top(OSWindowRef window, Qt::WindowType type) |
| { |
| // We create one static stays on top window group so that |
| // all stays on top (aka popups) will fall into the same |
| // group and be able to be raise()'d with releation to one another (from |
| // within the same window group). |
| qt_mac_set_window_group(window, type|Qt::WindowStaysOnTopHint, qt_mac_get_group_level(kOverlayWindowClass)); |
| } |
| |
| inline static void qt_mac_set_window_group_to_tooltip(OSWindowRef window) |
| { |
| // Since new groups are created for 'stays on top' windows, the |
| // same must be done for tooltips. Otherwise, tooltips would be drawn |
| // below 'stays on top' widgets even tough they are on the same level. |
| // Also, add 'two' to the group level to make sure they also get on top of popups. |
| qt_mac_set_window_group(window, Qt::ToolTip, qt_mac_get_group_level(kHelpWindowClass)+2); |
| } |
| |
| inline static void qt_mac_set_window_group_to_popup(OSWindowRef window) |
| { |
| // In Qt, a popup is seen as a 'stay on top' window. |
| // Since new groups are created for 'stays on top' windows, the |
| // same must be done for popups. Otherwise, popups would be drawn |
| // below 'stays on top' windows. Add 1 to get above pure stay-on-top windows. |
| qt_mac_set_window_group(window, Qt::Popup, qt_mac_get_group_level(kOverlayWindowClass)+1); |
| } |
| #endif |
| |
| #ifdef QT_MAC_USE_COCOA |
| void qt_mac_set_needs_display(QWidget *widget, QRegion region) |
| { |
| NSView *theNSView = qt_mac_nativeview_for(widget); |
| if (region.isEmpty()) { |
| [theNSView setNeedsDisplay:YES]; |
| return; |
| } |
| |
| QVector<QRect> rects = region.rects(); |
| for (int i = 0; i<rects.count(); ++i) { |
| const QRect &rect = rects.at(i); |
| NSRect nsrect = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); |
| [theNSView setNeedsDisplayInRect:nsrect]; |
| } |
| |
| } |
| #endif |
| |
| inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRect &rect) |
| { |
| if (!widget) |
| return false; |
| |
| #ifndef QT_NO_GRAPHICSVIEW |
| QWidget *tlw = widget->window(); |
| QWExtra *extra = qt_widget_private(tlw)->extra; |
| if (extra && extra->proxyWidget) { |
| extra->proxyWidget->update(rect.translated(widget->mapTo(tlw, QPoint()))); |
| return true; |
| } |
| #endif |
| |
| return false; |
| } |
| |
| inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRegion &rgn) |
| { |
| if (!widget) |
| return false; |
| |
| #ifndef QT_NO_GRAPHICSVIEW |
| QWidget *tlw = widget->window(); |
| QWExtra *extra = qt_widget_private(tlw)->extra; |
| if (extra && extra->proxyWidget) { |
| const QPoint offset(widget->mapTo(tlw, QPoint())); |
| const QVector<QRect> rects = rgn.rects(); |
| for (int i = 0; i < rects.size(); ++i) |
| extra->proxyWidget->update(rects.at(i).translated(offset)); |
| return true; |
| } |
| #endif |
| |
| return false; |
| } |
| |
| void QWidgetPrivate::macUpdateIsOpaque() |
| { |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; |
| #ifndef QT_MAC_USE_COCOA |
| HIViewFeatures bits; |
| HIViewRef hiview = qt_mac_nativeview_for(q); |
| HIViewGetFeatures(hiview, &bits); |
| if ((bits & kHIViewIsOpaque) == isOpaque) |
| return; |
| if (isOpaque) { |
| HIViewChangeFeatures(hiview, kHIViewIsOpaque, 0); |
| } else { |
| HIViewChangeFeatures(hiview, 0, kHIViewIsOpaque); |
| } |
| if (q->isVisible()) |
| HIViewReshapeStructure(qt_mac_nativeview_for(q)); |
| #else |
| if (isRealWindow() && !q->testAttribute(Qt::WA_MacBrushedMetal)) { |
| bool opaque = isOpaque; |
| if (extra && extra->imageMask) |
| opaque = false; // we are never opaque when we have a mask. |
| [qt_mac_window_for(q) setOpaque:opaque]; |
| } |
| #endif |
| } |
| #ifdef QT_MAC_USE_COCOA |
| static OSWindowRef qt_mac_create_window(QWidget *widget, WindowClass wclass, |
| NSUInteger wattr, const QRect &crect) |
| { |
| // Determine if we need to add in our "custom window" attribute. Cocoa is rather clever |
| // in deciding if we need the maximize button or not (i.e., it's resizeable, so you |
| // must need a maximize button). So, the only buttons we have control over are the |
| // close and minimize buttons. If someone wants to customize and NOT have the maximize |
| // button, then we have to do our hack. We only do it for these cases because otherwise |
| // the window looks different when activated. This "QtMacCustomizeWindow" attribute is |
| // intruding on a public space and WILL BREAK in the future. |
| // One can hope that there is a more public API available by that time. |
| Qt::WindowFlags flags = widget ? widget->windowFlags() : Qt::WindowFlags(0); |
| if ((flags & Qt::CustomizeWindowHint)) { |
| if ((flags & (Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint |
| | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint)) |
| && !(flags & Qt::WindowMaximizeButtonHint)) |
| wattr |= QtMacCustomizeWindow; |
| } |
| |
| // If we haven't created the desktop widget, you have to pass the rectangle |
| // in "cocoa coordinates" (i.e., top points to the lower left coordinate). |
| // Otherwise, we do the conversion for you. Since we are the only ones that |
| // create the desktop widget, this is OK (but confusing). |
| NSRect geo = NSMakeRect(crect.left(), |
| (qt_root_win != 0) ? flipYCoordinate(crect.bottom() + 1) : crect.top(), |
| crect.width(), crect.height()); |
| QMacCocoaAutoReleasePool pool; |
| OSWindowRef window; |
| switch (wclass) { |
| case kMovableModalWindowClass: |
| case kModalWindowClass: |
| case kSheetWindowClass: |
| case kFloatingWindowClass: |
| case kOverlayWindowClass: |
| case kHelpWindowClass: { |
| NSPanel *panel; |
| BOOL needFloating = NO; |
| BOOL worksWhenModal = widget && (widget->windowType() == Qt::Popup); |
| // Add in the extra flags if necessary. |
| switch (wclass) { |
| case kSheetWindowClass: |
| wattr |= NSDocModalWindowMask; |
| break; |
| case kFloatingWindowClass: |
| case kHelpWindowClass: |
| needFloating = YES; |
| wattr |= NSUtilityWindowMask; |
| break; |
| default: |
| break; |
| } |
| panel = [[QT_MANGLE_NAMESPACE(QCocoaPanel) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr]; |
| [panel setFloatingPanel:needFloating]; |
| [panel setWorksWhenModal:worksWhenModal]; |
| window = panel; |
| break; |
| } |
| case kDrawerWindowClass: { |
| NSDrawer *drawer = [[NSDrawer alloc] initWithContentSize:geo.size preferredEdge:NSMinXEdge]; |
| [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] becomeDelegateForDrawer:drawer widget:widget]; |
| QWidget *parentWidget = widget->parentWidget(); |
| if (parentWidget) |
| [drawer setParentWindow:qt_mac_window_for(parentWidget)]; |
| [drawer setLeadingOffset:0.0]; |
| [drawer setTrailingOffset:25.0]; |
| window = [[drawer contentView] window]; // Just to make sure we actually return a window |
| break; |
| } |
| default: |
| window = [[QT_MANGLE_NAMESPACE(QCocoaWindow) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr]; |
| break; |
| } |
| qt_syncCocoaTitleBarButtons(window, widget); |
| return window; |
| } |
| #else |
| static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAttributes wattr, |
| const QRect &crect) |
| { |
| OSWindowRef window; |
| Rect geo; |
| SetRect(&geo, crect.left(), crect.top(), crect.right() + 1, crect.bottom() + 1); |
| OSStatus err; |
| if(geo.right <= geo.left) geo.right = geo.left + 1; |
| if(geo.bottom <= geo.top) geo.bottom = geo.top + 1; |
| Rect null_rect; |
| SetRect(&null_rect, 0, 0, 1, 1); |
| err = CreateNewWindow(wclass, wattr, &null_rect, &window); |
| if(err == noErr) { |
| err = SetWindowBounds(window, kWindowContentRgn, &geo); |
| if(err != noErr) |
| qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__); |
| } |
| return window; |
| } |
| |
| #ifndef QT_NO_GESTURES |
| #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 |
| /* We build the release package against the 10.4 SDK. |
| So, to enable gestures for applications running on |
| 10.6+, we define the missing constants here: */ |
| enum { |
| kEventClassGesture = 'gest', |
| kEventGestureStarted = 1, |
| kEventGestureEnded = 2, |
| kEventGestureMagnify = 4, |
| kEventGestureSwipe = 5, |
| kEventGestureRotate = 6, |
| kEventParamRotationAmount = 'rota', |
| kEventParamSwipeDirection = 'swip', |
| kEventParamMagnificationAmount = 'magn' |
| }; |
| #endif |
| #endif // QT_NO_GESTURES |
| |
| // window events |
| static EventTypeSpec window_events[] = { |
| { kEventClassWindow, kEventWindowClose }, |
| { kEventClassWindow, kEventWindowExpanded }, |
| { kEventClassWindow, kEventWindowHidden }, |
| { kEventClassWindow, kEventWindowZoom }, |
| { kEventClassWindow, kEventWindowZoomed }, |
| { kEventClassWindow, kEventWindowCollapsed }, |
| { kEventClassWindow, kEventWindowToolbarSwitchMode }, |
| { kEventClassWindow, kEventWindowProxyBeginDrag }, |
| { kEventClassWindow, kEventWindowProxyEndDrag }, |
| { kEventClassWindow, kEventWindowResizeCompleted }, |
| { kEventClassWindow, kEventWindowBoundsChanging }, |
| { kEventClassWindow, kEventWindowGetRegion }, |
| { kEventClassWindow, kEventWindowGetClickModality }, |
| { kEventClassWindow, kEventWindowTransitionCompleted }, |
| { kEventClassGesture, kEventGestureStarted }, |
| { kEventClassGesture, kEventGestureEnded }, |
| { kEventClassGesture, kEventGestureMagnify }, |
| { kEventClassGesture, kEventGestureSwipe }, |
| { kEventClassGesture, kEventGestureRotate }, |
| { kEventClassMouse, kEventMouseDown } |
| }; |
| static EventHandlerUPP mac_win_eventUPP = 0; |
| static void cleanup_win_eventUPP() |
| { |
| DisposeEventHandlerUPP(mac_win_eventUPP); |
| mac_win_eventUPP = 0; |
| } |
| static const EventHandlerUPP make_win_eventUPP() |
| { |
| if(mac_win_eventUPP) |
| return mac_win_eventUPP; |
| qAddPostRoutine(cleanup_win_eventUPP); |
| return mac_win_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_window_event); |
| } |
| OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, void *) |
| { |
| QScopedLoopLevelCounter loopLevelCounter(qApp->d_func()->threadData); |
| bool handled_event = true; |
| UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); |
| switch(eclass) { |
| case kEventClassWindow: { |
| WindowRef wid = 0; |
| GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, |
| sizeof(WindowRef), 0, &wid); |
| QWidget *widget = qt_mac_find_window(wid); |
| if(!widget) { |
| handled_event = false; |
| } else if(ekind == kEventWindowGetClickModality) { |
| // Carbon will send us kEventWindowGetClickModality before every |
| // mouse press / release event. By returning 'true', we tell Carbon |
| // that we would like the event target to receive the mouse event even |
| // if the target is modally shaddowed. In Qt, this makes sense when we |
| // e.g. have a popup showing, as the popup will grab the event |
| // and perhaps use it to close itself. |
| // By also setting the current modal window back into the event, we |
| // help Carbon determining which window is supposed to be raised. |
| handled_event = qApp->activePopupWidget() ? true : false; |
| } else if(ekind == kEventWindowClose) { |
| widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); |
| QMenuBar::macUpdateMenuBar(); |
| } else if (ekind == kEventWindowTransitionCompleted) { |
| WindowTransitionAction transitionAction; |
| GetEventParameter(event, kEventParamWindowTransitionAction, typeWindowTransitionAction, |
| 0, sizeof(transitionAction), 0, &transitionAction); |
| if (transitionAction == kWindowHideTransitionAction) |
| widget->hide(); |
| } else if(ekind == kEventWindowExpanded) { |
| Qt::WindowStates currState = Qt::WindowStates(widget->data->window_state); |
| Qt::WindowStates newState = currState; |
| if (currState & Qt::WindowMinimized) |
| newState &= ~Qt::WindowMinimized; |
| if (!(currState & Qt::WindowActive)) |
| newState |= Qt::WindowActive; |
| if (newState != currState) { |
| // newState will differ from currState if the window |
| // was expanded after clicking on the jewels (as opposed |
| // to calling QWidget::setWindowState) |
| widget->data->window_state = newState; |
| QWindowStateChangeEvent e(currState); |
| QApplication::sendSpontaneousEvent(widget, &e); |
| } |
| |
| QShowEvent qse; |
| QApplication::sendSpontaneousEvent(widget, &qse); |
| } else if(ekind == kEventWindowZoom) { |
| widget->d_func()->topData()->normalGeometry = widget->geometry(); |
| handled_event = false; |
| } else if(ekind == kEventWindowZoomed) { |
| WindowPartCode windowPart; |
| GetEventParameter(event, kEventParamWindowPartCode, |
| typeWindowPartCode, 0, sizeof(windowPart), 0, &windowPart); |
| if(windowPart == inZoomIn && widget->isMaximized()) { |
| |
| widget->data->window_state = widget->data->window_state & ~Qt::WindowMaximized; |
| QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state | Qt::WindowMaximized)); |
| QApplication::sendSpontaneousEvent(widget, &e); |
| } else if(windowPart == inZoomOut && !widget->isMaximized()) { |
| widget->data->window_state = widget->data->window_state | Qt::WindowMaximized; |
| QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state |
| & ~Qt::WindowMaximized)); |
| QApplication::sendSpontaneousEvent(widget, &e); |
| } |
| qt_button_down = 0; |
| } else if(ekind == kEventWindowCollapsed) { |
| if (!widget->isMinimized()) { |
| widget->data->window_state = widget->data->window_state | Qt::WindowMinimized; |
| QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state & ~Qt::WindowMinimized)); |
| QApplication::sendSpontaneousEvent(widget, &e); |
| } |
| |
| // Deactivate this window: |
| if (widget->isActiveWindow() && !(widget->windowType() == Qt::Popup)) { |
| QWidget *w = 0; |
| if (widget->parentWidget()) |
| w = widget->parentWidget()->window(); |
| if (!w || (!w->isVisible() && !w->isMinimized())) { |
| for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true); |
| wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) { |
| if ((w = qt_mac_find_window(wp))) |
| break; |
| } |
| } |
| if(!(w && w->isVisible() && !w->isMinimized())) |
| qApp->setActiveWindow(0); |
| } |
| |
| //we send a hide to be like X11/Windows |
| QEvent e(QEvent::Hide); |
| QApplication::sendSpontaneousEvent(widget, &e); |
| qt_button_down = 0; |
| } else if(ekind == kEventWindowToolbarSwitchMode) { |
| macSendToolbarChangeEvent(widget); |
| HIToolbarRef toolbar; |
| if (GetWindowToolbar(wid, &toolbar) == noErr) { |
| if (toolbar) { |
| // Let HIToolbar do its thang, but things like the OpenGL context |
| // needs to know about it. |
| CallNextEventHandler(er, event); |
| qt_event_request_window_change(widget); |
| widget->data->fstrut_dirty = true; |
| } |
| } |
| } else if(ekind == kEventWindowGetRegion) { |
| WindowRef window; |
| GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, |
| sizeof(window), 0, &window); |
| WindowRegionCode wcode; |
| GetEventParameter(event, kEventParamWindowRegionCode, typeWindowRegionCode, 0, |
| sizeof(wcode), 0, &wcode); |
| if (wcode != kWindowOpaqueRgn){ |
| // If the region is kWindowOpaqueRgn, don't call next |
| // event handler cause this will make the shadow of |
| // masked windows become offset. Unfortunately, we're not sure why. |
| CallNextEventHandler(er, event); |
| } |
| RgnHandle rgn; |
| GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0, |
| sizeof(rgn), 0, &rgn); |
| |
| if(QWidgetPrivate::qt_widget_rgn(qt_mac_find_window(window), wcode, rgn, false)) |
| SetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, sizeof(rgn), &rgn); |
| } else if(ekind == kEventWindowProxyBeginDrag) { |
| QIconDragEvent e; |
| QApplication::sendSpontaneousEvent(widget, &e); |
| } else if(ekind == kEventWindowResizeCompleted) { |
| // Create a mouse up event, since such an event is not send by carbon to the |
| // application event handler (while a mouse down <b>is</b> on kEventWindowResizeStarted) |
| EventRef mouseUpEvent; |
| CreateEvent(0, kEventClassMouse, kEventMouseUp, 0, kEventAttributeUserEvent, &mouseUpEvent); |
| UInt16 mbutton = kEventMouseButtonPrimary; |
| SetEventParameter(mouseUpEvent, kEventParamMouseButton, typeMouseButton, sizeof(mbutton), &mbutton); |
| WindowRef window; |
| GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, sizeof(window), 0, &window); |
| Rect dragRect; |
| GetWindowBounds(window, kWindowGrowRgn, &dragRect); |
| Point pos = {dragRect.bottom, dragRect.right}; |
| SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos); |
| SendEventToApplication(mouseUpEvent); |
| ReleaseEvent(mouseUpEvent); |
| } else if(ekind == kEventWindowBoundsChanging) { |
| UInt32 flags = 0; |
| GetEventParameter(event, kEventParamAttributes, typeUInt32, 0, |
| sizeof(flags), 0, &flags); |
| Rect nr; |
| GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0, |
| sizeof(nr), 0, &nr); |
| |
| QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top); |
| |
| QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData(); |
| if (tlwExtra && tlwExtra->isSetGeometry == 1) { |
| widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove); |
| } else { |
| //implicitly removes the maximized bit |
| if((widget->data->window_state & Qt::WindowMaximized) && |
| IsWindowInStandardState(wid, 0, 0)) { |
| widget->data->window_state &= ~Qt::WindowMaximized; |
| QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state |
| | Qt::WindowMaximized)); |
| QApplication::sendSpontaneousEvent(widget, &e); |
| |
| } |
| |
| handled_event = false; |
| const QRect oldRect = widget->data->crect; |
| if((flags & kWindowBoundsChangeOriginChanged)) { |
| if(nr.left != oldRect.x() || nr.top != oldRect.y()) { |
| widget->data->crect.moveTo(nr.left, nr.top); |
| QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft()); |
| QApplication::sendSpontaneousEvent(widget, &qme); |
| } |
| } |
| if((flags & kWindowBoundsChangeSizeChanged)) { |
| if (widget->isWindow()) { |
| QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size()); |
| int dh = newSize.height() - newRect.height(); |
| int dw = newSize.width() - newRect.width(); |
| if (dw != 0 || dh != 0) { |
| handled_event = true; // We want to change the bounds, so we handle the event |
| |
| // set the rect, so we can also do the resize down below (yes, we need to resize). |
| newRect.setBottom(newRect.bottom() + dh); |
| newRect.setRight(newRect.right() + dw); |
| |
| nr.left = newRect.x(); |
| nr.top = newRect.y(); |
| nr.right = nr.left + newRect.width(); |
| nr.bottom = nr.top + newRect.height(); |
| SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr); |
| } |
| } |
| |
| if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) { |
| widget->data->crect.setSize(newRect.size()); |
| HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height()); |
| |
| // If the WA_StaticContents attribute is set we can optimize the resize |
| // by only repainting the newly exposed area. We do this by disabling |
| // painting when setting the size of the view. The OS will invalidate |
| // the newly exposed area for us. |
| const bool staticContents = widget->testAttribute(Qt::WA_StaticContents); |
| const HIViewRef view = qt_mac_nativeview_for(widget); |
| if (staticContents) |
| HIViewSetDrawingEnabled(view, false); |
| HIViewSetFrame(view, &bounds); |
| if (staticContents) |
| HIViewSetDrawingEnabled(view, true); |
| |
| QResizeEvent qre(newRect.size(), oldRect.size()); |
| QApplication::sendSpontaneousEvent(widget, &qre); |
| qt_event_request_window_change(widget); |
| } |
| } |
| } |
| } else if (ekind == kEventWindowHidden) { |
| // Make sure that we also hide any visible sheets on our window. |
| // Cocoa does the right thing for us. |
| const QObjectList children = widget->children(); |
| const int childCount = children.count(); |
| for (int i = 0; i < childCount; ++i) { |
| QObject *obj = children.at(i); |
| if (obj->isWidgetType()) { |
| QWidget *widget = static_cast<QWidget *>(obj); |
| if (qt_mac_is_macsheet(widget) && widget->isVisible()) |
| widget->hide(); |
| } |
| } |
| } else { |
| handled_event = false; |
| } |
| break; } |
| case kEventClassMouse: { |
| #if 0 |
| return SendEventToApplication(event); |
| #endif |
| |
| bool send_to_app = false; |
| { |
| WindowPartCode wpc; |
| if (GetEventParameter(event, kEventParamWindowPartCode, typeWindowPartCode, 0, |
| sizeof(wpc), 0, &wpc) == noErr && wpc != inContent) |
| send_to_app = true; |
| } |
| if(!send_to_app) { |
| WindowRef window; |
| if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0, |
| sizeof(window), 0, &window) == noErr) { |
| HIViewRef hiview; |
| if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) { |
| if(QWidget *w = QWidget::find((WId)hiview)) { |
| #if 0 |
| send_to_app = !w->isActiveWindow(); |
| #else |
| Q_UNUSED(w); |
| send_to_app = true; |
| #endif |
| } |
| } |
| } |
| } |
| if(send_to_app) |
| return SendEventToApplication(event); |
| handled_event = false; |
| break; } |
| |
| #ifndef QT_NO_GESTURES |
| case kEventClassGesture: { |
| // First, find the widget that was under |
| // the mouse when the gesture happened: |
| HIPoint screenLocation; |
| if (GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0, |
| sizeof(screenLocation), 0, &screenLocation) != noErr) { |
| handled_event = false; |
| break; |
| } |
| QWidget *widget = QApplication::widgetAt(screenLocation.x, screenLocation.y); |
| if (!widget) { |
| handled_event = false; |
| break; |
| } |
| |
| QNativeGestureEvent qNGEvent; |
| qNGEvent.position = QPoint(screenLocation.x, screenLocation.y); |
| |
| switch (ekind) { |
| case kEventGestureStarted: |
| qNGEvent.gestureType = QNativeGestureEvent::GestureBegin; |
| break; |
| case kEventGestureEnded: |
| qNGEvent.gestureType = QNativeGestureEvent::GestureEnd; |
| break; |
| case kEventGestureRotate: { |
| CGFloat amount; |
| if (GetEventParameter(event, kEventParamRotationAmount, 'cgfl', 0, |
| sizeof(amount), 0, &amount) != noErr) { |
| handled_event = false; |
| break; |
| } |
| qNGEvent.gestureType = QNativeGestureEvent::Rotate; |
| qNGEvent.percentage = float(-amount); |
| break; } |
| case kEventGestureSwipe: { |
| HIPoint swipeDirection; |
| if (GetEventParameter(event, kEventParamSwipeDirection, typeHIPoint, 0, |
| sizeof(swipeDirection), 0, &swipeDirection) != noErr) { |
| handled_event = false; |
| break; |
| } |
| qNGEvent.gestureType = QNativeGestureEvent::Swipe; |
| if (swipeDirection.x == 1) |
| qNGEvent.angle = 180.0f; |
| else if (swipeDirection.x == -1) |
| qNGEvent.angle = 0.0f; |
| else if (swipeDirection.y == 1) |
| qNGEvent.angle = 90.0f; |
| else if (swipeDirection.y == -1) |
| qNGEvent.angle = 270.0f; |
| break; } |
| case kEventGestureMagnify: { |
| CGFloat amount; |
| if (GetEventParameter(event, kEventParamMagnificationAmount, 'cgfl', 0, |
| sizeof(amount), 0, &amount) != noErr) { |
| handled_event = false; |
| break; |
| } |
| qNGEvent.gestureType = QNativeGestureEvent::Zoom; |
| qNGEvent.percentage = float(amount); |
| break; } |
| } |
| |
| QApplication::sendSpontaneousEvent(widget, &qNGEvent); |
| break; } |
| #endif // QT_NO_GESTURES |
| |
| default: |
| handled_event = false; |
| } |
| if(!handled_event) //let the event go through |
| return eventNotHandledErr; |
| return noErr; //we eat the event |
| } |
| |
| // widget events |
| static HIObjectClassRef widget_class = 0; |
| static EventTypeSpec widget_events[] = { |
| { kEventClassHIObject, kEventHIObjectConstruct }, |
| { kEventClassHIObject, kEventHIObjectDestruct }, |
| |
| { kEventClassControl, kEventControlDraw }, |
| { kEventClassControl, kEventControlInitialize }, |
| { kEventClassControl, kEventControlGetPartRegion }, |
| { kEventClassControl, kEventControlGetClickActivation }, |
| { kEventClassControl, kEventControlSetFocusPart }, |
| { kEventClassControl, kEventControlDragEnter }, |
| { kEventClassControl, kEventControlDragWithin }, |
| { kEventClassControl, kEventControlDragLeave }, |
| { kEventClassControl, kEventControlDragReceive }, |
| { kEventClassControl, kEventControlOwningWindowChanged }, |
| { kEventClassControl, kEventControlBoundsChanged }, |
| { kEventClassControl, kEventControlGetSizeConstraints }, |
| { kEventClassControl, kEventControlVisibilityChanged }, |
| |
| { kEventClassMouse, kEventMouseDown }, |
| { kEventClassMouse, kEventMouseUp }, |
| { kEventClassMouse, kEventMouseMoved }, |
| { kEventClassMouse, kEventMouseDragged } |
| }; |
| static EventHandlerUPP mac_widget_eventUPP = 0; |
| static void cleanup_widget_eventUPP() |
| { |
| DisposeEventHandlerUPP(mac_widget_eventUPP); |
| mac_widget_eventUPP = 0; |
| } |
| static const EventHandlerUPP make_widget_eventUPP() |
| { |
| if(mac_widget_eventUPP) |
| return mac_widget_eventUPP; |
| qAddPostRoutine(cleanup_widget_eventUPP); |
| return mac_widget_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_widget_event); |
| } |
| OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, void *) |
| { |
| QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); |
| |
| bool handled_event = true; |
| UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); |
| switch(eclass) { |
| case kEventClassHIObject: { |
| HIViewRef view = 0; |
| GetEventParameter(event, kEventParamHIObjectInstance, typeHIObjectRef, |
| 0, sizeof(view), 0, &view); |
| if(ekind == kEventHIObjectConstruct) { |
| if(view) { |
| HIViewChangeFeatures(view, kHIViewAllowsSubviews, 0); |
| SetEventParameter(event, kEventParamHIObjectInstance, |
| typeVoidPtr, sizeof(view), &view); |
| } |
| } else if(ekind == kEventHIObjectDestruct) { |
| //nothing to really do.. or is there? |
| } else { |
| handled_event = false; |
| } |
| break; } |
| case kEventClassControl: { |
| QWidget *widget = 0; |
| HIViewRef hiview = 0; |
| if(GetEventParameter(event, kEventParamDirectObject, typeControlRef, |
| 0, sizeof(hiview), 0, &hiview) == noErr) |
| widget = QWidget::find((WId)hiview); |
| if (widget && widget->macEvent(er, event)) |
| return noErr; |
| if(ekind == kEventControlDraw) { |
| if(widget && qt_isGenuineQWidget(hiview)) { |
| |
| // if there is a window change event pending for any gl child wigets, |
| // send it immediately. (required for flicker-free resizing) |
| extern void qt_mac_send_posted_gl_updates(QWidget *widget); |
| qt_mac_send_posted_gl_updates(widget); |
| |
| if (QApplicationPrivate::graphicsSystem() && !widget->d_func()->paintOnScreen()) { |
| widget->d_func()->syncBackingStore(); |
| widget->d_func()->dirtyOnWidget = QRegion(); |
| return noErr; |
| } |
| |
| //requested rgn |
| RgnHandle rgn; |
| GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0, sizeof(rgn), 0, &rgn); |
| QRegion qrgn(qt_mac_convert_mac_region(rgn)); |
| |
| //update handles |
| GrafPtr qd = 0; |
| CGContextRef cg = 0; |
| if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) { |
| Q_ASSERT(false); |
| } |
| widget->d_func()->hd = cg; |
| widget->d_func()->qd_hd = qd; |
| CGContextSaveGState(cg); |
| |
| #ifdef DEBUG_WIDGET_PAINT |
| const bool doDebug = true; |
| if(doDebug) { |
| qDebug("asked to draw %p[%p] [%s::%s] %p[%p] [%d] [%dx%d]", widget, hiview, widget->metaObject()->className(), |
| widget->objectName().local8Bit().data(), widget->parentWidget(), |
| (HIViewRef)(widget->parentWidget() ? qt_mac_nativeview_for(widget->parentWidget()) : (HIViewRef)0), |
| HIViewIsCompositingEnabled(hiview), qt_mac_posInWindow(widget).x(), qt_mac_posInWindow(widget).y()); |
| #if 0 |
| QVector<QRect> region_rects = qrgn.rects(); |
| qDebug("Region! %d", region_rects.count()); |
| for(int i = 0; i < region_rects.count(); i++) |
| qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(), |
| region_rects[i].width(), region_rects[i].height()); |
| region_rects = widget->d_func()->clp.rects(); |
| qDebug("Widget Region! %d", region_rects.count()); |
| for(int i = 0; i < region_rects.count(); i++) |
| qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(), |
| region_rects[i].width(), region_rects[i].height()); |
| #endif |
| } |
| #endif |
| if (widget->isVisible() && widget->updatesEnabled()) { //process the actual paint event. |
| if(widget->testAttribute(Qt::WA_WState_InPaintEvent)) |
| qWarning("QWidget::repaint: Recursive repaint detected"); |
| if (widget->isWindow() && !widget->d_func()->isOpaque |
| && !widget->testAttribute(Qt::WA_MacBrushedMetal)) { |
| QRect qrgnRect = qrgn.boundingRect(); |
| CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height())); |
| } |
| |
| QPoint redirectionOffset(0, 0); |
| QWidget *tl = widget->window(); |
| if (tl) { |
| Qt::WindowFlags flags = tl->windowFlags(); |
| if (flags & Qt::FramelessWindowHint |
| || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint))) { |
| if(tl->d_func()->extra && !tl->d_func()->extra->mask.isEmpty()) |
| redirectionOffset += tl->d_func()->extra->mask.boundingRect().topLeft(); |
| } |
| } |
| |
| //setup the context |
| widget->setAttribute(Qt::WA_WState_InPaintEvent); |
| QPaintEngine *engine = widget->paintEngine(); |
| if (engine) |
| engine->setSystemClip(qrgn); |
| |
| //handle the erase |
| if (engine && (!widget->testAttribute(Qt::WA_NoSystemBackground) |
| && (widget->isWindow() || widget->autoFillBackground()) |
| || widget->testAttribute(Qt::WA_TintedBackground) |
| || widget->testAttribute(Qt::WA_StyledBackground))) { |
| #ifdef DEBUG_WIDGET_PAINT |
| if(doDebug) |
| qDebug(" Handling erase for [%s::%s]", widget->metaObject()->className(), |
| widget->objectName().local8Bit().data()); |
| #endif |
| if (!redirectionOffset.isNull()) |
| widget->d_func()->setRedirected(widget, redirectionOffset); |
| |
| bool was_unclipped = widget->testAttribute(Qt::WA_PaintUnclipped); |
| widget->setAttribute(Qt::WA_PaintUnclipped, false); |
| QPainter p(widget); |
| p.setClipping(false); |
| if(was_unclipped) |
| widget->setAttribute(Qt::WA_PaintUnclipped); |
| widget->d_func()->paintBackground(&p, qrgn, widget->isWindow() ? DrawAsRoot : 0); |
| if (widget->testAttribute(Qt::WA_TintedBackground)) { |
| QColor tint = widget->palette().window().color(); |
| tint.setAlphaF(.6); |
| const QVector<QRect> &rects = qrgn.rects(); |
| for (int i = 0; i < rects.size(); ++i) |
| p.fillRect(rects.at(i), tint); |
| } |
| p.end(); |
| if (!redirectionOffset.isNull()) |
| widget->d_func()->restoreRedirected(); |
| } |
| |
| if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) |
| CallNextEventHandler(er, event); |
| |
| //send the paint |
| redirectionOffset += widget->data->wrect.topLeft(); // Map from system to qt coordinates |
| if (!redirectionOffset.isNull()) |
| widget->d_func()->setRedirected(widget, redirectionOffset); |
| qrgn.translate(redirectionOffset); |
| QPaintEvent e(qrgn); |
| widget->d_func()->dirtyOnWidget = QRegion(); |
| #ifdef QT3_SUPPORT |
| e.setErased(true); |
| #endif |
| QApplication::sendSpontaneousEvent(widget, &e); |
| if (!redirectionOffset.isNull()) |
| widget->d_func()->restoreRedirected(); |
| |
| //cleanup |
| if (engine) |
| engine->setSystemClip(QRegion()); |
| |
| widget->setAttribute(Qt::WA_WState_InPaintEvent, false); |
| if(!widget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && widget->paintingActive()) |
| qWarning("QWidget: It is dangerous to leave painters active on a widget outside of the PaintEvent"); |
| } |
| |
| widget->d_func()->hd = 0; |
| widget->d_func()->qd_hd = 0; |
| CGContextRestoreGState(cg); |
| } else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) { |
| CallNextEventHandler(er, event); |
| } |
| } else if(ekind == kEventControlInitialize) { |
| if(HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) { |
| UInt32 features = kControlSupportsDragAndDrop | kControlSupportsClickActivation | kControlSupportsFocus; |
| SetEventParameter(event, kEventParamControlFeatures, typeUInt32, sizeof(features), &features); |
| } else { |
| handled_event = false; |
| } |
| } else if(ekind == kEventControlSetFocusPart) { |
| if(widget) { |
| ControlPartCode part; |
| GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0, |
| sizeof(part), 0, &part); |
| if(part == kControlFocusNoPart){ |
| if (widget->hasFocus()) |
| QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason); |
| } else |
| widget->setFocus(); |
| } |
| if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) |
| CallNextEventHandler(er, event); |
| } else if(ekind == kEventControlGetClickActivation) { |
| ClickActivationResult clickT = kActivateAndIgnoreClick; |
| SetEventParameter(event, kEventParamClickActivation, typeClickActivationResult, |
| sizeof(clickT), &clickT); |
| } else if(ekind == kEventControlGetPartRegion) { |
| handled_event = false; |
| if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget) && CallNextEventHandler(er, event) == noErr) { |
| handled_event = true; |
| break; |
| } |
| if(widget && !widget->isWindow()) { |
| ControlPartCode part; |
| GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0, |
| sizeof(part), 0, &part); |
| if(part == kControlClickableMetaPart && widget->testAttribute(Qt::WA_TransparentForMouseEvents)) { |
| RgnHandle rgn; |
| GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0, |
| sizeof(rgn), 0, &rgn); |
| SetEmptyRgn(rgn); |
| handled_event = true; |
| } else if(part == kControlStructureMetaPart || part == kControlClickableMetaPart) { |
| RgnHandle rgn; |
| GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0, |
| sizeof(rgn), 0, &rgn); |
| SetRectRgn(rgn, 0, 0, widget->width(), widget->height()); |
| if(QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false)) |
| handled_event = true; |
| } else if(part == kControlOpaqueMetaPart) { |
| if(widget->d_func()->isOpaque) { |
| RgnHandle rgn; |
| GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0, |
| sizeof(RgnHandle), 0, &rgn); |
| SetRectRgn(rgn, 0, 0, widget->width(), widget->height()); |
| QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false); |
| SetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, |
| sizeof(RgnHandle), &rgn); |
| handled_event = true; |
| } |
| } |
| } |
| } else if(ekind == kEventControlOwningWindowChanged) { |
| if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) |
| CallNextEventHandler(er, event); |
| if(widget && qt_mac_window_for(hiview)) { |
| WindowRef foo = 0; |
| GetEventParameter(event, kEventParamControlCurrentOwningWindow, typeWindowRef, 0, |
| sizeof(foo), 0, &foo); |
| widget->d_func()->initWindowPtr(); |
| } |
| if (widget) |
| qt_event_request_window_change(widget); |
| } else if(ekind == kEventControlDragEnter || ekind == kEventControlDragWithin || |
| ekind == kEventControlDragLeave || ekind == kEventControlDragReceive) { |
| // dnd are really handled in qdnd_mac.cpp, |
| // just modularize the code a little... |
| DragRef drag; |
| GetEventParameter(event, kEventParamDragRef, typeDragRef, 0, sizeof(drag), 0, &drag); |
| handled_event = false; |
| bool drag_allowed = false; |
| |
| QWidget *dropWidget = widget; |
| if (qobject_cast<QFocusFrame *>(widget)){ |
| // We might shadow widgets underneath the focus |
| // frame, so stay interrested, and let the dnd through |
| drag_allowed = true; |
| handled_event = true; |
| Point where; |
| GetDragMouse(drag, &where, 0); |
| dropWidget = QApplication::widgetAt(QPoint(where.h, where.v)); |
| |
| if (dropWidget != QDragManager::self()->currentTarget()) { |
| // We have to 'fake' enter and leave events for the shaddowed widgets: |
| if (ekind == kEventControlDragEnter) { |
| if (QDragManager::self()->currentTarget()) |
| QDragManager::self()->currentTarget()->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag); |
| if (dropWidget) { |
| dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragEnter, drag); |
| } |
| // Set dropWidget to zero, so qt_mac_dnd_event |
| // doesn't get called a second time below: |
| dropWidget = 0; |
| } else if (ekind == kEventControlDragLeave) { |
| dropWidget = QDragManager::self()->currentTarget(); |
| if (dropWidget) { |
| dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag); |
| } |
| // Set dropWidget to zero, so qt_mac_dnd_event |
| // doesn't get called a second time below: |
| dropWidget = 0; |
| } |
| } |
| } |
| |
| // Send the dnd event to the widget: |
| if (dropWidget && dropWidget->d_func()->qt_mac_dnd_event(ekind, drag)) { |
| drag_allowed = true; |
| handled_event = true; |
| } |
| |
| if (ekind == kEventControlDragEnter) { |
| // If we don't accept the enter event, we will |
| // receive no more drag events for this widget |
| const Boolean wouldAccept = drag_allowed ? true : false; |
| SetEventParameter(event, kEventParamControlWouldAcceptDrop, typeBoolean, |
| sizeof(wouldAccept), &wouldAccept); |
| } |
| } else if (ekind == kEventControlBoundsChanged) { |
| if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_Moved) || widget->testAttribute(Qt::WA_Resized)) { |
| handled_event = false; |
| } else { |
| // Sync our view in case some other (non-Qt) view is controlling us. |
| handled_event = true; |
| Rect newBounds; |
| GetEventParameter(event, kEventParamCurrentBounds, |
| typeQDRectangle, 0, sizeof(Rect), 0, &newBounds); |
| QRect rect(newBounds.left, newBounds.top, |
| newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); |
| |
| bool moved = widget->testAttribute(Qt::WA_Moved); |
| bool resized = widget->testAttribute(Qt::WA_Resized); |
| widget->setGeometry(rect); |
| widget->setAttribute(Qt::WA_Moved, moved); |
| widget->setAttribute(Qt::WA_Resized, resized); |
| qt_event_request_window_change(widget); |
| } |
| } else if (ekind == kEventControlGetSizeConstraints) { |
| if (!widget || !qt_isGenuineQWidget(widget)) { |
| handled_event = false; |
| } else { |
| handled_event = true; |
| QWidgetItem item(widget); |
| QSize size = item.minimumSize(); |
| HISize hisize = { size.width(), size.height() }; |
| SetEventParameter(event, kEventParamMinimumSize, typeHISize, sizeof(HISize), &hisize); |
| size = item.maximumSize(); |
| hisize.width = size.width() + 2; // ### shouldn't have to add 2 (but it works). |
| hisize.height = size.height(); |
| SetEventParameter(event, kEventParamMaximumSize, typeHISize, sizeof(HISize), &hisize); |
| } |
| } else if (ekind == kEventControlVisibilityChanged) { |
| handled_event = false; |
| if (widget) { |
| qt_event_request_window_change(widget); |
| if (!HIViewIsVisible(HIViewRef(widget->winId()))) { |
| if (widget == qt_button_down) |
| qt_button_down = 0; |
| } |
| } |
| } |
| break; } |
| case kEventClassMouse: { |
| bool send_to_app = false; |
| if(qt_button_down) |
| send_to_app = true; |
| if(send_to_app) { |
| OSStatus err = SendEventToApplication(event); |
| if(err != noErr) |
| handled_event = false; |
| } else { |
| CallNextEventHandler(er, event); |
| } |
| break; } |
| default: |
| handled_event = false; |
| break; |
| } |
| if(!handled_event) //let the event go through |
| return eventNotHandledErr; |
| return noErr; //we eat the event |
| } |
| #endif |
| |
| OSViewRef qt_mac_create_widget(QWidget *widget, QWidgetPrivate *widgetPrivate, OSViewRef parent) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| QT_MANGLE_NAMESPACE(QCocoaView) *view = [[QT_MANGLE_NAMESPACE(QCocoaView) alloc] initWithQWidget:widget widgetPrivate:widgetPrivate]; |
| if (view && parent) |
| [parent addSubview:view]; |
| return view; |
| #else |
| Q_UNUSED(widget); |
| Q_UNUSED(widgetPrivate); |
| if(!widget_class) { |
| OSStatus err = HIObjectRegisterSubclass(kObjectQWidget, kHIViewClassID, 0, make_widget_eventUPP(), |
| GetEventTypeCount(widget_events), widget_events, |
| 0, &widget_class); |
| if (err && err != hiObjectClassExistsErr) |
| qWarning("QWidget: Internal error (%d)", __LINE__); |
| } |
| HIViewRef ret = 0; |
| if(HIObjectCreate(kObjectQWidget, 0, (HIObjectRef*)&ret) != noErr) |
| qWarning("QWidget: Internal error (%d)", __LINE__); |
| if(ret && parent) |
| HIViewAddSubview(parent, ret); |
| return ret; |
| #endif |
| } |
| |
| void qt_mac_unregister_widget() |
| { |
| #ifndef QT_MAC_USE_COCOA |
| HIObjectUnregisterClass(widget_class); |
| widget_class = 0; |
| #endif |
| } |
| |
| void QWidgetPrivate::toggleDrawers(bool visible) |
| { |
| for (int i = 0; i < children.size(); ++i) { |
| register QObject *object = children.at(i); |
| if (!object->isWidgetType()) |
| continue; |
| QWidget *widget = static_cast<QWidget*>(object); |
| if(qt_mac_is_macdrawer(widget)) { |
| bool oldState = widget->testAttribute(Qt::WA_WState_ExplicitShowHide); |
| if(visible) { |
| if (!widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) |
| widget->show(); |
| } else { |
| widget->hide(); |
| if(!oldState) |
| widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false); |
| } |
| } |
| } |
| } |
| |
| /***************************************************************************** |
| QWidgetPrivate member functions |
| *****************************************************************************/ |
| bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up) |
| { |
| // I'm not sure what "up" is |
| if(!w || !w->isWindow()) |
| return false; |
| |
| QTLWExtra *topData = w->d_func()->topData(); |
| QWExtra *extraData = w->d_func()->extraData(); |
| // topData->resizer is only 4 bits, so subtracting -1 from zero causes bad stuff |
| // to happen, prevent that here (you really want the thing hidden). |
| if (up >= 0 || topData->resizer != 0) |
| topData->resizer += up; |
| OSWindowRef windowRef = qt_mac_window_for(OSViewRef(w->winId())); |
| { |
| #ifndef QT_MAC_USE_COCOA |
| WindowClass wclass; |
| GetWindowClass(windowRef, &wclass); |
| if(!(GetAvailableWindowAttributes(wclass) & kWindowResizableAttribute)) |
| return true; |
| #endif |
| } |
| bool remove_grip = (topData->resizer || (w->windowFlags() & Qt::FramelessWindowHint) |
| || (extraData->maxw && extraData->maxh && |
| extraData->maxw == extraData->minw && extraData->maxh == extraData->minh)); |
| #ifndef QT_MAC_USE_COCOA |
| WindowAttributes attr; |
| GetWindowAttributes(windowRef, &attr); |
| if(remove_grip) { |
| if(attr & kWindowResizableAttribute) { |
| ChangeWindowAttributes(qt_mac_window_for(w), kWindowNoAttributes, |
| kWindowResizableAttribute); |
| ReshapeCustomWindow(qt_mac_window_for(w)); |
| } |
| } else if(!(attr & kWindowResizableAttribute)) { |
| ChangeWindowAttributes(windowRef, kWindowResizableAttribute, |
| kWindowNoAttributes); |
| ReshapeCustomWindow(windowRef); |
| } |
| #else |
| [windowRef setShowsResizeIndicator:!remove_grip]; |
| #endif |
| return true; |
| } |
| |
| void QWidgetPrivate::qt_clean_root_win() |
| { |
| #ifdef QT_MAC_USE_COCOA |
| [qt_root_win release]; |
| #else |
| if(!qt_root_win) |
| return; |
| CFRelease(qt_root_win); |
| #endif |
| qt_root_win = 0; |
| } |
| |
| bool QWidgetPrivate::qt_create_root_win() |
| { |
| if(qt_root_win) |
| return false; |
| const QSize desktopSize = qt_mac_desktopSize(); |
| QRect desktopRect(QPoint(0, 0), desktopSize); |
| #ifdef QT_MAC_USE_COCOA |
| qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, NSBorderlessWindowMask, desktopRect); |
| #else |
| WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute); |
| qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, wattr, desktopRect); |
| #endif |
| if(!qt_root_win) |
| return false; |
| qAddPostRoutine(qt_clean_root_win); |
| return true; |
| } |
| |
| bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false) |
| { |
| bool ret = false; |
| #ifndef QT_MAC_USE_COCOA |
| switch(wcode) { |
| case kWindowStructureRgn: { |
| if(widget) { |
| if(widget->d_func()->extra && !widget->d_func()->extra->mask.isEmpty()) { |
| QRegion rin = qt_mac_convert_mac_region(rgn); |
| if(!rin.isEmpty()) { |
| QPoint rin_tl = rin.boundingRect().topLeft(); //in offset |
| rin.translate(-rin_tl.x(), -rin_tl.y()); //bring into same space as below |
| QRegion mask = widget->d_func()->extra->mask; |
| Qt::WindowFlags flags = widget->windowFlags(); |
| if(widget->isWindow() |
| && !(flags & Qt::FramelessWindowHint |
| || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint)))) { |
| QRegion title; |
| { |
| QMacSmartQuickDrawRegion rgn(qt_mac_get_rgn()); |
| GetWindowRegion(qt_mac_window_for(widget), kWindowTitleBarRgn, rgn); |
| title = qt_mac_convert_mac_region(rgn); |
| } |
| QRect br = title.boundingRect(); |
| mask.translate(0, br.height()); //put the mask 'under' the title bar.. |
| title.translate(-br.x(), -br.y()); |
| mask += title; |
| } |
| |
| QRegion cr = rin & mask; |
| cr.translate(rin_tl.x(), rin_tl.y()); //translate back to incoming space |
| CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn); |
| } |
| ret = true; |
| } else if(force) { |
| QRegion cr(widget->geometry()); |
| CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn); |
| ret = true; |
| } |
| } |
| break; } |
| default: break; |
| } |
| //qDebug() << widget << ret << wcode << qt_mac_convert_mac_region(rgn); |
| #else |
| Q_UNUSED(widget); |
| Q_UNUSED(wcode); |
| Q_UNUSED(rgn); |
| Q_UNUSED(force); |
| #endif |
| return ret; |
| } |
| |
| /***************************************************************************** |
| QWidget member functions |
| *****************************************************************************/ |
| void QWidgetPrivate::determineWindowClass() |
| { |
| Q_Q(QWidget); |
| #if !defined(QT_NO_MAINWINDOW) && !defined(QT_NO_TOOLBAR) |
| // Make sure that QMainWindow has the MacWindowToolBarButtonHint when the |
| // unifiedTitleAndToolBarOnMac property is ON. This is to avoid reentry of |
| // setParent() triggered by the QToolBar::event(QEvent::ParentChange). |
| QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q); |
| if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) { |
| data.window_flags |= Qt::MacWindowToolBarButtonHint; |
| } |
| #endif |
| #ifndef QT_MAC_USE_COCOA |
| // ### COCOA:Interleave these better! |
| |
| const Qt::WindowType type = q->windowType(); |
| Qt::WindowFlags &flags = data.window_flags; |
| const bool popup = (type == Qt::Popup); |
| if (type == Qt::ToolTip || type == Qt::SplashScreen || popup) |
| flags |= Qt::FramelessWindowHint; |
| |
| WindowClass wclass = kSheetWindowClass; |
| if(qt_mac_is_macdrawer(q)) |
| wclass = kDrawerWindowClass; |
| else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint) |
| wclass = kDocumentWindowClass; |
| else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen)) |
| wclass = kModalWindowClass; |
| else if(q->testAttribute(Qt::WA_ShowModal)) |
| wclass = kMovableModalWindowClass; |
| else if(type == Qt::ToolTip) |
| wclass = kHelpWindowClass; |
| else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 |
| && type == Qt::SplashScreen)) |
| wclass = kFloatingWindowClass; |
| else |
| wclass = kDocumentWindowClass; |
| |
| WindowGroupRef grp = 0; |
| WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute); |
| if (q->testAttribute(Qt::WA_MacFrameworkScaled)) |
| wattr |= kWindowFrameworkScaledAttribute; |
| if(qt_mac_is_macsheet(q)) { |
| //grp = GetWindowGroupOfClass(kMovableModalWindowClass); |
| wclass = kSheetWindowClass; |
| } else { |
| grp = GetWindowGroupOfClass(wclass); |
| // Shift things around a bit to get the correct window class based on the presence |
| // (or lack) of the border. |
| bool customize = flags & Qt::CustomizeWindowHint; |
| bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); |
| if (framelessWindow) { |
| if(wclass == kDocumentWindowClass) { |
| wattr |= kWindowNoTitleBarAttribute; |
| } else if(wclass == kFloatingWindowClass) { |
| wattr |= kWindowNoTitleBarAttribute; |
| } else if (wclass == kMovableModalWindowClass) { |
| wclass = kModalWindowClass; |
| } |
| } else { |
| if(wclass != kModalWindowClass) |
| wattr |= kWindowResizableAttribute; |
| } |
| // Only add extra decorations (well, buttons) for widgets that can have them |
| // and have an actual border we can put them on. |
| if(wclass != kModalWindowClass && wclass != kMovableModalWindowClass |
| && wclass != kSheetWindowClass && wclass != kPlainWindowClass |
| && !framelessWindow && wclass != kDrawerWindowClass |
| && wclass != kHelpWindowClass) { |
| if (flags & Qt::WindowMaximizeButtonHint) |
| wattr |= kWindowFullZoomAttribute; |
| if (flags & Qt::WindowMinimizeButtonHint) |
| wattr |= kWindowCollapseBoxAttribute; |
| if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint) |
| wattr |= kWindowCloseBoxAttribute; |
| if (flags & Qt::MacWindowToolBarButtonHint) |
| wattr |= kWindowToolbarButtonAttribute; |
| } else { |
| // Clear these hints so that we aren't call them on invalid windows |
| flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint |
| | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint); |
| } |
| } |
| if((popup || type == Qt::Tool) && !q->isModal()) |
| wattr |= kWindowHideOnSuspendAttribute; |
| wattr |= kWindowLiveResizeAttribute; |
| |
| #ifdef DEBUG_WINDOW_CREATE |
| #define ADD_DEBUG_WINDOW_NAME(x) { x, #x } |
| struct { |
| UInt32 tag; |
| const char *name; |
| } known_attribs[] = { |
| ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), |
| { 0, 0 } |
| }, known_classes[] = { |
| ADD_DEBUG_WINDOW_NAME(kHelpWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kPlainWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kSheetWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kModalWindowClass), |
| { 0, 0 } |
| }; |
| qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(), |
| q->objectName().toLocal8Bit().constData()); |
| bool found_class = false; |
| for(int i = 0; known_classes[i].name; i++) { |
| if(wclass == known_classes[i].tag) { |
| found_class = true; |
| qDebug("Qt: internal: ** Class: %s", known_classes[i].name); |
| break; |
| } |
| } |
| if(!found_class) |
| qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass); |
| if(wattr) { |
| WindowAttributes tmp_wattr = wattr; |
| qDebug("Qt: internal: ** Attributes:"); |
| for(int i = 0; tmp_wattr && known_attribs[i].name; i++) { |
| if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) { |
| tmp_wattr ^= known_attribs[i].tag; |
| qDebug("Qt: internal: * %s %s", known_attribs[i].name, |
| (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)"); |
| } |
| } |
| if(tmp_wattr) |
| qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr); |
| } |
| #endif |
| |
| /* Just to be extra careful we will change to the kUtilityWindowClass if the |
| requested attributes cannot be used */ |
| if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) { |
| WindowClass tmp_class = wclass; |
| if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass) |
| wclass = kFloatingWindowClass; |
| if(tmp_class != wclass) { |
| if(!grp) |
| grp = GetWindowGroupOfClass(wclass); |
| wclass = tmp_class; |
| } |
| } |
| topData()->wclass = wclass; |
| topData()->wattr = wattr; |
| #else |
| const Qt::WindowType type = q->windowType(); |
| Qt::WindowFlags &flags = data.window_flags; |
| const bool popup = (type == Qt::Popup); |
| if (type == Qt::ToolTip || type == Qt::SplashScreen || popup) |
| flags |= Qt::FramelessWindowHint; |
| |
| WindowClass wclass = kSheetWindowClass; |
| if(qt_mac_is_macdrawer(q)) |
| wclass = kDrawerWindowClass; |
| else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint) |
| wclass = kDocumentWindowClass; |
| else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen)) |
| wclass = kModalWindowClass; |
| else if(type == Qt::Dialog) |
| wclass = kMovableModalWindowClass; |
| else if(type == Qt::ToolTip) |
| wclass = kHelpWindowClass; |
| else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 |
| && type == Qt::SplashScreen)) |
| wclass = kFloatingWindowClass; |
| else if(q->testAttribute(Qt::WA_ShowModal)) |
| wclass = kMovableModalWindowClass; |
| else |
| wclass = kDocumentWindowClass; |
| |
| WindowAttributes wattr = NSBorderlessWindowMask; |
| if(qt_mac_is_macsheet(q)) { |
| //grp = GetWindowGroupOfClass(kMovableModalWindowClass); |
| wclass = kSheetWindowClass; |
| wattr = NSTitledWindowMask | NSResizableWindowMask; |
| } else { |
| #ifndef QT_MAC_USE_COCOA |
| grp = GetWindowGroupOfClass(wclass); |
| #endif |
| // Shift things around a bit to get the correct window class based on the presence |
| // (or lack) of the border. |
| bool customize = flags & Qt::CustomizeWindowHint; |
| bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); |
| if (framelessWindow) { |
| if (wclass == kDocumentWindowClass) { |
| wclass = kSimpleWindowClass; |
| } else if (wclass == kFloatingWindowClass) { |
| wclass = kToolbarWindowClass; |
| } else if (wclass == kMovableModalWindowClass) { |
| wclass = kModalWindowClass; |
| } |
| } else { |
| wattr |= NSTitledWindowMask; |
| if (wclass != kModalWindowClass) |
| wattr |= NSResizableWindowMask; |
| } |
| // Only add extra decorations (well, buttons) for widgets that can have them |
| // and have an actual border we can put them on. |
| if (wclass != kModalWindowClass |
| && wclass != kSheetWindowClass && wclass != kPlainWindowClass |
| && !framelessWindow && wclass != kDrawerWindowClass |
| && wclass != kHelpWindowClass) { |
| if (flags & Qt::WindowMinimizeButtonHint) |
| wattr |= NSMiniaturizableWindowMask; |
| if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint) |
| wattr |= NSClosableWindowMask; |
| } else { |
| // Clear these hints so that we aren't call them on invalid windows |
| flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint |
| | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint); |
| } |
| } |
| if (q->testAttribute(Qt::WA_MacBrushedMetal)) |
| wattr |= NSTexturedBackgroundWindowMask; |
| |
| #ifdef DEBUG_WINDOW_CREATE |
| #define ADD_DEBUG_WINDOW_NAME(x) { x, #x } |
| struct { |
| UInt32 tag; |
| const char *name; |
| } known_attribs[] = { |
| ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute), |
| ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), |
| { 0, 0 } |
| }, known_classes[] = { |
| ADD_DEBUG_WINDOW_NAME(kHelpWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kPlainWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kSheetWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass), |
| ADD_DEBUG_WINDOW_NAME(kModalWindowClass), |
| { 0, 0 } |
| }; |
| qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(), |
| q->objectName().toLocal8Bit().constData()); |
| bool found_class = false; |
| for(int i = 0; known_classes[i].name; i++) { |
| if(wclass == known_classes[i].tag) { |
| found_class = true; |
| qDebug("Qt: internal: ** Class: %s", known_classes[i].name); |
| break; |
| } |
| } |
| if(!found_class) |
| qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass); |
| if(wattr) { |
| WindowAttributes tmp_wattr = wattr; |
| qDebug("Qt: internal: ** Attributes:"); |
| for(int i = 0; tmp_wattr && known_attribs[i].name; i++) { |
| if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) { |
| tmp_wattr ^= known_attribs[i].tag; |
| } |
| } |
| if(tmp_wattr) |
| qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr); |
| } |
| #endif |
| |
| #ifndef QT_MAC_USE_COCOA |
| /* Just to be extra careful we will change to the kUtilityWindowClass if the |
| requested attributes cannot be used */ |
| if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) { |
| WindowClass tmp_class = wclass; |
| if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass) |
| wclass = kFloatingWindowClass; |
| if(tmp_class != wclass) { |
| if(!grp) |
| grp = GetWindowGroupOfClass(wclass); |
| wclass = tmp_class; |
| } |
| } |
| #endif |
| #endif |
| topData()->wclass = wclass; |
| topData()->wattr = wattr; |
| } |
| |
| #ifndef QT_MAC_USE_COCOA // This is handled in Cocoa via our category. |
| void QWidgetPrivate::initWindowPtr() |
| { |
| Q_Q(QWidget); |
| OSWindowRef windowRef = qt_mac_window_for(qt_mac_nativeview_for(q)); //do not create! |
| if(!windowRef) |
| return; |
| QWidget *window = q->window(), *oldWindow = 0; |
| if(GetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(oldWindow), 0, &oldWindow) == noErr) { |
| Q_ASSERT(window == oldWindow); |
| return; |
| } |
| |
| if(SetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(window), &window) != noErr) |
| qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__); //no real way to recover |
| if(!q->windowType() != Qt::Desktop) { //setup an event callback handler on the window |
| InstallWindowEventHandler(windowRef, make_win_eventUPP(), GetEventTypeCount(window_events), |
| window_events, static_cast<void *>(qApp), &window_event); |
| } |
| } |
| |
| void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef) |
| { |
| Q_Q(QWidget); |
| const Qt::WindowType type = q->windowType(); |
| Qt::WindowFlags &flags = data.window_flags; |
| QWidget *parentWidget = q->parentWidget(); |
| |
| const bool desktop = (type == Qt::Desktop); |
| const bool dialog = (type == Qt::Dialog |
| || type == Qt::Sheet |
| || type == Qt::Drawer |
| || (flags & Qt::MSWindowsFixedSizeDialogHint)); |
| QTLWExtra *topExtra = topData(); |
| quint32 wattr = topExtra->wattr; |
| if (!desktop) |
| SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true); |
| HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0); |
| if (wattr & kWindowHideOnSuspendAttribute) |
| HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0); |
| else |
| HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden); |
| if ((flags & Qt::WindowStaysOnTopHint)) |
| ChangeWindowAttributes(windowRef, kWindowNoAttributes, kWindowHideOnSuspendAttribute); |
| if (qt_mac_is_macdrawer(q) && parentWidget) |
| SetDrawerParent(windowRef, qt_mac_window_for (parentWidget)); |
| if (topExtra->group) { |
| qt_mac_release_window_group(topExtra->group); |
| topExtra->group = 0; |
| } |
| if (type == Qt::ToolTip) |
| qt_mac_set_window_group_to_tooltip(windowRef); |
| else if (type == Qt::Popup && (flags & Qt::WindowStaysOnTopHint)) |
| qt_mac_set_window_group_to_popup(windowRef); |
| else if (flags & Qt::WindowStaysOnTopHint) |
| qt_mac_set_window_group_to_stays_on_top(windowRef, type); |
| else if (dialog) |
| SetWindowGroup(windowRef, GetWindowGroupOfClass(kMovableModalWindowClass)); |
| |
| #ifdef DEBUG_WINDOW_CREATE |
| if (WindowGroupRef grpf = GetWindowGroup(windowRef)) { |
| QCFString cfname; |
| CopyWindowGroupName(grpf, &cfname); |
| SInt32 lvl; |
| GetWindowGroupLevel(grpf, &lvl); |
| const char *from = "Default"; |
| if (topExtra && grpf == topData()->group) |
| from = "Created"; |
| else if (grpf == grp) |
| from = "Copied"; |
| qDebug("Qt: internal: With window group '%s' [%p] @ %d: %s", |
| static_cast<QString>(cfname).toLatin1().constData(), grpf, (int)lvl, from); |
| } else { |
| qDebug("Qt: internal: No window group!!!"); |
| } |
| HIWindowAvailability hi_avail = 0; |
| if (HIWindowGetAvailability(windowRef, &hi_avail) == noErr) { |
| struct { |
| UInt32 tag; |
| const char *name; |
| } known_avail[] = { |
| ADD_DEBUG_WINDOW_NAME(kHIWindowExposeHidden), |
| { 0, 0 } |
| }; |
| qDebug("Qt: internal: ** HIWindowAvailibility:"); |
| for (int i = 0; hi_avail && known_avail[i].name; i++) { |
| if ((hi_avail & known_avail[i].tag) == known_avail[i].tag) { |
| hi_avail ^= known_avail[i].tag; |
| qDebug("Qt: internal: * %s", known_avail[i].name); |
| } |
| } |
| if (hi_avail) |
| qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)hi_avail); |
| } |
| #undef ADD_DEBUG_WINDOW_NAME |
| #endif |
| if (extra && !extra->mask.isEmpty()) |
| ReshapeCustomWindow(windowRef); |
| SetWindowModality(windowRef, kWindowModalityNone, 0); |
| if (qt_mac_is_macdrawer(q)) |
| SetDrawerOffsets(windowRef, 0.0, 25.0); |
| data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty |
| HIViewRef hiview = (HIViewRef)data.winid; |
| HIViewRef window_hiview = qt_mac_get_contentview_for(windowRef); |
| if(!hiview) { |
| hiview = qt_mac_create_widget(q, this, window_hiview); |
| setWinId((WId)hiview); |
| } else { |
| HIViewAddSubview(window_hiview, hiview); |
| } |
| if (hiview) { |
| Rect win_rect; |
| GetWindowBounds(qt_mac_window_for (window_hiview), kWindowContentRgn, &win_rect); |
| HIRect bounds = CGRectMake(0, 0, win_rect.right-win_rect.left, win_rect.bottom-win_rect.top); |
| HIViewSetFrame(hiview, &bounds); |
| HIViewSetVisible(hiview, true); |
| if (q->testAttribute(Qt::WA_DropSiteRegistered)) |
| registerDropSite(true); |
| transferChildren(); |
| } |
| initWindowPtr(); |
| |
| if (topExtra->posFromMove) { |
| updateFrameStrut(); |
| const QRect &fStrut = frameStrut(); |
| Rect r; |
| SetRect(&r, data.crect.left(), data.crect.top(), data.crect.right() + 1, data.crect.bottom() + 1); |
| SetRect(&r, r.left + fStrut.left(), r.top + fStrut.top(), |
| (r.left + fStrut.left() + data.crect.width()) - fStrut.right(), |
| (r.top + fStrut.top() + data.crect.height()) - fStrut.bottom()); |
| SetWindowBounds(windowRef, kWindowContentRgn, &r); |
| topExtra->posFromMove = false; |
| } |
| |
| if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){ |
| q->setWindowOpacity(topExtra->opacity / 255.0f); |
| } else if (qt_mac_is_macsheet(q)){ |
| SetThemeWindowBackground(qt_mac_window_for(q), kThemeBrushSheetBackgroundTransparent, true); |
| CGFloat alpha = 0; |
| GetWindowAlpha(qt_mac_window_for(q), &alpha); |
| if (alpha == 1){ |
| // For some reason the 'SetThemeWindowBackground' does not seem |
| // to work. So we do this little hack until it hopefully starts to |
| // work in newer versions of mac OS. |
| q->setWindowOpacity(0.95f); |
| q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); |
| } |
| } else{ |
| // If the window has been recreated after beeing e.g. a sheet, |
| // make sure that we don't report a faulty opacity: |
| q->setWindowOpacity(1.0f); |
| q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); |
| } |
| |
| // Since we only now have a window, sync our state. |
| macUpdateHideOnSuspend(); |
| macUpdateOpaqueSizeGrip(); |
| macUpdateMetalAttribute(); |
| macUpdateIgnoreMouseEvents(); |
| setWindowTitle_helper(extra->topextra->caption); |
| setWindowIconText_helper(extra->topextra->iconText); |
| setWindowFilePath_helper(extra->topextra->filePath); |
| setWindowModified_sys(q->isWindowModified()); |
| updateFrameStrut(); |
| qt_mac_update_sizer(q); |
| applyMaxAndMinSizeOnWindow(); |
| } |
| #else // QT_MAC_USE_COCOA |
| |
| void QWidgetPrivate::setWindowLevel() |
| { |
| Q_Q(QWidget); |
| const QWidget * const windowParent = q->window()->parentWidget(); |
| const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0; |
| NSInteger winLevel = -1; |
| |
| if (q->windowType() == Qt::Popup) { |
| winLevel = NSPopUpMenuWindowLevel; |
| // Popup should be in at least the same level as its parent. |
| if (primaryWindow) { |
| OSWindowRef parentRef = qt_mac_window_for(primaryWindow); |
| winLevel = qMax([parentRef level], winLevel); |
| } |
| } else if (q->windowType() == Qt::Tool) { |
| winLevel = NSFloatingWindowLevel; |
| } else if (q->windowType() == Qt::Dialog) { |
| // Correct modality level (NSModalPanelWindowLevel) will be |
| // set by cocoa when creating a modal session later. |
| winLevel = NSNormalWindowLevel; |
| } |
| |
| // StayOnTop window should appear above Tool windows. |
| if (data.window_flags & Qt::WindowStaysOnTopHint) |
| winLevel = NSPopUpMenuWindowLevel; |
| // Tooltips should appear above StayOnTop windows. |
| if (q->windowType() == Qt::ToolTip) |
| winLevel = NSScreenSaverWindowLevel; |
| // All other types are Normal level. |
| if (winLevel == -1) |
| winLevel = NSNormalWindowLevel; |
| [qt_mac_window_for(q) setLevel:winLevel]; |
| } |
| |
| void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef) |
| { |
| Q_Q(QWidget); |
| QMacCocoaAutoReleasePool pool; |
| NSWindow *windowRef = static_cast<NSWindow *>(voidWindowRef); |
| const Qt::WindowType type = q->windowType(); |
| Qt::WindowFlags &flags = data.window_flags; |
| QWidget *parentWidget = q->parentWidget(); |
| |
| const bool popup = (type == Qt::Popup); |
| const bool dialog = (type == Qt::Dialog |
| || type == Qt::Sheet |
| || type == Qt::Drawer |
| || (flags & Qt::MSWindowsFixedSizeDialogHint)); |
| QTLWExtra *topExtra = topData(); |
| |
| if ((popup || type == Qt::Tool || type == Qt::ToolTip) && !q->isModal()) { |
| [windowRef setHidesOnDeactivate:YES]; |
| } else { |
| [windowRef setHidesOnDeactivate:NO]; |
| } |
| [windowRef setHasShadow:YES]; |
| Q_UNUSED(parentWidget); |
| Q_UNUSED(dialog); |
| |
| data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty |
| OSViewRef nsview = (OSViewRef)data.winid; |
| OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef); |
| if (!nsview) { |
| nsview = qt_mac_create_widget(q, this, window_contentview); |
| setWinId(WId(nsview)); |
| } else { |
| [window_contentview addSubview:nsview]; |
| } |
| if (nsview) { |
| NSRect bounds = [window_contentview bounds]; |
| [nsview setFrame:bounds]; |
| [nsview setHidden:NO]; |
| if (q->testAttribute(Qt::WA_DropSiteRegistered)) |
| registerDropSite(true); |
| transferChildren(); |
| |
| // Tell Cocoa explicit that we wan't the view to receive key events |
| // (regardless of focus policy) because this is how it works on other |
| // platforms (and in the carbon port): |
| if (!qApp->focusWidget()) |
| [windowRef makeFirstResponder:nsview]; |
| } |
| |
| if (topExtra->posFromMove) { |
| updateFrameStrut(); |
| |
| const QRect &fStrut = frameStrut(); |
| const QRect &crect = data.crect; |
| const QRect frameRect(QPoint(crect.left(), crect.top()), |
| QSize(fStrut.left() + fStrut.right() + crect.width(), |
| fStrut.top() + fStrut.bottom() + crect.height())); |
| NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), |
| frameRect.width(), frameRect.height()); |
| [windowRef setFrame:cocoaFrameRect display:NO]; |
| topExtra->posFromMove = false; |
| } |
| |
| if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){ |
| q->setWindowOpacity(topExtra->opacity / 255.0f); |
| } else if (qt_mac_is_macsheet(q)){ |
| CGFloat alpha = [qt_mac_window_for(q) alphaValue]; |
| if (alpha >= 1.0) { |
| q->setWindowOpacity(0.95f); |
| q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); |
| } |
| } else{ |
| // If the window has been recreated after beeing e.g. a sheet, |
| // make sure that we don't report a faulty opacity: |
| q->setWindowOpacity(1.0f); |
| q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); |
| } |
| |
| if (qApp->overrideCursor()) |
| [windowRef disableCursorRects]; |
| |
| setWindowLevel(); |
| macUpdateHideOnSuspend(); |
| macUpdateOpaqueSizeGrip(); |
| macUpdateIgnoreMouseEvents(); |
| setWindowTitle_helper(extra->topextra->caption); |
| setWindowIconText_helper(extra->topextra->iconText); |
| setWindowModified_sys(q->isWindowModified()); |
| updateFrameStrut(); |
| syncCocoaMask(); |
| macUpdateIsOpaque(); |
| qt_mac_update_sizer(q); |
| applyMaxAndMinSizeOnWindow(); |
| } |
| |
| #endif // QT_MAC_USE_COCOA |
| |
| /* |
| Recreates widget window. Useful if immutable |
| properties for it has changed. |
| */ |
| void QWidgetPrivate::recreateMacWindow() |
| { |
| Q_Q(QWidget); |
| OSViewRef myView = qt_mac_nativeview_for(q); |
| OSWindowRef oldWindow = qt_mac_window_for(myView); |
| #ifndef QT_MAC_USE_COCOA |
| HIViewRemoveFromSuperview(myView); |
| determineWindowClass(); |
| createWindow_sys(); |
| |
| if (QMainWindowLayout *mwl = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q))) { |
| mwl->updateHIToolBarStatus(); |
| } |
| |
| if (IsWindowVisible(oldWindow)) |
| show_sys(); |
| #else |
| QMacCocoaAutoReleasePool pool; |
| [myView removeFromSuperview]; |
| determineWindowClass(); |
| createWindow_sys(); |
| if (NSToolbar *toolbar = [oldWindow toolbar]) { |
| OSWindowRef newWindow = qt_mac_window_for(myView); |
| [newWindow setToolbar:toolbar]; |
| [toolbar setVisible:[toolbar isVisible]]; |
| } |
| if ([oldWindow isVisible]){ |
| if ([oldWindow isSheet]) |
| [NSApp endSheet:oldWindow]; |
| [oldWindow orderOut:oldWindow]; |
| show_sys(); |
| } |
| #endif // QT_MAC_USE_COCOA |
| |
| // Release the window after creating the new window, because releasing it early |
| // may cause the app to quit ("close on last window closed attribute") |
| qt_mac_destructWindow(oldWindow); |
| } |
| |
| void QWidgetPrivate::createWindow_sys() |
| { |
| Q_Q(QWidget); |
| Qt::WindowFlags &flags = data.window_flags; |
| QWidget *parentWidget = q->parentWidget(); |
| |
| QTLWExtra *topExtra = topData(); |
| if (topExtra->embedded) |
| return; // Simply return because this view "is" the top window. |
| quint32 wattr = topExtra->wattr; |
| |
| if(parentWidget && (parentWidget->window()->windowFlags() & Qt::WindowStaysOnTopHint)) // If our parent has Qt::WStyle_StaysOnTop, so must we |
| flags |= Qt::WindowStaysOnTopHint; |
| |
| data.fstrut_dirty = true; |
| |
| OSWindowRef windowRef = qt_mac_create_window(q, topExtra->wclass, wattr, data.crect); |
| if (windowRef == 0) |
| qWarning("QWidget: Internal error: %s:%d: If you reach this error please contact Qt Support and include the\n" |
| " WidgetFlags used in creating the widget.", __FILE__, __LINE__); |
| #ifndef QT_MAC_USE_COCOA |
| finishCreateWindow_sys_Carbon(windowRef); |
| #else |
| finishCreateWindow_sys_Cocoa(windowRef); |
| #endif |
| } |
| |
| void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) |
| { |
| Q_Q(QWidget); |
| OSViewRef destroyid = 0; |
| #ifndef QT_MAC_USE_COCOA |
| window_event = 0; |
| #endif |
| |
| Qt::WindowType type = q->windowType(); |
| Qt::WindowFlags flags = data.window_flags; |
| QWidget *parentWidget = q->parentWidget(); |
| |
| bool topLevel = (flags & Qt::Window); |
| bool popup = (type == Qt::Popup); |
| bool dialog = (type == Qt::Dialog |
| || type == Qt::Sheet |
| || type == Qt::Drawer |
| || (flags & Qt::MSWindowsFixedSizeDialogHint)); |
| bool desktop = (type == Qt::Desktop); |
| |
| // Determine this early for top-levels so, we can use it later. |
| if (topLevel) |
| determineWindowClass(); |
| |
| if (desktop) { |
| QSize desktopSize = qt_mac_desktopSize(); |
| q->setAttribute(Qt::WA_WState_Visible); |
| data.crect.setRect(0, 0, desktopSize.width(), desktopSize.height()); |
| dialog = popup = false; // force these flags off |
| } else { |
| q->setAttribute(Qt::WA_WState_Visible, false); |
| |
| if (topLevel && (type != Qt::Drawer)) { |
| if (QDesktopWidget *dsk = QApplication::desktop()) { // calc pos/size from screen |
| const bool wasResized = q->testAttribute(Qt::WA_Resized); |
| const bool wasMoved = q->testAttribute(Qt::WA_Moved); |
| int deskn = dsk->primaryScreen(); |
| if (parentWidget && parentWidget->windowType() != Qt::Desktop) |
| deskn = dsk->screenNumber(parentWidget); |
| QRect screenGeo = dsk->screenGeometry(deskn); |
| if (!wasResized) { |
| #ifndef QT_MAC_USE_COCOA |
| data.crect.setSize(QSize(screenGeo.width()/2, 4*screenGeo.height()/10)); |
| #else |
| NSRect newRect = [NSWindow frameRectForContentRect:NSMakeRect(0, 0, |
| screenGeo.width() / 2., |
| 4 * screenGeo.height() / 10.) |
| styleMask:topData()->wattr]; |
| data.crect.setSize(QSize(newRect.size.width, newRect.size.height)); |
| #endif |
| // Constrain to minimums and maximums we've set |
| if (extra->minw > 0) |
| data.crect.setWidth(qMax(extra->minw, data.crect.width())); |
| if (extra->minh > 0) |
| data.crect.setHeight(qMax(extra->minh, data.crect.height())); |
| if (extra->maxw > 0) |
| data.crect.setWidth(qMin(extra->maxw, data.crect.width())); |
| if (extra->maxh > 0) |
| data.crect.setHeight(qMin(extra->maxh, data.crect.height())); |
| } |
| if (!wasMoved && !q->testAttribute(Qt::WA_DontShowOnScreen)) |
| data.crect.moveTopLeft(QPoint(screenGeo.width()/4, |
| 3 * screenGeo.height() / 10)); |
| } |
| } |
| } |
| |
| |
| if(!window) // always initialize |
| initializeWindow=true; |
| |
| hd = 0; |
| if(window) { // override the old window (with a new NSView) |
| OSViewRef nativeView = OSViewRef(window); |
| OSViewRef parent = 0; |
| #ifndef QT_MAC_USE_COCOA |
| CFRetain(nativeView); |
| #else |
| [nativeView retain]; |
| #endif |
| if (destroyOldWindow) |
| destroyid = qt_mac_nativeview_for(q); |
| bool transfer = false; |
| setWinId((WId)nativeView); |
| #ifndef QT_MAC_USE_COCOA |
| #ifndef HIViewInstallEventHandler |
| // Macro taken from the CarbonEvents Header on Tiger |
| #define HIViewInstallEventHandler( target, handler, numTypes, list, userData, outHandlerRef ) \ |
| InstallEventHandler( HIObjectGetEventTarget( (HIObjectRef) (target) ), (handler), (numTypes), (list), (userData), (outHandlerRef) ) |
| #endif |
| HIViewInstallEventHandler(nativeView, make_widget_eventUPP(), GetEventTypeCount(widget_events), widget_events, 0, 0); |
| #endif |
| if(topLevel) { |
| for(int i = 0; i < 2; ++i) { |
| if(i == 1) { |
| if(!initializeWindow) |
| break; |
| createWindow_sys(); |
| } |
| if(OSWindowRef windowref = qt_mac_window_for(nativeView)) { |
| #ifndef QT_MAC_USE_COCOA |
| CFRetain(windowref); |
| #else |
| [windowref retain]; |
| #endif |
| if (initializeWindow) { |
| parent = qt_mac_get_contentview_for(windowref); |
| } else { |
| #ifndef QT_MAC_USE_COCOA |
| parent = HIViewGetSuperview(nativeView); |
| #else |
| parent = [nativeView superview]; |
| #endif |
| } |
| break; |
| } |
| } |
| if(!parent) |
| transfer = true; |
| } else if (parentWidget) { |
| // I need to be added to my parent, therefore my parent needs an NSView |
| parentWidget->createWinId(); |
| parent = qt_mac_nativeview_for(parentWidget); |
| } |
| if(parent != nativeView && parent) { |
| #ifndef QT_MAC_USE_COCOA |
| HIViewAddSubview(parent, nativeView); |
| #else |
| [parent addSubview:nativeView]; |
| #endif |
| } |
| if(transfer) |
| transferChildren(); |
| data.fstrut_dirty = true; // we'll re calculate this later |
| q->setAttribute(Qt::WA_WState_Visible, |
| #ifndef QT_MAC_USE_COCOA |
| HIViewIsVisible(nativeView) |
| #else |
| ![nativeView isHidden] |
| #endif |
| ); |
| if(initializeWindow) { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); |
| HIViewSetFrame(nativeView, &bounds); |
| q->setAttribute(Qt::WA_WState_Visible, HIViewIsVisible(nativeView)); |
| #else |
| NSRect bounds = NSMakeRect(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); |
| [nativeView setFrame:bounds]; |
| q->setAttribute(Qt::WA_WState_Visible, [nativeView isHidden]); |
| #endif |
| } |
| #ifndef QT_MAC_USE_COCOA |
| initWindowPtr(); |
| #endif |
| } else if (desktop) { // desktop widget |
| if (!qt_root_win) |
| QWidgetPrivate::qt_create_root_win(); |
| Q_ASSERT(qt_root_win); |
| WId rootWinID = 0; |
| #ifndef QT_MAC_USE_COCOA |
| CFRetain(qt_root_win); |
| if(HIViewRef rootContentView = HIViewGetRoot(qt_root_win)) { |
| rootWinID = (WId)rootContentView; |
| CFRetain(rootContentView); |
| } |
| #else |
| [qt_root_win retain]; |
| if (OSViewRef rootContentView = [qt_root_win contentView]) { |
| rootWinID = (WId)rootContentView; |
| [rootContentView retain]; |
| } |
| #endif |
| setWinId(rootWinID); |
| } else if (topLevel) { |
| determineWindowClass(); |
| if(OSViewRef osview = qt_mac_create_widget(q, this, 0)) { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), |
| data.crect.width(), data.crect.height()); |
| HIViewSetFrame(osview, &bounds); |
| #else |
| NSRect bounds = NSMakeRect(data.crect.x(), flipYCoordinate(data.crect.y()), |
| data.crect.width(), data.crect.height()); |
| [osview setFrame:bounds]; |
| #endif |
| setWinId((WId)osview); |
| } |
| } else { |
| data.fstrut_dirty = false; // non-toplevel widgets don't have a frame, so no need to update the strut |
| |
| #ifdef QT_MAC_USE_COCOA |
| if (q->testAttribute(Qt::WA_NativeWindow) == false || |
| q->internalWinId() != 0) { |
| #ifdef ALIEN_DEBUG |
| qDebug() << "Skipping native widget creation for" << this; |
| #endif |
| } else |
| #endif |
| if (OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); |
| HIViewSetFrame(osview, &bounds); |
| setWinId((WId)osview); |
| #else |
| NSRect bounds = NSMakeRect(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); |
| [osview setFrame:bounds]; |
| setWinId((WId)osview); |
| #endif |
| if (q->testAttribute(Qt::WA_DropSiteRegistered)) |
| registerDropSite(true); |
| } |
| } |
| |
| updateIsOpaque(); |
| if (q->hasFocus()) |
| setFocus_sys(); |
| if (!topLevel && initializeWindow) |
| setWSGeometry(); |
| if (destroyid) |
| qt_mac_destructView(destroyid); |
| if (q->testAttribute(Qt::WA_AcceptTouchEvents)) |
| registerTouchWindow(); |
| } |
| |
| /*! |
| Returns the QuickDraw handle of the widget. Use of this function is not |
| portable. This function will return 0 if QuickDraw is not supported, or |
| if the handle could not be created. |
| |
| \warning This function is only available on Mac OS X. |
| */ |
| |
| Qt::HANDLE |
| QWidget::macQDHandle() const |
| { |
| #ifndef QT_MAC_USE_COCOA |
| return d_func()->qd_hd; |
| #else |
| return 0; |
| #endif |
| } |
| |
| /*! |
| Returns the CoreGraphics handle of the widget. Use of this function is |
| not portable. This function will return 0 if no painter context can be |
| established, or if the handle could not be created. |
| |
| \warning This function is only available on Mac OS X. |
| */ |
| Qt::HANDLE |
| QWidget::macCGHandle() const |
| { |
| return handle(); |
| } |
| |
| void QWidget::destroy(bool destroyWindow, bool destroySubWindows) |
| { |
| Q_D(QWidget); |
| d->aboutToDestroy(); |
| if (!isWindow() && parentWidget()) |
| parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); |
| d->deactivateWidgetCleanup(); |
| qt_mac_event_release(this); |
| if(testAttribute(Qt::WA_WState_Created)) { |
| QMacCocoaAutoReleasePool pool; |
| setAttribute(Qt::WA_WState_Created, false); |
| QObjectList chldrn = children(); |
| for(int i = 0; i < chldrn.size(); i++) { // destroy all widget children |
| QObject *obj = chldrn.at(i); |
| if(obj->isWidgetType()) |
| static_cast<QWidget*>(obj)->destroy(destroySubWindows, destroySubWindows); |
| } |
| if(mac_mouse_grabber == this) |
| releaseMouse(); |
| if(mac_keyboard_grabber == this) |
| releaseKeyboard(); |
| |
| if(testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal |
| QApplicationPrivate::leaveModal(this); |
| else if((windowType() == Qt::Popup)) |
| qApp->d_func()->closePopup(this); |
| if (destroyWindow) { |
| if(OSViewRef hiview = qt_mac_nativeview_for(this)) { |
| OSWindowRef window = 0; |
| NSDrawer *drawer = nil; |
| #ifdef QT_MAC_USE_COCOA |
| if (qt_mac_is_macdrawer(this)) { |
| drawer = qt_mac_drawer_for(this); |
| } else |
| #endif |
| if (isWindow()) |
| window = qt_mac_window_for(hiview); |
| |
| // Because of how "destruct" works, we have to do just a normal release for the root_win. |
| if (window && window == qt_root_win) { |
| #ifndef QT_MAC_USE_COCOA |
| CFRelease(hiview); |
| #else |
| [hiview release]; |
| #endif |
| } else { |
| qt_mac_destructView(hiview); |
| } |
| if (drawer) |
| qt_mac_destructDrawer(drawer); |
| if (window) |
| qt_mac_destructWindow(window); |
| } |
| } |
| QT_TRY { |
| d->setWinId(0); |
| } QT_CATCH (const std::bad_alloc &) { |
| // swallow - destructors must not throw |
| } |
| } |
| } |
| |
| void QWidgetPrivate::transferChildren() |
| { |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; // Can't add any views anyway |
| |
| QObjectList chlist = q->children(); |
| for (int i = 0; i < chlist.size(); ++i) { |
| QObject *obj = chlist.at(i); |
| if (obj->isWidgetType()) { |
| QWidget *w = (QWidget *)obj; |
| if (!w->isWindow()) { |
| // This seems weird, no need to call it in a loop right? |
| if (!topData()->caption.isEmpty()) |
| setWindowTitle_helper(extra->topextra->caption); |
| if (w->testAttribute(Qt::WA_WState_Created)) { |
| #ifndef QT_MAC_USE_COCOA |
| HIViewAddSubview(qt_mac_nativeview_for(q), qt_mac_nativeview_for(w)); |
| #else |
| // New NSWindows get an extra reference when drops are |
| // registered (at least in 10.5) which means that we may |
| // access the window later and get a crash (becasue our |
| // widget is dead). Work around this be having the drop |
| // site disabled until it is part of the new hierarchy. |
| bool oldRegistered = w->testAttribute(Qt::WA_DropSiteRegistered); |
| w->setAttribute(Qt::WA_DropSiteRegistered, false); |
| [qt_mac_nativeview_for(w) retain]; |
| [qt_mac_nativeview_for(w) removeFromSuperview]; |
| [qt_mac_nativeview_for(q) addSubview:qt_mac_nativeview_for(w)]; |
| [qt_mac_nativeview_for(w) release]; |
| w->setAttribute(Qt::WA_DropSiteRegistered, oldRegistered); |
| #endif |
| } |
| } |
| } |
| } |
| } |
| |
| #ifdef QT_MAC_USE_COCOA |
| void QWidgetPrivate::setSubWindowStacking(bool set) |
| { |
| // After hitting too many unforeseen bugs trying to put Qt on top of the cocoa child |
| // window API, we have decided to revert this behaviour as much as we can. We |
| // therefore now only allow child windows to exist for children of modal dialogs. |
| static bool use_behaviour_qt473 = !qgetenv("QT_MAC_USE_CHILDWINDOWS").isEmpty(); |
| |
| // This will set/remove a visual relationship between parent and child on screen. |
| // The reason for doing this is to ensure that a child always stacks infront of |
| // its parent. Unfortunatly is turns out that [NSWindow addChildWindow] has |
| // several unwanted side-effects, one of them being the moving of a child when |
| // moving the parent, which we choose to accept. A way tougher side-effect is |
| // that Cocoa will hide the parent if you hide the child. And in the case of |
| // a tool window, since it will normally hide when you deactivate the |
| // application, Cocoa will hide the parent upon deactivate as well. The result often |
| // being no more visible windows on screen. So, to make a long story short, we only |
| // allow parent-child relationships between windows that both are either a plain window |
| // or a dialog. |
| |
| Q_Q(QWidget); |
| if (!q->isWindow()) |
| return; |
| NSWindow *qwin = [qt_mac_nativeview_for(q) window]; |
| if (!qwin) |
| return; |
| Qt::WindowType qtype = q->windowType(); |
| if (set && !(qtype == Qt::Window || qtype == Qt::Dialog)) |
| return; |
| if (set && ![qwin isVisible]) |
| return; |
| |
| if (QWidget *parent = q->parentWidget()) { |
| if (NSWindow *pwin = [qt_mac_nativeview_for(parent) window]) { |
| if (set) { |
| Qt::WindowType ptype = parent->window()->windowType(); |
| if ([pwin isVisible] |
| && (ptype == Qt::Window || ptype == Qt::Dialog) |
| && ![qwin parentWindow] |
| && (use_behaviour_qt473 || parent->windowModality() == Qt::ApplicationModal)) { |
| NSInteger level = [qwin level]; |
| [pwin addChildWindow:qwin ordered:NSWindowAbove]; |
| if ([qwin level] < level) |
| [qwin setLevel:level]; |
| } |
| } else { |
| [pwin removeChildWindow:qwin]; |
| } |
| } |
| } |
| |
| // Only set-up child windows for q if q is modal: |
| if (set && !use_behaviour_qt473 && q->windowModality() != Qt::ApplicationModal) |
| return; |
| |
| QObjectList widgets = q->children(); |
| for (int i=0; i<widgets.size(); ++i) { |
| QWidget *child = qobject_cast<QWidget *>(widgets.at(i)); |
| if (child && child->isWindow()) { |
| if (NSWindow *cwin = [qt_mac_nativeview_for(child) window]) { |
| if (set) { |
| Qt::WindowType ctype = child->window()->windowType(); |
| if ([cwin isVisible] && (ctype == Qt::Window || ctype == Qt::Dialog) && ![cwin parentWindow]) { |
| NSInteger level = [cwin level]; |
| [qwin addChildWindow:cwin ordered:NSWindowAbove]; |
| if ([cwin level] < level) |
| [cwin setLevel:level]; |
| } |
| } else { |
| [qwin removeChildWindow:qt_mac_window_for(child)]; |
| } |
| } |
| } |
| } |
| } |
| #endif |
| |
| void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) |
| { |
| Q_Q(QWidget); |
| QMacCocoaAutoReleasePool pool; |
| QTLWExtra *topData = maybeTopData(); |
| bool wasCreated = q->testAttribute(Qt::WA_WState_Created); |
| #ifdef QT_MAC_USE_COCOA |
| bool wasWindow = q->isWindow(); |
| #endif |
| OSViewRef old_id = 0; |
| |
| if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) |
| q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); |
| |
| // Maintain the glWidgets list on parent change: remove "our" gl widgets |
| // from the list on the old parent and grandparents. |
| if (glWidgets.isEmpty() == false) { |
| QWidget *current = q->parentWidget(); |
| while (current) { |
| for (QList<QWidgetPrivate::GlWidgetInfo>::const_iterator it = glWidgets.constBegin(); |
| it != glWidgets.constEnd(); ++it) |
| current->d_func()->glWidgets.removeAll(*it); |
| |
| if (current->isWindow()) |
| break; |
| current = current->parentWidget(); |
| } |
| } |
| |
| #ifndef QT_MAC_USE_COCOA |
| EventHandlerRef old_window_event = 0; |
| #else |
| bool oldToolbarVisible = false; |
| NSDrawer *oldDrawer = nil; |
| NSToolbar *oldToolbar = 0; |
| #endif |
| if (wasCreated && !(q->windowType() == Qt::Desktop)) { |
| old_id = qt_mac_nativeview_for(q); |
| #ifndef QT_MAC_USE_COCOA |
| old_window_event = window_event; |
| #else |
| OSWindowRef oldWindow = qt_mac_window_for(old_id); |
| if (qt_mac_is_macdrawer(q)) { |
| oldDrawer = qt_mac_drawer_for(q); |
| } |
| if (wasWindow) { |
| oldToolbar = [oldWindow toolbar]; |
| if (oldToolbar) { |
| [oldToolbar retain]; |
| oldToolbarVisible = [oldToolbar isVisible]; |
| [oldWindow setToolbar:nil]; |
| } |
| } |
| #endif |
| } |
| QWidget* oldtlw = q->window(); |
| |
| if (q->testAttribute(Qt::WA_DropSiteRegistered)) |
| q->setAttribute(Qt::WA_DropSiteRegistered, false); |
| |
| //recreate and setup flags |
| QObjectPrivate::setParent_helper(parent); |
| bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); |
| if (wasCreated && !qt_isGenuineQWidget(q)) |
| return; |
| |
| if (!q->testAttribute(Qt::WA_WState_WindowOpacitySet)) { |
| q->setWindowOpacity(1.0f); |
| q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); |
| } |
| |
| setWinId(0); //do after the above because they may want the id |
| |
| data.window_flags = f; |
| q->setAttribute(Qt::WA_WState_Created, false); |
| q->setAttribute(Qt::WA_WState_Visible, false); |
| q->setAttribute(Qt::WA_WState_Hidden, false); |
| adjustFlags(data.window_flags, q); |
| // keep compatibility with previous versions, we need to preserve the created state. |
| // (but we recreate the winId for the widget being reparented, again for compatibility, |
| // unless this is an alien widget. ) |
| const bool nonWindowWithCreatedParent = !q->isWindow() && parent->testAttribute(Qt::WA_WState_Created); |
| const bool nativeWidget = q->internalWinId() != 0; |
| if (wasCreated || nativeWidget && nonWindowWithCreatedParent) { |
| createWinId(); |
| if (q->isWindow()) { |
| #ifndef QT_MAC_USE_COCOA |
| // We do this down below for wasCreated, so avoid doing this twice |
| // (only for performance, it gets called a lot anyway). |
| if (!wasCreated) { |
| if (QMainWindowLayout *mwl = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q))) { |
| mwl->updateHIToolBarStatus(); |
| } |
| } |
| #else |
| // Simply transfer our toolbar over. Everything should stay put, unlike in Carbon. |
| if (oldToolbar && !(f & Qt::FramelessWindowHint)) { |
| OSWindowRef newWindow = qt_mac_window_for(q); |
| [newWindow setToolbar:oldToolbar]; |
| [oldToolbar release]; |
| [oldToolbar setVisible:oldToolbarVisible]; |
| } |
| #endif |
| } |
| } |
| if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) |
| q->setAttribute(Qt::WA_WState_Hidden); |
| q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); |
| |
| if (wasCreated) { |
| transferChildren(); |
| #ifndef QT_MAC_USE_COCOA |
| // If we were a unified window, We just transfered our toolbars out of the unified toolbar. |
| // So redo the status one more time. It apparently is not an issue with Cocoa. |
| if (q->isWindow()) { |
| if (QMainWindowLayout *mwl = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q))) { |
| mwl->updateHIToolBarStatus(); |
| } |
| } |
| #endif |
| |
| if (topData && |
| (!topData->caption.isEmpty() || !topData->filePath.isEmpty())) |
| setWindowTitle_helper(q->windowTitle()); |
| } |
| |
| if (q->testAttribute(Qt::WA_AcceptDrops) |
| || (!q->isWindow() && q->parentWidget() |
| && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) |
| q->setAttribute(Qt::WA_DropSiteRegistered, true); |
| |
| //cleanup |
| #ifndef QT_MAC_USE_COCOA |
| if (old_window_event) |
| RemoveEventHandler(old_window_event); |
| #endif |
| if (old_id) { //don't need old window anymore |
| OSWindowRef window = (oldtlw == q) ? qt_mac_window_for(old_id) : 0; |
| qt_mac_destructView(old_id); |
| |
| #ifdef QT_MAC_USE_COCOA |
| if (oldDrawer) { |
| qt_mac_destructDrawer(oldDrawer); |
| } else |
| #endif |
| if (window) |
| qt_mac_destructWindow(window); |
| } |
| |
| // Maintain the glWidgets list on parent change: add "our" gl widgets |
| // to the list on the new parent and grandparents. |
| if (glWidgets.isEmpty() == false) { |
| QWidget *current = q->parentWidget(); |
| while (current) { |
| current->d_func()->glWidgets += glWidgets; |
| if (current->isWindow()) |
| break; |
| current = current->parentWidget(); |
| } |
| } |
| invalidateBuffer(q->rect()); |
| qt_event_request_window_change(q); |
| } |
| |
| QPoint QWidget::mapToGlobal(const QPoint &pos) const |
| { |
| Q_D(const QWidget); |
| if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { |
| QPoint p = pos + data->crect.topLeft(); |
| return isWindow() ? p : parentWidget()->mapToGlobal(p); |
| } |
| #ifndef QT_MAC_USE_COCOA |
| QPoint tmp = d->mapToWS(pos); |
| HIPoint hi_pos = CGPointMake(tmp.x(), tmp.y()); |
| HIViewConvertPoint(&hi_pos, qt_mac_nativeview_for(this), 0); |
| Rect win_rect; |
| GetWindowBounds(qt_mac_window_for(this), kWindowStructureRgn, &win_rect); |
| return QPoint((int)hi_pos.x+win_rect.left, (int)hi_pos.y+win_rect.top); |
| #else |
| QPoint tmp = d->mapToWS(pos); |
| NSPoint hi_pos = NSMakePoint(tmp.x(), tmp.y()); |
| hi_pos = [qt_mac_nativeview_for(this) convertPoint:hi_pos toView:nil]; |
| NSRect win_rect = [qt_mac_window_for(this) frame]; |
| hi_pos.x += win_rect.origin.x; |
| hi_pos.y += win_rect.origin.y; |
| // If we aren't the desktop we need to flip, if you flip the desktop on itself, you get the other problem. |
| return ((window()->windowFlags() & Qt::Desktop) == Qt::Desktop) ? QPointF(hi_pos.x, hi_pos.y).toPoint() |
| : flipPoint(hi_pos).toPoint(); |
| #endif |
| } |
| |
| QPoint QWidget::mapFromGlobal(const QPoint &pos) const |
| { |
| Q_D(const QWidget); |
| if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { |
| QPoint p = isWindow() ? pos : parentWidget()->mapFromGlobal(pos); |
| return p - data->crect.topLeft(); |
| } |
| #ifndef QT_MAC_USE_COCOA |
| Rect win_rect; |
| GetWindowBounds(qt_mac_window_for(this), kWindowStructureRgn, &win_rect); |
| HIPoint hi_pos = CGPointMake(pos.x()-win_rect.left, pos.y()-win_rect.top); |
| HIViewConvertPoint(&hi_pos, 0, qt_mac_nativeview_for(this)); |
| return d->mapFromWS(QPoint((int)hi_pos.x, (int)hi_pos.y)); |
| #else |
| NSRect win_rect = [qt_mac_window_for(this) frame]; |
| // The Window point is in "Cocoa coordinates," but the view is in "Qt coordinates" |
| // so make sure to keep them in sync. |
| NSPoint hi_pos = NSMakePoint(pos.x()-win_rect.origin.x, |
| flipYCoordinate(pos.y())-win_rect.origin.y); |
| hi_pos = [qt_mac_nativeview_for(this) convertPoint:hi_pos fromView:0]; |
| return d->mapFromWS(QPoint(qRound(hi_pos.x), qRound(hi_pos.y))); |
| #endif |
| } |
| |
| void QWidgetPrivate::updateSystemBackground() |
| { |
| } |
| |
| void QWidgetPrivate::setCursor_sys(const QCursor &) |
| { |
| #ifndef QT_MAC_USE_COCOA |
| qt_mac_update_cursor(); |
| #else |
| Q_Q(QWidget); |
| if (q->testAttribute(Qt::WA_WState_Created)) { |
| QMacCocoaAutoReleasePool pool; |
| [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; |
| } |
| #endif |
| } |
| |
| void QWidgetPrivate::unsetCursor_sys() |
| { |
| #ifndef QT_MAC_USE_COCOA |
| qt_mac_update_cursor(); |
| #else |
| Q_Q(QWidget); |
| if (q->testAttribute(Qt::WA_WState_Created)) { |
| QMacCocoaAutoReleasePool pool; |
| [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; |
| } |
| #endif |
| } |
| |
| void QWidgetPrivate::setWindowTitle_sys(const QString &caption) |
| { |
| Q_Q(QWidget); |
| if (q->isWindow()) { |
| #ifndef QT_MAC_USE_COCOA |
| SetWindowTitleWithCFString(qt_mac_window_for(q), QCFString(caption)); |
| #else |
| QMacCocoaAutoReleasePool pool; |
| [qt_mac_window_for(q) setTitle:qt_mac_QStringToNSString(caption)]; |
| #endif |
| } |
| } |
| |
| void QWidgetPrivate::setWindowModified_sys(bool mod) |
| { |
| Q_Q(QWidget); |
| if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) { |
| #ifndef QT_MAC_USE_COCOA |
| SetWindowModified(qt_mac_window_for(q), mod); |
| #else |
| [qt_mac_window_for(q) setDocumentEdited:mod]; |
| #endif |
| } |
| } |
| |
| void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath) |
| { |
| Q_Q(QWidget); |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| QFileInfo fi(filePath); |
| [qt_mac_window_for(q) setRepresentedFilename:fi.exists() ? qt_mac_QStringToNSString(filePath) : @""]; |
| #else |
| bool validRef = false; |
| FSRef ref; |
| bzero(&ref, sizeof(ref)); |
| OSStatus status; |
| |
| if (!filePath.isEmpty()) { |
| status = FSPathMakeRef(reinterpret_cast<const UInt8 *>(filePath.toUtf8().constData()), &ref, 0); |
| validRef = (status == noErr); |
| } |
| // Set the proxy regardless, since this is our way of clearing it as well, but ignore the |
| // return value as well. |
| if (validRef) { |
| status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref); |
| } else { |
| status = RemoveWindowProxy(qt_mac_window_for(q)); |
| } |
| if (status != noErr) |
| qWarning("QWidget::setWindowFilePath: Error setting proxyicon for path (%s):%ld", |
| qPrintable(filePath), status); |
| #endif |
| } |
| |
| void QWidgetPrivate::setWindowIcon_sys(bool forceReset) |
| { |
| Q_Q(QWidget); |
| |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; |
| |
| QTLWExtra *topData = this->topData(); |
| if (topData->iconPixmap && !forceReset) // already set |
| return; |
| |
| QIcon icon = q->windowIcon(); |
| QPixmap *pm = 0; |
| if (!icon.isNull()) { |
| // now create the extra |
| if (!topData->iconPixmap) { |
| pm = new QPixmap(icon.pixmap(QSize(22, 22))); |
| topData->iconPixmap = pm; |
| } else { |
| pm = topData->iconPixmap; |
| } |
| } |
| if (q->isWindow()) { |
| #ifndef QT_MAC_USE_COCOA |
| IconRef previousIcon = 0; |
| if (icon.isNull()) { |
| RemoveWindowProxy(qt_mac_window_for(q)); |
| previousIcon = topData->windowIcon; |
| topData->windowIcon = 0; |
| } else { |
| WindowClass wclass; |
| GetWindowClass(qt_mac_window_for(q), &wclass); |
| |
| if (wclass == kDocumentWindowClass) { |
| IconRef newIcon = qt_mac_create_iconref(*pm); |
| previousIcon = topData->windowIcon; |
| topData->windowIcon = newIcon; |
| SetWindowProxyIcon(qt_mac_window_for(q), newIcon); |
| } |
| } |
| |
| // Release the previous icon if it was set by this function. |
| if (previousIcon != 0) |
| ReleaseIconRef(previousIcon); |
| #else |
| QMacCocoaAutoReleasePool pool; |
| NSButton *iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton]; |
| if (iconButton == nil) { |
| QCFString string(q->windowTitle()); |
| const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); |
| [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:tmpString]]; |
| iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton]; |
| } |
| if (icon.isNull()) { |
| [iconButton setImage:nil]; |
| } else { |
| QPixmap scaled = pm->scaled(QSize(16,16), Qt::KeepAspectRatio, Qt::SmoothTransformation); |
| NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(scaled)); |
| [iconButton setImage:image]; |
| [image release]; |
| } |
| #endif |
| } |
| } |
| |
| void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) |
| { |
| Q_Q(QWidget); |
| if(q->isWindow() && !iconText.isEmpty()) { |
| #ifndef QT_MAC_USE_COCOA |
| SetWindowAlternateTitle(qt_mac_window_for(q), QCFString(iconText)); |
| #else |
| QMacCocoaAutoReleasePool pool; |
| [qt_mac_window_for(q) setMiniwindowTitle:qt_mac_QStringToNSString(iconText)]; |
| #endif |
| } |
| } |
| |
| void QWidget::grabMouse() |
| { |
| if(isVisible() && !qt_nograb()) { |
| if(mac_mouse_grabber) |
| mac_mouse_grabber->releaseMouse(); |
| mac_mouse_grabber=this; |
| } |
| } |
| |
| #ifndef QT_NO_CURSOR |
| void QWidget::grabMouse(const QCursor &) |
| { |
| if(isVisible() && !qt_nograb()) { |
| if(mac_mouse_grabber) |
| mac_mouse_grabber->releaseMouse(); |
| mac_mouse_grabber=this; |
| } |
| } |
| #endif |
| |
| void QWidget::releaseMouse() |
| { |
| if(!qt_nograb() && mac_mouse_grabber == this) |
| mac_mouse_grabber = 0; |
| } |
| |
| void QWidget::grabKeyboard() |
| { |
| if(!qt_nograb()) { |
| if(mac_keyboard_grabber) |
| mac_keyboard_grabber->releaseKeyboard(); |
| mac_keyboard_grabber = this; |
| } |
| } |
| |
| void QWidget::releaseKeyboard() |
| { |
| if(!qt_nograb() && mac_keyboard_grabber == this) |
| mac_keyboard_grabber = 0; |
| } |
| |
| QWidget *QWidget::mouseGrabber() |
| { |
| return mac_mouse_grabber; |
| } |
| |
| QWidget *QWidget::keyboardGrabber() |
| { |
| return mac_keyboard_grabber; |
| } |
| |
| void QWidget::activateWindow() |
| { |
| QWidget *tlw = window(); |
| if(!tlw->isVisible() || !tlw->isWindow() || (tlw->windowType() == Qt::Desktop)) |
| return; |
| qt_event_remove_activate(); |
| |
| QWidget *fullScreenWidget = tlw; |
| QWidget *parentW = tlw; |
| // Find the oldest parent or the parent with fullscreen, whichever comes first. |
| while (parentW) { |
| fullScreenWidget = parentW->window(); |
| if (fullScreenWidget->windowState() & Qt::WindowFullScreen) |
| break; |
| parentW = fullScreenWidget->parentWidget(); |
| } |
| |
| if (fullScreenWidget->windowType() != Qt::ToolTip) { |
| qt_mac_set_fullscreen_mode((fullScreenWidget->windowState() & Qt::WindowFullScreen) && |
| qApp->desktop()->screenNumber(this) == 0); |
| } |
| |
| bool windowActive; |
| OSWindowRef win = qt_mac_window_for(tlw); |
| #ifndef QT_MAC_USE_COCOA |
| windowActive = IsWindowActive(win); |
| #else |
| QMacCocoaAutoReleasePool pool; |
| windowActive = [win isKeyWindow]; |
| #endif |
| if ((tlw->windowType() == Qt::Popup) |
| || (tlw->windowType() == Qt::Tool) |
| || qt_mac_is_macdrawer(tlw) |
| || windowActive) { |
| #ifndef QT_MAC_USE_COCOA |
| ActivateWindow(win, true); |
| qApp->setActiveWindow(tlw); |
| #else |
| [win makeKeyWindow]; |
| #endif |
| } else if(!isMinimized()) { |
| #ifndef QT_MAC_USE_COCOA |
| SelectWindow(win); |
| #else |
| [win makeKeyAndOrderFront:win]; |
| #endif |
| } |
| } |
| |
| QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() |
| { |
| return new QMacWindowSurface(q_func()); |
| } |
| |
| void QWidgetPrivate::update_sys(const QRect &r) |
| { |
| Q_Q(QWidget); |
| if (r == q->rect()) { |
| if (updateRedirectedToGraphicsProxyWidget(q, r)) |
| return; |
| dirtyOnWidget += r; |
| #ifndef QT_MAC_USE_COCOA |
| HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); |
| #else |
| qt_mac_set_needs_display(q, QRegion()); |
| #endif |
| return; |
| } |
| |
| int x = r.x(), y = r.y(), w = r.width(), h = r.height(); |
| if (w < 0) |
| w = q->data->crect.width() - x; |
| if (h < 0) |
| h = q->data->crect.height() - y; |
| if (w && h) { |
| const QRect updateRect = QRect(x, y, w, h); |
| if (updateRedirectedToGraphicsProxyWidget(q, updateRect)) |
| return; |
| #ifndef QT_MAC_USE_COCOA |
| dirtyOnWidget += updateRect; |
| HIRect r = CGRectMake(x, y, w, h); |
| HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true); |
| #else |
| [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(x, y, w, h)]; |
| #endif |
| } |
| } |
| |
| void QWidgetPrivate::update_sys(const QRegion &rgn) |
| { |
| Q_Q(QWidget); |
| if (updateRedirectedToGraphicsProxyWidget(q, rgn)) |
| return; |
| dirtyOnWidget += rgn; |
| #ifndef QT_MAC_USE_COCOA |
| RgnHandle rgnHandle = rgn.toQDRgnForUpdate_sys(); |
| if (rgnHandle) |
| HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true); |
| else { |
| HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow. |
| } |
| #else |
| // Alien support: get the first native ancestor widget (will be q itself in the non-alien case), |
| // map the coordinates from q space to NSView space and invalidate the rect. |
| QWidget *nativeParent = q->internalWinId() ? q : q->nativeParentWidget(); |
| if (nativeParent == 0) |
| return; |
| |
| QVector<QRect> rects = rgn.rects(); |
| for (int i = 0; i < rects.count(); ++i) { |
| const QRect &rect = rects.at(i); |
| |
| const QRect nativeBoundingRect = QRect( |
| QPoint(q->mapTo(nativeParent, rect.topLeft())), |
| QSize(rect.size())); |
| |
| [qt_mac_nativeview_for(nativeParent) setNeedsDisplayInRect:NSMakeRect(nativeBoundingRect.x(), |
| nativeBoundingRect.y(), nativeBoundingRect.width(), |
| nativeBoundingRect.height())]; |
| } |
| #endif |
| } |
| |
| bool QWidgetPrivate::isRealWindow() const |
| { |
| return q_func()->isWindow() && !topData()->embedded; |
| } |
| |
| void QWidgetPrivate::show_sys() |
| { |
| Q_Q(QWidget); |
| if ((q->windowType() == Qt::Desktop)) //desktop is always visible |
| return; |
| |
| invalidateBuffer(q->rect()); |
| if (q->testAttribute(Qt::WA_OutsideWSRange)) |
| return; |
| QMacCocoaAutoReleasePool pool; |
| q->setAttribute(Qt::WA_Mapped); |
| if (q->testAttribute(Qt::WA_DontShowOnScreen)) |
| return; |
| |
| bool realWindow = isRealWindow(); |
| #ifndef QT_MAC_USE_COCOA |
| if (realWindow && !q->testAttribute(Qt::WA_Moved)) { |
| if (qt_mac_is_macsheet(q)) |
| recreateMacWindow(); |
| q->createWinId(); |
| if (QWidget *p = q->parentWidget()) { |
| p->createWinId(); |
| RepositionWindow(qt_mac_window_for(q), qt_mac_window_for(p), kWindowCenterOnParentWindow); |
| } else { |
| RepositionWindow(qt_mac_window_for(q), 0, kWindowCenterOnMainScreen); |
| } |
| } |
| #endif |
| |
| data.fstrut_dirty = true; |
| if (realWindow) { |
| // Delegates can change window state, so record some things earlier. |
| bool isCurrentlyMinimized = (q->windowState() & Qt::WindowMinimized); |
| setModal_sys(); |
| OSWindowRef window = qt_mac_window_for(q); |
| #ifndef QT_MAC_USE_COCOA |
| SizeWindow(window, q->width(), q->height(), true); |
| #endif |
| |
| #ifdef QT_MAC_USE_COCOA |
| // Make sure that we end up sending a repaint event to |
| // the widget if the window has been visible one before: |
| [qt_mac_get_contentview_for(window) setNeedsDisplay:YES]; |
| #endif |
| if(qt_mac_is_macsheet(q)) { |
| qt_event_request_showsheet(q); |
| } else if(qt_mac_is_macdrawer(q)) { |
| #ifndef QT_MAC_USE_COCOA |
| OpenDrawer(window, kWindowEdgeDefault, false); |
| #else |
| NSDrawer *drawer = qt_mac_drawer_for(q); |
| [drawer openOnEdge:[drawer preferredEdge]]; |
| #endif |
| } else { |
| #ifndef QT_MAC_USE_COCOA |
| ShowHide(window, true); |
| #else |
| // sync the opacity value back (in case of a fade). |
| [window setAlphaValue:q->windowOpacity()]; |
| |
| QWidget *top = 0; |
| if (QApplicationPrivate::tryModalHelper(q, &top)) { |
| [window makeKeyAndOrderFront:window]; |
| // If this window is app modal, we need to start spinning |
| // a modal session for it. Interrupting |
| // the event dispatcher will make this happend: |
| if (data.window_modality == Qt::ApplicationModal) |
| QEventDispatcherMac::instance()->interrupt(); |
| } else { |
| // The window is modally shaddowed, so we need to make |
| // sure that we don't pop in front of the modal window: |
| [window orderFront:window]; |
| if (!top->testAttribute(Qt::WA_DontShowOnScreen)) { |
| if (NSWindow *modalWin = qt_mac_window_for(top)) |
| [modalWin orderFront:window]; |
| } |
| } |
| setSubWindowStacking(true); |
| #endif |
| if (q->windowType() == Qt::Popup) { |
| if (q->focusWidget()) |
| q->focusWidget()->d_func()->setFocus_sys(); |
| else |
| setFocus_sys(); |
| } |
| toggleDrawers(true); |
| } |
| if (isCurrentlyMinimized) { //show in collapsed state |
| #ifndef QT_MAC_USE_COCOA |
| CollapseWindow(window, true); |
| #else |
| [window miniaturize:window]; |
| #endif |
| } else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) { |
| #ifndef QT_MAC_USE_COCOA |
| qt_event_request_activate(q); |
| #endif |
| } |
| } else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) { |
| #ifndef QT_MAC_USE_COCOA |
| HIViewSetVisible(qt_mac_nativeview_for(q), true); |
| #else |
| [qt_mac_nativeview_for(q) setHidden:NO]; |
| |
| #endif |
| } |
| |
| if (!QWidget::mouseGrabber()){ |
| QWidget *enterWidget = QApplication::widgetAt(QCursor::pos()); |
| QApplicationPrivate::dispatchEnterLeave(enterWidget, qt_mouseover); |
| qt_mouseover = enterWidget; |
| } |
| |
| qt_event_request_window_change(q); |
| } |
| |
| |
| QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt) |
| { |
| #ifndef QT_MAC_USE_COCOA |
| CGPoint nativePoint = CGPointMake(pt.x(), pt.y()); |
| HIViewConvertPoint(&nativePoint, qt_mac_nativeview_for(child->parentWidget()), |
| qt_mac_nativeview_for(child)); |
| #else |
| NSPoint nativePoint = [qt_mac_nativeview_for(child) convertPoint:NSMakePoint(pt.x(), pt.y()) fromView:qt_mac_nativeview_for(child->parentWidget())]; |
| #endif |
| return QPoint(nativePoint.x, nativePoint.y); |
| } |
| |
| |
| void QWidgetPrivate::hide_sys() |
| { |
| Q_Q(QWidget); |
| if((q->windowType() == Qt::Desktop)) //you can't hide the desktop! |
| return; |
| QMacCocoaAutoReleasePool pool; |
| if(q->isWindow()) { |
| #ifdef QT_MAC_USE_COCOA |
| setSubWindowStacking(false); |
| #endif |
| OSWindowRef window = qt_mac_window_for(q); |
| if(qt_mac_is_macsheet(q)) { |
| #ifndef QT_MAC_USE_COCOA |
| WindowRef parent = 0; |
| if(GetSheetWindowParent(window, &parent) != noErr || !parent) |
| ShowHide(window, false); |
| else |
| HideSheetWindow(window); |
| #else |
| [NSApp endSheet:window]; |
| [window orderOut:window]; |
| #endif |
| } else if(qt_mac_is_macdrawer(q)) { |
| #ifndef QT_MAC_USE_COCOA |
| CloseDrawer(window, false); |
| #else |
| [qt_mac_drawer_for(q) close]; |
| #endif |
| } else { |
| #ifndef QT_MAC_USE_COCOA |
| ShowHide(window, false); |
| #else |
| [window orderOut:window]; |
| // Unfortunately it is not as easy as just hiding the window, we need |
| // to find out if we were in full screen mode. If we were and this is |
| // the last window in full screen mode then we need to unset the full screen |
| // mode. If this is not the last visible window in full screen mode then we |
| // don't change the full screen mode. |
| if(q->isFullScreen()) |
| { |
| bool keepFullScreen = false; |
| QWidgetList windowList = qApp->topLevelWidgets(); |
| int windowCount = windowList.count(); |
| for(int i = 0; i < windowCount; i++) |
| { |
| QWidget *w = windowList[i]; |
| // If it is the same window, we don't need to check :-) |
| if(q == w) |
| continue; |
| // If they are not visible or if they are minimized then |
| // we just ignore them. |
| if(!w->isVisible() || w->isMinimized()) |
| continue; |
| // Is it full screen? |
| // Notice that if there is one window in full screen mode then we |
| // cannot switch the full screen mode off, therefore we just abort. |
| if(w->isFullScreen()) { |
| keepFullScreen = true; |
| break; |
| } |
| } |
| // No windows in full screen mode, so let just unset that flag. |
| if(!keepFullScreen) |
| qt_mac_set_fullscreen_mode(false); |
| } |
| #endif |
| toggleDrawers(false); |
| #ifndef QT_MAC_USE_COCOA |
| // Clear modality (because it seems something that we've always done). |
| if (data.window_modality != Qt::NonModal) { |
| SetWindowModality(window, kWindowModalityNone, |
| q->parentWidget() ? qt_mac_window_for(q->parentWidget()->window()) : 0); |
| } |
| #endif |
| } |
| #ifndef QT_MAC_USE_COCOA |
| // If the window we now hide was the active window, we need |
| // to find, and activate another window on screen. NB: Cocoa takes care of this |
| // logic for us (and distinquishes between main windows and key windows) |
| if (q->isActiveWindow() && !(q->windowType() == Qt::Popup)) { |
| QWidget *w = 0; |
| if(q->parentWidget()) |
| w = q->parentWidget()->window(); |
| if(!w || (!w->isVisible() && !w->isMinimized())) { |
| for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true); |
| wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) { |
| if((w = qt_mac_find_window(wp))) |
| break; |
| } |
| if (!w){ |
| for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true); |
| wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) { |
| if((w = qt_mac_find_window(wp))) |
| break; |
| } |
| } |
| if (!w){ |
| for(WindowPtr wp = GetFrontWindowOfClass(kSimpleWindowClass, true); |
| wp; wp = GetNextWindowOfClass(wp, kSimpleWindowClass, true)) { |
| if((w = qt_mac_find_window(wp))) |
| break; |
| } |
| } |
| } |
| if(w && w->isVisible() && !w->isMinimized()) { |
| qt_event_request_activate(w); |
| } |
| } |
| #endif |
| } else { |
| invalidateBuffer(q->rect()); |
| #ifndef QT_MAC_USE_COCOA |
| HIViewSetVisible(qt_mac_nativeview_for(q), false); |
| #else |
| [qt_mac_nativeview_for(q) setHidden:YES]; |
| #endif |
| } |
| |
| if (!QWidget::mouseGrabber()){ |
| QWidget *enterWidget = QApplication::widgetAt(QCursor::pos()); |
| if (enterWidget && enterWidget->data->in_destructor) |
| enterWidget = 0; |
| QApplicationPrivate::dispatchEnterLeave(enterWidget, qt_mouseover); |
| qt_mouseover = enterWidget; |
| } |
| |
| qt_event_request_window_change(q); |
| deactivateWidgetCleanup(); |
| qt_mac_event_release(q); |
| } |
| |
| void QWidget::setWindowState(Qt::WindowStates newstate) |
| { |
| Q_D(QWidget); |
| bool needShow = false; |
| Qt::WindowStates oldstate = windowState(); |
| if (oldstate == newstate) |
| return; |
| |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| #endif |
| bool needSendStateChange = true; |
| if(isWindow()) { |
| if((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { |
| if(newstate & Qt::WindowFullScreen) { |
| if(QTLWExtra *tlextra = d->topData()) { |
| if(tlextra->normalGeometry.width() < 0) { |
| if(!testAttribute(Qt::WA_Resized)) |
| adjustSize(); |
| tlextra->normalGeometry = geometry(); |
| } |
| tlextra->savedFlags = windowFlags(); |
| } |
| needShow = isVisible(); |
| const QRect fullscreen(qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(this))); |
| setParent(parentWidget(), Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); //save |
| setGeometry(fullscreen); |
| if(!qApp->desktop()->screenNumber(this)) |
| qt_mac_set_fullscreen_mode(true); |
| } else { |
| needShow = isVisible(); |
| if(!qApp->desktop()->screenNumber(this)) |
| qt_mac_set_fullscreen_mode(false); |
| setParent(parentWidget(), d->topData()->savedFlags); |
| setGeometry(d->topData()->normalGeometry); |
| d->topData()->normalGeometry.setRect(0, 0, -1, -1); |
| } |
| } |
| |
| d->createWinId(); |
| |
| OSWindowRef window = qt_mac_window_for(this); |
| if((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { |
| if (newstate & Qt::WindowMinimized) { |
| #ifndef QT_MAC_USE_COCOA |
| CollapseWindow(window, true); |
| #else |
| [window miniaturize:window]; |
| #endif |
| } else { |
| #ifndef QT_MAC_USE_COCOA |
| CollapseWindow(window, false); |
| #else |
| [window deminiaturize:window]; |
| #endif |
| } |
| needSendStateChange = oldstate == windowState(); // Collapse didn't change our flags. |
| } |
| |
| if((newstate & Qt::WindowMaximized) && !((newstate & Qt::WindowFullScreen))) { |
| if(QTLWExtra *tlextra = d->topData()) { |
| if(tlextra->normalGeometry.width() < 0) { |
| if(!testAttribute(Qt::WA_Resized)) |
| adjustSize(); |
| tlextra->normalGeometry = geometry(); |
| } |
| } |
| } else if(!(newstate & Qt::WindowFullScreen)) { |
| // d->topData()->normalGeometry = QRect(0, 0, -1, -1); |
| } |
| |
| #ifdef DEBUG_WINDOW_STATE |
| #define WSTATE(x) qDebug("%s -- %s --> %s", #x, (oldstate & x) ? "true" : "false", (newstate & x) ? "true" : "false") |
| WSTATE(Qt::WindowMinimized); |
| WSTATE(Qt::WindowMaximized); |
| WSTATE(Qt::WindowFullScreen); |
| #undef WSTATE |
| #endif |
| if(!(newstate & (Qt::WindowMinimized|Qt::WindowFullScreen)) && |
| ((oldstate & Qt::WindowFullScreen) || (oldstate & Qt::WindowMinimized) || |
| (oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized))) { |
| if(newstate & Qt::WindowMaximized) { |
| data->fstrut_dirty = true; |
| #ifndef QT_MAC_USE_COCOA |
| HIToolbarRef toolbarRef; |
| if (GetWindowToolbar(window, &toolbarRef) == noErr && toolbarRef |
| && !isVisible() && !IsWindowToolbarVisible(window)) { |
| // HIToolbar, needs to be shown so that it's in the structure window |
| // Typically this is part of a main window and will get shown |
| // during the show, but it's will make the maximize all wrong. |
| ShowHideWindowToolbar(window, true, false); |
| d->updateFrameStrut(); // In theory the dirty would work, but it's optimized out if the window is not visible :( |
| } |
| Rect bounds; |
| QDesktopWidget *dsk = QApplication::desktop(); |
| QRect avail = dsk->availableGeometry(dsk->screenNumber(this)); |
| SetRect(&bounds, avail.x(), avail.y(), avail.x() + avail.width(), avail.y() + avail.height()); |
| if(QWExtra *extra = d->extraData()) { |
| if(bounds.right - bounds.left > extra->maxw) |
| bounds.right = bounds.left + extra->maxw; |
| if(bounds.bottom - bounds.top > extra->maxh) |
| bounds.bottom = bounds.top + extra->maxh; |
| } |
| if(d->topData()) { |
| QRect fs = d->frameStrut(); |
| bounds.left += fs.left(); |
| if(bounds.right < avail.x()+avail.width()) |
| bounds.right = qMin<short>((uint)avail.x()+avail.width(), bounds.right+fs.left()); |
| if(bounds.bottom < avail.y()+avail.height()) |
| bounds.bottom = qMin<short>((uint)avail.y()+avail.height(), bounds.bottom+fs.top()); |
| bounds.top += fs.top(); |
| bounds.right -= fs.right(); |
| bounds.bottom -= fs.bottom(); |
| } |
| QRect orect(geometry().x(), geometry().y(), width(), height()), |
| nrect(bounds.left, bounds.top, bounds.right - bounds.left, |
| bounds.bottom - bounds.top); |
| if(orect != nrect) { // the new rect differ from the old |
| Point idealSize = { nrect.height(), nrect.width() }; |
| ZoomWindowIdeal(window, inZoomOut, &idealSize); |
| } |
| #else |
| NSToolbar *toolbarRef = [window toolbar]; |
| if (toolbarRef && !isVisible() && ![toolbarRef isVisible]) { |
| // HIToolbar, needs to be shown so that it's in the structure window |
| // Typically this is part of a main window and will get shown |
| // during the show, but it's will make the maximize all wrong. |
| // ### Not sure this is right for NSToolbar... |
| [toolbarRef setVisible:true]; |
| // ShowHideWindowToolbar(window, true, false); |
| d->updateFrameStrut(); // In theory the dirty would work, but it's optimized out if the window is not visible :( |
| } |
| // Everything should be handled by Cocoa. |
| [window zoom:window]; |
| #endif |
| needSendStateChange = oldstate == windowState(); // Zoom didn't change flags. |
| } else if(oldstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen)) { |
| #ifndef QT_MAC_USE_COCOA |
| Point idealSize; |
| ZoomWindowIdeal(window, inZoomIn, &idealSize); |
| #else |
| [window zoom:window]; |
| #endif |
| if(QTLWExtra *tlextra = d->topData()) { |
| setGeometry(tlextra->normalGeometry); |
| tlextra->normalGeometry.setRect(0, 0, -1, -1); |
| } |
| } |
| } |
| } |
| |
| data->window_state = newstate; |
| |
| if(needShow) |
| show(); |
| |
| if(newstate & Qt::WindowActive) |
| activateWindow(); |
| |
| qt_event_request_window_change(this); |
| if (needSendStateChange) { |
| QWindowStateChangeEvent e(oldstate); |
| QApplication::sendEvent(this, &e); |
| } |
| } |
| |
| void QWidgetPrivate::setFocus_sys() |
| { |
| Q_Q(QWidget); |
| if (q->testAttribute(Qt::WA_WState_Created)) { |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| NSView *view = qt_mac_nativeview_for(q); |
| [[view window] makeFirstResponder:view]; |
| #else |
| SetKeyboardFocus(qt_mac_window_for(q), qt_mac_nativeview_for(q), 1); |
| #endif |
| } |
| } |
| |
| NSComparisonResult compareViews2Raise(id view1, id view2, void *context) |
| { |
| id topView = reinterpret_cast<id>(context); |
| if (view1 == topView) |
| return NSOrderedDescending; |
| if (view2 == topView) |
| return NSOrderedAscending; |
| return NSOrderedSame; |
| } |
| |
| void QWidgetPrivate::raise_sys() |
| { |
| Q_Q(QWidget); |
| if((q->windowType() == Qt::Desktop)) |
| return; |
| |
| #if QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| if (isRealWindow()) { |
| // With the introduction of spaces it is not as simple as just raising the window. |
| // First we need to check if we are in the right space. If we are, then we just continue |
| // as usual. The problem comes when we are not in the active space. There are two main cases: |
| // 1. Our parent was moved to a new space. In this case we want the window to be raised |
| // in the same space as its parent. |
| // 2. We don't have a parent. For this case we will just raise the window and let Cocoa |
| // switch to the corresponding space. |
| // NOTICE: There are a lot of corner cases here. We are keeping this simple for now, if |
| // required we will introduce special handling for some of them. |
| if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) { |
| OSWindowRef window = qt_mac_window_for(q); |
| // isOnActiveSpace is available only from 10.6 onwards, so we need to check if it is |
| // available before calling it. |
| if([window respondsToSelector:@selector(isOnActiveSpace)]) { |
| if(![window performSelector:@selector(isOnActiveSpace)]) { |
| QWidget *parentWidget = q->parentWidget(); |
| if(parentWidget) { |
| OSWindowRef parentWindow = qt_mac_window_for(parentWidget); |
| if(parentWindow && [parentWindow isOnActiveSpace]) { |
| // The window was created in a different space. Therefore if we want |
| // to show it in the current space we need to recreate it in the new |
| // space. |
| recreateMacWindow(); |
| window = qt_mac_window_for(q); |
| } |
| } |
| } |
| } |
| [window orderFront:window]; |
| } |
| if (qt_mac_raise_process) { //we get to be the active process now |
| ProcessSerialNumber psn; |
| GetCurrentProcess(&psn); |
| SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); |
| } |
| } else { |
| NSView *view = qt_mac_nativeview_for(q); |
| NSView *parentView = [view superview]; |
| [parentView sortSubviewsUsingFunction:compareViews2Raise context:reinterpret_cast<void *>(view)]; |
| } |
| #else |
| if(q->isWindow()) { |
| //raise this window |
| BringToFront(qt_mac_window_for(q)); |
| if(qt_mac_raise_process) { //we get to be the active process now |
| ProcessSerialNumber psn; |
| GetCurrentProcess(&psn); |
| SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); |
| } |
| } else if(q->parentWidget()) { |
| HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderAbove, 0); |
| qt_event_request_window_change(q); |
| } |
| #endif |
| } |
| |
| NSComparisonResult compareViews2Lower(id view1, id view2, void *context) |
| { |
| id topView = reinterpret_cast<id>(context); |
| if (view1 == topView) |
| return NSOrderedAscending; |
| if (view2 == topView) |
| return NSOrderedDescending; |
| return NSOrderedSame; |
| } |
| |
| void QWidgetPrivate::lower_sys() |
| { |
| Q_Q(QWidget); |
| if((q->windowType() == Qt::Desktop)) |
| return; |
| #ifdef QT_MAC_USE_COCOA |
| if (isRealWindow()) { |
| OSWindowRef window = qt_mac_window_for(q); |
| [window orderBack:window]; |
| } else { |
| NSView *view = qt_mac_nativeview_for(q); |
| NSView *parentView = [view superview]; |
| [parentView sortSubviewsUsingFunction:compareViews2Lower context:reinterpret_cast<void *>(view)]; |
| } |
| #else |
| if(q->isWindow()) { |
| SendBehind(qt_mac_window_for(q), 0); |
| } else if(q->parentWidget()) { |
| invalidateBuffer(q->rect()); |
| HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderBelow, 0); |
| qt_event_request_window_change(q); |
| } |
| #endif |
| } |
| |
| NSComparisonResult compareViews2StackUnder(id view1, id view2, void *context) |
| { |
| const QHash<NSView *, int> &viewOrder = *reinterpret_cast<QHash<NSView *, int> *>(context); |
| if (viewOrder[view1] < viewOrder[view2]) |
| return NSOrderedAscending; |
| if (viewOrder[view1] > viewOrder[view2]) |
| return NSOrderedDescending; |
| return NSOrderedSame; |
| } |
| |
| void QWidgetPrivate::stackUnder_sys(QWidget *w) |
| { |
| // stackUnder |
| Q_Q(QWidget); |
| if(!w || q->isWindow() || (q->windowType() == Qt::Desktop)) |
| return; |
| #ifdef QT_MAC_USE_COCOA |
| // Do the same trick as lower_sys() and put this widget before the widget passed in. |
| NSView *myView = qt_mac_nativeview_for(q); |
| NSView *wView = qt_mac_nativeview_for(w); |
| |
| QHash<NSView *, int> viewOrder; |
| NSView *parentView = [myView superview]; |
| NSArray *subviews = [parentView subviews]; |
| NSUInteger index = 1; |
| // make a hash of view->zorderindex and make sure z-value is always odd, |
| // so that when we modify the order we create a new (even) z-value which |
| // will not interfere with others. |
| for (NSView *subview in subviews) { |
| viewOrder.insert(subview, index * 2); |
| ++index; |
| } |
| viewOrder[myView] = viewOrder[wView] - 1; |
| |
| [parentView sortSubviewsUsingFunction:compareViews2StackUnder context:reinterpret_cast<void *>(&viewOrder)]; |
| #else |
| QWidget *p = q->parentWidget(); |
| if(!p || p != w->parentWidget()) |
| return; |
| invalidateBuffer(q->rect()); |
| HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderBelow, qt_mac_nativeview_for(w)); |
| qt_event_request_window_change(q); |
| #endif |
| } |
| |
| /* |
| Modifies the bounds for a widgets backing HIView during moves and resizes. Also updates the |
| widget, either by scrolling its contents or repainting, depending on the WA_StaticContents |
| flag |
| */ |
| static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRect) |
| { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect bounds = CGRectMake(newRect.x(), newRect.y(), |
| newRect.width(), newRect.height()); |
| |
| const HIViewRef view = qt_mac_nativeview_for(q); |
| const bool isMove = (oldRect.topLeft() != newRect.topLeft()); |
| const bool isResize = (oldRect.size() != newRect.size()); |
| |
| // qDebug() << oldRect << newRect << isMove << isResize << q->testAttribute(Qt::WA_OpaquePaintEvent) << q->testAttribute(Qt::WA_StaticContents); |
| QWidgetPrivate *qd = qt_widget_private(q); |
| |
| // Perform a normal (complete repaint) update in some cases: |
| if ( |
| // always repaint on move. |
| (isMove) || |
| |
| // limited update on resize requires WA_StaticContents. |
| (isResize && q->testAttribute(Qt::WA_StaticContents) == false) || |
| |
| // one of the rects are invalid |
| (oldRect.isValid() == false || newRect.isValid() == false) || |
| |
| // the position update is a part of a drag-and-drop operation |
| QDragManager::self()->object || |
| |
| // we are on Panther (no HIViewSetNeedsDisplayInRect) |
| QSysInfo::MacintoshVersion < QSysInfo::MV_10_4 |
| ){ |
| HIViewSetFrame(view, &bounds); |
| return; |
| } |
| |
| const int dx = newRect.x() - oldRect.x(); |
| const int dy = newRect.y() - oldRect.y(); |
| |
| if (isMove) { |
| // HIViewScrollRect silently fails if we try to scroll anything under the grow box. |
| // Check if there's one present within the widget rect, and if there is fall back |
| // to repainting the entire widget. |
| QWidget const * const parentWidget = q->parentWidget(); |
| const HIViewRef parentView = qt_mac_nativeview_for(parentWidget); |
| HIViewRef nativeSizeGrip = 0; |
| if (q->testAttribute(Qt::WA_WState_Created)) |
| HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(q->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip); |
| if (nativeSizeGrip) { |
| QWidget * const window = q->window(); |
| |
| const int sizeGripSize = 20; |
| const QRect oldWidgetRect = QRect(q->mapTo(window, QPoint(0, 0)), QSize(oldRect.width(), oldRect.height())); |
| const QRect newWidgetRect = QRect(q->mapTo(window, QPoint(0, 0)), QSize(newRect.width(), newRect.height())); |
| const QRect sizeGripRect = QRect(window->rect().bottomRight() - QPoint(sizeGripSize, sizeGripSize), |
| window->rect().bottomRight()); |
| |
| if (sizeGripRect.intersects(oldWidgetRect) || sizeGripRect.intersects(newWidgetRect)) { |
| HIViewSetFrame(view, &bounds); |
| return; |
| } |
| } |
| |
| // Don't scroll anything outside the parent widget rect. |
| const QRect scrollRect = (oldRect | newRect) & parentWidget->rect(); |
| const HIRect scrollBounds = |
| CGRectMake(scrollRect.x(), scrollRect.y(), scrollRect.width(), scrollRect.height()); |
| |
| // We cannot scroll when the widget has a mask as that would |
| // scroll the masked out areas too |
| if (qd->extra && qd->extra->hasMask) { |
| HIViewMoveBy(view, dx, dy); |
| return; |
| } |
| |
| OSStatus err = HIViewScrollRect(parentView, &scrollBounds, dx, dy); |
| if (err != noErr) { |
| HIViewSetNeedsDisplay(view, true); |
| qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__); |
| } |
| } |
| // Set the view bounds with drawing disabled to prevent repaints. |
| HIViewSetDrawingEnabled(view, false); |
| HIViewSetFrame(view, &bounds); |
| HIViewSetDrawingEnabled(view, true); |
| |
| // Update any newly exposed areas due to resizing. |
| const int startx = oldRect.width(); |
| const int stopx = newRect.width(); |
| const int starty = oldRect.height(); |
| const int stopy = newRect.height(); |
| |
| const HIRect verticalSlice = CGRectMake(startx, 0, stopx , stopy); |
| HIViewSetNeedsDisplayInRect(view, &verticalSlice, true); |
| const HIRect horizontalSlice = CGRectMake(0, starty, startx, stopy); |
| HIViewSetNeedsDisplayInRect(view, &horizontalSlice, true); |
| #else |
| Q_UNUSED(oldRect); |
| NSRect bounds = NSMakeRect(newRect.x(), newRect.y(), |
| newRect.width(), newRect.height()); |
| [qt_mac_nativeview_for(q) setFrame:bounds]; |
| #endif |
| } |
| |
| /* |
| Helper function for non-toplevel widgets. Helps to map Qt's 32bit |
| coordinate system to OS X's 16bit coordinate system. |
| |
| Sets the geometry of the widget to data.crect, but clipped to sizes |
| that OS X can handle. Unmaps widgets that are completely outside the |
| valid range. |
| |
| Maintains data.wrect, which is the geometry of the OS X widget, |
| measured in this widget's coordinate system. |
| |
| if the parent is not clipped, parentWRect is empty, otherwise |
| parentWRect is the geometry of the parent's OS X rect, measured in |
| parent's coord sys |
| */ |
| void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) |
| { |
| Q_Q(QWidget); |
| Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); |
| Q_UNUSED(oldRect); |
| /* |
| There are up to four different coordinate systems here: |
| Qt coordinate system for this widget. |
| X coordinate system for this widget (relative to wrect). |
| Qt coordinate system for parent |
| X coordinate system for parent (relative to parent's wrect). |
| */ |
| QRect wrect; |
| //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) |
| QRect xrect = data.crect; |
| |
| QRect parentWRect; |
| bool isEmbeddedWindow = (q->isWindow() && topData()->embedded); |
| if (isEmbeddedWindow) { |
| #ifndef QT_MAC_USE_COCOA |
| HIViewRef parentView = HIViewGetSuperview(qt_mac_nativeview_for(q)); |
| #else |
| NSView *parentView = [qt_mac_nativeview_for(q) superview]; |
| #endif |
| if (parentView) { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect tmpRect; |
| HIViewGetFrame(parentView, &tmpRect); |
| #else |
| NSRect tmpRect = [parentView frame]; |
| #endif |
| parentWRect = QRect(tmpRect.origin.x, tmpRect.origin.y, |
| tmpRect.size.width, tmpRect.size.height); |
| } else { |
| const QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX); |
| parentWRect = wrectRange; |
| } |
| } else { |
| parentWRect = q->parentWidget()->data->wrect; |
| } |
| |
| if (parentWRect.isValid()) { |
| // parent is clipped, and we have to clip to the same limit as parent |
| if (!parentWRect.contains(xrect) && !isEmbeddedWindow) { |
| xrect &= parentWRect; |
| wrect = xrect; |
| //translate from parent's to my Qt coord sys |
| wrect.translate(-data.crect.topLeft()); |
| } |
| //translate from parent's Qt coords to parent's X coords |
| xrect.translate(-parentWRect.topLeft()); |
| |
| } else { |
| // parent is not clipped, we may or may not have to clip |
| |
| if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) { |
| // This is where the main optimization is: we are already |
| // clipped, and if our clip is still valid, we can just |
| // move our window, and do not need to move or clip |
| // children |
| |
| QRect vrect = xrect & q->parentWidget()->rect(); |
| vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords |
| if (data.wrect.contains(vrect)) { |
| xrect = data.wrect; |
| xrect.translate(data.crect.topLeft()); |
| #ifndef QT_MAC_USE_COCOA |
| HIRect bounds = CGRectMake(xrect.x(), xrect.y(), |
| xrect.width(), xrect.height()); |
| HIViewSetFrame(qt_mac_nativeview_for(q), &bounds); |
| #else |
| NSRect bounds = NSMakeRect(xrect.x(), xrect.y(), |
| xrect.width(), xrect.height()); |
| [qt_mac_nativeview_for(q) setFrame:bounds]; |
| #endif |
| if (q->testAttribute(Qt::WA_OutsideWSRange)) { |
| q->setAttribute(Qt::WA_OutsideWSRange, false); |
| if (!dontShow) { |
| q->setAttribute(Qt::WA_Mapped); |
| #ifndef QT_MAC_USE_COCOA |
| HIViewSetVisible(qt_mac_nativeview_for(q), true); |
| #else |
| [qt_mac_nativeview_for(q) setHidden:NO]; |
| #endif |
| } |
| } |
| return; |
| } |
| } |
| |
| const QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); |
| if (!validRange.contains(xrect)) { |
| // we are too big, and must clip |
| QPoint screenOffset(0, 0); // offset of the part being on screen |
| const QWidget *parentWidget = q->parentWidget(); |
| while (parentWidget && !parentWidget->isWindow()) { |
| screenOffset -= parentWidget->data->crect.topLeft(); |
| parentWidget = parentWidget->parentWidget(); |
| } |
| QRect cropRect(screenOffset.x() - WRECT_MAX, |
| screenOffset.y() - WRECT_MAX, |
| 2*WRECT_MAX, |
| 2*WRECT_MAX); |
| |
| xrect &=cropRect; |
| wrect = xrect; |
| wrect.translate(-data.crect.topLeft()); // translate wrect in my Qt coordinates |
| } |
| } |
| |
| // unmap if we are outside the valid window system coord system |
| bool outsideRange = !xrect.isValid(); |
| bool mapWindow = false; |
| if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) { |
| q->setAttribute(Qt::WA_OutsideWSRange, outsideRange); |
| if (outsideRange) { |
| #ifndef QT_MAC_USE_COCOA |
| HIViewSetVisible(qt_mac_nativeview_for(q), false); |
| #else |
| [qt_mac_nativeview_for(q) setHidden:YES]; |
| #endif |
| q->setAttribute(Qt::WA_Mapped, false); |
| } else if (!q->isHidden()) { |
| mapWindow = true; |
| } |
| } |
| |
| if (outsideRange) |
| return; |
| |
| bool jump = (data.wrect != wrect); |
| data.wrect = wrect; |
| |
| |
| // and now recursively for all children... |
| // ### can be optimized |
| for (int i = 0; i < children.size(); ++i) { |
| QObject *object = children.at(i); |
| if (object->isWidgetType()) { |
| QWidget *w = static_cast<QWidget *>(object); |
| if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) |
| w->d_func()->setWSGeometry(); |
| } |
| } |
| |
| qt_mac_update_widget_position(q, oldRect, xrect); |
| |
| if (jump) |
| q->update(); |
| |
| if (mapWindow && !dontShow) { |
| q->setAttribute(Qt::WA_Mapped); |
| #ifndef QT_MAC_USE_COCOA |
| HIViewSetVisible(qt_mac_nativeview_for(q), true); |
| #else |
| [qt_mac_nativeview_for(q) setHidden:NO]; |
| #endif |
| } |
| } |
| |
| void QWidgetPrivate::adjustWithinMaxAndMinSize(int &w, int &h) |
| { |
| if (QWExtra *extra = extraData()) { |
| w = qMin(w, extra->maxw); |
| h = qMin(h, extra->maxh); |
| w = qMax(w, extra->minw); |
| h = qMax(h, extra->minh); |
| |
| // Deal with size increment |
| if (QTLWExtra *top = topData()) { |
| if(top->incw) { |
| w = w/top->incw; |
| w *= top->incw; |
| } |
| if(top->inch) { |
| h = h/top->inch; |
| h *= top->inch; |
| } |
| } |
| } |
| |
| if (isRealWindow()) { |
| w = qMax(0, w); |
| h = qMax(0, h); |
| } |
| } |
| |
| void QWidgetPrivate::applyMaxAndMinSizeOnWindow() |
| { |
| Q_Q(QWidget); |
| const float max_f(20000); |
| #ifndef QT_MAC_USE_COCOA |
| #define SF(x) ((x > max_f) ? max_f : x) |
| HISize max = CGSizeMake(SF(extra->maxw), SF(extra->maxh)); |
| HISize min = CGSizeMake(SF(extra->minw), SF(extra->minh)); |
| #undef SF |
| SetWindowResizeLimits(qt_mac_window_for(q), &min, &max); |
| #else |
| #define SF(x) ((x > max_f) ? max_f : x) |
| NSSize max = NSMakeSize(SF(extra->maxw), SF(extra->maxh)); |
| NSSize min = NSMakeSize(SF(extra->minw), SF(extra->minh)); |
| #undef SF |
| [qt_mac_window_for(q) setContentMinSize:min]; |
| [qt_mac_window_for(q) setContentMaxSize:max]; |
| #endif |
| } |
| |
| void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) |
| { |
| Q_Q(QWidget); |
| Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); |
| |
| if(q->windowType() == Qt::Desktop) |
| return; |
| |
| QMacCocoaAutoReleasePool pool; |
| bool realWindow = isRealWindow(); |
| BOOL needDisplay = realWindow ? YES : NO; |
| |
| if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen)){ |
| adjustWithinMaxAndMinSize(w, h); |
| #ifndef QT_MAC_USE_COCOA |
| if (w != 0 && h != 0) { |
| topData()->isSetGeometry = 1; |
| topData()->isMove = isMove; |
| Rect r; SetRect(&r, x, y, x + w, y + h); |
| SetWindowBounds(qt_mac_window_for(q), kWindowContentRgn, &r); |
| topData()->isSetGeometry = 0; |
| } else { |
| setGeometry_sys_helper(x, y, w, h, isMove); |
| } |
| #else |
| if (!isMove && !q->testAttribute(Qt::WA_Moved) && !q->isVisible()) { |
| // INVARIANT: The location of the window has not yet been set. The default will |
| // instead be to center it on the desktop, or over the parent, if any. Since we now |
| // resize the window, we need to adjust the top left position to keep the window |
| // centeralized. And we need to to this now (and before show) in case the positioning |
| // of other windows (e.g. sub-windows) depend on this position: |
| if (QWidget *p = q->parentWidget()) { |
| x = p->geometry().center().x() - (w / 2); |
| y = p->geometry().center().y() - (h / 2); |
| } else { |
| QRect availGeo = QApplication::desktop()->availableGeometry(q); |
| x = availGeo.center().x() - (w / 2); |
| y = availGeo.center().y() - (h / 2); |
| } |
| } |
| |
| QSize olds = q->size(); |
| const bool isResize = (olds != QSize(w, h)); |
| NSWindow *window = qt_mac_window_for(q); |
| const QRect &fStrut = frameStrut(); |
| const QRect frameRect(QPoint(x - fStrut.left(), y - fStrut.top()), |
| QSize(fStrut.left() + fStrut.right() + w, |
| fStrut.top() + fStrut.bottom() + h)); |
| NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), |
| frameRect.width(), frameRect.height()); |
| // The setFrame call will trigger a 'windowDidResize' notification for the corresponding |
| // NSWindow. The pending flag is set, so that the resize event can be send as non-spontaneous. |
| if (isResize) |
| q->setAttribute(Qt::WA_PendingResizeEvent); |
| QPoint currTopLeft = data.crect.topLeft(); |
| if (currTopLeft.x() == x && currTopLeft.y() == y |
| && cocoaFrameRect.size.width != 0 |
| && cocoaFrameRect.size.height != 0) { |
| [window setFrame:cocoaFrameRect display:needDisplay]; |
| } else { |
| // The window is moved and resized (or resized to zero). |
| // Since Cocoa usually only sends us a resize callback after |
| // setting a window frame, we issue an explicit move as |
| // well. To stop Cocoa from optimize away the move (since the move |
| // would have the same origin as the setFrame call) we shift the |
| // window back and forth inbetween. |
| cocoaFrameRect.origin.y += 1; |
| [window setFrame:cocoaFrameRect display:needDisplay]; |
| cocoaFrameRect.origin.y -= 1; |
| [window setFrameOrigin:cocoaFrameRect.origin]; |
| } |
| #endif |
| } else { |
| setGeometry_sys_helper(x, y, w, h, isMove); |
| } |
| } |
| |
| void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isMove) |
| { |
| Q_Q(QWidget); |
| bool realWindow = isRealWindow(); |
| |
| QPoint oldp = q->pos(); |
| QSize olds = q->size(); |
| // Apply size restrictions, applicable for Windows & Widgets. |
| if (QWExtra *extra = extraData()) { |
| w = qBound(extra->minw, w, extra->maxw); |
| h = qBound(extra->minh, h, extra->maxh); |
| } |
| const bool isResize = (olds != QSize(w, h)); |
| |
| if (!realWindow && !isResize && QPoint(x, y) == oldp) |
| return; |
| |
| if (isResize) |
| data.window_state = data.window_state & ~Qt::WindowMaximized; |
| |
| const bool visible = q->isVisible(); |
| data.crect = QRect(x, y, w, h); |
| |
| if (realWindow) { |
| adjustWithinMaxAndMinSize(w, h); |
| qt_mac_update_sizer(q); |
| |
| #ifndef QT_MAC_USE_COCOA |
| if (q->windowFlags() & Qt::WindowMaximizeButtonHint) { |
| OSWindowRef window = qt_mac_window_for(q); |
| if (extra->maxw && extra->maxh && extra->maxw == extra->minw |
| && extra->maxh == extra->minh) { |
| ChangeWindowAttributes(window, kWindowNoAttributes, kWindowFullZoomAttribute); |
| } else { |
| ChangeWindowAttributes(window, kWindowFullZoomAttribute, kWindowNoAttributes); |
| } |
| } |
| HIRect bounds = CGRectMake(0, 0, w, h); |
| HIViewSetFrame(qt_mac_nativeview_for(q), &bounds); |
| #else |
| [qt_mac_nativeview_for(q) setFrame:NSMakeRect(0, 0, w, h)]; |
| #endif |
| } else { |
| const QRect oldRect(oldp, olds); |
| if (!isResize && QApplicationPrivate::graphicsSystem()) |
| moveRect(oldRect, x - oldp.x(), y - oldp.y()); |
| setWSGeometry(false, oldRect); |
| if (isResize && QApplicationPrivate::graphicsSystem()) { |
| invalidateBuffer(q->rect()); |
| if (extra && !graphicsEffect && !extra->mask.isEmpty()) { |
| QRegion oldRegion(extra->mask.translated(oldp)); |
| oldRegion &= oldRect; |
| q->parentWidget()->d_func()->invalidateBuffer(oldRegion); |
| } else { |
| q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(oldRect)); |
| } |
| } |
| } |
| |
| if(isMove || isResize) { |
| if(!visible) { |
| if(isMove && q->pos() != oldp) |
| q->setAttribute(Qt::WA_PendingMoveEvent, true); |
| if(isResize) |
| q->setAttribute(Qt::WA_PendingResizeEvent, true); |
| } else { |
| if(isResize) { //send the resize event.. |
| QResizeEvent e(q->size(), olds); |
| QApplication::sendEvent(q, &e); |
| } |
| if(isMove && q->pos() != oldp) { //send the move event.. |
| QMoveEvent e(q->pos(), oldp); |
| QApplication::sendEvent(q, &e); |
| } |
| } |
| } |
| qt_event_request_window_change(q); |
| } |
| |
| void QWidgetPrivate::setConstraints_sys() |
| { |
| updateMaximizeButton_sys(); |
| applyMaxAndMinSizeOnWindow(); |
| } |
| |
| void QWidgetPrivate::updateMaximizeButton_sys() |
| { |
| Q_Q(QWidget); |
| if (q->data->window_flags & Qt::CustomizeWindowHint) |
| return; |
| |
| OSWindowRef window = qt_mac_window_for(q); |
| QTLWExtra * tlwExtra = topData(); |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| NSButton *maximizeButton = [window standardWindowButton:NSWindowZoomButton]; |
| #endif |
| if (extra->maxw && extra->maxh |
| && extra->maxw == extra->minw |
| && extra->maxh == extra->minh) { |
| // The window has a fixed size, so gray out the maximize button: |
| if (!tlwExtra->savedWindowAttributesFromMaximized) { |
| #ifndef QT_MAC_USE_COCOA |
| GetWindowAttributes(window, |
| (WindowAttributes*)&extra->topextra->savedWindowAttributesFromMaximized); |
| |
| #else |
| tlwExtra->savedWindowAttributesFromMaximized = (![maximizeButton isHidden] && [maximizeButton isEnabled]); |
| #endif |
| } |
| #ifndef QT_MAC_USE_COCOA |
| ChangeWindowAttributes(window, kWindowNoAttributes, kWindowFullZoomAttribute); |
| #else |
| [maximizeButton setEnabled:NO]; |
| #endif |
| |
| |
| } else { |
| if (tlwExtra->savedWindowAttributesFromMaximized) { |
| #ifndef QT_MAC_USE_COCOA |
| ChangeWindowAttributes(window, |
| extra->topextra->savedWindowAttributesFromMaximized, |
| kWindowNoAttributes); |
| #else |
| [maximizeButton setEnabled:YES]; |
| #endif |
| tlwExtra->savedWindowAttributesFromMaximized = 0; |
| } |
| } |
| |
| |
| } |
| |
| void QWidgetPrivate::scroll_sys(int dx, int dy) |
| { |
| if (QApplicationPrivate::graphicsSystem() && !paintOnScreen()) { |
| scrollChildren(dx, dy); |
| scrollRect(q_func()->rect(), dx, dy); |
| } else { |
| scroll_sys(dx, dy, QRect()); |
| } |
| } |
| |
| void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) |
| { |
| Q_Q(QWidget); |
| |
| if (QApplicationPrivate::graphicsSystem() && !paintOnScreen()) { |
| scrollRect(r, dx, dy); |
| return; |
| } |
| |
| const bool valid_rect = r.isValid(); |
| if (!q->updatesEnabled() && (valid_rect || q->children().isEmpty())) |
| return; |
| |
| qt_event_request_window_change(q); |
| |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| #endif |
| |
| if(!valid_rect) { // scroll children |
| QPoint pd(dx, dy); |
| QWidgetList moved; |
| QObjectList chldrn = q->children(); |
| for(int i = 0; i < chldrn.size(); i++) { //first move all children |
| QObject *obj = chldrn.at(i); |
| if(obj->isWidgetType()) { |
| QWidget *w = (QWidget*)obj; |
| if(!w->isWindow()) { |
| w->data->crect = QRect(w->pos() + pd, w->size()); |
| if (w->testAttribute(Qt::WA_WState_Created)) { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect bounds = CGRectMake(w->data->crect.x(), w->data->crect.y(), |
| w->data->crect.width(), w->data->crect.height()); |
| HIViewRef hiview = qt_mac_nativeview_for(w); |
| const bool opaque = q->testAttribute(Qt::WA_OpaquePaintEvent); |
| |
| if (opaque) |
| HIViewSetDrawingEnabled(hiview, false); |
| HIViewSetFrame(hiview, &bounds); |
| if (opaque) |
| HIViewSetDrawingEnabled(hiview, true); |
| #else |
| [qt_mac_nativeview_for(w) |
| setFrame:NSMakeRect(w->data->crect.x(), w->data->crect.y(), |
| w->data->crect.width(), w->data->crect.height())]; |
| #endif |
| } |
| moved.append(w); |
| } |
| } |
| } |
| //now send move events (do not do this in the above loop, breaks QAquaFocusWidget) |
| for(int i = 0; i < moved.size(); i++) { |
| QWidget *w = moved.at(i); |
| QMoveEvent e(w->pos(), w->pos() - pd); |
| QApplication::sendEvent(w, &e); |
| } |
| } |
| |
| if (!q->testAttribute(Qt::WA_WState_Created) || !q->isVisible()) |
| return; |
| |
| OSViewRef view = qt_mac_nativeview_for(q); |
| #ifndef QT_MAC_USE_COCOA |
| HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height()); |
| OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); |
| if (err) { |
| // The only parameter that can go wrong, is the rect. |
| qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect"); |
| scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0), |
| qMin(r.width(), q->width()), qMin(r.height(), q->height())); |
| _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); |
| } |
| #else |
| NSRect scrollRect = valid_rect ? NSMakeRect(r.x(), r.y(), r.width(), r.height()) |
| : NSMakeRect(0, 0, q->width(), q->height()); |
| |
| |
| // calc the updateRect |
| NSRect deltaXRect = { {0, 0}, {0, 0} }; |
| NSRect deltaYRect = { {0, 0}, {0, 0} }; |
| if (dy != 0) { |
| deltaYRect.size.width = scrollRect.size.width; |
| if (dy > 0) { |
| deltaYRect.size.height = dy; |
| } else { |
| deltaYRect.size.height = -dy; |
| deltaYRect.origin.y = scrollRect.size.height + dy; |
| } |
| } |
| if (dx != 0) { |
| deltaXRect.size.height = scrollRect.size.height; |
| if (dx > 0) { |
| deltaXRect.size.width = dx; |
| } else { |
| deltaXRect.size.width = -dx; |
| deltaXRect.origin.x = scrollRect.size.width + dx; |
| } |
| } |
| |
| // ### Scroll the dirty regions as well, the following is not correct. |
| QRegion displayRegion = r.isNull() ? dirtyOnWidget : (dirtyOnWidget & r); |
| const QVector<QRect> &rects = dirtyOnWidget.rects(); |
| const QVector<QRect>::const_iterator end = rects.end(); |
| QVector<QRect>::const_iterator it = rects.begin(); |
| while (it != end) { |
| const QRect rect = *it; |
| const NSRect dirtyRect = NSMakeRect(rect.x() + dx, rect.y() + dy, |
| rect.width(), rect.height()); |
| [view setNeedsDisplayInRect:dirtyRect]; |
| ++it; |
| } |
| |
| NSSize deltaSize = NSMakeSize(dx, dy); |
| [view scrollRect:scrollRect by:deltaSize]; |
| [view setNeedsDisplayInRect:deltaXRect]; |
| [view setNeedsDisplayInRect:deltaYRect]; |
| #endif // QT_MAC_USE_COCOA |
| } |
| |
| int QWidget::metric(PaintDeviceMetric m) const |
| { |
| switch(m) { |
| case PdmHeightMM: |
| return qRound(metric(PdmHeight) * 25.4 / qreal(metric(PdmDpiY))); |
| case PdmWidthMM: |
| return qRound(metric(PdmWidth) * 25.4 / qreal(metric(PdmDpiX))); |
| case PdmHeight: |
| case PdmWidth: { |
| #ifndef QT_MAC_USE_COCOA |
| HIRect rect; |
| HIViewGetFrame(qt_mac_nativeview_for(this), &rect); |
| #else |
| NSRect rect = [qt_mac_nativeview_for(this) frame]; |
| #endif |
| if(m == PdmWidth) |
| return (int)rect.size.width; |
| return (int)rect.size.height; } |
| case PdmDepth: |
| return 32; |
| case PdmNumColors: |
| return INT_MAX; |
| case PdmDpiX: |
| case PdmPhysicalDpiX: { |
| Q_D(const QWidget); |
| if (d->extra && d->extra->customDpiX) |
| return d->extra->customDpiX; |
| else if (d->parent) |
| return static_cast<QWidget *>(d->parent)->metric(m); |
| extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp |
| return int(qt_mac_defaultDpi_x()); } |
| case PdmDpiY: |
| case PdmPhysicalDpiY: { |
| Q_D(const QWidget); |
| if (d->extra && d->extra->customDpiY) |
| return d->extra->customDpiY; |
| else if (d->parent) |
| return static_cast<QWidget *>(d->parent)->metric(m); |
| extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp |
| return int(qt_mac_defaultDpi_y()); } |
| default: //leave this so the compiler complains when new ones are added |
| qWarning("QWidget::metric: Unhandled parameter %d", m); |
| return QPaintDevice::metric(m); |
| } |
| return 0; |
| } |
| |
| void QWidgetPrivate::createSysExtra() |
| { |
| #ifdef QT_MAC_USE_COCOA |
| extra->imageMask = 0; |
| #endif |
| } |
| |
| void QWidgetPrivate::deleteSysExtra() |
| { |
| #ifdef QT_MAC_USE_COCOA |
| if (extra->imageMask) |
| CFRelease(extra->imageMask); |
| #endif |
| } |
| |
| void QWidgetPrivate::createTLSysExtra() |
| { |
| extra->topextra->resizer = 0; |
| extra->topextra->isSetGeometry = 0; |
| extra->topextra->isMove = 0; |
| extra->topextra->wattr = 0; |
| extra->topextra->wclass = 0; |
| extra->topextra->group = 0; |
| extra->topextra->windowIcon = 0; |
| extra->topextra->savedWindowAttributesFromMaximized = 0; |
| } |
| |
| void QWidgetPrivate::deleteTLSysExtra() |
| { |
| #ifndef QT_MAC_USE_COCOA |
| if (extra->topextra->group) { |
| qt_mac_release_window_group(extra->topextra->group); |
| extra->topextra->group = 0; |
| } |
| if (extra->topextra->windowIcon) { |
| ReleaseIconRef(extra->topextra->windowIcon); |
| extra->topextra->windowIcon = 0; |
| } |
| #endif |
| } |
| |
| void QWidgetPrivate::updateFrameStrut() |
| { |
| Q_Q(QWidget); |
| |
| QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this); |
| |
| that->data.fstrut_dirty = false; |
| QTLWExtra *top = that->topData(); |
| |
| #if QT_MAC_USE_COCOA |
| // 1 Get the window frame |
| OSWindowRef oswnd = qt_mac_window_for(q); |
| NSRect frameW = [oswnd frame]; |
| // 2 Get the content frame - so now |
| NSRect frameC = [oswnd contentRectForFrameRect:frameW]; |
| top->frameStrut.setCoords(frameC.origin.x - frameW.origin.x, |
| (frameW.origin.y + frameW.size.height) - (frameC.origin.y + frameC.size.height), |
| (frameW.origin.x + frameW.size.width) - (frameC.origin.x + frameC.size.width), |
| frameC.origin.y - frameW.origin.y); |
| #else |
| Rect window_r; |
| GetWindowStructureWidths(qt_mac_window_for(q), &window_r); |
| top->frameStrut.setCoords(window_r.left, window_r.top, window_r.right, window_r.bottom); |
| #endif |
| } |
| |
| void QWidgetPrivate::registerDropSite(bool on) |
| { |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; |
| #ifndef QT_MAC_USE_COCOA |
| SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on); |
| #else |
| NSWindow *win = qt_mac_window_for(q); |
| if (on) { |
| if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaWindow) class]]) |
| [static_cast<QT_MANGLE_NAMESPACE(QCocoaWindow) *>(win) registerDragTypes]; |
| else if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaPanel) class]]) |
| [static_cast<QT_MANGLE_NAMESPACE(QCocoaPanel) *>(win) registerDragTypes]; |
| } |
| #endif |
| } |
| |
| void QWidgetPrivate::registerTouchWindow() |
| { |
| #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 |
| if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6) |
| return; |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; |
| #ifndef QT_MAC_USE_COCOA |
| // Needs implementation! |
| #else |
| NSView *view = qt_mac_nativeview_for(q); |
| [view setAcceptsTouchEvents:YES]; |
| #endif |
| #endif |
| } |
| |
| void QWidgetPrivate::setMask_sys(const QRegion ®ion) |
| { |
| Q_UNUSED(region); |
| #ifndef QT_MAC_USE_COCOA |
| Q_Q(QWidget); |
| if (q->isWindow()) |
| ReshapeCustomWindow(qt_mac_window_for(q)); |
| else |
| HIViewReshapeStructure(qt_mac_nativeview_for(q)); |
| #else |
| if (extra->mask.isEmpty()) { |
| extra->maskBits = QImage(); |
| finishCocoaMaskSetup(); |
| } else { |
| syncCocoaMask(); |
| } |
| |
| #endif |
| } |
| |
| void QWidgetPrivate::setWindowOpacity_sys(qreal level) |
| { |
| Q_Q(QWidget); |
| |
| if (!q->isWindow()) |
| return; |
| |
| level = qBound(0.0, level, 1.0); |
| topData()->opacity = (uchar)(level * 255); |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; |
| |
| OSWindowRef oswindow = qt_mac_window_for(q); |
| #if QT_MAC_USE_COCOA |
| [oswindow setAlphaValue:level]; |
| #else |
| SetWindowAlpha(oswindow, level); |
| #endif |
| } |
| |
| #ifdef QT_MAC_USE_COCOA |
| void QWidgetPrivate::syncCocoaMask() |
| { |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created) || !extra) |
| return; |
| |
| if (extra->hasMask) { |
| if(extra->maskBits.size() != q->size()) { |
| extra->maskBits = QImage(q->size(), QImage::Format_Mono); |
| } |
| extra->maskBits.fill(QColor(Qt::color1).rgba()); |
| extra->maskBits.setNumColors(2); |
| extra->maskBits.setColor(0, QColor(Qt::color0).rgba()); |
| extra->maskBits.setColor(1, QColor(Qt::color1).rgba()); |
| QPainter painter(&extra->maskBits); |
| painter.setBrush(Qt::color1); |
| painter.setPen(Qt::NoPen); |
| painter.drawRects(extra->mask.rects()); |
| painter.end(); |
| finishCocoaMaskSetup(); |
| } |
| } |
| |
| void QWidgetPrivate::finishCocoaMaskSetup() |
| { |
| Q_Q(QWidget); |
| |
| if (!q->testAttribute(Qt::WA_WState_Created) || !extra) |
| return; |
| |
| // Technically this is too late to release, because the data behind the image |
| // has already been released. But it's more tidy to do it here. |
| // If you are seeing a crash, consider doing a CFRelease before changing extra->maskBits. |
| if (extra->imageMask) { |
| CFRelease(extra->imageMask); |
| extra->imageMask = 0; |
| } |
| |
| if (!extra->maskBits.isNull()) { |
| QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, |
| extra->maskBits.bits(), |
| extra->maskBits.numBytes(), |
| 0); // shouldn't need to release. |
| CGFloat decode[2] = {1, 0}; |
| extra->imageMask = CGImageMaskCreate(extra->maskBits.width(), extra->maskBits.height(), |
| 1, 1, extra->maskBits.bytesPerLine(), dataProvider, |
| decode, false); |
| } |
| if (q->isWindow()) { |
| NSWindow *window = qt_mac_window_for(q); |
| [window setOpaque:(extra->imageMask == 0)]; |
| [window invalidateShadow]; |
| } |
| qt_mac_set_needs_display(q, QRegion()); |
| } |
| #endif |
| |
| struct QPaintEngineCleanupHandler |
| { |
| inline QPaintEngineCleanupHandler() : engine(0) {} |
| inline ~QPaintEngineCleanupHandler() { delete engine; } |
| QPaintEngine *engine; |
| }; |
| |
| Q_GLOBAL_STATIC(QPaintEngineCleanupHandler, engineHandler) |
| |
| QPaintEngine *QWidget::paintEngine() const |
| { |
| QPaintEngine *&pe = engineHandler()->engine; |
| if (!pe) |
| pe = new QCoreGraphicsPaintEngine(); |
| if (pe->isActive()) { |
| QPaintEngine *engine = new QCoreGraphicsPaintEngine(); |
| engine->setAutoDestruct(true); |
| return engine; |
| } |
| return pe; |
| } |
| |
| void QWidgetPrivate::setModal_sys() |
| { |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow()) |
| return; |
| const QWidget * const windowParent = q->window()->parentWidget(); |
| const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0; |
| OSWindowRef windowRef = qt_mac_window_for(q); |
| |
| #ifdef QT_MAC_USE_COCOA |
| QMacCocoaAutoReleasePool pool; |
| bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask; |
| |
| if (windowParent && q->windowModality() == Qt::WindowModal){ |
| // INVARIANT: Window should be window-modal (which implies a sheet). |
| if (!alreadySheet) { |
| // NB: the following call will call setModal_sys recursivly: |
| recreateMacWindow(); |
| windowRef = qt_mac_window_for(q); |
| } |
| if ([windowRef isKindOfClass:[NSPanel class]]){ |
| // If the primary window of the sheet parent is a child of a modal dialog, |
| // the sheet parent should not be modally shaddowed. |
| // This goes for the sheet as well: |
| OSWindowRef ref = primaryWindow ? qt_mac_window_for(primaryWindow) : 0; |
| bool isDialog = ref ? [ref isKindOfClass:[NSPanel class]] : false; |
| bool worksWhenModal = isDialog ? [static_cast<NSPanel *>(ref) worksWhenModal] : false; |
| if (worksWhenModal) |
| [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES]; |
| } |
| } else { |
| // INVARIANT: Window shold _not_ be window-modal (and as such, not a sheet). |
| if (alreadySheet){ |
| // NB: the following call will call setModal_sys recursivly: |
| recreateMacWindow(); |
| windowRef = qt_mac_window_for(q); |
| } |
| if (q->windowModality() == Qt::NonModal |
| && primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) { |
| // INVARIANT: Our window has a parent that is application modal. |
| // This means that q is supposed to be on top of this window and |
| // not be modally shaddowed: |
| if ([windowRef isKindOfClass:[NSPanel class]]) |
| [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES]; |
| } |
| } |
| |
| #else |
| const bool primaryWindowModal = primaryWindow ? primaryWindow->testAttribute(Qt::WA_ShowModal) : false; |
| const bool modal = q->testAttribute(Qt::WA_ShowModal); |
| |
| WindowClass old_wclass; |
| GetWindowClass(windowRef, &old_wclass); |
| |
| if (modal || primaryWindowModal) { |
| if (q->windowModality() == Qt::WindowModal |
| || (primaryWindow && primaryWindow->windowModality() == Qt::WindowModal)){ |
| // Window should be window-modal (which implies a sheet). |
| if (old_wclass != kSheetWindowClass){ |
| // We cannot convert a created window to a sheet. |
| // So we recreate the window: |
| recreateMacWindow(); |
| return; |
| } |
| } else { |
| // Window should be application-modal (which implies NOT using a sheet). |
| if (old_wclass == kSheetWindowClass){ |
| // We cannot convert a sheet to a window. |
| // So we recreate the window: |
| recreateMacWindow(); |
| return; |
| } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { |
| if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){ |
| // Only change the class to kMovableModalWindowClass if the no explicit jewels |
| // are set (kMovableModalWindowClass can't contain them), and the current window class |
| // can be converted to modal (according to carbon doc). Mind the order of |
| // HIWindowChangeClass and ChangeWindowAttributes. |
| WindowGroupRef group = GetWindowGroup(windowRef); |
| HIWindowChangeClass(windowRef, kMovableModalWindowClass); |
| quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute; |
| ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes); |
| ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr); |
| // If the window belongs to a qt-created group, set that group once more: |
| if (data.window_flags & Qt::WindowStaysOnTopHint |
| || q->windowType() == Qt::Popup |
| || q->windowType() == Qt::ToolTip) |
| SetWindowGroup(windowRef, group); |
| } |
| // Popups are usually handled "special" and are never modal. |
| Qt::WindowType winType = q->windowType(); |
| if (winType != Qt::Popup && winType != Qt::ToolTip) |
| SetWindowModality(windowRef, kWindowModalityAppModal, 0); |
| } |
| } |
| } else if (windowRef) { |
| if (old_wclass == kSheetWindowClass){ |
| // Converting a sheet to a window is complex. It's easier to recreate: |
| recreateMacWindow(); |
| return; |
| } |
| |
| SetWindowModality(windowRef, kWindowModalityNone, 0); |
| if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { |
| if (q->window()->d_func()->topData()->wattr |= kWindowCloseBoxAttribute) |
| ChangeWindowAttributes(windowRef, kWindowCloseBoxAttribute, kWindowNoAttributes); |
| if (q->window()->d_func()->topData()->wattr |= kWindowHorizontalZoomAttribute) |
| ChangeWindowAttributes(windowRef, kWindowHorizontalZoomAttribute, kWindowNoAttributes); |
| if (q->window()->d_func()->topData()->wattr |= kWindowCollapseBoxAttribute) |
| ChangeWindowAttributes(windowRef, kWindowCollapseBoxAttribute, kWindowNoAttributes); |
| } |
| |
| WindowClass newClass = q->window()->d_func()->topData()->wclass; |
| if (old_wclass != newClass && newClass != 0){ |
| WindowGroupRef group = GetWindowGroup(windowRef); |
| HIWindowChangeClass(windowRef, newClass); |
| // If the window belongs to a qt-created group, set that group once more: |
| if (data.window_flags & Qt::WindowStaysOnTopHint |
| || q->windowType() == Qt::Popup |
| || q->windowType() == Qt::ToolTip) |
| SetWindowGroup(windowRef, group); |
| } |
| } |
| |
| // Make sure that HIWindowChangeClass didn't remove drag support |
| // or reset the opaque size grip setting: |
| SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true); |
| macUpdateOpaqueSizeGrip(); |
| #endif |
| } |
| |
| void QWidgetPrivate::macUpdateHideOnSuspend() |
| { |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() || q->windowType() != Qt::Tool) |
| return; |
| #ifndef QT_MAC_USE_COCOA |
| if(q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) |
| ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowHideOnSuspendAttribute); |
| else |
| ChangeWindowAttributes(qt_mac_window_for(q), kWindowHideOnSuspendAttribute, 0); |
| #else |
| if(q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) |
| [qt_mac_window_for(q) setHidesOnDeactivate:NO]; |
| else |
| [qt_mac_window_for(q) setHidesOnDeactivate:YES]; |
| #endif |
| } |
| |
| void QWidgetPrivate::macUpdateOpaqueSizeGrip() |
| { |
| Q_Q(QWidget); |
| |
| if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow()) |
| return; |
| |
| #ifndef QT_MAC_USE_COCOA // Growbox is always transparent on Cocoa. Can emulate with setting a QSizeGrip |
| HIViewRef growBox; |
| HIViewFindByID(HIViewGetRoot(qt_mac_window_for(q)), kHIViewWindowGrowBoxID, &growBox); |
| if (!growBox) |
| return; |
| HIGrowBoxViewSetTransparent(growBox, !q->testAttribute(Qt::WA_MacOpaqueSizeGrip)); |
| #endif |
| } |
| |
| void QWidgetPrivate::macUpdateSizeAttribute() |
| { |
| Q_Q(QWidget); |
| QEvent event(QEvent::MacSizeChange); |
| QApplication::sendEvent(q, &event); |
| for (int i = 0; i < children.size(); ++i) { |
| QWidget *w = qobject_cast<QWidget *>(children.at(i)); |
| if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) |
| && !q->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent |
| && !w->testAttribute(Qt::WA_MacSmallSize) |
| && !w->testAttribute(Qt::WA_MacNormalSize)) |
| w->d_func()->macUpdateSizeAttribute(); |
| } |
| resolveFont(); |
| } |
| |
| void QWidgetPrivate::macUpdateIgnoreMouseEvents() |
| { |
| #ifndef QT_MAC_USE_COCOA // This is handled inside the mouse handler on Cocoa. |
| Q_Q(QWidget); |
| if (!q->testAttribute(Qt::WA_WState_Created)) |
| return; |
| |
| if(q->isWindow()) |
| { |
| if(q->testAttribute(Qt::WA_TransparentForMouseEvents)) |
| ChangeWindowAttributes(qt_mac_window_for(q), kWindowIgnoreClicksAttribute, 0); |
| else |
| ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowIgnoreClicksAttribute); |
| ReshapeCustomWindow(qt_mac_window_for(q)); |
| } else { |
| #ifndef kHIViewFeatureIgnoresClicks |
| #define kHIViewFeatureIgnoresClicks kHIViewIgnoresClicks |
| #endif |
| if(q->testAttribute(Qt::WA_TransparentForMouseEvents)) |
| HIViewChangeFeatures(qt_mac_nativeview_for(q), kHIViewFeatureIgnoresClicks, 0); |
| else |
| HIViewChangeFeatures(qt_mac_nativeview_for(q), 0, kHIViewFeatureIgnoresClicks); |
| HIViewReshapeStructure(qt_mac_nativeview_for(q)); |
| } |
| #endif |
| } |
| |
| void QWidgetPrivate::macUpdateMetalAttribute() |
| { |
| Q_Q(QWidget); |
| bool realWindow = isRealWindow(); |
| if (!q->testAttribute(Qt::WA_WState_Created) || !realWindow) |
| return; |
| |
| if (realWindow) { |
| #if QT_MAC_USE_COCOA |
| // Cocoa doesn't let us change the style mask once it's been changed |
| // So, that means we need to recreate the window. |
| OSWindowRef cocoaWindow = qt_mac_window_for(q); |
| if ([cocoaWindow styleMask] & NSTexturedBackgroundWindowMask) |
| return; |
| recreateMacWindow(); |
| #else |
| QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q)); |
| if (q->testAttribute(Qt::WA_MacBrushedMetal)) { |
| if (layout) |
| layout->updateHIToolBarStatus(); |
| ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0); |
| ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0); |
| } else { |
| ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute); |
| ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalAttribute); |
| if (layout) |
| layout->updateHIToolBarStatus(); |
| } |
| #endif |
| } |
| } |
| |
| void QWidgetPrivate::setEnabled_helper_sys(bool enable) |
| { |
| #ifdef QT_MAC_USE_COCOA |
| Q_Q(QWidget); |
| NSView *view = qt_mac_nativeview_for(q); |
| if ([view isKindOfClass:[NSControl class]]) |
| [static_cast<NSControl *>(view) setEnabled:enable]; |
| #else |
| Q_UNUSED(enable); |
| #endif |
| } |
| |
| QT_END_NAMESPACE |