summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/kernel
Long live Qt 4.5!
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri209
-rw-r--r--src/gui/kernel/mac.pri4
-rw-r--r--src/gui/kernel/qaction.cpp1396
-rw-r--r--src/gui/kernel/qaction.h246
-rw-r--r--src/gui/kernel/qaction_p.h129
-rw-r--r--src/gui/kernel/qactiongroup.cpp416
-rw-r--r--src/gui/kernel/qactiongroup.h112
-rw-r--r--src/gui/kernel/qapplication.cpp5051
-rw-r--r--src/gui/kernel/qapplication.h391
-rw-r--r--src/gui/kernel/qapplication_mac.mm2976
-rw-r--r--src/gui/kernel/qapplication_p.h438
-rw-r--r--src/gui/kernel/qapplication_qws.cpp3817
-rw-r--r--src/gui/kernel/qapplication_win.cpp3956
-rw-r--r--src/gui/kernel/qapplication_x11.cpp5919
-rw-r--r--src/gui/kernel/qboxlayout.cpp1534
-rw-r--r--src/gui/kernel/qboxlayout.h173
-rw-r--r--src/gui/kernel/qclipboard.cpp651
-rw-r--r--src/gui/kernel/qclipboard.h130
-rw-r--r--src/gui/kernel/qclipboard_mac.cpp612
-rw-r--r--src/gui/kernel/qclipboard_p.h131
-rw-r--r--src/gui/kernel/qclipboard_qws.cpp304
-rw-r--r--src/gui/kernel/qclipboard_win.cpp389
-rw-r--r--src/gui/kernel/qclipboard_x11.cpp1498
-rw-r--r--src/gui/kernel/qcocoaapplication_mac.mm114
-rw-r--r--src/gui/kernel/qcocoaapplication_mac_p.h103
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac.mm282
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac_p.h119
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac.mm215
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac_p.h90
-rw-r--r--src/gui/kernel/qcocoapanel_mac.mm79
-rw-r--r--src/gui/kernel/qcocoapanel_mac_p.h65
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm1254
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h109
-rw-r--r--src/gui/kernel/qcocoawindow_mac.mm185
-rw-r--r--src/gui/kernel/qcocoawindow_mac_p.h72
-rw-r--r--src/gui/kernel/qcocoawindowcustomthemeframe_mac.mm62
-rw-r--r--src/gui/kernel/qcocoawindowcustomthemeframe_mac_p.h61
-rw-r--r--src/gui/kernel/qcocoawindowdelegate_mac.mm349
-rw-r--r--src/gui/kernel/qcocoawindowdelegate_mac_p.h95
-rw-r--r--src/gui/kernel/qcursor.cpp565
-rw-r--r--src/gui/kernel/qcursor.h160
-rw-r--r--src/gui/kernel/qcursor_mac.mm556
-rw-r--r--src/gui/kernel/qcursor_p.h121
-rw-r--r--src/gui/kernel/qcursor_qws.cpp136
-rw-r--r--src/gui/kernel/qcursor_win.cpp493
-rw-r--r--src/gui/kernel/qcursor_x11.cpp594
-rw-r--r--src/gui/kernel/qdesktopwidget.h104
-rw-r--r--src/gui/kernel/qdesktopwidget_mac.mm244
-rw-r--r--src/gui/kernel/qdesktopwidget_mac_p.h74
-rw-r--r--src/gui/kernel/qdesktopwidget_qws.cpp159
-rw-r--r--src/gui/kernel/qdesktopwidget_win.cpp412
-rw-r--r--src/gui/kernel/qdesktopwidget_x11.cpp380
-rw-r--r--src/gui/kernel/qdnd.cpp697
-rw-r--r--src/gui/kernel/qdnd_mac.mm749
-rw-r--r--src/gui/kernel/qdnd_p.h333
-rw-r--r--src/gui/kernel/qdnd_qws.cpp422
-rw-r--r--src/gui/kernel/qdnd_win.cpp1036
-rw-r--r--src/gui/kernel/qdnd_x11.cpp2064
-rw-r--r--src/gui/kernel/qdrag.cpp357
-rw-r--r--src/gui/kernel/qdrag.h105
-rw-r--r--src/gui/kernel/qevent.cpp3509
-rw-r--r--src/gui/kernel/qevent.h726
-rw-r--r--src/gui/kernel/qevent_p.h94
-rw-r--r--src/gui/kernel/qeventdispatcher_glib_qws.cpp195
-rw-r--r--src/gui/kernel/qeventdispatcher_glib_qws_p.h78
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm926
-rw-r--r--src/gui/kernel/qeventdispatcher_mac_p.h197
-rw-r--r--src/gui/kernel/qeventdispatcher_qws.cpp168
-rw-r--r--src/gui/kernel/qeventdispatcher_qws_p.h86
-rw-r--r--src/gui/kernel/qeventdispatcher_x11.cpp191
-rw-r--r--src/gui/kernel/qeventdispatcher_x11_p.h86
-rw-r--r--src/gui/kernel/qformlayout.cpp2080
-rw-r--r--src/gui/kernel/qformlayout.h163
-rw-r--r--src/gui/kernel/qgridlayout.cpp1889
-rw-r--r--src/gui/kernel/qgridlayout.h176
-rw-r--r--src/gui/kernel/qguieventdispatcher_glib.cpp217
-rw-r--r--src/gui/kernel/qguieventdispatcher_glib_p.h78
-rw-r--r--src/gui/kernel/qguifunctions_wince.cpp377
-rw-r--r--src/gui/kernel/qguifunctions_wince.h157
-rw-r--r--src/gui/kernel/qguivariant.cpp669
-rw-r--r--src/gui/kernel/qkeymapper.cpp121
-rw-r--r--src/gui/kernel/qkeymapper_mac.cpp931
-rw-r--r--src/gui/kernel/qkeymapper_p.h213
-rw-r--r--src/gui/kernel/qkeymapper_qws.cpp77
-rw-r--r--src/gui/kernel/qkeymapper_win.cpp1259
-rw-r--r--src/gui/kernel/qkeymapper_x11.cpp1678
-rw-r--r--src/gui/kernel/qkeymapper_x11_p.cpp488
-rw-r--r--src/gui/kernel/qkeysequence.cpp1469
-rw-r--r--src/gui/kernel/qkeysequence.h231
-rw-r--r--src/gui/kernel/qkeysequence_p.h98
-rw-r--r--src/gui/kernel/qlayout.cpp1585
-rw-r--r--src/gui/kernel/qlayout.h242
-rw-r--r--src/gui/kernel/qlayout_p.h101
-rw-r--r--src/gui/kernel/qlayoutengine.cpp436
-rw-r--r--src/gui/kernel/qlayoutengine_p.h140
-rw-r--r--src/gui/kernel/qlayoutitem.cpp837
-rw-r--r--src/gui/kernel/qlayoutitem.h182
-rw-r--r--src/gui/kernel/qmacdefines_mac.h192
-rw-r--r--src/gui/kernel/qmime.cpp97
-rw-r--r--src/gui/kernel/qmime.h176
-rw-r--r--src/gui/kernel/qmime_mac.cpp1181
-rw-r--r--src/gui/kernel/qmime_win.cpp1594
-rw-r--r--src/gui/kernel/qmotifdnd_x11.cpp1028
-rw-r--r--src/gui/kernel/qnsframeview_mac_p.h154
-rw-r--r--src/gui/kernel/qnsthemeframe_mac_p.h246
-rw-r--r--src/gui/kernel/qnstitledframe_mac_p.h205
-rw-r--r--src/gui/kernel/qole_win.cpp255
-rw-r--r--src/gui/kernel/qpalette.cpp1396
-rw-r--r--src/gui/kernel/qpalette.h262
-rw-r--r--src/gui/kernel/qsessionmanager.h111
-rw-r--r--src/gui/kernel/qsessionmanager_qws.cpp171
-rw-r--r--src/gui/kernel/qshortcut.cpp408
-rw-r--r--src/gui/kernel/qshortcut.h107
-rw-r--r--src/gui/kernel/qshortcutmap.cpp901
-rw-r--r--src/gui/kernel/qshortcutmap_p.h122
-rw-r--r--src/gui/kernel/qsizepolicy.h225
-rw-r--r--src/gui/kernel/qsound.cpp386
-rw-r--r--src/gui/kernel/qsound.h95
-rw-r--r--src/gui/kernel/qsound_mac.mm184
-rw-r--r--src/gui/kernel/qsound_p.h100
-rw-r--r--src/gui/kernel/qsound_qws.cpp350
-rw-r--r--src/gui/kernel/qsound_win.cpp219
-rw-r--r--src/gui/kernel/qsound_x11.cpp296
-rw-r--r--src/gui/kernel/qstackedlayout.cpp545
-rw-r--r--src/gui/kernel/qstackedlayout.h115
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm1096
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h174
-rw-r--r--src/gui/kernel/qt_gui_pch.h85
-rw-r--r--src/gui/kernel/qt_mac.cpp144
-rw-r--r--src/gui/kernel/qt_mac_p.h265
-rw-r--r--src/gui/kernel/qt_x11_p.h723
-rw-r--r--src/gui/kernel/qtooltip.cpp609
-rw-r--r--src/gui/kernel/qtooltip.h84
-rw-r--r--src/gui/kernel/qwhatsthis.cpp772
-rw-r--r--src/gui/kernel/qwhatsthis.h88
-rw-r--r--src/gui/kernel/qwidget.cpp11398
-rw-r--r--src/gui/kernel/qwidget.h1045
-rw-r--r--src/gui/kernel/qwidget_mac.mm4842
-rw-r--r--src/gui/kernel/qwidget_p.h712
-rw-r--r--src/gui/kernel/qwidget_qws.cpp1198
-rw-r--r--src/gui/kernel/qwidget_win.cpp2124
-rw-r--r--src/gui/kernel/qwidget_wince.cpp707
-rw-r--r--src/gui/kernel/qwidget_x11.cpp2891
-rw-r--r--src/gui/kernel/qwidgetaction.cpp288
-rw-r--r--src/gui/kernel/qwidgetaction.h91
-rw-r--r--src/gui/kernel/qwidgetaction_p.h77
-rw-r--r--src/gui/kernel/qwidgetcreate_x11.cpp79
-rw-r--r--src/gui/kernel/qwindowdefs.h152
-rw-r--r--src/gui/kernel/qwindowdefs_win.h132
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp1807
-rw-r--r--src/gui/kernel/qx11embed_x11.h132
-rw-r--r--src/gui/kernel/qx11info_x11.cpp542
-rw-r--r--src/gui/kernel/qx11info_x11.h123
-rw-r--r--src/gui/kernel/win.pri4
-rw-r--r--src/gui/kernel/x11.pri4
155 files changed, 109156 insertions, 0 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
new file mode 100644
index 0000000000..cb2b0148ec
--- /dev/null
+++ b/src/gui/kernel/kernel.pri
@@ -0,0 +1,209 @@
+# Qt kernel module
+
+# Only used on platforms with CONFIG += precompile_header
+PRECOMPILED_HEADER = kernel/qt_gui_pch.h
+
+
+KERNEL_P= kernel
+HEADERS += \
+ kernel/qaction.h \
+ kernel/qactiongroup.h \
+ kernel/qapplication.h \
+ kernel/qapplication_p.h \
+ kernel/qboxlayout.h \
+ kernel/qclipboard.h \
+ kernel/qcursor.h \
+ kernel/qdesktopwidget.h \
+ kernel/qdrag.h \
+ kernel/qdnd_p.h \
+ kernel/qevent.h \
+ kernel/qevent_p.h \
+ kernel/qformlayout.h \
+ kernel/qgridlayout.h \
+ kernel/qkeysequence.h \
+ kernel/qlayout.h \
+ kernel/qlayout_p.h \
+ kernel/qlayoutengine_p.h \
+ kernel/qlayoutitem.h \
+ kernel/qmime.h \
+ kernel/qsessionmanager.h \
+ kernel/qshortcut.h \
+ kernel/qshortcutmap_p.h \
+ kernel/qsizepolicy.h \
+ kernel/qpalette.h \
+ kernel/qsound.h \
+ kernel/qsound_p.h \
+ kernel/qstackedlayout.h \
+ kernel/qtooltip.h \
+ kernel/qwhatsthis.h \
+ kernel/qwidget.h \
+ kernel/qwidget_p.h \
+ kernel/qwidgetaction.h \
+ kernel/qwidgetaction_p.h \
+ kernel/qwindowdefs.h \
+ kernel/qkeymapper_p.h
+
+SOURCES += \
+ kernel/qaction.cpp \
+ kernel/qactiongroup.cpp \
+ kernel/qapplication.cpp \
+ kernel/qboxlayout.cpp \
+ kernel/qclipboard.cpp \
+ kernel/qcursor.cpp \
+ kernel/qdrag.cpp \
+ kernel/qdnd.cpp \
+ kernel/qevent.cpp \
+ kernel/qformlayout.cpp \
+ kernel/qgridlayout.cpp \
+ kernel/qkeysequence.cpp \
+ kernel/qlayout.cpp \
+ kernel/qlayoutengine.cpp \
+ kernel/qlayoutitem.cpp \
+ kernel/qmime.cpp \
+ kernel/qpalette.cpp \
+ kernel/qshortcut.cpp \
+ kernel/qshortcutmap.cpp \
+ kernel/qsound.cpp \
+ kernel/qstackedlayout.cpp \
+ kernel/qtooltip.cpp \
+ kernel/qguivariant.cpp \
+ kernel/qwhatsthis.cpp \
+ kernel/qwidget.cpp \
+ kernel/qwidgetaction.cpp \
+ kernel/qkeymapper.cpp
+
+win32 {
+ DEFINES += QT_NO_DIRECTDRAW
+
+ SOURCES += \
+ kernel/qapplication_win.cpp \
+ kernel/qclipboard_win.cpp \
+ kernel/qcursor_win.cpp \
+ kernel/qdesktopwidget_win.cpp \
+ kernel/qdnd_win.cpp \
+ kernel/qmime_win.cpp \
+ kernel/qsound_win.cpp \
+ kernel/qwidget_win.cpp \
+ kernel/qole_win.cpp \
+ kernel/qkeymapper_win.cpp
+
+ !contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib
+}
+
+unix:x11 {
+ INCLUDEPATH += ../3rdparty/xorg
+ HEADERS += \
+ kernel/qx11embed_x11.h \
+ kernel/qx11info_x11.h
+
+ SOURCES += \
+ kernel/qapplication_x11.cpp \
+ kernel/qclipboard_x11.cpp \
+ kernel/qcursor_x11.cpp \
+ kernel/qdnd_x11.cpp \
+ kernel/qdesktopwidget_x11.cpp \
+ kernel/qmotifdnd_x11.cpp \
+ kernel/qsound_x11.cpp \
+ kernel/qwidget_x11.cpp \
+ kernel/qwidgetcreate_x11.cpp \
+ kernel/qx11embed_x11.cpp \
+ kernel/qx11info_x11.cpp \
+ kernel/qkeymapper_x11.cpp
+
+ contains(QT_CONFIG, glib) {
+ SOURCES += \
+ kernel/qguieventdispatcher_glib.cpp
+ HEADERS += \
+ kernel/qguieventdispatcher_glib_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ LIBS +=$$QT_LIBS_GLIB
+ }
+ SOURCES += \
+ kernel/qeventdispatcher_x11.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_x11_p.h
+}
+
+embedded {
+ HEADERS += \
+ kernel/qeventdispatcher_qws_p.h
+
+ SOURCES += \
+ kernel/qapplication_qws.cpp \
+ kernel/qclipboard_qws.cpp \
+ kernel/qcursor_qws.cpp \
+ kernel/qdesktopwidget_qws.cpp \
+ kernel/qdnd_qws.cpp \
+ kernel/qeventdispatcher_qws.cpp \
+ kernel/qsound_qws.cpp \
+ kernel/qwidget_qws.cpp \
+ kernel/qkeymapper_qws.cpp \
+ kernel/qsessionmanager_qws.cpp
+
+ contains(QT_CONFIG, glib) {
+ SOURCES += \
+ kernel/qeventdispatcher_glib_qws.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_glib_qws_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ }
+
+
+}
+
+!embedded:!x11:mac {
+ SOURCES += \
+ kernel/qclipboard_mac.cpp \
+ kernel/qmime_mac.cpp \
+ kernel/qt_mac.cpp \
+ kernel/qkeymapper_mac.cpp
+
+ OBJECTIVE_HEADERS += \
+ qcocoawindow_mac_p.h \
+ qcocoawindowdelegate_mac_p.h \
+ qcocoaview_mac_p.h \
+ qcocoaapplication_mac_p.h \
+ qcocoaapplicationdelegate_mac_p.h \
+
+ OBJECTIVE_SOURCES += \
+ kernel/qcursor_mac.mm \
+ kernel/qdnd_mac.mm \
+ kernel/qsound_mac.mm \
+ kernel/qapplication_mac.mm \
+ kernel/qwidget_mac.mm \
+ kernel/qcocoapanel_mac.mm \
+ kernel/qcocoaview_mac.mm \
+ kernel/qcocoawindow_mac.mm \
+ kernel/qcocoawindowdelegate_mac.mm \
+ kernel/qcocoamenuloader_mac.mm \
+ kernel/qcocoaapplication_mac.mm \
+ kernel/qcocoaapplicationdelegate_mac.mm \
+ kernel/qt_cocoa_helpers_mac.mm \
+ kernel/qdesktopwidget_mac.mm \
+ kernel/qeventdispatcher_mac.mm \
+ kernel/qcocoawindowcustomthemeframe_mac.mm
+
+ HEADERS += \
+ kernel/qt_cocoa_helpers_mac_p.h \
+ kernel/qcocoaapplication_mac_p.h \
+ kernel/qcocoaapplicationdelegate_mac_p.h \
+ kernel/qeventdispatcher_mac_p.h
+
+ MENU_NIB.files = mac/qt_menu.nib
+ MENU_NIB.path = Resources
+ MENU_NIB.version = Versions
+ QMAKE_BUNDLE_DATA += MENU_NIB
+ RESOURCES += mac/maccursors.qrc
+
+ LIBS += -framework AppKit
+}
+
+wince*: {
+ HEADERS += \
+ ../corelib/kernel/qfunctions_wince.h \
+ kernel/qguifunctions_wince.h
+
+ SOURCES += \
+ ../corelib/kernel/qfunctions_wince.cpp \
+ kernel/qguifunctions_wince.cpp
+}
diff --git a/src/gui/kernel/mac.pri b/src/gui/kernel/mac.pri
new file mode 100644
index 0000000000..415fe0aec5
--- /dev/null
+++ b/src/gui/kernel/mac.pri
@@ -0,0 +1,4 @@
+!x11:!embedded:mac {
+ LIBS += -framework Carbon -lz
+ *-mwerks:INCLUDEPATH += compat
+}
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
new file mode 100644
index 0000000000..abb17d7a63
--- /dev/null
+++ b/src/gui/kernel/qaction.cpp
@@ -0,0 +1,1396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaction.h"
+#include "qactiongroup.h"
+
+#ifndef QT_NO_ACTION
+#include "qaction_p.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qlist.h"
+#include "qdebug.h"
+#include <private/qshortcutmap_p.h>
+#include <private/qapplication_p.h>
+#include <private/qmenu_p.h>
+
+#define QAPP_CHECK(functionName) \
+ if (!qApp) { \
+ qWarning("QAction: Initialize QApplication before calling '" functionName "'."); \
+ return; \
+ }
+
+QT_BEGIN_NAMESPACE
+
+/*
+ internal: guesses a descriptive text from a text suited for a menu entry
+ */
+static QString qt_strippedText(QString s)
+{
+ s.remove( QString::fromLatin1("...") );
+ int i = 0;
+ while (i < s.size()) {
+ ++i;
+ if (s.at(i-1) != QLatin1Char('&'))
+ continue;
+ if (i < s.size() && s.at(i) == QLatin1Char('&'))
+ ++i;
+ s.remove(i-1,1);
+ }
+ return s.trimmed();
+};
+
+
+QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
+ visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
+ menuRole(QAction::TextHeuristicRole), iconVisibleInMenu(-1)
+{
+#ifdef QT3_SUPPORT
+ static int qt_static_action_id = -1;
+ param = id = --qt_static_action_id;
+ act_signal = 0;
+#endif
+#ifndef QT_NO_SHORTCUT
+ shortcutId = 0;
+ shortcutContext = Qt::WindowShortcut;
+ autorepeat = true;
+#endif
+}
+
+QActionPrivate::~QActionPrivate()
+{
+}
+
+void QActionPrivate::sendDataChanged()
+{
+ Q_Q(QAction);
+ QActionEvent e(QEvent::ActionChanged, q);
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *w = widgets.at(i);
+ QApplication::sendEvent(w, &e);
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ for (int i = 0; i < graphicsWidgets.size(); ++i) {
+ QGraphicsWidget *w = graphicsWidgets.at(i);
+ QApplication::sendEvent(w, &e);
+ }
+#endif
+ QApplication::sendEvent(q, &e);
+
+ emit q->changed();
+}
+
+#ifndef QT_NO_SHORTCUT
+void QActionPrivate::redoGrab(QShortcutMap &map)
+{
+ Q_Q(QAction);
+ if (shortcutId)
+ map.removeShortcut(shortcutId, q);
+ if (shortcut.isEmpty())
+ return;
+ shortcutId = map.addShortcut(q, shortcut, shortcutContext);
+ if (!enabled)
+ map.setShortcutEnabled(false, shortcutId, q);
+ if (!autorepeat)
+ map.setShortcutAutoRepeat(false, shortcutId, q);
+}
+
+void QActionPrivate::redoGrabAlternate(QShortcutMap &map)
+{
+ Q_Q(QAction);
+ foreach (int id, alternateShortcutIds)
+ if (id)
+ map.removeShortcut(id, q);
+ alternateShortcutIds.clear();
+ if (alternateShortcuts.isEmpty())
+ return;
+ foreach (const QKeySequence& alternate, alternateShortcuts) {
+ if (!alternate.isEmpty())
+ alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext));
+ else
+ alternateShortcutIds.append(0);
+ }
+ if (!enabled) {
+ foreach (int id, alternateShortcutIds)
+ map.setShortcutEnabled(false, id, q);
+ }
+ if (!autorepeat) {
+ foreach (int id, alternateShortcutIds)
+ map.setShortcutAutoRepeat(false, id, q);
+ }
+}
+
+void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
+{
+ Q_Q(QAction);
+ if (shortcutId)
+ map.setShortcutEnabled(enable, shortcutId, q);
+ foreach (int id, alternateShortcutIds)
+ if (id)
+ map.setShortcutEnabled(enable, id, q);
+}
+#endif // QT_NO_SHORTCUT
+
+
+/*!
+ \class QAction
+ \brief The QAction class provides an abstract user interface
+ action that can be inserted into widgets.
+
+ \ingroup application
+ \mainclass
+
+ \omit
+ * parent and widget are different
+ * parent does not define context
+ \endomit
+
+ In applications many common commands can be invoked via menus,
+ toolbar buttons, and keyboard shortcuts. Since the user expects
+ each command to be performed in the same way, regardless of the
+ user interface used, it is useful to represent each command as
+ an \e action.
+
+ Actions can be added to menus and toolbars, and will
+ automatically keep them in sync. For example, in a word processor,
+ if the user presses a Bold toolbar button, the Bold menu item
+ will automatically be checked.
+
+ Actions can be created as independent objects, but they may
+ also be created during the construction of menus; the QMenu class
+ contains convenience functions for creating actions suitable for
+ use as menu items.
+
+ A QAction may contain an icon, menu text, a shortcut, status text,
+ "What's This?" text, and a tooltip. Most of these can be set in
+ the constructor. They can also be set independently with
+ setIcon(), setText(), setIconText(), setShortcut(),
+ setStatusTip(), setWhatsThis(), and setToolTip(). For menu items,
+ it is possible to set an individual font with setFont().
+
+ Actions are added to widgets using QWidget::addAction() or
+ QGraphicsWidget::addAction(). Note that an action must be added to a
+ widget before it can be used; this is also true when the shortcut should
+ be global (i.e., Qt::ApplicationShortcut as Qt::ShortcutContext).
+
+ Once a QAction has been created it should be added to the relevant
+ menu and toolbar, then connected to the slot which will perform
+ the action. For example:
+
+ \snippet examples/mainwindows/application/mainwindow.cpp 19
+ \codeline
+ \snippet examples/mainwindows/application/mainwindow.cpp 28
+ \snippet examples/mainwindows/application/mainwindow.cpp 31
+
+ We recommend that actions are created as children of the window
+ they are used in. In most cases actions will be children of
+ the application's main window.
+
+ \sa QMenu, QToolBar, {Application Example}
+*/
+
+/*!
+ \fn void QAction::trigger()
+
+ This is a convenience slot that calls activate(Trigger).
+*/
+
+/*!
+ \fn void QAction::hover()
+
+ This is a convenience slot that calls activate(Hover).
+*/
+
+/*!
+ \enum QAction::MenuRole
+
+ This enum describes how an action should be moved into the application menu on Mac OS X.
+
+ \value NoRole This action should not be put into the application menu
+ \value TextHeuristicRole This action should be put in the application menu based on the action's text
+ as described in the QMenuBar documentation.
+ \value ApplicationSpecificRole This action should be put in the application menu with an application specific role
+ \value AboutQtRole This action matches handles the "About Qt" menu item.
+ \value AboutRole This action should be placed where the "About" menu item is in the application menu.
+ \value PreferencesRole This action should be placed where the "Preferences..." menu item is in the application menu.
+ \value QuitRole This action should be placed where the Quit menu item is in the application menu.
+*/
+
+/*!
+ Constructs an action with \a parent. If \a parent is an action
+ group the action will be automatically inserted into the group.
+*/
+QAction::QAction(QObject* parent)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+
+/*!
+ Constructs an action with some \a text and \a parent. If \a
+ parent is an action group the action will be automatically
+ inserted into the group.
+
+ The action uses a stripped version of \a text (e.g. "\&Menu
+ Option..." becomes "Menu Option") as descriptive text for
+ tool buttons. You can override this by setting a specific
+ description with setText(). The same text will be used for
+ tooltips unless you specify a different text using
+ setToolTip().
+
+*/
+QAction::QAction(const QString &text, QObject* parent)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ d->text = text;
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ Constructs an action with an \a icon and some \a text and \a
+ parent. If \a parent is an action group the action will be
+ automatically inserted into the group.
+
+ The action uses a stripped version of \a text (e.g. "\&Menu
+ Option..." becomes "Menu Option") as descriptive text for
+ tool buttons. You can override this by setting a specific
+ description with setText(). The same text will be used for
+ tooltips unless you specify a different text using
+ setToolTip().
+*/
+QAction::QAction(const QIcon &icon, const QString &text, QObject* parent)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ d->icon = icon;
+ d->text = text;
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ \internal
+*/
+QAction::QAction(QActionPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QAction);
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ Returns the parent widget.
+*/
+QWidget *QAction::parentWidget() const
+{
+ QObject *ret = parent();
+ while (ret && !ret->isWidgetType())
+ ret = ret->parent();
+ return (QWidget*)ret;
+}
+
+/*!
+ \since 4.2
+ Returns a list of widgets this action has been added to.
+
+ \sa QWidget::addAction(), associatedGraphicsWidgets()
+*/
+QList<QWidget *> QAction::associatedWidgets() const
+{
+ Q_D(const QAction);
+ return d->widgets;
+}
+
+#ifndef QT_NO_GRAPHICSVIEW
+/*!
+ \since 4.5
+ Returns a list of widgets this action has been added to.
+
+ \sa QWidget::addAction(), associatedWidgets()
+*/
+QList<QGraphicsWidget *> QAction::associatedGraphicsWidgets() const
+{
+ Q_D(const QAction);
+ return d->graphicsWidgets;
+}
+#endif
+
+#ifndef QT_NO_SHORTCUT
+/*!
+ \property QAction::shortcut
+ \brief the action's primary shortcut key
+
+ Valid keycodes for this property can be found in \l Qt::Key and
+ \l Qt::Modifier. There is no default shortcut key.
+*/
+void QAction::setShortcut(const QKeySequence &shortcut)
+{
+ QAPP_CHECK("setShortcut");
+
+ Q_D(QAction);
+ if (d->shortcut == shortcut)
+ return;
+
+ d->shortcut = shortcut;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+/*!
+ \since 4.2
+
+ Sets \a shortcuts as the list of shortcuts that trigger the
+ action. The first element of the list is the primary shortcut.
+
+ \sa shortcut
+*/
+void QAction::setShortcuts(const QList<QKeySequence> &shortcuts)
+{
+ Q_D(QAction);
+
+ QList <QKeySequence> listCopy = shortcuts;
+
+ QKeySequence primary;
+ if (!listCopy.isEmpty())
+ primary = listCopy.takeFirst();
+
+ if (d->shortcut == primary && d->alternateShortcuts == listCopy)
+ return;
+
+ QAPP_CHECK("setShortcuts");
+
+ d->shortcut = primary;
+ d->alternateShortcuts = listCopy;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->redoGrabAlternate(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+/*!
+ \since 4.2
+
+ Sets a platform dependent list of shortcuts based on the \a key.
+ The result of calling this function will depend on the currently running platform.
+ Note that more than one shortcut can assigned by this action.
+ If only the primary shortcut is required, use setShortcut instead.
+
+ \sa QKeySequence::keyBindings()
+*/
+void QAction::setShortcuts(QKeySequence::StandardKey key)
+{
+ QList <QKeySequence> list = QKeySequence::keyBindings(key);
+ setShortcuts(list);
+}
+
+/*!
+ Returns the primary shortcut.
+
+ \sa setShortcuts()
+*/
+QKeySequence QAction::shortcut() const
+{
+ Q_D(const QAction);
+ return d->shortcut;
+}
+
+/*!
+ \since 4.2
+
+ Returns the list of shortcuts, with the primary shortcut as
+ the first element of the list.
+
+ \sa setShortcuts()
+*/
+QList<QKeySequence> QAction::shortcuts() const
+{
+ Q_D(const QAction);
+ QList <QKeySequence> shortcuts;
+ if (!d->shortcut.isEmpty())
+ shortcuts << d->shortcut;
+ if (!d->alternateShortcuts.isEmpty())
+ shortcuts << d->alternateShortcuts;
+ return shortcuts;
+}
+
+/*!
+ \property QAction::shortcutContext
+ \brief the context for the action's shortcut
+
+ Valid values for this property can be found in \l Qt::ShortcutContext.
+ The default value is Qt::WindowShortcut.
+*/
+void QAction::setShortcutContext(Qt::ShortcutContext context)
+{
+ Q_D(QAction);
+ if (d->shortcutContext == context)
+ return;
+ QAPP_CHECK("setShortcutContext");
+ d->shortcutContext = context;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->redoGrabAlternate(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+Qt::ShortcutContext QAction::shortcutContext() const
+{
+ Q_D(const QAction);
+ return d->shortcutContext;
+}
+
+/*!
+ \property QAction::autoRepeat
+ \brief whether the action can auto repeat
+ \since 4.2
+
+ If true, the action will auto repeat when the keyboard shortcut
+ combination is held down, provided that keyboard auto repeat is
+ enabled on the system.
+ The default value is true.
+*/
+void QAction::setAutoRepeat(bool on)
+{
+ Q_D(QAction);
+ if (d->autorepeat == on)
+ return;
+ QAPP_CHECK("setAutoRepeat");
+ d->autorepeat = on;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ d->redoGrabAlternate(qApp->d_func()->shortcutMap);
+ d->sendDataChanged();
+}
+
+bool QAction::autoRepeat() const
+{
+ Q_D(const QAction);
+ return d->autorepeat;
+}
+#endif // QT_NO_SHORTCUT
+
+/*!
+ \property QAction::font
+ \brief the action's font
+
+ The font property is used to render the text set on the
+ QAction. The font will can be considered a hint as it will not be
+ consulted in all cases based upon application and style.
+
+ By default, this property contains the application's default font.
+
+ \sa QAction::setText() QStyle
+*/
+void QAction::setFont(const QFont &font)
+{
+ Q_D(QAction);
+ if (d->font == font)
+ return;
+
+ d->fontSet = true;
+ d->font = font;
+ d->sendDataChanged();
+}
+
+QFont QAction::font() const
+{
+ Q_D(const QAction);
+ return d->font;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use one of the QAction constructors that doesn't take a \a name
+ argument and call setObjectName() instead.
+*/
+QAction::QAction(QObject* parent, const char* name)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ setObjectName(QString::fromAscii(name));
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+
+/*!
+ Use one of the QAction constructors that doesn't take a \a name
+ argument and call setObjectName() instead.
+*/
+QAction::QAction(const QString &text, const QKeySequence &shortcut, QObject* parent, const char* name)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ setObjectName(QString::fromAscii(name));
+ d->text = text;
+ setShortcut(shortcut);
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+
+/*!
+ Use one of the QAction constructors that doesn't take a \a name
+ argument and call setObjectName() instead.
+*/
+QAction::QAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
+ QObject* parent, const char* name)
+ : QObject(*(new QActionPrivate), parent)
+{
+ Q_D(QAction);
+ setObjectName(QString::fromAscii(name));
+ d->text = text;
+ setShortcut(shortcut);
+ d->icon = icon;
+ d->group = qobject_cast<QActionGroup *>(parent);
+ if (d->group)
+ d->group->addAction(this);
+}
+#endif
+
+/*!
+ Destroys the object and frees allocated resources.
+*/
+QAction::~QAction()
+{
+ Q_D(QAction);
+ for (int i = d->widgets.size()-1; i >= 0; --i) {
+ QWidget *w = d->widgets.at(i);
+ w->removeAction(this);
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ for (int i = d->graphicsWidgets.size()-1; i >= 0; --i) {
+ QGraphicsWidget *w = d->graphicsWidgets.at(i);
+ w->removeAction(this);
+ }
+#endif
+ if (d->group)
+ d->group->removeAction(this);
+#ifndef QT_NO_SHORTCUT
+ if (d->shortcutId && qApp) {
+ qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this);
+ foreach (int id, d->alternateShortcutIds)
+ qApp->d_func()->shortcutMap.removeShortcut(id, this);
+ }
+#endif
+}
+
+/*!
+ Sets this action group to \a group. The action will be automatically
+ added to the group's list of actions.
+
+ Actions within the group will be mutually exclusive.
+
+ \sa QActionGroup, QAction::actionGroup()
+*/
+void QAction::setActionGroup(QActionGroup *group)
+{
+ Q_D(QAction);
+ if(group == d->group)
+ return;
+
+ if(d->group)
+ d->group->removeAction(this);
+ d->group = group;
+ if(group)
+ group->addAction(this);
+}
+
+/*!
+ Returns the action group for this action. If no action group manages
+ this action then 0 will be returned.
+
+ \sa QActionGroup, QAction::setActionGroup()
+*/
+QActionGroup *QAction::actionGroup() const
+{
+ Q_D(const QAction);
+ return d->group;
+}
+
+
+/*!
+ \property QAction::icon
+ \brief the action's icon
+
+ In toolbars, the icon is used as the tool button icon; in menus,
+ it is displayed to the left of the menu text. There is no default
+ icon.
+
+ If a null icon (QIcon::isNull() is passed into this function,
+ the icon of the action is cleared.
+*/
+void QAction::setIcon(const QIcon &icon)
+{
+ Q_D(QAction);
+ d->icon = icon;
+ d->sendDataChanged();
+}
+
+QIcon QAction::icon() const
+{
+ Q_D(const QAction);
+ return d->icon;
+}
+
+#ifndef QT_NO_MENU
+/*!
+ Returns the menu contained by this action. Actions that contain
+ menus can be used to create menu items with submenus, or inserted
+ into toolbars to create buttons with popup menus.
+
+ \sa QMenu::addAction()
+*/
+QMenu *QAction::menu() const
+{
+ Q_D(const QAction);
+ return d->menu;
+}
+
+/*!
+ Sets the menu contained by this action to the specified \a menu.
+*/
+void QAction::setMenu(QMenu *menu)
+{
+ Q_D(QAction);
+ if (d->menu)
+ d->menu->d_func()->setOverrideMenuAction(0); //we reset the default action of any previous menu
+ d->menu = menu;
+ if (menu)
+ menu->d_func()->setOverrideMenuAction(this);
+ d->sendDataChanged();
+}
+#endif // QT_NO_MENU
+
+/*!
+ If \a b is true then this action will be considered a separator.
+
+ How a separator is represented depends on the widget it is inserted
+ into. Under most circumstances the text, submenu, and icon will be
+ ignored for separator actions.
+
+ \sa QAction::isSeparator()
+*/
+void QAction::setSeparator(bool b)
+{
+ Q_D(QAction);
+ if (d->separator == b)
+ return;
+
+ d->separator = b;
+ d->sendDataChanged();
+}
+
+/*!
+ Returns true if this action is a separator action; otherwise it
+ returns false.
+
+ \sa QAction::setSeparator()
+*/
+bool QAction::isSeparator() const
+{
+ Q_D(const QAction);
+ return d->separator;
+}
+
+/*!
+ \property QAction::text
+ \brief the action's descriptive text
+
+ If the action is added to a menu, the menu option will consist of
+ the icon (if there is one), the text, and the shortcut (if there
+ is one). If the text is not explicitly set in the constructor, or
+ by using setText(), the action's description icon text will be
+ used as text. There is no default text.
+
+ \sa iconText
+*/
+void QAction::setText(const QString &text)
+{
+ Q_D(QAction);
+ if (d->text == text)
+ return;
+
+ d->text = text;
+ d->sendDataChanged();
+}
+
+QString QAction::text() const
+{
+ Q_D(const QAction);
+ QString s = d->text;
+ if(s.isEmpty()) {
+ s = d->iconText;
+ s.replace(QLatin1Char('&'), QLatin1String("&&"));
+ }
+ return s;
+}
+
+
+
+
+
+/*!
+ \property QAction::iconText
+ \brief the action's descriptive icon text
+
+ If QToolBar::toolButtonStyle is set to a value that permits text to
+ be displayed, the text defined held in this property appears as a
+ label in the relevant tool button.
+
+ It also serves as the default text in menus and tooltips if the action
+ has not been defined with setText() or setToolTip(), and will
+ also be used in toolbar buttons if no icon has been defined using setIcon().
+
+ If the icon text is not explicitly set, the action's normal text will be
+ used for the icon text.
+
+ By default, this property contains an empty string.
+
+ \sa setToolTip(), setStatusTip()
+*/
+void QAction::setIconText(const QString &text)
+{
+ Q_D(QAction);
+ if (d->iconText == text)
+ return;
+
+ d->iconText = text;
+ d->sendDataChanged();
+}
+
+QString QAction::iconText() const
+{
+ Q_D(const QAction);
+ if (d->iconText.isEmpty())
+ return qt_strippedText(d->text);
+ return d->iconText;
+}
+
+/*!
+ \property QAction::toolTip
+ \brief the action's tooltip
+
+ This text is used for the tooltip. If no tooltip is specified,
+ the action's text is used.
+
+ By default, this property contains the action's text.
+
+ \sa setStatusTip() setShortcut()
+*/
+void QAction::setToolTip(const QString &tooltip)
+{
+ Q_D(QAction);
+ if (d->tooltip == tooltip)
+ return;
+
+ d->tooltip = tooltip;
+ d->sendDataChanged();
+}
+
+QString QAction::toolTip() const
+{
+ Q_D(const QAction);
+ if (d->tooltip.isEmpty()) {
+ if (!d->text.isEmpty())
+ return qt_strippedText(d->text);
+ return qt_strippedText(d->iconText);
+ }
+ return d->tooltip;
+}
+
+/*!
+ \property QAction::statusTip
+ \brief the action's status tip
+
+ The status tip is displayed on all status bars provided by the
+ action's top-level parent widget.
+
+ By default, this property contains an empty string.
+
+ \sa setToolTip() showStatusText()
+*/
+void QAction::setStatusTip(const QString &statustip)
+{
+ Q_D(QAction);
+ if (d->statustip == statustip)
+ return;
+
+ d->statustip = statustip;
+ d->sendDataChanged();
+}
+
+QString QAction::statusTip() const
+{
+ Q_D(const QAction);
+ return d->statustip;
+}
+
+/*!
+ \property QAction::whatsThis
+ \brief the action's "What's This?" help text
+
+ The "What's This?" text is used to provide a brief description of
+ the action. The text may contain rich text. There is no default
+ "What's This?" text.
+
+ \sa QWhatsThis Q3StyleSheet
+*/
+void QAction::setWhatsThis(const QString &whatsthis)
+{
+ Q_D(QAction);
+ if (d->whatsthis == whatsthis)
+ return;
+
+ d->whatsthis = whatsthis;
+ d->sendDataChanged();
+}
+
+QString QAction::whatsThis() const
+{
+ Q_D(const QAction);
+ return d->whatsthis;
+}
+
+
+/*!
+ \property QAction::checkable
+ \brief whether the action is a checkable action
+
+ A checkable action is one which has an on/off state. For example,
+ in a word processor, a Bold toolbar button may be either on or
+ off. An action which is not a toggle action is a command action;
+ a command action is simply executed, e.g. file save.
+ By default, this property is false.
+
+ In some situations, the state of one toggle action should depend
+ on the state of others. For example, "Left Align", "Center" and
+ "Right Align" toggle actions are mutually exclusive. To achieve
+ exclusive toggling, add the relevant toggle actions to a
+ QActionGroup with the QActionGroup::exclusive property set to
+ true.
+
+ \sa QAction::setChecked()
+*/
+void QAction::setCheckable(bool b)
+{
+ Q_D(QAction);
+ if (d->checkable == b)
+ return;
+
+ d->checkable = b;
+ d->checked = false;
+ d->sendDataChanged();
+}
+
+bool QAction::isCheckable() const
+{
+ Q_D(const QAction);
+ return d->checkable;
+}
+
+/*!
+ \fn void QAction::toggle()
+
+ This is a convenience function for the \l checked property.
+ Connect to it to change the checked state to its opposite state.
+*/
+void QAction::toggle()
+{
+ Q_D(QAction);
+ setChecked(!d->checked);
+}
+
+/*!
+ \property QAction::checked
+ \brief whether the action is checked.
+
+ Only checkable actions can be checked. By default, this is false
+ (the action is unchecked).
+
+ \sa checkable
+*/
+void QAction::setChecked(bool b)
+{
+ Q_D(QAction);
+ if (!d->checkable || d->checked == b)
+ return;
+
+ QPointer<QAction> guard(this);
+ d->checked = b;
+ d->sendDataChanged();
+ if (guard)
+ emit toggled(b);
+}
+
+bool QAction::isChecked() const
+{
+ Q_D(const QAction);
+ return d->checked;
+}
+
+/*!
+ \fn void QAction::setDisabled(bool b)
+
+ This is a convenience function for the \l enabled property, that
+ is useful for signals--slots connections. If \a b is true the
+ action is disabled; otherwise it is enabled.
+*/
+
+/*!
+ \property QAction::enabled
+ \brief whether the action is enabled
+
+ Disabled actions cannot be chosen by the user. They do not
+ disappear from menus or toolbars, but they are displayed in a way
+ which indicates that they are unavailable. For example, they might
+ be displayed using only shades of gray.
+
+ \gui{What's This?} help on disabled actions is still available, provided
+ that the QAction::whatsThis property is set.
+
+ An action will be disabled when all widgets to which it is added
+ (with QWidget::addAction()) are disabled or not visible. When an
+ action is disabled, it is not possible to trigger it through its
+ shortcut.
+
+ By default, this property is true (actions are enabled).
+
+ \sa text
+*/
+void QAction::setEnabled(bool b)
+{
+ Q_D(QAction);
+ if (b == d->enabled && b != d->forceDisabled)
+ return;
+ d->forceDisabled = !b;
+ if (b && (!d->visible || (d->group && !d->group->isEnabled())))
+ return;
+ QAPP_CHECK("setEnabled");
+ d->enabled = b;
+#ifndef QT_NO_SHORTCUT
+ d->setShortcutEnabled(b, qApp->d_func()->shortcutMap);
+#endif
+ d->sendDataChanged();
+}
+
+bool QAction::isEnabled() const
+{
+ Q_D(const QAction);
+ return d->enabled;
+}
+
+/*!
+ \property QAction::visible
+ \brief whether the action can be seen (e.g. in menus and toolbars)
+
+ If \e visible is true the action can be seen (e.g. in menus and
+ toolbars) and chosen by the user; if \e visible is false the
+ action cannot be seen or chosen by the user.
+
+ Actions which are not visible are \e not grayed out; they do not
+ appear at all.
+
+ By default, this property is true (actions are visible).
+*/
+void QAction::setVisible(bool b)
+{
+ Q_D(QAction);
+ if (b == d->visible && b != d->forceInvisible)
+ return;
+ QAPP_CHECK("setVisible");
+ d->forceInvisible = !b;
+ d->visible = b;
+ d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ;
+#ifndef QT_NO_SHORTCUT
+ d->setShortcutEnabled(d->enabled, qApp->d_func()->shortcutMap);
+#endif
+ d->sendDataChanged();
+}
+
+
+bool QAction::isVisible() const
+{
+ Q_D(const QAction);
+ return d->visible;
+}
+
+/*!
+ \reimp
+*/
+bool
+QAction::event(QEvent *e)
+{
+#ifndef QT_NO_SHORTCUT
+ if (e->type() == QEvent::Shortcut) {
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
+ Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()),
+ "QAction::event",
+ "Received shortcut event from incorrect shortcut");
+ if (se->isAmbiguous())
+ qWarning("QAction::eventFilter: Ambiguous shortcut overload: %s", QString(se->key()).toLatin1().constData());
+ else
+ activate(Trigger);
+ return true;
+ }
+#endif
+ return QObject::event(e);
+}
+
+/*!
+ Returns the user data as set in QAction::setData.
+
+ \sa setData()
+*/
+QVariant
+QAction::data() const
+{
+ Q_D(const QAction);
+ return d->userData;
+}
+
+/*!
+ \fn void QAction::setData(const QVariant &userData)
+
+ Sets the action's internal data to the given \a userData.
+
+ \sa data()
+*/
+void
+QAction::setData(const QVariant &data)
+{
+ Q_D(QAction);
+ d->userData = data;
+ d->sendDataChanged();
+}
+
+
+/*!
+ Updates the relevant status bar for the \a widget specified by sending a
+ QStatusTipEvent to its parent widget. Returns true if an event was sent;
+ otherwise returns false.
+
+ If a null widget is specified, the event is sent to the action's parent.
+
+ \sa statusTip
+*/
+bool
+QAction::showStatusText(QWidget *widget)
+{
+#ifdef QT_NO_STATUSTIP
+ Q_UNUSED(widget);
+#else
+ if(QObject *object = widget ? widget : parent()) {
+ QStatusTipEvent tip(statusTip());
+ QApplication::sendEvent(object, &tip);
+ return true;
+ }
+#endif
+ return false;
+}
+
+/*!
+ Sends the relevant signals for ActionEvent \a event.
+
+ Action based widgets use this API to cause the QAction
+ to emit signals as well as emitting their own.
+*/
+void QAction::activate(ActionEvent event)
+{
+ Q_D(QAction);
+ if(event == Trigger) {
+ QObject *guard = this;
+ QMetaObject::addGuard(&guard);
+ if(d->checkable) {
+ // the checked action of an exclusive group cannot be unchecked
+ if (d->checked && (d->group && d->group->isExclusive()
+ && d->group->checkedAction() == this)) {
+ QMetaObject::removeGuard(&guard);
+ return;
+ }
+ setChecked(!d->checked);
+ }
+ if (guard)
+ emit triggered(d->checked);
+#ifdef QT3_SUPPORT
+ if (guard)
+ emit activated(d->param);
+#endif
+ QMetaObject::removeGuard(&guard);
+ } else if(event == Hover) {
+ emit hovered();
+ }
+}
+
+/*!
+ \fn void QAction::triggered(bool checked)
+
+ This signal is emitted when an action is activated by the user;
+ for example, when the user clicks a menu option, toolbar button,
+ or presses an action's shortcut key combination, or when trigger()
+ was called. Notably, it is \e not emitted when setChecked() or
+ toggle() is called.
+
+ If the action is checkable, \a checked is true if the action is
+ checked, or false if the action is unchecked.
+
+ \sa QAction::activate(), QAction::toggled(), checked
+*/
+
+/*!
+ \fn void QAction::toggled(bool checked)
+
+ This signal is emitted whenever a checkable action changes its
+ isChecked() status. This can be the result of a user interaction,
+ or because setChecked() was called.
+
+ \a checked is true if the action is checked, or false if the
+ action is unchecked.
+
+ \sa QAction::activate(), QAction::triggered(), checked
+*/
+
+/*!
+ \fn void QAction::hovered()
+
+ This signal is emitted when an action is highlighted by the user;
+ for example, when the user pauses with the cursor over a menu option,
+ toolbar button, or presses an action's shortcut key combination.
+
+ \sa QAction::activate()
+*/
+
+/*!
+ \fn void QAction::changed()
+
+ This signal is emitted when an action has changed. If you
+ are only interested in actions in a given widget, you can
+ watch for QWidget::actionEvent() sent with an
+ QEvent::ActionChanged.
+
+ \sa QWidget::actionEvent()
+*/
+
+/*!
+ \enum QAction::ActionEvent
+
+ This enum type is used when calling QAction::activate()
+
+ \value Trigger this will cause the QAction::triggered() signal to be emitted.
+
+ \value Hover this will cause the QAction::hovered() signal to be emitted.
+*/
+
+/*!
+ \fn void QAction::setMenuText(const QString &text)
+
+ Use setText() instead.
+*/
+
+/*!
+ \fn QString QAction::menuText() const
+
+ Use text() instead.
+*/
+
+/*!
+ \fn bool QAction::isOn() const
+
+ Use isChecked() instead.
+*/
+
+/*!
+ \fn void QAction::setOn(bool b)
+
+ Use setChecked() instead.
+*/
+
+/*!
+ \fn bool QAction::isToggleAction() const
+
+ Use isCheckable() instead.
+*/
+
+/*!
+ \fn void QAction::setToggleAction(bool b)
+
+ Use setCheckable() instead.
+*/
+
+/*!
+ \fn void QAction::setIconSet(const QIcon &i)
+
+ Use setIcon() instead.
+*/
+
+/*!
+ \fn bool QAction::addTo(QWidget *w)
+
+ Use QWidget::addAction() instead.
+
+ \oldcode
+ action->addTo(widget);
+ \newcode
+ widget->addAction(action);
+ \endcode
+*/
+
+/*!
+ \fn bool QAction::removeFrom(QWidget *w)
+
+ Use QWidget::removeAction() instead.
+
+ \oldcode
+ action->removeFrom(widget);
+ \newcode
+ widget->removeAction(action);
+ \endcode
+*/
+
+/*!
+ \fn void QAction::setAccel(const QKeySequence &shortcut)
+
+ Use setShortcut() instead.
+*/
+
+/*!
+ \fn QIcon QAction::iconSet() const
+
+ Use icon() instead.
+*/
+
+/*!
+ \fn QKeySequence QAction::accel() const
+
+ Use shortcut() instead.
+*/
+
+/*!
+ \fn void QAction::activated(int i);
+
+ Use triggered() instead.
+*/
+
+
+/*!
+ \property QAction::menuRole
+ \brief the action's menu role
+ \since 4.2
+
+ This indicates what role the action serves in the application menu on Mac
+ OS X. By default all action have the TextHeuristicRole, which means that
+ the action is added based on its text (see QMenuBar for more information).
+
+ The menu role can only be changed before the actions are put into the menu
+ bar in Mac OS X (usually just before the first application window is
+ shown).
+*/
+void QAction::setMenuRole(MenuRole menuRole)
+{
+ Q_D(QAction);
+ if (d->menuRole == menuRole)
+ return;
+
+ d->menuRole = menuRole;
+ d->sendDataChanged();
+}
+
+QAction::MenuRole QAction::menuRole() const
+{
+ Q_D(const QAction);
+ return d->menuRole;
+}
+
+/*!
+ \property QAction::iconVisibleInMenu
+ \brief Whether or not an action should show an icon in a menu
+ \since 4.4
+
+ In some applications, it may make sense to have actions with icons in the
+ toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it
+ is false, it is not shown.
+
+ The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute
+ is set for the application. Explicitly settings this property overrides
+ the presence (or abscence) of the attribute.
+
+ For example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qaction.cpp 0
+
+ \sa QAction::icon QApplication::setAttribute()
+*/
+void QAction::setIconVisibleInMenu(bool visible)
+{
+ Q_D(QAction);
+ if (visible != (bool)d->iconVisibleInMenu) {
+ int oldValue = d->iconVisibleInMenu;
+ d->iconVisibleInMenu = visible;
+ // Only send data changed if we really need to.
+ if (oldValue != -1
+ || (oldValue == -1
+ && visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus))) {
+ d->sendDataChanged();
+ }
+ }
+}
+
+bool QAction::isIconVisibleInMenu() const
+{
+ Q_D(const QAction);
+ if (d->iconVisibleInMenu == -1) {
+ return !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus);
+ }
+ return d->iconVisibleInMenu;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qaction.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
new file mode 100644
index 0000000000..d7bf8c356a
--- /dev/null
+++ b/src/gui/kernel/qaction.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTION_H
+#define QACTION_H
+
+#include <QtGui/qkeysequence.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qicon.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACTION
+
+class QMenu;
+class QActionGroup;
+class QActionPrivate;
+class QGraphicsWidget;
+
+class Q_GUI_EXPORT QAction : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAction)
+
+ Q_ENUMS(MenuRole)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
+ Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(QString iconText READ iconText WRITE setIconText)
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
+ Q_PROPERTY(QFont font READ font WRITE setFont)
+#ifndef QT_NO_SHORTCUT
+ Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
+ Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
+#endif
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
+ Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole)
+ Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu)
+
+public:
+ enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
+ AboutRole, PreferencesRole, QuitRole };
+ explicit QAction(QObject* parent);
+ QAction(const QString &text, QObject* parent);
+ QAction(const QIcon &icon, const QString &text, QObject* parent);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QAction(QObject* parent, const char* name);
+ QT3_SUPPORT_CONSTRUCTOR QAction(const QString &text, const QKeySequence &shortcut,
+ QObject* parent, const char* name);
+ QT3_SUPPORT_CONSTRUCTOR QAction(const QIcon &icon, const QString &text,
+ const QKeySequence &shortcut,
+ QObject* parent, const char* name);
+#endif
+ ~QAction();
+
+ void setActionGroup(QActionGroup *group);
+ QActionGroup *actionGroup() const;
+ void setIcon(const QIcon &icon);
+ QIcon icon() const;
+
+ void setText(const QString &text);
+ QString text() const;
+
+ void setIconText(const QString &text);
+ QString iconText() const;
+
+ void setToolTip(const QString &tip);
+ QString toolTip() const;
+
+ void setStatusTip(const QString &statusTip);
+ QString statusTip() const;
+
+ void setWhatsThis(const QString &what);
+ QString whatsThis() const;
+
+#ifndef QT_NO_MENU
+ QMenu *menu() const;
+ void setMenu(QMenu *menu);
+#endif
+
+ void setSeparator(bool b);
+ bool isSeparator() const;
+
+#ifndef QT_NO_SHORTCUT
+ void setShortcut(const QKeySequence &shortcut);
+ QKeySequence shortcut() const;
+
+ void setShortcuts(const QList<QKeySequence> &shortcuts);
+ void setShortcuts(QKeySequence::StandardKey);
+ QList<QKeySequence> shortcuts() const;
+
+ void setShortcutContext(Qt::ShortcutContext context);
+ Qt::ShortcutContext shortcutContext() const;
+
+ void setAutoRepeat(bool);
+ bool autoRepeat() const;
+#endif
+
+ void setFont(const QFont &font);
+ QFont font() const;
+
+ void setCheckable(bool);
+ bool isCheckable() const;
+
+ QVariant data() const;
+ void setData(const QVariant &var);
+
+ bool isChecked() const;
+
+ bool isEnabled() const;
+
+ bool isVisible() const;
+
+ enum ActionEvent { Trigger, Hover };
+ void activate(ActionEvent event);
+ bool showStatusText(QWidget *widget=0);
+
+ void setMenuRole(MenuRole menuRole);
+ MenuRole menuRole() const;
+
+ void setIconVisibleInMenu(bool visible);
+ bool isIconVisibleInMenu() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setMenuText(const QString &text) { setText(text); }
+ inline QT3_SUPPORT QString menuText() const { return text(); }
+ inline QT3_SUPPORT bool isOn() const { return isChecked(); }
+ inline QT3_SUPPORT bool isToggleAction() const { return isCheckable(); }
+ inline QT3_SUPPORT void setToggleAction(bool b) { setCheckable(b); }
+ inline QT3_SUPPORT void setIconSet(const QIcon &i) { setIcon(i); }
+ inline QT3_SUPPORT QIcon iconSet() const { return icon(); }
+ inline QT3_SUPPORT bool addTo(QWidget *w) { w->addAction(this); return true; }
+ inline QT3_SUPPORT bool removeFrom(QWidget *w) { w->removeAction(this); return true; }
+ inline QT3_SUPPORT void setAccel(const QKeySequence &shortcut) { setShortcut(shortcut); }
+ inline QT3_SUPPORT QKeySequence accel() const { return shortcut(); }
+#endif
+
+ QWidget *parentWidget() const;
+
+ QList<QWidget *> associatedWidgets() const;
+#ifndef QT_NO_GRAPHICSVIEW
+ QList<QGraphicsWidget *> associatedGraphicsWidgets() const; // ### suboptimal
+#endif
+
+protected:
+ bool event(QEvent *);
+ QAction(QActionPrivate &dd, QObject *parent);
+
+public Q_SLOTS:
+#ifdef QT3_SUPPORT
+ inline QT_MOC_COMPAT void setOn(bool b) { setChecked(b); }
+#endif
+ void trigger() { activate(Trigger); }
+ void hover() { activate(Hover); }
+ void setChecked(bool);
+ void toggle();
+ void setEnabled(bool);
+ inline void setDisabled(bool b) { setEnabled(!b); }
+ void setVisible(bool);
+
+Q_SIGNALS:
+ void changed();
+ void triggered(bool checked = false);
+ void hovered();
+ void toggled(bool);
+#ifdef QT3_SUPPORT
+ QT_MOC_COMPAT void activated(int = 0);
+#endif
+
+private:
+ Q_DISABLE_COPY(QAction)
+
+#ifdef QT3_SUPPORT
+ friend class QMenuItem;
+#endif
+ friend class QGraphicsWidget;
+ friend class QWidget;
+ friend class QActionGroup;
+ friend class QMenu;
+ friend class QMenuPrivate;
+ friend class QMenuBar;
+ friend class QShortcutMap;
+ friend class QToolButton;
+};
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtGui/qactiongroup.h>
+QT_END_INCLUDE_NAMESPACE
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACTION_H
diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h
new file mode 100644
index 0000000000..0617ef56c7
--- /dev/null
+++ b/src/gui/kernel/qaction_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTION_P_H
+#define QACTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qaction.h"
+#include "QtGui/qmenu.h"
+#include "private/qgraphicswidget_p.h"
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACTION
+
+#ifdef QT3_SUPPORT
+class QMenuItemEmitter;
+#endif
+
+class QShortcutMap;
+
+class Q_AUTOTEST_EXPORT QActionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAction)
+public:
+ QActionPrivate();
+ ~QActionPrivate();
+
+ QPointer<QActionGroup> group;
+ QString text;
+ QString iconText;
+ QIcon icon;
+ QString tooltip;
+ QString statustip;
+ QString whatsthis;
+#ifndef QT_NO_SHORTCUT
+ QKeySequence shortcut;
+ QList<QKeySequence> alternateShortcuts;
+#endif
+ QVariant userData;
+#ifndef QT_NO_SHORTCUT
+ int shortcutId;
+ QList<int> alternateShortcutIds;
+ Qt::ShortcutContext shortcutContext;
+ uint autorepeat : 1;
+#endif
+ QFont font;
+ QPointer<QMenu> menu;
+ uint enabled : 1, forceDisabled : 1;
+ uint visible : 1, forceInvisible : 1;
+ uint checkable : 1;
+ uint checked : 1;
+ uint separator : 1;
+ uint fontSet : 1;
+ QAction::MenuRole menuRole;
+ int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
+ QList<QWidget *> widgets;
+#ifndef QT_NO_GRAPHICSVIEW
+ QList<QGraphicsWidget *> graphicsWidgets;
+#endif
+#ifndef QT_NO_SHORTCUT
+ void redoGrab(QShortcutMap &map);
+ void redoGrabAlternate(QShortcutMap &map);
+ void setShortcutEnabled(bool enable, QShortcutMap &map);
+
+ static QShortcutMap *globalMap;
+#endif // QT_NO_SHORTCUT
+
+#ifdef QT3_SUPPORT //for menubar/menu compat
+ QMenuItemEmitter *act_signal;
+ int id, param;
+#endif
+ void sendDataChanged();
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+#endif // QACTION_P_H
diff --git a/src/gui/kernel/qactiongroup.cpp b/src/gui/kernel/qactiongroup.cpp
new file mode 100644
index 0000000000..2fd595e34c
--- /dev/null
+++ b/src/gui/kernel/qactiongroup.cpp
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qactiongroup.h"
+
+#ifndef QT_NO_ACTION
+
+#include "qaction_p.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qlist.h"
+
+QT_BEGIN_NAMESPACE
+
+class QActionGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QActionGroup)
+public:
+ QActionGroupPrivate() : exclusive(1), enabled(1), visible(1) { }
+ QList<QAction *> actions;
+ QPointer<QAction> current;
+ uint exclusive : 1;
+ uint enabled : 1;
+ uint visible : 1;
+
+private:
+ void _q_actionTriggered(); //private slot
+ void _q_actionChanged(); //private slot
+ void _q_actionHovered(); //private slot
+};
+
+void QActionGroupPrivate::_q_actionChanged()
+{
+ Q_Q(QActionGroup);
+ QAction *action = qobject_cast<QAction*>(q->sender());
+ Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error");
+ if(exclusive && action->isChecked() && action != current) {
+ if(current)
+ current->setChecked(false);
+ current = action;
+ }
+}
+
+void QActionGroupPrivate::_q_actionTriggered()
+{
+ Q_Q(QActionGroup);
+ QAction *action = qobject_cast<QAction*>(q->sender());
+ Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionTriggered", "internal error");
+ emit q->triggered(action);
+ emit q->selected(action);
+}
+
+void QActionGroupPrivate::_q_actionHovered()
+{
+ Q_Q(QActionGroup);
+ QAction *action = qobject_cast<QAction*>(q->sender());
+ Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionHovered", "internal error");
+ emit q->hovered(action);
+}
+
+/*!
+ \class QActionGroup
+ \brief The QActionGroup class groups actions together.
+
+ \ingroup application
+
+ In some situations it is useful to group actions together. For
+ example, if you have a \gui{Left Align} action, a \gui{Right
+ Align} action, a \gui{Justify} action, and a \gui{Center} action,
+ only one of these actions should be active at any one time. One
+ simple way of achieving this is to group the actions together in
+ an action group.
+
+ Here's a example (from the \l{mainwindows/menus}{Menus} example):
+
+ \snippet examples/mainwindows/menus/mainwindow.cpp 6
+
+ Here we create a new action group. Since the action group is
+ exclusive by default, only one of the actions in the group is
+ checked at any one time.
+
+ \img qactiongroup-align.png Alignment options in a QMenu
+
+ A QActionGroup emits an triggered() signal when one of its
+ actions is chosen. Each action in an action group emits its
+ triggered() signal as usual.
+
+ As stated above, an action group is \l exclusive by default; it
+ ensures that only one checkable action is active at any one time.
+ If you want to group checkable actions without making them
+ exclusive, you can turn of exclusiveness by calling
+ setExclusive(false).
+
+ Actions can be added to an action group using addAction(), but it
+ is usually more convenient to specify a group when creating
+ actions; this ensures that actions are automatically created with
+ a parent. Actions can be visually separated from each other by
+ adding a separator action to the group; create an action and use
+ QAction's \l {QAction::}{setSeparator()} function to make it
+ considered a separator. Action groups are added to widgets with
+ the QWidget::addActions() function.
+
+ \sa QAction
+*/
+
+/*!
+ Constructs an action group for the \a parent object.
+
+ The action group is exclusive by default. Call setExclusive(false)
+ to make the action group non-exclusive.
+*/
+QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent)
+{
+}
+
+/*!
+ Destroys the action group.
+*/
+QActionGroup::~QActionGroup()
+{
+}
+
+/*!
+ \fn QAction *QActionGroup::addAction(QAction *action)
+
+ Adds the \a action to this group, and returns it.
+
+ Normally an action is added to a group by creating it with the
+ group as its parent, so this function is not usually used.
+
+ \sa QAction::setActionGroup()
+*/
+QAction *QActionGroup::addAction(QAction* a)
+{
+ Q_D(QActionGroup);
+ if(!d->actions.contains(a)) {
+ d->actions.append(a);
+ QObject::connect(a, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+ QObject::connect(a, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
+ QObject::connect(a, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
+ }
+ if(!a->d_func()->forceDisabled) {
+ a->setEnabled(d->enabled);
+ a->d_func()->forceDisabled = false;
+ }
+ if(!a->d_func()->forceInvisible) {
+ a->setVisible(d->visible);
+ a->d_func()->forceInvisible = false;
+ }
+ if(a->isChecked())
+ d->current = a;
+ QActionGroup *oldGroup = a->d_func()->group;
+ if(oldGroup != this) {
+ if (oldGroup)
+ oldGroup->removeAction(a);
+ a->d_func()->group = this;
+ }
+ return a;
+}
+
+/*!
+ Creates and returns an action with \a text. The newly created
+ action is a child of this action group.
+
+ Normally an action is added to a group by creating it with the
+ group as parent, so this function is not usually used.
+
+ \sa QAction::setActionGroup()
+*/
+QAction *QActionGroup::addAction(const QString &text)
+{
+ return new QAction(text, this);
+}
+
+/*!
+ Creates and returns an action with \a text and an \a icon. The
+ newly created action is a child of this action group.
+
+ Normally an action is added to a group by creating it with the
+ group as its parent, so this function is not usually used.
+
+ \sa QAction::setActionGroup()
+*/
+QAction *QActionGroup::addAction(const QIcon &icon, const QString &text)
+{
+ return new QAction(icon, text, this);
+}
+
+/*!
+ Removes the \a action from this group. The action will have no
+ parent as a result.
+
+ \sa QAction::setActionGroup()
+*/
+void QActionGroup::removeAction(QAction *action)
+{
+ Q_D(QActionGroup);
+ if (d->actions.removeAll(action)) {
+ if (action == d->current)
+ d->current = 0;
+ QObject::disconnect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+ QObject::disconnect(action, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
+ QObject::disconnect(action, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
+ action->d_func()->group = 0;
+ }
+}
+
+/*!
+ Returns the list of this groups's actions. This may be empty.
+*/
+QList<QAction*> QActionGroup::actions() const
+{
+ Q_D(const QActionGroup);
+ return d->actions;
+}
+
+/*!
+ \property QActionGroup::exclusive
+ \brief whether the action group does exclusive checking
+
+ If exclusive is true, only one checkable action in the action group
+ can ever be active at any time. If the user chooses another
+ checkable action in the group, the one they chose becomes active and
+ the one that was active becomes inactive.
+
+ \sa QAction::checkable
+*/
+void QActionGroup::setExclusive(bool b)
+{
+ Q_D(QActionGroup);
+ d->exclusive = b;
+}
+
+bool QActionGroup::isExclusive() const
+{
+ Q_D(const QActionGroup);
+ return d->exclusive;
+}
+
+/*!
+ \fn void QActionGroup::setDisabled(bool b)
+
+ This is a convenience function for the \l enabled property, that
+ is useful for signals--slots connections. If \a b is true the
+ action group is disabled; otherwise it is enabled.
+*/
+
+/*!
+ \property QActionGroup::enabled
+ \brief whether the action group is enabled
+
+ Each action in the group will be enabled or disabled unless it
+ has been explicitly disabled.
+
+ \sa QAction::setEnabled()
+*/
+void QActionGroup::setEnabled(bool b)
+{
+ Q_D(QActionGroup);
+ d->enabled = b;
+ for(QList<QAction*>::const_iterator it = d->actions.constBegin(); it != d->actions.constEnd(); ++it) {
+ if(!(*it)->d_func()->forceDisabled) {
+ (*it)->setEnabled(b);
+ (*it)->d_func()->forceDisabled = false;
+ }
+ }
+}
+
+bool QActionGroup::isEnabled() const
+{
+ Q_D(const QActionGroup);
+ return d->enabled;
+}
+
+/*!
+ Returns the currently checked action in the group, or 0 if none
+ are checked.
+*/
+QAction *QActionGroup::checkedAction() const
+{
+ Q_D(const QActionGroup);
+ return d->current;
+}
+
+/*!
+ \property QActionGroup::visible
+ \brief whether the action group is visible
+
+ Each action in the action group will match the visible state of
+ this group unless it has been explicitly hidden.
+
+ \sa QAction::setEnabled()
+*/
+void QActionGroup::setVisible(bool b)
+{
+ Q_D(QActionGroup);
+ d->visible = b;
+ for(QList<QAction*>::Iterator it = d->actions.begin(); it != d->actions.end(); ++it) {
+ if(!(*it)->d_func()->forceInvisible) {
+ (*it)->setVisible(b);
+ (*it)->d_func()->forceInvisible = false;
+ }
+ }
+}
+
+bool QActionGroup::isVisible() const
+{
+ Q_D(const QActionGroup);
+ return d->visible;
+}
+
+/*!
+ \fn void QActionGroup::triggered(QAction *action)
+
+ This signal is emitted when the given \a action in the action
+ group is activated by the user; for example, when the user clicks
+ a menu option, toolbar button, or presses an action's shortcut key
+ combination.
+
+ Connect to this signal for command actions.
+
+ \sa QAction::activate()
+*/
+
+/*!
+ \fn void QActionGroup::hovered(QAction *action)
+
+ This signal is emitted when the given \a action in the action
+ group is highlighted by the user; for example, when the user
+ pauses with the cursor over a menu option, toolbar button, or
+ presses an action's shortcut key combination.
+
+ \sa QAction::activate()
+*/
+
+/*!
+ \fn void QActionGroup::add(QAction* a)
+
+ Use addAction() instead.
+*/
+
+/*!
+ \fn void QActionGroup::addSeparator()
+
+ Normally you add a separator to the menus or widgets to which
+ actions are added, so this function is very rarely needed.
+
+ \oldcode
+ actionGroup->addSeparator();
+ \newcode
+ QAction *separator = new QAction(this);
+ separator->setSeparator(true);
+ actionGroup->addAction(separator);
+ \endcode
+*/
+
+/*!
+ \fn bool QActionGroup::addTo(QWidget *widget)
+
+ \oldcode
+ actionGroup->addTo(widget);
+ \newcode
+ widget->addActions(actionGroup->actions());
+ \endcode
+*/
+
+/*!
+ \fn void QActionGroup::selected(QAction *action);
+
+ Use triggered() instead.
+
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qactiongroup.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/gui/kernel/qactiongroup.h b/src/gui/kernel/qactiongroup.h
new file mode 100644
index 0000000000..3d1231f092
--- /dev/null
+++ b/src/gui/kernel/qactiongroup.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIONGROUP_H
+#define QACTIONGROUP_H
+
+#include <QtGui/qaction.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACTION
+
+class QActionGroupPrivate;
+
+class Q_GUI_EXPORT QActionGroup : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QActionGroup)
+
+ Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
+
+public:
+ explicit QActionGroup(QObject* parent);
+ ~QActionGroup();
+
+ QAction *addAction(QAction* a);
+ QAction *addAction(const QString &text);
+ QAction *addAction(const QIcon &icon, const QString &text);
+ void removeAction(QAction *a);
+ QList<QAction*> actions() const;
+
+ QAction *checkedAction() const;
+ bool isExclusive() const;
+ bool isEnabled() const;
+ bool isVisible() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void add(QAction* a) { addAction(a); }
+ inline QT3_SUPPORT void addSeparator()
+ { QAction *act = new QAction(this); act->setSeparator(true); addAction(act); }
+ inline QT3_SUPPORT bool addTo(QWidget *w) { w->addActions(actions()); return true; }
+#endif
+
+public Q_SLOTS:
+ void setEnabled(bool);
+ inline void setDisabled(bool b) { setEnabled(!b); }
+ void setVisible(bool);
+ void setExclusive(bool);
+
+Q_SIGNALS:
+ void triggered(QAction *);
+ QT_MOC_COMPAT void selected(QAction *);
+ void hovered(QAction *);
+
+private:
+ Q_DISABLE_COPY(QActionGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered())
+ Q_PRIVATE_SLOT(d_func(), void _q_actionChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_actionHovered())
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACTIONGROUP_H
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
new file mode 100644
index 0000000000..1bbb0190c2
--- /dev/null
+++ b/src/gui/kernel/qapplication.cpp
@@ -0,0 +1,5051 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstracteventdispatcher.h"
+#include "qaccessible.h"
+#include "qapplication.h"
+#include "qclipboard.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "qdir.h"
+#include "qevent.h"
+#include "qfile.h"
+#include "qfileinfo.h"
+#include "qgraphicsscene.h"
+#include "qhash.h"
+#include "qset.h"
+#include "qlayout.h"
+#include "qsessionmanager.h"
+#include "qstyle.h"
+#include "qstylefactory.h"
+#include "qtextcodec.h"
+#include "qtranslator.h"
+#include "qvariant.h"
+#include "qwidget.h"
+#include "qdnd_p.h"
+#include "qcolormap.h"
+#include "qdebug.h"
+#include "private/qgraphicssystemfactory_p.h"
+#include "private/qstylesheetstyle_p.h"
+#include "private/qstyle_p.h"
+#include "qmessagebox.h"
+#include <QtGui/qgraphicsproxywidget.h>
+
+#include "qinputcontext.h"
+#include "qkeymapper_p.h"
+
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#include "qinputcontextfactory.h"
+#endif
+
+#include <qthread.h>
+#include <private/qthread_p.h>
+
+#include <private/qfont_p.h>
+
+#include <stdlib.h>
+
+#include "qapplication_p.h"
+#include "qwidget_p.h"
+
+#include "qapplication.h"
+
+#ifdef Q_OS_WINCE
+#include "qdatetime.h"
+#include "qguifunctions_wince.h"
+extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp
+extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp
+extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
+#endif
+
+//#define ALIEN_DEBUG
+
+static void initResources()
+{
+#ifdef Q_OS_WINCE
+ Q_INIT_RESOURCE(qstyle_wince);
+#else
+ Q_INIT_RESOURCE(qstyle);
+#endif
+
+#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
+ Q_INIT_RESOURCE(qpaintengine_d3d);
+#endif
+ Q_INIT_RESOURCE(qmessagebox);
+#if !defined(QT_NO_PRINTDIALOG)
+ Q_INIT_RESOURCE(qprintdialog);
+#endif
+
+}
+
+QT_BEGIN_NAMESPACE
+
+extern void qt_call_post_routines();
+
+int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0
+
+QApplication::Type qt_appType=QApplication::Tty;
+QApplicationPrivate *QApplicationPrivate::self = 0;
+
+QInputContext *QApplicationPrivate::inputContext;
+
+bool QApplicationPrivate::quitOnLastWindowClosed = true;
+
+#ifdef Q_OS_WINCE
+int QApplicationPrivate::autoMaximizeThreshold = -1;
+bool QApplicationPrivate::autoSipEnabled = false;
+#endif
+
+QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type)
+ : QCoreApplicationPrivate(argc, argv)
+{
+ application_type = type;
+ qt_appType = type;
+
+#ifndef QT_NO_SESSIONMANAGER
+ is_session_restored = false;
+#endif
+
+ quitOnLastWindowClosed = true;
+
+#ifdef QT3_SUPPORT
+ qt_compat_used = 0;
+ qt_compat_resolved = 0;
+ qt_tryAccelEvent = 0;
+ qt_tryComposeUnicode = 0;
+ qt_dispatchAccelEvent = 0;
+#endif
+#if defined(Q_WS_QWS) && !defined(QT_NO_DIRECTPAINTER)
+ directPainters = 0;
+#endif
+
+ if (!self)
+ self = this;
+}
+
+QApplicationPrivate::~QApplicationPrivate()
+{
+ if (self == this)
+ self = 0;
+}
+
+/*!
+ \class QApplication
+ \brief The QApplication class manages the GUI application's control
+ flow and main settings.
+
+ \ingroup application
+ \mainclass
+
+ It contains the main event loop, where all events from the window
+ system and other sources are processed and dispatched. It also
+ handles the application's initialization and finalization, and
+ provides session management. It also handles most system-wide and
+ application-wide settings.
+
+ For any GUI application that uses Qt, there is precisely one
+ QApplication object, no matter whether the application has 0, 1, 2
+ or more windows at any time. For non-GUI Qt applications, use
+ QCoreApplication instead, which doesn't depend on the \l QtGui
+ library.
+
+ The QApplication object is accessible through the instance()
+ function which return a pointer equivalent to the global qApp
+ pointer.
+
+ QApplication's main areas of responsibility are:
+ \list
+
+ \o It initializes the application with the user's desktop settings
+ such as palette(), font() and doubleClickInterval(). It keeps track
+ of these properties in case the user changes the desktop globally, for
+ example through some kind of control panel.
+
+ \o It performs event handling, meaning that it receives events
+ from the underlying window system and dispatches them to the relevant
+ widgets. By using sendEvent() and postEvent() you can send your own
+ events to widgets.
+
+ \o It parses common command line arguments and sets its internal
+ state accordingly. See the \link QApplication::QApplication()
+ constructor documentation\endlink below for more details about this.
+
+ \o It defines the application's look and feel, which is
+ encapsulated in a QStyle object. This can be changed at runtime
+ with setStyle().
+
+ \o It specifies how the application is to allocate colors.
+ See setColorSpec() for details.
+
+ \o It provides localization of strings that are visible to the user
+ via translate().
+
+ \o It provides some magical objects like the desktop() and the
+ clipboard().
+
+ \o It knows about the application's windows. You can ask which
+ widget is at a certain position using widgetAt(), get a list of
+ topLevelWidgets() and closeAllWindows(), etc.
+
+ \o It manages the application's mouse cursor handling,
+ see setOverrideCursor()
+
+ \o On the X window system, it provides functions to flush and sync
+ the communication stream, see flushX() and syncX().
+
+ \o It provides support for sophisticated \link
+ session.html session management \endlink. This makes it possible
+ for applications to terminate gracefully when the user logs out, to
+ cancel a shutdown process if termination isn't possible and even to
+ preserve the entire application's state for a future session. See
+ isSessionRestored(), sessionId() and commitData() and saveState()
+ for details.
+
+ \endlist
+
+ Since the QApplication object does so much initialization, it
+ \e{must} be created before any other objects related to the user
+ interface are created.
+
+ Since it also deals with common command line arguments, it is
+ usually a good idea to create it \e before any interpretation or
+ modification of \c argv is done in the application itself.
+
+ \table
+ \header \o{2,1} Groups of functions
+ \row
+ \o System settings
+ \o
+ desktopSettingsAware(),
+ setDesktopSettingsAware(),
+ cursorFlashTime(),
+ setCursorFlashTime(),
+ doubleClickInterval(),
+ setDoubleClickInterval(),
+ setKeyboardInputInterval(),
+ wheelScrollLines(),
+ setWheelScrollLines(),
+ palette(),
+ setPalette(),
+ font(),
+ setFont(),
+ fontMetrics().
+
+ \row
+ \o Event handling
+ \o
+ exec(),
+ processEvents(),
+ exit(),
+ quit().
+ sendEvent(),
+ postEvent(),
+ sendPostedEvents(),
+ removePostedEvents(),
+ hasPendingEvents(),
+ notify(),
+ macEventFilter(),
+ qwsEventFilter(),
+ x11EventFilter(),
+ x11ProcessEvent(),
+ winEventFilter().
+
+ \row
+ \o GUI Styles
+ \o
+ style(),
+ setStyle().
+
+ \row
+ \o Color usage
+ \o
+ colorSpec(),
+ setColorSpec(),
+ qwsSetCustomColors().
+
+ \row
+ \o Text handling
+ \o
+ installTranslator(),
+ removeTranslator()
+ translate().
+
+ \row
+ \o Widgets
+ \o
+ allWidgets(),
+ topLevelWidgets(),
+ desktop(),
+ activePopupWidget(),
+ activeModalWidget(),
+ clipboard(),
+ focusWidget(),
+ winFocus(),
+ activeWindow(),
+ widgetAt().
+
+ \row
+ \o Advanced cursor handling
+ \o
+ overrideCursor(),
+ setOverrideCursor(),
+ restoreOverrideCursor().
+
+ \row
+ \o X Window System synchronization
+ \o
+ flushX(),
+ syncX().
+
+ \row
+ \o Session management
+ \o
+ isSessionRestored(),
+ sessionId(),
+ commitData(),
+ saveState().
+
+ \row
+ \o Miscellaneous
+ \o
+ closeAllWindows(),
+ startingUp(),
+ closingDown(),
+ type().
+ \endtable
+
+ \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings
+*/
+
+/*!
+ \enum QApplication::Type
+
+ \value Tty a console application
+ \value GuiClient a GUI client application
+ \value GuiServer a GUI server application (for Qt for Embedded Linux)
+*/
+
+/*!
+ \enum QApplication::ColorSpec
+
+ \value NormalColor the default color allocation policy
+ \value CustomColor the same as NormalColor for X11; allocates colors
+ to a palette on demand under Windows
+ \value ManyColor the right choice for applications that use thousands of
+ colors
+
+ See setColorSpec() for full details.
+*/
+
+/*!
+ \fn QWidget *QApplication::topLevelAt(const QPoint &point)
+
+ Returns the top-level widget at the given \a point; returns 0 if
+ there is no such widget.
+*/
+/*!
+ \fn QWidget *QApplication::topLevelAt(int x, int y)
+
+ \overload
+
+ Returns the top-level widget at the point (\a{x}, \a{y}); returns
+ 0 if there is no such widget.
+*/
+
+
+/*
+ The qt_init() and qt_cleanup() functions are implemented in the
+ qapplication_xyz.cpp file.
+*/
+
+void qt_init(QApplicationPrivate *priv, int type
+#ifdef Q_WS_X11
+ , Display *display = 0, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0
+#endif
+ );
+void qt_cleanup();
+
+Qt::MouseButtons QApplicationPrivate::mouse_buttons = Qt::NoButton;
+Qt::KeyboardModifiers QApplicationPrivate::modifier_buttons = Qt::NoModifier;
+
+QStyle *QApplicationPrivate::app_style = 0; // default application style
+
+#ifndef QT_NO_STYLE_STYLESHEET
+QString QApplicationPrivate::styleSheet; // default application stylesheet
+#endif
+QPointer<QWidget> QApplicationPrivate::leaveAfterRelease = 0;
+
+int QApplicationPrivate::app_cspec = QApplication::NormalColor;
+QPalette *QApplicationPrivate::app_pal = 0; // default application palette
+QPalette *QApplicationPrivate::sys_pal = 0; // default system palette
+QPalette *QApplicationPrivate::set_pal = 0; // default palette set by programmer
+
+QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system
+QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization
+
+Q_GLOBAL_STATIC(QMutex, applicationFontMutex);
+QFont *QApplicationPrivate::app_font = 0; // default application font
+QFont *QApplicationPrivate::sys_font = 0; // default system font
+QFont *QApplicationPrivate::set_font = 0; // default font set by programmer
+
+QIcon *QApplicationPrivate::app_icon = 0;
+QWidget *QApplicationPrivate::main_widget = 0; // main application widget
+QWidget *QApplicationPrivate::focus_widget = 0; // has keyboard input focus
+QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard input focus after show()
+QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus
+bool QApplicationPrivate::obey_desktop_settings = true; // use winsys resources
+int QApplicationPrivate::cursor_flash_time = 1000; // text caret flash time
+int QApplicationPrivate::mouse_double_click_time = 400; // mouse dbl click limit
+int QApplicationPrivate::keyboard_input_time = 400; // keyboard input interval
+#ifndef QT_NO_WHEELEVENT
+int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll
+#endif
+bool qt_is_gui_used;
+bool Q_GUI_EXPORT qt_tab_all_widgets = true;
+bool qt_in_tab_key_event = false;
+int qt_antialiasing_threshold = -1;
+static int drag_time = 500;
+static int drag_distance = 4;
+static Qt::LayoutDirection layout_direction = Qt::LeftToRight;
+QSize QApplicationPrivate::app_strut = QSize(0,0); // no default application strut
+bool QApplicationPrivate::animate_ui = true;
+bool QApplicationPrivate::animate_menu = false;
+bool QApplicationPrivate::fade_menu = false;
+bool QApplicationPrivate::animate_combo = false;
+bool QApplicationPrivate::animate_tooltip = false;
+bool QApplicationPrivate::fade_tooltip = false;
+bool QApplicationPrivate::animate_toolbox = false;
+bool QApplicationPrivate::widgetCount = false;
+QString* QApplicationPrivate::styleOverride = 0;
+#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+bool QApplicationPrivate::inSizeMove = false;
+#endif
+#ifdef QT_KEYPAD_NAVIGATION
+bool QApplicationPrivate::keypadNavigation = false;
+QWidget *QApplicationPrivate::oldEditFocus = 0;
+#endif
+
+bool qt_tabletChokeMouse = false;
+static bool force_reverse = false;
+
+static inline bool isAlien(QWidget *widget)
+{
+ if (!widget)
+ return false;
+#ifdef Q_WS_MAC // Fake alien behavior on the Mac :)
+ return !widget->isWindow() && widget->window()->testAttribute(Qt::WA_DontShowOnScreen);
+#else
+ return !widget->internalWinId();
+#endif
+}
+
+// ######## move to QApplicationPrivate
+// Default application palettes and fonts (per widget type)
+
+typedef QHash<QByteArray, QPalette> PaletteHash;
+Q_GLOBAL_STATIC(PaletteHash, app_palettes)
+PaletteHash *qt_app_palettes_hash()
+{
+ return app_palettes();
+}
+
+typedef QHash<QByteArray, QFont> FontHash;
+Q_GLOBAL_STATIC(FontHash, app_fonts)
+FontHash *qt_app_fonts_hash()
+{
+ return app_fonts();
+}
+
+QWidgetList *QApplicationPrivate::popupWidgets = 0; // has keyboard input focus
+
+QDesktopWidget *qt_desktopWidget = 0; // root window widgets
+#ifndef QT_NO_CLIPBOARD
+QClipboard *qt_clipboard = 0; // global clipboard object
+#endif
+QWidgetList * qt_modal_stack=0; // stack of modal widgets
+
+/*!
+ \internal
+*/
+void QApplicationPrivate::process_cmdline()
+{
+ Q_Q(QApplication);
+ Q_UNUSED(q);// only static members being used.
+ // process platform-indep command line
+ if (!qt_is_gui_used || !argc)
+ return;
+
+ int i, j;
+
+ j = 1;
+ for (i=1; i<argc; i++) { // if you add anything here, modify QCoreApplication::arguments()
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QByteArray arg = argv[i];
+ arg = arg;
+ QString s;
+ if (arg == "-qdevel" || arg == "-qdebug") {
+ // obsolete argument
+ } else if (arg.indexOf("-style=", 0) != -1) {
+ s = QString::fromLocal8Bit(arg.right(arg.length() - 7).toLower());
+ } else if (arg == "-style" && i < argc-1) {
+ s = QString::fromLocal8Bit(argv[++i]).toLower();
+#ifndef QT_NO_SESSIONMANAGER
+ } else if (arg == "-session" && i < argc-1) {
+ ++i;
+ if (argv[i] && *argv[i]) {
+ session_id = QString::fromLatin1(argv[i]);
+ int p = session_id.indexOf(QLatin1Char('_'));
+ if (p >= 0) {
+ session_key = session_id.mid(p +1);
+ session_id = session_id.left(p);
+ }
+ is_session_restored = true;
+ }
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+ } else if (arg == "-stylesheet" && i < argc -1) {
+ styleSheet = QLatin1String("file:///");
+ styleSheet.append(QString::fromLocal8Bit(argv[++i]));
+ } else if (arg.indexOf("-stylesheet=") != -1) {
+ styleSheet = QLatin1String("file:///");
+ styleSheet.append(QString::fromLocal8Bit(arg.right(arg.length() - 12)));
+#endif
+ } else if (qstrcmp(arg, "-reverse") == 0) {
+ force_reverse = true;
+ q->setLayoutDirection(Qt::RightToLeft);
+ } else if (qstrcmp(arg, "-widgetcount") == 0) {
+ widgetCount = true;
+ } else if (arg == "-graphicssystem" && i < argc-1) {
+ graphics_system_name = QString::fromLocal8Bit(argv[++i]);
+ } else {
+ argv[j++] = argv[i];
+ }
+ if (!s.isEmpty()) {
+ if (app_style) {
+ delete app_style;
+ app_style = 0;
+ }
+ if (!styleOverride)
+ styleOverride = new QString;
+ *styleOverride = s;
+ }
+ }
+
+ if(j < argc) {
+ argv[j] = 0;
+ argc = j;
+ }
+}
+
+/*!
+ Initializes the window system and constructs an application object
+ with \a argc command line arguments in \a argv.
+
+ \warning The data referred to by \a argc and \a argv must stay valid
+ for the entire lifetime of the QApplication object. In addition,
+ \a argc must be greater than zero and \a argv must contain at least
+ one valid character string.
+
+ The global \c qApp pointer refers to this application object. Only
+ one application object should be created.
+
+ This application object must be constructed before any \link
+ QPaintDevice paint devices\endlink (including widgets, pixmaps, bitmaps
+ etc.).
+
+ Note that \a argc and \a argv might be changed. Qt removes command
+ line arguments that it recognizes.
+
+ Qt debugging options (not available if Qt was compiled without the
+ QT_DEBUG flag defined):
+ \list
+ \o -nograb, tells Qt that it must never grab the mouse or the keyboard.
+ \o -dograb (only under X11), running under a debugger can cause
+ an implicit -nograb, use -dograb to override.
+ \o -sync (only under X11), switches to synchronous mode for
+ debugging.
+ \endlist
+
+ See \link debug.html Debugging Techniques \endlink for a more
+ detailed explanation.
+
+ All Qt programs automatically support the following command line options:
+ \list
+ \o -style= \e style, sets the application GUI style. Possible values
+ are \c motif, \c windows, and \c platinum. If you compiled Qt
+ with additional styles or have additional styles as plugins these
+ will be available to the \c -style command line option.
+ \o -style \e style, is the same as listed above.
+ \o -stylesheet= \e stylesheet, sets the application \l styleSheet. The value
+ must be a path to a file that contains the Style Sheet. Note that relative URLs
+ in the Style Sheet file are relative to the Style Sheet file's path.
+ \o -stylesheet \e stylesheet, is the same as listed above.
+ \o -session= \e session, restores the application from an earlier
+ \link session.html session \endlink.
+ \o -session \e session, is the same as listed above.
+ \o -widgetcount, prints debug message at the end about number of widgets left
+ undestroyed and maximum number of widgets existed at the same time
+ \o -reverse, sets the application's layout direction to Qt::RightToLeft
+ \o -graphicssystem, sets the backend to be used for on-screen
+ widgets and QPixmaps. Available options are \c{raster} and \c{opengl}.
+
+ \endlist
+
+ The Windows version of Qt also support one additional command line
+ option, if Direct3D support has been compiled into Qt:
+ \list
+ \o -direct3d will make the Direct3D paint engine the default widget
+ paint engine in Qt. \bold {This functionality is experimental.}
+ \endlist
+
+ The X11 version of Qt also supports some traditional X11
+ command line options:
+ \list
+ \o -display \e display, sets the X display (default is $DISPLAY).
+ \o -geometry \e geometry, sets the client geometry of the
+ first window that is shown.
+ \o -fn or \c -font \e font, defines the application font. The
+ font should be specified using an X logical font description.
+ \o -bg or \c -background \e color, sets the default background color
+ and an application palette (light and dark shades are calculated).
+ \o -fg or \c -foreground \e color, sets the default foreground color.
+ \o -btn or \c -button \e color, sets the default button color.
+ \o -name \e name, sets the application name.
+ \o -title \e title, sets the application title.
+ \o -visual \c TrueColor, forces the application to use a TrueColor visual
+ on an 8-bit display.
+ \o -ncols \e count, limits the number of colors allocated in the
+ color cube on an 8-bit display, if the application is using the
+ QApplication::ManyColor color specification. If \e count is
+ 216 then a 6x6x6 color cube is used (i.e. 6 levels of red, 6 of green,
+ and 6 of blue); for other values, a cube
+ approximately proportional to a 2x3x1 cube is used.
+ \o -cmap, causes the application to install a private color map
+ on an 8-bit display.
+ \o -im, sets the input method server (equivalent to setting the XMODIFIERS
+ environment variable)
+ \o -inputstyle, defines how the input is inserted into the given widget. E.g.,
+ \c onTheSpot makes the input appear directly in the widget, while
+ \c overTheSpot makes the input appear in a box floating over the
+ widget and is not inserted until the editing is done.
+ \endlist
+
+ \sa arguments()
+*/
+
+QApplication::QApplication(int &argc, char **argv)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+{ Q_D(QApplication); d->construct(); }
+
+QApplication::QApplication(int &argc, char **argv, int _internal)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
+
+
+/*!
+ Constructs an application object with \a argc command line arguments
+ in \a argv. If \a GUIenabled is true, a GUI application is
+ constructed, otherwise a non-GUI (console) application is created.
+
+ \warning The data referred to by \a argc and \a argv must stay valid
+ for the entire lifetime of the QApplication object. In addition,
+ \a argc must be greater than zero and \a argv must contain at least
+ one valid character string.
+
+ Set \a GUIenabled to false for programs without a graphical user
+ interface that should be able to run without a window system.
+
+ On X11, the window system is initialized if \a GUIenabled is true.
+ If \a GUIenabled is false, the application does not connect to the
+ X server. On Windows and Macintosh, currently the window system is
+ always initialized, regardless of the value of GUIenabled. This may
+ change in future versions of Qt.
+
+ The following example shows how to create an application that
+ uses a graphical interface when available.
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 0
+*/
+
+QApplication::QApplication(int &argc, char **argv, bool GUIenabled )
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty))
+{ Q_D(QApplication); d->construct(); }
+
+QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _internal)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty))
+{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
+
+
+
+/*!
+ Constructs an application object with \a argc command line arguments
+ in \a argv.
+
+ \warning The data referred to by \a argc and \a argv must stay valid
+ for the entire lifetime of the QApplication object. In addition,
+ \a argc must be greater than zero and \a argv must contain at least
+ one valid character string.
+
+ With Qt for Embedded Linux, passing QApplication::GuiServer for \a type
+ makes this application the server (equivalent to running with the
+ \c -qws option).
+*/
+QApplication::QApplication(int &argc, char **argv, Type type)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, type))
+{ Q_D(QApplication); d->construct(); }
+
+QApplication::QApplication(int &argc, char **argv, Type type , int _internal)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, type))
+{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
+
+
+/*!
+ \internal
+*/
+void QApplicationPrivate::construct(
+#ifdef Q_WS_X11
+ Display *dpy, Qt::HANDLE visual, Qt::HANDLE cmap
+#endif
+ )
+{
+ initResources();
+
+ qt_is_gui_used = (qt_appType != QApplication::Tty);
+ process_cmdline();
+ // Must be called before initialize()
+ qt_init(this, qt_appType
+#ifdef Q_WS_X11
+ , dpy, visual, cmap
+#endif
+ );
+ initialize();
+ eventDispatcher->startingUp();
+
+#ifdef QT_EVAL
+ extern void qt_gui_eval_init(uint);
+ qt_gui_eval_init(application_type);
+#endif
+}
+
+#if defined(Q_WS_X11)
+// ### a string literal is a cont char*
+// ### using it as a char* is wrong and could lead to segfaults
+// ### if aargv is modified someday
+// ########## make it work with argc == argv == 0
+static int aargc = 1;
+static char *aargv[] = { (char*)"unknown", 0 };
+
+/*!
+ \fn QApplication::QApplication(Display* display, Qt::HANDLE visual, Qt::HANDLE colormap)
+
+ Create an application, given an already open display \a display. If \a
+ visual and \a colormap are non-zero, the application will use those as
+ the default Visual and Colormap contexts.
+
+ \warning Qt only supports TrueColor visuals at depths higher than 8
+ bits-per-pixel.
+
+ This is available only on X11.
+*/
+QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
+ : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+}
+
+QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal)
+ : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+ QApplicationPrivate::app_compile_version = _internal;
+}
+
+/*!
+ \fn QApplication::QApplication(Display *display, int &argc, char **argv,
+ Qt::HANDLE visual, Qt::HANDLE colormap)
+
+ Create an application, given an already open \a display and using \a
+ argc command line arguments in \a argv. If \a visual and \a colormap
+ are non-zero, the application will use those as the default Visual
+ and Colormap contexts.
+
+ \warning Qt only supports TrueColor visuals at depths higher than 8
+ bits-per-pixel.
+
+ This is available only on X11.
+
+*/
+QApplication::QApplication(Display *dpy, int &argc, char **argv,
+ Qt::HANDLE visual, Qt::HANDLE colormap)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+}
+
+QApplication::QApplication(Display *dpy, int &argc, char **argv,
+ Qt::HANDLE visual, Qt::HANDLE colormap, int _internal)
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+{
+ if (! dpy)
+ qWarning("QApplication: Invalid Display* argument");
+ Q_D(QApplication);
+ d->construct(dpy, visual, colormap);
+ QApplicationPrivate::app_compile_version = _internal;
+}
+
+#endif // Q_WS_X11
+
+
+/*!
+ Initializes the QApplication object, called from the constructors.
+*/
+extern void qInitDrawhelperAsm();
+
+void QApplicationPrivate::initialize()
+{
+ QWidgetPrivate::mapper = new QWidgetMapper;
+ QWidgetPrivate::uncreatedWidgets = new QWidgetSet;
+ if (qt_appType != QApplication::Tty)
+ (void) QApplication::style(); // trigger creation of application style
+ // trigger registering of QVariant's GUI types
+ extern int qRegisterGuiVariant();
+ qRegisterGuiVariant();
+
+ is_app_running = true; // no longer starting up
+
+ Q_Q(QApplication);
+#ifndef QT_NO_SESSIONMANAGER
+ // connect to the session manager
+ session_manager = new QSessionManager(q, session_id, session_key);
+#endif
+
+ if (qgetenv("QT_USE_NATIVE_WINDOWS").toInt() > 0)
+ q->setAttribute(Qt::AA_NativeWindows);
+
+#if defined(Q_WS_WIN)
+ // Alien is not currently working on Windows 98
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
+ q->setAttribute(Qt::AA_NativeWindows);
+#endif
+
+#ifdef Q_OS_WINCE
+#ifdef QT_AUTO_MAXIMIZE_THRESHOLD
+ autoMaximizeThreshold = QT_AUTO_MAXIMIZE_THRESHOLD;
+#else
+ if (qt_wince_is_mobile())
+ autoMaximizeThreshold = 50;
+ else
+ autoMaximizeThreshold = -1;
+#endif //QT_AUTO_MAXIMIZE_THRESHOLD
+#endif //Q_OS_WINCE
+
+ // Set up which span functions should be used in raster engine...
+ qInitDrawhelperAsm();
+
+#if !defined(Q_WS_X11) && !defined(Q_WS_QWS)
+ // initialize the graphics system - on X11 this is initialized inside
+ // qt_init() in qapplication_x11.cpp because of several reasons.
+ // On QWS, the graphics system is set by the QScreen plugin.
+ graphics_system = QGraphicsSystemFactory::create(graphics_system_name);
+#endif
+#ifndef QT_NO_WHEELEVENT
+#ifdef QT_MAC_USE_COCOA
+ QApplicationPrivate::wheel_scroll_lines = 1;
+#else
+ QApplicationPrivate::wheel_scroll_lines = 3;
+#endif
+#endif
+}
+
+/*!
+ Returns the type of application (\l Tty, GuiClient, or
+ GuiServer). The type is set when constructing the QApplication
+ object.
+*/
+QApplication::Type QApplication::type()
+{
+ return qt_appType;
+}
+
+/*****************************************************************************
+ Functions returning the active popup and modal widgets.
+ *****************************************************************************/
+
+/*!
+ Returns the active popup widget.
+
+ A popup widget is a special top-level widget that sets the \c
+ Qt::WType_Popup widget flag, e.g. the QMenu widget. When the
+ application opens a popup widget, all events are sent to the popup.
+ Normal widgets and modal widgets cannot be accessed before the popup
+ widget is closed.
+
+ Only other popup widgets may be opened when a popup widget is shown.
+ The popup widgets are organized in a stack. This function returns
+ the active popup widget at the top of the stack.
+
+ \sa activeModalWidget(), topLevelWidgets()
+*/
+
+QWidget *QApplication::activePopupWidget()
+{
+ return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ?
+ QApplicationPrivate::popupWidgets->last() : 0;
+}
+
+
+/*!
+ Returns the active modal widget.
+
+ A modal widget is a special top-level widget which is a subclass of
+ QDialog that specifies the modal parameter of the constructor as
+ true. A modal widget must be closed before the user can continue
+ with other parts of the program.
+
+ Modal widgets are organized in a stack. This function returns
+ the active modal widget at the top of the stack.
+
+ \sa activePopupWidget(), topLevelWidgets()
+*/
+
+QWidget *QApplication::activeModalWidget()
+{
+ return qt_modal_stack && !qt_modal_stack->isEmpty() ? qt_modal_stack->first() : 0;
+}
+
+/*!
+ Cleans up any window system resources that were allocated by this
+ application. Sets the global variable \c qApp to 0.
+*/
+
+QApplication::~QApplication()
+{
+ Q_D(QApplication);
+
+#ifndef QT_NO_CLIPBOARD
+ // flush clipboard contents
+ if (qt_clipboard) {
+ QEvent event(QEvent::Clipboard);
+ QApplication::sendEvent(qt_clipboard, &event);
+ }
+#endif
+
+ //### this should probable be done even later
+ qt_call_post_routines();
+
+ // kill timers before closing down the dispatcher
+ d->toolTipWakeUp.stop();
+ d->toolTipFallAsleep.stop();
+
+ d->eventDispatcher->closingDown();
+ d->eventDispatcher = 0;
+
+ delete qt_desktopWidget;
+ qt_desktopWidget = 0;
+ QApplicationPrivate::is_app_closing = true;
+ QApplicationPrivate::is_app_running = false;
+
+#ifndef QT_NO_CLIPBOARD
+ delete qt_clipboard;
+ qt_clipboard = 0;
+#endif
+
+ // delete widget mapper
+ if (QWidgetPrivate::mapper) {
+ QWidgetMapper * myMapper = QWidgetPrivate::mapper;
+ QWidgetPrivate::mapper = 0;
+ for (QWidgetMapper::Iterator it = myMapper->begin(); it != myMapper->end(); ++it) {
+ register QWidget *w = *it;
+ if (!w->parent()) // window
+ w->destroy(true, true);
+ }
+ delete myMapper;
+ }
+
+ // delete uncreated widgets
+ if (QWidgetPrivate::uncreatedWidgets) {
+ QWidgetSet *mySet = QWidgetPrivate::uncreatedWidgets;
+ QWidgetPrivate::uncreatedWidgets = 0;
+ for (QWidgetSet::Iterator it = mySet->begin(); it != mySet->end(); ++it) {
+ register QWidget *w = *it;
+ if (!w->parent()) // window
+ w->destroy(true, true);
+ }
+ delete mySet;
+ }
+
+ delete QApplicationPrivate::app_pal;
+ QApplicationPrivate::app_pal = 0;
+ delete QApplicationPrivate::sys_pal;
+ QApplicationPrivate::sys_pal = 0;
+ delete QApplicationPrivate::set_pal;
+ QApplicationPrivate::set_pal = 0;
+ app_palettes()->clear();
+
+ {
+ QMutexLocker locker(applicationFontMutex());
+ delete QApplicationPrivate::app_font;
+ QApplicationPrivate::app_font = 0;
+ }
+ delete QApplicationPrivate::sys_font;
+ QApplicationPrivate::sys_font = 0;
+ delete QApplicationPrivate::set_font;
+ QApplicationPrivate::set_font = 0;
+ app_fonts()->clear();
+
+ delete QApplicationPrivate::app_style;
+ QApplicationPrivate::app_style = 0;
+ delete QApplicationPrivate::app_icon;
+ QApplicationPrivate::app_icon = 0;
+#ifndef QT_NO_CURSOR
+ d->cursor_list.clear();
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+ if (qt_is_gui_used)
+ delete QDragManager::self();
+#endif
+
+ qt_cleanup();
+
+ if (QApplicationPrivate::widgetCount)
+ qDebug("Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances);
+#ifndef QT_NO_SESSIONMANAGER
+ delete d->session_manager;
+ d->session_manager = 0;
+#endif //QT_NO_SESSIONMANAGER
+
+ QApplicationPrivate::obey_desktop_settings = true;
+ QApplicationPrivate::cursor_flash_time = 1000;
+ QApplicationPrivate::mouse_double_click_time = 400;
+ QApplicationPrivate::keyboard_input_time = 400;
+
+ drag_time = 500;
+ drag_distance = 4;
+ layout_direction = Qt::LeftToRight;
+ QApplicationPrivate::app_strut = QSize(0, 0);
+ QApplicationPrivate::animate_ui = true;
+ QApplicationPrivate::animate_menu = false;
+ QApplicationPrivate::fade_menu = false;
+ QApplicationPrivate::animate_combo = false;
+ QApplicationPrivate::animate_tooltip = false;
+ QApplicationPrivate::fade_tooltip = false;
+ QApplicationPrivate::widgetCount = false;
+
+ // trigger unregistering of QVariant's GUI types
+ extern int qUnregisterGuiVariant();
+ qUnregisterGuiVariant();
+}
+
+
+/*!
+ \fn QWidget *QApplication::widgetAt(const QPoint &point)
+
+ Returns the widget at global screen position \a point, or 0 if there
+ is no Qt widget there.
+
+ This function can be slow.
+
+ \sa QCursor::pos(), QWidget::grabMouse(), QWidget::grabKeyboard()
+*/
+QWidget *QApplication::widgetAt(const QPoint &p)
+{
+ QWidget *window = QApplication::topLevelAt(p);
+ if (!window)
+ return 0;
+
+ QWidget *child = 0;
+
+ if (!window->testAttribute(Qt::WA_TransparentForMouseEvents))
+ child = window->childAt(window->mapFromGlobal(p));
+
+ if (child)
+ return child;
+
+ if (window->testAttribute(Qt::WA_TransparentForMouseEvents)) {
+ //shoot a hole in the widget and try once again,
+ //suboptimal on Qt for Embedded Linux where we do
+ //know the stacking order of the toplevels.
+ int x = p.x();
+ int y = p.y();
+ QRegion oldmask = window->mask();
+ QPoint wpoint = window->mapFromGlobal(QPoint(x, y));
+ QRegion newmask = (oldmask.isEmpty() ? QRegion(window->rect()) : oldmask)
+ - QRegion(wpoint.x(), wpoint.y(), 1, 1);
+ window->setMask(newmask);
+ QWidget *recurse = 0;
+ if (QApplication::topLevelAt(p) != window) // verify recursion will terminate
+ recurse = widgetAt(x, y);
+ if (oldmask.isEmpty())
+ window->clearMask();
+ else
+ window->setMask(oldmask);
+ return recurse;
+ }
+ return window;
+}
+
+/*!
+ \fn QWidget *QApplication::widgetAt(int x, int y)
+
+ \overload
+
+ Returns the widget at global screen position (\a x, \a y), or 0
+ if there is no Qt widget there.
+*/
+
+/*!
+ \fn void QApplication::setArgs(int argc, char **argv)
+ \internal
+*/
+
+
+
+/*!
+ \internal
+*/
+bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
+{
+ if ((event->type() == QEvent::UpdateRequest
+#ifdef QT3_SUPPORT
+ || event->type() == QEvent::LayoutHint
+#endif
+ || event->type() == QEvent::LayoutRequest
+ || event->type() == QEvent::Resize
+ || event->type() == QEvent::Move
+ || event->type() == QEvent::LanguageChange
+ || event->type() == QEvent::InputMethod)) {
+ for (int i = 0; i < postedEvents->size(); ++i) {
+ const QPostEvent &cur = postedEvents->at(i);
+ if (cur.receiver != receiver || cur.event == 0 || cur.event->type() != event->type())
+ continue;
+ if (cur.event->type() == QEvent::LayoutRequest
+#ifdef QT3_SUPPORT
+ || cur.event->type() == QEvent::LayoutHint
+#endif
+ || cur.event->type() == QEvent::UpdateRequest) {
+ ;
+ } else if (cur.event->type() == QEvent::Resize) {
+ ((QResizeEvent *)(cur.event))->s = ((QResizeEvent *)event)->s;
+ } else if (cur.event->type() == QEvent::Move) {
+ ((QMoveEvent *)(cur.event))->p = ((QMoveEvent *)event)->p;
+ } else if (cur.event->type() == QEvent::LanguageChange) {
+ ;
+ } else if ( cur.event->type() == QEvent::InputMethod ) {
+ *(QInputMethodEvent *)(cur.event) = *(QInputMethodEvent *)event;
+ } else {
+ continue;
+ }
+ delete event;
+ return true;
+ }
+ return false;
+ }
+ return QCoreApplication::compressEvent(event, receiver, postedEvents);
+}
+
+/*!
+ \property QApplication::styleSheet
+ \brief the application style sheet
+ \since 4.2
+
+ By default, this property returns an empty string unless the user specifies
+ the \c{-stylesheet} option on the command line when running the application.
+
+ \sa QWidget::setStyle(), {Qt Style Sheets}
+*/
+
+/*!
+ \property QApplication::autoMaximizeThreshold
+ \since 4.4
+ \brief defines a threshold for auto maximizing widgets
+
+ The auto maximize threshold is only available
+ as part of Qt for Windows CE.
+
+ This property defines a threshold for the size of a window as a percentage
+ of the screen size. If the minimum size hint of a window exceeds the threshold,
+ calling show() will then cause the window to be maximized automatically.
+
+ Setting the threshold to be 100 or greater means that it will cause it to always
+ be maximized. Setting it to be 50 means that the widget is maximized if the vertical
+ minimum size hint is at least 50% of the vertical screen size.
+
+ If -1 is specified then this will disable the feature.
+
+ On Windows CE the default is -1 (i.e. it is disabled).
+ On Windows Mobile the default is 40.
+*/
+
+/*!
+ \property QApplication::autoSipEnabled
+ \since 4.5
+ \brief toggles automatic SIP (software input panel) visibility
+
+ The auto SIP property is only available
+ as part of Qt for Windows CE.
+
+ Set this property to true to automatically display the SIP when entering
+ widgets that accept keyboard input. This only affects widgets that have the
+ attribute WA_InputMethodEnabled set.
+*/
+
+#ifdef Q_OS_WINCE
+void QApplication::setAutoMaximizeThreshold(const int threshold)
+{
+ QApplicationPrivate::autoMaximizeThreshold = threshold;
+}
+
+int QApplication::autoMaximizeThreshold() const
+{
+ return QApplicationPrivate::autoMaximizeThreshold;
+}
+
+void QApplication::setAutoSipEnabled(const bool enabled)
+{
+ QApplicationPrivate::autoSipEnabled = enabled;
+}
+
+bool QApplication::autoSipEnabled() const
+{
+ return QApplicationPrivate::autoSipEnabled;
+}
+#endif
+
+#ifndef QT_NO_STYLE_STYLESHEET
+
+QString QApplication::styleSheet() const
+{
+ return QApplicationPrivate::styleSheet;
+}
+
+void QApplication::setStyleSheet(const QString& styleSheet)
+{
+ QApplicationPrivate::styleSheet = styleSheet;
+ QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style);
+ if (styleSheet.isEmpty()) { // application style sheet removed
+ if (!proxy)
+ return; // there was no stylesheet before
+ setStyle(proxy->base);
+ } else if (proxy) { // style sheet update, just repolish
+ proxy->repolish(qApp);
+ } else { // stylesheet set the first time
+ QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style);
+ QApplicationPrivate::app_style->setParent(newProxy);
+ setStyle(newProxy);
+ }
+}
+
+#endif // QT_NO_STYLE_STYLESHEET
+
+/*!
+ Returns the application's style object.
+
+ \sa setStyle(), QStyle
+*/
+QStyle *QApplication::style()
+{
+ if (QApplicationPrivate::app_style)
+ return QApplicationPrivate::app_style;
+ if (!qt_is_gui_used) {
+ Q_ASSERT(!"No style available in non-gui applications!");
+ return 0;
+ }
+
+#if defined(Q_WS_X11)
+ if(!QApplicationPrivate::styleOverride)
+ QApplicationPrivate::x11_initialize_style(); // run-time search for default style
+#endif
+ if (!QApplicationPrivate::app_style) {
+ // Compile-time search for default style
+ //
+ QString style;
+ if (QApplicationPrivate::styleOverride) {
+ style = *QApplicationPrivate::styleOverride;
+ delete QApplicationPrivate::styleOverride;
+ QApplicationPrivate::styleOverride = 0;
+ } else {
+#if defined(Q_WS_WIN) && defined(Q_OS_WINCE)
+ if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
+ style = QLatin1String("WindowsMobile");
+ else
+ style = QLatin1String("WindowsCE");
+
+#elif defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ style = QLatin1String("WindowsVista");
+ else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ style = QLatin1String("WindowsXP");
+ else
+ style = QLatin1String("Windows"); // default styles for Windows
+#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
+ style = QLatin1String("CDE"); // default style for X11 on Solaris
+#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
+ style = QLatin1String("SGI"); // default style for X11 on IRIX
+#elif defined(Q_WS_X11) || defined(Q_WS_QWS)
+ style = QLatin1String("Plastique"); // default style for X11 and small devices
+#elif defined(Q_WS_MAC)
+ style = QLatin1String("Macintosh"); // default style for all Mac's
+#endif
+ }
+
+ QStyle *&app_style = QApplicationPrivate::app_style;
+ app_style = QStyleFactory::create(style);
+ if (!app_style) {
+ QStringList styles = QStyleFactory::keys();
+ for (int i = 0; i < styles.size(); ++i) {
+ if ((app_style = QStyleFactory::create(styles.at(i))))
+ break;
+ }
+ }
+ if (!app_style) {
+ Q_ASSERT(!"No styles available!");
+ return 0;
+ }
+ }
+ // take ownership of the style
+ QApplicationPrivate::app_style->setParent(qApp);
+
+ if (!QApplicationPrivate::sys_pal)
+ QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
+ if (QApplicationPrivate::set_pal) // repolish set palette with the new style
+ QApplication::setPalette(*QApplicationPrivate::set_pal);
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (!QApplicationPrivate::styleSheet.isEmpty()) {
+ qApp->setStyleSheet(QApplicationPrivate::styleSheet);
+ } else
+#endif
+ QApplicationPrivate::app_style->polish(qApp);
+
+ return QApplicationPrivate::app_style;
+}
+
+/*!
+ Sets the application's GUI style to \a style. Ownership of the style
+ object is transferred to QApplication, so QApplication will delete
+ the style object on application exit or when a new style is set and
+ the old style is still the parent of the application object.
+
+ Example usage:
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 1
+
+ When switching application styles, the color palette is set back to
+ the initial colors or the system defaults. This is necessary since
+ certain styles have to adapt the color palette to be fully
+ style-guide compliant.
+
+ Note that setting the style before a palette has been set
+ (i.e. before creating QApplication) will cause the application to
+ use QStyle::standardPalette() for the palette.
+
+ \warning Qt style sheets are currently not supported for custom QStyle
+ subclasses. We plan to address this in some future release.
+
+ \sa style(), QStyle, setPalette(), desktopSettingsAware()
+*/
+void QApplication::setStyle(QStyle *style)
+{
+ if (!style || style == QApplicationPrivate::app_style)
+ return;
+
+ QWidgetList all = allWidgets();
+
+ // clean up the old style
+ if (QApplicationPrivate::app_style) {
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (!(w->windowType() == Qt::Desktop) && // except desktop
+ w->testAttribute(Qt::WA_WState_Polished)) { // has been polished
+ QApplicationPrivate::app_style->unpolish(w);
+ }
+ }
+ }
+ QApplicationPrivate::app_style->unpolish(qApp);
+ }
+
+ QStyle *old = QApplicationPrivate::app_style; // save
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) {
+ // we have a stylesheet already and a new style is being set
+ QStyleSheetStyle *newProxy = new QStyleSheetStyle(style);
+ style->setParent(newProxy);
+ QApplicationPrivate::app_style = newProxy;
+ } else
+#endif // QT_NO_STYLE_STYLESHEET
+ QApplicationPrivate::app_style = style;
+
+ QApplicationPrivate::app_style->setParent(qApp); // take ownership
+
+ // take care of possible palette requirements of certain gui
+ // styles. Do it before polishing the application since the style
+ // might call QApplication::setPalette() itself
+ if (QApplicationPrivate::set_pal) {
+ QApplication::setPalette(*QApplicationPrivate::set_pal);
+ } else if (QApplicationPrivate::sys_pal) {
+ QApplicationPrivate::initializeWidgetPaletteHash();
+ QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false);
+ } else if (!QApplicationPrivate::sys_pal) {
+ // Initialize the sys_pal if it hasn't happened yet...
+ QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
+ }
+
+ // initialize the application with the new style
+ QApplicationPrivate::app_style->polish(qApp);
+
+ // re-polish existing widgets if necessary
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ for (QWidgetList::ConstIterator it1 = all.constBegin(); it1 != all.constEnd(); ++it1) {
+ register QWidget *w = *it1;
+ if (w->windowType() != Qt::Desktop && w->testAttribute(Qt::WA_WState_Polished)) {
+ if (w->style() == QApplicationPrivate::app_style)
+ QApplicationPrivate::app_style->polish(w); // repolish
+#ifndef QT_NO_STYLE_STYLESHEET
+ else
+ w->setStyleSheet(w->styleSheet()); // touch
+#endif
+ }
+ }
+
+ for (QWidgetList::ConstIterator it2 = all.constBegin(); it2 != all.constEnd(); ++it2) {
+ register QWidget *w = *it2;
+ if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) {
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(w, &e);
+#ifdef QT3_SUPPORT
+ if (old)
+ w->styleChange(*old);
+#endif
+ w->update();
+ }
+ }
+ }
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) {
+ oldProxy->deref();
+ } else
+#endif
+ if (old && old->parent() == qApp) {
+ delete old;
+ }
+
+ if (QApplicationPrivate::focus_widget) {
+ QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason);
+ QApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in);
+ QApplicationPrivate::focus_widget->update();
+ }
+}
+
+/*!
+ \overload
+
+ Requests a QStyle object for \a style from the QStyleFactory.
+
+ The string must be one of the QStyleFactory::keys(), typically one
+ of "windows", "motif", "cde", "plastique", "windowsxp", or
+ "macintosh". Style names are case insensitive.
+
+ Returns 0 if an unknown \a style is passed, otherwise the QStyle object
+ returned is set as the application's GUI style.
+
+ \warning To ensure that the application's style is set correctly, it is
+ best to call this function before the QApplication constructor, if
+ possible.
+*/
+QStyle* QApplication::setStyle(const QString& style)
+{
+ QStyle *s = QStyleFactory::create(style);
+ if (!s)
+ return 0;
+
+ setStyle(s);
+ return s;
+}
+
+/*!
+ \since 4.5
+
+ Sets the default graphics backend to \a system, which will be used
+ for on-screen widgets and QPixmaps. The available systems are
+ \c{"native"}, \c{"raster"} and \c{"opengl"}.
+
+ Note that this function call overrides both the application
+ commandline \c{-graphicssystem} switch and the configure
+ \c{-graphicssystem} switch.
+
+ \warning This function must be called before the QApplication
+ constructor is called.
+
+ The \c{"opengl"} option is currently considered experimental.
+*/
+
+void QApplication::setGraphicsSystem(const QString &system)
+{
+ QApplicationPrivate::graphics_system_name = system;
+}
+
+/*!
+ Returns the color specification.
+ \sa QApplication::setColorSpec()
+ */
+
+int QApplication::colorSpec()
+{
+ return QApplicationPrivate::app_cspec;
+}
+
+/*!
+ Sets the color specification for the application to \a spec.
+
+ The color specification controls how the application allocates colors
+ when run on a display with a limited amount of colors, e.g. 8 bit / 256
+ color displays.
+
+ The color specification must be set before you create the QApplication
+ object.
+
+ The options are:
+ \list
+ \o QApplication::NormalColor.
+ This is the default color allocation strategy. Use this option if
+ your application uses buttons, menus, texts and pixmaps with few
+ colors. With this option, the application uses system global
+ colors. This works fine for most applications under X11, but on
+ Windows machines it may cause dithering of non-standard colors.
+ \o QApplication::CustomColor.
+ Use this option if your application needs a small number of custom
+ colors. On X11, this option is the same as NormalColor. On Windows, Qt
+ creates a Windows palette, and allocates colors to it on demand.
+ \o QApplication::ManyColor.
+ Use this option if your application is very color hungry
+ (e.g. it requires thousands of colors).
+ Under X11 the effect is:
+ \list
+ \o For 256-color displays which have at best a 256 color true
+ color visual, the default visual is used, and colors are
+ allocated from a color cube. The color cube is the 6x6x6 (216
+ color) "Web palette" (the red, green, and blue components
+ always have one of the following values: 0x00, 0x33, 0x66,
+ 0x99, 0xCC, or 0xFF), but the number of colors can be changed
+ by the \e -ncols option. The user can force the application to
+ use the true color visual with the \link
+ QApplication::QApplication() -visual \endlink option.
+ \o For 256-color displays which have a true color visual with more
+ than 256 colors, use that visual. Silicon Graphics X servers
+ have this feature, for example. They provide an 8 bit visual
+ by default but can deliver true color when asked.
+ \endlist
+ On Windows, Qt creates a Windows palette, and fills it with a color cube.
+ \endlist
+
+ Be aware that the CustomColor and ManyColor choices may lead to colormap
+ flashing: The foreground application gets (most) of the available
+ colors, while the background windows will look less attractive.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 2
+
+ \sa colorSpec()
+*/
+
+void QApplication::setColorSpec(int spec)
+{
+ if (qApp)
+ qWarning("QApplication::setColorSpec: This function must be "
+ "called before the QApplication object is created");
+ QApplicationPrivate::app_cspec = spec;
+}
+
+/*!
+ \property QApplication::globalStrut
+ \brief the minimum size that any GUI element that the user can interact
+ with should have
+
+ For example, no button should be resized to be smaller than the
+ global strut size. The strut size should be considered when
+ reimplementing GUI controls that may be used on touch-screens or
+ similar I/O devices.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 3
+
+ By default, this property contains a QSize object with zero width and height.
+*/
+QSize QApplication::globalStrut()
+{
+ return QApplicationPrivate::app_strut;
+}
+
+void QApplication::setGlobalStrut(const QSize& strut)
+{
+ QApplicationPrivate::app_strut = strut;
+}
+
+/*!
+ Returns the application palette.
+
+ \sa setPalette(), QWidget::palette()
+*/
+QPalette QApplication::palette()
+{
+ if (!QApplicationPrivate::app_pal)
+ QApplicationPrivate::app_pal = new QPalette(Qt::black);
+ return *QApplicationPrivate::app_pal;
+}
+
+/*!
+ \fn QPalette QApplication::palette(const QWidget* widget)
+ \overload
+
+ If a \a widget is passed, the default palette for the
+ widget's class is returned. This may or may not be the application
+ palette. In most cases there isn't a special palette for certain
+ types of widgets, but one notable exception is the popup menu
+ under Windows, if the user has defined a special background color
+ for menus in the display settings.
+
+ \sa setPalette(), QWidget::palette()
+*/
+QPalette QApplication::palette(const QWidget* w)
+{
+ PaletteHash *hash = app_palettes();
+ if (w && hash && hash->size()) {
+ QHash<QByteArray, QPalette>::ConstIterator it = hash->constFind(w->metaObject()->className());
+ if (it != hash->constEnd())
+ return *it;
+ for (it = hash->constBegin(); it != hash->constEnd(); ++it) {
+ if (w->inherits(it.key()))
+ return it.value();
+ }
+ }
+ return palette();
+}
+
+/*!
+ \overload
+
+ Returns the palette for widgets of the given \a className.
+
+ \sa setPalette(), QWidget::palette()
+*/
+QPalette QApplication::palette(const char *className)
+{
+ if (!QApplicationPrivate::app_pal)
+ palette();
+ PaletteHash *hash = app_palettes();
+ if (className && hash && hash->size()) {
+ QHash<QByteArray, QPalette>::ConstIterator it = hash->constFind(className);
+ if (it != hash->constEnd())
+ return *it;
+ }
+ return *QApplicationPrivate::app_pal;
+}
+
+void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash)
+{
+ QPalette pal = palette;
+
+ if (QApplicationPrivate::app_style)
+ QApplicationPrivate::app_style->polish(pal); // NB: non-const reference
+
+ bool all = false;
+ PaletteHash *hash = app_palettes();
+ if (!className) {
+ if (QApplicationPrivate::app_pal && pal.isCopyOf(*QApplicationPrivate::app_pal))
+ return;
+ if (!QApplicationPrivate::app_pal)
+ QApplicationPrivate::app_pal = new QPalette(pal);
+ else
+ *QApplicationPrivate::app_pal = pal;
+ if (hash && hash->size()) {
+ all = true;
+ if (clearWidgetPaletteHash)
+ hash->clear();
+ }
+ } else if (hash) {
+ hash->insert(className, pal);
+ }
+
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ // Send ApplicationPaletteChange to qApp itself, and to the widgets.
+ QEvent e(QEvent::ApplicationPaletteChange);
+ QApplication::sendEvent(QApplication::instance(), &e);
+
+ QWidgetList wids = QApplication::allWidgets();
+ for (QWidgetList::ConstIterator it = wids.constBegin(); it != wids.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (all || (!className && w->isWindow()) || w->inherits(className)) // matching class
+ QApplication::sendEvent(w, &e);
+ }
+
+ // Send to all scenes as well.
+#ifndef QT_NO_GRAPHICSVIEW
+ QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list;
+ for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin();
+ it != scenes.constEnd(); ++it) {
+ QApplication::sendEvent(*it, &e);
+ }
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ if (!className && (!QApplicationPrivate::sys_pal || !palette.isCopyOf(*QApplicationPrivate::sys_pal))) {
+ if (!QApplicationPrivate::set_pal)
+ QApplicationPrivate::set_pal = new QPalette(palette);
+ else
+ *QApplicationPrivate::set_pal = palette;
+ }
+}
+
+/*!
+ Changes the default application palette to \a palette.
+
+ If \a className is passed, the change applies only to widgets that
+ inherit \a className (as reported by QObject::inherits()). If
+ \a className is left 0, the change affects all widgets, thus overriding
+ any previously set class specific palettes.
+
+ The palette may be changed according to the current GUI style in
+ QStyle::polish().
+
+ \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
+ When using style sheets, the palette of a widget can be customized using the "color",
+ "background-color", "selection-color", "selection-background-color" and
+ "alternate-background-color".
+
+ Note that some styles do not use the palette for all drawing,
+ for instance, if they make use of native theme engines. This is
+ the case for the Windows XP, Windows Vista, and Mac OS X styles.
+
+ \sa QWidget::setPalette(), palette(), QStyle::polish()
+*/
+
+void QApplication::setPalette(const QPalette &palette, const char* className)
+{
+ QApplicationPrivate::setPalette_helper(palette, className, /*clearWidgetPaletteHash=*/ true);
+}
+
+
+
+void QApplicationPrivate::setSystemPalette(const QPalette &pal)
+{
+ QPalette adjusted;
+
+#if 0
+ // adjust the system palette to avoid dithering
+ QColormap cmap = QColormap::instance();
+ if (cmap.depths() > 4 && cmap.depths() < 24) {
+ for (int g = 0; g < QPalette::NColorGroups; g++)
+ for (int i = 0; i < QPalette::NColorRoles; i++) {
+ QColor color = pal.color((QPalette::ColorGroup)g, (QPalette::ColorRole)i);
+ color = cmap.colorAt(cmap.pixel(color));
+ adjusted.setColor((QPalette::ColorGroup)g, (QPalette::ColorRole) i, color);
+ }
+ }
+#else
+ adjusted = pal;
+#endif
+
+ if (!sys_pal)
+ sys_pal = new QPalette(adjusted);
+ else
+ *sys_pal = adjusted;
+
+
+ if (!QApplicationPrivate::set_pal)
+ QApplication::setPalette(*sys_pal);
+}
+
+/*!
+ Returns the default application font.
+
+ \sa fontMetrics(), QWidget::font()
+*/
+QFont QApplication::font()
+{
+ QMutexLocker locker(applicationFontMutex());
+ if (!QApplicationPrivate::app_font)
+ QApplicationPrivate::app_font = new QFont(QLatin1String("Helvetica"));
+ return *QApplicationPrivate::app_font;
+}
+
+/*!
+ \overload
+
+ Returns the default font for the \a widget.
+
+ \sa fontMetrics(), QWidget::setFont()
+*/
+
+QFont QApplication::font(const QWidget *widget)
+{
+ FontHash *hash = app_fonts();
+
+#ifdef Q_WS_MAC
+ // short circuit for small and mini controls
+ if (widget->testAttribute(Qt::WA_MacSmallSize)) {
+ return hash->value("QSmallFont");
+ } else if (widget->testAttribute(Qt::WA_MacMiniSize)) {
+ return hash->value("QMiniFont");
+ }
+#endif
+ if (widget && hash && hash->size()) {
+ QHash<QByteArray, QFont>::ConstIterator it =
+ hash->constFind(widget->metaObject()->className());
+ if (it != hash->constEnd())
+ return it.value();
+ for (it = hash->constBegin(); it != hash->constEnd(); ++it) {
+ if (widget->inherits(it.key()))
+ return it.value();
+ }
+ }
+ return font();
+}
+
+/*!
+ \overload
+
+ Returns the font for widgets of the given \a className.
+
+ \sa setFont(), QWidget::font()
+*/
+QFont QApplication::font(const char *className)
+{
+ FontHash *hash = app_fonts();
+ if (className && hash && hash->size()) {
+ QHash<QByteArray, QFont>::ConstIterator it = hash->constFind(className);
+ if (it != hash->constEnd())
+ return *it;
+ }
+ return font();
+}
+
+
+/*!
+ Changes the default application font to \a font. If \a className
+ is passed, the change applies only to classes that inherit \a
+ className (as reported by QObject::inherits()).
+
+ On application start-up, the default font depends on the window
+ system. It can vary depending on both the window system version and
+ the locale. This function lets you override the default font; but
+ overriding may be a bad idea because, for example, some locales need
+ extra large fonts to support their special characters.
+
+ \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
+ The font of an application can be customized using the "font" style sheet
+ property. To set a bold font for all QPushButtons, set the application
+ styleSheet() as "QPushButton { font: bold }"
+
+ \sa font(), fontMetrics(), QWidget::setFont()
+*/
+
+void QApplication::setFont(const QFont &font, const char *className)
+{
+ bool all = false;
+ FontHash *hash = app_fonts();
+ if (!className) {
+ QMutexLocker locker(applicationFontMutex());
+ if (!QApplicationPrivate::app_font)
+ QApplicationPrivate::app_font = new QFont(font);
+ else
+ *QApplicationPrivate::app_font = font;
+ if (hash && hash->size()) {
+ all = true;
+ hash->clear();
+ }
+ } else if (hash) {
+ hash->insert(className, font);
+ }
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+ // Send ApplicationFontChange to qApp itself, and to the widgets.
+ QEvent e(QEvent::ApplicationFontChange);
+ QApplication::sendEvent(QApplication::instance(), &e);
+
+ QWidgetList wids = QApplication::allWidgets();
+ for (QWidgetList::ConstIterator it = wids.constBegin(); it != wids.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (all || (!className && w->isWindow()) || w->inherits(className)) // matching class
+ sendEvent(w, &e);
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Send to all scenes as well.
+ QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list;
+ for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin();
+ it != scenes.constEnd(); ++it) {
+ QApplication::sendEvent(*it, &e);
+ }
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ if (!className && (!QApplicationPrivate::sys_font || !font.isCopyOf(*QApplicationPrivate::sys_font))) {
+ if (!QApplicationPrivate::set_font)
+ QApplicationPrivate::set_font = new QFont(font);
+ else
+ *QApplicationPrivate::set_font = font;
+ }
+}
+
+/*! \internal
+*/
+void QApplicationPrivate::setSystemFont(const QFont &font)
+{
+ if (!sys_font)
+ sys_font = new QFont(font);
+ else
+ *sys_font = font;
+
+ if (!QApplicationPrivate::set_font)
+ QApplication::setFont(*sys_font);
+}
+
+/*!
+ \property QApplication::windowIcon
+ \brief the default window icon
+
+ \sa QWidget::setWindowIcon(), {Setting the Application Icon}
+*/
+QIcon QApplication::windowIcon()
+{
+ return QApplicationPrivate::app_icon ? *QApplicationPrivate::app_icon : QIcon();
+}
+
+void QApplication::setWindowIcon(const QIcon &icon)
+{
+ if (!QApplicationPrivate::app_icon)
+ QApplicationPrivate::app_icon = new QIcon();
+ *QApplicationPrivate::app_icon = icon;
+ if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
+#ifdef Q_WS_MAC
+ void qt_mac_set_app_icon(const QPixmap &); //qapplication_mac.cpp
+ QSize size = QApplicationPrivate::app_icon->actualSize(QSize(128, 128));
+ qt_mac_set_app_icon(QApplicationPrivate::app_icon->pixmap(size));
+#endif
+ QEvent e(QEvent::ApplicationWindowIconChange);
+ QWidgetList all = QApplication::allWidgets();
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (w->isWindow())
+ sendEvent(w, &e);
+ }
+ }
+}
+
+/*!
+ Returns a list of the top-level widgets (windows) in the
+ application.
+
+ Note that some of the top-level widgets may be hidden, for
+ example a tooltip if no tooltip is currently shown.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 4
+
+ \sa allWidgets(), QWidget::isWindow(), QWidget::isHidden()
+*/
+QWidgetList QApplication::topLevelWidgets()
+{
+ QWidgetList list;
+ QWidgetList all = allWidgets();
+
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ QWidget *w = *it;
+ if (w->isWindow() && w->windowType() != Qt::Desktop)
+ list.append(w);
+ }
+ return list;
+}
+
+/*!
+ Returns a list of all the widgets in the application.
+
+ The list is empty (QList::isEmpty()) if there are no widgets.
+
+ Note that some of the widgets may be hidden.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 5
+
+ \sa topLevelWidgets(), QWidget::isVisible()
+*/
+
+QWidgetList QApplication::allWidgets()
+{
+ QWidgetList list;
+ if (QWidgetPrivate::mapper)
+ list += QWidgetPrivate::mapper->values();
+ if (QWidgetPrivate::uncreatedWidgets)
+ list += QWidgetPrivate::uncreatedWidgets->toList();
+ return list;
+}
+
+/*!
+ Returns the application widget that has the keyboard input focus, or
+ 0 if no widget in this application has the focus.
+
+ \sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged()
+*/
+
+QWidget *QApplication::focusWidget()
+{
+ return QApplicationPrivate::focus_widget;
+}
+
+void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
+{
+ if (focus && focus->window()
+#ifndef QT_NO_GRAPHICSVIEW
+ && focus->window()->graphicsProxyWidget()
+#endif
+ )
+ return;
+
+ hidden_focus_widget = 0;
+
+ if (focus != focus_widget) {
+ if (focus && focus->isHidden()) {
+ hidden_focus_widget = focus;
+ return;
+ }
+
+ if (focus && (reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
+ && qt_in_tab_key_event)
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ else if (focus && reason == Qt::ShortcutFocusReason) {
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ }
+ QWidget *prev = focus_widget;
+ focus_widget = focus;
+
+ if (prev && reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason &&
+ prev->testAttribute(Qt::WA_InputMethodEnabled)) {
+ QInputContext *qic = prev->inputContext();
+ if(qic) {
+ qic->reset();
+ qic->setFocusWidget(0);
+ }
+ }
+
+ if(focus_widget)
+ focus_widget->d_func()->setFocus_sys();
+
+ if (reason != Qt::NoFocusReason) {
+
+ //send events
+ if (prev) {
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled()) {
+ if (prev->hasEditFocus() && reason != Qt::PopupFocusReason)
+ prev->setEditFocus(false);
+ }
+#endif
+ QFocusEvent out(QEvent::FocusOut, reason);
+ QPointer<QWidget> that = prev;
+ QApplication::sendEvent(prev, &out);
+ if (that)
+ QApplication::sendEvent(that->style(), &out);
+ }
+ if(focus && QApplicationPrivate::focus_widget == focus) {
+ if (focus->testAttribute(Qt::WA_InputMethodEnabled)) {
+ QInputContext *qic = focus->inputContext();
+ if (qic && focus_widget->testAttribute(Qt::WA_WState_Created))
+ qic->setFocusWidget( focus_widget );
+ }
+ QFocusEvent in(QEvent::FocusIn, reason);
+ QPointer<QWidget> that = focus;
+ QApplication::sendEvent(focus, &in);
+ if (that)
+ QApplication::sendEvent(that->style(), &in);
+ }
+ }
+ emit qApp->focusChanged(prev, focus_widget);
+ }
+}
+
+
+/*!
+ Returns the application top-level window that has the keyboard input
+ focus, or 0 if no application window has the focus. Note that
+ there might be an activeWindow() even if there is no focusWidget(),
+ for example if no widget in that window accepts key events.
+
+ \sa QWidget::setFocus(), QWidget::hasFocus(), focusWidget()
+*/
+
+QWidget *QApplication::activeWindow()
+{
+ return QApplicationPrivate::active_window;
+}
+
+/*!
+ Returns display (screen) font metrics for the application font.
+
+ \sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics()
+*/
+
+QFontMetrics QApplication::fontMetrics()
+{
+ return desktop()->fontMetrics();
+}
+
+
+/*!
+ Closes all top-level windows.
+
+ This function is particularly useful for applications with many
+ top-level windows. It could, for example, be connected to a
+ \gui{Exit} entry in the \gui{File} menu:
+
+ \snippet examples/mainwindows/mdi/mainwindow.cpp 0
+
+ The windows are closed in random order, until one window does not
+ accept the close event. The application quits when the last window
+ was successfully closed; this can be turned off by setting \l
+ quitOnLastWindowClosed to false.
+
+ \sa quitOnLastWindowClosed, lastWindowClosed() QWidget::close(), QWidget::closeEvent(), lastWindowClosed(),
+ quit(), topLevelWidgets(), QWidget::isWindow()
+*/
+void QApplication::closeAllWindows()
+{
+ bool did_close = true;
+ QWidget *w;
+ while((w = activeModalWidget()) && did_close) {
+ if(!w->isVisible())
+ break;
+ did_close = w->close();
+ }
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; did_close && i < list.size(); ++i) {
+ w = list.at(i);
+ if (w->isVisible() && w->windowType() != Qt::Desktop) {
+ did_close = w->close();
+ list = QApplication::topLevelWidgets();
+ i = -1;
+ }
+ }
+}
+
+/*!
+ Displays a simple message box about Qt. The message includes the
+ version number of Qt being used by the application.
+
+ This is useful for inclusion in the \gui Help menu of an application,
+ as shown in the \l{mainwindows/menus}{Menus} example.
+
+ This function is a convenience slot for QMessageBox::aboutQt().
+*/
+void QApplication::aboutQt()
+{
+#ifndef QT_NO_MESSAGEBOX
+ QMessageBox::aboutQt(
+#ifdef Q_WS_MAC
+ 0
+#else
+ activeWindow()
+#endif // Q_WS_MAC
+ );
+#endif // QT_NO_MESSAGEBOX
+}
+
+
+/*!
+ \fn void QApplication::lastWindowClosed()
+
+ This signal is emitted from QApplication::exec() when the last
+ visible primary window (i.e. window with no parent) with the
+ Qt::WA_QuitOnClose attribute set is closed.
+
+ By default,
+
+ \list
+
+ \i this attribute is set for all widgets except transient windows
+ such as splash screens, tool windows, and popup menus
+
+ \i QApplication implicitly quits when this signal is emitted.
+
+ \endlist
+
+ This feature be turned off by setting \l quitOnLastWindowClosed to
+ false.
+
+ \sa QWidget::close()
+*/
+
+/*!
+ \since 4.1
+ \fn void QApplication::focusChanged(QWidget *old, QWidget *now)
+
+ This signal is emitted when the widget that has keyboard focus
+ changed from \a old to \a now, i.e. because the user pressed the
+ tab-key, clicked into a widget or changed the active window. Note
+ that both \a old and \a now can be the null-pointer.
+
+ The signal is emitted after both widget have been notified about
+ the change through QFocusEvent.
+
+ \sa QWidget::setFocus() QWidget::clearFocus() Qt::FocusReason
+*/
+
+/*!
+ \since 4.5
+ \fn void QApplication::fontDatabaseChanged()
+
+ This signal is emitted when application fonts are loaded or removed.
+
+ \sa QFontDatabase::addApplicationFont()
+ \sa QFontDatabase::addApplicationFontFromData()
+ \sa QFontDatabase::removeAllApplicationFonts()
+ \sa QFontDatabase::removeApplicationFont()
+*/
+
+#ifndef QT_NO_TRANSLATION
+static bool qt_detectRTLLanguage()
+{
+ return force_reverse ^
+ (QApplication::tr("QT_LAYOUT_DIRECTION",
+ "Translate this string to the string 'LTR' in left-to-right"
+ " languages or to 'RTL' in right-to-left languages (such as Hebrew"
+ " and Arabic) to get proper widget layout.") == QLatin1String("RTL"));
+}
+#endif
+
+/*!\reimp
+
+*/
+bool QApplication::event(QEvent *e)
+{
+ Q_D(QApplication);
+ if(e->type() == QEvent::Close) {
+ QCloseEvent *ce = static_cast<QCloseEvent*>(e);
+ ce->accept();
+ closeAllWindows();
+
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && !(w->windowType() == Qt::Desktop) && !(w->windowType() == Qt::Popup) &&
+ (!(w->windowType() == Qt::Dialog) || !w->parentWidget())) {
+ ce->ignore();
+ break;
+ }
+ }
+ if(ce->isAccepted())
+ return true;
+ } else if(e->type() == QEvent::LanguageChange) {
+#ifndef QT_NO_TRANSLATION
+ setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight);
+#endif
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (!(w->windowType() == Qt::Desktop))
+ postEvent(w, new QEvent(QEvent::LanguageChange));
+ }
+ } else if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ Q_ASSERT(te != 0);
+ if (te->timerId() == d->toolTipWakeUp.timerId()) {
+ d->toolTipWakeUp.stop();
+ if (d->toolTipWidget) {
+ QWidget *w = d->toolTipWidget->window();
+ // show tooltip if WA_AlwaysShowToolTips is set, or if
+ // any ancestor of d->toolTipWidget is the active
+ // window
+ bool showToolTip = w->testAttribute(Qt::WA_AlwaysShowToolTips);
+ while (w && !showToolTip) {
+ showToolTip = w->isActiveWindow();
+ w = w->parentWidget();
+ w = w ? w->window() : 0;
+ }
+ if (showToolTip) {
+ QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos);
+ QApplication::sendEvent(d->toolTipWidget, &e);
+ if (e.isAccepted())
+ d->toolTipFallAsleep.start(2000, this);
+ }
+ }
+ } else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
+ d->toolTipFallAsleep.stop();
+ }
+#ifdef QT_MAC_USE_COCOA
+ } else if (e->type() == QEvent::CocoaRequestModal) {
+ d->_q_runAppModalWindow();
+#endif
+ }
+ return QCoreApplication::event(e);
+}
+#if !defined(Q_WS_X11)
+
+// The doc and X implementation of this function is in qapplication_x11.cpp
+
+void QApplication::syncX() {} // do nothing
+
+#endif
+
+/*!
+ \fn Qt::WindowsVersion QApplication::winVersion()
+
+ Use \l QSysInfo::WindowsVersion instead.
+*/
+
+/*!
+ \fn void QApplication::setActiveWindow(QWidget* active)
+
+ Sets the active window to the \a active widget in response to a system
+ event. The function is called from the platform specific event
+ handlers.
+
+ \warning This function does \e not set the keyboard focus to the
+ active widget. Call QWidget::activateWindow() instead.
+
+ It sets the activeWindow() and focusWidget() attributes and sends
+ proper \l{QEvent::WindowActivate}{WindowActivate}/\l{QEvent::WindowDeactivate}{WindowDeactivate}
+ and \l{QEvent::FocusIn}{FocusIn}/\l{QEvent::FocusOut}{FocusOut} events
+ to all appropriate widgets. The window will then be painted in
+ active state (e.g. cursors in line edits will blink), and it will
+ have tool tips enabled.
+
+ \sa activeWindow(), QWidget::activateWindow()
+*/
+void QApplication::setActiveWindow(QWidget* act)
+{
+ QWidget* window = act?act->window():0;
+
+ if (QApplicationPrivate::active_window == window)
+ return;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (window && window->graphicsProxyWidget()) {
+ // Activate the proxy's view->viewport() ?
+ return;
+ }
+#endif
+
+ QWidgetList toBeActivated;
+ QWidgetList toBeDeactivated;
+
+ if (QApplicationPrivate::active_window) {
+ if (style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, QApplicationPrivate::active_window)) {
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && w->isActiveWindow())
+ toBeDeactivated.append(w);
+ }
+ } else {
+ toBeDeactivated.append(QApplicationPrivate::active_window);
+ }
+ }
+
+#if !defined(Q_WS_MAC)
+ QWidget *previousActiveWindow = QApplicationPrivate::active_window;
+#endif
+ QApplicationPrivate::active_window = window;
+
+ if (QApplicationPrivate::active_window) {
+ if (style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, QApplicationPrivate::active_window)) {
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && w->isActiveWindow())
+ toBeActivated.append(w);
+ }
+ } else {
+ toBeActivated.append(QApplicationPrivate::active_window);
+ }
+
+ }
+
+ // first the activation/deactivation events
+ QEvent activationChange(QEvent::ActivationChange);
+ QEvent windowActivate(QEvent::WindowActivate);
+ QEvent windowDeactivate(QEvent::WindowDeactivate);
+
+#if !defined(Q_WS_MAC)
+ if (!previousActiveWindow) {
+ QEvent appActivate(QEvent::ApplicationActivate);
+ sendSpontaneousEvent(qApp, &appActivate);
+ }
+#endif
+
+ for (int i = 0; i < toBeActivated.size(); ++i) {
+ QWidget *w = toBeActivated.at(i);
+ sendSpontaneousEvent(w, &windowActivate);
+ sendSpontaneousEvent(w, &activationChange);
+ }
+
+ for(int i = 0; i < toBeDeactivated.size(); ++i) {
+ QWidget *w = toBeDeactivated.at(i);
+ sendSpontaneousEvent(w, &windowDeactivate);
+ sendSpontaneousEvent(w, &activationChange);
+ }
+
+#if !defined(Q_WS_MAC)
+ if (!QApplicationPrivate::active_window) {
+ QEvent appDeactivate(QEvent::ApplicationDeactivate);
+ sendSpontaneousEvent(qApp, &appDeactivate);
+ }
+#endif
+
+ if (QApplicationPrivate::popupWidgets == 0) { // !inPopupMode()
+ // then focus events
+ if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
+ QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
+ } else if (QApplicationPrivate::active_window) {
+ QWidget *w = QApplicationPrivate::active_window->focusWidget();
+ if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/)
+ w->setFocus(Qt::ActiveWindowFocusReason);
+ else {
+ w = QApplicationPrivate::focusNextPrevChild_helper(QApplicationPrivate::active_window, true);
+ if (w) {
+ w->setFocus(Qt::ActiveWindowFocusReason);
+ } else {
+ // If the focus widget is not in the activate_window, clear the focus
+ w = QApplicationPrivate::focus_widget;
+ if (w && !QApplicationPrivate::active_window->isAncestorOf(w))
+ QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
+ }
+ }
+ }
+ }
+}
+
+/*!internal
+ * Helper function that returns the new focus widget, but does not set the focus reason.
+ * Returns 0 if a new focus widget could not be found.
+*/
+QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next)
+{
+ uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
+
+ QWidget *f = toplevel->focusWidget();
+ if (!f)
+ f = toplevel;
+
+ QWidget *w = f;
+ QWidget *test = f->d_func()->focus_next;
+ while (test && test != f) {
+ if ((test->focusPolicy() & focus_flag) == focus_flag
+ && !(test->d_func()->extra && test->d_func()->extra->focus_proxy)
+ && test->isVisibleTo(toplevel) && test->isEnabled()
+ && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test))
+ && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) {
+ w = test;
+ if (next)
+ break;
+ }
+ test = test->d_func()->focus_next;
+ }
+ if (w == f) {
+ if (qt_in_tab_key_event) {
+ w->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ w->update();
+ }
+ return 0;
+ }
+ return w;
+}
+
+/*!
+ \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave)
+ \internal
+
+ Creates the proper Enter/Leave event when widget \a enter is entered
+ and widget \a leave is left.
+ */
+#if defined(Q_WS_WIN)
+ extern void qt_win_set_cursor(QWidget *, bool);
+#elif defined(Q_WS_X11)
+ extern void qt_x11_enforce_cursor(QWidget *, bool);
+#endif
+
+void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
+#if 0
+ if (leave) {
+ QEvent e(QEvent::Leave);
+ QApplication::sendEvent(leave, & e);
+ }
+ if (enter) {
+ QEvent e(QEvent::Enter);
+ QApplication::sendEvent(enter, & e);
+ }
+ return;
+#endif
+
+ QWidget* w ;
+ if ((!enter && !leave) || (enter == leave))
+ return;
+#ifdef ALIEN_DEBUG
+ qDebug() << "QApplicationPrivate::dispatchEnterLeave, ENTER:" << enter << "LEAVE:" << leave;
+#endif
+ QWidgetList leaveList;
+ QWidgetList enterList;
+
+ bool sameWindow = leave && enter && leave->window() == enter->window();
+ if (leave && !sameWindow) {
+ w = leave;
+ do {
+ leaveList.append(w);
+ } while (!w->isWindow() && (w = w->parentWidget()));
+ }
+ if (enter && !sameWindow) {
+ w = enter;
+ do {
+ enterList.prepend(w);
+ } while (!w->isWindow() && (w = w->parentWidget()));
+ }
+ if (sameWindow) {
+ int enterDepth = 0;
+ int leaveDepth = 0;
+ w = enter;
+ while (!w->isWindow() && (w = w->parentWidget()))
+ enterDepth++;
+ w = leave;
+ while (!w->isWindow() && (w = w->parentWidget()))
+ leaveDepth++;
+ QWidget* wenter = enter;
+ QWidget* wleave = leave;
+ while (enterDepth > leaveDepth) {
+ wenter = wenter->parentWidget();
+ enterDepth--;
+ }
+ while (leaveDepth > enterDepth) {
+ wleave = wleave->parentWidget();
+ leaveDepth--;
+ }
+ while (!wenter->isWindow() && wenter != wleave) {
+ wenter = wenter->parentWidget();
+ wleave = wleave->parentWidget();
+ }
+
+ w = leave;
+ while (w != wleave) {
+ leaveList.append(w);
+ w = w->parentWidget();
+ }
+ w = enter;
+ while (w != wenter) {
+ enterList.prepend(w);
+ w = w->parentWidget();
+ }
+ }
+
+ QEvent leaveEvent(QEvent::Leave);
+ for (int i = 0; i < leaveList.size(); ++i) {
+ w = leaveList.at(i);
+ if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ if (leaveAfterRelease == w)
+ leaveAfterRelease = 0;
+#endif
+ QApplication::sendEvent(w, &leaveEvent);
+ if (w->testAttribute(Qt::WA_Hover) &&
+ (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ Q_ASSERT(instance());
+ QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos));
+ qApp->d_func()->notify_helper(w, &he);
+ }
+ }
+ }
+ QPoint posEnter = QCursor::pos();
+ QEvent enterEvent(QEvent::Enter);
+ for (int i = 0; i < enterList.size(); ++i) {
+ w = enterList.at(i);
+ if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+ QApplication::sendEvent(w, &enterEvent);
+ if (w->testAttribute(Qt::WA_Hover) &&
+ (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ QHoverEvent he(QEvent::HoverEnter, w->mapFromGlobal(posEnter), QPoint(-1, -1));
+ qApp->d_func()->notify_helper(w, &he);
+ }
+ }
+ }
+
+#ifndef QT_NO_CURSOR
+ // Update cursor for alien/graphics widgets.
+
+ const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen)));
+#if defined(Q_WS_X11)
+ //Whenever we leave an alien widget on X11, we need to reset its nativeParentWidget()'s cursor.
+ // This is not required on Windows as the cursor is reset on every single mouse move.
+ QWidget *parentOfLeavingCursor = 0;
+ for (int i = 0; i < leaveList.size(); ++i) {
+ w = leaveList.at(i);
+ if (!isAlien(w))
+ break;
+ if (w->testAttribute(Qt::WA_SetCursor)) {
+ parentOfLeavingCursor = w->parentWidget();
+ //continue looping, we need to find the downest alien widget with a cursor.
+ // (downest on the screen)
+ }
+ }
+ //check that we will not call qt_x11_enforce_cursor twice with the same native widget
+ if (parentOfLeavingCursor && (!enterOnAlien
+ || parentOfLeavingCursor->effectiveWinId() != enter->effectiveWinId())) {
+#ifndef QT_NO_GRAPHICSVIEW
+ if (!parentOfLeavingCursor->window()->graphicsProxyWidget())
+#endif
+ {
+ qt_x11_enforce_cursor(parentOfLeavingCursor,true);
+ }
+ }
+#endif
+ if (enterOnAlien) {
+ QWidget *cursorWidget = enter;
+ while (!cursorWidget->isWindow() && !cursorWidget->isEnabled())
+ cursorWidget = cursorWidget->parentWidget();
+
+ if (!cursorWidget)
+ return;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (cursorWidget->window()->graphicsProxyWidget()) {
+ QWidgetPrivate::nearestGraphicsProxyWidget(cursorWidget)->setCursor(cursorWidget->cursor());
+ } else
+#endif
+ {
+#if defined(Q_WS_WIN)
+ qt_win_set_cursor(cursorWidget, true);
+#elif defined(Q_WS_X11)
+ qt_x11_enforce_cursor(cursorWidget, true);
+#endif
+ }
+ }
+#endif
+}
+
+/* exported for the benefit of testing tools */
+Q_GUI_EXPORT bool qt_tryModalHelper(QWidget *widget, QWidget **rettop)
+{
+ return QApplicationPrivate::tryModalHelper(widget, rettop);
+}
+
+/*! \internal
+ Returns true if \a widget is blocked by a modal window.
+ */
+bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
+{
+ widget = widget->window();
+ if (!modalState())
+ return false;
+ if (qApp->activePopupWidget() == widget)
+ return false;
+
+ for (int i = 0; i < qt_modal_stack->size(); ++i) {
+ QWidget *modalWidget = qt_modal_stack->at(i);
+
+ {
+ // check if the active modal widget is our widget or a parent of our widget
+ QWidget *w = widget;
+ while (w) {
+ if (w == modalWidget)
+ return false;
+ w = w->parentWidget();
+ }
+#ifdef Q_WS_WIN
+ if ((widget->testAttribute(Qt::WA_WState_Created) || widget->data->winid)
+ && (modalWidget->testAttribute(Qt::WA_WState_Created) || modalWidget->data->winid)
+ && IsChild(modalWidget->data->winid, widget->data->winid))
+ return false;
+#endif
+ }
+
+ Qt::WindowModality windowModality = modalWidget->windowModality();
+ if (windowModality == Qt::NonModal) {
+ // determine the modality type if it hasn't been set on the
+ // modalWidget, this normally happens when waiting for a
+ // native dialog. use WindowModal if we are the child of a
+ // group leader; otherwise use ApplicationModal.
+ QWidget *m = modalWidget;
+ while (m && !m->testAttribute(Qt::WA_GroupLeader)) {
+ m = m->parentWidget();
+ if (m)
+ m = m->window();
+ }
+ windowModality = (m && m->testAttribute(Qt::WA_GroupLeader))
+ ? Qt::WindowModal
+ : Qt::ApplicationModal;
+ }
+
+ switch (windowModality) {
+ case Qt::ApplicationModal:
+ {
+ QWidget *groupLeaderForWidget = widget;
+ while (groupLeaderForWidget && !groupLeaderForWidget->testAttribute(Qt::WA_GroupLeader))
+ groupLeaderForWidget = groupLeaderForWidget->parentWidget();
+
+ if (groupLeaderForWidget) {
+ // if \a widget has WA_GroupLeader, it can only be blocked by ApplicationModal children
+ QWidget *m = modalWidget;
+ while (m && m != groupLeaderForWidget && !m->testAttribute(Qt::WA_GroupLeader))
+ m = m->parentWidget();
+ if (m == groupLeaderForWidget)
+ return true;
+ } else if (modalWidget != widget) {
+ return true;
+ }
+ break;
+ }
+ case Qt::WindowModal:
+ {
+ QWidget *w = widget;
+ do {
+ QWidget *m = modalWidget;
+ do {
+ if (m == w)
+ return true;
+ m = m->parentWidget();
+ if (m)
+ m = m->window();
+ } while (m);
+ w = w->parentWidget();
+ if (w)
+ w = w->window();
+ } while (w);
+ break;
+ }
+ default:
+ Q_ASSERT_X(false, "QApplication", "internal error, a modal widget cannot be modeless");
+ break;
+ }
+ }
+ return false;
+}
+
+/*!\internal
+ */
+void QApplicationPrivate::enterModal(QWidget *widget)
+{
+ QSet<QWidget*> blocked;
+ QList<QWidget*> windows = qApp->topLevelWidgets();
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if (window->windowType() != Qt::Tool && isBlockedByModal(window))
+ blocked.insert(window);
+ }
+
+ enterModal_sys(widget);
+
+ windows = qApp->topLevelWidgets();
+ QEvent e(QEvent::WindowBlocked);
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if (!blocked.contains(window) && window->windowType() != Qt::Tool && isBlockedByModal(window))
+ QApplication::sendEvent(window, &e);
+ }
+}
+
+/*!\internal
+ */
+void QApplicationPrivate::leaveModal(QWidget *widget)
+{
+ QSet<QWidget*> blocked;
+ QList<QWidget*> windows = qApp->topLevelWidgets();
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if (window->windowType() != Qt::Tool && isBlockedByModal(window))
+ blocked.insert(window);
+ }
+
+ leaveModal_sys(widget);
+
+ windows = qApp->topLevelWidgets();
+ QEvent e(QEvent::WindowUnblocked);
+ for (int i = 0; i < windows.count(); ++i) {
+ QWidget *window = windows.at(i);
+ if(blocked.contains(window) && window->windowType() != Qt::Tool && !isBlockedByModal(window))
+ QApplication::sendEvent(window, &e);
+ }
+}
+
+
+
+/*!\internal
+
+ Called from qapplication_\e{platform}.cpp, returns true
+ if the widget should accept the event.
+ */
+bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
+{
+ QWidget *top = QApplication::activeModalWidget();
+ if (rettop)
+ *rettop = top;
+
+ // the active popup widget always gets the input event
+ if (qApp->activePopupWidget())
+ return true;
+
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ top = QApplicationPrivate::tryModalHelper_sys(top);
+ if (rettop)
+ *rettop = top;
+#endif
+
+ return !isBlockedByModal(widget->window());
+}
+
+/*
+ \internal
+*/
+QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint &globalPos,
+ QPoint &pos, QEvent::Type type,
+ Qt::MouseButtons buttons, QWidget *buttonDown,
+ QWidget *alienWidget)
+{
+ Q_ASSERT(candidate);
+
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ if (((type == QEvent::MouseMove && buttons) || (type == QEvent::MouseButtonRelease))
+ && !buttonDown && !mouseGrabber) {
+ return 0;
+ }
+
+ if (alienWidget && alienWidget->internalWinId())
+ alienWidget = 0;
+
+ QWidget *receiver = candidate;
+
+ if (!mouseGrabber)
+ mouseGrabber = buttonDown ? buttonDown : alienWidget;
+
+ if (mouseGrabber && mouseGrabber != candidate) {
+ receiver = mouseGrabber;
+ pos = receiver->mapFromGlobal(globalPos);
+#ifdef ALIEN_DEBUG
+ qDebug() << " ** receiver adjusted to:" << receiver << "pos:" << pos;
+#endif
+ }
+
+ return receiver;
+
+}
+
+/*
+ \internal
+*/
+bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
+ QWidget *alienWidget, QWidget *nativeWidget,
+ QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver)
+{
+ Q_ASSERT(receiver);
+ Q_ASSERT(event);
+ Q_ASSERT(nativeWidget);
+ Q_ASSERT(buttonDown);
+
+ if (alienWidget && !isAlien(alienWidget))
+ alienWidget = 0;
+
+ QPointer<QWidget> receiverGuard = receiver;
+ QPointer<QWidget> nativeGuard = nativeWidget;
+ QPointer<QWidget> alienGuard = alienWidget;
+ QPointer<QWidget> activePopupWidget = qApp->activePopupWidget();
+
+ const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen);
+
+ if (*buttonDown) {
+ if (!graphicsWidget) {
+ // Register the widget that shall receive a leave event
+ // after the last button is released.
+ if ((alienWidget || !receiver->internalWinId()) && !leaveAfterRelease && !QWidget::mouseGrabber())
+ leaveAfterRelease = *buttonDown;
+ if (event->type() == QEvent::MouseButtonRelease && !event->buttons())
+ *buttonDown = 0;
+ }
+ } else if (lastMouseReceiver) {
+ // Dispatch enter/leave if we move:
+ // 1) from an alien widget to another alien widget or
+ // from a native widget to an alien widget (first OR case)
+ // 2) from an alien widget to a native widget (second OR case)
+ if ((alienWidget && alienWidget != lastMouseReceiver)
+ || (isAlien(lastMouseReceiver) && !alienWidget)) {
+ if (activePopupWidget) {
+ if (!QWidget::mouseGrabber())
+ dispatchEnterLeave(alienWidget ? alienWidget : nativeWidget, lastMouseReceiver);
+ } else {
+ dispatchEnterLeave(receiver, lastMouseReceiver);
+ }
+
+ }
+ }
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QApplicationPrivate::sendMouseEvent: receiver:" << receiver
+ << "pos:" << event->pos() << "alien" << alienWidget << "button down"
+ << *buttonDown << "last" << lastMouseReceiver << "leave after release"
+ << leaveAfterRelease;
+#endif
+
+ // We need this quard in case someone opens a modal dialog / popup. If that's the case
+ // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
+ const bool wasLeaveAfterRelease = leaveAfterRelease != 0;
+ bool result = QApplication::sendSpontaneousEvent(receiver, event);
+
+ if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
+ && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
+ // Dispatch enter/leave if:
+ // 1) the mouse grabber is an alien widget
+ // 2) the button is released on an alien widget
+
+ QWidget *enter = 0;
+ if (nativeGuard)
+ enter = alienGuard ? alienWidget : nativeWidget;
+ else // The receiver is typically deleted on mouse release with drag'n'drop.
+ enter = QApplication::widgetAt(event->globalPos());
+
+ dispatchEnterLeave(enter, leaveAfterRelease);
+ leaveAfterRelease = 0;
+ lastMouseReceiver = enter;
+ } else if (!wasLeaveAfterRelease) {
+ if (activePopupWidget) {
+ if (!QWidget::mouseGrabber())
+ lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : 0);
+ } else {
+ lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPos());
+ }
+ }
+
+ return result;
+}
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+/*
+ This function should only be called when the widget changes visibility, i.e.
+ when the \a widget is shown, hidden or deleted. This function does nothing
+ if the widget is a top-level or native, i.e. not an alien widget. In that
+ case enter/leave events are genereated by the underlying windowing system.
+*/
+extern QPointer<QWidget> qt_last_mouse_receiver;
+extern QWidget *qt_button_down;
+void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
+{
+#ifndef QT_NO_CURSOR
+ if (!widget || widget->internalWinId() || widget->isWindow())
+ return;
+
+ const bool widgetInShow = widget->isVisible() && !widget->data->in_destructor;
+ if (!widgetInShow && widget != qt_last_mouse_receiver)
+ return; // Widget was not under the cursor when it was hidden/deleted.
+
+ if (widgetInShow && widget->parentWidget()->data->in_show)
+ return; // Ingore recursive show.
+
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ if (mouseGrabber && mouseGrabber != widget)
+ return; // Someone else has the grab; enter/leave should not occur.
+
+ QWidget *tlw = widget->window();
+ if (tlw->data->in_destructor || tlw->data->is_closing)
+ return; // Closing down the business.
+
+ if (widgetInShow && (!qt_last_mouse_receiver || qt_last_mouse_receiver->window() != tlw))
+ return; // Mouse cursor not inside the widget's top-level.
+
+ const QPoint globalPos(QCursor::pos());
+ QPoint pos = tlw->mapFromGlobal(globalPos);
+
+ // Find the current widget under the mouse. If this function was called from
+ // the widget's destructor, we have to make sure childAt() doesn't take into
+ // account widgets that are about to be destructed.
+ QWidget *widgetUnderCursor = tlw->d_func()->childAt_helper(pos, widget->data->in_destructor);
+ if (!widgetUnderCursor)
+ widgetUnderCursor = tlw;
+ else
+ pos = widgetUnderCursor->mapFrom(tlw, pos);
+
+ if (widgetInShow && widgetUnderCursor != widget && !widget->isAncestorOf(widgetUnderCursor))
+ return; // Mouse cursor not inside the widget or any of its children.
+
+ if (widget->data->in_destructor && qt_button_down == widget)
+ qt_button_down = 0;
+
+ // Send enter/leave events followed by a mouse move on the entered widget.
+ QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, mouse_buttons, modifier_buttons);
+ sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver);
+#endif // QT_NO_CURSOR
+}
+#endif // Q_WS_WIN || Q_WS_X11
+
+/*!
+ Returns the desktop widget (also called the root window).
+
+ Note that the desktop may be composed of multiple screens, so it would be
+ incorrect, for example, to attempt to \e center some widget in the
+ desktop's geometry. QDesktopWidget has various functions for obtaining
+ useful geometries upon the desktop, such as QDesktopWidget::screenGeometry()
+ and QDesktopWidget::availableGeometry().
+
+ On X11, it is also possible to draw on the desktop.
+*/
+QDesktopWidget *QApplication::desktop()
+{
+ if (!qt_desktopWidget || // not created yet
+ !(qt_desktopWidget->windowType() == Qt::Desktop)) { // reparented away
+ qt_desktopWidget = new QDesktopWidget();
+ }
+ return qt_desktopWidget;
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ Returns a pointer to the application global clipboard.
+
+ \note The QApplication object should already be constructed before
+ accessing the clipboard.
+*/
+QClipboard *QApplication::clipboard()
+{
+ if (qt_clipboard == 0) {
+ if (!qApp) {
+ qWarning("QApplication: Must construct a QApplication before accessing a QClipboard");
+ return 0;
+ }
+ qt_clipboard = new QClipboard(0);
+ }
+ return qt_clipboard;
+}
+#endif // QT_NO_CLIPBOARD
+
+/*!
+ Sets whether Qt should use the system's standard colors, fonts,
+ etc., to \a on. By default, this is true.
+
+ This function must be called before creating the QApplication
+ object, like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 6
+
+ \sa desktopSettingsAware()
+*/
+void QApplication::setDesktopSettingsAware(bool on)
+{
+ QApplicationPrivate::obey_desktop_settings = on;
+}
+
+/*!
+ Returns true if Qt is set to use the system's standard colors,
+ fonts, etc.; otherwise returns false. The default is true.
+
+ \sa setDesktopSettingsAware()
+*/
+bool QApplication::desktopSettingsAware()
+{
+ return QApplicationPrivate::obey_desktop_settings;
+}
+
+/*!
+ Returns the current state of the modifier keys on the keyboard. The
+ current state is updated sychronously as the event queue is emptied
+ of events that will spontaneously change the keyboard state
+ (QEvent::KeyPress and QEvent::KeyRelease events).
+
+ It should be noted this may not reflect the actual keys held on the
+ input device at the time of calling but rather the modifiers as
+ last reported in one of the above events. If no keys are being held
+ Qt::NoModifier is returned.
+
+ \sa mouseButtons()
+*/
+
+Qt::KeyboardModifiers QApplication::keyboardModifiers()
+{
+ return QApplicationPrivate::modifier_buttons;
+}
+
+/*!
+ Returns the current state of the buttons on the mouse. The current
+ state is updated syncronously as the event queue is emptied of
+ events that will spontaneously change the mouse state
+ (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events).
+
+ It should be noted this may not reflect the actual buttons held on
+ theinput device at the time of calling but rather the mouse buttons
+ as last reported in one of the above events. If no mouse buttons are
+ being held Qt::NoButton is returned.
+
+ \sa keyboardModifiers()
+*/
+
+Qt::MouseButtons QApplication::mouseButtons()
+{
+ return QApplicationPrivate::mouse_buttons;
+}
+
+/*!
+ \fn bool QApplication::isSessionRestored() const
+
+ Returns true if the application has been restored from an earlier
+ \link session.html session\endlink; otherwise returns false.
+
+ \sa sessionId(), commitData(), saveState()
+*/
+
+
+/*!
+ \fn QString QApplication::sessionId() const
+
+ Returns the current \link session.html session's\endlink identifier.
+
+ If the application has been restored from an earlier session, this
+ identifier is the same as it was in that previous session.
+
+ The session identifier is guaranteed to be unique both for different
+ applications and for different instances of the same application.
+
+ \sa isSessionRestored(), sessionKey(), commitData(), saveState()
+ */
+
+/*!
+ \fn QString QApplication::sessionKey() const
+
+ Returns the session key in the current \link session.html
+ session\endlink.
+
+ If the application has been restored from an earlier session, this
+ key is the same as it was when the previous session ended.
+
+ The session key changes with every call of commitData() or
+ saveState().
+
+ \sa isSessionRestored(), sessionId(), commitData(), saveState()
+ */
+#ifndef QT_NO_SESSIONMANAGER
+bool QApplication::isSessionRestored() const
+{
+ Q_D(const QApplication);
+ return d->is_session_restored;
+}
+
+QString QApplication::sessionId() const
+{
+ Q_D(const QApplication);
+ return d->session_id;
+}
+
+QString QApplication::sessionKey() const
+{
+ Q_D(const QApplication);
+ return d->session_key;
+}
+#endif
+
+
+
+
+
+/*!
+ \since 4.2
+ \fn void QApplication::commitDataRequest(QSessionManager &manager)
+
+ This signal deals with \link session.html session
+ management\endlink. It is emitted when the QSessionManager wants the
+ application to commit all its data.
+
+ Usually this means saving all open files, after getting
+ permission from the user. Furthermore you may want to provide a means
+ by which the user can cancel the shutdown.
+
+ Note that you should not exit the application when called.
+ Instead, the session manager may or may not do this afterwards,
+ depending on the context.
+
+ \warning Within this signal, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details and example
+ usage.
+
+ Note: You should use Qt::DirectConnection when connecting to this signal.
+
+ \sa isSessionRestored(), sessionId(), saveState(), {Session Management}
+*/
+
+/*!
+ This function deals with \link session.html session
+ management\endlink. It is invoked when the QSessionManager wants the
+ application to commit all its data.
+
+ Usually this means saving all open files, after getting
+ permission from the user. Furthermore you may want to provide a means
+ by which the user can cancel the shutdown.
+
+ Note that you should not exit the application within this function.
+ Instead, the session manager may or may not do this afterwards,
+ depending on the context.
+
+ \warning Within this function, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details and example
+ usage.
+
+ The default implementation requests interaction and sends a close
+ event to all visible top-level widgets. If any event was
+ rejected, the shutdown is canceled.
+
+ \sa isSessionRestored(), sessionId(), saveState(), {Session Management}
+*/
+#ifndef QT_NO_SESSIONMANAGER
+void QApplication::commitData(QSessionManager& manager )
+{
+ emit commitDataRequest(manager);
+ if (manager.allowsInteraction()) {
+ QWidgetList done;
+ QWidgetList list = QApplication::topLevelWidgets();
+ bool cancelled = false;
+ for (int i = 0; !cancelled && i < list.size(); ++i) {
+ QWidget* w = list.at(i);
+ if (w->isVisible() && !done.contains(w)) {
+ cancelled = !w->close();
+ if (!cancelled)
+ done.append(w);
+ list = QApplication::topLevelWidgets();
+ i = -1;
+ }
+ }
+ if (cancelled)
+ manager.cancel();
+ }
+}
+
+/*!
+ \since 4.2
+ \fn void QApplication::saveStateRequest(QSessionManager &manager)
+
+ This signal deals with \link session.html session
+ management\endlink. It is invoked when the
+ \link QSessionManager session manager \endlink wants the application
+ to preserve its state for a future session.
+
+ For example, a text editor would create a temporary file that
+ includes the current contents of its edit buffers, the location of
+ the cursor and other aspects of the current editing session.
+
+ Note that you should never exit the application within this
+ signal. Instead, the session manager may or may not do this
+ afterwards, depending on the context. Futhermore, most session
+ managers will very likely request a saved state immediately after
+ the application has been started. This permits the session manager
+ to learn about the application's restart policy.
+
+ \warning Within this function, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details.
+
+ Note:: You should use Qt::DirectConnection when connecting to this signal.
+
+ \sa isSessionRestored(), sessionId(), commitData(), {Session Management}
+*/
+
+/*!
+ This function deals with \link session.html session
+ management\endlink. It is invoked when the
+ \link QSessionManager session manager \endlink wants the application
+ to preserve its state for a future session.
+
+ For example, a text editor would create a temporary file that
+ includes the current contents of its edit buffers, the location of
+ the cursor and other aspects of the current editing session.
+
+ Note that you should never exit the application within this
+ function. Instead, the session manager may or may not do this
+ afterwards, depending on the context. Futhermore, most session
+ managers will very likely request a saved state immediately after
+ the application has been started. This permits the session manager
+ to learn about the application's restart policy.
+
+ \warning Within this function, no user interaction is possible, \e
+ unless you ask the \a manager for explicit permission. See
+ QSessionManager::allowsInteraction() and
+ QSessionManager::allowsErrorInteraction() for details.
+
+ \sa isSessionRestored(), sessionId(), commitData(), {Session Management}
+*/
+
+void QApplication::saveState(QSessionManager &manager)
+{
+ emit saveStateRequest(manager);
+}
+#endif //QT_NO_SESSIONMANAGER
+/*
+ Sets the time after which a drag should start to \a ms ms.
+
+ \sa startDragTime()
+*/
+
+void QApplication::setStartDragTime(int ms)
+{
+ drag_time = ms;
+}
+
+/*!
+ \property QApplication::startDragTime
+ \brief the time in milliseconds that a mouse button must be held down
+ before a drag and drop operation will begin
+
+ If you support drag and drop in your application, and want to start a
+ drag and drop operation after the user has held down a mouse button for
+ a certain amount of time, you should use this property's value as the
+ delay.
+
+ Qt also uses this delay internally, e.g. in QTextEdit and QLineEdit,
+ for starting a drag.
+
+ The default value is 500 ms.
+
+ \sa startDragDistance(), {Drag and Drop}
+*/
+
+int QApplication::startDragTime()
+{
+ return drag_time;
+}
+
+/*
+ Sets the distance after which a drag should start to \a l pixels.
+
+ \sa startDragDistance()
+*/
+
+void QApplication::setStartDragDistance(int l)
+{
+ drag_distance = l;
+}
+
+/*!
+ \property QApplication::startDragDistance
+
+ If you support drag and drop in your application, and want to start a
+ drag and drop operation after the user has moved the cursor a certain
+ distance with a button held down, you should use this property's value
+ as the minimum distance required.
+
+ For example, if the mouse position of the click is stored in \c
+ startPos and the current position (e.g. in the mouse move event) is
+ \c currentPos, you can find out if a drag should be started with code
+ like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 7
+
+ Qt uses this value internally, e.g. in QFileDialog.
+
+ The default value is 4 pixels.
+
+ \sa startDragTime() QPoint::manhattanLength() {Drag and Drop}
+*/
+
+int QApplication::startDragDistance()
+{
+ return drag_distance;
+}
+
+/*!
+ \fn void QApplication::setReverseLayout(bool reverse)
+
+ Use setLayoutDirection() instead.
+*/
+
+/*!
+ \fn void QApplication::reverseLayout()
+
+ Use layoutDirection() instead.
+*/
+
+/*!
+ \fn bool QApplication::isRightToLeft()
+
+ Returns true if the application's layout direction is
+ Qt::RightToLeft; otherwise returns false.
+
+ \sa layoutDirection(), isLeftToRight()
+*/
+
+/*!
+ \fn bool QApplication::isLeftToRight()
+
+ Returns true if the application's layout direction is
+ Qt::LeftToRight; otherwise returns false.
+
+ \sa layoutDirection(), isRightToLeft()
+*/
+
+/*! \property QApplication::layoutDirection
+
+ \brief the default layout direction for this application
+
+ On system start-up, the default layout direction depends on the
+ application's language.
+
+ \sa QWidget::layoutDirection, isLeftToRight(), isRightToLeft()
+ */
+
+void QApplication::setLayoutDirection(Qt::LayoutDirection direction)
+{
+ if (layout_direction == direction)
+ return;
+
+ layout_direction = direction;
+
+ QWidgetList list = topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ QEvent ev(QEvent::ApplicationLayoutDirectionChange);
+ sendEvent(w, &ev);
+ }
+}
+
+Qt::LayoutDirection QApplication::layoutDirection()
+{
+ return layout_direction;
+}
+
+
+/*! \obsolete
+
+ Strips out vertical alignment flags and transforms an
+ alignment \a align of Qt::AlignLeft into Qt::AlignLeft or
+ Qt::AlignRight according to the language used.
+*/
+
+#ifdef QT3_SUPPORT
+Qt::Alignment QApplication::horizontalAlignment(Qt::Alignment align)
+{
+ return QStyle::visualAlignment(layoutDirection(), align);
+}
+#endif
+
+
+/*!
+ \fn QCursor *QApplication::overrideCursor()
+
+ Returns the active application override cursor.
+
+ This function returns 0 if no application cursor has been defined
+ (i.e. the internal cursor stack is empty).
+
+ \sa setOverrideCursor(), restoreOverrideCursor()
+*/
+#ifndef QT_NO_CURSOR
+QCursor *QApplication::overrideCursor()
+{
+ return qApp->d_func()->cursor_list.isEmpty() ? 0 : &qApp->d_func()->cursor_list.first();
+}
+
+/*!
+ Changes the currently active application override cursor to \a cursor.
+
+ This function has no effect if setOverrideCursor() wasn't called.
+
+ \sa setOverrideCursor() overrideCursor() restoreOverrideCursor() QWidget::setCursor()
+ */
+void QApplication::changeOverrideCursor(const QCursor &cursor)
+{
+ if (qApp->d_func()->cursor_list.isEmpty())
+ return;
+ qApp->d_func()->cursor_list.removeFirst();
+ setOverrideCursor(cursor);
+}
+#endif
+
+/*!
+ \fn void QApplication::setOverrideCursor(const QCursor &cursor, bool replace)
+
+ Use changeOverrideCursor(\a cursor) (if \a replace is true)
+ or setOverrideCursor(\a cursor) (if \a replace is false).
+*/
+
+/*!
+ Enters the main event loop and waits until exit() is called, then returns
+ the value that was set to exit() (which is 0 if exit() is called via
+ quit()).
+
+ It is necessary to call this function to start event handling. The
+ main event loop receives events from the window system and
+ dispatches these to the application widgets.
+
+ Generally speaking, no user interaction can take place before
+ calling exec(). As a special case, modal widgets like QMessageBox
+ can be used before calling exec(), because modal widgets call
+ exec() to start a local event loop.
+
+ To make your application perform idle processing, i.e. executing a
+ special function whenever there are no pending events, use a
+ QTimer with 0 timeout. More advanced idle processing schemes can
+ be achieved using processEvents().
+
+ We recommend that you connect clean-up code to the
+ \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in
+ your application's \c{main()} function because on some platforms the
+ QApplication::exec() call may not return. For example, on Windows
+ when the user logs off, the system terminates the process after Qt
+ closes all top-level windows. Hence, there is no guarantee that the
+ application will have time to exit its event loop and execute code at
+ the end of the \c{main()} function after the QApplication::exec()
+ call.
+
+ \sa quitOnLastWindowClosed, quit(), exit(), processEvents(),
+ QCoreApplication::exec()
+*/
+int QApplication::exec()
+{
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::setRootObject(qApp);
+#endif
+ return QCoreApplication::exec();
+}
+
+/*! \reimp
+ */
+bool QApplication::notify(QObject *receiver, QEvent *e)
+{
+ Q_D(QApplication);
+ // no events are delivered after ~QCoreApplication() has started
+ if (QApplicationPrivate::is_app_closing)
+ return true;
+
+ if (receiver == 0) { // serious error
+ qWarning("QApplication::notify: Unexpected null receiver");
+ return true;
+ }
+
+#ifndef QT_NO_DEBUG
+ d->checkReceiverThread(receiver);
+#endif
+
+#ifdef QT3_SUPPORT
+ if (e->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty())
+ receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(e)->child());
+#endif // QT3_SUPPORT
+
+ // capture the current mouse/keyboard state
+ if(e->spontaneous()) {
+ if (e->type() == QEvent::KeyPress
+ || e->type() == QEvent::KeyRelease) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ QApplicationPrivate::modifier_buttons = ke->modifiers();
+ } else if(e->type() == QEvent::MouseButtonPress
+ || e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QApplicationPrivate::modifier_buttons = me->modifiers();
+ if(me->type() == QEvent::MouseButtonPress)
+ QApplicationPrivate::mouse_buttons |= me->button();
+ else
+ QApplicationPrivate::mouse_buttons &= ~me->button();
+ }
+#if !defined(QT_NO_WHEELEVENT) || !defined(QT_NO_TABLETEVENT)
+ else if (
+# ifndef QT_NO_WHEELEVENT
+ e->type() == QEvent::Wheel ||
+# endif
+# ifndef QT_NO_TABLETEVENT
+ e->type() == QEvent::TabletMove
+ || e->type() == QEvent::TabletPress
+ || e->type() == QEvent::TabletRelease
+# endif
+ ) {
+ QInputEvent *ie = static_cast<QInputEvent*>(e);
+ QApplicationPrivate::modifier_buttons = ie->modifiers();
+ }
+#endif // !QT_NO_WHEELEVENT || !QT_NO_TABLETEVENT
+ }
+
+ // User input and window activation makes tooltips sleep
+ switch (e->type()) {
+ case QEvent::Wheel:
+ case QEvent::ActivationChange:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::FocusOut:
+ case QEvent::FocusIn:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ d->toolTipFallAsleep.stop();
+ case QEvent::Leave:
+ d->toolTipWakeUp.stop();
+ default:
+ break;
+ }
+
+ bool res = false;
+ if (!receiver->isWidgetType()) {
+ res = d->notify_helper(receiver, e);
+ } else switch (e->type()) {
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ case QEvent::Accel:
+ {
+ if (d->use_compat()) {
+ QKeyEvent* key = static_cast<QKeyEvent*>(e);
+ res = d->notify_helper(receiver, e);
+
+ if (!res && !key->isAccepted())
+ res = d->qt_dispatchAccelEvent(static_cast<QWidget *>(receiver), key);
+
+ // next lines are for compatibility with Qt <= 3.0.x: old
+ // QAccel was listening on toplevel widgets
+ if (!res && !key->isAccepted() && !static_cast<QWidget *>(receiver)->isWindow())
+ res = d->notify_helper(static_cast<QWidget *>(receiver)->window(), e);
+ }
+ break;
+ }
+#endif //QT3_SUPPORT && !QT_NO_SHORTCUT
+ case QEvent::ShortcutOverride:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ {
+ bool isWidget = receiver->isWidgetType();
+ bool isGraphicsWidget = false;
+#ifndef QT_NO_GRAPHICSVIEW
+ isGraphicsWidget = !isWidget && qobject_cast<QGraphicsWidget *>(receiver);
+#endif
+ if (!isWidget && !isGraphicsWidget) {
+ res = d->notify_helper(receiver, e);
+ break;
+ }
+
+ QKeyEvent* key = static_cast<QKeyEvent*>(e);
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ if (d->use_compat() && d->qt_tryComposeUnicode(static_cast<QWidget*>(receiver), key))
+ break;
+#endif
+ if (key->type()==QEvent::KeyPress) {
+#ifndef QT_NO_SHORTCUT
+ // Try looking for a Shortcut before sending key events
+ if ((res = qApp->d_func()->shortcutMap.tryShortcutEvent(receiver, key)))
+ return res;
+#endif
+ qt_in_tab_key_event = (key->key() == Qt::Key_Backtab
+ || key->key() == Qt::Key_Tab
+ || key->key() == Qt::Key_Left
+ || key->key() == Qt::Key_Up
+ || key->key() == Qt::Key_Right
+ || key->key() == Qt::Key_Down);
+ }
+ bool def = key->isAccepted();
+ QPointer<QObject> pr = receiver;
+ while (receiver) {
+ if (def)
+ key->accept();
+ else
+ key->ignore();
+ res = d->notify_helper(receiver, e);
+ QWidget *w = isWidget ? static_cast<QWidget *>(receiver) : 0;
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsWidget *gw = isGraphicsWidget ? static_cast<QGraphicsWidget *>(receiver) : 0;
+#endif
+
+ if ((res && key->isAccepted())
+ /*
+ QLineEdit will emit a signal on Key_Return, but
+ ignore the event, and sometimes the connected
+ slot deletes the QLineEdit (common in itemview
+ delegates), so we have to check if the widget
+ was destroyed even if the event was ignored (to
+ prevent a crash)
+
+ note that we don't have to reset pw while
+ propagating (because the original receiver will
+ be destroyed if one of its ancestors is)
+ */
+ || !pr
+ || (isWidget && (w->isWindow() || !w->parentWidget()))
+#ifndef QT_NO_GRAPHICSVIEW
+ || (isGraphicsWidget && (gw->isWindow() || !gw->parentWidget()))
+#endif
+ ) {
+ break;
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ receiver = w ? (QObject *)w->parentWidget() : (QObject *)gw->parentWidget();
+#else
+ receiver = w->parentWidget();
+#endif
+ }
+ qt_in_tab_key_event = false;
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+
+ QMouseEvent* mouse = static_cast<QMouseEvent*>(e);
+ QPoint relpos = mouse->pos();
+
+ if (e->spontaneous()) {
+
+ if (e->type() == QEvent::MouseButtonPress) {
+ QWidget *fw = w;
+ while (fw) {
+ if (fw->isEnabled()
+ && QApplicationPrivate::shouldSetFocus(fw, Qt::ClickFocus)) {
+ fw->setFocus(Qt::MouseFocusReason);
+ break;
+ }
+ if (fw->isWindow())
+ break;
+ fw = fw->parentWidget();
+ }
+ }
+
+ if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) {
+ d->toolTipWidget = w;
+ d->toolTipPos = relpos;
+ d->toolTipGlobalPos = mouse->globalPos();
+ d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive()?20:700, this);
+ }
+ }
+
+ bool eventAccepted = mouse->isAccepted();
+
+ QPointer<QWidget> pw = w;
+ while (w) {
+ QMouseEvent me(mouse->type(), relpos, mouse->globalPos(), mouse->button(), mouse->buttons(),
+ mouse->modifiers());
+ me.spont = mouse->spontaneous();
+ // throw away any mouse-tracking-only mouse events
+ if (!w->hasMouseTracking()
+ && mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {
+ // but still send them through all application event filters (normally done by notify_helper)
+ for (int i = 0; i < d->eventFilters.size(); ++i) {
+ register QObject *obj = d->eventFilters.at(i);
+ if (!obj)
+ continue;
+ if (obj->d_func()->threadData != w->d_func()->threadData) {
+ qWarning("QApplication: Object event filter cannot be in a different thread.");
+ continue;
+ }
+ if (obj->eventFilter(w, w == receiver ? mouse : &me))
+ break;
+ }
+ res = true;
+ } else {
+ w->setAttribute(Qt::WA_NoMouseReplay, false);
+ res = d->notify_helper(w, w == receiver ? mouse : &me);
+ e->spont = false;
+ }
+ eventAccepted = (w == receiver ? mouse : &me)->isAccepted();
+ if (res && eventAccepted)
+ break;
+ if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+
+ mouse->setAccepted(eventAccepted);
+
+ if (e->type() == QEvent::MouseMove) {
+ if (!pw)
+ break;
+
+ w = static_cast<QWidget *>(receiver);
+ relpos = mouse->pos();
+ QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
+ while (w) {
+ if (w->testAttribute(Qt::WA_Hover) &&
+ (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff);
+ d->notify_helper(w, &he);
+ }
+ if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ }
+
+ d->hoverGlobalPos = mouse->globalPos();
+ }
+ break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
+ QPoint relpos = wheel->pos();
+ bool eventAccepted = wheel->isAccepted();
+
+ if (e->spontaneous()) {
+ QWidget *fw = w;
+ while (fw) {
+ if (fw->isEnabled()
+ && QApplicationPrivate::shouldSetFocus(fw, Qt::WheelFocus)) {
+ fw->setFocus(Qt::MouseFocusReason);
+ break;
+ }
+ if (fw->isWindow())
+ break;
+ fw = fw->parentWidget();
+ }
+ }
+
+ while (w) {
+ QWheelEvent we(relpos, wheel->globalPos(), wheel->delta(), wheel->buttons(),
+ wheel->modifiers(), wheel->orientation());
+ we.spont = wheel->spontaneous();
+ res = d->notify_helper(w, w == receiver ? wheel : &we);
+ eventAccepted = ((w == receiver) ? wheel : &we)->isAccepted();
+ e->spont = false;
+ if ((res && eventAccepted)
+ || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ wheel->setAccepted(eventAccepted);
+ }
+ break;
+#endif
+#ifndef QT_NO_CONTEXTMENU
+ case QEvent::ContextMenu:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QContextMenuEvent *context = static_cast<QContextMenuEvent*>(e);
+ QPoint relpos = context->pos();
+ bool eventAccepted = context->isAccepted();
+ while (w) {
+ QContextMenuEvent ce(context->reason(), relpos, context->globalPos(), context->modifiers());
+ ce.spont = e->spontaneous();
+ res = d->notify_helper(w, w == receiver ? context : &ce);
+ eventAccepted = ((w == receiver) ? context : &ce)->isAccepted();
+ e->spont = false;
+
+ if ((res && eventAccepted)
+ || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ context->setAccepted(eventAccepted);
+ }
+ break;
+#endif // QT_NO_CONTEXTMENU
+#ifndef QT_NO_TABLETEVENT
+ case QEvent::TabletMove:
+ case QEvent::TabletPress:
+ case QEvent::TabletRelease:
+ {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QTabletEvent *tablet = static_cast<QTabletEvent*>(e);
+ QPoint relpos = tablet->pos();
+ bool eventAccepted = tablet->isAccepted();
+ while (w) {
+ QTabletEvent te(tablet->type(), relpos, tablet->globalPos(),
+ tablet->hiResGlobalPos(), tablet->device(), tablet->pointerType(),
+ tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
+ tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
+ tablet->modifiers(), tablet->uniqueId());
+ te.spont = e->spontaneous();
+ res = d->notify_helper(w, w == receiver ? tablet : &te);
+ eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
+ e->spont = false;
+ if ((res && eventAccepted)
+ || w->isWindow()
+ || w->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ tablet->setAccepted(eventAccepted);
+ qt_tabletChokeMouse = tablet->isAccepted();
+ }
+ break;
+#endif // QT_NO_TABLETEVENT
+
+#if !defined(QT_NO_TOOLTIP) || !defined(QT_NO_WHATSTHIS)
+ case QEvent::ToolTip:
+ case QEvent::WhatsThis:
+ case QEvent::QueryWhatsThis:
+ {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QHelpEvent *help = static_cast<QHelpEvent*>(e);
+ QPoint relpos = help->pos();
+ bool eventAccepted = help->isAccepted();
+ while (w) {
+ QHelpEvent he(help->type(), relpos, help->globalPos());
+ he.spont = e->spontaneous();
+ res = d->notify_helper(w, w == receiver ? help : &he);
+ e->spont = false;
+ eventAccepted = (w == receiver ? help : &he)->isAccepted();
+ if ((res && eventAccepted) || w->isWindow())
+ break;
+
+ relpos += w->pos();
+ w = w->parentWidget();
+ }
+ help->setAccepted(eventAccepted);
+ }
+ break;
+#endif
+#if !defined(QT_NO_STATUSTIP) || !defined(QT_NO_WHATSTHIS)
+ case QEvent::StatusTip:
+ case QEvent::WhatsThisClicked:
+ {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ while (w) {
+ res = d->notify_helper(w, e);
+ if ((res && e->isAccepted()) || w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ }
+ break;
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::DragEnter: {
+ QWidget* w = static_cast<QWidget *>(receiver);
+ QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(e);
+#ifdef Q_WS_MAC
+ // HIView has a slight difference in how it delivers events to children and parents
+ // It will not give a leave to a child's parent when it enters a child.
+ QWidget *currentTarget = QDragManager::self()->currentTarget();
+ if (currentTarget) {
+ // Assume currentTarget did not get a leave
+ QDragLeaveEvent event;
+ QApplication::sendEvent(currentTarget, &event);
+ }
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+ // QGraphicsProxyWidget handles its own propagation,
+ // and we must not change QDragManagers currentTarget.
+ QWExtra *extra = w->window()->d_func()->extra;
+ if (extra && extra->proxyWidget) {
+ res = d->notify_helper(w, dragEvent);
+ break;
+ }
+#endif
+ while (w) {
+ if (w->isEnabled() && w->acceptDrops()) {
+ res = d->notify_helper(w, dragEvent);
+ if (res && dragEvent->isAccepted()) {
+ QDragManager::self()->setCurrentTarget(w);
+ break;
+ }
+ }
+ if (w->isWindow())
+ break;
+ dragEvent->p = w->mapToParent(dragEvent->p);
+ w = w->parentWidget();
+ }
+ }
+ break;
+ case QEvent::DragMove:
+ case QEvent::Drop:
+ case QEvent::DragLeave: {
+ QWidget* w = static_cast<QWidget *>(receiver);
+#ifndef QT_NO_GRAPHICSVIEW
+ // QGraphicsProxyWidget handles its own propagation,
+ // and we must not change QDragManagers currentTarget.
+ QWExtra *extra = w->window()->d_func()->extra;
+ bool isProxyWidget = extra && extra->proxyWidget;
+ if (!isProxyWidget)
+#endif
+ w = QDragManager::self()->currentTarget();
+
+ if (!w) {
+#ifdef Q_WS_MAC
+ // HIView has a slight difference in how it delivers events to children and parents
+ // It will not give an enter to a child's parent when it leaves the child.
+ if (e->type() == QEvent::DragLeave)
+ break;
+ // Assume that w did not get an enter.
+ QDropEvent *dropEvent = static_cast<QDropEvent *>(e);
+ QDragEnterEvent dragEnterEvent(dropEvent->pos(), dropEvent->possibleActions(),
+ dropEvent->mimeData(), dropEvent->mouseButtons(),
+ dropEvent->keyboardModifiers());
+ QApplication::sendEvent(receiver, &dragEnterEvent);
+ w = QDragManager::self()->currentTarget();
+ if (!w)
+#endif
+ break;
+ }
+ if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) {
+ QDropEvent *dragEvent = static_cast<QDropEvent *>(e);
+ QWidget *origReciver = static_cast<QWidget *>(receiver);
+ while (origReciver && w != origReciver) {
+ dragEvent->p = origReciver->mapToParent(dragEvent->p);
+ origReciver = origReciver->parentWidget();
+ }
+ }
+ res = d->notify_helper(w, e);
+ if (e->type() != QEvent::DragMove
+#ifndef QT_NO_GRAPHICSVIEW
+ && !isProxyWidget
+#endif
+ )
+ QDragManager::self()->setCurrentTarget(0, e->type() == QEvent::Drop);
+ }
+ break;
+#endif
+
+ default:
+ res = d->notify_helper(receiver, e);
+ break;
+ }
+
+ return res;
+}
+
+bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
+{
+ // send to all application event filters
+ if (sendThroughApplicationEventFilters(receiver, e))
+ return true;
+
+ if (receiver->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+
+#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+ // toggle HasMouse widget state on enter and leave
+ if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
+ (!qApp->activePopupWidget() || qApp->activePopupWidget() == widget->window()))
+ widget->setAttribute(Qt::WA_UnderMouse, true);
+ else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
+ widget->setAttribute(Qt::WA_UnderMouse, false);
+#endif
+
+ if (QLayout *layout=widget->d_func()->layout) {
+ layout->widgetEvent(e);
+ }
+ }
+
+ // send to all receiver event filters
+ if (sendThroughObjectEventFilters(receiver, e))
+ return true;
+
+ // deliver the event
+ bool consumed = receiver->event(e);
+ e->spont = false;
+ return consumed;
+}
+
+
+/*!
+ \class QSessionManager
+ \brief The QSessionManager class provides access to the session manager.
+
+ \ingroup application
+ \ingroup environment
+
+ A session manager in a desktop environment (in which Qt GUI
+ applications live) keeps track of a session, which is a group of
+ running applications, each of which has a particular state. The
+ state of an application contains (most notably) the documents the
+ application has open and the position and size of its windows.
+
+ The session manager is used to save the session, e.g. when the
+ machine is shut down, and to restore a session, e.g. when the
+ machine is started up. We recommend that you use QSettings to save
+ an individual application's settings, e.g. window positions,
+ recently used files, etc. When the application is restarted by the
+ session manager, you can restore the settings.
+
+ QSessionManager provides an interface between the application
+ and the session manager so that the program can work well with the
+ session manager. In Qt, session management requests for action are
+ handled by the two virtual functions QApplication::commitData()
+ and QApplication::saveState(). Both provide a reference to a
+ session manager object as argument, to allow the application to
+ communicate with the session manager. The session manager can only
+ be accessed through these functions.
+
+ No user interaction is possible \e unless the application gets
+ explicit permission from the session manager. You ask for permission
+ by calling allowsInteraction() or, if it's really urgent,
+ allowsErrorInteraction(). Qt does not enforce this, but the session
+ manager may.
+
+ You can try to abort the shutdown process by calling cancel(). The
+ default commitData() function does this if some top-level window
+ rejected its closeEvent().
+
+ For sophisticated session managers provided on Unix/X11, QSessionManager
+ offers further possibilities to fine-tune an application's session
+ management behavior: setRestartCommand(), setDiscardCommand(),
+ setRestartHint(), setProperty(), requestPhase2(). See the respective
+ function descriptions for further details.
+
+ \sa QApplication, {Session Management}
+*/
+
+/*! \enum QSessionManager::RestartHint
+
+ This enum type defines the circumstances under which this
+ application wants to be restarted by the session manager. The
+ current values are
+
+ \value RestartIfRunning if the application is still running when
+ the session is shut down, it wants to be restarted at the start of
+ the next session.
+
+ \value RestartAnyway the application wants to be started at the
+ start of the next session, no matter what. (This is useful for
+ utilities that run just after startup and then quit.)
+
+ \value RestartImmediately the application wants to be started
+ immediately whenever it is not running.
+
+ \value RestartNever the application does not want to be restarted
+ automatically.
+
+ The default hint is \c RestartIfRunning.
+*/
+
+
+/*!
+ \fn QString QSessionManager::sessionId() const
+
+ Returns the identifier of the current session.
+
+ If the application has been restored from an earlier session, this
+ identifier is the same as it was in that earlier session.
+
+ \sa sessionKey(), QApplication::sessionId()
+ */
+
+/*!
+ \fn QString QSessionManager::sessionKey() const
+
+ Returns the session key in the current session.
+
+ If the application has been restored from an earlier session, this
+ key is the same as it was when the previous session ended.
+
+ The session key changes with every call of commitData() or
+ saveState().
+
+ \sa sessionId(), QApplication::sessionKey()
+ */
+
+/*!
+ \fn void* QSessionManager::handle() const
+
+ \internal
+*/
+
+/*!
+ \fn bool QSessionManager::allowsInteraction()
+
+ Asks the session manager for permission to interact with the
+ user. Returns true if interaction is permitted; otherwise
+ returns false.
+
+ The rationale behind this mechanism is to make it possible to
+ synchronize user interaction during a shutdown. Advanced session
+ managers may ask all applications simultaneously to commit their
+ data, resulting in a much faster shutdown.
+
+ When the interaction is completed we strongly recommend releasing the
+ user interaction semaphore with a call to release(). This way, other
+ applications may get the chance to interact with the user while your
+ application is still busy saving data. (The semaphore is implicitly
+ released when the application exits.)
+
+ If the user decides to cancel the shutdown process during the
+ interaction phase, you must tell the session manager that this has
+ happened by calling cancel().
+
+ Here's an example of how an application's QApplication::commitData()
+ might be implemented:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 8
+
+ If an error occurred within the application while saving its data,
+ you may want to try allowsErrorInteraction() instead.
+
+ \sa QApplication::commitData(), release(), cancel()
+*/
+
+
+/*!
+ \fn bool QSessionManager::allowsErrorInteraction()
+
+ Returns true if error interaction is permitted; otherwise returns false.
+
+ This is similar to allowsInteraction(), but also enables the application
+ to tell the user about any errors that occur. Session managers
+ may give error interaction requests higher priority, which means that it
+ is more likely that an error interaction is permitted. However, you are
+ still not guaranteed that the session manager will allow interaction.
+
+ \sa allowsInteraction(), release(), cancel()
+*/
+
+/*!
+ \fn void QSessionManager::release()
+
+ Releases the session manager's interaction semaphore after an
+ interaction phase.
+
+ \sa allowsInteraction(), allowsErrorInteraction()
+*/
+
+/*!
+ \fn void QSessionManager::cancel()
+
+ Tells the session manager to cancel the shutdown process. Applications
+ should not call this function without first asking the user.
+
+ \sa allowsInteraction(), allowsErrorInteraction()
+
+*/
+
+/*!
+ \fn void QSessionManager::setRestartHint(RestartHint hint)
+
+ Sets the application's restart hint to \a hint. On application
+ startup the hint is set to \c RestartIfRunning.
+
+ Note that these flags are only hints, a session manager may or may
+ not respect them.
+
+ We recommend setting the restart hint in QApplication::saveState()
+ because most session managers perform a checkpoint shortly after an
+ application's startup.
+
+ \sa restartHint()
+*/
+
+/*!
+ \fn QSessionManager::RestartHint QSessionManager::restartHint() const
+
+ Returns the application's current restart hint. The default is
+ \c RestartIfRunning.
+
+ \sa setRestartHint()
+*/
+
+/*!
+ \fn void QSessionManager::setRestartCommand(const QStringList& command)
+
+ If the session manager is capable of restoring sessions it will
+ execute \a command in order to restore the application. The command
+ defaults to
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 9
+
+ The \c -session option is mandatory; otherwise QApplication cannot
+ tell whether it has been restored or what the current session
+ identifier is. See QApplication::isSessionRestored() and
+ QApplication::sessionId() for details.
+
+ If your application is very simple, it may be possible to store the
+ entire application state in additional command line options. This
+ is usually a very bad idea because command lines are often limited
+ to a few hundred bytes. Instead, use QSettings, or temporary files
+ or a database for this purpose. By marking the data with the unique
+ sessionId(), you will be able to restore the application in a future
+ session.
+
+ \sa restartCommand(), setDiscardCommand(), setRestartHint()
+*/
+
+/*!
+ \fn QStringList QSessionManager::restartCommand() const
+
+ Returns the currently set restart command.
+
+ To iterate over the list, you can use the \l foreach
+ pseudo-keyword:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 10
+
+ \sa setRestartCommand(), restartHint()
+*/
+
+/*!
+ \fn void QSessionManager::setDiscardCommand(const QStringList& list)
+
+ Sets the discard command to the given \a list.
+
+ \sa discardCommand(), setRestartCommand()
+*/
+
+
+/*!
+ \fn QStringList QSessionManager::discardCommand() const
+
+ Returns the currently set discard command.
+
+ To iterate over the list, you can use the \l foreach
+ pseudo-keyword:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 11
+
+ \sa setDiscardCommand(), restartCommand(), setRestartCommand()
+*/
+
+/*!
+ \fn void QSessionManager::setManagerProperty(const QString &name, const QString &value)
+ \overload
+
+ Low-level write access to the application's identification and state
+ records are kept in the session manager.
+
+ The property called \a name has its value set to the string \a value.
+*/
+
+/*!
+ \fn void QSessionManager::setManagerProperty(const QString& name,
+ const QStringList& value)
+
+ Low-level write access to the application's identification and state
+ record are kept in the session manager.
+
+ The property called \a name has its value set to the string list \a value.
+*/
+
+/*!
+ \fn bool QSessionManager::isPhase2() const
+
+ Returns true if the session manager is currently performing a second
+ session management phase; otherwise returns false.
+
+ \sa requestPhase2()
+*/
+
+/*!
+ \fn void QSessionManager::requestPhase2()
+
+ Requests a second session management phase for the application. The
+ application may then return immediately from the
+ QApplication::commitData() or QApplication::saveState() function,
+ and they will be called again once most or all other applications have
+ finished their session management.
+
+ The two phases are useful for applications such as the X11 window manager
+ that need to store information about another application's windows
+ and therefore have to wait until these applications have completed their
+ respective session management tasks.
+
+ Note that if another application has requested a second phase it
+ may get called before, simultaneously with, or after your
+ application's second phase.
+
+ \sa isPhase2()
+*/
+
+/*****************************************************************************
+ Stubbed session management support
+ *****************************************************************************/
+#ifndef QT_NO_SESSIONMANAGER
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+
+#if defined(Q_OS_WINCE)
+HRESULT qt_CoCreateGuid(GUID* guid)
+{
+ // We will use the following information to create the GUID
+ // 1. absolute path to application
+ wchar_t tempFilename[512];
+ if (!GetModuleFileNameW(0, tempFilename, 512))
+ return S_FALSE;
+ unsigned int hash = qHash(QString::fromUtf16((const unsigned short *) tempFilename));
+ guid->Data1 = hash;
+ // 2. creation time of file
+ QFileInfo info(QString::fromUtf16((const unsigned short *) tempFilename));
+ guid->Data2 = qHash(info.created().toTime_t());
+ // 3. current system time
+ guid->Data3 = qHash(QDateTime::currentDateTime().toTime_t());
+ return S_OK;
+}
+#if !defined(OLE32_MCOMGUID) || defined(QT_WINCE_FORCE_CREATE_GUID)
+#define CoCreateGuid qt_CoCreateGuid
+#endif
+
+#endif
+
+class QSessionManagerPrivate : public QObjectPrivate
+{
+public:
+ QStringList restartCommand;
+ QStringList discardCommand;
+ QString sessionId;
+ QString sessionKey;
+ QSessionManager::RestartHint restartHint;
+};
+
+QSessionManager* qt_session_manager_self = 0;
+QSessionManager::QSessionManager(QApplication * app, QString &id, QString &key)
+ : QObject(*new QSessionManagerPrivate, app)
+{
+ Q_D(QSessionManager);
+ setObjectName(QLatin1String("qt_sessionmanager"));
+ qt_session_manager_self = this;
+#if defined(Q_WS_WIN)
+ wchar_t guidstr[40];
+ GUID guid;
+ CoCreateGuid(&guid);
+ StringFromGUID2(guid, guidstr, 40);
+ id = QString::fromUtf16((ushort*)guidstr);
+ CoCreateGuid(&guid);
+ StringFromGUID2(guid, guidstr, 40);
+ key = QString::fromUtf16((ushort*)guidstr);
+#endif
+ d->sessionId = id;
+ d->sessionKey = key;
+ d->restartHint = RestartIfRunning;
+}
+
+QSessionManager::~QSessionManager()
+{
+ qt_session_manager_self = 0;
+}
+
+QString QSessionManager::sessionId() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionId;
+}
+
+QString QSessionManager::sessionKey() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionKey;
+}
+
+
+#if defined(Q_WS_X11) || defined(Q_WS_MAC)
+void* QSessionManager::handle() const
+{
+ return 0;
+}
+#endif
+
+#if !defined(Q_WS_WIN)
+bool QSessionManager::allowsInteraction()
+{
+ return true;
+}
+
+bool QSessionManager::allowsErrorInteraction()
+{
+ return true;
+}
+void QSessionManager::release()
+{
+}
+
+void QSessionManager::cancel()
+{
+}
+#endif
+
+
+void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
+{
+ Q_D(QSessionManager);
+ d->restartHint = hint;
+}
+
+QSessionManager::RestartHint QSessionManager::restartHint() const
+{
+ Q_D(const QSessionManager);
+ return d->restartHint;
+}
+
+void QSessionManager::setRestartCommand(const QStringList& command)
+{
+ Q_D(QSessionManager);
+ d->restartCommand = command;
+}
+
+QStringList QSessionManager::restartCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->restartCommand;
+}
+
+void QSessionManager::setDiscardCommand(const QStringList& command)
+{
+ Q_D(QSessionManager);
+ d->discardCommand = command;
+}
+
+QStringList QSessionManager::discardCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->discardCommand;
+}
+
+void QSessionManager::setManagerProperty(const QString&, const QString&)
+{
+}
+
+void QSessionManager::setManagerProperty(const QString&, const QStringList&)
+{
+}
+
+bool QSessionManager::isPhase2() const
+{
+ return false;
+}
+
+void QSessionManager::requestPhase2()
+{
+}
+
+#endif
+#endif // QT_NO_SESSIONMANAGER
+
+/*!
+ \typedef QApplication::ColorMode
+ \compat
+
+ Use ColorSpec instead.
+*/
+
+/*!
+ \fn Qt::MacintoshVersion QApplication::macVersion()
+
+ Use QSysInfo::MacintoshVersion instead.
+*/
+
+/*!
+ \fn QApplication::ColorMode QApplication::colorMode()
+
+ Use colorSpec() instead, and use ColorSpec as the enum type.
+*/
+
+/*!
+ \fn void QApplication::setColorMode(ColorMode mode)
+
+ Use setColorSpec() instead, and pass a ColorSpec value instead.
+*/
+
+/*!
+ \fn bool QApplication::hasGlobalMouseTracking()
+
+ This feature does not exist anymore. This function
+ always returns true in Qt 4.
+*/
+
+/*!
+ \fn void QApplication::setGlobalMouseTracking(bool dummy)
+
+ This function does nothing in Qt 4. The \a dummy parameter
+ is ignored.
+*/
+
+/*!
+ \fn void QApplication::flushX()
+
+ Use flush() instead.
+*/
+
+/*!
+ \fn void QApplication::setWinStyleHighlightColor(const QColor &c)
+
+ Use the palette instead.
+
+ \oldcode
+ app.setWinStyleHighlightColor(color);
+ \newcode
+ QPalette palette(qApp->palette());
+ palette.setColor(QPalette::Highlight, color);
+ qApp->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QApplication::setPalette(const QPalette &pal, bool b, const char* className = 0)
+
+ Use the two-argument overload instead.
+*/
+
+/*!
+ \fn void QApplication::setFont(const QFont &font, bool b, const char* className = 0)
+
+ Use the two-argument overload instead.
+*/
+
+/*!
+ \fn const QColor &QApplication::winStyleHighlightColor()
+
+ Use qApp->palette().color(QPalette::Active, QPalette::Highlight)
+ instead.
+*/
+
+/*!
+ \fn QWidget *QApplication::widgetAt(int x, int y, bool child)
+
+ Use the two-argument widgetAt() overload to get the child widget.
+ To get the top-level widget do this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 12
+*/
+
+/*!
+ \fn QWidget *QApplication::widgetAt(const QPoint &point, bool child)
+
+ Use the single-argument widgetAt() overload to get the child widget.
+ To get the top-level widget do this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication.cpp 13
+*/
+
+#ifdef QT3_SUPPORT
+QWidget *QApplication::mainWidget()
+{
+ return QApplicationPrivate::main_widget;
+}
+#endif
+bool QApplicationPrivate::inPopupMode() const
+{
+ return QApplicationPrivate::popupWidgets != 0;
+}
+
+/*!
+ \property QApplication::quitOnLastWindowClosed
+
+ \brief whether the application implicitly quits when the last window is
+ closed.
+
+ The default is true.
+
+ If this property is true, the applications quits when the last visible
+ primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose
+ attribute set is closed. By default this attribute is set for all widgets
+ except for sub-windows. Refer to \l{Qt::WindowType} for a detailed list of
+ Qt::Window objects.
+
+ \sa quit(), QWidget::close()
+ */
+
+void QApplication::setQuitOnLastWindowClosed(bool quit)
+{
+ QApplicationPrivate::quitOnLastWindowClosed = quit;
+}
+
+bool QApplication::quitOnLastWindowClosed()
+{
+ return QApplicationPrivate::quitOnLastWindowClosed;
+}
+
+void QApplicationPrivate::emitLastWindowClosed()
+{
+ if (qApp && qApp->d_func()->in_exec) {
+ if (QApplicationPrivate::quitOnLastWindowClosed) {
+ // get ready to quit, this event might be removed if the
+ // event loop is re-entered, however
+ QApplication::postEvent(qApp, new QEvent(QEvent::Quit));
+ }
+ emit qApp->lastWindowClosed();
+ }
+}
+
+/*! \variable QApplication::NormalColors
+ \compat
+
+ Use \l NormalColor instead.
+*/
+
+/*! \variable QApplication::CustomColors
+ \compat
+
+ Use \l CustomColor instead.
+*/
+
+#ifdef QT_KEYPAD_NAVIGATION
+/*!
+ Sets whether Qt should use focus navigation suitable for use with a
+ minimal keypad.
+
+ If \a enable is true, Qt::Key_Up and Qt::Key_Down are used to
+ change focus.
+
+ This feature is only available in Qt for Embedded Linux.
+
+ \sa keypadNavigationEnabled()
+*/
+void QApplication::setKeypadNavigationEnabled(bool enable)
+{
+ QApplicationPrivate::keypadNavigation = enable;
+}
+
+/*!
+ Returns true if Qt is set to use keypad navigation; otherwise returns
+ false. The default is false.
+
+ This feature is only available in Qt for Embedded Linux.
+ \sa setKeypadNavigationEnabled()
+*/
+bool QApplication::keypadNavigationEnabled()
+{
+ return QApplicationPrivate::keypadNavigation;
+}
+#endif
+
+/*!
+ \fn void QApplication::alert(QWidget *widget, int msec)
+ \since 4.3
+
+ Causes an alert to be shown for \a widget if the window is not the active
+ window. The alert is shown for \a msec miliseconds. If \a msec is zero (the
+ default), then the alert is shown indefinitely until the window becomes
+ active again.
+
+ Currently this function does nothing on Qt for Embedded Linux.
+
+ On Mac OS X, this works more at the application level and will cause the
+ application icon to bounce in the dock.
+
+ On Windows this causes the window's taskbar entry to flash for a time. If \a
+ msec is zero, the flashing will stop and the taskbar entry will turn a
+ different color (currently orange).
+
+ On X11, this will cause the window to be marked as "demands attention",
+ the window must not be hidden (i.e. not have hide() called on it, but be
+ visible in some sort of way) in order for this to work.
+*/
+
+/*!
+ \property QApplication::cursorFlashTime
+ \brief the text cursor's flash (blink) time in milliseconds
+
+ The flash time is the time required to display, invert and
+ restore the caret display. Usually the text cursor is displayed
+ for half the cursor flash time, then hidden for the same amount
+ of time, but this may vary.
+
+ The default value on X11 is 1000 milliseconds. On Windows, the
+ control panel value is used. Widgets should not cache this value
+ since it may be changed at any time by the user changing the
+ global desktop settings.
+
+ Note that on Microsoft Windows, setting this property sets the
+ cursor flash time for all applications.
+*/
+
+/*!
+ \property QApplication::doubleClickInterval
+ \brief the time limit in milliseconds that distinguishes a double click from two
+ consecutive mouse clicks
+
+ The default value on X11 is 400 milliseconds. On Windows and Mac
+ OS X, the operating system's value is used.
+
+ On Microsoft Windows, calling this function sets the
+ double click interval for all applications.
+*/
+
+/*!
+ \property QApplication::keyboardInputInterval
+ \brief the time limit in milliseconds that distinguishes a key press
+ from two consecutive key presses
+ \since 4.2
+
+ The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the
+ operating system's value is used.
+*/
+
+/*!
+ \property QApplication::wheelScrollLines
+ \brief the number of lines to scroll a widget, when the
+ mouse wheel is rotated.
+
+ If the value exceeds the widget's number of visible lines, the
+ widget should interpret the scroll operation as a single \e{page
+ up} or \e{page down}. If the widget is an \l{QAbstractItemView}
+ {item view class}, then the result of scrolling one \e line
+ depends on the setting of the widget's
+ \l{QAbstractItemView::verticalScrollMode()} {scroll mode}. Scroll
+ one \e line can mean \l{QAbstractItemView::ScrollPerItem} {scroll
+ one item} or \l{QAbstractItemView::ScrollPerPixel} {scroll one
+ pixel}.
+
+ By default, this property has a value of 3.
+*/
+
+/*!
+ \fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+
+ Enables the UI effect \a effect if \a enable is true, otherwise
+ the effect will not be used.
+
+ Note: All effects are disabled on screens running at less than
+ 16-bit color depth.
+
+ \sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
+*/
+
+/*!
+ \fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+
+ Returns true if \a effect is enabled; otherwise returns false.
+
+ By default, Qt will try to use the desktop settings. Call
+ setDesktopSettingsAware(false) to prevent this.
+
+ Note: All effects are disabled on screens running at less than
+ 16-bit color depth.
+
+ \sa setEffectEnabled(), Qt::UIEffect
+*/
+
+/*!
+ \fn QWidget *QApplication::mainWidget()
+
+ Returns the main application widget, or 0 if there is no main
+ widget.
+*/
+
+/*!
+ \fn void QApplication::setMainWidget(QWidget *mainWidget)
+
+ Sets the application's main widget to \a mainWidget.
+
+ In most respects the main widget is like any other widget, except
+ that if it is closed, the application exits. Note that
+ QApplication does \e not take ownership of the \a mainWidget, so
+ if you create your main widget on the heap you must delete it
+ yourself.
+
+ You need not have a main widget; connecting lastWindowClosed() to
+ quit() is an alternative.
+
+ For X11, this function also resizes and moves the main widget
+ according to the \e -geometry command-line option, so you should
+ set the default geometry (using \l QWidget::setGeometry()) before
+ calling setMainWidget().
+
+ \sa mainWidget(), exec(), quit()
+*/
+
+/*!
+ \fn void QApplication::beep()
+
+ Sounds the bell, using the default volume and sound. The function
+ is \e not available in Qt for Embedded Linux.
+*/
+
+/*!
+ \fn void QApplication::setOverrideCursor(const QCursor &cursor)
+
+ Sets the application override cursor to \a cursor.
+
+ Application override cursors are intended for showing the user
+ that the application is in a special state, for example during an
+ operation that might take some time.
+
+ This cursor will be displayed in all the application's widgets
+ until restoreOverrideCursor() or another setOverrideCursor() is
+ called.
+
+ Application cursors are stored on an internal stack.
+ setOverrideCursor() pushes the cursor onto the stack, and
+ restoreOverrideCursor() pops the active cursor off the
+ stack. changeOverrideCursor() changes the curently active
+ application override cursor. Every setOverrideCursor() must
+ eventually be followed by a corresponding restoreOverrideCursor(),
+ otherwise the stack will never be emptied.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qapplication_x11.cpp 0
+
+ \sa overrideCursor() restoreOverrideCursor() changeOverrideCursor() QWidget::setCursor()
+*/
+
+/*!
+ \fn void QApplication::restoreOverrideCursor()
+
+ Undoes the last setOverrideCursor().
+
+ If setOverrideCursor() has been called twice, calling
+ restoreOverrideCursor() will activate the first cursor set.
+ Calling this function a second time restores the original widgets'
+ cursors.
+
+ \sa setOverrideCursor(), overrideCursor()
+*/
+
+/*!
+ \macro qApp
+ \relates QApplication
+
+ A global pointer referring to the unique application object. It is
+ equivalent to the pointer returned by the
+ QCoreApplication::instance() function except that, in GUI applications,
+ it is a pointer to a QApplication instance.
+
+ Only one application object can be created.
+
+ \sa QCoreApplication::instance()
+*/
+
+// ************************************************************************
+// Input Method support
+// ************************************************************************
+
+/*!
+ This function replaces the QInputContext instance used by the
+ application with \a inputContext.
+
+ \sa inputContext()
+*/
+void QApplication::setInputContext(QInputContext *inputContext)
+{
+ Q_D(QApplication);
+ Q_UNUSED(d);// only static members being used.
+ if (!inputContext) {
+ qWarning("QApplication::setInputContext: called with 0 input context");
+ return;
+ }
+ if (d->inputContext)
+ delete d->inputContext;
+ d->inputContext = inputContext;
+}
+
+/*!
+ Returns the QInputContext instance used by the application.
+
+ \sa setInputContext()
+*/
+QInputContext *QApplication::inputContext() const
+{
+ Q_D(const QApplication);
+ Q_UNUSED(d);// only static members being used.
+#ifdef Q_WS_X11
+ if (!X11)
+ return 0;
+ if (!d->inputContext) {
+ QApplication *that = const_cast<QApplication *>(this);
+ QInputContext *qic = QInputContextFactory::create(X11->default_im, that);
+ // fallback to default X Input Method.
+ if (!qic)
+ qic = QInputContextFactory::create(QLatin1String("xim"), that);
+ that->d_func()->inputContext = qic;
+ }
+#endif
+ return d->inputContext;
+}
+
+//Returns the current platform used by keyBindings
+uint QApplicationPrivate::currentPlatform(){
+ uint platform = KB_Win;
+#ifdef Q_WS_MAC
+ platform = KB_Mac;
+#elif defined Q_WS_X11
+ platform = KB_X11;
+ if (X11->desktopEnvironment == DE_KDE)
+ platform |= KB_KDE;
+ if (X11->desktopEnvironment == DE_GNOME)
+ platform |= KB_Gnome;
+ if (X11->desktopEnvironment == DE_CDE)
+ platform |= KB_CDE;
+#endif
+ return platform;
+}
+
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{
+ return QCoreApplication::sendSpontaneousEvent(receiver, event);
+}
+
+
+/*!
+ \since 4.2
+
+ Returns the current keyboard input locale.
+*/
+QLocale QApplication::keyboardInputLocale()
+{
+ if (!QApplicationPrivate::checkInstance("keyboardInputLocale"))
+ return QLocale::c();
+ return qt_keymapper_private()->keyboardInputLocale;
+}
+
+/*!
+ \since 4.2
+
+ Returns the current keyboard input direction.
+*/
+Qt::LayoutDirection QApplication::keyboardInputDirection()
+{
+ if (!QApplicationPrivate::checkInstance("keyboardInputDirection"))
+ return Qt::LeftToRight;
+ return qt_keymapper_private()->keyboardInputDirection;
+}
+
+bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
+{
+ QWidget *f = w;
+ while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
+ f = f->d_func()->extra->focus_proxy;
+
+ if ((w->focusPolicy() & policy) != policy)
+ return false;
+ if (w != f && (f->focusPolicy() & policy) != policy)
+ return false;
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
new file mode 100644
index 0000000000..1d6941d5fc
--- /dev/null
+++ b/src/gui/kernel/qapplication.h
@@ -0,0 +1,391 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAPPLICATION_H
+#define QAPPLICATION_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+#include <QtGui/qcursor.h>
+#ifdef QT_INCLUDE_COMPAT
+# include <QtGui/qdesktopwidget.h>
+#endif
+#ifdef QT3_SUPPORT
+# include <QtGui/qwidget.h>
+# include <QtGui/qpalette.h>
+#endif
+#ifdef Q_WS_QWS
+# include <QtGui/qrgb.h>
+# include <QtGui/qtransportauth_qws.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QSessionManager;
+class QDesktopWidget;
+class QStyle;
+class QEventLoop;
+class QIcon;
+class QInputContext;
+template <typename T> class QList;
+class QLocale;
+#if defined(Q_WS_QWS)
+class QDecoration;
+#endif
+
+class QApplication;
+class QApplicationPrivate;
+#if defined(qApp)
+#undef qApp
+#endif
+#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
+
+class Q_GUI_EXPORT QApplication : public QCoreApplication
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection)
+ Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon)
+ Q_PROPERTY(int cursorFlashTime READ cursorFlashTime WRITE setCursorFlashTime)
+ Q_PROPERTY(int doubleClickInterval READ doubleClickInterval WRITE setDoubleClickInterval)
+ Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval WRITE setKeyboardInputInterval)
+#ifndef QT_NO_WHEELEVENT
+ Q_PROPERTY(int wheelScrollLines READ wheelScrollLines WRITE setWheelScrollLines)
+#endif
+ Q_PROPERTY(QSize globalStrut READ globalStrut WRITE setGlobalStrut)
+ Q_PROPERTY(int startDragTime READ startDragTime WRITE setStartDragTime)
+ Q_PROPERTY(int startDragDistance READ startDragDistance WRITE setStartDragDistance)
+ Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed)
+#ifndef QT_NO_STYLE_STYLESHEET
+ Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
+#endif
+#ifdef Q_OS_WINCE
+ Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold)
+ Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
+#endif
+
+public:
+ enum Type { Tty, GuiClient, GuiServer };
+#ifndef qdoc
+ QApplication(int &argc, char **argv, int = QT_VERSION);
+ QApplication(int &argc, char **argv, bool GUIenabled, int = QT_VERSION);
+ QApplication(int &argc, char **argv, Type, int = QT_VERSION);
+#if defined(Q_WS_X11)
+ QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = QT_VERSION);
+ QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = QT_VERSION);
+#endif
+#endif
+ virtual ~QApplication();
+
+ static Type type();
+
+ static QStyle *style();
+ static void setStyle(QStyle*);
+ static QStyle *setStyle(const QString&);
+ enum ColorSpec { NormalColor=0, CustomColor=1, ManyColor=2 };
+ static int colorSpec();
+ static void setColorSpec(int);
+ static void setGraphicsSystem(const QString &);
+
+#ifndef QT_NO_CURSOR
+ static QCursor *overrideCursor();
+ static void setOverrideCursor(const QCursor &);
+ static void changeOverrideCursor(const QCursor &);
+ static void restoreOverrideCursor();
+#endif
+ static QPalette palette();
+ static QPalette palette(const QWidget *);
+ static QPalette palette(const char *className);
+ static void setPalette(const QPalette &, const char* className = 0);
+ static QFont font();
+ static QFont font(const QWidget*);
+ static QFont font(const char *className);
+ static void setFont(const QFont &, const char* className = 0);
+ static QFontMetrics fontMetrics();
+
+ static void setWindowIcon(const QIcon &icon);
+ static QIcon windowIcon();
+
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QWidget *mainWidget();
+ static QT3_SUPPORT void setMainWidget(QWidget *);
+#endif
+
+ static QWidgetList allWidgets();
+ static QWidgetList topLevelWidgets();
+
+ static QDesktopWidget *desktop();
+
+ static QWidget *activePopupWidget();
+ static QWidget *activeModalWidget();
+#ifndef QT_NO_CLIPBOARD
+ static QClipboard *clipboard();
+#endif
+ static QWidget *focusWidget();
+
+ static QWidget *activeWindow();
+ static void setActiveWindow(QWidget* act);
+
+ static QWidget *widgetAt(const QPoint &p);
+ static inline QWidget *widgetAt(int x, int y) { return widgetAt(QPoint(x, y)); }
+ static QWidget *topLevelAt(const QPoint &p);
+ static inline QWidget *topLevelAt(int x, int y) { return topLevelAt(QPoint(x, y)); }
+
+ static void syncX();
+ static void beep();
+ static void alert(QWidget *widget, int duration = 0);
+
+ static Qt::KeyboardModifiers keyboardModifiers();
+ static Qt::MouseButtons mouseButtons();
+
+ static void setDesktopSettingsAware(bool);
+ static bool desktopSettingsAware();
+
+ static void setCursorFlashTime(int);
+ static int cursorFlashTime();
+
+ static void setDoubleClickInterval(int);
+ static int doubleClickInterval();
+
+ static void setKeyboardInputInterval(int);
+ static int keyboardInputInterval();
+
+#ifndef QT_NO_WHEELEVENT
+ static void setWheelScrollLines(int);
+ static int wheelScrollLines();
+#endif
+ static void setGlobalStrut(const QSize &);
+ static QSize globalStrut();
+
+ static void setStartDragTime(int ms);
+ static int startDragTime();
+ static void setStartDragDistance(int l);
+ static int startDragDistance();
+
+ static void setLayoutDirection(Qt::LayoutDirection direction);
+ static Qt::LayoutDirection layoutDirection();
+
+ static inline bool isRightToLeft() { return layoutDirection() == Qt::RightToLeft; }
+ static inline bool isLeftToRight() { return layoutDirection() == Qt::LeftToRight; }
+
+ static bool isEffectEnabled(Qt::UIEffect);
+ static void setEffectEnabled(Qt::UIEffect, bool enable = true);
+
+#if defined(Q_WS_MAC)
+ virtual bool macEventFilter(EventHandlerCallRef, EventRef);
+#endif
+#if defined(Q_WS_X11)
+ virtual bool x11EventFilter(XEvent *);
+ virtual int x11ClientMessage(QWidget*, XEvent*, bool passive_only);
+ int x11ProcessEvent(XEvent*);
+#endif
+#if defined(Q_WS_QWS)
+ virtual bool qwsEventFilter(QWSEvent *);
+ int qwsProcessEvent(QWSEvent*);
+ void qwsSetCustomColors(QRgb *colortable, int start, int numColors);
+#ifndef QT_NO_QWS_MANAGER
+ static QDecoration &qwsDecoration();
+ static void qwsSetDecoration(QDecoration *);
+ static QDecoration *qwsSetDecoration(const QString &decoration);
+#endif
+#endif
+
+
+#if defined(Q_WS_WIN)
+ void winFocus(QWidget *, bool);
+ static void winMouseButtonUp();
+#endif
+
+#ifndef QT_NO_SESSIONMANAGER
+ // session management
+ bool isSessionRestored() const;
+ QString sessionId() const;
+ QString sessionKey() const;
+ virtual void commitData(QSessionManager& sm);
+ virtual void saveState(QSessionManager& sm);
+#endif
+ void setInputContext(QInputContext *);
+ QInputContext *inputContext() const;
+
+ static QLocale keyboardInputLocale();
+ static Qt::LayoutDirection keyboardInputDirection();
+
+ static int exec();
+ bool notify(QObject *, QEvent *);
+
+
+ static void setQuitOnLastWindowClosed(bool quit);
+ static bool quitOnLastWindowClosed();
+
+#ifdef QT_KEYPAD_NAVIGATION
+ static void setKeypadNavigationEnabled(bool);
+ static bool keypadNavigationEnabled();
+#endif
+
+Q_SIGNALS:
+ void lastWindowClosed();
+ void focusChanged(QWidget *old, QWidget *now);
+ void fontDatabaseChanged();
+#ifndef QT_NO_SESSIONMANAGER
+ void commitDataRequest(QSessionManager &sessionManager);
+ void saveStateRequest(QSessionManager &sessionManager);
+#endif
+
+public:
+ QString styleSheet() const;
+public Q_SLOTS:
+#ifndef QT_NO_STYLE_STYLESHEET
+ void setStyleSheet(const QString& sheet);
+#endif
+#ifdef Q_OS_WINCE
+ void setAutoMaximizeThreshold(const int threshold);
+ int autoMaximizeThreshold() const;
+ void setAutoSipEnabled(const bool enabled);
+ bool autoSipEnabled() const;
+#endif
+ static void closeAllWindows();
+ static void aboutQt();
+
+protected:
+#if defined(Q_WS_QWS)
+ void setArgs(int, char **);
+#endif
+ bool event(QEvent *);
+ bool compressEvent(QEvent *, QObject *receiver, QPostEventList *);
+
+#ifdef QT3_SUPPORT
+public:
+ static inline QT3_SUPPORT void setReverseLayout(bool b) { setLayoutDirection(b?Qt::RightToLeft:Qt::LeftToRight); }
+ static inline bool QT3_SUPPORT reverseLayout() { return layoutDirection() == Qt::RightToLeft; }
+ static QT3_SUPPORT Qt::Alignment horizontalAlignment(Qt::Alignment align);
+ typedef int ColorMode;
+ enum { NormalColors = NormalColor, CustomColors = CustomColor };
+ static inline QT3_SUPPORT ColorMode colorMode() { return static_cast<ColorMode>(colorSpec()); }
+ static inline QT3_SUPPORT void setColorMode(ColorMode mode) { setColorSpec(int(mode)); }
+#if defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN)
+ static QT3_SUPPORT Qt::WindowsVersion winVersion() { return (Qt::WindowsVersion)QSysInfo::WindowsVersion; }
+#endif
+#if defined(Q_OS_MAC)
+ static QT3_SUPPORT Qt::MacintoshVersion macVersion() { return (Qt::MacintoshVersion)QSysInfo::MacintoshVersion; }
+#endif
+# ifndef QT_NO_CURSOR
+ inline static QT3_SUPPORT void setOverrideCursor(const QCursor &cursor, bool replace)
+ { if (replace) changeOverrideCursor(cursor); else setOverrideCursor(cursor); }
+# endif
+ inline static QT3_SUPPORT bool hasGlobalMouseTracking() {return true;}
+ inline static QT3_SUPPORT void setGlobalMouseTracking(bool) {};
+ inline static QT3_SUPPORT void flushX() { flush(); }
+ static inline QT3_SUPPORT void setWinStyleHighlightColor(const QColor &c) {
+ QPalette p(palette());
+ p.setColor(QPalette::Highlight, c);
+ setPalette(p);
+ }
+ static inline QT3_SUPPORT const QColor &winStyleHighlightColor()
+ { return palette().color(QPalette::Active, QPalette::Highlight); }
+ static inline QT3_SUPPORT void setPalette(const QPalette &pal, bool, const char* className = 0)
+ { setPalette(pal, className); };
+ static inline QT3_SUPPORT void setFont(const QFont &font, bool, const char* className = 0)
+ { setFont(font, className); }
+
+ static inline QT3_SUPPORT QWidget *widgetAt(int x, int y, bool child)
+ { QWidget *w = widgetAt(x, y); return child ? w : (w ? w->window() : 0); }
+ static inline QT3_SUPPORT QWidget *widgetAt(const QPoint &p, bool child)
+ { QWidget *w = widgetAt(p); return child ? w : (w ? w->window() : 0); }
+#endif // QT3_SUPPORT
+
+#if defined(Q_INTERNAL_QAPP_SRC) || defined(qdoc)
+ QApplication(int &argc, char **argv);
+ QApplication(int &argc, char **argv, bool GUIenabled);
+ QApplication(int &argc, char **argv, Type);
+#if defined(Q_WS_X11)
+ QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0);
+ QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
+#endif
+#endif
+
+private:
+ Q_DISABLE_COPY(QApplication)
+ Q_DECLARE_PRIVATE(QApplication)
+
+ friend class QGraphicsWidget;
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+ friend class QETWidget;
+ friend class Q3AccelManager;
+ friend class QTranslator;
+ friend class QWidgetAnimator;
+#ifndef QT_NO_SHORTCUT
+ friend class QShortcut;
+ friend class QLineEdit;
+ friend class QTextControl;
+#endif
+ friend class QAction;
+ friend class QFontDatabasePrivate;
+
+#if defined(Q_WS_QWS)
+ friend class QInputContext;
+ friend class QWSDirectPainterSurface;
+ friend class QDirectPainter;
+ friend class QDirectPainterPrivate;
+#endif
+
+#if defined(Q_WS_WIN)
+ friend QApplicationPrivate* getQApplicationPrivateInternal();
+#endif
+
+#if defined(Q_WS_MAC) || defined(Q_WS_X11)
+ Q_PRIVATE_SLOT(d_func(), void _q_alertTimeOut())
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAPPLICATION_H
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
new file mode 100644
index 0000000000..5f8c572d94
--- /dev/null
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -0,0 +1,2976 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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 <Cocoa/Cocoa.h>
+
+#include "qapplication.h"
+#include "qbitarray.h"
+#include "qclipboard.h"
+#include "qcursor.h"
+#include "qdatastream.h"
+#include "qdatetime.h"
+#include "qdesktopwidget.h"
+#include "qdockwidget.h"
+#include "qevent.h"
+#include "qhash.h"
+#include "qlayout.h"
+#include "qmenubar.h"
+#include "qmessagebox.h"
+#include "qmime.h"
+#include "qpixmapcache.h"
+#include "qpointer.h"
+#include "qsessionmanager.h"
+#include "qsettings.h"
+#include "qsocketnotifier.h"
+#include "qstyle.h"
+#include "qstylefactory.h"
+#include "qtextcodec.h"
+#include "qtoolbar.h"
+#include "qvariant.h"
+#include "qwidget.h"
+#include "qcolormap.h"
+#include "qdir.h"
+#include "qdebug.h"
+#include "qtimer.h"
+#include "private/qmacinputcontext_p.h"
+#include "private/qpaintengine_mac_p.h"
+#include "private/qcursor_p.h"
+#include "private/qapplication_p.h"
+#include "private/qcolor_p.h"
+#include "private/qwidget_p.h"
+#include "private/qkeymapper_p.h"
+#include "private/qeventdispatcher_mac_p.h"
+#include "private/qeventdispatcher_unix_p.h"
+#include <private/qcocoamenuloader_mac_p.h>
+#include <private/qcocoaapplication_mac_p.h>
+#include <private/qcocoaapplicationdelegate_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qcocoawindow_mac_p.h>
+#include <private/qpixmap_mac_p.h>
+#include <private/qdesktopwidget_mac_p.h>
+#include <private/qeventdispatcher_mac_p.h>
+#include <qvarlengtharray.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
+
+#ifndef QT_NO_THREAD
+# include "qmutex.h"
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+/*****************************************************************************
+ QApplication debug facilities
+ *****************************************************************************/
+//#define DEBUG_EVENTS //like EventDebug but more specific to Qt
+//#define DEBUG_DROPPED_EVENTS
+//#define DEBUG_MOUSE_MAPS
+//#define DEBUG_MODAL_EVENTS
+//#define DEBUG_PLATFORM_SETTINGS
+
+#define QMAC_SPEAK_TO_ME
+#ifdef QMAC_SPEAK_TO_ME
+#include "qregexp.h"
+#endif
+
+#ifndef kThemeBrushAlternatePrimaryHighlightColor
+#define kThemeBrushAlternatePrimaryHighlightColor -5
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+//for qt_mac.h
+QPaintDevice *qt_mac_safe_pdev = 0;
+QList<QMacWindowChangeEvent*> *QMacWindowChangeEvent::change_events = 0;
+extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp
+
+/*****************************************************************************
+ Internal variables and functions
+ *****************************************************************************/
+static struct {
+ bool use_qt_time_limit;
+ QPointer<QWidget> last_widget;
+ int last_x, last_y;
+ int last_modifiers, last_button;
+ EventTime last_time;
+} qt_mac_dblclick = { false, 0, -1, -1, 0, 0, -2 };
+
+static bool app_do_modal = false; // modal mode
+extern QWidgetList *qt_modal_stack; // stack of modal widgets
+extern bool qt_tab_all_widgets; // from qapplication.cpp
+bool qt_mac_app_fullscreen = false;
+bool qt_scrollbar_jump_to_pos = false;
+static bool qt_mac_collapse_on_dblclick = true;
+extern int qt_antialiasing_threshold; // from qapplication.cpp
+QPointer<QWidget> qt_button_down; // widget got last button-down
+#ifndef QT_MAC_USE_COCOA
+static bool qt_button_down_in_content; // whether the button_down was in the content area.
+static bool qt_mac_previous_press_in_popup_mode = false;
+static bool qt_mac_no_click_through_mode = false;
+static int tablet_button_state = 0;
+#endif
+QPointer<QWidget> qt_mouseover;
+#if defined(QT_DEBUG)
+static bool appNoGrab = false; // mouse/keyboard grabbing
+#endif
+#ifndef QT_MAC_USE_COCOA
+static EventHandlerRef app_proc_handler = 0;
+static EventHandlerUPP app_proc_handlerUPP = 0;
+static AEEventHandlerUPP app_proc_ae_handlerUPP = NULL;
+#endif
+static EventHandlerRef tablet_proximity_handler = 0;
+static EventHandlerUPP tablet_proximity_UPP = 0;
+bool QApplicationPrivate::native_modal_dialog_active;
+
+/*****************************************************************************
+ External functions
+ *****************************************************************************/
+extern void qt_mac_beep(); //qsound_mac.mm
+extern Qt::KeyboardModifiers qt_mac_get_modifiers(int keys); //qkeymapper_mac.cpp
+extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
+extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
+extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.cpp
+extern QWidget *qt_mac_find_window(OSWindowRef); //qwidget_mac.cpp
+extern void qt_mac_set_cursor(const QCursor *, const QPoint &); //qcursor_mac.cpp
+extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp
+extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
+extern void qt_mac_command_set_enabled(MenuRef, UInt32, bool); //qmenu_mac.cpp
+extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); // qapplication.cpp
+
+// Forward Decls
+void onApplicationWindowChangedActivation( QWidget*widget, bool activated );
+void onApplicationChangedActivation( bool activated );
+
+Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret) {
+ OSStatus err;
+ AEDesc scriptTextDesc;
+ ComponentInstance theComponent = 0;
+ OSAID scriptID = kOSANullScript, resultID = kOSANullScript;
+
+ // set up locals to a known state
+ AECreateDesc(typeNull, 0, 0, &scriptTextDesc);
+ scriptID = kOSANullScript;
+ resultID = kOSANullScript;
+
+ // open the scripting component
+ theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
+ if (!theComponent) {
+ err = paramErr;
+ goto bail;
+ }
+
+ // put the script text into an aedesc
+ err = AECreateDesc(typeUTF8Text, script, script_len, &scriptTextDesc);
+ if (err != noErr)
+ goto bail;
+
+ // compile the script
+ err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID);
+ if (err != noErr)
+ goto bail;
+
+ // run the script
+ err = OSAExecute(theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID);
+
+ // collect the results - if any
+ if (ret) {
+ AECreateDesc(typeNull, 0, 0, ret);
+ if (err == errOSAScriptError)
+ OSAScriptError(theComponent, kOSAErrorMessage, typeChar, ret);
+ else if (err == noErr && resultID != kOSANullScript)
+ OSADisplay(theComponent, resultID, typeChar, kOSAModeNull, ret);
+ }
+bail:
+ AEDisposeDesc(&scriptTextDesc);
+ if (scriptID != kOSANullScript)
+ OSADispose(theComponent, scriptID);
+ if (resultID != kOSANullScript)
+ OSADispose(theComponent, resultID);
+ if (theComponent)
+ CloseComponent(theComponent);
+ return err == noErr;
+}
+
+Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, AEDesc *ret)
+{
+ return qt_mac_execute_apple_script(script, qstrlen(script), ret);
+}
+
+Q_GUI_EXPORT bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret)
+{
+ const QByteArray l = script.toUtf8(); return qt_mac_execute_apple_script(l.constData(), l.size(), ret);
+}
+
+/* Resolution change magic */
+void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags flags, void *)
+{
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+ const bool resized = flags & kCGDisplayDesktopShapeChangedFlag;
+#else
+ Q_UNUSED(flags);
+ const bool resized = true;
+#endif
+ if (resized && qApp) {
+ if (QDesktopWidget *dw = qApp->desktop()) {
+ QResizeEvent *re = new QResizeEvent(dw->size(), dw->size());
+ QApplication::postEvent(dw, re);
+ QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
+ }
+ }
+}
+
+#ifdef DEBUG_PLATFORM_SETTINGS
+static void qt_mac_debug_palette(const QPalette &pal, const QPalette &pal2, const QString &where)
+{
+ const char *const groups[] = {"Active", "Disabled", "Inactive" };
+ const char *const roles[] = { "WindowText", "Button", "Light", "Midlight", "Dark", "Mid",
+ "Text", "BrightText", "ButtonText", "Base", "Window", "Shadow",
+ "Highlight", "HighlightedText", "Link", "LinkVisited" };
+ if (!where.isNull())
+ qDebug("qt-internal: %s", where.toLatin1().constData());
+ for(int grp = 0; grp < QPalette::NColorGroups; grp++) {
+ for(int role = 0; role < QPalette::NColorRoles; role++) {
+ QBrush b = pal.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role);
+ QPixmap pm = b.texture();
+ qDebug(" %s::%s %d::%d::%d [%p]%s", groups[grp], roles[role], b.color().red(),
+ b.color().green(), b.color().blue(), pm.isNull() ? 0 : &pm,
+ pal2.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role) != b ? " (*)" : "");
+ }
+ }
+
+}
+#else
+#define qt_mac_debug_palette(x, y, z)
+#endif
+
+//raise a notification
+#ifndef QT_MAC_USE_COCOA
+static NMRec qt_mac_notification = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+void qt_mac_send_notification()
+{
+#ifndef QT_MAC_USE_COCOA
+ //send it
+ qt_mac_notification.nmMark = 1; //non-zero magic number
+ qt_mac_notification.qType = nmType;
+ NMInstall(&qt_mac_notification);
+#else
+ QMacCocoaAutoReleasePool pool;
+ [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
+#endif
+}
+
+void qt_mac_cancel_notification()
+{
+#ifndef QT_MAC_USE_COCOA
+ NMRemove(&qt_mac_notification);
+#else
+ QMacCocoaAutoReleasePool pool;
+ [[NSApplication sharedApplication] cancelUserAttentionRequest:NSInformationalRequest];
+#endif
+}
+
+#ifndef QT_MAC_USE_COCOA
+//find widget (and part) at a given point
+static short qt_mac_window_at(int x, int y, QWidget **w=0)
+{
+ Point p;
+ p.h = x;
+ p.v = y;
+ OSWindowRef wp;
+ WindowPartCode wpc;
+ OSStatus err = FindWindowOfClass(&p, kAllWindowClasses, &wp, &wpc);
+ if(err != noErr) {
+ if(w)
+ (*w) = 0;
+ return wpc;
+ }
+ if(w) {
+ if(wp) {
+ *w = qt_mac_find_window(wp);
+#if 0
+ if(!*w)
+ qWarning("QApplication: qt_mac_window_at: Couldn't find %d",(int)wp);
+#endif
+ } else {
+ *w = 0;
+ }
+ }
+ return wpc;
+}
+
+#endif
+
+void qt_mac_set_app_icon(const QPixmap &pixmap)
+{
+#ifndef QT_MAC_USE_COCOA
+ if(pixmap.isNull()) {
+ RestoreApplicationDockTileImage();
+ } else {
+ CGImageRef img = (CGImageRef)pixmap.macCGHandle();
+ SetApplicationDockTileImage(img);
+ CGImageRelease(img);
+ }
+#else
+ QMacCocoaAutoReleasePool pool;
+ NSImage *image = NULL;
+ if (pixmap.isNull()) {
+ // Get Application icon from bundle
+ image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; // released below
+ } else {
+ image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
+ }
+
+ [NSApp setApplicationIconImage:image];
+ [image release];
+#endif
+}
+
+Q_GUI_EXPORT void qt_mac_set_press_and_hold_context(bool b)
+{
+ Q_UNUSED(b);
+ qWarning("qt_mac_set_press_and_hold_context: This functionality is no longer available");
+}
+
+bool qt_nograb() // application no-grab option
+{
+#if defined(QT_DEBUG)
+ return appNoGrab;
+#else
+ return false;
+#endif
+}
+
+void qt_mac_update_os_settings()
+{
+ if (!qApp)
+ return;
+ if (!QApplication::startingUp()) {
+ static bool needToPolish = true;
+ if (needToPolish) {
+ QApplication::style()->polish(qApp);
+ needToPolish = false;
+ }
+ }
+ //focus mode
+ /* First worked as of 10.2.3 */
+ QSettings appleSettings(QLatin1String("apple.com"));
+ QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
+ qt_tab_all_widgets = (appleValue.toInt() & 0x2);
+ //paging mode
+ /* First worked as of 10.2.3 */
+ appleValue = appleSettings.value(QLatin1String("AppleScrollerPagingBehavior"), false);
+ qt_scrollbar_jump_to_pos = appleValue.toBool();
+ //collapse
+ /* First worked as of 10.3.3 */
+ appleValue = appleSettings.value(QLatin1String("AppleMiniaturizeOnDoubleClick"), true);
+ qt_mac_collapse_on_dblclick = appleValue.toBool();
+
+ // Anti-aliasing threshold
+ appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
+ if (appleValue.isValid())
+ qt_antialiasing_threshold = appleValue.toInt();
+
+#ifdef DEBUG_PLATFORM_SETTINGS
+ qDebug("qt_mac_update_os_settings *********************************************************************");
+#endif
+ { // setup the global palette
+ QColor qc;
+ (void) QApplication::style(); // trigger creation of application style and system palettes
+ QPalette pal = *QApplicationPrivate::sys_pal;
+
+ pal.setBrush( QPalette::Active, QPalette::Highlight, qcolorForTheme(kThemeBrushPrimaryHighlightColor) );
+ pal.setBrush( QPalette::Inactive, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) );
+
+ pal.setBrush( QPalette::Disabled, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) );
+ pal.setBrush( QPalette::Active, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonActiveDarkShadow) );
+
+ pal.setBrush( QPalette::Inactive, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) );
+ pal.setBrush( QPalette::Disabled, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) );
+
+ qc = qcolorForThemeTextColor(kThemeTextColorDialogActive);
+ pal.setColor(QPalette::Active, QPalette::Text, qc);
+ pal.setColor(QPalette::Active, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
+
+ qc = qcolorForThemeTextColor(kThemeTextColorDialogInactive);
+ pal.setColor(QPalette::Inactive, QPalette::Text, qc);
+ pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::Text, qc);
+ pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
+ pal.setBrush(QPalette::ToolTipBase, QColor(255, 255, 199));
+
+ if (!QApplicationPrivate::sys_pal || *QApplicationPrivate::sys_pal != pal) {
+ QApplicationPrivate::setSystemPalette(pal);
+ QApplication::setPalette(pal);
+ }
+#ifdef DEBUG_PLATFORM_SETTINGS
+ qt_mac_debug_palette(pal, QApplication::palette(), "Global Palette");
+#endif
+ }
+
+ QFont fnt = qfontForThemeFont(kThemeApplicationFont);
+#ifdef DEBUG_PLATFORM_SETTINGS
+ qDebug("qt-internal: Font for Application [%s::%d::%d::%d]",
+ fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic());
+#endif
+ if (!QApplicationPrivate::sys_font || *QApplicationPrivate::sys_font != fnt)
+ QApplicationPrivate::setSystemFont(fnt);
+
+ { //setup the fonts
+ struct FontMap {
+ FontMap(const char *qc, short fk) : qt_class(qc), font_key(fk) { }
+ const char *const qt_class;
+ short font_key;
+ } mac_widget_fonts[] = {
+ FontMap("QPushButton", kThemePushButtonFont),
+ FontMap("QListView", kThemeViewsFont),
+ FontMap("QListBox", kThemeViewsFont),
+ FontMap("QTitleBar", kThemeWindowTitleFont),
+ FontMap("QMenuBar", kThemeMenuTitleFont),
+ FontMap("QMenu", kThemeMenuItemFont),
+ FontMap("QComboMenuItem", kThemeSystemFont),
+ FontMap("QHeaderView", kThemeSmallSystemFont),
+ FontMap("Q3Header", kThemeSmallSystemFont),
+ FontMap("QTipLabel", kThemeSmallSystemFont),
+ FontMap("QLabel", kThemeSystemFont),
+ FontMap("QToolButton", kThemeSmallSystemFont),
+ FontMap("QMenuItem", kThemeMenuItemCmdKeyFont), // It doesn't exist, but its unique.
+ FontMap("QComboLineEdit", kThemeViewsFont), // It doesn't exist, but its unique.
+ FontMap("QSmallFont", kThemeSmallSystemFont), // It doesn't exist, but its unique.
+ FontMap("QMiniFont", kThemeMiniSystemFont), // It doesn't exist, but its unique.
+ FontMap(0, 0) };
+ for(int i = 0; mac_widget_fonts[i].qt_class; i++) {
+ QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key);
+ bool set_font = true;
+ QHash<QByteArray, QFont> *hash = qt_app_fonts_hash();
+ if (!hash->isEmpty()) {
+ QHash<QByteArray, QFont>::const_iterator it
+ = hash->constFind(mac_widget_fonts[i].qt_class);
+ if (it != hash->constEnd())
+ set_font = (fnt != *it);
+ }
+ if (set_font) {
+ QApplication::setFont(fnt, mac_widget_fonts[i].qt_class);
+#ifdef DEBUG_PLATFORM_SETTINGS
+ qDebug("qt-internal: Font for %s [%s::%d::%d::%d]", mac_widget_fonts[i].qt_class,
+ fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic());
+#endif
+ }
+ }
+ }
+ QApplicationPrivate::initializeWidgetPaletteHash();
+#ifdef DEBUG_PLATFORM_SETTINGS
+ qDebug("qt_mac_update_os_settings END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+#endif
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+ { //setup the palette
+ struct PaletteMap {
+ inline PaletteMap(const char *qc, ThemeBrush a, ThemeBrush i) :
+ qt_class(qc), active(a), inactive(i) { }
+ const char *const qt_class;
+ ThemeBrush active, inactive;
+ } mac_widget_colors[] = {
+ PaletteMap("QToolButton", kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive),
+ PaletteMap("QAbstractButton", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+ PaletteMap("QHeaderView", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+ PaletteMap("Q3Header", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+ PaletteMap("QComboBox", kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
+ PaletteMap("QAbstractItemView", kThemeTextColorListView, kThemeTextColorDialogInactive),
+ PaletteMap("QMessageBoxLabel", kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
+ PaletteMap("QTabBar", kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
+ PaletteMap("QLabel", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
+ PaletteMap("QGroupBox", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
+ PaletteMap("QMenu", kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive),
+ PaletteMap("QTextEdit", 0, 0),
+ PaletteMap("QTextControl", 0, 0),
+ PaletteMap("QLineEdit", 0, 0),
+ PaletteMap(0, 0, 0) };
+ QColor qc;
+ for(int i = 0; mac_widget_colors[i].qt_class; i++) {
+ QPalette pal;
+ if (mac_widget_colors[i].active != 0) {
+ qc = qcolorForThemeTextColor(mac_widget_colors[i].active);
+ pal.setColor(QPalette::Active, QPalette::Text, qc);
+ pal.setColor(QPalette::Active, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
+ qc = qcolorForThemeTextColor(mac_widget_colors[i].inactive);
+ pal.setColor(QPalette::Inactive, QPalette::Text, qc);
+ pal.setColor(QPalette::Disabled, QPalette::Text, qc);
+ pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
+ }
+ if (!strcmp(mac_widget_colors[i].qt_class, "QMenu")) {
+ qc = qcolorForThemeTextColor(kThemeTextColorMenuItemActive);
+ pal.setBrush(QPalette::ButtonText, qc);
+ qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::HighlightedText, qc);
+ qc = qcolorForThemeTextColor(kThemeTextColorMenuItemDisabled);
+ pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
+ } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractButton")
+ || !strcmp(mac_widget_colors[i].qt_class, "QHeaderView")
+ || !strcmp(mac_widget_colors[i].qt_class, "Q3Header")) { //special
+ pal.setColor(QPalette::Disabled, QPalette::ButtonText,
+ pal.color(QPalette::Disabled, QPalette::Text));
+ pal.setColor(QPalette::Inactive, QPalette::ButtonText,
+ pal.color(QPalette::Inactive, QPalette::Text));
+ pal.setColor(QPalette::Active, QPalette::ButtonText,
+ pal.color(QPalette::Active, QPalette::Text));
+ } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractItemView")) {
+ pal.setBrush(QPalette::Active, QPalette::Highlight,
+ qcolorForTheme(kThemeBrushAlternatePrimaryHighlightColor));
+ qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc);
+#if 1
+ pal.setBrush(QPalette::Inactive, QPalette::Text,
+ pal.brush(QPalette::Active, QPalette::Text));
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+#endif
+ } else if (!strcmp(mac_widget_colors[i].qt_class, "QTextEdit")
+ || !strcmp(mac_widget_colors[i].qt_class, "QTextControl")) {
+ pal.setBrush(QPalette::Inactive, QPalette::Text,
+ pal.brush(QPalette::Active, QPalette::Text));
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+ } else if (!strcmp(mac_widget_colors[i].qt_class, "QLineEdit")) {
+ pal.setBrush(QPalette::Disabled, QPalette::Base,
+ pal.brush(QPalette::Active, QPalette::Base));
+ }
+
+ bool set_palette = true;
+ extern QHash<QByteArray, QPalette> *qt_app_palettes_hash(); //qapplication.cpp
+ QHash<QByteArray, QPalette> *phash = qt_app_palettes_hash();
+ if (!phash->isEmpty()) {
+ QHash<QByteArray, QPalette>::const_iterator it
+ = phash->constFind(mac_widget_colors[i].qt_class);
+ if (it != phash->constEnd())
+ set_palette = (pal != *it);
+ }
+ if (set_palette) {
+ QApplication::setPalette(pal, mac_widget_colors[i].qt_class);
+#ifdef DEBUG_PLATFORM_SETTINGS
+ qt_mac_debug_palette(pal, QApplication::palette(), QLatin1String("Palette for ") + QString::fromLatin1(mac_widget_colors[i].qt_class));
+#endif
+ }
+ }
+ }
+}
+
+static void qt_mac_event_release(EventRef &event)
+{
+ ReleaseEvent(event);
+ event = 0;
+}
+#ifndef QT_MAC_USE_COCOA
+static void qt_mac_event_release(QWidget *w, EventRef &event)
+{
+ if (event) {
+ QWidget *widget = 0;
+ if (GetEventParameter(event, kEventParamQWidget, typeQWidget, 0, sizeof(widget), 0, &widget) == noErr
+ && w == widget) {
+ if (IsEventInQueue(GetMainEventQueue(), event))
+ RemoveEventFromQueue(GetMainEventQueue(), event);
+ qt_mac_event_release(event);
+ }
+ }
+}
+
+static bool qt_mac_event_remove(EventRef &event)
+{
+ if (event) {
+ if (IsEventInQueue(GetMainEventQueue(), event))
+ RemoveEventFromQueue(GetMainEventQueue(), event);
+ qt_mac_event_release(event);
+ return true;
+ }
+ return false;
+}
+#endif
+
+/* sheets */
+#ifndef QT_MAC_USE_COCOA
+static EventRef request_showsheet_pending = 0;
+#endif
+void qt_event_request_showsheet(QWidget *w)
+{
+ Q_ASSERT(qt_mac_is_macsheet(w));
+#ifdef QT_MAC_USE_COCOA
+ [NSApp beginSheet:qt_mac_window_for(w) modalForWindow:qt_mac_window_for(w->parentWidget())
+ modalDelegate:nil didEndSelector:nil contextInfo:0];
+#else
+ qt_mac_event_remove(request_showsheet_pending);
+ CreateEvent(0, kEventClassQt, kEventQtRequestShowSheet, GetCurrentEventTime(),
+ kEventAttributeUserEvent, &request_showsheet_pending);
+ SetEventParameter(request_showsheet_pending, kEventParamQWidget, typeQWidget, sizeof(w), &w);
+ PostEventToQueue(GetMainEventQueue(), request_showsheet_pending, kEventPriorityStandard);
+#endif
+}
+
+static void qt_post_window_change_event(QWidget *widget)
+{
+ qt_widget_private(widget)->needWindowChange = true;
+ QEvent *glWindowChangeEvent = new QEvent(QEvent::MacGLWindowChange);
+ QApplication::postEvent(widget, glWindowChangeEvent);
+}
+
+/*
+ Posts updates to all child and grandchild OpenGL widgets for the given widget.
+*/
+static void qt_mac_update_child_gl_widgets(QWidget *widget)
+{
+ if (widget->isWindow())
+ return;
+
+ // Update all OpenGL child widgets for the given widget.
+ QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets;
+ QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
+ QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
+
+ for (;it != end; ++it) {
+ qt_post_window_change_event(it->widget);
+ }
+}
+
+/*
+ Sends updates to all child and grandchild gl widgets that have updates pending.
+*/
+void qt_mac_send_posted_gl_updates(QWidget *widget)
+{
+ QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets;
+ QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
+ QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
+
+ for (;it != end; ++it) {
+ QWidget *glWidget = it->widget;
+ if (qt_widget_private(glWidget)->needWindowChange) {
+ QEvent glChangeEvent(QEvent::MacGLWindowChange);
+ QApplication::sendEvent(glWidget, &glChangeEvent);
+ }
+ }
+}
+
+/*
+ Posts updates to all OpenGL widgets within the window that the given widget intersects.
+*/
+static void qt_mac_update_intersected_gl_widgets(QWidget *widget)
+{
+#ifndef QT_MAC_USE_COCOA
+ QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget->window())->glWidgets;
+ if (glWidgets.isEmpty())
+ return;
+
+ // Exit if the window has not been created yet (mapToGlobal/size will force create it)
+ if (widget->testAttribute(Qt::WA_WState_Created) == false || HIViewGetWindow(qt_mac_nativeview_for(widget)) == 0)
+ return;
+
+ const QRect globalWidgetRect = QRect(widget->mapToGlobal(QPoint(0, 0)), widget->size());
+
+ QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
+ QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
+
+ for (;it != end; ++it){
+ QWidget *glWidget = it->widget;
+ const QRect globalGlWidgetRect = QRect(glWidget->mapToGlobal(QPoint(0, 0)), glWidget->size());
+ if (globalWidgetRect.intersects(globalGlWidgetRect)) {
+ qt_post_window_change_event(glWidget);
+ it->lastUpdateWidget = widget;
+ } else if (it->lastUpdateWidget == widget) {
+ // Update the gl wigets that the widget intersected the last time around,
+ // and that we are not intersecting now. This prevents paint errors when the
+ // intersecting widget leaves a gl widget.
+ qt_post_window_change_event(glWidget);
+ it->lastUpdateWidget = 0;
+ }
+ }
+#else
+ Q_UNUSED(widget);
+#endif
+}
+
+/*
+ Posts a kEventQtRequestWindowChange event to the main Carbon event queue.
+*/
+static EventRef request_window_change_pending = 0;
+Q_GUI_EXPORT void qt_event_request_window_change()
+{
+ if(request_window_change_pending)
+ return;
+
+ CreateEvent(0, kEventClassQt, kEventQtRequestWindowChange, GetCurrentEventTime(),
+ kEventAttributeUserEvent, &request_window_change_pending);
+ PostEventToQueue(GetMainEventQueue(), request_window_change_pending, kEventPriorityHigh);
+}
+
+/* window changing. This is a hack around Apple's missing functionality, pending the toolbox
+ team fix. --Sam */
+Q_GUI_EXPORT void qt_event_request_window_change(QWidget *widget)
+{
+ if (!widget)
+ return;
+
+ // Post a kEventQtRequestWindowChange event. This event is semi-public,
+ // don't remove this line!
+ qt_event_request_window_change();
+
+ // Post update request on gl widgets unconditionally.
+ if (qt_widget_private(widget)->isGLWidget == true) {
+ qt_post_window_change_event(widget);
+ return;
+ }
+
+ qt_mac_update_child_gl_widgets(widget);
+ qt_mac_update_intersected_gl_widgets(widget);
+}
+
+/* activation */
+static struct {
+ QPointer<QWidget> widget;
+ EventRef event;
+ EventLoopTimerRef timer;
+ EventLoopTimerUPP timerUPP;
+} request_activate_pending = { 0, 0, 0, 0 };
+bool qt_event_remove_activate()
+{
+ if (request_activate_pending.timer) {
+ RemoveEventLoopTimer(request_activate_pending.timer);
+ request_activate_pending.timer = 0;
+ }
+ if (request_activate_pending.event)
+ qt_mac_event_release(request_activate_pending.event);
+ return true;
+}
+
+void qt_event_activate_timer_callbk(EventLoopTimerRef r, void *)
+{
+ EventLoopTimerRef otc = request_activate_pending.timer;
+ qt_event_remove_activate();
+ if (r == otc && !request_activate_pending.widget.isNull()) {
+ const QWidget *tlw = request_activate_pending.widget->window();
+ Qt::WindowType wt = tlw->windowType();
+ if (tlw->isVisible()
+ && ((wt != Qt::Desktop && wt != Qt::Popup && wt != Qt::Tool) || tlw->isModal())) {
+ CreateEvent(0, kEventClassQt, kEventQtRequestActivate, GetCurrentEventTime(),
+ kEventAttributeUserEvent, &request_activate_pending.event);
+ PostEventToQueue(GetMainEventQueue(), request_activate_pending.event, kEventPriorityHigh);
+ }
+ }
+}
+
+void qt_event_request_activate(QWidget *w)
+{
+ if (w == request_activate_pending.widget)
+ return;
+
+ /* We put these into a timer because due to order of events being sent we need to be sure this
+ comes from inside of the event loop */
+ qt_event_remove_activate();
+ if (!request_activate_pending.timerUPP)
+ request_activate_pending.timerUPP = NewEventLoopTimerUPP(qt_event_activate_timer_callbk);
+ request_activate_pending.widget = w;
+ InstallEventLoopTimer(GetMainEventLoop(), 0, 0, request_activate_pending.timerUPP, 0, &request_activate_pending.timer);
+}
+
+
+/* menubars */
+#ifndef QT_MAC_USE_COCOA
+static EventRef request_menubarupdate_pending = 0;
+#endif
+void qt_event_request_menubarupdate()
+{
+#ifndef QT_MAC_USE_COCOA
+ if (request_menubarupdate_pending) {
+ if (IsEventInQueue(GetMainEventQueue(), request_menubarupdate_pending))
+ return;
+#ifdef DEBUG_DROPPED_EVENTS
+ qDebug("%s:%d Whoa, we dropped an event on the floor!", __FILE__, __LINE__);
+#endif
+ }
+
+ CreateEvent(0, kEventClassQt, kEventQtRequestMenubarUpdate, GetCurrentEventTime(),
+ kEventAttributeUserEvent, &request_menubarupdate_pending);
+ PostEventToQueue(GetMainEventQueue(), request_menubarupdate_pending, kEventPriorityHigh);
+#else
+ // Just call this. The request has the benefit that we don't call this multiple times, but
+ // we can optimize this.
+ QMenuBar::macUpdateMenuBar();
+#endif
+}
+
+#ifndef QT_MAC_USE_COCOA
+//context menu
+static EventRef request_context_pending = 0;
+static void qt_event_request_context(QWidget *w=0, EventRef *where=0)
+{
+ if (!where)
+ where = &request_context_pending;
+ if (*where)
+ return;
+ CreateEvent(0, kEventClassQt, kEventQtRequestContext, GetCurrentEventTime(),
+ kEventAttributeUserEvent, where);
+ if (w)
+ SetEventParameter(*where, kEventParamQWidget, typeQWidget, sizeof(w), &w);
+ PostEventToQueue(GetMainEventQueue(), *where, kEventPriorityStandard);
+}
+#endif
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+ if (q->type() != QApplication::Tty)
+ eventDispatcher = new QEventDispatcherMac(q);
+ else
+ eventDispatcher = new QEventDispatcherUNIX(q);
+}
+
+/* clipboard */
+void qt_event_send_clipboard_changed()
+{
+#ifndef QT_MAC_USE_COCOA
+ AppleEvent ae;
+ if (AECreateAppleEvent(kEventClassQt, typeAEClipboardChanged, 0, kAutoGenerateReturnID, kAnyTransactionID, &ae) != noErr)
+ qDebug("Can't happen!!");
+ AppleEvent reply;
+ AESend(&ae, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, 0, 0);
+#endif
+}
+
+/* app menu */
+static QMenu *qt_mac_dock_menu = 0;
+Q_GUI_EXPORT void qt_mac_set_dock_menu(QMenu *menu)
+{
+ qt_mac_dock_menu = menu;
+#ifdef QT_MAC_USE_COCOA
+ [NSApp setDockMenu:menu->macMenu()];
+#else
+ SetApplicationDockTileMenu(menu->macMenu());
+#endif
+}
+
+/* events that hold pointers to widgets, must be cleaned up like this */
+void qt_mac_event_release(QWidget *w)
+{
+ if (w) {
+#ifndef QT_MAC_USE_COCOA
+ qt_mac_event_release(w, request_showsheet_pending);
+ qt_mac_event_release(w, request_context_pending);
+#endif
+ if (w == qt_mac_dock_menu) {
+ qt_mac_dock_menu = 0;
+#ifndef QT_MAC_USE_COCOA
+ SetApplicationDockTileMenu(0);
+#else
+ [NSApp setDockMenu:0];
+#endif
+ }
+ }
+}
+
+#ifndef QT_MAC_USE_COCOA
+struct QMacAppleEventTypeSpec {
+ AEEventClass mac_class;
+ AEEventID mac_id;
+} app_apple_events[] = {
+ { kCoreEventClass, kAEQuitApplication },
+ { kCoreEventClass, kAEOpenDocuments }
+};
+/* watched events */
+static EventTypeSpec app_events[] = {
+ { kEventClassQt, kEventQtRequestWindowChange },
+ { kEventClassQt, kEventQtRequestShowSheet },
+ { kEventClassQt, kEventQtRequestContext },
+ { kEventClassQt, kEventQtRequestActivate },
+ { kEventClassQt, kEventQtRequestMenubarUpdate },
+
+ { kEventClassWindow, kEventWindowActivated },
+ { kEventClassWindow, kEventWindowDeactivated },
+
+ { kEventClassMouse, kEventMouseWheelMoved },
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassMouse, kEventMouseMoved },
+
+ { kEventClassTablet, kEventTabletProximity },
+
+ { kEventClassApplication, kEventAppActivated },
+ { kEventClassApplication, kEventAppDeactivated },
+ { kEventClassApplication, kEventAppAvailableWindowBoundsChanged },
+
+ // { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassKeyboard, kEventRawKeyDown },
+
+ { kEventClassCommand, kEventCommandProcess },
+
+ { kEventClassAppleEvent, kEventAppleEvent },
+
+ { kAppearanceEventClass, kAEAppearanceChanged }
+};
+
+void qt_init_app_proc_handler()
+{
+ InstallEventHandler(GetApplicationEventTarget(), app_proc_handlerUPP,
+ GetEventTypeCount(app_events), app_events, (void *)qApp,
+ &app_proc_handler);
+}
+#endif // QT_MAC_USE_COCOA
+
+static void qt_init_tablet_proximity_handler()
+{
+ EventTypeSpec tabletProximityEvent = { kEventClassTablet, kEventTabletProximity };
+ InstallEventHandler(GetEventMonitorTarget(), tablet_proximity_UPP,
+ 1, &tabletProximityEvent, qApp, &tablet_proximity_handler);
+}
+
+static void qt_release_tablet_proximity_handler()
+{
+ RemoveEventHandler(tablet_proximity_handler);
+}
+
+QString QApplicationPrivate::appName() const
+{
+ static QString applName;
+ if (applName.isEmpty()) {
+ applName = QCoreApplicationPrivate::macMenuBarName();
+ ProcessSerialNumber psn;
+ if (applName.isEmpty() && qt_is_gui_used && GetCurrentProcess(&psn) == noErr) {
+ QCFString cfstr;
+ CopyProcessName(&psn, &cfstr);
+ applName = cfstr;
+ }
+ }
+ return applName;
+}
+
+void qt_release_app_proc_handler()
+{
+#ifndef QT_MAC_USE_COCOA
+ if (app_proc_handler) {
+ RemoveEventHandler(app_proc_handler);
+ app_proc_handler = 0;
+ }
+#endif
+}
+
+/* platform specific implementations */
+void qt_init(QApplicationPrivate *priv, int)
+{
+ if (qt_is_gui_used) {
+ CGDisplayRegisterReconfigurationCallback(qt_mac_display_change_callbk, 0);
+ ProcessSerialNumber psn;
+ if (GetCurrentProcess(&psn) == noErr) {
+ // Jambi needs to transform itself since most people aren't "used"
+ // to putting things in bundles, but other people may actually not
+ // want to tranform the process (running as a helper or somethng)
+ // so don't do that for them. This means checking both LSUIElement
+ // and LSBackgroundOnly. If you set them both... well, you
+ // shouldn't do that.
+
+ bool forceTransform = true;
+ CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
+ CFSTR("LSUIElement"));
+ if (value) {
+ CFTypeID valueType = CFGetTypeID(value);
+ // Officially it's supposed to be a string, a boolean makes sense, so we'll check.
+ // A number less so, but OK.
+ if (valueType == CFStringGetTypeID())
+ forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt());
+ else if (valueType == CFBooleanGetTypeID())
+ forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
+ else if (valueType == CFNumberGetTypeID()) {
+ int valueAsInt;
+ CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
+ forceTransform = !valueAsInt;
+ }
+ }
+
+ if (forceTransform) {
+ value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
+ CFSTR("LSBackgroundOnly"));
+ if (value) {
+ CFTypeID valueType = CFGetTypeID(value);
+ if (valueType == CFBooleanGetTypeID())
+ forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
+ else if (valueType == CFStringGetTypeID())
+ forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt());
+ else if (valueType == CFNumberGetTypeID()) {
+ int valueAsInt;
+ CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
+ forceTransform = !valueAsInt;
+ }
+ }
+ }
+
+
+ if (forceTransform) {
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ }
+ }
+ }
+
+ char **argv = priv->argv;
+
+ // Get command line params
+ if (int argc = priv->argc) {
+ int i, j = 1;
+ QString passed_psn;
+ for(i=1; i < argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QByteArray arg(argv[i]);
+#if defined(QT_DEBUG)
+ if (arg == "-nograb")
+ appNoGrab = !appNoGrab;
+ else
+#endif // QT_DEBUG
+ if (arg.left(5) == "-psn_") {
+ passed_psn = QString::fromLatin1(arg.mid(6));
+ } else {
+ argv[j++] = argv[i];
+ }
+ }
+ if (j < priv->argc) {
+ priv->argv[j] = 0;
+ priv->argc = j;
+ }
+
+ //special hack to change working directory (for an app bundle) when running from finder
+ if (!passed_psn.isNull() && QDir::currentPath() == QLatin1String("/")) {
+ QCFType<CFURLRef> bundleURL(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
+ QString qbundlePath = QCFString(CFURLCopyFileSystemPath(bundleURL,
+ kCFURLPOSIXPathStyle));
+ if (qbundlePath.endsWith(QLatin1String(".app")))
+ QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
+ }
+ }
+
+ QMacPasteboardMime::initialize();
+
+ qApp->setObjectName(priv->appName());
+ if (qt_is_gui_used) {
+ QColormap::initialize();
+ QFont::initialize();
+ QCursorData::initialize();
+ QCoreGraphicsPaintEngine::initialize();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::initialize();
+#endif
+ QMacInputContext::initialize();
+ QApplicationPrivate::inputContext = new QMacInputContext;
+
+ if (QApplication::desktopSettingsAware())
+ qt_mac_update_os_settings();
+#ifndef QT_MAC_USE_COCOA
+ if (!app_proc_handler) {
+ app_proc_handlerUPP = NewEventHandlerUPP(QApplicationPrivate::globalEventProcessor);
+ qt_init_app_proc_handler();
+ }
+
+ if (!app_proc_ae_handlerUPP) {
+ app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
+ for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
+ AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
+ app_proc_ae_handlerUPP, SRefCon(qApp), true);
+ }
+#endif
+
+ if (QApplicationPrivate::app_style) {
+ QEvent ev(QEvent::Style);
+ qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
+ }
+ }
+ if (QApplication::desktopSettingsAware())
+ QApplicationPrivate::qt_mac_apply_settings();
+ // Cocoa application delegate
+#ifdef QT_MAC_USE_COCOA
+ NSApplication *cocoaApp = [NSApplication sharedApplication];
+ QMacCocoaAutoReleasePool pool;
+ NSObject *oldDelegate = [cocoaApp delegate];
+ QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
+ Q_ASSERT(newDelegate);
+ [newDelegate setQtPrivate:priv];
+ // Only do things that make sense to do once, otherwise we crash.
+ if (oldDelegate != newDelegate && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
+ [newDelegate setReflectionDelegate:oldDelegate];
+ [cocoaApp setDelegate:newDelegate];
+
+ QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) alloc] init];
+ if ([NSBundle loadNibNamed:@"qt_menu" owner:qtMenuLoader] == false) {
+ qFatal("Qt internal error: qt_menu.nib could not be loaded. The .nib file"
+ " should be placed in QtGui.framework/Versions/Current/Resources/ "
+ " or in the resources directory of your application bundle.");
+ }
+
+ [cocoaApp setMenu:[qtMenuLoader menu]];
+ [newDelegate setMenuLoader:qtMenuLoader];
+ [qtMenuLoader release];
+ }
+#endif
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
+ extern void qt_mac_set_native_menubar(bool);
+ qt_mac_set_native_menubar(false);
+ }
+ // Register for Carbon tablet proximity events on the event monitor target.
+ // This means that we should receive proximity events even when we aren't the active application.
+ if (!tablet_proximity_handler) {
+ tablet_proximity_UPP = NewEventHandlerUPP(QApplicationPrivate::tabletProximityCallback);
+ qt_init_tablet_proximity_handler();
+ }
+ priv->native_modal_dialog_active = false;
+
+}
+
+/*****************************************************************************
+ qt_cleanup() - cleans up when the application is finished
+ *****************************************************************************/
+
+void qt_cleanup()
+{
+ CGDisplayRemoveReconfigurationCallback(qt_mac_display_change_callbk, 0);
+#ifndef QT_MAC_USE_COCOA
+ qt_release_app_proc_handler();
+ if (app_proc_handlerUPP) {
+ DisposeEventHandlerUPP(app_proc_handlerUPP);
+ app_proc_handlerUPP = 0;
+ }
+ if(app_proc_ae_handlerUPP) {
+ for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
+ AERemoveEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
+ app_proc_ae_handlerUPP, true);
+ DisposeAEEventHandlerUPP(app_proc_ae_handlerUPP);
+ app_proc_ae_handlerUPP = NULL;
+ }
+#endif
+
+ qt_release_tablet_proximity_handler();
+ if (tablet_proximity_UPP)
+ DisposeEventHandlerUPP(tablet_proximity_UPP);
+
+ QPixmapCache::clear();
+ if (qt_is_gui_used) {
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::cleanup();
+#endif
+ QMacInputContext::cleanup();
+ QCursorData::cleanup();
+ QFont::cleanup();
+ QColormap::cleanup();
+ if (qt_mac_safe_pdev) {
+ delete qt_mac_safe_pdev;
+ qt_mac_safe_pdev = 0;
+ }
+ extern void qt_mac_unregister_widget(); // qapplication_mac.cpp
+ qt_mac_unregister_widget();
+ }
+}
+
+/*****************************************************************************
+ Platform specific global and internal functions
+ *****************************************************************************/
+void qt_updated_rootinfo()
+{
+}
+
+bool qt_wstate_iconified(WId)
+{
+ return false;
+}
+
+/*****************************************************************************
+ Platform specific QApplication members
+ *****************************************************************************/
+extern QWidget * mac_mouse_grabber;
+extern QWidget * mac_keyboard_grabber;
+
+#ifdef QT3_SUPPORT
+void QApplication::setMainWidget(QWidget *mainWidget)
+{
+ QApplicationPrivate::main_widget = mainWidget;
+ if (QApplicationPrivate::main_widget && windowIcon().isNull()
+ && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
+ setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
+}
+#endif
+#ifndef QT_NO_CURSOR
+
+/*****************************************************************************
+ QApplication cursor stack
+ *****************************************************************************/
+void QApplication::setOverrideCursor(const QCursor &cursor)
+{
+ qApp->d_func()->cursor_list.prepend(cursor);
+
+ if (qApp && qApp->activeWindow())
+ qt_mac_set_cursor(&qApp->d_func()->cursor_list.first(), QCursor::pos());
+}
+
+void QApplication::restoreOverrideCursor()
+{
+ if (qApp->d_func()->cursor_list.isEmpty())
+ return;
+ qApp->d_func()->cursor_list.removeFirst();
+
+ if (qApp && qApp->activeWindow()) {
+ const QCursor def(Qt::ArrowCursor);
+ qt_mac_set_cursor(qApp->d_func()->cursor_list.isEmpty() ? &def : &qApp->d_func()->cursor_list.first(), QCursor::pos());
+ }
+}
+#endif
+
+QWidget *QApplication::topLevelAt(const QPoint &p)
+{
+#ifndef QT_MAC_USE_COCOA
+ QWidget *widget;
+ qt_mac_window_at(p.x(), p.y(), &widget);
+ return widget;
+#else
+ NSInteger windowCount;
+ NSCountWindows(&windowCount);
+ if (windowCount <= 0)
+ return 0; // There's no window to find!
+ QMacCocoaAutoReleasePool pool;
+ NSPoint cocoaPoint = flipPoint(p);
+ QVarLengthArray<NSInteger> windowList(windowCount);
+ NSWindowList(windowCount, windowList.data());
+ for (int i = 0; i < windowCount; ++i) {
+ NSWindow *window = [NSApp windowWithWindowNumber:windowList[i]];
+ if (window && NSPointInRect(cocoaPoint, [window frame])) {
+ QWidget *candidateWindow = [window QT_MANGLE_NAMESPACE(qt_qwidget)];
+ // Check to see if there's a hole in the window where the mask is.
+ // If there is, we should just continue to see if there is a window below.
+ if (candidateWindow && !candidateWindow->mask().isEmpty()) {
+ QPoint localPoint = candidateWindow->mapFromGlobal(p);
+ if (!candidateWindow->mask().contains(localPoint)) {
+ continue;
+ }
+ }
+ return candidateWindow;
+ }
+ }
+ return 0; // Couldn't find a window at this point
+#endif
+}
+
+static QWidget *qt_mac_recursive_widgetAt(QWidget *widget, int x, int y)
+{
+ if (!widget)
+ return 0;
+ const QObjectList kids = widget->children();
+ for(int i = kids.size()-1; i >= 0; --i) {
+ if ( QWidget *kid = qobject_cast<QWidget*>(kids.at(i)) ) {
+ if (kid->isVisible() && !kid->isTopLevel() &&
+ !kid->testAttribute(Qt::WA_TransparentForMouseEvents)) {
+ const int wx=kid->x(), wy=kid->y(),
+ wx2=wx+kid->width(), wy2=wy+kid->height();
+ if (x >= wx && y >= wy && x < wx2 && y < wy2) {
+ const QRegion mask = kid->mask();
+ if (!mask.isEmpty() && !mask.contains(QPoint(x-wx, y-wy)))
+ continue;
+ return qt_mac_recursive_widgetAt(kid, x-wx, y-wy);
+ }
+ }
+ }
+ }
+ return widget;
+}
+
+/*****************************************************************************
+ Main event loop
+ *****************************************************************************/
+
+bool QApplicationPrivate::modalState()
+{
+ return app_do_modal;
+}
+
+#ifdef QT_MAC_USE_COCOA
+#endif
+
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
+{
+#ifdef DEBUG_MODAL_EVENTS
+ Q_ASSERT(widget);
+ qDebug("Entering modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(),
+ widget, qt_modal_stack ? (int)qt_modal_stack->count() : -1);
+#endif
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+
+ dispatchEnterLeave(0, qt_mouseover);
+ qt_mouseover = 0;
+
+ qt_modal_stack->insert(0, widget);
+ if (!app_do_modal)
+ qt_event_request_menubarupdate();
+ app_do_modal = true;
+ qt_button_down = 0;
+
+#ifdef QT_MAC_USE_COCOA
+ if (!qt_mac_is_macsheet(widget)) {
+ // Add a new, empty (null), NSModalSession to the stack.
+ // The next time we spin the event dispatcher, it will
+ // check the stack, and recurse into a modal session for it:
+ QCocoaModalSessionInfo info = {widget, 0};
+ QEventDispatcherMacPrivate::cocoaModalSessionStack.push(info);
+ }
+#endif
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *widget)
+{
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+#ifdef DEBUG_MODAL_EVENTS
+ qDebug("Leaving modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(),
+ widget, qt_modal_stack->count());
+#endif
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ QPoint p(QCursor::pos());
+ app_do_modal = false;
+ QWidget* w = 0;
+ if (QWidget *grabber = QWidget::mouseGrabber())
+ w = grabber;
+ else
+ w = QApplication::widgetAt(p.x(), p.y());
+ dispatchEnterLeave(w, qt_mouseover); // send synthetic enter event
+ qt_mouseover = w;
+ }
+#ifdef QT_MAC_USE_COCOA
+ if (!qt_mac_is_macsheet(widget))
+ QEventDispatcherMacPrivate::rebuildModalSessionStack(true);
+#endif
+ }
+#ifdef DEBUG_MODAL_EVENTS
+ else qDebug("Failure to remove %s::%s::%p -- %p", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(), widget, qt_modal_stack);
+#endif
+ app_do_modal = (qt_modal_stack != 0);
+ if (!app_do_modal)
+ qt_event_request_menubarupdate();
+}
+
+#if defined(QT_MAC_USE_COCOA)
+void QApplicationPrivate::_q_runAppModalWindow()
+{
+ if (QEventDispatcherMacPrivate::blockCocoaRequestModal) {
+ // Just postpone the event until the event dispatcher tells
+ // us (by releasing the block) that it is OK to recurse into
+ // a new event loop for our non-execing modal window:
+ qApp->postEvent(qApp, new QEvent(QEvent::CocoaRequestModal));
+ } else {
+ // Recurse into a new event loop for the current app modal window:
+ threadData->eventDispatcher->processEvents(QEventLoop::DialogExec);
+ }
+}
+#endif
+
+QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top)
+{
+#ifndef QT_MAC_USE_COCOA
+ if(top && qt_mac_is_macsheet(top) && !IsWindowVisible(qt_mac_window_for(top))) {
+ if(OSWindowRef wp = GetFrontWindowOfClass(kSheetWindowClass, true)) {
+ if(QWidget *sheet = qt_mac_find_window(wp))
+ top = sheet;
+ }
+ }
+#endif
+ return top;
+}
+
+static bool qt_try_modal(QWidget *widget, EventRef event)
+{
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ // INVARIANT: widget is modally shaddowed within its
+ // window, and should therefore not handle the event.
+ // However, if the window is not active, the event
+ // might suggest that we should bring it to front:
+
+ bool block_event = false;
+
+ if (event) {
+ switch (GetEventClass(event)) {
+ case kEventClassMouse:
+ case kEventClassKeyboard:
+ block_event = true;
+ break;
+ }
+ }
+
+ QWidget *activeWidget = QApplication::activeWindow();
+ if ((!activeWidget || QApplicationPrivate::isBlockedByModal(activeWidget)) &&
+ top->isWindow() && block_event && !QApplicationPrivate::native_modal_dialog_active)
+ top->raise();
+
+#ifdef DEBUG_MODAL_EVENTS
+ qDebug("%s:%d -- final decision! (%s)", __FILE__, __LINE__, block_event ? "false" : "true");
+#endif
+ return !block_event;
+}
+
+OSStatus QApplicationPrivate::tabletProximityCallback(EventHandlerCallRef, EventRef carbonEvent,
+ void *)
+{
+ OSType eventClass = GetEventClass(carbonEvent);
+ UInt32 eventKind = GetEventKind(carbonEvent);
+ if (eventClass != kEventClassTablet || eventKind != kEventTabletProximity)
+ return eventNotHandledErr;
+
+ // Get the current point of the device and its unique ID.
+ ::TabletProximityRec proxRec;
+ GetEventParameter(carbonEvent, kEventParamTabletProximityRec, typeTabletProximityRec, 0,
+ sizeof(proxRec), 0, &proxRec);
+ qt_dispatchTabletProximityEvent(proxRec);
+ return noErr;
+}
+
+OSStatus
+QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event, void *data)
+{
+#ifndef QT_MAC_USE_COCOA
+ QApplication *app = (QApplication *)data;
+ QScopedLoopLevelCounter loopLevelCounter(app->d_func()->threadData);
+ long result;
+ if (app->filterEvent(&event, &result))
+ return result;
+ if(app->macEventFilter(er, event)) //someone else ate it
+ return noErr;
+ QPointer<QWidget> widget;
+
+ /*We assume all events are handled and in
+ the code below we set it to false when we know we didn't handle it, this
+ will let rogue events through (shouldn't really happen, but better safe
+ than sorry) */
+ bool handled_event=true;
+ UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
+ switch(eclass)
+ {
+ case kEventClassQt:
+ if(ekind == kEventQtRequestShowSheet) {
+ request_showsheet_pending = 0;
+ QWidget *widget = 0;
+ GetEventParameter(event, kEventParamQWidget, typeQWidget, 0,
+ sizeof(widget), 0, &widget);
+ if(widget) {
+ if (widget->macEvent(er, event))
+ return noErr;
+ WindowPtr window = qt_mac_window_for(widget);
+ bool just_show = !qt_mac_is_macsheet(widget);
+ if(!just_show) {
+ OSStatus err = ShowSheetWindow(window, qt_mac_window_for(widget->parentWidget()));
+ if(err != noErr)
+ qWarning("Qt: QWidget: Unable to show as sheet %s::%s [%ld]", widget->metaObject()->className(),
+ widget->objectName().toLocal8Bit().constData(), long(err));
+ just_show = true;
+ }
+ if(just_show) //at least the window will be visible, but the sheet flag doesn't work sadly (probalby too many sheets)
+ ShowHide(window, true);
+ }
+ } else if(ekind == kEventQtRequestWindowChange) {
+ qt_mac_event_release(request_window_change_pending);
+ } else if(ekind == kEventQtRequestMenubarUpdate) {
+ qt_mac_event_release(request_menubarupdate_pending);
+ QMenuBar::macUpdateMenuBar();
+ } else if(ekind == kEventQtRequestActivate) {
+ qt_mac_event_release(request_activate_pending.event);
+ if(request_activate_pending.widget) {
+ QWidget *tlw = request_activate_pending.widget->window();
+ if (tlw->macEvent(er, event))
+ return noErr;
+ request_activate_pending.widget = 0;
+ tlw->activateWindow();
+ SelectWindow(qt_mac_window_for(tlw));
+ }
+ } else if(ekind == kEventQtRequestContext) {
+ bool send = false;
+ if ((send = (event == request_context_pending)))
+ qt_mac_event_release(request_context_pending);
+ if(send) {
+ //figure out which widget to send it to
+ QPoint where = QCursor::pos();
+ QWidget *widget = 0;
+ GetEventParameter(event, kEventParamQWidget, typeQWidget, 0,
+ sizeof(widget), 0, &widget);
+ if(!widget) {
+ if(qt_button_down)
+ widget = qt_button_down;
+ else
+ widget = QApplication::widgetAt(where.x(), where.y());
+ }
+ if(widget && !isBlockedByModal(widget)) {
+ if (widget->macEvent(er, event))
+ return noErr;
+ QPoint plocal(widget->mapFromGlobal(where));
+ const Qt::KeyboardModifiers keyboardModifiers = qt_mac_get_modifiers(GetCurrentEventKeyModifiers());
+ QContextMenuEvent qme(QContextMenuEvent::Mouse, plocal, where, keyboardModifiers);
+ QApplication::sendEvent(widget, &qme);
+ if(qme.isAccepted()) { //once this happens the events before are pitched
+ qt_button_down = 0;
+ qt_mac_dblclick.last_widget = 0;
+ }
+ } else {
+ handled_event = false;
+ }
+ }
+ } else {
+ handled_event = false;
+ }
+ break;
+ case kEventClassTablet:
+ switch (ekind) {
+ case kEventTabletProximity:
+ // Get the current point of the device and its unique ID.
+ ::TabletProximityRec proxRec;
+ GetEventParameter(event, kEventParamTabletProximityRec, typeTabletProximityRec, 0,
+ sizeof(proxRec), 0, &proxRec);
+ qt_dispatchTabletProximityEvent(proxRec);
+ }
+ break;
+ case kEventClassMouse:
+ {
+ static const int kEventParamQAppSeenMouseEvent = 'QASM';
+ // Check if we've seen the event, if we have we shouldn't process
+ // it again as it may lead to spurious "double events"
+ bool seenEvent;
+ if (GetEventParameter(event, kEventParamQAppSeenMouseEvent,
+ typeBoolean, 0, sizeof(bool), 0, &seenEvent) == noErr) {
+ if (seenEvent)
+ return eventNotHandledErr;
+ }
+ seenEvent = true;
+ SetEventParameter(event, kEventParamQAppSeenMouseEvent, typeBoolean,
+ sizeof(bool), &seenEvent);
+
+ Point where;
+ bool inNonClientArea = false;
+ GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0,
+ sizeof(where), 0, &where);
+ if(ekind == kEventMouseMoved && qt_mac_app_fullscreen &&
+ QApplication::desktop()->screenNumber(QPoint(where.h, where.v)) ==
+ QApplication::desktop()->primaryScreen()) {
+ if(where.v <= 0)
+ ShowMenuBar();
+ else if(qt_mac_window_at(where.h, where.v, 0) != inMenuBar)
+ HideMenuBar();
+ }
+
+#if defined(DEBUG_MOUSE_MAPS)
+ const char *edesc = 0;
+ switch(ekind) {
+ case kEventMouseDown: edesc = "MouseButtonPress"; break;
+ case kEventMouseUp: edesc = "MouseButtonRelease"; break;
+ case kEventMouseDragged: case kEventMouseMoved: edesc = "MouseMove"; break;
+ case kEventMouseWheelMoved: edesc = "MouseWheelMove"; break;
+ }
+ if(ekind == kEventMouseDown || ekind == kEventMouseUp)
+ qDebug("Handling mouse: %s", edesc);
+#endif
+ QEvent::Type etype = QEvent::None;
+ Qt::KeyboardModifiers modifiers;
+ {
+ UInt32 mac_modifiers = 0;
+ GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0,
+ sizeof(mac_modifiers), 0, &mac_modifiers);
+ modifiers = qt_mac_get_modifiers(mac_modifiers);
+ }
+ Qt::MouseButtons buttons;
+ {
+ UInt32 mac_buttons = 0;
+ GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0,
+ sizeof(mac_buttons), 0, &mac_buttons);
+ buttons = qt_mac_get_buttons(mac_buttons);
+ }
+ int wheel_delta=0;
+ if(ekind == kEventMouseWheelMoved) {
+ int mdelt = 0;
+ GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0,
+ sizeof(mdelt), 0, &mdelt);
+ wheel_delta = mdelt * 120;
+ }
+
+ Qt::MouseButton button = Qt::NoButton;
+ if(ekind == kEventMouseDown || ekind == kEventMouseUp) {
+ EventMouseButton mac_button = 0;
+ GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0,
+ sizeof(mac_button), 0, &mac_button);
+ button = qt_mac_get_button(mac_button);
+ }
+
+ switch(ekind) {
+ case kEventMouseDown:
+ etype = QEvent::MouseButtonPress;
+ break;
+ case kEventMouseUp:
+ etype = QEvent::MouseButtonRelease;
+ break;
+ case kEventMouseDragged:
+ case kEventMouseMoved:
+ etype = QEvent::MouseMove;
+ break;
+ }
+
+ const bool inPopupMode = app->d_func()->inPopupMode();
+
+ // A click outside a popup closes the popup. Make sure
+ // that no events are generated for the release part of that click.
+ // (The press goes to the popup and closes it.)
+ if (etype == QEvent::MouseButtonPress) {
+ qt_mac_previous_press_in_popup_mode = inPopupMode;
+ } else if (qt_mac_previous_press_in_popup_mode && !inPopupMode && etype == QEvent::MouseButtonRelease) {
+ qt_mac_previous_press_in_popup_mode = false;
+ handled_event = true;
+#if defined(DEBUG_MOUSE_MAPS)
+ qDebug("Bail out early due to qt_mac_previous_press_in_popup_mode");
+#endif
+ break; // break from case kEventClassMouse
+ }
+
+ //figure out which widget to send it to
+ if(inPopupMode) {
+ QWidget *popup = qApp->activePopupWidget();
+ if (qt_button_down && qt_button_down->window() == popup) {
+ widget = qt_button_down;
+ } else {
+ QPoint pos = popup->mapFromGlobal(QPoint(where.h, where.v));
+ widget = popup->childAt(pos);
+ }
+ if(!widget)
+ widget = popup;
+ } else {
+ if(mac_mouse_grabber) {
+ widget = mac_mouse_grabber;
+ } else if (qt_button_down) {
+ widget = qt_button_down;
+ } else {
+ {
+ WindowPtr window = 0;
+ if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0,
+ sizeof(window), 0, &window) != noErr)
+ FindWindowOfClass(&where, kAllWindowClasses, &window, 0);
+ if(window) {
+ HIViewRef hiview;
+ if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) {
+ widget = QWidget::find((WId)hiview);;
+ if (widget) {
+ // Make sure we didn't pass over a widget with a "fake hole" in it.
+ QWidget *otherWidget = QApplication::widgetAt(where.h, where.v);
+ if (otherWidget && otherWidget->testAttribute(Qt::WA_MouseNoMask))
+ widget = otherWidget;
+ }
+ }
+ }
+ }
+ if(!widget) //fallback
+ widget = QApplication::widgetAt(where.h, where.v);
+ if(ekind == kEventMouseUp && widget) {
+ short part = qt_mac_window_at(where.h, where.v);
+ if(part == inDrag) {
+ UInt32 count = 0;
+ GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL,
+ sizeof(count), NULL, &count);
+ if(count == 2 && qt_mac_collapse_on_dblclick) {
+ if (widget->macEvent(er, event))
+ return noErr;
+ widget->setWindowState(widget->windowState() | Qt::WindowMinimized);
+ //we send a hide to be like X11/Windows
+ QEvent e(QEvent::Hide);
+ QApplication::sendSpontaneousEvent(widget, &e);
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (widget && widget->macEvent(er, event))
+ return noErr;
+ WindowPartCode wpc = qt_mac_window_at(where.h, where.v, 0);
+ if (wpc == inProxyIcon && modifiers == Qt::ControlModifier && buttons != Qt::NoButton) {
+ QIconDragEvent e;
+ QApplication::sendSpontaneousEvent(widget, &e);
+ if (e.isAccepted()) {
+ return noErr; // IconDrag ate it.
+ }
+ }
+ if (inPopupMode == false
+ && (qt_button_down == 0 || qt_button_down_in_content == false)
+ && (wpc != inContent && wpc != inStructure)) {
+ inNonClientArea = true;
+ switch (etype) {
+ case QEvent::MouseButtonPress: {
+ UInt32 count = 0;
+ GetEventParameter(event, kEventParamClickCount, typeUInt32, 0,
+ sizeof(count), 0, &count);
+ if(count % 2 || count == 0) {
+ etype = QEvent::NonClientAreaMouseButtonPress;
+ } else {
+ etype = QEvent::NonClientAreaMouseButtonDblClick;
+ }} break;
+ case QEvent::MouseButtonRelease:
+ etype = QEvent::NonClientAreaMouseButtonRelease;
+ break;
+ case QEvent::MouseMove:
+ if (widget == 0 || widget->hasMouseTracking())
+ etype = QEvent::NonClientAreaMouseMove;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(qt_mac_find_window((FrontWindow()))) { //set the cursor up
+ QCursor cursor(Qt::ArrowCursor);
+ QWidget *cursor_widget = widget;
+ if(cursor_widget && cursor_widget == qt_button_down && ekind == kEventMouseUp)
+ cursor_widget = QApplication::widgetAt(where.h, where.v);
+ if(cursor_widget) { //only over the app, do we set a cursor..
+ if(!qApp->d_func()->cursor_list.isEmpty()) {
+ cursor = qApp->d_func()->cursor_list.first();
+ } else {
+ for(; cursor_widget; cursor_widget = cursor_widget->parentWidget()) {
+ QWExtra *extra = cursor_widget->d_func()->extraData();
+ if(extra && extra->curs && cursor_widget->isEnabled()) {
+ cursor = *extra->curs;
+ break;
+ }
+ }
+ }
+ }
+ qt_mac_set_cursor(&cursor, QPoint(where.h, where.v));
+ }
+
+ //This mouse button state stuff looks like this on purpose
+ //although it looks hacky it is VERY intentional..
+ if(widget && app_do_modal && !qt_try_modal(widget, event)) {
+ if(ekind == kEventMouseDown && qt_mac_is_macsheet(QApplication::activeModalWidget()))
+ QApplication::activeModalWidget()->parentWidget()->activateWindow(); //sheets have a parent
+ handled_event = false;
+#if defined(DEBUG_MOUSE_MAPS)
+ qDebug("Bail out early due to qt_try_modal");
+#endif
+ break;
+ }
+
+ UInt32 tabletEventType = 0;
+ GetEventParameter(event, kEventParamTabletEventType, typeUInt32, 0,
+ sizeof(tabletEventType), 0, &tabletEventType);
+ if (tabletEventType == kEventTabletPoint) {
+ TabletPointRec tabletPointRec;
+ GetEventParameter(event, kEventParamTabletPointRec, typeTabletPointRec, 0,
+ sizeof(tabletPointRec), 0, &tabletPointRec);
+ QEvent::Type t = QEvent::TabletMove; //default
+ int new_tablet_button_state = tabletPointRec.buttons ? 1 : 0;
+ if (new_tablet_button_state != tablet_button_state)
+ if (new_tablet_button_state)
+ t = QEvent::TabletPress;
+ else
+ t = QEvent::TabletRelease;
+ tablet_button_state = new_tablet_button_state;
+
+ QMacTabletHash *tabletHash = qt_mac_tablet_hash();
+ if (!tabletHash->contains(tabletPointRec.deviceID)) {
+ qWarning("QCocoaView handleTabletEvent: This tablet device is unknown"
+ " (received no proximity event for it). Discarding event.");
+ return false;
+ }
+ QTabletDeviceData &deviceData = tabletHash->operator[](tabletPointRec.deviceID);
+ if (t == QEvent::TabletPress) {
+ deviceData.widgetToGetPress = widget;
+ } else if (t == QEvent::TabletRelease && deviceData.widgetToGetPress) {
+ widget = deviceData.widgetToGetPress;
+ deviceData.widgetToGetPress = 0;
+ }
+
+ if (widget) {
+ int tiltX = ((int)tabletPointRec.tiltX)/(32767/64); // 32K -> 60
+ int tiltY = ((int)tabletPointRec.tiltY)/(-32767/64); // 32K -> 60
+ HIPoint hiPoint;
+ GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0, sizeof(HIPoint), 0, &hiPoint);
+ QPointF hiRes(hiPoint.x, hiPoint.y);
+ QPoint global(where.h, where.v);
+
+
+
+ QPoint local(widget->mapFromGlobal(global));
+ int z = 0;
+ qreal rotation = 0.0;
+ qreal tp = 0.0;
+ // Again from the Wacom.h header
+
+ if (deviceData.capabilityMask & 0x0200) // Z-axis
+ z = tabletPointRec.absZ;
+
+ if (deviceData.capabilityMask & 0x0800) // Tangential pressure
+ tp = tabletPointRec.tangentialPressure / 32767.0;
+
+ if (deviceData.capabilityMask & 0x2000) // Rotation
+ rotation = qreal(tabletPointRec.rotation) / 64.0;
+
+ QTabletEvent e(t, local, global, hiRes, deviceData.tabletDeviceType,
+ deviceData.tabletPointerType,
+ qreal(tabletPointRec.pressure / qreal(0xffff)), tiltX, tiltY,
+ tp, rotation, z, modifiers, deviceData.tabletUniqueID);
+ QApplication::sendSpontaneousEvent(widget, &e);
+ if (e.isAccepted()) {
+#if defined(DEBUG_MOUSE_MAPS)
+ qDebug("Bail out early due to table acceptance");
+#endif
+ break;
+ }
+ }
+ }
+
+ if(ekind == kEventMouseDown) {
+ qt_mac_no_click_through_mode = false;
+ const short windowPart = qt_mac_window_at(where.h, where.v, 0);
+ // Menubar almost always wins.
+ if (!inPopupMode && windowPart == inMenuBar) {
+ MenuSelect(where); //allow menu tracking
+ return noErr;
+ }
+
+ if (widget && !(GetCurrentKeyModifiers() & cmdKey)) {
+ extern bool qt_isGenuineQWidget(const QWidget *); // qwidget_mac.cpp
+ QWidget *window = widget->window();
+ bool genuineQtWidget = qt_isGenuineQWidget(widget); // the widget, not the window.
+ window->raise();
+
+ bool needActivate = (window->windowType() != Qt::Desktop)
+ && (window->windowType() != Qt::Popup)
+ && !qt_mac_is_macsheet(window);
+ if (needActivate && (!window->isModal() && qobject_cast<QDockWidget *>(window)))
+ needActivate = false;
+
+ if (genuineQtWidget && needActivate)
+ needActivate = !window->isActiveWindow()
+ || !IsWindowActive(qt_mac_window_for(window));
+
+ if (needActivate) {
+ window->activateWindow();
+ if (!qt_mac_can_clickThrough(widget)) {
+ qt_mac_no_click_through_mode = true;
+ handled_event = false;
+#if defined(DEBUG_MOUSE_MAPS)
+ qDebug("Bail out early due to qt_mac_canClickThrough %s::%s", widget->metaObject()->className(),
+ widget->objectName().toLocal8Bit().constData());
+#endif
+ break;
+ }
+ }
+ }
+
+ if(qt_mac_dblclick.last_widget &&
+ qt_mac_dblclick.last_x != -1 && qt_mac_dblclick.last_y != -1 &&
+ QRect(qt_mac_dblclick.last_x-2, qt_mac_dblclick.last_y-2, 4, 4).contains(QPoint(where.h, where.v))) {
+ if(qt_mac_dblclick.use_qt_time_limit) {
+ EventTime now = GetEventTime(event);
+ if(qt_mac_dblclick.last_time != -2 && qt_mac_dblclick.last_widget == widget &&
+ now - qt_mac_dblclick.last_time <= ((double)QApplicationPrivate::mouse_double_click_time)/1000 &&
+ qt_mac_dblclick.last_button == button)
+ etype = QEvent::MouseButtonDblClick;
+ } else {
+ UInt32 count = 0;
+ GetEventParameter(event, kEventParamClickCount, typeUInt32, 0,
+ sizeof(count), 0, &count);
+ if(!(count % 2) && qt_mac_dblclick.last_modifiers == modifiers &&
+ qt_mac_dblclick.last_widget == widget && qt_mac_dblclick.last_button == button)
+ etype = QEvent::MouseButtonDblClick;
+ }
+ if(etype == QEvent::MouseButtonDblClick)
+ qt_mac_dblclick.last_widget = 0;
+ }
+ if(etype != QEvent::MouseButtonDblClick) {
+ qt_mac_dblclick.last_x = where.h;
+ qt_mac_dblclick.last_y = where.v;
+ } else {
+ qt_mac_dblclick.last_x = qt_mac_dblclick.last_y = -1;
+ }
+ } else if(qt_mac_no_click_through_mode) {
+ if(ekind == kEventMouseUp)
+ qt_mac_no_click_through_mode = false;
+ handled_event = false;
+#if defined(DEBUG_MOUSE_MAPS)
+ qDebug("Bail out early due to qt_mac_no_click_through_mode");
+#endif
+ break;
+ }
+
+ QPointer<QWidget> leaveAfterRelease = 0;
+ switch(ekind) {
+ case kEventMouseUp:
+ if (!buttons) {
+ if (!inPopupMode && !QWidget::mouseGrabber())
+ leaveAfterRelease = qt_button_down;
+ qt_button_down = 0;
+ }
+ break;
+ case kEventMouseDown: {
+ if (!qt_button_down)
+ qt_button_down = widget;
+ WindowPartCode wpc = qt_mac_window_at(where.h, where.v, 0);
+ qt_button_down_in_content = (wpc == inContent || wpc == inStructure);
+ break; }
+ }
+
+ // Check if we should send enter/leave events:
+ switch(ekind) {
+ case kEventMouseDragged:
+ case kEventMouseMoved:
+ case kEventMouseUp:
+ case kEventMouseDown: {
+ // If we are in popup mode, widget will point to the current popup no matter
+ // where the mouse cursor is. In that case find out if the mouse cursor is
+ // really over the popup in order to send correct enter / leave envents.
+ QWidget * const enterLeaveWidget = (inPopupMode || ekind == kEventMouseUp) ?
+ QApplication::widgetAt(where.h, where.v) : static_cast<QWidget*>(widget);
+
+ if ((QWidget *) qt_mouseover != enterLeaveWidget || inNonClientArea) {
+#ifdef DEBUG_MOUSE_MAPS
+ qDebug("Entering: %p - %s (%s), Leaving %s (%s)", (QWidget*)enterLeaveWidget,
+ enterLeaveWidget ? enterLeaveWidget->metaObject()->className() : "none",
+ enterLeaveWidget ? enterLeaveWidget->objectName().toLocal8Bit().constData() : "",
+ qt_mouseover ? qt_mouseover->metaObject()->className() : "none",
+ qt_mouseover ? qt_mouseover->objectName().toLocal8Bit().constData() : "");
+#endif
+
+ QWidget * const mouseGrabber = QWidget::mouseGrabber();
+
+ if (inPopupMode) {
+ QWidget *enter = enterLeaveWidget;
+ QWidget *leave = qt_mouseover;
+ if (mouseGrabber) {
+ QWidget * const popupWidget = qApp->activePopupWidget();
+ if (leave == popupWidget)
+ enter = mouseGrabber;
+ if (enter == popupWidget)
+ leave = mouseGrabber;
+ if ((enter == mouseGrabber && leave == popupWidget)
+ || (leave == mouseGrabber && enter == popupWidget)) {
+ QApplicationPrivate::dispatchEnterLeave(enter, leave);
+ qt_mouseover = enter;
+ }
+ } else {
+ QApplicationPrivate::dispatchEnterLeave(enter, leave);
+ qt_mouseover = enter;
+ }
+ } else if ((!qt_button_down || !qt_mouseover) && !mouseGrabber && !leaveAfterRelease) {
+ QApplicationPrivate::dispatchEnterLeave(enterLeaveWidget, qt_mouseover);
+ qt_mouseover = enterLeaveWidget;
+ }
+ }
+ break; }
+ }
+
+ if(widget) {
+ QPoint p(where.h, where.v);
+ QPoint plocal(widget->mapFromGlobal(p));
+ if(etype == QEvent::MouseButtonPress) {
+ qt_mac_dblclick.last_widget = widget;
+ qt_mac_dblclick.last_modifiers = modifiers;
+ qt_mac_dblclick.last_button = button;
+ qt_mac_dblclick.last_time = GetEventTime(event);
+ }
+ if(wheel_delta) {
+ EventMouseWheelAxis axis;
+ GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0,
+ sizeof(axis), 0, &axis);
+ QWheelEvent qwe(plocal, p, wheel_delta, buttons, modifiers,
+ axis == kEventMouseWheelAxisX ? Qt::Horizontal : Qt::Vertical);
+ QApplication::sendSpontaneousEvent(widget, &qwe);
+ if(!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
+ QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
+ wheel_delta, buttons, modifiers,
+ axis == kEventMouseWheelAxisX ? Qt::Horizontal : Qt::Vertical);
+ QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
+ if(!qwe2.isAccepted())
+ handled_event = false;
+ }
+ } else {
+#ifdef QMAC_SPEAK_TO_ME
+ const int speak_keys = Qt::AltModifier | Qt::ShiftModifier;
+ if(etype == QMouseEvent::MouseButtonDblClick && ((modifiers & speak_keys) == speak_keys)) {
+ QVariant v = widget->property("displayText");
+ if(!v.isValid()) v = widget->property("text");
+ if(!v.isValid()) v = widget->property("windowTitle");
+ if(v.isValid()) {
+ QString s = v.toString();
+ s.replace(QRegExp(QString::fromLatin1("(\\&|\\<[^\\>]*\\>)")), QLatin1String(""));
+ SpeechChannel ch;
+ NewSpeechChannel(0, &ch);
+ SpeakText(ch, s.toLatin1().constData(), s.length());
+ DisposeSpeechChannel(ch);
+ }
+ }
+#endif
+ Qt::MouseButton buttonToSend = button;
+ static bool lastButtonTranslated = false;
+ if(ekind == kEventMouseDown &&
+ button == Qt::LeftButton && (modifiers & Qt::MetaModifier)) {
+ buttonToSend = Qt::RightButton;
+ lastButtonTranslated = true;
+ } else if(ekind == kEventMouseUp && lastButtonTranslated) {
+ buttonToSend = Qt::RightButton;
+ lastButtonTranslated = false;
+ }
+ QMouseEvent qme(etype, plocal, p, buttonToSend, buttons, modifiers);
+ QApplication::sendSpontaneousEvent(widget, &qme);
+ if(!qme.isAccepted() || inNonClientArea)
+ handled_event = false;
+ }
+
+ if (leaveAfterRelease) {
+ QWidget *enter = QApplication::widgetAt(where.h, where.v);
+ QApplicationPrivate::dispatchEnterLeave(enter, leaveAfterRelease);
+ qt_mouseover = enter;
+ leaveAfterRelease = 0;
+ }
+
+ if(ekind == kEventMouseDown &&
+ ((button == Qt::RightButton) ||
+ (button == Qt::LeftButton && (modifiers & Qt::MetaModifier))))
+ qt_event_request_context();
+
+#ifdef DEBUG_MOUSE_MAPS
+ const char *event_desc = edesc;
+ if(etype == QEvent::MouseButtonDblClick)
+ event_desc = "Double Click";
+ else if(etype == QEvent::NonClientAreaMouseButtonPress)
+ event_desc = "NonClientMousePress";
+ else if(etype == QEvent::NonClientAreaMouseButtonRelease)
+ event_desc = "NonClientMouseRelease";
+ else if(etype == QEvent::NonClientAreaMouseMove)
+ event_desc = "NonClientMouseMove";
+ else if(etype == QEvent::NonClientAreaMouseButtonDblClick)
+ event_desc = "NonClientMouseDblClick";
+ qDebug("%d %d (%d %d) - Would send (%s) event to %p %s %s (%d 0x%08x 0x%08x %d)", p.x(), p.y(),
+ plocal.x(), plocal.y(), event_desc, (QWidget*)widget,
+ widget ? widget->objectName().toLocal8Bit().constData() : "*Unknown*",
+ widget ? widget->metaObject()->className() : "*Unknown*",
+ button, (int)buttons, (int)modifiers, wheel_delta);
+#endif
+ } else {
+ handled_event = false;
+ }
+ break;
+ }
+ case kEventClassTextInput:
+ case kEventClassKeyboard: {
+ EventRef key_event = event;
+ if(eclass == kEventClassTextInput) {
+ Q_ASSERT(ekind == kEventTextInputUnicodeForKeyEvent);
+ OSStatus err = GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, 0,
+ sizeof(key_event), 0, &key_event);
+ Q_ASSERT(err == noErr);
+ Q_UNUSED(err);
+ }
+ const UInt32 key_ekind = GetEventKind(key_event);
+ Q_ASSERT(GetEventClass(key_event) == kEventClassKeyboard);
+
+ if(key_ekind == kEventRawKeyDown)
+ qt_keymapper_private()->updateKeyMap(er, key_event, data);
+ if(mac_keyboard_grabber)
+ widget = mac_keyboard_grabber;
+ else if (app->activePopupWidget())
+ widget = (app->activePopupWidget()->focusWidget() ?
+ app->activePopupWidget()->focusWidget() : app->activePopupWidget());
+ else if(QApplication::focusWidget())
+ widget = QApplication::focusWidget();
+ else
+ widget = app->activeWindow();
+
+ if (widget) {
+ if (widget->macEvent(er, event))
+ return noErr;
+ } else {
+ // Darn, I need to update tho modifier state, even though
+ // Qt itself isn't getting them, otherwise the keyboard state get inconsistent.
+ if (key_ekind == kEventRawKeyModifiersChanged) {
+ UInt32 modifiers = 0;
+ GetEventParameter(key_event, kEventParamKeyModifiers, typeUInt32, 0,
+ sizeof(modifiers), 0, &modifiers);
+ extern void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object); // qkeymapper_mac.cpp
+ // Just send it to the qApp for the time being.
+ qt_mac_send_modifiers_changed(modifiers, qApp);
+ }
+ handled_event = false;
+ break;
+ }
+
+ if(app_do_modal && !qt_try_modal(widget, key_event))
+ break;
+ if (eclass == kEventClassTextInput) {
+ handled_event = false;
+ } else {
+ handled_event = qt_keymapper_private()->translateKeyEvent(widget, er, key_event, data,
+ widget == mac_keyboard_grabber);
+ }
+ break; }
+ case kEventClassWindow: {
+ WindowRef wid = 0;
+ GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
+ sizeof(WindowRef), 0, &wid);
+ widget = qt_mac_find_window(wid);
+ if (widget && widget->macEvent(er, event))
+ return noErr;
+ if(ekind == kEventWindowActivated) {
+ if(QApplicationPrivate::app_style) {
+ QEvent ev(QEvent::Style);
+ QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
+ }
+
+ if(widget && app_do_modal && !qt_try_modal(widget, event))
+ break;
+
+ if(widget && widget->window()->isVisible()) {
+ QWidget *tlw = widget->window();
+ if(tlw->isWindow() && !(tlw->windowType() == Qt::Popup)
+ && !qt_mac_is_macdrawer(tlw)
+ && (!tlw->parentWidget() || tlw->isModal()
+ || !(tlw->windowType() == Qt::Tool))) {
+ bool just_send_event = false;
+ {
+ WindowActivationScope scope;
+ if(GetWindowActivationScope((WindowRef)wid, &scope) == noErr &&
+ scope == kWindowActivationScopeIndependent) {
+ if(GetFrontWindowOfClass(kAllWindowClasses, true) != wid)
+ just_send_event = true;
+ }
+ }
+ if(just_send_event) {
+ QEvent e(QEvent::WindowActivate);
+ QApplication::sendSpontaneousEvent(widget, &e);
+ } else {
+ app->setActiveWindow(tlw);
+ }
+ }
+ QMenuBar::macUpdateMenuBar();
+ }
+ } else if(ekind == kEventWindowDeactivated) {
+ if(widget && QApplicationPrivate::active_window == widget)
+ app->setActiveWindow(0);
+ } else {
+ handled_event = false;
+ }
+ break; }
+ case kEventClassApplication:
+ if(ekind == kEventAppActivated) {
+ if(QApplication::desktopSettingsAware())
+ qt_mac_update_os_settings();
+ if(qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
+ QEvent ev(QEvent::Clipboard);
+ QApplication::sendSpontaneousEvent(qt_clipboard, &ev);
+ }
+ if(app) {
+ QEvent ev(QEvent::ApplicationActivate);
+ QApplication::sendSpontaneousEvent(app, &ev);
+ }
+ if(!app->activeWindow()) {
+ WindowPtr wp = ActiveNonFloatingWindow();
+ if(QWidget *tmp_w = qt_mac_find_window(wp))
+ app->setActiveWindow(tmp_w);
+ }
+ QMenuBar::macUpdateMenuBar();
+ } else if(ekind == kEventAppDeactivated) {
+ //qt_mac_no_click_through_mode = false;
+ while(app->d_func()->inPopupMode())
+ app->activePopupWidget()->close();
+ if(app) {
+ QEvent ev(QEvent::ApplicationDeactivate);
+ QApplication::sendSpontaneousEvent(app, &ev);
+ }
+ app->setActiveWindow(0);
+ } else if(ekind == kEventAppAvailableWindowBoundsChanged) {
+ QDesktopWidgetImplementation::instance()->onResize();
+ } else {
+ handled_event = false;
+ }
+ break;
+ case kAppearanceEventClass:
+ if(ekind == kAEAppearanceChanged) {
+ if(QApplication::desktopSettingsAware())
+ qt_mac_update_os_settings();
+ if(QApplicationPrivate::app_style) {
+ QEvent ev(QEvent::Style);
+ QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
+ }
+ } else {
+ handled_event = false;
+ }
+ break;
+ case kEventClassAppleEvent:
+ if(ekind == kEventAppleEvent) {
+ EventRecord erec;
+ if(!ConvertEventRefToEventRecord(event, &erec))
+ qDebug("Qt: internal: WH0A, unexpected condition reached. %s:%d", __FILE__, __LINE__);
+ else if(AEProcessAppleEvent(&erec) != noErr)
+ handled_event = false;
+ } else {
+ handled_event = false;
+ }
+ break;
+ case kEventClassCommand:
+ if(ekind == kEventCommandProcess) {
+ HICommand cmd;
+ GetEventParameter(event, kEventParamDirectObject, typeHICommand,
+ 0, sizeof(cmd), 0, &cmd);
+ handled_event = false;
+ if(!cmd.menu.menuRef && GetApplicationDockTileMenu()) {
+ EventRef copy = CopyEvent(event);
+ HICommand copy_cmd;
+ GetEventParameter(event, kEventParamDirectObject, typeHICommand,
+ 0, sizeof(copy_cmd), 0, &copy_cmd);
+ copy_cmd.menu.menuRef = GetApplicationDockTileMenu();
+ SetEventParameter(copy, kEventParamDirectObject, typeHICommand, sizeof(copy_cmd), &copy_cmd);
+ if(SendEventToMenu(copy, copy_cmd.menu.menuRef) == noErr)
+ handled_event = true;
+ }
+ if(!handled_event) {
+ if(cmd.commandID == kHICommandQuit) {
+ handled_event = true;
+ HiliteMenu(0);
+ bool handle_quit = true;
+ if(QApplicationPrivate::modalState()) {
+ int visible = 0;
+ const QWidgetList tlws = QApplication::topLevelWidgets();
+ for(int i = 0; i < tlws.size(); ++i) {
+ if(tlws.at(i)->isVisible())
+ ++visible;
+ }
+ handle_quit = (visible <= 1);
+ }
+ if(handle_quit) {
+ QCloseEvent ev;
+ QApplication::sendSpontaneousEvent(app, &ev);
+ if(ev.isAccepted())
+ app->quit();
+ } else {
+ QApplication::beep();
+ }
+ } else if(cmd.commandID == kHICommandSelectWindow) {
+ if((GetCurrentKeyModifiers() & cmdKey))
+ handled_event = true;
+ } else if(cmd.commandID == kHICommandAbout) {
+ QMessageBox::aboutQt(0);
+ HiliteMenu(0);
+ handled_event = true;
+ }
+ }
+ }
+ break;
+ }
+
+#ifdef DEBUG_EVENTS
+ qDebug("%shandled event %c%c%c%c %d", handled_event ? "(*) " : "",
+ char(eclass >> 24), char((eclass >> 16) & 255), char((eclass >> 8) & 255),
+ char(eclass & 255), (int)ekind);
+#endif
+ if(!handled_event) //let the event go through
+ return eventNotHandledErr;
+ return noErr; //we eat the event
+#else
+ Q_UNUSED(er);
+ Q_UNUSED(event);
+ Q_UNUSED(data);
+ return eventNotHandledErr;
+#endif
+}
+
+OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, AppleEvent *, long handlerRefcon)
+{
+ QApplication *app = (QApplication *)handlerRefcon;
+ bool handled_event=false;
+ OSType aeID=typeWildCard, aeClass=typeWildCard;
+ AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0);
+ AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
+ if(aeClass == kCoreEventClass) {
+ switch(aeID) {
+ case kAEQuitApplication: {
+ extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp
+ if(!QApplicationPrivate::modalState() && qt_mac_quit_menu_item_enabled) {
+ QCloseEvent ev;
+ QApplication::sendSpontaneousEvent(app, &ev);
+ if(ev.isAccepted()) {
+ handled_event = true;
+ app->quit();
+ }
+ } else {
+ QApplication::beep(); // Sorry, you can't quit right now.
+ }
+ break; }
+ case kAEOpenDocuments: {
+ AEDescList docs;
+ if(AEGetParamDesc(ae, keyDirectObject, typeAEList, &docs) == noErr) {
+ long cnt = 0;
+ AECountItems(&docs, &cnt);
+ UInt8 *str_buffer = NULL;
+ for(int i = 0; i < cnt; i++) {
+ FSRef ref;
+ if(AEGetNthPtr(&docs, i+1, typeFSRef, 0, 0, &ref, sizeof(ref), 0) != noErr)
+ continue;
+ if(!str_buffer)
+ str_buffer = (UInt8 *)malloc(1024);
+ FSRefMakePath(&ref, str_buffer, 1024);
+ QFileOpenEvent ev(QString::fromUtf8((const char *)str_buffer));
+ QApplication::sendSpontaneousEvent(app, &ev);
+ }
+ if(str_buffer)
+ free(str_buffer);
+ }
+ break; }
+ default:
+ break;
+ }
+ }
+#ifdef DEBUG_EVENTS
+ qDebug("Qt: internal: %shandled Apple event! %c%c%c%c %c%c%c%c", handled_event ? "(*)" : "",
+ char(aeID >> 24), char((aeID >> 16) & 255), char((aeID >> 8) & 255),char(aeID & 255),
+ char(aeClass >> 24), char((aeClass >> 16) & 255), char((aeClass >> 8) & 255),char(aeClass & 255));
+#else
+ if(!handled_event) //let the event go through
+ return eventNotHandledErr;
+ return noErr; //we eat the event
+#endif
+}
+
+/*!
+ \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event)
+
+ \warning This virtual function is only implemented under Mac OS X when against Carbon.
+
+ If you create an application that inherits QApplication and reimplement
+ this function, you get direct access to all Carbon Events that Qt registers
+ for from Mac OS X with this function being called with the \a caller and
+ the \a event.
+
+ Return true if you want to stop the event from being processed.
+ Return false for normal event dispatching. The default
+ implementation returns false.
+
+ Cocoa uses a different event system which means this function is NOT CALLED
+ when building Qt against Cocoa. If you want similar functionality subclass
+ NSApplication and reimplement the sendEvent: message to handle all the
+ NSEvents. You also will need to to instantiate your custom NSApplication
+ before creating a QApplication. See \l
+ {http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html}{Apple's
+ NSApplication Reference} for more information.
+
+*/
+bool QApplication::macEventFilter(EventHandlerCallRef, EventRef)
+{
+ return false;
+}
+
+/*!
+ \internal
+*/
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets) // create list
+ QApplicationPrivate::popupWidgets = new QWidgetList;
+ QApplicationPrivate::popupWidgets->append(popup); // add to end of list
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
+ popup->setFocus(Qt::PopupFocusReason);
+ }
+}
+
+/*!
+ \internal
+*/
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ Q_Q(QApplication);
+ if (!QApplicationPrivate::popupWidgets)
+ return;
+
+ QApplicationPrivate::popupWidgets->removeAll(popup);
+ if (popup == qt_button_down)
+ qt_button_down = 0;
+ if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+
+ // Special case for Tool windows: since they are activated and deactived together
+ // with a normal window they never become the QApplicationPrivate::active_window.
+ QWidget *appFocusWidget = QApplication::focusWidget();
+ if (appFocusWidget && appFocusWidget->window()->windowType() == Qt::Tool) {
+ appFocusWidget->setFocus(Qt::PopupFocusReason);
+ } else if (QApplicationPrivate::active_window) {
+ if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q->sendEvent(fw, &e);
+ }
+ }
+ }
+ } else {
+ // popups are not focus-handled by the window system (the
+ // first popup grabbed the keyboard), so we have to do that
+ // manually: A popup was closed, so the previous popup gets
+ // the focus.
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+ }
+}
+
+void QApplication::beep()
+{
+ qt_mac_beep();
+}
+
+void QApplication::alert(QWidget *widget, int duration)
+{
+ if (!QApplicationPrivate::checkInstance("alert"))
+ return;
+
+ QWidgetList windowsToMark;
+ if (!widget)
+ windowsToMark += topLevelWidgets();
+ else
+ windowsToMark.append(widget->window());
+
+ bool needNotification = false;
+ for (int i = 0; i < windowsToMark.size(); ++i) {
+ QWidget *window = windowsToMark.at(i);
+ if (!window->isActiveWindow() && window->isVisible()) {
+ needNotification = true; // yeah, we may set it multiple times, but that's OK.
+ if (duration != 0) {
+ QTimer *timer = new QTimer(qApp);
+ timer->setSingleShot(true);
+ connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut()));
+ if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(widget)) {
+ qApp->d_func()->alertTimerHash.remove(widget);
+ delete oldTimer;
+ }
+ qApp->d_func()->alertTimerHash.insert(widget, timer);
+ timer->start(duration);
+ }
+ }
+ }
+ if (needNotification)
+ qt_mac_send_notification();
+}
+
+void QApplicationPrivate::_q_alertTimeOut()
+{
+ if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) {
+ QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin();
+ while (it != alertTimerHash.end()) {
+ if (it.value() == timer) {
+ alertTimerHash.erase(it);
+ timer->deleteLater();
+ break;
+ }
+ ++it;
+ }
+ if (alertTimerHash.isEmpty()) {
+ qt_mac_cancel_notification();
+ }
+ }
+}
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ qt_mac_dblclick.use_qt_time_limit = true;
+ QApplicationPrivate::mouse_double_click_time = ms;
+}
+
+int QApplication::doubleClickInterval()
+{
+ if (!qt_mac_dblclick.use_qt_time_limit) { //get it from the system
+ QSettings appleSettings(QLatin1String("apple.com"));
+ /* First worked as of 10.3.3 */
+ double dci = appleSettings.value(QLatin1String("com/apple/mouse/doubleClickThreshold"), 0.5).toDouble();
+ return int(dci * 1000);
+ }
+ return QApplicationPrivate::mouse_double_click_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::keyboardInputInterval()
+{
+ // FIXME: get from the system
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+void QApplication::setWheelScrollLines(int n)
+{
+ QApplicationPrivate::wheel_scroll_lines = n;
+}
+
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ switch (effect) {
+ case Qt::UI_FadeMenu:
+ QApplicationPrivate::fade_menu = enable;
+ break;
+ case Qt::UI_AnimateMenu:
+ QApplicationPrivate::animate_menu = enable;
+ break;
+ case Qt::UI_FadeTooltip:
+ QApplicationPrivate::fade_tooltip = enable;
+ break;
+ case Qt::UI_AnimateTooltip:
+ QApplicationPrivate::animate_tooltip = enable;
+ break;
+ case Qt::UI_AnimateCombo:
+ QApplicationPrivate::animate_combo = enable;
+ break;
+ case Qt::UI_AnimateToolBox:
+ QApplicationPrivate::animate_toolbox = enable;
+ break;
+ case Qt::UI_General:
+ QApplicationPrivate::fade_tooltip = true;
+ break;
+ default:
+ QApplicationPrivate::animate_ui = enable;
+ break;
+ }
+
+ if (enable)
+ QApplicationPrivate::animate_ui = true;
+}
+
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
+ return false;
+
+ switch(effect) {
+ case Qt::UI_AnimateMenu:
+ return QApplicationPrivate::animate_menu;
+ case Qt::UI_FadeMenu:
+ return QApplicationPrivate::fade_menu;
+ case Qt::UI_AnimateCombo:
+ return QApplicationPrivate::animate_combo;
+ case Qt::UI_AnimateTooltip:
+ return QApplicationPrivate::animate_tooltip;
+ case Qt::UI_FadeTooltip:
+ return QApplicationPrivate::fade_tooltip;
+ case Qt::UI_AnimateToolBox:
+ return QApplicationPrivate::animate_toolbox;
+ default:
+ break;
+ }
+ return QApplicationPrivate::animate_ui;
+}
+
+/*!
+ \internal
+*/
+bool QApplicationPrivate::qt_mac_apply_settings()
+{
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+
+ /*
+ Qt settings. This is how they are written into the datastream.
+ Palette/ * - QPalette
+ font - QFont
+ libraryPath - QStringList
+ style - QString
+ doubleClickInterval - int
+ cursorFlashTime - int
+ wheelScrollLines - int
+ colorSpec - QString
+ defaultCodec - QString
+ globalStrut/width - int
+ globalStrut/height - int
+ GUIEffects - QStringList
+ Font Substitutions/ * - QStringList
+ Font Substitutions/... - QStringList
+ */
+
+ // read library (ie. plugin) path list
+ QString libpathkey =
+ QString::fromLatin1("%1.%2/libraryPath")
+ .arg(QT_VERSION >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8);
+ QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
+ if (!pathlist.isEmpty()) {
+ QStringList::ConstIterator it = pathlist.begin();
+ while(it != pathlist.end())
+ QApplication::addLibraryPath(*it++);
+ }
+
+ QString defaultcodec = settings.value(QLatin1String("defaultCodec"), QVariant(QLatin1String("none"))).toString();
+ if (defaultcodec != QLatin1String("none")) {
+ QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1().constData());
+ if (codec)
+ QTextCodec::setCodecForTr(codec);
+ }
+
+ if (qt_is_gui_used) {
+ QString str;
+ QStringList strlist;
+ int num;
+
+ // read new palette
+ int i;
+ QPalette pal(QApplication::palette());
+ strlist = settings.value(QLatin1String("Palette/active")).toStringList();
+ if (strlist.count() == QPalette::NColorRoles) {
+ for (i = 0; i < QPalette::NColorRoles; i++)
+ pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+ strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
+ if (strlist.count() == QPalette::NColorRoles) {
+ for (i = 0; i < QPalette::NColorRoles; i++)
+ pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+ strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
+ if (strlist.count() == QPalette::NColorRoles) {
+ for (i = 0; i < QPalette::NColorRoles; i++)
+ pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+
+ if (pal != QApplication::palette())
+ QApplication::setPalette(pal);
+
+ // read new font
+ QFont font(QApplication::font());
+ str = settings.value(QLatin1String("font")).toString();
+ if (!str.isEmpty()) {
+ font.fromString(str);
+ if (font != QApplication::font())
+ QApplication::setFont(font);
+ }
+
+ // read new QStyle
+ QString stylename = settings.value(QLatin1String("style")).toString();
+ if (! stylename.isNull() && ! stylename.isEmpty()) {
+ QStyle *style = QStyleFactory::create(stylename);
+ if (style)
+ QApplication::setStyle(style);
+ else
+ stylename = QLatin1String("default");
+ } else {
+ stylename = QLatin1String("default");
+ }
+
+ num = settings.value(QLatin1String("doubleClickInterval"),
+ QApplication::doubleClickInterval()).toInt();
+ QApplication::setDoubleClickInterval(num);
+
+ num = settings.value(QLatin1String("cursorFlashTime"),
+ QApplication::cursorFlashTime()).toInt();
+ QApplication::setCursorFlashTime(num);
+
+ num = settings.value(QLatin1String("wheelScrollLines"),
+ QApplication::wheelScrollLines()).toInt();
+ QApplication::setWheelScrollLines(num);
+
+ QString colorspec = settings.value(QLatin1String("colorSpec"),
+ QVariant(QLatin1String("default"))).toString();
+ if (colorspec == QLatin1String("normal"))
+ QApplication::setColorSpec(QApplication::NormalColor);
+ else if (colorspec == QLatin1String("custom"))
+ QApplication::setColorSpec(QApplication::CustomColor);
+ else if (colorspec == QLatin1String("many"))
+ QApplication::setColorSpec(QApplication::ManyColor);
+ else if (colorspec != QLatin1String("default"))
+ colorspec = QLatin1String("default");
+
+ int w = settings.value(QLatin1String("globalStrut/width")).toInt();
+ int h = settings.value(QLatin1String("globalStrut/height")).toInt();
+ QSize strut(w, h);
+ if (strut.isValid())
+ QApplication::setGlobalStrut(strut);
+
+ QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
+ if (!effects.isEmpty()) {
+ if (effects.contains(QLatin1String("none")))
+ QApplication::setEffectEnabled(Qt::UI_General, false);
+ if (effects.contains(QLatin1String("general")))
+ QApplication::setEffectEnabled(Qt::UI_General, true);
+ if (effects.contains(QLatin1String("animatemenu")))
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu, true);
+ if (effects.contains(QLatin1String("fademenu")))
+ QApplication::setEffectEnabled(Qt::UI_FadeMenu, true);
+ if (effects.contains(QLatin1String("animatecombo")))
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo, true);
+ if (effects.contains(QLatin1String("animatetooltip")))
+ QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, true);
+ if (effects.contains(QLatin1String("fadetooltip")))
+ QApplication::setEffectEnabled(Qt::UI_FadeTooltip, true);
+ if (effects.contains(QLatin1String("animatetoolbox")))
+ QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, true);
+ } else {
+ QApplication::setEffectEnabled(Qt::UI_General, true);
+ }
+
+ settings.beginGroup(QLatin1String("Font Substitutions"));
+ QStringList fontsubs = settings.childKeys();
+ if (!fontsubs.isEmpty()) {
+ QStringList::Iterator it = fontsubs.begin();
+ for (; it != fontsubs.end(); ++it) {
+ QString fam = QString::fromLatin1((*it).toLatin1().constData());
+ QStringList subs = settings.value(fam).toStringList();
+ QFont::insertSubstitutions(fam, subs);
+ }
+ }
+ settings.endGroup();
+ }
+
+ settings.endGroup();
+ return true;
+}
+
+// DRSWAT
+
+bool QApplicationPrivate::canQuit()
+{
+#ifndef QT_MAC_USE_COCOA
+ return true;
+#else
+ Q_Q(QApplication);
+#ifdef QT_MAC_USE_COCOA
+ [[NSApp mainMenu] cancelTracking];
+#else
+ HiliteMenu(0);
+#endif
+
+ bool handle_quit = true;
+ if (QApplicationPrivate::modalState() && [[[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]
+ menuLoader] quitMenuItem] isEnabled]) {
+ int visible = 0;
+ const QWidgetList tlws = QApplication::topLevelWidgets();
+ for(int i = 0; i < tlws.size(); ++i) {
+ if (tlws.at(i)->isVisible())
+ ++visible;
+ }
+ handle_quit = (visible <= 1);
+ }
+ if (handle_quit) {
+ QCloseEvent ev;
+ QApplication::sendSpontaneousEvent(q, &ev);
+ if (ev.isAccepted()) {
+ return true;
+ }
+ }
+ return false;
+#endif
+}
+
+void onApplicationWindowChangedActivation( QWidget*widget, bool activated )
+{
+#if QT_MAC_USE_COCOA
+ QApplication *app = qApp;
+
+ if ( activated )
+ {
+ if (QApplicationPrivate::app_style)
+ {
+ QEvent ev(QEvent::Style);
+ qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
+ }
+
+ if (widget && app_do_modal && !qt_try_modal(widget, NULL))
+ return;
+
+ if (widget && widget->window()->isVisible())
+ {
+ QWidget *tlw = widget->window();
+
+ if (tlw->isWindow() && !(tlw->windowType() == Qt::Popup)
+ && !qt_mac_is_macdrawer(tlw)
+ && (!tlw->parentWidget() || tlw->isModal() || !(tlw->windowType() == Qt::Tool))) {
+ bool just_send_event = false;
+#if 0
+ WindowActivationScope scope;
+ if ( GetWindowActivationScope((OSWindowRef)wid, &scope) == noErr &&
+ scope == kWindowActivationScopeIndependent)
+ {
+ if ( GetFrontWindowOfClass(kAllWindowClasses, true) != wid )
+ just_send_event = true;
+ }
+#endif
+ if (just_send_event) {
+ QEvent e(QEvent::WindowActivate);
+ qt_sendSpontaneousEvent(widget, &e);
+ } else {
+ app->setActiveWindow(tlw);
+ }
+ }
+ }
+ } else { // deactivated
+ if (widget && QApplicationPrivate::active_window == widget)
+ app->setActiveWindow(0);
+ }
+ QMenuBar::macUpdateMenuBar();
+#else
+ Q_UNUSED(widget);
+ Q_UNUSED(activated);
+#endif
+}
+
+
+void onApplicationChangedActivation( bool activated )
+{
+#if QT_MAC_USE_COCOA
+ QApplication *app = qApp;
+
+//NSLog(@"App Changed Activation\n");
+
+ if ( activated ) {
+ if (QApplication::desktopSettingsAware())
+ qt_mac_update_os_settings();
+
+ if (qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
+ QEvent ev(QEvent::Clipboard);
+ qt_sendSpontaneousEvent(qt_clipboard, &ev);
+ }
+
+ if (app) {
+ QEvent ev(QEvent::ApplicationActivate);
+ qt_sendSpontaneousEvent(app, &ev);
+ }
+
+ if (!app->activeWindow()) {
+#if QT_MAC_USE_COCOA
+ OSWindowRef wp = [NSApp keyWindow];
+#else
+ OSWindowRef wp = ActiveNonFloatingWindow();
+#endif
+ if (QWidget *tmp_w = qt_mac_find_window(wp))
+ app->setActiveWindow(tmp_w);
+ }
+ QMenuBar::macUpdateMenuBar();
+ } else { // de-activated
+ QApplicationPrivate *priv = [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate];
+ while (priv->inPopupMode())
+ app->activePopupWidget()->close();
+ if (app) {
+ QEvent ev(QEvent::ApplicationDeactivate);
+ qt_sendSpontaneousEvent(app, &ev);
+ }
+ app->setActiveWindow(0);
+ }
+#else
+ Q_UNUSED(activated);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
new file mode 100644
index 0000000000..7487f0a919
--- /dev/null
+++ b/src/gui/kernel/qapplication_p.h
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAPPLICATION_P_H
+#define QAPPLICATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qapplication.h"
+#include "QtGui/qfont.h"
+#include "QtGui/qcursor.h"
+#include "QtGui/qregion.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qtranslator.h"
+#include "QtCore/qbasictimer.h"
+#include "QtCore/qhash.h"
+#include "QtCore/qpointer.h"
+#include "private/qcoreapplication_p.h"
+#include "private/qshortcutmap_p.h"
+#include <private/qthread_p.h>
+#ifdef Q_WS_QWS
+#include "QtGui/qscreen_qws.h"
+#include <private/qgraphicssystem_qws_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QClipboard;
+class QGraphicsScene;
+class QGraphicsSystem;
+class QInputContext;
+class QKeyEvent;
+class QMouseEvent;
+class QObject;
+class QWheelEvent;
+class QWidget;
+
+extern bool qt_is_gui_used;
+#ifndef QT_NO_CLIPBOARD
+extern QClipboard *qt_clipboard;
+#endif
+
+#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN) || defined(Q_OS_WINCE)
+extern QSysInfo::WinVersion qt_winver;
+enum { QT_TABLET_NPACKETQSIZE = 128 };
+# ifdef Q_OS_WINCE
+ extern DWORD qt_cever;
+# endif
+#elif defined (Q_OS_MAC)
+extern QSysInfo::MacVersion qt_macver;
+#endif
+#if defined(Q_WS_QWS)
+class QWSManager;
+class QDirectPainter;
+#endif
+
+#ifndef QT_NO_TABLET
+struct QTabletDeviceData
+{
+#ifndef Q_WS_MAC
+ int minPressure;
+ int maxPressure;
+ int minTanPressure;
+ int maxTanPressure;
+ int minX, maxX, minY, maxY, minZ, maxZ;
+ inline QPointF scaleCoord(int coordX, int coordY, int outOriginX, int outExtentX,
+ int outOriginY, int outExtentY) const;
+#endif
+
+#if defined(Q_WS_X11) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
+ QPointer<QWidget> widgetToGetPress;
+#endif
+
+#ifdef Q_WS_X11
+ int deviceType;
+ enum {
+ TOTAL_XINPUT_EVENTS = 64
+ };
+ void *device;
+ int eventCount;
+ long unsigned int eventList[TOTAL_XINPUT_EVENTS]; // XEventClass is in fact a long unsigned int
+
+ int xinput_motion;
+ int xinput_key_press;
+ int xinput_key_release;
+ int xinput_button_press;
+ int xinput_button_release;
+ int xinput_proximity_in;
+ int xinput_proximity_out;
+#elif defined(Q_WS_WIN)
+ qint64 llId;
+ int currentDevice;
+ int currentPointerType;
+#elif defined(Q_WS_MAC)
+ quint64 tabletUniqueID;
+ int tabletDeviceType;
+ int tabletPointerType;
+ int capabilityMask;
+#endif
+};
+
+static inline int sign(int x)
+{
+ return x >= 0 ? 1 : -1;
+}
+
+#ifndef Q_WS_MAC
+inline QPointF QTabletDeviceData::scaleCoord(int coordX, int coordY,
+ int outOriginX, int outExtentX,
+ int outOriginY, int outExtentY) const
+{
+ QPointF ret;
+ if (sign(outExtentX) == sign(maxX))
+ ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX))) + outOriginX);
+ else
+ ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX)))
+ + outOriginX);
+
+ if (sign(outExtentY) == sign(maxY))
+ ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY))) + outOriginY);
+ else
+ ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY)))
+ + outOriginY);
+ return ret;
+}
+#endif
+
+typedef QList<QTabletDeviceData> QTabletDeviceDataList;
+QTabletDeviceDataList *qt_tablet_devices();
+# if defined(Q_WS_MAC)
+typedef QHash<int, QTabletDeviceData> QMacTabletHash;
+QMacTabletHash *qt_mac_tablet_hash();
+# endif
+#endif
+
+#ifdef QT3_SUPPORT
+extern "C" {
+ typedef bool (*Ptrqt_tryAccelEvent)(QWidget *w, QKeyEvent *e);
+ typedef bool (*Ptrqt_tryComposeUnicode)(QWidget *w, QKeyEvent *e);
+ typedef bool (*Ptrqt_dispatchAccelEvent)(QWidget *w, QKeyEvent *e);
+}
+#endif
+
+class QScopedLoopLevelCounter
+{
+ QThreadData *threadData;
+public:
+ QScopedLoopLevelCounter(QThreadData *threadData)
+ : threadData(threadData)
+ { ++threadData->loopLevel; }
+ ~QScopedLoopLevelCounter()
+ { --threadData->loopLevel; }
+};
+
+class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate
+{
+ Q_DECLARE_PUBLIC(QApplication)
+public:
+ QApplicationPrivate(int &argc, char **argv, QApplication::Type type);
+ ~QApplicationPrivate();
+
+#if defined(Q_WS_X11)
+#ifndef QT_NO_SETTINGS
+ static QString kdeHome();
+ static bool x11_apply_settings();
+#endif
+ static void reset_instance_pointer();
+#elif defined(Q_WS_QWS)
+ static bool qws_apply_settings();
+ static QWidget *findWidget(const QObjectList&, const QPoint &, bool rec);
+#endif
+ static bool quitOnLastWindowClosed;
+ static void emitLastWindowClosed();
+#ifdef Q_OS_WINCE
+ static int autoMaximizeThreshold;
+ static bool autoSipEnabled;
+#endif
+
+ static QGraphicsSystem *graphicsSystem()
+#if !defined(Q_WS_QWS)
+ { return graphics_system; }
+#else
+ { return QScreen::instance()->graphicsSystem(); }
+#endif
+
+ void createEventDispatcher();
+ QString appName() const;
+
+ static void dispatchEnterLeave(QWidget *enter, QWidget *leave);
+
+ //modality
+ static void enterModal(QWidget*);
+ static void leaveModal(QWidget*);
+ static void enterModal_sys(QWidget*);
+ static void leaveModal_sys(QWidget*);
+ static bool isBlockedByModal(QWidget *widget);
+ static bool modalState();
+ static bool tryModalHelper(QWidget *widget, QWidget **rettop = 0);
+#ifdef Q_WS_MAC
+ static QWidget *tryModalHelper_sys(QWidget *top);
+ bool canQuit();
+#endif
+
+ bool notify_helper(QObject *receiver, QEvent * e);
+
+ void construct(
+#ifdef Q_WS_X11
+ Display *dpy = 0, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0
+#endif
+ );
+ void initialize();
+ void process_cmdline();
+
+#if defined(Q_WS_X11)
+ static void x11_initialize_style();
+#endif
+
+ enum KeyPlatform {
+ KB_Win = 1,
+ KB_Mac = 2,
+ KB_X11 = 4,
+ KB_KDE = 8,
+ KB_Gnome = 16,
+ KB_CDE = 32,
+ KB_All = 0xffff
+ };
+
+ static uint currentPlatform();
+ bool inPopupMode() const;
+ void closePopup(QWidget *popup);
+ void openPopup(QWidget *popup);
+ static void setFocusWidget(QWidget *focus, Qt::FocusReason reason);
+ static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next);
+
+#ifndef QT_NO_SESSIONMANAGER
+ QSessionManager *session_manager;
+ QString session_id;
+ QString session_key;
+ bool is_session_restored;
+#endif
+
+#ifndef QT_NO_CURSOR
+ QList<QCursor> cursor_list;
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+ // Maintain a list of all scenes to ensure font and palette propagation to
+ // all scenes.
+ QList<QGraphicsScene *> scene_list;
+#endif
+
+ QBasicTimer toolTipWakeUp, toolTipFallAsleep;
+ QPoint toolTipPos, toolTipGlobalPos, hoverGlobalPos;
+ QPointer<QWidget> toolTipWidget;
+#ifndef QT_NO_SHORTCUT
+ QShortcutMap shortcutMap;
+#endif
+
+#ifdef QT3_SUPPORT
+ bool qt_compat_used;
+ bool qt_compat_resolved;
+ Ptrqt_tryAccelEvent qt_tryAccelEvent;
+ Ptrqt_tryComposeUnicode qt_tryComposeUnicode;
+ Ptrqt_dispatchAccelEvent qt_dispatchAccelEvent;
+
+ bool use_compat() {
+ return qt_tryAccelEvent
+ && qt_tryComposeUnicode
+ && qt_dispatchAccelEvent;
+ }
+#endif
+ static QInputContext *inputContext;
+
+ static Qt::MouseButtons mouse_buttons;
+ static Qt::KeyboardModifiers modifier_buttons;
+
+ static QSize app_strut;
+ static QWidgetList *popupWidgets;
+ static QStyle *app_style;
+ static int app_cspec;
+ static QPalette *app_pal;
+ static QPalette *sys_pal;
+ static QPalette *set_pal;
+ static QGraphicsSystem *graphics_system;
+ static QString graphics_system_name;
+
+private:
+ static QFont *app_font; // private for a reason! Always use QApplication::font() instead!
+public:
+ static QFont *sys_font;
+ static QFont *set_font;
+ static QWidget *main_widget;
+ static QWidget *focus_widget;
+ static QWidget *hidden_focus_widget;
+ static QWidget *active_window;
+ static QIcon *app_icon;
+ static bool obey_desktop_settings;
+ static int cursor_flash_time;
+ static int mouse_double_click_time;
+ static int keyboard_input_time;
+ static int wheel_scroll_lines;
+
+ static bool animate_ui;
+ static bool animate_menu;
+ static bool animate_tooltip;
+ static bool animate_combo;
+ static bool fade_menu;
+ static bool fade_tooltip;
+ static bool animate_toolbox;
+ static bool widgetCount; // Coupled with -widgetcount switch
+#ifdef Q_WS_MAC
+ static bool native_modal_dialog_active;
+#endif
+#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+ static bool inSizeMove;
+#endif
+
+ static void setSystemPalette(const QPalette &pal);
+ static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash);
+ static void initializeWidgetPaletteHash();
+ static void setSystemFont(const QFont &font);
+
+#if defined(Q_WS_X11)
+ static void applyX11SpecificCommandLineArguments(QWidget *main_widget);
+#elif defined(Q_WS_QWS)
+ static void applyQWSSpecificCommandLineArguments(QWidget *main_widget);
+#endif
+
+#ifdef Q_WS_MAC
+ static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
+ static OSStatus globalAppleEventProcessor(const AppleEvent *, AppleEvent *, long);
+ static OSStatus tabletProximityCallback(EventHandlerCallRef, EventRef, void *);
+ static bool qt_mac_apply_settings();
+#endif
+
+#ifdef Q_WS_QWS
+ QPointer<QWSManager> last_manager;
+# ifndef QT_NO_DIRECTPAINTER
+ QMap<WId, QDirectPainter *> *directPainters;
+# endif
+ QRect maxWindowRect(const QScreen *screen) const { return maxWindowRects[screen]; }
+ void setMaxWindowRect(const QScreen *screen, int screenNo, const QRect &rect);
+ void setScreenTransformation(QScreen *screen, int screenNo, int transformation);
+#endif
+
+ static QApplicationPrivate *instance() { return self; }
+
+ static QString *styleOverride;
+
+ static int app_compile_version;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ static bool keypadNavigation;
+ static QWidget *oldEditFocus;
+#endif
+
+#if defined(Q_WS_MAC) || defined(Q_WS_X11)
+ void _q_alertTimeOut();
+ QHash<QWidget *, QTimer *> alertTimerHash;
+#endif
+#if defined(QT_MAC_USE_COCOA)
+ void _q_runAppModalWindow();
+#endif
+#if defined(QT_MAC_USE_COCOA)
+ void _q_runModalWindow();
+#endif
+#ifndef QT_NO_STYLE_STYLESHEET
+ static QString styleSheet;
+#endif
+ static QPointer<QWidget> leaveAfterRelease;
+ static QWidget *pickMouseReceiver(QWidget *candidate, const QPoint &globalPos, QPoint &pos,
+ QEvent::Type type, Qt::MouseButtons buttons,
+ QWidget *buttonDown, QWidget *alienWidget);
+ static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
+ QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver);
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ void sendSyntheticEnterLeave(QWidget *widget);
+#endif
+
+private:
+#ifdef Q_WS_QWS
+ QMap<const QScreen*, QRect> maxWindowRects;
+#endif
+
+ static QApplicationPrivate *self;
+ static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
+};
+
+QT_END_NAMESPACE
+
+#endif // QAPPLICATION_P_H
diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp
new file mode 100644
index 0000000000..2deda8e7df
--- /dev/null
+++ b/src/gui/kernel/qapplication_qws.cpp
@@ -0,0 +1,3817 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+#include "qlibrary.h"
+#include "qcursor.h"
+#include "qapplication.h"
+#include "private/qapplication_p.h"
+#include "qwidget.h"
+#include "qbitarray.h"
+#include "qpainter.h"
+#include "qpixmapcache.h"
+#include "qdatetime.h"
+#include "qtextcodec.h"
+#include "qdatastream.h"
+#include "qbuffer.h"
+#include "qsocketnotifier.h"
+#include "qsessionmanager.h"
+#include "qclipboard.h"
+#include "qbitmap.h"
+#include "qwssocket_qws.h"
+#include "qtransportauth_qws.h"
+#include "private/qtransportauth_qws_p.h"
+#include "qwsevent_qws.h"
+#include "private/qwscommand_qws_p.h"
+#include "qwsproperty_qws.h"
+#include "qscreen_qws.h"
+#include "qscreenproxy_qws.h"
+#include "qcopchannel_qws.h"
+#include "private/qlock_p.h"
+#include "private/qwslock_p.h"
+//#include "qmemorymanager_qws.h"
+#include "qwsmanager_qws.h"
+//#include "qwsregionmanager_qws.h"
+#include "qwindowsystem_qws.h"
+#include "private/qwindowsystem_p.h"
+
+#include "qwsdisplay_qws.h"
+#include "private/qwsdisplay_qws_p.h"
+#include "private/qwsinputcontext_p.h"
+#include "qfile.h"
+#include "qhash.h"
+#include "qdesktopwidget.h"
+#include "qcolormap.h"
+#include "private/qcursor_p.h"
+#include "qsettings.h"
+#include "qdebug.h"
+#include "qeventdispatcher_qws_p.h"
+#if !defined(QT_NO_GLIB)
+# include "qeventdispatcher_glib_qws_p.h"
+#endif
+
+
+#include "private/qwidget_p.h"
+#include "private/qbackingstore_p.h"
+#include "private/qwindowsurface_qws_p.h"
+#include "private/qfont_p.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+#ifdef QT_NO_QSHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#ifndef Q_OS_DARWIN
+# include <sys/sem.h>
+#endif
+#include <sys/socket.h>
+#else
+#include "private/qwssharedmemory_p.h"
+#endif
+#endif
+
+#ifndef QT_NO_DIRECTPAINTER
+class QDirectPainter;
+extern void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type);
+#ifndef QT_NO_QWSEMBEDWIDGET
+extern void qt_directpainter_embedevent(QDirectPainter *dp,
+ const QWSEmbedEvent *e);
+#endif
+#endif // QT_NO_DIRECTPAINTER
+
+const int qwsSharedRamSize = 1 * 1024; // misc data, written by server, read by clients
+
+extern QApplication::Type qt_appType;
+extern QDesktopWidget *qt_desktopWidget;
+
+//these used to be environment variables, they are initialized from
+//environment variables in
+
+bool qws_savefonts = false;
+bool qws_screen_is_interlaced=false; //### should be detected
+bool qws_shared_memory = false;
+bool qws_sw_cursor = true;
+bool qws_accel = true; // ### never set
+QByteArray qws_display_spec(":0");
+Q_GUI_EXPORT int qws_display_id = 0;
+Q_GUI_EXPORT int qws_client_id = 0;
+QWidget *qt_pressGrab = 0;
+QWidget *qt_mouseGrb = 0;
+int *qt_last_x = 0;
+int *qt_last_y = 0;
+
+static int mouse_x_root = -1;
+static int mouse_y_root = -1;
+static int mouse_state = 0;
+static int mouse_double_click_distance = 5;
+
+int qt_servershmid = -1;
+
+bool qws_overrideCursor = false;
+#ifndef QT_NO_QWS_MANAGER
+#include "qdecorationfactory_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+static QDecoration *qws_decoration = 0;
+#endif
+
+#if defined(QT_DEBUG)
+/*
+extern "C" void dumpmem(const char* m)
+{
+ static int init=0;
+ static int prev=0;
+ FILE* f = fopen("/proc/meminfo","r");
+ // char line[100];
+ int total=0,used=0,free=0,shared=0,buffers=0,cached=0;
+ fscanf(f,"%*[^M]Mem: %d %d %d %d %d %d",&total,&used,&free,&shared,&buffers,&cached);
+ used -= buffers + cached;
+ if (!init) {
+ init=used;
+ } else {
+ printf("%40s: %+8d = %8d\n",m,used-init-prev,used-init);
+ prev = used-init;
+ }
+ fclose(f);
+}
+*/
+#endif
+
+// Get the name of the directory where Qt for Embedded Linux temporary data should
+// live.
+QString qws_dataDir()
+{
+ static QString result;
+ if (!result.isEmpty())
+ return result;
+ QByteArray dataDir = QString(QLatin1String("/tmp/qtembedded-%1")).arg(qws_display_id).toLocal8Bit();
+ if (mkdir(dataDir, 0700)) {
+ if (errno != EEXIST) {
+ qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
+ }
+ }
+
+ struct stat buf;
+ if (lstat(dataDir, &buf))
+ qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData());
+
+ if (!S_ISDIR(buf.st_mode))
+ qFatal("%s is not a directory", dataDir.constData());
+
+#ifndef Q_OS_INTEGRITY
+ if (buf.st_uid != getuid())
+ qFatal("Qt for Embedded Linux data directory is not owned by user %d", getuid());
+
+ if ((buf.st_mode & 0677) != 0600)
+ qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData());
+#endif
+ dataDir += "/";
+
+ result = QString::fromLocal8Bit(dataDir);
+ return result;
+}
+
+// Get the filename of the pipe Qt for Embedded Linux uses for server/client comms
+Q_GUI_EXPORT QString qws_qtePipeFilename()
+{
+ return (qws_dataDir() + QString(QLatin1String(QTE_PIPE)).arg(qws_display_id));
+}
+
+static void setMaxWindowRect(const QRect &rect)
+{
+ const QList<QScreen*> subScreens = qt_screen->subScreens();
+ QScreen *screen = qt_screen;
+ int screenNo = 0;
+ for (int i = 0; i < subScreens.size(); ++i) {
+ if (subScreens.at(i)->region().contains(rect)) {
+ screen = subScreens.at(i);
+ screenNo = i;
+ break;
+ }
+ }
+
+ QApplicationPrivate *ap = QApplicationPrivate::instance();
+ ap->setMaxWindowRect(screen, screenNo, rect);
+}
+
+void QApplicationPrivate::setMaxWindowRect(const QScreen *screen, int screenNo,
+ const QRect &rect)
+{
+ if (maxWindowRects.value(screen) == rect)
+ return;
+
+ maxWindowRects[screen] = rect;
+
+ // Re-resize any maximized windows
+ QWidgetList l = QApplication::topLevelWidgets();
+ for (int i = 0; i < l.size(); ++i) {
+ QWidget *w = l.at(i);
+ QScreen *s = w->d_func()->getScreen();
+ if (w->isMaximized() && s == screen)
+ w->d_func()->setMaxWindowState_helper();
+ }
+
+ if ( qt_desktopWidget ) // XXX workaround crash
+ emit QApplication::desktop()->workAreaResized(screenNo);
+}
+
+#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+
+typedef void (*TransformFunc)(QScreen *, int);
+#ifndef QT_NO_QWS_TRANSFORMED
+extern "C" void qws_setScreenTransformation(QScreen *, int);
+#endif
+static TransformFunc getTransformationFunction()
+{
+ static TransformFunc func = 0;
+
+ if (!func) {
+#ifdef QT_NO_QWS_TRANSFORMED
+# ifndef QT_NO_LIBRARY
+ // symbol is not built into the library, search for the plugin
+ const QStringList paths = QApplication::libraryPaths();
+ foreach (const QString &path, paths) {
+ const QString file = path + QLatin1String("/gfxdrivers/libqgfxtransformed");
+ func = (TransformFunc)QLibrary::resolve(file,
+ "qws_setScreenTransformation");
+ if (func)
+ break;
+ }
+# endif
+#else
+ func = qws_setScreenTransformation;
+#endif
+ if (!func)
+ func = (TransformFunc)-1;
+ }
+
+ if (func == (TransformFunc)-1)
+ return 0;
+
+ return func;
+}
+
+static void setScreenTransformation(int screenNo, int transformation)
+{
+ QScreen *screen = QScreen::instance();
+ const QList<QScreen*> subScreens = screen->subScreens();
+
+ if (screenNo == -1)
+ screenNo = 0;
+
+ if (screenNo == -1 && !subScreens.isEmpty())
+ screenNo = 0;
+
+ if (subScreens.isEmpty() && screenNo == 0) {
+ // nothing
+ } else if (screenNo < 0 || screenNo >= subScreens.size()) {
+ qWarning("setScreenTransformation: invalid screen %i", screenNo);
+ return;
+ }
+
+ if (screenNo < subScreens.size())
+ screen = subScreens.at(screenNo);
+
+ QApplicationPrivate *ap = QApplicationPrivate::instance();
+ ap->setScreenTransformation(screen, screenNo, transformation);
+}
+
+void QApplicationPrivate::setScreenTransformation(QScreen *screen,
+ int screenNo,
+ int transformation)
+{
+ QScreen *transformed = screen;
+
+ while (transformed->classId() == QScreen::ProxyClass)
+ transformed = static_cast<QProxyScreen*>(transformed)->screen();
+
+ if (transformed->classId() != QScreen::TransformedClass)
+ return;
+
+ TransformFunc setScreenTransformation = getTransformationFunction();
+ if (!setScreenTransformation)
+ return;
+
+ setScreenTransformation(transformed, transformation);
+
+ // need to re-configure() proxies bottom-up
+ if (screen->classId() == QScreen::ProxyClass) {
+ QList<QProxyScreen*> proxies;
+ QScreen *s = screen;
+
+ do {
+ QProxyScreen *proxy = static_cast<QProxyScreen*>(s);
+ proxies.append(proxy);
+ s = proxy->screen();
+ } while (s->classId() == QScreen::ProxyClass);
+
+ do {
+ QProxyScreen *proxy = proxies.takeLast();
+ proxy->setScreen(proxy->screen()); // triggers configure()
+ } while (!proxies.isEmpty());
+ }
+
+ if (qt_desktopWidget) { // XXX workaround crash for early screen transform events
+ QDesktopWidget *desktop = QApplication::desktop();
+
+ emit desktop->resized(screenNo);
+ if (maxWindowRect(screen).isEmpty()) // not explicitly set
+ emit desktop->workAreaResized(screenNo);
+ }
+
+ QWSServer *server = QWSServer::instance();
+ if (server) {
+ server->updateWindowRegions();
+ QRegion r = screen->region();
+ server->refresh(r);
+ }
+
+ // make sure maximized and fullscreen windows are updated
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ QWidget *w = list.at(i);
+ if (w->isFullScreen())
+ w->d_func()->setFullScreenSize_helper();
+ else if (w->isMaximized())
+ w->d_func()->setMaxWindowState_helper();
+ }
+}
+
+#endif // QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+
+/*****************************************************************************
+ Internal variables and functions
+ *****************************************************************************/
+
+
+static QString appName; // application name
+static const char *appFont = 0; // application font
+static const char *appBGCol = 0; // application bg color
+static const char *appFGCol = 0; // application fg color
+static const char *appBTNCol = 0; // application btn color
+static const char *mwGeometry = 0; // main widget geometry
+static const char *mwTitle = 0; // main widget title
+//static bool mwIconic = false; // main widget iconified
+
+static bool app_do_modal = false; // modal mode
+Q_GUI_EXPORT QWSDisplay *qt_fbdpy = 0; // QWS `display'
+QLock *QWSDisplay::lock = 0;
+
+static int mouseButtonPressed = 0; // last mouse button pressed
+static int mouseButtonPressTime = 0; // when was a button pressed
+static short mouseXPos, mouseYPos; // mouse position in act window
+
+extern QWidgetList *qt_modal_stack; // stack of modal widgets
+
+static QWidget *popupButtonFocus = 0;
+static QWidget *popupOfPopupButtonFocus = 0;
+static bool popupCloseDownMode = false;
+static bool popupGrabOk;
+static QPointer<QWidget> *mouseInWidget = 0;
+
+static bool sm_blockUserInput = false; // session management
+
+QWidget *qt_button_down = 0; // widget got last button-down
+WId qt_last_cursor = 0xffffffff; // Was -1, but WIds are unsigned
+
+class QWSMouseEvent;
+class QWSKeyEvent;
+
+class QETWidget : public QWidget // event translator widget
+{
+public:
+ bool translateMouseEvent(const QWSMouseEvent *, int oldstate);
+ bool translateKeyEvent(const QWSKeyEvent *, bool grab);
+ bool translateRegionEvent(const QWSRegionEvent *);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ void translateEmbedEvent(const QWSEmbedEvent *event);
+#endif
+ bool translateWheelEvent(const QWSMouseEvent *me);
+ void repaintDecoration(QRegion r, bool post);
+ void updateRegion();
+
+ bool raiseOnClick()
+ {
+ // With limited windowmanagement/taskbar/etc., raising big windows
+ // (eg. spreadsheet) over the top of everything else (eg. calculator)
+ // is just annoying.
+ return !isMaximized() && !isFullScreen();
+ }
+};
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+#if !defined(QT_NO_GLIB)
+ if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
+ eventDispatcher = (q->type() != QApplication::Tty
+ ? new QWSEventDispatcherGlib(q)
+ : new QEventDispatcherGlib(q));
+ else
+#endif
+ eventDispatcher = (q->type() != QApplication::Tty
+ ? new QEventDispatcherQWS(q)
+ : new QEventDispatcherUNIX(q));
+}
+
+// Single-process stuff. This should maybe move into qwindowsystem_qws.cpp
+
+static bool qws_single_process;
+static QList<QWSEvent*> incoming;
+static QList<QWSCommand*> outgoing;
+
+void qt_client_enqueue(const QWSEvent *event)
+{
+ QWSEvent *copy = QWSEvent::factory(event->type);
+ copy->copyFrom(event);
+ incoming.append(copy);
+}
+
+QList<QWSCommand*> *qt_get_server_queue()
+{
+ return &outgoing;
+}
+
+void qt_server_enqueue(const QWSCommand *command)
+{
+ QWSCommand *copy = QWSCommand::factory(command->type);
+ copy->copyFrom(command);
+ outgoing.append(copy);
+}
+
+QWSDisplay::Data::Data(QObject* parent, bool singleProcess)
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ Q_UNUSED(parent);
+ Q_UNUSED(singleProcess);
+#else
+ if (singleProcess)
+ csocket = 0;
+ else {
+ csocket = new QWSSocket(parent);
+ QObject::connect(csocket, SIGNAL(disconnected()),
+ qApp, SLOT(quit()));
+ }
+ clientLock = 0;
+#endif
+ init();
+}
+
+QWSDisplay::Data::~Data()
+{
+// delete rgnMan; rgnMan = 0;
+// delete memorymanager; memorymanager = 0;
+ qt_screen->disconnect();
+ delete qt_screen; qt_screen = 0;
+#ifndef QT_NO_QWS_CURSOR
+ delete qt_screencursor; qt_screencursor = 0;
+#endif
+#ifndef QT_NO_QWS_MULTIPROCESS
+ shm.detach();
+ if (csocket) {
+ QWSCommand shutdownCmd(QWSCommand::Shutdown, 0, 0);
+ shutdownCmd.write(csocket);
+ csocket->flush(); // may be pending QCop message, eg.
+ delete csocket;
+ }
+ delete clientLock;
+ clientLock = 0;
+#endif
+ delete connected_event;
+ delete mouse_event;
+ delete current_event;
+ qDeleteAll(queue);
+#ifndef QT_NO_COP
+ delete qcop_response;
+#endif
+}
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+bool QWSDisplay::Data::lockClient(QWSLock::LockType type, int timeout)
+{
+ return !clientLock || clientLock->lock(type, timeout);
+}
+
+void QWSDisplay::Data::unlockClient(QWSLock::LockType type)
+{
+ if (clientLock) clientLock->unlock(type);
+}
+
+bool QWSDisplay::Data::waitClient(QWSLock::LockType type, int timeout)
+{
+ return !clientLock || clientLock->wait(type, timeout);
+}
+
+QWSLock* QWSDisplay::Data::getClientLock()
+{
+ return clientLock;
+}
+#endif // QT_NO_QWS_MULTIPROCESS
+
+void QWSDisplay::Data::flush()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket) {
+ csocket->waitForReadyRead(0);
+ csocket->flush();
+ }
+#endif
+}
+
+#if 0
+void QWSDisplay::Data::debugQueue() {
+ for (int i = 0; i < queue.size(); ++i) {
+ QWSEvent *e = queue.at(i);
+ qDebug( " ev %d type %d sl %d rl %d", i, e->type, e->simpleLen, e->rawLen);
+ }
+}
+#endif
+
+bool QWSDisplay::Data::queueNotEmpty()
+{
+ return mouse_event/*||region_event*/||queue.count() > 0;
+}
+QWSEvent* QWSDisplay::Data::dequeue()
+{
+ QWSEvent *r=0;
+ if (queue.count()) {
+ r = queue.first();
+ queue.removeFirst();
+ if (r->type == QWSEvent::Region)
+ region_events_count--;
+ } else if (mouse_event) {
+ r = mouse_event;
+ mouse_event = 0;
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ mouse_event_count = 0;
+#endif
+ }
+ return r;
+}
+
+QWSEvent* QWSDisplay::Data::peek()
+{
+ return queue.first();
+}
+
+bool QWSDisplay::Data::directServerConnection()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ return csocket == 0;
+#else
+ return true;
+#endif
+}
+
+void QWSDisplay::Data::create(int n)
+{
+ QWSCreateCommand cmd(n);
+ sendCommand(cmd);
+}
+
+void QWSDisplay::Data::flushCommands()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket)
+ csocket->flush();
+#endif
+}
+
+void QWSDisplay::Data::sendCommand(QWSCommand & cmd)
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket)
+ cmd.write(csocket);
+ else
+#endif
+ qt_server_enqueue(&cmd);
+}
+
+void QWSDisplay::Data::sendSynchronousCommand(QWSCommand & cmd)
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket) {
+ lockClient(QWSLock::Communication);
+ cmd.write(csocket);
+ bool ok = true;
+ while (csocket->bytesToWrite() > 0) {
+ if (!csocket->waitForBytesWritten(-1)) {
+ qCritical("QWSDisplay::Data::sendSynchronousCommand: %s",
+ qPrintable(csocket->errorString()));
+ ok = false;
+ break;
+ }
+ }
+ if (ok)
+ waitClient(QWSLock::Communication);
+ } else
+#endif
+ qt_server_enqueue(&cmd);
+}
+
+int QWSDisplay::Data::takeId()
+{
+ if (unused_identifiers.count() == 10)
+ create(15);
+ if (unused_identifiers.count() == 0)
+ waitForCreation();
+ return unused_identifiers.takeFirst();
+}
+
+void QWSDisplay::Data::setMouseFilter(void (*filter)(QWSMouseEvent*))
+{
+ mouseFilter = filter;
+}
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+QWSLock* QWSDisplay::Data::clientLock = 0;
+
+void Q_GUI_EXPORT qt_app_reinit( const QString& newAppName )
+{
+ qt_fbdpy->d->reinit( newAppName );
+}
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
+class QDesktopWidget;
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void QWSDisplay::Data::reinit( const QString& newAppName )
+{
+ Q_ASSERT(csocket);
+
+ delete connected_event;
+ connected_event = 0;
+ region_events_count = 0;
+// region_ack = 0;
+ delete mouse_event;
+ mouse_event = 0;
+// region_event = 0;
+ region_offset_window = 0;
+#ifndef QT_NO_COP
+ delete qcop_response;
+ qcop_response = 0;
+#endif
+ delete current_event;
+ current_event = 0;
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ mouse_event_count = 0;
+#endif
+ mouseFilter = 0;
+
+ qt_desktopWidget = 0;
+ delete QWSDisplay::Data::clientLock;
+ QWSDisplay::Data::clientLock = 0;
+
+ QString pipe = qws_qtePipeFilename();
+
+ // QWS client
+ // Cleanup all cached ids
+ unused_identifiers.clear();
+ delete csocket;
+
+ appName = newAppName;
+ qApp->setObjectName( appName );
+
+ csocket = new QWSSocket();
+ QObject::connect(csocket, SIGNAL(disconnected()),
+ qApp, SLOT(quit()));
+ csocket->connectToLocalFile(pipe);
+
+ QWSDisplay::Data::clientLock = new QWSLock();
+
+ QWSIdentifyCommand cmd;
+ cmd.setId(appName, QWSDisplay::Data::clientLock->id());
+
+#ifndef QT_NO_SXE
+ QTransportAuth *a = QTransportAuth::getInstance();
+ QTransportAuth::Data *d = a->connectTransport(
+ QTransportAuth::UnixStreamSock |
+ QTransportAuth::Trusted,
+ csocket->socketDescriptor());
+ QAuthDevice *ad = a->authBuf( d, csocket );
+ ad->setClient( csocket );
+
+ cmd.write(ad);
+#else
+ cmd.write(csocket);
+#endif
+
+ // wait for connect confirmation
+ waitForConnection();
+
+ qws_client_id = connected_event->simpleData.clientId;
+
+ if (!QWSDisplay::initLock(pipe, false))
+ qFatal("Cannot get display lock");
+
+ if (shm.attach(connected_event->simpleData.servershmid)) {
+ sharedRam = static_cast<uchar *>(shm.address());
+ QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData());
+ if (s)
+ sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData()));
+ } else {
+ perror("QWSDisplay::Data::init");
+ qFatal("Client can't attach to main ram memory.");
+ }
+
+ qApp->desktop();
+
+ // We wait for creation mainly so that we can process important
+ // initialization events such as MaxWindowRect that are sent
+ // before object id creation. Waiting here avoids later window
+ // resizing since we have the MWR before windows are displayed.
+ waitForCreation();
+
+ sharedRamSize -= sizeof(int);
+ qt_last_x = reinterpret_cast<int *>(sharedRam + sharedRamSize);
+ sharedRamSize -= sizeof(int);
+ qt_last_y = reinterpret_cast<int *>(sharedRam + sharedRamSize);
+
+#ifndef QT_NO_COP
+ QCopChannel::reregisterAll();
+#endif
+ csocket->flush();
+}
+#endif
+
+void QWSDisplay::Data::init()
+{
+ connected_event = 0;
+ region_events_count = 0;
+// region_ack = 0;
+ mouse_event = 0;
+ mouse_state = -1;
+ mouse_winid = 0;
+// region_event = 0;
+ region_offset_window = 0;
+#ifndef QT_NO_COP
+ qcop_response = 0;
+#endif
+ current_event = 0;
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ mouse_event_count = 0;
+#endif
+ mouseFilter = 0;
+
+ QString pipe = qws_qtePipeFilename();
+
+ sharedRamSize = qwsSharedRamSize;
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket) {
+ // QWS client
+
+ connectToPipe();
+
+ QWSDisplay::Data::clientLock = new QWSLock();
+
+ QWSIdentifyCommand cmd;
+ cmd.setId(appName, QWSDisplay::Data::clientLock->id());
+#ifndef QT_NO_SXE
+ QTransportAuth *a = QTransportAuth::getInstance();
+ QTransportAuth::Data *d = a->connectTransport(
+ QTransportAuth::UnixStreamSock |
+ QTransportAuth::Trusted,
+ csocket->socketDescriptor());
+ QAuthDevice *ad = a->authBuf( d, csocket );
+ ad->setClient( csocket );
+ cmd.write(ad);
+#else
+ cmd.write(csocket);
+#endif
+
+ // create(30); // not necessary, server will send ids anyway
+ waitForConnection();
+
+ qws_client_id = connected_event->simpleData.clientId;
+
+ // now we want to get the exact display spec to use if we haven't
+ // specified anything.
+ if (qws_display_spec.at(0) == ':')
+ qws_display_spec = connected_event->display;
+
+ if (!QWSDisplay::initLock(pipe, false))
+ qFatal("Cannot get display lock");
+
+ if (shm.attach(connected_event->simpleData.servershmid)) {
+ sharedRam = static_cast<uchar *>(shm.address());
+ QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData());
+ if (s)
+ sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData()));
+ } else {
+ perror("QWSDisplay::Data::init");
+ qFatal("Client can't attach to main ram memory.");
+ }
+
+ // We wait for creation mainly so that we can process important
+ // initialization events such as MaxWindowRect that are sent
+ // before object id creation. Waiting here avoids later window
+ // resizing since we have the MWR before windows are displayed.
+ waitForCreation();
+ } else
+#endif
+ {
+ create(30);
+
+ // QWS server
+ if (!QWSDisplay::initLock(pipe, true))
+ qFatal("Cannot get display lock");
+
+ QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData());
+ if (s)
+ sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData()));
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+ if (!shm.create(sharedRamSize)) {
+ perror("Cannot create main ram shared memory\n");
+ qFatal("Unable to allocate %d bytes of shared memory", sharedRamSize);
+ }
+ qt_servershmid = shm.id();
+ sharedRam = static_cast<uchar *>(shm.address());
+#else
+ sharedRam=static_cast<uchar *>(malloc(sharedRamSize));
+#endif
+ // Need to zero index count at end of block, might as well zero
+ // the rest too
+ memset(sharedRam,0,sharedRamSize);
+
+ QWSIdentifyCommand cmd;
+ cmd.setId(appName, -1);
+ qt_server_enqueue(&cmd);
+ }
+
+ // Allow some memory for the graphics driver too
+ //### Note that sharedRamSize() has side effects; it must be called
+ //### once, and only once, and before initDevice()
+ sharedRamSize -= qt_screen->sharedRamSize(sharedRam+sharedRamSize);
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if(!csocket)
+#endif
+ {
+ //QWS server process
+ if (!qt_screen->initDevice())
+ qFatal("Unable to initialize screen driver!");
+ }
+
+ sharedRamSize -= sizeof(int);
+ qt_last_x = reinterpret_cast<int *>(sharedRam + sharedRamSize);
+ sharedRamSize -= sizeof(int);
+ qt_last_y = reinterpret_cast<int *>(sharedRam + sharedRamSize);
+
+ /* Initialise framebuffer memory manager */
+ /* Add 4k for luck and to avoid clobbering hardware cursor */
+// int screensize=qt_screen->screenSize();
+// memorymanager=new QMemoryManager(qt_screen->base()+screensize+4096,
+// qt_screen->totalSize()-(screensize+4096),0);
+
+// #ifndef QT_NO_QWS_MULTIPROCESS
+// rgnMan = new QWSRegionManager(pipe, csocket);
+// #else
+// rgnMan = new QWSRegionManager(pipe, 0); //####### not necessary
+// #endif
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket)
+ csocket->flush();
+#endif
+}
+
+
+QWSEvent* QWSDisplay::Data::readMore()
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ return incoming.isEmpty() ? 0 : incoming.takeFirst();
+#else
+ if (!csocket)
+ return incoming.isEmpty() ? 0 : incoming.takeFirst();
+ // read next event
+ if (!current_event) {
+ int event_type = qws_read_uint(csocket);
+
+ if (event_type >= 0) {
+ current_event = QWSEvent::factory(event_type);
+ }
+ }
+
+ if (current_event) {
+ if (current_event->read(csocket)) {
+ // Finished reading a whole event.
+ QWSEvent* result = current_event;
+ current_event = 0;
+ return result;
+ }
+ }
+
+ // Not finished reading a whole event.
+ return 0;
+#endif
+}
+
+void QWSDisplay::Data::fillQueue()
+{
+ QWSServer::processEventQueue();
+ QWSEvent *e = readMore();
+#ifndef QT_NO_QWS_MULTIPROCESS
+ int bytesAvailable = csocket ? csocket->bytesAvailable() : 0;
+ int bytesRead = 0;
+#endif
+ while (e) {
+#ifndef QT_NO_QWS_MULTIPROCESS
+ bytesRead += QWS_PROTOCOL_ITEM_SIZE((*e));
+#endif
+ if (e->type == QWSEvent::Connected) {
+ connected_event = static_cast<QWSConnectedEvent *>(e);
+ return;
+ } else if (e->type == QWSEvent::Creation) {
+ QWSCreationEvent *ce = static_cast<QWSCreationEvent*>(e);
+ int id = ce->simpleData.objectid;
+ int count = ce->simpleData.count;
+ for (int i = 0; i < count; ++i)
+ unused_identifiers.append(id++);
+ delete e;
+ } else if (e->type == QWSEvent::Mouse) {
+ if (!qt_screen) {
+ delete e;
+ } else {
+ QWSMouseEvent *me = static_cast<QWSMouseEvent*>(e);
+ if (mouseFilter)
+ mouseFilter(me);
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ static const char *defaultAction= "INITIAL";
+ const char * action = defaultAction;
+#endif
+ delete mouse_event;
+ if (mouse_winid != me->window ()
+ || mouse_state != me->simpleData.state) {
+ queue.append(me);
+ mouse_winid = me->window();
+ mouse_state = me->simpleData.state;
+ mouse_event = 0;
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ mouse_event_count = 0;
+ action = "ENQUEUE";
+#endif
+ } else {
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ if (mouse_event)
+ action = "COMPRESS";
+ mouse_event_count++;
+#endif
+ mouse_event = me;
+ }
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ if (me->simpleData.state !=0 || action != defaultAction || mouse_event_count != 0)
+ qDebug("fillQueue %s (%d,%d), state %x win %d count %d", action,
+ me->simpleData.x_root, me->simpleData.y_root, me->simpleData.state,
+ me->window(), mouse_event_count);
+#endif
+ }
+#ifndef QT_NO_QWS_MULTIPROCESS
+ } else if (e->type == QWSEvent::Region && clientLock) {
+ // not really an unlock, decrements the semaphore
+ region_events_count++;
+ clientLock->unlock(QWSLock::RegionEvent);
+ queue.append(e);
+#endif
+#ifndef QT_NO_QWS_PROPERTIES
+ } else if (e->type == QWSEvent::PropertyReply) {
+ QWSPropertyReplyEvent *pe = static_cast<QWSPropertyReplyEvent*>(e);
+ int len = pe->simpleData.len;
+ char *data;
+ if (len <= 0) {
+ data = 0;
+ } else {
+ data = new char[len];
+ memcpy(data, pe->data, len) ;
+ }
+ QPaintDevice::qwsDisplay()->getPropertyLen = len;
+ QPaintDevice::qwsDisplay()->getPropertyData = data;
+ delete e;
+#endif // QT_NO_QWS_PROPERTIES
+ } else if (e->type==QWSEvent::MaxWindowRect && qt_screen) {
+ // Process this ASAP, in case new widgets are created (startup)
+ setMaxWindowRect((static_cast<QWSMaxWindowRectEvent*>(e))->simpleData.rect);
+ delete e;
+#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+ } else if (e->type == QWSEvent::ScreenTransformation) {
+ QWSScreenTransformationEvent *pe = static_cast<QWSScreenTransformationEvent*>(e);
+ setScreenTransformation(pe->simpleData.screen,
+ pe->simpleData.transformation);
+ delete e;
+#endif
+#ifndef QT_NO_COP
+ } else if (e->type == QWSEvent::QCopMessage) {
+ QWSQCopMessageEvent *pe = static_cast<QWSQCopMessageEvent*>(e);
+ if (pe->simpleData.is_response) {
+ qcop_response = pe;
+ } else {
+ queue.append(e);
+ }
+#endif
+ } else {
+ queue.append(e);
+ }
+ //debugQueue();
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket && bytesRead >= bytesAvailable)
+ break;
+#endif
+ e = readMore();
+ }
+}
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+static int qws_connection_timeout = 5;
+
+void QWSDisplay::Data::connectToPipe()
+{
+ Q_ASSERT(csocket);
+
+ int timeout = qgetenv("QWS_CONNECTION_TIMEOUT").toInt();
+ if (timeout)
+ qws_connection_timeout = timeout;
+
+ const QString pipe = qws_qtePipeFilename();
+ int i = 0;
+ while (!csocket->connectToLocalFile(pipe)) {
+ if (++i > qws_connection_timeout) {
+ qWarning("No Qt for Embedded Linux server appears to be running.");
+ qWarning("If you want to run this program as a server,");
+ qWarning("add the \"-qws\" command-line option.");
+ exit(1);
+ }
+ sleep(1);
+ }
+}
+
+void QWSDisplay::Data::waitForConnection()
+{
+ connected_event = 0;
+
+ for (int i = 0; i < qws_connection_timeout; i++) {
+ fillQueue();
+ if (connected_event)
+ return;
+ csocket->flush();
+ csocket->waitForReadyRead(1000);
+ }
+
+ csocket->flush();
+ if (!connected_event)
+ qFatal("Did not receive a connection event from the qws server");
+}
+
+void QWSDisplay::Data::waitForRegionAck(int winId)
+{
+ QWSEvent *ack = 0;
+
+ if (csocket) { // GuiClient
+ int i = 0;
+ while (!ack) {
+ fillQueue();
+
+ while (i < queue.size()) {
+ QWSEvent *e = queue.at(i);
+ if (e->type == QWSEvent::Region && e->window() == winId) {
+ ack = e;
+ queue.removeAt(i);
+ break;
+ }
+ ++i;
+ }
+
+ if (!ack) {
+ csocket->flush();
+ csocket->waitForReadyRead(1000);
+ }
+ }
+ } else { // GuiServer
+ fillQueue();
+ for (int i = 0; i < queue.size(); /* nothing */) {
+ QWSEvent *e = queue.at(i);
+ if (e->type == QWSEvent::Region && e->window() == winId) {
+ ack = e;
+ queue.removeAt(i);
+ break;
+ }
+ ++i;
+ }
+ if (!ack) // already processed
+ return;
+ }
+
+ Q_ASSERT(ack);
+
+ qApp->qwsProcessEvent(ack);
+ delete ack;
+ region_events_count--;
+}
+
+void QWSDisplay::Data::waitForRegionEvents(int winId, bool ungrabDisplay)
+{
+ if (!clientLock)
+ return;
+
+ int removedEventsCount = 0;
+
+ // fill queue with unreceived region events
+ if (!clientLock->hasLock(QWSLock::RegionEvent)) {
+ bool ungrabbed = false;
+ if (ungrabDisplay && QWSDisplay::grabbed()) {
+ QWSDisplay::ungrab();
+ ungrabbed = true;
+ }
+
+ for (;;) {
+ fillQueue();
+ if (clientLock->hasLock(QWSLock::RegionEvent))
+ break;
+ csocket->flush();
+ csocket->waitForReadyRead(1000);
+ }
+
+ if (ungrabbed)
+ QWSDisplay::grab(true);
+ }
+
+ // check the queue for pending region events
+ QWSEvent *regionEvent = 0;
+ for (int i = 0; i < queue.size(); /* nothing */) {
+ QWSEvent *e = queue.at(i);
+ if (e->type == QWSEvent::Region && e->window() == winId) {
+ QWSRegionEvent *re = static_cast<QWSRegionEvent*>(e);
+ if (re->simpleData.type == QWSRegionEvent::Allocation) {
+ delete regionEvent;
+ regionEvent = re;
+ }
+ queue.removeAt(i);
+ removedEventsCount++;
+ } else {
+ ++i;
+ }
+ }
+
+ if (regionEvent) {
+ qApp->qwsProcessEvent(regionEvent);
+ delete regionEvent;
+ }
+ region_events_count -= removedEventsCount;
+}
+
+bool QWSDisplay::Data::hasPendingRegionEvents() const
+{
+ if (clientLock && !clientLock->hasLock(QWSLock::RegionEvent))
+ return true;
+
+ return region_events_count > 0;
+}
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
+void QWSDisplay::Data::waitForCreation()
+{
+ fillQueue();
+#ifndef QT_NO_QWS_MULTIPROCESS
+ while (unused_identifiers.count() == 0) {
+ if (csocket) {
+ csocket->flush();
+ csocket->waitForReadyRead(1000);
+ }
+ fillQueue();
+ }
+#endif
+}
+
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void QWSDisplay::Data::waitForPropertyReply()
+{
+ if (!csocket)
+ return;
+ fillQueue();
+ while (qt_fbdpy->getPropertyLen == -2) {
+ csocket->flush();
+ csocket->waitForReadyRead(1000);
+ fillQueue();
+ }
+}
+#endif
+
+#ifndef QT_NO_COP
+void QWSDisplay::Data::waitForQCopResponse()
+{
+ for (;;) {
+ fillQueue();
+ if (qcop_response)
+ break;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket) {
+ csocket->flush();
+ csocket->waitForReadyRead(1000);
+ }
+#endif
+ }
+ queue.prepend(qcop_response);
+ qcop_response = 0;
+}
+#endif
+
+/*!
+ \class QWSDisplay
+ \brief The QWSDisplay class provides a display for QWS; it is an internal class.
+
+ \internal
+
+ \ingroup qws
+*/
+
+QWSDisplay::QWSDisplay()
+{
+ d = new Data(0, qws_single_process);
+}
+
+QWSDisplay::~QWSDisplay()
+{
+ delete d;
+ delete lock;
+ lock = 0;
+}
+
+bool QWSDisplay::grabbed()
+{
+ return lock->locked();
+}
+
+void QWSDisplay::grab()
+{
+ lock->lock(QLock::Read);
+}
+
+void QWSDisplay::grab(bool write)
+{
+ lock->lock(write ? QLock::Write : QLock::Read);
+
+}
+void QWSDisplay::ungrab()
+{
+ lock->unlock();
+}
+
+#if 0
+QWSRegionManager *QWSDisplay::regionManager() const
+{
+ return d->rgnMan;
+}
+#endif
+
+bool QWSDisplay::eventPending() const
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ d->flush();
+#endif
+ d->fillQueue();
+ return d->queueNotEmpty();
+}
+
+
+/*
+ Caller must delete return value!
+ */
+QWSEvent *QWSDisplay::getEvent()
+{
+ d->fillQueue();
+ Q_ASSERT(d->queueNotEmpty());
+ QWSEvent* e = d->dequeue();
+
+ return e;
+}
+
+uchar* QWSDisplay::frameBuffer() const { return qt_screen->base(); }
+int QWSDisplay::width() const { return qt_screen->width(); }
+int QWSDisplay::height() const { return qt_screen->height(); }
+int QWSDisplay::depth() const { return qt_screen->depth(); }
+int QWSDisplay::pixmapDepth() const { return qt_screen->pixmapDepth(); }
+bool QWSDisplay::supportsDepth(int depth) const { return qt_screen->supportsDepth(depth); }
+uchar *QWSDisplay::sharedRam() const { return d->sharedRam; }
+int QWSDisplay::sharedRamSize() const { return d->sharedRamSize; }
+
+#ifndef QT_NO_QWS_PROPERTIES
+
+void QWSDisplay::addProperty(int winId, int property)
+{
+ QWSAddPropertyCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.property = property;
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::setProperty(int winId, int property, int mode, const QByteArray &data)
+{
+ QWSSetPropertyCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.property = property;
+ cmd.simpleData.mode = mode;
+ cmd.setData(data.constData(), data.size());
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::setProperty(int winId, int property, int mode,
+ const char * data)
+{
+ QWSSetPropertyCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.property = property;
+ cmd.simpleData.mode = mode;
+ cmd.setData(data, strlen(data));
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::removeProperty(int winId, int property)
+{
+ QWSRemovePropertyCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.property = property;
+ d->sendCommand(cmd);
+}
+
+/*
+ It is the caller's responsibility to delete[] \a data.
+ */
+bool QWSDisplay::getProperty(int winId, int property, char *&data, int &len)
+{
+ if (d->directServerConnection()) {
+ const char *propertyData;
+ bool retval = qwsServer->d_func()->get_property(winId, property, propertyData, len);
+ if (len <= 0) {
+ data = 0;
+ } else {
+ data = new char[len];
+ memcpy(data, propertyData, len) ;
+ }
+ return retval;
+ }
+ QWSGetPropertyCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.property = property;
+ d->sendCommand(cmd);
+
+ getPropertyLen = -2;
+ getPropertyData = 0;
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ d->waitForPropertyReply();
+#endif
+
+ len = getPropertyLen;
+ data = getPropertyData;
+
+ getPropertyLen = -2;
+ getPropertyData = 0;
+
+ return len != -1;
+}
+
+#endif // QT_NO_QWS_PROPERTIES
+
+void QWSDisplay::setAltitude(int winId, int alt, bool fixed)
+{
+ QWSChangeAltitudeCommand cmd;
+#ifdef QT_DEBUG
+ memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
+#endif
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.altitude = QWSChangeAltitudeCommand::Altitude(alt);
+ cmd.simpleData.fixed = fixed;
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->set_altitude(&cmd);
+ } else {
+ d->sendSynchronousCommand(cmd);
+ }
+}
+
+void QWSDisplay::setOpacity(int winId, int opacity)
+{
+ QWSSetOpacityCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.opacity = opacity;
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->set_opacity(&cmd);
+ } else {
+ d->sendCommand(cmd);
+ }
+}
+
+
+
+void QWSDisplay::requestFocus(int winId, bool get)
+{
+ QWSRequestFocusCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.flag = get;
+ if (d->directServerConnection())
+ qwsServer->d_func()->request_focus(&cmd);
+ else
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::setIdentity(const QString &appName)
+{
+ QWSIdentifyCommand cmd;
+#ifdef QT_NO_QWS_MULTIPROCESS
+ const int id = -1;
+#else
+ const int id = QWSDisplay::Data::clientLock ? QWSDisplay::Data::clientLock->id() : -1;
+#endif
+ cmd.setId(appName, id);
+ if (d->directServerConnection())
+ qwsServer->d_func()->set_identity(&cmd);
+ else
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::nameRegion(int winId, const QString& n, const QString &c)
+{
+ QWSRegionNameCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.setName(n, c);
+ if (d->directServerConnection())
+ qwsServer->d_func()->name_region(&cmd);
+ else
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::requestRegion(int winId, const QString &surfaceKey,
+ const QByteArray &surfaceData,
+ const QRegion &region)
+{
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->request_region(winId, surfaceKey,
+ surfaceData, region);
+ } else {
+ QWSRegionCommand cmd;
+ cmd.setData(winId, surfaceKey, surfaceData, region);
+ d->sendSynchronousCommand(cmd);
+ }
+}
+
+void QWSDisplay::repaintRegion(int winId, int windowFlags, bool opaque, QRegion r)
+{
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->repaint_region(winId, windowFlags, opaque, r);
+ } else {
+ QVector<QRect> ra = r.rects();
+
+ /*
+ for (int i = 0; i < ra.size(); i++) {
+ QRect r(ra[i]);
+ qDebug("rect: %d %d %d %d", r.x(), r.y(), r.right(), r.bottom());
+ }
+ */
+
+ QWSRepaintRegionCommand cmd;
+ /* XXX QWSRegionCommand is padded out in a compiler dependent way.
+ Zeroed out to avoid valgrind reporting uninitialized memory usage.
+ */
+#ifdef QT_DEBUG
+ memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
+#endif
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.windowFlags = windowFlags;
+ cmd.simpleData.opaque = opaque;
+ cmd.simpleData.nrectangles = ra.count();
+ cmd.setData(reinterpret_cast<const char *>(ra.constData()),
+ ra.count() * sizeof(QRect), false);
+
+ d->sendSynchronousCommand(cmd);
+ }
+}
+
+
+void QWSDisplay::moveRegion(int winId, int dx, int dy)
+{
+ QWSRegionMoveCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.dx = dx;
+ cmd.simpleData.dy = dy;
+
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->move_region(&cmd);
+ } else {
+ d->sendSynchronousCommand(cmd);
+ }
+// d->offsetPendingExpose(winId, QPoint(cmd.simpleData.dx, cmd.simpleData.dy));
+}
+
+void QWSDisplay::destroyRegion(int winId)
+{
+ QWSRegionDestroyCommand cmd;
+ cmd.simpleData.windowid = winId;
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->destroy_region(&cmd);
+ } else {
+ d->sendCommand(cmd);
+ }
+}
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+void QWSDisplay::sendIMUpdate(int type, int winId, int widgetid)
+{
+ QWSIMUpdateCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.widgetid = widgetid;
+
+ cmd.simpleData.type = type;
+
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->im_update(&cmd);
+ } else {
+ d->sendCommand(cmd);
+ }
+}
+
+void QWSDisplay::sendIMResponse(int winId, int property, const QVariant &result)
+{
+ QWSIMResponseCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.property = property;
+
+ cmd.setResult(result);
+
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->im_response(&cmd);
+ } else {
+ d->sendCommand(cmd);
+ }
+}
+
+void QWSDisplay::resetIM()
+{
+ sendIMUpdate(QWSInputMethod::Reset, -1, -1);
+}
+
+void QWSDisplay::sendIMMouseEvent(int index, bool isPress)
+{
+ QWSIMMouseCommand cmd;
+ cmd.simpleData.index = index;
+ cmd.simpleData.state = isPress ? QWSServer::MousePress : QWSServer::MouseRelease;
+ if (d->directServerConnection()) {
+ qwsServer->d_func()->send_im_mouse(&cmd);
+ } else {
+ d->sendCommand(cmd);
+ }
+}
+
+#endif
+
+int QWSDisplay::takeId()
+{
+ return d->takeId();
+}
+
+bool QWSDisplay::initLock(const QString &filename, bool create)
+{
+ if (!lock) {
+ lock = new QLock(filename, 'd', create);
+
+ if (!lock->isValid()) {
+ delete lock;
+ lock = 0;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void QWSDisplay::setSelectionOwner(int winId, const QTime &time)
+{
+ QWSSetSelectionOwnerCommand cmd;
+ cmd.simpleData.windowid = winId;
+ cmd.simpleData.hour = time.hour();
+ cmd.simpleData.minute = time.minute();
+ cmd.simpleData.sec = time.second();
+ cmd.simpleData.ms = time.msec();
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::convertSelection(int winId, int selectionProperty, const QString &mimeTypes)
+{
+#ifdef QT_NO_QWS_PROPERTIES
+ Q_UNUSED(mimeTypes);
+#else
+ // ### we need the atom/property thingy like in X here
+ addProperty(winId, QT_QWS_PROPERTY_CONVERTSELECTION);
+ setProperty(winId, QT_QWS_PROPERTY_CONVERTSELECTION,
+ int(QWSPropertyManager::PropReplace), mimeTypes.toLatin1());
+#endif
+ QWSConvertSelectionCommand cmd;
+ cmd.simpleData.requestor = winId;
+ cmd.simpleData.selection = selectionProperty;
+ cmd.simpleData.mimeTypes = QT_QWS_PROPERTY_CONVERTSELECTION;
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::defineCursor(int id, const QBitmap &curs, const QBitmap &mask,
+ int hotX, int hotY)
+{
+ const QImage cursImg = curs.toImage().convertToFormat(QImage::Format_MonoLSB);
+ const QImage maskImg = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
+
+ QWSDefineCursorCommand cmd;
+ cmd.simpleData.width = curs.width();
+ cmd.simpleData.height = curs.height();
+ cmd.simpleData.hotX = hotX;
+ cmd.simpleData.hotY = hotY;
+ cmd.simpleData.id = id;
+
+
+ // must copy each scanline since there might be gaps between them
+ const int height = curs.height();
+ const int width = curs.width();
+ const int dst_bpl = (width + 7) / 8;
+
+ int dataLen = dst_bpl * height;
+ uchar *data = new uchar[dataLen*2];
+ uchar *dst = data;
+
+ int src_bpl = cursImg.bytesPerLine();
+ const uchar *cursSrc = cursImg.bits();
+ for (int i = 0; i < height; ++i) {
+ memcpy(dst, cursSrc + i*src_bpl, dst_bpl);
+ dst += dst_bpl;
+ }
+
+ src_bpl = maskImg.bytesPerLine();
+ const uchar *maskSrc = maskImg.bits();
+ for (int i = 0; i < height; ++i) {
+ memcpy(dst, maskSrc + i*src_bpl, dst_bpl);
+ dst += dst_bpl;
+ }
+
+ cmd.setData(reinterpret_cast<char*>(data), dataLen*2);
+ delete [] data;
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::destroyCursor(int id)
+{
+ QWSDefineCursorCommand cmd;
+ cmd.simpleData.width = 0;
+ cmd.simpleData.height = 0;
+ cmd.simpleData.hotX = 0;
+ cmd.simpleData.hotY = 0;
+ cmd.simpleData.id = id;
+ cmd.setData(0, 0);
+
+ d->sendCommand(cmd);
+}
+
+#ifndef QT_NO_SOUND
+void QWSDisplay::playSoundFile(const QString& f)
+{
+ QWSPlaySoundCommand cmd;
+ cmd.setFileName(f);
+ d->sendCommand(cmd);
+}
+#endif
+
+#ifndef QT_NO_COP
+void QWSDisplay::registerChannel(const QString& channel)
+{
+ QWSQCopRegisterChannelCommand reg;
+ reg.setChannel(channel);
+ qt_fbdpy->d->sendCommand(reg);
+}
+
+void QWSDisplay::sendMessage(const QString &channel, const QString &msg,
+ const QByteArray &data)
+{
+ QWSQCopSendCommand com;
+ com.setMessage(channel, msg, data);
+ qt_fbdpy->d->sendCommand(com);
+}
+
+void QWSDisplay::flushCommands()
+{
+ qt_fbdpy->d->flushCommands();
+}
+
+/*
+ caller deletes result
+*/
+QWSQCopMessageEvent* QWSDisplay::waitForQCopResponse()
+{
+ qt_fbdpy->d->waitForQCopResponse();
+ QWSQCopMessageEvent *e = static_cast<QWSQCopMessageEvent*>(qt_fbdpy->d->dequeue());
+ Q_ASSERT(e->type == QWSEvent::QCopMessage);
+ return e;
+}
+#endif
+
+void QWSDisplay::sendFontCommand(int type, const QByteArray &fontName)
+{
+ QWSFontCommand cmd;
+ cmd.simpleData.type = type;
+ cmd.setFontName(fontName);
+ d->sendCommand(cmd);
+}
+
+void QWSDisplay::setWindowCaption(QWidget *w, const QString &c)
+{
+ if (w->isWindow()) {
+ nameRegion(w->internalWinId(), w->objectName(), c);
+ static_cast<QETWidget *>(w)->repaintDecoration(qApp->desktop()->rect(), true);
+ }
+}
+
+void QWSDisplay::selectCursor(QWidget *w, unsigned int cursId)
+{
+ if (cursId != qt_last_cursor)
+ {
+ QWidget *top = w->window();
+ qt_last_cursor = cursId;
+ QWSSelectCursorCommand cmd;
+ cmd.simpleData.windowid = top->internalWinId();
+ cmd.simpleData.id = cursId;
+ d->sendCommand(cmd);
+ d->flush();
+ }
+}
+
+void QWSDisplay::setCursorPosition(int x, int y)
+{
+ QWSPositionCursorCommand cmd;
+ cmd.simpleData.newX = x;
+ cmd.simpleData.newY = y;
+ d->sendCommand(cmd);
+ d->flush();
+}
+
+void QWSDisplay::grabMouse(QWidget *w, bool grab)
+{
+ QWidget *top = w->window();
+ QWSGrabMouseCommand cmd;
+#ifdef QT_DEBUG
+ memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
+#endif
+ cmd.simpleData.windowid = top->winId();
+ cmd.simpleData.grab = grab;
+ d->sendCommand(cmd);
+ d->flush();
+}
+
+void QWSDisplay::grabKeyboard(QWidget *w, bool grab)
+{
+ QWidget *top = w->window();
+ QWSGrabKeyboardCommand cmd;
+#ifdef QT_DEBUG
+ memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
+#endif
+ cmd.simpleData.windowid = top->winId();
+ cmd.simpleData.grab = grab;
+ d->sendCommand(cmd);
+ d->flush();
+}
+
+QList<QWSWindowInfo> QWSDisplay::windowList()
+{
+ QList<QWSWindowInfo> ret;
+ if(d->directServerConnection()) {
+ QList<QWSInternalWindowInfo*> * qin=QWSServer::windowList();
+ for (int i = 0; i < qin->count(); ++i) {
+ QWSInternalWindowInfo * qwi = qin->at(i);
+ QWSWindowInfo tmp;
+ tmp.winid = qwi->winid;
+ tmp.clientid = qwi->clientid;
+ tmp.name = QString(qwi->name);
+ ret.append(tmp);
+ }
+ qDeleteAll(*qin);
+ delete qin;
+ }
+ return ret;
+}
+
+int QWSDisplay::windowAt(const QPoint &p)
+{
+ //### currently only implemented for the server process
+ int ret = 0;
+ if(d->directServerConnection()) {
+ QWSWindow *win = qwsServer->windowAt(p);
+ if (win)
+ return win->winId();
+ }
+ return ret;
+}
+
+void QWSDisplay::setRawMouseEventFilter(void (*filter)(QWSMouseEvent *))
+{
+ if (qt_fbdpy)
+ qt_fbdpy->d->setMouseFilter(filter);
+}
+
+/*!
+ \relates QScreen
+
+ Here it is. \a transformation and \a screenNo
+ */
+void QWSDisplay::setTransformation(int transformation, int screenNo)
+{
+ QWSScreenTransformCommand cmd;
+ cmd.setTransformation(screenNo, transformation);
+ QWSDisplay::instance()->d->sendCommand(cmd);
+}
+
+static bool qt_try_modal(QWidget *, QWSEvent *);
+
+/*****************************************************************************
+ qt_init() - initializes Qt/FB
+ *****************************************************************************/
+
+static void qt_set_qws_resources()
+
+{
+ if (QApplication::desktopSettingsAware())
+ QApplicationPrivate::qws_apply_settings();
+
+ if (appFont)
+ QApplication::setFont(QFont(QString::fromLocal8Bit(appFont)));
+
+ if (appBGCol || appBTNCol || appFGCol) {
+ (void) QApplication::style(); // trigger creation of application style and system palettes
+ QColor btn;
+ QColor bg;
+ QColor fg;
+ if (appBGCol)
+ bg = QColor(appBGCol);
+ else
+ bg = QApplicationPrivate::sys_pal->color(QPalette::Window);
+ if (appFGCol)
+ fg = QColor(appFGCol);
+ else
+ fg = QApplicationPrivate::sys_pal->color(QPalette::WindowText);
+ if (appBTNCol)
+ btn = QColor(appBTNCol);
+ else
+ btn = QApplicationPrivate::sys_pal->color(QPalette::Button);
+
+ int h,s,v;
+ fg.getHsv(&h,&s,&v);
+ QColor base = Qt::white;
+ bool bright_mode = false;
+ if (v >= 255 - 50) {
+ base = btn.darker(150);
+ bright_mode = true;
+ }
+
+ QPalette pal(fg, btn, btn.lighter(), btn.darker(), btn.darker(150), fg, Qt::white, base, bg);
+ if (bright_mode) {
+ pal.setColor(QPalette::HighlightedText, base);
+ pal.setColor(QPalette::Highlight, Qt::white);
+ } else {
+ pal.setColor(QPalette::HighlightedText, Qt::white);
+ pal.setColor(QPalette::Highlight, Qt::darkBlue);
+ }
+ QColor disabled((fg.red() + btn.red()) / 2,
+ (fg.green() + btn.green())/ 2,
+ (fg.blue() + btn.blue()) / 2);
+ pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.lighter(125),
+ btn.darker(), btn.darker(150), disabled, Qt::white, Qt::white, bg);
+ if (bright_mode) {
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base);
+ pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white);
+ } else {
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white);
+ pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
+ }
+ QApplicationPrivate::setSystemPalette(pal);
+
+ }
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+}
+
+/*! \internal
+ apply the settings to the application
+*/
+bool QApplicationPrivate::qws_apply_settings()
+{
+#ifndef QT_NO_SETTINGS
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+
+ QStringList strlist;
+ int i;
+ QPalette pal(Qt::black);
+ int groupCount = 0;
+ strlist = settings.value(QLatin1String("Palette/active")).toStringList();
+ if (strlist.count() == QPalette::NColorRoles) {
+ ++groupCount;
+ for (i = 0; i < QPalette::NColorRoles; i++)
+ pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+ strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
+ if (strlist.count() == QPalette::NColorRoles) {
+ ++groupCount;
+ for (i = 0; i < QPalette::NColorRoles; i++)
+ pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+ strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
+ if (strlist.count() == QPalette::NColorRoles) {
+ ++groupCount;
+ for (i = 0; i < QPalette::NColorRoles; i++)
+ pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+
+
+ if (groupCount == QPalette::NColorGroups)
+ QApplicationPrivate::setSystemPalette(pal);
+
+ QString str = settings.value(QLatin1String("font")).toString();
+ if (!str.isEmpty()) {
+ QFont font(QApplication::font());
+ font.fromString(str);
+ QApplicationPrivate::setSystemFont(font);
+ }
+
+ // read library (ie. plugin) path list
+ QString libpathkey =
+ QString::fromLatin1("%1.%2/libraryPath")
+ .arg(QT_VERSION >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8);
+ QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
+#ifndef QT_NO_LIBRARY
+ if (! pathlist.isEmpty()) {
+ QStringList::ConstIterator it = pathlist.constBegin();
+ while (it != pathlist.constEnd())
+ QApplication::addLibraryPath(*it++);
+ }
+#endif
+
+ // read new QStyle
+ QString stylename = settings.value(QLatin1String("style")).toString();
+ if (QCoreApplication::startingUp()) {
+ if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
+ QApplicationPrivate::styleOverride = new QString(stylename);
+ } else {
+ QApplication::setStyle(stylename);
+ }
+
+ int num =
+ settings.value(QLatin1String("doubleClickInterval"),
+ QApplication::doubleClickInterval()).toInt();
+ QApplication::setDoubleClickInterval(num);
+
+ num =
+ settings.value(QLatin1String("cursorFlashTime"),
+ QApplication::cursorFlashTime()).toInt();
+ QApplication::setCursorFlashTime(num);
+
+#ifndef QT_NO_WHEELEVENT
+ num =
+ settings.value(QLatin1String("wheelScrollLines"),
+ QApplication::wheelScrollLines()).toInt();
+ QApplication::setWheelScrollLines(num);
+#endif
+
+ QString colorspec = settings.value(QLatin1String("colorSpec"),
+ QVariant(QLatin1String("default"))).toString();
+ if (colorspec == QLatin1String("normal"))
+ QApplication::setColorSpec(QApplication::NormalColor);
+ else if (colorspec == QLatin1String("custom"))
+ QApplication::setColorSpec(QApplication::CustomColor);
+ else if (colorspec == QLatin1String("many"))
+ QApplication::setColorSpec(QApplication::ManyColor);
+ else if (colorspec != QLatin1String("default"))
+ colorspec = QLatin1String("default");
+
+#ifndef QT_NO_TEXTCODEC
+ QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
+ QVariant(QLatin1String("none"))).toString();
+ if (defaultcodec != QLatin1String("none")) {
+ QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
+ if (codec)
+ QTextCodec::setCodecForTr(codec);
+ }
+#endif
+
+ int w = settings.value(QLatin1String("globalStrut/width")).toInt();
+ int h = settings.value(QLatin1String("globalStrut/height")).toInt();
+ QSize strut(w, h);
+ if (strut.isValid())
+ QApplication::setGlobalStrut(strut);
+
+ QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
+ QApplication::setEffectEnabled(Qt::UI_General,
+ effects.contains(QLatin1String("general")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
+ effects.contains(QLatin1String("animatemenu")));
+ QApplication::setEffectEnabled(Qt::UI_FadeMenu,
+ effects.contains(QLatin1String("fademenu")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
+ effects.contains(QLatin1String("animatecombo")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
+ effects.contains(QLatin1String("animatetooltip")));
+ QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
+ effects.contains(QLatin1String("fadetooltip")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
+ effects.contains(QLatin1String("animatetoolbox")));
+
+ settings.beginGroup(QLatin1String("Font Substitutions"));
+ QStringList fontsubs = settings.childKeys();
+ if (!fontsubs.isEmpty()) {
+ QStringList::Iterator it = fontsubs.begin();
+ for (; it != fontsubs.end(); ++it) {
+ QString fam = *it;
+ QStringList subs = settings.value(fam).toStringList();
+ QFont::insertSubstitutions(fam, subs);
+ }
+ }
+ settings.endGroup();
+
+ settings.endGroup(); // Qt
+
+ settings.beginGroup(QLatin1String("QWS Font Fallbacks"));
+ if (!settings.childKeys().isEmpty()) {
+ // from qfontdatabase_qws.cpp
+ extern void qt_applyFontDatabaseSettings(const QSettings &);
+ qt_applyFontDatabaseSettings(settings);
+ }
+ settings.endGroup();
+
+ return true;
+#else
+ return false;
+#endif // QT_NO_SETTINGS
+}
+
+
+
+static void init_display()
+{
+ if (qt_fbdpy) return; // workaround server==client case
+
+ // Connect to FB server
+ qt_fbdpy = new QWSDisplay();
+
+ // Get display parameters
+ // Set paintdevice parameters
+ // XXX initial info sent from server
+ // Misc. initialization
+
+ QColormap::initialize();
+ QFont::initialize();
+#ifndef QT_NO_CURSOR
+ QCursorData::initialize();
+#endif
+
+ qApp->setObjectName(appName);
+
+ if (!QApplicationPrivate::sys_font) {
+#ifdef QT_NO_FREETYPE
+ QFont f = QFont(QLatin1String("helvetica"), 10);
+#else
+ QFont f = QFont(QLatin1String("DejaVu Sans"), 12);
+#endif
+ QApplicationPrivate::setSystemFont(f);
+ }
+ qt_set_qws_resources();
+}
+
+void qt_init_display()
+{
+ qt_is_gui_used = true;
+ qws_single_process = true;
+ init_display();
+}
+
+static bool read_bool_env_var(const char *var, bool defaultvalue)
+{
+ // returns true if env variable is set to non-zero
+ // returns false if env var is set to zero
+ // returns defaultvalue if env var not set
+ char *x = ::getenv(var);
+ return (x && *x) ? (strcmp(x,"0") != 0) : defaultvalue;
+}
+
+static int read_int_env_var(const char *var, int defaultvalue)
+{
+ bool ok;
+ int r = qgetenv(var).toInt(&ok);
+ return ok ? r : defaultvalue;
+}
+
+void qt_init(QApplicationPrivate *priv, int type)
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ if (type == QApplication::GuiClient)
+ type = QApplication::GuiServer;
+#endif
+ if (type == QApplication::GuiServer)
+ qt_is_gui_used = false; //we'll turn it on in a second
+ qws_sw_cursor = read_bool_env_var("QWS_SW_CURSOR",qws_sw_cursor);
+ qws_screen_is_interlaced = read_bool_env_var("QWS_INTERLACE",false);
+
+ const char *display = ::getenv("QWS_DISPLAY");
+ if (display)
+ qws_display_spec = display; // since we setenv later!
+
+ //qws_savefonts = qgetenv("QWS_SAVEFONTS") != 0;
+ //qws_shared_memory = qgetenv("QWS_NOSHARED") == 0;
+
+ mouse_double_click_distance = read_int_env_var("QWS_DBLCLICK_DISTANCE", 5);
+
+ int flags = 0;
+ char *p;
+ int argc = priv->argc;
+ char **argv = priv->argv;
+ int j;
+
+ // Set application name
+
+ if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms
+ p = strrchr(argv[0], '/');
+ appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
+ }
+
+ // Get command line params
+
+ j = argc ? 1 : 0;
+ QString decoration;
+ for (int i=1; i<argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QByteArray arg = argv[i];
+ if (arg == "-fn" || arg == "-font") {
+ if (++i < argc)
+ appFont = argv[i];
+ } else if (arg == "-bg" || arg == "-background") {
+ if (++i < argc)
+ appBGCol = argv[i];
+ } else if (arg == "-btn" || arg == "-button") {
+ if (++i < argc)
+ appBTNCol = argv[i];
+ } else if (arg == "-fg" || arg == "-foreground") {
+ if (++i < argc)
+ appFGCol = argv[i];
+ } else if (arg == "-name") {
+ if (++i < argc)
+ appName = QString::fromLocal8Bit(argv[i]);
+ } else if (arg == "-title") {
+ if (++i < argc)
+ mwTitle = argv[i];
+ } else if (arg == "-geometry") {
+ if (++i < argc)
+ mwGeometry = argv[i];
+ } else if (arg == "-shared") {
+ qws_shared_memory = true;
+ } else if (arg == "-noshared") {
+ qws_shared_memory = false;
+ } else if (arg == "-savefonts") {
+ qws_savefonts = true;
+ } else if (arg == "-nosavefonts") {
+ qws_savefonts = false;
+ } else if (arg == "-swcursor") {
+ qws_sw_cursor = true;
+ } else if (arg == "-noswcursor") {
+ qws_sw_cursor = false;
+ } else if (arg == "-keyboard") {
+ flags &= ~QWSServer::DisableKeyboard;
+ } else if (arg == "-nokeyboard") {
+ flags |= QWSServer::DisableKeyboard;
+ } else if (arg == "-mouse") {
+ flags &= ~QWSServer::DisableMouse;
+ } else if (arg == "-nomouse") {
+ flags |= QWSServer::DisableMouse;
+ } else if (arg == "-qws") {
+ type = QApplication::GuiServer;
+ } else if (arg == "-interlaced") {
+ qws_screen_is_interlaced = true;
+ } else if (arg == "-display") {
+ if (++i < argc)
+ qws_display_spec = argv[i];
+ } else if (arg == "-decoration") {
+ if (++i < argc)
+ decoration = QString::fromLocal8Bit(argv[i]);
+ } else {
+ argv[j++] = argv[i];
+ }
+ }
+ if(j < priv->argc) {
+ priv->argv[j] = 0;
+ priv->argc = j;
+ }
+
+ mouseInWidget = new QPointer<QWidget>;
+
+ const QString disp = QString::fromLatin1(qws_display_spec);
+ QRegExp regexp(QLatin1String(":(\\d+)$"));
+ if (regexp.lastIndexIn(disp) != -1) {
+ const QString capture = regexp.cap(1);
+ bool ok = false;
+ int id = capture.toInt(&ok);
+ if (ok)
+ qws_display_id = id;
+ }
+
+ if (type == QApplication::GuiServer) {
+ qt_appType = QApplication::Type(type);
+ qws_single_process = true;
+ QWSServer::startup(flags);
+ setenv("QWS_DISPLAY", qws_display_spec.constData(), 0);
+ }
+
+ if(qt_is_gui_used) {
+ init_display();
+#ifndef QT_NO_QWS_MANAGER
+ if (decoration.isEmpty() && !qws_decoration) {
+ const QStringList keys = QDecorationFactory::keys();
+ if (!keys.isEmpty())
+ decoration = keys.first();
+ }
+ if (!decoration.isEmpty())
+ qws_decoration = QApplication::qwsSetDecoration(decoration);
+#endif // QT_NO_QWS_MANAGER
+#ifndef QT_NO_QWS_INPUTMETHODS
+ qApp->setInputContext(new QWSInputContext);
+#endif
+ }
+
+/*### convert interlace style
+ if (qws_screen_is_interlaced)
+ QApplication::setStyle(new QInterlaceStyle);
+*/
+}
+
+/*****************************************************************************
+ qt_cleanup() - cleans up when the application is finished
+ *****************************************************************************/
+
+void qt_cleanup()
+{
+ QPixmapCache::clear();
+#ifndef QT_NO_CURSOR
+ QCursorData::cleanup();
+#endif
+ QFont::cleanup();
+ QColormap::cleanup();
+
+ if (qws_single_process) {
+ QWSServer::closedown();
+ }
+
+ qDeleteAll(outgoing);
+ outgoing.clear();
+ qDeleteAll(incoming);
+ incoming.clear();
+
+ if (qt_is_gui_used) {
+ delete qt_fbdpy;
+ }
+ qt_fbdpy = 0;
+
+#ifndef QT_NO_QWS_MANAGER
+ delete qws_decoration;
+ qws_decoration = 0;
+#endif
+
+ delete mouseInWidget;
+ mouseInWidget = 0;
+}
+
+
+/*****************************************************************************
+ Platform specific global and internal functions
+ *****************************************************************************/
+
+QString QApplicationPrivate::appName() const // get application name
+{
+ return ::appName;
+}
+
+/*****************************************************************************
+ Platform specific QApplication members
+ *****************************************************************************/
+
+#define NoValue 0x0000
+#define XValue 0x0001
+#define YValue 0x0002
+#define WidthValue 0x0004
+#define HeightValue 0x0008
+#define AllValues 0x000F
+#define XNegative 0x0010
+#define YNegative 0x0020
+
+/* Copyright notice for ReadInteger and parseGeometry
+
+Copyright (c) 1985, 1986, 1987 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+/*
+ * XParseGeometry parses strings of the form
+ * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
+ * width, height, xoffset, and yoffset are unsigned integers.
+ * Example: "=80x24+300-49"
+ * The equal sign is optional.
+ * It returns a bitmask that indicates which of the four values
+ * were actually found in the string. For each value found,
+ * the corresponding argument is updated; for each value
+ * not found, the corresponding argument is left unchanged.
+ */
+
+static int
+ReadInteger(char *string, char **NextString)
+{
+ register int Result = 0;
+ int Sign = 1;
+
+ if (*string == '+')
+ string++;
+ else if (*string == '-')
+ {
+ string++;
+ Sign = -1;
+ }
+ for (; (*string >= '0') && (*string <= '9'); string++)
+ {
+ Result = (Result * 10) + (*string - '0');
+ }
+ *NextString = string;
+ if (Sign >= 0)
+ return Result;
+ else
+ return -Result;
+}
+
+static int parseGeometry(const char* string,
+ int* x, int* y, int* width, int* height)
+{
+ int mask = NoValue;
+ register char *strind;
+ unsigned int tempWidth=0, tempHeight=0;
+ int tempX=0, tempY=0;
+ char *nextCharacter;
+
+ if (!string || (*string == '\0')) return mask;
+ if (*string == '=')
+ string++; /* ignore possible '=' at beg of geometry spec */
+
+ strind = const_cast<char *>(string);
+ if (*strind != '+' && *strind != '-' && *strind != 'x') {
+ tempWidth = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= WidthValue;
+ }
+
+ if (*strind == 'x' || *strind == 'X') {
+ strind++;
+ tempHeight = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= HeightValue;
+ }
+
+ if ((*strind == '+') || (*strind == '-')) {
+ if (*strind == '-') {
+ strind++;
+ tempX = -ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= XNegative;
+
+ }
+ else
+ { strind++;
+ tempX = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ }
+ mask |= XValue;
+ if ((*strind == '+') || (*strind == '-')) {
+ if (*strind == '-') {
+ strind++;
+ tempY = -ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= YNegative;
+
+ }
+ else
+ {
+ strind++;
+ tempY = ReadInteger(strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ }
+ mask |= YValue;
+ }
+ }
+
+ /* If strind isn't at the end of the string then it's an invalid
+ geometry specification. */
+
+ if (*strind != '\0') return 0;
+
+ if (mask & XValue)
+ *x = tempX;
+ if (mask & YValue)
+ *y = tempY;
+ if (mask & WidthValue)
+ *width = tempWidth;
+ if (mask & HeightValue)
+ *height = tempHeight;
+ return mask;
+}
+
+#ifdef QT3_SUPPORT
+void QApplication::setMainWidget(QWidget *mainWidget)
+{
+ QApplicationPrivate::main_widget = mainWidget;
+ if (QApplicationPrivate::main_widget) // give WM command line
+ QApplicationPrivate::applyQWSSpecificCommandLineArguments(QApplicationPrivate::main_widget);
+}
+#endif
+
+void QApplicationPrivate::applyQWSSpecificCommandLineArguments(QWidget *main_widget)
+{
+ static bool beenHereDoneThat = false;
+ if (beenHereDoneThat)
+ return;
+ beenHereDoneThat = true;
+ if (qApp->windowIcon().isNull() && main_widget->testAttribute(Qt::WA_SetWindowIcon))
+ qApp->setWindowIcon(main_widget->windowIcon());
+ if (mwTitle) // && main_widget->windowTitle().isEmpty())
+ main_widget->setWindowTitle(QString::fromLocal8Bit(mwTitle));
+ if (mwGeometry) { // parse geometry
+ int x = 0;
+ int y = 0;
+ int w = 0;
+ int h = 0;
+ int m = parseGeometry(mwGeometry, &x, &y, &w, &h);
+ QSize minSize = main_widget->minimumSize();
+ QSize maxSize = main_widget->maximumSize();
+ if ((m & XValue) == 0)
+ x = main_widget->geometry().x();
+ if ((m & YValue) == 0)
+ y = main_widget->geometry().y();
+ if ((m & WidthValue) == 0)
+ w = main_widget->width();
+ if ((m & HeightValue) == 0)
+ h = main_widget->height();
+ w = qMin(w,maxSize.width());
+ h = qMin(h,maxSize.height());
+ w = qMax(w,minSize.width());
+ h = qMax(h,minSize.height());
+ if ((m & XNegative)) {
+ x = qApp->desktop()->width() + x - w;
+ x -= (main_widget->frameGeometry().width() - main_widget->width()) / 2;
+ } else {
+ x += (main_widget->geometry().x() - main_widget->x());
+ }
+ if ((m & YNegative)) {
+ y = qApp->desktop()->height() + y - h;
+ } else {
+ y += (main_widget->geometry().y() - main_widget->y());
+ }
+
+ main_widget->setGeometry(x, y, w, h);
+ }
+}
+
+/*****************************************************************************
+ QApplication cursor stack
+ *****************************************************************************/
+#ifndef QT_NO_CURSOR
+void QApplication::setOverrideCursor(const QCursor &cursor)
+{
+ qApp->d_func()->cursor_list.prepend(cursor);
+
+ QWidget *w = QWidget::mouseGrabber();
+ if (!w && qt_last_x)
+ w = topLevelAt(*qt_last_x, *qt_last_y);
+ if (!w)
+ w = desktop();
+ QPaintDevice::qwsDisplay()->selectCursor(w, qApp->d_func()->cursor_list.first().handle());
+}
+
+void QApplication::restoreOverrideCursor()
+{
+ if (qApp->d_func()->cursor_list.isEmpty())
+ return;
+ qApp->d_func()->cursor_list.removeFirst();
+
+ QWidget *w = QWidget::mouseGrabber();
+ if (!w && qt_last_x)
+ w = topLevelAt(*qt_last_x, *qt_last_y);
+ if (!w)
+ w = desktop();
+
+ int cursor_handle = Qt::ArrowCursor;
+ if (qApp->d_func()->cursor_list.isEmpty()) {
+ qws_overrideCursor = false;
+ QWidget *upw = QApplication::widgetAt(*qt_last_x, *qt_last_y);
+ if (upw)
+ cursor_handle = upw->cursor().handle();
+ } else {
+ cursor_handle = qApp->d_func()->cursor_list.first().handle();
+ }
+ QPaintDevice::qwsDisplay()->selectCursor(w, cursor_handle);
+}
+#endif// QT_NO_CURSOR
+
+
+
+/*****************************************************************************
+ Routines to find a Qt widget from a screen position
+ *****************************************************************************/
+
+/*!
+ \internal
+*/
+QWidget *QApplicationPrivate::findWidget(const QObjectList& list,
+ const QPoint &pos, bool rec)
+{
+ QWidget *w;
+
+ for (int i = list.size()-1; i >= 0; --i) {
+ if (list.at(i)->isWidgetType()) {
+ w = static_cast<QWidget*>(list.at(i));
+ if (w->isVisible() && !w->testAttribute(Qt::WA_TransparentForMouseEvents) && w->geometry().contains(pos)
+ && (!w->d_func()->extra || w->d_func()->extra->mask.isEmpty() || w->d_func()->extra->mask.contains(pos - w->geometry().topLeft()) )) {
+ if (!rec)
+ return w;
+ QWidget *c = w->childAt(w->mapFromParent(pos));
+ return c ? c : w;
+ }
+ }
+ }
+ return 0;
+}
+
+
+QWidget *QApplication::topLevelAt(const QPoint &pos)
+{
+ //### QWSDisplay::windowAt() is currently only implemented in the server process
+ int winId = QPaintDevice::qwsDisplay()->windowAt(pos);
+ if (winId !=0)
+ return QWidget::find(winId);
+
+#if 1
+ // fallback implementation for client processes
+//### This is slightly wrong: we have no guarantee that the list is in
+//### stacking order, so if the topmost window is transparent, we may
+//### return the wrong widget
+
+ QWidgetList list = topLevelWidgets();
+ for (int i = list.size()-1; i >= 0; --i) {
+ QWidget *w = list[i];
+ if (w != QApplication::desktop() &&
+ w->isVisible() && w->d_func()->localAllocatedRegion().contains(w->mapFromParent(pos))
+ )
+ return w;
+ }
+#endif
+ return 0;
+}
+
+void QApplication::beep()
+{
+}
+
+void QApplication::alert(QWidget *, int)
+{
+}
+
+/*!
+ \internal
+*/
+int QApplication::qwsProcessEvent(QWSEvent* event)
+{
+ Q_D(QApplication);
+ QScopedLoopLevelCounter loopLevelCounter(d->threadData);
+ int oldstate = -1;
+ bool isMove = false;
+ if (event->type == QWSEvent::Mouse) {
+ QWSMouseEvent::SimpleData &mouse = event->asMouse()->simpleData;
+ isMove = mouse_x_root != mouse.x_root || mouse_y_root != mouse.y_root;
+ oldstate = mouse_state;
+ mouse_x_root = mouse.x_root;
+ mouse_y_root = mouse.y_root;
+ mouse_state = mouse.state;
+ }
+
+ long unused;
+ if (filterEvent(event, &unused)) // send through app filter
+ return 1;
+
+ if (qwsEventFilter(event)) // send through app filter
+ return 1;
+
+
+#ifndef QT_NO_QWS_PROPERTIES
+ if (event->type == QWSEvent::PropertyNotify) {
+ QWSPropertyNotifyEvent *e = static_cast<QWSPropertyNotifyEvent*>(event);
+ if (e->simpleData.property == 424242) { // Clipboard
+#ifndef QT_NO_CLIPBOARD
+ if (qt_clipboard) {
+ QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
+ QApplication::sendEvent(qt_clipboard, &e);
+ }
+#endif
+ }
+ }
+#endif //QT_NO_QWS_PROPERTIES
+#ifndef QT_NO_COP
+ else if (event->type == QWSEvent::QCopMessage) {
+ QWSQCopMessageEvent *e = static_cast<QWSQCopMessageEvent*>(event);
+ QCopChannel::sendLocally(QLatin1String(e->channel), QLatin1String(e->message), e->data);
+ return 0;
+ }
+#endif
+#if !defined(QT_NO_QWS_QPF2)
+ else if (event->type == QWSEvent::Font) {
+ QWSFontEvent *e = static_cast<QWSFontEvent *>(event);
+ if (e->simpleData.type == QWSFontEvent::FontRemoved) {
+ QFontCache::instance()->removeEngineForFont(e->fontName);
+ }
+ }
+#endif
+
+ QPointer<QETWidget> widget = static_cast<QETWidget*>(QWidget::find(WId(event->window())));
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ if (!widget) { // XXX: hw: hack for accessing subsurfaces
+ extern QWSWindowSurface* qt_findWindowSurface(int);
+ QWSWindowSurface *s = qt_findWindowSurface(event->window());
+ if (s)
+ widget = static_cast<QETWidget*>(s->window());
+ }
+#endif
+
+#ifndef QT_NO_DIRECTPAINTER
+ if (!widget && d->directPainters) {
+ QDirectPainter *dp = d->directPainters->value(WId(event->window()));
+ if (dp == 0) {
+ } else if (event->type == QWSEvent::Region) {
+ QWSRegionEvent *e = static_cast<QWSRegionEvent*>(event);
+ QRegion reg;
+ reg.setRects(e->rectangles, e->simpleData.nrectangles);
+ qt_directpainter_region(dp, reg, e->simpleData.type);
+ return 1;
+#ifndef QT_NO_QWSEMBEDWIDGET
+ } else if (event->type == QWSEvent::Embed) {
+ QWSEmbedEvent *e = static_cast<QWSEmbedEvent*>(event);
+ qt_directpainter_embedevent(dp, e);
+ return 1;
+ #endif // QT_NO_QWSEMBEDWIDGET
+ }
+ }
+#endif // QT_NO_DIRECTPAINTER
+
+#ifndef QT_NO_QWS_MANAGER
+ if (d->last_manager && event->type == QWSEvent::Mouse) {
+ QPoint pos(event->asMouse()->simpleData.x_root, event->asMouse()->simpleData.y_root);
+ if (!d->last_manager->cachedRegion().contains(pos)) {
+ // MouseEvent not yet delivered, so QCursor::pos() is not yet updated, sending 2 x pos
+ QMouseEvent outside(QEvent::MouseMove, pos, pos, Qt::NoButton, 0, 0);
+ QApplication::sendSpontaneousEvent(d->last_manager, &outside);
+ d->last_manager = 0;
+ qt_last_cursor = 0xffffffff; //decoration is like another window; must redo cursor
+ }
+ }
+#endif // QT_NO_QWS_MANAGER
+
+ QETWidget *keywidget=0;
+ bool grabbed=false;
+ if (event->type==QWSEvent::Key || event->type == QWSEvent::IMEvent || event->type == QWSEvent::IMQuery) {
+ keywidget = static_cast<QETWidget*>(QWidget::keyboardGrabber());
+ if (keywidget) {
+ grabbed = true;
+ } else {
+ if (QWidget *popup = QApplication::activePopupWidget()) {
+ if (popup->focusWidget())
+ keywidget = static_cast<QETWidget*>(popup->focusWidget());
+ else
+ keywidget = static_cast<QETWidget*>(popup);
+ } else if (QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget->isVisible())
+ keywidget = static_cast<QETWidget*>(QApplicationPrivate::focus_widget);
+ else if (widget)
+ keywidget = static_cast<QETWidget*>(widget->window());
+ }
+ } else if (event->type==QWSEvent::MaxWindowRect) {
+ QRect r = static_cast<QWSMaxWindowRectEvent*>(event)->simpleData.rect;
+ setMaxWindowRect(r);
+ return 0;
+#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
+ } else if (event->type == QWSEvent::ScreenTransformation) {
+ QWSScreenTransformationEvent *pe = static_cast<QWSScreenTransformationEvent*>(event);
+ setScreenTransformation(pe->simpleData.screen,
+ pe->simpleData.transformation);
+ return 0;
+#endif
+ } else if (widget && event->type==QWSEvent::Mouse) {
+ // The mouse event is to one of my top-level widgets
+ // which one?
+ const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
+ QPoint p(event->asMouse()->simpleData.x_root,
+ event->asMouse()->simpleData.y_root);
+ int mouseButtonState = event->asMouse()->simpleData.state & btnMask;
+ static int btnstate = 0;
+
+ QETWidget *w = static_cast<QETWidget*>(QWidget::mouseGrabber());
+ if (w && !mouseButtonState && qt_pressGrab == w)
+ qt_pressGrab = 0;
+#ifndef QT_NO_QWS_MANAGER
+ if (!w)
+ w = static_cast<QETWidget*>(QWSManager::grabbedMouse());
+#endif
+ if (w) {
+ // Our mouse is grabbed - send it.
+ widget = w;
+ btnstate = mouseButtonState;
+ } else {
+ static QWidget *gw = 0;
+ // Three jobs to do here:
+ // 1. find the child widget this event belongs to.
+ // 2. make sure the cursor is correct.
+ // 3. handle implicit mouse grab due to button press.
+ w = widget; // w is the widget the cursor is in.
+
+ //### ??? alloc_region
+ //#### why should we get events outside alloc_region ????
+ if (1 /*widget->data->alloc_region.contains(dp) */) {
+ // Find the child widget that the cursor is in.
+ w = static_cast<QETWidget*>(widget->childAt(widget->mapFromParent(p)));
+ if (!w)
+ w = widget;
+#ifndef QT_NO_CURSOR
+ // Update Cursor.
+ if (!gw || gw != w || qt_last_cursor == 0xffffffff) {
+ QCursor *curs = 0;
+ if (!qApp->d_func()->cursor_list.isEmpty())
+ curs = &qApp->d_func()->cursor_list.first();
+ else if (w->d_func()->extraData())
+ curs = w->d_func()->extraData()->curs;
+ QWidget *pw = w;
+ // If this widget has no cursor set, try parent.
+ while (!curs) {
+ pw = pw->parentWidget();
+ if (!pw)
+ break;
+ if (pw->d_func()->extraData())
+ curs = pw->d_func()->extraData()->curs;
+ }
+ if (!qws_overrideCursor) {
+ if (curs)
+ QPaintDevice::qwsDisplay()->selectCursor(widget, curs->handle());
+ else
+ QPaintDevice::qwsDisplay()->selectCursor(widget, Qt::ArrowCursor);
+ }
+ }
+#endif
+ gw = w;
+ } else {
+ // This event is not for any of our widgets
+ gw = 0;
+ }
+ if (mouseButtonState && !btnstate) {
+ // The server has grabbed the mouse for us.
+ // Remember which of my widgets has it.
+ qt_pressGrab = w;
+ if (!widget->isActiveWindow() &&
+ (!app_do_modal || QApplication::activeModalWidget() == widget) &&
+ !((widget->windowFlags() & Qt::FramelessWindowHint) || (widget->windowType() == Qt::Tool))) {
+ widget->activateWindow();
+ if (widget->raiseOnClick())
+ widget->raise();
+ }
+ }
+ btnstate = mouseButtonState;
+ widget = w;
+ }
+ }
+
+ if (!widget) { // don't know this window
+ if (!QWidget::mouseGrabber()
+#ifndef QT_NO_QWS_MANAGER
+ && !QWSManager::grabbedMouse()
+#endif
+ ) {
+ qt_last_cursor = 0xffffffff; // cursor can be changed by another application
+ }
+
+ QWidget* popup = QApplication::activePopupWidget();
+ if (popup) {
+
+ /*
+ That is more than suboptimal. The real solution should
+ do some keyevent and buttonevent translation, so that
+ the popup still continues to work as the user expects.
+ Unfortunately this translation is currently only
+ possible with a known widget. I'll change that soon
+ (Matthias).
+ */
+
+ // Danger - make sure we don't lock the server
+ switch (event->type) {
+ case QWSEvent::Mouse:
+ case QWSEvent::Key:
+ do {
+ popup->close();
+ } while ((popup = qApp->activePopupWidget()));
+ return 1;
+ }
+ }
+ if (event->type == QWSEvent::Mouse && *mouseInWidget) {
+ QApplicationPrivate::dispatchEnterLeave(0, *mouseInWidget);
+ (*mouseInWidget) = 0;
+ }
+ return -1;
+ }
+
+ if (app_do_modal) // modal event handling
+ if (!qt_try_modal(widget, event)) {
+ return 1;
+ }
+
+ if (widget->qwsEvent(event)) // send through widget filter
+ return 1;
+ switch (event->type) {
+
+ case QWSEvent::Mouse: { // mouse event
+ QWSMouseEvent *me = event->asMouse();
+ QWSMouseEvent::SimpleData &mouse = me->simpleData;
+
+ // Translate a QWS event into separate move
+ // and press/release events
+ // Beware of reentrancy: we can enter a modal state
+ // inside translateMouseEvent
+
+ if (isMove) {
+ QWSMouseEvent move = *me;
+ move.simpleData.state = oldstate;
+ widget->translateMouseEvent(&move, oldstate);
+ }
+ if ((mouse.state&Qt::MouseButtonMask) != (oldstate&Qt::MouseButtonMask)) {
+ widget->translateMouseEvent(me, oldstate);
+ }
+
+ if (mouse.delta != 0)
+ widget->translateWheelEvent(me);
+
+ if (qt_button_down && (mouse_state & Qt::MouseButtonMask) == 0)
+ qt_button_down = 0;
+
+ break;
+ }
+ case QWSEvent::Key: // keyboard event
+ if (keywidget) // should always exist
+ keywidget->translateKeyEvent(static_cast<QWSKeyEvent*>(event), grabbed);
+ break;
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ case QWSEvent::IMEvent:
+ if (keywidget) // should always exist
+ QWSInputContext::translateIMEvent(keywidget, static_cast<QWSIMEvent*>(event));
+ break;
+
+ case QWSEvent::IMQuery:
+ if (keywidget) // should always exist
+ QWSInputContext::translateIMQueryEvent(keywidget, static_cast<QWSIMQueryEvent*>(event));
+ break;
+
+ case QWSEvent::IMInit:
+ QWSInputContext::translateIMInitEvent(static_cast<QWSIMInitEvent*>(event));
+ break;
+#endif
+ case QWSEvent::Region:
+ widget->translateRegionEvent(static_cast<QWSRegionEvent*>(event));
+ break;
+ case QWSEvent::Focus:
+ if ((static_cast<QWSFocusEvent*>(event))->simpleData.get_focus) {
+ if (widget == static_cast<QWidget *>(desktop()))
+ return true; // not interesting
+ if (activeWindow() != widget) {
+ setActiveWindow(widget);
+ if (QApplicationPrivate::active_window)
+ static_cast<QETWidget *>(QApplicationPrivate::active_window)->repaintDecoration(desktop()->rect(), false);
+ if (widget && !d->inPopupMode()) {
+ QWidget *w = widget->focusWidget();
+ while (w && w->focusProxy())
+ w = w->focusProxy();
+ if (w && (w->focusPolicy() != Qt::NoFocus))
+ w->setFocus();
+ else
+ widget->QWidget::focusNextPrevChild(true);
+ if (!QApplicationPrivate::focus_widget) {
+ if (widget->focusWidget())
+ widget->focusWidget()->setFocus();
+ else
+ widget->window()->setFocus();
+ }
+ }
+ }
+ } else { // lost focus
+ if (widget == static_cast<QWidget *>(desktop()))
+ return true; // not interesting
+ if (QApplicationPrivate::focus_widget) {
+ QETWidget *old = static_cast<QETWidget *>(QApplicationPrivate::active_window);
+ setActiveWindow(0);
+ qt_last_cursor = 0xffffffff;
+ //QApplicationPrivate::active_window = 0;
+ if (old)
+ old->repaintDecoration(desktop()->rect(), false);
+ /* activateWindow() sends focus events
+ QApplication::setFocusWidget(0);
+ */
+ }
+ }
+ break;
+
+ case QWSEvent::WindowOperation:
+ if (static_cast<QWidget *>(widget) == desktop())
+ return true;
+ switch ((static_cast<QWSWindowOperationEvent *>(event))->simpleData.op) {
+ case QWSWindowOperationEvent::Show:
+ widget->show();
+ break;
+ case QWSWindowOperationEvent::Hide:
+ widget->hide();
+ break;
+ case QWSWindowOperationEvent::ShowMaximized:
+ widget->showMaximized();
+ break;
+ case QWSWindowOperationEvent::ShowMinimized:
+ widget->showMinimized();
+ break;
+ case QWSWindowOperationEvent::ShowNormal:
+ widget->showNormal();
+ break;
+ case QWSWindowOperationEvent::Close:
+ widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+ break;
+ }
+ break;
+#ifndef QT_NO_QWSEMBEDWIDGET
+ case QWSEvent::Embed:
+ widget->translateEmbedEvent(static_cast<QWSEmbedEvent*>(event));
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ \fn bool QApplication::qwsEventFilter(QWSEvent *event)
+
+ This virtual function is only implemented under Qt for Embedded Linux.
+
+ If you create an application that inherits QApplication and
+ reimplement this function, you get direct access to all QWS (Q
+ Window System) events that the are received from the QWS master
+ process. The events are passed in the \a event parameter.
+
+ Return true if you want to stop the event from being processed.
+ Return false for normal event dispatching. The default
+ implementation returns false.
+*/
+bool QApplication::qwsEventFilter(QWSEvent *)
+{
+ return false;
+}
+
+/*!
+ Set Qt for Embedded Linux custom color table.
+
+ Qt for Embedded Linux on 8-bpp displays allocates a standard 216 color cube.
+ The remaining 40 colors may be used by setting a custom color
+ table in the QWS master process before any clients connect.
+
+ \a colorTable is an array of up to 40 custom colors. \a start is
+ the starting index (0-39) and \a numColors is the number of colors
+ to be set (1-40).
+
+ This method is non-portable. It is available \e only in
+ Qt for Embedded Linux.
+
+ \note The custom colors will not be used by the default screen
+ driver. To make use of the new colors, implement a custom screen
+ driver, or use QDirectPainter.
+*/
+void QApplication::qwsSetCustomColors(QRgb *colorTable, int start, int numColors)
+{
+ if (start < 0 || start > 39) {
+ qWarning("QApplication::qwsSetCustomColors: start < 0 || start > 39");
+ return;
+ }
+ if (start + numColors > 40) {
+ numColors = 40 - start;
+ qWarning("QApplication::qwsSetCustomColors: Too many colors");
+ }
+ start += 216;
+ for (int i = 0; i < numColors; i++) {
+ qt_screen->set(start + i, qRed(colorTable[i]), qGreen(colorTable[i]),
+ qBlue(colorTable[i]));
+ }
+}
+
+#ifndef QT_NO_QWS_MANAGER
+/*!
+ Return the QWSDecoration used for decorating windows.
+
+ \warning This method is non-portable. It is only available in
+ Qt for Embedded Linux.
+
+ \sa QDecoration
+*/
+QDecoration &QApplication::qwsDecoration()
+{
+ return *qws_decoration;
+}
+
+/*!
+ \fn void QApplication::qwsSetDecoration(QDecoration *decoration)
+
+ Sets the QDecoration derived class to use for decorating the
+ windows used by Qt for Embedded Linux to the \a decoration
+ specified.
+
+ This method is non-portable. It is only available in Qt for Embedded Linux.
+
+ \sa QDecoration
+*/
+void QApplication::qwsSetDecoration(QDecoration *dec)
+{
+ if (dec) {
+ delete qws_decoration;
+ qws_decoration = dec;
+ QWidgetList widgets = topLevelWidgets();
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *w = widgets[i];
+ if (w->isVisible() && w != desktop()) {
+ static_cast<QETWidget *>(w)->updateRegion();
+ static_cast<QETWidget *>(w)->repaintDecoration(desktop()->rect(), false);
+ if (w->isMaximized())
+ w->showMaximized();
+ }
+ }
+ }
+}
+
+/*!
+ \overload
+
+ Requests a QDecoration object for \a decoration from the QDecorationFactory.
+
+ The string must be one of the QDecorationFactory::keys(). Keys are
+ case insensitive.
+
+ A later call to the QApplication constructor will override the
+ requested style when a "-style" option is passed in as a commandline
+ parameter.
+
+ Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object
+ returned is set as the application's GUI style.
+*/
+QDecoration* QApplication::qwsSetDecoration(const QString &decoration)
+{
+ QDecoration *decore = QDecorationFactory::create(decoration);
+ if (!decore)
+ return 0;
+
+ qwsSetDecoration(decore);
+ return decore;
+}
+
+#endif
+
+bool QApplicationPrivate::modalState()
+{
+ return app_do_modal;
+}
+
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
+{
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+ qt_modal_stack->insert(0, widget);
+ app_do_modal = true;
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *widget)
+{
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ }
+ }
+ app_do_modal = qt_modal_stack != 0;
+}
+
+static bool qt_try_modal(QWidget *widget, QWSEvent *event)
+{
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ bool block_event = false;
+ bool paint_event = false;
+
+ switch (event->type) {
+ case QWSEvent::Focus:
+ if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
+ break;
+ // drop through
+ case QWSEvent::Mouse: // disallow mouse/key events
+ case QWSEvent::Key:
+ block_event = true;
+ break;
+ }
+
+ if (top->parentWidget() == 0 && (block_event || paint_event))
+ top->raise();
+
+ return !block_event;
+}
+
+static int openPopupCount = 0;
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ openPopupCount++;
+ if (!popupWidgets) { // create list
+ popupWidgets = new QWidgetList;
+
+ /* only grab if you are the first/parent popup */
+ QPaintDevice::qwsDisplay()->grabMouse(popup,true);
+ QPaintDevice::qwsDisplay()->grabKeyboard(popup,true);
+ popupGrabOk = true;
+ }
+ popupWidgets->append(popup); // add to end of list
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (popupWidgets->count() == 1) { // this was the first popup
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ QApplication::sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ if (!popupWidgets)
+ return;
+
+ popupWidgets->removeAll(popup);
+ if (popup == popupOfPopupButtonFocus) {
+ popupButtonFocus = 0;
+ popupOfPopupButtonFocus = 0;
+ }
+ if (popupWidgets->count() == 0) { // this was the last popup
+ popupCloseDownMode = true; // control mouse events
+ delete popupWidgets;
+ popupWidgets = 0;
+ if (popupGrabOk) { // grabbing not disabled
+ QPaintDevice::qwsDisplay()->grabMouse(popup,false);
+ QPaintDevice::qwsDisplay()->grabKeyboard(popup,false);
+ popupGrabOk = false;
+ // XXX ungrab keyboard
+ }
+ if (active_window) {
+ if (QWidget *fw = active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ QApplication::sendEvent(fw, &e);
+ }
+ }
+ }
+ } else {
+ // popups are not focus-handled by the window system (the
+ // first popup grabbed the keyboard), so we have to do that
+ // manually: A popup was closed, so the previous popup gets
+ // the focus.
+ QWidget* aw = popupWidgets->last();
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+ }
+}
+
+/*****************************************************************************
+ Event translation; translates FB events to Qt events
+ *****************************************************************************/
+
+//
+// Mouse event translation
+//
+// FB doesn't give mouse double click events, so we generate them by
+// comparing window, time and position between two mouse press events.
+//
+
+
+// Needed for QCursor::pos
+
+static const int AnyButton = (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
+
+
+
+//
+// Wheel event translation
+//
+bool QETWidget::translateWheelEvent(const QWSMouseEvent *me)
+{
+#ifdef QT_NO_WHEELEVENT
+ Q_UNUSED(me);
+ return false;
+#else
+ const QWSMouseEvent::SimpleData &mouse = me->simpleData;
+
+ // Figure out wheeling direction:
+ // Horizontal wheel w/o Alt
+ // OR Vertical wheel w/ Alt ==> Horizontal wheeling
+ // ..all other permutations ==> Vertical wheeling
+ int axis = mouse.delta / 120; // WHEEL_DELTA?
+ Qt::Orientation orient = ((axis == 2 || axis == -2) && ((mouse.state & Qt::AltModifier) == 0))
+ ||((axis == 1 || axis == -1) && mouse.state & Qt::AltModifier)
+ ? Qt::Horizontal : Qt::Vertical;
+
+ QPoint mousePoint = QPoint(mouse.x_root, mouse.y_root);
+
+ // send the event to the widget or its ancestors
+ QWidget* popup = qApp->activePopupWidget();
+ if (popup && window() != popup)
+ popup->close();
+ QWheelEvent we(mapFromGlobal(mousePoint), mousePoint, mouse.delta,
+ Qt::MouseButtons(mouse.state & Qt::MouseButtonMask),
+ Qt::KeyboardModifiers(mouse.state & Qt::KeyboardModifierMask), orient);
+ if (QApplication::sendSpontaneousEvent(this, &we))
+ return true;
+
+ // send the event to the widget that has the focus or its ancestors, if different
+ QWidget *w = this;
+ if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
+ QWidget* popup = qApp->activePopupWidget();
+ if (popup && w != popup)
+ popup->hide();
+ if (QApplication::sendSpontaneousEvent(w, &we))
+ return true;
+ }
+ return false;
+#endif
+}
+
+bool QETWidget::translateMouseEvent(const QWSMouseEvent *event, int prevstate)
+{
+ static bool manualGrab = false;
+ QPoint pos;
+ QPoint globalPos;
+ int button = 0;
+
+ if (sm_blockUserInput) // block user interaction during session management
+ return true;
+ const QWSMouseEvent::SimpleData &mouse = event->simpleData;
+ pos = mapFromGlobal(QPoint(mouse.x_root, mouse.y_root));
+// if (qt_last_x) {
+// *qt_last_x=mouse.x_root;
+// *qt_last_y=mouse.y_root;
+// }
+ globalPos.rx() = mouse.x_root;
+ globalPos.ry() = mouse.y_root;
+
+ QEvent::Type type = QEvent::None;
+
+ Qt::MouseButtons buttonstate = Qt::MouseButtons(mouse.state & Qt::MouseButtonMask);
+ Qt::KeyboardModifiers keystate = Qt::KeyboardModifiers(mouse.state & Qt::KeyboardModifierMask);
+
+ if (mouse.state == prevstate) {
+ // mouse move
+ type = QEvent::MouseMove;
+ } else if ((mouse.state&AnyButton) != (prevstate&AnyButton)) {
+ Qt::MouseButtons current_buttons = Qt::MouseButtons(prevstate&Qt::MouseButtonMask);
+ for (button = Qt::LeftButton; !type && button <= Qt::MidButton; button<<=1) {
+ if ((mouse.state&button) != (current_buttons&button)) {
+ // button press or release
+ current_buttons = Qt::MouseButtons(current_buttons ^ button);
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ //############ We used to do a QInputContext::reset(oldFocus);
+ // when we changed the focus widget. See change 93389 for where the
+ // focus code went. The IM code was (after testing for ClickToFocus):
+ //if (mouse.state&button && w != QInputContext::microFocusWidget()) //button press
+ // QInputContext::reset(oldFocus);
+
+#endif
+ if (mouse.state&button) { //button press
+ qt_button_down = childAt(pos);
+ if (!qt_button_down)
+ qt_button_down = this;
+ if (/*XXX mouseActWindow == this &&*/
+ mouseButtonPressed == button &&
+ long(mouse.time) -long(mouseButtonPressTime)
+ < QApplication::doubleClickInterval() &&
+ qAbs(mouse.x_root - mouseXPos) < mouse_double_click_distance &&
+ qAbs(mouse.y_root - mouseYPos) < mouse_double_click_distance ) {
+ type = QEvent::MouseButtonDblClick;
+ mouseButtonPressTime -= 2000; // no double-click next time
+ } else {
+ type = QEvent::MouseButtonPress;
+ mouseButtonPressTime = mouse.time;
+ }
+ mouseButtonPressed = button; // save event params for
+ mouseXPos = globalPos.x(); // future double click tests
+ mouseYPos = globalPos.y();
+ } else { // mouse button released
+ if (manualGrab) { // release manual grab
+ manualGrab = false;
+ // XXX XUngrabPointer(x11Display(), CurrentTime);
+ }
+
+ type = QEvent::MouseButtonRelease;
+ }
+ }
+ }
+ button >>= 1;
+ }
+ //XXX mouseActWindow = winId(); // save some event params
+
+ if (type == 0) { // event consumed
+ return false; //EXIT in the normal case
+ }
+
+ if (qApp->d_func()->inPopupMode()) { // in popup mode
+ QWidget *popup = qApp->activePopupWidget();
+ // in X11, this would be the window we are over.
+ // in QWS this is the top level popup. to allow mouse
+ // events to other widgets, need to go through qApp->QApplicationPrivate::popupWidgets.
+ QSize s(qt_screen->width(), qt_screen->height());
+ for (int i = 0; i < QApplicationPrivate::popupWidgets->size(); ++i) {
+ QWidget *w = QApplicationPrivate::popupWidgets->at(i);
+
+ if ((w->windowType() == Qt::Popup) && w->d_func()->localAllocatedRegion().contains(globalPos - w->geometry().topLeft()))
+ {
+ popup = w;
+ break;
+ }
+ }
+ pos = popup->mapFromGlobal(globalPos);
+ bool releaseAfter = false;
+ QWidget *popupChild = popup->childAt(pos);
+ QWidget *popupTarget = popupChild ? popupChild : popup;
+
+ if (popup != popupOfPopupButtonFocus){
+ popupButtonFocus = 0;
+ popupOfPopupButtonFocus = 0;
+ }
+
+ if (!popupTarget->isEnabled()) {
+ return false; //EXIT special case
+ }
+
+ switch (type) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ popupButtonFocus = popupChild;
+ popupOfPopupButtonFocus = popup;
+ break;
+ case QEvent::MouseButtonRelease:
+ releaseAfter = true;
+ break;
+ default:
+ break; // nothing for mouse move
+ }
+
+ int oldOpenPopupCount = openPopupCount;
+
+ if (popupButtonFocus) {
+ QMouseEvent e(type, popupButtonFocus->mapFromGlobal(globalPos),
+ globalPos, Qt::MouseButton(button), buttonstate, keystate);
+ QApplication::sendSpontaneousEvent(popupButtonFocus, & e);
+ if (releaseAfter) {
+ popupButtonFocus = 0;
+ popupOfPopupButtonFocus = 0;
+ }
+ } else if (popupChild) {
+ QMouseEvent e(type, popupChild->mapFromGlobal(globalPos),
+ globalPos, Qt::MouseButton(button), buttonstate, keystate);
+ QApplication::sendSpontaneousEvent(popupChild, & e);
+ } else {
+ QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), buttonstate, keystate);
+ QApplication::sendSpontaneousEvent(popupChild ? popupChild : popup, & e);
+ }
+#ifndef QT_NO_CONTEXTMENU
+ if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) {
+ QWidget *popupEvent = popup;
+ if(popupButtonFocus)
+ popupEvent = popupButtonFocus;
+ else if(popupChild)
+ popupEvent = popupChild;
+ QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, keystate);
+ QApplication::sendSpontaneousEvent(popupEvent, &e);
+ }
+#endif // QT_NO_CONTEXTMENU
+
+ if (releaseAfter)
+ qt_button_down = 0;
+
+ } else { //qApp not in popup mode
+ QWidget *widget = this;
+ QWidget *w = QWidget::mouseGrabber();
+ if (!w && qt_button_down)
+ w = qt_button_down;
+ if (w && w != this) {
+ widget = w;
+ pos = mapToGlobal(pos);
+ pos = w->mapFromGlobal(pos);
+ }
+
+ if (popupCloseDownMode) {
+ popupCloseDownMode = false;
+ if ((windowType() == Qt::Popup)) // ignore replayed event
+ return true; //EXIT
+ }
+
+ QPointer<QWidget> leaveAfterRelease = 0;
+ if (type == QEvent::MouseButtonRelease &&
+ (mouse.state & (~button) & (Qt::LeftButton |
+ Qt::MidButton |
+ Qt::RightButton)) == 0) {
+ // Button released outside the widget -> leave the widget after the
+ // release event has been delivered.
+ if (widget == qt_button_down && (pos.x() < 0 || pos.y() < 0))
+ leaveAfterRelease = qt_button_down;
+ qt_button_down = 0;
+ }
+
+ int oldOpenPopupCount = openPopupCount;
+
+ QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), buttonstate, keystate);
+#ifndef QT_NO_QWS_MANAGER
+ if (widget->isWindow() && widget->d_func()->topData()->qwsManager
+ && (widget->d_func()->topData()->qwsManager->region().contains(globalPos)
+ || QWSManager::grabbedMouse() )) {
+ if ((*mouseInWidget)) {
+ QApplicationPrivate::dispatchEnterLeave(0, *mouseInWidget);
+ (*mouseInWidget) = 0;
+ }
+ QApplication::sendSpontaneousEvent(widget->d_func()->topData()->qwsManager, &e);
+ qApp->d_func()->last_manager = widget->d_func()->topData()->qwsManager;
+ } else
+#endif
+ {
+ if (widget != (*mouseInWidget)) {
+ QApplicationPrivate::dispatchEnterLeave(widget, *mouseInWidget);
+ (*mouseInWidget) = widget;
+ }
+ QApplication::sendSpontaneousEvent(widget, &e);
+ if (leaveAfterRelease && !QWidget::mouseGrabber()) {
+ *mouseInWidget = QApplication::widgetAt(globalPos);
+ QApplicationPrivate::dispatchEnterLeave(*mouseInWidget, leaveAfterRelease);
+ leaveAfterRelease = 0;
+ }
+ }
+#ifndef QT_NO_CONTEXTMENU
+ if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) {
+ QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, keystate);
+ QApplication::sendSpontaneousEvent(widget, &e);
+ }
+#endif // QT_NO_CONTEXTMENU
+ }
+ return true;
+}
+
+
+bool QETWidget::translateKeyEvent(const QWSKeyEvent *event, bool grab) /* grab is used in the #ifdef */
+{
+ int code = -1;
+ //### Qt assumes keyboard state is state *before*, while QWS uses state after the event
+ static Qt::KeyboardModifiers oldstate;
+ Qt::KeyboardModifiers state = oldstate;
+ oldstate = event->simpleData.modifiers;
+
+ if (sm_blockUserInput) // block user interaction during session management
+ return true;
+
+ if (!isEnabled())
+ return true;
+
+ QEvent::Type type = event->simpleData.is_press ?
+ QEvent::KeyPress : QEvent::KeyRelease;
+ bool autor = event->simpleData.is_auto_repeat;
+ QString text;
+ char ascii = 0;
+ if (event->simpleData.unicode) {
+ QChar ch(event->simpleData.unicode);
+ if (ch.unicode() != 0xffff)
+ text += ch;
+ ascii = ch.toLatin1();
+ }
+ code = event->simpleData.keycode;
+
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ if (type == QEvent::KeyPress && !grab
+ && static_cast<QApplicationPrivate*>(qApp->d_ptr)->use_compat()) {
+ // send accel events if the keyboard is not grabbed
+ QKeyEvent a(type, code, state, text, autor, int(text.length()));
+ if (static_cast<QApplicationPrivate*>(qApp->d_ptr)->qt_tryAccelEvent(this, &a))
+ return true;
+ }
+#else
+ Q_UNUSED(grab);
+#endif
+ if (!text.isEmpty() && testAttribute(Qt::WA_KeyCompression)) {
+ // the widget wants key compression so it gets it
+
+ // XXX not implemented
+ }
+
+ QKeyEvent e(type, code, state, text, autor, int(text.length()));
+ return QApplication::sendSpontaneousEvent(this, &e);
+}
+
+bool QETWidget::translateRegionEvent(const QWSRegionEvent *event)
+{
+ QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(windowSurface());
+ Q_ASSERT(surface);
+
+ QRegion region;
+ region.setRects(event->rectangles, event->simpleData.nrectangles);
+
+ switch (event->simpleData.type) {
+ case QWSRegionEvent::Allocation:
+ region.translate(-mapToGlobal(QPoint()));
+ surface->setClipRegion(region);
+ break;
+#ifdef QT_QWS_CLIENTBLIT
+ case QWSRegionEvent::DirectPaint:
+ surface->setDirectRegion(region, event->simpleData.id);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return true;
+}
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+void QETWidget::translateEmbedEvent(const QWSEmbedEvent *event)
+{
+ if (event->simpleData.type | QWSEmbedEvent::Region) {
+ const QRegion region = event->region;
+ setGeometry(region.boundingRect());
+ setVisible(!region.isEmpty());
+ }
+}
+#endif // QT_NO_QWSEMBEDWIDGET
+
+void QETWidget::repaintDecoration(QRegion r, bool post)
+{
+ Q_UNUSED(post);
+#ifdef QT_NO_QWS_MANAGER
+ Q_UNUSED(r);
+#else
+ //please note that qwsManager is a QObject, not a QWidget.
+ //therefore, normal ways of painting do not work.
+ // However, it does listen to paint events.
+
+ Q_D(QWidget);
+ if (isWindow() && d->topData()->qwsManager && isVisible()) {
+ QWSManager *manager = d->topData()->qwsManager;
+ r &= manager->region();
+ if (!r.isEmpty())
+ manager->repaintRegion(QDecoration::All, QDecoration::Normal);
+ }
+#endif
+}
+
+void QETWidget::updateRegion()
+{
+ Q_D(QWidget);
+
+ QTLWExtra *topextra = d->maybeTopData();
+ if (!topextra)
+ return;
+
+ QRegion myregion = d->localRequestedRegion();
+ myregion.translate(geometry().topLeft());
+
+#ifndef QT_NO_QWS_MANAGER
+ QWSManager *manager = topextra->qwsManager;
+ if (manager)
+ myregion += manager->region();
+#endif
+
+ QRect br(myregion.boundingRect());
+ topextra->frameStrut.setCoords(d->data.crect.x() - br.x(),
+ d->data.crect.y() - br.y(),
+ br.right() - d->data.crect.right(),
+ br.bottom() - d->data.crect.bottom());
+}
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ QApplicationPrivate::mouse_double_click_time = ms;
+}
+
+int QApplication::doubleClickInterval()
+{
+ return QApplicationPrivate::mouse_double_click_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::keyboardInputInterval()
+{
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+#ifndef QT_NO_WHEELEVENT
+void QApplication::setWheelScrollLines(int lines)
+{
+ QApplicationPrivate::wheel_scroll_lines = lines;
+}
+
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+#endif
+
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ switch (effect) {
+ case Qt::UI_AnimateMenu:
+ QApplicationPrivate::animate_menu = enable;
+ break;
+ case Qt::UI_FadeMenu:
+ if (enable)
+ QApplicationPrivate::animate_menu = true;
+ QApplicationPrivate::fade_menu = enable;
+ break;
+ case Qt::UI_AnimateCombo:
+ QApplicationPrivate::animate_combo = enable;
+ break;
+ case Qt::UI_AnimateTooltip:
+ QApplicationPrivate::animate_tooltip = enable;
+ break;
+ case Qt::UI_FadeTooltip:
+ if (enable)
+ QApplicationPrivate::animate_tooltip = true;
+ QApplicationPrivate::fade_tooltip = enable;
+ break;
+ case Qt::UI_AnimateToolBox:
+ QApplicationPrivate::animate_toolbox = enable;
+ break;
+ default:
+ QApplicationPrivate::animate_ui = enable;
+ break;
+ }
+}
+
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
+ return false;
+
+ switch(effect) {
+ case Qt::UI_AnimateMenu:
+ return QApplicationPrivate::animate_menu;
+ case Qt::UI_FadeMenu:
+ return QApplicationPrivate::fade_menu;
+ case Qt::UI_AnimateCombo:
+ return QApplicationPrivate::animate_combo;
+ case Qt::UI_AnimateTooltip:
+ return QApplicationPrivate::animate_tooltip;
+ case Qt::UI_FadeTooltip:
+ return QApplicationPrivate::fade_tooltip;
+ case Qt::UI_AnimateToolBox:
+ return QApplicationPrivate::animate_toolbox;
+ default:
+ return QApplicationPrivate::animate_ui;
+ }
+}
+
+void QApplication::setArgs(int c, char **v)
+{
+ Q_D(QApplication);
+ d->argc = c;
+ d->argv = v;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
new file mode 100644
index 0000000000..fae0335a2d
--- /dev/null
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -0,0 +1,3956 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef Q_OS_WINCE
+#include "qguifunctions_wince.h"
+#include "qmenubar.h"
+extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
+extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.cpp
+#endif
+#ifdef Q_OS_WINCE_WM
+#include <windowsm.h>
+#include <tpcshell.h>
+#endif
+
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "private/qeventdispatcher_win_p.h"
+#include "qeventloop.h"
+#include "qclipboard.h"
+#include "qcursor.h"
+#include "qdatetime.h"
+#include "qpointer.h"
+#include "qhash.h"
+#include "qlibrary.h"
+#include "qmetaobject.h"
+#include "qmime.h"
+#include "qpainter.h"
+#include "qpixmapcache.h"
+#include "qsessionmanager.h"
+#include "qstyle.h"
+#include "qwhatsthis.h" // ######## dependency
+#include "qwidget.h"
+#include "qcolormap.h"
+#include "qlayout.h"
+#include "qtooltip.h"
+#include "qt_windows.h"
+#if defined(QT_NON_COMMERCIAL)
+#include "qnc_win.h"
+#endif
+#include "private/qwininputcontext_p.h"
+#include "private/qcursor_p.h"
+#include "private/qmath_p.h"
+#include "private/qapplication_p.h"
+#include "private/qbackingstore_p.h"
+#include "private/qwindowsurface_raster_p.h"
+#include "qdebug.h"
+#include <private/qkeymapper_p.h>
+#include <private/qlocale_p.h>
+
+//#define ALIEN_DEBUG
+
+#ifndef QT_NO_THREAD
+#include "qmutex.h"
+#endif
+
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+
+#include <oleacc.h>
+#ifndef WM_GETOBJECT
+#define WM_GETOBJECT 0x003D
+#endif
+#endif // QT_NO_ACCESSIBILITY
+
+#include <winuser.h>
+#if !defined(WINABLEAPI)
+# if defined(Q_OS_WINCE)
+# include <bldver.h>
+# endif
+# include <winable.h>
+#endif
+
+
+#ifndef FLASHW_STOP
+typedef struct {
+ UINT cbSize;
+ HWND hwnd;
+ DWORD dwFlags;
+ UINT uCount;
+ DWORD dwTimeout;
+} FLASHWINFO, *PFLASHWINFO;
+#define FLASHW_STOP 0
+#define FLASHW_CAPTION 0x00000001
+#define FLASHW_TRAY 0x00000002
+#define FLASHW_ALL (FLASHW_CAPTION | FLASHW_TRAY)
+#define FLASHW_TIMER 0x00000004
+#define FLASHW_TIMERNOFG 0x0000000C
+#endif /* FLASHW_STOP */
+typedef BOOL (WINAPI *PtrFlashWindowEx)(PFLASHWINFO pfwi);
+static PtrFlashWindowEx pFlashWindowEx = 0;
+
+#include <windowsx.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
+ | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#define PACKETMODE 0
+
+#include <wintab.h>
+#ifndef CSR_TYPE
+#define CSR_TYPE 20 // Some old Wacom wintab.h may not provide this constant.
+#endif
+#include <pktdef.h>
+
+#if defined(__CYGWIN32__)
+#define __INSIDE_CYGWIN32__
+#include <mywinsock.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WINCE
+#ifndef SHRG_RETURNCMD
+struct SHRGINFO {
+ DWORD cbSize;
+ HWND hwndClient;
+ POINT ptDown;
+ DWORD dwFlags;
+};
+#define GN_CONTEXTMENU 1000
+#define SHRG_RETURNCMD 0x00000001
+#define SHRG_NOANIMATION 0x00000010
+#endif
+
+#ifndef SPI_SETSIPINFO
+#define SPI_SETSIPINFO 224
+#endif
+
+typedef DWORD (API *AygRecognizeGesture)(SHRGINFO*);
+static AygRecognizeGesture ptrRecognizeGesture = 0;
+static bool aygResolved = false;
+static void resolveAygLibs()
+{
+ if (!aygResolved) {
+ aygResolved = true;
+ QLibrary ayglib(QLatin1String("aygshell"));
+ if (!ayglib.load())
+ return;
+ ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture");
+ }
+}
+
+#endif
+
+#ifndef SPI_SETFONTSMOOTHINGTYPE
+# define SPI_SETFONTSMOOTHINGTYPE 0x200B
+#endif
+#ifndef SPI_GETFONTSMOOTHINGTYPE
+# define SPI_GETFONTSMOOTHINGTYPE 0x200A
+#endif
+#ifndef FE_FONTSMOOTHINGCLEARTYPE
+# define FE_FONTSMOOTHINGCLEARTYPE 0x0002
+#endif
+
+bool qt_cleartype_enabled;
+Q_GUI_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default
+
+typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
+typedef BOOL (API *PtrWTClose)(HCTX);
+typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
+typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
+typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
+typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
+typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
+typedef int (API *PtrWTQueueSizeGet)(HCTX);
+typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
+
+static PtrWTInfo ptrWTInfo = 0;
+static PtrWTEnable ptrWTEnable = 0;
+static PtrWTOverlap ptrWTOverlap = 0;
+static PtrWTPacketsGet ptrWTPacketsGet = 0;
+static PtrWTGet ptrWTGet = 0;
+
+static PACKET localPacketBuf[QT_TABLET_NPACKETQSIZE]; // our own tablet packet queue.
+HCTX qt_tablet_context; // the hardware context for the tablet (like a window handle)
+bool qt_tablet_tilt_support;
+static void tabletInit(UINT wActiveCsr, HCTX hTab);
+static void initWinTabFunctions(); // resolve the WINTAB api functions
+
+
+#ifndef QT_NO_ACCESSIBILITY
+extern IAccessible *qt_createWindowsAccessible(QAccessibleInterface *object);
+#endif // QT_NO_ACCESSIBILITY
+
+extern bool qt_tabletChokeMouse;
+extern QWidget* qt_get_tablet_widget();
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+extern QRegion qt_dirtyRegion(QWidget *);
+
+typedef QHash<UINT, QTabletDeviceData> QTabletCursorInfo;
+Q_GLOBAL_STATIC(QTabletCursorInfo, tCursorInfo)
+QTabletDeviceData currentTabletPointer;
+
+// from qregion_win.cpp
+extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom);
+
+Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax, UINT wRemoveMsg);
+Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// support for on-the-fly changes of the XP theme engine
+#ifndef WM_THEMECHANGED
+#define WM_THEMECHANGED 0x031A
+#endif
+#ifndef COLOR_MENUHILIGHT
+#define COLOR_MENUHILIGHT 29
+#define COLOR_MENUBAR 30
+#endif
+
+// support for xbuttons
+#ifndef WM_XBUTTONDOWN
+#define WM_XBUTTONDOWN 0x020B
+#define WM_XBUTTONUP 0x020C
+#define WM_XBUTTONDBLCLK 0x020D
+#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
+#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
+#define XBUTTON1 0x0001
+#define XBUTTON2 0x0002
+#define MK_XBUTTON1 0x0020
+#define MK_XBUTTON2 0x0040
+#endif
+
+#ifdef Q_OS_WINCE
+#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
+#endif
+
+// support for multi-media-keys on ME/2000/XP
+#ifndef WM_APPCOMMAND
+#define WM_APPCOMMAND 0x0319
+
+#define FAPPCOMMAND_MOUSE 0x8000
+#define FAPPCOMMAND_KEY 0
+#define FAPPCOMMAND_OEM 0x1000
+#define FAPPCOMMAND_MASK 0xF000
+#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
+#define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
+#define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM
+#define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam))
+#define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam)
+
+#define APPCOMMAND_BROWSER_BACKWARD 1
+#define APPCOMMAND_BROWSER_FORWARD 2
+#define APPCOMMAND_BROWSER_REFRESH 3
+#define APPCOMMAND_BROWSER_STOP 4
+#define APPCOMMAND_BROWSER_SEARCH 5
+#define APPCOMMAND_BROWSER_FAVORITES 6
+#define APPCOMMAND_BROWSER_HOME 7
+#define APPCOMMAND_VOLUME_MUTE 8
+#define APPCOMMAND_VOLUME_DOWN 9
+#define APPCOMMAND_VOLUME_UP 10
+#define APPCOMMAND_MEDIA_NEXTTRACK 11
+#define APPCOMMAND_MEDIA_PREVIOUSTRACK 12
+#define APPCOMMAND_MEDIA_STOP 13
+#define APPCOMMAND_MEDIA_PLAY_PAUSE 14
+#define APPCOMMAND_LAUNCH_MAIL 15
+#define APPCOMMAND_LAUNCH_MEDIA_SELECT 16
+#define APPCOMMAND_LAUNCH_APP1 17
+#define APPCOMMAND_LAUNCH_APP2 18
+#define APPCOMMAND_BASS_DOWN 19
+#define APPCOMMAND_BASS_BOOST 20
+#define APPCOMMAND_BASS_UP 21
+#define APPCOMMAND_TREBLE_DOWN 22
+#define APPCOMMAND_TREBLE_UP 23
+
+// New commands from Windows XP (some even Sp1)
+#ifndef APPCOMMAND_MICROPHONE_VOLUME_MUTE
+#define APPCOMMAND_MICROPHONE_VOLUME_MUTE 24
+#define APPCOMMAND_MICROPHONE_VOLUME_DOWN 25
+#define APPCOMMAND_MICROPHONE_VOLUME_UP 26
+#define APPCOMMAND_HELP 27
+#define APPCOMMAND_FIND 28
+#define APPCOMMAND_NEW 29
+#define APPCOMMAND_OPEN 30
+#define APPCOMMAND_CLOSE 31
+#define APPCOMMAND_SAVE 32
+#define APPCOMMAND_PRINT 33
+#define APPCOMMAND_UNDO 34
+#define APPCOMMAND_REDO 35
+#define APPCOMMAND_COPY 36
+#define APPCOMMAND_CUT 37
+#define APPCOMMAND_PASTE 38
+#define APPCOMMAND_REPLY_TO_MAIL 39
+#define APPCOMMAND_FORWARD_MAIL 40
+#define APPCOMMAND_SEND_MAIL 41
+#define APPCOMMAND_SPELL_CHECK 42
+#define APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE 43
+#define APPCOMMAND_MIC_ON_OFF_TOGGLE 44
+#define APPCOMMAND_CORRECTION_LIST 45
+#define APPCOMMAND_MEDIA_PLAY 46
+#define APPCOMMAND_MEDIA_PAUSE 47
+#define APPCOMMAND_MEDIA_RECORD 48
+#define APPCOMMAND_MEDIA_FAST_FORWARD 49
+#define APPCOMMAND_MEDIA_REWIND 50
+#define APPCOMMAND_MEDIA_CHANNEL_UP 51
+#define APPCOMMAND_MEDIA_CHANNEL_DOWN 52
+#endif // APPCOMMAND_MICROPHONE_VOLUME_MUTE
+
+#endif // WM_APPCOMMAND
+
+static UINT WM95_MOUSEWHEEL = 0;
+
+#if (_WIN32_WINNT < 0x0400)
+// This struct is defined in winuser.h if the _WIN32_WINNT >= 0x0400 -- in the
+// other cases we have to define it on our own.
+typedef struct tagTRACKMOUSEEVENT {
+ DWORD cbSize;
+ DWORD dwFlags;
+ HWND hwndTrack;
+ DWORD dwHoverTime;
+} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
+#endif
+#ifndef WM_MOUSELEAVE
+#define WM_MOUSELEAVE 0x02A3
+#endif
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "private/qwidget_p.h"
+QT_END_INCLUDE_NAMESPACE
+
+static int translateButtonState(int s, int type, int button);
+
+// ##### get rid of this!
+QRgb qt_colorref2qrgb(COLORREF col)
+{
+ return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
+}
+
+
+/*****************************************************************************
+ Internal variables and functions
+ *****************************************************************************/
+
+extern Q_CORE_EXPORT char theAppName[];
+extern Q_CORE_EXPORT char appFileName[];
+extern Q_CORE_EXPORT HINSTANCE appInst; // handle to app instance
+extern Q_CORE_EXPORT HINSTANCE appPrevInst; // handle to prev app instance
+extern Q_CORE_EXPORT int appCmdShow; // main window show command
+static HWND curWin = 0; // current window
+static HDC displayDC = 0; // display device context
+
+// Session management
+static bool sm_blockUserInput = false;
+static bool sm_smActive = false;
+extern QSessionManager* qt_session_manager_self;
+static bool sm_cancel;
+
+static bool replayPopupMouseEvent = false; // replay handling when popups close
+
+// ignore the next release event if return from a modal widget
+Q_GUI_EXPORT bool qt_win_ignoreNextMouseReleaseEvent = false;
+
+
+#if defined(QT_DEBUG)
+static bool appNoGrab = false; // mouse/keyboard grabbing
+#endif
+
+static bool app_do_modal = false; // modal mode
+extern QWidgetList *qt_modal_stack;
+extern QDesktopWidget *qt_desktopWidget;
+static QPointer<QWidget> popupButtonFocus;
+static bool qt_try_modal(QWidget *, MSG *, int& ret);
+
+QWidget *qt_button_down = 0; // widget got last button-down
+QPointer<QWidget> qt_last_mouse_receiver = 0;
+
+static HWND autoCaptureWnd = 0;
+static HWND imeParentWnd = 0;
+static void setAutoCapture(HWND); // automatic capture
+static void releaseAutoCapture();
+
+static void unregWinClasses();
+
+extern QCursor *qt_grab_cursor();
+
+#if defined(Q_WS_WIN)
+#define __export
+#endif
+
+QApplicationPrivate* getQApplicationPrivateInternal()
+{
+ return qApp->d_func();
+}
+
+extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+
+class QETWidget : public QWidget // event translator widget
+{
+public:
+ QWExtra *xtra() { return d_func()->extraData(); }
+ QTLWExtra *topData() { return d_func()->topData(); }
+ QTLWExtra *maybeTopData() { return d_func()->maybeTopData(); }
+ void syncBackingStore(const QRegion &rgn) { d_func()->syncBackingStore(rgn); }
+ void syncBackingStore() { d_func()->syncBackingStore(); }
+ QWidgetData *dataPtr() { return data; }
+ QWidgetPrivate *dptr() { return d_func(); }
+ QRect frameStrut() const { return d_func()->frameStrut(); }
+ bool winEvent(MSG *m, long *r) { return QWidget::winEvent(m, r); }
+ void markFrameStrutDirty() { data->fstrut_dirty = 1; }
+ bool translateMouseEvent(const MSG &msg);
+ bool translateWheelEvent(const MSG &msg);
+ bool translatePaintEvent(const MSG &msg);
+ bool translateConfigEvent(const MSG &msg);
+ bool translateCloseEvent(const MSG &msg);
+ bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets);
+ void repolishStyle(QStyle &style);
+ inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); }
+ inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); }
+ inline uint testWindowState(uint teststate){ return dataPtr()->window_state & teststate; }
+ inline void setWindowTitle_helper(const QString &title) { d_func()->setWindowTitle_helper(title); }
+ inline void forceUpdate() {
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && tlwExtra->backingStore)
+ tlwExtra->backingStore->markDirty(rect(), this, true, true);
+ }
+};
+
+// need to get default font?
+extern bool qt_app_has_font;
+
+extern QFont qt_LOGFONTtoQFont(LOGFONT& lf,bool scale);
+
+static void qt_set_windows_color_resources()
+{
+ // Do the color settings
+ QPalette pal;
+ pal.setColor(QPalette::WindowText,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOWTEXT))));
+ pal.setColor(QPalette::Button,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNFACE))));
+ pal.setColor(QPalette::Light,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNHIGHLIGHT))));
+ pal.setColor(QPalette::Dark,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNSHADOW))));
+ pal.setColor(QPalette::Mid, pal.button().color().darker(150));
+ pal.setColor(QPalette::Text,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOWTEXT))));
+ pal.setColor(QPalette::BrightText,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNHIGHLIGHT))));
+ pal.setColor(QPalette::Base,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOW))));
+ pal.setColor(QPalette::Window,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNFACE))));
+ pal.setColor(QPalette::ButtonText,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNTEXT))));
+ pal.setColor(QPalette::Midlight,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_3DLIGHT))));
+ pal.setColor(QPalette::Shadow,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_3DDKSHADOW))));
+ pal.setColor(QPalette::Highlight,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHT))));
+ pal.setColor(QPalette::HighlightedText,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT))));
+
+#if defined(Q_OS_WINCE)
+ // ### hardcoded until I find out how to get it from the system settings.
+ pal.setColor(QPalette::LinkVisited, pal.highlight().color().dark(150));
+ pal.setColor(QPalette::Link, pal.highlight().color().light(130));
+ // Background == Base on Windows CE
+ if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
+ pal.setColor(QPalette::Background, pal.base().color());
+#else
+ pal.setColor(QPalette::Link, Qt::blue);
+ pal.setColor(QPalette::LinkVisited, Qt::magenta);
+#endif
+
+
+
+ pal.setColor(QPalette::Inactive, QPalette::Button, pal.button().color());
+ pal.setColor(QPalette::Inactive, QPalette::Window, pal.background().color());
+ pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color());
+ pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color());
+
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) {
+ if (pal.midlight() == pal.button())
+ pal.setColor(QPalette::Midlight, pal.button().color().lighter(110));
+ if (pal.background() != pal.base()) {
+ pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window));
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text));
+ }
+ }
+ const QColor bg = pal.background().color();
+ const QColor fg = pal.foreground().color(), btn = pal.button().color();
+ QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2,
+ (fg.blue()+btn.blue())/2);
+ pal.setColorGroup(QPalette::Disabled, pal.foreground(), pal.button(), pal.light(),
+ pal.dark(), pal.mid(), pal.text(), pal.brightText(), pal.base(), pal.background() );
+ pal.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
+ pal.setColor(QPalette::Disabled, QPalette::Text, disabled);
+ pal.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
+ pal.setColor(QPalette::Disabled, QPalette::Highlight,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHT))));
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText,
+ QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT))));
+ pal.setColor(QPalette::Disabled, QPalette::Base, bg);
+
+ QApplicationPrivate::setSystemPalette(pal);
+
+ QApplicationPrivate::initializeWidgetPaletteHash();
+
+ QColor ttip(qt_colorref2qrgb(GetSysColor(COLOR_INFOBK)));
+
+ QColor ttipText(qt_colorref2qrgb(GetSysColor(COLOR_INFOTEXT)));
+ {
+#ifndef QT_NO_TOOLTIP
+ QPalette tiplabel(pal);
+ tiplabel.setColor(QPalette::All, QPalette::Button, ttip);
+ tiplabel.setColor(QPalette::All, QPalette::Window, ttip);
+ tiplabel.setColor(QPalette::All, QPalette::Text, ttipText);
+ tiplabel.setColor(QPalette::All, QPalette::WindowText, ttipText);
+ tiplabel.setColor(QPalette::All, QPalette::ButtonText, ttipText);
+ tiplabel.setColor(QPalette::All, QPalette::Button, ttip);
+ tiplabel.setColor(QPalette::All, QPalette::Window, ttip);
+ tiplabel.setColor(QPalette::All, QPalette::Text, ttipText);
+ tiplabel.setColor(QPalette::All, QPalette::WindowText, ttipText);
+ tiplabel.setColor(QPalette::All, QPalette::ButtonText, ttipText);
+ const QColor fg = tiplabel.foreground().color(), btn = tiplabel.button().color();
+ QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2,
+ (fg.blue()+btn.blue())/2);
+ tiplabel.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
+ tiplabel.setColor(QPalette::Disabled, QPalette::Text, disabled);
+ tiplabel.setColor(QPalette::Disabled, QPalette::Base, Qt::white);
+ tiplabel.setColor(QPalette::Disabled, QPalette::BrightText, Qt::white);
+ QToolTip::setPalette(tiplabel);
+#endif //QT_NO_TOOLTIP
+ }
+}
+
+static void qt_set_windows_font_resources()
+{
+#ifndef Q_OS_WINCE
+ QFont menuFont;
+ QFont messageFont;
+ QFont statusFont;
+ QFont titleFont;
+ QFont iconTitleFont;
+ QT_WA({
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONTW);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+ menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont,true);
+ messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont,true);
+ statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont,true);
+ titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont,true);
+ LOGFONTW lfIconTitleFont;
+ SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
+ iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont,true);
+ } , {
+ // A version
+ NONCLIENTMETRICSA ncm;
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, lfMessageFont) + sizeof(LOGFONTA);
+ SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
+ menuFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMenuFont,true);
+ messageFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMessageFont,true);
+ statusFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfStatusFont,true);
+ titleFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfCaptionFont,true);
+ LOGFONTA lfIconTitleFont;
+ SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
+ iconTitleFont = qt_LOGFONTtoQFont((LOGFONT&)lfIconTitleFont,true);
+ });
+
+ QApplication::setFont(menuFont, "QMenu");
+ QApplication::setFont(menuFont, "QMenuBar");
+ QApplication::setFont(messageFont, "QMessageBox");
+ QApplication::setFont(statusFont, "QTipLabel");
+ QApplication::setFont(statusFont, "QStatusBar");
+ QApplication::setFont(titleFont, "Q3TitleBar");
+ QApplication::setFont(titleFont, "QWorkspaceTitleBar");
+ QApplication::setFont(iconTitleFont, "QAbstractItemView");
+ QApplication::setFont(iconTitleFont, "QDockWidgetTitle");
+
+#else
+ LOGFONT lf;
+ HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
+ GetObject(stockFont, sizeof(lf), &lf);
+ QFont systemFont = qt_LOGFONTtoQFont(lf, true);
+ QApplicationPrivate::setSystemFont(systemFont);
+ QFont smallerFont = systemFont;
+ if (qt_wince_is_mobile()) {
+ smallerFont.setPointSize(systemFont.pointSize()-1);
+ QApplication::setFont(smallerFont, "QTabBar");
+ }
+#endif// Q_OS_WINCE
+}
+
+static void qt_win_read_cleartype_settings()
+{
+ QT_WA({
+ UINT result;
+ BOOL ok;
+ ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
+ if (ok)
+ qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
+ }, {
+ UINT result;
+ BOOL ok;
+ ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
+ if (ok)
+ qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
+ });
+}
+
+
+static void qt_set_windows_resources()
+{
+ if (QApplication::type() != QApplication::Tty)
+ (void) QApplication::style(); // trigger creation of application style
+ qt_set_windows_font_resources();
+ qt_set_windows_color_resources();
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+ QPalette pal = *QApplicationPrivate::sys_pal;
+ QColor menuCol(qt_colorref2qrgb(GetSysColor(COLOR_MENU)));
+ QColor menuText(qt_colorref2qrgb(GetSysColor(COLOR_MENUTEXT)));
+ BOOL isFlat = 0;
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ SystemParametersInfo(0x1022 /*SPI_GETFLATMENU*/, 0, &isFlat, 0);
+ QPalette menu(pal);
+ // we might need a special color group for the menu.
+ menu.setColor(QPalette::Active, QPalette::Button, menuCol);
+ menu.setColor(QPalette::Active, QPalette::Text, menuText);
+ menu.setColor(QPalette::Active, QPalette::WindowText, menuText);
+ menu.setColor(QPalette::Active, QPalette::ButtonText, menuText);
+ const QColor fg = menu.foreground().color(), btn = menu.button().color();
+ QColor disabled(qt_colorref2qrgb(GetSysColor(COLOR_GRAYTEXT)));
+ menu.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
+ menu.setColor(QPalette::Disabled, QPalette::Text, disabled);
+ menu.setColor(QPalette::Disabled, QPalette::Highlight,
+ QColor(qt_colorref2qrgb(GetSysColor(
+ (QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ && isFlat ? COLOR_MENUHILIGHT
+ : COLOR_HIGHLIGHT))));
+ menu.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
+ menu.setColor(QPalette::Disabled, QPalette::Button,
+ menu.color(QPalette::Active, QPalette::Button));
+ menu.setColor(QPalette::Inactive, QPalette::Button,
+ menu.color(QPalette::Active, QPalette::Button));
+ menu.setColor(QPalette::Inactive, QPalette::Text,
+ menu.color(QPalette::Active, QPalette::Text));
+ menu.setColor(QPalette::Inactive, QPalette::WindowText,
+ menu.color(QPalette::Active, QPalette::WindowText));
+ menu.setColor(QPalette::Inactive, QPalette::ButtonText,
+ menu.color(QPalette::Active, QPalette::ButtonText));
+ menu.setColor(QPalette::Inactive, QPalette::Highlight,
+ menu.color(QPalette::Active, QPalette::Highlight));
+ menu.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ menu.color(QPalette::Active, QPalette::HighlightedText));
+
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95)
+ menu.setColor(QPalette::Inactive, QPalette::ButtonText,
+ pal.color(QPalette::Inactive, QPalette::Dark));
+ QApplication::setPalette(menu, "QMenu");
+
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) && isFlat) {
+ QColor menubar(qt_colorref2qrgb(GetSysColor(COLOR_MENUBAR)));
+ menu.setColor(QPalette::Active, QPalette::Button, menubar);
+ menu.setColor(QPalette::Disabled, QPalette::Button, menubar);
+ menu.setColor(QPalette::Inactive, QPalette::Button, menubar);
+ }
+ QApplication::setPalette(menu, "QMenuBar");
+}
+
+/*****************************************************************************
+ qt_init() - initializes Qt for Windows
+ *****************************************************************************/
+
+typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst,
+ const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey,
+ const Q_BLENDFUNCTION *pblend, DWORD dwflags);
+static PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0;
+
+static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info)
+{
+ return (*ptrUpdateLayeredWindow)(hwnd, info->hdcDst, info->pptDst, info->psize, info->hdcSrc,
+ info->pptSrc, info->crKey, info->pblend, info->dwFlags);
+}
+
+void qt_init(QApplicationPrivate *priv, int)
+{
+
+ int argc = priv->argc;
+ char **argv = priv->argv;
+ int i, j;
+
+ // Get command line params
+
+ j = argc ? 1 : 0;
+ for (i=1; i<argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+#if defined(QT_DEBUG)
+ if (qstrcmp(argv[i], "-nograb") == 0)
+ appNoGrab = !appNoGrab;
+ else
+#endif // QT_DEBUG
+ if (qstrcmp(argv[i], "-direct3d") == 0)
+ QApplication::setAttribute(Qt::AA_MSWindowsUseDirect3DByDefault);
+ else
+ argv[j++] = argv[i];
+ }
+ if(j < priv->argc) {
+ priv->argv[j] = 0;
+ priv->argc = j;
+ }
+
+ // Get the application name/instance if qWinMain() was not invoked
+#ifndef Q_OS_WINCE
+ // No message boxes but important ones
+ SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+#endif
+
+ if (appInst == 0) {
+ QT_WA({
+ appInst = GetModuleHandle(0);
+ }, {
+ appInst = GetModuleHandleA(0);
+ });
+ }
+
+#ifndef Q_OS_WINCE
+ // Initialize OLE/COM
+ // S_OK means success and S_FALSE means that it has already
+ // been initialized
+ HRESULT r;
+ r = OleInitialize(0);
+ if (r != S_OK && r != S_FALSE) {
+ qWarning("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
+ }
+#endif
+
+ // Misc. initialization
+#if defined(QT_DEBUG) && !defined(Q_OS_WINCE)
+ GdiSetBatchLimit(1);
+#endif
+
+ // initialize key mapper
+ QKeyMapper::changeKeyboard();
+
+ QColormap::initialize();
+ QFont::initialize();
+#ifndef QT_NO_CURSOR
+ QCursorData::initialize();
+#endif
+ qApp->setObjectName(QLatin1String(theAppName));
+
+#if !defined(Q_OS_WINCE)
+ // default font
+ HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ QFont f(QLatin1String("MS Sans Serif"),8);
+ int result = 0;
+ QT_WA({
+ LOGFONT lf;
+ if (result = GetObject(hfont, sizeof(lf), &lf))
+ f = qt_LOGFONTtoQFont((LOGFONT&)lf,true);
+ } , {
+ LOGFONTA lf;
+ if (result = GetObjectA(hfont, sizeof(lf), &lf))
+ f = qt_LOGFONTtoQFont((LOGFONT&)lf,true);
+ });
+ if (result
+ && QSysInfo::WindowsVersion >= QSysInfo::WV_2000
+ && QSysInfo::WindowsVersion <= QSysInfo::WV_NT_based
+ && f.family() == QLatin1String("MS Shell Dlg"))
+ f.setFamily(QLatin1String("MS Shell Dlg 2"));
+ QApplicationPrivate::setSystemFont(f);
+#else //Q_OS_WINCE
+ LOGFONT lf;
+ HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
+ int result = 0;
+ result = GetObject(stockFont, sizeof(lf), &lf);
+ QFont font = qt_LOGFONTtoQFont(lf, true);
+ if (result)
+ QApplicationPrivate::setSystemFont(font);
+#endif //Q_OS_WINCE
+
+ // QFont::locale_init(); ### Uncomment when it does something on Windows
+
+ if (QApplication::desktopSettingsAware())
+ qt_set_windows_resources();
+
+ QT_WA({
+ WM95_MOUSEWHEEL = RegisterWindowMessage(L"MSWHEEL_ROLLMSG");
+ } , {
+ WM95_MOUSEWHEEL = RegisterWindowMessageA("MSWHEEL_ROLLMSG");
+ });
+ initWinTabFunctions();
+ QApplicationPrivate::inputContext = new QWinInputContext(0);
+
+ // Read the initial cleartype settings...
+ qt_win_read_cleartype_settings();
+ qt_win_owndc_required = false;
+
+ extern void qt_win_initialize_directdraw();
+ qt_win_initialize_directdraw();
+
+#ifndef Q_OS_WINCE
+ ptrUpdateLayeredWindowIndirect =
+ (PtrUpdateLayeredWindowIndirect) QLibrary::resolve(QLatin1String("user32"),
+ "UpdateLayeredWindowIndirect");
+ ptrUpdateLayeredWindow =
+ (PtrUpdateLayeredWindow) QLibrary::resolve(QLatin1String("user32"),
+ "UpdateLayeredWindow");
+
+ if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect)
+ ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect;
+#endif
+}
+
+/*****************************************************************************
+ qt_cleanup() - cleans up when the application is finished
+ *****************************************************************************/
+
+void qt_cleanup()
+{
+ unregWinClasses();
+ QPixmapCache::clear();
+
+#ifndef QT_NO_CURSOR
+ QCursorData::cleanup();
+#endif
+ QFont::cleanup();
+ QColormap::cleanup();
+ if (displayDC) {
+ ReleaseDC(0, displayDC);
+ displayDC = 0;
+ }
+
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = 0;
+
+#ifndef Q_OS_WINCE
+ // Deinitialize OLE/COM
+ OleUninitialize();
+#endif
+}
+
+
+/*****************************************************************************
+ Platform specific global and internal functions
+ *****************************************************************************/
+
+Q_GUI_EXPORT int qWinAppCmdShow() // get main window show command
+{
+ return appCmdShow;
+}
+
+
+Q_GUI_EXPORT HDC qt_win_display_dc() // get display DC
+{
+ Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
+ if (!displayDC)
+ displayDC = GetDC(0);
+ return displayDC;
+}
+
+bool qt_nograb() // application no-grab option
+{
+#if defined(QT_DEBUG)
+ return appNoGrab;
+#else
+ return false;
+#endif
+}
+
+typedef QHash<QString, int> WinClassNameHash;
+Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
+
+const QString qt_reg_winclass(QWidget *w) // register window class
+{
+ int flags = w->windowFlags();
+ int type = flags & Qt::WindowType_Mask;
+
+ uint style;
+ bool icon;
+ QString cname;
+ if (flags & Qt::MSWindowsOwnDC) {
+ cname = QLatin1String("QWidgetOwnDC");
+ style = CS_DBLCLKS;
+#ifndef Q_OS_WINCE
+ style |= CS_OWNDC;
+#endif
+ icon = true;
+ } else if (type == Qt::Tool || type == Qt::ToolTip){
+ style = CS_DBLCLKS;
+ if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) {
+ style |= 0x00020000; // CS_DROPSHADOW
+ }
+ cname = QLatin1String("QToolTip");
+ } else {
+ cname = QLatin1String("QTool");
+ }
+#ifndef Q_OS_WINCE
+ style |= CS_SAVEBITS;
+#endif
+ icon = false;
+ } else if (type == Qt::Popup) {
+ cname = QLatin1String("QPopup");
+ style = CS_DBLCLKS;
+#ifndef Q_OS_WINCE
+ style |= CS_SAVEBITS;
+#endif
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ style |= 0x00020000; // CS_DROPSHADOW
+ icon = false;
+ } else {
+ cname = QLatin1String("QWidget");
+ style = CS_DBLCLKS;
+ icon = true;
+ }
+
+#ifndef Q_OS_WINCE
+ // force CS_OWNDC when the GL graphics system is
+ // used as the default renderer
+ if (qt_win_owndc_required)
+ style |= CS_OWNDC;
+#endif
+
+#ifdef Q_OS_WINCE
+ // We need to register the classes with the
+ // unique ID on WinCE to make sure we can
+ // move the windows to the front when starting
+ // a second instance.
+ wchar_t uniqueAppID[256];
+ GetModuleFileNameW(0, uniqueAppID, 255);
+ cname = QString::number(RegisterWindowMessageW(
+ (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QString(QString::fromLatin1("\\")),
+ QString(QString::fromLatin1("_"))).utf16()));
+#endif
+
+ // since multiple Qt versions can be used in one process
+ // each one has to have window class names with a unique name
+ // The first instance gets the unmodified name; if the class
+ // has already been registered by another instance of Qt then
+ // add an instance-specific ID, the address of the window proc.
+ static int classExists = -1;
+
+ if (classExists == -1) {
+ QT_WA({
+ WNDCLASS wcinfo;
+ classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo);
+ classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
+ }, {
+ WNDCLASSA wcinfo;
+ classExists = GetClassInfoA((HINSTANCE)qWinAppInst(), cname.toLatin1(), &wcinfo);
+ classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
+ });
+ }
+
+ if (classExists)
+ cname += QString::number((quintptr)QtWndProc);
+
+ if (winclassNames()->contains(cname)) // already registered in our list
+ return cname;
+
+ ATOM atom;
+#ifndef Q_OS_WINCE
+ HBRUSH bgBrush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
+ QT_WA({
+ WNDCLASS wc;
+ wc.style = style;
+ wc.lpfnWndProc = (WNDPROC)QtWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = (HINSTANCE)qWinAppInst();
+ if (icon) {
+ wc.hIcon = LoadIcon(appInst, L"IDI_ICON1");
+ if (!wc.hIcon)
+ wc.hIcon = LoadIcon(0, IDI_APPLICATION);
+ } else {
+ wc.hIcon = 0;
+ }
+ wc.hCursor = 0;
+ wc.hbrBackground= bgBrush;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName= (TCHAR*)cname.utf16();
+ atom = RegisterClass(&wc);
+ } , {
+ WNDCLASSA wc;
+ wc.style = style;
+ wc.lpfnWndProc = (WNDPROC)QtWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = (HINSTANCE)qWinAppInst();
+ if (icon) {
+ wc.hIcon = LoadIconA(appInst, (char*)"IDI_ICON1");
+ if (!wc.hIcon)
+ wc.hIcon = LoadIconA(0, (char*)IDI_APPLICATION);
+ } else {
+ wc.hIcon = 0;
+ }
+ wc.hCursor = 0;
+ wc.hbrBackground= bgBrush;
+ wc.lpszMenuName = 0;
+ QByteArray tempArray = cname.toLatin1();
+ wc.lpszClassName= tempArray;
+ atom = RegisterClassA(&wc);
+ });
+#else
+ WNDCLASS wc;
+ wc.style = style;
+ wc.lpfnWndProc = (WNDPROC)QtWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = (HINSTANCE)qWinAppInst();
+ if (icon) {
+ wc.hIcon = LoadIcon(appInst, L"IDI_ICON1");
+// if (!wc.hIcon)
+// wc.hIcon = LoadIcon(0, IDI_APPLICATION);
+ } else {
+ wc.hIcon = 0;
+ }
+ wc.hCursor = 0;
+ wc.hbrBackground= 0;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName= (TCHAR*)cname.utf16();
+ atom = RegisterClass(&wc);
+#endif
+
+#ifndef QT_NO_DEBUG
+ if (!atom)
+ qErrnoWarning("QApplication::regClass: Registering window class failed.");
+#endif
+
+ winclassNames()->insert(cname, 1);
+ return cname;
+}
+
+Q_GUI_EXPORT const QString qt_getRegisteredWndClass()
+{
+ QWidget w;
+ return qt_reg_winclass(&w);
+}
+
+static void unregWinClasses()
+{
+ WinClassNameHash *hash = winclassNames();
+ QHash<QString, int>::ConstIterator it = hash->constBegin();
+ while (it != hash->constEnd()) {
+ QT_WA({
+ UnregisterClass((TCHAR*)it.key().utf16(), (HINSTANCE)qWinAppInst());
+ } , {
+ UnregisterClassA(it.key().toLatin1(), (HINSTANCE)qWinAppInst());
+ });
+ ++it;
+ }
+ hash->clear();
+}
+
+
+/*****************************************************************************
+ Safe configuration (move,resize,setGeometry) mechanism to avoid
+ recursion when processing messages.
+ *****************************************************************************/
+
+struct QWinConfigRequest {
+ WId id; // widget to be configured
+ int req; // 0=move, 1=resize, 2=setGeo
+ int x, y, w, h; // request parameters
+};
+
+static QList<QWinConfigRequest*> *configRequests = 0;
+
+void qWinRequestConfig(WId id, int req, int x, int y, int w, int h)
+{
+ if (!configRequests) // create queue
+ configRequests = new QList<QWinConfigRequest*>;
+ QWinConfigRequest *r = new QWinConfigRequest;
+ r->id = id; // create new request
+ r->req = req;
+ r->x = x;
+ r->y = y;
+ r->w = w;
+ r->h = h;
+ configRequests->append(r); // store request in queue
+}
+
+Q_GUI_EXPORT void qWinProcessConfigRequests() // perform requests in queue
+{
+ if (!configRequests)
+ return;
+ QWinConfigRequest *r;
+ for (;;) {
+ if (configRequests->isEmpty())
+ break;
+ r = configRequests->takeLast();
+ QWidget *w = QWidget::find(r->id);
+ QRect rect(r->x, r->y, r->w, r->h);
+ int req = r->req;
+ delete r;
+
+ if ( w ) { // widget exists
+ if (w->testAttribute(Qt::WA_WState_ConfigPending))
+ return; // biting our tail
+ if (req == 0)
+ w->move(rect.topLeft());
+ else if (req == 1)
+ w->resize(rect.size());
+ else
+ w->setGeometry(rect);
+ }
+ }
+ delete configRequests;
+ configRequests = 0;
+}
+
+
+/*****************************************************************************
+ GUI event dispatcher
+ *****************************************************************************/
+
+class QGuiEventDispatcherWin32 : public QEventDispatcherWin32
+{
+ Q_DECLARE_PRIVATE(QEventDispatcherWin32)
+public:
+ QGuiEventDispatcherWin32(QObject *parent = 0);
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+};
+
+QGuiEventDispatcherWin32::QGuiEventDispatcherWin32(QObject *parent)
+ : QEventDispatcherWin32(parent)
+{
+ createInternalHwnd();
+}
+
+bool QGuiEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ if (!QEventDispatcherWin32::processEvents(flags))
+ return false;
+
+ if (configRequests) // any pending configs?
+ qWinProcessConfigRequests();
+
+ return true;
+}
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+ if (q->type() != QApplication::Tty)
+ eventDispatcher = new QGuiEventDispatcherWin32(q);
+ else
+ eventDispatcher = new QEventDispatcherWin32(q);
+}
+
+/*****************************************************************************
+ Platform specific QApplication members
+ *****************************************************************************/
+
+#ifdef QT3_SUPPORT
+void QApplication::setMainWidget(QWidget *mainWidget)
+{
+ QApplicationPrivate::main_widget = mainWidget;
+ if (QApplicationPrivate::main_widget && windowIcon().isNull()
+ && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
+ setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
+}
+#endif
+
+#ifndef QT_NO_CURSOR
+
+/*****************************************************************************
+ QApplication cursor stack
+ *****************************************************************************/
+
+void QApplication::setOverrideCursor(const QCursor &cursor)
+{
+ qApp->d_func()->cursor_list.prepend(cursor);
+ SetCursor(qApp->d_func()->cursor_list.first().handle());
+}
+
+void QApplication::restoreOverrideCursor()
+{
+ if (qApp->d_func()->cursor_list.isEmpty())
+ return;
+ qApp->d_func()->cursor_list.removeFirst();
+
+ if (!qApp->d_func()->cursor_list.isEmpty()) {
+ SetCursor(qApp->d_func()->cursor_list.first().handle());
+ } else {
+ QWidget *w = QWidget::find(curWin);
+ if (w)
+ SetCursor(w->cursor().handle());
+ else
+ SetCursor(QCursor(Qt::ArrowCursor).handle());
+ }
+}
+
+#endif
+
+/*
+ Internal function called from QWidget::setCursor()
+ force is true if this function is called from dispatchEnterLeave, it means that the
+ mouse is actually directly under this widget.
+*/
+
+#ifndef QT_NO_CURSOR
+void qt_win_set_cursor(QWidget *w, bool force)
+{
+ static QPointer<QWidget> lastUnderMouse = 0;
+ if (force) {
+ lastUnderMouse = w;
+ } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse
+ && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
+ w = lastUnderMouse;
+ }
+
+ if (!curWin && w && w->internalWinId())
+ return;
+ QWidget* cW = w && !w->internalWinId() ? w : QWidget::find(curWin);
+ if (!cW || cW->window() != w->window() ||
+ !cW->isVisible() || !cW->underMouse() || QApplication::overrideCursor())
+ return;
+
+ SetCursor(cW->cursor().handle());
+}
+#endif // QT_NO_CURSOR
+
+Qt::KeyboardModifiers qt_win_getKeyboardModifiers()
+{
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+ if (GetKeyState(VK_SHIFT) < 0)
+ modifiers |= Qt::ShiftModifier;
+ if (GetKeyState(VK_CONTROL) < 0)
+ modifiers |= Qt::ControlModifier;
+ if (GetKeyState(VK_MENU) < 0)
+ modifiers |= Qt::AltModifier;
+ return modifiers;
+}
+
+/*****************************************************************************
+ Routines to find a Qt widget from a screen position
+ *****************************************************************************/
+
+QWidget *QApplication::topLevelAt(const QPoint &pos)
+{
+ POINT p;
+ HWND win;
+ QWidget *w;
+ p.x = pos.x();
+ p.y = pos.y();
+ win = WindowFromPoint(p);
+ if (!win)
+ return 0;
+
+ w = QWidget::find(win);
+ while (!w && win) {
+ win = GetParent(win);
+ w = QWidget::find(win);
+ }
+ return w ? w->window() : 0;
+}
+
+void QApplication::beep()
+{
+ MessageBeep(MB_OK);
+}
+
+static void alert_widget(QWidget *widget, int duration)
+{
+ bool stopFlash = duration < 0;
+
+ if (!pFlashWindowEx) {
+#ifndef Q_OS_WINCE
+ QLibrary themeLib(QLatin1String("user32"));
+ pFlashWindowEx = (PtrFlashWindowEx)themeLib.resolve("FlashWindowEx");
+#endif
+ }
+
+ if (pFlashWindowEx && widget && (!widget->isActiveWindow() || stopFlash)) {
+ DWORD timeOut = GetCaretBlinkTime();
+ if (timeOut <= 0)
+ timeOut = 250;
+
+ UINT flashCount;
+ if (duration == 0)
+ flashCount = 10;
+ else
+ flashCount = duration/timeOut;
+
+ FLASHWINFO info;
+ info.cbSize = sizeof(info);
+ info.hwnd = widget->window()->winId();
+ info.dwFlags = stopFlash ? FLASHW_STOP : FLASHW_TRAY;
+ info.dwTimeout = stopFlash ? 0 : timeOut;
+ info.uCount = stopFlash ? 0 : flashCount;
+
+ pFlashWindowEx(&info);
+ }
+}
+
+void QApplication::alert(QWidget *widget, int duration)
+{
+ if (!QApplicationPrivate::checkInstance("alert"))
+ return;
+
+ if (widget) {
+ alert_widget(widget, duration);
+ } else {
+ const QWidgetList toplevels(topLevelWidgets());
+ for (int i = 0; i < toplevels.count(); ++i) {
+ QWidget *topLevel = toplevels.at(i);
+ alert_widget(topLevel, duration);
+ }
+ }
+}
+
+QString QApplicationPrivate::appName() const
+{
+ return QCoreApplicationPrivate::appName();
+}
+
+
+/*****************************************************************************
+ Main event loop
+ *****************************************************************************/
+
+extern uint qGlobalPostedEventsCount();
+
+/*!
+ \internal
+ \since 4.1
+
+ If \a gotFocus is true, \a widget will become the active window.
+ Otherwise the active window is reset to 0.
+*/
+void QApplication::winFocus(QWidget *widget, bool gotFocus)
+{
+ if (d_func()->inPopupMode()) // some delayed focus event to ignore
+ return;
+ if (gotFocus) {
+ setActiveWindow(widget);
+ if (QApplicationPrivate::active_window
+ && (QApplicationPrivate::active_window->windowType() == Qt::Dialog)) {
+ // raise the entire application, not just the dialog
+ QWidget* mw = QApplicationPrivate::active_window;
+#ifndef Q_OS_WINCE
+ while(mw->parentWidget() && (mw->windowType() == Qt::Dialog))
+ mw = mw->parentWidget()->window();
+ if (mw->testAttribute(Qt::WA_WState_Created) && mw != QApplicationPrivate::active_window)
+ SetWindowPos(mw->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+#else
+ // On Desktop Windows, we set the first parent of the dialog on top
+ // Child windows will be automatically set above again.
+ // On Windows CE we pass no parent in CreateWindowEx as otherwise
+ // dialogs get embedded into the parent window. Thus we need to
+ // manually iterate and reactivate all windows from bottom up.
+ QList<QWidget*> raiseList;
+ raiseList.push_back(mw);
+ while(mw->parentWidget() && (mw->windowType() == Qt::Dialog)) {
+ mw = mw->parentWidget()->window();
+ raiseList.push_back(mw);
+ }
+ while(!raiseList.isEmpty()) {
+ mw = raiseList.takeLast();
+ if (mw->testAttribute(Qt::WA_WState_Created)) {
+ HWND state = HWND_TOP;
+ if (mw->windowFlags() & Qt::WindowStaysOnBottomHint)
+ state = HWND_BOTTOM;
+ else if (mw->windowFlags() & Qt::WindowStaysOnTopHint)
+ state = HWND_TOPMOST;
+ SetWindowPos(mw->internalWinId(), state, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+ }
+ }
+#endif
+ }
+ } else {
+ setActiveWindow(0);
+ }
+}
+
+
+//
+// QtWndProc() receives all messages from the main event loop
+//
+
+static bool inLoop = false;
+static int inputcharset = CP_ACP;
+
+#define RETURN(x) { inLoop=false;return x; }
+
+static bool qt_is_translatable_mouse_event(UINT message)
+{
+ return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST ||
+ message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK)
+ && message != WM_MOUSEWHEEL
+
+#ifndef Q_OS_WINCE
+ || message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK
+#endif
+ ;
+}
+
+extern "C"
+LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ bool result = true;
+ QEvent::Type evt_type = QEvent::None;
+ QETWidget *widget = 0;
+
+ // there is no need to process pakcets from tablet unless
+ // it is actually on the tablet, a flag to let us know...
+ int nPackets; // the number of packets we get from the queue
+
+ long res = 0;
+ if (!qApp) // unstable app state
+ RETURN(QWinInputContext::DefWindowProc(hwnd,message,wParam,lParam))
+
+ QScopedLoopLevelCounter loopLevelCounter(QThreadData::get2(qApp->thread()));
+
+#if 0
+ // make sure we update widgets also when the user resizes
+ if (inLoop && qApp->loopLevel())
+ qApp->sendPostedEvents(0, QEvent::Paint);
+#endif
+
+ inLoop = true;
+
+ MSG msg;
+ msg.hwnd = hwnd; // create MSG structure
+ msg.message = message; // time and pt fields ignored
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ msg.pt.x = GET_X_LPARAM(lParam);
+ msg.pt.y = GET_Y_LPARAM(lParam);
+ // If it's a non-client-area message the coords are screen coords, otherwise they are
+ // client coords.
+#ifndef Q_OS_WINCE
+ if (message < WM_NCMOUSEMOVE || message > WM_NCMBUTTONDBLCLK)
+#endif
+ ClientToScreen(msg.hwnd, &msg.pt);
+
+ /*
+ // sometimes the autograb is not released, so the clickevent is sent
+ // to the wrong window. We ignore this for now, because it doesn't
+ // cause any problems.
+ if (msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN) {
+ HWND handle = WindowFromPoint(msg.pt);
+ if (msg.hwnd != handle) {
+ msg.hwnd = handle;
+ hwnd = handle;
+ }
+ }
+ */
+
+#if defined(QT_NON_COMMERCIAL)
+ QT_NC_WNDPROC
+#endif
+
+ // send through app filter
+ if (qApp->filterEvent(&msg, &res))
+ return res;
+
+ // close any opened ime candidate window (enabled only on a popup widget)
+ if (imeParentWnd && QApplication::activePopupWidget()
+ && (message == WM_MBUTTONDOWN || message == WM_XBUTTONDOWN
+ || message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN
+#ifndef Q_OS_WINCE
+ || message == WM_NCMBUTTONDOWN || message == WM_NCLBUTTONDOWN
+ || message == WM_NCRBUTTONDOWN)) {
+#else
+ )) {
+#endif
+ ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0);
+ }
+
+ switch (message) {
+#ifndef Q_OS_WINCE
+ case WM_QUERYENDSESSION: {
+ if (sm_smActive) // bogus message from windows
+ RETURN(true);
+
+ sm_smActive = true;
+ sm_blockUserInput = true; // prevent user-interaction outside interaction windows
+ sm_cancel = false;
+ if (qt_session_manager_self)
+ qApp->commitData(*qt_session_manager_self);
+ if (lParam & ENDSESSION_LOGOFF) {
+ _flushall();
+ }
+ RETURN(!sm_cancel);
+ }
+ case WM_ENDSESSION: {
+ sm_smActive = false;
+ sm_blockUserInput = false;
+ bool endsession = (bool) wParam;
+
+ // we receive the message for each toplevel window included internal hidden ones,
+ // but the aboutToQuit signal should be emitted only once.
+ QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal();
+ if (endsession && !qAppPriv->aboutToQuitEmitted) {
+ qAppPriv->aboutToQuitEmitted = true;
+ int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
+ qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0);
+ // since the process will be killed immediately quit() has no real effect
+ qApp->quit();
+ }
+
+ RETURN(0);
+ }
+ case WM_DISPLAYCHANGE:
+ if (qApp->type() == QApplication::Tty)
+ break;
+ if (qt_desktopWidget) {
+ qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77));
+ QSize sz(GetSystemMetrics(78), GetSystemMetrics(79));
+ if (sz == qt_desktopWidget->size()) {
+ // a screen resized without changing size of the virtual desktop
+ QResizeEvent rs(sz, qt_desktopWidget->size());
+ QApplication::sendEvent(qt_desktopWidget, &rs);
+ } else {
+ qt_desktopWidget->resize(sz);
+ }
+ }
+ break;
+#endif
+
+ case WM_SETTINGCHANGE:
+#ifdef Q_OS_WINCE
+ // CE SIP hide/show
+ if (wParam == SPI_SETSIPINFO) {
+ QResizeEvent re(QSize(0, 0), QSize(0, 0)); // Calculated by QDesktopWidget
+ QApplication::sendEvent(qt_desktopWidget, &re);
+ break;
+ }
+#endif
+ // ignore spurious XP message when user logs in again after locking
+ if (qApp->type() == QApplication::Tty)
+ break;
+ if (QApplication::desktopSettingsAware() && wParam != SPI_SETWORKAREA) {
+ widget = (QETWidget*)QWidget::find(hwnd);
+ if (widget) {
+ if (wParam == SPI_SETNONCLIENTMETRICS)
+ widget->markFrameStrutDirty();
+ }
+ }
+ else if (qt_desktopWidget && wParam == SPI_SETWORKAREA) {
+ qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77));
+ QSize sz(GetSystemMetrics(78), GetSystemMetrics(79));
+ if (sz == qt_desktopWidget->size()) {
+ // a screen resized without changing size of the virtual desktop
+ QResizeEvent rs(sz, qt_desktopWidget->size());
+ QApplication::sendEvent(qt_desktopWidget, &rs);
+ } else {
+ qt_desktopWidget->resize(sz);
+ }
+ }
+
+ if (wParam == SPI_SETFONTSMOOTHINGTYPE) {
+ qt_win_read_cleartype_settings();
+ foreach (QWidget *w, qApp->topLevelWidgets()) {
+ if (!w->isVisible())
+ continue;
+ ((QETWidget *) w)->forceUpdate();
+ }
+ }
+
+ break;
+ case WM_SYSCOLORCHANGE:
+ if (qApp->type() == QApplication::Tty)
+ break;
+ if (QApplication::desktopSettingsAware()) {
+ widget = (QETWidget*)QWidget::find(hwnd);
+ if (widget && !widget->parentWidget())
+ qt_set_windows_color_resources();
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ if (qt_win_ignoreNextMouseReleaseEvent)
+ qt_win_ignoreNextMouseReleaseEvent = false;
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_XBUTTONUP:
+ if (qt_win_ignoreNextMouseReleaseEvent) {
+ qt_win_ignoreNextMouseReleaseEvent = false;
+ if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) {
+ releaseAutoCapture();
+ qt_button_down = 0;
+ }
+
+ RETURN(0);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (!widget)
+ widget = (QETWidget*)QWidget::find(hwnd);
+ if (!widget) // don't know this widget
+ goto do_default;
+
+ if (app_do_modal) { // modal event handling
+ int ret = 0;
+ if (!qt_try_modal(widget, &msg, ret))
+ RETURN(ret);
+ }
+
+ res = 0;
+ if (widget->winEvent(&msg, &res)) // send through widget filter
+ RETURN(res);
+
+ if (qt_is_translatable_mouse_event(message)) {
+ if (qApp->activePopupWidget() != 0) { // in popup mode
+ POINT curPos = msg.pt;
+ QWidget* w = QApplication::widgetAt(curPos.x, curPos.y);
+ if (w)
+ widget = (QETWidget*)w;
+ }
+
+ if (!qt_tabletChokeMouse) {
+ result = widget->translateMouseEvent(msg); // mouse event
+#if defined(Q_OS_WINCE) && !defined(QT_NO_CONTEXTMENU)
+ if (message == WM_LBUTTONDOWN && widget != qApp->activePopupWidget()) {
+ QWidget* alienWidget = widget;
+ if ((alienWidget != qApp->activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) {
+ QPoint pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ QPoint globalPos(msg.pt.x, msg.pt.y);
+ // In case we are using Alien, then the widget to
+ // send the context menu event is a different one
+ if (!alienWidget->testAttribute(Qt::WA_NativeWindow) && !alienWidget->testAttribute(Qt::WA_PaintOnScreen)) {
+ alienWidget = QApplication::widgetAt(globalPos);
+ pos = alienWidget->mapFromGlobal(globalPos);
+ }
+ SHRGINFO shrg;
+ shrg.cbSize = sizeof(shrg);
+ shrg.hwndClient = hwnd;
+ shrg.ptDown.x = GET_X_LPARAM(lParam);
+ shrg.ptDown.y = GET_Y_LPARAM(lParam);
+ shrg.dwFlags = SHRG_RETURNCMD | SHRG_NOANIMATION;
+ resolveAygLibs();
+ if (ptrRecognizeGesture && (ptrRecognizeGesture(&shrg) == GN_CONTEXTMENU)) {
+ if (qApp->activePopupWidget())
+ qApp->activePopupWidget()->close();
+ QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos);
+ result = qt_sendSpontaneousEvent(alienWidget, &e);
+ }
+ }
+ }
+#endif
+ } else {
+ // Sometimes we only get a WM_MOUSEMOVE message
+ // and sometimes we get both a WM_MOUSEMOVE and
+ // a WM_LBUTTONDOWN/UP, this creates a spurious mouse
+ // press/release event, using the winPeekMessage
+ // will help us fix this. This leaves us with a
+ // question:
+ // This effectively kills using the mouse AND the
+ // tablet simultaneously, well creates wacky input.
+ // Is this going to be a problem? (probably not)
+ bool next_is_button = false;
+ bool is_mouse_move = (message == WM_MOUSEMOVE);
+ if (is_mouse_move) {
+ MSG msg1;
+ if (winPeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST,
+ WM_MOUSELAST, PM_NOREMOVE))
+ next_is_button = (msg1.message == WM_LBUTTONUP
+ || msg1.message == WM_LBUTTONDOWN);
+ }
+ if (!is_mouse_move || (is_mouse_move && !next_is_button))
+ qt_tabletChokeMouse = false;
+ }
+ } else if (message == WM95_MOUSEWHEEL) {
+ result = widget->translateWheelEvent(msg);
+ } else {
+ switch (message) {
+ case WM_KEYDOWN: // keyboard event
+ case WM_SYSKEYDOWN:
+ qt_keymapper_private()->updateKeyMap(msg);
+ // fall-through intended
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ case WM_IME_CHAR:
+ case WM_IME_KEYDOWN:
+ case WM_CHAR: {
+ MSG msg1;
+ bool anyMsg = winPeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE);
+ if (anyMsg && msg1.message == WM_DEADCHAR) {
+ result = true; // consume event since there is a dead char next
+ break;
+ }
+ QWidget *g = QWidget::keyboardGrabber();
+ if (g && qt_get_tablet_widget() && hwnd == qt_get_tablet_widget()->winId()) {
+ // if we get an event for the internal tablet widget,
+ // then don't send it to the keyboard grabber, but
+ // send it to the widget itself (we don't use it right
+ // now, just in case).
+ g = 0;
+ }
+ if (g)
+ widget = (QETWidget*)g;
+ else if (QApplication::activePopupWidget())
+ widget = (QETWidget*)QApplication::activePopupWidget()->focusWidget()
+ ? (QETWidget*)QApplication::activePopupWidget()->focusWidget()
+ : (QETWidget*)QApplication::activePopupWidget();
+ else if (qApp->focusWidget())
+ widget = (QETWidget*)QApplication::focusWidget();
+ else if (!widget || widget->internalWinId() == GetFocus()) // We faked the message to go to exactly that widget.
+ widget = (QETWidget*)widget->window();
+ if (widget->isEnabled())
+ result = sm_blockUserInput
+ ? true
+ : qt_keymapper_private()->translateKeyEvent(widget, msg, g != 0);
+ break;
+ }
+ case WM_SYSCHAR:
+ result = true; // consume event
+ break;
+
+ case WM_MOUSEWHEEL:
+ result = widget->translateWheelEvent(msg);
+ break;
+
+ case WM_APPCOMMAND:
+ {
+ uint cmd = GET_APPCOMMAND_LPARAM(lParam);
+ uint uDevice = GET_DEVICE_LPARAM(lParam);
+ uint dwKeys = GET_KEYSTATE_LPARAM(lParam);
+
+ int state = translateButtonState(dwKeys, QEvent::KeyPress, 0);
+
+ switch (uDevice) {
+ case FAPPCOMMAND_KEY:
+ {
+ int key = 0;
+
+ switch(cmd) {
+ case APPCOMMAND_BASS_BOOST:
+ key = Qt::Key_BassBoost;
+ break;
+ case APPCOMMAND_BASS_DOWN:
+ key = Qt::Key_BassDown;
+ break;
+ case APPCOMMAND_BASS_UP:
+ key = Qt::Key_BassUp;
+ break;
+ case APPCOMMAND_BROWSER_BACKWARD:
+ key = Qt::Key_Back;
+ break;
+ case APPCOMMAND_BROWSER_FAVORITES:
+ key = Qt::Key_Favorites;
+ break;
+ case APPCOMMAND_BROWSER_FORWARD:
+ key = Qt::Key_Forward;
+ break;
+ case APPCOMMAND_BROWSER_HOME:
+ key = Qt::Key_HomePage;
+ break;
+ case APPCOMMAND_BROWSER_REFRESH:
+ key = Qt::Key_Refresh;
+ break;
+ case APPCOMMAND_BROWSER_SEARCH:
+ key = Qt::Key_Search;
+ break;
+ case APPCOMMAND_BROWSER_STOP:
+ key = Qt::Key_Stop;
+ break;
+ case APPCOMMAND_LAUNCH_APP1:
+ key = Qt::Key_Launch0;
+ break;
+ case APPCOMMAND_LAUNCH_APP2:
+ key = Qt::Key_Launch1;
+ break;
+ case APPCOMMAND_LAUNCH_MAIL:
+ key = Qt::Key_LaunchMail;
+ break;
+ case APPCOMMAND_LAUNCH_MEDIA_SELECT:
+ key = Qt::Key_LaunchMedia;
+ break;
+ case APPCOMMAND_MEDIA_NEXTTRACK:
+ key = Qt::Key_MediaNext;
+ break;
+ case APPCOMMAND_MEDIA_PLAY_PAUSE:
+ key = Qt::Key_MediaPlay;
+ break;
+ case APPCOMMAND_MEDIA_PREVIOUSTRACK:
+ key = Qt::Key_MediaPrevious;
+ break;
+ case APPCOMMAND_MEDIA_STOP:
+ key = Qt::Key_MediaStop;
+ break;
+ case APPCOMMAND_TREBLE_DOWN:
+ key = Qt::Key_TrebleDown;
+ break;
+ case APPCOMMAND_TREBLE_UP:
+ key = Qt::Key_TrebleUp;
+ break;
+ case APPCOMMAND_VOLUME_DOWN:
+ key = Qt::Key_VolumeDown;
+ break;
+ case APPCOMMAND_VOLUME_MUTE:
+ key = Qt::Key_VolumeMute;
+ break;
+ case APPCOMMAND_VOLUME_UP:
+ key = Qt::Key_VolumeUp;
+ break;
+ // Commands new in Windows XP
+ case APPCOMMAND_HELP:
+ key = Qt::Key_Help;
+ break;
+ case APPCOMMAND_FIND:
+ key = Qt::Key_Search;
+ break;
+ case APPCOMMAND_PRINT:
+ key = Qt::Key_Print;
+ break;
+ case APPCOMMAND_MEDIA_PLAY:
+ key = Qt::Key_MediaPlay;
+ break;
+ default:
+ break;
+ }
+ if (key) {
+ bool res = false;
+ QWidget *g = QWidget::keyboardGrabber();
+ if (g)
+ widget = (QETWidget*)g;
+ else if (qApp->focusWidget())
+ widget = (QETWidget*)qApp->focusWidget();
+ else
+ widget = (QETWidget*)widget->window();
+ if (widget->isEnabled()) {
+ res = QKeyMapper::sendKeyEvent(widget, g != 0, QEvent::KeyPress, key,
+ Qt::KeyboardModifier(state),
+ QString(), false, 0, 0, 0, 0);
+ }
+ if (res)
+ return true;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ result = false;
+ }
+ break;
+
+#ifndef Q_OS_WINCE
+ case WM_NCHITTEST:
+ if (widget->isWindow()) {
+ QPoint pos = widget->mapFromGlobal(QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+ // don't show resize-cursors for fixed-size widgets
+ QRect fs = widget->frameStrut();
+ if (!widget->isMinimized()) {
+ if (widget->minimumWidth() == widget->maximumWidth() && (pos.x() < 0 || pos.x() >= widget->width()))
+ break;
+ if (widget->minimumHeight() == widget->maximumHeight() && (pos.y() < -(fs.top() - fs.left()) || pos.y() >= widget->height()))
+ break;
+ }
+ }
+
+ result = false;
+ break;
+#endif
+
+ case WM_SYSCOMMAND: {
+#ifndef Q_OS_WINCE
+ bool window_state_change = false;
+ Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state);
+ // MSDN:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are
+ // used internally by the system. To obtain the correct result when testing the value of
+ // wParam, an application must combine the value 0xFFF0 with the wParam value by using
+ // the bitwise AND operator.
+ switch(0xfff0 & wParam) {
+ case SC_CONTEXTHELP:
+#ifndef QT_NO_WHATSTHIS
+ QWhatsThis::enterWhatsThisMode();
+#endif
+ QT_WA({
+ DefWindowProc(hwnd, WM_NCPAINT, 1, 0);
+ } , {
+ DefWindowProcA(hwnd, WM_NCPAINT, 1, 0);
+ });
+ break;
+#if defined(QT_NON_COMMERCIAL)
+ QT_NC_SYSCOMMAND
+#endif
+ case SC_MINIMIZE:
+ window_state_change = true;
+ widget->dataPtr()->window_state |= Qt::WindowMinimized;
+ if (widget->isVisible()) {
+ QHideEvent e;
+ qt_sendSpontaneousEvent(widget, &e);
+ widget->hideChildren(true);
+#ifndef Q_OS_WINCE
+ const QString title = widget->windowIconText();
+ if (!title.isEmpty())
+ widget->setWindowTitle_helper(title);
+#endif
+ }
+ result = false;
+ break;
+ case SC_MAXIMIZE:
+ if(widget->isWindow())
+ widget->topData()->normalGeometry = widget->geometry();
+ case SC_RESTORE:
+ window_state_change = true;
+ if ((0xfff0 & wParam) == SC_MAXIMIZE)
+ widget->dataPtr()->window_state |= Qt::WindowMaximized;
+ else if (!widget->isMinimized())
+ widget->dataPtr()->window_state &= ~Qt::WindowMaximized;
+
+ if (widget->isMinimized()) {
+ widget->dataPtr()->window_state &= ~Qt::WindowMinimized;
+ widget->showChildren(true);
+ QShowEvent e;
+ qt_sendSpontaneousEvent(widget, &e);
+#ifndef Q_OS_WINCE
+ const QString title = widget->windowTitle();
+ if (!title.isEmpty())
+ widget->setWindowTitle_helper(title);
+#endif
+ }
+ result = false;
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ if (window_state_change) {
+ QWindowStateChangeEvent e(oldstate);
+ qt_sendSpontaneousEvent(widget, &e);
+ }
+#endif
+
+ break;
+ }
+
+ case WM_SETTINGCHANGE:
+ if ( qApp->type() == QApplication::Tty )
+ break;
+
+ if (!msg.wParam) {
+ QString area = QT_WA_INLINE(QString::fromUtf16((unsigned short *)msg.lParam),
+ QString::fromLocal8Bit((char*)msg.lParam));
+ if (area == QLatin1String("intl")) {
+ QLocalePrivate::updateSystemPrivate();
+ if (!widget->testAttribute(Qt::WA_SetLocale))
+ widget->dptr()->setLocale_helper(QLocale(), true);
+ }
+ }
+ else if (msg.wParam == SPI_SETICONTITLELOGFONT) {
+ if (qApp->desktopSettingsAware()) {
+ widget = (QETWidget*)QWidget::find(hwnd);
+ if (widget && !widget->parentWidget()) {
+ qt_set_windows_font_resources();
+ }
+ }
+ }
+ break;
+
+ case WM_PAINT: // paint event
+ case WM_ERASEBKGND: // erase window background
+ result = widget->translatePaintEvent(msg);
+ break;
+
+#ifndef Q_OS_WINCE
+ case WM_ENTERSIZEMOVE:
+ autoCaptureWnd = hwnd;
+ QApplicationPrivate::inSizeMove = true;
+ break;
+ case WM_EXITSIZEMOVE:
+ autoCaptureWnd = 0;
+ QApplicationPrivate::inSizeMove = false;
+ break;
+#endif
+ case WM_MOVE: // move window
+ case WM_SIZE: // resize window
+ result = widget->translateConfigEvent(msg);
+ break;
+
+ case WM_ACTIVATEAPP:
+ if (wParam == FALSE) {
+ QApplication::setActiveWindow(0);
+ // Another application was activated while our popups are open,
+ // then close all popups. In case some popup refuses to close,
+ // we give up after 1024 attempts (to avoid an infinite loop).
+ int maxiter = 1024;
+ QWidget *popup;
+ while ((popup=QApplication::activePopupWidget()) && maxiter--)
+ popup->close();
+ }
+ break;
+
+ case WM_ACTIVATE:
+ if ( qApp->type() == QApplication::Tty )
+ break;
+
+ if (ptrWTOverlap && ptrWTEnable) {
+ // cooperate with other tablet applications, but when
+ // we get focus, I want to use the tablet...
+ if (qt_tablet_context && GET_WM_ACTIVATE_STATE(wParam, lParam)) {
+ if (ptrWTEnable(qt_tablet_context, true))
+ ptrWTOverlap(qt_tablet_context, true);
+ }
+ }
+ if (QApplication::activePopupWidget() && LOWORD(wParam) == WA_INACTIVE &&
+ QWidget::find((HWND)lParam) == 0) {
+ // Another application was activated while our popups are open,
+ // then close all popups. In case some popup refuses to close,
+ // we give up after 1024 attempts (to avoid an infinite loop).
+ int maxiter = 1024;
+ QWidget *popup;
+ while ((popup=QApplication::activePopupWidget()) && maxiter--)
+ popup->close();
+ }
+
+ if (LOWORD(wParam) != WA_INACTIVE) {
+ // WM_ACTIVATEAPP handles the "true" false case, as this is only when the application
+ // loses focus. Doing it here would result in the widget getting focus to not know
+ // where it got it from; it would simply get a 0 value as the old focus widget.
+ if (!(widget->windowState() & Qt::WindowMinimized)) {
+ // Ignore the activate message send by WindowsXP to a minimized window
+#ifdef Q_OS_WINCE_WM
+ if (widget->windowState() & Qt::WindowFullScreen)
+ qt_wince_hide_taskbar(widget->winId());
+#endif
+ qApp->winFocus(widget, true);
+ // reset any window alert flashes
+ alert_widget(widget, -1);
+ }
+ }
+
+ // Windows tries to activate a modally blocked window.
+ // This happens when restoring an application after "Show Desktop"
+ if (app_do_modal && LOWORD(wParam) == WA_ACTIVE) {
+ QWidget *top = 0;
+ if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && widget != top) {
+ if (top->isVisible()) {
+ top->activateWindow();
+ } else {
+ // This is the case when native file dialogs are shown
+ QWidget *p = (top->parentWidget() ? top->parentWidget()->window() : 0);
+ if (p && p->isVisible())
+ p->activateWindow();
+ }
+ }
+ }
+ break;
+
+#ifndef Q_OS_WINCE
+ case WM_MOUSEACTIVATE:
+ if (widget->window()->windowType() == Qt::Tool) {
+ QWidget *w = widget;
+ if (!w->window()->focusWidget()) {
+ while (w && (w->focusPolicy() & Qt::ClickFocus) == 0) {
+ if (w->isWindow()) {
+ QWidget *fw = w;
+ while ((fw = fw->nextInFocusChain()) != w && fw->focusPolicy() == Qt::NoFocus)
+ ;
+ if (fw != w)
+ break;
+ QWidget *pw = w->parentWidget();
+ while (pw) {
+ pw = pw->window();
+ if (pw && pw->isVisible() && pw->focusWidget()) {
+ Q_ASSERT(pw->testAttribute(Qt::WA_WState_Created));
+ SetWindowPos(pw->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ break;
+ }
+ pw = pw->parentWidget();
+ }
+ RETURN(MA_NOACTIVATE);
+ }
+ w = w->parentWidget();
+ }
+ }
+ }
+ RETURN(MA_ACTIVATE);
+ break;
+#endif
+ case WM_SHOWWINDOW:
+ if (lParam == SW_PARENTOPENING) {
+ if (widget->testAttribute(Qt::WA_WState_Hidden))
+ RETURN(0);
+ }
+ if (widget->isWindow() && widget->testAttribute(Qt::WA_WState_Visible)
+ && !widget->testWindowState(Qt::WindowMinimized)) {
+ if (lParam == SW_PARENTOPENING) {
+ QShowEvent e;
+ qt_sendSpontaneousEvent(widget, &e);
+ widget->showChildren(true);
+ } else if (lParam == SW_PARENTCLOSING) {
+ QHideEvent e;
+ qt_sendSpontaneousEvent(widget, &e);
+ widget->hideChildren(true);
+ }
+ }
+ if (!wParam && autoCaptureWnd == widget->internalWinId())
+ releaseAutoCapture();
+ result = false;
+ break;
+
+ case WM_PALETTECHANGED: // our window changed palette
+ if (QColormap::hPal() && (WId)wParam == widget->internalWinId())
+ RETURN(0); // otherwise: FALL THROUGH!
+ // FALL THROUGH
+ case WM_QUERYNEWPALETTE: // realize own palette
+ if (QColormap::hPal()) {
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ HDC hdc = GetDC(widget->internalWinId());
+ HPALETTE hpalOld = SelectPalette(hdc, QColormap::hPal(), FALSE);
+ uint n = RealizePalette(hdc);
+ if (n)
+ InvalidateRect(widget->internalWinId(), 0, TRUE);
+ SelectPalette(hdc, hpalOld, TRUE);
+ RealizePalette(hdc);
+ ReleaseDC(widget->internalWinId(), hdc);
+ RETURN(n);
+ }
+ break;
+ case WM_CLOSE: // close window
+ widget->translateCloseEvent(msg);
+ RETURN(0); // always handled
+
+ case WM_DESTROY: // destroy window
+ if (hwnd == curWin) {
+ QWidget *enter = QWidget::mouseGrabber();
+ if (enter == widget)
+ enter = 0;
+ QApplicationPrivate::dispatchEnterLeave(enter, widget);
+ curWin = enter ? enter->effectiveWinId() : 0;
+ qt_last_mouse_receiver = enter;
+ }
+ if (widget == popupButtonFocus)
+ popupButtonFocus = 0;
+ result = false;
+ break;
+
+#ifndef Q_OS_WINCE
+ case WM_WINDOWPOSCHANGING:
+ {
+ result = false;
+ if (widget->isWindow()) {
+ WINDOWPOS *winPos = (WINDOWPOS *)lParam;
+ if (widget->layout() && widget->layout()->hasHeightForWidth()
+ && !(winPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE))) {
+ QRect fs = widget->frameStrut();
+ QRect rect = widget->geometry();
+ QRect newRect = QRect(winPos->x + fs.left(),
+ winPos->y + fs.top(),
+ winPos->cx - fs.left() - fs.right(),
+ winPos->cy - fs.top() - fs.bottom());
+
+ QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size());
+
+ int dh = newSize.height() - newRect.height();
+ int dw = newSize.width() - newRect.width();
+ if (!dw && ! dh)
+ break; // Size OK
+
+ if (rect.y() != newRect.y()) {
+ newRect.setTop(newRect.top() - dh);
+ } else {
+ newRect.setBottom(newRect.bottom() + dh);
+ }
+
+ if (rect.x() != newRect.x()) {
+ newRect.setLeft(newRect.left() - dw);
+ } else {
+ newRect.setRight(newRect.right() + dw);
+ }
+
+ winPos->x = newRect.x() - fs.left();
+ winPos->y = newRect.y() - fs.top();
+ winPos->cx = newRect.width() + fs.left() + fs.right();
+ winPos->cy = newRect.height() + fs.top() + fs.bottom();
+
+ RETURN(0);
+ }
+ if (widget->windowFlags() & Qt::WindowStaysOnBottomHint) {
+ winPos->hwndInsertAfter = HWND_BOTTOM;
+ }
+ }
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ if (widget->xtra()) {
+ MINMAXINFO *mmi = (MINMAXINFO *)lParam;
+ QWExtra *x = widget->xtra();
+ QRect fs = widget->frameStrut();
+ if ( x->minw > 0 )
+ mmi->ptMinTrackSize.x = x->minw + fs.right() + fs.left();
+ if ( x->minh > 0 )
+ mmi->ptMinTrackSize.y = x->minh + fs.top() + fs.bottom();
+ qint32 maxw = (x->maxw >= x->minw) ? x->maxw : x->minw;
+ qint32 maxh = (x->maxh >= x->minh) ? x->maxh : x->minh;
+ if ( maxw < QWIDGETSIZE_MAX ) {
+ mmi->ptMaxTrackSize.x = maxw + fs.right() + fs.left();
+ // windows with title bar have an implicit size limit of 112 pixels
+ if (widget->windowFlags() & Qt::WindowTitleHint)
+ mmi->ptMaxTrackSize.x = qMax<long>(mmi->ptMaxTrackSize.x, 112);
+ }
+ if ( maxh < QWIDGETSIZE_MAX )
+ mmi->ptMaxTrackSize.y = maxh + fs.top() + fs.bottom();
+ RETURN(0);
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ // it's not VK_APPS or Shift+F10, but a click in the NC area
+ if (lParam != (int)0xffffffff) {
+ result = false;
+ break;
+ }
+
+ QWidget *fw = QWidget::keyboardGrabber();
+ if (!fw) {
+ if (qApp->activePopupWidget())
+ fw = (qApp->activePopupWidget()->focusWidget()
+ ? qApp->activePopupWidget()->focusWidget()
+ : qApp->activePopupWidget());
+ else if (qApp->focusWidget())
+ fw = qApp->focusWidget();
+ else if (widget)
+ fw = widget->window();
+ }
+ if (fw && fw->isEnabled()) {
+ QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center();
+ QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
+ qt_win_getKeyboardModifiers());
+ result = qt_sendSpontaneousEvent(fw, &e);
+ }
+ }
+ break;
+#endif
+
+ case WM_IME_STARTCOMPOSITION:
+ case WM_IME_ENDCOMPOSITION:
+ case WM_IME_COMPOSITION: {
+ QWidget *fw = qApp->focusWidget();
+ QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0;
+ if (fw && im) {
+ if(message == WM_IME_STARTCOMPOSITION)
+ result = im->startComposition();
+ else if (message == WM_IME_ENDCOMPOSITION)
+ result = im->endComposition();
+ else if (message == WM_IME_COMPOSITION)
+ result = im->composition(lParam);
+ }
+ break;
+ }
+
+#ifndef Q_OS_WINCE
+ case WM_CHANGECBCHAIN:
+ case WM_DRAWCLIPBOARD:
+#endif
+ case WM_RENDERFORMAT:
+ case WM_RENDERALLFORMATS:
+#ifndef QT_NO_CLIPBOARD
+ case WM_DESTROYCLIPBOARD:
+ if (qt_clipboard) {
+ QClipboardEvent e(reinterpret_cast<QEventPrivate *>(&msg));
+ qt_sendSpontaneousEvent(qt_clipboard, &e);
+ RETURN(0);
+ }
+ result = false;
+ break;
+#endif //QT_NO_CLIPBOARD
+#ifndef QT_NO_ACCESSIBILITY
+ case WM_GETOBJECT:
+ {
+ // Ignoring all requests while starting up
+ if (qApp->startingUp() || qApp->closingDown() || (DWORD)lParam != OBJID_CLIENT) {
+ result = false;
+ break;
+ }
+
+ typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN);
+ static PtrLresultFromObject ptrLresultFromObject = 0;
+ static bool oleaccChecked = false;
+
+ if (!oleaccChecked) {
+ oleaccChecked = true;
+#if !defined(Q_OS_WINCE)
+ ptrLresultFromObject = (PtrLresultFromObject)QLibrary::resolve(QLatin1String("oleacc.dll"), "LresultFromObject");
+#endif
+ }
+ if (ptrLresultFromObject) {
+ QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(widget);
+ if (!acc) {
+ result = false;
+ break;
+ }
+
+ // and get an instance of the IAccessibile implementation
+ IAccessible *iface = qt_createWindowsAccessible(acc);
+ res = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2
+ iface->Release(); // the client will release the object again, and then it will destroy itself
+
+ if (res > 0)
+ RETURN(res);
+ }
+ }
+ result = false;
+ break;
+ case WM_GETTEXT:
+ if (!widget->isWindow()) {
+ int ret = 0;
+ QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(widget);
+ if (acc) {
+ QString text = acc->text(QAccessible::Name, 0);
+ if (text.isEmpty())
+ text = widget->objectName();
+ ret = qMin<int>(wParam - 1, text.size());
+ text.resize(ret);
+ QT_WA({
+ memcpy((void *)lParam, text.utf16(), (text.size() + 1) * 2);
+ }, {
+ memcpy((void *)lParam, text.toLocal8Bit().data(), text.size() + 1);
+ });
+ delete acc;
+ }
+ if (!ret) {
+ result = false;
+ break;
+ }
+ RETURN(ret);
+ }
+ result = false;
+ break;
+#endif
+ case WT_PACKET:
+ if (ptrWTPacketsGet) {
+ if ((nPackets = ptrWTPacketsGet(qt_tablet_context, QT_TABLET_NPACKETQSIZE, &localPacketBuf))) {
+ result = widget->translateTabletEvent(msg, localPacketBuf, nPackets);
+ }
+ }
+ break;
+ case WT_PROXIMITY:
+ if (ptrWTPacketsGet) {
+ bool enteredProximity = LOWORD(lParam) != 0;
+ PACKET proximityBuffer[QT_TABLET_NPACKETQSIZE];
+ int totalPacks = ptrWTPacketsGet(qt_tablet_context, QT_TABLET_NPACKETQSIZE, proximityBuffer);
+ if (totalPacks > 0 && enteredProximity) {
+ uint currentCursor = proximityBuffer[0].pkCursor;
+ if (!tCursorInfo()->contains(currentCursor))
+ tabletInit(currentCursor, qt_tablet_context);
+ currentTabletPointer = tCursorInfo()->value(currentCursor);
+ }
+ qt_tabletChokeMouse = false;
+#ifndef QT_NO_TABLETEVENT
+ QTabletEvent tabletProximity(enteredProximity ? QEvent::TabletEnterProximity
+ : QEvent::TabletLeaveProximity,
+ QPoint(), QPoint(), QPointF(), currentTabletPointer.currentDevice, currentTabletPointer.currentPointerType, 0, 0,
+ 0, 0, 0, 0, 0, currentTabletPointer.llId);
+ QApplication::sendEvent(qApp, &tabletProximity);
+#endif // QT_NO_TABLETEVENT
+ }
+ break;
+#ifdef Q_OS_WINCE_WM
+ case WM_SETFOCUS: {
+ HIMC hC;
+ hC = ImmGetContext(hwnd);
+ ImmSetOpenStatus(hC, TRUE);
+ ImmEscape(NULL, hC, IME_ESC_SET_MODE, (LPVOID)IM_SPELL);
+ result = false;
+ }
+ break;
+#endif
+ case WM_KILLFOCUS:
+ if (!QWidget::find((HWND)wParam)) { // we don't get focus, so unset it now
+ if (!widget->hasFocus()) // work around Windows bug after minimizing/restoring
+ widget = (QETWidget*)qApp->focusWidget();
+ HWND focus = ::GetFocus();
+ //if there is a current widget and the new widget belongs to the same toplevel window
+ //then we clear the focus on the widget
+ //in case the new widget belongs to a different widget hierarchy, clearing the focus
+ //will be handled because the active window will change
+ if (widget && ::IsChild(widget->window()->internalWinId(), focus)) {
+ widget->clearFocus();
+ result = true;
+ } else {
+ result = false;
+ }
+ } else {
+ result = false;
+ }
+ break;
+ case WM_THEMECHANGED:
+ if ((widget->windowType() == Qt::Desktop) || !qApp || qApp->closingDown()
+ || qApp->type() == QApplication::Tty)
+ break;
+
+ if (widget->testAttribute(Qt::WA_WState_Polished))
+ qApp->style()->unpolish(widget);
+
+ if (widget->testAttribute(Qt::WA_WState_Polished))
+ qApp->style()->polish(widget);
+ widget->repolishStyle(*qApp->style());
+ if (widget->isVisible())
+ widget->update();
+ break;
+
+#ifndef Q_OS_WINCE
+ case WM_INPUTLANGCHANGE: {
+ char info[7];
+ if (!GetLocaleInfoA(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) {
+ inputcharset = CP_ACP;
+ } else {
+ inputcharset = QString::fromLatin1(info).toInt();
+ }
+ QKeyMapper::changeKeyboard();
+ break;
+ }
+#else
+ case WM_COMMAND: {
+ bool OkCommand = (LOWORD(wParam) == 0x1);
+ bool CancelCommand = (LOWORD(wParam) == 0x2);
+ if (OkCommand)
+ QApplication::postEvent(widget, new QEvent(QEvent::OkRequest));
+ if (CancelCommand)
+ QApplication::postEvent(widget, new QEvent(QEvent::Close));
+ else
+#ifndef QT_NO_MENUBAR
+ QMenuBar::wceCommands(LOWORD(wParam), (HWND) lParam);
+#endif
+ result = true;
+ }
+ break;
+ case WM_HELP:
+ QApplication::postEvent(widget, new QEvent(QEvent::HelpRequest));
+ result = true;
+ break;
+#endif
+
+ case WM_MOUSELEAVE:
+ // We receive a mouse leave for curWin, meaning
+ // the mouse was moved outside our widgets
+ if (widget->internalWinId() == curWin) {
+ bool dispatch = !widget->underMouse();
+ // hasMouse is updated when dispatching enter/leave,
+ // so test if it is actually up-to-date
+ if (!dispatch) {
+ QRect geom = widget->geometry();
+ if (widget->parentWidget() && !widget->isWindow()) {
+ QPoint gp = widget->parentWidget()->mapToGlobal(widget->pos());
+ geom.setX(gp.x());
+ geom.setY(gp.y());
+ }
+ QPoint cpos = QCursor::pos();
+ dispatch = !geom.contains(cpos);
+ if ( !dispatch && !QWidget::mouseGrabber()) {
+ QWidget *hittest = QApplication::widgetAt(cpos);
+ dispatch = !hittest || hittest->internalWinId() != curWin;
+ }
+ if (!dispatch) {
+ HRGN hrgn = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0);
+ if (GetWindowRgn(curWin, hrgn) != ERROR) {
+ QPoint lcpos = widget->mapFromGlobal(cpos);
+ dispatch = !PtInRegion(hrgn, lcpos.x(), lcpos.y());
+ }
+ DeleteObject(hrgn);
+ }
+ }
+ if (dispatch) {
+ if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
+ QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver);
+ else
+ QApplicationPrivate::dispatchEnterLeave(0, QWidget::find((WId)curWin));
+ curWin = 0;
+ qt_last_mouse_receiver = 0;
+ }
+ }
+ break;
+
+ case WM_CANCELMODE:
+ {
+ // this goes through QMenuBar's event filter
+ QEvent e(QEvent::ActivationChange);
+ QApplication::sendEvent(qApp, &e);
+ }
+ break;
+
+ case WM_IME_NOTIFY:
+ // special handling for ime, only for widgets in a popup
+ if (wParam == IMN_OPENCANDIDATE) {
+ imeParentWnd = hwnd;
+ if (QApplication::activePopupWidget()) {
+ // temporarily disable the mouse grab to allow mouse input in
+ // the ime candidate window. The actual handle is untouched
+ if (autoCaptureWnd)
+ ReleaseCapture();
+ }
+ } else if (wParam == IMN_CLOSECANDIDATE) {
+ imeParentWnd = 0;
+ if (QApplication::activePopupWidget()) {
+ // undo the action above, when candidate window is closed
+ if (autoCaptureWnd)
+ SetCapture(autoCaptureWnd);
+ }
+ }
+ result = false;
+ break;
+ default:
+ result = false; // event was not processed
+ break;
+ }
+ }
+
+ if (evt_type != QEvent::None) { // simple event
+ QEvent e(evt_type);
+ result = qt_sendSpontaneousEvent(widget, &e);
+ }
+
+ if (result)
+ RETURN(false);
+
+do_default:
+ RETURN(QWinInputContext::DefWindowProc(hwnd,message,wParam,lParam))
+}
+
+
+/*****************************************************************************
+ Modal widgets; We have implemented our own modal widget mechanism
+ to get total control.
+ A modal widget without a parent becomes application-modal.
+ A modal widget with a parent becomes modal to its parent and grandparents..
+
+ QApplicationPrivate::enterModal()
+ Enters modal state
+ Arguments:
+ QWidget *widget A modal widget
+
+ QApplicationPrivate::leaveModal()
+ Leaves modal state for a widget
+ Arguments:
+ QWidget *widget A modal widget
+ *****************************************************************************/
+
+bool QApplicationPrivate::modalState()
+{
+ return app_do_modal;
+}
+
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
+{
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+
+ releaseAutoCapture();
+ ClipCursor(0);
+ QWidget *leave = qt_last_mouse_receiver;
+ if (!leave)
+ leave = QWidget::find((WId)curWin);
+ QApplicationPrivate::dispatchEnterLeave(0, leave);
+ qt_modal_stack->insert(0, widget);
+ app_do_modal = true;
+ curWin = 0;
+ qt_last_mouse_receiver = 0;
+ qt_win_ignoreNextMouseReleaseEvent = false;
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *widget)
+{
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ QPoint p(QCursor::pos());
+ app_do_modal = false; // necessary, we may get recursively into qt_try_modal below
+ QWidget* w = QApplication::widgetAt(p.x(), p.y());
+ QWidget *leave = qt_last_mouse_receiver;
+ if (!leave)
+ leave = QWidget::find((WId)curWin);
+ if (QWidget *grabber = QWidget::mouseGrabber()) {
+ w = grabber;
+ if (leave == w)
+ leave = 0;
+ }
+ QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event
+ curWin = w ? w->effectiveWinId() : 0;
+ qt_last_mouse_receiver = w;
+ }
+ qt_win_ignoreNextMouseReleaseEvent = true;
+ }
+ app_do_modal = qt_modal_stack != 0;
+}
+
+bool qt_try_modal(QWidget *widget, MSG *msg, int& ret)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(ret);
+#endif
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ int type = msg->message;
+
+ bool block_event = false;
+#ifndef Q_OS_WINCE
+ if (type != WM_NCHITTEST)
+#endif
+ if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) ||
+ type == WM_MOUSEWHEEL || type == (int)WM95_MOUSEWHEEL ||
+ type == WM_MOUSELEAVE ||
+ (type >= WM_KEYFIRST && type <= WM_KEYLAST)
+#ifndef Q_OS_WINCE
+ || type == WM_NCMOUSEMOVE
+#endif
+ ) {
+ if (type == WM_MOUSEMOVE
+#ifndef Q_OS_WINCE
+ || type == WM_NCMOUSEMOVE
+#endif
+ ) {
+#ifndef QT_NO_CURSOR
+ QCursor *c = qt_grab_cursor();
+ if (!c)
+ c = QApplication::overrideCursor();
+ if (c) // application cursor defined
+ SetCursor(c->handle());
+ else
+ SetCursor(QCursor(Qt::ArrowCursor).handle());
+#endif // QT_NO_CURSOR
+ }
+ block_event = true;
+ } else if (type == WM_CLOSE) {
+ block_event = true;
+ }
+#ifndef Q_OS_WINCE
+ else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){
+ if (!top->isActiveWindow()) {
+ top->activateWindow();
+ } else {
+ QApplication::beep();
+ }
+ block_event = true;
+ ret = MA_NOACTIVATEANDEAT;
+ } else if (type == WM_SYSCOMMAND) {
+ if (!(msg->wParam == SC_RESTORE && widget->isMinimized()))
+ block_event = true;
+ }
+#endif
+
+ return !block_event;
+}
+
+
+/*****************************************************************************
+ Popup widget mechanism
+
+ openPopup()
+ Adds a widget to the list of popup widgets
+ Arguments:
+ QWidget *widget The popup widget to be added
+
+ closePopup()
+ Removes a widget from the list of popup widgets
+ Arguments:
+ QWidget *widget The popup widget to be removed
+ *****************************************************************************/
+
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets)
+ QApplicationPrivate::popupWidgets = new QWidgetList;
+ QApplicationPrivate::popupWidgets->append(popup);
+ if (!popup->isEnabled())
+ return;
+
+ // close any opened 'ime candidate window'
+ if (imeParentWnd)
+ ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0);
+
+ if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()) {
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ setAutoCapture(popup->internalWinId()); // grab mouse/keyboard
+ }
+ // Popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
+ if (QWidget *fw = q_func()->focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets)
+ return;
+ QApplicationPrivate::popupWidgets->removeAll(popup);
+ POINT curPos;
+ GetCursorPos(&curPos);
+
+ // close any opened 'ime candidate window'
+ if (imeParentWnd)
+ ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0);
+
+ if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+ replayPopupMouseEvent = (!popup->geometry().contains(QPoint(curPos.x, curPos.y))
+ && !popup->testAttribute(Qt::WA_NoMouseReplay));
+ if (!popup->isEnabled())
+ return;
+ if (!qt_nograb()) // grabbing not disabled
+ releaseAutoCapture();
+ QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
+ : q_func()->focusWidget();
+ if (fw) {
+ if (fw != q_func()->focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+ } else {
+ // Popups are not focus-handled by the window system (the
+ // first popup grabbed the keyboard), so we have to do that
+ // manually: A popup was closed, so the previous popup gets
+ // the focus.
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QApplicationPrivate::popupWidgets->count() == 1) {
+ Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created));
+ setAutoCapture(aw->internalWinId());
+ }
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+ }
+}
+
+
+
+
+/*****************************************************************************
+ Event translation; translates Windows events to Qt events
+ *****************************************************************************/
+
+//
+// Auto-capturing for mouse press and mouse release
+//
+
+static void setAutoCapture(HWND h)
+{
+ if (autoCaptureWnd)
+ releaseAutoCapture();
+ autoCaptureWnd = h;
+ SetCapture(h);
+}
+
+static void releaseAutoCapture()
+{
+ if (autoCaptureWnd) {
+ ReleaseCapture();
+ autoCaptureWnd = 0;
+ }
+}
+
+
+//
+// Mouse event translation
+//
+// Non-client mouse messages are not translated
+//
+
+static const ushort mouseTbl[] = {
+ WM_MOUSEMOVE, QEvent::MouseMove, 0,
+ WM_LBUTTONDOWN, QEvent::MouseButtonPress, Qt::LeftButton,
+ WM_LBUTTONUP, QEvent::MouseButtonRelease, Qt::LeftButton,
+ WM_LBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton,
+ WM_RBUTTONDOWN, QEvent::MouseButtonPress, Qt::RightButton,
+ WM_RBUTTONUP, QEvent::MouseButtonRelease, Qt::RightButton,
+ WM_RBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton,
+ WM_MBUTTONDOWN, QEvent::MouseButtonPress, Qt::MidButton,
+ WM_MBUTTONUP, QEvent::MouseButtonRelease, Qt::MidButton,
+ WM_MBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton,
+ // use XButton1 for now, the real X button is decided later
+ WM_XBUTTONDOWN, QEvent::MouseButtonPress, Qt::XButton1,
+ WM_XBUTTONUP, QEvent::MouseButtonRelease, Qt::XButton1,
+ WM_XBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::XButton1,
+
+#ifndef Q_OS_WINCE
+ WM_NCMOUSEMOVE, QEvent::NonClientAreaMouseMove, 0,
+ WM_NCLBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton,
+ WM_NCLBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton,
+ WM_NCLBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::LeftButton,
+ WM_NCRBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::RightButton,
+ WM_NCRBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton,
+ WM_NCRBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::RightButton,
+ WM_NCMBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::MidButton,
+ WM_NCMBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton,
+ WM_NCMBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::MidButton,
+#endif
+
+ 0, 0, 0
+};
+
+static int translateButtonState(int s, int type, int button)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(button);
+ int bst = 0;
+ if (s & MK_LBUTTON)
+ bst |= Qt::LeftButton;
+ if (s & MK_MBUTTON)
+ bst |= Qt::MidButton;
+ if (s & MK_RBUTTON)
+ bst |= Qt::RightButton;
+ if (s & MK_SHIFT)
+ bst |= Qt::ShiftModifier;
+ if (s & MK_CONTROL)
+ bst |= Qt::ControlModifier;
+
+ if (s & MK_XBUTTON1)
+ bst |= Qt::XButton1;
+ if (s & MK_XBUTTON2)
+ bst |= Qt::XButton2;
+
+ if (GetKeyState(VK_MENU) < 0)
+ bst |= Qt::AltModifier;
+
+ if ((GetKeyState(VK_LWIN) < 0) ||
+ (GetKeyState(VK_RWIN) < 0))
+ bst |= Qt::MetaModifier;
+
+ return bst;
+}
+
+void qt_win_eatMouseMove()
+{
+ // after closing a windows dialog with a double click (i.e. open a file)
+ // the message queue still contains a dubious WM_MOUSEMOVE message where
+ // the left button is reported to be down (wParam != 0).
+ // remove all those messages (usually 1) and post the last one with a
+ // reset button state
+
+ MSG msg = {0, 0, 0, 0, 0, 0, 0};
+ QT_WA( {
+ while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
+ ;
+ if (msg.message == WM_MOUSEMOVE)
+ PostMessage(msg.hwnd, msg.message, 0, msg.lParam);
+ }, {
+ MSG msg;
+ msg.message = 0;
+ while (PeekMessageA(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
+ ;
+ if (msg.message == WM_MOUSEMOVE)
+ PostMessageA(msg.hwnd, msg.message, 0, msg.lParam);
+ } );
+}
+
+// In DnD, the mouse release event never appears, so the
+// mouse button state machine must be manually reset
+/*! \internal */
+void QApplication::winMouseButtonUp()
+{
+ qt_button_down = 0;
+ releaseAutoCapture();
+}
+
+void QETWidget::repolishStyle(QStyle &)
+{
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(this, &e);
+}
+
+bool QETWidget::translateMouseEvent(const MSG &msg)
+{
+ if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
+ Q_ASSERT(internalWinId());
+
+ static QPoint pos;
+ static POINT gpos={-1,-1};
+ QEvent::Type type; // event parameters
+ int button;
+ int state;
+ int i;
+
+ if (sm_blockUserInput) //block user interaction during session management
+ return true;
+
+ // Compress mouse move events
+ if (msg.message == WM_MOUSEMOVE) {
+ MSG mouseMsg;
+ while (winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST,
+ WM_MOUSELAST, PM_NOREMOVE)) {
+ if (mouseMsg.message == WM_MOUSEMOVE) {
+#define PEEKMESSAGE_IS_BROKEN 1
+#ifdef PEEKMESSAGE_IS_BROKEN
+ // Since the Windows PeekMessage() function doesn't
+ // correctly return the wParam for WM_MOUSEMOVE events
+ // if there is a key release event in the queue
+ // _before_ the mouse event, we have to also consider
+ // key release events (kls 2003-05-13):
+ MSG keyMsg;
+ bool done = false;
+ while (winPeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST,
+ PM_NOREMOVE)) {
+ if (keyMsg.time < mouseMsg.time) {
+ if ((keyMsg.lParam & 0xC0000000) == 0x40000000) {
+ winPeekMessage(&keyMsg, 0, keyMsg.message,
+ keyMsg.message, PM_REMOVE);
+ } else {
+ done = true;
+ break;
+ }
+ } else {
+ break; // no key event before the WM_MOUSEMOVE event
+ }
+ }
+ if (done)
+ break;
+#else
+ // Actually the following 'if' should work instead of
+ // the above key event checking, but apparently
+ // PeekMessage() is broken :-(
+ if (mouseMsg.wParam != msg.wParam)
+ break; // leave the message in the queue because
+ // the key state has changed
+#endif
+ MSG *msgPtr = (MSG *)(&msg);
+ // Update the passed in MSG structure with the
+ // most recent one.
+ msgPtr->lParam = mouseMsg.lParam;
+ msgPtr->wParam = mouseMsg.wParam;
+ msgPtr->pt = mouseMsg.pt;
+ // Remove the mouse move message
+ winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE,
+ WM_MOUSEMOVE, PM_REMOVE);
+ } else {
+ break; // there was no more WM_MOUSEMOVE event
+ }
+ }
+ }
+
+ for (i=0; (UINT)mouseTbl[i] != msg.message && mouseTbl[i]; i += 3)
+ ;
+ if (!mouseTbl[i])
+ return false;
+ type = (QEvent::Type)mouseTbl[++i]; // event type
+ button = mouseTbl[++i]; // which button
+ if (button == Qt::XButton1) {
+ switch(GET_XBUTTON_WPARAM(msg.wParam)) {
+ case XBUTTON1:
+ button = Qt::XButton1;
+ break;
+ case XBUTTON2:
+ button = Qt::XButton2;
+ break;
+ }
+ }
+ state = translateButtonState(msg.wParam, type, button); // button state
+ const QPoint widgetPos = mapFromGlobal(QPoint(msg.pt.x, msg.pt.y));
+ QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos);
+ if (alienWidget && alienWidget->internalWinId())
+ alienWidget = 0;
+
+ if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove) {
+ if (!(state & Qt::MouseButtonMask))
+ qt_button_down = 0;
+#ifndef QT_NO_CURSOR
+ QCursor *c = qt_grab_cursor();
+ if (!c)
+ c = QApplication::overrideCursor();
+ if (c) // application cursor defined
+ SetCursor(c->handle());
+ else if (type != QEvent::NonClientAreaMouseMove && !qt_button_down) {
+ // use widget cursor if widget is enabled
+ QWidget *w = alienWidget ? alienWidget : this;
+ while (!w->isWindow() && !w->isEnabled())
+ w = w->parentWidget();
+ SetCursor(w->cursor().handle());
+ }
+#endif // QT_NO_CURSOR
+
+ HWND id = effectiveWinId();
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ QWidget *activePopupWidget = qApp->activePopupWidget();
+ if (mouseGrabber) {
+ if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos)))
+ id = mouseGrabber->effectiveWinId();
+ } else if (type == QEvent::NonClientAreaMouseMove) {
+ id = 0;
+ }
+
+ if (curWin != id) { // new current window
+ if (id == 0) {
+ QWidget *leave = qt_last_mouse_receiver;
+ if (!leave)
+ leave = QWidget::find(curWin);
+ QApplicationPrivate::dispatchEnterLeave(0, leave);
+ qt_last_mouse_receiver = 0;
+ curWin = 0;
+ } else {
+ QWidget *leave = 0;
+ if (curWin && qt_last_mouse_receiver)
+ leave = qt_last_mouse_receiver;
+ else
+ leave = QWidget::find(curWin);
+ QWidget *enter = alienWidget ? alienWidget : this;
+ if (mouseGrabber && activePopupWidget) {
+ if (leave != mouseGrabber)
+ enter = mouseGrabber;
+ else
+ enter = activePopupWidget == this ? this : mouseGrabber;
+ }
+ QApplicationPrivate::dispatchEnterLeave(enter, leave);
+ qt_last_mouse_receiver = enter;
+ curWin = enter ? enter->effectiveWinId() : 0;
+ }
+#ifndef Q_OS_WINCE
+
+ if (curWin != 0) {
+ static bool trackMouseEventLookup = false;
+ typedef BOOL (WINAPI *PtrTrackMouseEvent)(LPTRACKMOUSEEVENT);
+ static PtrTrackMouseEvent ptrTrackMouseEvent = 0;
+ if (!trackMouseEventLookup) {
+ trackMouseEventLookup = true;
+ ptrTrackMouseEvent = (PtrTrackMouseEvent)QLibrary::resolve(QLatin1String("comctl32"), "_TrackMouseEvent");
+ }
+ if (ptrTrackMouseEvent && !qApp->d_func()->inPopupMode()) {
+ // We always have to set the tracking, since
+ // Windows detects more leaves than we do..
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = 0x00000002; // TME_LEAVE
+ tme.hwndTrack = curWin; // Track on window receiving msgs
+ tme.dwHoverTime = (DWORD)-1; // HOVER_DEFAULT
+ ptrTrackMouseEvent(&tme);
+ }
+ }
+#endif // Q_OS_WINCE
+ }
+
+ POINT curPos = msg.pt;
+ if (curPos.x == gpos.x && curPos.y == gpos.y)
+ return true; // same global position
+ gpos = curPos;
+
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ ScreenToClient(internalWinId(), &curPos);
+
+ pos.rx() = curPos.x;
+ pos.ry() = curPos.y;
+ pos = d_func()->mapFromWS(pos);
+ } else {
+ gpos = msg.pt;
+ pos = mapFromGlobal(QPoint(gpos.x, gpos.y));
+
+ // mouse button pressed
+ if (!qt_button_down && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)) {
+ QWidget *tlw = window();
+ if (QWidget *child = tlw->childAt(mapTo(tlw, pos)))
+ qt_button_down = child;
+ else
+ qt_button_down = this;
+ }
+ }
+
+ bool res = false;
+
+ bool nonClientAreaEvent = type >= QEvent::NonClientAreaMouseMove
+ && type <= QEvent::NonClientAreaMouseButtonDblClick;
+
+ if (qApp->d_func()->inPopupMode()) { // in popup mode
+
+ if (nonClientAreaEvent)
+ return false;
+
+ replayPopupMouseEvent = false;
+ QWidget* activePopupWidget = qApp->activePopupWidget();
+ QWidget *target = activePopupWidget;
+ const QPoint globalPos(gpos.x, gpos.y);
+
+ if (target != this) {
+ if ((windowType() == Qt::Popup) && rect().contains(pos) && 0)
+ target = this;
+ else // send to last popup
+ pos = target->mapFromGlobal(globalPos);
+ }
+ QWidget *popupChild = target->childAt(pos);
+ bool releaseAfter = false;
+ switch (type) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ popupButtonFocus = popupChild;
+ break;
+ case QEvent::MouseButtonRelease:
+ releaseAfter = true;
+ break;
+ default:
+ break; // nothing for mouse move
+ }
+
+ if (target->isEnabled()) {
+ if (popupButtonFocus) {
+ target = popupButtonFocus;
+ } else if (popupChild) {
+ // forward mouse events to the popup child. mouse move events
+ // are only forwarded to popup children that enable mouse tracking.
+ if (type != QEvent::MouseMove || popupChild->hasMouseTracking())
+ target = popupChild;
+ }
+
+ pos = target->mapFromGlobal(globalPos);
+ QMouseEvent e(type, pos, globalPos,
+ Qt::MouseButton(button),
+ Qt::MouseButtons(state & Qt::MouseButtonMask),
+ Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
+ res = QApplicationPrivate::sendMouseEvent(target, &e, alienWidget, this, &qt_button_down,
+ qt_last_mouse_receiver);
+ res = res && e.isAccepted();
+ } else {
+ // close disabled popups when a mouse button is pressed or released
+ switch (type) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonRelease:
+ target->close();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (releaseAfter) {
+ popupButtonFocus = 0;
+ qt_button_down = 0;
+ }
+
+ if (type == QEvent::MouseButtonPress
+ && qApp->activePopupWidget() != activePopupWidget
+ && replayPopupMouseEvent) {
+ // the popup dissappeared. Replay the event
+ QWidget* w = QApplication::widgetAt(gpos.x, gpos.y);
+ if (w && !QApplicationPrivate::isBlockedByModal(w)) {
+ Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
+ HWND hwndTarget = w->effectiveWinId();
+ if (QWidget::mouseGrabber() == 0)
+ setAutoCapture(hwndTarget);
+ if (!w->isActiveWindow())
+ w->activateWindow();
+ POINT widgetpt = gpos;
+ ScreenToClient(hwndTarget, &widgetpt);
+ LPARAM lParam = MAKELPARAM(widgetpt.x, widgetpt.y);
+ winPostMessage(hwndTarget, msg.message, msg.wParam, lParam);
+ }
+ } else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton
+ && qApp->activePopupWidget() == activePopupWidget) {
+ // popup still alive and received right-button-release
+#if !defined(QT_NO_CONTEXTMENU)
+ QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos,
+ qt_win_getKeyboardModifiers());
+ bool res2 = QApplication::sendSpontaneousEvent( target, &e2 );
+ if (!res) // RMB not accepted
+ res = res2 && e2.isAccepted();
+#endif
+ }
+ } else { // not popup mode
+ int bs = state & Qt::MouseButtonMask;
+ if ((type == QEvent::MouseButtonPress ||
+ type == QEvent::MouseButtonDblClick) && bs == button) {
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ if (QWidget::mouseGrabber() == 0)
+ setAutoCapture(internalWinId());
+ } else if (type == QEvent::MouseButtonRelease && bs == 0) {
+ if (QWidget::mouseGrabber() == 0)
+ releaseAutoCapture();
+ }
+
+ const QPoint globalPos(gpos.x,gpos.y);
+ QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type,
+ Qt::MouseButtons(bs),
+ qt_button_down, alienWidget);
+ if (!widget)
+ return false; // don't send event
+
+ QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button),
+ Qt::MouseButtons(state & Qt::MouseButtonMask),
+ Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
+
+ res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
+ qt_last_mouse_receiver);
+
+ // non client area events are only informational, you cannot "handle" them
+ res = res && e.isAccepted() && !nonClientAreaEvent;
+#if !defined(QT_NO_CONTEXTMENU)
+ if (type == QEvent::MouseButtonRelease && button == Qt::RightButton) {
+ QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos,
+ qt_win_getKeyboardModifiers());
+ bool res2 = QApplication::sendSpontaneousEvent(widget, &e2);
+ if (!res)
+ res = res2 && e2.isAccepted();
+ }
+#endif
+
+ if (type != QEvent::MouseMove)
+ pos.rx() = pos.ry() = -9999; // init for move compression
+ }
+ return res;
+}
+
+bool QETWidget::translateWheelEvent(const MSG &msg)
+{
+ int state = 0;
+
+ if (sm_blockUserInput) // block user interaction during session management
+ return true;
+
+ state = translateButtonState(GET_KEYSTATE_WPARAM(msg.wParam), 0, 0);
+
+ int delta;
+ if (msg.message == WM_MOUSEWHEEL)
+ delta = (short) HIWORD (msg.wParam);
+ else
+ delta = (int) msg.wParam;
+
+ Qt::Orientation orient = (state&Qt::AltModifier
+#if 0
+ // disabled for now - Trenton's one-wheel mouse makes trouble...
+ // "delta" for usual wheels is +-120. +-240 seems to indicate
+ // the second wheel see more recent MSDN for WM_MOUSEWHEEL
+
+ ( // <- parantheses added to make update happy, remove if the
+ // #if 0 is removed
+ || delta == 240 || delta == -240)?Qt::Horizontal:Vertical;
+ if (delta == 240 || delta == -240)
+ delta /= 2;
+#endif
+ ) ? Qt::Horizontal : Qt::Vertical;
+
+ QPoint globalPos;
+
+ globalPos.rx() = (short)LOWORD (msg.lParam);
+ globalPos.ry() = (short)HIWORD (msg.lParam);
+
+
+ // if there is a widget under the mouse and it is not shadowed
+ // by modality, we send the event to it first
+ int ret = 0;
+ QWidget* w = QApplication::widgetAt(globalPos);
+ if (!w || !qt_try_modal(w, (MSG*)&msg, ret)) {
+ //synaptics touchpad shows its own widget at this position
+ //so widgetAt() will fail with that HWND, try child of this widget
+ w = this->childAt(this->mapFromGlobal(globalPos));
+ if (!w)
+ w = this;
+ }
+
+ // send the event to the widget or its ancestors
+ {
+ QWidget* popup = qApp->activePopupWidget();
+ if (popup && w->window() != popup)
+ popup->close();
+#ifndef QT_NO_WHEELEVENT
+ QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta,
+ Qt::MouseButtons(state & Qt::MouseButtonMask),
+ Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient);
+
+ if (QApplication::sendSpontaneousEvent(w, &e))
+#else
+ Q_UNUSED(orient);
+#endif //QT_NO_WHEELEVENT
+ return true;
+ }
+
+ // send the event to the widget that has the focus or its ancestors, if different
+ if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
+ QWidget* popup = qApp->activePopupWidget();
+ if (popup && w->window() != popup)
+ popup->close();
+#ifndef QT_NO_WHEELEVENT
+ QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta,
+ Qt::MouseButtons(state & Qt::MouseButtonMask),
+ Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient);
+ if (QApplication::sendSpontaneousEvent(w, &e))
+#endif //QT_NO_WHEELEVENT
+ return true;
+ }
+ return false;
+}
+
+
+//
+// Windows Wintab to QTabletEvent translation
+//
+
+// the following is adapted from the wintab syspress example (public domain)
+/* -------------------------------------------------------------------------- */
+static void tabletInit(UINT wActiveCsr, HCTX hTab)
+{
+ /* browse WinTab's many info items to discover pressure handling. */
+ if (ptrWTInfo && ptrWTGet) {
+ AXIS np;
+ LOGCONTEXT lc;
+ BYTE wPrsBtn;
+ BYTE logBtns[32];
+ UINT size;
+
+ /* discover the LOGICAL button generated by the pressure channel. */
+ /* get the PHYSICAL button from the cursor category and run it */
+ /* through that cursor's button map (usually the identity map). */
+ wPrsBtn = (BYTE)-1;
+ ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_NPBUTTON, &wPrsBtn);
+ size = ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_BUTTONMAP, &logBtns);
+ if ((UINT)wPrsBtn < size)
+ wPrsBtn = logBtns[wPrsBtn];
+
+ /* get the current context for its device variable. */
+ ptrWTGet(hTab, &lc);
+
+ /* get the size of the pressure axis. */
+ QTabletDeviceData tdd;
+ ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np);
+ tdd.minPressure = int(np.axMin);
+ tdd.maxPressure = int(np.axMax);
+
+ ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np);
+ tdd.minTanPressure = int(np.axMin);
+ tdd.maxTanPressure = int(np.axMax);
+
+ ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_X, &np);
+ tdd.minX = int(np.axMin);
+ tdd.maxX = int(np.axMax);
+
+ ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Y, &np);
+ tdd.minY = int(np.axMin);
+ tdd.maxY = int(np.axMax);
+
+ ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Z, &np);
+ tdd.minZ = int(np.axMin);
+ tdd.maxZ = int(np.axMax);
+
+ int csr_type,
+ csr_physid;
+ ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_TYPE, &csr_type);
+ ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_PHYSID, &csr_physid);
+ tdd.llId = csr_type & 0x0F06;
+ tdd.llId = (tdd.llId << 24) | csr_physid;
+#ifndef QT_NO_TABLETEVENT
+ if (((csr_type & 0x0006) == 0x0002) && ((csr_type & 0x0F06) != 0x0902)) {
+ tdd.currentDevice = QTabletEvent::Stylus;
+ } else {
+ switch (csr_type & 0x0F06) {
+ case 0x0802:
+ tdd.currentDevice = QTabletEvent::Stylus;
+ break;
+ case 0x0902:
+ tdd.currentDevice = QTabletEvent::Airbrush;
+ break;
+ case 0x0004:
+ tdd.currentDevice = QTabletEvent::FourDMouse;
+ break;
+ case 0x0006:
+ tdd.currentDevice = QTabletEvent::Puck;
+ break;
+ case 0x0804:
+ tdd.currentDevice = QTabletEvent::RotationStylus;
+ break;
+ default:
+ tdd.currentDevice = QTabletEvent::NoDevice;
+ }
+ }
+
+ switch (wActiveCsr % 3) {
+ case 2:
+ tdd.currentPointerType = QTabletEvent::Eraser;
+ break;
+ case 1:
+ tdd.currentPointerType = QTabletEvent::Pen;
+ break;
+ case 0:
+ tdd.currentPointerType = QTabletEvent::Cursor;
+ break;
+ default:
+ tdd.currentPointerType = QTabletEvent::UnknownPointer;
+ }
+#endif // QT_NO_TABLETEVENT
+ tCursorInfo()->insert(wActiveCsr, tdd);
+ }
+}
+
+bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf,
+ int numPackets)
+{
+ Q_UNUSED(msg);
+ POINT ptNew;
+ static DWORD btnNew, btnOld, btnChange;
+ qreal prsNew;
+ ORIENTATION ort;
+ static bool button_pressed = false;
+ int i,
+ tiltX,
+ tiltY;
+ bool sendEvent = false;
+ QEvent::Type t;
+ int z = 0;
+ qreal rotation = 0.0;
+ qreal tangentialPressure;
+
+ // the most common event that we get...
+ t = QEvent::TabletMove;
+ for (i = 0; i < numPackets; i++) {
+ // get the unique ID of the device...
+ btnOld = btnNew;
+ btnNew = localPacketBuf[i].pkButtons;
+ btnChange = btnOld ^ btnNew;
+
+ if (btnNew & btnChange) {
+ button_pressed = true;
+ t = QEvent::TabletPress;
+ }
+ ptNew.x = UINT(localPacketBuf[i].pkX);
+ ptNew.y = UINT(localPacketBuf[i].pkY);
+#ifndef QT_NO_TABLETEVENT
+ z = (currentTabletPointer.currentDevice == QTabletEvent::FourDMouse) ? UINT(localPacketBuf[i].pkZ) : 0;
+#else
+ Q_UNUSED(z);
+#endif // QT_NO_TABLETEVENT
+ prsNew = 0.0;
+ QRect desktopArea = QApplication::desktop()->geometry();
+ QPointF hiResGlobal = currentTabletPointer.scaleCoord(ptNew.x, ptNew.y, desktopArea.left(),
+ desktopArea.width(), desktopArea.top(),
+ desktopArea.height());
+
+ if (btnNew) {
+#ifndef QT_NO_TABLETEVENT
+ if (currentTabletPointer.currentPointerType == QTabletEvent::Pen || currentTabletPointer.currentPointerType == QTabletEvent::Eraser)
+ prsNew = localPacketBuf[i].pkNormalPressure
+ / qreal(currentTabletPointer.maxPressure
+ - currentTabletPointer.minPressure);
+ else
+#endif // QT_NO_TABLETEVENT
+ prsNew = 0;
+ } else if (button_pressed) {
+ // One button press, should only give one button release
+ t = QEvent::TabletRelease;
+ button_pressed = false;
+ }
+ QPoint globalPos(qRound(hiResGlobal.x()), qRound(hiResGlobal.y()));
+
+ // make sure the tablet event get's sent to the proper widget...
+ QWidget *w = QApplication::widgetAt(globalPos);
+ if (qt_button_down)
+ w = qt_button_down; // Pass it to the thing that's grabbed it.
+
+ if (!w)
+ w = this;
+ QPoint localPos = w->mapFromGlobal(globalPos);
+#ifndef QT_NO_TABLETEVENT
+ if (currentTabletPointer.currentDevice == QTabletEvent::Airbrush) {
+ tangentialPressure = localPacketBuf[i].pkTangentPressure
+ / qreal(currentTabletPointer.maxTanPressure
+ - currentTabletPointer.minTanPressure);
+ } else {
+ tangentialPressure = 0.0;
+ }
+#else
+ tangentialPressure = 0.0;
+#endif // QT_NO_TABLETEVENT
+
+ if (!qt_tablet_tilt_support) {
+ tiltX = tiltY = 0;
+ rotation = 0.0;
+ } else {
+ ort = localPacketBuf[i].pkOrientation;
+ // convert from azimuth and altitude to x tilt and y tilt
+ // what follows is the optimized version. Here are the equations
+ // I used to get to this point (in case things change :)
+ // X = sin(azimuth) * cos(altitude)
+ // Y = cos(azimuth) * cos(altitude)
+ // Z = sin(altitude)
+ // X Tilt = arctan(X / Z)
+ // Y Tilt = arctan(Y / Z)
+ double radAzim = (ort.orAzimuth / 10) * (Q_PI / 180);
+ //double radAlt = abs(ort.orAltitude / 10) * (Q_PI / 180);
+ double tanAlt = tan((abs(ort.orAltitude / 10)) * (Q_PI / 180));
+
+ double degX = atan(sin(radAzim) / tanAlt);
+ double degY = atan(cos(radAzim) / tanAlt);
+ tiltX = int(degX * (180 / Q_PI));
+ tiltY = int(-degY * (180 / Q_PI));
+ rotation = ort.orTwist;
+ }
+#ifndef QT_NO_TABLETEVENT
+ QTabletEvent e(t, localPos, globalPos, hiResGlobal, currentTabletPointer.currentDevice,
+ currentTabletPointer.currentPointerType, prsNew, tiltX, tiltY,
+ tangentialPressure, rotation, z, QApplication::keyboardModifiers(), currentTabletPointer.llId);
+ sendEvent = QApplication::sendSpontaneousEvent(w, &e);
+#endif // QT_NO_TABLETEVENT
+ }
+ return sendEvent;
+}
+
+extern bool qt_is_gui_used;
+static void initWinTabFunctions()
+{
+#if defined(Q_OS_WINCE)
+ return;
+#else
+ if (!qt_is_gui_used)
+ return;
+
+ QLibrary library(QLatin1String("wintab32"));
+ if (library.load()) {
+ QT_WA({
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
+ ptrWTGet = (PtrWTGet)library.resolve("WTGetW");
+ } , {
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA");
+ ptrWTGet = (PtrWTGet)library.resolve("WTGetA");
+ });
+
+ ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable");
+ ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap");
+ ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet");
+ }
+#endif // Q_OS_WINCE
+}
+
+
+//
+// Paint event translation
+//
+bool QETWidget::translatePaintEvent(const MSG &msg)
+{
+ if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
+ Q_ASSERT(internalWinId());
+
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ if (!GetUpdateRect(internalWinId(), 0, FALSE)) { // The update bounding rect is invalid
+ d_func()->hd = 0;
+ setAttribute(Qt::WA_PendingUpdate, false);
+ return false;
+ }
+
+ if (msg.message == WM_ERASEBKGND)
+ return true;
+
+ setAttribute(Qt::WA_PendingUpdate, false);
+ const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
+ // Make sure the invalidated region contains the region we're about to repaint.
+ // BeginPaint will set the clip to the invalidated region and it is impossible
+ // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient
+ // as it may return an invalid context (especially on Windows Vista).
+ if (!dirtyInBackingStore.isEmpty())
+ InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false);
+ PAINTSTRUCT ps;
+ d_func()->hd = BeginPaint(internalWinId(), &ps);
+
+ const QRect updateRect(QPoint(ps.rcPaint.left, ps.rcPaint.top),
+ QPoint(ps.rcPaint.right, ps.rcPaint.bottom));
+
+ // Mapping region from system to qt (32 bit) coordinate system.
+ d_func()->syncBackingStore(updateRect.translated(data->wrect.topLeft()));
+
+ d_func()->hd = 0;
+ EndPaint(internalWinId(), &ps);
+
+ return true;
+}
+
+//
+// Window move and resize (configure) events
+//
+
+bool QETWidget::translateConfigEvent(const MSG &msg)
+{
+ if (!testAttribute(Qt::WA_WState_Created)) // in QWidget::create()
+ return true;
+ if (testAttribute(Qt::WA_WState_ConfigPending))
+ return true;
+ if (testAttribute(Qt::WA_DontShowOnScreen))
+ return true;
+ if (!isWindow())
+ return true;
+ setAttribute(Qt::WA_WState_ConfigPending); // set config flag
+ QRect cr = geometry();
+ if (msg.message == WM_SIZE) { // resize event
+ WORD a = LOWORD(msg.lParam);
+ WORD b = HIWORD(msg.lParam);
+ QSize oldSize = size();
+ QSize newSize(a, b);
+#ifdef Q_OS_WINCE_WM
+ if (isFullScreen() && (oldSize.width() == newSize.height()) && (oldSize.height() == newSize.width()))
+ qt_wince_hide_taskbar(internalWinId());
+#endif
+ cr.setSize(newSize);
+ if (msg.wParam != SIZE_MINIMIZED)
+ data->crect = cr;
+ if (isWindow()) { // update title/icon text
+ d_func()->createTLExtra();
+ // Capture SIZE_MINIMIZED without preceding WM_SYSCOMMAND
+ // (like Windows+M)
+ if (msg.wParam == SIZE_MINIMIZED && !isMinimized()) {
+#ifndef Q_OS_WINCE
+ const QString title = windowIconText();
+ if (!title.isEmpty())
+ d_func()->setWindowTitle_helper(title);
+#endif
+ data->window_state |= Qt::WindowMinimized;
+ if (isVisible()) {
+ QHideEvent e;
+ QApplication::sendSpontaneousEvent(this, &e);
+ hideChildren(true);
+ }
+ } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) {
+#ifndef Q_OS_WINCE
+ const QString title = windowTitle();
+ if (!title.isEmpty())
+ d_func()->setWindowTitle_helper(title);
+#endif
+ data->window_state &= ~Qt::WindowMinimized;
+ showChildren(true);
+ QShowEvent e;
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
+ }
+ if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) {
+ if (isVisible()) {
+ QTLWExtra *tlwExtra = maybeTopData();
+ static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ const bool hasStaticContents = tlwExtra && tlwExtra->backingStore
+ && tlwExtra->backingStore->hasStaticContents();
+ // If we have a backing store with static contents, we have to disable the top-level
+ // resize optimization in order to get invalidated regions for resized widgets.
+ // The optimization discards all invalidateBuffer() calls since we're going to
+ // repaint everything anyways, but that's not the case with static contents.
+ if (!slowResize && tlwExtra && !hasStaticContents)
+ tlwExtra->inTopLevelResize = true;
+ QResizeEvent e(newSize, oldSize);
+ QApplication::sendSpontaneousEvent(this, &e);
+ if (d_func()->paintOnScreen()) {
+ QRegion updateRegion(rect());
+ if (testAttribute(Qt::WA_StaticContents))
+ updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
+ d_func()->syncBackingStore(updateRegion);
+ } else {
+ d_func()->syncBackingStore();
+ }
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = false;
+ } else {
+ QResizeEvent *e = new QResizeEvent(newSize, oldSize);
+ QApplication::postEvent(this, e);
+ }
+ }
+} else if (msg.message == WM_MOVE) { // move event
+ int a = (int) (short) LOWORD(msg.lParam);
+ int b = (int) (short) HIWORD(msg.lParam);
+ QPoint oldPos = geometry().topLeft();
+ QPoint newCPos(a, b);
+ // Ignore silly Windows move event to wild pos after iconify.
+#if !defined(Q_OS_WINCE)
+ if (!IsIconic(internalWinId()) && newCPos != oldPos) {
+#endif
+ cr.moveTopLeft(newCPos);
+ data->crect = cr;
+ if (isVisible()) {
+ QMoveEvent e(newCPos, oldPos); // cpos (client position)
+ QApplication::sendSpontaneousEvent(this, &e);
+ } else {
+ QMoveEvent * e = new QMoveEvent(newCPos, oldPos);
+ QApplication::postEvent(this, e);
+ }
+#if !defined(Q_OS_WINCE)
+ }
+#endif
+ }
+ setAttribute(Qt::WA_WState_ConfigPending, false); // clear config flag
+ return true;
+}
+
+
+//
+// Close window event translation.
+//
+// This class is a friend of QApplication because it needs to emit the
+// lastWindowClosed() signal when the last top level widget is closed.
+//
+
+bool QETWidget::translateCloseEvent(const MSG &)
+{
+ return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+}
+
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ SetCaretBlinkTime(msecs / 2);
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+
+int QApplication::cursorFlashTime()
+{
+ int blink = (int)GetCaretBlinkTime();
+ if (!blink)
+ return QApplicationPrivate::cursor_flash_time;
+ if (blink > 0)
+ return 2*blink;
+ return 0;
+}
+
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+#ifndef Q_OS_WINCE
+ SetDoubleClickTime(ms);
+#endif
+ QApplicationPrivate::mouse_double_click_time = ms;
+}
+
+int QApplication::doubleClickInterval()
+{
+ int ms = GetDoubleClickTime();
+ if (ms != 0)
+ return ms;
+ return QApplicationPrivate::mouse_double_click_time;
+}
+
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::keyboardInputInterval()
+{
+ // FIXME: get from the system
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+#ifndef QT_NO_WHEELEVENT
+void QApplication::setWheelScrollLines(int n)
+{
+#ifdef SPI_SETWHEELSCROLLLINES
+ if (n < 0)
+ n = 0;
+ QT_WA({
+ SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0);
+ } , {
+ SystemParametersInfoA(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0);
+ });
+#else
+ QApplicationPrivate::wheel_scroll_lines = n;
+#endif
+}
+
+int QApplication::wheelScrollLines()
+{
+#ifdef SPI_GETWHEELSCROLLLINES
+ uint i = 3;
+ QT_WA({
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0);
+ } , {
+ SystemParametersInfoA(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0);
+ });
+ if (i > INT_MAX)
+ i = INT_MAX;
+ return i;
+#else
+ return QApplicationPrivate::wheel_scroll_lines;
+#endif
+}
+#endif //QT_NO_WHEELEVENT
+
+static bool effect_override = false;
+
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ effect_override = true;
+ switch (effect) {
+ case Qt::UI_AnimateMenu:
+ QApplicationPrivate::animate_menu = enable;
+ break;
+ case Qt::UI_FadeMenu:
+ QApplicationPrivate::fade_menu = enable;
+ break;
+ case Qt::UI_AnimateCombo:
+ QApplicationPrivate::animate_combo = enable;
+ break;
+ case Qt::UI_AnimateTooltip:
+ QApplicationPrivate::animate_tooltip = enable;
+ break;
+ case Qt::UI_FadeTooltip:
+ QApplicationPrivate::fade_tooltip = enable;
+ break;
+ case Qt::UI_AnimateToolBox:
+ QApplicationPrivate::animate_toolbox = enable;
+ break;
+ default:
+ QApplicationPrivate::animate_ui = enable;
+ break;
+ }
+}
+
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ if (QColormap::instance().depth() < 16)
+ return false;
+
+ if (!effect_override && desktopSettingsAware()
+ && !(QSysInfo::WindowsVersion == QSysInfo::WV_95 || QSysInfo::WindowsVersion == QSysInfo::WV_NT)) {
+ // we know that they can be used when we are here
+ BOOL enabled = false;
+ UINT api;
+ switch (effect) {
+ case Qt::UI_AnimateMenu:
+ api = SPI_GETMENUANIMATION;
+ break;
+ case Qt::UI_FadeMenu:
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
+ return false;
+ api = SPI_GETMENUFADE;
+ break;
+ case Qt::UI_AnimateCombo:
+ api = SPI_GETCOMBOBOXANIMATION;
+ break;
+ case Qt::UI_AnimateTooltip:
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
+ api = SPI_GETMENUANIMATION;
+ else
+ api = SPI_GETTOOLTIPANIMATION;
+ break;
+ case Qt::UI_FadeTooltip:
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
+ return false;
+ api = SPI_GETTOOLTIPFADE;
+ break;
+ default:
+ api = SPI_GETUIEFFECTS;
+ break;
+ }
+ QT_WA({
+ SystemParametersInfo(api, 0, &enabled, 0);
+ } , {
+ SystemParametersInfoA(api, 0, &enabled, 0);
+ });
+ return enabled;
+ }
+
+ switch(effect) {
+ case Qt::UI_AnimateMenu:
+ return QApplicationPrivate::animate_menu;
+ case Qt::UI_FadeMenu:
+ return QApplicationPrivate::fade_menu;
+ case Qt::UI_AnimateCombo:
+ return QApplicationPrivate::animate_combo;
+ case Qt::UI_AnimateTooltip:
+ return QApplicationPrivate::animate_tooltip;
+ case Qt::UI_FadeTooltip:
+ return QApplicationPrivate::fade_tooltip;
+ case Qt::UI_AnimateToolBox:
+ return QApplicationPrivate::animate_toolbox;
+ default:
+ return QApplicationPrivate::animate_ui;
+ }
+}
+
+#ifndef QT_NO_SESSIONMANAGER
+
+bool QSessionManager::allowsInteraction()
+{
+ sm_blockUserInput = false;
+ return true;
+}
+
+bool QSessionManager::allowsErrorInteraction()
+{
+ sm_blockUserInput = false;
+ return true;
+}
+
+void QSessionManager::release()
+{
+ if (sm_smActive)
+ sm_blockUserInput = true;
+}
+
+void QSessionManager::cancel()
+{
+ sm_cancel = true;
+}
+
+#endif //QT_NO_SESSIONMANAGER
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
new file mode 100644
index 0000000000..1df442f39c
--- /dev/null
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -0,0 +1,5919 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// ### 4.0: examine Q_EXPORT's below. The respective symbols had all
+// been in use (e.g. in the KDE wm) before the introduction of a version
+// map. One might want to turn some of them into proper public API and
+// provide a proper alternative for others. See also the exports in
+// qapplication_win.cpp, which suggest a unification.
+
+#include "qplatformdefs.h"
+
+#include "qcolormap.h"
+#include "qdesktopwidget.h"
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qcursor.h"
+#include "qwidget.h"
+#include "qbitarray.h"
+#include "qpainter.h"
+#include "qfile.h"
+#include "qpixmapcache.h"
+#include "qdatetime.h"
+#include "qtextcodec.h"
+#include "qdatastream.h"
+#include "qbuffer.h"
+#include "qsocketnotifier.h"
+#include "qsessionmanager.h"
+#include "qclipboard.h"
+#include "qwhatsthis.h"
+#include "qsettings.h"
+#include "qstylefactory.h"
+#include "qfileinfo.h"
+#include "qdir.h"
+#include "qhash.h"
+#include "qevent.h"
+#include "qevent_p.h"
+#include "qvarlengtharray.h"
+#include "qdebug.h"
+#include <private/qunicodetables_p.h>
+#include <private/qcrashhandler_p.h>
+#include <private/qcolor_p.h>
+#include <private/qcursor_p.h>
+#include "qstyle.h"
+#include "qmetaobject.h"
+#include "qtimer.h"
+#include "qlibrary.h"
+#include <private/qgraphicssystemfactory_p.h>
+
+#if !defined (QT_NO_TABLET)
+extern "C" {
+# define class c_class //XIproto.h has a name member named 'class' which the c++ compiler doesn't like
+# include <wacomcfg.h>
+# undef class
+}
+#endif
+
+//#define ALIEN_DEBUG
+
+#if !defined(QT_NO_GLIB)
+# include "qguieventdispatcher_glib_p.h"
+#endif
+#include "qeventdispatcher_x11_p.h"
+#include <private/qpaintengine_x11_p.h>
+
+#include <private/qkeymapper_p.h>
+
+// Input method stuff
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qinputcontextfactory.h"
+#endif // QT_NO_IM
+
+#ifndef QT_NO_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif // QT_NO_XFIXES
+
+#include "qt_x11_p.h"
+#include "qx11info_x11.h"
+
+#define XK_MISCELLANY
+#include <X11/keysymdef.h>
+#include <X11/extensions/XI.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
+
+#include "qwidget_p.h"
+
+#include <private/qbackingstore_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define X_NOT_BROKEN
+#ifdef X_NOT_BROKEN
+// Some X libraries are built with setlocale #defined to _Xsetlocale,
+// even though library users are then built WITHOUT such a definition.
+// This creates a problem - Qt might setlocale() one value, but then
+// X looks and doesn't see the value Qt set. The solution here is to
+// implement _Xsetlocale just in case X calls it - redirecting it to
+// the real libC version.
+//
+# ifndef setlocale
+extern "C" char *_Xsetlocale(int category, const char *locale);
+char *_Xsetlocale(int category, const char *locale)
+{
+ //qDebug("_Xsetlocale(%d,%s),category,locale");
+ return setlocale(category,locale);
+}
+# endif // setlocale
+#endif // X_NOT_BROKEN
+
+/* Warning: if you modify this string, modify the list of atoms in qt_x11_p.h as well! */
+static const char * x11_atomnames = {
+ // window-manager <-> client protocols
+ "WM_PROTOCOLS\0"
+ "WM_DELETE_WINDOW\0"
+ "WM_TAKE_FOCUS\0"
+ "_NET_WM_PING\0"
+ "_NET_WM_CONTEXT_HELP\0"
+
+ // ICCCM window state
+ "WM_STATE\0"
+ "WM_CHANGE_STATE\0"
+
+ // Session management
+ "WM_CLIENT_LEADER\0"
+ "WM_WINDOW_ROLE\0"
+ "SM_CLIENT_ID\0"
+
+ // Clipboard
+ "CLIPBOARD\0"
+ "INCR\0"
+ "TARGETS\0"
+ "MULTIPLE\0"
+ "TIMESTAMP\0"
+ "CLIP_TEMPORARY\0"
+ "_QT_SELECTION\0"
+ "_QT_CLIPBOARD_SENTINEL\0"
+ "_QT_SELECTION_SENTINEL\0"
+
+ "RESOURCE_MANAGER\0"
+
+ "_XSETROOT_ID\0"
+
+ "_QT_SCROLL_DONE\0"
+ "_QT_INPUT_ENCODING\0"
+
+ "_MOTIF_WM_HINTS\0"
+
+ "DTWM_IS_RUNNING\0"
+ "KDE_FULL_SESSION\0"
+ "KWIN_RUNNING\0"
+ "KWM_RUNNING\0"
+ "GNOME_BACKGROUND_PROPERTIES\0"
+ "ENLIGHTENMENT_DESKTOP\0"
+ "_SGI_DESKS_MANAGER\0"
+
+ // EWMH (aka NETWM)
+ "_NET_SUPPORTED\0"
+ "_NET_VIRTUAL_ROOTS\0"
+ "_NET_WORKAREA\0"
+
+ "_NET_MOVERESIZE_WINDOW\0"
+ "_NET_WM_MOVERESIZE\0"
+
+ "_NET_WM_NAME\0"
+ "_NET_WM_ICON_NAME\0"
+ "_NET_WM_ICON\0"
+
+ "_NET_WM_PID\0"
+
+ "_NET_WM_WINDOW_OPACITY\0"
+
+ "_NET_WM_STATE\0"
+ "_NET_WM_STATE_ABOVE\0"
+ "_NET_WM_STATE_BELOW\0"
+ "_NET_WM_STATE_FULLSCREEN\0"
+ "_NET_WM_STATE_MAXIMIZED_HORZ\0"
+ "_NET_WM_STATE_MAXIMIZED_VERT\0"
+ "_NET_WM_STATE_MODAL\0"
+ "_NET_WM_STATE_STAYS_ON_TOP\0"
+ "_NET_WM_STATE_DEMANDS_ATTENTION\0"
+
+ "_NET_WM_USER_TIME\0"
+ "_NET_WM_USER_TIME_WINDOW\0"
+ "_NET_WM_FULL_PLACEMENT\0"
+
+ "_NET_WM_WINDOW_TYPE\0"
+ "_NET_WM_WINDOW_TYPE_DESKTOP\0"
+ "_NET_WM_WINDOW_TYPE_DOCK\0"
+ "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
+ "_NET_WM_WINDOW_TYPE_MENU\0"
+ "_NET_WM_WINDOW_TYPE_UTILITY\0"
+ "_NET_WM_WINDOW_TYPE_SPLASH\0"
+ "_NET_WM_WINDOW_TYPE_DIALOG\0"
+ "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
+ "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
+ "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
+ "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
+ "_NET_WM_WINDOW_TYPE_COMBO\0"
+ "_NET_WM_WINDOW_TYPE_DND\0"
+ "_NET_WM_WINDOW_TYPE_NORMAL\0"
+ "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
+
+ "_KDE_NET_WM_FRAME_STRUT\0"
+
+ "_NET_STARTUP_INFO\0"
+ "_NET_STARTUP_INFO_BEGIN\0"
+
+ "_NET_SUPPORTING_WM_CHECK\0"
+
+ "_NET_WM_CM_S0\0"
+
+ "_NET_SYSTEM_TRAY_VISUAL\0"
+
+ // Property formats
+ "COMPOUND_TEXT\0"
+ "TEXT\0"
+ "UTF8_STRING\0"
+
+ // xdnd
+ "XdndEnter\0"
+ "XdndPosition\0"
+ "XdndStatus\0"
+ "XdndLeave\0"
+ "XdndDrop\0"
+ "XdndFinished\0"
+ "XdndTypeList\0"
+ "XdndActionList\0"
+
+ "XdndSelection\0"
+
+ "XdndAware\0"
+ "XdndProxy\0"
+
+ "XdndActionCopy\0"
+ "XdndActionLink\0"
+ "XdndActionMove\0"
+ "XdndActionPrivate\0"
+
+ // Motif DND
+ "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
+ "_MOTIF_DRAG_INITIATOR_INFO\0"
+ "_MOTIF_DRAG_RECEIVER_INFO\0"
+ "_MOTIF_DRAG_WINDOW\0"
+ "_MOTIF_DRAG_TARGETS\0"
+
+ "XmTRANSFER_SUCCESS\0"
+ "XmTRANSFER_FAILURE\0"
+
+ // Xkb
+ "_XKB_RULES_NAMES\0"
+
+ // XEMBED
+ "_XEMBED\0"
+ "_XEMBED_INFO\0"
+};
+
+Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
+
+/*****************************************************************************
+ Internal variables and functions
+ *****************************************************************************/
+static const char *appName = 0; // application name
+static const char *appClass = 0; // application class
+static const char *appFont = 0; // application font
+static const char *appBGCol = 0; // application bg color
+static const char *appFGCol = 0; // application fg color
+static const char *appBTNCol = 0; // application btn color
+static const char *mwGeometry = 0; // main widget geometry
+static const char *mwTitle = 0; // main widget title
+char *qt_ximServer = 0; // XIM Server will connect to
+static bool appSync = false; // X11 synchronization
+#if defined(QT_DEBUG)
+static bool appNoGrab = false; // X11 grabbing enabled
+static bool appDoGrab = false; // X11 grabbing override (gdb)
+#endif
+static bool app_save_rootinfo = false; // save root info
+static bool app_do_modal = false; // modal mode
+static Window curWin = 0; // current window
+
+
+// function to update the workarea of the screen - in qdesktopwidget_x11.cpp
+extern void qt_desktopwidget_update_workarea();
+
+// Function to change the window manager state (from qwidget_x11.cpp)
+extern void qt_change_net_wm_state(const QWidget *w, bool set, Atom one, Atom two = 0);
+
+// modifier masks for alt, meta, super, hyper, and mode_switch - detected when the application starts
+// and/or keyboard layout changes
+uchar qt_alt_mask = 0;
+uchar qt_meta_mask = 0;
+uchar qt_super_mask = 0;
+uchar qt_hyper_mask = 0;
+uchar qt_mode_switch_mask = 0;
+
+// flags for extensions for special Languages, currently only for RTL languages
+bool qt_use_rtl_extensions = false;
+
+static Window mouseActWindow = 0; // window where mouse is
+static Qt::MouseButton mouseButtonPressed = Qt::NoButton; // last mouse button pressed
+static Qt::MouseButtons mouseButtonState = Qt::NoButton; // mouse button state
+static Time mouseButtonPressTime = 0; // when was a button pressed
+static short mouseXPos, mouseYPos; // mouse pres position in act window
+static short mouseGlobalXPos, mouseGlobalYPos; // global mouse press position
+
+extern QWidgetList *qt_modal_stack; // stack of modal widgets
+
+// window where mouse buttons have been pressed
+static Window pressed_window = XNone;
+
+// popup control
+static bool replayPopupMouseEvent = false;
+static bool popupGrabOk;
+
+bool qt_sm_blockUserInput = false; // session management
+
+Q_GUI_EXPORT int qt_xfocusout_grab_counter = 0;
+
+#if !defined (QT_NO_TABLET)
+Q_GLOBAL_STATIC(QTabletDeviceDataList, tablet_devices)
+QTabletDeviceDataList *qt_tablet_devices()
+{
+ return tablet_devices();
+}
+
+extern bool qt_tabletChokeMouse;
+#endif
+
+static bool qt_x11EventFilter(XEvent* ev)
+{
+ long unused;
+ if (qApp->filterEvent(ev, &unused))
+ return true;
+ return qApp->x11EventFilter(ev);
+}
+
+#if !defined(QT_NO_XIM)
+XIMStyle qt_xim_preferred_style = 0;
+#endif
+int qt_ximComposingKeycode=0;
+QTextCodec * qt_input_mapper = 0;
+
+extern bool qt_check_clipboard_sentinel(); //def in qclipboard_x11.cpp
+extern bool qt_check_selection_sentinel(); //def in qclipboard_x11.cpp
+extern bool qt_xfixes_clipboard_changed(Window clipboardOwner, Time timestamp); //def in qclipboard_x11.cpp
+extern bool qt_xfixes_selection_changed(Window selectionOwner, Time timestamp); //def in qclipboard_x11.cpp
+
+static void qt_save_rootinfo();
+Q_GUI_EXPORT bool qt_try_modal(QWidget *, XEvent *);
+
+QWidget *qt_button_down = 0; // last widget to be pressed with the mouse
+QPointer<QWidget> qt_last_mouse_receiver = 0;
+static QWidget *qt_popup_down = 0; // popup that contains the pressed widget
+
+extern bool qt_xdnd_dragging;
+
+// gui or non-gui from qapplication.cpp
+extern bool qt_is_gui_used;
+
+/*!
+ \internal
+ Try to resolve a \a symbol from \a library with the version specified
+ by \a vernum.
+
+ Note that, in the case of the Xfixes library, \a vernum is not the same as
+ \c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes
+ version.
+*/
+static void* qt_load_library_runtime(const char *library, int vernum,
+ int highestVernum, const char *symbol)
+{
+ QList<int> versions;
+ // we try to load in the following order:
+ // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) )
+ if (vernum != -1)
+ versions << vernum;
+ versions << -1;
+ if (vernum != -1) {
+ for(int i = highestVernum; i > vernum; --i)
+ versions << i;
+ }
+ Q_FOREACH(int version, versions) {
+ QLatin1String libName(library);
+ QLibrary xfixesLib(libName, version);
+ if (xfixesLib.load()) {
+ void *ptr = xfixesLib.resolve(symbol);
+ if (ptr)
+ return ptr;
+ }
+ }
+ return 0;
+}
+
+#ifndef QT_NO_XINPUT
+# ifdef QT_RUNTIME_XINPUT
+# define XINPUT_LOAD_RUNTIME(vernum, symbol, symbol_type) \
+ (symbol_type)qt_load_library_runtime("libXi", vernum, 6, #symbol);
+# define XINPUT_LOAD(symbol) \
+ XINPUT_LOAD_RUNTIME(1, symbol, Ptr##symbol)
+# else // not runtime XInput
+# define XINPUT_LOAD(symbol) symbol
+# endif // QT_RUNTIME_XINPUT
+#else // not using Xinput at all
+# define XINPUT_LOAD(symbol) 0
+#endif // QT_NO_XINPUT
+
+#ifndef QT_NO_XFIXES
+# ifdef QT_RUNTIME_XFIXES
+# define XFIXES_LOAD_RUNTIME(vernum, symbol, symbol_type) \
+ (symbol_type)qt_load_library_runtime("libXfixes", vernum, 4, #symbol);
+# define XFIXES_LOAD_V1(symbol) \
+ XFIXES_LOAD_RUNTIME(1, symbol, Ptr##symbol)
+# define XFIXES_LOAD_V2(symbol) \
+ XFIXES_LOAD_RUNTIME(2, symbol, Ptr##symbol)
+
+# else // not runtime Xfixes
+
+# if XFIXES_MAJOR >= 2
+# define XFIXES_LOAD_V1(symbol) symbol
+# define XFIXES_LOAD_V2(symbol) symbol
+# elif XFIXES_MAJOR >= 1
+# define XFIXES_LOAD_V1(symbol) symbol
+# define XFIXES_LOAD_V2(symbol) 0
+# else
+# error Unsupported version of Xfixes
+# endif
+# endif // QT_RUNTIME_XFIXES
+#else // not using Xfixes at all
+# define XFIXES_LOAD_V1(symbol) 0
+# define XFIXES_LOAD_V2(symbol) 0
+#endif // QT_NO_XFIXES
+
+#ifndef QT_NO_XFIXES
+
+struct qt_xfixes_selection_event_data
+{
+ // which selection to filter out.
+ Atom selection;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
+{
+ qt_xfixes_selection_event_data *data =
+ reinterpret_cast<qt_xfixes_selection_event_data*>(arg);
+ if (event->type == X11->xfixes_eventbase + XFixesSelectionNotify) {
+ XFixesSelectionNotifyEvent *xfixes_event = reinterpret_cast<XFixesSelectionNotifyEvent*>(event);
+ if (xfixes_event->selection == data->selection)
+ return true;
+ }
+ return false;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+#endif // QT_NO_XFIXES
+
+class QETWidget : public QWidget // event translator widget
+{
+public:
+ bool translateMouseEvent(const XEvent *);
+ void translatePaintEvent(const XEvent *);
+ bool translateConfigEvent(const XEvent *);
+ bool translateCloseEvent(const XEvent *);
+ bool translateScrollDoneEvent(const XEvent *);
+ bool translateWheelEvent(int global_x, int global_y, int delta, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers, Qt::Orientation orient);
+#if !defined (QT_NO_TABLET)
+ bool translateXinputEvent(const XEvent*, QTabletDeviceData *tablet);
+#endif
+ bool translatePropertyEvent(const XEvent *);
+
+ void doDeferredMap()
+ {
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ if (!testAttribute(Qt::WA_Resized)) {
+ adjustSize();
+ setAttribute(Qt::WA_Resized, false);
+ }
+
+ /*
+ workaround for WM's that throw away ConfigureRequests from the following:
+
+ window->hide();
+ window->move(x, y); // could also be resize(), move()+resize(), or setGeometry()
+ window->show();
+ */
+ QRect r = geometry();
+
+ XMoveResizeWindow(X11->display,
+ internalWinId(),
+ r.x(),
+ r.y(),
+ r.width(),
+ r.height());
+
+ // static gravity!
+ XSizeHints sh;
+ long unused;
+ XGetWMNormalHints(X11->display, internalWinId(), &sh, &unused);
+ sh.flags |= USPosition | PPosition | USSize | PSize | PWinGravity;
+ sh.x = r.x();
+ sh.y = r.y();
+ sh.width = r.width();
+ sh.height = r.height();
+ sh.win_gravity = StaticGravity;
+ XSetWMNormalHints(X11->display, internalWinId(), &sh);
+
+ setAttribute(Qt::WA_Mapped);
+ if (testAttribute(Qt::WA_DontShowOnScreen))
+ return;
+ d_func()->topData()->waitingForMapNotify = 1;
+ XMapWindow(X11->display, internalWinId());
+ }
+};
+
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+#if !defined(QT_NO_GLIB)
+ if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
+ eventDispatcher = (q->type() != QApplication::Tty
+ ? new QGuiEventDispatcherGlib(q)
+ : new QEventDispatcherGlib(q));
+ else
+#endif
+ eventDispatcher = (q->type() != QApplication::Tty
+ ? new QEventDispatcherX11(q)
+ : new QEventDispatcherUNIX(q));
+}
+
+/*****************************************************************************
+ Default X error handlers
+ *****************************************************************************/
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static int (*original_x_errhandler)(Display *dpy, XErrorEvent *);
+static int (*original_xio_errhandler)(Display *dpy);
+
+static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
+{
+ switch (err->error_code) {
+ case BadAtom:
+ if (err->request_code == 20 /* X_GetProperty */
+ && (err->resourceid == XA_RESOURCE_MANAGER
+ || err->resourceid == XA_RGB_DEFAULT_MAP
+ || err->resourceid == ATOM(_NET_SUPPORTED)
+ || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK)
+ || err->resourceid == ATOM(KDE_FULL_SESSION)
+ || err->resourceid == ATOM(KWIN_RUNNING)
+ || err->resourceid == ATOM(XdndProxy)
+ || err->resourceid == ATOM(XdndAware))) {
+ // Perhaps we're running under SECURITY reduction? :/
+ return 0;
+ }
+ break;
+
+ case BadWindow:
+ if (err->request_code == 2 /* X_ChangeWindowAttributes */
+ || err->request_code == 38 /* X_QueryPointer */) {
+ for (int i = 0; i < ScreenCount(dpy); ++i) {
+ if (err->resourceid == RootWindow(dpy, i)) {
+ // Perhaps we're running under SECURITY reduction? :/
+ return 0;
+ }
+ }
+ }
+ X11->seen_badwindow = true;
+ if (err->request_code == 25 /* X_SendEvent */) {
+ for (int i = 0; i < ScreenCount(dpy); ++i) {
+ if (err->resourceid == RootWindow(dpy, i)) {
+ // Perhaps we're running under SECURITY reduction? :/
+ return 0;
+ }
+ }
+ if (X11->xdndHandleBadwindow()) {
+ qDebug("xdndHandleBadwindow returned true");
+ return 0;
+ }
+ }
+ if (X11->ignore_badwindow)
+ return 0;
+ break;
+
+ case BadMatch:
+ if (err->request_code == 42 /* X_SetInputFocus */)
+ return 0;
+ break;
+
+ default:
+ if (err->request_code == X11->xinput_major
+ && err->error_code == (X11->xinput_errorbase + XI_BadDevice)
+ && err->minor_code == 3 /* X_OpenDevice */) {
+ return 0;
+ }
+ break;
+ }
+
+ char errstr[256];
+ XGetErrorText( dpy, err->error_code, errstr, 256 );
+ char buffer[256];
+ char request_str[256];
+ qsnprintf(buffer, 256, "%d", err->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256);
+ if (err->request_code < 128) {
+ // X error for a normal protocol request
+ qWarning( "X Error: %s %d\n"
+ " Major opcode: %d (%s)\n"
+ " Resource id: 0x%lx",
+ errstr, err->error_code,
+ err->request_code,
+ request_str,
+ err->resourceid );
+ } else {
+ // X error for an extension request
+ const char *extensionName = 0;
+ if (err->request_code == X11->xrender_major)
+ extensionName = "RENDER";
+ else if (err->request_code == X11->xrandr_major)
+ extensionName = "RANDR";
+ else if (err->request_code == X11->xinput_major)
+ extensionName = "XInputExtension";
+ else if (err->request_code == X11->mitshm_major)
+ extensionName = "MIT-SHM";
+
+ char minor_str[256];
+ if (extensionName) {
+ qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code);
+ XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256);
+ } else {
+ extensionName = "Uknown extension";
+ qsnprintf(minor_str, 256, "Unknown request");
+ }
+ qWarning( "X Error: %s %d\n"
+ " Extension: %d (%s)\n"
+ " Minor opcode: %d (%s)\n"
+ " Resource id: 0x%lx",
+ errstr, err->error_code,
+ err->request_code,
+ extensionName,
+ err->minor_code,
+ minor_str,
+ err->resourceid );
+ }
+
+ // ### we really should distinguish between severe, non-severe and
+ // ### application specific errors
+
+ return 0;
+}
+
+
+static int qt_xio_errhandler(Display *)
+{
+ qWarning("%s: Fatal IO error: client killed", appName);
+ QApplicationPrivate::reset_instance_pointer();
+ exit(1);
+ //### give the application a chance for a proper shutdown instead,
+ //### exit(1) doesn't help.
+ return 0;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+
+static void qt_x11_create_intern_atoms()
+{
+ const char *names[QX11Data::NAtoms];
+ const char *ptr = x11_atomnames;
+
+ int i = 0;
+ while (*ptr) {
+ names[i++] = ptr;
+ while (*ptr)
+ ++ptr;
+ ++ptr;
+ }
+
+ Q_ASSERT(i == QX11Data::NPredefinedAtoms);
+
+ QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
+ settings_atom_name += XDisplayName(X11->displayName);
+ names[i++] = settings_atom_name;
+
+ Q_ASSERT(i == QX11Data::NAtoms);
+#if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6)
+ XInternAtoms(X11->display, (char **)names, i, False, X11->atoms);
+#else
+ for (i = 0; i < QX11Data::NAtoms; ++i)
+ X11->atoms[i] = XInternAtom(X11->display, (char *)names[i], False);
+#endif
+}
+
+Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
+{
+ QByteArray stamp;
+ QDataStream s(&stamp, QIODevice::WriteOnly);
+ s << QDateTime::currentDateTime();
+
+ XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0),
+ ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8,
+ PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
+}
+
+/*! \internal
+ Gets the current KDE 3 or 4 home path
+*/
+QString QApplicationPrivate::kdeHome()
+{
+ static QString kdeHomePath;
+ if (kdeHomePath.isEmpty()) {
+ kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
+ if (kdeHomePath.isEmpty()) {
+ int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
+ QDir homeDir(QDir::homePath());
+ QString kdeConfDir(QLatin1String("/.kde"));
+ if (4 == kdeSessionVersion && homeDir.exists(QLatin1String(".kde4")))
+ kdeConfDir = QLatin1String("/.kde4");
+ kdeHomePath = QDir::homePath() + kdeConfDir;
+ }
+ }
+ return kdeHomePath;
+}
+
+/*! \internal
+ apply the settings to the application
+*/
+bool QApplicationPrivate::x11_apply_settings()
+{
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+
+ settings.beginGroup(QLatin1String("Qt"));
+
+ /*
+ Qt settings. This is now they are written into the datastream.
+
+ Palette / * - QPalette
+ font - QFont
+ libraryPath - QStringList
+ style - QString
+ doubleClickInterval - int
+ keyboardInputInterval - int
+ cursorFlashTime - int
+ wheelScrollLines - int
+ colorSpec - QString
+ defaultCodec - QString
+ globalStrut/width - int
+ globalStrut/height - int
+ GUIEffects - QStringList
+ Font Substitutions/ * - QStringList
+ Font Substitutions/... - QStringList
+ */
+
+ QStringList strlist;
+ int i;
+ QPalette pal(Qt::black);
+ int groupCount = 0;
+ strlist = settings.value(QLatin1String("Palette/active")).toStringList();
+ if (!strlist.isEmpty()) {
+ ++groupCount;
+ for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
+ pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+ strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
+ if (!strlist.isEmpty()) {
+ ++groupCount;
+ for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
+ pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+ strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
+ if (!strlist.isEmpty()) {
+ ++groupCount;
+ for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
+ pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
+ QColor(strlist[i]));
+ }
+
+ if (groupCount == QPalette::NColorGroups)
+ QApplicationPrivate::setSystemPalette(pal);
+
+ int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
+
+ if (!appFont) {
+ QFont font(QApplication::font());
+ QString fontDescription;
+ // Override Qt font if KDE4 settings can be used
+ if (4 == kdeSessionVersion) {
+ QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ fontDescription = kdeSettings.value(QLatin1String("font")).toString();
+ if (fontDescription.isEmpty()) {
+ // KDE stores fonts without quotes
+ fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(","));
+ }
+ }
+ if (fontDescription.isEmpty())
+ fontDescription = settings.value(QLatin1String("font")).toString();
+ if (!fontDescription .isEmpty()) {
+ font.fromString(fontDescription );
+ QApplicationPrivate::setSystemFont(font);
+ }
+ }
+
+ // read library (ie. plugin) path list
+ QString libpathkey =
+ QString::fromLatin1("%1.%2/libraryPath")
+ .arg(QT_VERSION >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8);
+ QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
+ if (! pathlist.isEmpty()) {
+ QStringList::ConstIterator it = pathlist.constBegin();
+ while (it != pathlist.constEnd())
+ QApplication::addLibraryPath(*it++);
+ }
+
+ // read new QStyle
+ QString stylename = settings.value(QLatin1String("style")).toString();
+ if (stylename.isEmpty() && !QApplicationPrivate::styleOverride && X11->use_xrender) {
+ QStringList availableStyles = QStyleFactory::keys();
+ // Override Qt style if KDE4 settings can be used
+ if (4 == kdeSessionVersion) {
+ QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ QString kde4Style = kdeSettings.value(QLatin1String("widgetStyle"),
+ QLatin1String("Oxygen")).toString();
+ foreach (const QString &style, availableStyles) {
+ if (style.toLower() == kde4Style.toLower())
+ stylename = kde4Style;
+ }
+ // Set QGtkStyle for GNOME
+ } else if (X11->desktopEnvironment == DE_GNOME) {
+ QString gtkStyleKey = QString::fromLatin1("GTK+");
+ if (availableStyles.contains(gtkStyleKey))
+ stylename = gtkStyleKey;
+ }
+ }
+
+ if (QCoreApplication::startingUp()) {
+ if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
+ QApplicationPrivate::styleOverride = new QString(stylename);
+ } else {
+ QApplication::setStyle(stylename);
+ }
+
+ int num =
+ settings.value(QLatin1String("doubleClickInterval"),
+ QApplication::doubleClickInterval()).toInt();
+ QApplication::setDoubleClickInterval(num);
+
+ num =
+ settings.value(QLatin1String("cursorFlashTime"),
+ QApplication::cursorFlashTime()).toInt();
+ QApplication::setCursorFlashTime(num);
+
+ num =
+ settings.value(QLatin1String("wheelScrollLines"),
+ QApplication::wheelScrollLines()).toInt();
+ QApplication::setWheelScrollLines(num);
+
+ QString colorspec = settings.value(QLatin1String("colorSpec"),
+ QVariant(QLatin1String("default"))).toString();
+ if (colorspec == QLatin1String("normal"))
+ QApplication::setColorSpec(QApplication::NormalColor);
+ else if (colorspec == QLatin1String("custom"))
+ QApplication::setColorSpec(QApplication::CustomColor);
+ else if (colorspec == QLatin1String("many"))
+ QApplication::setColorSpec(QApplication::ManyColor);
+ else if (colorspec != QLatin1String("default"))
+ colorspec = QLatin1String("default");
+
+ QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
+ QVariant(QLatin1String("none"))).toString();
+ if (defaultcodec != QLatin1String("none")) {
+ QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
+ if (codec)
+ QTextCodec::setCodecForTr(codec);
+ }
+
+ int w = settings.value(QLatin1String("globalStrut/width")).toInt();
+ int h = settings.value(QLatin1String("globalStrut/height")).toInt();
+ QSize strut(w, h);
+ if (strut.isValid())
+ QApplication::setGlobalStrut(strut);
+
+ QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
+ QApplication::setEffectEnabled(Qt::UI_General,
+ effects.contains(QLatin1String("general")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
+ effects.contains(QLatin1String("animatemenu")));
+ QApplication::setEffectEnabled(Qt::UI_FadeMenu,
+ effects.contains(QLatin1String("fademenu")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
+ effects.contains(QLatin1String("animatecombo")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
+ effects.contains(QLatin1String("animatetooltip")));
+ QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
+ effects.contains(QLatin1String("fadetooltip")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
+ effects.contains(QLatin1String("animatetoolbox")));
+
+ if (!X11->has_fontconfig) {
+ settings.beginGroup(QLatin1String("Font Substitutions"));
+ QStringList fontsubs = settings.childKeys();
+ if (!fontsubs.isEmpty()) {
+ QStringList::Iterator it = fontsubs.begin();
+ for (; it != fontsubs.end(); ++it) {
+ QString fam = *it;
+ QStringList subs = settings.value(fam).toStringList();
+ QFont::insertSubstitutions(fam, subs);
+ }
+ }
+ settings.endGroup();
+ }
+
+ qt_use_rtl_extensions =
+ settings.value(QLatin1String("useRtlExtensions"), false).toBool();
+
+#ifndef QT_NO_XIM
+ if (qt_xim_preferred_style == 0) {
+ QString ximInputStyle = settings.value(QLatin1String("XIMInputStyle"),
+ QVariant(QLatin1String("on the spot"))).toString().toLower();
+ if (ximInputStyle == QLatin1String("on the spot"))
+ qt_xim_preferred_style = XIMPreeditCallbacks | XIMStatusNothing;
+ else if (ximInputStyle == QLatin1String("over the spot"))
+ qt_xim_preferred_style = XIMPreeditPosition | XIMStatusNothing;
+ else if (ximInputStyle == QLatin1String("off the spot"))
+ qt_xim_preferred_style = XIMPreeditArea | XIMStatusArea;
+ else if (ximInputStyle == QLatin1String("root"))
+ qt_xim_preferred_style = XIMPreeditNothing | XIMStatusNothing;
+ }
+#endif
+ QStringList inputMethods = QInputContextFactory::keys();
+ if (inputMethods.size() > 2 && inputMethods.contains(QLatin1String("imsw-multi"))) {
+ X11->default_im = QLatin1String("imsw-multi");
+ } else {
+ X11->default_im = settings.value(QLatin1String("DefaultInputMethod"),
+ QLatin1String("xim")).toString();
+ }
+
+ settings.endGroup(); // Qt
+
+ return true;
+}
+
+
+/*! \internal
+ Resets the QApplication::instance() pointer to zero
+*/
+void QApplicationPrivate::reset_instance_pointer()
+{ QApplication::self = 0; }
+
+
+// read the _QT_INPUT_ENCODING property and apply the settings to
+// the application
+static void qt_set_input_encoding()
+{
+ Atom type;
+ int format;
+ ulong nitems, after = 1;
+ unsigned char *data = 0;
+
+ int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_QT_INPUT_ENCODING), 0, 1024,
+ False, XA_STRING, &type, &format, &nitems,
+ &after, &data);
+ if (e != Success || !nitems || type == XNone) {
+ // Always use the locale codec, since we have no examples of non-local
+ // XIMs, and since we cannot get a sensible answer about the encoding
+ // from the XIM.
+ qt_input_mapper = QTextCodec::codecForLocale();
+
+ } else {
+ if (!qstricmp((char *)data, "locale"))
+ qt_input_mapper = QTextCodec::codecForLocale();
+ else
+ qt_input_mapper = QTextCodec::codecForName((char *)data);
+ // make sure we have an input codec
+ if(!qt_input_mapper)
+ qt_input_mapper = QTextCodec::codecForName("ISO 8859-1");
+ }
+ if (qt_input_mapper && qt_input_mapper->mibEnum() == 11) // 8859-8
+ qt_input_mapper = QTextCodec::codecForName("ISO 8859-8-I");
+ if(data)
+ XFree((char *)data);
+}
+
+// Reads a KDE color setting
+static QColor kdeColor(const QString &key)
+{
+ QSettings kdeSettings(QApplicationPrivate::kdeHome() +
+ QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ QVariant variant = kdeSettings.value(key);
+ if (variant.isValid()) {
+ QStringList values = variant.toStringList();
+ if (values.size() == 3) {
+ int r = values[0].toInt();
+ int g = values[1].toInt();
+ int b = values[2].toInt();
+ return QColor(r, g, b);
+ }
+ }
+ return QColor();
+}
+
+// set font, foreground and background from x11 resources. The
+// arguments may override the resource settings.
+static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
+ const char* bg = 0, const char* button = 0)
+{
+
+ QString resFont, resFG, resBG, resButton, resEF, sysFont, selectBackground, selectForeground;
+
+ QApplication::setEffectEnabled(Qt::UI_General, false);
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
+ QApplication::setEffectEnabled(Qt::UI_FadeMenu, false);
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
+ QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, false);
+ QApplication::setEffectEnabled(Qt::UI_FadeTooltip, false);
+ QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, false);
+
+ bool paletteAlreadySet = false;
+ if (QApplication::desktopSettingsAware()) {
+ // first, read from settings
+ QApplicationPrivate::x11_apply_settings();
+
+ // the call to QApplication::style() below creates the system
+ // palette, which breaks the logic after the RESOURCE_MANAGER
+ // loop... so I have to save this value to be able to use it later
+ paletteAlreadySet = (QApplicationPrivate::sys_pal != 0);
+
+ // second, parse the RESOURCE_MANAGER property
+ int format;
+ ulong nitems, after = 1;
+ QString res;
+ long offset = 0;
+ Atom type = XNone;
+
+ while (after > 0) {
+ uchar *data = 0;
+ if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(0),
+ ATOM(RESOURCE_MANAGER),
+ offset, 8192, False, AnyPropertyType,
+ &type, &format, &nitems, &after,
+ &data) != Success) {
+ res = QString();
+ break;
+ }
+ if (type == XA_STRING)
+ res += QString::fromLatin1((char*)data);
+ else
+ res += QString::fromLocal8Bit((char*)data);
+ offset += 2048; // offset is in 32bit quantities... 8192/4 == 2048
+ if (data)
+ XFree((char *)data);
+ }
+
+ QString key, value;
+ int l = 0, r;
+ QString apn = QString::fromLocal8Bit(appName);
+ QString apc = QString::fromLocal8Bit(appClass);
+ int apnl = apn.length();
+ int apcl = apc.length();
+ int resl = res.length();
+
+ while (l < resl) {
+ r = res.indexOf(QLatin1Char('\n'), l);
+ if (r < 0)
+ r = resl;
+ while (res.at(l).isSpace())
+ l++;
+ bool mine = false;
+ QChar sc = res.at(l + 1);
+ if (res.at(l) == QLatin1Char('*') &&
+ (sc == QLatin1Char('f') || sc == QLatin1Char('b') || sc == QLatin1Char('g') ||
+ sc == QLatin1Char('F') || sc == QLatin1Char('B') || sc == QLatin1Char('G') ||
+ sc == QLatin1Char('s') || sc == QLatin1Char('S')
+ // capital T only, since we're looking for "Text.selectSomething"
+ || sc == QLatin1Char('T'))) {
+ // OPTIMIZED, since we only want "*[fbgsT].."
+ QString item = res.mid(l, r - l).simplified();
+ int i = item.indexOf(QLatin1Char(':'));
+ key = item.left(i).trimmed().mid(1).toLower();
+ value = item.right(item.length() - i - 1).trimmed();
+ mine = true;
+ } else if ((apnl && res.at(l) == apn.at(0)) || (appClass && apcl && res.at(l) == apc.at(0))) {
+ if (res.mid(l,apnl) == apn && (res.at(l+apnl) == QLatin1Char('.')
+ || res.at(l+apnl) == QLatin1Char('*'))) {
+ QString item = res.mid(l, r - l).simplified();
+ int i = item.indexOf(QLatin1Char(':'));
+ key = item.left(i).trimmed().mid(apnl+1).toLower();
+ value = item.right(item.length() - i - 1).trimmed();
+ mine = true;
+ } else if (res.mid(l,apcl) == apc && (res.at(l+apcl) == QLatin1Char('.')
+ || res.at(l+apcl) == QLatin1Char('*'))) {
+ QString item = res.mid(l, r - l).simplified();
+ int i = item.indexOf(QLatin1Char(':'));
+ key = item.left(i).trimmed().mid(apcl+1).toLower();
+ value = item.right(item.length() - i - 1).trimmed();
+ mine = true;
+ }
+ }
+
+ if (mine) {
+ if (!font && key == QLatin1String("systemfont"))
+ sysFont = value.left(value.lastIndexOf(QLatin1Char(':')));
+ if (!font && key == QLatin1String("font"))
+ resFont = value;
+ else if (!fg && !paletteAlreadySet) {
+ if (key == QLatin1String("foreground"))
+ resFG = value;
+ else if (!bg && key == QLatin1String("background"))
+ resBG = value;
+ else if (!bg && !button && key == QLatin1String("button.background"))
+ resButton = value;
+ else if (key == QLatin1String("text.selectbackground")) {
+ selectBackground = value;
+ } else if (key == QLatin1String("text.selectforeground")) {
+ selectForeground = value;
+ }
+ } else if (key == QLatin1String("guieffects"))
+ resEF = value;
+ // NOTE: if you add more, change the [fbg] stuff above
+ }
+
+ l = r + 1;
+ }
+ }
+ if (!sysFont.isEmpty())
+ resFont = sysFont;
+ if (resFont.isEmpty())
+ resFont = QString::fromLocal8Bit(font);
+ if (resFG.isEmpty())
+ resFG = QString::fromLocal8Bit(fg);
+ if (resBG.isEmpty())
+ resBG = QString::fromLocal8Bit(bg);
+ if (resButton.isEmpty())
+ resButton = QString::fromLocal8Bit(button);
+ if (!resFont.isEmpty()
+ && !X11->has_fontconfig
+ && !QApplicationPrivate::sys_font) {
+ // set application font
+ QFont fnt;
+ fnt.setRawName(resFont);
+
+ // the font we get may actually be an alias for another font,
+ // so we reset the application font to the real font info.
+ if (! fnt.exactMatch()) {
+ QFontInfo fontinfo(fnt);
+ fnt.setFamily(fontinfo.family());
+ fnt.setRawMode(fontinfo.rawMode());
+
+ if (! fnt.rawMode()) {
+ fnt.setItalic(fontinfo.italic());
+ fnt.setWeight(fontinfo.weight());
+ fnt.setUnderline(fontinfo.underline());
+ fnt.setStrikeOut(fontinfo.strikeOut());
+ fnt.setStyleHint(fontinfo.styleHint());
+
+ if (fnt.pointSize() <= 0 && fnt.pixelSize() <= 0) {
+ // size is all wrong... fix it
+ qreal pointSize = fontinfo.pixelSize() * 72. / (float) QX11Info::appDpiY();
+ if (pointSize <= 0)
+ pointSize = 12;
+ fnt.setPointSize(qRound(pointSize));
+ }
+ }
+ }
+
+ QApplicationPrivate::setSystemFont(fnt);
+ }
+ bool kdeColors = (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE);
+
+ if (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty())) {// set app colors
+ bool allowX11ColorNames = QColor::allowX11ColorNames();
+ QColor::setAllowX11ColorNames(true);
+
+ (void) QApplication::style(); // trigger creation of application style and system palettes
+ QColor btn;
+ QColor bg;
+ QColor fg;
+ QColor bfg;
+ QColor wfg;
+ if (!resBG.isEmpty())
+ bg = QColor(resBG);
+ if (!bg.isValid())
+ bg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Window);
+
+ if (!resFG.isEmpty())
+ fg = QColor(resFG);
+ if (!fg.isValid())
+ fg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::WindowText);
+
+ if (!resButton.isEmpty())
+ btn = QColor(resButton);
+ else if (!resBG.isEmpty())
+ btn = bg;
+ if (!btn.isValid())
+ btn = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Button);
+
+ int h,s,v;
+ fg.getHsv(&h,&s,&v);
+ QColor base = Qt::white;
+ bool bright_mode = false;
+ if (v >= 255 - 50) {
+ base = btn.darker(150);
+ bright_mode = true;
+ }
+
+ if (kdeColors) {
+ // Setup KDE palette
+ QColor color;
+ color = kdeColor(QLatin1String("buttonBackground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"));
+ if (color.isValid())
+ btn = color;
+
+ color = kdeColor(QLatin1String("background"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"));
+ if (color.isValid())
+ bg = color;
+
+ color = kdeColor(QLatin1String("foreground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"));
+ if (color.isValid()) {
+ fg = color;
+ }
+
+ color = kdeColor(QLatin1String("windowForeground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"));
+ if (color.isValid())
+ wfg = color;
+
+ color = kdeColor(QLatin1String("windowBackground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"));
+ if (color.isValid())
+ base = color;
+ }
+
+ QPalette pal(fg, btn, btn.lighter(125), btn.darker(130), btn.darker(120), wfg.isValid() ? wfg : fg, Qt::white, base, bg);
+ QColor disabled((fg.red() + btn.red()) / 2,
+ (fg.green() + btn.green())/ 2,
+ (fg.blue() + btn.blue()) / 2);
+ pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.lighter(125),
+ btn.darker(130), btn.darker(150), disabled, Qt::white, Qt::white, bg);
+
+ QColor highlight, highlightText;
+ if (!selectBackground.isEmpty() && !selectForeground.isEmpty()) {
+ highlight = QColor(selectBackground);
+ highlightText = QColor(selectForeground);
+ }
+ // Use KDE3 or KDE4 color settings if present
+ if (kdeColors) {
+ QColor color = kdeColor(QLatin1String("selectBackground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"));
+ if (color.isValid())
+ highlight = color;
+
+ color = kdeColor(QLatin1String("selectForeground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"));
+ if (color.isValid())
+ highlightText = color;
+
+ color = kdeColor(QLatin1String("alternateBackground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"));
+ if (color.isValid())
+ pal.setColor(QPalette::AlternateBase, color);
+ else
+ pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
+
+ color = kdeColor(QLatin1String("buttonForeground"));
+ if (!color.isValid())
+ color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"));
+ if (color.isValid())
+ pal.setColor(QPalette::ButtonText, color);
+ }
+
+ if (highlight.isValid() && highlightText.isValid()) {
+ pal.setColor(QPalette::Highlight, highlight);
+ pal.setColor(QPalette::HighlightedText, highlightText);
+
+ // calculate disabled colors by removing saturation
+ highlight.setHsv(highlight.hue(), 0, highlight.value(), highlight.alpha());
+ highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha());
+ pal.setColor(QPalette::Disabled, QPalette::Highlight, highlight);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText);
+ } else if (bright_mode) {
+ pal.setColor(QPalette::HighlightedText, base);
+ pal.setColor(QPalette::Highlight, Qt::white);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base);
+ pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white);
+ } else {
+ pal.setColor(QPalette::HighlightedText, Qt::white);
+ pal.setColor(QPalette::Highlight, Qt::darkBlue);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white);
+ pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
+ }
+
+ QApplicationPrivate::setSystemPalette(pal);
+
+ QColor::setAllowX11ColorNames(allowX11ColorNames);
+ }
+
+ if (!resEF.isEmpty()) {
+ QStringList effects = resEF.split(QLatin1Char(' '));
+ QApplication::setEffectEnabled(Qt::UI_General, effects.contains(QLatin1String("general")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
+ effects.contains(QLatin1String("animatemenu")));
+ QApplication::setEffectEnabled(Qt::UI_FadeMenu,
+ effects.contains(QLatin1String("fademenu")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
+ effects.contains(QLatin1String("animatecombo")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
+ effects.contains(QLatin1String("animatetooltip")));
+ QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
+ effects.contains(QLatin1String("fadetooltip")));
+ QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
+ effects.contains(QLatin1String("animatetoolbox")));
+ }
+}
+
+
+// update the supported array
+static void qt_get_net_supported()
+{
+ Atom type;
+ int format;
+ long offset = 0;
+ unsigned long nitems, after;
+ unsigned char *data = 0;
+
+ int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_NET_SUPPORTED), 0, 0,
+ False, XA_ATOM, &type, &format, &nitems, &after, &data);
+ if (data)
+ XFree(data);
+
+ if (X11->net_supported_list)
+ delete [] X11->net_supported_list;
+ X11->net_supported_list = 0;
+
+ if (e == Success && type == XA_ATOM && format == 32) {
+ QBuffer ts;
+ ts.open(QIODevice::WriteOnly);
+
+ while (after > 0) {
+ XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_NET_SUPPORTED), offset, 1024,
+ False, XA_ATOM, &type, &format, &nitems, &after, &data);
+
+ if (type == XA_ATOM && format == 32) {
+ ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long));
+ offset += nitems;
+ } else
+ after = 0;
+ if (data)
+ XFree(data);
+ }
+
+ // compute nitems
+ QByteArray buffer(ts.buffer());
+ nitems = buffer.size() / sizeof(Atom);
+ X11->net_supported_list = new Atom[nitems + 1];
+ Atom *a = (Atom *) buffer.data();
+ uint i;
+ for (i = 0; i < nitems; i++)
+ X11->net_supported_list[i] = a[i];
+ X11->net_supported_list[nitems] = 0;
+ }
+}
+
+
+bool QX11Data::isSupportedByWM(Atom atom)
+{
+ if (!X11->net_supported_list)
+ return false;
+
+ bool supported = false;
+ int i = 0;
+ while (X11->net_supported_list[i] != 0) {
+ if (X11->net_supported_list[i++] == atom) {
+ supported = true;
+ break;
+ }
+ }
+
+ return supported;
+}
+
+
+// update the virtual roots array
+static void qt_get_net_virtual_roots()
+{
+ if (X11->net_virtual_root_list)
+ delete [] X11->net_virtual_root_list;
+ X11->net_virtual_root_list = 0;
+
+ if (!X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)))
+ return;
+
+ Atom type;
+ int format;
+ long offset = 0;
+ unsigned long nitems, after;
+ unsigned char *data;
+
+ int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_NET_VIRTUAL_ROOTS), 0, 0,
+ False, XA_ATOM, &type, &format, &nitems, &after, &data);
+ if (data)
+ XFree(data);
+
+ if (e == Success && type == XA_ATOM && format == 32) {
+ QBuffer ts;
+ ts.open(QIODevice::WriteOnly);
+
+ while (after > 0) {
+ XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_NET_VIRTUAL_ROOTS), offset, 1024,
+ False, XA_ATOM, &type, &format, &nitems, &after, &data);
+
+ if (type == XA_ATOM && format == 32) {
+ ts.write(reinterpret_cast<char *>(data), nitems * 4);
+ offset += nitems;
+ } else
+ after = 0;
+ if (data)
+ XFree(data);
+ }
+
+ // compute nitems
+ QByteArray buffer(ts.buffer());
+ nitems = buffer.size() / sizeof(Window);
+ X11->net_virtual_root_list = new Window[nitems + 1];
+ Window *a = (Window *) buffer.data();
+ uint i;
+ for (i = 0; i < nitems; i++)
+ X11->net_virtual_root_list[i] = a[i];
+ X11->net_virtual_root_list[nitems] = 0;
+ }
+}
+
+void qt_net_remove_user_time(QWidget *tlw)
+{
+ Q_ASSERT(tlw);
+ QTLWExtra *extra = tlw->d_func()->maybeTopData();
+ if (extra && extra->userTimeWindow) {
+ Q_ASSERT(tlw->internalWinId());
+ XDeleteProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME_WINDOW));
+ XDestroyWindow(X11->display, extra->userTimeWindow);
+ extra->userTimeWindow = 0;
+ }
+}
+
+void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp)
+{
+ Q_ASSERT(tlw);
+ Q_ASSERT(tlw->isWindow());
+ Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *extra = tlw->d_func()->topData();
+ WId wid = tlw->internalWinId();
+ const bool isSupportedByWM = X11->isSupportedByWM(ATOM(_NET_WM_USER_TIME_WINDOW));
+ if (extra->userTimeWindow || isSupportedByWM) {
+ if (!extra->userTimeWindow) {
+ extra->userTimeWindow = XCreateSimpleWindow(X11->display,
+ tlw->internalWinId(),
+ -1, -1, 1, 1, 0, 0, 0);
+ wid = extra->userTimeWindow;
+ XChangeProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME_WINDOW),
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)&wid, 1);
+ XDeleteProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME));
+ } else if (!isSupportedByWM) {
+ // WM no longer supports it, then we should remove the
+ // _NET_WM_USER_TIME_WINDOW atom.
+ qt_net_remove_user_time(tlw);
+ } else {
+ wid = extra->userTimeWindow;
+ }
+ }
+ XChangeProperty(X11->display, wid, ATOM(_NET_WM_USER_TIME),
+ XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &timestamp, 1);
+}
+
+static void qt_check_focus_model()
+{
+ Window fw = XNone;
+ int unused;
+ XGetInputFocus(X11->display, &fw, &unused);
+ if (fw == PointerRoot)
+ X11->focus_model = QX11Data::FM_PointerRoot;
+ else
+ X11->focus_model = QX11Data::FM_Other;
+}
+
+#ifndef QT_NO_TABLET
+
+#if !defined (Q_OS_IRIX)
+// from include/Xwacom.h
+# define XWACOM_PARAM_TOOLID 322
+# define XWACOM_PARAM_TOOLSERIAL 323
+
+typedef WACOMCONFIG * (*PtrWacomConfigInit) (Display*, WACOMERRORFUNC);
+typedef WACOMDEVICE * (*PtrWacomConfigOpenDevice) (WACOMCONFIG*, const char*);
+typedef int *(*PtrWacomConfigGetRawParam) (WACOMDEVICE*, int, int*, int, unsigned*);
+typedef int (*PtrWacomConfigCloseDevice) (WACOMDEVICE *);
+typedef void (*PtrWacomConfigTerm) (WACOMCONFIG *);
+
+static PtrWacomConfigInit ptrWacomConfigInit = 0;
+static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0;
+static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0;
+static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0;
+static PtrWacomConfigTerm ptrWacomConfigTerm = 0;
+#endif
+
+#endif
+
+/*****************************************************************************
+ qt_init() - initializes Qt for X11
+ *****************************************************************************/
+
+#if !defined(QT_NO_FONTCONFIG)
+static void getXDefault(const char *group, const char *key, int *val)
+{
+ char *str = XGetDefault(X11->display, group, key);
+ if (str) {
+ char *end = 0;
+ int v = strtol(str, &end, 0);
+ if (str != end)
+ *val = v;
+ }
+}
+
+static void getXDefault(const char *group, const char *key, double *val)
+{
+ char *str = XGetDefault(X11->display, group, key);
+ if (str) {
+ bool ok;
+ double v = QByteArray(str).toDouble(&ok);
+ if (ok)
+ *val = v;
+ }
+}
+
+static void getXDefault(const char *group, const char *key, bool *val)
+{
+ char *str = XGetDefault(X11->display, group, key);
+ if (str) {
+ char c = str[0];
+ if (isupper((int)c))
+ c = tolower(c);
+ if (c == 't' || c == 'y' || c == '1')
+ *val = true;
+ else if (c == 'f' || c == 'n' || c == '0')
+ *val = false;
+ if (c == 'o') {
+ c = str[1];
+ if (isupper((int)c))
+ c = tolower(c);
+ if (c == 'n')
+ *val = true;
+ if (c == 'f')
+ *val = false;
+ }
+ }
+}
+#endif
+
+// ### This should be static but it isn't because of the friend declaration
+// ### in qpaintdevice.h which then should have a static too but can't have
+// ### it because "storage class specifiers invalid in friend function
+// ### declarations" :-) Ideas anyone?
+void qt_init(QApplicationPrivate *priv, int,
+ Display *display, Qt::HANDLE visual, Qt::HANDLE colormap)
+{
+ X11 = new QX11Data;
+ X11->display = display;
+ X11->displayName = 0;
+ X11->foreignDisplay = (display != 0);
+ X11->focus_model = -1;
+
+ // RANDR
+ X11->use_xrandr = false;
+ X11->xrandr_major = 0;
+ X11->xrandr_eventbase = 0;
+ X11->xrandr_errorbase = 0;
+
+ // RENDER
+ X11->use_xrender = false;
+ X11->xrender_major = 0;
+ X11->xrender_version = 0;
+
+ // XFIXES
+ X11->use_xfixes = false;
+ X11->xfixes_major = 0;
+ X11->xfixes_eventbase = 0;
+ X11->xfixes_errorbase = 0;
+
+ // XInputExtension
+ X11->use_xinput = false;
+ X11->xinput_major = 0;
+ X11->xinput_eventbase = 0;
+ X11->xinput_errorbase = 0;
+
+ // MIT-SHM
+ X11->use_mitshm = false;
+ X11->mitshm_major = 0;
+
+ X11->sip_serial = 0;
+ X11->net_supported_list = 0;
+ X11->net_virtual_root_list = 0;
+ X11->wm_client_leader = 0;
+ X11->screens = 0;
+ X11->argbVisuals = 0;
+ X11->argbColormaps = 0;
+ X11->screenCount = 0;
+ X11->time = CurrentTime;
+ X11->userTime = CurrentTime;
+ X11->ignore_badwindow = false;
+ X11->seen_badwindow = false;
+
+ X11->motifdnd_active = false;
+
+ X11->default_im = QLatin1String("imsw-multi");
+ priv->inputContext = 0;
+
+ // colormap control
+ X11->visual_class = -1;
+ X11->visual_id = -1;
+ X11->color_count = 0;
+ X11->custom_cmap = false;
+
+ // outside visual/colormap
+ X11->visual = reinterpret_cast<Visual *>(visual);
+ X11->colormap = colormap;
+
+ // Fontconfig
+ X11->has_fontconfig = false;
+#if !defined(QT_NO_FONTCONFIG)
+ if (qgetenv("QT_X11_NO_FONTCONFIG").isNull())
+ X11->has_fontconfig = FcInit();
+ X11->fc_antialias = true;
+#endif
+
+#ifndef QT_NO_XRENDER
+ memset(X11->solid_fills, 0, sizeof(X11->solid_fills));
+ for (int i = 0; i < X11->solid_fill_count; ++i)
+ X11->solid_fills[i].screen = -1;
+ memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills));
+ for (int i = 0; i < X11->pattern_fill_count; ++i)
+ X11->pattern_fills[i].screen = -1;
+#endif
+
+ X11->startupId = X11->originalStartupId = 0;
+
+ int argc = priv->argc;
+ char **argv = priv->argv;
+
+ if (X11->display) {
+ // Qt part of other application
+
+ // Set application name and class
+ appName = qstrdup("Qt-subapplication");
+ char *app_class = 0;
+ if (argv) {
+ const char* p = strrchr(argv[0], '/');
+ app_class = qstrdup(p ? p + 1 : argv[0]);
+ if (app_class[0])
+ app_class[0] = toupper(app_class[0]);
+ }
+ appClass = app_class;
+ } else {
+ // Qt controls everything (default)
+
+ // Set application name and class
+ char *app_class = 0;
+ if (argv && argv[0]) {
+ const char *p = strrchr(argv[0], '/');
+ appName = p ? p + 1 : argv[0];
+ app_class = qstrdup(appName);
+ if (app_class[0])
+ app_class[0] = toupper(app_class[0]);
+ }
+ appClass = app_class;
+ }
+
+ // Install default error handlers
+ original_x_errhandler = XSetErrorHandler(qt_x_errhandler);
+ original_xio_errhandler = XSetIOErrorHandler(qt_xio_errhandler);
+
+ // Get command line params
+ int j = argc ? 1 : 0;
+ for (int i=1; i<argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QByteArray arg(argv[i]);
+ if (arg == "-display") {
+ if (++i < argc && !X11->display)
+ X11->displayName = argv[i];
+ } else if (arg == "-fn" || arg == "-font") {
+ if (++i < argc)
+ appFont = argv[i];
+ } else if (arg == "-bg" || arg == "-background") {
+ if (++i < argc)
+ appBGCol = argv[i];
+ } else if (arg == "-btn" || arg == "-button") {
+ if (++i < argc)
+ appBTNCol = argv[i];
+ } else if (arg == "-fg" || arg == "-foreground") {
+ if (++i < argc)
+ appFGCol = argv[i];
+ } else if (arg == "-name") {
+ if (++i < argc)
+ appName = argv[i];
+ } else if (arg == "-title") {
+ if (++i < argc)
+ mwTitle = argv[i];
+ } else if (arg == "-geometry") {
+ if (++i < argc)
+ mwGeometry = argv[i];
+ } else if (arg == "-im") {
+ if (++i < argc)
+ qt_ximServer = argv[i];
+ } else if (arg == "-ncols") { // xv and netscape use this name
+ if (++i < argc)
+ X11->color_count = qMax(0,atoi(argv[i]));
+ } else if (arg == "-visual") { // xv and netscape use this name
+ if (++i < argc && !X11->visual) {
+ QString s = QString::fromLocal8Bit(argv[i]).toLower();
+ if (s == QLatin1String("staticgray"))
+ X11->visual_class = StaticGray;
+ else if (s == QLatin1String("grayscale"))
+ X11->visual_class = XGrayScale;
+ else if (s == QLatin1String("staticcolor"))
+ X11->visual_class = StaticColor;
+ else if (s == QLatin1String("pseudocolor"))
+ X11->visual_class = PseudoColor;
+ else if (s == QLatin1String("truecolor"))
+ X11->visual_class = TrueColor;
+ else if (s == QLatin1String("directcolor"))
+ X11->visual_class = DirectColor;
+ else
+ X11->visual_id = static_cast<int>(strtol(argv[i], 0, 0));
+ }
+#ifndef QT_NO_XIM
+ } else if (arg == "-inputstyle") {
+ if (++i < argc) {
+ QString s = QString::fromLocal8Bit(argv[i]).toLower();
+ if (s == QLatin1String("onthespot"))
+ qt_xim_preferred_style = XIMPreeditCallbacks |
+ XIMStatusNothing;
+ else if (s == QLatin1String("overthespot"))
+ qt_xim_preferred_style = XIMPreeditPosition |
+ XIMStatusNothing;
+ else if (s == QLatin1String("offthespot"))
+ qt_xim_preferred_style = XIMPreeditArea |
+ XIMStatusArea;
+ else if (s == QLatin1String("root"))
+ qt_xim_preferred_style = XIMPreeditNothing |
+ XIMStatusNothing;
+ }
+#endif
+ } else if (arg == "-cmap") { // xv uses this name
+ if (!X11->colormap)
+ X11->custom_cmap = true;
+ }
+ else if (arg == "-sync")
+ appSync = !appSync;
+#if defined(QT_DEBUG)
+ else if (arg == "-nograb")
+ appNoGrab = !appNoGrab;
+ else if (arg == "-dograb")
+ appDoGrab = !appDoGrab;
+#endif
+ else
+ argv[j++] = argv[i];
+ }
+
+ priv->argc = j;
+
+#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
+ if (!appNoGrab && !appDoGrab) {
+ QString s;
+ s.sprintf("/proc/%d/cmdline", getppid());
+ QFile f(s);
+ if (f.open(QIODevice::ReadOnly)) {
+ s.clear();
+ char c;
+ while (f.getChar(&c) && c) {
+ if (c == '/')
+ s.clear();
+ else
+ s += QLatin1Char(c);
+ }
+ if (s == QLatin1String("gdb")) {
+ appNoGrab = true;
+ qDebug("Qt: gdb: -nograb added to command-line options.\n"
+ "\t Use the -dograb option to enforce grabbing.");
+ }
+ f.close();
+ }
+ }
+#endif
+
+ // Connect to X server
+ if (qt_is_gui_used && !X11->display) {
+ if ((X11->display = XOpenDisplay(X11->displayName)) == 0) {
+ qWarning("%s: cannot connect to X server %s", appName,
+ XDisplayName(X11->displayName));
+ QApplicationPrivate::reset_instance_pointer();
+ exit(1);
+ }
+
+ if (appSync) // if "-sync" argument
+ XSynchronize(X11->display, true);
+ }
+
+ // Common code, regardless of whether display is foreign.
+
+ // Get X parameters
+
+ if (qt_is_gui_used) {
+ X11->defaultScreen = DefaultScreen(X11->display);
+ X11->screenCount = ScreenCount(X11->display);
+
+ X11->screens = new QX11InfoData[X11->screenCount];
+ X11->argbVisuals = new Visual *[X11->screenCount];
+ X11->argbColormaps = new Colormap[X11->screenCount];
+
+ for (int s = 0; s < X11->screenCount; s++) {
+ QX11InfoData *screen = X11->screens + s;
+ screen->ref = 1; // ensures it doesn't get deleted
+ screen->screen = s;
+ screen->dpiX = (DisplayWidth(X11->display, s) * 254 + DisplayWidthMM(X11->display, s)*5)
+ / (DisplayWidthMM(X11->display, s)*10);
+ screen->dpiY = (DisplayHeight(X11->display, s) * 254 + DisplayHeightMM(X11->display, s)*5)
+ / (DisplayHeightMM(X11->display, s)*10);
+
+ X11->argbVisuals[s] = 0;
+ X11->argbColormaps[s] = 0;
+ }
+
+
+#ifndef QT_NO_XRENDER
+ int xrender_eventbase, xrender_errorbase;
+ // See if XRender is supported on the connected display
+ if (XQueryExtension(X11->display, "RENDER", &X11->xrender_major,
+ &xrender_eventbase, &xrender_errorbase)
+ && XRenderQueryExtension(X11->display, &xrender_eventbase,
+ &xrender_errorbase)) {
+ // Check the version as well - we need v0.4 or higher
+ int major = 0;
+ int minor = 0;
+ XRenderQueryVersion(X11->display, &major, &minor);
+ if (qgetenv("QT_X11_NO_XRENDER").isNull()) {
+ X11->use_xrender = (major >= 0 && minor >= 5);
+ X11->xrender_version = major*100+minor;
+ // workaround for broken XServer on Ubuntu Breezy (6.8 compiled with 7.0
+ // protocol headers)
+ if (X11->xrender_version == 10
+ && VendorRelease(X11->display) < 60900000
+ && QByteArray(ServerVendor(X11->display)).contains("X.Org"))
+ X11->xrender_version = 9;
+ }
+ }
+#endif // QT_NO_XRENDER
+
+#ifndef QT_NO_MITSHM
+ int mitshm_minor;
+ int mitshm_major;
+ int mitshm_eventbase;
+ int mitshm_errorbase;
+ int mitshm_pixmaps;
+ if (XQueryExtension(X11->display, "MIT-SHM", &X11->mitshm_major,
+ &mitshm_eventbase, &mitshm_errorbase)
+ && XShmQueryVersion(X11->display, &mitshm_major, &mitshm_minor,
+ &mitshm_pixmaps))
+ {
+ QString displayName = QLatin1String(XDisplayName(NULL));
+
+ // apparently MITSHM only works for local displays, so do a quick check here
+ // to determine whether the display is local or not (not 100 % accurate)
+ bool local = displayName.isEmpty() || displayName.lastIndexOf(QLatin1Char(':')) == 0;
+ if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0))
+ X11->use_mitshm = mitshm_pixmaps;
+ }
+#endif // QT_NO_MITSHM
+
+ // initialize the graphics system - order is imporant here - it must be done before
+ // the QColormap::initialize() call
+ QApplicationPrivate::graphics_system = QGraphicsSystemFactory::create(QApplicationPrivate::graphics_system_name);
+ QColormap::initialize();
+
+ // Support protocols
+ X11->xdndSetup();
+
+ // Finally create all atoms
+ qt_x11_create_intern_atoms();
+
+ // initialize NET lists
+ qt_get_net_supported();
+ qt_get_net_virtual_roots();
+
+#ifndef QT_NO_XRANDR
+ // See if XRandR is supported on the connected display
+ if (XQueryExtension(X11->display, "RANDR", &X11->xrandr_major,
+ &X11->xrandr_eventbase, &X11->xrandr_errorbase)) {
+
+# ifdef QT_RUNTIME_XRANDR
+ X11->ptrXRRSelectInput = 0;
+ X11->ptrXRRUpdateConfiguration = 0;
+ X11->ptrXRRRootToScreen = 0;
+ X11->ptrXRRQueryExtension = 0;
+ QLibrary xrandrLib(QLatin1String("Xrandr"), 2);
+ if (!xrandrLib.load()) { // try without the version number
+ xrandrLib.setFileName(QLatin1String("Xrandr"));
+ xrandrLib.load();
+ }
+ if (xrandrLib.isLoaded()) {
+ X11->ptrXRRSelectInput =
+ (PtrXRRSelectInput) xrandrLib.resolve("XRRSelectInput");
+ X11->ptrXRRUpdateConfiguration =
+ (PtrXRRUpdateConfiguration) xrandrLib.resolve("XRRUpdateConfiguration");
+ X11->ptrXRRRootToScreen =
+ (PtrXRRRootToScreen) xrandrLib.resolve("XRRRootToScreen");
+ X11->ptrXRRQueryExtension =
+ (PtrXRRQueryExtension) xrandrLib.resolve("XRRQueryExtension");
+ }
+# else
+ X11->ptrXRRSelectInput = XRRSelectInput;
+ X11->ptrXRRUpdateConfiguration = XRRUpdateConfiguration;
+ X11->ptrXRRRootToScreen = XRRRootToScreen;
+ X11->ptrXRRQueryExtension = XRRQueryExtension;
+# endif
+
+ if (X11->ptrXRRQueryExtension
+ && X11->ptrXRRQueryExtension(X11->display, &X11->xrandr_eventbase, &X11->xrandr_errorbase)) {
+ // XRandR is supported
+ X11->use_xrandr = true;
+ }
+ }
+#endif // QT_NO_XRANDR
+
+#ifndef QT_NO_XRENDER
+ if (X11->use_xrender) {
+ // XRender is supported, let's see if we have a PictFormat for the
+ // default visual
+ XRenderPictFormat *format =
+ XRenderFindVisualFormat(X11->display,
+ (Visual *) QX11Info::appVisual(X11->defaultScreen));
+
+ if (!format) {
+ X11->use_xrender = false;
+ }
+ }
+#endif // QT_NO_XRENDER
+
+#ifndef QT_NO_XFIXES
+ // See if Xfixes is supported on the connected display
+ if (XQueryExtension(X11->display, "XFIXES", &X11->xfixes_major,
+ &X11->xfixes_eventbase, &X11->xfixes_errorbase)) {
+ X11->ptrXFixesQueryExtension = XFIXES_LOAD_V1(XFixesQueryExtension);
+ X11->ptrXFixesQueryVersion = XFIXES_LOAD_V1(XFixesQueryVersion);
+ X11->ptrXFixesSetCursorName = XFIXES_LOAD_V2(XFixesSetCursorName);
+ X11->ptrXFixesSelectSelectionInput = XFIXES_LOAD_V2(XFixesSelectSelectionInput);
+
+ if(X11->ptrXFixesQueryExtension && X11->ptrXFixesQueryVersion
+ && X11->ptrXFixesQueryExtension(X11->display, &X11->xfixes_eventbase,
+ &X11->xfixes_errorbase)) {
+ // Xfixes is supported.
+ // Note: the XFixes protocol version is negotiated using QueryVersion.
+ // We supply the highest version we support, the X server replies with
+ // the highest version it supports, but no higher than the version we
+ // asked for. The version sent back is the protocol version the X server
+ // will use to talk us. If this call is removed, the behavior of the
+ // X server when it receives an XFixes request is undefined.
+ int major = 3;
+ int minor = 0;
+ X11->ptrXFixesQueryVersion(X11->display, &major, &minor);
+ X11->use_xfixes = (major >= 1);
+ X11->xfixes_major = major;
+ }
+ }
+ if (X11->use_xfixes && X11->ptrXFixesSelectSelectionInput) {
+ const unsigned long eventMask =
+ XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask;
+ X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(0),
+ XA_PRIMARY, eventMask);
+ X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(0),
+ ATOM(CLIPBOARD), eventMask);
+ }
+#endif // QT_NO_XFIXES
+
+#ifndef QT_NO_XCURSOR
+#ifdef QT_RUNTIME_XCURSOR
+ X11->ptrXcursorLibraryLoadCursor = 0;
+ QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
+ bool xcursorFound = xcursorLib.load();
+ if (!xcursorFound) { //try without the version number
+ xcursorLib.setFileName(QLatin1String("Xcursor"));
+ xcursorFound = xcursorLib.load();
+ }
+ if (xcursorFound) {
+ X11->ptrXcursorLibraryLoadCursor =
+ (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
+ }
+#else
+ X11->ptrXcursorLibraryLoadCursor = XcursorLibraryLoadCursor;
+#endif // QT_RUNTIME_XCURSOR
+#endif // QT_NO_XCURSOR
+
+#ifndef QT_NO_XINERAMA
+#ifdef QT_RUNTIME_XINERAMA
+ X11->ptrXineramaQueryExtension = 0;
+ X11->ptrXineramaIsActive = 0;
+ X11->ptrXineramaQueryScreens = 0;
+ QLibrary xineramaLib(QLatin1String("Xinerama"), 1);
+ bool xineramaFound = xineramaLib.load();
+ if (!xineramaFound) { //try without the version number
+ xineramaLib.setFileName(QLatin1String("Xinerama"));
+ xineramaFound = xineramaLib.load();
+ }
+ if (xineramaFound) {
+ X11->ptrXineramaQueryExtension =
+ (PtrXineramaQueryExtension) xineramaLib.resolve("XineramaQueryExtension");
+ X11->ptrXineramaIsActive =
+ (PtrXineramaIsActive) xineramaLib.resolve("XineramaIsActive");
+ X11->ptrXineramaQueryScreens =
+ (PtrXineramaQueryScreens) xineramaLib.resolve("XineramaQueryScreens");
+ }
+#else
+ X11->ptrXineramaQueryScreens = XineramaQueryScreens;
+ X11->ptrXineramaIsActive = XineramaIsActive;
+ X11->ptrXineramaQueryExtension = XineramaQueryExtension;
+#endif // QT_RUNTIME_XINERAMA
+#endif // QT_NO_XINERAMA
+
+#ifndef QT_NO_XINPUT
+ // See if Xinput is supported on the connected display
+ X11->ptrXCloseDevice = 0;
+ X11->ptrXListInputDevices = 0;
+ X11->ptrXOpenDevice = 0;
+ X11->ptrXFreeDeviceList = 0;
+ X11->ptrXSelectExtensionEvent = 0;
+ X11->use_xinput = XQueryExtension(X11->display, "XInputExtension", &X11->xinput_major,
+ &X11->xinput_eventbase, &X11->xinput_errorbase);
+ if (X11->use_xinput) {
+ X11->ptrXCloseDevice = XINPUT_LOAD(XCloseDevice);
+ X11->ptrXListInputDevices = XINPUT_LOAD(XListInputDevices);
+ X11->ptrXOpenDevice = XINPUT_LOAD(XOpenDevice);
+ X11->ptrXFreeDeviceList = XINPUT_LOAD(XFreeDeviceList);
+ X11->ptrXSelectExtensionEvent = XINPUT_LOAD(XSelectExtensionEvent);
+ }
+#endif // QT_NO_XINPUT
+
+#if !defined(QT_NO_FONTCONFIG)
+ int dpi = 0;
+ getXDefault("Xft", FC_DPI, &dpi);
+ if (dpi) {
+ for (int s = 0; s < ScreenCount(X11->display); ++s) {
+ QX11Info::setAppDpiX(s, dpi);
+ QX11Info::setAppDpiY(s, dpi);
+ }
+ }
+ double fc_scale = 1.;
+ getXDefault("Xft", FC_SCALE, &fc_scale);
+ X11->fc_scale = fc_scale;
+ for (int s = 0; s < ScreenCount(X11->display); ++s) {
+ int subpixel = FC_RGBA_UNKNOWN;
+#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
+ if (X11->use_xrender) {
+ int rsp = XRenderQuerySubpixelOrder(X11->display, s);
+ switch (rsp) {
+ default:
+ case SubPixelUnknown:
+ subpixel = FC_RGBA_UNKNOWN;
+ break;
+ case SubPixelHorizontalRGB:
+ subpixel = FC_RGBA_RGB;
+ break;
+ case SubPixelHorizontalBGR:
+ subpixel = FC_RGBA_BGR;
+ break;
+ case SubPixelVerticalRGB:
+ subpixel = FC_RGBA_VRGB;
+ break;
+ case SubPixelVerticalBGR:
+ subpixel = FC_RGBA_VBGR;
+ break;
+ case SubPixelNone:
+ subpixel = FC_RGBA_NONE;
+ break;
+ }
+ }
+#endif
+
+ char *rgba = XGetDefault(X11->display, "Xft", FC_RGBA);
+ if (rgba) {
+ char *end = 0;
+ int v = strtol(rgba, &end, 0);
+ if (rgba != end) {
+ subpixel = v;
+ } else if (qstrncmp(rgba, "unknown", 7) == 0) {
+ subpixel = FC_RGBA_UNKNOWN;
+ } else if (qstrncmp(rgba, "rgb", 3) == 0) {
+ subpixel = FC_RGBA_RGB;
+ } else if (qstrncmp(rgba, "bgr", 3) == 0) {
+ subpixel = FC_RGBA_BGR;
+ } else if (qstrncmp(rgba, "vrgb", 4) == 0) {
+ subpixel = FC_RGBA_VRGB;
+ } else if (qstrncmp(rgba, "vbgr", 4) == 0) {
+ subpixel = FC_RGBA_VBGR;
+ } else if (qstrncmp(rgba, "none", 4) == 0) {
+ subpixel = FC_RGBA_NONE;
+ }
+ }
+ X11->screens[s].subpixel = subpixel;
+ }
+ getXDefault("Xft", FC_ANTIALIAS, &X11->fc_antialias);
+#ifdef FC_HINT_STYLE
+ getXDefault("Xft", FC_HINT_STYLE, &X11->fc_hint_style);
+#endif
+#if 0
+ // ###### these are implemented by Xft, not sure we need them
+ getXDefault("Xft", FC_AUTOHINT, &X11->fc_autohint);
+ getXDefault("Xft", FC_HINTING, &X11->fc_autohint);
+ getXDefault("Xft", FC_MINSPACE, &X11->fc_autohint);
+#endif
+#endif // QT_NO_XRENDER
+
+ // initialize key mapper
+ QKeyMapper::changeKeyboard();
+
+#ifndef QT_NO_XKB
+ if (qt_keymapper_private()->useXKB) {
+ // If XKB is detected, set the GrabsUseXKBState option so input method
+ // compositions continue to work (ie. deadkeys)
+ unsigned int state = XkbPCF_GrabsUseXKBStateMask;
+ (void) XkbSetPerClientControls(X11->display, state, &state);
+ }
+#endif // QT_NO_XKB
+
+ // Misc. initialization
+#if 0 //disabled for now..
+ QSegfaultHandler::initialize(priv->argv, priv->argc);
+#endif
+ QCursorData::initialize();
+ }
+ QFont::initialize();
+
+ if(qt_is_gui_used) {
+ qApp->setObjectName(QString::fromLocal8Bit(appName));
+
+ int screen;
+ for (screen = 0; screen < X11->screenCount; ++screen) {
+ XSelectInput(X11->display, QX11Info::appRootWindow(screen),
+ KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask);
+
+#ifndef QT_NO_XRANDR
+ if (X11->use_xrandr)
+ X11->ptrXRRSelectInput(X11->display, QX11Info::appRootWindow(screen), True);
+#endif // QT_NO_XRANDR
+ }
+ }
+
+ if (qt_is_gui_used) {
+ // Attempt to determine the current running X11 Desktop Enviornment
+ // Use dbus if/when we can, but fall back to using windowManagerName() for now
+
+ X11->compositingManagerRunning = XGetSelectionOwner(X11->display,
+ ATOM(_NET_WM_CM_S0));
+ X11->desktopEnvironment = DE_UNKNOWN;
+
+ // See if the current window manager is using the freedesktop.org spec to give its name
+ Window windowManagerWindow = XNone;
+ Atom typeReturned;
+ int formatReturned;
+ unsigned long nitemsReturned;
+ unsigned long unused;
+ unsigned char *data = 0;
+ if (XGetWindowProperty(QX11Info::display(), QX11Info::appRootWindow(),
+ ATOM(_NET_SUPPORTING_WM_CHECK),
+ 0, 1024, False, XA_WINDOW, &typeReturned,
+ &formatReturned, &nitemsReturned, &unused, &data)
+ == Success) {
+ if (typeReturned == XA_WINDOW && formatReturned == 32)
+ windowManagerWindow = *((Window*) data);
+ if (data)
+ XFree(data);
+
+ if (windowManagerWindow != XNone) {
+ QString wmName;
+ Atom utf8atom = ATOM(UTF8_STRING);
+ if (XGetWindowProperty(QX11Info::display(), windowManagerWindow, ATOM(_NET_WM_NAME),
+ 0, 1024, False, utf8atom, &typeReturned,
+ &formatReturned, &nitemsReturned, &unused, &data)
+ == Success) {
+ if (typeReturned == utf8atom && formatReturned == 8)
+ wmName = QString::fromUtf8((const char*)data);
+ if (data)
+ XFree(data);
+ if (wmName == QLatin1String("KWin"))
+ X11->desktopEnvironment = DE_KDE;
+ if (wmName == QLatin1String("Metacity"))
+ X11->desktopEnvironment = DE_GNOME;
+ }
+ }
+ }
+
+ // Running a different/newer/older window manager? Try some other things
+ if (X11->desktopEnvironment == DE_UNKNOWN){
+ Atom type;
+ int format;
+ unsigned long length, after;
+ uchar *data = 0;
+
+ if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
+ 0, 1, False, AnyPropertyType, &type, &format, &length,
+ &after, &data) == Success && length) {
+ // DTWM is running, meaning most likely CDE is running...
+ X11->desktopEnvironment = DE_CDE;
+ } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(GNOME_BACKGROUND_PROPERTIES), 0, 1, False, AnyPropertyType,
+ &type, &format, &length, &after, &data) == Success && length) {
+ X11->desktopEnvironment = DE_GNOME;
+ } else if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
+ X11->desktopEnvironment = DE_GNOME;
+ } else if ((XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KDE_FULL_SESSION),
+ 0, 1, False, AnyPropertyType, &type, &format, &length, &after, &data) == Success
+ && length)
+ || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWIN_RUNNING),
+ 0, 1, False, AnyPropertyType, &type, &format, &length,
+ &after, &data) == Success
+ && length)
+ || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWM_RUNNING),
+ 0, 1, False, AnyPropertyType, &type, &format, &length,
+ &after, &data) == Success && length)) {
+ X11->desktopEnvironment = DE_KDE;
+ } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_SGI_DESKS_MANAGER),
+ 0, 1, False, XA_WINDOW, &type, &format, &length, &after, &data) == Success
+ && length) {
+ X11->desktopEnvironment = DE_4DWM;
+ }
+ if (data)
+ XFree((char *)data);
+ }
+
+ qt_set_input_encoding();
+
+ qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol);
+
+ // be smart about the size of the default font. most X servers have helvetica
+ // 12 point available at 2 resolutions:
+ // 75dpi (12 pixels) and 100dpi (17 pixels).
+ // At 95 DPI, a 12 point font should be 16 pixels tall - in which case a 17
+ // pixel font is a closer match than a 12 pixel font
+ int ptsz = (X11->use_xrender
+ ? 9
+ : (int) (((QX11Info::appDpiY() >= 95 ? 17. : 12.) *
+ 72. / (float) QX11Info::appDpiY()) + 0.5));
+
+ if (!QApplicationPrivate::sys_font) {
+ // no font from settings or RESOURCE_MANAGER, provide a fallback
+ QFont f(X11->has_fontconfig ? QLatin1String("Sans Serif") : QLatin1String("Helvetica"),
+ ptsz);
+ QApplicationPrivate::setSystemFont(f);
+ }
+
+#if !defined (QT_NO_TABLET)
+ if (X11->use_xinput) {
+ int ndev,
+ i,
+ j;
+ bool gotStylus,
+ gotEraser;
+ XDeviceInfo *devices = 0, *devs;
+ XInputClassInfo *ip;
+ XAnyClassPtr any;
+ XValuatorInfoPtr v;
+ XAxisInfoPtr a;
+ XDevice *dev = 0;
+
+#if !defined(Q_OS_IRIX)
+ // XFree86 divides a stylus and eraser into 2 devices, so we must do for both...
+ const QString XFREENAMESTYLUS = QLatin1String("stylus");
+ const QString XFREENAMEPEN = QLatin1String("pen");
+ const QString XFREENAMEERASER = QLatin1String("eraser");
+#endif
+
+ if (X11->ptrXListInputDevices) {
+ devices = X11->ptrXListInputDevices(X11->display, &ndev);
+ if (!devices)
+ qWarning("QApplication: Failed to get list of tablet devices");
+ }
+ if (!devices)
+ ndev = -1;
+ QTabletEvent::TabletDevice deviceType;
+ for (devs = devices, i = 0; i < ndev && devs; i++, devs++) {
+ dev = 0;
+ deviceType = QTabletEvent::NoDevice;
+ gotStylus = false;
+ gotEraser = false;
+
+ QString devName = QString::fromLocal8Bit(devs->name).toLower();
+#if defined(Q_OS_IRIX)
+ if (devName == QLatin1String(WACOM_NAME)) {
+ deviceType = QTabletEvent::Stylus;
+ gotStylus = true;
+ }
+#else
+ if (devName.startsWith(XFREENAMEPEN)
+ || devName.startsWith(XFREENAMESTYLUS)) {
+ deviceType = QTabletEvent::Stylus;
+ gotStylus = true;
+ } else if (devName.startsWith(XFREENAMEERASER)) {
+ deviceType = QTabletEvent::XFreeEraser;
+ gotEraser = true;
+ }
+#endif
+ if (deviceType == QTabletEvent::NoDevice)
+ continue;
+
+ if (gotStylus || gotEraser) {
+ if (X11->ptrXOpenDevice)
+ dev = X11->ptrXOpenDevice(X11->display, devs->id);
+
+ if (!dev)
+ continue;
+
+ QTabletDeviceData device_data;
+ device_data.deviceType = deviceType;
+ device_data.eventCount = 0;
+ device_data.device = dev;
+ device_data.xinput_motion = -1;
+ device_data.xinput_key_press = -1;
+ device_data.xinput_key_release = -1;
+ device_data.xinput_button_press = -1;
+ device_data.xinput_button_release = -1;
+ device_data.xinput_proximity_in = -1;
+ device_data.xinput_proximity_out = -1;
+ device_data.widgetToGetPress = 0;
+
+ if (dev->num_classes > 0) {
+ for (ip = dev->classes, j = 0; j < dev->num_classes;
+ ip++, j++) {
+ switch (ip->input_class) {
+ case KeyClass:
+ DeviceKeyPress(dev, device_data.xinput_key_press,
+ device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ DeviceKeyRelease(dev, device_data.xinput_key_release,
+ device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ break;
+ case ButtonClass:
+ DeviceButtonPress(dev, device_data.xinput_button_press,
+ device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ DeviceButtonRelease(dev, device_data.xinput_button_release,
+ device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ break;
+ case ValuatorClass:
+ // I'm only going to be interested in motion when the
+ // stylus is already down anyway!
+ DeviceMotionNotify(dev, device_data.xinput_motion,
+ device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ ProximityIn(dev, device_data.xinput_proximity_in, device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ ProximityOut(dev, device_data.xinput_proximity_out, device_data.eventList[device_data.eventCount]);
+ if (device_data.eventList[device_data.eventCount])
+ ++device_data.eventCount;
+ default:
+ break;
+ }
+ }
+ }
+
+ // get the min/max value for pressure!
+ any = (XAnyClassPtr) (devs->inputclassinfo);
+ for (j = 0; j < devs->num_classes; j++) {
+ if (any->c_class == ValuatorClass) {
+ v = (XValuatorInfoPtr) any;
+ a = (XAxisInfoPtr) ((char *) v +
+ sizeof (XValuatorInfo));
+#if defined (Q_OS_IRIX)
+ // I'm not exaclty wild about this, but the
+ // dimensions of the tablet are more relevant here
+ // than the min and max values from the axis
+ // (actually it seems to be 2/3 or what is in the
+ // axis. So we'll try to parse it from this
+ // string. --tws
+ char returnString[SGIDeviceRtrnLen];
+ int tmp;
+ if (XSGIMiscQueryExtension(X11->display, &tmp, &tmp)
+ && XSGIDeviceQuery(X11->display, devs->id,
+ "dimensions", returnString)) {
+ QString str = QLatin1String(returnString);
+ int comma = str.indexOf(',');
+ device_data.minX = 0;
+ device_data.minY = 0;
+ device_data.maxX = str.left(comma).toInt();
+ device_data.maxY = str.mid(comma + 1).toInt();
+ } else {
+ device_data.minX = a[WAC_XCOORD_I].min_value;
+ device_data.maxX = a[WAC_XCOORD_I].max_value;
+ device_data.minY = a[WAC_YCOORD_I].min_value;
+ device_data.maxY = a[WAC_YCOORD_I].max_value;
+ }
+ device_data.minPressure = a[WAC_PRESSURE_I].min_value;
+ device_data.maxPressure = a[WAC_PRESSURE_I].max_value;
+ device_data.minTanPressure = a[WAC_TAN_PRESSURE_I].min_value;
+ device_data.maxTanPressure = a[WAC_TAN_PRESSURE_I].max_value;
+ device_data.minZ = a[WAC_ZCOORD_I].min_value;
+ device_data.maxZ = a[WAC_ZCOORD_I].max_value;
+#else
+ device_data.minX = a[0].min_value;
+ device_data.maxX = a[0].max_value;
+ device_data.minY = a[1].min_value;
+ device_data.maxY = a[1].max_value;
+ device_data.minPressure = a[2].min_value;
+ device_data.maxPressure = a[2].max_value;
+ device_data.minTanPressure = 0;
+ device_data.maxTanPressure = 0;
+ device_data.minZ = 0;
+ device_data.maxZ = 0;
+#endif
+
+ // got the max pressure no need to go further...
+ break;
+ }
+ any = (XAnyClassPtr) ((char *) any + any->length);
+ } // end of for loop
+
+ tablet_devices()->append(device_data);
+ } // if (gotStylus || gotEraser)
+ }
+ if (X11->ptrXFreeDeviceList)
+ X11->ptrXFreeDeviceList(devices);
+ }
+#endif // QT_NO_TABLET
+
+ X11->startupId = getenv("DESKTOP_STARTUP_ID");
+ X11->originalStartupId = X11->startupId;
+ static char desktop_startup_id[] = "DESKTOP_STARTUP_ID=";
+ putenv(desktop_startup_id);
+
+ } else {
+ // read some non-GUI settings when not using the X server...
+
+ if (QApplication::desktopSettingsAware()) {
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+
+ // read library (ie. plugin) path list
+ QString libpathkey = QString::fromLatin1("%1.%2/libraryPath")
+ .arg(QT_VERSION >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8);
+ QStringList pathlist =
+ settings.value(libpathkey).toString().split(QLatin1Char(':'));
+ if (! pathlist.isEmpty()) {
+ QStringList::ConstIterator it = pathlist.constBegin();
+ while (it != pathlist.constEnd())
+ QApplication::addLibraryPath(*it++);
+ }
+
+ QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
+ QVariant(QLatin1String("none"))).toString();
+ if (defaultcodec != QLatin1String("none")) {
+ QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
+ if (codec)
+ QTextCodec::setCodecForTr(codec);
+ }
+
+ settings.endGroup(); // Qt
+ }
+ }
+
+#if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET)
+ QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this.
+ if (wacom.load()) {
+ // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x
+ ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit");
+ ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice");
+ ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam");
+ ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice");
+ ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm");
+
+ if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0
+ || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none.
+ ptrWacomConfigInit = 0;
+ ptrWacomConfigOpenDevice = 0;
+ ptrWacomConfigGetRawParam = 0;
+ ptrWacomConfigCloseDevice = 0;
+ ptrWacomConfigTerm = 0;
+ }
+ }
+#endif
+}
+
+
+ // run-time search for default style
+/*!
+ \internal
+*/
+void QApplicationPrivate::x11_initialize_style()
+{
+ if (QApplicationPrivate::app_style)
+ return;
+
+ switch(X11->desktopEnvironment) {
+ case DE_KDE:
+ if (X11->use_xrender)
+ QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique"));
+ else
+ QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
+ break;
+ case DE_GNOME:
+ if (X11->use_xrender)
+ QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks"));
+ else
+ QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
+ break;
+ case DE_CDE:
+ QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde"));
+ break;
+ default:
+ // Don't do anything
+ break;
+ }
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+}
+
+/*****************************************************************************
+ qt_cleanup() - cleans up when the application is finished
+ *****************************************************************************/
+
+void qt_cleanup()
+{
+ if (app_save_rootinfo) // root window must keep state
+ qt_save_rootinfo();
+
+ if (qt_is_gui_used) {
+ QPixmapCache::clear();
+ QCursorData::cleanup();
+ QFont::cleanup();
+ QColormap::cleanup();
+
+#if !defined (QT_NO_TABLET)
+ QTabletDeviceDataList *devices = qt_tablet_devices();
+ if (X11->ptrXCloseDevice)
+ for (int i = 0; i < devices->size(); ++i)
+ X11->ptrXCloseDevice(X11->display, (XDevice*)devices->at(i).device);
+ devices->clear();
+#endif
+ }
+
+ // restore original value back. This is also done in QWidgetPrivate::show_sys.
+ if (X11->originalStartupId)
+ putenv(X11->originalStartupId);
+
+#ifndef QT_NO_XRENDER
+ for (int i = 0; i < X11->solid_fill_count; ++i) {
+ if (X11->solid_fills[i].picture)
+ XRenderFreePicture(X11->display, X11->solid_fills[i].picture);
+ }
+ for (int i = 0; i < X11->pattern_fill_count; ++i) {
+ if (X11->pattern_fills[i].picture)
+ XRenderFreePicture(X11->display, X11->pattern_fills[i].picture);
+ }
+#endif
+
+#if !defined(QT_NO_IM)
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = 0;
+#endif
+
+ // Reset the error handlers
+ if (qt_is_gui_used)
+ XSync(X11->display, False); // sync first to process all possible errors
+ XSetErrorHandler(original_x_errhandler);
+ XSetIOErrorHandler(original_xio_errhandler);
+
+ if (X11->argbColormaps) {
+ for (int s = 0; s < X11->screenCount; s++) {
+ if (X11->argbColormaps[s])
+ XFreeColormap(X11->display, X11->argbColormaps[s]);
+ }
+ }
+
+ if (qt_is_gui_used && !X11->foreignDisplay)
+ XCloseDisplay(X11->display); // close X display
+ X11->display = 0;
+
+ delete [] X11->screens;
+ delete [] X11->argbVisuals;
+ delete [] X11->argbColormaps;
+
+ if (X11->foreignDisplay) {
+ delete [] (char *)appName;
+ appName = 0;
+ }
+
+ delete [] (char *)appClass;
+ appClass = 0;
+
+ if (X11->net_supported_list)
+ delete [] X11->net_supported_list;
+ X11->net_supported_list = 0;
+
+ if (X11->net_virtual_root_list)
+ delete [] X11->net_virtual_root_list;
+ X11->net_virtual_root_list = 0;
+
+ delete X11;
+ X11 = 0;
+}
+
+
+/*****************************************************************************
+ Platform specific global and internal functions
+ *****************************************************************************/
+
+void qt_save_rootinfo() // save new root info
+{
+ Atom type;
+ int format;
+ unsigned long length, after;
+ uchar *data = 0;
+
+ if (ATOM(_XSETROOT_ID)) { // kill old pixmap
+ if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_XSETROOT_ID), 0, 1,
+ True, AnyPropertyType, &type, &format,
+ &length, &after, &data) == Success) {
+ if (type == XA_PIXMAP && format == 32 && length == 1 &&
+ after == 0 && data) {
+ XKillClient(X11->display, *((Pixmap*)data));
+ }
+ Pixmap dummy = XCreatePixmap(X11->display, QX11Info::appRootWindow(),
+ 1, 1, 1);
+ XChangeProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_XSETROOT_ID), XA_PIXMAP, 32,
+ PropModeReplace, (uchar *)&dummy, 1);
+ XSetCloseDownMode(X11->display, RetainPermanent);
+ }
+ }
+ if (data)
+ XFree((char *)data);
+}
+
+void qt_updated_rootinfo()
+{
+ app_save_rootinfo = true;
+}
+
+// ### Cleanup, this function is not in use!
+bool qt_wstate_iconified(WId winid)
+{
+ Atom type;
+ int format;
+ unsigned long length, after;
+ uchar *data = 0;
+ int r = XGetWindowProperty(X11->display, winid, ATOM(WM_STATE), 0, 2,
+ False, AnyPropertyType, &type, &format,
+ &length, &after, &data);
+ bool iconic = false;
+ if (r == Success && data && format == 32) {
+ // quint32 *wstate = (quint32*)data;
+ unsigned long *wstate = (unsigned long *) data;
+ iconic = (*wstate == IconicState);
+ XFree((char *)data);
+ }
+ return iconic;
+}
+
+QString QApplicationPrivate::appName() const
+{
+ return QString::fromLocal8Bit(QT_PREPEND_NAMESPACE(appName));
+}
+
+const char *QX11Info::appClass() // get application class
+{
+ return QT_PREPEND_NAMESPACE(appClass);
+}
+
+bool qt_nograb() // application no-grab option
+{
+#if defined(QT_DEBUG)
+ return appNoGrab;
+#else
+ return false;
+#endif
+}
+
+
+/*****************************************************************************
+ Platform specific QApplication members
+ *****************************************************************************/
+
+#ifdef QT3_SUPPORT
+void QApplication::setMainWidget(QWidget *mainWidget)
+{
+#ifndef QT_NO_DEBUG
+ if (mainWidget && mainWidget->parentWidget() && mainWidget->isWindow())
+ qWarning("QApplication::setMainWidget: New main widget (%s/%s) "
+ "has a parent",
+ mainWidget->metaObject()->className(), mainWidget->objectName().toLocal8Bit().constData());
+#endif
+ if (mainWidget)
+ mainWidget->d_func()->createWinId();
+ QApplicationPrivate::main_widget = mainWidget;
+ if (QApplicationPrivate::main_widget) // give WM command line
+ QApplicationPrivate::applyX11SpecificCommandLineArguments(QApplicationPrivate::main_widget);
+}
+#endif
+
+void QApplicationPrivate::applyX11SpecificCommandLineArguments(QWidget *main_widget)
+{
+ static bool beenHereDoneThat = false;
+ if (beenHereDoneThat)
+ return;
+ beenHereDoneThat = true;
+ Q_ASSERT(main_widget->testAttribute(Qt::WA_WState_Created));
+ if (mwTitle) {
+ XStoreName(X11->display, main_widget->effectiveWinId(), (char*)mwTitle);
+ QByteArray net_wm_name = QString::fromLocal8Bit(mwTitle).toUtf8();
+ XChangeProperty(X11->display, main_widget->effectiveWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
+ PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
+ }
+ if (mwGeometry) { // parse geometry
+ int x, y;
+ int w, h;
+ int m = XParseGeometry((char*)mwGeometry, &x, &y, (uint*)&w, (uint*)&h);
+ QSize minSize = main_widget->minimumSize();
+ QSize maxSize = main_widget->maximumSize();
+ if ((m & XValue) == 0)
+ x = main_widget->geometry().x();
+ if ((m & YValue) == 0)
+ y = main_widget->geometry().y();
+ if ((m & WidthValue) == 0)
+ w = main_widget->width();
+ if ((m & HeightValue) == 0)
+ h = main_widget->height();
+ w = qMin(w,maxSize.width());
+ h = qMin(h,maxSize.height());
+ w = qMax(w,minSize.width());
+ h = qMax(h,minSize.height());
+ if ((m & XNegative)) {
+ x = QApplication::desktop()->width() + x - w;
+ }
+ if ((m & YNegative)) {
+ y = QApplication::desktop()->height() + y - h;
+ }
+ main_widget->setGeometry(x, y, w, h);
+ }
+}
+
+#ifndef QT_NO_CURSOR
+
+/*****************************************************************************
+ QApplication cursor stack
+ *****************************************************************************/
+
+extern void qt_x11_enforce_cursor(QWidget * w);
+
+void QApplication::setOverrideCursor(const QCursor &cursor)
+{
+ qApp->d_func()->cursor_list.prepend(cursor);
+
+ QWidgetList all = allWidgets();
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if ((w->testAttribute(Qt::WA_SetCursor) || w->isWindow()) && (w->windowType() != Qt::Desktop))
+ qt_x11_enforce_cursor(w);
+ }
+ XFlush(X11->display); // make X execute it NOW
+}
+
+void QApplication::restoreOverrideCursor()
+{
+ if (qApp->d_func()->cursor_list.isEmpty())
+ return;
+ qApp->d_func()->cursor_list.removeFirst();
+
+ if (QWidgetPrivate::mapper != 0 && !closingDown()) {
+ QWidgetList all = allWidgets();
+ for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
+ register QWidget *w = *it;
+ if ((w->testAttribute(Qt::WA_SetCursor) || w->isWindow()) && (w->windowType() != Qt::Desktop))
+ qt_x11_enforce_cursor(w);
+ }
+ XFlush(X11->display);
+ }
+}
+
+#endif
+
+
+/*****************************************************************************
+ Routines to find a Qt widget from a screen position
+ *****************************************************************************/
+
+Window QX11Data::findClientWindow(Window win, Atom property, bool leaf)
+{
+ Atom type = XNone;
+ int format, i;
+ ulong nitems, after;
+ uchar *data = 0;
+ Window root, parent, target=0, *children=0;
+ uint nchildren;
+ if (XGetWindowProperty(X11->display, win, property, 0, 0, false, AnyPropertyType,
+ &type, &format, &nitems, &after, &data) == Success) {
+ if (data)
+ XFree((char *)data);
+ if (type)
+ return win;
+ }
+ if (!XQueryTree(X11->display,win,&root,&parent,&children,&nchildren)) {
+ if (children)
+ XFree((char *)children);
+ return 0;
+ }
+ for (i=nchildren-1; !target && i >= 0; i--)
+ target = X11->findClientWindow(children[i], property, leaf);
+ if (children)
+ XFree((char *)children);
+ return target;
+}
+
+QWidget *QApplication::topLevelAt(const QPoint &p)
+{
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(p);
+ return 0;
+#else
+ int screen = QCursor::x11Screen();
+ int unused;
+
+ int x = p.x();
+ int y = p.y();
+ Window target;
+ if (!XTranslateCoordinates(X11->display,
+ QX11Info::appRootWindow(screen),
+ QX11Info::appRootWindow(screen),
+ x, y, &unused, &unused, &target)) {
+ return 0;
+ }
+ if (!target || target == QX11Info::appRootWindow(screen))
+ return 0;
+ QWidget *w;
+ w = QWidget::find((WId)target);
+
+ if (!w) {
+ X11->ignoreBadwindow();
+ target = X11->findClientWindow(target, ATOM(WM_STATE), true);
+ if (X11->badwindow())
+ return 0;
+ w = QWidget::find((WId)target);
+ if (!w) {
+ // Perhaps the widget at (x,y) is inside a foreign application?
+ // Search all toplevel widgets to see if one is within target
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ Window ctarget = target;
+ if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ Window wid = widget->internalWinId();
+ while (ctarget && !w) {
+ X11->ignoreBadwindow();
+ XTranslateCoordinates(X11->display,
+ QX11Info::appRootWindow(screen),
+ ctarget, x, y, &unused, &unused, &ctarget);
+ if (X11->badwindow())
+ break;
+ if (ctarget == wid) {
+ // Found!
+ w = widget;
+ break;
+ }
+ }
+ }
+ if (w)
+ break;
+ }
+ }
+ }
+ return w ? w->window() : 0;
+#endif
+}
+
+/*!
+ Synchronizes with the X server in the X11 implementation. This
+ normally takes some time. Does nothing on other platforms.
+*/
+
+void QApplication::syncX()
+{
+ if (X11->display)
+ XSync(X11->display, False); // don't discard events
+}
+
+
+void QApplication::beep()
+{
+ if (X11->display)
+ XBell(X11->display, 0);
+ else
+ printf("\7");
+}
+
+void QApplication::alert(QWidget *widget, int msec)
+{
+ if (!QApplicationPrivate::checkInstance("alert"))
+ return;
+
+ QWidgetList windowsToMark;
+ if (!widget) {
+ windowsToMark += topLevelWidgets();
+ } else {
+ windowsToMark.append(widget->window());
+ }
+
+ for (int i = 0; i < windowsToMark.size(); ++i) {
+ QWidget *window = windowsToMark.at(i);
+ if (!window->isActiveWindow()) {
+ qt_change_net_wm_state(window, true, ATOM(_NET_WM_STATE_DEMANDS_ATTENTION));
+ if (msec != 0) {
+ QTimer *timer = new QTimer(qApp);
+ timer->setSingleShot(true);
+ connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut()));
+ if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(window)) {
+ qApp->d_func()->alertTimerHash.remove(window);
+ delete oldTimer;
+ }
+ qApp->d_func()->alertTimerHash.insert(window, timer);
+ timer->start(msec);
+ }
+ }
+ }
+}
+
+void QApplicationPrivate::_q_alertTimeOut()
+{
+ if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) {
+ QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin();
+ while (it != alertTimerHash.end()) {
+ if (it.value() == timer) {
+ QWidget *window = it.key();
+ qt_change_net_wm_state(window, false, ATOM(_NET_WM_STATE_DEMANDS_ATTENTION));
+ alertTimerHash.erase(it);
+ timer->deleteLater();
+ break;
+ }
+ ++it;
+ }
+ }
+}
+
+/*****************************************************************************
+ Special lookup functions for windows that have been reparented recently
+ *****************************************************************************/
+
+static QWidgetMapper *wPRmapper = 0; // alternative widget mapper
+
+void qPRCreate(const QWidget *widget, Window oldwin)
+{ // QWidget::reparent mechanism
+ if (!wPRmapper)
+ wPRmapper = new QWidgetMapper;
+
+ QETWidget *w = static_cast<QETWidget *>(const_cast<QWidget *>(widget));
+ wPRmapper->insert((int)oldwin, w); // add old window to mapper
+ w->setAttribute(Qt::WA_WState_Reparented); // set reparented flag
+}
+
+void qPRCleanup(QWidget *widget)
+{
+ QETWidget *etw = static_cast<QETWidget *>(const_cast<QWidget *>(widget));
+ if (!(wPRmapper && widget->testAttribute(Qt::WA_WState_Reparented)))
+ return; // not a reparented widget
+ QWidgetMapper::Iterator it = wPRmapper->begin();
+ while (it != wPRmapper->constEnd()) {
+ QWidget *w = *it;
+ if (w == etw) { // found widget
+ etw->setAttribute(Qt::WA_WState_Reparented, false); // clear flag
+ it = wPRmapper->erase(it);// old window no longer needed
+ } else {
+ ++it;
+ }
+ }
+ if (wPRmapper->size() == 0) { // became empty
+ delete wPRmapper; // then reset alt mapper
+ wPRmapper = 0;
+ }
+}
+
+static QETWidget *qPRFindWidget(Window oldwin)
+{
+ return wPRmapper ? (QETWidget*)wPRmapper->value((int)oldwin, 0) : 0;
+}
+
+/*!
+ \internal
+*/
+int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
+{
+ if (w && !w->internalWinId())
+ return 0;
+ QETWidget *widget = (QETWidget*)w;
+ if (event->xclient.format == 32 && event->xclient.message_type) {
+ if (event->xclient.message_type == ATOM(WM_PROTOCOLS)) {
+ Atom a = event->xclient.data.l[0];
+ if (a == ATOM(WM_DELETE_WINDOW)) {
+ if (passive_only) return 0;
+ widget->translateCloseEvent(event);
+ }
+ else if (a == ATOM(WM_TAKE_FOCUS)) {
+ if ((ulong) event->xclient.data.l[1] > X11->time)
+ X11->time = event->xclient.data.l[1];
+ QWidget *amw = activeModalWidget();
+ if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
+ QWidget *p = amw->parentWidget();
+ while (p && p != widget)
+ p = p->parentWidget();
+ if (!p || !X11->net_supported_list)
+ amw->raise(); // help broken window managers
+ amw->activateWindow();
+ }
+#ifndef QT_NO_WHATSTHIS
+ } else if (a == ATOM(_NET_WM_CONTEXT_HELP)) {
+ QWhatsThis::enterWhatsThisMode();
+#endif // QT_NO_WHATSTHIS
+ } else if (a == ATOM(_NET_WM_PING)) {
+ // avoid send/reply loops
+ Window root = RootWindow(X11->display, w->x11Info().screen());
+ if (event->xclient.window != root) {
+ event->xclient.window = root;
+ XSendEvent(event->xclient.display, event->xclient.window,
+ False, SubstructureNotifyMask|SubstructureRedirectMask, event);
+ }
+ }
+ } else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
+ widget->translateScrollDoneEvent(event);
+ } else if (event->xclient.message_type == ATOM(XdndPosition)) {
+ X11->xdndHandlePosition(widget, event, passive_only);
+ } else if (event->xclient.message_type == ATOM(XdndEnter)) {
+ X11->xdndHandleEnter(widget, event, passive_only);
+ } else if (event->xclient.message_type == ATOM(XdndStatus)) {
+ X11->xdndHandleStatus(widget, event, passive_only);
+ } else if (event->xclient.message_type == ATOM(XdndLeave)) {
+ X11->xdndHandleLeave(widget, event, passive_only);
+ } else if (event->xclient.message_type == ATOM(XdndDrop)) {
+ X11->xdndHandleDrop(widget, event, passive_only);
+ } else if (event->xclient.message_type == ATOM(XdndFinished)) {
+ X11->xdndHandleFinished(widget, event, passive_only);
+ } else {
+ if (passive_only) return 0;
+ // All other are interactions
+ }
+ } else {
+ X11->motifdndHandle(widget, event, passive_only);
+ }
+
+ return 0;
+}
+
+/*!
+ This function does the core processing of individual X
+ \a{event}s, normally by dispatching Qt events to the right
+ destination.
+
+ It returns 1 if the event was consumed by special handling, 0 if
+ the \a event was consumed by normal handling, and -1 if the \a
+ event was for an unrecognized widget.
+
+ \sa x11EventFilter()
+*/
+int QApplication::x11ProcessEvent(XEvent* event)
+{
+ Q_D(QApplication);
+ QScopedLoopLevelCounter loopLevelCounter(d->threadData);
+#ifdef ALIEN_DEBUG
+ //qDebug() << "QApplication::x11ProcessEvent:" << event->type;
+#endif
+ switch (event->type) {
+ case ButtonPress:
+ pressed_window = event->xbutton.window;
+ X11->userTime = event->xbutton.time;
+ // fallthrough intended
+ case ButtonRelease:
+ X11->time = event->xbutton.time;
+ break;
+ case MotionNotify:
+ X11->time = event->xmotion.time;
+ break;
+ case XKeyPress:
+ X11->userTime = event->xkey.time;
+ // fallthrough intended
+ case XKeyRelease:
+ X11->time = event->xkey.time;
+ break;
+ case PropertyNotify:
+ X11->time = event->xproperty.time;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ X11->time = event->xcrossing.time;
+ break;
+ case SelectionClear:
+ X11->time = event->xselectionclear.time;
+ break;
+ default:
+ break;
+ }
+#ifndef QT_NO_XFIXES
+ if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) {
+ XFixesSelectionNotifyEvent *req =
+ reinterpret_cast<XFixesSelectionNotifyEvent *>(event);
+ X11->time = req->selection_timestamp;
+ }
+#endif
+
+ QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
+
+ if (wPRmapper) { // just did a widget reparent?
+ if (widget == 0) { // not in std widget mapper
+ switch (event->type) { // only for mouse/key events
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case XKeyPress:
+ case XKeyRelease:
+ widget = qPRFindWidget(event->xany.window);
+ break;
+ }
+ }
+ else if (widget->testAttribute(Qt::WA_WState_Reparented))
+ qPRCleanup(widget); // remove from alt mapper
+ }
+
+ QETWidget *keywidget=0;
+ bool grabbed=false;
+ if (event->type==XKeyPress || event->type==XKeyRelease) {
+ keywidget = (QETWidget*)QWidget::keyboardGrabber();
+ if (keywidget) {
+ grabbed = true;
+ } else if (!keywidget) {
+ if (d->inPopupMode()) // no focus widget, see if we have a popup
+ keywidget = (QETWidget*) (activePopupWidget()->focusWidget() ? activePopupWidget()->focusWidget() : activePopupWidget());
+ else if (QApplicationPrivate::focus_widget)
+ keywidget = (QETWidget*)QApplicationPrivate::focus_widget;
+ else if (widget)
+ keywidget = (QETWidget*)widget->window();
+ }
+ }
+
+#ifndef QT_NO_IM
+ // Filtering input events by the input context. It has to be taken
+ // place before any other key event consumers such as eventfilters
+ // and accelerators because some input methods require quite
+ // various key combination and sequences. It often conflicts with
+ // accelerators and so on, so we must give the input context the
+ // filtering opportunity first to ensure all input methods work
+ // properly regardless of application design.
+
+ if(keywidget && keywidget->isEnabled() && keywidget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ // block user interaction during session management
+ if((event->type==XKeyPress || event->type==XKeyRelease) && qt_sm_blockUserInput)
+ return true;
+
+ // for XIM handling
+ QInputContext *qic = keywidget->inputContext();
+ if(qic && qic->x11FilterEvent(keywidget, event))
+ return true;
+
+ // filterEvent() accepts QEvent *event rather than preexpanded
+ // key event attribute values. This is intended to pass other
+ // QInputEvent in future. Other non IM-related events should
+ // not be forwarded to input contexts to prevent weird event
+ // handling.
+ if ((event->type == XKeyPress || event->type == XKeyRelease)) {
+ int code = -1;
+ int count = 0;
+ Qt::KeyboardModifiers modifiers;
+ QEvent::Type type;
+ QString text;
+ KeySym keySym;
+
+ qt_keymapper_private()->translateKeyEventInternal(keywidget, event, keySym, count,
+ text, modifiers, code, type, false);
+
+ // both key press/release is required for some complex
+ // input methods. don't eliminate anything.
+ QKeyEventEx keyevent(type, code, modifiers, text, false, qMax(qMax(count, 1), text.length()),
+ event->xkey.keycode, keySym, event->xkey.state);
+ if(qic && qic->filterEvent(&keyevent))
+ return true;
+ }
+ } else
+#endif // QT_NO_IM
+ {
+ if (XFilterEvent(event, XNone))
+ return true;
+ }
+
+ if (qt_x11EventFilter(event)) // send through app filter
+ return 1;
+
+ if (event->type == MappingNotify) {
+ // keyboard mapping changed
+ XRefreshKeyboardMapping(&event->xmapping);
+
+ QKeyMapper::changeKeyboard();
+ return 0;
+ }
+
+ if (!widget) { // don't know this windows
+ QWidget* popup = QApplication::activePopupWidget();
+ if (popup) {
+
+ /*
+ That is more than suboptimal. The real solution should
+ do some keyevent and buttonevent translation, so that
+ the popup still continues to work as the user expects.
+ Unfortunately this translation is currently only
+ possible with a known widget. I'll change that soon
+ (Matthias).
+ */
+
+ // Danger - make sure we don't lock the server
+ switch (event->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ case XKeyPress:
+ case XKeyRelease:
+ do {
+ popup->close();
+ } while ((popup = qApp->activePopupWidget()));
+ return 1;
+ }
+ }
+ return -1;
+ }
+
+ if (event->type == XKeyPress || event->type == XKeyRelease)
+ widget = keywidget; // send XKeyEvents through keywidget->x11Event()
+
+ if (app_do_modal) // modal event handling
+ if (!qt_try_modal(widget, event)) {
+ if (event->type == ClientMessage && !widget->x11Event(event))
+ x11ClientMessage(widget, event, true);
+ return 1;
+ }
+
+
+ if (widget->x11Event(event)) // send through widget filter
+ return 1;
+#if !defined (QT_NO_TABLET)
+ if (!qt_xdnd_dragging) {
+ QTabletDeviceDataList *tablets = qt_tablet_devices();
+ for (int i = 0; i < tablets->size(); ++i) {
+ QTabletDeviceData &tab = tablets->operator [](i);
+ if (event->type == tab.xinput_motion
+ || event->type == tab.xinput_button_release
+ || event->type == tab.xinput_button_press
+ || event->type == tab.xinput_proximity_in
+ || event->type == tab.xinput_proximity_out) {
+ widget->translateXinputEvent(event, &tab);
+ return 0;
+ }
+ }
+ }
+#endif
+
+#ifndef QT_NO_XRANDR
+ if (X11->use_xrandr && event->type == (X11->xrandr_eventbase + RRScreenChangeNotify)) {
+ // update Xlib internals with the latest screen configuration
+ X11->ptrXRRUpdateConfiguration(event);
+
+ // update the size for desktop widget
+ int scr = X11->ptrXRRRootToScreen(X11->display, event->xany.window);
+ QWidget *w = desktop()->screen(scr);
+ QSize oldSize(w->size());
+ w->data->crect.setWidth(DisplayWidth(X11->display, scr));
+ w->data->crect.setHeight(DisplayHeight(X11->display, scr));
+ if (w->size() != oldSize) {
+ QResizeEvent e(w->size(), oldSize);
+ QApplication::sendEvent(w, &e);
+ emit desktop()->resized(scr);
+ }
+ }
+#endif // QT_NO_XRANDR
+
+#ifndef QT_NO_XFIXES
+ if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) {
+ XFixesSelectionNotifyEvent *req = reinterpret_cast<XFixesSelectionNotifyEvent *>(event);
+
+ // compress all XFixes events related to this selection
+ // we don't want to handle old SelectionNotify events.
+ qt_xfixes_selection_event_data xfixes_event;
+ xfixes_event.selection = req->selection;
+ for (XEvent ev;;) {
+ if (!XCheckIfEvent(X11->display, &ev, &qt_xfixes_scanner, (XPointer)&xfixes_event))
+ break;
+ }
+
+ if (req->selection == ATOM(CLIPBOARD)) {
+ if (qt_xfixes_clipboard_changed(req->owner, req->selection_timestamp)) {
+ emit clipboard()->changed(QClipboard::Clipboard);
+ emit clipboard()->dataChanged();
+ }
+ } else if (req->selection == XA_PRIMARY) {
+ if (qt_xfixes_selection_changed(req->owner, req->selection_timestamp)) {
+ emit clipboard()->changed(QClipboard::Selection);
+ emit clipboard()->selectionChanged();
+ }
+ }
+ }
+#endif // QT_NO_XFIXES
+
+ switch (event->type) {
+
+ case ButtonRelease: // mouse event
+ if (!d->inPopupMode() && !QWidget::mouseGrabber() && pressed_window != widget->internalWinId()
+ && (widget = (QETWidget*) QWidget::find((WId)pressed_window)) == 0)
+ break;
+ // fall through intended
+ case ButtonPress:
+ if (event->xbutton.root != RootWindow(X11->display, widget->x11Info().screen())
+ && ! qt_xdnd_dragging) {
+ while (activePopupWidget())
+ activePopupWidget()->close();
+ return 1;
+ }
+ if (event->type == ButtonPress)
+ qt_net_update_user_time(widget->window(), X11->userTime);
+ // fall through intended
+ case MotionNotify:
+#if !defined(QT_NO_TABLET)
+ if (!qt_tabletChokeMouse) {
+#endif
+ if (widget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
+ QPoint pos(event->xbutton.x, event->xbutton.y);
+ pos = widget->d_func()->mapFromWS(pos);
+ QWidget *window = widget->window();
+ pos = widget->mapTo(window, pos);
+ if (QWidget *child = window->childAt(pos)) {
+ widget = static_cast<QETWidget *>(child);
+ pos = child->mapFrom(window, pos);
+ event->xbutton.x = pos.x();
+ event->xbutton.y = pos.y();
+ }
+ }
+ widget->translateMouseEvent(event);
+#if !defined(QT_NO_TABLET)
+ } else {
+ qt_tabletChokeMouse = false;
+ }
+#endif
+ break;
+
+ case XKeyPress: // keyboard event
+ qt_net_update_user_time(widget->window(), X11->userTime);
+ // fallthrough intended
+ case XKeyRelease:
+ {
+ if (keywidget && keywidget->isEnabled()) { // should always exist
+ // qDebug("sending key event");
+ qt_keymapper_private()->translateKeyEvent(keywidget, event, grabbed);
+ }
+ break;
+ }
+
+ case GraphicsExpose:
+ case Expose: // paint event
+ widget->translatePaintEvent(event);
+ break;
+
+ case ConfigureNotify: // window move/resize event
+ if (event->xconfigure.event == event->xconfigure.window)
+ widget->translateConfigEvent(event);
+ break;
+
+ case XFocusIn: { // got focus
+ if ((widget->windowType() == Qt::Desktop))
+ break;
+ if (d->inPopupMode()) // some delayed focus event to ignore
+ break;
+ if (!widget->isWindow())
+ break;
+ if (event->xfocus.detail != NotifyAncestor &&
+ event->xfocus.detail != NotifyInferior &&
+ event->xfocus.detail != NotifyNonlinear)
+ break;
+ setActiveWindow(widget);
+ if (X11->focus_model == QX11Data::FM_PointerRoot) {
+ // We got real input focus from somewhere, but we were in PointerRoot
+ // mode, so we don't trust this event. Check the focus model to make
+ // sure we know what focus mode we are using...
+ qt_check_focus_model();
+ }
+ }
+ break;
+
+ case XFocusOut: // lost focus
+ if ((widget->windowType() == Qt::Desktop))
+ break;
+ if (!widget->isWindow())
+ break;
+ if (event->xfocus.mode == NotifyGrab) {
+ qt_xfocusout_grab_counter++;
+ break;
+ }
+ if (event->xfocus.detail != NotifyAncestor &&
+ event->xfocus.detail != NotifyNonlinearVirtual &&
+ event->xfocus.detail != NotifyNonlinear)
+ break;
+ if (!d->inPopupMode() && widget == QApplicationPrivate::active_window) {
+ XEvent ev;
+ bool focus_will_change = false;
+ if (XCheckTypedEvent(X11->display, XFocusIn, &ev)) {
+ // we're about to get an XFocusIn, if we know we will
+ // get a new active window, we don't want to set the
+ // active window to 0 now
+ QWidget *w2 = QWidget::find(ev.xany.window);
+ if (w2
+ && w2->windowType() != Qt::Desktop
+ && !d->inPopupMode() // some delayed focus event to ignore
+ && w2->isWindow()
+ && (ev.xfocus.detail == NotifyAncestor
+ || ev.xfocus.detail == NotifyInferior
+ || ev.xfocus.detail == NotifyNonlinear))
+ focus_will_change = true;
+
+ XPutBackEvent(X11->display, &ev);
+ }
+ if (!focus_will_change)
+ setActiveWindow(0);
+ }
+ break;
+
+ case EnterNotify: { // enter window
+ if (QWidget::mouseGrabber() && (!d->inPopupMode() || widget->window() != activePopupWidget()))
+ break;
+ if ((event->xcrossing.mode != NotifyNormal
+ && event->xcrossing.mode != NotifyUngrab)
+ || event->xcrossing.detail == NotifyVirtual
+ || event->xcrossing.detail == NotifyNonlinearVirtual)
+ break;
+ if (event->xcrossing.focus &&
+ !(widget->windowType() == Qt::Desktop) && !widget->isActiveWindow()) {
+ if (X11->focus_model == QX11Data::FM_Unknown) // check focus model
+ qt_check_focus_model();
+ if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode
+ setActiveWindow(widget);
+ }
+
+ if (qt_button_down && !d->inPopupMode())
+ break;
+
+ QWidget *alien = widget->childAt(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x,
+ event->xcrossing.y)));
+ QWidget *enter = alien ? alien : widget;
+ QWidget *leave = 0;
+ if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
+ leave = qt_last_mouse_receiver;
+ else
+ leave = QWidget::find(curWin);
+
+ // ### Alien: enter/leave might be wrong here with overlapping siblings
+ // if the enter widget is native and stacked under a non-native widget.
+ QApplicationPrivate::dispatchEnterLeave(enter, leave);
+ curWin = widget->internalWinId();
+ qt_last_mouse_receiver = enter;
+ if (!d->inPopupMode() || widget->window() == activePopupWidget())
+ widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
+ }
+ break;
+ case LeaveNotify: { // leave window
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ if (mouseGrabber && !d->inPopupMode())
+ break;
+ if (curWin && widget->internalWinId() != curWin)
+ break;
+ if ((event->xcrossing.mode != NotifyNormal
+ && event->xcrossing.mode != NotifyUngrab)
+ || event->xcrossing.detail == NotifyInferior)
+ break;
+ if (!(widget->windowType() == Qt::Desktop))
+ widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
+
+ QWidget* enter = 0;
+ QPoint enterPoint;
+ XEvent ev;
+ while (XCheckMaskEvent(X11->display, EnterWindowMask | LeaveWindowMask , &ev)
+ && !qt_x11EventFilter(&ev)) {
+ QWidget* event_widget = QWidget::find(ev.xcrossing.window);
+ if(event_widget && event_widget->x11Event(&ev))
+ break;
+ if (ev.type == LeaveNotify
+ || (ev.xcrossing.mode != NotifyNormal
+ && ev.xcrossing.mode != NotifyUngrab)
+ || ev.xcrossing.detail == NotifyVirtual
+ || ev.xcrossing.detail == NotifyNonlinearVirtual)
+ continue;
+ enter = event_widget;
+ if (enter)
+ enterPoint = enter->d_func()->mapFromWS(QPoint(ev.xcrossing.x, ev.xcrossing.y));
+ if (ev.xcrossing.focus &&
+ enter && !(enter->windowType() == Qt::Desktop) && !enter->isActiveWindow()) {
+ if (X11->focus_model == QX11Data::FM_Unknown) // check focus model
+ qt_check_focus_model();
+ if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode
+ setActiveWindow(enter);
+ }
+ break;
+ }
+
+ if ((! enter || (enter->windowType() == Qt::Desktop)) &&
+ event->xcrossing.focus && widget == QApplicationPrivate::active_window &&
+ X11->focus_model == QX11Data::FM_PointerRoot // PointerRoot mode
+ ) {
+ setActiveWindow(0);
+ }
+
+ if (qt_button_down && !d->inPopupMode())
+ break;
+
+ if (!curWin)
+ QApplicationPrivate::dispatchEnterLeave(widget, 0);
+
+ if (enter) {
+ QWidget *alienEnter = enter->childAt(enterPoint);
+ if (alienEnter)
+ enter = alienEnter;
+ }
+
+ QWidget *leave = qt_last_mouse_receiver ? qt_last_mouse_receiver : widget;
+ QWidget *activePopupWidget = qApp->activePopupWidget();
+
+ if (mouseGrabber && activePopupWidget && leave == activePopupWidget)
+ enter = mouseGrabber;
+ else if (enter != widget && mouseGrabber) {
+ if (!widget->rect().contains(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x,
+ event->xcrossing.y))))
+ break;
+ }
+
+ QApplicationPrivate::dispatchEnterLeave(enter, leave);
+ qt_last_mouse_receiver = enter;
+
+ if (enter && QApplicationPrivate::tryModalHelper(enter, 0)) {
+ QWidget *nativeEnter = enter->internalWinId() ? enter : enter->nativeParentWidget();
+ curWin = nativeEnter->internalWinId();
+ static_cast<QETWidget *>(nativeEnter)->translateMouseEvent(&ev); //we don't get MotionNotify, emulate it
+ } else {
+ curWin = 0;
+ qt_last_mouse_receiver = 0;
+ }
+ }
+ break;
+
+ case UnmapNotify: // window hidden
+ if (widget->isWindow()) {
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ widget->d_func()->topData()->waitingForMapNotify = 0;
+
+ if (widget->windowType() != Qt::Popup && !widget->testAttribute(Qt::WA_DontShowOnScreen)) {
+ widget->setAttribute(Qt::WA_Mapped, false);
+ if (widget->isVisible()) {
+ widget->d_func()->topData()->spont_unmapped = 1;
+ QHideEvent e;
+ QApplication::sendSpontaneousEvent(widget, &e);
+ widget->d_func()->hideChildren(true);
+ }
+ }
+
+ if (!widget->d_func()->topData()->validWMState && X11->deferred_map.removeAll(widget))
+ widget->doDeferredMap();
+ }
+ break;
+
+ case MapNotify: // window shown
+ if (widget->isWindow()) {
+ widget->d_func()->topData()->waitingForMapNotify = 0;
+
+ if (widget->windowType() != Qt::Popup) {
+ widget->setAttribute(Qt::WA_Mapped);
+ if (widget->d_func()->topData()->spont_unmapped) {
+ widget->d_func()->topData()->spont_unmapped = 0;
+ widget->d_func()->showChildren(true);
+ QShowEvent e;
+ QApplication::sendSpontaneousEvent(widget, &e);
+
+ // show() must have been called on this widget in
+ // order to reach this point, but we could have
+ // cleared these 2 attributes in case something
+ // previously forced us into WithdrawnState
+ // (e.g. kdocker)
+ widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
+ widget->setAttribute(Qt::WA_WState_Visible, true);
+ }
+ }
+ }
+ break;
+
+ case ClientMessage: // client message
+ return x11ClientMessage(widget,event,False);
+
+ case ReparentNotify: { // window manager reparents
+ // compress old reparent events to self
+ XEvent ev;
+ while (XCheckTypedWindowEvent(X11->display,
+ widget->effectiveWinId(),
+ ReparentNotify,
+ &ev)) {
+ if (ev.xreparent.window != ev.xreparent.event) {
+ XPutBackEvent(X11->display, &ev);
+ break;
+ }
+ }
+ if (widget->isWindow()) {
+ QTLWExtra *topData = widget->d_func()->topData();
+
+ // store the parent. Useful for many things, embedding for instance.
+ topData->parentWinId = event->xreparent.parent;
+
+ // the widget frame strut should also be invalidated
+ widget->data->fstrut_dirty = 1;
+
+ // work around broken window managers... if we get a
+ // ReparentNotify before the MapNotify, we assume that
+ // we're being managed by a reparenting window
+ // manager.
+ //
+ // however, the WM_STATE property may not have been set
+ // yet, but we are going to assume that it will
+ // be... otherwise we could try to map again after getting
+ // an UnmapNotify... which could then, in turn, trigger a
+ // race in the window manager which causes the window to
+ // disappear when it really should be hidden.
+ if (topData->waitingForMapNotify && !topData->validWMState) {
+ topData->waitingForMapNotify = 0;
+ topData->validWMState = 1;
+ }
+
+ if (X11->focus_model != QX11Data::FM_Unknown) {
+ // toplevel reparented...
+ QWidget *newparent = QWidget::find(event->xreparent.parent);
+ if (! newparent || (newparent->windowType() == Qt::Desktop)) {
+ // we dont' know about the new parent (or we've been
+ // reparented to root), perhaps a window manager
+ // has been (re)started? reset the focus model to unknown
+ X11->focus_model = QX11Data::FM_Unknown;
+ }
+ }
+ }
+ break;
+ }
+ case SelectionRequest: {
+ XSelectionRequestEvent *req = &event->xselectionrequest;
+ if (! req)
+ break;
+
+ if (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)) {
+ X11->xdndHandleSelectionRequest(req);
+
+ } else if (qt_clipboard) {
+ QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
+ QApplication::sendSpontaneousEvent(qt_clipboard, &e);
+ }
+ break;
+ }
+ case SelectionClear: {
+ XSelectionClearEvent *req = &event->xselectionclear;
+ // don't deliver dnd events to the clipboard, it gets confused
+ if (! req || (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)))
+ break;
+
+ if (qt_clipboard && !X11->use_xfixes) {
+ QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
+ QApplication::sendSpontaneousEvent(qt_clipboard, &e);
+ }
+ break;
+ }
+
+ case SelectionNotify: {
+ XSelectionEvent *req = &event->xselection;
+ // don't deliver dnd events to the clipboard, it gets confused
+ if (! req || (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)))
+ break;
+
+ if (qt_clipboard) {
+ QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
+ QApplication::sendSpontaneousEvent(qt_clipboard, &e);
+ }
+ break;
+ }
+ case PropertyNotify:
+ // some properties changed
+ if (event->xproperty.window == QX11Info::appRootWindow(0)) {
+ // root properties for the first screen
+ if (!X11->use_xfixes && event->xproperty.atom == ATOM(_QT_CLIPBOARD_SENTINEL)) {
+ if (qt_check_clipboard_sentinel()) {
+ emit clipboard()->changed(QClipboard::Clipboard);
+ emit clipboard()->dataChanged();
+ }
+ } else if (!X11->use_xfixes && event->xproperty.atom == ATOM(_QT_SELECTION_SENTINEL)) {
+ if (qt_check_selection_sentinel()) {
+ emit clipboard()->changed(QClipboard::Selection);
+ emit clipboard()->selectionChanged();
+ }
+ } else if (QApplicationPrivate::obey_desktop_settings) {
+ if (event->xproperty.atom == ATOM(RESOURCE_MANAGER))
+ qt_set_x11_resources();
+ else if (event->xproperty.atom == ATOM(_QT_SETTINGS_TIMESTAMP))
+ qt_set_x11_resources();
+ }
+ }
+ if (event->xproperty.window == QX11Info::appRootWindow()) {
+ // root properties for the default screen
+ if (event->xproperty.atom == ATOM(_QT_INPUT_ENCODING)) {
+ qt_set_input_encoding();
+ } else if (event->xproperty.atom == ATOM(_NET_SUPPORTED)) {
+ qt_get_net_supported();
+ } else if (event->xproperty.atom == ATOM(_NET_VIRTUAL_ROOTS)) {
+ qt_get_net_virtual_roots();
+ } else if (event->xproperty.atom == ATOM(_NET_WORKAREA)) {
+ qt_desktopwidget_update_workarea();
+ }
+ } else if (widget) {
+ widget->translatePropertyEvent(event);
+ } else {
+ return -1; // don't know this window
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ \fn bool QApplication::x11EventFilter(XEvent *event)
+
+ \warning This virtual function is only implemented under X11.
+
+ If you create an application that inherits QApplication and
+ reimplement this function, you get direct access to all X events
+ that the are received from the X server. The events are passed in
+ the \a event parameter.
+
+ Return true if you want to stop the event from being processed.
+ Return false for normal event dispatching. The default
+ implementation returns false.
+
+ It is only the directly addressed messages that are filtered.
+ You must install an event filter directly on the event
+ dispatcher, which is returned by
+ QAbstractEventDispatcher::instance(), to handle system wide
+ messages.
+
+ \sa x11ProcessEvent()
+*/
+
+bool QApplication::x11EventFilter(XEvent *)
+{
+ return false;
+}
+
+
+
+/*****************************************************************************
+ Modal widgets; Since Xlib has little support for this we roll our own
+ modal widget mechanism.
+ A modal widget without a parent becomes application-modal.
+ A modal widget with a parent becomes modal to its parent and grandparents..
+
+ QApplicationPrivate::enterModal()
+ Enters modal state
+ Arguments:
+ QWidget *widget A modal widget
+
+ QApplicationPrivate::leaveModal()
+ Leaves modal state for a widget
+ Arguments:
+ QWidget *widget A modal widget
+ *****************************************************************************/
+
+bool QApplicationPrivate::modalState()
+{
+ return app_do_modal;
+}
+
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
+{
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+
+ QWidget *leave = qt_last_mouse_receiver;
+ if (!leave)
+ leave = QWidget::find((WId)curWin);
+ QApplicationPrivate::dispatchEnterLeave(0, leave);
+ qt_modal_stack->insert(0, widget);
+ app_do_modal = true;
+ curWin = 0;
+ qt_last_mouse_receiver = 0;
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *widget)
+{
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ QPoint p(QCursor::pos());
+ QWidget* w = QApplication::widgetAt(p.x(), p.y());
+ QWidget *leave = qt_last_mouse_receiver;
+ if (!leave)
+ leave = QWidget::find((WId)curWin);
+ if (QWidget *grabber = QWidget::mouseGrabber()) {
+ w = grabber;
+ if (leave == w)
+ leave = 0;
+ }
+ QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event
+ curWin = w ? w->effectiveWinId() : 0;
+ qt_last_mouse_receiver = w;
+ }
+ }
+ app_do_modal = qt_modal_stack != 0;
+}
+
+bool qt_try_modal(QWidget *widget, XEvent *event)
+{
+ if (qt_xdnd_dragging) {
+ // allow mouse events while DnD is active
+ switch (event->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ // allow mouse release events to be sent to widgets that have been pressed
+ if (event->type == ButtonRelease) {
+ QWidget *alienWidget = widget->childAt(widget->mapFromGlobal(QPoint(event->xbutton.x_root,
+ event->xbutton.y_root)));
+ if (widget == qt_button_down || (alienWidget && alienWidget == qt_button_down))
+ return true;
+ }
+
+ if (QApplicationPrivate::tryModalHelper(widget))
+ return true;
+
+ // disallow mouse/key events
+ switch (event->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case XKeyPress:
+ case XKeyRelease:
+ case EnterNotify:
+ case LeaveNotify:
+ case ClientMessage:
+ return false;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+
+/*****************************************************************************
+ Popup widget mechanism
+
+ openPopup()
+ Adds a widget to the list of popup widgets
+ Arguments:
+ QWidget *widget The popup widget to be added
+
+ closePopup()
+ Removes a widget from the list of popup widgets
+ Arguments:
+ QWidget *widget The popup widget to be removed
+ *****************************************************************************/
+
+
+static int openPopupCount = 0;
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ Q_Q(QApplication);
+ openPopupCount++;
+ if (!QApplicationPrivate::popupWidgets) { // create list
+ QApplicationPrivate::popupWidgets = new QWidgetList;
+ }
+ QApplicationPrivate::popupWidgets->append(popup); // add to end of list
+ Display *dpy = X11->display;
+ if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ int r = XGrabKeyboard(dpy, popup->effectiveWinId(), false,
+ GrabModeAsync, GrabModeAsync, X11->time);
+ if ((popupGrabOk = (r == GrabSuccess))) {
+ r = XGrabPointer(dpy, popup->effectiveWinId(), true,
+ (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+ | EnterWindowMask | LeaveWindowMask | PointerMotionMask),
+ GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time);
+ if (!(popupGrabOk = (r == GrabSuccess))) {
+ // transfer grab back to the keyboard grabber if any
+ if (QWidgetPrivate::keyboardGrabber != 0)
+ QWidgetPrivate::keyboardGrabber->grabKeyboard();
+ else
+ XUngrabKeyboard(dpy, X11->time);
+ }
+ }
+ }
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ q->sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ Q_Q(QApplication);
+ if (!QApplicationPrivate::popupWidgets)
+ return;
+ QApplicationPrivate::popupWidgets->removeAll(popup);
+ if (popup == qt_popup_down) {
+ qt_button_down = 0;
+ qt_popup_down = 0;
+ }
+ if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+ if (!qt_nograb() && popupGrabOk) { // grabbing not disabled
+ Display *dpy = X11->display;
+ if (popup->geometry().contains(QPoint(mouseGlobalXPos, mouseGlobalYPos))
+ || popup->testAttribute(Qt::WA_NoMouseReplay)) {
+ // mouse release event or inside
+ replayPopupMouseEvent = false;
+ } else { // mouse press event
+ mouseButtonPressTime -= 10000; // avoid double click
+ replayPopupMouseEvent = true;
+ }
+ // transfer grab back to mouse grabber if any, otherwise release the grab
+ if (QWidgetPrivate::mouseGrabber != 0)
+ QWidgetPrivate::mouseGrabber->grabMouse();
+ else
+ XUngrabPointer(dpy, X11->time);
+
+ // transfer grab back to keyboard grabber if any, otherwise release the grab
+ if (QWidgetPrivate::keyboardGrabber != 0)
+ QWidgetPrivate::keyboardGrabber->grabKeyboard();
+ else
+ XUngrabKeyboard(dpy, X11->time);
+
+ XFlush(dpy);
+ }
+ if (QApplicationPrivate::active_window) {
+ if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q->sendEvent(fw, &e);
+ }
+ }
+ }
+ } else {
+ // popups are not focus-handled by the window system (the
+ // first popup grabbed the keyboard), so we have to do that
+ // manually: A popup was closed, so the previous popup gets
+ // the focus.
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+
+ // regrab the keyboard and mouse in case 'popup' lost the grab
+ if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard
+ Display *dpy = X11->display;
+ Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created));
+ int r = XGrabKeyboard(dpy, aw->effectiveWinId(), false,
+ GrabModeAsync, GrabModeAsync, X11->time);
+ if ((popupGrabOk = (r == GrabSuccess))) {
+ r = XGrabPointer(dpy, aw->effectiveWinId(), true,
+ (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+ | EnterWindowMask | LeaveWindowMask | PointerMotionMask),
+ GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time);
+ if (!(popupGrabOk = (r == GrabSuccess))) {
+ // transfer grab back to keyboard grabber
+ if (QWidgetPrivate::keyboardGrabber != 0)
+ QWidgetPrivate::keyboardGrabber->grabKeyboard();
+ else
+ XUngrabKeyboard(dpy, X11->time);
+ }
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ Event translation; translates X11 events to Qt events
+ *****************************************************************************/
+
+//
+// Mouse event translation
+//
+// Xlib doesn't give mouse double click events, so we generate them by
+// comparing window, time and position between two mouse press events.
+//
+
+static Qt::MouseButtons translateMouseButtons(int s)
+{
+ Qt::MouseButtons ret = 0;
+ if (s & Button1Mask)
+ ret |= Qt::LeftButton;
+ if (s & Button2Mask)
+ ret |= Qt::MidButton;
+ if (s & Button3Mask)
+ ret |= Qt::RightButton;
+ return ret;
+}
+
+Qt::KeyboardModifiers QX11Data::translateModifiers(int s)
+{
+ Qt::KeyboardModifiers ret = 0;
+ if (s & ShiftMask)
+ ret |= Qt::ShiftModifier;
+ if (s & ControlMask)
+ ret |= Qt::ControlModifier;
+ if (s & qt_alt_mask)
+ ret |= Qt::AltModifier;
+ if (s & qt_meta_mask)
+ ret |= Qt::MetaModifier;
+ if (s & qt_mode_switch_mask)
+ ret |= Qt::GroupSwitchModifier;
+ return ret;
+}
+
+bool QETWidget::translateMouseEvent(const XEvent *event)
+{
+ if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
+ Q_ASSERT(internalWinId());
+
+ Q_D(QWidget);
+ QEvent::Type type; // event parameters
+ QPoint pos;
+ QPoint globalPos;
+ Qt::MouseButton button = Qt::NoButton;
+ Qt::MouseButtons buttons;
+ Qt::KeyboardModifiers modifiers;
+ XEvent nextEvent;
+
+ if (qt_sm_blockUserInput) // block user interaction during session management
+ return true;
+
+ if (event->type == MotionNotify) { // mouse move
+ if (event->xmotion.root != RootWindow(X11->display, x11Info().screen()) &&
+ ! qt_xdnd_dragging)
+ return false;
+
+ XMotionEvent lastMotion = event->xmotion;
+ while(XPending(X11->display)) { // compress mouse moves
+ XNextEvent(X11->display, &nextEvent);
+ if (nextEvent.type == ConfigureNotify
+ || nextEvent.type == PropertyNotify
+ || nextEvent.type == Expose
+ || nextEvent.type == GraphicsExpose
+ || nextEvent.type == NoExpose
+ || nextEvent.type == KeymapNotify
+ || ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
+ && qt_button_down == this)
+ || (nextEvent.type == ClientMessage
+ && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) {
+ qApp->x11ProcessEvent(&nextEvent);
+ continue;
+ } else if (nextEvent.type != MotionNotify ||
+ nextEvent.xmotion.window != event->xmotion.window ||
+ nextEvent.xmotion.state != event->xmotion.state) {
+ XPutBackEvent(X11->display, &nextEvent);
+ break;
+ }
+ if (!qt_x11EventFilter(&nextEvent)
+ && !x11Event(&nextEvent)) // send event through filter
+ lastMotion = nextEvent.xmotion;
+ else
+ break;
+ }
+ type = QEvent::MouseMove;
+ pos.rx() = lastMotion.x;
+ pos.ry() = lastMotion.y;
+ pos = d->mapFromWS(pos);
+ globalPos.rx() = lastMotion.x_root;
+ globalPos.ry() = lastMotion.y_root;
+ buttons = translateMouseButtons(lastMotion.state);
+ modifiers = X11->translateModifiers(lastMotion.state);
+ if (qt_button_down && !buttons)
+ qt_button_down = 0;
+ } else if (event->type == EnterNotify || event->type == LeaveNotify) {
+ XEvent *xevent = (XEvent *)event;
+ //unsigned int xstate = event->xcrossing.state;
+ type = QEvent::MouseMove;
+ pos.rx() = xevent->xcrossing.x;
+ pos.ry() = xevent->xcrossing.y;
+ pos = d->mapFromWS(pos);
+ globalPos.rx() = xevent->xcrossing.x_root;
+ globalPos.ry() = xevent->xcrossing.y_root;
+ buttons = translateMouseButtons(xevent->xcrossing.state);
+ modifiers = X11->translateModifiers(xevent->xcrossing.state);
+ if (qt_button_down && !buttons)
+ qt_button_down = 0;
+ if (qt_button_down)
+ return true;
+ } else { // button press or release
+ pos.rx() = event->xbutton.x;
+ pos.ry() = event->xbutton.y;
+ pos = d->mapFromWS(pos);
+ globalPos.rx() = event->xbutton.x_root;
+ globalPos.ry() = event->xbutton.y_root;
+ buttons = translateMouseButtons(event->xbutton.state);
+ modifiers = X11->translateModifiers(event->xbutton.state);
+ switch (event->xbutton.button) {
+ case Button1: button = Qt::LeftButton; break;
+ case Button2: button = Qt::MidButton; break;
+ case Button3: button = Qt::RightButton; break;
+ case Button4:
+ case Button5:
+ case 6:
+ case 7:
+ // the fancy mouse wheel.
+
+ // We are only interested in ButtonPress.
+ if (event->type == ButtonPress){
+ // compress wheel events (the X Server will simply
+ // send a button press for each single notch,
+ // regardless whether the application can catch up
+ // or not)
+ int delta = 1;
+ XEvent xevent;
+ while (XCheckTypedWindowEvent(X11->display, effectiveWinId(), ButtonPress, &xevent)){
+ if (xevent.xbutton.button != event->xbutton.button){
+ XPutBackEvent(X11->display, &xevent);
+ break;
+ }
+ delta++;
+ }
+
+ // the delta is defined as multiples of
+ // WHEEL_DELTA, which is set to 120. Future wheels
+ // may offer a finer-resolution. A positive delta
+ // indicates forward rotation, a negative one
+ // backward rotation respectively.
+ int btn = event->xbutton.button;
+ delta *= 120 * ((btn == Button4 || btn == 6) ? 1 : -1);
+ bool hor = (((btn == Button4 || btn == Button5) && (modifiers & Qt::AltModifier)) ||
+ (btn == 6 || btn == 7));
+ translateWheelEvent(globalPos.x(), globalPos.y(), delta, buttons,
+ modifiers, (hor) ? Qt::Horizontal: Qt::Vertical);
+ }
+ return true;
+ case 8: button = Qt::XButton1; break;
+ case 9: button = Qt::XButton2; break;
+ }
+ if (event->type == ButtonPress) { // mouse button pressed
+ buttons |= button;
+#if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET)
+ QTabletDeviceDataList *tablets = qt_tablet_devices();
+ for (int i = 0; i < tablets->size(); ++i) {
+ QTabletDeviceData &tab = tablets->operator[](i);
+ XEvent myEv;
+ if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) {
+ if (translateXinputEvent(&myEv, &tab)) {
+ //Spontaneous event sent. Check if we need to continue.
+ if (qt_tabletChokeMouse) {
+ qt_tabletChokeMouse = false;
+ return false;
+ }
+ }
+ }
+ }
+#endif
+ if (!qt_button_down) {
+ qt_button_down = childAt(pos); //magic for masked widgets
+ if (!qt_button_down)
+ qt_button_down = this;
+ }
+ if (mouseActWindow == event->xbutton.window &&
+ mouseButtonPressed == button &&
+ (long)event->xbutton.time -(long)mouseButtonPressTime
+ < QApplication::doubleClickInterval() &&
+ qAbs(event->xbutton.x - mouseXPos) < 5 &&
+ qAbs(event->xbutton.y - mouseYPos) < 5) {
+ type = QEvent::MouseButtonDblClick;
+ mouseButtonPressTime -= 2000; // no double-click next time
+ } else {
+ type = QEvent::MouseButtonPress;
+ mouseButtonPressTime = event->xbutton.time;
+ }
+ mouseButtonPressed = button; // save event params for
+ mouseXPos = event->xbutton.x; // future double click tests
+ mouseYPos = event->xbutton.y;
+ mouseGlobalXPos = globalPos.x();
+ mouseGlobalYPos = globalPos.y();
+ } else { // mouse button released
+ buttons &= ~button;
+#if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET)
+ QTabletDeviceDataList *tablets = qt_tablet_devices();
+ for (int i = 0; i < tablets->size(); ++i) {
+ QTabletDeviceData &tab = tablets->operator[](i);
+ XEvent myEv;
+ if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) {
+ if (translateXinputEvent(&myEv, &tab)) {
+ //Spontaneous event sent. Check if we need to continue.
+ if (qt_tabletChokeMouse) {
+ qt_tabletChokeMouse = false;
+ return false;
+ }
+ }
+ }
+ }
+#endif
+ type = QEvent::MouseButtonRelease;
+ }
+ }
+ mouseActWindow = effectiveWinId(); // save some event params
+ mouseButtonState = buttons;
+ if (type == 0) // don't send event
+ return false;
+
+ if (qApp->d_func()->inPopupMode()) { // in popup mode
+ QWidget *activePopupWidget = qApp->activePopupWidget();
+ QWidget *popup = qApp->activePopupWidget();
+ if (popup != this) {
+ if (event->type == LeaveNotify)
+ return false;
+ if ((windowType() == Qt::Popup) && rect().contains(pos) && 0)
+ popup = this;
+ else // send to last popup
+ pos = popup->mapFromGlobal(globalPos);
+ }
+ bool releaseAfter = false;
+ QWidget *popupChild = popup->childAt(pos);
+
+ if (popup != qt_popup_down){
+ qt_button_down = 0;
+ qt_popup_down = 0;
+ }
+
+ switch (type) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ qt_button_down = popupChild;
+ qt_popup_down = popup;
+ break;
+ case QEvent::MouseButtonRelease:
+ releaseAfter = true;
+ break;
+ default:
+ break; // nothing for mouse move
+ }
+
+ int oldOpenPopupCount = openPopupCount;
+
+ if (popup->isEnabled()) {
+ // deliver event
+ replayPopupMouseEvent = false;
+ QWidget *receiver = popup;
+ QPoint widgetPos = pos;
+ if (qt_button_down)
+ receiver = qt_button_down;
+ else if (popupChild)
+ receiver = popupChild;
+ if (receiver != popup)
+ widgetPos = receiver->mapFromGlobal(globalPos);
+ QWidget *alien = childAt(mapFromGlobal(globalPos));
+ QMouseEvent e(type, widgetPos, globalPos, button, buttons, modifiers);
+ QApplicationPrivate::sendMouseEvent(receiver, &e, alien, this, &qt_button_down, qt_last_mouse_receiver);
+ } else {
+ // close disabled popups when a mouse button is pressed or released
+ switch (type) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonRelease:
+ popup->close();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (qApp->activePopupWidget() != activePopupWidget
+ && replayPopupMouseEvent) {
+ // the active popup was closed, replay the mouse event
+ if (!(windowType() == Qt::Popup)) {
+#if 1
+ qt_button_down = 0;
+#else
+ if (buttons == button)
+ qt_button_down = this;
+ QMouseEvent e(type, mapFromGlobal(globalPos), globalPos, button,
+ buttons, modifiers);
+ QApplication::sendSpontaneousEvent(this, &e);
+
+ if (type == QEvent::MouseButtonPress
+ && button == Qt::RightButton
+ && (openPopupCount == oldOpenPopupCount)) {
+ QContextMenuEvent e(QContextMenuEvent::Mouse, mapFromGlobal(globalPos),
+ globalPos, modifiers);
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
+#endif
+ }
+ replayPopupMouseEvent = false;
+ } else if (type == QEvent::MouseButtonPress
+ && button == Qt::RightButton
+ && (openPopupCount == oldOpenPopupCount)) {
+ QWidget *popupEvent = popup;
+ if (qt_button_down)
+ popupEvent = qt_button_down;
+ else if(popupChild)
+ popupEvent = popupChild;
+ QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers);
+ QApplication::sendSpontaneousEvent(popupEvent, &e);
+ }
+
+ if (releaseAfter) {
+ qt_button_down = 0;
+ qt_popup_down = 0;
+ }
+ } else {
+ QWidget *alienWidget = childAt(pos);
+ QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type, buttons,
+ qt_button_down, alienWidget);
+ if (!widget) {
+ if (type == QEvent::MouseButtonRelease)
+ QApplicationPrivate::mouse_buttons &= ~button;
+ return false; // don't send event
+ }
+
+ int oldOpenPopupCount = openPopupCount;
+ QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
+ QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
+ qt_last_mouse_receiver);
+
+ if (type == QEvent::MouseButtonPress
+ && button == Qt::RightButton
+ && (openPopupCount == oldOpenPopupCount)) {
+ QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers);
+ QApplication::sendSpontaneousEvent(widget, &e);
+ }
+ }
+ return true;
+}
+
+
+//
+// Wheel event translation
+//
+bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ Qt::Orientation orient)
+{
+ const QPoint globalPos = QPoint(global_x, global_y);
+ QPoint pos = mapFromGlobal(globalPos);
+ QWidget *widget = childAt(pos);
+ if (!widget)
+ widget = this;
+ else if (!widget->internalWinId())
+ pos = widget->mapFromGlobal(globalPos);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QETWidget::translateWheelEvent: receiver:" << widget << "pos:" << pos;
+#endif
+
+ // send the event to the widget or its ancestors
+ {
+ QWidget* popup = qApp->activePopupWidget();
+ if (popup && window() != popup)
+ popup->close();
+ QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
+ if (QApplication::sendSpontaneousEvent(widget, &e))
+ return true;
+ }
+
+ // send the event to the widget that has the focus or its ancestors, if different
+ if (widget != qApp->focusWidget() && (widget = qApp->focusWidget())) {
+ if (widget && !widget->internalWinId())
+ pos = widget->mapFromGlobal(globalPos);
+ QWidget* popup = qApp->activePopupWidget();
+ if (popup && widget != popup)
+ popup->hide();
+ QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
+ if (QApplication::sendSpontaneousEvent(widget, &e))
+ return true;
+ }
+ return false;
+}
+
+
+//
+// XInput Translation Event
+//
+#if !defined (QT_NO_TABLET)
+
+#if !defined (Q_OS_IRIX)
+void fetchWacomToolId(int &deviceType, qint64 &serialId)
+{
+ if (ptrWacomConfigInit == 0) // we actually have the lib
+ return;
+ WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0);
+ if (config == 0)
+ return;
+ const char *name = "stylus"; // TODO get this from the X config instead (users may have called it differently)
+ WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, name);
+ if (device == 0)
+ return;
+ unsigned keys[1];
+ int serialInt;
+ ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLSERIAL, &serialInt, 1, keys);
+ serialId = serialInt;
+ int toolId;
+ ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLID, &toolId, 1, keys);
+ switch(toolId) {
+ case 0x007: /* Mouse 4D and 2D */
+ case 0x017: /* Intuos3 2D Mouse */
+ case 0x094:
+ case 0x09c:
+ deviceType = QTabletEvent::FourDMouse;
+ break;
+ case 0x096: /* Lens cursor */
+ case 0x097: /* Intuos3 Lens cursor */
+ deviceType = QTabletEvent::Puck;
+ break;
+ case 0x0fa:
+ case 0x81b: /* Intuos3 Classic Pen Eraser */
+ case 0x82a: /* Eraser */
+ case 0x82b: /* Intuos3 Grip Pen Eraser */
+ case 0x85a:
+ case 0x91a:
+ case 0x91b: /* Intuos3 Airbrush Eraser */
+ case 0xd1a:
+ deviceType = QTabletEvent::XFreeEraser;
+ break;
+ case 0x112:
+ case 0x912:
+ case 0x913: /* Intuos3 Airbrush */
+ case 0xd12:
+ deviceType = QTabletEvent::Airbrush;
+ break;
+ case 0x012:
+ case 0x022:
+ case 0x032:
+ case 0x801: /* Intuos3 Inking pen */
+ case 0x812: /* Inking pen */
+ case 0x813: /* Intuos3 Classic Pen */
+ case 0x822: /* Pen */
+ case 0x823: /* Intuos3 Grip Pen */
+ case 0x832: /* Stroke pen */
+ case 0x842:
+ case 0x852:
+ case 0x885: /* Intuos3 Marker Pen */
+ default: /* Unknown tool */
+ deviceType = QTabletEvent::Stylus;
+ }
+
+ /* Close device and return */
+ ptrWacomConfigCloseDevice (device);
+ ptrWacomConfigTerm(config);
+}
+#endif
+
+bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet)
+{
+#if defined (Q_OS_IRIX)
+ // Wacom has put defines in their wacom.h file so it would be quite wise
+ // to use them, need to think of a decent way of not using
+ // it when it doesn't exist...
+ XDeviceState *s;
+ XInputClass *iClass;
+ XValuatorState *vs;
+ int j;
+#endif
+
+ Q_ASSERT(tablet != 0);
+
+ QWidget *w = this;
+ QPoint global,
+ curr;
+ QPointF hiRes;
+ qreal pressure = 0;
+ int xTilt = 0,
+ yTilt = 0,
+ z = 0;
+ qreal tangentialPressure = 0;
+ qreal rotation = 0;
+ int deviceType = QTabletEvent::NoDevice;
+ int pointerType = QTabletEvent::UnknownPointer;
+ XEvent xinputMotionEvent;
+ XEvent mouseMotionEvent;
+ const XDeviceMotionEvent *motion = 0;
+ XDeviceButtonEvent *button = 0;
+ const XProximityNotifyEvent *proximity = 0;
+ QEvent::Type t;
+ Qt::KeyboardModifiers modifiers = 0;
+ bool reinsertMouseEvent = false;
+ bool neverFoundMouseEvent = true;
+ XEvent xinputMotionEventNext;
+ XEvent mouseMotionEventSave;
+#if !defined (Q_OS_IRIX)
+ XID device_id;
+#endif
+
+ if (ev->type == tablet->xinput_motion) {
+ motion = reinterpret_cast<const XDeviceMotionEvent*>(ev);
+ for (;;) {
+ // get the corresponding mouseMotionEvent for motion
+ if (XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent)) {
+ mouseMotionEventSave = mouseMotionEvent;
+ reinsertMouseEvent = true;
+ neverFoundMouseEvent = false;
+
+ if (mouseMotionEvent.xmotion.time > motion->time) {
+ XEvent xinputMotionEventLoop = *ev;
+
+ // xinput event is older than the mouse event --> search for the corresponding xinput event for the given mouse event
+ while (mouseMotionEvent.xmotion.time > (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEventLoop))->time) {
+ if (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) {
+ xinputMotionEvent = xinputMotionEventLoop;
+ }
+ else {
+ break;
+ }
+ }
+ motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent);
+ }
+
+ // get the next xinputMotionEvent, for the next loop run
+ if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventNext)) {
+ XPutBackEvent(X11->display, &mouseMotionEvent);
+ reinsertMouseEvent = false;
+ break;
+ }
+
+ if (mouseMotionEvent.xmotion.time != motion->time) {
+ // reinsert in order
+ if (mouseMotionEvent.xmotion.time >= motion->time) {
+ XPutBackEvent(X11->display, &mouseMotionEvent);
+ XPutBackEvent(X11->display, &xinputMotionEventNext);
+ // next entry in queue is xinputMotionEventNext
+ }
+ else {
+ XPutBackEvent(X11->display, &xinputMotionEventNext);
+ XPutBackEvent(X11->display, &mouseMotionEvent);
+ // next entry in queue is mouseMotionEvent
+ }
+ reinsertMouseEvent = false;
+ break;
+ }
+ }
+ else {
+ break;
+ }
+
+ xinputMotionEvent = xinputMotionEventNext;
+ motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent));
+ }
+
+ if (reinsertMouseEvent) {
+ XPutBackEvent(X11->display, &mouseMotionEventSave);
+ }
+
+ if (neverFoundMouseEvent) {
+ XEvent xinputMotionEventLoop;
+ bool eventFound = false;
+ // xinput event without mouseMotionEvent --> search the newest xinputMotionEvent
+ while (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) {
+ xinputMotionEvent = xinputMotionEventLoop;
+ eventFound = true;
+ }
+ if (eventFound) motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent);
+ }
+
+ t = QEvent::TabletMove;
+ global = QPoint(motion->x_root, motion->y_root);
+ curr = QPoint(motion->x, motion->y);
+#if !defined (Q_OS_IRIX)
+ device_id = motion->deviceid;
+#endif
+ } else if (ev->type == tablet->xinput_button_press || ev->type == tablet->xinput_button_release) {
+ if (ev->type == tablet->xinput_button_press) {
+ t = QEvent::TabletPress;
+ } else {
+ t = QEvent::TabletRelease;
+ }
+ button = (XDeviceButtonEvent*)ev;
+
+ global = QPoint(button->x_root, button->y_root);
+ curr = QPoint(button->x, button->y);
+#if !defined (Q_OS_IRIX)
+ device_id = button->deviceid;
+#endif
+ } else { // Proximity
+ if (ev->type == tablet->xinput_proximity_in)
+ t = QEvent::TabletEnterProximity;
+ else
+ t = QEvent::TabletLeaveProximity;
+ proximity = (const XProximityNotifyEvent*)ev;
+#if !defined (Q_OS_IRIX)
+ device_id = proximity->deviceid;
+#endif
+ }
+
+ qint64 uid = 0;
+#if defined (Q_OS_IRIX)
+ QRect screenArea = qApp->desktop()->screenGeometry(this);
+ s = XQueryDeviceState(X11->display, static_cast<XDevice *>(tablet->device));
+ if (!s)
+ return false;
+ iClass = s->data;
+ for (j = 0; j < s->num_classes; j++) {
+ if (iClass->c_class == ValuatorClass) {
+ vs = reinterpret_cast<XValuatorState *>(iClass);
+ // figure out what device we have, based on bitmasking...
+ if (vs->valuators[WAC_TRANSDUCER_I]
+ & WAC_TRANSDUCER_PROX_MSK) {
+ switch (vs->valuators[WAC_TRANSDUCER_I]
+ & WAC_TRANSDUCER_MSK) {
+ case WAC_PUCK_ID:
+ pointerType = QTabletEvent::Puck;
+ break;
+ case WAC_STYLUS_ID:
+ pointerType = QTabletEvent::Pen;
+ break;
+ case WAC_ERASER_ID:
+ pointerType = QTabletEvent::Eraser;
+ break;
+ }
+ // Get a Unique Id for the device, Wacom gives us this ability
+ uid = vs->valuators[WAC_TRANSDUCER_I] & WAC_TRANSDUCER_ID_MSK;
+ uid = (uid << 24) | vs->valuators[WAC_SERIAL_NUM_I];
+ switch (WAC_TRANSDUCER_I & 0x0F0600) {
+ case 0x080200:
+ deviceType = QTabletEvent::Stylus;
+ break;
+ case 0x090200:
+ deviceType = QTabletEvent::Airbrush;
+ break;
+ case 0x000400:
+ deviceType = QTabletEvent::FourDMouse;
+ break;
+ case 0x000600:
+ deviceType = QTabletEvent::Puck;
+ break;
+ case 0x080400:
+ deviceType = QTabletEvent::RotationStylus;
+ break;
+ }
+ } else {
+ pointerType = QTabletEvent::UnknownPointer;
+ deviceType = QTabletEvent::NoDevice;
+ uid = 0;
+ }
+
+ if (!proximity) {
+ // apparently Wacom needs a cast for the +/- values to make sense
+ xTilt = short(vs->valuators[WAC_XTILT_I]);
+ yTilt = short(vs->valuators[WAC_YTILT_I]);
+ pressure = vs->valuators[WAC_PRESSURE_I];
+ if (deviceType == QTabletEvent::FourDMouse
+ || deviceType == QTabletEvent::RotationStylus) {
+ rotation = vs->valuators[WAC_ROTATION_I] / 64.0;
+ if (deviceType == QTabletEvent::FourDMouse)
+ z = vs->valuators[WAC_ZCOORD_I];
+ } else if (deviceType == QTabletEvent::Airbrush) {
+ tangentialPressure = vs->valuators[WAC_TAN_PRESSURE_I]
+ / qreal(tablet->maxTanPressure - tablet->minTanPressure);
+ }
+
+ hiRes = tablet->scaleCoord(vs->valuators[WAC_XCOORD_I], vs->valuators[WAC_YCOORD_I],
+ screenArea.x(), screenArea.width(),
+ screenArea.y(), screenArea.height());
+ }
+ break;
+ }
+ iClass = reinterpret_cast<XInputClass*>(reinterpret_cast<char*>(iClass) + iClass->length);
+ }
+ XFreeDeviceState(s);
+#else
+ QTabletDeviceDataList *tablet_list = qt_tablet_devices();
+ for (int i = 0; i < tablet_list->size(); ++i) {
+ const QTabletDeviceData &t = tablet_list->at(i);
+ if (device_id == static_cast<XDevice *>(t.device)->device_id) {
+ deviceType = t.deviceType;
+ if (t.deviceType == QTabletEvent::XFreeEraser) {
+ deviceType = QTabletEvent::Stylus;
+ pointerType = QTabletEvent::Eraser;
+ } else if (t.deviceType == QTabletEvent::Stylus) {
+ pointerType = QTabletEvent::Pen;
+ }
+ break;
+ }
+ }
+
+ fetchWacomToolId(deviceType, uid);
+
+ QRect screenArea = qApp->desktop()->rect();
+ if (motion) {
+ xTilt = (short) motion->axis_data[3];
+ yTilt = (short) motion->axis_data[4];
+ rotation = ((short) motion->axis_data[5]) / 64.0;
+ pressure = (short) motion->axis_data[2];
+ modifiers = X11->translateModifiers(motion->state);
+ hiRes = tablet->scaleCoord(motion->axis_data[0], motion->axis_data[1],
+ screenArea.x(), screenArea.width(),
+ screenArea.y(), screenArea.height());
+ } else if (button) {
+ xTilt = (short) button->axis_data[3];
+ yTilt = (short) button->axis_data[4];
+ rotation = ((short) button->axis_data[5]) / 64.0;
+ pressure = (short) button->axis_data[2];
+ modifiers = X11->translateModifiers(button->state);
+ hiRes = tablet->scaleCoord(button->axis_data[0], button->axis_data[1],
+ screenArea.x(), screenArea.width(),
+ screenArea.y(), screenArea.height());
+ } else if (proximity) {
+ pressure = 0;
+ modifiers = 0;
+ }
+ if (deviceType == QTabletEvent::Airbrush) {
+ tangentialPressure = rotation;
+ rotation = 0.;
+ }
+#endif
+
+ QWidget *child = w->childAt(curr);
+ if (child) {
+ w = child;
+ curr = w->mapFromGlobal(global);
+ }
+
+ if (t == QEvent::TabletPress) {
+ tablet->widgetToGetPress = w;
+ } else if (t == QEvent::TabletRelease && tablet->widgetToGetPress) {
+ w = tablet->widgetToGetPress;
+ curr = w->mapFromGlobal(global);
+ tablet->widgetToGetPress = 0;
+ }
+
+ QTabletEvent e(t, curr, global, hiRes,
+ deviceType, pointerType,
+ qreal(pressure / qreal(tablet->maxPressure - tablet->minPressure)),
+ xTilt, yTilt, tangentialPressure, rotation, z, modifiers, uid);
+ if (proximity)
+ QApplication::sendSpontaneousEvent(qApp, &e);
+ else
+ QApplication::sendSpontaneousEvent(w, &e);
+ return true;
+}
+#endif
+
+bool QETWidget::translatePropertyEvent(const XEvent *event)
+{
+ Q_D(QWidget);
+ if (!isWindow()) return true;
+
+ Atom ret;
+ int format, e;
+ unsigned char *data = 0;
+ unsigned long nitems, after;
+
+ if (event->xproperty.atom == ATOM(_KDE_NET_WM_FRAME_STRUT)) {
+ this->data->fstrut_dirty = 1;
+
+ if (event->xproperty.state == PropertyNewValue) {
+ e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_KDE_NET_WM_FRAME_STRUT),
+ 0, 4, // struts are 4 longs
+ False, XA_CARDINAL, &ret, &format, &nitems, &after, &data);
+
+ if (e == Success && ret == XA_CARDINAL &&
+ format == 32 && nitems == 4) {
+ long *strut = (long *) data;
+ d->topData()->frameStrut.setCoords(strut[0], strut[2], strut[1], strut[3]);
+ this->data->fstrut_dirty = 0;
+ }
+ }
+ } else if (event->xproperty.atom == ATOM(_NET_WM_STATE)) {
+ bool max = false;
+ bool full = false;
+ Qt::WindowStates oldState = Qt::WindowStates(this->data->window_state);
+
+ if (event->xproperty.state == PropertyNewValue) {
+ // using length of 1024 should be safe for all current and
+ // possible NET states...
+ e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_NET_WM_STATE), 0, 1024,
+ False, XA_ATOM, &ret, &format, &nitems, &after, &data);
+
+ if (e == Success && ret == XA_ATOM && format == 32 && nitems > 0) {
+ Atom *states = (Atom *) data;
+
+ unsigned long i;
+ uint maximized = 0;
+ for (i = 0; i < nitems; i++) {
+ if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
+ maximized |= 1;
+ else if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
+ maximized |= 2;
+ else if (states[i] == ATOM(_NET_WM_STATE_FULLSCREEN))
+ full = true;
+ }
+ if (maximized == 3) {
+ // only set maximized if both horizontal and vertical properties are set
+ max = true;
+ }
+ }
+ }
+
+ bool send_event = false;
+
+ if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
+ && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) {
+ if (max && !isMaximized()) {
+ this->data->window_state = this->data->window_state | Qt::WindowMaximized;
+ send_event = true;
+ } else if (!max && isMaximized()) {
+ this->data->window_state &= ~Qt::WindowMaximized;
+ send_event = true;
+ }
+ }
+
+ if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
+ if (full && !isFullScreen()) {
+ this->data->window_state = this->data->window_state | Qt::WindowFullScreen;
+ send_event = true;
+ } else if (!full && isFullScreen()) {
+ this->data->window_state &= ~Qt::WindowFullScreen;
+ send_event = true;
+ }
+ }
+
+ if (send_event) {
+ QWindowStateChangeEvent e(oldState);
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
+ } else if (event->xproperty.atom == ATOM(WM_STATE)) {
+ // the widget frame strut should also be invalidated
+ this->data->fstrut_dirty = 1;
+
+ if (event->xproperty.state == PropertyDelete) {
+ // the window manager has removed the WM State property,
+ // so it is now in the withdrawn state (ICCCM 4.1.3.1) and
+ // we are free to reuse this window
+ d->topData()->parentWinId = 0;
+ d->topData()->validWMState = 0;
+ // map the window if we were waiting for a transition to
+ // withdrawn
+ if (X11->deferred_map.removeAll(this)) {
+ doDeferredMap();
+ } else if (isVisible()
+ && !testAttribute(Qt::WA_Mapped)
+ && !testAttribute(Qt::WA_OutsideWSRange)) {
+ // so that show() will work again. As stated in the
+ // ICCCM section 4.1.4: "Only the client can effect a
+ // transition into or out of the Withdrawn state.",
+ // but apparently this particular window manager
+ // doesn't seem to care
+ setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ setAttribute(Qt::WA_WState_Visible, false);
+ }
+ } else {
+ // the window manager has changed the WM State property...
+ // we are wanting to see if we are withdrawn so that we
+ // can reuse this window...
+ e = XGetWindowProperty(X11->display, internalWinId(), ATOM(WM_STATE), 0, 2, False,
+ ATOM(WM_STATE), &ret, &format, &nitems, &after, &data);
+
+ if (e == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) {
+ long *state = (long *) data;
+ switch (state[0]) {
+ case WithdrawnState:
+ // if we are in the withdrawn state, we are free
+ // to reuse this window provided we remove the
+ // WM_STATE property (ICCCM 4.1.3.1)
+ XDeleteProperty(X11->display, internalWinId(), ATOM(WM_STATE));
+
+ // set the parent id to zero, so that show() will
+ // work again
+ d->topData()->parentWinId = 0;
+ d->topData()->validWMState = 0;
+ // map the window if we were waiting for a
+ // transition to withdrawn
+ if (X11->deferred_map.removeAll(this)) {
+ doDeferredMap();
+ } else if (isVisible()
+ && !testAttribute(Qt::WA_Mapped)
+ && !testAttribute(Qt::WA_OutsideWSRange)) {
+ // so that show() will work again. As stated
+ // in the ICCCM section 4.1.4: "Only the
+ // client can effect a transition into or out
+ // of the Withdrawn state.", but apparently
+ // this particular window manager doesn't seem
+ // to care
+ setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ setAttribute(Qt::WA_WState_Visible, false);
+ }
+ break;
+
+ case IconicState:
+ d->topData()->validWMState = 1;
+ if (!isMinimized()) {
+ // window was minimized
+ this->data->window_state = this->data->window_state | Qt::WindowMinimized;
+ QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state & ~Qt::WindowMinimized));
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
+ break;
+
+ default:
+ d->topData()->validWMState = 1;
+ if (isMinimized()) {
+ // window was un-minimized
+ this->data->window_state &= ~Qt::WindowMinimized;
+ QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state | Qt::WindowMinimized));
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
+ break;
+ }
+ }
+ }
+ } else if (event->xproperty.atom == ATOM(_NET_WM_WINDOW_OPACITY)) {
+ // the window opacity was changed
+ if (event->xproperty.state == PropertyNewValue) {
+ e = XGetWindowProperty(event->xclient.display,
+ event->xclient.window,
+ ATOM(_NET_WM_WINDOW_OPACITY),
+ 0, 1, False, XA_CARDINAL,
+ &ret, &format, &nitems, &after, &data);
+
+ if (e == Success && ret == XA_CARDINAL && format == 32 && nitems == 1
+ && after == 0 && data) {
+ ulong value = *(ulong*)(data);
+ d->topData()->opacity = uint(value >> 24);
+ }
+ } else
+ d->topData()->opacity = 255;
+ }
+
+ if (data)
+ XFree(data);
+
+ return true;
+}
+
+//
+// Paint event translation
+//
+// When receiving many expose events, we compress them (union of all expose
+// rectangles) into one event which is sent to the widget.
+
+struct PaintEventInfo {
+ Window window;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool isPaintOrScrollDoneEvent(Display *, XEvent *ev, XPointer a)
+{
+ PaintEventInfo *info = (PaintEventInfo *)a;
+ if (ev->type == Expose || ev->type == GraphicsExpose
+ || (ev->type == ClientMessage && ev->xclient.message_type == ATOM(_QT_SCROLL_DONE)))
+ {
+ if (ev->xexpose.window == info->window)
+ return True;
+ }
+ return False;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+
+
+static
+bool translateBySips(QWidget* that, QRect& paintRect)
+{
+ int dx=0, dy=0;
+ int sips=0;
+ for (int i = 0; i < X11->sip_list.size(); ++i) {
+ const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
+ if (sip.scrolled_widget == that) {
+ if (sips) {
+ dx += sip.dx;
+ dy += sip.dy;
+ }
+ sips++;
+ }
+ }
+ if (sips > 1) {
+ paintRect.translate(dx, dy);
+ return true;
+ }
+ return false;
+}
+
+void QETWidget::translatePaintEvent(const XEvent *event)
+{
+ if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
+ Q_ASSERT(internalWinId());
+
+ Q_D(QWidget);
+ QRect paintRect(event->xexpose.x, event->xexpose.y,
+ event->xexpose.width, event->xexpose.height);
+ XEvent xevent;
+ PaintEventInfo info;
+ info.window = internalWinId();
+ translateBySips(this, paintRect);
+ paintRect = d->mapFromWS(paintRect);
+
+ QRegion paintRegion = paintRect;
+
+ // WARNING: this is O(number_of_events * number_of_matching_events)
+ while (XCheckIfEvent(X11->display,&xevent,isPaintOrScrollDoneEvent,
+ (XPointer)&info) &&
+ !qt_x11EventFilter(&xevent) &&
+ !x11Event(&xevent)) // send event through filter
+ {
+ if (xevent.type == Expose || xevent.type == GraphicsExpose) {
+ QRect exposure(xevent.xexpose.x,
+ xevent.xexpose.y,
+ xevent.xexpose.width,
+ xevent.xexpose.height);
+ translateBySips(this, exposure);
+ exposure = d->mapFromWS(exposure);
+ paintRegion |= exposure;
+ } else {
+ translateScrollDoneEvent(&xevent);
+ }
+ }
+
+ if (!paintRegion.isEmpty() && !testAttribute(Qt::WA_WState_ConfigPending))
+ d->syncBackingStore(paintRegion);
+}
+
+//
+// Scroll-done event translation.
+//
+
+bool QETWidget::translateScrollDoneEvent(const XEvent *event)
+{
+ long id = event->xclient.data.l[0];
+
+ // Remove any scroll-in-progress record for the given id.
+ for (int i = 0; i < X11->sip_list.size(); ++i) {
+ const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
+ if (sip.id == id) {
+ X11->sip_list.removeAt(i);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//
+// ConfigureNotify (window move and resize) event translation
+
+bool QETWidget::translateConfigEvent(const XEvent *event)
+{
+ Q_ASSERT((!isWindow() && !testAttribute(Qt::WA_NativeWindow)) ? internalWinId() : true);
+
+ Q_D(QWidget);
+ bool wasResize = testAttribute(Qt::WA_WState_ConfigPending); // set in QWidget::setGeometry_sys()
+ setAttribute(Qt::WA_WState_ConfigPending, false);
+
+ if (testAttribute(Qt::WA_OutsideWSRange)) {
+ // discard events for windows that have a geometry X can't handle
+ XEvent xevent;
+ while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
+ !qt_x11EventFilter(&xevent) &&
+ !x11Event(&xevent)) // send event through filter
+ ;
+ return true;
+ }
+
+ const QSize oldSize = size();
+
+ if (isWindow()) {
+ QPoint newCPos(geometry().topLeft());
+ QSize newSize(event->xconfigure.width, event->xconfigure.height);
+
+ bool trust = isVisible()
+ && (d->topData()->parentWinId == XNone ||
+ d->topData()->parentWinId == QX11Info::appRootWindow());
+
+ if (event->xconfigure.send_event || trust) {
+ // if a ConfigureNotify comes from a real sendevent request, we can
+ // trust its values.
+ newCPos.rx() = event->xconfigure.x + event->xconfigure.border_width;
+ newCPos.ry() = event->xconfigure.y + event->xconfigure.border_width;
+ }
+
+ if (isVisible())
+ QApplication::syncX();
+
+ if (d->extra->compress_events) {
+ // ConfigureNotify compression for faster opaque resizing
+ XEvent otherEvent;
+ while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify,
+ &otherEvent)) {
+ if (qt_x11EventFilter(&otherEvent))
+ continue;
+
+ if (x11Event(&otherEvent))
+ continue;
+
+ if (otherEvent.xconfigure.event != otherEvent.xconfigure.window)
+ continue;
+
+ newSize.setWidth(otherEvent.xconfigure.width);
+ newSize.setHeight(otherEvent.xconfigure.height);
+
+ if (otherEvent.xconfigure.send_event || trust) {
+ newCPos.rx() = otherEvent.xconfigure.x +
+ otherEvent.xconfigure.border_width;
+ newCPos.ry() = otherEvent.xconfigure.y +
+ otherEvent.xconfigure.border_width;
+ }
+ }
+ }
+
+ QRect cr (geometry());
+ if (newCPos != cr.topLeft()) { // compare with cpos (exluding frame)
+ QPoint oldPos = geometry().topLeft();
+ cr.moveTopLeft(newCPos);
+ data->crect = cr;
+ if (isVisible()) {
+ QMoveEvent e(newCPos, oldPos); // pos (including frame), not cpos
+ QApplication::sendSpontaneousEvent(this, &e);
+ } else {
+ setAttribute(Qt::WA_PendingMoveEvent, true);
+ }
+ }
+ if (newSize != cr.size()) { // size changed
+ cr.setSize(newSize);
+ data->crect = cr;
+
+ uint old_state = data->window_state;
+ if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
+ && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
+ data->window_state &= ~Qt::WindowMaximized;
+ if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
+ data->window_state &= ~Qt::WindowFullScreen;
+
+ if (old_state != data->window_state) {
+ QWindowStateChangeEvent e((Qt::WindowStates) old_state);
+ QApplication::sendEvent(this, &e);
+ }
+
+ if (!isVisible())
+ setAttribute(Qt::WA_PendingResizeEvent, true);
+ wasResize = true;
+ }
+
+ } else {
+ XEvent xevent;
+ while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
+ !qt_x11EventFilter(&xevent) &&
+ !x11Event(&xevent)) // send event through filter
+ ;
+ }
+
+ if (wasResize) {
+ static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ if (d->extra->compress_events && !slowResize && !data->in_show && isVisible()) {
+ QApplication::syncX();
+ XEvent otherEvent;
+ while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify, &otherEvent)
+ && !qt_x11EventFilter(&otherEvent) && !x11Event(&otherEvent)
+ && otherEvent.xconfigure.event == otherEvent.xconfigure.window) {
+ data->crect.setWidth(otherEvent.xconfigure.width);
+ data->crect.setHeight(otherEvent.xconfigure.height);
+ }
+ }
+
+ if (isVisible() && data->crect.size() != oldSize) {
+ Q_ASSERT(d->extra->topextra);
+ QWidgetBackingStore *bs = d->extra->topextra->backingStore;
+ const bool hasStaticContents = bs && bs->hasStaticContents();
+ // If we have a backing store with static contents, we have to disable the top-level
+ // resize optimization in order to get invalidated regions for resized widgets.
+ // The optimization discards all invalidateBuffer() calls since we're going to
+ // repaint everything anyways, but that's not the case with static contents.
+ if (!slowResize && !hasStaticContents)
+ d->extra->topextra->inTopLevelResize = true;
+ QResizeEvent e(data->crect.size(), oldSize);
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
+
+ const bool waitingForMapNotify = d->extra->topextra && d->extra->topextra->waitingForMapNotify;
+ if (!waitingForMapNotify) {
+ if (d->paintOnScreen()) {
+ QRegion updateRegion(rect());
+ if (testAttribute(Qt::WA_StaticContents))
+ updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
+ d->syncBackingStore(updateRegion);
+ } else {
+ d->syncBackingStore();
+ }
+ }
+
+ if (d->extra && d->extra->topextra)
+ d->extra->topextra->inTopLevelResize = false;
+ }
+ return true;
+}
+
+//
+// Close window event translation.
+//
+bool QETWidget::translateCloseEvent(const XEvent *)
+{
+ Q_D(QWidget);
+ return d->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+}
+
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ QApplicationPrivate::mouse_double_click_time = ms;
+}
+
+int QApplication::doubleClickInterval()
+{
+ return QApplicationPrivate::mouse_double_click_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::keyboardInputInterval()
+{
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+void QApplication::setWheelScrollLines(int n)
+{
+ QApplicationPrivate::wheel_scroll_lines = n;
+}
+
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ switch (effect) {
+ case Qt::UI_AnimateMenu:
+ if (enable) QApplicationPrivate::fade_menu = false;
+ QApplicationPrivate::animate_menu = enable;
+ break;
+ case Qt::UI_FadeMenu:
+ if (enable)
+ QApplicationPrivate::animate_menu = true;
+ QApplicationPrivate::fade_menu = enable;
+ break;
+ case Qt::UI_AnimateCombo:
+ QApplicationPrivate::animate_combo = enable;
+ break;
+ case Qt::UI_AnimateTooltip:
+ if (enable) QApplicationPrivate::fade_tooltip = false;
+ QApplicationPrivate::animate_tooltip = enable;
+ break;
+ case Qt::UI_FadeTooltip:
+ if (enable)
+ QApplicationPrivate::animate_tooltip = true;
+ QApplicationPrivate::fade_tooltip = enable;
+ break;
+ case Qt::UI_AnimateToolBox:
+ QApplicationPrivate::animate_toolbox = enable;
+ break;
+ default:
+ QApplicationPrivate::animate_ui = enable;
+ break;
+ }
+}
+
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
+ return false;
+
+ switch(effect) {
+ case Qt::UI_AnimateMenu:
+ return QApplicationPrivate::animate_menu;
+ case Qt::UI_FadeMenu:
+ return QApplicationPrivate::fade_menu;
+ case Qt::UI_AnimateCombo:
+ return QApplicationPrivate::animate_combo;
+ case Qt::UI_AnimateTooltip:
+ return QApplicationPrivate::animate_tooltip;
+ case Qt::UI_FadeTooltip:
+ return QApplicationPrivate::fade_tooltip;
+ case Qt::UI_AnimateToolBox:
+ return QApplicationPrivate::animate_toolbox;
+ default:
+ return QApplicationPrivate::animate_ui;
+ }
+}
+
+/*****************************************************************************
+ Session management support
+ *****************************************************************************/
+
+#ifndef QT_NO_SESSIONMANAGER
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <X11/SM/SMlib.h>
+QT_END_INCLUDE_NAMESPACE
+
+class QSessionManagerPrivate : public QObjectPrivate
+{
+public:
+ QSessionManagerPrivate(QSessionManager* mgr, QString& id, QString& key)
+ : QObjectPrivate(), sm(mgr), sessionId(id), sessionKey(key), eventLoop(0) {}
+ QSessionManager* sm;
+ QStringList restartCommand;
+ QStringList discardCommand;
+ QString& sessionId;
+ QString& sessionKey;
+ QSessionManager::RestartHint restartHint;
+ QEventLoop *eventLoop;
+};
+
+class QSmSocketReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ QSmSocketReceiver(int socket)
+ {
+ QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this);
+ connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int)));
+ }
+
+public slots:
+ void socketActivated(int);
+};
+
+
+static SmcConn smcConnection = 0;
+static bool sm_interactionActive;
+static bool sm_smActive;
+static int sm_interactStyle;
+static int sm_saveType;
+static bool sm_cancel;
+// static bool sm_waitingForPhase2; ### never used?!?
+static bool sm_waitingForInteraction;
+static bool sm_isshutdown;
+// static bool sm_shouldbefast; ### never used?!?
+static bool sm_phase2;
+static bool sm_in_phase2;
+
+static QSmSocketReceiver* sm_receiver = 0;
+
+static void resetSmState();
+static void sm_setProperty(const char* name, const char* type,
+ int num_vals, SmPropValue* vals);
+static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
+ int saveType, Bool shutdown , int interactStyle, Bool fast);
+static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData) ;
+static void sm_dieCallback(SmcConn smcConn, SmPointer clientData) ;
+static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData);
+static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer clientData);
+static void sm_interactCallback(SmcConn smcConn, SmPointer clientData);
+static void sm_performSaveYourself(QSessionManagerPrivate*);
+
+static void resetSmState()
+{
+// sm_waitingForPhase2 = false; ### never used?!?
+ sm_waitingForInteraction = false;
+ sm_interactionActive = false;
+ sm_interactStyle = SmInteractStyleNone;
+ sm_smActive = false;
+ qt_sm_blockUserInput = false;
+ sm_isshutdown = false;
+// sm_shouldbefast = false; ### never used?!?
+ sm_phase2 = false;
+ sm_in_phase2 = false;
+}
+
+
+// theoretically it's possible to set several properties at once. For
+// simplicity, however, we do just one property at a time
+static void sm_setProperty(const char* name, const char* type,
+ int num_vals, SmPropValue* vals)
+{
+ if (num_vals) {
+ SmProp prop;
+ prop.name = (char*)name;
+ prop.type = (char*)type;
+ prop.num_vals = num_vals;
+ prop.vals = vals;
+
+ SmProp* props[1];
+ props[0] = &prop;
+ SmcSetProperties(smcConnection, 1, props);
+ }
+ else {
+ char* names[1];
+ names[0] = (char*) name;
+ SmcDeleteProperties(smcConnection, 1, names);
+ }
+}
+
+static void sm_setProperty(const QString& name, const QString& value)
+{
+ QByteArray v = value.toUtf8();
+ SmPropValue prop;
+ prop.length = v.length();
+ prop.value = (SmPointer) v.constData();
+ sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop);
+}
+
+static void sm_setProperty(const QString& name, const QStringList& value)
+{
+ SmPropValue *prop = new SmPropValue[value.count()];
+ int count = 0;
+ QList<QByteArray> vl;
+ for (QStringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
+ prop[count].length = (*it).length();
+ vl.append((*it).toUtf8());
+ prop[count].value = (char*)vl.last().data();
+ ++count;
+ }
+ sm_setProperty(name.toLatin1().data(), SmLISTofARRAY8, count, prop);
+ delete [] prop;
+}
+
+
+// workaround for broken libsm, see below
+struct QT_smcConn {
+ unsigned int save_yourself_in_progress : 1;
+ unsigned int shutdown_in_progress : 1;
+};
+
+static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
+ int saveType, Bool shutdown , int interactStyle, Bool /*fast*/)
+{
+ if (smcConn != smcConnection)
+ return;
+ sm_cancel = false;
+ sm_smActive = true;
+ sm_isshutdown = shutdown;
+ sm_saveType = saveType;
+ sm_interactStyle = interactStyle;
+// sm_shouldbefast = fast; ### never used?!?
+
+ // ugly workaround for broken libSM. libSM should do that _before_
+ // actually invoking the callback in sm_process.c
+ ((QT_smcConn*)smcConn)->save_yourself_in_progress = true;
+ if (sm_isshutdown)
+ ((QT_smcConn*)smcConn)->shutdown_in_progress = true;
+
+ sm_performSaveYourself((QSessionManagerPrivate*) clientData);
+ if (!sm_isshutdown) // we cannot expect a confirmation message in that case
+ resetSmState();
+}
+
+static void sm_performSaveYourself(QSessionManagerPrivate* smd)
+{
+ if (sm_isshutdown)
+ qt_sm_blockUserInput = true;
+
+ QSessionManager* sm = smd->sm;
+
+ // generate a new session key
+ timeval tv;
+ gettimeofday(&tv, 0);
+ smd->sessionKey = QString::number(qulonglong(tv.tv_sec)) + QLatin1Char('_') + QString::number(qulonglong(tv.tv_usec));
+
+ QStringList arguments = qApp->arguments();
+ QString argument0 = arguments.isEmpty() ? qApp->applicationFilePath() : arguments.at(0);
+
+ // tell the session manager about our program in best POSIX style
+ sm_setProperty(QString::fromLatin1(SmProgram), argument0);
+ // tell the session manager about our user as well.
+ struct passwd *entryPtr = 0;
+#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+ QVarLengthArray<char, 1024> buf(sysconf(_SC_GETPW_R_SIZE_MAX));
+ struct passwd entry;
+ getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr);
+#else
+ entryPtr = getpwuid(geteuid());
+#endif
+ if (entryPtr)
+ sm_setProperty(QString::fromLatin1(SmUserID), QString::fromLatin1(entryPtr->pw_name));
+
+ // generate a restart and discard command that makes sense
+ QStringList restart;
+ restart << argument0 << QLatin1String("-session")
+ << smd->sessionId + QLatin1Char('_') + smd->sessionKey;
+ if (qstricmp(appName, QX11Info::appClass()) != 0)
+ restart << QLatin1String("-name") << qAppName();
+ sm->setRestartCommand(restart);
+ QStringList discard;
+ sm->setDiscardCommand(discard);
+
+ switch (sm_saveType) {
+ case SmSaveBoth:
+ qApp->commitData(*sm);
+ if (sm_isshutdown && sm_cancel)
+ break; // we cancelled the shutdown, no need to save state
+ // fall through
+ case SmSaveLocal:
+ qApp->saveState(*sm);
+ break;
+ case SmSaveGlobal:
+ qApp->commitData(*sm);
+ break;
+ default:
+ break;
+ }
+
+ if (sm_phase2 && !sm_in_phase2) {
+ SmcRequestSaveYourselfPhase2(smcConnection, sm_saveYourselfPhase2Callback, (SmPointer*) smd);
+ qt_sm_blockUserInput = false;
+ }
+ else {
+ // close eventual interaction monitors and cancel the
+ // shutdown, if required. Note that we can only cancel when
+ // performing a shutdown, it does not work for checkpoints
+ if (sm_interactionActive) {
+ SmcInteractDone(smcConnection, sm_isshutdown && sm_cancel);
+ sm_interactionActive = false;
+ }
+ else if (sm_cancel && sm_isshutdown) {
+ if (sm->allowsErrorInteraction()) {
+ SmcInteractDone(smcConnection, True);
+ sm_interactionActive = false;
+ }
+ }
+
+ // set restart and discard command in session manager
+ sm_setProperty(QString::fromLatin1(SmRestartCommand), sm->restartCommand());
+ sm_setProperty(QString::fromLatin1(SmDiscardCommand), sm->discardCommand());
+
+ // set the restart hint
+ SmPropValue prop;
+ prop.length = sizeof(int);
+ int value = sm->restartHint();
+ prop.value = (SmPointer) &value;
+ sm_setProperty(SmRestartStyleHint, SmCARD8, 1, &prop);
+
+ // we are done
+ SmcSaveYourselfDone(smcConnection, !sm_cancel);
+ }
+}
+
+static void sm_dieCallback(SmcConn smcConn, SmPointer /* clientData */)
+{
+ if (smcConn != smcConnection)
+ return;
+ resetSmState();
+ QEvent quitEvent(QEvent::Quit);
+ QApplication::sendEvent(qApp, &quitEvent);
+}
+
+static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData)
+{
+ if (smcConn != smcConnection)
+ return;
+ if (sm_waitingForInteraction)
+ ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
+ resetSmState();
+}
+
+static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer /*clientData */)
+{
+ if (smcConn != smcConnection)
+ return;
+ resetSmState();
+}
+
+static void sm_interactCallback(SmcConn smcConn, SmPointer clientData)
+{
+ if (smcConn != smcConnection)
+ return;
+ if (sm_waitingForInteraction)
+ ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
+}
+
+static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData)
+{
+ if (smcConn != smcConnection)
+ return;
+ sm_in_phase2 = true;
+ sm_performSaveYourself((QSessionManagerPrivate*) clientData);
+}
+
+
+void QSmSocketReceiver::socketActivated(int)
+{
+ IceProcessMessages(SmcGetIceConnection(smcConnection), 0, 0);
+}
+
+
+#undef Bool
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qapplication_x11.moc"
+QT_END_INCLUDE_NAMESPACE
+
+QSessionManager::QSessionManager(QApplication * app, QString &id, QString& key)
+ : QObject(*new QSessionManagerPrivate(this, id, key), app)
+{
+ Q_D(QSessionManager);
+ d->restartHint = RestartIfRunning;
+
+ resetSmState();
+ char cerror[256];
+ char* myId = 0;
+ QByteArray b_id = id.toLatin1();
+ char* prevId = b_id.data();
+
+ SmcCallbacks cb;
+ cb.save_yourself.callback = sm_saveYourselfCallback;
+ cb.save_yourself.client_data = (SmPointer) d;
+ cb.die.callback = sm_dieCallback;
+ cb.die.client_data = (SmPointer) d;
+ cb.save_complete.callback = sm_saveCompleteCallback;
+ cb.save_complete.client_data = (SmPointer) d;
+ cb.shutdown_cancelled.callback = sm_shutdownCancelledCallback;
+ cb.shutdown_cancelled.client_data = (SmPointer) d;
+
+ // avoid showing a warning message below
+ if (qgetenv("SESSION_MANAGER").isEmpty())
+ return;
+
+ smcConnection = SmcOpenConnection(0, 0, 1, 0,
+ SmcSaveYourselfProcMask |
+ SmcDieProcMask |
+ SmcSaveCompleteProcMask |
+ SmcShutdownCancelledProcMask,
+ &cb,
+ prevId,
+ &myId,
+ 256, cerror);
+
+ id = QString::fromLatin1(myId);
+ ::free(myId); // it was allocated by C
+
+ QString error = QString::fromLocal8Bit(cerror);
+ if (!smcConnection) {
+ qWarning("Qt: Session management error: %s", qPrintable(error));
+ }
+ else {
+ sm_receiver = new QSmSocketReceiver(IceConnectionNumber(SmcGetIceConnection(smcConnection)));
+ }
+}
+
+QSessionManager::~QSessionManager()
+{
+ if (smcConnection)
+ SmcCloseConnection(smcConnection, 0, 0);
+ smcConnection = 0;
+ delete sm_receiver;
+}
+
+QString QSessionManager::sessionId() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionId;
+}
+
+QString QSessionManager::sessionKey() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionKey;
+}
+
+
+void* QSessionManager::handle() const
+{
+ return (void*) smcConnection;
+}
+
+
+bool QSessionManager::allowsInteraction()
+{
+ Q_D(QSessionManager);
+ if (sm_interactionActive)
+ return true;
+
+ if (sm_waitingForInteraction)
+ return false;
+
+ if (sm_interactStyle == SmInteractStyleAny) {
+ sm_waitingForInteraction = SmcInteractRequest(smcConnection, SmDialogNormal,
+ sm_interactCallback, (SmPointer*) d);
+ }
+ if (sm_waitingForInteraction) {
+ QEventLoop eventLoop;
+ d->eventLoop = &eventLoop;
+ (void) eventLoop.exec();
+ d->eventLoop = 0;
+
+ sm_waitingForInteraction = false;
+ if (sm_smActive) { // not cancelled
+ sm_interactionActive = true;
+ qt_sm_blockUserInput = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QSessionManager::allowsErrorInteraction()
+{
+ Q_D(QSessionManager);
+ if (sm_interactionActive)
+ return true;
+
+ if (sm_waitingForInteraction)
+ return false;
+
+ if (sm_interactStyle == SmInteractStyleAny || sm_interactStyle == SmInteractStyleErrors) {
+ sm_waitingForInteraction = SmcInteractRequest(smcConnection, SmDialogError,
+ sm_interactCallback, (SmPointer*) d);
+ }
+ if (sm_waitingForInteraction) {
+ QEventLoop eventLoop;
+ d->eventLoop = &eventLoop;
+ (void) eventLoop.exec();
+ d->eventLoop = 0;
+
+ sm_waitingForInteraction = false;
+ if (sm_smActive) { // not cancelled
+ sm_interactionActive = true;
+ qt_sm_blockUserInput = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+void QSessionManager::release()
+{
+ if (sm_interactionActive) {
+ SmcInteractDone(smcConnection, False);
+ sm_interactionActive = false;
+ if (sm_smActive && sm_isshutdown)
+ qt_sm_blockUserInput = true;
+ }
+}
+
+void QSessionManager::cancel()
+{
+ sm_cancel = true;
+}
+
+void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
+{
+ Q_D(QSessionManager);
+ d->restartHint = hint;
+}
+
+QSessionManager::RestartHint QSessionManager::restartHint() const
+{
+ Q_D(const QSessionManager);
+ return d->restartHint;
+}
+
+void QSessionManager::setRestartCommand(const QStringList& command)
+{
+ Q_D(QSessionManager);
+ d->restartCommand = command;
+}
+
+QStringList QSessionManager::restartCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->restartCommand;
+}
+
+void QSessionManager::setDiscardCommand(const QStringList& command)
+{
+ Q_D(QSessionManager);
+ d->discardCommand = command;
+}
+
+QStringList QSessionManager::discardCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->discardCommand;
+}
+
+void QSessionManager::setManagerProperty(const QString& name, const QString& value)
+{
+ sm_setProperty(name, value);
+}
+
+void QSessionManager::setManagerProperty(const QString& name, const QStringList& value)
+{
+ sm_setProperty(name, value);
+}
+
+bool QSessionManager::isPhase2() const
+{
+ return sm_in_phase2;
+}
+
+void QSessionManager::requestPhase2()
+{
+ sm_phase2 = true;
+}
+
+#endif // QT_NO_SESSIONMANAGER
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qboxlayout.cpp b/src/gui/kernel/qboxlayout.cpp
new file mode 100644
index 0000000000..49dd4a5690
--- /dev/null
+++ b/src/gui/kernel/qboxlayout.cpp
@@ -0,0 +1,1534 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboxlayout.h"
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qlist.h"
+#include "qsizepolicy.h"
+#include "qvector.h"
+
+#include "qlayoutengine_p.h"
+#include "qlayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Returns true if the \a widget can be added to the \a layout;
+ otherwise returns false.
+*/
+static bool checkWidget(QLayout *layout, QWidget *widget)
+{
+ if (!widget) {
+ qWarning("QLayout: Cannot add null widget to %s/%s", layout->metaObject()->className(),
+ layout->objectName().toLocal8Bit().data());
+ return false;
+ }
+ return true;
+}
+
+struct QBoxLayoutItem
+{
+ QBoxLayoutItem(QLayoutItem *it, int stretch_ = 0)
+ : item(it), stretch(stretch_), magic(false) { }
+ ~QBoxLayoutItem() { delete item; }
+
+ int hfw(int w) {
+ if (item->hasHeightForWidth()) {
+ return item->heightForWidth(w);
+ } else {
+ return item->sizeHint().height();
+ }
+ }
+ int mhfw(int w) {
+ if (item->hasHeightForWidth()) {
+ return item->heightForWidth(w);
+ } else {
+ return item->minimumSize().height();
+ }
+ }
+ int hStretch() {
+ if (stretch == 0 && item->widget()) {
+ return item->widget()->sizePolicy().horizontalStretch();
+ } else {
+ return stretch;
+ }
+ }
+ int vStretch() {
+ if (stretch == 0 && item->widget()) {
+ return item->widget()->sizePolicy().verticalStretch();
+ } else {
+ return stretch;
+ }
+ }
+
+ QLayoutItem *item;
+ int stretch;
+ bool magic;
+};
+
+class QBoxLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QBoxLayout)
+public:
+ QBoxLayoutPrivate() : hfwWidth(-1), dirty(true), spacing(-1) { }
+ ~QBoxLayoutPrivate();
+
+ void setDirty() {
+ geomArray.clear();
+ hfwWidth = -1;
+ hfwHeight = -1;
+ dirty = true;
+ }
+
+ QList<QBoxLayoutItem *> list;
+ QVector<QLayoutStruct> geomArray;
+ int hfwWidth;
+ int hfwHeight;
+ int hfwMinHeight;
+ QSize sizeHint;
+ QSize minSize;
+ QSize maxSize;
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ Qt::Orientations expanding;
+ uint hasHfw : 1;
+ uint dirty : 1;
+ QBoxLayout::Direction dir;
+ int spacing;
+
+ inline void deleteAll() { while (!list.isEmpty()) delete list.takeFirst(); }
+
+ void setupGeom();
+ void calcHfw(int);
+
+ void effectiveMargins(int *left, int *top, int *right, int *bottom) const;
+};
+
+QBoxLayoutPrivate::~QBoxLayoutPrivate()
+{
+}
+
+static inline bool horz(QBoxLayout::Direction dir)
+{
+ return dir == QBoxLayout::RightToLeft || dir == QBoxLayout::LeftToRight;
+}
+
+/**
+ * The purpose of this function is to make sure that widgets are not laid out outside its layout.
+ * E.g. the layoutItemRect margins are only meant to take of the surrounding margins/spacings.
+ * However, if the margin is 0, it can easily cover the area of a widget above it.
+ */
+void QBoxLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *bottom) const
+{
+ int l = leftMargin;
+ int t = topMargin;
+ int r = rightMargin;
+ int b = bottomMargin;
+#ifdef Q_WS_MAC
+ Q_Q(const QBoxLayout);
+ if (horz(dir)) {
+ QBoxLayoutItem *leftBox = 0;
+ QBoxLayoutItem *rightBox = 0;
+
+ if (left || right) {
+ leftBox = list.value(0);
+ rightBox = list.value(list.count() - 1);
+ if (dir == QBoxLayout::RightToLeft)
+ qSwap(leftBox, rightBox);
+
+ int leftDelta = 0;
+ int rightDelta = 0;
+ if (leftBox) {
+ QLayoutItem *itm = leftBox->item;
+ if (QWidget *w = itm->widget())
+ leftDelta = itm->geometry().left() - w->geometry().left();
+ }
+ if (rightBox) {
+ QLayoutItem *itm = rightBox->item;
+ if (QWidget *w = itm->widget())
+ rightDelta = w->geometry().right() - itm->geometry().right();
+ }
+ QWidget *w = q->parentWidget();
+ Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QApplication::layoutDirection();
+ if (layoutDirection == Qt::RightToLeft)
+ qSwap(leftDelta, rightDelta);
+
+ l = qMax(l, leftDelta);
+ r = qMax(r, rightDelta);
+ }
+
+ int count = top || bottom ? list.count() : 0;
+ for (int i = 0; i < count; ++i) {
+ QBoxLayoutItem *box = list.at(i);
+ QLayoutItem *itm = box->item;
+ QWidget *w = itm->widget();
+ if (w) {
+ QRect lir = itm->geometry();
+ QRect wr = w->geometry();
+ if (top)
+ t = qMax(t, lir.top() - wr.top());
+ if (bottom)
+ b = qMax(b, wr.bottom() - lir.bottom());
+ }
+ }
+ } else { // vertical layout
+ QBoxLayoutItem *topBox = 0;
+ QBoxLayoutItem *bottomBox = 0;
+
+ if (top || bottom) {
+ topBox = list.value(0);
+ bottomBox = list.value(list.count() - 1);
+ if (dir == QBoxLayout::BottomToTop) {
+ qSwap(topBox, bottomBox);
+ }
+
+ if (top && topBox) {
+ QLayoutItem *itm = topBox->item;
+ QWidget *w = itm->widget();
+ if (w)
+ t = qMax(t, itm->geometry().top() - w->geometry().top());
+ }
+
+ if (bottom && bottomBox) {
+ QLayoutItem *itm = bottomBox->item;
+ QWidget *w = itm->widget();
+ if (w)
+ b = qMax(b, w->geometry().bottom() - itm->geometry().bottom());
+ }
+ }
+
+ int count = left || right ? list.count() : 0;
+ for (int i = 0; i < count; ++i) {
+ QBoxLayoutItem *box = list.at(i);
+ QLayoutItem *itm = box->item;
+ QWidget *w = itm->widget();
+ if (w) {
+ QRect lir = itm->geometry();
+ QRect wr = w->geometry();
+ if (left)
+ l = qMax(l, lir.left() - wr.left());
+ if (right)
+ r = qMax(r, wr.right() - lir.right());
+ }
+ }
+ }
+#endif
+ if (left)
+ *left = l;
+ if (top)
+ *top = t;
+ if (right)
+ *right = r;
+ if (bottom)
+ *bottom = b;
+}
+
+
+/*
+ Initializes the data structure needed by qGeomCalc and
+ recalculates max/min and size hint.
+*/
+void QBoxLayoutPrivate::setupGeom()
+{
+ if (!dirty)
+ return;
+
+ Q_Q(QBoxLayout);
+ int maxw = horz(dir) ? 0 : QLAYOUTSIZE_MAX;
+ int maxh = horz(dir) ? QLAYOUTSIZE_MAX : 0;
+ int minw = 0;
+ int minh = 0;
+ int hintw = 0;
+ int hinth = 0;
+
+ bool horexp = false;
+ bool verexp = false;
+
+ hasHfw = false;
+
+ int n = list.count();
+ geomArray.clear();
+ QVector<QLayoutStruct> a(n);
+
+ QSizePolicy::ControlTypes controlTypes1;
+ QSizePolicy::ControlTypes controlTypes2;
+ int fixedSpacing = q->spacing();
+ int previousNonEmptyIndex = -1;
+
+ QStyle *style = 0;
+ if (fixedSpacing < 0) {
+ if (QWidget *parentWidget = q->parentWidget())
+ style = parentWidget->style();
+ }
+
+ for (int i = 0; i < n; i++) {
+ QBoxLayoutItem *box = list.at(i);
+ QSize max = box->item->maximumSize();
+ QSize min = box->item->minimumSize();
+ QSize hint = box->item->sizeHint();
+ Qt::Orientations exp = box->item->expandingDirections();
+ bool empty = box->item->isEmpty();
+ int spacing = 0;
+
+ if (!empty) {
+ if (fixedSpacing >= 0) {
+ spacing = (previousNonEmptyIndex >= 0) ? fixedSpacing : 0;
+#ifdef Q_WS_MAC
+ if (!horz(dir) && previousNonEmptyIndex >= 0) {
+ QBoxLayoutItem *sibling = (dir == QBoxLayout::TopToBottom ? box : list.at(previousNonEmptyIndex));
+ if (sibling) {
+ QWidget *wid = sibling->item->widget();
+ if (wid)
+ spacing = qMax(spacing, sibling->item->geometry().top() - wid->geometry().top());
+ }
+ }
+#endif
+ } else {
+ controlTypes1 = controlTypes2;
+ controlTypes2 = box->item->controlTypes();
+ if (previousNonEmptyIndex >= 0) {
+ QSizePolicy::ControlTypes actual1 = controlTypes1;
+ QSizePolicy::ControlTypes actual2 = controlTypes2;
+ if (dir == QBoxLayout::RightToLeft || dir == QBoxLayout::BottomToTop)
+ qSwap(actual1, actual2);
+
+ if (style) {
+ spacing = style->combinedLayoutSpacing(actual1, actual2,
+ horz(dir) ? Qt::Horizontal : Qt::Vertical,
+ 0, q->parentWidget());
+ if (spacing < 0)
+ spacing = 0;
+ }
+ }
+ }
+
+ if (previousNonEmptyIndex >= 0)
+ a[previousNonEmptyIndex].spacing = spacing;
+ previousNonEmptyIndex = i;
+ }
+
+ bool ignore = empty && box->item->widget(); // ignore hidden widgets
+ bool dummy = true;
+ if (horz(dir)) {
+ bool expand = (exp & Qt::Horizontal || box->stretch > 0);
+ horexp = horexp || expand;
+ maxw += spacing + max.width();
+ minw += spacing + min.width();
+ hintw += spacing + hint.width();
+ if (!ignore)
+ qMaxExpCalc(maxh, verexp, dummy,
+ max.height(), exp & Qt::Vertical, box->item->isEmpty());
+ minh = qMax(minh, min.height());
+ hinth = qMax(hinth, hint.height());
+
+ a[i].sizeHint = hint.width();
+ a[i].maximumSize = max.width();
+ a[i].minimumSize = min.width();
+ a[i].expansive = expand;
+ a[i].stretch = box->stretch ? box->stretch : box->hStretch();
+ } else {
+ bool expand = (exp & Qt::Vertical || box->stretch > 0);
+ verexp = verexp || expand;
+ maxh += spacing + max.height();
+ minh += spacing + min.height();
+ hinth += spacing + hint.height();
+ if (!ignore)
+ qMaxExpCalc(maxw, horexp, dummy,
+ max.width(), exp & Qt::Horizontal, box->item->isEmpty());
+ minw = qMax(minw, min.width());
+ hintw = qMax(hintw, hint.width());
+
+ a[i].sizeHint = hint.height();
+ a[i].maximumSize = max.height();
+ a[i].minimumSize = min.height();
+ a[i].expansive = expand;
+ a[i].stretch = box->stretch ? box->stretch : box->vStretch();
+ }
+
+ a[i].empty = empty;
+ a[i].spacing = 0; // might be be initialized with a non-zero value in a later iteration
+ hasHfw = hasHfw || box->item->hasHeightForWidth();
+ }
+
+ geomArray = a;
+
+ expanding = (Qt::Orientations)
+ ((horexp ? Qt::Horizontal : 0)
+ | (verexp ? Qt::Vertical : 0));
+
+ minSize = QSize(minw, minh);
+ maxSize = QSize(maxw, maxh).expandedTo(minSize);
+ sizeHint = QSize(hintw, hinth).expandedTo(minSize).boundedTo(maxSize);
+
+ q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ int left, top, right, bottom;
+ effectiveMargins(&left, &top, &right, &bottom);
+ QSize extra(left + right, top + bottom);
+
+ minSize += extra;
+ maxSize += extra;
+ sizeHint += extra;
+
+ dirty = false;
+}
+
+/*
+ Calculates and stores the preferred height given the width \a w.
+*/
+void QBoxLayoutPrivate::calcHfw(int w)
+{
+ QVector<QLayoutStruct> &a = geomArray;
+ int n = a.count();
+ int h = 0;
+ int mh = 0;
+
+ Q_ASSERT(n == list.size());
+
+ if (horz(dir)) {
+ qGeomCalc(a, 0, n, 0, w);
+ for (int i = 0; i < n; i++) {
+ QBoxLayoutItem *box = list.at(i);
+ h = qMax(h, box->hfw(a.at(i).size));
+ mh = qMax(mh, box->mhfw(a.at(i).size));
+ }
+ } else {
+ for (int i = 0; i < n; ++i) {
+ QBoxLayoutItem *box = list.at(i);
+ int spacing = a.at(i).spacing;
+ h += box->hfw(w);
+ mh += box->mhfw(w);
+ h += spacing;
+ mh += spacing;
+ }
+ }
+ hfwWidth = w;
+ hfwHeight = h;
+ hfwMinHeight = mh;
+}
+
+
+/*!
+ \class QBoxLayout
+
+ \brief The QBoxLayout class lines up child widgets horizontally or
+ vertically.
+
+ \ingroup geomanagement
+ \ingroup appearance
+
+ QBoxLayout takes the space it gets (from its parent layout or from
+ the parentWidget()), divides it up into a row of boxes, and makes
+ each managed widget fill one box.
+
+ \image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
+
+ If the QBoxLayout's orientation is Qt::Horizontal the boxes are
+ placed in a row, with suitable sizes. Each widget (or other box)
+ will get at least its minimum size and at most its maximum size.
+ Any excess space is shared according to the stretch factors (more
+ about that below).
+
+ \image qvboxlayout-with-5-children.png Vertical box layout with five child widgets
+
+ If the QBoxLayout's orientation is Qt::Vertical, the boxes are
+ placed in a column, again with suitable sizes.
+
+ The easiest way to create a QBoxLayout is to use one of the
+ convenience classes, e.g. QHBoxLayout (for Qt::Horizontal boxes)
+ or QVBoxLayout (for Qt::Vertical boxes). You can also use the
+ QBoxLayout constructor directly, specifying its direction as
+ LeftToRight, RightToLeft, TopToBottom, or BottomToTop.
+
+ If the QBoxLayout is not the top-level layout (i.e. it is not
+ managing all of the widget's area and children), you must add it
+ to its parent layout before you can do anything with it. The
+ normal way to add a layout is by calling
+ parentLayout-\>addLayout().
+
+ Once you have done this, you can add boxes to the QBoxLayout using
+ one of four functions:
+
+ \list
+ \o addWidget() to add a widget to the QBoxLayout and set the
+ widget's stretch factor. (The stretch factor is along the row of
+ boxes.)
+
+ \o addSpacing() to create an empty box; this is one of the
+ functions you use to create nice and spacious dialogs. See below
+ for ways to set margins.
+
+ \o addStretch() to create an empty, stretchable box.
+
+ \o addLayout() to add a box containing another QLayout to the row
+ and set that layout's stretch factor.
+ \endlist
+
+ Use insertWidget(), insertSpacing(), insertStretch() or
+ insertLayout() to insert a box at a specified position in the
+ layout.
+
+ QBoxLayout also includes two margin widths:
+
+ \list
+ \o setContentsMargins() sets the width of the outer border on
+ each side of the widget. This is the width of the reserved space
+ along each of the QBoxLayout's four sides.
+ \o setSpacing() sets the width between neighboring boxes. (You
+ can use addSpacing() to get more space at a particular spot.)
+ \endlist
+
+ The margin default is provided by the style. The default margin
+ most Qt styles specify is 9 for child widgets and 11 for windows.
+ The spacing defaults to the same as the margin width for a
+ top-level layout, or to the same as the parent layout.
+
+ To remove a widget from a layout, call removeWidget(). Calling
+ QWidget::hide() on a widget also effectively removes the widget
+ from the layout until QWidget::show() is called.
+
+ You will almost always want to use QVBoxLayout and QHBoxLayout
+ rather than QBoxLayout because of their convenient constructors.
+
+ \sa QGridLayout, QStackedLayout, {Layout Classes}
+*/
+
+/*!
+ \enum QBoxLayout::Direction
+
+ This type is used to determine the direction of a box layout.
+
+ \value LeftToRight Horizontal from left to right.
+ \value RightToLeft Horizontal from right to left.
+ \value TopToBottom Vertical from top to bottom.
+ \value BottomToTop Vertical from bottom to top.
+
+ \omitvalue Down
+ \omitvalue Up
+*/
+
+/*!
+ Constructs a new QBoxLayout with direction \a dir and parent widget \a
+ parent.
+
+ \sa direction()
+*/
+QBoxLayout::QBoxLayout(Direction dir, QWidget *parent)
+ : QLayout(*new QBoxLayoutPrivate, 0, parent)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new QBoxLayout with direction \a dir and main widget \a
+ parent. \a parent may not be 0.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and its managed children. The \a spacing is the default
+ number of pixels between neighboring children. If \a spacing is -1
+ the value of \a margin is used for \a spacing.
+
+ \a name is the internal object name.
+
+ \sa direction()
+*/
+QBoxLayout::QBoxLayout(QWidget *parent, Direction dir,
+ int margin, int spacing, const char *name)
+ : QLayout(*new QBoxLayoutPrivate, 0, parent)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+ setMargin(margin);
+ setObjectName(QString::fromAscii(name));
+ setSpacing(spacing<0 ? margin : spacing);
+}
+
+/*!
+ Constructs a new QBoxLayout called \a name, with direction \a dir,
+ and inserts it into \a parentLayout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, the layout will inherit its
+ parent's spacing().
+*/
+QBoxLayout::QBoxLayout(QLayout *parentLayout, Direction dir, int spacing,
+ const char *name)
+ : QLayout(*new QBoxLayoutPrivate, parentLayout, 0)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+ setObjectName(QString::fromAscii(name));
+ setSpacing(spacing);
+}
+
+/*!
+ Constructs a new QBoxLayout called \a name, with direction \a dir.
+
+ If \a spacing is -1, the layout will inherit its parent's
+ spacing(); otherwise \a spacing is used.
+
+ You must insert this box into another layout.
+*/
+QBoxLayout::QBoxLayout(Direction dir, int spacing, const char *name)
+ : QLayout(*new QBoxLayoutPrivate,0, 0)
+{
+ Q_D(QBoxLayout);
+ d->dir = dir;
+ setObjectName(QString::fromAscii(name));
+ setSpacing(spacing);
+}
+#endif // QT3_SUPPORT
+
+
+/*!
+ Destroys this box layout.
+
+ The layout's widgets aren't destroyed.
+*/
+QBoxLayout::~QBoxLayout()
+{
+ Q_D(QBoxLayout);
+ d->deleteAll(); // must do it before QObject deletes children, so can't be in ~QBoxLayoutPrivate
+}
+
+/*!
+ Reimplements QLayout::spacing(). If the spacing property is
+ valid, that value is returned. Otherwise, a value for the spacing
+ property is computed and returned. Since layout spacing in a widget
+ is style dependent, if the parent is a widget, it queries the style
+ for the (horizontal or vertical) spacing of the layout. Otherwise,
+ the parent is a layout, and it queries the parent layout for the
+ spacing().
+
+ \sa QLayout::spacing(), setSpacing()
+ */
+int QBoxLayout::spacing() const
+{
+ Q_D(const QBoxLayout);
+ if (d->spacing >=0) {
+ return d->spacing;
+ } else {
+ return qSmartSpacing(this, d->dir == LeftToRight || d->dir == RightToLeft
+ ? QStyle::PM_LayoutHorizontalSpacing
+ : QStyle::PM_LayoutVerticalSpacing);
+ }
+}
+
+/*!
+ Reimplements QLayout::setSpacing(). Sets the spacing
+ property to \a spacing.
+
+ \sa QLayout::setSpacing(), spacing()
+ */
+void QBoxLayout::setSpacing(int spacing)
+{
+ Q_D(QBoxLayout);
+ d->spacing = spacing;
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+QSize QBoxLayout::sizeHint() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->sizeHint;
+}
+
+/*!
+ \reimp
+*/
+QSize QBoxLayout::minimumSize() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->minSize;
+}
+
+/*!
+ \reimp
+*/
+QSize QBoxLayout::maximumSize() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+
+ QSize s = d->maxSize.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
+
+ if (alignment() & Qt::AlignHorizontal_Mask)
+ s.setWidth(QLAYOUTSIZE_MAX);
+ if (alignment() & Qt::AlignVertical_Mask)
+ s.setHeight(QLAYOUTSIZE_MAX);
+ return s;
+}
+
+/*!
+ \reimp
+*/
+bool QBoxLayout::hasHeightForWidth() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->hasHfw;
+}
+
+/*!
+ \reimp
+*/
+int QBoxLayout::heightForWidth(int w) const
+{
+ Q_D(const QBoxLayout);
+ if (!hasHeightForWidth())
+ return -1;
+
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+
+ w -= left + right;
+ if (w != d->hfwWidth)
+ const_cast<QBoxLayout*>(this)->d_func()->calcHfw(w);
+
+ return d->hfwHeight + top + bottom;
+}
+
+/*!
+ \reimp
+*/
+int QBoxLayout::minimumHeightForWidth(int w) const
+{
+ Q_D(const QBoxLayout);
+ (void) heightForWidth(w);
+ int top, bottom;
+ d->effectiveMargins(0, &top, 0, &bottom);
+ return d->hasHfw ? (d->hfwMinHeight + top + bottom) : -1;
+}
+
+/*!
+ Resets cached information.
+*/
+void QBoxLayout::invalidate()
+{
+ Q_D(QBoxLayout);
+ d->setDirty();
+ QLayout::invalidate();
+}
+
+/*!
+ \reimp
+*/
+int QBoxLayout::count() const
+{
+ Q_D(const QBoxLayout);
+ return d->list.count();
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QBoxLayout::itemAt(int index) const
+{
+ Q_D(const QBoxLayout);
+ return index >= 0 && index < d->list.count() ? d->list.at(index)->item : 0;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QBoxLayout::takeAt(int index)
+{
+ Q_D(QBoxLayout);
+ if (index < 0 || index >= d->list.count())
+ return 0;
+ QBoxLayoutItem *b = d->list.takeAt(index);
+ QLayoutItem *item = b->item;
+ b->item = 0;
+ delete b;
+
+ invalidate();
+ return item;
+}
+
+
+/*!
+ \reimp
+*/
+Qt::Orientations QBoxLayout::expandingDirections() const
+{
+ Q_D(const QBoxLayout);
+ if (d->dirty)
+ const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
+ return d->expanding;
+}
+
+/*!
+ \reimp
+*/
+void QBoxLayout::setGeometry(const QRect &r)
+{
+ Q_D(QBoxLayout);
+ if (d->dirty || r != geometry()) {
+ QRect oldRect = geometry();
+ QLayout::setGeometry(r);
+ if (d->dirty)
+ d->setupGeom();
+ QRect cr = alignment() ? alignmentRect(r) : r;
+
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ QRect s(cr.x() + left, cr.y() + top,
+ cr.width() - (left + right),
+ cr.height() - (top + bottom));
+
+ QVector<QLayoutStruct> a = d->geomArray;
+ int pos = horz(d->dir) ? s.x() : s.y();
+ int space = horz(d->dir) ? s.width() : s.height();
+ int n = a.count();
+ if (d->hasHfw && !horz(d->dir)) {
+ for (int i = 0; i < n; i++) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->item->hasHeightForWidth())
+ a[i].sizeHint = a[i].minimumSize =
+ box->item->heightForWidth(s.width());
+ }
+ }
+
+ Direction visualDir = d->dir;
+ QWidget *parent = parentWidget();
+ if (parent && parent->isRightToLeft()) {
+ if (d->dir == LeftToRight)
+ visualDir = RightToLeft;
+ else if (d->dir == RightToLeft)
+ visualDir = LeftToRight;
+ }
+
+ qGeomCalc(a, 0, n, pos, space);
+
+ bool reverse = (horz(visualDir)
+ ? ((r.right() > oldRect.right()) != (visualDir == RightToLeft))
+ : r.bottom() > oldRect.bottom());
+ for (int j = 0; j < n; j++) {
+ int i = reverse ? n-j-1 : j;
+ QBoxLayoutItem *box = d->list.at(i);
+
+ switch (visualDir) {
+ case LeftToRight:
+ box->item->setGeometry(QRect(a.at(i).pos, s.y(), a.at(i).size, s.height()));
+ break;
+ case RightToLeft:
+ box->item->setGeometry(QRect(s.left() + s.right() - a.at(i).pos - a.at(i).size + 1,
+ s.y(), a.at(i).size, s.height()));
+ break;
+ case TopToBottom:
+ box->item->setGeometry(QRect(s.x(), a.at(i).pos, s.width(), a.at(i).size));
+ break;
+ case BottomToTop:
+ box->item->setGeometry(QRect(s.x(),
+ s.top() + s.bottom() - a.at(i).pos - a.at(i).size + 1,
+ s.width(), a.at(i).size));
+ }
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QBoxLayout::addItem(QLayoutItem *item)
+{
+ Q_D(QBoxLayout);
+ QBoxLayoutItem *it = new QBoxLayoutItem(item);
+ d->list.append(it);
+ invalidate();
+}
+
+/*!
+ Inserts \a item into this box layout at position \a index. If \a
+ index is negative, the item is added at the end.
+
+ \sa addItem(), insertWidget(), insertLayout(), insertStretch(),
+ insertSpacing()
+*/
+void QBoxLayout::insertItem(int index, QLayoutItem *item)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(item);
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts a non-stretchable space (a QSpacerItem) at position \a index, with
+ size \a size. If \a index is negative the space is added at the end.
+
+ The box layout has default margin and spacing. This function adds
+ additional space.
+
+ \sa addSpacing(), insertItem(), QSpacerItem
+*/
+void QBoxLayout::insertSpacing(int index, int size)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QLayoutItem *b;
+ if (horz(d->dir))
+ b = QLayoutPrivate::createSpacerItem(this, size, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
+ else
+ b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts a stretchable space (a QSpacerItem) at position \a
+ index, with zero minimum size and stretch factor \a stretch. If \a
+ index is negative the space is added at the end.
+
+ \sa addStretch(), insertItem(), QSpacerItem
+*/
+void QBoxLayout::insertStretch(int index, int stretch)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QLayoutItem *b;
+ if (horz(d->dir))
+ b = QLayoutPrivate::createSpacerItem(this, 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ else
+ b = QLayoutPrivate::createSpacerItem(this, 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch);
+ it->magic = true;
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ \since 4.4
+
+ Inserts \a spacerItem at position \a index, with zero minimum
+ size and stretch factor. If \a index is negative the
+ space is added at the end.
+
+ \sa addSpacerItem(), insertStretch(), insertSpacing()
+*/
+void QBoxLayout::insertSpacerItem(int index, QSpacerItem *spacerItem)
+{
+ Q_D(QBoxLayout);
+ if (index < 0) // append
+ index = d->list.count();
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(spacerItem);
+ it->magic = true;
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts \a layout at position \a index, with stretch factor \a
+ stretch. If \a index is negative, the layout is added at the end.
+
+ \a layout becomes a child of the box layout.
+
+ \sa addLayout(), insertItem()
+*/
+void QBoxLayout::insertLayout(int index, QLayout *layout, int stretch)
+{
+ Q_D(QBoxLayout);
+ addChildLayout(layout);
+ if (index < 0) // append
+ index = d->list.count();
+ QBoxLayoutItem *it = new QBoxLayoutItem(layout, stretch);
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Inserts \a widget at position \a index, with stretch factor \a
+ stretch and alignment \a alignment. If \a index is negative, the
+ widget is added at the end.
+
+ The stretch factor applies only in the \l{direction()}{direction}
+ of the QBoxLayout, and is relative to the other boxes and widgets
+ in this QBoxLayout. Widgets and boxes with higher stretch factors
+ grow more.
+
+ If the stretch factor is 0 and nothing else in the QBoxLayout has
+ a stretch factor greater than zero, the space is distributed
+ according to the QWidget:sizePolicy() of each widget that's
+ involved.
+
+ The alignment is specified by \a alignment. The default alignment
+ is 0, which means that the widget fills the entire cell.
+
+ \sa addWidget(), insertItem()
+*/
+void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch,
+ Qt::Alignment alignment)
+{
+ Q_D(QBoxLayout);
+ if (!checkWidget(this, widget))
+ return;
+ addChildWidget(widget);
+ if (index < 0) // append
+ index = d->list.count();
+ QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
+ b->setAlignment(alignment);
+ QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch);
+ d->list.insert(index, it);
+ invalidate();
+}
+
+/*!
+ Adds a non-stretchable space (a QSpacerItem) with size \a size
+ to the end of this box layout. QBoxLayout provides default margin
+ and spacing. This function adds additional space.
+
+ \sa insertSpacing(), addItem(), QSpacerItem
+*/
+void QBoxLayout::addSpacing(int size)
+{
+ insertSpacing(-1, size);
+}
+
+/*!
+ Adds a stretchable space (a QSpacerItem) with zero minimum
+ size and stretch factor \a stretch to the end of this box layout.
+
+ \sa insertStretch(), addItem(), QSpacerItem
+*/
+void QBoxLayout::addStretch(int stretch)
+{
+ insertStretch(-1, stretch);
+}
+
+/*!
+ \since 4.4
+
+ Adds \a spacerItem to the end of this box layout.
+
+ \sa addSpacing(), addStretch()
+*/
+void QBoxLayout::addSpacerItem(QSpacerItem *spacerItem)
+{
+ insertSpacerItem(-1, spacerItem);
+}
+
+/*!
+ Adds \a widget to the end of this box layout, with a stretch
+ factor of \a stretch and alignment \a alignment.
+
+ The stretch factor applies only in the \l{direction()}{direction}
+ of the QBoxLayout, and is relative to the other boxes and widgets
+ in this QBoxLayout. Widgets and boxes with higher stretch factors
+ grow more.
+
+ If the stretch factor is 0 and nothing else in the QBoxLayout has
+ a stretch factor greater than zero, the space is distributed
+ according to the QWidget:sizePolicy() of each widget that's
+ involved.
+
+ The alignment is specified by \a alignment. The default
+ alignment is 0, which means that the widget fills the entire cell.
+
+ \sa insertWidget(), addItem(), addLayout(), addStretch(),
+ addSpacing(), addStrut()
+*/
+void QBoxLayout::addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
+{
+ insertWidget(-1, widget, stretch, alignment);
+}
+
+/*!
+ Adds \a layout to the end of the box, with serial stretch factor
+ \a stretch.
+
+ \sa insertLayout(), addItem(), addWidget()
+*/
+void QBoxLayout::addLayout(QLayout *layout, int stretch)
+{
+ insertLayout(-1, layout, stretch);
+}
+
+/*!
+ Limits the perpendicular dimension of the box (e.g. height if the
+ box is \l LeftToRight) to a minimum of \a size. Other constraints
+ may increase the limit.
+
+ \sa addItem()
+*/
+void QBoxLayout::addStrut(int size)
+{
+ Q_D(QBoxLayout);
+ QLayoutItem *b;
+ if (horz(d->dir))
+ b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Fixed, QSizePolicy::Minimum);
+ else
+ b = QLayoutPrivate::createSpacerItem(this, size, 0, QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.append(it);
+ invalidate();
+}
+
+/*!
+ \fn int QBoxLayout::findWidget(QWidget *widget)
+
+ Use indexOf(\a widget) instead.
+*/
+
+/*!
+ Sets the stretch factor for \a widget to \a stretch and returns
+ true if \a widget is found in this layout (not including child
+ layouts); otherwise returns false.
+
+ \sa setAlignment()
+*/
+bool QBoxLayout::setStretchFactor(QWidget *widget, int stretch)
+{
+ Q_D(QBoxLayout);
+ if (!widget)
+ return false;
+ for (int i = 0; i < d->list.size(); ++i) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->item->widget() == widget) {
+ box->stretch = stretch;
+ invalidate();
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Sets the stretch factor for the layout \a layout to \a stretch and
+ returns true if \a layout is found in this layout (not including
+ child layouts); otherwise returns false.
+*/
+bool QBoxLayout::setStretchFactor(QLayout *layout, int stretch)
+{
+ Q_D(QBoxLayout);
+ for (int i = 0; i < d->list.size(); ++i) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->item->layout() == layout) {
+ if (box->stretch != stretch) {
+ box->stretch = stretch;
+ invalidate();
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ Sets the stretch factor at position \a index. to \a stretch.
+
+ \since 4.5
+*/
+
+void QBoxLayout::setStretch(int index, int stretch)
+{
+ Q_D(QBoxLayout);
+ if (index >= 0 && index < d->list.size()) {
+ QBoxLayoutItem *box = d->list.at(index);
+ if (box->stretch != stretch) {
+ box->stretch = stretch;
+ invalidate();
+ }
+ }
+}
+
+/*!
+ Returns the stretch factor at position \a index.
+
+ \since 4.5
+*/
+
+int QBoxLayout::stretch(int index) const
+{
+ Q_D(const QBoxLayout);
+ if (index >= 0 && index < d->list.size())
+ return d->list.at(index)->stretch;
+ return -1;
+}
+
+/*!
+ Sets the direction of this layout to \a direction.
+*/
+void QBoxLayout::setDirection(Direction direction)
+{
+ Q_D(QBoxLayout);
+ if (d->dir == direction)
+ return;
+ if (horz(d->dir) != horz(direction)) {
+ //swap around the spacers (the "magic" bits)
+ //#### a bit yucky, knows too much.
+ //#### probably best to add access functions to spacerItem
+ //#### or even a QSpacerItem::flip()
+ for (int i = 0; i < d->list.size(); ++i) {
+ QBoxLayoutItem *box = d->list.at(i);
+ if (box->magic) {
+ QSpacerItem *sp = box->item->spacerItem();
+ if (sp) {
+ if (sp->expandingDirections() == Qt::Orientations(0) /*No Direction*/) {
+ //spacing or strut
+ QSize s = sp->sizeHint();
+ sp->changeSize(s.height(), s.width(),
+ horz(direction) ? QSizePolicy::Fixed:QSizePolicy::Minimum,
+ horz(direction) ? QSizePolicy::Minimum:QSizePolicy::Fixed);
+
+ } else {
+ //stretch
+ if (horz(direction))
+ sp->changeSize(0, 0, QSizePolicy::Expanding,
+ QSizePolicy::Minimum);
+ else
+ sp->changeSize(0, 0, QSizePolicy::Minimum,
+ QSizePolicy::Expanding);
+ }
+ }
+ }
+ }
+ }
+ d->dir = direction;
+ invalidate();
+}
+
+/*!
+ \fn QBoxLayout::Direction QBoxLayout::direction() const
+
+ Returns the direction of the box. addWidget() and addSpacing()
+ work in this direction; the stretch stretches in this direction.
+
+ \sa QBoxLayout::Direction addWidget() addSpacing()
+*/
+
+QBoxLayout::Direction QBoxLayout::direction() const
+{
+ Q_D(const QBoxLayout);
+ return d->dir;
+}
+
+/*!
+ \class QHBoxLayout
+ \brief The QHBoxLayout class lines up widgets horizontally.
+
+ \ingroup geomanagement
+ \ingroup appearance
+ \mainclass
+
+ This class is used to construct horizontal box layout objects. See
+ QBoxLayout for details.
+
+ The simplest use of the class is like this:
+
+ \snippet doc/src/snippets/layouts/layouts.cpp 0
+ \snippet doc/src/snippets/layouts/layouts.cpp 1
+ \snippet doc/src/snippets/layouts/layouts.cpp 2
+ \codeline
+ \snippet doc/src/snippets/layouts/layouts.cpp 3
+ \snippet doc/src/snippets/layouts/layouts.cpp 4
+ \snippet doc/src/snippets/layouts/layouts.cpp 5
+
+ First, we create the widgets we want in the layout. Then, we
+ create the QHBoxLayout object and add the widgets into the
+ layout. Finally, we call QWidget::setLayout() to install the
+ QHBoxLayout object onto the widget. At that point, the widgets in
+ the layout are reparented to have \c window as their parent.
+
+ \image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
+
+ \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+*/
+
+
+/*!
+ Constructs a new top-level horizontal box with
+ parent \a parent.
+*/
+QHBoxLayout::QHBoxLayout(QWidget *parent)
+ : QBoxLayout(LeftToRight, parent)
+{
+}
+
+/*!
+ Constructs a new horizontal box. You must add
+ it to another layout.
+*/
+QHBoxLayout::QHBoxLayout()
+ : QBoxLayout(LeftToRight)
+{
+}
+
+
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new top-level horizontal box called \a name, with
+ parent \a parent.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and its managed children. The \a spacing is the default
+ number of pixels between neighboring children. If \a spacing is -1
+ the value of \a margin is used for \a spacing.
+*/
+QHBoxLayout::QHBoxLayout(QWidget *parent, int margin,
+ int spacing, const char *name)
+ : QBoxLayout(LeftToRight, parent)
+{
+ setMargin(margin);
+ setSpacing(spacing<0 ? margin : spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ Constructs a new horizontal box called name \a name and adds it to
+ \a parentLayout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QHBoxLayout will inherit its
+ parent's spacing().
+*/
+QHBoxLayout::QHBoxLayout(QLayout *parentLayout, int spacing,
+ const char *name)
+ : QBoxLayout(LeftToRight)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+ if (parentLayout) {
+ setParent(parentLayout);
+ parentLayout->addItem(this);
+ }
+}
+
+/*!
+ Constructs a new horizontal box called name \a name. You must add
+ it to another layout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QHBoxLayout will inherit its
+ parent's spacing().
+*/
+QHBoxLayout::QHBoxLayout(int spacing, const char *name)
+ : QBoxLayout(LeftToRight)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+
+/*!
+ Destroys this box layout.
+
+ The layout's widgets aren't destroyed.
+*/
+QHBoxLayout::~QHBoxLayout()
+{
+}
+
+/*!
+ \class QVBoxLayout
+ \brief The QVBoxLayout class lines up widgets vertically.
+
+ \ingroup geomanagement
+ \ingroup appearance
+ \mainclass
+
+ This class is used to construct vertical box layout objects. See
+ QBoxLayout for details.
+
+ The simplest use of the class is like this:
+
+ \snippet doc/src/snippets/layouts/layouts.cpp 6
+ \snippet doc/src/snippets/layouts/layouts.cpp 7
+ \snippet doc/src/snippets/layouts/layouts.cpp 8
+ \codeline
+ \snippet doc/src/snippets/layouts/layouts.cpp 9
+ \snippet doc/src/snippets/layouts/layouts.cpp 10
+ \snippet doc/src/snippets/layouts/layouts.cpp 11
+
+ First, we create the widgets we want in the layout. Then, we
+ create the QVBoxLayout object and add the widgets into the
+ layout. Finally, we call QWidget::setLayout() to install the
+ QVBoxLayout object onto the widget. At that point, the widgets in
+ the layout are reparented to have \c window as their parent.
+
+ \image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets
+
+ \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+*/
+
+/*!
+ Constructs a new top-level vertical box with
+ parent \a parent.
+*/
+QVBoxLayout::QVBoxLayout(QWidget *parent)
+ : QBoxLayout(TopToBottom, parent)
+{
+}
+
+/*!
+ Constructs a new vertical box. You must add
+ it to another layout.
+
+*/
+QVBoxLayout::QVBoxLayout()
+ : QBoxLayout(TopToBottom)
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new top-level vertical box called \a name, with
+ parent \a parent.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and its managed children. The \a spacing is the default
+ number of pixels between neighboring children. If \a spacing is -1
+ the value of \a margin is used for \a spacing.
+*/
+QVBoxLayout::QVBoxLayout(QWidget *parent, int margin, int spacing,
+ const char *name)
+ : QBoxLayout(TopToBottom, parent)
+{
+ setMargin(margin);
+ setSpacing(spacing<0 ? margin : spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ Constructs a new vertical box called name \a name and adds it to
+ \a parentLayout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QVBoxLayout will inherit its
+ parent's spacing().
+*/
+QVBoxLayout::QVBoxLayout(QLayout *parentLayout, int spacing,
+ const char *name)
+ : QBoxLayout(TopToBottom)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+ if (parentLayout) {
+ setParent(parentLayout);
+ parentLayout->addItem(this);
+ }
+}
+
+/*!
+ Constructs a new vertical box called name \a name. You must add
+ it to another layout.
+
+ The \a spacing is the default number of pixels between neighboring
+ children. If \a spacing is -1, this QVBoxLayout will inherit its
+ parent's spacing().
+*/
+QVBoxLayout::QVBoxLayout(int spacing, const char *name)
+ : QBoxLayout(TopToBottom)
+{
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+
+#endif
+
+/*!
+ Destroys this box layout.
+
+ The layout's widgets aren't destroyed.
+*/
+QVBoxLayout::~QVBoxLayout()
+{
+}
+
+/*!
+ \fn QWidget *QLayout::mainWidget() const
+
+ Use parentWidget() instead.
+*/
+
+/*!
+ \fn void QLayout::remove(QWidget *widget)
+
+ Use removeWidget(\a widget) instead.
+*/
+
+/*!
+ \fn void QLayout::add(QWidget *widget)
+
+ Use addWidget(\a widget) instead.
+*/
+
+/*!
+ \fn QLayoutIterator QLayout::iterator()
+
+ Use a QLayoutIterator() constructor instead.
+*/
+
+/*!
+ \fn int QLayout::defaultBorder() const
+
+ Use spacing() instead.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qboxlayout.h b/src/gui/kernel/qboxlayout.h
new file mode 100644
index 0000000000..f4ba0c7409
--- /dev/null
+++ b/src/gui/kernel/qboxlayout.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBOXLAYOUT_H
+#define QBOXLAYOUT_H
+
+#include <QtGui/qlayout.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <QtGui/qwidget.h>
+#endif
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QBoxLayoutPrivate;
+
+class Q_GUI_EXPORT QBoxLayout : public QLayout
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QBoxLayout)
+public:
+ enum Direction { LeftToRight, RightToLeft, TopToBottom, BottomToTop,
+ Down = TopToBottom, Up = BottomToTop };
+
+ explicit QBoxLayout(Direction, QWidget *parent = 0);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QBoxLayout(QWidget *parent, Direction, int border = 0, int spacing = -1,
+ const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QBoxLayout(QLayout *parentLayout, Direction, int spacing = -1,
+ const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QBoxLayout(Direction, int spacing, const char *name = 0);
+#endif
+ ~QBoxLayout();
+
+ Direction direction() const;
+ void setDirection(Direction);
+
+ void addSpacing(int size);
+ void addStretch(int stretch = 0);
+ void addSpacerItem(QSpacerItem *spacerItem);
+ void addWidget(QWidget *, int stretch = 0, Qt::Alignment alignment = 0);
+ void addLayout(QLayout *layout, int stretch = 0);
+ void addStrut(int);
+ void addItem(QLayoutItem *);
+
+ void insertSpacing(int index, int size);
+ void insertStretch(int index, int stretch = 0);
+ void insertSpacerItem(int index, QSpacerItem *spacerItem);
+ void insertWidget(int index, QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0);
+ void insertLayout(int index, QLayout *layout, int stretch = 0);
+
+ int spacing() const;
+ void setSpacing(int spacing);
+
+ bool setStretchFactor(QWidget *w, int stretch);
+ bool setStretchFactor(QLayout *l, int stretch);
+ void setStretch(int index, int stretch);
+ int stretch(int index) const;
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int minimumHeightForWidth(int) const;
+
+ Qt::Orientations expandingDirections() const;
+ void invalidate();
+ QLayoutItem *itemAt(int) const;
+ QLayoutItem *takeAt(int);
+ int count() const;
+ void setGeometry(const QRect&);
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT int findWidget(QWidget* w) {return indexOf(w);}
+#endif
+protected:
+ // ### Qt 5: make public
+ void insertItem(int index, QLayoutItem *);
+
+private:
+ Q_DISABLE_COPY(QBoxLayout)
+};
+
+class Q_GUI_EXPORT QHBoxLayout : public QBoxLayout
+{
+ Q_OBJECT
+public:
+ QHBoxLayout();
+ explicit QHBoxLayout(QWidget *parent);
+ ~QHBoxLayout();
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QHBoxLayout(QWidget *parent, int border,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QHBoxLayout(QLayout *parentLayout,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QHBoxLayout(int spacing, const char *name = 0);
+#endif
+
+private:
+ Q_DISABLE_COPY(QHBoxLayout)
+};
+
+class Q_GUI_EXPORT QVBoxLayout : public QBoxLayout
+{
+ Q_OBJECT
+public:
+ QVBoxLayout();
+ explicit QVBoxLayout(QWidget *parent);
+ ~QVBoxLayout();
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QVBoxLayout(QWidget *parent, int border,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QVBoxLayout(QLayout *parentLayout,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QVBoxLayout(int spacing, const char *name = 0);
+#endif
+
+private:
+ Q_DISABLE_COPY(QVBoxLayout)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBOXLAYOUT_H
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
new file mode 100644
index 0000000000..917b5d59f5
--- /dev/null
+++ b/src/gui/kernel/qclipboard.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qpixmap.h"
+#include "qclipboard_p.h"
+#include "qvariant.h"
+#include "qbuffer.h"
+#include "qimage.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QClipboard
+ \brief The QClipboard class provides access to the window system clipboard.
+
+ \ingroup io
+ \ingroup environment
+ \mainclass
+
+ The clipboard offers a simple mechanism to copy and paste data
+ between applications.
+
+ QClipboard supports the same data types that QDrag does, and uses
+ similar mechanisms. For advanced clipboard usage read \l{Drag and
+ Drop}.
+
+ There is a single QClipboard object in an application, accessible
+ as QApplication::clipboard().
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qclipboard.cpp 0
+
+ QClipboard features some convenience functions to access common
+ data types: setText() allows the exchange of Unicode text and
+ setPixmap() and setImage() allows the exchange of QPixmaps and
+ QImages between applications. The setMimeData() function is the
+ ultimate in flexibility: it allows you to add any QMimeData into
+ the clipboard. There are corresponding getters for each of these,
+ e.g. text(), image() and pixmap(). You can clear the clipboard by
+ calling clear().
+
+ A typical example of the use of these functions follows:
+
+ \snippet doc/src/snippets/droparea.cpp 0
+
+ \section1 Notes for X11 Users
+
+ \list
+
+ \i The X11 Window System has the concept of a separate selection
+ and clipboard. When text is selected, it is immediately available
+ as the global mouse selection. The global mouse selection may
+ later be copied to the clipboard. By convention, the middle mouse
+ button is used to paste the global mouse selection.
+
+ \i X11 also has the concept of ownership; if you change the
+ selection within a window, X11 will only notify the owner and the
+ previous owner of the change, i.e. it will not notify all
+ applications that the selection or clipboard data changed.
+
+ \i Lastly, the X11 clipboard is event driven, i.e. the clipboard
+ will not function properly if the event loop is not running.
+ Similarly, it is recommended that the contents of the clipboard
+ are stored or retrieved in direct response to user-input events,
+ e.g. mouse button or key presses and releases. You should not
+ store or retrieve the clipboard contents in response to timer or
+ non-user-input events.
+
+ \endlist
+
+ \section1 Notes for Mac OS X Users
+
+ Mac OS X supports a separate find buffer that holds the current
+ search string in Find operations. This find clipboard can be accessed
+ by specifying the FindBuffer mode.
+
+ \section1 Notes for Windows and Mac OS X Users
+
+ \list
+
+ \i Windows and Mac OS X do not support the global mouse
+ selection; they only supports the global clipboard, i.e. they
+ only add text to the clipboard when an explicit copy or cut is
+ made.
+
+ \i Windows and Mac OS X does not have the concept of ownership;
+ the clipboard is a fully global resource so all applications are
+ notified of changes.
+
+ \endlist
+
+ \sa QApplication
+*/
+
+#ifndef Q_WS_X11
+// for X11 there is a separate implementation of a constructor.
+/*!
+ \internal
+
+ Constructs a clipboard object.
+
+ Do not call this function.
+
+ Call QApplication::clipboard() instead to get a pointer to the
+ application's global clipboard object.
+
+ There is only one clipboard in the window system, and creating
+ more than one object to represent it is almost certainly an error.
+*/
+
+QClipboard::QClipboard(QObject *parent)
+ : QObject(*new QClipboardPrivate, parent)
+{
+ // nothing
+}
+#endif
+
+#ifndef Q_WS_WIN32
+/*!
+ \internal
+
+ Destroys the clipboard.
+
+ You should never delete the clipboard. QApplication will do this
+ when the application terminates.
+*/
+QClipboard::~QClipboard()
+{
+}
+#endif
+
+/*!
+ \fn void QClipboard::changed(QClipboard::Mode mode)
+ \since 4.2
+
+ This signal is emitted when the data for the given clipboard \a
+ mode is changed.
+
+ \sa dataChanged(), selectionChanged(), findBufferChanged()
+*/
+
+/*!
+ \fn void QClipboard::dataChanged()
+
+ This signal is emitted when the clipboard data is changed.
+
+ On Mac OS X and with Qt version 4.3 or higher, clipboard
+ changes made by other applications will only be detected
+ when the application is activated.
+
+ \sa findBufferChanged(), selectionChanged(), changed()
+*/
+
+/*!
+ \fn void QClipboard::selectionChanged()
+
+ This signal is emitted when the selection is changed. This only
+ applies to windowing systems that support selections, e.g. X11.
+ Windows and Mac OS X don't support selections.
+
+ \sa dataChanged(), findBufferChanged(), changed()
+*/
+
+/*!
+ \fn void QClipboard::findBufferChanged()
+ \since 4.2
+
+ This signal is emitted when the find buffer is changed. This only
+ applies to Mac OS X.
+
+ With Qt version 4.3 or higher, clipboard changes made by other
+ applications will only be detected when the application is activated.
+
+ \sa dataChanged(), selectionChanged(), changed()
+*/
+
+
+/*! \enum QClipboard::Mode
+ \keyword clipboard mode
+
+ This enum type is used to control which part of the system clipboard is
+ used by QClipboard::mimeData(), QClipboard::setMimeData() and related functions.
+
+ \value Clipboard indicates that data should be stored and retrieved from
+ the global clipboard.
+
+ \value Selection indicates that data should be stored and retrieved from
+ the global mouse selection. Support for \c Selection is provided only on
+ systems with a global mouse selection (e.g. X11).
+
+ \value FindBuffer indicates that data should be stored and retrieved from
+ the Find buffer. This mode is used for holding search strings on Mac OS X.
+
+ \omitvalue LastMode
+
+ \sa QClipboard::supportsSelection()
+*/
+
+
+/*****************************************************************************
+ QApplication member functions related to QClipboard.
+ *****************************************************************************/
+
+// text handling is done directly in qclipboard_qws, for now
+
+/*!
+ \fn bool QClipboard::event(QEvent *e)
+ \reimp
+*/
+
+/*!
+ \overload
+
+ Returns the clipboard text in subtype \a subtype, or an empty string
+ if the clipboard does not contain any text. If \a subtype is null,
+ any subtype is acceptable, and \a subtype is set to the chosen
+ subtype.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ text is retrieved from the global clipboard. If \a mode is
+ QClipboard::Selection, the text is retrieved from the global
+ mouse selection.
+
+ Common values for \a subtype are "plain" and "html".
+
+ Note that calling this function repeatedly, for instance from a
+ key event handler, may be slow. In such cases, you should use the
+ \c dataChanged() signal instead.
+
+ \sa setText(), mimeData()
+*/
+QString QClipboard::text(QString &subtype, Mode mode) const
+{
+ const QMimeData *data = mimeData(mode);
+ if (!data)
+ return QString();
+ if (subtype.isEmpty()) {
+ QStringList formats = data->formats();
+ if (formats.contains(QLatin1String("text/plain")))
+ subtype = QLatin1String("plain");
+ else {
+ for (int i = 0; i < formats.size(); ++i)
+ if (formats.at(i).startsWith(QLatin1String("text/"))) {
+ subtype = formats.at(i).mid(5);
+ break;
+ }
+ }
+ }
+ if (subtype.isEmpty())
+ return QString();
+ if (subtype == QLatin1String("plain"))
+ return data->text();
+ return QString::fromUtf8(data->data(QLatin1String("text/") + subtype));
+}
+
+/*!
+ Returns the clipboard text as plain text, or an empty string if the
+ clipboard does not contain any text.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ text is retrieved from the global clipboard. If \a mode is
+ QClipboard::Selection, the text is retrieved from the global
+ mouse selection. If \a mode is QClipboard::FindBuffer, the
+ text is retrieved from the search string buffer.
+
+ \sa setText(), mimeData()
+*/
+QString QClipboard::text(Mode mode) const
+{
+ const QMimeData *data = mimeData(mode);
+ return data ? data->text() : QString();
+}
+
+/*!
+ Copies \a text into the clipboard as plain text.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ text is stored in the global clipboard. If \a mode is
+ QClipboard::Selection, the text is stored in the global
+ mouse selection. If \a mode is QClipboard::FindBuffer, the
+ text is stored in the search string buffer.
+
+ \sa text(), setMimeData()
+*/
+void QClipboard::setText(const QString &text, Mode mode)
+{
+ QMimeData *data = new QMimeData;
+ data->setText(text);
+ setMimeData(data, mode);
+}
+
+/*!
+ Returns the clipboard image, or returns a null image if the
+ clipboard does not contain an image or if it contains an image in
+ an unsupported image format.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ image is retrieved from the global clipboard. If \a mode is
+ QClipboard::Selection, the image is retrieved from the global
+ mouse selection.
+
+ \sa setImage() pixmap() mimeData(), QImage::isNull()
+*/
+QImage QClipboard::image(Mode mode) const
+{
+ const QMimeData *data = mimeData(mode);
+ if (!data)
+ return QImage();
+ return qvariant_cast<QImage>(data->imageData());
+}
+
+/*!
+ Copies the \a image into the clipboard.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ image is stored in the global clipboard. If \a mode is
+ QClipboard::Selection, the data is stored in the global
+ mouse selection.
+
+ This is shorthand for:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qclipboard.cpp 1
+
+ \sa image(), setPixmap() setMimeData()
+*/
+void QClipboard::setImage(const QImage &image, Mode mode)
+{
+ QMimeData *data = new QMimeData;
+ data->setImageData(image);
+ setMimeData(data, mode);
+}
+
+/*!
+ Returns the clipboard pixmap, or null if the clipboard does not
+ contain a pixmap. Note that this can lose information. For
+ example, if the image is 24-bit and the display is 8-bit, the
+ result is converted to 8 bits, and if the image has an alpha
+ channel, the result just has a mask.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ pixmap is retrieved from the global clipboard. If \a mode is
+ QClipboard::Selection, the pixmap is retrieved from the global
+ mouse selection.
+
+ \sa setPixmap() image() mimeData() QPixmap::convertFromImage()
+*/
+QPixmap QClipboard::pixmap(Mode mode) const
+{
+ const QMimeData *data = mimeData(mode);
+ return data ? qvariant_cast<QPixmap>(data->imageData()) : QPixmap();
+}
+
+/*!
+ Copies \a pixmap into the clipboard. Note that this is slower
+ than setImage() because it needs to convert the QPixmap to a
+ QImage first.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ pixmap is stored in the global clipboard. If \a mode is
+ QClipboard::Selection, the pixmap is stored in the global
+ mouse selection.
+
+ \sa pixmap() setImage() setMimeData()
+*/
+void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
+{
+ QMimeData *data = new QMimeData;
+ data->setImageData(pixmap);
+ setMimeData(data, mode);
+}
+
+
+/*!
+ \fn QMimeData *QClipboard::mimeData(Mode mode) const
+
+ Returns a reference to a QMimeData representation of the current
+ clipboard data.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ data is retrieved from the global clipboard. If \a mode is
+ QClipboard::Selection, the data is retrieved from the global
+ mouse selection. If \a mode is QClipboard::FindBuffer, the
+ data is retrieved from the search string buffer.
+
+ The text(), image(), and pixmap() functions are simpler
+ wrappers for retrieving text, image, and pixmap data.
+
+ \sa setMimeData()
+*/
+
+/*!
+ \fn void QClipboard::setMimeData(QMimeData *src, Mode mode)
+
+ Sets the clipboard data to \a src. Ownership of the data is
+ transferred to the clipboard. If you want to remove the data
+ either call clear() or call setMimeData() again with new data.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, the
+ data is stored in the global clipboard. If \a mode is
+ QClipboard::Selection, the data is stored in the global
+ mouse selection. If \a mode is QClipboard::FindBuffer, the
+ data is stored in the search string buffer.
+
+ The setText(), setImage() and setPixmap() functions are simpler
+ wrappers for setting text, image and pixmap data respectively.
+
+ \sa mimeData()
+*/
+
+/*!
+ \fn void QClipboard::clear(Mode mode)
+ Clear the clipboard contents.
+
+ The \a mode argument is used to control which part of the system
+ clipboard is used. If \a mode is QClipboard::Clipboard, this
+ function clears the the global clipboard contents. If \a mode is
+ QClipboard::Selection, this function clears the global mouse
+ selection contents. If \a mode is QClipboard::FindBuffer, this
+ function clears the search string buffer.
+
+ \sa QClipboard::Mode, supportsSelection()
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ \fn QMimeSource *QClipboard::data(Mode mode) const
+ \compat
+
+ Use mimeData() instead.
+*/
+QMimeSource *QClipboard::data(Mode mode) const
+{
+ Q_D(const QClipboard);
+
+ if (supportsMode(mode) == false)
+ return 0;
+
+ if (d->compat_data[mode])
+ return d->compat_data[mode];
+
+ d->wrapper[mode]->data = mimeData(mode);
+ return d->wrapper[mode];
+}
+
+
+/*!
+ \fn void QClipboard::setData(QMimeSource *src, Mode mode)
+ \compat
+
+ Use setMimeData() instead.
+*/
+void QClipboard::setData(QMimeSource *source, Mode mode)
+{
+ Q_D(QClipboard);
+
+ if (supportsMode(mode) == false)
+ return;
+
+ d->compat_data[mode] = source;
+ setMimeData(new QMimeSourceWrapper(d, mode), mode);
+}
+#endif // QT3_SUPPORT
+
+/*!
+ Returns true if the clipboard supports mouse selection; otherwise
+ returns false.
+*/
+bool QClipboard::supportsSelection() const
+{
+ return supportsMode(Selection);
+}
+
+/*!
+ Returns true if the clipboard supports a separate search buffer; otherwise
+ returns false.
+*/
+bool QClipboard::supportsFindBuffer() const
+{
+ return supportsMode(FindBuffer);
+}
+
+/*!
+ Returns true if this clipboard object owns the clipboard data;
+ otherwise returns false.
+*/
+bool QClipboard::ownsClipboard() const
+{
+ return ownsMode(Clipboard);
+}
+
+/*!
+ Returns true if this clipboard object owns the mouse selection
+ data; otherwise returns false.
+*/
+bool QClipboard::ownsSelection() const
+{
+ return ownsMode(Selection);
+}
+
+/*!
+ \since 4.2
+
+ Returns true if this clipboard object owns the find buffer data;
+ otherwise returns false.
+*/
+bool QClipboard::ownsFindBuffer() const
+{
+ return ownsMode(FindBuffer);
+}
+
+/*!
+ \internal
+ \fn bool QClipboard::supportsMode(Mode mode) const;
+ Returns true if the clipboard supports the clipboard mode speacified by \a mode;
+ otherwise returns false.
+*/
+
+/*!
+ \internal
+ \fn bool QClipboard::ownsMode(Mode mode) const;
+ Returns true if the clipboard supports the clipboard data speacified by \a mode;
+ otherwise returns false.
+*/
+
+/*!
+ \internal
+ Emits the appropriate changed signal for \a mode.
+*/
+void QClipboard::emitChanged(Mode mode)
+{
+ switch (mode) {
+ case Clipboard:
+ emit dataChanged();
+ break;
+ case Selection:
+ emit selectionChanged();
+ break;
+ case FindBuffer:
+ emit findBufferChanged();
+ break;
+ default:
+ break;
+ }
+ emit changed(mode);
+}
+
+const char* QMimeDataWrapper::format(int n) const
+{
+ if (formats.isEmpty()) {
+ QStringList fmts = data->formats();
+ for (int i = 0; i < fmts.size(); ++i)
+ formats.append(fmts.at(i).toLatin1());
+ }
+ if (n < 0 || n >= formats.size())
+ return 0;
+ return formats.at(n).data();
+}
+
+QByteArray QMimeDataWrapper::encodedData(const char *format) const
+{
+ if (QLatin1String(format) != QLatin1String("application/x-qt-image")){
+ return data->data(QLatin1String(format));
+ } else{
+ QVariant variant = data->imageData();
+ QImage img = qVariantValue<QImage>(variant);
+ QByteArray ba;
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::WriteOnly);
+ img.save(&buffer, "PNG");
+ return ba;
+ }
+}
+
+QVariant QMimeSourceWrapper::retrieveData(const QString &mimetype, QVariant::Type) const
+{
+ return source->encodedData(mimetype.toLatin1());
+}
+
+bool QMimeSourceWrapper::hasFormat(const QString &mimetype) const
+{
+ return source->provides(mimetype.toLatin1());
+}
+
+QStringList QMimeSourceWrapper::formats() const
+{
+ QStringList fmts;
+ int i = 0;
+ const char *fmt;
+ while ((fmt = source->format(i))) {
+ fmts.append(QLatin1String(fmt));
+ ++i;
+ }
+ return fmts;
+}
+
+#endif // QT_NO_CLIPBOARD
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qclipboard.h b/src/gui/kernel/qclipboard.h
new file mode 100644
index 0000000000..fa3c6fabf0
--- /dev/null
+++ b/src/gui/kernel/qclipboard.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCLIPBOARD_H
+#define QCLIPBOARD_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_CLIPBOARD
+
+class QMimeSource;
+class QMimeData;
+class QImage;
+class QPixmap;
+
+class QClipboardPrivate;
+
+class Q_GUI_EXPORT QClipboard : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QClipboard)
+private:
+ QClipboard(QObject *parent);
+ ~QClipboard();
+
+public:
+ enum Mode { Clipboard, Selection, FindBuffer, LastMode = FindBuffer };
+
+ void clear(Mode mode = Clipboard);
+
+ bool supportsSelection() const;
+ bool supportsFindBuffer() const;
+
+ bool ownsSelection() const;
+ bool ownsClipboard() const;
+ bool ownsFindBuffer() const;
+
+ QString text(Mode mode = Clipboard) const;
+ QString text(QString& subtype, Mode mode = Clipboard) const;
+ void setText(const QString &, Mode mode = Clipboard);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT QMimeSource *data(Mode mode = Clipboard) const;
+ QT3_SUPPORT void setData(QMimeSource*, Mode mode = Clipboard);
+#endif
+ const QMimeData *mimeData(Mode mode = Clipboard ) const;
+ void setMimeData(QMimeData *data, Mode mode = Clipboard);
+
+ QImage image(Mode mode = Clipboard) const;
+ QPixmap pixmap(Mode mode = Clipboard) const;
+ void setImage(const QImage &, Mode mode = Clipboard);
+ void setPixmap(const QPixmap &, Mode mode = Clipboard);
+
+Q_SIGNALS:
+ void changed(QClipboard::Mode mode);
+ void selectionChanged();
+ void findBufferChanged();
+ void dataChanged();
+private Q_SLOTS:
+ void ownerDestroyed();
+
+protected:
+ void connectNotify(const char *);
+ bool event(QEvent *);
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QBaseApplication;
+ friend class QDragManager;
+ friend class QMimeSource;
+
+private:
+ Q_DISABLE_COPY(QClipboard)
+
+ bool supportsMode(Mode mode) const;
+ bool ownsMode(Mode mode) const;
+ void emitChanged(Mode mode);
+};
+
+#endif // QT_NO_CLIPBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCLIPBOARD_H
diff --git a/src/gui/kernel/qclipboard_mac.cpp b/src/gui/kernel/qclipboard_mac.cpp
new file mode 100644
index 0000000000..aafa5879b7
--- /dev/null
+++ b/src/gui/kernel/qclipboard_mac.cpp
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qdebug.h"
+#include "qapplication_p.h"
+#include <private/qt_mac_p.h>
+#include "qevent.h"
+#include "qurl.h"
+#include <stdlib.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+/*****************************************************************************
+ QClipboard debug facilities
+ *****************************************************************************/
+//#define DEBUG_PASTEBOARD
+
+#ifndef QT_NO_CLIPBOARD
+
+/*****************************************************************************
+ QClipboard member functions for mac.
+ *****************************************************************************/
+
+static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0};
+
+static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode)
+{
+ Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer);
+ if (mode == QClipboard::Clipboard)
+ return qt_mac_pasteboards[0];
+ else
+ return qt_mac_pasteboards[1];
+}
+
+static void qt_mac_cleanupPasteboard() {
+ delete qt_mac_pasteboards[0];
+ delete qt_mac_pasteboards[1];
+ qt_mac_pasteboards[0] = 0;
+ qt_mac_pasteboards[1] = 0;
+}
+
+static bool qt_mac_updateScrap(QClipboard::Mode mode)
+{
+ if(!qt_mac_pasteboards[0]) {
+ qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP);
+ qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP);
+ qAddPostRoutine(qt_mac_cleanupPasteboard);
+ return true;
+ }
+ return qt_mac_pasteboard(mode)->sync();
+}
+
+void QClipboard::clear(Mode mode)
+{
+ if (!supportsMode(mode))
+ return;
+ qt_mac_updateScrap(mode);
+ qt_mac_pasteboard(mode)->clear();
+ setMimeData(0, mode);
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+
+
+void QClipboard::connectNotify(const char *signal)
+{
+ Q_UNUSED(signal);
+}
+
+bool QClipboard::event(QEvent *e)
+{
+ if(e->type() != QEvent::Clipboard)
+ return QObject::event(e);
+
+ if (qt_mac_updateScrap(QClipboard::Clipboard)) {
+ emitChanged(QClipboard::Clipboard);
+ }
+
+ if (qt_mac_updateScrap(QClipboard::FindBuffer)) {
+ emitChanged(QClipboard::FindBuffer);
+ }
+
+ return QObject::event(e);
+}
+
+const QMimeData *QClipboard::mimeData(Mode mode) const
+{
+ if (!supportsMode(mode))
+ return 0;
+ qt_mac_updateScrap(mode);
+ return qt_mac_pasteboard(mode)->mimeData();
+}
+
+void QClipboard::setMimeData(QMimeData *src, Mode mode)
+{
+ if (!supportsMode(mode))
+ return;
+ qt_mac_updateScrap(mode);
+ qt_mac_pasteboard(mode)->setMimeData(src);
+ emitChanged(mode);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard || mode == FindBuffer);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ Q_UNUSED(mode);
+ return false;
+}
+
+#endif // QT_NO_CLIPBOARD
+
+/*****************************************************************************
+ QMacPasteboard code
+*****************************************************************************/
+
+QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = p;
+ CFRetain(paste);
+}
+
+QMacPasteboard::QMacPasteboard(uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = 0;
+ OSStatus err = PasteboardCreate(0, &paste);
+ if(err == noErr) {
+ PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
+ } else {
+ qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err);
+ }
+}
+
+QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = 0;
+ OSStatus err = PasteboardCreate(name, &paste);
+ if(err == noErr) {
+ PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
+ } else {
+ qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err);
+ }
+}
+
+QMacPasteboard::~QMacPasteboard()
+{
+ // commit all promises for paste after exit close
+ for (int i = 0; i < promises.count(); ++i) {
+ const Promise &promise = promises.at(i);
+ QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
+ promiseKeeper(paste, (PasteboardItemID)promise.itemId, flavor, this);
+ }
+
+ if(paste)
+ CFRelease(paste);
+}
+
+PasteboardRef
+QMacPasteboard::pasteBoard() const
+{
+ return paste;
+}
+
+OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, CFStringRef flavor, void *_qpaste)
+{
+ QMacPasteboard *qpaste = (QMacPasteboard*)_qpaste;
+ const long promise_id = (long)id;
+
+ // Find the kept promise
+ const QString flavorAsQString = QCFString::toQString(flavor);
+ QMacPasteboard::Promise promise;
+ for (int i = 0; i < qpaste->promises.size(); i++){
+ QMacPasteboard::Promise tmp = qpaste->promises[i];
+ if (tmp.itemId == promise_id && tmp.convertor->canConvert(tmp.mime, flavorAsQString)){
+ promise = tmp;
+ break;
+ }
+ }
+
+ if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) {
+ // we have promised this data, but wont be able to convert, so return null data.
+ // This helps in making the application/x-qt-mime-type-name hidden from normal use.
+ QByteArray ba;
+ QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
+ return noErr;
+ }
+
+ if (!promise.itemId) {
+ // There was no promise that could deliver data for the
+ // given id and flavor. This should not happend.
+ qDebug("Pasteboard: %d: Request for %ld, %s, but no promise found!", __LINE__, promise_id, qPrintable(flavorAsQString));
+ return cantGetFlavorErr;
+ }
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: Calling in promise for %s[%ld] [%s] (%s) [%d]", qPrintable(promise.mime), promise_id,
+ qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset);
+#endif
+
+ QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString);
+ if (md.size() <= promise.offset)
+ return cantGetFlavorErr;
+ const QByteArray &ba = md[promise.offset];
+ QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
+ return noErr;
+}
+
+bool
+QMacPasteboard::hasOSType(int c_flavor) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if(PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasOSType [%c%c%c%c]", (c_flavor>>24)&0xFF, (c_flavor>>16)&0xFF,
+ (c_flavor>>8)&0xFF, (c_flavor>>0)&0xFF);
+#endif
+ for(uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ return false;
+
+ QCFType<CFArrayRef> types;
+ if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ return false;
+
+ const int type_count = CFArrayGetCount(types);
+ for(int i = 0; i < type_count; ++i) {
+ CFStringRef flavor = (CFStringRef)CFArrayGetValueAtIndex(types, i);
+ const int os_flavor = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(flavor, kUTTagClassOSType));
+ if(os_flavor == c_flavor) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - Found!");
+#endif
+ return true;
+ }
+ }
+ }
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NotFound!");
+#endif
+ return false;
+}
+
+bool
+QMacPasteboard::hasFlavor(QString c_flavor) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if(PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasFlavor [%s]", qPrintable(c_flavor));
+#endif
+ for(uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ return false;
+
+ PasteboardFlavorFlags flags;
+ if(PasteboardGetItemFlavorFlags(paste, id, QCFString(c_flavor), &flags) == noErr) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - Found!");
+#endif
+ return true;
+ }
+ }
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NotFound!");
+#endif
+ return false;
+}
+
+class QMacPasteboardMimeSource : public QMimeData {
+ const QMacPasteboard *paste;
+public:
+ QMacPasteboardMimeSource(const QMacPasteboard *p) : QMimeData(), paste(p) { }
+ ~QMacPasteboardMimeSource() { }
+ virtual QStringList formats() const { return paste->formats(); }
+ virtual QVariant retrieveData(const QString &format, QVariant::Type type) const { return paste->retrieveData(format, type); }
+};
+
+QMimeData
+*QMacPasteboard::mimeData() const
+{
+ if(!mime) {
+ mac_mime_source = true;
+ mime = new QMacPasteboardMimeSource(this);
+
+ }
+ return mime;
+}
+
+class QMacMimeData : public QMimeData
+{
+public:
+ QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
+private:
+ QMacMimeData();
+};
+
+void
+QMacPasteboard::setMimeData(QMimeData *mime_src)
+{
+ if (!paste)
+ return;
+
+ if (mime == mime_src || (!mime_src && mime && mac_mime_source))
+ return;
+ mac_mime_source = false;
+ delete mime;
+ mime = mime_src;
+
+ QList<QMacPasteboardMime*> availableConverters = QMacPasteboardMime::all(mime_type);
+ if (mime != 0) {
+ clear_helper();
+ QStringList formats = mime_src->formats();
+
+ for(int f = 0; f < formats.size(); ++f) {
+ QString mimeType = formats.at(f);
+ for (QList<QMacPasteboardMime *>::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) {
+ QMacPasteboardMime *c = (*it);
+ QString flavor(c->flavorFor(mimeType));
+ if(!flavor.isEmpty()) {
+ QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType);
+#if 0
+ //### Grrr, why didn't I put in a virtual int QMacPasteboardMime::count()? --Sam
+ const int numItems = c->convertFromMime(mimeType, mimeData, flavor).size();
+#else
+ int numItems = 1; //this is a hack but it is much faster than allowing conversion above
+ if(c->convertorName() == QLatin1String("FileURL"))
+ numItems = mime_src->urls().count();
+#endif
+ for(int item = 0; item < numItems; ++item) {
+ const int itemID = item+1; //id starts at 1
+ promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item));
+ PasteboardPutItemFlavor(paste, (PasteboardItemID)itemID, QCFString(flavor), 0, kPasteboardFlavorNoFlags);
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - adding %d %s [%s] <%s> [%d]",
+ itemID, qPrintable(mimeType), qPrintable(flavor), qPrintable(c->convertorName()), item);
+#endif
+ }
+ }
+ }
+ }
+ }
+}
+
+QStringList
+QMacPasteboard::formats() const
+{
+ if (!paste)
+ return QStringList();
+
+ sync();
+
+ QStringList ret;
+ ItemCount cnt = 0;
+ if(PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return ret;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: Formats [%d]", (int)cnt);
+#endif
+ for(uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for(int i = 0; i < type_count; ++i) {
+ const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -%s", qPrintable(QString(flavor)));
+#endif
+ QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
+ if(!mimeType.isEmpty() && !ret.contains(mimeType)) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -<%d> %s [%s]", ret.size(), qPrintable(mimeType), qPrintable(QString(flavor)));
+#endif
+ ret << mimeType;
+ }
+ }
+ }
+ return ret;
+}
+
+bool
+QMacPasteboard::hasFormat(const QString &format) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if(PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasFormat [%s]", qPrintable(format));
+#endif
+ for(uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for(int i = 0; i < type_count; ++i) {
+ const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -%s [0x%x]", qPrintable(QString(flavor)), mime_type);
+#endif
+ QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
+#ifdef DEBUG_PASTEBOARD
+ if(!mimeType.isEmpty())
+ qDebug(" - %s", qPrintable(mimeType));
+#endif
+ if(mimeType == format)
+ return true;
+ }
+ }
+ return false;
+}
+
+QVariant
+QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
+{
+ if (!paste)
+ return QVariant();
+
+ sync();
+
+ ItemCount cnt = 0;
+ if(PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return QByteArray();
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("Pasteboard: retrieveData [%s]", qPrintable(format));
+#endif
+ const QList<QMacPasteboardMime *> mimes = QMacPasteboardMime::all(mime_type);
+ for(int mime = 0; mime < mimes.size(); ++mime) {
+ QMacPasteboardMime *c = mimes.at(mime);
+ QString c_flavor = c->flavorFor(format);
+ if(!c_flavor.isEmpty()) {
+ // Handle text/plain a little differently. Try handling Unicode first.
+ if((c_flavor == QLatin1String("com.apple.traditional-mac-plain-text") || c_flavor == QLatin1String("public.utf8-plain-text")) &&
+ hasFlavor(QLatin1String("public.utf16-plain-text")))
+ c_flavor = QLatin1String("public.utf16-plain-text");
+
+ QVariant ret;
+ QList<QByteArray> retList;
+ for(uint index = 1; index <= cnt; ++index) {
+ PasteboardItemID id;
+ if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for(int i = 0; i < type_count; ++i) {
+ CFStringRef flavor = static_cast<CFStringRef>(CFArrayGetValueAtIndex(types, i));
+ if(c_flavor == QCFString::toQString(flavor)) {
+ QCFType<CFDataRef> macBuffer;
+ if(PasteboardCopyItemFlavorData(paste, id, flavor, &macBuffer) == noErr) {
+ QByteArray buffer((const char *)CFDataGetBytePtr(macBuffer), CFDataGetLength(macBuffer));
+ if(!buffer.isEmpty()) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - %s [%s] (%s)", qPrintable(format), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
+#endif
+ buffer.detach(); //detach since we release the macBuffer
+ retList.append(buffer);
+ break; //skip to next element
+ }
+ }
+ } else {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NoMatch %s [%s] (%s)", qPrintable(c_flavor), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
+#endif
+ }
+ }
+ }
+
+ if (!retList.isEmpty()) {
+ ret = c->convertToMime(format, retList, c_flavor);
+ return ret;
+ }
+ }
+ }
+ return QVariant();
+}
+
+void QMacPasteboard::clear_helper()
+{
+ if (paste)
+ PasteboardClear(paste);
+ promises.clear();
+}
+
+void
+QMacPasteboard::clear()
+{
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: clear!");
+#endif
+ clear_helper();
+}
+
+bool
+QMacPasteboard::sync() const
+{
+ if (!paste)
+ return false;
+ const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified;
+
+ if (fromGlobal)
+ const_cast<QMacPasteboard *>(this)->setMimeData(0);
+
+#ifdef DEBUG_PASTEBOARD
+ if(fromGlobal)
+ qDebug("Pasteboard: Syncronize!");
+#endif
+ return fromGlobal;
+}
+
+
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qclipboard_p.h b/src/gui/kernel/qclipboard_p.h
new file mode 100644
index 0000000000..ef6dc3f405
--- /dev/null
+++ b/src/gui/kernel/qclipboard_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCLIPBOARD_P_H
+#define QCLIPBOARD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+#include "QtGui/qmime.h"
+#include "QtGui/qclipboard.h"
+
+QT_BEGIN_NAMESPACE
+
+class QClipboardPrivate;
+
+class QMimeDataWrapper : public QMimeSource
+{
+public:
+ QMimeDataWrapper() {}
+
+ const char* format(int n) const;
+ QByteArray encodedData(const char*) const;
+
+ mutable QList<QByteArray> formats;
+ const QMimeData *data;
+};
+
+class QMimeSourceWrapper : public QMimeData
+{
+public:
+ QMimeSourceWrapper(QClipboardPrivate *priv, QClipboard::Mode m);
+ ~QMimeSourceWrapper();
+
+ bool hasFormat(const QString &mimetype) const;
+ QStringList formats() const;
+
+protected:
+ QVariant retrieveData(const QString &mimetype, QVariant::Type) const;
+private:
+ QClipboardPrivate *d;
+ QClipboard::Mode mode;
+ QMimeSource *source;
+};
+
+
+class QClipboardPrivate : public QObjectPrivate
+{
+public:
+ QClipboardPrivate() : QObjectPrivate() {
+ for (int i = 0; i <= QClipboard::LastMode; ++i) {
+ compat_data[i] = 0;
+ wrapper[i] = new QMimeDataWrapper();
+ }
+ }
+ ~QClipboardPrivate() {
+ for (int i = 0; i <= QClipboard::LastMode; ++i) {
+ delete wrapper[i];
+ delete compat_data[i];
+ }
+ }
+
+ mutable QMimeDataWrapper *wrapper[QClipboard::LastMode + 1];
+ mutable QMimeSource *compat_data[QClipboard::LastMode + 1];
+};
+
+inline QMimeSourceWrapper::QMimeSourceWrapper(QClipboardPrivate *priv, QClipboard::Mode m)
+ : QMimeData()
+{
+ d = priv;
+ mode = m;
+ source = d->compat_data[mode];
+}
+
+inline QMimeSourceWrapper::~QMimeSourceWrapper()
+{
+ if (d->compat_data[mode] == source)
+ d->compat_data[mode] = 0;
+ delete source;
+}
+
+QT_END_NAMESPACE
+
+#endif // QCLIPBOARD_P_H
diff --git a/src/gui/kernel/qclipboard_qws.cpp b/src/gui/kernel/qclipboard_qws.cpp
new file mode 100644
index 0000000000..1a03149e7d
--- /dev/null
+++ b/src/gui/kernel/qclipboard_qws.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qbuffer.h"
+#include "qwidget.h"
+#include "qevent.h"
+
+#include <qwsdisplay_qws.h>
+#include <qwsproperty_qws.h>
+#include <qwsevent_qws.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+
+/*****************************************************************************
+ Internal QClipboard functions for Qt for Embedded Linux
+ *****************************************************************************/
+
+static const int TextClipboard=424242;
+static bool init = false;
+
+static inline void qwsInitClipboard()
+{
+ //### this should go into QWSServer; it only needs to happen once.
+ if( !init ) {
+ QPaintDevice::qwsDisplay()->addProperty(0, TextClipboard);
+ init = true;
+ }
+}
+
+static QString qwsClipboardText()
+{
+ char * data;
+ int len;
+ qwsInitClipboard();
+ if( !QPaintDevice::qwsDisplay()->getProperty(0, TextClipboard, data, len) ) {
+// qDebug("Property received: %d bytes", len);
+ }
+
+ QString s((const QChar*)data, len/sizeof(QChar));
+ // qDebug("Property received: '%s'", s.toAscii().constData());
+ delete[] data;
+ return s;
+}
+
+
+static void qwsSetClipboardText(const QString& s)
+{
+ qwsInitClipboard();
+ // qDebug("qwsSetClipboardText( %s )", s.toAscii().data());
+ int len = s.length()*sizeof(QChar);
+ QByteArray ba((const char*)s.unicode(), len);
+ QPaintDevice::qwsDisplay()->
+ setProperty(0, TextClipboard, QWSPropertyManager::PropReplace, ba);
+
+}
+
+class QClipboardData
+{
+public:
+ QClipboardData();
+ ~QClipboardData();
+
+ void setSource(QMimeData* s)
+ {
+ if (s == src)
+ return;
+ delete src;
+ src = s;
+ }
+ QMimeData* source()
+ { return src; }
+#if 0
+ void addTransferredPixmap(QPixmap pm)
+ { /* TODO: queue them */
+ transferred[tindex] = pm;
+ tindex=(tindex+1)%2;
+ }
+ void clearTransfers()
+ {
+ transferred[0] = QPixmap();
+ transferred[1] = QPixmap();
+ }
+#endif
+
+ void clear();
+
+private:
+ QMimeData* src;
+
+#if 0
+ QPixmap transferred[2];
+ int tindex;
+#endif
+};
+
+QClipboardData::QClipboardData()
+{
+ src = 0;
+#if 0
+ tindex=0;
+#endif
+}
+
+QClipboardData::~QClipboardData()
+{
+ delete src;
+}
+
+void QClipboardData::clear()
+{
+ delete src;
+ src = 0;
+}
+
+
+static QClipboardData *internalCbData = 0;
+
+static void cleanupClipboardData()
+{
+ delete internalCbData;
+ internalCbData = 0;
+}
+
+static QClipboardData *clipboardData()
+{
+ if (internalCbData == 0) {
+ internalCbData = new QClipboardData;
+ qAddPostRoutine(cleanupClipboardData);
+ }
+ return internalCbData;
+}
+
+
+/*****************************************************************************
+ QClipboard member functions for FB.
+ *****************************************************************************/
+
+#if 0
+
+QString QClipboard::text() const
+{
+ return qwsClipboardText();
+}
+
+void QClipboard::setText(const QString &text)
+{
+ qwsSetClipboardText(text);
+}
+
+QString QClipboard::text(QString& subtype) const
+{
+ QString r;
+ if (subtype == "plain")
+ r = text();
+ return r;
+}
+
+#endif
+
+void QClipboard::clear(Mode mode)
+{
+ setText(QString(), mode);
+}
+
+
+bool QClipboard::event(QEvent *e)
+{
+ static bool recursionWatch = false;
+ if (e->type() != QEvent::Clipboard || recursionWatch)
+ return QObject::event(e);
+
+ recursionWatch = true;
+ QWSPropertyNotifyEvent *event = (QWSPropertyNotifyEvent *)(((QClipboardEvent *)e)->data());
+ if (event && event->simpleData.state == QWSPropertyNotifyEvent::PropertyNewValue) {
+ QClipboardData *d = clipboardData();
+ QString t = qwsClipboardText();
+ if( (d->source() == 0 && !t.isEmpty()) || (d->source() != 0 && d->source()->text() != t) ) {
+ if( !d->source() )
+ d->setSource(new QMimeData);
+ d->source()->setText( t );
+ emitChanged(QClipboard::Clipboard);
+ }
+ }
+
+ recursionWatch = false;
+ return true;
+}
+
+const QMimeData* QClipboard::mimeData(Mode mode) const
+{
+ if (mode != Clipboard) return 0;
+
+ QClipboardData *d = clipboardData();
+ // Try and get data from QWSProperty if no mime data has been set on us.
+ if( !d->source() ) {
+ QString t = qwsClipboardText();
+ if( !t.isEmpty() ) {
+ QMimeData* nd = new QMimeData;
+ nd->setText( t );
+ d->setSource( nd );
+ }
+ }
+ return d->source();
+}
+
+void QClipboard::setMimeData(QMimeData* src, Mode mode)
+{
+ if (mode != Clipboard) return;
+
+ QClipboardData *d = clipboardData();
+
+ /* Propagate text data to other QWSClients */
+
+ QString newText;
+ if( src != 0 )
+ newText = src->text();
+ QString oldText;
+ if( d->source() != 0 )
+ oldText = d->source()->text();
+
+ d->setSource(src);
+
+ if( oldText != newText ) {
+ if( d->source() == 0 ) {
+ qwsSetClipboardText( QString() );
+ } else {
+ qwsSetClipboardText( d->source()->text() );
+ }
+ }
+
+ emitChanged(QClipboard::Clipboard);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ if (mode == Clipboard)
+ qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!");
+ return false;
+}
+
+void QClipboard::connectNotify( const char * )
+{
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+
+#endif // QT_NO_CLIPBOARD
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp
new file mode 100644
index 0000000000..90d436251c
--- /dev/null
+++ b/src/gui/kernel/qclipboard_win.cpp
@@ -0,0 +1,389 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qeventloop.h"
+#include "qwidget.h"
+#include "qevent.h"
+#include "qmime.h"
+#include "qt_windows.h"
+#include "qdnd_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_WINCE)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qguifunctions_wince.h"
+QT_END_INCLUDE_NAMESPACE
+
+HRESULT QtCeGetClipboard(IDataObject** obj);
+HRESULT QtCeSetClipboard(IDataObject* obj);
+void QtCeFlushClipboard();
+
+#define OleGetClipboard QtCeGetClipboard
+#define OleSetClipboard QtCeSetClipboard
+#define OleFlushClipboard QtCeFlushClipboard
+
+#endif
+
+
+class QClipboardWatcher : public QInternalMimeData {
+public:
+ QClipboardWatcher()
+ : QInternalMimeData()
+ {
+ }
+
+ bool hasFormat_sys(const QString &mimetype) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const;
+};
+
+
+bool QClipboardWatcher::hasFormat_sys(const QString &mime) const
+{
+ IDataObject * pDataObj = 0;
+
+ if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity
+ return false;
+
+ bool has = QWindowsMime::converterToMime(mime, pDataObj) != 0;
+
+ pDataObj->Release();
+
+ return has;
+}
+
+QStringList QClipboardWatcher::formats_sys() const
+{
+ QStringList fmts;
+ IDataObject * pDataObj = 0;
+
+ if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity
+ return QStringList();
+
+ fmts = QWindowsMime::allMimesForFormats(pDataObj);
+
+ pDataObj->Release();
+
+ return fmts;
+}
+
+QVariant QClipboardWatcher::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant result;
+ IDataObject * pDataObj = 0;
+
+ if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity
+ return result;
+
+ QWindowsMime *converter = QWindowsMime::converterToMime(mimeType, pDataObj);
+
+ if (converter)
+ result = converter->convertToMime(mimeType, pDataObj, type);
+
+ pDataObj->Release();
+
+ return result;
+}
+
+class QClipboardData
+{
+public:
+ QClipboardData()
+ : iData(0)
+ , nextClipboardViewer(0)
+ {
+ clipBoardViewer = new QWidget();
+ clipBoardViewer->createWinId();
+ clipBoardViewer->setObjectName(QLatin1String("internal clipboard owner"));
+ }
+
+ ~QClipboardData()
+ {
+ Q_ASSERT(clipBoardViewer->testAttribute(Qt::WA_WState_Created));
+ ChangeClipboardChain(clipBoardViewer->internalWinId(), nextClipboardViewer);
+ delete clipBoardViewer;
+ releaseIData();
+ }
+
+ void releaseIData()
+ {
+ if (iData) {
+ delete iData->mimeData();
+ iData->releaseQt();
+ iData->Release();
+ iData = 0;
+ }
+ }
+
+ QOleDataObject * iData;
+ QWidget *clipBoardViewer;
+ HWND nextClipboardViewer;
+ QClipboardWatcher watcher;
+};
+
+static QClipboardData *ptrClipboardData = 0;
+
+static QClipboardData *clipboardData()
+{
+ if (ptrClipboardData == 0) {
+ ptrClipboardData = new QClipboardData;
+ // this needs to be done here to avoid recursion
+ Q_ASSERT(ptrClipboardData->clipBoardViewer->testAttribute(Qt::WA_WState_Created));
+ ptrClipboardData->nextClipboardViewer = SetClipboardViewer(ptrClipboardData->clipBoardViewer->internalWinId());
+ }
+ return ptrClipboardData;
+}
+
+static void cleanupClipboardData()
+{
+ delete ptrClipboardData;
+ ptrClipboardData = 0;
+}
+
+#if defined(Q_OS_WINCE)
+HRESULT QtCeGetClipboard(IDataObject** obj)
+{
+ HWND owner = ptrClipboardData->clipBoardViewer->internalWinId();
+ if (!OpenClipboard(owner))
+ return !S_OK;
+
+ if (!IsClipboardFormatAvailable(CF_TEXT) && !IsClipboardFormatAvailable(CF_UNICODETEXT))
+ return !S_OK;
+
+ HANDLE clipData = GetClipboardData(CF_TEXT);
+ QString clipText;
+ if (clipData == 0) {
+ clipData = GetClipboardData(CF_UNICODETEXT);
+ if (clipData != 0)
+ clipText = QString::fromUtf16((unsigned short *)clipData);
+ } else {
+ clipText = QString::fromLatin1((const char*)clipData);
+ }
+
+ QMimeData *mimeData = new QMimeData();
+ mimeData->setText(clipText);
+ QOleDataObject* data = new QOleDataObject(mimeData);
+ *obj = data;
+ CloseClipboard();
+ return S_OK;
+}
+
+HRESULT QtCeSetClipboard(IDataObject* obj)
+{
+ HWND owner = ptrClipboardData->clipBoardViewer->internalWinId();
+ if (!OpenClipboard(owner))
+ return !S_OK;
+
+ bool result = false;
+ if (obj == 0) {
+ result = true;
+ EmptyClipboard();
+ CloseClipboard();
+ } else {
+ QOleDataObject* qobj = static_cast<QOleDataObject*>(obj);
+
+ const QMimeData* data = qobj->mimeData();
+ if (data->hasText()) {
+ EmptyClipboard();
+ result = SetClipboardData(CF_UNICODETEXT, wcsdup(reinterpret_cast<const wchar_t *> (data->text().utf16()))) != NULL;
+ CloseClipboard();
+ result = true;
+ }
+ }
+ return result ? S_OK : !S_OK;
+}
+
+void QtCeFlushClipboard() { }
+#endif
+
+
+
+QClipboard::~QClipboard()
+{
+ cleanupClipboardData();
+}
+
+void QClipboard::setMimeData(QMimeData *src, Mode mode)
+{
+ if (mode != Clipboard)
+ return;
+ QClipboardData *d = clipboardData();
+
+ if (!(d->iData && d->iData->mimeData() == src)) {
+ d->releaseIData();
+ d->iData = new QOleDataObject(src);
+ }
+
+ if (OleSetClipboard(d->iData) != S_OK) {
+ d->releaseIData();
+ qErrnoWarning("QClipboard::setMimeData: Failed to set data on clipboard");
+ return;
+ }
+#if defined(Q_OS_WINCE)
+ // As WinCE does not support notifications we send the signal here
+ // We will get no event when the clipboard changes outside...
+ emit dataChanged();
+ emit changed(Clipboard);
+#endif
+}
+
+void QClipboard::clear(Mode mode)
+{
+ if (mode != Clipboard) return;
+
+ QClipboardData *d = clipboardData();
+
+ d->releaseIData();
+
+ if (OleSetClipboard(0) != S_OK) {
+ qErrnoWarning("QClipboard::clear: Failed to clear data on clipboard");
+ return;
+ }
+#if defined(Q_OS_WINCE)
+ // As WinCE does not support notifications we send the signal here
+ // We will get no event when the clipboard changes outside...
+ emit dataChanged();
+ emit changed(Clipboard);
+#endif
+}
+
+bool QClipboard::event(QEvent *e)
+{
+ if (e->type() != QEvent::Clipboard)
+ return QObject::event(e);
+
+ QClipboardData *d = clipboardData();
+
+ MSG *m = (MSG *)((QClipboardEvent*)e)->data();
+ if (!m) {
+ // this is sent to render all formats at app shut down
+ if (ownsClipboard()) {
+ OleFlushClipboard();
+ d->releaseIData();
+ }
+ return true;
+ }
+
+ bool propagate = false;
+
+ if (m->message == WM_CHANGECBCHAIN) {
+ if ((HWND)m->wParam == d->nextClipboardViewer)
+ d->nextClipboardViewer = (HWND)m->lParam;
+ else
+ propagate = true;
+ } else if (m->message == WM_DRAWCLIPBOARD) {
+ emitChanged(QClipboard::Clipboard);
+ if (!ownsClipboard() && d->iData)
+ // clean up the clipboard object if we no longer own the clipboard
+ d->releaseIData();
+ propagate = true;
+ }
+
+ if (propagate && d->nextClipboardViewer) {
+ QT_WA({
+ SendMessage(d->nextClipboardViewer, m->message,
+ m->wParam, m->lParam);
+ } , {
+ SendMessageA(d->nextClipboardViewer, m->message,
+ m->wParam, m->lParam);
+ });
+ }
+
+ return true;
+}
+
+void QClipboard::connectNotify(const char *signal)
+{
+ if (qstrcmp(signal,SIGNAL(dataChanged())) == 0) {
+ // ensure we are up and running but block signals so the dataChange signal
+ // is not emitted while being connected to.
+ bool blocked = blockSignals(true);
+ QClipboardData *d = clipboardData();
+ blockSignals(blocked);
+ Q_UNUSED(d);
+ }
+}
+
+const QMimeData *QClipboard::mimeData(Mode mode) const
+{
+ if (mode != Clipboard)
+ return 0;
+
+ QClipboardData *data = clipboardData();
+ // sort cut for local copy / paste
+ if (ownsClipboard() && data->iData->mimeData())
+ return data->iData->mimeData();
+ return &data->watcher;
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ if (mode == Clipboard) {
+ QClipboardData *d = clipboardData();
+#if !defined(Q_OS_WINCE)
+ return d->iData && OleIsCurrentClipboard(d->iData) == S_OK;
+#else
+ return d->iData && GetClipboardOwner() == d->clipBoardViewer->internalWinId();
+#endif
+ } else {
+ return false;
+ }
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp
new file mode 100644
index 0000000000..089cc43937
--- /dev/null
+++ b/src/gui/kernel/qclipboard_x11.cpp
@@ -0,0 +1,1498 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// #define QCLIPBOARD_DEBUG
+// #define QCLIPBOARD_DEBUG_VERBOSE
+
+#ifdef QCLIPBOARD_DEBUG
+# define DEBUG qDebug
+#else
+# define DEBUG if (false) qDebug
+#endif
+
+#ifdef QCLIPBOARD_DEBUG_VERBOSE
+# define VDEBUG qDebug
+#else
+# define VDEBUG if (false) qDebug
+#endif
+
+#include "qplatformdefs.h"
+
+#include "qclipboard.h"
+#include "qclipboard_p.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qabstracteventdispatcher.h"
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qiodevice.h"
+#include "qbuffer.h"
+#include "qtextcodec.h"
+#include "qlist.h"
+#include "qmap.h"
+#include "qapplication_p.h"
+#include "qevent.h"
+#include "qt_x11_p.h"
+#include "qx11info_x11.h"
+#include "qimagewriter.h"
+#include "qvariant.h"
+#include "qdnd_p.h"
+
+#ifndef QT_NO_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif // QT_NO_XFIXES
+
+QT_BEGIN_NAMESPACE
+
+/*****************************************************************************
+ Internal QClipboard functions for X11.
+ *****************************************************************************/
+
+static int clipboard_timeout = 5000; // 5s timeout on clipboard operations
+
+static QWidget * owner = 0;
+static QWidget *requestor = 0;
+static bool timer_event_clear = false;
+static int timer_id = 0;
+
+static int pending_timer_id = 0;
+static bool pending_clipboard_changed = false;
+static bool pending_selection_changed = false;
+
+
+// event capture mechanism for qt_xclb_wait_for_event
+static bool waiting_for_data = false;
+static bool has_captured_event = false;
+static Window capture_event_win = XNone;
+static int capture_event_type = -1;
+static XEvent captured_event;
+
+class QClipboardWatcher; // forward decl
+static QClipboardWatcher *selection_watcher = 0;
+static QClipboardWatcher *clipboard_watcher = 0;
+
+static void cleanup()
+{
+ delete owner;
+ delete requestor;
+ owner = 0;
+ requestor = 0;
+}
+
+static
+void setupOwner()
+{
+ if (owner)
+ return;
+ owner = new QWidget(0);
+ owner->setObjectName(QLatin1String("internal clipboard owner"));
+ owner->createWinId();
+ requestor = new QWidget(0);
+ requestor->createWinId();
+ requestor->setObjectName(QLatin1String("internal clipboard requestor"));
+ qAddPostRoutine(cleanup);
+}
+
+
+class QClipboardWatcher : public QInternalMimeData {
+public:
+ QClipboardWatcher(QClipboard::Mode mode);
+ ~QClipboardWatcher();
+ bool empty() const;
+ virtual bool hasFormat_sys(const QString &mimetype) const;
+ virtual QStringList formats_sys() const;
+
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type type) const;
+ QByteArray getDataInFormat(Atom fmtatom) const;
+
+ Atom atom;
+ mutable QStringList formatList;
+ mutable QByteArray format_atoms;
+};
+
+class QClipboardData
+{
+private:
+ QMimeData *&mimeDataRef() const
+ {
+ if(mode == QClipboard::Selection)
+ return selectionData;
+ return clipboardData;
+ }
+
+public:
+ QClipboardData(QClipboard::Mode mode);
+ ~QClipboardData();
+
+ void setSource(QMimeData* s)
+ {
+ if ((mode == QClipboard::Selection && selectionData == s)
+ || clipboardData == s) {
+ return;
+ }
+
+ if (selectionData != clipboardData) {
+ delete mimeDataRef();
+ }
+
+ mimeDataRef() = s;
+ }
+
+ QMimeData *source() const
+ {
+ return mimeDataRef();
+ }
+
+ void clear()
+ {
+ timestamp = CurrentTime;
+ if (selectionData == clipboardData) {
+ mimeDataRef() = 0;
+ } else {
+ QMimeData *&src = mimeDataRef();
+ delete src;
+ src = 0;
+ }
+ }
+
+ static QMimeData *selectionData;
+ static QMimeData *clipboardData;
+ Time timestamp;
+ QClipboard::Mode mode;
+};
+
+QMimeData *QClipboardData::selectionData = 0;
+QMimeData *QClipboardData::clipboardData = 0;
+
+QClipboardData::QClipboardData(QClipboard::Mode clipboardMode)
+{
+ timestamp = CurrentTime;
+ mode = clipboardMode;
+}
+
+QClipboardData::~QClipboardData()
+{ clear(); }
+
+
+static QClipboardData *internalCbData = 0;
+static QClipboardData *internalSelData = 0;
+
+static void cleanupClipboardData()
+{
+ delete internalCbData;
+ internalCbData = 0;
+}
+
+static QClipboardData *clipboardData()
+{
+ if (internalCbData == 0) {
+ internalCbData = new QClipboardData(QClipboard::Clipboard);
+ qAddPostRoutine(cleanupClipboardData);
+ }
+ return internalCbData;
+}
+
+static void cleanupSelectionData()
+{
+ delete internalSelData;
+ internalSelData = 0;
+}
+
+static QClipboardData *selectionData()
+{
+ if (internalSelData == 0) {
+ internalSelData = new QClipboardData(QClipboard::Selection);
+ qAddPostRoutine(cleanupSelectionData);
+ }
+ return internalSelData;
+}
+
+class QClipboardINCRTransaction
+{
+public:
+ QClipboardINCRTransaction(Window w, Atom p, Atom t, int f, QByteArray d, unsigned int i);
+ ~QClipboardINCRTransaction(void);
+
+ int x11Event(XEvent *event);
+
+ Window window;
+ Atom property, target;
+ int format;
+ QByteArray data;
+ unsigned int increment;
+ unsigned int offset;
+};
+
+typedef QMap<Window,QClipboardINCRTransaction*> TransactionMap;
+static TransactionMap *transactions = 0;
+static QApplication::EventFilter prev_event_filter = 0;
+static int incr_timer_id = 0;
+
+static bool qt_x11_incr_event_filter(void *message, long *result)
+{
+ XEvent *event = reinterpret_cast<XEvent *>(message);
+ TransactionMap::Iterator it = transactions->find(event->xany.window);
+ if (it != transactions->end()) {
+ if ((*it)->x11Event(event) != 0)
+ return true;
+ }
+ if (prev_event_filter)
+ return prev_event_filter(event, result);
+ return false;
+}
+
+/*
+ called when no INCR activity has happened for 'clipboard_timeout'
+ milliseconds... we assume that all unfinished transactions have
+ timed out and remove everything from the transaction map
+*/
+static void qt_xclb_incr_timeout(void)
+{
+ qWarning("QClipboard: Timed out while sending data");
+
+ while (transactions)
+ delete *transactions->begin();
+}
+
+QClipboardINCRTransaction::QClipboardINCRTransaction(Window w, Atom p, Atom t, int f,
+ QByteArray d, unsigned int i)
+ : window(w), property(p), target(t), format(f), data(d), increment(i), offset(0u)
+{
+ DEBUG("QClipboard: sending %d bytes (INCR transaction %p)", d.size(), this);
+
+ XSelectInput(X11->display, window, PropertyChangeMask);
+
+ if (! transactions) {
+ VDEBUG("QClipboard: created INCR transaction map");
+ transactions = new TransactionMap;
+ prev_event_filter = qApp->setEventFilter(qt_x11_incr_event_filter);
+ incr_timer_id = QApplication::clipboard()->startTimer(clipboard_timeout);
+ }
+ transactions->insert(window, this);
+}
+
+QClipboardINCRTransaction::~QClipboardINCRTransaction(void)
+{
+ VDEBUG("QClipboard: destroyed INCR transacton %p", this);
+
+ XSelectInput(X11->display, window, NoEventMask);
+
+ transactions->remove(window);
+ if (transactions->isEmpty()) {
+ VDEBUG("QClipboard: no more INCR transactions");
+ delete transactions;
+ transactions = 0;
+
+ (void)qApp->setEventFilter(prev_event_filter);
+
+ if (incr_timer_id != 0) {
+ QApplication::clipboard()->killTimer(incr_timer_id);
+ incr_timer_id = 0;
+ }
+ }
+}
+
+int QClipboardINCRTransaction::x11Event(XEvent *event)
+{
+ if (event->type != PropertyNotify
+ || (event->xproperty.state != PropertyDelete
+ || event->xproperty.atom != property))
+ return 0;
+
+ // restart the INCR timer
+ if (incr_timer_id) QApplication::clipboard()->killTimer(incr_timer_id);
+ incr_timer_id = QApplication::clipboard()->startTimer(clipboard_timeout);
+
+ unsigned int bytes_left = data.size() - offset;
+ if (bytes_left > 0) {
+ unsigned int xfer = qMin(increment, bytes_left);
+ VDEBUG("QClipboard: sending %d bytes, %d remaining (INCR transaction %p)",
+ xfer, bytes_left - xfer, this);
+
+ XChangeProperty(X11->display, window, property, target, format,
+ PropModeReplace, (uchar *) data.data() + offset, xfer);
+ offset += xfer;
+ } else {
+ // INCR transaction finished...
+ XChangeProperty(X11->display, window, property, target, format,
+ PropModeReplace, (uchar *) data.data(), 0);
+ delete this;
+ }
+
+ return 1;
+}
+
+
+/*****************************************************************************
+ QClipboard member functions for X11.
+ *****************************************************************************/
+
+struct qt_init_timestamp_data
+{
+ Time timestamp;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_init_timestamp_scanner(Display*, XEvent *event, XPointer arg)
+{
+ qt_init_timestamp_data *data =
+ reinterpret_cast<qt_init_timestamp_data*>(arg);
+ switch(event->type)
+ {
+ case ButtonPress:
+ case ButtonRelease:
+ data->timestamp = event->xbutton.time;
+ break;
+ case MotionNotify:
+ data->timestamp = event->xmotion.time;
+ break;
+ case XKeyPress:
+ case XKeyRelease:
+ data->timestamp = event->xkey.time;
+ break;
+ case PropertyNotify:
+ data->timestamp = event->xproperty.time;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ data->timestamp = event->xcrossing.time;
+ break;
+ case SelectionClear:
+ data->timestamp = event->xselectionclear.time;
+ break;
+ default:
+ break;
+ }
+#ifndef QT_NO_XFIXES
+ if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) {
+ XFixesSelectionNotifyEvent *req =
+ reinterpret_cast<XFixesSelectionNotifyEvent *>(event);
+ data->timestamp = req->selection_timestamp;
+ }
+#endif
+ return false;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+QClipboard::QClipboard(QObject *parent)
+ : QObject(*new QClipboardPrivate, parent)
+{
+ // create desktop widget since we need it to get PropertyNotify or
+ // XFixesSelectionNotify events when someone changes the
+ // clipboard.
+ (void)QApplication::desktop();
+ if (X11->time == CurrentTime) {
+ // send a dummy event to myself to get the timestamp from X11.
+ qt_init_timestamp_data data;
+ data.timestamp = CurrentTime;
+ XEvent ev;
+ XCheckIfEvent(X11->display, &ev, &qt_init_timestamp_scanner, (XPointer)&data);
+ if (data.timestamp == CurrentTime) {
+ setupOwner();
+ int dummy = 0;
+ Window ownerId = owner->internalWinId();
+ XChangeProperty(X11->display, ownerId,
+ ATOM(CLIP_TEMPORARY), XA_INTEGER, 32,
+ PropModeReplace, (uchar*)&dummy, 1);
+ XWindowEvent(X11->display, ownerId, PropertyChangeMask, &ev);
+ data.timestamp = ev.xproperty.time;
+ XDeleteProperty(X11->display, ownerId, ATOM(CLIP_TEMPORARY));
+ }
+ X11->time = data.timestamp;
+ }
+}
+
+void QClipboard::clear(Mode mode)
+{
+ setMimeData(0, mode);
+}
+
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard || mode == Selection);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ if (mode == Clipboard)
+ return clipboardData()->timestamp != CurrentTime;
+ else if(mode == Selection)
+ return selectionData()->timestamp != CurrentTime;
+ else
+ return false;
+}
+
+
+// event filter function... captures interesting events while
+// qt_xclb_wait_for_event is running the event loop
+static bool qt_x11_clipboard_event_filter(void *message, long *)
+{
+ XEvent *event = reinterpret_cast<XEvent *>(message);
+ if (event->xany.type == capture_event_type &&
+ event->xany.window == capture_event_win) {
+ VDEBUG("QClipboard: event_filter(): caught event type %d", event->type);
+ has_captured_event = true;
+ captured_event = *event;
+ return true;
+ }
+ return false;
+}
+
+static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer)
+{
+ return ((e->type == SelectionRequest && (e->xselectionrequest.selection == XA_PRIMARY
+ || e->xselectionrequest.selection == ATOM(CLIPBOARD)))
+ || (e->type == SelectionClear && (e->xselectionclear.selection == XA_PRIMARY
+ || e->xselectionclear.selection == ATOM(CLIPBOARD))));
+}
+
+bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int timeout)
+{
+ QTime started = QTime::currentTime();
+ QTime now = started;
+
+ if (QAbstractEventDispatcher::instance()->inherits("QtMotif")
+ || QApplication::clipboard()->property("useEventLoopWhenWaiting").toBool()) {
+ if (waiting_for_data) {
+ Q_ASSERT(!"QClipboard: internal error, qt_xclb_wait_for_event recursed");
+ return false;
+ }
+ waiting_for_data = true;
+
+
+ has_captured_event = false;
+ capture_event_win = win;
+ capture_event_type = type;
+
+ QApplication::EventFilter old_event_filter =
+ qApp->setEventFilter(qt_x11_clipboard_event_filter);
+
+ do {
+ if (XCheckTypedWindowEvent(display, win, type, event)) {
+ waiting_for_data = false;
+ qApp->setEventFilter(old_event_filter);
+ return true;
+ }
+
+ XSync(X11->display, false);
+ usleep(50000);
+
+ now = QTime::currentTime();
+ if (started > now) // crossed midnight
+ started = now;
+
+ QEventLoop::ProcessEventsFlags flags(QEventLoop::ExcludeUserInputEvents
+ | QEventLoop::ExcludeSocketNotifiers
+ | QEventLoop::WaitForMoreEvents
+ | QEventLoop::X11ExcludeTimers);
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
+ eventDispatcher->processEvents(flags);
+
+ if (has_captured_event) {
+ waiting_for_data = false;
+ *event = captured_event;
+ qApp->setEventFilter(old_event_filter);
+ return true;
+ }
+ } while (started.msecsTo(now) < timeout);
+
+ waiting_for_data = false;
+ qApp->setEventFilter(old_event_filter);
+ } else {
+ do {
+ if (XCheckTypedWindowEvent(X11->display,win,type,event))
+ return true;
+
+ // process other clipboard events, since someone is probably requesting data from us
+ XEvent e;
+ if (XCheckIfEvent(X11->display, &e, checkForClipboardEvents, 0))
+ qApp->x11ProcessEvent(&e);
+
+ now = QTime::currentTime();
+ if ( started > now ) // crossed midnight
+ started = now;
+
+ XFlush(X11->display);
+
+ // sleep 50 ms, so we don't use up CPU cycles all the time.
+ struct timeval usleep_tv;
+ usleep_tv.tv_sec = 0;
+ usleep_tv.tv_usec = 50000;
+ select(0, 0, 0, 0, &usleep_tv);
+ } while (started.msecsTo(now) < timeout);
+ }
+ return false;
+}
+
+
+static inline int maxSelectionIncr(Display *dpy)
+{ return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; }
+
+bool QX11Data::clipboardReadProperty(Window win, Atom property, bool deleteProperty,
+ QByteArray *buffer, int *size, Atom *type, int *format, bool nullterm)
+{
+ int maxsize = maxSelectionIncr(display);
+ ulong bytes_left; // bytes_after
+ ulong length; // nitems
+ uchar *data;
+ Atom dummy_type;
+ int dummy_format;
+ int r;
+
+ if (!type) // allow null args
+ type = &dummy_type;
+ if (!format)
+ format = &dummy_format;
+
+ // Don't read anything, just get the size of the property data
+ r = XGetWindowProperty(display, win, property, 0, 0, False,
+ AnyPropertyType, type, format,
+ &length, &bytes_left, &data);
+ if (r != Success || (type && *type == XNone)) {
+ buffer->resize(0);
+ return false;
+ }
+ XFree((char*)data);
+
+ int offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left;
+
+ VDEBUG("QClipboard: read_property(): initial property length: %d", proplen);
+
+ switch (*format) {
+ case 8:
+ default:
+ format_inc = sizeof(char) / 1;
+ break;
+
+ case 16:
+ format_inc = sizeof(short) / 2;
+ proplen *= sizeof(short) / 2;
+ break;
+
+ case 32:
+ format_inc = sizeof(long) / 4;
+ proplen *= sizeof(long) / 4;
+ break;
+ }
+
+ int newSize = proplen + (nullterm ? 1 : 0);
+ buffer->resize(newSize);
+
+ bool ok = (buffer->size() == newSize);
+ VDEBUG("QClipboard: read_property(): buffer resized to %d", buffer->size());
+
+ if (ok) {
+ // could allocate buffer
+
+ while (bytes_left) {
+ // more to read...
+
+ r = XGetWindowProperty(display, win, property, offset, maxsize/4,
+ False, AnyPropertyType, type, format,
+ &length, &bytes_left, &data);
+ if (r != Success || (type && *type == XNone))
+ break;
+
+ offset += length / (32 / *format);
+ length *= format_inc * (*format) / 8;
+
+ // Here we check if we get a buffer overflow and tries to
+ // recover -- this shouldn't normally happen, but it doesn't
+ // hurt to be defensive
+ if ((int)(buffer_offset + length) > buffer->size()) {
+ length = buffer->size() - buffer_offset;
+
+ // escape loop
+ bytes_left = 0;
+ }
+
+ memcpy(buffer->data() + buffer_offset, data, length);
+ buffer_offset += length;
+
+ XFree((char*)data);
+ }
+
+ if (*format == 8 && *type == ATOM(COMPOUND_TEXT)) {
+ // convert COMPOUND_TEXT to a multibyte string
+ XTextProperty textprop;
+ textprop.encoding = *type;
+ textprop.format = *format;
+ textprop.nitems = length;
+ textprop.value = (unsigned char *) buffer->data();
+
+ char **list_ret = 0;
+ int count;
+ if (XmbTextPropertyToTextList(display, &textprop, &list_ret,
+ &count) == Success && count && list_ret) {
+ offset = strlen(list_ret[0]);
+ buffer->resize(offset + (nullterm ? 1 : 0));
+ memcpy(buffer->data(), list_ret[0], offset);
+ }
+ if (list_ret) XFreeStringList(list_ret);
+ }
+
+ // zero-terminate (for text)
+ if (nullterm)
+ buffer->data()[buffer_offset] = '\0';
+ }
+
+ // correct size, not 0-term.
+ if (size)
+ *size = buffer_offset;
+
+ VDEBUG("QClipboard: read_property(): buffer size %d, buffer offset %d, offset %d",
+ buffer->size(), buffer_offset, offset);
+
+ if (deleteProperty)
+ XDeleteProperty(display, win, property);
+
+ XFlush(display);
+
+ return ok;
+}
+
+QByteArray QX11Data::clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm)
+{
+ XEvent event;
+
+ QByteArray buf;
+ QByteArray tmp_buf;
+ bool alloc_error = false;
+ int length;
+ int offset = 0;
+
+ if (nbytes > 0) {
+ // Reserve buffer + zero-terminator (for text data)
+ // We want to complete the INCR transfer even if we cannot
+ // allocate more memory
+ buf.resize(nbytes+1);
+ alloc_error = buf.size() != nbytes+1;
+ }
+
+ for (;;) {
+ XFlush(display);
+ if (!clipboardWaitForEvent(win,PropertyNotify,&event,clipboard_timeout))
+ break;
+ if (event.xproperty.atom != property ||
+ event.xproperty.state != PropertyNewValue)
+ continue;
+ if (X11->clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0, false)) {
+ if (length == 0) { // no more data, we're done
+ if (nullterm) {
+ buf.resize(offset+1);
+ buf[offset] = '\0';
+ } else {
+ buf.resize(offset);
+ }
+ return buf;
+ } else if (!alloc_error) {
+ if (offset+length > (int)buf.size()) {
+ buf.resize(offset+length+65535);
+ if (buf.size() != offset+length+65535) {
+ alloc_error = true;
+ length = buf.size() - offset;
+ }
+ }
+ memcpy(buf.data()+offset, tmp_buf.constData(), length);
+ tmp_buf.resize(0);
+ offset += length;
+ }
+ } else {
+ break;
+ }
+ }
+
+ // timed out ... create a new requestor window, otherwise the requestor
+ // could consider next request to be still part of this timed out request
+ delete requestor;
+ requestor = new QWidget(0);
+ requestor->setObjectName(QLatin1String("internal clipboard requestor"));
+
+ return QByteArray();
+}
+
+static Atom send_targets_selection(QClipboardData *d, Window window, Atom property)
+{
+ QVector<Atom> types;
+ QStringList formats = QInternalMimeData::formatsHelper(d->source());
+ for (int i = 0; i < formats.size(); ++i) {
+ QList<Atom> atoms = X11->xdndMimeAtomsForFormat(formats.at(i));
+ for (int j = 0; j < atoms.size(); ++j) {
+ if (!types.contains(atoms.at(j)))
+ types.append(atoms.at(j));
+ }
+ }
+ types.append(ATOM(TARGETS));
+ types.append(ATOM(MULTIPLE));
+ types.append(ATOM(TIMESTAMP));
+
+ XChangeProperty(X11->display, window, property, XA_ATOM, 32,
+ PropModeReplace, (uchar *) types.data(), types.size());
+ return property;
+}
+
+static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom property)
+{
+ Atom atomFormat = target;
+ int dataFormat = 0;
+ QByteArray data;
+
+ QByteArray fmt = X11->xdndAtomToString(target);
+ if (fmt.isEmpty() || !QInternalMimeData::hasFormatHelper(QString::fromAscii(fmt), d->source())) { // Not a MIME type we have
+ DEBUG("QClipboard: send_selection(): converting to type '%s' is not supported", fmt.data());
+ return XNone;
+ }
+ DEBUG("QClipboard: send_selection(): converting to type '%s'", fmt.data());
+
+ if (X11->xdndMimeDataForAtom(target, d->source(), &data, &atomFormat, &dataFormat)) {
+
+ VDEBUG("QClipboard: send_selection():\n"
+ " property type %lx\n"
+ " property name '%s'\n"
+ " format %d\n"
+ " %d bytes\n",
+ target, X11->xdndMimeAtomToString(atomFormat).toLatin1().data(), dataFormat, data.size());
+
+ // don't allow INCR transfers when using MULTIPLE or to
+ // Motif clients (since Motif doesn't support INCR)
+ static Atom motif_clip_temporary = ATOM(CLIP_TEMPORARY);
+ bool allow_incr = property != motif_clip_temporary;
+
+ // X_ChangeProperty protocol request is 24 bytes
+ const int increment = (XMaxRequestSize(X11->display) * 4) - 24;
+ if (data.size() > increment && allow_incr) {
+ long bytes = data.size();
+ XChangeProperty(X11->display, window, property,
+ ATOM(INCR), 32, PropModeReplace, (uchar *) &bytes, 1);
+
+ (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment);
+ return ATOM(INCR);
+ }
+
+ // make sure we can perform the XChangeProperty in a single request
+ if (data.size() > increment)
+ return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend?
+ int dataSize = data.size() / (dataFormat / 8);
+ // use a single request to transfer data
+ XChangeProperty(X11->display, window, property, atomFormat,
+ dataFormat, PropModeReplace, (uchar *) data.data(),
+ dataSize);
+ }
+ return property;
+}
+
+/*! \internal
+ Internal cleanup for Windows.
+*/
+void QClipboard::ownerDestroyed()
+{ }
+
+
+/*! \internal
+ Internal optimization for Windows.
+*/
+void QClipboard::connectNotify(const char *)
+{ }
+
+
+bool QClipboard::event(QEvent *e)
+{
+ if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = (QTimerEvent *) e;
+
+ if (waiting_for_data) // should never happen
+ return false;
+
+ if (te->timerId() == timer_id) {
+ killTimer(timer_id);
+ timer_id = 0;
+
+ timer_event_clear = true;
+ if (selection_watcher) // clear selection
+ selectionData()->clear();
+ if (clipboard_watcher) // clear clipboard
+ clipboardData()->clear();
+ timer_event_clear = false;
+
+ return true;
+ } else if (te->timerId() == pending_timer_id) {
+ // I hate klipper
+ killTimer(pending_timer_id);
+ pending_timer_id = 0;
+
+ if (pending_clipboard_changed) {
+ pending_clipboard_changed = false;
+ clipboardData()->clear();
+ emitChanged(QClipboard::Clipboard);
+ }
+ if (pending_selection_changed) {
+ pending_selection_changed = false;
+ selectionData()->clear();
+ emitChanged(QClipboard::Selection);
+ }
+
+ return true;
+ } else if (te->timerId() == incr_timer_id) {
+ killTimer(incr_timer_id);
+ incr_timer_id = 0;
+
+ qt_xclb_incr_timeout();
+
+ return true;
+ } else {
+ return QObject::event(e);
+ }
+ } else if (e->type() != QEvent::Clipboard) {
+ return QObject::event(e);
+ }
+
+ XEvent *xevent = (XEvent *)(((QClipboardEvent *)e)->data());
+ Display *dpy = X11->display;
+
+ if (!xevent)
+ return true;
+
+ switch (xevent->type) {
+
+ case SelectionClear:
+ // new selection owner
+ if (xevent->xselectionclear.selection == XA_PRIMARY) {
+ QClipboardData *d = selectionData();
+
+ // ignore the event if it was generated before we gained selection ownership
+ if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp)
+ break;
+
+ DEBUG("QClipboard: new selection owner 0x%lx at time %lx (ours %lx)",
+ XGetSelectionOwner(dpy, XA_PRIMARY),
+ xevent->xselectionclear.time, d->timestamp);
+
+ if (! waiting_for_data) {
+ d->clear();
+ emitChanged(QClipboard::Selection);
+ } else {
+ pending_selection_changed = true;
+ if (! pending_timer_id)
+ pending_timer_id = QApplication::clipboard()->startTimer(0);
+ }
+ } else if (xevent->xselectionclear.selection == ATOM(CLIPBOARD)) {
+ QClipboardData *d = clipboardData();
+
+ // ignore the event if it was generated before we gained selection ownership
+ if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp)
+ break;
+
+ DEBUG("QClipboard: new clipboard owner 0x%lx at time %lx (%lx)",
+ XGetSelectionOwner(dpy, ATOM(CLIPBOARD)),
+ xevent->xselectionclear.time, d->timestamp);
+
+ if (! waiting_for_data) {
+ d->clear();
+ emitChanged(QClipboard::Clipboard);
+ } else {
+ pending_clipboard_changed = true;
+ if (! pending_timer_id)
+ pending_timer_id = QApplication::clipboard()->startTimer(0);
+ }
+ } else {
+ qWarning("QClipboard: Unknown SelectionClear event received");
+ return false;
+ }
+ break;
+
+ case SelectionNotify:
+ /*
+ Something has delivered data to us, but this was not caught
+ by QClipboardWatcher::getDataInFormat()
+
+ Just skip the event to prevent Bad Things (tm) from
+ happening later on...
+ */
+ break;
+
+ case SelectionRequest:
+ {
+ // someone wants our data
+ XSelectionRequestEvent *req = &xevent->xselectionrequest;
+
+ if (requestor && req->requestor == requestor->internalWinId())
+ break;
+
+ XEvent event;
+ event.xselection.type = SelectionNotify;
+ event.xselection.display = req->display;
+ event.xselection.requestor = req->requestor;
+ event.xselection.selection = req->selection;
+ event.xselection.target = req->target;
+ event.xselection.property = XNone;
+ event.xselection.time = req->time;
+
+ DEBUG("QClipboard: SelectionRequest from %lx\n"
+ " selection 0x%lx (%s) target 0x%lx (%s)",
+ req->requestor,
+ req->selection,
+ X11->xdndAtomToString(req->selection).data(),
+ req->target,
+ X11->xdndAtomToString(req->target).data());
+
+ QClipboardData *d;
+ if (req->selection == XA_PRIMARY) {
+ d = selectionData();
+ } else if (req->selection == ATOM(CLIPBOARD)) {
+ d = clipboardData();
+ } else {
+ qWarning("QClipboard: Unknown selection '%lx'", req->selection);
+ XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
+ break;
+ }
+
+ if (! d->source()) {
+ qWarning("QClipboard: Cannot transfer data, no data available");
+ XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
+ break;
+ }
+
+ DEBUG("QClipboard: SelectionRequest at time %lx (ours %lx)",
+ req->time, d->timestamp);
+
+ if (d->timestamp == CurrentTime // we don't own the selection anymore
+ || (req->time != CurrentTime && req->time < d->timestamp)) {
+ DEBUG("QClipboard: SelectionRequest too old");
+ XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
+ break;
+ }
+
+ Atom xa_targets = ATOM(TARGETS);
+ Atom xa_multiple = ATOM(MULTIPLE);
+ Atom xa_timestamp = ATOM(TIMESTAMP);
+
+ struct AtomPair { Atom target; Atom property; } *multi = 0;
+ Atom multi_type = XNone;
+ int multi_format = 0;
+ int nmulti = 0;
+ int imulti = -1;
+ bool multi_writeback = false;
+
+ if (req->target == xa_multiple) {
+ QByteArray multi_data;
+ if (req->property == XNone
+ || !X11->clipboardReadProperty(req->requestor, req->property, false, &multi_data,
+ 0, &multi_type, &multi_format, 0)
+ || multi_format != 32) {
+ // MULTIPLE property not formatted correctly
+ XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
+ break;
+ }
+ nmulti = multi_data.size()/sizeof(*multi);
+ multi = new AtomPair[nmulti];
+ memcpy(multi,multi_data.data(),multi_data.size());
+ imulti = 0;
+ }
+
+ for (; imulti < nmulti; ++imulti) {
+ Atom target;
+ Atom property;
+
+ if (multi) {
+ target = multi[imulti].target;
+ property = multi[imulti].property;
+ } else {
+ target = req->target;
+ property = req->property;
+ if (property == XNone) // obsolete client
+ property = target;
+ }
+
+ Atom ret = XNone;
+ if (target == XNone || property == XNone) {
+ ;
+ } else if (target == xa_timestamp) {
+ if (d->timestamp != CurrentTime) {
+ XChangeProperty(dpy, req->requestor, property, XA_INTEGER, 32,
+ PropModeReplace, (uchar *) &d->timestamp, 1);
+ ret = property;
+ } else {
+ qWarning("QClipboard: Invalid data timestamp");
+ }
+ } else if (target == xa_targets) {
+ ret = send_targets_selection(d, req->requestor, property);
+ } else {
+ ret = send_selection(d, target, req->requestor, property);
+ }
+
+ if (nmulti > 0) {
+ if (ret == XNone) {
+ multi[imulti].property = XNone;
+ multi_writeback = true;
+ }
+ } else {
+ event.xselection.property = ret;
+ break;
+ }
+ }
+
+ if (nmulti > 0) {
+ if (multi_writeback) {
+ // according to ICCCM 2.6.2 says to put None back
+ // into the original property on the requestor window
+ XChangeProperty(dpy, req->requestor, req->property, multi_type, 32,
+ PropModeReplace, (uchar *) multi, nmulti * 2);
+ }
+
+ delete [] multi;
+ event.xselection.property = req->property;
+ }
+
+ // send selection notify to requestor
+ XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
+
+ DEBUG("QClipboard: SelectionNotify to 0x%lx\n"
+ " property 0x%lx (%s)",
+ req->requestor, event.xselection.property,
+ X11->xdndAtomToString(event.xselection.property).data());
+ }
+ break;
+ }
+
+ return true;
+}
+
+
+
+
+
+
+QClipboardWatcher::QClipboardWatcher(QClipboard::Mode mode)
+ : QInternalMimeData()
+{
+ switch (mode) {
+ case QClipboard::Selection:
+ atom = XA_PRIMARY;
+ break;
+
+ case QClipboard::Clipboard:
+ atom = ATOM(CLIPBOARD);
+ break;
+
+ default:
+ qWarning("QClipboardWatcher: Internal error: Unsupported clipboard mode");
+ break;
+ }
+
+ setupOwner();
+}
+
+QClipboardWatcher::~QClipboardWatcher()
+{
+ if(selection_watcher == this)
+ selection_watcher = 0;
+ if(clipboard_watcher == this)
+ clipboard_watcher = 0;
+}
+
+bool QClipboardWatcher::empty() const
+{
+ Display *dpy = X11->display;
+ Window win = XGetSelectionOwner(dpy, atom);
+
+ if(win == requestor->internalWinId()) {
+ qWarning("QClipboardWatcher::empty: Internal error: Application owns the selection");
+ return true;
+ }
+
+ return win == XNone;
+}
+
+QStringList QClipboardWatcher::formats_sys() const
+{
+ if (empty())
+ return QStringList();
+
+ if (!formatList.count()) {
+ // get the list of targets from the current clipboard owner - we do this
+ // once so that multiple calls to this function don't require multiple
+ // server round trips...
+
+ format_atoms = getDataInFormat(ATOM(TARGETS));
+
+ if (format_atoms.size() > 0) {
+ Atom *targets = (Atom *) format_atoms.data();
+ int size = format_atoms.size() / sizeof(Atom);
+
+ for (int i = 0; i < size; ++i) {
+ if (targets[i] == 0)
+ continue;
+
+ QStringList formatsForAtom = X11->xdndMimeFormatsForAtom(targets[i]);
+ for (int j = 0; j < formatsForAtom.size(); ++j) {
+ if (!formatList.contains(formatsForAtom.at(j)))
+ formatList.append(formatsForAtom.at(j));
+ }
+ VDEBUG(" format: %s", X11->xdndAtomToString(targets[i]).data());
+ VDEBUG(" data:\n%s\n", getDataInFormat(targets[i]).data());
+ }
+ DEBUG("QClipboardWatcher::format: %d formats available", formatList.count());
+ }
+ }
+
+ return formatList;
+}
+
+bool QClipboardWatcher::hasFormat_sys(const QString &format) const
+{
+ QStringList list = formats();
+ return list.contains(format);
+}
+
+QVariant QClipboardWatcher::retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const
+{
+ if (fmt.isEmpty() || empty())
+ return QByteArray();
+
+ (void)formats(); // trigger update of format list
+ DEBUG("QClipboardWatcher::data: fetching format '%s'", fmt.toLatin1().data());
+
+ QList<Atom> atoms;
+ Atom *targets = (Atom *) format_atoms.data();
+ int size = format_atoms.size() / sizeof(Atom);
+ for (int i = 0; i < size; ++i)
+ atoms.append(targets[i]);
+
+ QByteArray encoding;
+ Atom fmtatom = X11->xdndMimeAtomForFormat(fmt, requestedType, atoms, &encoding);
+
+ if (fmtatom == 0)
+ return QVariant();
+
+ return X11->xdndMimeConvertToFormat(fmtatom, getDataInFormat(fmtatom), fmt, requestedType, encoding);
+}
+
+QByteArray QClipboardWatcher::getDataInFormat(Atom fmtatom) const
+{
+ QByteArray buf;
+
+ Display *dpy = X11->display;
+ requestor->createWinId();
+ Window win = requestor->internalWinId();
+ Q_ASSERT(requestor->testAttribute(Qt::WA_WState_Created));
+
+ DEBUG("QClipboardWatcher::getDataInFormat: selection '%s' format '%s'",
+ X11->xdndAtomToString(atom).data(), X11->xdndAtomToString(fmtatom).data());
+
+ XSelectInput(dpy, win, NoEventMask); // don't listen for any events
+
+ XDeleteProperty(dpy, win, ATOM(_QT_SELECTION));
+ XConvertSelection(dpy, atom, fmtatom, ATOM(_QT_SELECTION), win, X11->time);
+ XSync(dpy, false);
+
+ VDEBUG("QClipboardWatcher::getDataInFormat: waiting for SelectionNotify event");
+
+ XEvent xevent;
+ if (!X11->clipboardWaitForEvent(win,SelectionNotify,&xevent,clipboard_timeout) ||
+ xevent.xselection.property == XNone) {
+ DEBUG("QClipboardWatcher::getDataInFormat: format not available");
+ return buf;
+ }
+
+ VDEBUG("QClipboardWatcher::getDataInFormat: fetching data...");
+
+ Atom type;
+ XSelectInput(dpy, win, PropertyChangeMask);
+
+ if (X11->clipboardReadProperty(win, ATOM(_QT_SELECTION), true, &buf, 0, &type, 0, false)) {
+ if (type == ATOM(INCR)) {
+ int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0;
+ buf = X11->clipboardReadIncrementalProperty(win, ATOM(_QT_SELECTION), nbytes, false);
+ }
+ }
+
+ XSelectInput(dpy, win, NoEventMask);
+
+ DEBUG("QClipboardWatcher::getDataInFormat: %d bytes received", buf.size());
+
+ return buf;
+}
+
+
+const QMimeData* QClipboard::mimeData(Mode mode) const
+{
+ QClipboardData *d = 0;
+ switch (mode) {
+ case Selection:
+ d = selectionData();
+ break;
+ case Clipboard:
+ d = clipboardData();
+ break;
+ default:
+ qWarning("QClipboard::mimeData: unsupported mode '%d'", mode);
+ return 0;
+ }
+
+ if (! d->source() && ! timer_event_clear) {
+ if (mode == Selection) {
+ if (! selection_watcher)
+ selection_watcher = new QClipboardWatcher(mode);
+ d->setSource(selection_watcher);
+ } else {
+ if (! clipboard_watcher)
+ clipboard_watcher = new QClipboardWatcher(mode);
+ d->setSource(clipboard_watcher);
+ }
+
+ if (! timer_id) {
+ // start a zero timer - we will clear cached data when the timer
+ // times out, which will be the next time we hit the event loop...
+ // that way, the data is cached long enough for calls within a single
+ // loop/function, but the data doesn't linger around in case the selection
+ // changes
+ QClipboard *that = ((QClipboard *) this);
+ timer_id = that->startTimer(0);
+ }
+ }
+
+ return d->source();
+}
+
+
+void QClipboard::setMimeData(QMimeData* src, Mode mode)
+{
+ Atom atom, sentinel_atom;
+ QClipboardData *d;
+ switch (mode) {
+ case Selection:
+ atom = XA_PRIMARY;
+ sentinel_atom = ATOM(_QT_SELECTION_SENTINEL);
+ d = selectionData();
+ break;
+
+ case Clipboard:
+ atom = ATOM(CLIPBOARD);
+ sentinel_atom = ATOM(_QT_CLIPBOARD_SENTINEL);
+ d = clipboardData();
+ break;
+
+ default:
+ qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode);
+ return;
+ }
+
+ Display *dpy = X11->display;
+ Window newOwner;
+
+ if (! src) { // no data, clear clipboard contents
+ newOwner = XNone;
+ d->clear();
+ } else {
+ setupOwner();
+
+ newOwner = owner->internalWinId();
+
+ d->setSource(src);
+ d->timestamp = X11->time;
+ }
+
+ Window prevOwner = XGetSelectionOwner(dpy, atom);
+ // use X11->time, since d->timestamp == CurrentTime when clearing
+ XSetSelectionOwner(dpy, atom, newOwner, X11->time);
+
+ if (mode == Selection)
+ emitChanged(QClipboard::Selection);
+ else
+ emitChanged(QClipboard::Clipboard);
+
+ if (XGetSelectionOwner(dpy, atom) != newOwner) {
+ qWarning("QClipboard::setData: Cannot set X11 selection owner for %s",
+ X11->xdndAtomToString(atom).data());
+ d->clear();
+ return;
+ }
+
+ // Signal to other Qt processes that the selection has changed
+ Window owners[2];
+ owners[0] = newOwner;
+ owners[1] = prevOwner;
+ XChangeProperty(dpy, QApplication::desktop()->screen(0)->internalWinId(),
+ sentinel_atom, XA_WINDOW, 32, PropModeReplace,
+ (unsigned char*)&owners, 2);
+}
+
+
+/*
+ Called by the main event loop in qapplication_x11.cpp when either
+ the _QT_SELECTION_SENTINEL property has been changed (i.e. when some
+ Qt process has performed QClipboard::setData()) or when Xfixes told
+ us that an other application changed the selection. If it returns
+ true, the QClipBoard dataChanged() signal should be emitted.
+*/
+
+bool qt_check_selection_sentinel()
+{
+ bool doIt = true;
+ if (owner && !X11->use_xfixes) {
+ /*
+ Since the X selection mechanism cannot give any signal when
+ the selection has changed, we emulate it (for Qt processes) here.
+ The notification should be ignored in case of either
+ a) This is the process that did setData (because setData()
+ then has already emitted dataChanged())
+ b) This is the process that owned the selection when dataChanged()
+ was called (because we have then received a SelectionClear event,
+ and have already emitted dataChanged() as a result of that)
+ */
+
+ unsigned char *retval;
+ Atom actualType;
+ int actualFormat;
+ ulong nitems;
+ ulong bytesLeft;
+
+ if (XGetWindowProperty(X11->display,
+ QApplication::desktop()->screen(0)->internalWinId(),
+ ATOM(_QT_SELECTION_SENTINEL), 0, 2, False, XA_WINDOW,
+ &actualType, &actualFormat, &nitems,
+ &bytesLeft, &retval) == Success) {
+ Window *owners = (Window *)retval;
+ if (actualType == XA_WINDOW && actualFormat == 32 && nitems == 2) {
+ Window win = owner->internalWinId();
+ if (owners[0] == win || owners[1] == win)
+ doIt = false;
+ }
+
+ XFree(owners);
+ }
+ }
+
+ if (doIt) {
+ if (waiting_for_data) {
+ pending_selection_changed = true;
+ if (! pending_timer_id)
+ pending_timer_id = QApplication::clipboard()->startTimer(0);
+ doIt = false;
+ } else {
+ selectionData()->clear();
+ }
+ }
+
+ return doIt;
+}
+
+
+bool qt_check_clipboard_sentinel()
+{
+ bool doIt = true;
+ if (owner && !X11->use_xfixes) {
+ unsigned char *retval;
+ Atom actualType;
+ int actualFormat;
+ unsigned long nitems, bytesLeft;
+
+ if (XGetWindowProperty(X11->display,
+ QApplication::desktop()->screen(0)->internalWinId(),
+ ATOM(_QT_CLIPBOARD_SENTINEL), 0, 2, False, XA_WINDOW,
+ &actualType, &actualFormat, &nitems, &bytesLeft,
+ &retval) == Success) {
+ Window *owners = (Window *)retval;
+ if (actualType == XA_WINDOW && actualFormat == 32 && nitems == 2) {
+ Window win = owner->internalWinId();
+ if (owners[0] == win || owners[1] == win)
+ doIt = false;
+ }
+
+ XFree(owners);
+ }
+ }
+
+ if (doIt) {
+ if (waiting_for_data) {
+ pending_clipboard_changed = true;
+ if (! pending_timer_id)
+ pending_timer_id = QApplication::clipboard()->startTimer(0);
+ doIt = false;
+ } else {
+ clipboardData()->clear();
+ }
+ }
+
+ return doIt;
+}
+
+bool qt_xfixes_selection_changed(Window selectionOwner, Time timestamp)
+{
+ QClipboardData *d = selectionData();
+#ifdef QCLIPBOARD_DEBUG
+ DEBUG("qt_xfixes_selection_changed: owner = %u; selectionOwner = %u; internal timestamp = %u; external timestamp = %u",
+ (unsigned int)(owner ? (int)owner->internalWinId() : 0), (unsigned int)selectionOwner,
+ (unsigned int)(d ? d->timestamp : 0), (unsigned int)timestamp);
+#endif
+ if (!owner || (selectionOwner && selectionOwner != owner->internalWinId()) ||
+ (!selectionOwner && d->timestamp != CurrentTime && d->timestamp < timestamp))
+ return qt_check_selection_sentinel();
+ return false;
+}
+
+bool qt_xfixes_clipboard_changed(Window clipboardOwner, Time timestamp)
+{
+ QClipboardData *d = clipboardData();
+#ifdef QCLIPBOARD_DEBUG
+ DEBUG("qt_xfixes_clipboard_changed: owner = %u; clipboardOwner = %u; internal timestamp = %u; external timestamp = %u",
+ (unsigned int)(owner ? (int)owner->internalWinId() : 0), (unsigned int)clipboardOwner,
+ (unsigned int)(d ? d->timestamp : 0), (unsigned int)timestamp);
+#endif
+ if (!owner || (clipboardOwner && clipboardOwner != owner->internalWinId()) ||
+ (!clipboardOwner && d->timestamp != CurrentTime && d->timestamp < timestamp))
+ return qt_check_clipboard_sentinel();
+ return false;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm
new file mode 100644
index 0000000000..f95f004f33
--- /dev/null
+++ b/src/gui/kernel/qcocoaapplication_mac.mm
@@ -0,0 +1,114 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+/****************************************************************************
+**
+** 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 <qglobal.h>
+#ifdef QT_MAC_USE_COCOA
+#include <private/qcocoaapplication_mac_p.h>
+#include <private/qcocoaapplicationdelegate_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+
+@implementation NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration))
+
+- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu
+{
+ [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] setDockMenu:newMenu];
+}
+
+- (QApplicationPrivate *)QT_MANGLE_NAMESPACE(qt_qappPrivate)
+{
+ return [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate];
+}
+
+- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)
+{
+ return [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] menuLoader];
+}
+
+- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel
+{
+ Q_UNUSED(fontPanel);
+ // only display those things that QFont can handle
+ return NSFontPanelFaceModeMask
+ | NSFontPanelSizeModeMask
+ | NSFontPanelCollectionModeMask
+ | NSFontPanelUnderlineEffectModeMask
+ | NSFontPanelStrikethroughEffectModeMask;
+}
+
+@end
+#endif
diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h
new file mode 100644
index 0000000000..15c64d53fe
--- /dev/null
+++ b/src/gui/kernel/qcocoaapplication_mac_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+/*
+ Cocoa Application Categories
+*/
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#import <AppKit/AppKit.h>
+QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
+@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader);
+
+@interface NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration))
+- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu;
+- (QApplicationPrivate *)QT_MANGLE_NAMESPACE(qt_qappPrivate);
+- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader);
+- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel;
+@end
+#endif
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
new file mode 100644
index 0000000000..650ebbd663
--- /dev/null
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
@@ -0,0 +1,282 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+/****************************************************************************
+ **
+ ** 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 "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+
+#import <private/qcocoaapplicationdelegate_mac_p.h>
+#import <private/qcocoamenuloader_mac_p.h>
+#include <private/qapplication_p.h>
+#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qdesktopwidget_mac_p.h>
+#include <qevent.h>
+#include <qapplication.h>
+
+QT_BEGIN_NAMESPACE
+extern void onApplicationChangedActivation(bool); // qapplication_mac.mm
+QT_END_NAMESPACE
+
+QT_FORWARD_DECLARE_CLASS(QDesktopWidgetImplementation)
+QT_USE_NAMESPACE
+
+static QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *sharedCocoaApplicationDelegate = nil;
+
+static void cleanupCocoaApplicationDelegate()
+{
+ [sharedCocoaApplicationDelegate release];
+}
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)
+
+- (id)init
+{
+ self = [super init];
+ return self;
+}
+
+- (void)dealloc
+{
+ sharedCocoaApplicationDelegate = nil;
+ [dockMenu release];
+ [qtMenuLoader release];
+ if (reflectionDelegate) {
+ [NSApp setDelegate:reflectionDelegate];
+ [reflectionDelegate release];
+ }
+ [super dealloc];
+}
+
++ (id)allocWithZone:(NSZone *)zone
+{
+ @synchronized(self) {
+ if (sharedCocoaApplicationDelegate == nil) {
+ sharedCocoaApplicationDelegate = [super allocWithZone:zone];
+ return sharedCocoaApplicationDelegate;
+ qAddPostRoutine(cleanupCocoaApplicationDelegate);
+ }
+ }
+ return nil;
+}
+
++ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate
+{
+ @synchronized(self) {
+ if (sharedCocoaApplicationDelegate == nil)
+ [[self alloc] init];
+ }
+ return [[sharedCocoaApplicationDelegate retain] autorelease];
+}
+
+- (void)setDockMenu:(NSMenu*)newMenu
+{
+ [newMenu retain];
+ [dockMenu release];
+ dockMenu = newMenu;
+}
+
+- (NSMenu *)applicationDockMenu
+{
+ return [[dockMenu retain] autorelease];
+}
+
+- (QApplicationPrivate *)qAppPrivate
+{
+ return qtPrivate;
+}
+
+- (void)setQtPrivate:(QApplicationPrivate *)value
+{
+ qtPrivate = value;
+}
+
+- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader
+{
+ [menuLoader retain];
+ [qtMenuLoader release];
+ qtMenuLoader = menuLoader;
+}
+
+- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader;
+{
+ return [[qtMenuLoader retain] autorelease];
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ Q_UNUSED(sender);
+ // The reflection delegate gets precedence
+ NSApplicationTerminateReply reply = NSTerminateCancel;
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)]) {
+ return [reflectionDelegate applicationShouldTerminate:sender];
+ }
+
+ if (qtPrivate->canQuit()) {
+ reply = NSTerminateNow;
+ if (!startedQuit) {
+ startedQuit = true;
+ qAppInstance()->quit();
+ startedQuit = false;
+ }
+ }
+ return reply;
+}
+
+- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
+{
+ unsigned int ix;
+ for( ix = 0; ix < [filenames count]; ix++) {
+ NSString *fileName = [filenames objectAtIndex:ix];
+ qApp->postEvent(qApp, new QFileOpenEvent(QCFString::toQString((CFStringRef)fileName)));
+ }
+
+ if (reflectionDelegate &&
+ [reflectionDelegate respondsToSelector:@selector(application:openFiles:)])
+ [reflectionDelegate application:sender openFiles:filenames];
+}
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
+{
+ // If we have a reflection delegate, that will get to call the shots.
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:
+ @selector(applicationShouldTerminateAfterLastWindowClosed:)])
+ return [reflectionDelegate applicationShouldTerminateAfterLastWindowClosed:sender];
+ return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together.
+}
+
+
+- (void)applicationDidBecomeActive:(NSNotification *)notification
+{
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
+ [reflectionDelegate applicationDidBecomeActive:notification];
+ onApplicationChangedActivation(true);
+}
+
+- (void)applicationDidResignActive:(NSNotification *)notification;
+{
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
+ [reflectionDelegate applicationDidResignActive:notification];
+ onApplicationChangedActivation(false);
+}
+
+class QDesktopWidgetImplementation;
+- (void)applicationDidChangeScreenParameters:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QDesktopWidgetImplementation::instance()->onResize();
+}
+
+- (void)setReflectionDelegate:(NSObject *)oldDelegate
+{
+ [oldDelegate retain];
+ [reflectionDelegate release];
+ reflectionDelegate = oldDelegate;
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
+{
+ NSMethodSignature *result = [super methodSignatureForSelector:aSelector];
+ if (!result && reflectionDelegate) {
+ result = [reflectionDelegate methodSignatureForSelector:aSelector];
+ }
+ return result;
+}
+
+- (BOOL)respondsToSelector:(SEL)aSelector
+{
+ BOOL result = [super respondsToSelector:aSelector];
+ if (!result && reflectionDelegate)
+ result = [reflectionDelegate respondsToSelector:aSelector];
+ return result;
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+ SEL invocationSelector = [invocation selector];
+ if (reflectionDelegate && [reflectionDelegate respondsToSelector:invocationSelector])
+ [invocation invokeWithTarget:reflectionDelegate];
+ else
+ [self doesNotRecognizeSelector:invocationSelector];
+}
+
+@end
+#endif
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h b/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h
new file mode 100644
index 0000000000..c5336f1797
--- /dev/null
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+ **
+ ****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+
+QT_FORWARD_DECLARE_CLASS(QApplicationPrivate);
+
+@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
+
+@protocol NSApplicationDelegate <NSObject> @end
+
+#endif
+
+@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> {
+ bool startedQuit;
+ QApplicationPrivate *qtPrivate;
+ NSMenu *dockMenu;
+ QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader;
+ id <NSApplicationDelegate> reflectionDelegate;
+}
++ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate;
+- (void)setDockMenu:(NSMenu *)newMenu;
+- (void)setQtPrivate:(QApplicationPrivate *)value;
+- (QApplicationPrivate *)qAppPrivate;
+- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader)*)menuLoader;
+- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader;
+- (void)setReflectionDelegate:(NSObject *)oldDelegate;
+@end
+#endif
diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm
new file mode 100644
index 0000000000..7ecb765b3c
--- /dev/null
+++ b/src/gui/kernel/qcocoamenuloader_mac.mm
@@ -0,0 +1,215 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#include <qaction.h>
+#include <qcoreapplication.h>
+#include <private/qcocoamenuloader_mac_p.h>
+#include <private/qt_mac_p.h>
+#include <qmenubar.h>
+
+QT_FORWARD_DECLARE_CLASS(QCFString)
+QT_FORWARD_DECLARE_CLASS(QString)
+
+QT_USE_NAMESPACE
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaMenuLoader)
+
+- (void)awakeFromNib
+{
+ // Get the names in the nib to match the app name set by Qt.
+ NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName()));
+ [quitItem setTitle:[[quitItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
+ withString:appName]];
+ [hideItem setTitle:[[hideItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
+ withString:appName]];
+ [aboutItem setTitle:[[aboutItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
+ withString:appName]];
+ [appName release];
+ // Disable the items that don't do anything. If someone associates a QAction with them
+ // They should get synced back in.
+ [preferencesItem setEnabled:NO];
+ [preferencesItem setHidden:YES];
+ [aboutItem setEnabled:NO];
+ [aboutItem setHidden:YES];
+}
+
+- (void)ensureAppMenuInMenu:(NSMenu *)menu
+{
+ NSMenu *mainMenu = [NSApp mainMenu];
+ if ([NSApp mainMenu] == menu)
+ return; // nothing to do!
+#ifndef QT_NAMESPACE
+ Q_ASSERT(mainMenu);
+#endif
+ // Grab the app menu out of the current menu.
+ int numItems = [mainMenu numberOfItems];
+ NSMenuItem *oldAppMenuItem = 0;
+ for (int i = 0; i < numItems; ++i) {
+ NSMenuItem *item = [mainMenu itemAtIndex:i];
+ if ([item submenu] == appMenu) {
+ oldAppMenuItem = item;
+ [oldAppMenuItem retain];
+ [mainMenu removeItemAtIndex:i];
+ break;
+ }
+ }
+
+ if (oldAppMenuItem) {
+ [oldAppMenuItem setSubmenu:nil];
+ [oldAppMenuItem release];
+ NSMenuItem *appMenuItem = [[NSMenuItem alloc] initWithTitle:@"Apple"
+ action:nil keyEquivalent:@""];
+ [appMenuItem setSubmenu:appMenu];
+ [menu insertItem:appMenuItem atIndex:0];
+ }
+}
+
+- (void)dealloc
+{
+ [lastAppSpecificItem release];
+ [theMenu release];
+ [appMenu release];
+ [super dealloc];
+}
+
+- (NSMenu *)menu
+{
+ return [[theMenu retain] autorelease];
+}
+
+- (NSMenu *)applicationMenu
+{
+ return [[appMenu retain] autorelease];
+}
+
+- (NSMenuItem *)quitMenuItem
+{
+ return [[quitItem retain] autorelease];
+}
+
+- (NSMenuItem *)preferencesMenuItem
+{
+ return [[preferencesItem retain] autorelease];
+}
+
+- (NSMenuItem *)aboutMenuItem
+{
+ return [[aboutItem retain] autorelease];
+}
+
+- (NSMenuItem *)aboutQtMenuItem
+{
+ return [[aboutQtItem retain] autorelease];
+}
+
+- (NSMenuItem *)hideMenuItem;
+{
+ return [[hideItem retain] autorelease];
+}
+
+- (NSMenuItem *)appSpecificMenuItem;
+{
+ // Create an App-Specific menu item, insert it into the menu and return
+ // it as an autorelease item.
+ NSMenuItem *item = [[NSMenuItem alloc] init];
+
+ NSInteger location;
+ if (lastAppSpecificItem == nil) {
+ location = [appMenu indexOfItem:aboutQtItem];
+ } else {
+ location = [appMenu indexOfItem:lastAppSpecificItem];
+ [lastAppSpecificItem release];
+ }
+ lastAppSpecificItem = item; // Keep track of this for later (i.e., don't release it)
+ [appMenu insertItem:item atIndex:location + 1];
+
+ return [[item retain] autorelease];
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (void)terminate:(id)sender
+{
+ [NSApp terminate:sender];
+}
+
+- (void)orderFrontStandardAboutPanel:(id)sender
+{
+ [NSApp orderFrontStandardAboutPanel:sender];
+}
+
+- (void)hideOtherApplications:(id)sender
+{
+ [NSApp hideOtherApplications:sender];
+}
+
+- (void)unhideAllApplications:(id)sender
+{
+ [NSApp unhideAllApplications:sender];
+}
+
+- (void)hide:(id)sender
+{
+ [NSApp hide:sender];
+}
+
+- (IBAction)qtDispatcherToQAction:(id)sender
+{
+ NSMenuItem *item = static_cast<NSMenuItem *>(sender);
+ if (QAction *action = reinterpret_cast<QAction *>([item tag])) {
+ action->trigger();
+ } else if (item == quitItem) {
+ // We got here because someone was once the quitItem, but it has been
+ // abandoned (e.g., the menubar was deleted). In the meantime, just do
+ // normal QApplication::quit().
+ qApp->quit();
+ }
+}
+@end
+#endif // QT_MAC_USE_COCOA
diff --git a/src/gui/kernel/qcocoamenuloader_mac_p.h b/src/gui/kernel/qcocoamenuloader_mac_p.h
new file mode 100644
index 0000000000..cc7338cc3d
--- /dev/null
+++ b/src/gui/kernel/qcocoamenuloader_mac_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOAMENULOADER_P_H
+#define QCOCOAMENULOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+
+@interface QT_MANGLE_NAMESPACE(QCocoaMenuLoader) : NSResponder
+{
+ IBOutlet NSMenu *theMenu;
+ IBOutlet NSMenu *appMenu;
+ IBOutlet NSMenuItem *quitItem;
+ IBOutlet NSMenuItem *preferencesItem;
+ IBOutlet NSMenuItem *aboutItem;
+ IBOutlet NSMenuItem *aboutQtItem;
+ IBOutlet NSMenuItem *hideItem;
+ NSMenuItem *lastAppSpecificItem;
+
+}
+- (void)ensureAppMenuInMenu:(NSMenu *)menu;
+- (NSMenu *)applicationMenu;
+- (NSMenu *)menu;
+- (NSMenuItem *)quitMenuItem;
+- (NSMenuItem *)preferencesMenuItem;
+- (NSMenuItem *)aboutMenuItem;
+- (NSMenuItem *)aboutQtMenuItem;
+- (NSMenuItem *)hideMenuItem;
+- (NSMenuItem *)appSpecificMenuItem;
+- (IBAction)terminate:(id)sender;
+- (IBAction)orderFrontStandardAboutPanel:(id)sender;
+- (IBAction)hideOtherApplications:(id)sender;
+- (IBAction)unhideAllApplications:(id)sender;
+- (IBAction)hide:(id)sender;
+- (IBAction)qtDispatcherToQAction:(id)sender;
+@end
+
+#endif // QT_MAC_USE_COCOA
+#endif // QCOCOAMENULOADER_P_H
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm
new file mode 100644
index 0000000000..6aeee34400
--- /dev/null
+++ b/src/gui/kernel/qcocoapanel_mac.mm
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import <private/qcocoapanel_mac_p.h>
+#ifdef QT_MAC_USE_COCOA
+#import <private/qt_cocoa_helpers_mac_p.h>
+#import <private/qcocoawindow_mac_p.h>
+#import <private/qcocoawindowcustomthemeframe_mac_p.h>
+
+#include <QtGui/QWidget>
+
+QT_USE_NAMESPACE
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaPanel)
+
+- (BOOL)canBecomeKeyWindow
+{
+ QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)];
+
+ bool isToolTip = (widget->windowType() == Qt::ToolTip);
+ bool isPopup = (widget->windowType() == Qt::Popup);
+ return !(isPopup || isToolTip);
+}
+
+- (void)sendEvent:(NSEvent *)event
+{
+ [self retain];
+ [super sendEvent:event];
+ qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton);
+ [self release];
+}
+
++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask
+{
+ if (styleMask & QtMacCustomizeWindow)
+ return [QCocoaWindowCustomThemeFrame class];
+ return [super frameViewClassForStyleMask:styleMask];
+}
+
+@end
+#endif
diff --git a/src/gui/kernel/qcocoapanel_mac_p.h b/src/gui/kernel/qcocoapanel_mac_p.h
new file mode 100644
index 0000000000..0d1f0083aa
--- /dev/null
+++ b/src/gui/kernel/qcocoapanel_mac_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+
+
+@interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel {
+ bool leftButtonIsRightButton;
+}
+
++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
+
+@end
+#endif
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
new file mode 100644
index 0000000000..19367d1fc8
--- /dev/null
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -0,0 +1,1254 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import <private/qcocoaview_mac_p.h>
+#ifdef QT_MAC_USE_COCOA
+
+#include <private/qwidget_p.h>
+#include <private/qt_mac_p.h>
+#include <private/qapplication_p.h>
+#include <private/qabstractscrollarea_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qdnd_p.h>
+#include <private/qmacinputcontext_p.h>
+
+#include <qscrollarea.h>
+#include <qhash.h>
+#include <qtextformat.h>
+#include <qpaintengine.h>
+#include <QUrl>
+#include <QAccessible>
+#include <QFileInfo>
+#include <QFile>
+
+#include <qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(DnDParams, qMacDnDParams);
+
+extern void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos); // qcursor_mac.mm
+extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp
+extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm
+extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp
+extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm
+
+Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
+{
+ if (buttonNum == 0)
+ return Qt::LeftButton;
+ if (buttonNum == 1)
+ return Qt::RightButton;
+ if (buttonNum == 2)
+ return Qt::MidButton;
+ if (buttonNum == 3)
+ return Qt::XButton1;
+ if (buttonNum == 4)
+ return Qt::XButton2;
+ return Qt::NoButton;
+}
+
+struct dndenum_mapper
+{
+ NSDragOperation mac_code;
+ Qt::DropAction qt_code;
+ bool Qt2Mac;
+};
+
+static dndenum_mapper dnd_enums[] = {
+ { NSDragOperationLink, Qt::LinkAction, true },
+ { NSDragOperationMove, Qt::MoveAction, true },
+ { NSDragOperationCopy, Qt::CopyAction, true },
+ { NSDragOperationGeneric, Qt::CopyAction, false },
+ { NSDragOperationEvery, Qt::ActionMask, false },
+ { NSDragOperationNone, Qt::IgnoreAction, false }
+};
+
+static NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
+{
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) {
+ return dnd_enums[i].mac_code;
+ }
+ }
+ return NSDragOperationNone;
+}
+
+static NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
+{
+ NSDragOperation nsActions = NSDragOperationNone;
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code))
+ nsActions |= dnd_enums[i].mac_code;
+ }
+ return nsActions;
+}
+
+static Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
+{
+ Qt::DropAction action = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ return dnd_enums[i].qt_code;
+ }
+ return action;
+}
+
+static Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ actions |= dnd_enums[i].qt_code;
+ }
+ return actions;
+}
+
+static QColor colorFrom(NSColor *color)
+{
+ QColor qtColor;
+ NSString *colorSpace = [color colorSpaceName];
+ if (colorSpace == NSDeviceCMYKColorSpace) {
+ CGFloat cyan, magenta, yellow, black, alpha;
+ [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha];
+ qtColor.setCmykF(cyan, magenta, yellow, black, alpha);
+ } else {
+ NSColor *tmpColor;
+ tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ CGFloat red, green, blue, alpha;
+ [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ qtColor.setRgbF(red, green, blue, alpha);
+ }
+ return qtColor;
+}
+
+QT_END_NAMESPACE
+
+QT_FORWARD_DECLARE_CLASS(QMacCocoaAutoReleasePool)
+QT_FORWARD_DECLARE_CLASS(QCFString)
+QT_FORWARD_DECLARE_CLASS(QDragManager)
+QT_FORWARD_DECLARE_CLASS(QMimeData)
+QT_FORWARD_DECLARE_CLASS(QPoint)
+QT_FORWARD_DECLARE_CLASS(QApplication)
+QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
+QT_FORWARD_DECLARE_CLASS(QDragEnterEvent)
+QT_FORWARD_DECLARE_CLASS(QDragMoveEvent)
+QT_FORWARD_DECLARE_CLASS(QStringList)
+QT_FORWARD_DECLARE_CLASS(QString)
+QT_FORWARD_DECLARE_CLASS(QRect)
+QT_FORWARD_DECLARE_CLASS(QRegion)
+QT_FORWARD_DECLARE_CLASS(QAbstractScrollArea)
+QT_FORWARD_DECLARE_CLASS(QAbstractScrollAreaPrivate)
+QT_FORWARD_DECLARE_CLASS(QPaintEvent)
+QT_FORWARD_DECLARE_CLASS(QPainter)
+QT_FORWARD_DECLARE_CLASS(QHoverEvent)
+QT_USE_NAMESPACE
+extern "C" {
+ extern NSString *NSTextInputReplacementRangeAttributeName;
+}
+
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaView)
+
+- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate
+{
+ self = [super init];
+ if (self) {
+ [self finishInitWithQWidget:widget widgetPrivate:widgetprivate];
+ }
+ composing = false;
+ sendKeyEvents = true;
+ [self setHidden:YES];
+ return self;
+}
+
+- (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate
+{
+ qwidget = widget;
+ qwidgetprivate = widgetprivate;
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(frameDidChange:)
+ name:@"NSViewFrameDidChangeNotification"
+ object:self];
+}
+
+-(void)registerDragTypes:(bool)accept
+{
+ QMacCocoaAutoReleasePool pool;
+ if (accept) {
+ const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
+ NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
+ NSFilenamesPboardType, NSStringPboardType,
+ NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
+ NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
+ NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
+ NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
+ NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
+ NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
+ // Add custom types supported by the application.
+ const QStringList& customTypes = qEnabledDraggedTypes();
+ for (int i = 0; i < customTypes.size(); i++) {
+ [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))];
+ }
+ [self registerForDraggedTypes:supportedTypes];
+ } else {
+ [self unregisterDraggedTypes];
+ }
+}
+
+- (void)removeDropData
+{
+ if (dropData) {
+ delete dropData;
+ dropData = 0;
+ }
+}
+
+- (void)addDropData:(id <NSDraggingInfo>)sender
+{
+ [self removeDropData];
+ CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name];
+ dropData = new QCocoaDropData(dropPasteboard);
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ [self addDropData:sender];
+ QMimeData *mimeData = dropData;
+ if (QDragManager::self()->source())
+ mimeData = QDragManager::self()->dragPrivate()->data;
+ NSPoint windowPoint = [sender draggingLocation];
+ NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
+ NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
+ QPoint posDrag(localPoint.x, localPoint.y);
+ NSDragOperation nsActions = [sender draggingSourceOperationMask];
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions);
+ // send the drag enter event to the widget.
+ QDragEnterEvent qDEEvent(posDrag, qtAllowed, mimeData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ QApplication::sendEvent(qwidget, &qDEEvent);
+ if (!qDEEvent.isAccepted()) {
+ // widget is not interested in this drag, so ignore this drop data.
+ [self removeDropData];
+ return NSDragOperationNone;
+ } else {
+ // send a drag move event immediately after a drag enter event (as per documentation).
+ QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ qDMEvent.setDropAction(qDEEvent.dropAction());
+ qDMEvent.accept(); // accept by default, since enter event was accepted.
+ QApplication::sendEvent(qwidget, &qDMEvent);
+ if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) {
+ // since we accepted the drag enter event, the widget expects
+ // future drage move events.
+ // ### check if we need to treat this like the drag enter event.
+ nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDEEvent.dropAction());
+ } else {
+ nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDMEvent.dropAction());
+ }
+ QT_PREPEND_NAMESPACE(qt_mac_copy_answer_rect)(qDMEvent);
+ return nsActions;
+ }
+ }
+
+- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
+{
+ // drag enter event was rejected, so ignore the move event.
+ if (dropData == 0)
+ return NSDragOperationNone;
+ // return last value, if we are still in the answerRect.
+ NSPoint windowPoint = [sender draggingLocation];
+ NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
+ NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
+ QPoint posDrag(localPoint.x, localPoint.y);
+ if (qt_mac_mouse_inside_answer_rect(posDrag))
+ return QT_PREPEND_NAMESPACE(qt_mac_mapDropActions)(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastAction));
+ // send drag move event to the widget
+ NSDragOperation nsActions = [sender draggingSourceOperationMask];
+ Qt::DropActions qtAllowed = QT_PREPEND_NAMESPACE(qt_mac_mapNSDragOperations)(nsActions);
+ QMimeData *mimeData = dropData;
+ if (QDragManager::self()->source())
+ mimeData = QDragManager::self()->dragPrivate()->data;
+ QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ qDMEvent.setDropAction(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).lastAction);
+ qDMEvent.accept();
+ QApplication::sendEvent(qwidget, &qDMEvent);
+ qt_mac_copy_answer_rect(qDMEvent);
+
+ NSDragOperation operation = qt_mac_mapDropAction(qDMEvent.dropAction());
+ if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) {
+ // ignore this event (we will still receive further notifications)
+ operation = NSDragOperationNone;
+ }
+ return operation;
+}
+
+- (void)draggingExited:(id < NSDraggingInfo >)sender
+{
+ Q_UNUSED(sender)
+ // drag enter event was rejected, so ignore the move event.
+ if (dropData) {
+ QDragLeaveEvent de;
+ QApplication::sendEvent(qwidget, &de);
+ [self removeDropData];
+ }
+
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ [self addDropData:sender];
+
+ NSPoint windowPoint = [sender draggingLocation];
+ NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
+ NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
+ QPoint posDrop(localPoint.x, localPoint.y);
+
+ NSDragOperation nsActions = [sender draggingSourceOperationMask];
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions);
+ QMimeData *mimeData = dropData;
+ if (QDragManager::self()->source())
+ mimeData = QDragManager::self()->dragPrivate()->data;
+ // send the drop event to the widget.
+ QDropEvent de(posDrop, qtAllowed, mimeData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ if (QDragManager::self()->object)
+ QDragManager::self()->dragPrivate()->target = qwidget;
+ QApplication::sendEvent(qwidget, &de);
+ if (!de.isAccepted())
+ return NO;
+ else
+ return YES;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [super dealloc];
+}
+
+- (BOOL)isOpaque;
+{
+ return qwidgetprivate->isOpaque;
+}
+
+- (BOOL)isFlipped;
+{
+ return YES;
+}
+
+- (BOOL) preservesContentDuringLiveResize;
+{
+ return qwidget->testAttribute(Qt::WA_StaticContents);
+}
+
+- (void) setFrameSize:(NSSize)newSize
+{
+ [super setFrameSize:newSize];
+
+ // A change in size has required the view to be invalidated.
+ if ([self inLiveResize])
+ {
+ NSRect rects[4];
+ NSInteger count;
+ [self getRectsExposedDuringLiveResize:rects count:&count];
+ while (count-- > 0)
+ {
+ [self setNeedsDisplayInRect:rects[count]];
+ }
+ }
+ else
+ {
+ [self setNeedsDisplay:YES];
+ }
+}
+
+- (void)drawRect:(NSRect)aRect
+{
+ CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ qwidgetprivate->hd = cg;
+ CGContextSaveGState(cg);
+
+ if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event.
+ if (qwidget->testAttribute(Qt::WA_WState_InPaintEvent))
+ qWarning("QWidget::repaint: Recursive repaint detected");
+
+ const QRect qrect = QRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);
+ QRegion qrgn(qrect);
+
+ if (!qwidget->isWindow() && !qobject_cast<QAbstractScrollArea *>(qwidget->parent())) {
+ const QRegion &parentMask = qwidget->window()->mask();
+ if (!parentMask.isEmpty()) {
+ const QPoint mappedPoint = qwidget->mapTo(qwidget->window(), qrect.topLeft());
+ qrgn.translate(mappedPoint);
+ qrgn &= parentMask;
+ qrgn.translate(-mappedPoint.x(), -mappedPoint.y());
+ }
+ }
+
+ QPoint redirectionOffset(0, 0);
+ //setup the context
+ qwidget->setAttribute(Qt::WA_WState_InPaintEvent);
+ QPaintEngine *engine = qwidget->paintEngine();
+ if (engine)
+ engine->setSystemClip(qrgn);
+ if (qwidgetprivate->extra && qwidgetprivate->extra->hasMask) {
+ CGRect widgetRect = CGRectMake(0, 0, qwidget->width(), qwidget->height());
+ CGContextTranslateCTM (cg, 0, widgetRect.size.height);
+ CGContextScaleCTM(cg, 1, -1);
+ if (qwidget->isWindow())
+ CGContextClearRect(cg, widgetRect);
+ CGContextClipToMask(cg, widgetRect, qwidgetprivate->extra->imageMask);
+ CGContextScaleCTM(cg, 1, -1);
+ CGContextTranslateCTM (cg, 0, -widgetRect.size.height);
+ }
+
+ if (qwidget->isWindow() && !qwidgetprivate->isOpaque
+ && !qwidget->testAttribute(Qt::WA_MacBrushedMetal)) {
+ CGContextClearRect(cg, NSRectToCGRect(aRect));
+ }
+
+ if (engine && !qwidget->testAttribute(Qt::WA_NoSystemBackground)
+ && (qwidget->isWindow() || qwidget->autoFillBackground())
+ || qwidget->testAttribute(Qt::WA_TintedBackground)
+ || qwidget->testAttribute(Qt::WA_StyledBackground)) {
+#ifdef DEBUG_WIDGET_PAINT
+ if(doDebug)
+ qDebug(" Handling erase for [%s::%s]", qwidget->metaObject()->className(),
+ qwidget->objectName().local8Bit().data());
+#endif
+ QPainter p(qwidget);
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(qwidget->parent());
+ QPoint scrollAreaOffset;
+ if (scrollArea && scrollArea->viewport() == qwidget) {
+ QAbstractScrollAreaPrivate *priv
+ = static_cast<QAbstractScrollAreaPrivate *>(qt_widget_private(scrollArea));
+ scrollAreaOffset = priv->contentsOffset();
+ p.translate(-scrollAreaOffset);
+ }
+ qwidgetprivate->paintBackground(&p, qrgn, scrollAreaOffset,
+ qwidget->isWindow() ? QWidgetPrivate::DrawAsRoot : 0);
+ p.end();
+ }
+ QPaintEvent e(qrgn);
+#ifdef QT3_SUPPORT
+ e.setErased(true);
+#endif
+ qt_sendSpontaneousEvent(qwidget, &e);
+ if (!redirectionOffset.isNull())
+ QPainter::restoreRedirected(qwidget);
+#ifdef QT_RASTER_PAINTENGINE
+ if(engine && engine->type() == QPaintEngine::Raster)
+ static_cast<QRasterPaintEngine*>(engine)->flush(qwidget,
+ qrgn.boundingRect().topLeft());
+#endif
+ if (engine)
+ engine->setSystemClip(QRegion());
+ qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false);
+ if(!qwidget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && qwidget->paintingActive())
+ qWarning("QWidget: It is dangerous to leave painters active on a"
+ " widget outside of the PaintEvent");
+ }
+ qwidgetprivate->hd = 0;
+ CGContextRestoreGState(cg);
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+ Q_UNUSED(theEvent);
+ return !qwidget->testAttribute(Qt::WA_MacNoClickThrough);
+}
+
+- (void)updateTrackingAreas
+{
+ QMacCocoaAutoReleasePool pool;
+ if (NSArray *trackingArray = [self trackingAreas]) {
+ NSUInteger size = [trackingArray count];
+ for (NSUInteger i = 0; i < size; ++i) {
+ NSTrackingArea *t = [trackingArray objectAtIndex:i];
+ [self removeTrackingArea:t];
+ }
+ }
+ NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
+ | NSTrackingInVisibleRect;
+ if (qwidget->hasMouseTracking() || !qwidgetprivate->toolTip.isEmpty()
+ || qwidget->testAttribute(Qt::WA_Hover))
+ trackingOptions |= NSTrackingMouseMoved;
+ NSTrackingArea *ta = [[NSTrackingArea alloc] initWithRect:NSMakeRect(0, 0,
+ qwidget->width(),
+ qwidget->height())
+ options:trackingOptions
+ owner:self
+ userInfo:nil];
+ [self addTrackingArea:ta];
+ [ta release];
+}
+
+- (void)mouseEntered:(NSEvent *)event
+{
+ QEvent enterEvent(QEvent::Enter);
+ NSPoint windowPoint = [event locationInWindow];
+ NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint];
+ NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil];
+ if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
+ QApplication::sendEvent(qwidget, &enterEvent);
+ qt_mouseover = qwidget;
+
+ // Update cursor and dispatch hover events.
+ qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint());
+ if (qwidget->testAttribute(Qt::WA_Hover) &&
+ (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window())) {
+ QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1));
+ QApplicationPrivate::instance()->notify_helper(qwidget, &he);
+ }
+ }
+}
+
+- (void)mouseExited:(NSEvent *)event
+{
+ QEvent leaveEvent(QEvent::Leave);
+ NSPoint globalPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
+ if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
+ QApplication::sendEvent(qwidget, &leaveEvent);
+
+ // ### Think about if it is necessary to update the cursor, should only be for a few cases.
+ qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint());
+ if (qwidget->testAttribute(Qt::WA_Hover)
+ && (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window())) {
+ QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1),
+ qwidget->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos));
+ QApplicationPrivate::instance()->notify_helper(qwidget, &he);
+ }
+ }
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+ QWidget *widgetToGetKey = qwidget;
+
+ QWidget *popup = qAppInstance()->activePopupWidget();
+ if (popup && popup != qwidget->window())
+ widgetToGetKey = popup->focusWidget() ? popup->focusWidget() : popup;
+ qt_dispatchModifiersChanged(theEvent, widgetToGetKey);
+ [super flagsChanged:theEvent];
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton);
+}
+
+- (NSView *)viewUnderTransparentForMouseView:(NSView *)mouseView widget:(QWidget *)widgetToGetMouse
+ withWindowPoint:(NSPoint)windowPoint
+{
+ NSMutableArray *viewsToLookAt = [NSMutableArray arrayWithCapacity:5];
+ [viewsToLookAt addObject:mouseView];
+ QWidget *parentWidget = widgetToGetMouse->parentWidget();
+ while (parentWidget) {
+ [viewsToLookAt addObject:qt_mac_nativeview_for(parentWidget)];
+ parentWidget = parentWidget->parentWidget();
+ }
+
+ // Now walk through the subviews of each view and determine which subview should
+ // get the event. We look through all the subviews at a given level with
+ // the assumption that the last item to be found the candidate has a higher z-order.
+ // Unfortunately, fast enumeration doesn't go backwards in 10.5, so assume go fast
+ // forward is quicker than the slow normal way backwards.
+ NSView *candidateView = nil;
+ for (NSView *lookView in viewsToLookAt) {
+ NSPoint tmpPoint = [lookView convertPoint:windowPoint fromView:nil];
+ for (NSView *view in [lookView subviews]) {
+ if (view == mouseView)
+ continue;
+ NSRect frameRect = [view frame];
+ if (NSMouseInRect(tmpPoint, [view frame], [view isFlipped]))
+ candidateView = view;
+ }
+ if (candidateView)
+ break;
+ }
+
+
+ if (candidateView != nil) {
+ // Now that we've got a candidate, we have to dig into it's tree and see where it is.
+ NSView *lowerView = nil;
+ NSView *viewForDescent = candidateView;
+ while (viewForDescent) {
+ NSPoint tmpPoint = [viewForDescent convertPoint:windowPoint fromView:nil];
+ // Apply same rule as above wrt z-order.
+ for (NSView *view in [viewForDescent subviews]) {
+ if (NSMouseInRect(tmpPoint, [view frame], [view isFlipped]))
+ lowerView = view;
+ }
+ if (!lowerView) // Low as we can be at this point.
+ candidateView = viewForDescent;
+
+ // Try to go deeper, will also exit out of the loop, if we found the point.
+ viewForDescent = lowerView;
+ lowerView = nil;
+ }
+ }
+ // I am transparent, so I can't be a candidate.
+ if (candidateView == mouseView)
+ candidateView = nil;
+ return candidateView;
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::LeftButton);
+ // Don't call super here. This prevents us from getting the mouseUp event,
+ // which we need to send even if the mouseDown event was not accepted.
+ // (this is standard Qt behavior.)
+}
+
+
+- (void)mouseUp:(NSEvent *)theEvent
+{
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::LeftButton);
+
+ if (!mouseOK)
+ [super mouseUp:theEvent];
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent
+{
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton);
+
+ if (!mouseOK)
+ [super rightMouseDown:theEvent];
+}
+
+- (void)rightMouseUp:(NSEvent *)theEvent
+{
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::RightButton);
+
+ if (!mouseOK)
+ [super rightMouseUp:theEvent];
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent
+{
+ Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]);
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, mouseButton);
+
+ if (!mouseOK)
+ [super otherMouseDown:theEvent];
+}
+
+- (void)otherMouseUp:(NSEvent *)theEvent
+{
+ Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]);
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, mouseButton);
+
+ if (!mouseOK)
+ [super otherMouseUp:theEvent];
+
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent
+{
+ qMacDnDParams()->view = self;
+ qMacDnDParams()->theEvent = theEvent;
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::LeftButton);
+
+ if (!mouseOK)
+ [super mouseDragged:theEvent];
+}
+
+- (void)rightMouseDragged:(NSEvent *)theEvent
+{
+ qMacDnDParams()->view = self;
+ qMacDnDParams()->theEvent = theEvent;
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::RightButton);
+
+ if (!mouseOK)
+ [super rightMouseDragged:theEvent];
+}
+
+- (void)otherMouseDragged:(NSEvent *)theEvent
+{
+ qMacDnDParams()->view = self;
+ qMacDnDParams()->theEvent = theEvent;
+ Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]);
+ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, mouseButton);
+
+ if (!mouseOK)
+ [super otherMouseDragged:theEvent];
+}
+
+- (void)scrollWheel:(NSEvent *)theEvent
+{
+ // Give the Input Manager a chance to process the wheel event.
+ NSInputManager *currentIManager = [NSInputManager currentInputManager];
+ if (currentIManager && [currentIManager wantsToHandleMouseEvents]) {
+ [currentIManager handleMouseEvent:theEvent];
+ }
+
+ NSPoint windowPoint = [theEvent locationInWindow];
+ NSPoint globalPoint = [[theEvent window] convertBaseToScreen:windowPoint];
+ NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
+ QPoint qlocal = QPoint(localPoint.x, localPoint.y);
+ QPoint qglobal = QPoint(globalPoint.x, globalPoint.y);
+ Qt::MouseButton buttons = cocoaButton2QtButton([theEvent buttonNumber]);
+ bool wheelOK = false;
+ Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]);
+
+ // Mouse wheel deltas seem to tick in at increments of 0.1. Qt widgets
+ // expect the delta to be a multiple of 120.
+ const int ScrollFactor = 10 * 120;
+ // The qMax(...) factor reduces the
+ // acceleration for large wheel deltas.
+ int deltaX = [theEvent deltaX] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaX]));
+ int deltaY = [theEvent deltaY] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaY]));
+ int deltaZ = [theEvent deltaZ] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaZ]));
+
+ if (deltaX != 0) {
+ QWheelEvent qwe(qlocal, qglobal, deltaX, buttons, keyMods, Qt::Horizontal);
+ qt_sendSpontaneousEvent(qwidget, &qwe);
+ wheelOK = qwe.isAccepted();
+ if (!wheelOK && QApplicationPrivate::focus_widget
+ && QApplicationPrivate::focus_widget != qwidget) {
+ QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal,
+ deltaX, buttons, keyMods, Qt::Horizontal);
+ qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
+ wheelOK = qwe2.isAccepted();
+ }
+ }
+
+ if (deltaY) {
+ QWheelEvent qwe(qlocal, qglobal, deltaY, buttons, keyMods, Qt::Vertical);
+ qt_sendSpontaneousEvent(qwidget, &qwe);
+ wheelOK = qwe.isAccepted();
+ if (wheelOK && QApplicationPrivate::focus_widget
+ && QApplicationPrivate::focus_widget != qwidget) {
+ QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal,
+ deltaZ, buttons, keyMods, Qt::Vertical);
+ qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
+ wheelOK = qwe2.isAccepted();
+ }
+ }
+
+ if (deltaZ) {
+ // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to
+ // try to be ahead of the pack, I'm adding this extra value.
+ QWheelEvent qwe(qlocal, qglobal, deltaZ, buttons, keyMods, (Qt::Orientation)3);
+ qt_sendSpontaneousEvent(qwidget, &qwe);
+ wheelOK = qwe.isAccepted();
+ if (!wheelOK && QApplicationPrivate::focus_widget
+ && QApplicationPrivate::focus_widget != qwidget) {
+ QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal,
+ deltaZ, buttons, keyMods, (Qt::Orientation)3);
+ qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
+ wheelOK = qwe2.isAccepted();
+ }
+ }
+ if (!wheelOK) {
+ return [super scrollWheel:theEvent];
+ }
+}
+
+- (void)tabletProximity:(NSEvent *)tabletEvent
+{
+ qt_dispatchTabletProximityEvent(tabletEvent);
+}
+
+- (void)tabletPoint:(NSEvent *)tabletEvent
+{
+ if (!qt_mac_handleTabletEvent(self, tabletEvent))
+ [super tabletPoint:tabletEvent];
+}
+
+- (void)frameDidChange:(NSNotification *)note
+{
+ Q_UNUSED(note);
+ if (qwidget->isWindow())
+ return;
+ NSRect newFrame = [self frame];
+ QRect newGeo(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height);
+ bool moved = qwidget->testAttribute(Qt::WA_Moved);
+ bool resized = qwidget->testAttribute(Qt::WA_Resized);
+ qwidget->setGeometry(newGeo);
+ qwidget->setAttribute(Qt::WA_Moved, moved);
+ qwidget->setAttribute(Qt::WA_Resized, resized);
+ qwidgetprivate->syncCocoaMask();
+}
+
+- (BOOL)isEnabled
+{
+ if (!qwidget)
+ return [super isEnabled];
+ return [super isEnabled] && qwidget->isEnabled();
+}
+
+- (void)setEnabled:(BOOL)flag
+{
+ QMacCocoaAutoReleasePool pool;
+ [super setEnabled:flag];
+ if (qwidget->isEnabled() != flag)
+ qwidget->setEnabled(flag);
+}
+
++ (Class)cellClass
+{
+ return [NSActionCell class];
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ if (qwidget->isWindow())
+ return YES; // Always do it, so that windows can accept key press events.
+ return qwidget->focusPolicy() != Qt::NoFocus;
+}
+
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
+{
+ Q_UNUSED(isLocal);
+ return supportedActions;
+}
+
+- (void)setSupportedActions:(NSDragOperation)actions
+{
+ supportedActions = actions;
+}
+
+- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
+{
+ Q_UNUSED(anImage);
+ Q_UNUSED(aPoint);
+ qMacDnDParams()->performedAction = operation;
+}
+
+- (QWidget *)qt_qwidget
+{
+ return qwidget;
+}
+
+- (BOOL)qt_leftButtonIsRightButton
+{
+ return leftButtonIsRightButton;
+}
+
+- (void)qt_setLeftButtonIsRightButton:(BOOL)isSwapped
+{
+ leftButtonIsRightButton = isSwapped;
+}
+
++ (DnDParams*)currentMouseEvent
+{
+ return qMacDnDParams();
+}
+
+- (void)keyDown:(NSEvent *)theEvent
+{
+ sendKeyEvents = true;
+
+ QWidget *widgetToGetKey = qwidget;
+
+ QWidget *popup = qAppInstance()->activePopupWidget();
+ bool sendToPopup = false;
+ if (popup && popup != qwidget->window()) {
+ widgetToGetKey = popup->focusWidget() ? popup->focusWidget() : popup;
+ sendToPopup = true;
+ }
+
+ if (widgetToGetKey->testAttribute(Qt::WA_InputMethodEnabled)) {
+ [qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]];
+ }
+ if (sendKeyEvents && !composing) {
+ bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey);
+ if (!keyOK && !sendToPopup)
+ [super keyDown:theEvent];
+ }
+}
+
+
+- (void)keyUp:(NSEvent *)theEvent
+{
+ if (sendKeyEvents) {
+ bool keyOK = qt_dispatchKeyEvent(theEvent, qwidget);
+ if (!keyOK)
+ [super keyUp:theEvent];
+ }
+}
+
+// NSTextInput Protocol implementation
+
+- (void) insertText:(id)aString
+{
+ if (composing) {
+ // Send the commit string to the widget.
+ QString commitText;
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
+ commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string]));
+ } else {
+ commitText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString));
+ };
+ composing = false;
+ sendKeyEvents = false;
+ QInputMethodEvent e;
+ e.setCommitString(commitText);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+}
+
+- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange
+{
+ // Generate the QInputMethodEvent with preedit string and the attributes
+ // for rendering it. The attributes handled here are 'underline',
+ // 'underline color' and 'cursor position'.
+ sendKeyEvents = false;
+ composing = true;
+ QString qtText;
+ // Cursor position is retrived from the range.
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location, 1, QVariant());
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
+ qtText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string]));
+ composingLength = qtText.length();
+ int index = 0;
+ // Create attributes for individual sections of preedit text
+ while (index < composingLength) {
+ NSRange effectiveRange;
+ NSRange range = NSMakeRange(index, composingLength-index);
+ NSDictionary *attributes = [aString attributesAtIndex:index
+ longestEffectiveRange:&effectiveRange
+ inRange:range];
+ NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName];
+ if (underlineStyle) {
+ QColor clr (Qt::black);
+ NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName];
+ if (color) {
+ clr = colorFrom(color);
+ }
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ format.setUnderlineColor(clr);
+ attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ effectiveRange.location,
+ effectiveRange.length,
+ format);
+ }
+ index = effectiveRange.location + effectiveRange.length;
+ }
+ } else {
+ // No attributes specified, take only the preedit text.
+ qtText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString));
+ composingLength = qtText.length();
+ }
+ // Make sure that we have at least one text format.
+ if (attrs.size() <= 1) {
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ 0, composingLength, format);
+ }
+ QInputMethodEvent e(qtText, attrs);
+ qt_sendSpontaneousEvent(qwidget, &e);
+}
+
+- (void) unmarkText
+{
+ composing = false;
+}
+
+- (BOOL) hasMarkedText
+{
+ return (composing ? YES: NO);
+}
+
+- (void) doCommandBySelector:(SEL)aSelector
+{
+ Q_UNUSED(aSelector);
+}
+
+- (BOOL)isComposing
+{
+ return composing;
+}
+
+- (NSInteger) conversationIdentifier
+{
+ // Return a unique identifier fot this ime conversation
+ return (NSInteger)self;
+}
+
+- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange
+{
+ QString selectedText(qwidget->inputMethodQuery(Qt::ImCurrentSelection).toString());
+ if (!selectedText.isEmpty()) {
+ QCFString string(selectedText.mid(theRange.location, theRange.length));
+ const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
+ return [[[NSAttributedString alloc] initWithString:tmpString] autorelease];
+ } else {
+ return nil;
+ }
+}
+
+- (NSRange) markedRange
+{
+ NSRange range;
+ if (composing) {
+ range.location = 0;
+ range.length = composingLength;
+ } else {
+ range.location = NSNotFound;
+ range.length = 0;
+ }
+ return range;
+}
+
+- (NSRange) selectedRange
+{
+ NSRange selRange;
+ QString selectedText(qwidget->inputMethodQuery(Qt::ImCurrentSelection).toString());
+ if (!selectedText.isEmpty()) {
+ // Consider only the selected text.
+ selRange.location = 0;
+ selRange.length = selectedText.length();
+ } else {
+ // No selected text.
+ selRange.location = NSNotFound;
+ selRange.length = 0;
+ }
+ return selRange;
+
+}
+
+- (NSRect) firstRectForCharacterRange:(NSRange)theRange
+{
+ Q_UNUSED(theRange);
+ // The returned rect is always based on the internal cursor.
+ QRect mr(qwidget->inputMethodQuery(Qt::ImMicroFocus).toRect());
+ QPoint mp(qwidget->mapToGlobal(QPoint(mr.bottomLeft())));
+ NSRect rect ;
+ rect.origin.x = mp.x();
+ rect.origin.y = flipYCoordinate(mp.y());
+ rect.size.width = mr.width();
+ rect.size.height = mr.height();
+ return rect;
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
+{
+ // We dont support cursor movements using mouse while composing.
+ Q_UNUSED(thePoint);
+ return NSNotFound;
+}
+
+- (NSArray*) validAttributesForMarkedText
+{
+ if (!qwidget->testAttribute(Qt::WA_InputMethodEnabled))
+ return nil; // Not sure if that's correct, but it's saves a malloc.
+
+ // Support only underline color/style.
+ return [NSArray arrayWithObjects:NSUnderlineColorAttributeName,
+ NSUnderlineStyleAttributeName, nil];
+}
+@end
+
+QT_BEGIN_NAMESPACE
+void QMacInputContext::reset()
+{
+ QWidget *w = QInputContext::focusWidget();
+ if (w) {
+ NSView *view = qt_mac_nativeview_for(w);
+ if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QCocoaView) *qc = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view);
+ NSInputManager *currentIManager = [NSInputManager currentInputManager];
+ if (currentIManager) {
+ [currentIManager markedTextAbandoned:view];
+ [qc unmarkText];
+ }
+ }
+ }
+}
+
+bool QMacInputContext::isComposing() const
+{
+ QWidget *w = QInputContext::focusWidget();
+ if (w) {
+ NSView *view = qt_mac_nativeview_for(w);
+ if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
+ return [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) isComposing];
+ }
+ }
+ return false;
+}
+
+extern bool qt_mac_in_drag;
+void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm);
+static const int default_pm_hotx = -2;
+static const int default_pm_hoty = -16;
+static const char* default_pm[] = {
+ "13 9 3 1",
+ ". c None",
+ " c #000000",
+ "X c #FFFFFF",
+ "X X X X X X X",
+ " X X X X X X ",
+ "X ......... X",
+ " X.........X ",
+ "X ......... X",
+ " X.........X ",
+ "X ......... X",
+ " X X X X X X ",
+ "X X X X X X X",
+};
+
+Qt::DropAction QDragManager::drag(QDrag *o)
+{
+ if(qt_mac_in_drag) { //just make sure..
+ qWarning("Qt: Internal error: WH0A, unexpected condition reached");
+ return Qt::IgnoreAction;
+ }
+ if(object == o)
+ return Qt::IgnoreAction;
+ /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button
+ so we just bail early to prevent it */
+ if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary))
+ return Qt::IgnoreAction;
+
+ if(object) {
+ dragPrivate()->source->removeEventFilter(this);
+ cancel();
+ beingCancelled = false;
+ }
+
+ object = o;
+ dragPrivate()->target = 0;
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart);
+#endif
+
+ // setup the data
+ QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND);
+ dragPrivate()->data->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray());
+ dragBoard.setMimeData(dragPrivate()->data);
+
+ // create the image
+ QPoint hotspot;
+ QPixmap pix = dragPrivate()->pixmap;
+ if(pix.isNull()) {
+ if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) {
+ // get the string
+ QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text()
+ : dragPrivate()->data->urls().first().toString();
+ if(s.length() > 26)
+ s = s.left(23) + QChar(0x2026);
+ if(!s.isEmpty()) {
+ // draw it
+ QFont f(qApp->font());
+ f.setPointSize(12);
+ QFontMetrics fm(f);
+ QPixmap tmp(fm.width(s), fm.height());
+ if(!tmp.isNull()) {
+ QPainter p(&tmp);
+ p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0);
+ p.setPen(Qt::color1);
+ p.setFont(f);
+ p.drawText(0, fm.ascent(), s);
+ // save it
+ pix = tmp;
+ hotspot = QPoint(tmp.width() / 2, tmp.height() / 2);
+ }
+ }
+ } else {
+ pix = QPixmap(default_pm);
+ hotspot = QPoint(default_pm_hotx, default_pm_hoty);
+ }
+ } else {
+ hotspot = dragPrivate()->hotspot;
+ }
+ // convert the image to NSImage.
+ NSImage *image = (NSImage *)qt_mac_create_nsimage(pix);
+ [image retain];
+ DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
+ // save supported actions
+ [dndParams->view setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)];
+ NSPoint imageLoc = {dndParams->localPoint.x - hotspot.x(),
+ dndParams->localPoint.y + pix.height() - hotspot.y()};
+ NSSize mouseOffset = {0.0, 0.0};
+ NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ NSPoint windowPoint = [dndParams->theEvent locationInWindow];
+ // do the drag
+ [dndParams->view retain];
+ [dndParams->view dragImage:image
+ at:imageLoc
+ offset:mouseOffset
+ event:dndParams->theEvent
+ pasteboard:pboard
+ source:dndParams->view
+ slideBack:YES];
+ [dndParams->view release];
+ [image release];
+ object = 0;
+ Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams->performedAction));
+ // do post drag processing, if required.
+ if(performedAction != Qt::IgnoreAction) {
+ // check if the receiver points us to a file location.
+ // if so, we need to do the file copy/move ourselves.
+ QCFType<CFURLRef> pasteLocation = 0;
+ PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation);
+ if (pasteLocation) {
+ QList<QUrl> urls = o->mimeData()->urls();
+ for (int i = 0; i < urls.size(); ++i) {
+ QUrl fromUrl = urls.at(i);
+ QString filename = QFileInfo(fromUrl.path()).fileName();
+ QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename);
+ if (performedAction == Qt::MoveAction)
+ QFile::rename(fromUrl.path(), toUrl.path());
+ else if (performedAction == Qt::CopyAction)
+ QFile::copy(fromUrl.path(), toUrl.path());
+ }
+ }
+ }
+ return performedAction;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_MAC_USE_COCOA
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
new file mode 100644
index 0000000000..9de94d5fc7
--- /dev/null
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qevent.h>
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+
+@class QT_MANGLE_NAMESPACE(QCocoaView);
+QT_FORWARD_DECLARE_CLASS(QWidgetPrivate);
+QT_FORWARD_DECLARE_CLASS(QWidget);
+QT_FORWARD_DECLARE_CLASS(QEvent);
+QT_FORWARD_DECLARE_CLASS(QCocoaDropData);
+
+QT_BEGIN_NAMESPACE
+struct DnDParams
+{
+ QT_MANGLE_NAMESPACE(QCocoaView) *view;
+ NSEvent *theEvent;
+ NSPoint localPoint;
+ NSDragOperation performedAction;
+};
+
+QT_END_NAMESPACE
+
+QT_FORWARD_DECLARE_STRUCT(DnDParams);
+
+Q_GUI_EXPORT
+@interface QT_MANGLE_NAMESPACE(QCocoaView) : NSControl <NSTextInput> {
+ QWidget *qwidget;
+ QWidgetPrivate *qwidgetprivate;
+ bool leftButtonIsRightButton;
+ QCocoaDropData *dropData;
+ NSDragOperation supportedActions;
+ bool composing;
+ int composingLength;
+ bool sendKeyEvents;
+}
+- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate;
+- (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate;
+- (void)frameDidChange:(NSNotification *)note;
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
+- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender;
+- (void)draggingExited:(id < NSDraggingInfo >)sender;
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
+- (void)registerDragTypes:(bool)accept;
+- (void)removeDropData;
+- (void)addDropData:(id <NSDraggingInfo>)sender;
+- (void)setSupportedActions:(NSDragOperation)actions;
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
+- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
+- (BOOL)isComposing;
+- (QWidget *)qt_qwidget;
+- (BOOL)qt_leftButtonIsRightButton;
+- (void)qt_setLeftButtonIsRightButton:(BOOL)isSwapped;
+- (NSView *)viewUnderTransparentForMouseView:(NSView *)mouseView widget:(QWidget *)widgetToGetMouse
+ withWindowPoint:(NSPoint)windowPoint;
++ (DnDParams*)currentMouseEvent;
+
+@end
+#endif
diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm
new file mode 100644
index 0000000000..6b304440a7
--- /dev/null
+++ b/src/gui/kernel/qcocoawindow_mac.mm
@@ -0,0 +1,185 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#import <private/qcocoawindow_mac_p.h>
+#import <private/qcocoawindowdelegate_mac_p.h>
+#import <private/qcocoaview_mac_p.h>
+#import <private/qt_cocoa_helpers_mac_p.h>
+#import <private/qcocoawindowcustomthemeframe_mac_p.h>
+
+#include <QtGui/QWidget>
+
+QT_FORWARD_DECLARE_CLASS(QWidget);
+QT_USE_NAMESPACE
+
+extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
+
+@implementation NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration))
+
+- (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget*)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask;
+{
+ self = [self initWithContentRect:rect styleMask:mask backing:NSBackingStoreBuffered defer:YES];
+ if (self) {
+ [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] becomeDelegteForWindow:self widget:widget];
+ [self setReleasedWhenClosed:NO];
+ }
+ return self;
+}
+
+- (QWidget *)QT_MANGLE_NAMESPACE(qt_qwidget)
+{
+ QWidget *widget = 0;
+ if ([self delegate] == [QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate])
+ widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
+ return widget;
+}
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaWindow)
+
+- (BOOL)canBecomeKeyWindow
+{
+ return YES;
+}
+
+/*
+ The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever
+ get hit. We automatically say we can be first responder if we are a window.
+ So, the handling should get handled by the view. This is here more as a
+ last resort (i.e., this is code that can potentially be removed).
+ */
+
+- (void)keyDown:(NSEvent *)theEvent
+{
+ bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
+ if (!keyOK)
+ [super keyDown:theEvent];
+}
+
+- (void)keyUp:(NSEvent *)theEvent
+{
+ bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
+ if (!keyOK)
+ [super keyUp:theEvent];
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+ qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
+ [super flagsChanged:theEvent];
+}
+
+
+- (void)tabletProximity:(NSEvent *)tabletEvent
+{
+ qt_dispatchTabletProximityEvent(tabletEvent);
+}
+
+- (void)sendEvent:(NSEvent *)event
+{
+ [self retain];
+
+ QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
+ QCocoaView *view = static_cast<QCocoaView *>(qt_mac_nativeview_for(widget));
+ Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]);
+
+ // sometimes need to redirect mouse events to the popup.
+ QWidget *popup = qAppInstance()->activePopupWidget();
+ if (popup && popup != widget) {
+ switch([event type])
+ {
+ case NSLeftMouseDown:
+ qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton);
+ // Don't call super here. This prevents us from getting the mouseUp event,
+ // which we need to send even if the mouseDown event was not accepted.
+ // (this is standard Qt behavior.)
+ break;
+ case NSRightMouseDown:
+ case NSOtherMouseDown:
+ if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton))
+ [super sendEvent:event];
+ break;
+ case NSLeftMouseUp:
+ case NSRightMouseUp:
+ case NSOtherMouseUp:
+ if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton))
+ [super sendEvent:event];
+ break;
+ case NSMouseMoved:
+ qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton);
+ break;
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view;
+ [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event;
+ if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton))
+ [super sendEvent:event];
+ break;
+ default:
+ [super sendEvent:event];
+ break;
+ }
+ } else {
+ [super sendEvent:event];
+ }
+ qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton);
+
+
+ [self release];
+}
+
++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask
+{
+ if (styleMask & QtMacCustomizeWindow)
+ return [QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) class];
+ return [super frameViewClassForStyleMask:styleMask];
+}
+
+@end
+
+#endif
diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h
new file mode 100644
index 0000000000..4f207ac411
--- /dev/null
+++ b/src/gui/kernel/qcocoawindow_mac_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmacdefines_mac.h"
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+
+enum { QtMacCustomizeWindow = 1 << 21 }; // This will one day be run over by
+
+QT_FORWARD_DECLARE_CLASS(QWidget);
+
+@interface NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration))
+- (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget *)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask;
+- (QWidget *)QT_MANGLE_NAMESPACE(qt_qwidget);
+@end
+
+@interface QT_MANGLE_NAMESPACE(QCocoaWindow) : NSWindow {
+ bool leftButtonIsRightButton;
+}
+
++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
+@end
+#endif
diff --git a/src/gui/kernel/qcocoawindowcustomthemeframe_mac.mm b/src/gui/kernel/qcocoawindowcustomthemeframe_mac.mm
new file mode 100644
index 0000000000..98625e47e4
--- /dev/null
+++ b/src/gui/kernel/qcocoawindowcustomthemeframe_mac.mm
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmacdefines_mac.h"
+
+#ifdef QT_MAC_USE_COCOA
+
+#import "private/qcocoawindowcustomthemeframe_mac_p.h"
+#import "private/qcocoawindow_mac_p.h"
+#include "private/qt_cocoa_helpers_mac_p.h"
+#include "qwidget.h"
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame)
+
+- (void)_updateButtons
+{
+ [super _updateButtons];
+ NSWindow *window = [self window];
+ qt_syncCocoaTitleBarButtons(window, [window QT_MANGLE_NAMESPACE(qt_qwidget)]);
+}
+
+@end
+
+#endif
diff --git a/src/gui/kernel/qcocoawindowcustomthemeframe_mac_p.h b/src/gui/kernel/qcocoawindowcustomthemeframe_mac_p.h
new file mode 100644
index 0000000000..c30b67acd0
--- /dev/null
+++ b/src/gui/kernel/qcocoawindowcustomthemeframe_mac_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+#import <Cocoa/Cocoa.h>
+#include "qmacdefines_mac.h"
+#import "qnsthemeframe_mac_p.h"
+
+@interface QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) : NSThemeFrame
+{
+}
+
+@end
diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm
new file mode 100644
index 0000000000..848017915f
--- /dev/null
+++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm
@@ -0,0 +1,349 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+#import "private/qcocoawindowdelegate_mac_p.h"
+#ifdef QT_MAC_USE_COCOA
+#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <qevent.h>
+#include <qlayout.h>
+#include <qcoreapplication.h>
+#include <qmenubar.h>
+
+QT_BEGIN_NAMESPACE
+extern QWidgetData *qt_qwidget_data(QWidget *); // qwidget.cpp
+extern void onApplicationWindowChangedActivation(QWidget *, bool); //qapplication_mac.mm
+extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+static QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) *sharedCocoaWindowDelegate = nil;
+
+// This is a singleton, but unlike most Cocoa singletons, it lives in a library and could be
+// pontentially loaded and unloaded. This means we should at least attempt to do the
+// memory management correctly.
+
+static void cleanupCocoaWindowDelegate()
+{
+ [sharedCocoaWindowDelegate release];
+}
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil) {
+ m_windowHash = new QHash<NSWindow *, QWidget *>();
+ m_drawerHash = new QHash<NSDrawer *, QWidget *>();
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ sharedCocoaWindowDelegate = nil;
+ QHash<NSWindow *, QWidget *>::const_iterator windowIt = m_windowHash->constBegin();
+ while (windowIt != m_windowHash->constEnd()) {
+ [windowIt.key() setDelegate:nil];
+ ++windowIt;
+ }
+ delete m_windowHash;
+ QHash<NSDrawer *, QWidget *>::const_iterator drawerIt = m_drawerHash->constBegin();
+ while (drawerIt != m_drawerHash->constEnd()) {
+ [drawerIt.key() setDelegate:nil];
+ ++drawerIt;
+ }
+ delete m_drawerHash;
+ [super dealloc];
+}
+
++ (id)allocWithZone:(NSZone *)zone
+{
+ @synchronized(self) {
+ if (sharedCocoaWindowDelegate == nil) {
+ sharedCocoaWindowDelegate = [super allocWithZone:zone];
+ return sharedCocoaWindowDelegate;
+ qAddPostRoutine(cleanupCocoaWindowDelegate);
+ }
+ }
+ return nil;
+}
+
++ (QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)*)sharedDelegate
+{
+ @synchronized(self) {
+ if (sharedCocoaWindowDelegate == nil)
+ [[self alloc] init];
+ }
+ return [[sharedCocoaWindowDelegate retain] autorelease];
+}
+
+-(void)syncSizeForWidget:(QWidget *)qwidget toSize:(const QSize &)newSize fromSize:(const QSize &)oldSize
+{
+ qt_qwidget_data(qwidget)->crect.setSize(newSize);
+ // ### static contents optimization needs to go here
+ const OSViewRef view = qt_mac_nativeview_for(qwidget);
+ [view setFrameSize:NSMakeSize(newSize.width(), newSize.height())];
+ if (!qwidget->isVisible()) {
+ qwidget->setAttribute(Qt::WA_PendingResizeEvent, true);
+ } else {
+ QResizeEvent qre(newSize, oldSize);
+ qt_sendSpontaneousEvent(qwidget, &qre);
+ }
+}
+
+- (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window;
+{
+ if (!window)
+ return; // Nothing to do.
+ QWidgetData *widgetData = qt_qwidget_data(qwidget);
+ if ((widgetData->window_state & Qt::WindowMaximized) && ![window isZoomed]) {
+ widgetData->window_state &= ~Qt::WindowMaximized;
+ QWindowStateChangeEvent e(Qt::WindowState(widgetData->window_state | Qt::WindowMaximized));
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+}
+
+- (NSSize)closestAcceptableSizeForWidget:(QWidget *)qwidget window:(NSWindow *)window
+ withNewSize:(NSSize)proposedSize
+{
+ [self dumpMaximizedStateforWidget:qwidget window:window];
+ QSize newSize = QLayout::closestAcceptableSize(qwidget,
+ QSize(proposedSize.width, proposedSize.height));
+ return [NSWindow frameRectForContentRect:
+ NSMakeRect(0., 0., newSize.width(), newSize.height())
+ styleMask:[window styleMask]].size;
+}
+
+- (NSSize)windowWillResize:(NSWindow *)windowToResize toSize:(NSSize)proposedFrameSize
+{
+ QWidget *qwidget = m_windowHash->value(windowToResize);
+ return [self closestAcceptableSizeForWidget:qwidget window:windowToResize
+ withNewSize:[NSWindow contentRectForFrameRect:
+ NSMakeRect(0, 0,
+ proposedFrameSize.width,
+ proposedFrameSize.height)
+ styleMask:[windowToResize styleMask]].size];
+}
+
+- (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize
+{
+ QWidget *qwidget = m_drawerHash->value(sender);
+ return [self closestAcceptableSizeForWidget:qwidget window:nil withNewSize:contentSize];
+}
+
+-(void)windowDidMiniaturize:(NSNotification*)notification
+{
+ QWidget *qwidget = m_windowHash->value([notification object]);
+ if (!qwidget->isMinimized()) {
+ QWidgetData *widgetData = qt_qwidget_data(qwidget);
+ widgetData->window_state = widgetData->window_state | Qt::WindowMinimized;
+ QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state & ~Qt::WindowMinimized));
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+ // Send hide to match Qt on X11 and Windows
+ QEvent e(QEvent::Hide);
+ qt_sendSpontaneousEvent(qwidget, &e);
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+ NSWindow *window = [notification object];
+ QWidget *qwidget = m_windowHash->value(window);
+ // Just here to handle the is zoomed method.
+ QWidgetData *widgetData = qt_qwidget_data(qwidget);
+ if (!(qwidget->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) && [window isZoomed]) {
+ widgetData->window_state = widgetData->window_state | Qt::WindowMaximized;
+ QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state
+ & ~Qt::WindowMaximized));
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+ [self checkForMove:[window frame] forWidget:qwidget];
+ NSRect rect = [[window contentView] frame];
+ const QSize newSize(rect.size.width, rect.size.height);
+ const QSize &oldSize = widgetData->crect.size();
+ if (newSize != oldSize) {
+ QWidgetPrivate::qt_mac_update_sizer(qwidget);
+ [self syncSizeForWidget:qwidget toSize:newSize fromSize:oldSize];
+ }
+}
+
+- (void)checkForMove:(const NSRect &)newRect forWidget:(QWidget *)qwidget
+{
+ // newRect's origin is bottom left.
+ QPoint qtPoint = flipPoint(NSMakePoint(newRect.origin.x,
+ newRect.origin.y + newRect.size.height)).toPoint();
+ const QRect &oldRect = qwidget->frameGeometry();
+ if (qtPoint.x() != oldRect.x() || qtPoint.y() != oldRect.y()) {
+ QWidgetData *widgetData = qt_qwidget_data(qwidget);
+ QRect oldCRect = widgetData->crect;
+ QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget);
+ const QRect &fStrut = widgetPrivate->frameStrut();
+ widgetData->crect.moveTo(qtPoint.x() + fStrut.left(), qtPoint.y() + fStrut.top());
+ if (!qwidget->isVisible()) {
+ qwidget->setAttribute(Qt::WA_PendingMoveEvent, true);
+ } else {
+ QMoveEvent qme(qtPoint, oldRect.topLeft());
+ qt_sendSpontaneousEvent(qwidget, &qme);
+ }
+ }
+}
+
+- (void)windowDidMove:(NSNotification *)notification
+{
+ [self windowDidResize:notification];
+}
+
+-(BOOL)windowShouldClose:(id)windowThatWantsToClose
+{
+ QWidget *qwidget = m_windowHash->value(windowThatWantsToClose);
+ QScopedLoopLevelCounter counter(qt_widget_private(qwidget)->threadData);
+ return qt_widget_private(qwidget)->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+}
+
+-(void)windowDidDeminiaturize:(NSNotification *)notification
+{
+ QWidget *qwidget = m_windowHash->value([notification object]);
+ QWidgetData *widgetData = qt_qwidget_data(qwidget);
+ Qt::WindowStates currState = Qt::WindowStates(widgetData->window_state);
+ Qt::WindowStates newState = currState;
+ if (currState & Qt::WindowMinimized)
+ newState &= ~Qt::WindowMinimized;
+ if (!(currState & Qt::WindowActive))
+ newState |= Qt::WindowActive;
+ if (newState != currState) {
+ widgetData->window_state = newState;
+ QWindowStateChangeEvent e(currState);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+ QShowEvent qse;
+ qt_sendSpontaneousEvent(qwidget, &qse);
+}
+
+-(void)windowDidBecomeMain:(NSNotification*)notification
+{
+ QWidget *qwidget = m_windowHash->value([notification object]);
+ Q_ASSERT(qwidget);
+ if (qwidget->isActiveWindow())
+ return; // Widget is already active, no need to go through re-activation.
+
+ onApplicationWindowChangedActivation(qwidget, true);
+}
+
+-(void)windowDidResignMain:(NSNotification*)notification
+{
+ QWidget *qwidget = m_windowHash->value([notification object]);
+ Q_ASSERT(qwidget);
+ onApplicationWindowChangedActivation(qwidget, false);
+}
+
+// These are the same as main, but they are probably better to keep separate since there is a
+// tiny difference between main and key windows.
+-(void)windowDidBecomeKey:(NSNotification*)notification
+{
+ QWidget *qwidget = m_windowHash->value([notification object]);
+ Q_ASSERT(qwidget);
+ if (qwidget->isActiveWindow())
+ return; // Widget is already active, no need to go through re-activation
+
+
+ onApplicationWindowChangedActivation(qwidget, true);
+}
+
+-(void)windowDidResignKey:(NSNotification*)notification
+{
+ QWidget *qwidget = m_windowHash->value([notification object]);
+ Q_ASSERT(qwidget);
+ onApplicationWindowChangedActivation(qwidget, false);
+}
+
+-(QWidget *)qt_qwidgetForWindow:(NSWindow *)window
+{
+ return m_windowHash->value(window);
+}
+
+- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame
+{
+ NSRect frameToReturn = defaultFrame;
+ QWidget *qwidget = m_windowHash->value(window);
+ QSizeF size = qwidget->maximumSize();
+ frameToReturn.size.width = qMin<CGFloat>(frameToReturn.size.width, size.width());
+ frameToReturn.size.height = qMin<CGFloat>(frameToReturn.size.height, size.height());
+ return frameToReturn;
+}
+
+- (void)becomeDelegteForWindow:(NSWindow *)window widget:(QWidget *)widget
+{
+ m_windowHash->insert(window, widget);
+ [window setDelegate:self];
+}
+
+- (void)resignDelegateForWindow:(NSWindow *)window
+{
+ [window setDelegate:nil];
+ m_windowHash->remove(window);
+}
+
+- (void)becomeDelegateForDrawer:(NSDrawer *)drawer widget:(QWidget *)widget
+{
+ m_drawerHash->insert(drawer, widget);
+ [drawer setDelegate:self];
+ NSWindow *window = [[drawer contentView] window];
+ [self becomeDelegteForWindow:window widget:widget];
+}
+
+- (void)resignDelegateForDrawer:(NSDrawer *)drawer
+{
+ QWidget *widget = m_drawerHash->value(drawer);
+ [drawer setDelegate:nil];
+ if (widget)
+ [self resignDelegateForWindow:[[drawer contentView] window]];
+ m_drawerHash->remove(drawer);
+}
+
+@end
+#endif// QT_MAC_USE_COCOA
diff --git a/src/gui/kernel/qcocoawindowdelegate_mac_p.h b/src/gui/kernel/qcocoawindowdelegate_mac_p.h
new file mode 100644
index 0000000000..7456ff75dc
--- /dev/null
+++ b/src/gui/kernel/qcocoawindowdelegate_mac_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmacdefines_mac.h"
+
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+
+QT_BEGIN_NAMESPACE
+template <class Key, class T> class QHash;
+QT_END_NAMESPACE
+using QT_PREPEND_NAMESPACE(QHash);
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_FORWARD_DECLARE_CLASS(QSize)
+QT_FORWARD_DECLARE_CLASS(QWidgetData)
+
+@interface QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) : NSObject {
+ QHash<NSWindow *, QWidget *> *m_windowHash;
+ QHash<NSDrawer *, QWidget *> *m_drawerHash;
+}
++ (QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)*)sharedDelegate;
+- (void)becomeDelegteForWindow:(NSWindow *)window widget:(QWidget *)widget;
+- (void)resignDelegateForWindow:(NSWindow *)window;
+- (void)becomeDelegateForDrawer:(NSDrawer *)drawer widget:(QWidget *)widget;
+- (void)resignDelegateForDrawer:(NSDrawer *)drawer;
+- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
+- (void)windowDidMiniaturize:(NSNotification*)notification;
+- (void)windowDidResize:(NSNotification *)notification;
+- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame;
+- (void)windowDidMove:(NSNotification *)notification;
+- (BOOL)windowShouldClose:(id)window;
+- (void)windowDidDeminiaturize:(NSNotification *)notification;
+- (void)windowDidBecomeMain:(NSNotification*)notification;
+- (void)windowDidResignMain:(NSNotification*)notification;
+- (void)windowDidBecomeKey:(NSNotification*)notification;
+- (void)windowDidResignKey:(NSNotification*)notification;
+- (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window;
+- (void)syncSizeForWidget:(QWidget *)qwidget
+ toSize:(const QSize &)newSize
+ fromSize:(const QSize &)oldSize;
+- (NSSize)closestAcceptableSizeForWidget:(QWidget *)qwidget
+ window:(NSWindow *)window withNewSize:(NSSize)proposedSize;
+- (QWidget *)qt_qwidgetForWindow:(NSWindow *)window;
+- (void)checkForMove:(const NSRect &)newRect forWidget:(QWidget *)qwidget;
+@end
+#endif
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
new file mode 100644
index 0000000000..ed7e020d23
--- /dev/null
+++ b/src/gui/kernel/qcursor.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcursor.h"
+
+#ifndef QT_NO_CURSOR
+
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qdatastream.h>
+#include <qvariant.h>
+#include <private/qcursor_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCursor
+
+ \brief The QCursor class provides a mouse cursor with an arbitrary
+ shape.
+
+ \ingroup appearance
+ \ingroup shared
+ \mainclass
+
+ This class is mainly used to create mouse cursors that are
+ associated with particular widgets and to get and set the position
+ of the mouse cursor.
+
+ Qt has a number of standard cursor shapes, but you can also make
+ custom cursor shapes based on a QBitmap, a mask and a hotspot.
+
+ To associate a cursor with a widget, use QWidget::setCursor(). To
+ associate a cursor with all widgets (normally for a short period
+ of time), use QApplication::setOverrideCursor().
+
+ To set a cursor shape use QCursor::setShape() or use the QCursor
+ constructor which takes the shape as argument, or you can use one
+ of the predefined cursors defined in the \l Qt::CursorShape enum.
+
+ If you want to create a cursor with your own bitmap, either use
+ the QCursor constructor which takes a bitmap and a mask or the
+ constructor which takes a pixmap as arguments.
+
+ To set or get the position of the mouse cursor use the static
+ methods QCursor::pos() and QCursor::setPos().
+
+ \bold{Note:} It is possible to create a QCursor before
+ QApplication, but it is not useful except as a place-holder for a
+ real QCursor created after QApplication. Attempting to use a
+ QCursor that was created before QApplication will result in a
+ crash.
+
+ \section1 A Note for X11 Users
+
+ On X11, Qt supports the \link
+ http://www.xfree86.org/4.3.0/Xcursor.3.html Xcursor\endlink
+ library, which allows for full color icon themes. The table below
+ shows the cursor name used for each Qt::CursorShape value. If a
+ cursor cannot be found using the name shown below, a standard X11
+ cursor will be used instead. Note: X11 does not provide
+ appropriate cursors for all possible Qt::CursorShape values. It
+ is possible that some cursors will be taken from the Xcursor
+ theme, while others will use an internal bitmap cursor.
+
+ \table
+ \header \o Shape \o Qt::CursorShape Value \o Cursor Name
+ \o Shape \o Qt::CursorShape Value \o Cursor Name
+ \row \o \inlineimage cursor-arrow.png
+ \o Qt::ArrowCursor \o \c left_ptr
+ \o \inlineimage cursor-sizev.png
+ \o Qt::SizeVerCursor \o \c size_ver
+ \row \o \inlineimage cursor-uparrow.png
+ \o Qt::UpArrowCursor \o \c up_arrow
+ \o \inlineimage cursor-sizeh.png
+ \o Qt::SizeHorCursor \o \c size_hor
+ \row \o \inlineimage cursor-cross.png
+ \o Qt::CrossCursor \o \c cross
+ \o \inlineimage cursor-sizeb.png
+ \o Qt::SizeBDiagCursor \o \c size_bdiag
+ \row \o \inlineimage cursor-ibeam.png
+ \o Qt::IBeamCursor \o \c ibeam
+ \o \inlineimage cursor-sizef.png
+ \o Qt::SizeFDiagCursor \o \c size_fdiag
+ \row \o \inlineimage cursor-wait.png
+ \o Qt::WaitCursor \o \c wait
+ \o \inlineimage cursor-sizeall.png
+ \o Qt::SizeAllCursor \o \c size_all
+ \row \o \inlineimage cursor-busy.png
+ \o Qt::BusyCursor \o \c left_ptr_watch
+ \o \inlineimage cursor-hsplit.png
+ \o Qt::SplitVCursor \o \c split_v
+ \row \o \inlineimage cursor-forbidden.png
+ \o Qt::ForbiddenCursor \o \c forbidden
+ \o \inlineimage cursor-vsplit.png
+ \o Qt::SplitHCursor \o \c split_h
+ \row \o \inlineimage cursor-hand.png
+ \o Qt::PointingHandCursor \o \c pointing_hand
+ \o \inlineimage cursor-openhand.png
+ \o Qt::OpenHandCursor \o \c openhand
+ \row \o \inlineimage cursor-whatsthis.png
+ \o Qt::WhatsThisCursor \o \c whats_this
+ \o \inlineimage cursor-closedhand.png
+ \o Qt::ClosedHandCursor \o \c closedhand
+ \endtable
+
+ \sa QWidget, {fowler}{GUI Design Handbook: Cursors}
+*/
+
+/*!
+ \fn HCURSOR_or_HANDLE QCursor::handle() const
+
+ Returns a platform-specific cursor handle. The \c
+ HCURSOR_or_HANDLE type is \c HCURSOR on Windows and Qt::HANDLE on X11
+ and Mac OS X. On \l{Qt for Embedded Linux} it is an integer.
+
+ \warning Using the value returned by this function is not
+ portable.
+*/
+
+/*!
+ \fn QCursor::QCursor(HCURSOR cursor)
+
+ Constructs a Qt cursor from the given Windows \a cursor.
+
+ \warning This function is only available on Windows.
+
+ \sa handle()
+*/
+
+/*!
+ \fn QCursor::QCursor(Qt::HANDLE handle)
+
+ Constructs a Qt cursor from the given \a handle.
+
+ \warning This function is only available on X11.
+
+ \sa handle()
+*/
+
+/*!
+ \fn QPoint QCursor::pos()
+
+ Returns the position of the cursor (hot spot) in global screen
+ coordinates.
+
+ You can call QWidget::mapFromGlobal() to translate it to widget
+ coordinates.
+
+ \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
+*/
+
+/*!
+ \fn void QCursor::setPos(int x, int y)
+
+ Moves the cursor (hot spot) to the global screen position (\a x,
+ \a y).
+
+ You can call QWidget::mapToGlobal() to translate widget
+ coordinates to global screen coordinates.
+
+ \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
+*/
+
+/*!
+ \fn void QCursor::setPos (const QPoint &p)
+
+ \overload
+
+ Moves the cursor (hot spot) to the global screen position at point
+ \a p.
+*/
+
+/*****************************************************************************
+ QCursor stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
+ \relates QCursor
+
+ Writes the \a cursor to the \a stream.
+
+ \sa {Format of the QDataStream operators}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QCursor &c)
+{
+ s << (qint16)c.shape(); // write shape id to stream
+ if (c.shape() == Qt::BitmapCursor) { // bitmap cursor
+ bool isPixmap = false;
+ if (s.version() >= 7) {
+ isPixmap = !c.pixmap().isNull();
+ s << isPixmap;
+ }
+ if (isPixmap)
+ s << c.pixmap();
+ else
+ s << *c.bitmap() << *c.mask();
+ s << c.hotSpot();
+ }
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QCursor &cursor)
+ \relates QCursor
+
+ Reads the \a cursor from the \a stream.
+
+ \sa {Format of the QDataStream operators}
+*/
+
+QDataStream &operator>>(QDataStream &s, QCursor &c)
+{
+ qint16 shape;
+ s >> shape; // read shape id from stream
+ if (shape == Qt::BitmapCursor) { // read bitmap cursor
+ bool isPixmap = false;
+ if (s.version() >= 7)
+ s >> isPixmap;
+ if (isPixmap) {
+ QPixmap pm;
+ QPoint hot;
+ s >> pm >> hot;
+ c = QCursor(pm, hot.x(), hot.y());
+ } else {
+ QBitmap bm, bmm;
+ QPoint hot;
+ s >> bm >> bmm >> hot;
+ c = QCursor(bm, bmm, hot.x(), hot.y());
+ }
+ } else {
+ c.setShape((Qt::CursorShape)shape); // create cursor with shape
+ }
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+
+/*!
+ Constructs a custom pixmap cursor.
+
+ \a pixmap is the image. It is usual to give it a mask (set using
+ QPixmap::setMask()). \a hotX and \a hotY define the cursor's hot
+ spot.
+
+ If \a hotX is negative, it is set to the \c{pixmap().width()/2}.
+ If \a hotY is negative, it is set to the \c{pixmap().height()/2}.
+
+ Valid cursor sizes depend on the display hardware (or the
+ underlying window system). We recommend using 32 x 32 cursors,
+ because this size is supported on all platforms. Some platforms
+ also support 16 x 16, 48 x 48, and 64 x 64 cursors.
+
+ \note On Windows CE, the cursor size is fixed. If the pixmap
+ is bigger than the system size, it will be scaled.
+
+ \sa QPixmap::QPixmap(), QPixmap::setMask()
+*/
+
+QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
+ : d(0)
+{
+ QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
+ QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither);
+ QBitmap bmm = pixmap.mask();
+ if (!bmm.isNull()) {
+ QBitmap nullBm;
+ bm.setMask(nullBm);
+ }
+ else if (!pixmap.mask().isNull()) {
+ QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
+ bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither);
+ }
+ else {
+ bmm = QBitmap(bm.size());
+ bmm.fill(Qt::color1);
+ }
+
+ d = QCursorData::setBitmap(bm, bmm, hotX, hotY);
+ d->pixmap = pixmap;
+}
+
+
+
+/*!
+ Constructs a custom bitmap cursor.
+
+ \a bitmap and
+ \a mask make up the bitmap.
+ \a hotX and
+ \a hotY define the cursor's hot spot.
+
+ If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
+ If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
+
+ The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
+ \list
+ \o B=1 and M=1 gives black.
+ \o B=0 and M=1 gives white.
+ \o B=0 and M=0 gives transparent.
+ \o B=1 and M=0 gives an XOR'd result.
+ \endlist
+
+ Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
+ draw 1-pixels in the bitmaps.
+
+ Valid cursor sizes depend on the display hardware (or the
+ underlying window system). We recommend using 32 x 32 cursors,
+ because this size is supported on all platforms. Some platforms
+ also support 16 x 16, 48 x 48, and 64 x 64 cursors.
+
+ \note On Windows CE, the cursor size is fixed. If the pixmap
+ is bigger than the system size, it will be scaled.
+
+ \sa QBitmap::QBitmap(), QBitmap::setMask()
+*/
+
+QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+ : d(0)
+{
+ d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
+}
+
+QCursorData *qt_cursorTable[Qt::LastCursor + 1];
+bool QCursorData::initialized = false;
+
+/*! \internal */
+void QCursorData::cleanup()
+{
+ if(!QCursorData::initialized)
+ return;
+
+ for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
+ delete qt_cursorTable[shape];
+ qt_cursorTable[shape] = 0;
+ }
+ QCursorData::initialized = false;
+}
+
+/*! \internal */
+void QCursorData::initialize()
+{
+ if (QCursorData::initialized)
+ return;
+#ifdef Q_WS_MAC
+ // DRSWAT - Not Needed Cocoa or Carbon
+ //InitCursor();
+#endif
+ for (int shape = 0; shape <= Qt::LastCursor; ++shape)
+ qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
+ QCursorData::initialized = true;
+}
+
+/*!
+ Constructs a cursor with the default arrow shape.
+*/
+QCursor::QCursor()
+{
+ if (!QCursorData::initialized) {
+ if (qApp->startingUp()) {
+ d = 0;
+ return;
+ }
+ QCursorData::initialize();
+ }
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ d = c;
+}
+
+/*!
+ Constructs a cursor with the specified \a shape.
+
+ See \l Qt::CursorShape for a list of shapes.
+
+ \sa setShape()
+*/
+QCursor::QCursor(Qt::CursorShape shape)
+ : d(0)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ setShape(shape);
+}
+
+
+/*!
+ Returns the cursor shape identifier. The return value is one of
+ the \l Qt::CursorShape enum values (cast to an int).
+
+ \sa setShape()
+*/
+Qt::CursorShape QCursor::shape() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ return d->cshape;
+}
+
+/*!
+ Sets the cursor to the shape identified by \a shape.
+
+ See \l Qt::CursorShape for the list of cursor shapes.
+
+ \sa shape()
+*/
+void QCursor::setShape(Qt::CursorShape shape)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : 0;
+ if (!c)
+ c = qt_cursorTable[0];
+ c->ref.ref();
+ if (!d) {
+ d = c;
+ } else {
+ if (!d->ref.deref())
+ delete d;
+ d = c;
+ }
+}
+
+/*!
+ Returns the cursor bitmap, or 0 if it is one of the standard
+ cursors.
+*/
+const QBitmap *QCursor::bitmap() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ return d->bm;
+}
+
+/*!
+ Returns the cursor bitmap mask, or 0 if it is one of the standard
+ cursors.
+*/
+
+const QBitmap *QCursor::mask() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ return d->bmm;
+}
+
+/*!
+ Returns the cursor pixmap. This is only valid if the cursor is a
+ pixmap cursor.
+*/
+
+QPixmap QCursor::pixmap() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ return d->pixmap;
+}
+
+/*!
+ Returns the cursor hot spot, or (0, 0) if it is one of the
+ standard cursors.
+*/
+
+QPoint QCursor::hotSpot() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ return QPoint(d->hx, d->hy);
+}
+
+/*!
+ Constructs a copy of the cursor \a c.
+*/
+
+QCursor::QCursor(const QCursor &c)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ d = c.d;
+ d->ref.ref();
+}
+
+/*!
+ Destroys the cursor.
+*/
+
+QCursor::~QCursor()
+{
+ if (d && !d->ref.deref())
+ delete d;
+}
+
+
+/*!
+ Assigns \a c to this cursor and returns a reference to this
+ cursor.
+*/
+
+QCursor &QCursor::operator=(const QCursor &c)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (c.d)
+ c.d->ref.ref();
+ if (d && !d->ref.deref())
+ delete d;
+ d = c.d;
+ return *this;
+}
+
+/*!
+ Returns the cursor as a QVariant.
+*/
+QCursor::operator QVariant() const
+{
+ return QVariant(QVariant::Cursor, this);
+}
+
+#endif // QT_NO_CURSOR
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
new file mode 100644
index 0000000000..15b4597193
--- /dev/null
+++ b/src/gui/kernel/qcursor.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCURSOR_H
+#define QCURSOR_H
+
+#include <QtCore/qpoint.h>
+#include <QtGui/qwindowdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QVariant;
+
+/*
+ ### The fake cursor has to go first with old qdoc.
+*/
+#ifdef QT_NO_CURSOR
+
+class Q_GUI_EXPORT QCursor
+{
+public:
+ static QPoint pos();
+ static void setPos(int x, int y);
+ inline static void setPos(const QPoint &p) { setPos(p.x(), p.y()); }
+private:
+ QCursor();
+};
+
+#endif // QT_NO_CURSOR
+
+#ifndef QT_NO_CURSOR
+
+struct QCursorData;
+class QBitmap;
+class QPixmap;
+
+#if defined(Q_WS_MAC)
+void qt_mac_set_cursor(const QCursor *c, const QPoint &p);
+#endif
+
+class Q_GUI_EXPORT QCursor
+{
+public:
+ QCursor();
+ QCursor(Qt::CursorShape shape);
+ QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX=-1, int hotY=-1);
+ QCursor(const QPixmap &pixmap, int hotX=-1, int hotY=-1);
+ QCursor(const QCursor &cursor);
+ ~QCursor();
+ QCursor &operator=(const QCursor &cursor);
+ operator QVariant() const;
+
+ Qt::CursorShape shape() const;
+ void setShape(Qt::CursorShape newShape);
+
+ const QBitmap *bitmap() const;
+ const QBitmap *mask() const;
+ QPixmap pixmap() const;
+ QPoint hotSpot() const;
+
+ static QPoint pos();
+ static void setPos(int x, int y);
+ inline static void setPos(const QPoint &p) { setPos(p.x(), p.y()); }
+
+#ifdef qdoc
+ HCURSOR_or_HANDLE handle() const;
+ QCursor(HCURSOR cursor);
+ QCursor(Qt::HANDLE cursor);
+#endif
+
+#ifndef qdoc
+#if defined(Q_WS_WIN)
+ HCURSOR handle() const;
+ QCursor(HCURSOR cursor);
+#elif defined(Q_WS_X11)
+ Qt::HANDLE handle() const;
+ QCursor(Qt::HANDLE cursor);
+ static int x11Screen();
+#elif defined(Q_WS_MAC)
+ Qt::HANDLE handle() const;
+#elif defined(Q_WS_QWS)
+ int handle() const;
+#endif
+#endif
+
+private:
+ QCursorData *d;
+#if defined(Q_WS_MAC)
+ friend void qt_mac_set_cursor(const QCursor *c, const QPoint &p);
+#endif
+};
+
+#ifdef QT3_SUPPORT
+// CursorShape is defined in X11/X.h
+#ifdef CursorShape
+#define X_CursorShape CursorShape
+#undef CursorShape
+#endif
+typedef Qt::CursorShape QCursorShape;
+#ifdef X_CursorShape
+#define CursorShape X_CursorShape
+#endif
+#endif
+
+/*****************************************************************************
+ QCursor stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &outS, const QCursor &cursor);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &inS, QCursor &cursor);
+#endif
+#endif // QT_NO_CURSOR
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCURSOR_H
diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm
new file mode 100644
index 0000000000..d632eb7949
--- /dev/null
+++ b/src/gui/kernel/qcursor_mac.mm
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qcursor_p.h>
+#include <private/qpixmap_mac_p.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qcursor.h>
+#include <qevent.h>
+#include <string.h>
+#include <unistd.h>
+#include <AppKit/NSCursor.h>
+#include <qpainter.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*****************************************************************************
+ Externals
+ *****************************************************************************/
+extern QCursorData *qt_cursorTable[Qt::LastCursor + 1];
+extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp
+extern GrafPtr qt_mac_qd_context(const QPaintDevice *); //qpaintdevice_mac.cpp
+extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_mac.cpp
+
+/*****************************************************************************
+ Internal QCursorData class
+ *****************************************************************************/
+
+class QMacAnimateCursor : public QObject
+{
+ int timerId, step;
+ ThemeCursor curs;
+public:
+ QMacAnimateCursor() : QObject(), timerId(-1) { }
+ void start(ThemeCursor c) {
+ step = 1;
+ if(timerId != -1)
+ killTimer(timerId);
+ timerId = startTimer(300);
+ curs = c;
+ }
+ void stop() {
+ if(timerId != -1) {
+ killTimer(timerId);
+ timerId = -1;
+ }
+ }
+protected:
+ void timerEvent(QTimerEvent *e) {
+ if(e->timerId() == timerId) {
+ /*
+ if(SetAnimatedThemeCursor(curs, step++) == themeBadCursorIndexErr)
+ stop();
+ */
+ }
+ }
+};
+
+static QCursorData *currentCursor = 0; //current cursor
+void qt_mac_set_cursor(const QCursor *c, const QPoint &)
+{
+ if (!c) {
+ currentCursor = 0;
+ return;
+ }
+ c->handle(); //force the cursor to get loaded, if it's not
+
+ if(1 || currentCursor != c->d) {
+ if(currentCursor && currentCursor->type == QCursorData::TYPE_ThemeCursor
+ && currentCursor->curs.tc.anim)
+ currentCursor->curs.tc.anim->stop();
+ QMacCocoaAutoReleasePool pool;
+ if(c->d->type == QCursorData::TYPE_ImageCursor) {
+ [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
+ } else if(c->d->type == QCursorData::TYPE_ThemeCursor) {
+#ifdef QT_MAC_USE_COCOA
+ if (c->d->curs.cp.nscursor == 0)
+ [[NSCursor arrowCursor] set];
+ [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
+#else
+ if(SetAnimatedThemeCursor(c->d->curs.tc.curs, 0) == themeBadCursorIndexErr) {
+ SetThemeCursor(c->d->curs.tc.curs);
+ } else {
+ if(!c->d->curs.tc.anim)
+ c->d->curs.tc.anim = new QMacAnimateCursor;
+ c->d->curs.tc.anim->start(c->d->curs.tc.curs);
+ }
+#endif
+ }
+ }
+ currentCursor = c->d;
+}
+
+void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos)
+{
+ QCursor cursor(Qt::ArrowCursor);
+ if (QApplication::overrideCursor()) {
+ cursor = *QApplication::overrideCursor();
+ } else {
+ for(QWidget *w = QApplication::widgetAt(globalPos); w; w = w->parentWidget()) {
+ if(w->testAttribute(Qt::WA_SetCursor)) {
+ cursor = w->cursor();
+ break;
+ }
+ }
+ }
+ qt_mac_set_cursor(&cursor, globalPos);
+}
+
+void qt_mac_update_cursor()
+{
+ qt_mac_update_cursor_at_global_pos(QCursor::pos());
+}
+
+static int nextCursorId = Qt::BitmapCursor;
+
+QCursorData::QCursorData(Qt::CursorShape s)
+ : cshape(s), bm(0), bmm(0), hx(-1), hy(-1), mId(s), type(TYPE_None)
+{
+ ref = 1;
+ memset(&curs, '\0', sizeof(curs));
+}
+
+QCursorData::~QCursorData()
+{
+ if (type == TYPE_ImageCursor) {
+ if (curs.cp.my_cursor) {
+ QMacCocoaAutoReleasePool pool;
+ [static_cast<NSCursor *>(curs.cp.nscursor) release];
+ }
+ } else if(type == TYPE_ThemeCursor) {
+ delete curs.tc.anim;
+ }
+ type = TYPE_None;
+
+ delete bm;
+ delete bmm;
+ if(currentCursor == this)
+ currentCursor = 0;
+}
+
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
+ qWarning("Qt: QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ return c;
+ }
+ // This is silly, but this is apparently called outside the constructor, so we have
+ // to be ready for that case.
+ QCursorData *x = new QCursorData;
+ x->ref = 1;
+ x->mId = ++nextCursorId;
+ x->bm = new QBitmap(bitmap);
+ x->bmm = new QBitmap(mask);
+ x->cshape = Qt::BitmapCursor;
+ x->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
+ x->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+ return x;
+}
+
+Qt::HANDLE QCursor::handle() const
+{
+ if(!QCursorData::initialized)
+ QCursorData::initialize();
+ if(d->type == QCursorData::TYPE_None)
+ d->update();
+ return (Qt::HANDLE)d->mId;
+}
+
+QPoint QCursor::pos()
+{
+ return flipPoint([NSEvent mouseLocation]).toPoint();
+}
+
+void QCursor::setPos(int x, int y)
+{
+ CGWarpMouseCursorPosition(CGPointMake(x, y));
+
+ /* I'm not too keen on doing this, but this makes it a lot easier, so I just
+ send the event back through the event system and let it get propagated correctly
+ ideally this would not really need to be faked --Sam
+ */
+ QWidget *widget = 0;
+ if(QWidget *grb = QWidget::mouseGrabber())
+ widget = grb;
+ else
+ widget = QApplication::widgetAt(QPoint(x, y));
+ if(widget) {
+ QMouseEvent me(QMouseEvent::MouseMove, widget->mapFromGlobal(QPoint(x, y)), Qt::NoButton,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ qt_sendSpontaneousEvent(widget, &me);
+ }
+}
+
+void QCursorData::initCursorFromBitmap()
+{
+ NSImage *nsimage;
+ QImage finalCursor(bm->size(), QImage::Format_ARGB32);
+ QImage bmi = bm->toImage().convertToFormat(QImage::Format_RGB32);
+ QImage bmmi = bmm->toImage().convertToFormat(QImage::Format_RGB32);
+ for (int row = 0; row < finalCursor.height(); ++row) {
+ QRgb *bmData = reinterpret_cast<QRgb *>(bmi.scanLine(row));
+ QRgb *bmmData = reinterpret_cast<QRgb *>(bmmi.scanLine(row));
+ QRgb *finalData = reinterpret_cast<QRgb *>(finalCursor.scanLine(row));
+ for (int col = 0; col < finalCursor.width(); ++col) {
+ if (bmmData[col] == 0xff000000 && bmData[col] == 0xffffffff) {
+ finalData[col] = 0xffffffff;
+ } else if (bmmData[col] == 0xff000000 && bmData[col] == 0xffffffff) {
+ finalData[col] = 0x7f000000;
+ } else if (bmmData[col] == 0xffffffff && bmData[col] == 0xffffffff) {
+ finalData[col] = 0x00000000;
+ } else {
+ finalData[col] = 0xff000000;
+ }
+ }
+ }
+ type = QCursorData::TYPE_ImageCursor;
+ curs.cp.my_cursor = true;
+ QPixmap bmCopy = QPixmap::fromImage(finalCursor);
+ NSPoint hotSpot = { hx, hy };
+ nsimage = static_cast<NSImage*>(qt_mac_create_nsimage(bmCopy));
+ curs.cp.nscursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot];
+ [nsimage release];
+}
+
+void QCursorData::initCursorFromPixmap()
+{
+ type = QCursorData::TYPE_ImageCursor;
+ curs.cp.my_cursor = true;
+ NSPoint hotSpot = { hx, hy };
+ NSImage *nsimage;
+ nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
+ curs.cp.nscursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot];
+ [nsimage release];
+}
+
+void QCursorData::update()
+{
+ if(!QCursorData::initialized)
+ QCursorData::initialize();
+ if(type != QCursorData::TYPE_None)
+ return;
+
+ /* Note to self... ***
+ * mask x data
+ * 0xFF x 0x00 == fully opaque white
+ * 0x00 x 0xFF == xor'd black
+ * 0xFF x 0xFF == fully opaque black
+ * 0x00 x 0x00 == fully transparent
+ */
+
+ if (hx < 0)
+ hx = 0;
+ if (hy < 0)
+ hy = 0;
+
+#define QT_USE_APPROXIMATE_CURSORS
+#ifdef QT_USE_APPROXIMATE_CURSORS
+ static const uchar cur_ver_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0,
+ 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0f, 0xf0,
+ 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00 };
+ static const uchar mcur_ver_bits[] = {
+ 0x00, 0x00, 0x03, 0x80, 0x07, 0xc0, 0x0f, 0xe0, 0x1f, 0xf0, 0x3f, 0xf8,
+ 0x7f, 0xfc, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x7f, 0xfc, 0x3f, 0xf8,
+ 0x1f, 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80 };
+
+ static const uchar cur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x18, 0x30,
+ 0x38, 0x38, 0x7f, 0xfc, 0x7f, 0xfc, 0x38, 0x38, 0x18, 0x30, 0x08, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar mcur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x0c, 0x60, 0x1c, 0x70, 0x3c, 0x78,
+ 0x7f, 0xfc, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfc, 0x3c, 0x78,
+ 0x1c, 0x70, 0x0c, 0x60, 0x04, 0x40, 0x00, 0x00 };
+
+ static const uchar cur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0xf8, 0x00, 0x78,
+ 0x00, 0xf8, 0x01, 0xd8, 0x23, 0x88, 0x37, 0x00, 0x3e, 0x00, 0x3c, 0x00,
+ 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar mcur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0xfc,
+ 0x41, 0xfc, 0x63, 0xfc, 0x77, 0xdc, 0x7f, 0x8c, 0x7f, 0x04, 0x7e, 0x00,
+ 0x7f, 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x00, 0x00 };
+
+ static const uchar cur_bdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e, 0x00,
+ 0x37, 0x00, 0x23, 0x88, 0x01, 0xd8, 0x00, 0xf8, 0x00, 0x78, 0x00, 0xf8,
+ 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar mcur_bdiag_bits[] = {
+ 0x00, 0x00, 0x7f, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7e, 0x00, 0x7f, 0x04,
+ 0x7f, 0x8c, 0x77, 0xdc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01, 0xfc,
+ 0x03, 0xfc, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00 };
+
+ static const unsigned char cur_up_arrow_bits[] = {
+ 0x00, 0x80, 0x01, 0x40, 0x01, 0x40, 0x02, 0x20, 0x02, 0x20, 0x04, 0x10,
+ 0x04, 0x10, 0x08, 0x08, 0x0f, 0x78, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,
+ 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0xc0 };
+ static const unsigned char mcur_up_arrow_bits[] = {
+ 0x00, 0x80, 0x01, 0xc0, 0x01, 0xc0, 0x03, 0xe0, 0x03, 0xe0, 0x07, 0xf0,
+ 0x07, 0xf0, 0x0f, 0xf8, 0x0f, 0xf8, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
+ 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0 };
+#endif
+ const uchar *cursorData = 0;
+ const uchar *cursorMaskData = 0;
+#ifdef QT_MAC_USE_COCOA
+ switch (cshape) { // map Q cursor to MAC cursor
+ case Qt::BitmapCursor: {
+ if (pixmap.isNull())
+ initCursorFromBitmap();
+ else
+ initCursorFromPixmap();
+ break; }
+ case Qt::BlankCursor: {
+ pixmap = QPixmap(16, 16);
+ pixmap.fill(Qt::transparent);
+ initCursorFromPixmap();
+ break; }
+ case Qt::ArrowCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor arrowCursor];
+ break; }
+ case Qt::CrossCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor crosshairCursor];
+ break; }
+ case Qt::WaitCursor: {
+ pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/spincursor.png"));
+ initCursorFromPixmap();
+ break; }
+ case Qt::IBeamCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor IBeamCursor];
+ break; }
+ case Qt::SizeAllCursor: {
+ pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/pluscursor.png"));
+ initCursorFromPixmap();
+ break; }
+ case Qt::WhatsThisCursor: { //for now just use the pointing hand
+ case Qt::PointingHandCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor pointingHandCursor];
+ break; }
+ case Qt::BusyCursor: {
+ pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/waitcursor.png"));
+ initCursorFromPixmap();
+ break; }
+ case Qt::SplitVCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor resizeUpDownCursor];
+ break; }
+ case Qt::SplitHCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor resizeLeftRightCursor];
+ break; }
+ case Qt::ForbiddenCursor: {
+ pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/forbiddencursor.png"));
+ initCursorFromPixmap();
+ break; }
+ case Qt::OpenHandCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor openHandCursor];
+ break;
+ case Qt::ClosedHandCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor closedHandCursor];
+ break;
+#define QT_USE_APPROXIMATE_CURSORS
+#ifdef QT_USE_APPROXIMATE_CURSORS
+ case Qt::SizeVerCursor:
+ cursorData = cur_ver_bits;
+ cursorMaskData = mcur_ver_bits;
+ hx = hy = 8;
+ break;
+ case Qt::SizeHorCursor:
+ cursorData = cur_hor_bits;
+ cursorMaskData = mcur_hor_bits;
+ hx = hy = 8;
+ break;
+ case Qt::SizeBDiagCursor:
+ cursorData = cur_fdiag_bits;
+ cursorMaskData = mcur_fdiag_bits;
+ hx = hy = 8;
+ break;
+ case Qt::SizeFDiagCursor:
+ cursorData = cur_bdiag_bits;
+ cursorMaskData = mcur_bdiag_bits;
+ hx = hy = 8;
+ break;
+ case Qt::UpArrowCursor:
+ cursorData = cur_up_arrow_bits;
+ cursorMaskData = mcur_up_arrow_bits;
+ hx = 8;
+ break;
+#endif
+ default:
+ qWarning("Qt: QCursor::update: Invalid cursor shape %d", cshape);
+ return;
+ }
+#else
+ // Carbon
+ switch (cshape) { // map Q cursor to MAC cursor
+ case Qt::BitmapCursor: {
+ if (pixmap.isNull())
+ initCursorFromBitmap();
+ else
+ initCursorFromPixmap();
+ break; }
+ case Qt::BlankCursor: {
+ pixmap = QPixmap(16, 16);
+ pixmap.fill(Qt::transparent);
+ initCursorFromPixmap();
+ break; }
+ case Qt::ArrowCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeArrowCursor;
+ break; }
+ case Qt::CrossCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeCrossCursor;
+ break; }
+ case Qt::WaitCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeWatchCursor;
+ break; }
+ case Qt::IBeamCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeIBeamCursor;
+ break; }
+ case Qt::SizeAllCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemePlusCursor;
+ break; }
+ case Qt::WhatsThisCursor: { //for now just use the pointing hand
+ case Qt::PointingHandCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemePointingHandCursor;
+ break; }
+ case Qt::BusyCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeSpinningCursor;
+ break; }
+ case Qt::SplitVCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeResizeUpDownCursor;
+ break; }
+ case Qt::SplitHCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeResizeLeftRightCursor;
+ break; }
+ case Qt::ForbiddenCursor: {
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeNotAllowedCursor;
+ break; }
+ case Qt::OpenHandCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeOpenHandCursor;
+ break;
+ case Qt::ClosedHandCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeClosedHandCursor;
+ break;
+#define QT_USE_APPROXIMATE_CURSORS
+#ifdef QT_USE_APPROXIMATE_CURSORS
+ case Qt::SizeVerCursor:
+ cursorData = cur_ver_bits;
+ cursorMaskData = mcur_ver_bits;
+ hx = hy = 8;
+ break;
+ case Qt::SizeHorCursor:
+ cursorData = cur_hor_bits;
+ cursorMaskData = mcur_hor_bits;
+ hx = hy = 8;
+ break;
+ case Qt::SizeBDiagCursor:
+ cursorData = cur_fdiag_bits;
+ cursorMaskData = mcur_fdiag_bits;
+ hx = hy = 8;
+ break;
+ case Qt::SizeFDiagCursor:
+ cursorData = cur_bdiag_bits;
+ cursorMaskData = mcur_bdiag_bits;
+ hx = hy = 8;
+ break;
+ case Qt::UpArrowCursor:
+ cursorData = cur_up_arrow_bits;
+ cursorMaskData = mcur_up_arrow_bits;
+ hx = 8;
+ break;
+#endif
+ default:
+ qWarning("Qt: QCursor::update: Invalid cursor shape %d", cshape);
+ return;
+ }
+#endif
+
+ if (cursorData) {
+ bm = new QBitmap(QBitmap::fromData(QSize(16, 16), cursorData,
+ QImage::Format_Mono));
+ bmm = new QBitmap(QBitmap::fromData(QSize(16, 16), cursorMaskData,
+ QImage::Format_Mono));
+ initCursorFromBitmap();
+ }
+
+#if 0
+ if(type == QCursorData::TYPE_CursPtr && curs.cp.hcurs && curs.cp.my_cursor) {
+ curs.cp.hcurs->hotSpot.h = hx >= 0 ? hx : 8;
+ curs.cp.hcurs->hotSpot.v = hy >= 0 ? hy : 8;
+ }
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h
new file mode 100644
index 0000000000..42682ac702
--- /dev/null
+++ b/src/gui/kernel/qcursor_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCURSOR_P_H
+#define QCURSOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qatomic.h"
+#include "QtCore/qglobal.h"
+#include "QtCore/qnamespace.h"
+#include "QtGui/qpixmap.h"
+
+# if defined (Q_WS_MAC)
+# include "private/qt_mac_p.h"
+# elif defined(Q_WS_X11)
+# include "private/qt_x11_p.h"
+# elif defined(Q_WS_WIN)
+# include "QtCore/qt_windows.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined (Q_WS_MAC)
+class QMacAnimateCursor;
+#endif
+
+class QBitmap;
+struct QCursorData {
+ QCursorData(Qt::CursorShape s = Qt::ArrowCursor);
+ ~QCursorData();
+
+ static void initialize();
+ static void cleanup();
+
+ QAtomicInt ref;
+ Qt::CursorShape cshape;
+ QBitmap *bm, *bmm;
+ QPixmap pixmap;
+ short hx, hy;
+#if defined (Q_WS_MAC)
+ int mId;
+#elif defined(Q_WS_QWS)
+ int id;
+#endif
+#if defined (Q_WS_WIN)
+ HCURSOR hcurs;
+#elif defined (Q_WS_X11)
+ XColor fg, bg;
+ Cursor hcurs;
+ Pixmap pm, pmm;
+#elif defined (Q_WS_MAC)
+ enum { TYPE_None, TYPE_ImageCursor, TYPE_ThemeCursor } type;
+ union {
+ struct {
+ uint my_cursor:1;
+ void *nscursor;
+ } cp;
+ struct {
+ QMacAnimateCursor *anim;
+ ThemeCursor curs;
+ } tc;
+ } curs;
+ void initCursorFromBitmap();
+ void initCursorFromPixmap();
+#endif
+ static bool initialized;
+ void update();
+ static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY);
+};
+
+QT_END_NAMESPACE
+
+#endif // QCURSOR_P_H
diff --git a/src/gui/kernel/qcursor_qws.cpp b/src/gui/kernel/qcursor_qws.cpp
new file mode 100644
index 0000000000..097b982041
--- /dev/null
+++ b/src/gui/kernel/qcursor_qws.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcursor.h>
+#include <private/qcursor_p.h>
+#include <qbitmap.h>
+#include <qwsdisplay_qws.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#ifndef QT_NO_CURSOR
+
+static int nextCursorId = Qt::BitmapCursor;
+
+/*****************************************************************************
+ Internal QCursorData class
+ *****************************************************************************/
+
+QCursorData::QCursorData(Qt::CursorShape s)
+ : cshape(s), bm(0), bmm(0), hx(0), hy(0), id(s)
+{
+ ref = 1;
+}
+
+QCursorData::~QCursorData()
+{
+ delete bm;
+ delete bmm;
+ QPaintDevice::qwsDisplay()->destroyCursor(id);
+}
+
+
+/*****************************************************************************
+ Global cursors
+ *****************************************************************************/
+
+extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
+
+int QCursor::handle() const
+{
+ return d->id;
+}
+
+
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
+ qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ return c;
+ }
+ QCursorData *d = new QCursorData;
+ d->bm = new QBitmap(bitmap);
+ d->bmm = new QBitmap(mask);
+ d->cshape = Qt::BitmapCursor;
+ d->id = ++nextCursorId;
+ d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
+ d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+
+ QPaintDevice::qwsDisplay()->defineCursor(d->id, *d->bm, *d->bmm, d->hx, d->hy);
+ return d;
+}
+
+void QCursorData::update()
+{
+}
+
+#endif //QT_NO_CURSOR
+
+extern int *qt_last_x,*qt_last_y;
+
+QPoint QCursor::pos()
+{
+ // This doesn't know about hotspots yet so we disable it
+ //qt_accel_update_cursor();
+ if (qt_last_x)
+ return QPoint(*qt_last_x, *qt_last_y);
+ else
+ return QPoint();
+}
+
+void QCursor::setPos(int x, int y)
+{
+ // Need to check, since some X servers generate null mouse move
+ // events, causing looping in applications which call setPos() on
+ // every mouse move event.
+ //
+ if (pos() == QPoint(x, y))
+ return;
+ QPaintDevice::qwsDisplay()->setCursorPosition(x, y);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp
new file mode 100644
index 0000000000..85d5a11500
--- /dev/null
+++ b/src/gui/kernel/qcursor_win.cpp
@@ -0,0 +1,493 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qcursor_p.h>
+#include <qbitmap.h>
+#include <qcursor.h>
+
+#ifndef QT_NO_CURSOR
+
+#include <qimage.h>
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
+
+/*****************************************************************************
+ Internal QCursorData class
+ *****************************************************************************/
+
+QCursorData::QCursorData(Qt::CursorShape s)
+ : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(0)
+{
+ ref = 1;
+}
+
+QCursorData::~QCursorData()
+{
+ delete bm;
+ delete bmm;
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+ if (hcurs)
+ DestroyCursor(hcurs);
+#endif
+}
+
+
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
+ qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ return c;
+ }
+ QCursorData *d = new QCursorData;
+ d->bm = new QBitmap(bitmap);
+ d->bmm = new QBitmap(mask);
+ d->hcurs = 0;
+ d->cshape = Qt::BitmapCursor;
+ d->hx = hotX >= 0 ? hotX : bitmap.width()/2;
+ d->hy = hotY >= 0 ? hotY : bitmap.height()/2;
+ return d;
+}
+
+HCURSOR QCursor::handle() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (!d->hcurs)
+ d->update();
+ return d->hcurs;
+}
+
+QCursor::QCursor(HCURSOR handle)
+{
+ d = new QCursorData(Qt::CustomCursor);
+ d->hcurs = handle;
+}
+
+#endif //QT_NO_CURSOR
+
+QPoint QCursor::pos()
+{
+ POINT p;
+ GetCursorPos(&p);
+ return QPoint(p.x, p.y);
+}
+
+void QCursor::setPos(int x, int y)
+{
+ SetCursorPos(x, y);
+}
+
+#ifndef QT_NO_CURSOR
+
+extern HBITMAP qt_createIconMask(const QBitmap &bitmap);
+
+static HCURSOR create32BitCursor(const QPixmap &pixmap, int hx, int hy)
+{
+ HCURSOR cur = 0;
+#if !defined(Q_OS_WINCE)
+ QBitmap mask = pixmap.mask();
+ if (mask.isNull()) {
+ mask = QBitmap(pixmap.size());
+ mask.fill(Qt::color1);
+ }
+
+ HBITMAP ic = pixmap.toWinHBITMAP(QPixmap::Alpha);
+ HBITMAP im = qt_createIconMask(mask);
+
+ ICONINFO ii;
+ ii.fIcon = 0;
+ ii.xHotspot = hx;
+ ii.yHotspot = hy;
+ ii.hbmMask = im;
+ ii.hbmColor = ic;
+
+ cur = CreateIconIndirect(&ii);
+
+ DeleteObject(ic);
+ DeleteObject(im);
+#elif defined(GWES_ICONCURS)
+ QImage bbits, mbits;
+ bool invb, invm;
+ bbits = pixmap.toImage().convertToFormat(QImage::Format_Mono);
+ mbits = pixmap.toImage().convertToFormat(QImage::Format_Mono);
+ invb = bbits.numColors() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
+ invm = mbits.numColors() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
+
+ int sysW = GetSystemMetrics(SM_CXCURSOR);
+ int sysH = GetSystemMetrics(SM_CYCURSOR);
+ int sysN = qMax(1, sysW / 8);
+ int n = qMax(1, bbits.width() / 8);
+ int h = bbits.height();
+
+ uchar* xBits = new uchar[sysH * sysN];
+ uchar* xMask = new uchar[sysH * sysN];
+ int x = 0;
+ for (int i = 0; i < sysH; ++i) {
+ if (i >= h) {
+ memset(&xBits[x] , 255, sysN);
+ memset(&xMask[x] , 0, sysN);
+ x += sysN;
+ } else {
+ int fillWidth = n > sysN ? sysN : n;
+ uchar *bits = bbits.scanLine(i);
+ uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < fillWidth; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xFF;
+ if (invm)
+ m ^= 0xFF;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ for (int j = fillWidth; j < sysN; ++j ) {
+ xBits[x] = 255;
+ xMask[x] = 0;
+ ++x;
+ }
+ }
+ }
+
+ cur = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH,
+ xBits, xMask);
+#else
+ Q_UNUSED(pixmap);
+ Q_UNUSED(hx);
+ Q_UNUSED(hy);
+#endif
+ return cur;
+}
+
+void QCursorData::update()
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (hcurs)
+ return;
+
+ if (cshape == Qt::BitmapCursor && !pixmap.isNull()) {
+ hcurs = create32BitCursor(pixmap, hx, hy);
+ if (hcurs)
+ return;
+ }
+
+
+ // Non-standard Windows cursors are created from bitmaps
+
+ static const uchar vsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar vsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar hsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
+ 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar hsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
+ 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
+ 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
+ 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar phand_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00,
+ 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00,
+ 0x80, 0x1c, 0x00, 0x00, 0x80, 0xe4, 0x00, 0x00, 0x80, 0x24, 0x03, 0x00,
+ 0x80, 0x24, 0x05, 0x00, 0xb8, 0x24, 0x09, 0x00, 0xc8, 0x00, 0x09, 0x00,
+ 0x88, 0x00, 0x08, 0x00, 0x90, 0x00, 0x08, 0x00, 0xa0, 0x00, 0x08, 0x00,
+ 0x20, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x04, 0x00,
+ 0x80, 0x00, 0x04, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x01, 0x02, 0x00,
+ 0x00, 0x01, 0x02, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ static const uchar phandm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00,
+ 0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00,
+ 0x80, 0x1f, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x80, 0xff, 0x03, 0x00,
+ 0x80, 0xff, 0x07, 0x00, 0xb8, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x0f, 0x00,
+ 0xf8, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xe0, 0xff, 0x0f, 0x00,
+ 0xe0, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x07, 0x00,
+ 0x80, 0xff, 0x07, 0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0xff, 0x03, 0x00,
+ 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ static const uchar openhand_bits[] = {
+ 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
+ 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
+ 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
+ static const uchar openhandm_bits[] = {
+ 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
+ 0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
+ 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
+ static const uchar closedhand_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
+ 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
+ 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
+ static const uchar closedhandm_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
+ 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
+ 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
+
+ static const uchar * const cursor_bits32[] = {
+ vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
+ phand_bits, phandm_bits
+ };
+
+ unsigned short *sh;
+ switch (cshape) { // map to windows cursor
+ case Qt::ArrowCursor:
+ sh = (unsigned short*)IDC_ARROW;
+ break;
+ case Qt::UpArrowCursor:
+ sh = (unsigned short*)IDC_UPARROW;
+ break;
+ case Qt::CrossCursor:
+ sh = (unsigned short*)IDC_CROSS;
+ break;
+ case Qt::WaitCursor:
+ sh = (unsigned short*)IDC_WAIT;
+ break;
+ case Qt::IBeamCursor:
+ sh = (unsigned short*)IDC_IBEAM;
+ break;
+ case Qt::SizeVerCursor:
+ sh = (unsigned short*)IDC_SIZENS;
+ break;
+ case Qt::SizeHorCursor:
+ sh = (unsigned short*)IDC_SIZEWE;
+ break;
+ case Qt::SizeBDiagCursor:
+ sh = (unsigned short*)IDC_SIZENESW;
+ break;
+ case Qt::SizeFDiagCursor:
+ sh = (unsigned short*)IDC_SIZENWSE;
+ break;
+ case Qt::SizeAllCursor:
+ sh = (unsigned short*)IDC_SIZEALL;
+ break;
+ case Qt::ForbiddenCursor:
+ sh = (unsigned short*)IDC_NO;
+ break;
+ case Qt::WhatsThisCursor:
+ sh = (unsigned short*)IDC_HELP;
+ break;
+ case Qt::BusyCursor:
+ sh = (unsigned short*)IDC_APPSTARTING;
+ break;
+ case Qt::PointingHandCursor:
+ if ((QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) > QSysInfo::WV_95 ||
+ (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) > QSysInfo::WV_NT) {
+ sh = (unsigned short*)IDC_HAND;
+ break;
+ }
+ // fall through
+ case Qt::BlankCursor:
+ case Qt::SplitVCursor:
+ case Qt::SplitHCursor:
+ case Qt::OpenHandCursor:
+ case Qt::ClosedHandCursor:
+ case Qt::BitmapCursor: {
+ QImage bbits, mbits;
+ bool invb, invm;
+ if (cshape == Qt::BlankCursor) {
+ bbits = QImage(32, 32, QImage::Format_Mono);
+ bbits.fill(0); // ignore color table
+ mbits = bbits.copy();
+ hx = hy = 16;
+ invb = invm = false;
+ } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
+ bool open = cshape == Qt::OpenHandCursor;
+ QBitmap cb = QBitmap::fromData(QSize(16, 16), open ? openhand_bits : closedhand_bits);
+ QBitmap cm = QBitmap::fromData(QSize(16, 16), open ? openhandm_bits : closedhandm_bits);
+ bbits = cb.toImage().convertToFormat(QImage::Format_Mono);
+ mbits = cm.toImage().convertToFormat(QImage::Format_Mono);
+ hx = hy = 8;
+ invb = invm = false;
+ } else if (cshape != Qt::BitmapCursor) {
+ int i = cshape - Qt::SplitVCursor;
+ QBitmap cb = QBitmap::fromData(QSize(32, 32), cursor_bits32[i * 2]);
+ QBitmap cm = QBitmap::fromData(QSize(32, 32), cursor_bits32[i * 2 + 1]);
+ bbits = cb.toImage().convertToFormat(QImage::Format_Mono);
+ mbits = cm.toImage().convertToFormat(QImage::Format_Mono);
+ if (cshape == Qt::PointingHandCursor) {
+ hx = 7;
+ hy = 0;
+ } else
+ hx = hy = 16;
+ invb = invm = false;
+ } else {
+ bbits = bm->toImage().convertToFormat(QImage::Format_Mono);
+ mbits = bmm->toImage().convertToFormat(QImage::Format_Mono);
+ invb = bbits.numColors() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
+ invm = mbits.numColors() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
+ }
+ int n = qMax(1, bbits.width() / 8);
+ int h = bbits.height();
+#if !defined(Q_OS_WINCE)
+ uchar* xBits = new uchar[h * n];
+ uchar* xMask = new uchar[h * n];
+ int x = 0;
+ for (int i = 0; i < h; ++i) {
+ uchar *bits = bbits.scanLine(i);
+ uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < n; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xff;
+ if (invm)
+ m ^= 0xff;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ }
+ hcurs = CreateCursor(qWinAppInst(), hx, hy, bbits.width(), bbits.height(),
+ xBits, xMask);
+ delete [] xBits;
+ delete [] xMask;
+#elif defined(GWES_ICONCURS) // Q_OS_WINCE
+ // Windows CE only supports fixed cursor size.
+ int sysW = GetSystemMetrics(SM_CXCURSOR);
+ int sysH = GetSystemMetrics(SM_CYCURSOR);
+ int sysN = qMax(1, sysW / 8);
+ uchar* xBits = new uchar[sysH * sysN];
+ uchar* xMask = new uchar[sysH * sysN];
+ int x = 0;
+ for (int i = 0; i < sysH; ++i) {
+ if (i >= h) {
+ memset(&xBits[x] , 255, sysN);
+ memset(&xMask[x] , 0, sysN);
+ x += sysN;
+ } else {
+ int fillWidth = n > sysN ? sysN : n;
+ uchar *bits = bbits.scanLine(i);
+ uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < fillWidth; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xFF;
+ if (invm)
+ m ^= 0xFF;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ for (int j = fillWidth; j < sysN; ++j ) {
+ xBits[x] = 255;
+ xMask[x] = 0;
+ ++x;
+ }
+ }
+ }
+
+ hcurs = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH,
+ xBits, xMask);
+ delete [] xBits;
+ delete [] xMask;
+#else
+ Q_UNUSED(n);
+ Q_UNUSED(h);
+#endif
+ return;
+ }
+ default:
+ qWarning("QCursor::update: Invalid cursor shape %d", cshape);
+ return;
+ }
+ // ### From MSDN:
+ // ### LoadCursor has been superseded by the LoadImage function.
+ QT_WA({
+ hcurs = LoadCursorW(0, reinterpret_cast<const TCHAR *>(sh));
+ } , {
+ hcurs = LoadCursorA(0, reinterpret_cast<const char*>(sh));
+ });
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_CURSOR
diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp
new file mode 100644
index 0000000000..252b4ee584
--- /dev/null
+++ b/src/gui/kernel/qcursor_x11.cpp
@@ -0,0 +1,594 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdatastream.h>
+#include <private/qcursor_p.h>
+#include <private/qt_x11_p.h>
+#include <qbitmap.h>
+#include <qcursor.h>
+#include <X11/cursorfont.h>
+
+#include <qlibrary.h>
+
+#ifndef QT_NO_XCURSOR
+# include <X11/Xcursor/Xcursor.h>
+#endif // QT_NO_XCURSOR
+
+#ifndef QT_NO_XFIXES
+# include <X11/extensions/Xfixes.h>
+#endif // QT_NO_XFIXES
+
+#include "qx11info_x11.h"
+
+QT_BEGIN_NAMESPACE
+
+// Define QT_USE_APPROXIMATE_CURSORS when compiling if you REALLY want to
+// use the ugly X11 cursors.
+
+extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
+
+/*****************************************************************************
+ Internal QCursorData class
+ *****************************************************************************/
+
+QCursorData::QCursorData(Qt::CursorShape s)
+ : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(0), pm(0), pmm(0)
+{
+ ref = 1;
+}
+
+QCursorData::~QCursorData()
+{
+ Display *dpy = X11 ? X11->display : (Display*)0;
+
+ // Add in checking for the display too as on HP-UX
+ // we seem to get a core dump as the cursor data is
+ // deleted again from main() on exit...
+ if (hcurs && dpy)
+ XFreeCursor(dpy, hcurs);
+ if (pm && dpy)
+ XFreePixmap(dpy, pm);
+ if (pmm && dpy)
+ XFreePixmap(dpy, pmm);
+ delete bm;
+ delete bmm;
+}
+
+#ifndef QT_NO_CURSOR
+QCursor::QCursor(Qt::HANDLE cursor)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ d = new QCursorData(Qt::CustomCursor);
+ d->hcurs = cursor;
+}
+#endif
+
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
+ qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ return c;
+ }
+ QCursorData *d = new QCursorData;
+ d->ref = 1;
+
+ extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
+ d->bm = new QBitmap(qt_toX11Pixmap(bitmap));
+ d->bmm = new QBitmap(qt_toX11Pixmap(mask));
+
+ d->hcurs = 0;
+ d->cshape = Qt::BitmapCursor;
+ d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
+ d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+ d->fg.red = 0x0000;
+ d->fg.green = 0x0000;
+ d->fg.blue = 0x0000;
+ d->bg.red = 0xffff;
+ d->bg.green = 0xffff;
+ d->bg.blue = 0xffff;
+ return d;
+}
+
+
+
+#ifndef QT_NO_CURSOR
+Qt::HANDLE QCursor::handle() const
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (!d->hcurs)
+ d->update();
+ return d->hcurs;
+}
+#endif
+
+QPoint QCursor::pos()
+{
+ Window root;
+ Window child;
+ int root_x, root_y, win_x, win_y;
+ uint buttons;
+ Display* dpy = X11->display;
+ for (int i = 0; i < ScreenCount(dpy); ++i) {
+ if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
+ &win_x, &win_y, &buttons))
+
+ return QPoint(root_x, root_y);
+ }
+ return QPoint();
+}
+
+/*! \internal
+*/
+#ifndef QT_NO_CURSOR
+int QCursor::x11Screen()
+{
+ Window root;
+ Window child;
+ int root_x, root_y, win_x, win_y;
+ uint buttons;
+ Display* dpy = X11->display;
+ for (int i = 0; i < ScreenCount(dpy); ++i) {
+ if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
+ &win_x, &win_y, &buttons))
+ return i;
+ }
+ return -1;
+}
+#endif
+
+void QCursor::setPos(int x, int y)
+{
+ QPoint current, target(x, y);
+
+ // this is copied from pos(), since we need the screen number for the correct
+ // root window in the XWarpPointer call
+ Window root;
+ Window child;
+ int root_x, root_y, win_x, win_y;
+ uint buttons;
+ Display* dpy = X11->display;
+ int screen;
+ for (screen = 0; screen < ScreenCount(dpy); ++screen) {
+ if (XQueryPointer(dpy, QX11Info::appRootWindow(screen), &root, &child, &root_x, &root_y,
+ &win_x, &win_y, &buttons)) {
+ current = QPoint(root_x, root_y);
+ break;
+ }
+ }
+
+ if (screen >= ScreenCount(dpy))
+ return;
+
+ // Need to check, since some X servers generate null mouse move
+ // events, causing looping in applications which call setPos() on
+ // every mouse move event.
+ //
+ if (current == target)
+ return;
+
+ XWarpPointer(X11->display, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y);
+}
+
+
+/*!
+ \internal
+
+ Creates the cursor.
+*/
+
+void QCursorData::update()
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (hcurs)
+ return;
+
+ Display *dpy = X11->display;
+ Window rootwin = QX11Info::appRootWindow();
+
+ if (cshape == Qt::BitmapCursor) {
+ extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
+#ifndef QT_NO_XRENDER
+ if (!pixmap.isNull() && X11->use_xrender) {
+ pixmap = qt_toX11Pixmap(pixmap);
+ hcurs = XRenderCreateCursor (X11->display, pixmap.x11PictureHandle(), hx, hy);
+ } else
+#endif
+ {
+ hcurs = XCreatePixmapCursor(dpy, bm->handle(), bmm->handle(), &fg, &bg, hx, hy);
+ }
+ return;
+ }
+
+ static const char *cursorNames[] = {
+ "left_ptr",
+ "up_arrow",
+ "cross",
+ "wait",
+ "ibeam",
+ "size_ver",
+ "size_hor",
+ "size_bdiag",
+ "size_fdiag",
+ "size_all",
+ "blank",
+ "split_v",
+ "split_h",
+ "pointing_hand",
+ "forbidden",
+ "whats_this",
+ "left_ptr_watch",
+ "openhand",
+ "closedhand"
+ };
+
+#ifndef QT_NO_XCURSOR
+ if (X11->ptrXcursorLibraryLoadCursor)
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ if (hcurs)
+ return;
+#endif // QT_NO_XCURSOR
+
+ static const char cur_blank_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ // Non-standard X11 cursors are created from bitmaps
+
+#ifndef QT_USE_APPROXIMATE_CURSORS
+ static const char cur_ver_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
+ 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
+ 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
+ static const char mcur_ver_bits[] = {
+ 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
+ 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
+ 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
+ static const char cur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
+ 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const char mcur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
+ 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
+ 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
+ static const char cur_bdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
+ 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
+ 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const char mcur_bdiag_bits[] = {
+ 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
+ 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
+ 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static const char cur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
+ 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
+ 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
+ static const char mcur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
+ 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
+ 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
+ static const char *cursor_bits16[] = {
+ cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits,
+ cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits,
+ 0, 0, cur_blank_bits, cur_blank_bits };
+
+ static const char vsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const char vsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const char hsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
+ 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const char hsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
+ 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
+ 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
+ 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const char whatsthis_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
+ 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
+ 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
+ 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00,
+ 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00,
+ 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+ static const char whatsthism_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
+ 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
+ 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
+ 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00,
+ 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00,
+ 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+ static const char busy_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+ 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
+ 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00,
+ 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00,
+ 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00,
+ 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00,
+ 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ static const char busym_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
+ 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00,
+ 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00,
+ 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00,
+ 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00,
+ 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ static const char * const cursor_bits32[] = {
+ vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
+ 0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits
+ };
+
+ static const char forbidden_bits[] = {
+ 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
+ 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
+ 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
+ 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
+
+ static const char forbiddenm_bits[] = {
+ 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
+ 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
+ 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
+ 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
+
+ static const char openhand_bits[] = {
+ 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
+ 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
+ 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
+ static const char openhandm_bits[] = {
+ 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
+ 0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
+ 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
+ static const char closedhand_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
+ 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
+ 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
+ static const char closedhandm_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
+ 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
+ 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
+
+ static const char * const cursor_bits20[] = {
+ forbidden_bits, forbiddenm_bits
+ };
+
+ if ((cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor)
+ || cshape == Qt::BlankCursor) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ int i = (cshape - Qt::SizeVerCursor) * 2;
+ pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits16[i], 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits16[i + 1], 16, 16);
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
+ } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
+ || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ int i = (cshape - Qt::SplitVCursor) * 2;
+ pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits32[i], 32, 32);
+ pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits32[i + 1], 32, 32);
+ int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
+ || cshape == Qt::BusyCursor) ? 0 : 16;
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, hs, hs);
+ } else if (cshape == Qt::ForbiddenCursor) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ int i = (cshape - Qt::ForbiddenCursor) * 2;
+ pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits20[i], 20, 20);
+ pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits20[i + 1], 20, 20);
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 10, 10);
+ } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ bool open = cshape == Qt::OpenHandCursor;
+ pm = XCreateBitmapFromData(dpy, rootwin, open ? openhand_bits : closedhand_bits, 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, open ? openhandm_bits : closedhandm_bits, 16, 16);
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
+ }
+
+ if (hcurs)
+ {
+#ifndef QT_NO_XFIXES
+ if (X11->use_xfixes && X11->ptrXFixesSetCursorName)
+ X11->ptrXFixesSetCursorName(dpy, hcurs, cursorNames[cshape]);
+#endif /* ! QT_NO_XFIXES */
+ return;
+ }
+
+#endif /* ! QT_USE_APPROXIMATE_CURSORS */
+
+ uint sh;
+ switch (cshape) { // map Q cursor to X cursor
+ case Qt::ArrowCursor:
+ sh = XC_left_ptr;
+ break;
+ case Qt::UpArrowCursor:
+ sh = XC_center_ptr;
+ break;
+ case Qt::CrossCursor:
+ sh = XC_crosshair;
+ break;
+ case Qt::WaitCursor:
+ sh = XC_watch;
+ break;
+ case Qt::IBeamCursor:
+ sh = XC_xterm;
+ break;
+ case Qt::SizeAllCursor:
+ sh = XC_fleur;
+ break;
+ case Qt::PointingHandCursor:
+ sh = XC_hand2;
+ break;
+#ifdef QT_USE_APPROXIMATE_CURSORS
+ case Qt::SizeBDiagCursor:
+ sh = XC_top_right_corner;
+ break;
+ case Qt::SizeFDiagCursor:
+ sh = XC_bottom_right_corner;
+ break;
+ case Qt::BlankCursor:
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ pm = XCreateBitmapFromData(dpy, rootwin, cur_blank_bits, 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, cur_blank_bits, 16, 16);
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
+ return;
+ break;
+ case Qt::SizeVerCursor:
+ case Qt::SplitVCursor:
+ sh = XC_sb_v_double_arrow;
+ break;
+ case Qt::SizeHorCursor:
+ case Qt::SplitHCursor:
+ sh = XC_sb_h_double_arrow;
+ break;
+ case Qt::WhatsThisCursor:
+ sh = XC_question_arrow;
+ break;
+ case Qt::ForbiddenCursor:
+ sh = XC_circle;
+ break;
+ case Qt::BusyCursor:
+ sh = XC_watch;
+ break;
+#endif /* QT_USE_APPROXIMATE_CURSORS */
+ default:
+ qWarning("QCursor::update: Invalid cursor shape %d", cshape);
+ return;
+ }
+ hcurs = XCreateFontCursor(dpy, sh);
+
+#ifndef QT_NO_XFIXES
+ if (X11->use_xfixes && X11->ptrXFixesSetCursorName)
+ X11->ptrXFixesSetCursorName(dpy, hcurs, cursorNames[cshape]);
+#endif /* ! QT_NO_XFIXES */
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h
new file mode 100644
index 0000000000..c107ee0091
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESKTOPWIDGET_H
+#define QDESKTOPWIDGET_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QApplication;
+class QDesktopWidgetPrivate;
+
+class Q_GUI_EXPORT QDesktopWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ QDesktopWidget();
+ ~QDesktopWidget();
+
+ bool isVirtualDesktop() const;
+
+ int numScreens() const;
+ int primaryScreen() const;
+
+ int screenNumber(const QWidget *widget = 0) const;
+ int screenNumber(const QPoint &) const;
+
+ QWidget *screen(int screen = -1);
+
+ const QRect screenGeometry(int screen = -1) const;
+ const QRect screenGeometry(const QWidget *widget) const
+ { return screenGeometry(screenNumber(widget)); }
+ const QRect screenGeometry(const QPoint &point) const
+ { return screenGeometry(screenNumber(point)); }
+
+ const QRect availableGeometry(int screen = -1) const;
+ const QRect availableGeometry(const QWidget *widget) const
+ { return availableGeometry(screenNumber(widget)); }
+ const QRect availableGeometry(const QPoint &point) const
+ { return availableGeometry(screenNumber(point)); }
+
+Q_SIGNALS:
+ void resized(int);
+ void workAreaResized(int);
+
+protected:
+ void resizeEvent(QResizeEvent *e);
+
+private:
+ Q_DISABLE_COPY(QDesktopWidget)
+ Q_DECLARE_PRIVATE(QDesktopWidget)
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDESKTOPWIDGET_H
diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm
new file mode 100644
index 0000000000..77989cb663
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_mac.mm
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+**
+****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include <private/qt_mac_p.h>
+#include "qwidget_p.h"
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qdesktopwidget_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+/*****************************************************************************
+ Externals
+ *****************************************************************************/
+
+/*****************************************************************************
+ QDesktopWidget member functions
+ *****************************************************************************/
+
+Q_GLOBAL_STATIC(QDesktopWidgetImplementation, qdesktopWidgetImplementation)
+
+QDesktopWidgetImplementation::QDesktopWidgetImplementation()
+ : appScreen(0), displays(0)
+{
+ onResize();
+}
+
+QDesktopWidgetImplementation::~QDesktopWidgetImplementation()
+{
+ if (displays)
+ [displays release];
+}
+
+QDesktopWidgetImplementation *QDesktopWidgetImplementation::instance()
+{
+ return qdesktopWidgetImplementation();
+}
+
+QRect QDesktopWidgetImplementation::availableRect(int screenIndex) const
+{
+ if (screenIndex < 0 || screenIndex >= screenCount)
+ screenIndex = appScreen;
+
+ NSRect r = [[displays objectAtIndex:screenIndex] visibleFrame];
+ NSRect primaryRect = [[displays objectAtIndex:0] frame];
+
+ const int flippedY = - r.origin.y + // account for position offset and
+ primaryRect.size.height - r.size.height; // height difference.
+ return QRectF(r.origin.x, flippedY,
+ r.size.width, r.size.height).toRect();
+}
+
+QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const
+{
+ if (screenIndex < 0 || screenIndex >= screenCount)
+ screenIndex = appScreen;
+
+ NSRect r = [[displays objectAtIndex:screenIndex] frame];
+ NSRect primaryRect = [[displays objectAtIndex:0] frame];
+
+ const int flippedY = - r.origin.y + // account for position offset and
+ primaryRect.size.height - r.size.height; // height difference.
+ return QRectF(r.origin.x, flippedY,
+ r.size.width, r.size.height).toRect();
+}
+
+void QDesktopWidgetImplementation::onResize()
+{
+ if (displays)
+ [displays release];
+
+ displays = [[NSScreen screens] retain];
+ screenCount = [displays count];
+}
+
+
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(0, Qt::Desktop)
+{
+ setObjectName(QLatin1String("desktop"));
+ setAttribute(Qt::WA_WState_Visible);
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return true;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return qdesktopWidgetImplementation()->appScreen;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ return qdesktopWidgetImplementation()->screenCount;
+}
+
+QWidget *QDesktopWidget::screen(int)
+{
+ return this;
+}
+
+const QRect QDesktopWidget::availableGeometry(int screen) const
+{
+ return qdesktopWidgetImplementation()->availableRect(screen);
+}
+
+const QRect QDesktopWidget::screenGeometry(int screen) const
+{
+ return qdesktopWidgetImplementation()->screenRect(screen);
+}
+
+int QDesktopWidget::screenNumber(const QWidget *widget) const
+{
+ QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+ if (!widget)
+ return d->appScreen;
+ QRect frame = widget->frameGeometry();
+ if (!widget->isWindow())
+ frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
+ int maxSize = -1, maxScreen = -1;
+ for (int i = 0; i < d->screenCount; ++i) {
+ QRect rr = d->screenRect(i);
+ QRect sect = rr.intersected(frame);
+ int size = sect.width() * sect.height();
+ if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
+ maxSize = size;
+ maxScreen = i;
+ }
+ }
+ return maxScreen;
+}
+
+int QDesktopWidget::screenNumber(const QPoint &point) const
+{
+ QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+ int closestScreen = -1;
+ int shortestDistance = INT_MAX;
+ for (int i = 0; i < d->screenCount; ++i) {
+ QRect rr = d->screenRect(i);
+ int thisDistance = QWidgetPrivate::pointToRect(point, rr);
+ if (thisDistance < shortestDistance) {
+ shortestDistance = thisDistance;
+ closestScreen = i;
+ }
+ }
+ return closestScreen;
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+ QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+
+ d->onResize();
+
+ for (int i = 0; i < d->screenCount; ++i) {
+ emit resized(i);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_mac_p.h b/src/gui/kernel/qdesktopwidget_mac_p.h
new file mode 100644
index 0000000000..09cbacc214
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_mac_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Mac developers at Qt Software. This header file may change
+// from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qrect.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesktopWidgetImplementation
+{
+public:
+ QDesktopWidgetImplementation();
+ ~QDesktopWidgetImplementation();
+ static QDesktopWidgetImplementation *instance();
+
+ int appScreen;
+ int screenCount;
+
+ NSArray *displays;
+
+ QRect availableRect(int screenIndex) const;
+ QRect screenRect(int screenIndex) const;
+ void onResize();
+};
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_qws.cpp b/src/gui/kernel/qdesktopwidget_qws.cpp
new file mode 100644
index 0000000000..cfeaee9915
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_qws.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesktopwidget.h"
+#include "qscreen_qws.h"
+#include "private/qapplication_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(0, Qt::Desktop)
+{
+ setObjectName(QLatin1String("desktop"));
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return true;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return 0;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ QScreen *screen = QScreen::instance();
+ if (!screen)
+ return 0;
+
+ const QList<QScreen*> subScreens = screen->subScreens();
+ return qMax(subScreens.size(), 1);
+}
+
+QWidget *QDesktopWidget::screen(int)
+{
+ return this;
+}
+
+const QRect QDesktopWidget::availableGeometry(int screenNo) const
+{
+ const QScreen *screen = QScreen::instance();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (!screen || screenNo < 0)
+ return QRect();
+
+ const QList<QScreen*> subScreens = screen->subScreens();
+ if (!subScreens.isEmpty()) {
+ if (screenNo >= subScreens.size())
+ return QRect();
+ screen = subScreens.at(screenNo);
+ }
+
+ QApplicationPrivate *ap = QApplicationPrivate::instance();
+ const QRect r = ap->maxWindowRect(screen);
+ if (!r.isEmpty())
+ return r;
+
+ return screen->region().boundingRect();
+}
+
+const QRect QDesktopWidget::screenGeometry(int screenNo) const
+{
+ const QScreen *screen = QScreen::instance();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (!screen || screenNo < 0)
+ return QRect();
+
+ const QList<QScreen*> subScreens = screen->subScreens();
+ if (subScreens.size() == 0 && screenNo == 0)
+ return screen->region().boundingRect();
+
+ if (screenNo >= subScreens.size())
+ return QRect();
+
+ return subScreens.at(screenNo)->region().boundingRect();
+}
+
+int QDesktopWidget::screenNumber(const QWidget *w) const
+{
+ if (!w)
+ return 0;
+
+ QRect frame = w->frameGeometry();
+ if (!w->isWindow())
+ frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0)));
+ const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2;
+ return screenNumber(midpoint);
+}
+
+int QDesktopWidget::screenNumber(const QPoint &p) const
+{
+ const QScreen *screen = QScreen::instance();
+ if (!screen || !screen->region().contains(p))
+ return -1;
+
+ const QList<QScreen*> subScreens = screen->subScreens();
+ if (subScreens.size() == 0)
+ return 0;
+
+ for (int i = 0; i < subScreens.size(); ++i)
+ if (subScreens.at(i)->region().contains(p))
+ return i;
+
+ return -1;
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp
new file mode 100644
index 0000000000..725e985870
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_win.cpp
@@ -0,0 +1,412 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesktopwidget.h"
+#include "qt_windows.h"
+#include "qapplication_p.h"
+#include "qlibrary.h"
+#include <qvector.h>
+#include <limits.h>
+#ifdef Q_OS_WINCE
+#include <sipapi.h>
+#endif
+#include "qwidget_p.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesktopWidgetPrivate : public QWidgetPrivate
+{
+public:
+ QDesktopWidgetPrivate();
+ ~QDesktopWidgetPrivate();
+
+ static void init(QDesktopWidget *that);
+ static void cleanup();
+ static int screenCount;
+ static int primaryScreen;
+
+ static QVector<QRect> *rects;
+ static QVector<QRect> *workrects;
+
+ struct MONITORINFO
+ {
+ DWORD cbSize;
+ RECT rcMonitor;
+ RECT rcWork;
+ DWORD dwFlags;
+ };
+
+ typedef BOOL (WINAPI *InfoFunc)(HMONITOR, MONITORINFO*);
+ typedef BOOL (CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
+ typedef BOOL (WINAPI *EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM);
+
+ static EnumFunc enumDisplayMonitors;
+ static InfoFunc getMonitorInfo;
+ static int refcount;
+};
+
+int QDesktopWidgetPrivate::screenCount = 1;
+int QDesktopWidgetPrivate::primaryScreen = 0;
+QDesktopWidgetPrivate::EnumFunc QDesktopWidgetPrivate::enumDisplayMonitors = 0;
+QDesktopWidgetPrivate::InfoFunc QDesktopWidgetPrivate::getMonitorInfo = 0;
+QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
+QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
+static int screen_number = 0;
+int QDesktopWidgetPrivate::refcount = 0;
+#ifdef Q_OS_WINCE_WM
+// Use SIP information, if available
+// SipGetInfo is not supported by SSDK (no definition!).
+static inline void qt_get_sip_info(QRect &rect)
+{
+ SIPINFO sip;
+ memset(&sip, 0, sizeof(SIPINFO));
+ sip.cbSize = sizeof(SIPINFO);
+ if (SipGetInfo(&sip))
+ rect = QRect(QPoint(sip.rcVisibleDesktop.left, sip.rcVisibleDesktop.top),
+ QPoint(sip.rcVisibleDesktop.right - 1, sip.rcVisibleDesktop.bottom - 1));
+}
+#endif
+
+
+BOOL CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
+{
+ QDesktopWidgetPrivate::screenCount++;
+ QDesktopWidgetPrivate::rects->resize(QDesktopWidgetPrivate::screenCount);
+ QDesktopWidgetPrivate::workrects->resize(QDesktopWidgetPrivate::screenCount);
+ // Get the MONITORINFO block
+ QDesktopWidgetPrivate::MONITORINFO info;
+ memset(&info, 0, sizeof(QDesktopWidgetPrivate::MONITORINFO));
+ info.cbSize = sizeof(QDesktopWidgetPrivate::MONITORINFO);
+ BOOL res = QDesktopWidgetPrivate::getMonitorInfo(hMonitor, &info);
+ if (!res) {
+ (*QDesktopWidgetPrivate::rects)[screen_number] = QRect();
+ (*QDesktopWidgetPrivate::workrects)[screen_number] = QRect();
+ return true;
+ }
+
+ // Fill list of rects
+ RECT r = info.rcMonitor;
+ QRect qr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
+ (*QDesktopWidgetPrivate::rects)[screen_number] = qr;
+
+ r = info.rcWork;
+ qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
+ (*QDesktopWidgetPrivate::workrects)[screen_number] = qr;
+
+ if (info.dwFlags & 0x00000001) //MONITORINFOF_PRIMARY
+ QDesktopWidgetPrivate::primaryScreen = screen_number;
+
+ ++screen_number;
+ // Stop the enumeration if we have them all
+ return true;
+}
+
+QDesktopWidgetPrivate::QDesktopWidgetPrivate()
+{
+ ++refcount;
+}
+
+void QDesktopWidgetPrivate::init(QDesktopWidget *that)
+{
+ if (rects)
+ return;
+
+ rects = new QVector<QRect>();
+ workrects = new QVector<QRect>();
+
+#ifndef Q_OS_WINCE
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
+ screenCount = 0;
+ // Trying to get the function pointers to Win98/2000 only functions
+ QLibrary user32Lib(QLatin1String("user32"));
+ if (!user32Lib.load())
+ return;
+ enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
+ QT_WA({
+ getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
+ } , {
+ getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoA");
+ });
+
+ if (!enumDisplayMonitors || !getMonitorInfo) {
+ screenCount = GetSystemMetrics(80); // SM_CMONITORS
+ rects->resize(screenCount);
+ for (int i = 0; i < screenCount; ++i)
+ rects->replace(i, that->rect());
+ return;
+ }
+ // Calls enumCallback
+ enumDisplayMonitors(0, 0, enumCallback, 0);
+ enumDisplayMonitors = 0;
+ getMonitorInfo = 0;
+ } else {
+ rects->resize(1);
+ rects->replace(0, that->rect());
+ workrects->resize(1);
+ workrects->replace(0, that->rect());
+ }
+#else
+ screenCount = 0;
+
+ QLibrary coreLib(QLatin1String("coredll"));
+ if (coreLib.load()) {
+ // CE >= 4.0 case
+ enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors");
+ getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo");
+ }
+
+ if ((!enumDisplayMonitors || !getMonitorInfo)) {
+ screenCount = GetSystemMetrics(SM_CMONITORS);
+ return;
+ }
+
+ if (!coreLib.isLoaded() || !enumDisplayMonitors || !getMonitorInfo) {
+ rects->resize(screenCount);
+ for (int i = 0; i < screenCount; ++i)
+ (*rects)[i] = that->rect();
+
+ RECT r;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
+
+#if defined(Q_OS_WINCE_WM)
+ qt_get_sip_info(qr);
+#endif
+
+ workrects->resize(screenCount);
+ for (int j = 0; j < screenCount; ++j)
+ (*workrects)[j] = qr;
+ return;
+ }
+
+ // Calls enumCallback
+ enumDisplayMonitors(0, 0, enumCallback, 0);
+ enumDisplayMonitors = 0;
+ getMonitorInfo = 0;
+#endif // Q_OS_WINCE
+}
+
+QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
+{
+ if (!--refcount)
+ cleanup();
+}
+
+void QDesktopWidgetPrivate::cleanup()
+{
+ screen_number = 0;
+ screenCount = 1;
+ primaryScreen = 0;
+ enumDisplayMonitors = 0;
+ getMonitorInfo = 0;
+ delete rects;
+ rects = 0;
+ delete workrects;
+ workrects = 0;
+}
+
+/*
+ \omit
+ Function is commented out in header
+ \fn void *QDesktopWidget::handle(int screen) const
+
+ Returns the window system handle of the display device with the
+ index \a screen, for low-level access. Using this function is not
+ portable.
+
+ The return type varies with platform; see qwindowdefs.h for details.
+
+ \sa x11Display(), QPaintDevice::handle()
+ \endomit
+*/
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ setObjectName(QLatin1String("desktop"));
+ QDesktopWidgetPrivate::init(this);
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return true;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return d_func()->primaryScreen;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ return d_func()->screenCount;
+}
+
+QWidget *QDesktopWidget::screen(int /* screen */)
+{
+ // It seems that a Qt::WType_Desktop cannot be moved?
+ return this;
+}
+
+//
+// MSVC 7.10 warns that d (the result of the expanded Q_D macro) as a local variable that is not referenced.
+// Therefore, we ignore that warning with the following pragmas
+// I've also tried to eliminate the macro, but to no use...
+// We pop it further down
+#ifdef Q_CC_MSVC
+# pragma warning(push)
+# pragma warning(disable : 4189)
+#endif
+const QRect QDesktopWidget::availableGeometry(int screen) const
+{
+ Q_D(const QDesktopWidget);
+#ifdef Q_OS_WINCE_WM
+ for(int i=0; i < d->workrects->size(); ++i)
+ qt_get_sip_info((*d->workrects)[i]);
+#endif
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->primaryScreen;
+
+ return d->workrects->at(screen);
+ } else {
+ return d->workrects->at(d->primaryScreen);
+ }
+}
+
+const QRect QDesktopWidget::screenGeometry(int screen) const
+{
+ const QDesktopWidgetPrivate *d = d_func();
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->primaryScreen;
+
+ return d->rects->at(screen);
+ } else {
+ return d->rects->at(d->primaryScreen);
+ }
+}
+
+int QDesktopWidget::screenNumber(const QWidget *widget) const
+{
+ Q_D(const QDesktopWidget);
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
+ if (!widget)
+ return d->primaryScreen;
+ QRect frame = widget->frameGeometry();
+ if (!widget->isWindow())
+ frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
+
+ int maxSize = -1;
+ int maxScreen = -1;
+
+ for (int i = 0; i < d->screenCount; ++i) {
+ QRect sect = d->rects->at(i).intersected(frame);
+ int size = sect.width() * sect.height();
+ if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
+ maxSize = size;
+ maxScreen = i;
+ }
+ }
+ return maxScreen;
+ } else {
+ return d->primaryScreen;
+ }
+}
+
+int QDesktopWidget::screenNumber(const QPoint &point) const
+{
+ Q_D(const QDesktopWidget);
+ int closestScreen = -1;
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
+ int shortestDistance = INT_MAX;
+ for (int i = 0; i < d->screenCount; ++i) {
+ int thisDistance = d->pointToRect(point, d->rects->at(i));
+ if (thisDistance < shortestDistance) {
+ shortestDistance = thisDistance;
+ closestScreen = i;
+ }
+ }
+ }
+ return closestScreen;
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QDesktopWidget);
+ QVector<QRect> oldrects;
+ oldrects = *d->rects;
+ QVector<QRect> oldworkrects;
+ oldworkrects = *d->workrects;
+ int oldscreencount = d->screenCount;
+
+ QDesktopWidgetPrivate::cleanup();
+ QDesktopWidgetPrivate::init(this);
+#ifdef Q_OS_WINCE_WM
+ for(int i=0; i < d->workrects->size(); ++i)
+ qt_get_sip_info((*d->workrects)[i]);
+#endif
+
+ for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
+ QRect oldrect = oldrects[i];
+ QRect newrect = d->rects->at(i);
+ if (oldrect != newrect)
+ emit resized(i);
+ }
+
+ for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
+ QRect oldrect = oldworkrects[j];
+ QRect newrect = d->workrects->at(j);
+ if (oldrect != newrect)
+ emit workAreaResized(j);
+ }
+}
+
+#ifdef Q_CC_MSVC
+# pragma warning(pop)
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_x11.cpp b/src/gui/kernel/qdesktopwidget_x11.cpp
new file mode 100644
index 0000000000..7b823f0d38
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_x11.cpp
@@ -0,0 +1,380 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include "qlibrary.h"
+#include "qt_x11_p.h"
+#include "qvariant.h"
+#include "qwidget_p.h"
+#include "qx11info_x11.h"
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+// defined in qwidget_x11.cpp
+extern int qt_x11_create_desktop_on_screen;
+
+
+// function to update the workarea of the screen
+static bool qt_desktopwidget_workarea_dirty = true;
+void qt_desktopwidget_update_workarea()
+{
+ qt_desktopwidget_workarea_dirty = true;
+}
+
+
+class QSingleDesktopWidget : public QWidget
+{
+public:
+ QSingleDesktopWidget();
+ ~QSingleDesktopWidget();
+};
+
+QSingleDesktopWidget::QSingleDesktopWidget()
+ : QWidget(0, Qt::Desktop)
+{
+}
+
+QSingleDesktopWidget::~QSingleDesktopWidget()
+{
+ const QObjectList &childList = children();
+ for (int i = childList.size(); i > 0 ;) {
+ --i;
+ childList.at(i)->setParent(0);
+ }
+}
+
+
+class QDesktopWidgetPrivate : public QWidgetPrivate
+{
+public:
+ QDesktopWidgetPrivate();
+ ~QDesktopWidgetPrivate();
+
+ void init();
+
+ bool use_xinerama;
+ int defaultScreen;
+ int screenCount;
+
+ QWidget **screens;
+ QRect *rects;
+ QRect *workareas;
+};
+
+QDesktopWidgetPrivate::QDesktopWidgetPrivate()
+ : use_xinerama(false), defaultScreen(0), screenCount(1),
+ screens(0), rects(0), workareas(0)
+{
+}
+
+QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
+{
+ if (screens) {
+ for (int i = 0; i < screenCount; ++i) {
+ if (i == defaultScreen) continue;
+ delete screens[i];
+ screens[i] = 0;
+ }
+
+ free (screens);
+ }
+
+ if (rects) delete [] rects;
+ if (workareas) delete [] workareas;
+}
+
+void QDesktopWidgetPrivate::init()
+{
+ // get the screen count
+ int newScreenCount = ScreenCount(X11->display);
+#ifndef QT_NO_XINERAMA
+
+ XineramaScreenInfo *xinerama_screeninfo = 0;
+
+ // we ignore the Xinerama extension when using the display is
+ // using traditional multi-screen (with multiple root windows)
+ if (newScreenCount == 1
+ && X11->ptrXineramaQueryExtension
+ && X11->ptrXineramaIsActive
+ && X11->ptrXineramaQueryScreens) {
+ int unused;
+ use_xinerama = (X11->ptrXineramaQueryExtension(X11->display, &unused, &unused)
+ && X11->ptrXineramaIsActive(X11->display));
+ }
+
+ if (use_xinerama) {
+ xinerama_screeninfo =
+ X11->ptrXineramaQueryScreens(X11->display, &newScreenCount);
+ }
+
+ if (xinerama_screeninfo) {
+ defaultScreen = 0;
+ } else
+#endif // QT_NO_XINERAMA
+ {
+ defaultScreen = DefaultScreen(X11->display);
+ newScreenCount = ScreenCount(X11->display);
+ use_xinerama = false;
+ }
+
+ delete [] rects;
+ rects = new QRect[newScreenCount];
+ delete [] workareas;
+ workareas = new QRect[newScreenCount];
+
+ // get the geometry of each screen
+ int i, j, x, y, w, h;
+ for (i = 0, j = 0; i < newScreenCount; i++, j++) {
+
+#ifndef QT_NO_XINERAMA
+ if (use_xinerama) {
+ x = xinerama_screeninfo[i].x_org;
+ y = xinerama_screeninfo[i].y_org;
+ w = xinerama_screeninfo[i].width;
+ h = xinerama_screeninfo[i].height;
+ } else
+#endif // QT_NO_XINERAMA
+ {
+ x = 0;
+ y = 0;
+ w = WidthOfScreen(ScreenOfDisplay(X11->display, i));
+ h = HeightOfScreen(ScreenOfDisplay(X11->display, i));
+ }
+
+ rects[j].setRect(x, y, w, h);
+
+ if (use_xinerama && j > 0 && rects[j-1].intersects(rects[j])) {
+ // merge a "cloned" screen with the previous, hiding all crtcs
+ // that are currently showing a sub-rect of the previous screen
+ if ((rects[j].width()*rects[j].height()) >
+ (rects[j-1].width()*rects[j-1].height()))
+ rects[j-1] = rects[j];
+ j--;
+ }
+
+ workareas[i] = QRect();
+ }
+
+ if (screens) {
+ // leaks QWidget* pointers on purpose, can't delete them as pointer escapes
+ screens = (QWidget**) realloc(screens, j * sizeof(QWidget*));
+ if (j > screenCount)
+ memset(&screens[screenCount], 0, (j-screenCount) * sizeof(QWidget*));
+ }
+
+ screenCount = j;
+
+#ifndef QT_NO_XINERAMA
+ if (use_xinerama && screenCount == 1)
+ use_xinerama = false;
+
+ if (xinerama_screeninfo)
+ XFree(xinerama_screeninfo);
+#endif // QT_NO_XINERAMA
+
+}
+
+// the QDesktopWidget itself will be created on the default screen
+// as qt_x11_create_desktop_on_screen defaults to -1
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ Q_D(QDesktopWidget);
+ d->init();
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ Q_D(const QDesktopWidget);
+ return d->use_xinerama;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ Q_D(const QDesktopWidget);
+ return d->defaultScreen;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ Q_D(const QDesktopWidget);
+ return d->screenCount;
+}
+
+QWidget *QDesktopWidget::screen(int screen)
+{
+ Q_D(QDesktopWidget);
+ if (d->use_xinerama)
+ return this;
+
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->defaultScreen;
+
+ if (! d->screens) {
+ d->screens = (QWidget**) calloc( d->screenCount, sizeof(QWidget*));
+ d->screens[d->defaultScreen] = this;
+ }
+
+ if (! d->screens[screen] || // not created yet
+ ! (d->screens[screen]->windowType() == Qt::Desktop)) { // reparented away
+ qt_x11_create_desktop_on_screen = screen;
+ d->screens[screen] = new QSingleDesktopWidget;
+ qt_x11_create_desktop_on_screen = -1;
+ }
+
+ return d->screens[screen];
+}
+
+const QRect QDesktopWidget::availableGeometry(int screen) const
+{
+ Q_D(const QDesktopWidget);
+ if (qt_desktopwidget_workarea_dirty) {
+ // the workareas are dirty, invalidate them
+ for (int i = 0; i < d->screenCount; ++i)
+ d->workareas[i] = QRect();
+ qt_desktopwidget_workarea_dirty = false;
+ }
+
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->defaultScreen;
+
+ if (d->workareas[screen].isValid())
+ return d->workareas[screen];
+
+ if ((d->screenCount == 1 || !isVirtualDesktop())
+ && X11->isSupportedByWM(ATOM(_NET_WORKAREA))) {
+ Atom ret;
+ int format, e;
+ unsigned char *data = 0;
+ unsigned long nitems, after;
+
+ e = XGetWindowProperty(X11->display,
+ QX11Info::appRootWindow(screen),
+ ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL,
+ &ret, &format, &nitems, &after, &data);
+
+ if (e == Success && ret == XA_CARDINAL &&
+ format == 32 && nitems == 4) {
+ long *workarea = (long *) data;
+ d->workareas[screen].setRect(workarea[0], workarea[1],
+ workarea[2], workarea[3]);
+ } else {
+ d->workareas[screen] = screenGeometry(screen);
+ }
+ if (data)
+ XFree(data);
+ } else {
+ d->workareas[screen] = screenGeometry(screen);
+ }
+
+ return d->workareas[screen];
+}
+
+const QRect QDesktopWidget::screenGeometry(int screen) const
+{
+ Q_D(const QDesktopWidget);
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->defaultScreen;
+
+ return d->rects[screen];
+}
+
+int QDesktopWidget::screenNumber(const QWidget *widget) const
+{
+ Q_D(const QDesktopWidget);
+ if (!widget)
+ return d->defaultScreen;
+
+#ifndef QT_NO_XINERAMA
+ if (d->use_xinerama) {
+ // this is how we do it for xinerama
+ QRect frame = widget->frameGeometry();
+ if (!widget->isWindow())
+ frame.moveTopLeft(widget->mapToGlobal(QPoint(0, 0)));
+
+ int maxSize = -1;
+ int maxScreen = -1;
+
+ for (int i = 0; i < d->screenCount; ++i) {
+ QRect sect = d->rects[i].intersected(frame);
+ int size = sect.width() * sect.height();
+ if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
+ maxSize = size;
+ maxScreen = i;
+ }
+ }
+ return maxScreen;
+ }
+#endif // QT_NO_XINERAMA
+
+ return widget->x11Info().screen();
+}
+
+int QDesktopWidget::screenNumber(const QPoint &point) const
+{
+ Q_D(const QDesktopWidget);
+ int closestScreen = -1;
+ int shortestDistance = INT_MAX;
+ for (int i = 0; i < d->screenCount; ++i) {
+ int thisDistance = d->pointToRect(point, d->rects[i]);
+ if (thisDistance < shortestDistance) {
+ shortestDistance = thisDistance;
+ closestScreen = i;
+ }
+ }
+ return closestScreen;
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *event)
+{
+ Q_D(QDesktopWidget);
+ d->init();
+ qt_desktopwidget_workarea_dirty = true;
+ QWidget::resizeEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
new file mode 100644
index 0000000000..a5092a0be0
--- /dev/null
+++ b/src/gui/kernel/qdnd.cpp
@@ -0,0 +1,697 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qbitmap.h"
+#include "qdrag.h"
+#include "qpixmap.h"
+#include "qevent.h"
+#include "qfile.h"
+#include "qtextcodec.h"
+#include "qapplication.h"
+#include "qpoint.h"
+#include "qwidget.h"
+#include "qbuffer.h"
+#include "qimage.h"
+#include "qregexp.h"
+#include "qdir.h"
+#include "qdnd_p.h"
+#include "qimagereader.h"
+#include "qimagewriter.h"
+#include "qdebug.h"
+#include <ctype.h>
+
+#ifndef QT_NO_DRAGANDDROP
+
+QT_BEGIN_NAMESPACE
+
+// These pixmaps approximate the images in the Windows User Interface Guidelines.
+
+// XPM
+
+static const char * const move_xpm[] = {
+"11 20 3 1",
+". c None",
+#if defined(Q_WS_WIN)
+"a c #000000",
+"X c #FFFFFF", // Windows cursor is traditionally white
+#else
+"a c #FFFFFF",
+"X c #000000", // X11 cursor is traditionally black
+#endif
+"aa.........",
+"aXa........",
+"aXXa.......",
+"aXXXa......",
+"aXXXXa.....",
+"aXXXXXa....",
+"aXXXXXXa...",
+"aXXXXXXXa..",
+"aXXXXXXXXa.",
+"aXXXXXXXXXa",
+"aXXXXXXaaaa",
+"aXXXaXXa...",
+"aXXaaXXa...",
+"aXa..aXXa..",
+"aa...aXXa..",
+"a.....aXXa.",
+"......aXXa.",
+".......aXXa",
+".......aXXa",
+"........aa."};
+
+#ifdef Q_WS_WIN
+/* XPM */
+static const char * const ignore_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa.....XXXX.....",
+".......aXXa..XXaaaaXX...",
+".......aXXa.XaaaaaaaaX..",
+"........aa.XaaaXXXXaaaX.",
+"...........XaaaaX..XaaX.",
+"..........XaaXaaaX..XaaX",
+"..........XaaXXaaaX.XaaX",
+"..........XaaX.XaaaXXaaX",
+"..........XaaX..XaaaXaaX",
+"...........XaaX..XaaaaX.",
+"...........XaaaXXXXaaaX.",
+"............XaaaaaaaaX..",
+".............XXaaaaXX...",
+"...............XXXX....."};
+#endif
+
+/* XPM */
+static const char * const copy_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXaaaaaXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+/* XPM */
+static const char * const link_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXaaaaXXa",
+".............aXXXXaaaXXa",
+".............aXXXaaaaXXa",
+".............aXXaaaXaXXa",
+".............aXXaaXXXXXa",
+".............aXXaXXXXXXa",
+".............aXXXaXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+#ifndef QT_NO_DRAGANDDROP
+
+//#define QDND_DEBUG
+
+#ifdef QDND_DEBUG
+QString dragActionsToString(Qt::DropActions actions)
+{
+ QString str;
+ if (actions == Qt::IgnoreAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "IgnoreAction";
+ }
+ if (actions & Qt::LinkAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "LinkAction";
+ }
+ if (actions & Qt::CopyAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "CopyAction";
+ }
+ if (actions & Qt::MoveAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "MoveAction";
+ }
+ if ((actions & Qt::TargetMoveAction) == Qt::TargetMoveAction ) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "TargetMoveAction";
+ }
+ return str;
+}
+
+QString KeyboardModifiersToString(Qt::KeyboardModifiers moderfies)
+{
+ QString str;
+ if (moderfies & Qt::ControlModifier) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += Qt::ControlModifier;
+ }
+ if (moderfies & Qt::AltModifier) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += Qt::AltModifier;
+ }
+ if (moderfies & Qt::ShiftModifier) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += Qt::ShiftModifier;
+ }
+ return str;
+}
+#endif
+
+
+// the universe's only drag manager
+QDragManager *QDragManager::instance = 0;
+
+
+QDragManager::QDragManager()
+ : QObject(qApp)
+{
+ Q_ASSERT(!instance);
+
+#ifdef Q_WS_WIN
+ n_cursor = 4;
+#else
+ n_cursor = 3;
+#endif
+
+#ifdef Q_WS_QWS
+ currentActionForOverrideCursor = Qt::IgnoreAction;
+#endif
+ pm_cursor = new QPixmap[n_cursor];
+ pm_cursor[0] = QPixmap((const char **)move_xpm);
+ pm_cursor[1] = QPixmap((const char **)copy_xpm);
+ pm_cursor[2] = QPixmap((const char **)link_xpm);
+#ifdef Q_WS_WIN
+ pm_cursor[3] = QPixmap((const char **)ignore_xpm);
+#endif
+ object = 0;
+ beingCancelled = false;
+ restoreCursor = false;
+ willDrop = false;
+ eventLoop = 0;
+ dropData = new QDropData();
+ currentDropTarget = 0;
+#ifdef Q_WS_X11
+ xdndMimeTransferedPixmapIndex = 0;
+#endif
+}
+
+
+QDragManager::~QDragManager()
+{
+#ifndef QT_NO_CURSOR
+ if (restoreCursor)
+ QApplication::restoreOverrideCursor();
+#endif
+ instance = 0;
+ delete [] pm_cursor;
+ delete dropData;
+}
+
+QDragManager *QDragManager::self()
+{
+ if (!instance && qApp && !qApp->closingDown())
+ instance = new QDragManager;
+ return instance;
+}
+
+QPixmap QDragManager::dragCursor(Qt::DropAction action) const
+{
+ QDragPrivate * d = dragPrivate();
+ if (d && d->customCursors.contains(action))
+ return d->customCursors[action];
+ else if (action == Qt::MoveAction)
+ return pm_cursor[0];
+ else if (action == Qt::CopyAction)
+ return pm_cursor[1];
+ else if (action == Qt::LinkAction)
+ return pm_cursor[2];
+#ifdef Q_WS_WIN
+ else if (action == Qt::IgnoreAction)
+ return pm_cursor[3];
+#endif
+ return QPixmap();
+}
+
+bool QDragManager::hasCustomDragCursors() const
+{
+ QDragPrivate * d = dragPrivate();
+ return d && !d->customCursors.isEmpty();
+}
+
+Qt::DropAction QDragManager::defaultAction(Qt::DropActions possibleActions,
+ Qt::KeyboardModifiers modifiers) const
+{
+#ifdef QDND_DEBUG
+ qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)");
+ qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1());
+#endif
+
+ QDragPrivate *d = dragPrivate();
+ Qt::DropAction defaultAction = d ? d->defaultDropAction : Qt::IgnoreAction;
+
+ if (defaultAction == Qt::IgnoreAction) {
+ //This means that the drag was initiated by QDrag::start and we need to
+ //preserve the old behavior
+#ifdef Q_WS_MAC
+ defaultAction = Qt::MoveAction;
+#else
+ defaultAction = Qt::CopyAction;
+#endif
+ }
+
+#ifdef Q_WS_MAC
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::AltModifier)
+ defaultAction = Qt::LinkAction;
+ else if (modifiers & Qt::AltModifier)
+ defaultAction = Qt::CopyAction;
+ else if (modifiers & Qt::ControlModifier)
+ defaultAction = Qt::MoveAction;
+#else
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier)
+ defaultAction = Qt::LinkAction;
+ else if (modifiers & Qt::ControlModifier)
+ defaultAction = Qt::CopyAction;
+ else if (modifiers & Qt::ShiftModifier)
+ defaultAction = Qt::MoveAction;
+ else if (modifiers & Qt::AltModifier)
+ defaultAction = Qt::LinkAction;
+#endif
+
+ // if the object is set take the list of possibles from it
+ if (object)
+ possibleActions = object->d_func()->possible_actions;
+
+#ifdef QDND_DEBUG
+ qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1());
+#endif
+
+ // Check if the action determined is allowed
+ if (!(possibleActions & defaultAction)) {
+ if (possibleActions & Qt::CopyAction)
+ defaultAction = Qt::CopyAction;
+ else if (possibleActions & Qt::MoveAction)
+ defaultAction = Qt::MoveAction;
+ else if (possibleActions & Qt::LinkAction)
+ defaultAction = Qt::LinkAction;
+ else
+ defaultAction = Qt::IgnoreAction;
+ }
+
+#ifdef QDND_DEBUG
+ qDebug("default action : %s", dragActionsToString(defaultAction).latin1());
+#endif
+
+ return defaultAction;
+}
+
+void QDragManager::setCurrentTarget(QWidget *target, bool dropped)
+{
+ if (currentDropTarget == target)
+ return;
+
+ currentDropTarget = target;
+ if (!dropped && object) {
+ object->d_func()->target = target;
+ emit object->targetChanged(target);
+ }
+
+}
+
+QWidget *QDragManager::currentTarget()
+{
+ return currentDropTarget;
+}
+
+#endif
+
+QDropData::QDropData()
+ : QInternalMimeData()
+{
+}
+
+QDropData::~QDropData()
+{
+}
+#endif // QT_NO_DRAGANDDROP
+
+#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
+
+static QStringList imageReadMimeFormats()
+{
+ QStringList formats;
+ QList<QByteArray> imageFormats = QImageReader::supportedImageFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ QString format = QLatin1String("image/");
+ format += QString::fromLatin1(imageFormats.at(i).toLower());
+ formats.append(format);
+ }
+
+ //put png at the front because it is best
+ int pngIndex = formats.indexOf(QLatin1String("image/png"));
+ if (pngIndex != -1 && pngIndex != 0)
+ formats.move(pngIndex, 0);
+
+ return formats;
+}
+
+
+static QStringList imageWriteMimeFormats()
+{
+ QStringList formats;
+ QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ QString format = QLatin1String("image/");
+ format += QString::fromLatin1(imageFormats.at(i).toLower());
+ formats.append(format);
+ }
+
+ //put png at the front because it is best
+ int pngIndex = formats.indexOf(QLatin1String("image/png"));
+ if (pngIndex != -1 && pngIndex != 0)
+ formats.move(pngIndex, 0);
+
+ return formats;
+}
+
+QInternalMimeData::QInternalMimeData()
+ : QMimeData()
+{
+}
+
+QInternalMimeData::~QInternalMimeData()
+{
+}
+
+bool QInternalMimeData::hasFormat(const QString &mimeType) const
+{
+ bool foundFormat = hasFormat_sys(mimeType);
+ if (!foundFormat && mimeType == QLatin1String("application/x-qt-image")) {
+ QStringList imageFormats = imageReadMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if ((foundFormat = hasFormat_sys(imageFormats.at(i))))
+ break;
+ }
+ }
+ return foundFormat;
+}
+
+QStringList QInternalMimeData::formats() const
+{
+ QStringList realFormats = formats_sys();
+ if (!realFormats.contains(QLatin1String("application/x-qt-image"))) {
+ QStringList imageFormats = imageReadMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if (realFormats.contains(imageFormats.at(i))) {
+ realFormats += QLatin1String("application/x-qt-image");
+ break;
+ }
+ }
+ }
+ return realFormats;
+}
+
+QVariant QInternalMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant data = retrieveData_sys(mimeType, type);
+ if (mimeType == QLatin1String("application/x-qt-image")) {
+ if (data.isNull() || (data.type() == QVariant::ByteArray && data.toByteArray().isEmpty())) {
+ // try to find an image
+ QStringList imageFormats = imageReadMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ data = retrieveData_sys(imageFormats.at(i), type);
+ if (data.isNull() || (data.type() == QVariant::ByteArray && data.toByteArray().isEmpty()))
+ continue;
+ break;
+ }
+ }
+ // we wanted some image type, but all we got was a byte array. Convert it to an image.
+ if (data.type() == QVariant::ByteArray
+ && (type == QVariant::Image || type == QVariant::Pixmap || type == QVariant::Bitmap))
+ data = QImage::fromData(data.toByteArray());
+
+ } else if (mimeType == QLatin1String("application/x-color") && data.type() == QVariant::ByteArray) {
+ QColor c;
+ QByteArray ba = data.toByteArray();
+ if (ba.size() == 8) {
+ ushort * colBuf = (ushort *)ba.data();
+ c.setRgbF(qreal(colBuf[0]) / qreal(0xFFFF),
+ qreal(colBuf[1]) / qreal(0xFFFF),
+ qreal(colBuf[2]) / qreal(0xFFFF),
+ qreal(colBuf[3]) / qreal(0xFFFF));
+ data = c;
+ } else {
+ qWarning("Qt: Invalid color format");
+ }
+ } else if (data.type() != type && data.type() == QVariant::ByteArray) {
+ // try to use mime data's internal conversion stuf.
+ QInternalMimeData *that = const_cast<QInternalMimeData *>(this);
+ that->setData(mimeType, data.toByteArray());
+ data = QMimeData::retrieveData(mimeType, type);
+ that->clear();
+ }
+ return data;
+}
+
+bool QInternalMimeData::canReadData(const QString &mimeType)
+{
+ return imageReadMimeFormats().contains(mimeType);
+}
+
+// helper functions for rendering mimedata to the system, this is needed because QMimeData is in core.
+QStringList QInternalMimeData::formatsHelper(const QMimeData *data)
+{
+ QStringList realFormats = data->formats();
+ if (realFormats.contains(QLatin1String("application/x-qt-image"))) {
+ // add all supported image formats
+ QStringList imageFormats = imageWriteMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if (!realFormats.contains(imageFormats.at(i)))
+ realFormats.append(imageFormats.at(i));
+ }
+ }
+ return realFormats;
+}
+
+bool QInternalMimeData::hasFormatHelper(const QString &mimeType, const QMimeData *data)
+{
+
+ bool foundFormat = data->hasFormat(mimeType);
+ if (!foundFormat) {
+ if (mimeType == QLatin1String("application/x-qt-image")) {
+ // check all supported image formats
+ QStringList imageFormats = imageWriteMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if ((foundFormat = data->hasFormat(imageFormats.at(i))))
+ break;
+ }
+ } else if (mimeType.startsWith(QLatin1String("image/"))) {
+ return data->hasImage() && imageWriteMimeFormats().contains(mimeType);
+ }
+ }
+ return foundFormat;
+}
+
+QByteArray QInternalMimeData::renderDataHelper(const QString &mimeType, const QMimeData *data)
+{
+ QByteArray ba;
+ if (mimeType == QLatin1String("application/x-color")) {
+ /* QMimeData can only provide colors as QColor or the name
+ of a color as a QByteArray or a QString. So we need to do
+ the conversion to application/x-color here.
+ The application/x-color format is :
+ type: application/x-color
+ format: 16
+ data[0]: red
+ data[1]: green
+ data[2]: blue
+ data[3]: opacity
+ */
+ ba.resize(8);
+ ushort * colBuf = (ushort *)ba.data();
+ QColor c = qvariant_cast<QColor>(data->colorData());
+ colBuf[0] = ushort(c.redF() * 0xFFFF);
+ colBuf[1] = ushort(c.greenF() * 0xFFFF);
+ colBuf[2] = ushort(c.blueF() * 0xFFFF);
+ colBuf[3] = ushort(c.alphaF() * 0xFFFF);
+ } else {
+ ba = data->data(mimeType);
+ if (ba.isEmpty()) {
+ if (mimeType == QLatin1String("application/x-qt-image") && data->hasImage()) {
+ QImage image = qvariant_cast<QImage>(data->imageData());
+ QBuffer buf(&ba);
+ buf.open(QBuffer::WriteOnly);
+ // would there not be PNG ??
+ image.save(&buf, "PNG");
+ } else if (mimeType.startsWith(QLatin1String("image/")) && data->hasImage()) {
+ QImage image = qvariant_cast<QImage>(data->imageData());
+ QBuffer buf(&ba);
+ buf.open(QBuffer::WriteOnly);
+ image.save(&buf, mimeType.mid(mimeType.indexOf(QLatin1Char('/')) + 1).toLatin1().toUpper());
+ }
+ }
+ }
+ return ba;
+}
+
+#endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd_mac.mm b/src/gui/kernel/qdnd_mac.mm
new file mode 100644
index 0000000000..0b8a48569e
--- /dev/null
+++ b/src/gui/kernel/qdnd_mac.mm
@@ -0,0 +1,749 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#ifndef QT_NO_DRAGANDDROP
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qurl.h"
+#include "qwidget.h"
+#include "qfile.h"
+#include "qfileinfo.h"
+#include <stdlib.h>
+#include <string.h>
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
+
+#include <private/qapplication_p.h>
+#include <private/qwidget_p.h>
+#include <private/qdnd_p.h>
+#include <private/qt_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+QMacDndAnswerRecord qt_mac_dnd_answer_rec;
+
+/*****************************************************************************
+ QDnD debug facilities
+ *****************************************************************************/
+//#define DEBUG_DRAG_EVENTS
+//#define DEBUG_DRAG_PROMISES
+
+/*****************************************************************************
+ QDnD globals
+ *****************************************************************************/
+bool qt_mac_in_drag = false;
+#ifndef QT_MAC_USE_COCOA
+static DragReference qt_mac_current_dragRef = 0;
+#endif
+
+/*****************************************************************************
+ Externals
+ *****************************************************************************/
+extern void qt_mac_send_modifiers_changed(quint32, QObject *); //qapplication_mac.cpp
+extern uint qGlobalPostedEventsCount(); //qapplication.cpp
+extern RgnHandle qt_mac_get_rgn(); // qregion_mac.cpp
+extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp
+/*****************************************************************************
+ QDnD utility functions
+ *****************************************************************************/
+
+//default pixmap
+static const int default_pm_hotx = -2;
+static const int default_pm_hoty = -16;
+#ifndef QT_MAC_USE_COCOA
+static const char * const default_pm[] = {
+ "13 9 3 1",
+ ". c None",
+ " c #000000",
+ "X c #FFFFFF",
+ "X X X X X X X",
+ " X X X X X X ",
+ "X ......... X",
+ " X.........X ",
+ "X ......... X",
+ " X.........X ",
+ "X ......... X",
+ " X X X X X X ",
+ "X X X X X X X",
+};
+#endif
+
+//action management
+#ifdef DEBUG_DRAG_EVENTS
+# define MAP_MAC_ENUM(x) x, #x
+#else
+# define MAP_MAC_ENUM(x) x
+#endif
+struct mac_enum_mapper
+{
+ int mac_code;
+ int qt_code;
+#ifdef DEBUG_DRAG_EVENTS
+ char *qt_desc;
+#endif
+};
+#ifndef QT_MAC_USE_COCOA
+static mac_enum_mapper dnd_action_symbols[] = {
+ { kDragActionAlias, MAP_MAC_ENUM(Qt::LinkAction) },
+ { kDragActionMove, MAP_MAC_ENUM(Qt::MoveAction) },
+ { kDragActionGeneric, MAP_MAC_ENUM(Qt::CopyAction) },
+ { kDragActionCopy, MAP_MAC_ENUM(Qt::CopyAction) },
+ { 0, MAP_MAC_ENUM(0) }
+};
+static DragActions qt_mac_dnd_map_qt_actions(Qt::DropActions qActions)
+{
+ DragActions ret = kDragActionNothing;
+ for(int i = 0; dnd_action_symbols[i].qt_code; ++i) {
+ if(qActions & dnd_action_symbols[i].qt_code)
+ ret |= dnd_action_symbols[i].mac_code;
+ }
+ return ret;
+}
+static Qt::DropActions qt_mac_dnd_map_mac_actions(DragActions macActions)
+{
+#ifdef DEBUG_DRAG_EVENTS
+ qDebug("Converting DND ActionList: 0x%lx", macActions);
+#endif
+ Qt::DropActions ret = Qt::IgnoreAction;
+ for(int i = 0; dnd_action_symbols[i].qt_code; ++i) {
+#ifdef DEBUG_DRAG_EVENTS
+ qDebug(" %d) [%s] : %s", i, dnd_action_symbols[i].qt_desc,
+ (macActions & dnd_action_symbols[i].mac_code) ? "true" : "false");
+#endif
+ if(macActions & dnd_action_symbols[i].mac_code)
+ ret |= Qt::DropAction(dnd_action_symbols[i].qt_code);
+ }
+ return ret;
+}
+static Qt::DropAction qt_mac_dnd_map_mac_default_action(DragActions macActions)
+{
+ static Qt::DropAction preferred_actions[] = { Qt::CopyAction, Qt::LinkAction, //in order
+ Qt::MoveAction, Qt::IgnoreAction };
+ Qt::DropAction ret = Qt::IgnoreAction;
+ const Qt::DropActions qtActions = qt_mac_dnd_map_mac_actions(macActions);
+ for(int i = 0; preferred_actions[i] != Qt::IgnoreAction; ++i) {
+ if(qtActions & preferred_actions[i]) {
+ ret = preferred_actions[i];
+ break;
+ }
+ }
+#ifdef DEBUG_DRAG_EVENTS
+ for(int i = 0; dnd_action_symbols[i].qt_code; ++i) {
+ if(dnd_action_symbols[i].qt_code == ret) {
+ qDebug("Got default action: %s [0x%lx]", dnd_action_symbols[i].qt_desc, macActions);
+ break;
+ }
+ }
+#endif
+ return ret;
+}
+static void qt_mac_dnd_update_action(DragReference dragRef) {
+ SInt16 modifiers;
+ GetDragModifiers(dragRef, &modifiers, 0, 0);
+ qt_mac_send_modifiers_changed(modifiers, qApp);
+
+ Qt::DropAction qtAction = Qt::IgnoreAction;
+ {
+ DragActions macAllowed = kDragActionNothing;
+ GetDragDropAction(dragRef, &macAllowed);
+ Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(macAllowed);
+ qtAction = QDragManager::self()->defaultAction(qtAllowed, QApplication::keyboardModifiers());
+#if 1
+ if(!(qtAllowed & qtAction))
+ qtAction = qt_mac_dnd_map_mac_default_action(macAllowed);
+#endif
+ }
+ DragActions macAction = qt_mac_dnd_map_qt_actions(qtAction);
+
+ DragActions currentActions;
+ GetDragDropAction(dragRef, &currentActions);
+ if(currentActions != macAction) {
+ SetDragDropAction(dragRef, macAction);
+ QDragManager::self()->emitActionChanged(qtAction);
+ }
+}
+#endif // !QT_MAC_USE_COCOA
+
+/*****************************************************************************
+ DnD functions
+ *****************************************************************************/
+bool QDropData::hasFormat_sys(const QString &mime) const
+{
+#ifndef QT_MAC_USE_COCOA
+ OSPasteboardRef board;
+ if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return false;
+ }
+ return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mime);
+#else
+ Q_UNUSED(mime);
+ return false;
+#endif // !QT_MAC_USE_COCOA
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mime, QVariant::Type type) const
+{
+#ifndef QT_MAC_USE_COCOA
+ OSPasteboardRef board;
+ if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return QVariant();
+ }
+ return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mime, type);
+#else
+ Q_UNUSED(mime);
+ Q_UNUSED(type);
+ return QVariant();
+#endif // !QT_MAC_USE_COCOA
+}
+
+QStringList QDropData::formats_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ OSPasteboardRef board;
+ if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return QStringList();
+ }
+ return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats();
+#else
+ return QStringList();
+#endif
+}
+
+void QDragManager::timerEvent(QTimerEvent*)
+{
+}
+
+bool QDragManager::eventFilter(QObject *, QEvent *)
+{
+ return false;
+}
+
+void QDragManager::updateCursor()
+{
+}
+
+void QDragManager::cancel(bool)
+{
+ if(object) {
+ beingCancelled = true;
+ object = 0;
+ }
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd);
+#endif
+}
+
+void QDragManager::move(const QPoint &)
+{
+}
+
+void QDragManager::drop()
+{
+}
+
+/**
+ If a drop action is already set on the carbon event
+ (from e.g. an earlier enter event), we insert the same
+ action on the new Qt event that has yet to be sendt.
+*/
+static inline bool qt_mac_set_existing_drop_action(const DragRef &dragRef, QDropEvent &event)
+{
+#ifndef QT_MAC_USE_COCOA
+ DragActions currentAction = kDragActionNothing;
+ OSStatus err = GetDragDropAction(dragRef, &currentAction);
+ if (err == noErr && currentAction != kDragActionNothing) {
+ // This looks a bit evil, but we only ever set one action, so it's OK.
+ event.setDropAction(Qt::DropAction(int(qt_mac_dnd_map_mac_actions(currentAction))));
+ return true;
+ }
+#else
+ Q_UNUSED(dragRef);
+ Q_UNUSED(event);
+#endif
+ return false;
+}
+
+/**
+ If an answer rect has been set on the event (after being sent
+ to the global event processor), we store that rect so we can
+ check if the mouse is in the same area upon next drag move event.
+*/
+void qt_mac_copy_answer_rect(const QDragMoveEvent &event)
+{
+ if (!event.answerRect().isEmpty()) {
+ qt_mac_dnd_answer_rec.rect = event.answerRect();
+ qt_mac_dnd_answer_rec.buttons = event.mouseButtons();
+ qt_mac_dnd_answer_rec.modifiers = event.keyboardModifiers();
+ qt_mac_dnd_answer_rec.lastAction = event.dropAction();
+ }
+}
+
+bool qt_mac_mouse_inside_answer_rect(QPoint mouse)
+{
+ if (!qt_mac_dnd_answer_rec.rect.isEmpty()
+ && qt_mac_dnd_answer_rec.rect.contains(mouse)
+ && QApplication::mouseButtons() == qt_mac_dnd_answer_rec.buttons
+ && QApplication::keyboardModifiers() == qt_mac_dnd_answer_rec.modifiers)
+ return true;
+ else
+ return false;
+}
+
+bool QWidgetPrivate::qt_mac_dnd_event(uint kind, DragRef dragRef)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_Q(QWidget);
+ qt_mac_current_dragRef = dragRef;
+ if (kind != kEventControlDragLeave)
+ qt_mac_dnd_update_action(dragRef);
+
+ Point mouse;
+ GetDragMouse(dragRef, &mouse, 0L);
+ if(!mouse.h && !mouse.v)
+ GetGlobalMouse(&mouse);
+
+ if(QApplicationPrivate::modalState()) {
+ for(QWidget *modal = q; modal; modal = modal->parentWidget()) {
+ if(modal->isWindow()) {
+ if(modal != QApplication::activeModalWidget())
+ return noErr;
+ break;
+ }
+ }
+ }
+
+ //lookup the possible actions
+ DragActions allowed = kDragActionNothing;
+ GetDragAllowableActions(dragRef, &allowed);
+ Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(allowed);
+
+ //lookup the source dragAccepted
+ QMimeData *dropdata = QDragManager::self()->dropData;
+ if(QDragManager::self()->source())
+ dropdata = QDragManager::self()->dragPrivate()->data;
+
+ // 'interrestedInDrag' should end up being 'true' if a later drop
+ // will be accepted by the widget for the current mouse position
+ bool interrestedInDrag = true;
+
+ //Dispatch events
+ if (kind == kEventControlDragWithin) {
+ if (qt_mac_mouse_inside_answer_rect(q->mapFromGlobal(QPoint(mouse.h, mouse.v))))
+ return qt_mac_dnd_answer_rec.lastAction == Qt::IgnoreAction;
+ else
+ qt_mac_dnd_answer_rec.clear();
+
+ QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+
+ // Accept the event by default if a
+ // drag action exists on the carbon event
+ if (qt_mac_set_existing_drop_action(dragRef, qDMEvent))
+ qDMEvent.accept();
+
+ QApplication::sendEvent(q, &qDMEvent);
+ if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction)
+ interrestedInDrag = false;
+
+ qt_mac_copy_answer_rect(qDMEvent);
+ SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction()));
+
+ } else if (kind == kEventControlDragEnter) {
+ qt_mac_dnd_answer_rec.clear();
+
+ QDragEnterEvent qDEEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ qt_mac_set_existing_drop_action(dragRef, qDEEvent);
+ QApplication::sendEvent(q, &qDEEvent);
+ SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDEEvent.dropAction()));
+
+ if (!qDEEvent.isAccepted())
+ // The widget is simply not interrested in this
+ // drag. So tell carbon this by returning 'false'. We will then
+ // not receive any further move, drop or leave events for this widget.
+ return false;
+ else {
+ // Documentation states that a drag move event is sendt immidiatly after
+ // a drag enter event. So we do that. This will honor widgets overriding
+ // 'dragMoveEvent' only, and not 'dragEnterEvent'
+ QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ qDMEvent.accept(); // accept by default, since enter event was accepted.
+ qDMEvent.setDropAction(qDEEvent.dropAction());
+ QApplication::sendEvent(q, &qDMEvent);
+ if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction)
+ interrestedInDrag = false;
+
+ qt_mac_copy_answer_rect(qDMEvent);
+ SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction()));
+ }
+
+ } else if(kind == kEventControlDragLeave) {
+ QDragLeaveEvent de;
+ QApplication::sendEvent(q, &de);
+ } else if(kind == kEventControlDragReceive) {
+ QDropEvent de(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ if(QDragManager::self()->object)
+ QDragManager::self()->dragPrivate()->target = q;
+ QApplication::sendEvent(q, &de);
+ if(!de.isAccepted()) {
+ interrestedInDrag = false;
+ SetDragDropAction(dragRef, kDragActionNothing);
+ } else {
+ if(QDragManager::self()->object)
+ QDragManager::self()->dragPrivate()->executed_action = de.dropAction();
+ SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(de.dropAction()));
+ }
+ }
+
+#ifdef DEBUG_DRAG_EVENTS
+ {
+ const char *desc = 0;
+ switch(kind) {
+ case kEventControlDragWithin: desc = "DragMove"; break;
+ case kEventControlDragEnter: desc = "DragEnter"; break;
+ case kEventControlDragLeave: desc = "DragLeave"; break;
+ case kEventControlDragReceive: desc = "DragDrop"; break;
+ }
+ if(desc) {
+ QPoint pos(q->mapFromGlobal(QPoint(mouse.h, mouse.v)));
+ qDebug("Sending <%s>(%d, %d) event to %p(%s::%s) [%d] (%p)",
+ desc, pos.x(), pos.y(), q, q->metaObject()->className(),
+ q->objectName().toLocal8Bit().constData(), ret, dragRef);
+ }
+ }
+#endif
+
+ //set the cursor
+ bool found_cursor = false;
+ if(kind == kEventControlDragWithin || kind == kEventControlDragEnter) {
+ ThemeCursor cursor = kThemeNotAllowedCursor;
+ found_cursor = true;
+ if (interrestedInDrag) {
+ DragActions action = kDragActionNothing;
+ GetDragDropAction(dragRef, &action);
+ switch(qt_mac_dnd_map_mac_default_action(action)) {
+ case Qt::IgnoreAction:
+ cursor = kThemeNotAllowedCursor;
+ break;
+ case Qt::MoveAction:
+ cursor = kThemeArrowCursor;
+ break;
+ case Qt::CopyAction:
+ cursor = kThemeCopyArrowCursor;
+ break;
+ case Qt::LinkAction:
+ cursor = kThemeAliasArrowCursor;
+ break;
+ default:
+ cursor = kThemeNotAllowedCursor;
+ break;
+ }
+ }
+ SetThemeCursor(cursor);
+ }
+ if(found_cursor) {
+ qt_mac_set_cursor(0, QPoint()); //just use our's
+ } else {
+ QCursor cursor(Qt::ArrowCursor);
+ if(qApp && qApp->overrideCursor()) {
+ cursor = *qApp->overrideCursor();
+ } else if(q) {
+ for(QWidget *p = q; p; p = p->parentWidget()) {
+ if(p->isEnabled() && p->testAttribute(Qt::WA_SetCursor)) {
+ cursor = p->cursor();
+ break;
+ }
+ }
+ }
+ qt_mac_set_cursor(&cursor, QPoint(mouse.h, mouse.v));
+ }
+
+ //idle things
+ if(qGlobalPostedEventsCount()) {
+ QApplication::sendPostedEvents();
+ QApplication::flush();
+ }
+
+ // If this was not a drop, tell carbon that we will be interresed in receiving more
+ // events for the current drag. We do that by returning true.
+ if (kind == kEventControlDragReceive)
+ return interrestedInDrag;
+ else
+ return true;
+#else
+ Q_UNUSED(kind);
+ Q_UNUSED(dragRef);
+ return false;
+#endif // !QT_MAC_USE_COCOA
+}
+
+#ifndef QT_MAC_USE_COCOA
+Qt::DropAction QDragManager::drag(QDrag *o)
+{
+
+ if(qt_mac_in_drag) { //just make sure..
+ qWarning("Qt: Internal error: WH0A, unexpected condition reached");
+ return Qt::IgnoreAction;
+ }
+ if(object == o)
+ return Qt::IgnoreAction;
+ /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button
+ so we just bail early to prevent it */
+ if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary))
+ return Qt::IgnoreAction;
+
+ if(object) {
+ dragPrivate()->source->removeEventFilter(this);
+ cancel();
+ beingCancelled = false;
+ }
+
+ object = o;
+ dragPrivate()->target = 0;
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart);
+#endif
+
+ //setup the data
+ QMacPasteboard dragBoard(QMacPasteboardMime::MIME_DND);
+ dragBoard.setMimeData(dragPrivate()->data);
+
+ //create the drag
+ OSErr result;
+ DragRef dragRef;
+ if((result = NewDragWithPasteboard(dragBoard.pasteBoard(), &dragRef)))
+ return Qt::IgnoreAction;
+ //setup the actions
+ DragActions possibleActions = qt_mac_dnd_map_qt_actions(dragPrivate()->possible_actions);
+ SetDragAllowableActions(dragRef, //local
+ possibleActions,
+ true);
+ SetDragAllowableActions(dragRef, //remote (same as local)
+ possibleActions,
+ false);
+
+
+ QPoint hotspot;
+ QPixmap pix = dragPrivate()->pixmap;
+ if(pix.isNull()) {
+ if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) {
+ //get the string
+ QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text()
+ : dragPrivate()->data->urls().first().toString();
+ if(s.length() > 26)
+ s = s.left(23) + QChar(0x2026);
+ if(!s.isEmpty()) {
+ //draw it
+ QFont f(qApp->font());
+ f.setPointSize(12);
+ QFontMetrics fm(f);
+ const int width = fm.width(s);
+ const int height = fm.height();
+ if(width > 0 && height > 0) {
+ QPixmap tmp(width, height);
+ QPainter p(&tmp);
+ p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0);
+ p.setPen(Qt::color1);
+ p.setFont(f);
+ p.drawText(0, fm.ascent(), s);
+ p.end();
+ //save it
+ pix = tmp;
+ hotspot = QPoint(tmp.width() / 2, tmp.height() / 2);
+ }
+ }
+ } else {
+ pix = QPixmap(default_pm);
+ hotspot = QPoint(default_pm_hotx, default_pm_hoty);
+ }
+ } else {
+ hotspot = dragPrivate()->hotspot;
+ }
+
+ //so we must fake an event
+ EventRecord fakeEvent;
+ GetGlobalMouse(&(fakeEvent.where));
+ fakeEvent.message = 0;
+ fakeEvent.what = mouseDown;
+ fakeEvent.when = EventTimeToTicks(GetCurrentEventTime());
+ fakeEvent.modifiers = GetCurrentKeyModifiers();
+ if(GetCurrentEventButtonState() & 2)
+ fakeEvent.modifiers |= controlKey;
+
+ //find the hotspot in relation to the pixmap
+ Point boundsPoint;
+ boundsPoint.h = fakeEvent.where.h - hotspot.x();
+ boundsPoint.v = fakeEvent.where.v - hotspot.y();
+ Rect boundsRect;
+ SetRect(&boundsRect, boundsPoint.h, boundsPoint.v, boundsPoint.h + pix.width(), boundsPoint.v + pix.height());
+
+ //set the drag image
+ QRegion dragRegion(boundsPoint.h, boundsPoint.v, pix.width(), pix.height()), pixRegion;
+ if(!pix.isNull()) {
+ HIPoint hipoint = { -hotspot.x(), -hotspot.y() };
+ CGImageRef img = (CGImageRef)pix.macCGHandle();
+ SetDragImageWithCGImage(dragRef, img, &hipoint, 0);
+ CGImageRelease(img);
+ }
+
+ SetDragItemBounds(dragRef, (ItemReference)1 , &boundsRect);
+ { //do the drag
+ qt_mac_in_drag = true;
+ qt_mac_dnd_update_action(dragRef);
+ result = TrackDrag(dragRef, &fakeEvent, QMacSmartQuickDrawRegion(dragRegion.toQDRgn()));
+ qt_mac_in_drag = false;
+ }
+ object = 0;
+ if(result == noErr) {
+ // Check if the receiver points us to
+ // a file location. If so, we need to do
+ // the file copy/move ourselves:
+ QCFType<CFURLRef> pasteLocation = 0;
+ PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation);
+ if (pasteLocation){
+ Qt::DropAction action = o->d_func()->defaultDropAction;
+ if (action == Qt::IgnoreAction){
+ if (o->d_func()->possible_actions & Qt::MoveAction)
+ action = Qt::MoveAction;
+ else if (o->d_func()->possible_actions & Qt::CopyAction)
+ action = Qt::CopyAction;
+
+ }
+ bool atleastOne = false;
+ QList<QUrl> urls = o->mimeData()->urls();
+ for (int i = 0; i < urls.size(); ++i){
+ QUrl fromUrl = urls.at(i);
+ QString filename = QFileInfo(fromUrl.path()).fileName();
+ QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename);
+ if (action == Qt::MoveAction){
+ if (QFile::rename(fromUrl.path(), toUrl.path()))
+ atleastOne = true;
+ } else if (action == Qt::CopyAction){
+ if (QFile::copy(fromUrl.path(), toUrl.path()))
+ atleastOne = true;
+ }
+ }
+ if (atleastOne){
+ DisposeDrag(dragRef);
+ return action;
+ }
+ }
+
+ DragActions ret = kDragActionNothing;
+ GetDragDropAction(dragRef, &ret);
+ DisposeDrag(dragRef); //cleanup
+ return qt_mac_dnd_map_mac_default_action(ret);
+ }
+ DisposeDrag(dragRef); //cleanup
+ return Qt::IgnoreAction;
+}
+#endif
+
+void QDragManager::updatePixmap()
+{
+}
+
+QCocoaDropData::QCocoaDropData(CFStringRef pasteboard)
+ : QInternalMimeData()
+{
+ NSString* pasteboardName = (NSString*)pasteboard;
+ [pasteboardName retain];
+ dropPasteboard = pasteboard;
+}
+
+QCocoaDropData::~QCocoaDropData()
+{
+ NSString* pasteboardName = (NSString*)dropPasteboard;
+ [pasteboardName release];
+}
+
+QStringList QCocoaDropData::formats_sys() const
+{
+ QStringList formats;
+ OSPasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return formats;
+ }
+ formats = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats();
+ return formats;
+}
+
+QVariant QCocoaDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant data;
+ OSPasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return data;
+ }
+ data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type);
+ CFRelease(board);
+ return data;
+}
+
+bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const
+{
+ bool has = false;
+ OSPasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return has;
+ }
+ has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType);
+ CFRelease(board);
+ return has;
+}
+
+#endif // QT_NO_DRAGANDDROP
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
new file mode 100644
index 0000000000..7a0cb7ac45
--- /dev/null
+++ b/src/gui/kernel/qdnd_p.h
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDND_P_H
+#define QDND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+#include "QtCore/qmap.h"
+#include "QtGui/qmime.h"
+#include "QtGui/qdrag.h"
+#include "QtGui/qpixmap.h"
+#include "QtCore/qpoint.h"
+#include "private/qobject_p.h"
+#ifdef Q_WS_MAC
+# include "private/qt_mac_p.h"
+#endif
+
+#if defined(Q_WS_WIN)
+# include <windows.h>
+# include <objidl.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QEventLoop;
+
+#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
+
+class QInternalMimeData : public QMimeData
+{
+ Q_OBJECT
+public:
+ QInternalMimeData();
+ ~QInternalMimeData();
+
+ bool hasFormat(const QString &mimeType) const;
+ QStringList formats() const;
+ static bool canReadData(const QString &mimeType);
+
+
+ static QStringList formatsHelper(const QMimeData *data);
+ static bool hasFormatHelper(const QString &mimeType, const QMimeData *data);
+ static QByteArray renderDataHelper(const QString &mimeType, const QMimeData *data);
+
+protected:
+ QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
+
+ virtual bool hasFormat_sys(const QString &mimeType) const = 0;
+ virtual QStringList formats_sys() const = 0;
+ virtual QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const = 0;
+};
+
+#ifdef Q_WS_WIN
+class QOleDataObject : public IDataObject
+{
+public:
+ explicit QOleDataObject(QMimeData *mimeData);
+ virtual ~QOleDataObject();
+
+ void releaseQt();
+ const QMimeData *mimeData() const;
+ DWORD reportedPerformedEffect() const;
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IDataObject methods
+ STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
+ STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium);
+ STDMETHOD(QueryGetData)(LPFORMATETC pformatetc);
+ STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData)(LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease);
+ STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc);
+ STDMETHOD(DAdvise)(FORMATETC FAR* pFormatetc, DWORD advf,
+ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection);
+ STDMETHOD(DUnadvise)(DWORD dwConnection);
+ STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise);
+
+private:
+ ULONG m_refs;
+ QPointer<QMimeData> data;
+ int CF_PERFORMEDDROPEFFECT;
+ DWORD performedEffect;
+};
+
+class QOleEnumFmtEtc : public IEnumFORMATETC
+{
+public:
+ explicit QOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs);
+ explicit QOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs);
+ virtual ~QOleEnumFmtEtc();
+
+ bool isNull() const;
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IEnumFORMATETC methods
+ STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(LPENUMFORMATETC FAR* newEnum);
+
+private:
+ bool copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const;
+
+ ULONG m_dwRefs;
+ ULONG m_nIndex;
+ QVector<LPFORMATETC> m_lpfmtetcs;
+ bool m_isNull;
+};
+
+#endif
+
+#endif //QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
+
+#ifndef QT_NO_DRAGANDDROP
+
+class QDragPrivate : public QObjectPrivate
+{
+public:
+ QWidget *source;
+ QWidget *target;
+ QMimeData *data;
+ QPixmap pixmap;
+ QPoint hotspot;
+ Qt::DropActions possible_actions;
+ Qt::DropAction executed_action;
+ QMap<Qt::DropAction, QPixmap> customCursors;
+ Qt::DropAction defaultDropAction;
+};
+
+class QDropData : public QInternalMimeData
+{
+ Q_OBJECT
+public:
+ QDropData();
+ ~QDropData();
+
+protected:
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+
+#if defined(Q_WS_WIN)
+public:
+ LPDATAOBJECT currentDataObject;
+#endif
+};
+
+class Q_GUI_EXPORT QDragManager: public QObject {
+ Q_OBJECT
+
+ QDragManager();
+ ~QDragManager();
+ // only friend classes can use QDragManager.
+ friend class QDrag;
+ friend class QDragMoveEvent;
+ friend class QDropEvent;
+ friend class QApplication;
+#ifdef Q_WS_MAC
+ friend class QWidgetPrivate; //dnd is implemented here
+#endif
+
+ bool eventFilter(QObject *, QEvent *);
+ void timerEvent(QTimerEvent*);
+
+public:
+ Qt::DropAction drag(QDrag *);
+
+ void cancel(bool deleteSource = true);
+ void move(const QPoint &);
+ void drop();
+ void updatePixmap();
+ QWidget *source() const { return object ? object->d_func()->source : 0; }
+ QDragPrivate *dragPrivate() const { return object ? object->d_func() : 0; }
+ static QDragPrivate *dragPrivate(QDrag *drag) { return drag ? drag->d_func() : 0; }
+
+ static QDragManager *self();
+ Qt::DropAction defaultAction(Qt::DropActions possibleActions,
+ Qt::KeyboardModifiers modifiers) const;
+
+ QDrag *object;
+
+ void updateCursor();
+
+ bool beingCancelled;
+ bool restoreCursor;
+ bool willDrop;
+ QEventLoop *eventLoop;
+
+ QPixmap dragCursor(Qt::DropAction action) const;
+
+ bool hasCustomDragCursors() const;
+
+ QDropData *dropData;
+
+ void emitActionChanged(Qt::DropAction newAction) { if (object) emit object->actionChanged(newAction); }
+
+ void setCurrentTarget(QWidget *target, bool dropped = false);
+ QWidget *currentTarget();
+
+#ifdef Q_WS_X11
+ QPixmap xdndMimeTransferedPixmap[2];
+ int xdndMimeTransferedPixmapIndex;
+#endif
+
+private:
+ QPixmap *pm_cursor;
+ int n_cursor;
+#ifdef Q_WS_QWS
+ Qt::DropAction currentActionForOverrideCursor;
+#endif
+
+ QWidget *currentDropTarget;
+
+ static QDragManager *instance;
+ Q_DISABLE_COPY(QDragManager)
+};
+
+
+#if defined(Q_WS_WIN)
+
+class QOleDropTarget : public IDropTarget
+{
+public:
+ QOleDropTarget(QWidget* w);
+ virtual ~QOleDropTarget() {}
+
+ void releaseQt();
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IDropTarget methods
+ STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+ STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+ STDMETHOD(DragLeave)();
+ STDMETHOD(Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+
+private:
+ ULONG m_refs;
+ QWidget* widget;
+ QPointer<QWidget> currentWidget;
+ QRect answerRect;
+ QPoint lastPoint;
+ DWORD chosenEffect;
+ DWORD lastKeyState;
+
+ void sendDragEnterEvent(QWidget *to, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+};
+
+#endif
+
+#if defined (Q_WS_MAC)
+class QCocoaDropData : public QInternalMimeData
+{
+ Q_OBJECT
+public:
+ QCocoaDropData(CFStringRef pasteboard);
+ ~QCocoaDropData();
+
+protected:
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+public:
+ CFStringRef dropPasteboard;
+};
+#endif
+
+#endif // !QT_NO_DRAGANDDROP
+
+
+QT_END_NAMESPACE
+
+#endif // QDND_P_H
diff --git a/src/gui/kernel/qdnd_qws.cpp b/src/gui/kernel/qdnd_qws.cpp
new file mode 100644
index 0000000000..98a60a1f5f
--- /dev/null
+++ b/src/gui/kernel/qdnd_qws.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+#include "qwidget.h"
+#include "qdatetime.h"
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qdnd_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+static QPixmap *defaultPm = 0;
+static const int default_pm_hotx = -2;
+static const int default_pm_hoty = -16;
+static const char *const default_pm[] = {
+"13 9 3 1",
+". c None",
+" c #000000",
+"X c #FFFFFF",
+"X X X X X X X",
+" X X X X X X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X X X X X X ",
+"X X X X X X X",
+};
+
+// Shift/Ctrl handling, and final drop status
+static Qt::DropAction global_accepted_action = Qt::CopyAction;
+static Qt::DropActions possible_actions = Qt::IgnoreAction;
+
+
+// static variables in place of a proper cross-process solution
+static QDrag *drag_object;
+static bool qt_qws_dnd_dragging = false;
+
+
+static Qt::KeyboardModifiers oldstate;
+
+class QShapedPixmapWidget : public QWidget {
+ QPixmap pixmap;
+public:
+ QShapedPixmapWidget() :
+ QWidget(0, Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint)
+ {
+ // ### Temporary workaround for 4.2-rc1!!! To prevent flickering when
+ // using drag'n drop in a client application. (task 126956)
+ // setAttribute() should be done unconditionally!
+ if (QApplication::type() == QApplication::GuiServer)
+ setAttribute(Qt::WA_TransparentForMouseEvents);
+ }
+
+ void setPixmap(QPixmap pm)
+ {
+ pixmap = pm;
+ if (!pixmap.mask().isNull()) {
+ setMask(pixmap.mask());
+ } else {
+ clearMask();
+ }
+ resize(pm.width(),pm.height());
+ }
+
+ void paintEvent(QPaintEvent*)
+ {
+ QPainter p(this);
+ p.drawPixmap(0,0,pixmap);
+ }
+};
+
+
+static QShapedPixmapWidget *qt_qws_dnd_deco = 0;
+
+
+void QDragManager::updatePixmap()
+{
+ if (qt_qws_dnd_deco) {
+ QPixmap pm;
+ QPoint pm_hot(default_pm_hotx,default_pm_hoty);
+ if (drag_object) {
+ pm = drag_object->pixmap();
+ if (!pm.isNull())
+ pm_hot = drag_object->hotSpot();
+ }
+ if (pm.isNull()) {
+ if (!defaultPm)
+ defaultPm = new QPixmap(default_pm);
+ pm = *defaultPm;
+ }
+ qt_qws_dnd_deco->setPixmap(pm);
+ qt_qws_dnd_deco->move(QCursor::pos()-pm_hot);
+ if (willDrop) {
+ qt_qws_dnd_deco->show();
+ } else {
+ qt_qws_dnd_deco->hide();
+ }
+ }
+}
+
+void QDragManager::timerEvent(QTimerEvent *) { }
+
+void QDragManager::move(const QPoint &) { }
+
+void QDragManager::updateCursor()
+{
+#ifndef QT_NO_CURSOR
+ if (willDrop) {
+ if (qt_qws_dnd_deco)
+ qt_qws_dnd_deco->show();
+ if (currentActionForOverrideCursor != global_accepted_action) {
+ QApplication::changeOverrideCursor(QCursor(dragCursor(global_accepted_action), 0, 0));
+ currentActionForOverrideCursor = global_accepted_action;
+ }
+ } else {
+ QCursor *overrideCursor = QApplication::overrideCursor();
+ if (!overrideCursor || overrideCursor->shape() != Qt::ForbiddenCursor) {
+ QApplication::changeOverrideCursor(QCursor(Qt::ForbiddenCursor));
+ currentActionForOverrideCursor = Qt::IgnoreAction;
+ }
+ if (qt_qws_dnd_deco)
+ qt_qws_dnd_deco->hide();
+ }
+#endif
+}
+
+
+bool QDragManager::eventFilter(QObject *o, QEvent *e)
+{
+ if (beingCancelled) {
+ if (e->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
+ qApp->removeEventFilter(this);
+ Q_ASSERT(object == 0);
+ beingCancelled = false;
+ eventLoop->exit();
+ return true; // block the key release
+ }
+ return false;
+ }
+
+
+
+ if (!o->isWidgetType())
+ return false;
+
+ switch(e->type()) {
+
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ {
+ QKeyEvent *ke = ((QKeyEvent*)e);
+ if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ eventLoop->exit();
+ } else {
+ updateCursor();
+ }
+ return true; // Eat all key events
+ }
+
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ {
+ if (!object) { //#### this should not happen
+ qWarning("QDragManager::eventFilter: No object");
+ return true;
+ }
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+ if (manager->object)
+ possible_actions = manager->dragPrivate()->possible_actions;
+ else
+ possible_actions = Qt::IgnoreAction;
+
+ QMouseEvent *me = (QMouseEvent *)e;
+ if (me->buttons()) {
+ Qt::DropAction prevAction = global_accepted_action;
+ QWidget *cw = QApplication::widgetAt(me->globalPos());
+
+ // Fix for when we move mouse on to the deco widget
+ if (qt_qws_dnd_deco && cw == qt_qws_dnd_deco)
+ cw = object->target();
+
+ while (cw && !cw->acceptDrops() && !cw->isWindow())
+ cw = cw->parentWidget();
+
+ if (object->target() != cw) {
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QApplication::sendEvent(object->target(), &dle);
+ willDrop = false;
+ global_accepted_action = Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ object->d_func()->target = 0;
+ }
+ if (cw && cw->acceptDrops()) {
+ object->d_func()->target = cw;
+ QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(object->target(), &dee);
+ willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
+ global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ }
+ } else if (cw) {
+ QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ if (global_accepted_action != Qt::IgnoreAction) {
+ dme.setDropAction(global_accepted_action);
+ dme.accept();
+ }
+ QApplication::sendEvent(cw, &dme);
+ willDrop = dme.isAccepted();
+ global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;
+ updatePixmap();
+ updateCursor();
+ }
+ if (global_accepted_action != prevAction)
+ emitActionChanged(global_accepted_action);
+ }
+ return true; // Eat all mouse events
+ }
+
+ case QEvent::MouseButtonRelease:
+ {
+ qApp->removeEventFilter(this);
+ if (restoreCursor) {
+ willDrop = false;
+#ifndef QT_NO_CURSOR
+ QApplication::restoreOverrideCursor();
+#endif
+ restoreCursor = false;
+ }
+ if (object && object->target()) {
+ QMouseEvent *me = (QMouseEvent *)e;
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+
+ QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(object->target(), &de);
+ if (de.isAccepted())
+ global_accepted_action = de.dropAction();
+ else
+ global_accepted_action = Qt::IgnoreAction;
+
+ if (object)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+ eventLoop->exit();
+ return true; // Eat all mouse events
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+Qt::DropAction QDragManager::drag(QDrag *o)
+{
+ if (object == o || !o || !o->source())
+ return Qt::IgnoreAction;
+
+ if (object) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ }
+
+ object = drag_object = o;
+ qt_qws_dnd_deco = new QShapedPixmapWidget();
+ oldstate = Qt::NoModifier; // #### Should use state that caused the drag
+// drag_mode = mode;
+
+ willDrop = false;
+ updatePixmap();
+ updateCursor();
+ restoreCursor = true;
+ object->d_func()->target = 0;
+ qApp->installEventFilter(this);
+
+ global_accepted_action = Qt::CopyAction;
+#ifndef QT_NO_CURSOR
+ qApp->setOverrideCursor(Qt::ArrowCursor);
+ restoreCursor = true;
+ updateCursor();
+#endif
+
+ qt_qws_dnd_dragging = true;
+
+ eventLoop = new QEventLoop;
+ (void) eventLoop->exec();
+ delete eventLoop;
+ eventLoop = 0;
+
+ delete qt_qws_dnd_deco;
+ qt_qws_dnd_deco = 0;
+ qt_qws_dnd_dragging = false;
+
+
+ return global_accepted_action;
+}
+
+
+void QDragManager::cancel(bool deleteSource)
+{
+// qDebug("QDragManager::cancel");
+ beingCancelled = true;
+
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QApplication::sendEvent(object->target(), &dle);
+ }
+
+#ifndef QT_NO_CURSOR
+ if (restoreCursor) {
+ QApplication::restoreOverrideCursor();
+ restoreCursor = false;
+ }
+#endif
+
+ if (drag_object) {
+ if (deleteSource)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+
+ delete qt_qws_dnd_deco;
+ qt_qws_dnd_deco = 0;
+
+ global_accepted_action = Qt::IgnoreAction;
+}
+
+
+void QDragManager::drop()
+{
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
+{
+ if (!drag_object)
+ return QVariant();
+ QByteArray data = drag_object->mimeData()->data(mimetype);
+ if (type == QVariant::String)
+ return QString::fromUtf8(data);
+ return data;
+}
+
+bool QDropData::hasFormat_sys(const QString &format) const
+{
+ return formats().contains(format);
+}
+
+QStringList QDropData::formats_sys() const
+{
+ if (drag_object)
+ return drag_object->mimeData()->formats();
+ return QStringList();
+}
+
+
+#endif // QT_NO_DRAGANDDROP
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp
new file mode 100644
index 0000000000..8bf5c846a8
--- /dev/null
+++ b/src/gui/kernel/qdnd_win.cpp
@@ -0,0 +1,1036 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+
+#include "qapplication_p.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qwidget.h"
+#include "qbuffer.h"
+#include "qdatastream.h"
+#include "qcursor.h"
+#include "qt_windows.h"
+#include <shlobj.h>
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#include "qdnd_p.h"
+#include "qdebug.h"
+
+#if defined(Q_OS_WINCE)
+#include "qguifunctions_wince.h"
+#endif
+
+// support for xbuttons
+#ifndef MK_XBUTTON1
+#define MK_XBUTTON1 0x0020
+#define MK_XBUTTON2 0x0040
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
+
+//---------------------------------------------------------------------
+// QOleDataObject Constructor
+//---------------------------------------------------------------------
+
+QOleDataObject::QOleDataObject(QMimeData *mimeData)
+{
+ m_refs = 1;
+ data = mimeData;
+ CF_PERFORMEDDROPEFFECT = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
+ performedEffect = DROPEFFECT_NONE;
+}
+
+QOleDataObject::~QOleDataObject()
+{
+}
+
+void QOleDataObject::releaseQt()
+{
+ data = 0;
+}
+
+const QMimeData *QOleDataObject::mimeData() const
+{
+ return data;
+}
+
+DWORD QOleDataObject::reportedPerformedEffect() const
+{
+ return performedEffect;
+}
+
+//---------------------------------------------------------------------
+// IUnknown Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+QOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv)
+{
+ if (iid == IID_IUnknown || iid == IID_IDataObject) {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG)
+QOleDataObject::AddRef(void)
+{
+ return ++m_refs;
+}
+
+STDMETHODIMP_(ULONG)
+QOleDataObject::Release(void)
+{
+ if (--m_refs == 0) {
+ releaseQt();
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+//---------------------------------------------------------------------
+// IDataObject Methods
+//
+// The following methods are NOT supported for data transfer using the
+// clipboard or drag-drop:
+//
+// IDataObject::SetData -- return E_NOTIMPL
+// IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
+// ::DUnadvise
+// ::EnumDAdvise
+// IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
+// (NOTE: must set pformatetcOut->ptd = NULL)
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)");
+#ifndef Q_OS_WINCE
+ char buf[256] = {0};
+ GetClipboardFormatNameA(pformatetc->cfFormat, buf, 255);
+ qDebug("CF = %d : %s", pformatetc->cfFormat, buf);
+#endif
+#endif
+
+ if (!data)
+ return ResultFromScode(DATA_E_FORMATETC);
+
+ QWindowsMime *converter = QWindowsMime::converterFromMime(*pformatetc, data);
+
+ if (converter && converter->convertFromMime(*pformatetc, data, pmedium))
+ return ResultFromScode(S_OK);
+ else
+ return ResultFromScode(DATA_E_FORMATETC);
+}
+
+STDMETHODIMP
+QOleDataObject::GetDataHere(LPFORMATETC, LPSTGMEDIUM)
+{
+ return ResultFromScode(DATA_E_FORMATETC);
+}
+
+STDMETHODIMP
+QOleDataObject::QueryGetData(LPFORMATETC pformatetc)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDataObject::QueryGetData(LPFORMATETC pformatetc)");
+#endif
+
+ if (!data)
+ return ResultFromScode(DATA_E_FORMATETC);
+
+ if (QWindowsMime::converterFromMime(*pformatetc, data))
+ return ResultFromScode(S_OK);
+ return ResultFromScode(S_FALSE);
+}
+
+STDMETHODIMP
+QOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut)
+{
+ pformatetcOut->ptd = NULL;
+ return ResultFromScode(E_NOTIMPL);
+}
+
+STDMETHODIMP
+QOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL fRelease)
+{
+ if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) {
+ DWORD * val = (DWORD*)GlobalLock(pMedium->hGlobal);
+ performedEffect = *val;
+ GlobalUnlock(pMedium->hGlobal);
+ if (fRelease)
+ ReleaseStgMedium(pMedium);
+ return ResultFromScode(S_OK);
+ }
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+STDMETHODIMP
+QOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)");
+#endif
+
+ if (!data)
+ return ResultFromScode(DATA_E_FORMATETC);
+
+ SCODE sc = S_OK;
+
+ QVector<FORMATETC> fmtetcs;
+ if (dwDirection == DATADIR_GET) {
+ fmtetcs = QWindowsMime::allFormatsForMime(data);
+ } else {
+ FORMATETC formatetc;
+ formatetc.cfFormat = CF_PERFORMEDDROPEFFECT;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.lindex = -1;
+ formatetc.ptd = NULL;
+ formatetc.tymed = TYMED_HGLOBAL;
+ fmtetcs.append(formatetc);
+ }
+
+ QOleEnumFmtEtc *enumFmtEtc = new QOleEnumFmtEtc(fmtetcs);
+ *ppenumFormatEtc = enumFmtEtc;
+ if (enumFmtEtc->isNull()) {
+ delete enumFmtEtc;
+ *ppenumFormatEtc = NULL;
+ sc = E_OUTOFMEMORY;
+ }
+
+ return ResultFromScode(sc);
+}
+
+STDMETHODIMP
+QOleDataObject::DAdvise(FORMATETC FAR*, DWORD,
+ LPADVISESINK, DWORD FAR*)
+{
+ return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
+}
+
+
+STDMETHODIMP
+QOleDataObject::DUnadvise(DWORD)
+{
+ return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
+}
+
+STDMETHODIMP
+QOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*)
+{
+ return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
+}
+
+#endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
+
+#ifndef QT_NO_DRAGANDDROP
+
+//#define QDND_DEBUG
+
+#ifdef QDND_DEBUG
+extern QString dragActionsToString(Qt::DropActions actions);
+#endif
+
+Qt::DropActions translateToQDragDropActions(DWORD pdwEffects)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ if (pdwEffects & DROPEFFECT_LINK)
+ actions |= Qt::LinkAction;
+ if (pdwEffects & DROPEFFECT_COPY)
+ actions |= Qt::CopyAction;
+ if (pdwEffects & DROPEFFECT_MOVE)
+ actions |= Qt::MoveAction;
+ return actions;
+}
+
+Qt::DropAction translateToQDragDropAction(DWORD pdwEffect)
+{
+ if (pdwEffect & DROPEFFECT_LINK)
+ return Qt::LinkAction;
+ if (pdwEffect & DROPEFFECT_COPY)
+ return Qt::CopyAction;
+ if (pdwEffect & DROPEFFECT_MOVE)
+ return Qt::MoveAction;
+ return Qt::IgnoreAction;
+}
+
+DWORD translateToWinDragEffects(Qt::DropActions action)
+{
+ DWORD effect = DROPEFFECT_NONE;
+ if (action & Qt::LinkAction)
+ effect |= DROPEFFECT_LINK;
+ if (action & Qt::CopyAction)
+ effect |= DROPEFFECT_COPY;
+ if (action & Qt::MoveAction)
+ effect |= DROPEFFECT_MOVE;
+ return effect;
+}
+
+Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState)
+{
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+
+ if (keyState & MK_SHIFT)
+ modifiers |= Qt::ShiftModifier;
+ if (keyState & MK_CONTROL)
+ modifiers |= Qt::ControlModifier;
+ if (keyState & MK_ALT)
+ modifiers |= Qt::AltModifier;
+
+ return modifiers;
+}
+
+Qt::MouseButtons toQtMouseButtons(DWORD keyState)
+{
+ Qt::MouseButtons buttons = Qt::NoButton;
+
+ if (keyState & MK_LBUTTON)
+ buttons |= Qt::LeftButton;
+ if (keyState & MK_RBUTTON)
+ buttons |= Qt::RightButton;
+ if (keyState & MK_MBUTTON)
+ buttons |= Qt::MidButton;
+
+ return buttons;
+}
+
+class QOleDropSource : public IDropSource
+{
+public:
+ QOleDropSource();
+ virtual ~QOleDropSource();
+
+ void createCursors();
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IDropSource methods
+ STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState);
+ STDMETHOD(GiveFeedback)(DWORD dwEffect);
+
+private:
+ Qt::MouseButtons currentButtons;
+ Qt::DropAction currentAction;
+ QMap <Qt::DropAction, QCursor> cursors;
+
+ ULONG m_refs;
+};
+
+
+QOleDropSource::QOleDropSource()
+{
+ currentButtons = Qt::NoButton;
+ m_refs = 1;
+ currentAction = Qt::IgnoreAction;
+}
+
+QOleDropSource::~QOleDropSource()
+{
+}
+
+void QOleDropSource::createCursors()
+{
+ QDragManager *manager = QDragManager::self();
+ if (manager && manager->object
+ && (!manager->object->pixmap().isNull()
+ || manager->hasCustomDragCursors())) {
+ QPixmap pm = manager->object->pixmap();
+ QList<Qt::DropAction> actions;
+ actions << Qt::MoveAction << Qt::CopyAction << Qt::LinkAction;
+ if (!manager->object->pixmap().isNull())
+ actions << Qt::IgnoreAction;
+ QPoint hotSpot = manager->object->hotSpot();
+ for (int cnum = 0; cnum < actions.size(); ++cnum) {
+ QPixmap cpm = manager->dragCursor(actions.at(cnum));
+ int w = cpm.width();
+ int h = cpm.height();
+
+ if (!pm.isNull()) {
+ int x1 = qMin(-hotSpot.x(),0);
+ int x2 = qMax(pm.width()-hotSpot.x(),cpm.width());
+ int y1 = qMin(-hotSpot.y(),0);
+ int y2 = qMax(pm.height()-hotSpot.y(),cpm.height());
+
+ w = x2-x1+1;
+ h = y2-y1+1;
+ }
+
+ QRect srcRect = pm.rect();
+ QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
+ QPoint newHotSpot = hotSpot;
+
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+ bool limitedCursorSize = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
+ || (QSysInfo::WindowsVersion == QSysInfo::WV_NT)
+ || (QSysInfo::WindowsVersion == QSysInfo::WV_CE);
+
+ if (limitedCursorSize) {
+ // Limited cursor size
+ int reqw = GetSystemMetrics(SM_CXCURSOR);
+ int reqh = GetSystemMetrics(SM_CYCURSOR);
+
+ QPoint hotspotInPM = newHotSpot - pmDest;
+ if (reqw < w) {
+ // Not wide enough - move objectpm right
+ qreal r = qreal(newHotSpot.x()) / w;
+ newHotSpot = QPoint(int(r * reqw), newHotSpot.y());
+ if (newHotSpot.x() + cpm.width() > reqw)
+ newHotSpot.setX(reqw - cpm.width());
+
+ srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height()));
+ }
+ if (reqh < h) {
+ qreal r = qreal(newHotSpot.y()) / h;
+ newHotSpot = QPoint(newHotSpot.x(), int(r * reqh));
+ if (newHotSpot.y() + cpm.height() > reqh)
+ newHotSpot.setY(reqh - cpm.height());
+
+ srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh));
+ }
+ // Always use system cursor size
+ w = reqw;
+ h = reqh;
+ }
+#endif
+ QPixmap newCursor(w, h);
+ if (!pm.isNull()) {
+ newCursor.fill(QColor(0, 0, 0, 0));
+ QPainter p(&newCursor);
+ p.drawPixmap(pmDest, pm, srcRect);
+ p.drawPixmap(qMax(0,newHotSpot.x()),qMax(0,newHotSpot.y()),cpm);
+ } else {
+ newCursor = cpm;
+ }
+
+#ifndef QT_NO_CURSOR
+ cursors[actions.at(cnum)] = QCursor(newCursor, pm.isNull() ? 0 : qMax(0,newHotSpot.x()),
+ pm.isNull() ? 0 : qMax(0,newHotSpot.y()));
+#endif
+ }
+ }
+}
+
+
+
+//---------------------------------------------------------------------
+// IUnknown Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+QOleDropSource::QueryInterface(REFIID iid, void FAR* FAR* ppv)
+{
+ if(iid == IID_IUnknown || iid == IID_IDropSource)
+ {
+ *ppv = this;
+ ++m_refs;
+ return NOERROR;
+ }
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+
+STDMETHODIMP_(ULONG)
+QOleDropSource::AddRef(void)
+{
+ return ++m_refs;
+}
+
+
+STDMETHODIMP_(ULONG)
+QOleDropSource::Release(void)
+{
+ if(--m_refs == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+static inline Qt::MouseButtons keystate_to_mousebutton(DWORD grfKeyState)
+{
+ Qt::MouseButtons result;
+ if (grfKeyState & MK_LBUTTON)
+ result |= Qt::LeftButton;
+ if (grfKeyState & MK_MBUTTON)
+ result |= Qt::MidButton;
+ if (grfKeyState & MK_RBUTTON)
+ result |= Qt::RightButton;
+ if (grfKeyState & MK_XBUTTON1)
+ result |= Qt::XButton1;
+ if (grfKeyState & MK_XBUTTON2)
+ result |= Qt::XButton2;
+ return result;
+}
+
+//---------------------------------------------------------------------
+// IDropSource Methods
+//---------------------------------------------------------------------
+STDMETHODIMP
+QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDropSource::QueryContinueDrag(fEscapePressed %d, grfKeyState %d)", fEscapePressed, grfKeyState);
+#endif
+
+ if (fEscapePressed) {
+ return ResultFromScode(DRAGDROP_S_CANCEL);
+ } else if (!(grfKeyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))) {
+ return ResultFromScode(DRAGDROP_S_DROP);
+ } else {
+#if defined(Q_OS_WINCE)
+ // grfKeyState is broken on CE, therefore need to check
+ // the state manually
+ if ((GetAsyncKeyState(VK_LBUTTON) == 0) &&
+ (GetAsyncKeyState(VK_MBUTTON) == 0) &&
+ (GetAsyncKeyState(VK_RBUTTON) == 0)) {
+ return ResultFromScode(DRAGDROP_S_DROP);
+ }
+#else
+ if (currentButtons == Qt::NoButton) {
+ currentButtons = keystate_to_mousebutton(grfKeyState);
+ } else {
+ Qt::MouseButtons buttons = keystate_to_mousebutton(grfKeyState);
+ if (!(currentButtons & buttons))
+ return ResultFromScode(DRAGDROP_S_DROP);
+ }
+#endif
+ qApp->processEvents();
+ return NOERROR;
+ }
+}
+
+STDMETHODIMP
+QOleDropSource::GiveFeedback(DWORD dwEffect)
+{
+ Qt::DropAction action = translateToQDragDropAction(dwEffect);
+
+#ifdef QDND_DEBUG
+ qDebug("QOleDropSource::GiveFeedback(DWORD dwEffect)");
+ qDebug("dwEffect = %s", dragActionsToString(action).toLatin1().data());
+#endif
+
+ if (currentAction != action) {
+ currentAction = action;
+ QDragManager::self()->emitActionChanged(currentAction);
+ }
+
+ if (cursors.contains(currentAction)) {
+#ifndef QT_NO_CURSOR
+ SetCursor(cursors[currentAction].handle());
+#endif
+ return ResultFromScode(S_OK);
+ }
+
+ return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);
+}
+
+//---------------------------------------------------------------------
+// QOleDropTarget
+//---------------------------------------------------------------------
+
+QOleDropTarget::QOleDropTarget(QWidget* w)
+: widget(w)
+{
+ m_refs = 1;
+}
+
+void QOleDropTarget::releaseQt()
+{
+ widget = 0;
+}
+
+//---------------------------------------------------------------------
+// IUnknown Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+QOleDropTarget::QueryInterface(REFIID iid, void FAR* FAR* ppv)
+{
+ if(iid == IID_IUnknown || iid == IID_IDropTarget)
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+
+STDMETHODIMP_(ULONG)
+QOleDropTarget::AddRef(void)
+{
+ return ++m_refs;
+}
+
+
+STDMETHODIMP_(ULONG)
+QOleDropTarget::Release(void)
+{
+ if(--m_refs == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+//---------------------------------------------------------------------
+// IDropTarget Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)");
+#endif
+
+ if (!QApplicationPrivate::tryModalHelper(widget)) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return NOERROR;
+ }
+
+ QDragManager *manager = QDragManager::self();
+ manager->dropData->currentDataObject = pDataObj;
+ manager->dropData->currentDataObject->AddRef();
+ sendDragEnterEvent(widget, grfKeyState, pt, pdwEffect);
+ *pdwEffect = chosenEffect;
+
+ return NOERROR;
+}
+
+void QOleDropTarget::sendDragEnterEvent(QWidget *dragEnterWidget, DWORD grfKeyState,
+ POINTL pt, LPDWORD pdwEffect)
+{
+ Q_ASSERT(dragEnterWidget);
+ lastPoint = dragEnterWidget->mapFromGlobal(QPoint(pt.x,pt.y));
+ lastKeyState = grfKeyState;
+
+ chosenEffect = DROPEFFECT_NONE;
+ currentWidget = dragEnterWidget;
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData * md = manager->source() ? manager->dragPrivate()->data : manager->dropData;
+ QDragEnterEvent enterEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md,
+ toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
+ QApplication::sendEvent(dragEnterWidget, &enterEvent);
+ answerRect = enterEvent.answerRect();
+
+ if (enterEvent.isAccepted()) {
+ chosenEffect = translateToWinDragEffects(enterEvent.dropAction());
+ }
+
+ // Documentation states that a drag move event is sendt immidiatly after
+ // a drag enter event. This will honor widgets overriding dragMoveEvent only:
+ if (enterEvent.isAccepted()) {
+ QDragMoveEvent moveEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md,
+ toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
+ answerRect = enterEvent.answerRect();
+ moveEvent.setDropAction(enterEvent.dropAction());
+ moveEvent.accept(); // accept by default, since enter event was accepted.
+
+ QApplication::sendEvent(dragEnterWidget, &moveEvent);
+ if (moveEvent.isAccepted()) {
+ answerRect = moveEvent.answerRect();
+ chosenEffect = translateToWinDragEffects(moveEvent.dropAction());
+ } else {
+ chosenEffect = DROPEFFECT_NONE;
+ }
+ }
+
+}
+
+STDMETHODIMP
+QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDropTarget::DragOver(grfKeyState %d, pt (%d,%d), pdwEffect %d)", grfKeyState, pt.x, pt.y, pdwEffect);
+#endif
+
+ QWidget *dragOverWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y)));
+ if (!dragOverWidget)
+ dragOverWidget = widget;
+
+
+ if (!QApplicationPrivate::tryModalHelper(dragOverWidget)
+ || !dragOverWidget->testAttribute(Qt::WA_DropSiteRegistered)) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return NOERROR;
+ }
+
+ QPoint tmpPoint = dragOverWidget->mapFromGlobal(QPoint(pt.x, pt.y));
+ // see if we should compress this event
+ if ((tmpPoint == lastPoint || answerRect.contains(tmpPoint)) && lastKeyState == grfKeyState) {
+ *pdwEffect = chosenEffect;
+ return NOERROR;
+ }
+
+ if (!dragOverWidget->internalWinId() && dragOverWidget != currentWidget) {
+ QPointer<QWidget> dragOverWidgetGuard(dragOverWidget);
+ // Send drag leave event to the previous drag widget.
+ QDragLeaveEvent dragLeave;
+ if (currentWidget)
+ QApplication::sendEvent(currentWidget, &dragLeave);
+ if (!dragOverWidgetGuard) {
+ dragOverWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y)));
+ if (!dragOverWidget)
+ dragOverWidget = widget;
+ }
+ // Send drag enter event to the current drag widget.
+ sendDragEnterEvent(dragOverWidget, grfKeyState, pt, pdwEffect);
+ }
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *md = manager->source() ? manager->dragPrivate()->data : manager->dropData;
+
+ QDragMoveEvent oldEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md,
+ toQtMouseButtons(lastKeyState), toQtKeyboardModifiers(lastKeyState));
+
+
+ lastPoint = tmpPoint;
+ lastKeyState = grfKeyState;
+
+ QDragMoveEvent e(lastPoint, translateToQDragDropActions(*pdwEffect), md,
+ toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
+ if (chosenEffect != DROPEFFECT_NONE) {
+ if (oldEvent.dropAction() == e.dropAction() &&
+ oldEvent.keyboardModifiers() == e.keyboardModifiers())
+ e.setDropAction(translateToQDragDropAction(chosenEffect));
+ e.accept();
+ }
+ QApplication::sendEvent(dragOverWidget, &e);
+
+ answerRect = e.answerRect();
+ if (e.isAccepted())
+ chosenEffect = translateToWinDragEffects(e.dropAction());
+ else
+ chosenEffect = DROPEFFECT_NONE;
+ *pdwEffect = chosenEffect;
+
+ return NOERROR;
+}
+
+STDMETHODIMP
+QOleDropTarget::DragLeave()
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDropTarget::DragLeave()");
+#endif
+
+ if (!QApplicationPrivate::tryModalHelper(widget)) {
+ return NOERROR;
+ }
+
+ currentWidget = 0;
+ QDragLeaveEvent e;
+ QApplication::sendEvent(widget, &e);
+
+ QDragManager *manager = QDragManager::self();
+
+ if (manager->dropData->currentDataObject) { // Sanity
+ manager->dropData->currentDataObject->Release();
+ manager->dropData->currentDataObject = 0;
+ }
+
+ return NOERROR;
+}
+
+#define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)
+
+STDMETHODIMP
+QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
+{
+#ifdef QDND_DEBUG
+ qDebug("QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, grfKeyState %d, POINTL pt, LPDWORD pdwEffect)", grfKeyState);
+#endif
+
+ QWidget *dropWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y)));
+ if (!dropWidget)
+ dropWidget = widget;
+
+ if (!QApplicationPrivate::tryModalHelper(dropWidget)
+ || !dropWidget->testAttribute(Qt::WA_DropSiteRegistered)) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return NOERROR;
+ }
+
+ lastPoint = dropWidget->mapFromGlobal(QPoint(pt.x,pt.y));
+ // grfKeyState does not all ways contain button state in the drop so if
+ // it doesn't then use the last known button state;
+ if ((grfKeyState & KEY_STATE_BUTTON_MASK) == 0)
+ grfKeyState |= lastKeyState & KEY_STATE_BUTTON_MASK;
+ lastKeyState = grfKeyState;
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *md = manager->source() ? manager->dragPrivate()->data : manager->dropData;
+ QDropEvent e(lastPoint, translateToQDragDropActions(*pdwEffect), md,
+ toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
+ if (chosenEffect != DROPEFFECT_NONE) {
+ e.setDropAction(translateToQDragDropAction(chosenEffect));
+ }
+ QApplication::sendEvent(dropWidget, &e);
+
+ if (chosenEffect != DROPEFFECT_NONE) {
+ e.accept();
+ }
+
+
+ if (e.isAccepted()) {
+ if (e.dropAction() == Qt::MoveAction || e.dropAction() == Qt::TargetMoveAction) {
+ if (e.dropAction() == Qt::MoveAction)
+ chosenEffect = DROPEFFECT_MOVE;
+ else
+ chosenEffect = DROPEFFECT_COPY;
+ HGLOBAL hData = GlobalAlloc(0, sizeof(DWORD));
+ if (hData) {
+ DWORD *moveEffect = (DWORD *)GlobalLock(hData);;
+ *moveEffect = DROPEFFECT_MOVE;
+ GlobalUnlock(hData);
+ STGMEDIUM medium;
+ memset(&medium, 0, sizeof(STGMEDIUM));
+ medium.tymed = TYMED_HGLOBAL;
+ medium.hGlobal = hData;
+ FORMATETC format;
+ format.cfFormat = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
+ format.tymed = TYMED_HGLOBAL;
+ format.ptd = 0;
+ format.dwAspect = 1;
+ format.lindex = -1;
+ manager->dropData->currentDataObject->SetData(&format, &medium, true);
+ }
+ } else {
+ chosenEffect = translateToWinDragEffects(e.dropAction());
+ }
+ } else {
+ chosenEffect = DROPEFFECT_NONE;
+ }
+ *pdwEffect = chosenEffect;
+
+
+ if (manager->dropData->currentDataObject) {
+ manager->dropData->currentDataObject->Release();
+ manager->dropData->currentDataObject = 0;
+ }
+
+ return NOERROR;
+
+ // We won't get any mouserelease-event, so manually adjust qApp state:
+///### test this QApplication::winMouseButtonUp();
+}
+
+//---------------------------------------------------------------------
+// QDropData
+//---------------------------------------------------------------------
+
+bool QDropData::hasFormat_sys(const QString &mimeType) const
+{
+ if (!currentDataObject) // Sanity
+ return false;
+
+ return QWindowsMime::converterToMime(mimeType, currentDataObject) != 0;
+}
+
+QStringList QDropData::formats_sys() const
+{
+ QStringList fmts;
+ if (!currentDataObject) // Sanity
+ return fmts;
+
+ fmts = QWindowsMime::allMimesForFormats(currentDataObject);
+
+ return fmts;
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant result;
+
+ if (!currentDataObject) // Sanity
+ return result;
+
+ QWindowsMime *converter = QWindowsMime::converterToMime(mimeType, currentDataObject);
+
+ if (converter)
+ result = converter->convertToMime(mimeType, currentDataObject, type);
+
+ return result;
+}
+
+Qt::DropAction QDragManager::drag(QDrag *o)
+
+{
+#ifdef QDND_DEBUG
+ qDebug("QDragManager::drag(QDrag *drag)");
+#endif
+
+ if (object == o || !o || !o->d_func()->source)
+ return Qt::IgnoreAction;
+
+ if (object) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ }
+
+ object = o;
+
+#ifdef QDND_DEBUG
+ qDebug("actions = %s", dragActionsToString(dragPrivate()->possible_actions).toLatin1().data());
+#endif
+
+ dragPrivate()->target = 0;
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart);
+#endif
+
+ DWORD resultEffect;
+ QOleDropSource *src = new QOleDropSource();
+ src->createCursors();
+ QOleDataObject *obj = new QOleDataObject(o->mimeData());
+ DWORD allowedEffects = translateToWinDragEffects(dragPrivate()->possible_actions);
+
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+ HRESULT r = DoDragDrop(obj, src, allowedEffects, &resultEffect);
+#else
+ HRESULT r = DRAGDROP_S_CANCEL;
+ resultEffect = DROPEFFECT_MOVE;
+#endif
+
+ Qt::DropAction ret = Qt::IgnoreAction;
+ if (r == DRAGDROP_S_DROP) {
+ if (obj->reportedPerformedEffect() == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
+ ret = Qt::TargetMoveAction;
+ resultEffect = DROPEFFECT_MOVE;
+ } else {
+ ret = translateToQDragDropAction(resultEffect);
+ }
+ // Force it to be a copy if an unsupported operation occurred.
+ // This indicates a bug in the drop target.
+ if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects))
+ ret = Qt::CopyAction;
+ } else {
+ dragPrivate()->target = 0;
+ }
+
+ // clean up
+ obj->releaseQt();
+ obj->Release(); // Will delete obj if refcount becomes 0
+ src->Release(); // Will delete src if refcount becomes 0
+ object = 0;
+ o->setMimeData(0);
+ o->deleteLater();
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd);
+#endif
+
+ return ret;
+}
+
+void QDragManager::cancel(bool /* deleteSource */)
+{
+ if (object) {
+ beingCancelled = true;
+ object = 0;
+ }
+
+#ifndef QT_NO_CURSOR
+ // insert cancel code here ######## todo
+
+ if (restoreCursor) {
+ QApplication::restoreOverrideCursor();
+ restoreCursor = false;
+ }
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd);
+#endif
+}
+
+void QDragManager::updatePixmap()
+{
+ // not used in windows implementation
+}
+
+bool QDragManager::eventFilter(QObject *, QEvent *)
+{
+ // not used in windows implementation
+ return false;
+}
+
+void QDragManager::timerEvent(QTimerEvent*)
+{
+ // not used in windows implementation
+}
+
+void QDragManager::move(const QPoint &)
+{
+ // not used in windows implementation
+}
+
+void QDragManager::drop()
+{
+ // not used in windows implementation
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
new file mode 100644
index 0000000000..4c9c73c466
--- /dev/null
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -0,0 +1,2064 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qapplication.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+#include "qwidget.h"
+#include "qpainter.h"
+#include "qpixmap.h"
+#include "qbitmap.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qdatetime.h"
+#include "qiodevice.h"
+#include "qpointer.h"
+#include "qcursor.h"
+#include "qvariant.h"
+#include "qvector.h"
+#include "qurl.h"
+#include "qdebug.h"
+#include "qimagewriter.h"
+#include "qbuffer.h"
+#include "qtextcodec.h"
+
+#include "qdnd_p.h"
+#include "qt_x11_p.h"
+#include "qx11info_x11.h"
+
+#include "qwidget_p.h"
+#include "qcursor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// #define DND_DEBUG
+#ifdef DND_DEBUG
+#define DEBUG qDebug
+#else
+#define DEBUG if(0) qDebug
+#endif
+
+#ifdef DND_DEBUG
+#define DNDDEBUG qDebug()
+#else
+#define DNDDEBUG if(0) qDebug()
+#endif
+
+static int findXdndDropTransactionByWindow(Window window)
+{
+ int at = -1;
+ for (int i = 0; i < X11->dndDropTransactions.count(); ++i) {
+ const QXdndDropTransaction &t = X11->dndDropTransactions.at(i);
+ if (t.target == window || t.proxy_target == window) {
+ at = i;
+ break;
+ }
+ }
+ return at;
+}
+
+static int findXdndDropTransactionByTime(Time timestamp)
+{
+ int at = -1;
+ for (int i = 0; i < X11->dndDropTransactions.count(); ++i) {
+ const QXdndDropTransaction &t = X11->dndDropTransactions.at(i);
+ if (t.timestamp == timestamp) {
+ at = i;
+ break;
+ }
+ }
+ return at;
+}
+
+// timer used to discard old XdndDrop transactions
+static int transaction_expiry_timer = -1;
+enum { XdndDropTransactionTimeout = 5000 }; // 5 seconds
+
+static void restartXdndDropExpiryTimer()
+{
+ if (transaction_expiry_timer != -1)
+ QDragManager::self()->killTimer(transaction_expiry_timer);
+ transaction_expiry_timer = QDragManager::self()->startTimer(XdndDropTransactionTimeout);
+}
+
+
+// find an ancestor with XdndAware on it
+static Window findXdndAwareParent(Window window)
+{
+ Window target = 0;
+ forever {
+ // check if window has XdndAware
+ Atom type = 0;
+ int f;
+ unsigned long n, a;
+ unsigned char *data = 0;
+ if (XGetWindowProperty(X11->display, window, ATOM(XdndAware), 0, 0, False,
+ AnyPropertyType, &type, &f,&n,&a,&data) == Success) {
+ if (data)
+ XFree(data);
+ if (type) {
+ target = window;
+ break;
+ }
+ }
+
+ // try window's parent
+ Window root;
+ Window parent;
+ Window *children;
+ uint unused;
+ if (!XQueryTree(X11->display, window, &root, &parent, &children, &unused))
+ break;
+ if (children)
+ XFree(children);
+ if (window == root)
+ break;
+ window = parent;
+ }
+ return target;
+}
+
+
+
+
+// and all this stuff is copied -into- qapp_x11.cpp
+
+static void handle_xdnd_position(QWidget *, const XEvent *, bool);
+static void handle_xdnd_status(QWidget * w, const XEvent * xe, bool /*passive*/);
+
+const int xdnd_version = 5;
+
+static Qt::DropAction xdndaction_to_qtaction(Atom atom)
+{
+ if (atom == ATOM(XdndActionCopy) || atom == 0)
+ return Qt::CopyAction;
+ if (atom == ATOM(XdndActionLink))
+ return Qt::LinkAction;
+ if (atom == ATOM(XdndActionMove))
+ return Qt::MoveAction;
+ return Qt::CopyAction;
+}
+
+static int qtaction_to_xdndaction(Qt::DropAction a)
+{
+ switch (a) {
+ case Qt::CopyAction:
+ return ATOM(XdndActionCopy);
+ case Qt::LinkAction:
+ return ATOM(XdndActionLink);
+ case Qt::MoveAction:
+ case Qt::TargetMoveAction:
+ return ATOM(XdndActionMove);
+ case Qt::IgnoreAction:
+ return XNone;
+ default:
+ return ATOM(XdndActionCopy);
+ }
+}
+
+// clean up the stuff used.
+static void qt_xdnd_cleanup();
+
+static void qt_xdnd_send_leave();
+
+// real variables:
+// xid of current drag source
+static Atom qt_xdnd_dragsource_xid = 0;
+
+// the types in this drop. 100 is no good, but at least it's big.
+const int qt_xdnd_max_type = 100;
+static Atom qt_xdnd_types[qt_xdnd_max_type + 1];
+
+// timer used when target wants "continuous" move messages (eg. scroll)
+static int heartbeat = -1;
+// rectangle in which the answer will be the same
+static QRect qt_xdnd_source_sameanswer;
+// top-level window we sent position to last.
+static Window qt_xdnd_current_target;
+// window to send events to (always valid if qt_xdnd_current_target)
+static Window qt_xdnd_current_proxy_target;
+static Time qt_xdnd_source_current_time;
+
+// widget we forwarded position to last, and local position
+static QPointer<QWidget> qt_xdnd_current_widget;
+static QPoint qt_xdnd_current_position;
+// timestamp from the XdndPosition and XdndDrop
+static Time qt_xdnd_target_current_time;
+// screen number containing the pointer... -1 means default
+static int qt_xdnd_current_screen = -1;
+// state of dragging... true if dragging, false if not
+bool qt_xdnd_dragging = false;
+
+static bool waiting_for_status = false;
+
+// used to preset each new QDragMoveEvent
+static Qt::DropAction last_target_accepted_action = Qt::IgnoreAction;
+
+// Shift/Ctrl handling, and final drop status
+static Qt::DropAction global_accepted_action = Qt::CopyAction;
+static Qt::DropActions possible_actions = Qt::IgnoreAction;
+
+// for embedding only
+static QWidget* current_embedding_widget = 0;
+static XEvent last_enter_event;
+
+// cursors
+static QCursor *noDropCursor = 0;
+static QCursor *moveCursor = 0;
+static QCursor *copyCursor = 0;
+static QCursor *linkCursor = 0;
+
+static QPixmap *defaultPm = 0;
+
+static const int default_pm_hotx = -2;
+static const int default_pm_hoty = -16;
+static const char* const default_pm[] = {
+"13 9 3 1",
+". c None",
+" c #000000",
+"X c #FFFFFF",
+"X X X X X X X",
+" X X X X X X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X X X X X X ",
+"X X X X X X X"
+};
+
+class QShapedPixmapWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ QShapedPixmapWidget(QWidget* w) :
+ QWidget(w,
+ Qt::Tool | Qt::FramelessWindowHint
+ | Qt::X11BypassWindowManagerHint
+ | Qt::BypassGraphicsProxyWidget)
+ {
+ setAttribute(Qt::WA_X11NetWmWindowTypeDND);
+ }
+
+ void setPixmap(const QPixmap &pm)
+ {
+ QBitmap mask = pm.mask();
+ if (!mask.isNull()) {
+ setMask(mask);
+ } else {
+ clearMask();
+ }
+ resize(pm.width(),pm.height());
+ pixmap = pm;
+ update();
+ }
+ QPoint pm_hot;
+
+protected:
+ QPixmap pixmap;
+ void paintEvent(QPaintEvent*)
+ {
+ QPainter p(this);
+ p.drawPixmap(0, 0, pixmap);
+ }
+};
+
+#include "qdnd_x11.moc"
+
+struct XdndData {
+ QShapedPixmapWidget *deco;
+ QWidget* desktop_proxy;
+};
+
+static XdndData xdnd_data = { 0, 0 };
+
+class QExtraWidget : public QWidget
+{
+ Q_DECLARE_PRIVATE(QWidget)
+public:
+ inline QWExtra* extraData();
+ inline QTLWExtra* topData();
+};
+
+inline QWExtra* QExtraWidget::extraData() { return d_func()->extraData(); }
+inline QTLWExtra* QExtraWidget::topData() { return d_func()->topData(); }
+
+
+static WId xdndProxy(WId w)
+{
+ Atom type = XNone;
+ int f;
+ unsigned long n, a;
+ unsigned char *retval = 0;
+ XGetWindowProperty(X11->display, w, ATOM(XdndProxy), 0, 1, False,
+ XA_WINDOW, &type, &f,&n,&a,&retval);
+ WId *proxy_id_ptr = (WId *)retval;
+ WId proxy_id = 0;
+ if (type == XA_WINDOW && proxy_id_ptr) {
+ proxy_id = *proxy_id_ptr;
+ XFree(proxy_id_ptr);
+ proxy_id_ptr = 0;
+ // Already exists. Real?
+ X11->ignoreBadwindow();
+ XGetWindowProperty(X11->display, proxy_id, ATOM(XdndProxy), 0, 1, False,
+ XA_WINDOW, &type, &f,&n,&a,&retval);
+ proxy_id_ptr = (WId *)retval;
+ if (X11->badwindow() || type != XA_WINDOW || !proxy_id_ptr || *proxy_id_ptr != proxy_id)
+ // Bogus - we will overwrite.
+ proxy_id = 0;
+ }
+ if (proxy_id_ptr)
+ XFree(proxy_id_ptr);
+ return proxy_id;
+}
+
+static bool xdndEnable(QWidget* w, bool on)
+{
+ DNDDEBUG << "xdndEnable" << w << on;
+ if (on) {
+ QWidget * xdnd_widget = 0;
+ if ((w->windowType() == Qt::Desktop)) {
+ if (xdnd_data.desktop_proxy) // *WE* already have one.
+ return false;
+
+ // As per Xdnd4, use XdndProxy
+ XGrabServer(X11->display);
+ Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
+ WId proxy_id = xdndProxy(w->effectiveWinId());
+
+ if (!proxy_id) {
+ xdnd_widget = xdnd_data.desktop_proxy = new QWidget;
+ proxy_id = xdnd_data.desktop_proxy->effectiveWinId();
+ XChangeProperty (X11->display, w->effectiveWinId(), ATOM(XdndProxy),
+ XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1);
+ XChangeProperty (X11->display, proxy_id, ATOM(XdndProxy),
+ XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1);
+ }
+
+ XUngrabServer(X11->display);
+ } else {
+ xdnd_widget = w->window();
+ }
+ if (xdnd_widget) {
+ DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->effectiveWinId();
+ Atom atm = (Atom)xdnd_version;
+ Q_ASSERT(xdnd_widget->testAttribute(Qt::WA_WState_Created));
+ XChangeProperty(X11->display, xdnd_widget->effectiveWinId(), ATOM(XdndAware),
+ XA_ATOM, 32, PropModeReplace, (unsigned char *)&atm, 1);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if ((w->windowType() == Qt::Desktop)) {
+ XDeleteProperty(X11->display, w->internalWinId(), ATOM(XdndProxy));
+ delete xdnd_data.desktop_proxy;
+ xdnd_data.desktop_proxy = 0;
+ } else {
+ DNDDEBUG << "not deleting XDndAware";
+ }
+ return true;
+ }
+}
+
+QByteArray QX11Data::xdndAtomToString(Atom a)
+{
+ if (!a) return 0;
+
+ if (a == XA_STRING || a == ATOM(UTF8_STRING)) {
+ return "text/plain"; // some Xdnd clients are dumb
+ }
+ char *atom = XGetAtomName(display, a);
+ QByteArray result = atom;
+ XFree(atom);
+ return result;
+}
+
+Atom QX11Data::xdndStringToAtom(const char *mimeType)
+{
+ if (!mimeType || !*mimeType)
+ return 0;
+ return XInternAtom(display, mimeType, False);
+}
+
+//$$$
+QString QX11Data::xdndMimeAtomToString(Atom a)
+{
+ QString atomName;
+ if (a) {
+ char *atom = XGetAtomName(display, a);
+ atomName = QString::fromLatin1(atom);
+ XFree(atom);
+ }
+ return atomName;
+}
+
+//$$$
+Atom QX11Data::xdndMimeStringToAtom(const QString &mimeType)
+{
+ if (mimeType.isEmpty())
+ return 0;
+ return XInternAtom(display, mimeType.toLatin1().constData(), False);
+}
+
+//$$$ replace ccxdndAtomToString()
+QStringList QX11Data::xdndMimeFormatsForAtom(Atom a)
+{
+ QStringList formats;
+ if (a) {
+ QString atomName = xdndMimeAtomToString(a);
+ formats.append(atomName);
+
+ // special cases for string type
+ if (a == ATOM(UTF8_STRING) || a == XA_STRING
+ || a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT))
+ formats.append(QLatin1String("text/plain"));
+
+ // special cases for uris
+ if (atomName == QLatin1String("text/x-moz-url"))
+ formats.append(QLatin1String("text/uri-list"));
+
+ // special case for images
+ if (a == XA_PIXMAP)
+ formats.append(QLatin1String("image/ppm"));
+ }
+ return formats;
+}
+
+//$$$
+bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat)
+{
+ bool ret = false;
+ *atomFormat = a;
+ *dataFormat = 8;
+ QString atomName = xdndMimeAtomToString(a);
+ if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) {
+ *data = QInternalMimeData::renderDataHelper(atomName, mimeData);
+ if (atomName == QLatin1String("application/x-color"))
+ *dataFormat = 16;
+ ret = true;
+ } else {
+ if ((a == ATOM(UTF8_STRING) || a == XA_STRING
+ || a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT))
+ && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) {
+ if (a == ATOM(UTF8_STRING)){
+ *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData);
+ ret = true;
+ } else if (a == XA_STRING) {
+ *data = QString::fromUtf8(QInternalMimeData::renderDataHelper(
+ QLatin1String("text/plain"), mimeData)).toLocal8Bit();
+ ret = true;
+ } else if (a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT)) {
+ // the ICCCM states that TEXT and COMPOUND_TEXT are in the
+ // encoding of choice, so we choose the encoding of the locale
+ QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper(
+ QLatin1String("text/plain"), mimeData)).toLocal8Bit();
+ char *list[] = { strData.data(), NULL };
+
+ XICCEncodingStyle style = (a == ATOM(COMPOUND_TEXT))
+ ? XCompoundTextStyle : XStdICCTextStyle;
+ XTextProperty textprop;
+ if (list[0] != NULL
+ && XmbTextListToTextProperty(X11->display, list, 1, style,
+ &textprop) == Success) {
+ *atomFormat = textprop.encoding;
+ *dataFormat = textprop.format;
+ *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8);
+
+ DEBUG(" textprop type %lx\n"
+ " textprop name '%s'\n"
+ " format %d\n"
+ " %ld items\n"
+ " %d bytes\n",
+ textprop.encoding,
+ X11->xdndMimeAtomToString(textprop.encoding).toLatin1().data(),
+ textprop.format, textprop.nitems, data->size());
+
+ XFree(textprop.value);
+ }
+ }
+ } else if (atomName == QLatin1String("text/x-moz-url") &&
+ QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) {
+ QByteArray uri = QInternalMimeData::renderDataHelper(
+ QLatin1String("text/uri-list"), mimeData).split('\n').first();
+ QString mozUri = QString::fromLatin1(uri, uri.size());
+ mozUri += QLatin1Char('\n');
+ *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2);
+ ret = true;
+ } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) {
+ QPixmap pm = qvariant_cast<QPixmap>(mimeData->imageData());
+ if (a == XA_BITMAP && pm.depth() != 1) {
+ QImage img = pm.toImage();
+ img = img.convertToFormat(QImage::Format_MonoLSB);
+ pm = QPixmap::fromImage(img);
+ }
+ QDragManager *dm = QDragManager::self();
+ if (dm) {
+ Pixmap handle = pm.handle();
+ *data = QByteArray((const char *) &handle, sizeof(Pixmap));
+ dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm;
+ dm->xdndMimeTransferedPixmapIndex =
+ (dm->xdndMimeTransferedPixmapIndex + 1) % 2;
+ }
+ }
+ }
+ return data;
+}
+
+//$$$
+QList<Atom> QX11Data::xdndMimeAtomsForFormat(const QString &format)
+{
+ QList<Atom> atoms;
+ atoms.append(xdndMimeStringToAtom(format));
+
+ // special cases for strings
+ if (format == QLatin1String("text/plain")) {
+ atoms.append(ATOM(UTF8_STRING));
+ atoms.append(XA_STRING);
+ atoms.append(ATOM(TEXT));
+ atoms.append(ATOM(COMPOUND_TEXT));
+ }
+
+ // special cases for uris
+ if (format == QLatin1String("text/uri-list")) {
+ atoms.append(xdndMimeStringToAtom(QLatin1String("text/x-moz-url")));
+ }
+
+ //special cases for images
+ if (format == QLatin1String("image/ppm"))
+ atoms.append(XA_PIXMAP);
+ if (format == QLatin1String("image/pbm"))
+ atoms.append(XA_BITMAP);
+
+ return atoms;
+}
+
+//$$$
+QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding)
+{
+ QString atomName = xdndMimeAtomToString(a);
+ if (atomName == format)
+ return data;
+
+ if (!encoding.isEmpty()
+ && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) {
+
+ if (requestedType == QVariant::String) {
+ QTextCodec *codec = QTextCodec::codecForName(encoding);
+ if (codec)
+ return codec->toUnicode(data);
+ }
+
+ return data;
+ }
+
+ // special cases for string types
+ if (format == QLatin1String("text/plain")) {
+ if (a == ATOM(UTF8_STRING))
+ return QString::fromUtf8(data);
+ if (a == XA_STRING)
+ return QString::fromLatin1(data);
+ if (a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT))
+ // #### might be wrong for COMPUND_TEXT
+ return QString::fromLocal8Bit(data, data.size());
+ }
+
+ // special case for uri types
+ if (format == QLatin1String("text/uri-list")) {
+ if (atomName == QLatin1String("text/x-moz-url")) {
+ // we expect this as utf16 <url><space><title>
+ // the first part is a url that should only contain ascci char
+ // so it should be safe to check that the second char is 0
+ // to verify that it is utf16
+ if (data.size() > 1 && data.at(1) == 0)
+ return QString::fromUtf16(reinterpret_cast<const ushort *>(data.constData()),
+ data.size() / 2).split(QLatin1Char('\n')).first().toLatin1();
+ }
+ }
+
+ // special cas for images
+ if (format == QLatin1String("image/ppm")) {
+ if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) {
+ Pixmap xpm = *((Pixmap*)data.data());
+ Display *dpy = display;
+ Window r;
+ int x,y;
+ uint w,h,bw,d;
+ if (!xpm)
+ return QByteArray();
+ XGetGeometry(dpy,xpm, &r,&x,&y,&w,&h,&bw,&d);
+ QImageWriter imageWriter;
+ GC gc = XCreateGC(dpy, xpm, 0, 0);
+ QImage imageToWrite;
+ if (d == 1) {
+ QBitmap qbm(w,h);
+ XCopyArea(dpy,xpm,qbm.handle(),gc,0,0,w,h,0,0);
+ imageWriter.setFormat("PBMRAW");
+ imageToWrite = qbm.toImage();
+ } else {
+ QPixmap qpm(w,h);
+ XCopyArea(dpy,xpm,qpm.handle(),gc,0,0,w,h,0,0);
+ imageWriter.setFormat("PPMRAW");
+ imageToWrite = qpm.toImage();
+ }
+ XFreeGC(dpy,gc);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ imageWriter.setDevice(&buf);
+ imageWriter.write(imageToWrite);
+ return buf.buffer();
+ }
+ }
+ return QVariant();
+}
+
+//$$$ middle of xdndObtainData
+Atom QX11Data::xdndMimeAtomForFormat(const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *encoding)
+{
+ encoding->clear();
+
+ // find matches for string types
+ if (format == QLatin1String("text/plain")) {
+ if (atoms.contains(ATOM(UTF8_STRING)))
+ return ATOM(UTF8_STRING);
+ if (atoms.contains(ATOM(COMPOUND_TEXT)))
+ return ATOM(COMPOUND_TEXT);
+ if (atoms.contains(ATOM(TEXT)))
+ return ATOM(TEXT);
+ if (atoms.contains(XA_STRING))
+ return XA_STRING;
+ }
+
+ // find matches for uri types
+ if (format == QLatin1String("text/uri-list")) {
+ Atom a = xdndMimeStringToAtom(format);
+ if (a && atoms.contains(a))
+ return a;
+ a = xdndMimeStringToAtom(QLatin1String("text/x-moz-url"));
+ if (a && atoms.contains(a))
+ return a;
+ }
+
+ // find match for image
+ if (format == QLatin1String("image/ppm")) {
+ if (atoms.contains(XA_PIXMAP))
+ return XA_PIXMAP;
+ }
+
+ // for string/text requests try to use a format with a well-defined charset
+ // first to avoid encoding problems
+ if (requestedType == QVariant::String
+ && format.startsWith(QLatin1String("text/"))
+ && !format.contains(QLatin1String("charset="))) {
+
+ QString formatWithCharset = format;
+ formatWithCharset.append(QLatin1String(";charset=utf-8"));
+
+ Atom a = xdndMimeStringToAtom(formatWithCharset);
+ if (a && atoms.contains(a)) {
+ *encoding = "utf-8";
+ return a;
+ }
+ }
+
+ Atom a = xdndMimeStringToAtom(format);
+ if (a && atoms.contains(a))
+ return a;
+
+ return 0;
+}
+
+void QX11Data::xdndSetup() {
+ QCursorData::initialize();
+ qAddPostRoutine(qt_xdnd_cleanup);
+}
+
+
+void qt_xdnd_cleanup()
+{
+ delete noDropCursor;
+ noDropCursor = 0;
+ delete copyCursor;
+ copyCursor = 0;
+ delete moveCursor;
+ moveCursor = 0;
+ delete linkCursor;
+ linkCursor = 0;
+ delete defaultPm;
+ defaultPm = 0;
+ delete xdnd_data.desktop_proxy;
+ xdnd_data.desktop_proxy = 0;
+ delete xdnd_data.deco;
+ xdnd_data.deco = 0;
+}
+
+
+static QWidget *find_child(QWidget *tlw, QPoint & p)
+{
+ QWidget *widget = tlw;
+
+ p = widget->mapFromGlobal(p);
+ bool done = false;
+ while (!done) {
+ done = true;
+ if (((QExtraWidget*)widget)->extraData() &&
+ ((QExtraWidget*)widget)->extraData()->xDndProxy != 0)
+ break; // stop searching for widgets under the mouse cursor if found widget is a proxy.
+ QObjectList children = widget->children();
+ if (!children.isEmpty()) {
+ for(int i = children.size(); i > 0;) {
+ --i;
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (!w)
+ continue;
+ if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
+ continue;
+ if (w->isVisible() &&
+ w->geometry().contains(p) &&
+ !w->isWindow()) {
+ widget = w;
+ done = false;
+ p = widget->mapFromParent(p);
+ break;
+ }
+ }
+ }
+ }
+ return widget;
+}
+
+
+static bool checkEmbedded(QWidget* w, const XEvent* xe)
+{
+ if (!w)
+ return false;
+
+ if (current_embedding_widget != 0 && current_embedding_widget != w) {
+ qt_xdnd_current_target = ((QExtraWidget*)current_embedding_widget)->extraData()->xDndProxy;
+ qt_xdnd_current_proxy_target = qt_xdnd_current_target;
+ qt_xdnd_send_leave();
+ qt_xdnd_current_target = 0;
+ qt_xdnd_current_proxy_target = 0;
+ current_embedding_widget = 0;
+ }
+
+ QWExtra* extra = ((QExtraWidget*)w)->extraData();
+ if (extra && extra->xDndProxy != 0) {
+
+ if (current_embedding_widget != w) {
+
+ last_enter_event.xany.window = extra->xDndProxy;
+ XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, &last_enter_event);
+ current_embedding_widget = w;
+ }
+
+ ((XEvent*)xe)->xany.window = extra->xDndProxy;
+ XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, (XEvent*)xe);
+ if (qt_xdnd_current_widget != w) {
+ qt_xdnd_current_widget = w;
+ }
+ return true;
+ }
+ current_embedding_widget = 0;
+ return false;
+}
+
+void QX11Data::xdndHandleEnter(QWidget *, const XEvent * xe, bool /*passive*/)
+{
+ motifdnd_active = false;
+
+ last_enter_event.xclient = xe->xclient;
+
+ const long *l = xe->xclient.data.l;
+ int version = (int)(((unsigned long)(l[1])) >> 24);
+
+ if (version > xdnd_version)
+ return;
+
+ qt_xdnd_dragsource_xid = l[0];
+
+ int j = 0;
+ if (l[1] & 1) {
+ // get the types from XdndTypeList
+ Atom type = XNone;
+ int f;
+ unsigned long n, a;
+ unsigned char *retval;
+ XGetWindowProperty(X11->display, qt_xdnd_dragsource_xid, ATOM(XdndTypelist), 0,
+ qt_xdnd_max_type, False, XA_ATOM, &type, &f,&n,&a,&retval);
+ Atom *data = (Atom *)retval;
+ for (; j<qt_xdnd_max_type && j < (int)n; j++) {
+ qt_xdnd_types[j] = data[j];
+ }
+ if (data)
+ XFree((uchar*)data);
+ } else {
+ // get the types from the message
+ int i;
+ for(i=2; i < 5; i++) {
+ qt_xdnd_types[j++] = l[i];
+ }
+ }
+ qt_xdnd_types[j] = 0;
+}
+
+static void handle_xdnd_position(QWidget *w, const XEvent * xe, bool passive)
+{
+ const unsigned long *l = (const unsigned long *)xe->xclient.data.l;
+
+ QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff);
+ QWidget * c = find_child(w, p); // changes p to to c-local coordinates
+
+ if (!passive && checkEmbedded(c, xe))
+ return;
+
+ if (!c || (!c->acceptDrops() && (c->windowType() == Qt::Desktop)))
+ return;
+
+ if (l[0] != qt_xdnd_dragsource_xid) {
+ DEBUG("xdnd drag position from unexpected source (%08lx not %08lx)", l[0], qt_xdnd_dragsource_xid);
+ return;
+ }
+
+ // timestamp from the source
+ if (l[3] != 0) {
+ // Some X server/client combination swallow the first 32 bit and
+ // interpret a set bit 31 as negative sign.
+ qt_xdnd_target_current_time = X11->userTime =
+ ((sizeof(Time) == 8 && xe->xclient.data.l[3] < 0)
+ ? uint(l[3])
+ : l[3]);
+ }
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+
+ XClientMessageEvent response;
+ response.type = ClientMessage;
+ response.window = qt_xdnd_dragsource_xid;
+ response.format = 32;
+ response.message_type = ATOM(XdndStatus);
+ response.data.l[0] = w->effectiveWinId();
+ response.data.l[1] = 0; // flags
+ response.data.l[2] = 0; // x, y
+ response.data.l[3] = 0; // w, h
+ response.data.l[4] = 0; // action
+
+ if (!passive) { // otherwise just reject
+ while (c && !c->acceptDrops() && !c->isWindow()) {
+ p = c->mapToParent(p);
+ c = c->parentWidget();
+ }
+ QWidget *target_widget = c && c->acceptDrops() ? c : 0;
+
+ QRect answerRect(c->mapToGlobal(p), QSize(1,1));
+
+ if (manager->object) {
+ possible_actions = manager->dragPrivate()->possible_actions;
+ } else {
+ possible_actions = Qt::DropActions(xdndaction_to_qtaction(l[4]));
+// possible_actions |= Qt::CopyAction;
+ }
+ QDragMoveEvent me(p, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers());
+
+ Qt::DropAction accepted_action = Qt::IgnoreAction;
+
+
+ if (target_widget != qt_xdnd_current_widget) {
+ if (qt_xdnd_current_widget) {
+ QDragLeaveEvent e;
+ QApplication::sendEvent(qt_xdnd_current_widget, &e);
+ }
+ if (qt_xdnd_current_widget != target_widget) {
+ qt_xdnd_current_widget = target_widget;
+ }
+ if (target_widget) {
+ qt_xdnd_current_position = p;
+
+ last_target_accepted_action = Qt::IgnoreAction;
+ QDragEnterEvent de(p, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ QApplication::sendEvent(target_widget, &de);
+ if (de.isAccepted() && de.dropAction() != Qt::IgnoreAction)
+ last_target_accepted_action = de.dropAction();
+ }
+ }
+
+ DEBUG() << "qt_handle_xdnd_position action=" << X11->xdndAtomToString(l[4]);
+ if (!target_widget) {
+ answerRect = QRect(p, QSize(1, 1));
+ } else {
+ qt_xdnd_current_widget = c;
+ qt_xdnd_current_position = p;
+
+ if (last_target_accepted_action != Qt::IgnoreAction) {
+ me.setDropAction(last_target_accepted_action);
+ me.accept();
+ }
+ QApplication::sendEvent(c, &me);
+ if (me.isAccepted()) {
+ response.data.l[1] = 1; // yes
+ accepted_action = me.dropAction();
+ last_target_accepted_action = accepted_action;
+ } else {
+ response.data.l[0] = 0;
+ last_target_accepted_action = Qt::IgnoreAction;
+ }
+ answerRect = me.answerRect().intersected(c->rect());
+ }
+ answerRect = QRect(c->mapToGlobal(answerRect.topLeft()), answerRect.size());
+
+ if (answerRect.left() < 0)
+ answerRect.setLeft(0);
+ if (answerRect.right() > 4096)
+ answerRect.setRight(4096);
+ if (answerRect.top() < 0)
+ answerRect.setTop(0);
+ if (answerRect.bottom() > 4096)
+ answerRect.setBottom(4096);
+ if (answerRect.width() < 0)
+ answerRect.setWidth(0);
+ if (answerRect.height() < 0)
+ answerRect.setHeight(0);
+
+ response.data.l[2] = (answerRect.x() << 16) + answerRect.y();
+ response.data.l[3] = (answerRect.width() << 16) + answerRect.height();
+ response.data.l[4] = qtaction_to_xdndaction(accepted_action);
+ }
+
+ // reset
+ qt_xdnd_target_current_time = CurrentTime;
+
+ QWidget * source = QWidget::find(qt_xdnd_dragsource_xid);
+ if (source && (source->windowType() == Qt::Desktop) && !source->acceptDrops())
+ source = 0;
+
+ DEBUG() << "sending XdndStatus";
+ if (source)
+ handle_xdnd_status(source, (const XEvent *)&response, passive);
+ else
+ XSendEvent(X11->display, qt_xdnd_dragsource_xid, False, NoEventMask, (XEvent*)&response);
+}
+
+static Bool xdnd_position_scanner(Display *, XEvent *event, XPointer)
+{
+ if (event->type != ClientMessage)
+ return false;
+ XClientMessageEvent *ev = &event->xclient;
+
+ if (ev->message_type == ATOM(XdndPosition))
+ return true;
+
+ return false;
+}
+
+void QX11Data::xdndHandlePosition(QWidget * w, const XEvent * xe, bool passive)
+{
+ DEBUG("xdndHandlePosition");
+ while (XCheckIfEvent(X11->display, (XEvent *)xe, xdnd_position_scanner, 0))
+ ;
+
+ handle_xdnd_position(w, xe, passive);
+}
+
+
+static void handle_xdnd_status(QWidget *, const XEvent * xe, bool)
+{
+ const unsigned long *l = (const unsigned long *)xe->xclient.data.l;
+ // ignore late status messages
+ if (l[0] && l[0] != qt_xdnd_current_proxy_target)
+ return;
+ Qt::DropAction newAction = (l[1] & 0x1) ? xdndaction_to_qtaction(l[4]) : Qt::IgnoreAction;
+
+ if ((int)(l[1] & 2) == 0) {
+ QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff);
+ QSize s((l[3] & 0xffff0000) >> 16, l[3] & 0x0000ffff);
+ qt_xdnd_source_sameanswer = QRect(p, s);
+ } else {
+ qt_xdnd_source_sameanswer = QRect();
+ }
+ QDragManager *manager = QDragManager::self();
+ manager->willDrop = (l[1] & 0x1);
+ if (global_accepted_action != newAction)
+ manager->emitActionChanged(newAction);
+ global_accepted_action = newAction;
+ manager->updateCursor();
+ waiting_for_status = false;
+}
+
+static Bool xdnd_status_scanner(Display *, XEvent *event, XPointer)
+{
+ if (event->type != ClientMessage)
+ return false;
+ XClientMessageEvent *ev = &event->xclient;
+
+ if (ev->message_type == ATOM(XdndStatus))
+ return true;
+
+ return false;
+}
+
+void QX11Data::xdndHandleStatus(QWidget * w, const XEvent * xe, bool passive)
+{
+ DEBUG("xdndHandleStatus");
+ while (XCheckIfEvent(X11->display, (XEvent *)xe, xdnd_status_scanner, 0))
+ ;
+
+ handle_xdnd_status(w, xe, passive);
+ DEBUG("xdndHandleStatus end");
+}
+
+void QX11Data::xdndHandleLeave(QWidget *w, const XEvent * xe, bool /*passive*/)
+{
+ DEBUG("xdnd leave");
+ if (!qt_xdnd_current_widget ||
+ w->window() != qt_xdnd_current_widget->window()) {
+ return; // sanity
+ }
+
+ if (checkEmbedded(current_embedding_widget, xe)) {
+ current_embedding_widget = 0;
+ qt_xdnd_current_widget = 0;
+ return;
+ }
+
+ const unsigned long *l = (const unsigned long *)xe->xclient.data.l;
+
+ QDragLeaveEvent e;
+ QApplication::sendEvent(qt_xdnd_current_widget, &e);
+
+ if (l[0] != qt_xdnd_dragsource_xid) {
+ // This often happens - leave other-process window quickly
+ DEBUG("xdnd drag leave from unexpected source (%08lx not %08lx", l[0], qt_xdnd_dragsource_xid);
+ qt_xdnd_current_widget = 0;
+ return;
+ }
+
+ qt_xdnd_dragsource_xid = 0;
+ qt_xdnd_types[0] = 0;
+ qt_xdnd_current_widget = 0;
+}
+
+
+void qt_xdnd_send_leave()
+{
+ if (!qt_xdnd_current_target)
+ return;
+
+ XClientMessageEvent leave;
+ leave.type = ClientMessage;
+ leave.window = qt_xdnd_current_target;
+ leave.format = 32;
+ leave.message_type = ATOM(XdndLeave);
+ leave.data.l[0] = qt_xdnd_dragsource_xid;
+ leave.data.l[1] = 0; // flags
+ leave.data.l[2] = 0; // x, y
+ leave.data.l[3] = 0; // w, h
+ leave.data.l[4] = 0; // just null
+
+ QWidget * w = QWidget::find(qt_xdnd_current_proxy_target);
+
+ if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops())
+ w = 0;
+
+ if (w)
+ X11->xdndHandleLeave(w, (const XEvent *)&leave, false);
+ else
+ XSendEvent(X11->display, qt_xdnd_current_proxy_target, False,
+ NoEventMask, (XEvent*)&leave);
+ // reset the drag manager state
+ QDragManager *manager = QDragManager::self();
+ manager->willDrop = false;
+ if (global_accepted_action != Qt::IgnoreAction)
+ manager->emitActionChanged(Qt::IgnoreAction);
+ global_accepted_action = Qt::IgnoreAction;
+ manager->updateCursor();
+ qt_xdnd_current_target = 0;
+ qt_xdnd_current_proxy_target = 0;
+ qt_xdnd_source_current_time = 0;
+ waiting_for_status = false;
+}
+
+
+
+void QX11Data::xdndHandleDrop(QWidget *, const XEvent * xe, bool passive)
+{
+ DEBUG("xdndHandleDrop");
+ if (!qt_xdnd_current_widget) {
+ qt_xdnd_dragsource_xid = 0;
+ return; // sanity
+ }
+
+ if (!passive && checkEmbedded(qt_xdnd_current_widget, xe)){
+ current_embedding_widget = 0;
+ qt_xdnd_dragsource_xid = 0;
+ qt_xdnd_current_widget = 0;
+ return;
+ }
+ const unsigned long *l = (const unsigned long *)xe->xclient.data.l;
+
+ QDragManager *manager = QDragManager::self();
+ DEBUG("xdnd drop");
+
+ if (l[0] != qt_xdnd_dragsource_xid) {
+ DEBUG("xdnd drop from unexpected source (%08lx not %08lx", l[0], qt_xdnd_dragsource_xid);
+ return;
+ }
+
+ // update the "user time" from the timestamp in the event.
+ if (l[2] != 0) {
+ // Some X server/client combination swallow the first 32 bit and
+ // interpret a set bit 31 as negative sign.
+ qt_xdnd_target_current_time = X11->userTime =
+ ((sizeof(Time) == 8 && xe->xclient.data.l[2] < 0)
+ ? uint(l[2])
+ : l[2]);
+ }
+
+ if (!passive) {
+ // this could be a same-application drop, just proxied due to
+ // some XEMBEDding, so try to find the real QMimeData used
+ // based on the timestamp for this drop.
+ QMimeData *dropData = 0;
+ int at = findXdndDropTransactionByTime(qt_xdnd_target_current_time);
+ if (at != -1)
+ dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
+ // if we can't find it, then use the data in the drag manager
+ if (!dropData)
+ dropData = (manager->object) ? manager->dragPrivate()->data : manager->dropData;
+
+ QDropEvent de(qt_xdnd_current_position, possible_actions, dropData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ QApplication::sendEvent(qt_xdnd_current_widget, &de);
+ if (!de.isAccepted()) {
+ // Ignore a failed drag
+ global_accepted_action = Qt::IgnoreAction;
+ } else {
+ global_accepted_action = de.dropAction();
+ }
+ XClientMessageEvent finished;
+ finished.type = ClientMessage;
+ finished.window = qt_xdnd_dragsource_xid;
+ finished.format = 32;
+ finished.message_type = ATOM(XdndFinished);
+ DNDDEBUG << "xdndHandleDrop"
+ << "qt_xdnd_current_widget" << qt_xdnd_current_widget
+ << (qt_xdnd_current_widget ? qt_xdnd_current_widget->effectiveWinId() : 0)
+ << "t_xdnd_current_widget->window()"
+ << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window() : 0)
+ << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window()->internalWinId() : 0);
+ finished.data.l[0] = qt_xdnd_current_widget?qt_xdnd_current_widget->window()->internalWinId():0;
+ finished.data.l[1] = de.isAccepted() ? 1 : 0; // flags
+ finished.data.l[2] = qtaction_to_xdndaction(global_accepted_action);
+ XSendEvent(X11->display, qt_xdnd_dragsource_xid, False,
+ NoEventMask, (XEvent*)&finished);
+ } else {
+ QDragLeaveEvent e;
+ QApplication::sendEvent(qt_xdnd_current_widget, &e);
+ }
+ qt_xdnd_dragsource_xid = 0;
+ qt_xdnd_current_widget = 0;
+ waiting_for_status = false;
+
+ // reset
+ qt_xdnd_target_current_time = CurrentTime;
+}
+
+
+void QX11Data::xdndHandleFinished(QWidget *, const XEvent * xe, bool passive)
+{
+ DEBUG("xdndHandleFinished");
+ const unsigned long *l = (const unsigned long *)xe->xclient.data.l;
+
+ DNDDEBUG << "xdndHandleFinished, l[0]" << l[0]
+ << "qt_xdnd_current_target" << qt_xdnd_current_target
+ << "qt_xdnd_current_proxy_targe" << qt_xdnd_current_proxy_target;
+
+ if (l[0]) {
+ int at = findXdndDropTransactionByWindow(l[0]);
+ if (at != -1) {
+ restartXdndDropExpiryTimer();
+
+ QXdndDropTransaction t = X11->dndDropTransactions.takeAt(at);
+ QDragManager *manager = QDragManager::self();
+
+ Window target = qt_xdnd_current_target;
+ Window proxy_target = qt_xdnd_current_proxy_target;
+ QWidget *embedding_widget = current_embedding_widget;
+ QDrag *currentObject = manager->object;
+
+ qt_xdnd_current_target = t.target;
+ qt_xdnd_current_proxy_target = t.proxy_target;
+ current_embedding_widget = t.embedding_widget;
+ manager->object = t.object;
+
+ if (!passive)
+ (void) checkEmbedded(qt_xdnd_current_widget, xe);
+
+ current_embedding_widget = 0;
+ qt_xdnd_current_target = 0;
+ qt_xdnd_current_proxy_target = 0;
+
+ if (t.object)
+ t.object->deleteLater();
+
+ qt_xdnd_current_target = target;
+ qt_xdnd_current_proxy_target = proxy_target;
+ current_embedding_widget = embedding_widget;
+ manager->object = currentObject;
+ }
+ }
+ waiting_for_status = false;
+}
+
+
+void QDragManager::timerEvent(QTimerEvent* e)
+{
+ if (e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull()) {
+ move(QCursor::pos());
+ } else if (e->timerId() == transaction_expiry_timer) {
+ for (int i = 0; i < X11->dndDropTransactions.count(); ++i) {
+ const QXdndDropTransaction &t = X11->dndDropTransactions.at(i);
+ if (t.targetWidget) {
+ // dnd within the same process, don't delete these
+ continue;
+ }
+ t.object->deleteLater();
+ X11->dndDropTransactions.removeAt(i--);
+ }
+
+ killTimer(transaction_expiry_timer);
+ transaction_expiry_timer = -1;
+ }
+}
+
+bool QDragManager::eventFilter(QObject * o, QEvent * e)
+{
+ if (beingCancelled) {
+ if (e->type() == QEvent::KeyRelease && ((QKeyEvent*)e)->key() == Qt::Key_Escape) {
+ qApp->removeEventFilter(this);
+ Q_ASSERT(object == 0);
+ beingCancelled = false;
+ eventLoop->exit();
+ return true; // block the key release
+ }
+ return false;
+ }
+
+ Q_ASSERT(object != 0);
+
+ if (!o->isWidgetType())
+ return false;
+
+ if (e->type() == QEvent::MouseMove) {
+ QMouseEvent* me = (QMouseEvent *)e;
+ move(me->globalPos());
+ return true;
+ } else if (e->type() == QEvent::MouseButtonRelease) {
+ DEBUG("pre drop");
+ qApp->removeEventFilter(this);
+ if (willDrop)
+ drop();
+ else
+ cancel();
+ DEBUG("drop, resetting object");
+ beingCancelled = false;
+ eventLoop->exit();
+ return true;
+ }
+
+ if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
+ QKeyEvent *ke = ((QKeyEvent*)e);
+ if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ eventLoop->exit();
+ } else {
+ qt_xdnd_source_sameanswer = QRect(); // force move
+ move(QCursor::pos());
+ }
+ return true; // Eat all key events
+ }
+
+ // ### We bind modality to widgets, so we have to do this
+ // ### "manually".
+ // DnD is modal - eat all other interactive events
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::Wheel:
+ case QEvent::ShortcutOverride:
+#ifdef QT3_SUPPORT
+ case QEvent::Accel:
+ case QEvent::AccelAvailable:
+#endif
+ return true;
+ default:
+ return false;
+ }
+}
+
+void QDragManager::updateCursor()
+{
+ if (!noDropCursor) {
+#ifndef QT_NO_CURSOR
+ noDropCursor = new QCursor(Qt::ForbiddenCursor);
+ moveCursor = new QCursor(dragCursor(Qt::MoveAction), 0,0);
+ copyCursor = new QCursor(dragCursor(Qt::CopyAction), 0,0);
+ linkCursor = new QCursor(dragCursor(Qt::LinkAction), 0,0);
+#endif
+ }
+
+ QCursor *c;
+ if (willDrop) {
+ if (global_accepted_action == Qt::CopyAction) {
+ c = copyCursor;
+ } else if (global_accepted_action == Qt::LinkAction) {
+ c = linkCursor;
+ } else {
+ c = moveCursor;
+ }
+ if (xdnd_data.deco) {
+ xdnd_data.deco->show();
+ xdnd_data.deco->raise();
+ }
+ } else {
+ c = noDropCursor;
+ //if (qt_xdnd_deco)
+ // qt_xdnd_deco->hide();
+ }
+#ifndef QT_NO_CURSOR
+ if (c)
+ qApp->changeOverrideCursor(*c);
+#endif
+}
+
+
+void QDragManager::cancel(bool deleteSource)
+{
+ DEBUG("QDragManager::cancel");
+ Q_ASSERT(heartbeat != -1);
+ killTimer(heartbeat);
+ heartbeat = -1;
+ beingCancelled = true;
+ qt_xdnd_dragging = false;
+
+ if (qt_xdnd_current_target)
+ qt_xdnd_send_leave();
+
+#ifndef QT_NO_CURSOR
+ if (restoreCursor) {
+ QApplication::restoreOverrideCursor();
+ restoreCursor = false;
+ }
+#endif
+
+ if (deleteSource && object)
+ object->deleteLater();
+ object = 0;
+ qDeleteInEventHandler(xdnd_data.deco);
+ xdnd_data.deco = 0;
+
+ global_accepted_action = Qt::IgnoreAction;
+}
+
+static
+Window findRealWindow(const QPoint & pos, Window w, int md)
+{
+ if (xdnd_data.deco && w == xdnd_data.deco->effectiveWinId())
+ return 0;
+
+ if (md) {
+ X11->ignoreBadwindow();
+ XWindowAttributes attr;
+ XGetWindowAttributes(X11->display, w, &attr);
+ if (X11->badwindow())
+ return 0;
+
+ if (attr.map_state == IsViewable
+ && QRect(attr.x,attr.y,attr.width,attr.height).contains(pos)) {
+ {
+ Atom type = XNone;
+ int f;
+ unsigned long n, a;
+ unsigned char *data;
+
+ XGetWindowProperty(X11->display, w, ATOM(XdndAware), 0, 0, False,
+ AnyPropertyType, &type, &f,&n,&a,&data);
+ if (data) XFree(data);
+ if (type)
+ return w;
+ }
+
+ Window r, p;
+ Window* c;
+ uint nc;
+ if (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
+ r=0;
+ for (uint i=nc; !r && i--;) {
+ r = findRealWindow(pos-QPoint(attr.x,attr.y),
+ c[i], md-1);
+ }
+ XFree(c);
+ if (r)
+ return r;
+
+ // We didn't find a client window! Just use the
+ // innermost window.
+ }
+
+ // No children!
+ return w;
+ }
+ }
+ return 0;
+}
+
+void QDragManager::move(const QPoint & globalPos)
+{
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(globalPos);
+ return;
+#else
+ DEBUG() << "QDragManager::move enter";
+ if (!object) {
+ // perhaps the target crashed?
+ return;
+ }
+
+ int screen = QCursor::x11Screen();
+ if ((qt_xdnd_current_screen == -1 && screen != X11->defaultScreen) || (screen != qt_xdnd_current_screen)) {
+ // recreate the pixmap on the new screen...
+ delete xdnd_data.deco;
+ QWidget* parent = object->source()->window()->x11Info().screen() == screen
+ ? object->source()->window() : QApplication::desktop()->screen(screen);
+ xdnd_data.deco = new QShapedPixmapWidget(parent);
+ if (!QWidget::mouseGrabber()) {
+ updatePixmap();
+ xdnd_data.deco->grabMouse();
+ }
+ }
+ xdnd_data.deco->move(QCursor::pos() - xdnd_data.deco->pm_hot);
+
+ if (qt_xdnd_source_sameanswer.contains(globalPos) && qt_xdnd_source_sameanswer.isValid())
+ return;
+
+ qt_xdnd_current_screen = screen;
+ Window rootwin = QX11Info::appRootWindow(qt_xdnd_current_screen);
+ Window target = 0;
+ int lx = 0, ly = 0;
+ if (!XTranslateCoordinates(X11->display, rootwin, rootwin, globalPos.x(), globalPos.y(), &lx, &ly, &target))
+ // some weird error...
+ return;
+
+ if (target == rootwin) {
+ // Ok.
+ } else if (target) {
+ //me
+ Window src = rootwin;
+ while (target != 0) {
+ DNDDEBUG << "checking target for XdndAware" << QWidget::find(target) << target;
+ int lx2, ly2;
+ Window t;
+ // translate coordinates
+ if (!XTranslateCoordinates(X11->display, src, target, lx, ly, &lx2, &ly2, &t)) {
+ target = 0;
+ break;
+ }
+ lx = lx2;
+ ly = ly2;
+ src = target;
+
+ // check if it has XdndAware
+ Atom type = 0;
+ int f;
+ unsigned long n, a;
+ unsigned char *data = 0;
+ XGetWindowProperty(X11->display, target, ATOM(XdndAware), 0, 0, False,
+ AnyPropertyType, &type, &f,&n,&a,&data);
+ if (data)
+ XFree(data);
+ if (type) {
+ DNDDEBUG << "Found XdndAware on " << QWidget::find(target) << target;
+ break;
+ }
+
+ // find child at the coordinates
+ if (!XTranslateCoordinates(X11->display, src, src, lx, ly, &lx2, &ly2, &target)) {
+ target = 0;
+ break;
+ }
+ }
+ if (xdnd_data.deco && (!target || target == xdnd_data.deco->effectiveWinId())) {
+ DNDDEBUG << "need to find real window";
+ target = findRealWindow(globalPos, rootwin, 6);
+ DNDDEBUG << "real window found" << QWidget::find(target) << target;
+ }
+ }
+
+ QWidget* w;
+ if (target) {
+ w = QWidget::find((WId)target);
+ if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops())
+ w = 0;
+ } else {
+ w = 0;
+ target = rootwin;
+ }
+
+ DNDDEBUG << "and the final target is " << QWidget::find(target) << target;
+ DNDDEBUG << "the widget w is" << w;
+
+ WId proxy_target = xdndProxy(target);
+ if (!proxy_target)
+ proxy_target = target;
+ int target_version = 1;
+
+ if (proxy_target) {
+ Atom type = XNone;
+ int r, f;
+ unsigned long n, a;
+ unsigned char *retval;
+ X11->ignoreBadwindow();
+ r = XGetWindowProperty(X11->display, proxy_target, ATOM(XdndAware), 0,
+ 1, False, AnyPropertyType, &type, &f,&n,&a,&retval);
+ int *tv = (int *)retval;
+ if (r != Success || X11->badwindow()) {
+ target = 0;
+ } else {
+ target_version = qMin(xdnd_version,tv ? *tv : 1);
+ if (tv)
+ XFree(tv);
+// if (!(!X11->badwindow() && type))
+// target = 0;
+ }
+ }
+
+ if (target != qt_xdnd_current_target) {
+ if (qt_xdnd_current_target)
+ qt_xdnd_send_leave();
+
+ qt_xdnd_current_target = target;
+ qt_xdnd_current_proxy_target = proxy_target;
+ if (target) {
+ QVector<Atom> types;
+ int flags = target_version << 24;
+ QStringList fmts = QInternalMimeData::formatsHelper(dragPrivate()->data);
+ for (int i = 0; i < fmts.size(); ++i) {
+ QList<Atom> atoms = X11->xdndMimeAtomsForFormat(fmts.at(i));
+ for (int j = 0; j < atoms.size(); ++j) {
+ if (!types.contains(atoms.at(j)))
+ types.append(atoms.at(j));
+ }
+ }
+ if (types.size() > 3) {
+ XChangeProperty(X11->display,
+ dragPrivate()->source->effectiveWinId(), ATOM(XdndTypelist),
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)types.data(),
+ types.size());
+ flags |= 0x0001;
+ }
+ XClientMessageEvent enter;
+ enter.type = ClientMessage;
+ enter.window = target;
+ enter.format = 32;
+ enter.message_type = ATOM(XdndEnter);
+ enter.data.l[0] = dragPrivate()->source->effectiveWinId();
+ enter.data.l[1] = flags;
+ enter.data.l[2] = types.size()>0 ? types.at(0) : 0;
+ enter.data.l[3] = types.size()>1 ? types.at(1) : 0;
+ enter.data.l[4] = types.size()>2 ? types.at(2) : 0;
+ // provisionally set the rectangle to 5x5 pixels...
+ qt_xdnd_source_sameanswer = QRect(globalPos.x() - 2,
+ globalPos.y() -2 , 5, 5);
+
+ DEBUG("sending Xdnd enter");
+ if (w)
+ X11->xdndHandleEnter(w, (const XEvent *)&enter, false);
+ else if (target)
+ XSendEvent(X11->display, proxy_target, False, NoEventMask, (XEvent*)&enter);
+ waiting_for_status = false;
+ }
+ }
+ if (waiting_for_status)
+ return;
+
+ if (target) {
+ waiting_for_status = true;
+
+ XClientMessageEvent move;
+ move.type = ClientMessage;
+ move.window = target;
+ move.format = 32;
+ move.message_type = ATOM(XdndPosition);
+ move.window = target;
+ move.data.l[0] = dragPrivate()->source->effectiveWinId();
+ move.data.l[1] = 0; // flags
+ move.data.l[2] = (globalPos.x() << 16) + globalPos.y();
+ move.data.l[3] = X11->time;
+ move.data.l[4] = qtaction_to_xdndaction(defaultAction(dragPrivate()->possible_actions, QApplication::keyboardModifiers()));
+ DEBUG("sending Xdnd position");
+
+ qt_xdnd_source_current_time = X11->time;
+
+ if (w)
+ handle_xdnd_position(w, (const XEvent *)&move, false);
+ else
+ XSendEvent(X11->display, proxy_target, False, NoEventMask,
+ (XEvent*)&move);
+ } else {
+ if (willDrop) {
+ willDrop = false;
+ updateCursor();
+ }
+ }
+ DEBUG() << "QDragManager::move leave";
+#endif
+}
+
+
+void QDragManager::drop()
+{
+ Q_ASSERT(heartbeat != -1);
+ killTimer(heartbeat);
+ heartbeat = -1;
+ qt_xdnd_dragging = false;
+
+ if (!qt_xdnd_current_target)
+ return;
+
+ qDeleteInEventHandler(xdnd_data.deco);
+ xdnd_data.deco = 0;
+
+ XClientMessageEvent drop;
+ drop.type = ClientMessage;
+ drop.window = qt_xdnd_current_target;
+ drop.format = 32;
+ drop.message_type = ATOM(XdndDrop);
+ drop.data.l[0] = dragPrivate()->source->effectiveWinId();
+ drop.data.l[1] = 0; // flags
+ drop.data.l[2] = X11->time;
+
+ drop.data.l[3] = 0;
+ drop.data.l[4] = 0;
+
+ QWidget * w = QWidget::find(qt_xdnd_current_proxy_target);
+
+ if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops())
+ w = 0;
+
+ QXdndDropTransaction t = {
+ X11->time,
+ qt_xdnd_current_target,
+ qt_xdnd_current_proxy_target,
+ w,
+ current_embedding_widget,
+ object
+ };
+ X11->dndDropTransactions.append(t);
+ restartXdndDropExpiryTimer();
+
+ if (w)
+ X11->xdndHandleDrop(w, (const XEvent *)&drop, false);
+ else
+ XSendEvent(X11->display, qt_xdnd_current_proxy_target, False,
+ NoEventMask, (XEvent*)&drop);
+
+ qt_xdnd_current_target = 0;
+ qt_xdnd_current_proxy_target = 0;
+ qt_xdnd_source_current_time = 0;
+ current_embedding_widget = 0;
+ object = 0;
+
+#ifndef QT_NO_CURSOR
+ if (restoreCursor) {
+ QApplication::restoreOverrideCursor();
+ restoreCursor = false;
+ }
+#endif
+}
+
+
+
+bool QX11Data::xdndHandleBadwindow()
+{
+ if (qt_xdnd_current_target) {
+ QDragManager *manager = QDragManager::self();
+ if (manager->object) {
+ qt_xdnd_current_target = 0;
+ qt_xdnd_current_proxy_target = 0;
+ manager->object->deleteLater();
+ manager->object = 0;
+ delete xdnd_data.deco;
+ xdnd_data.deco = 0;
+ return true;
+ }
+ }
+ if (qt_xdnd_dragsource_xid) {
+ qt_xdnd_dragsource_xid = 0;
+ if (qt_xdnd_current_widget) {
+ QApplication::postEvent(qt_xdnd_current_widget, new QDragLeaveEvent);
+ qt_xdnd_current_widget = 0;
+ }
+ return true;
+ }
+ return false;
+}
+
+void QX11Data::xdndHandleSelectionRequest(const XSelectionRequestEvent * req)
+{
+ if (!req)
+ return;
+ XEvent evt;
+ evt.xselection.type = SelectionNotify;
+ evt.xselection.display = req->display;
+ evt.xselection.requestor = req->requestor;
+ evt.xselection.selection = req->selection;
+ evt.xselection.target = XNone;
+ evt.xselection.property = XNone;
+ evt.xselection.time = req->time;
+
+ QDragManager *manager = QDragManager::self();
+ QDrag *currentObject = manager->object;
+
+ // which transaction do we use? (note: -2 means use current manager->object)
+ int at = -1;
+
+ // figure out which data the requestor is really interested in
+ if (manager->object && req->time == qt_xdnd_source_current_time) {
+ // requestor wants the current drag data
+ at = -2;
+ } else {
+ // if someone has requested data in response to XdndDrop, find the corresponding transaction. the
+ // spec says to call XConvertSelection() using the timestamp from the XdndDrop
+ at = findXdndDropTransactionByTime(req->time);
+ if (at == -1) {
+ // no dice, perhaps the client was nice enough to use the same window id in XConvertSelection()
+ // that we sent the XdndDrop event to.
+ at = findXdndDropTransactionByWindow(req->requestor);
+ }
+ if (at == -1 && req->time == CurrentTime) {
+ // previous Qt versions always requested the data on a child of the target window
+ // using CurrentTime... but it could be asking for either drop data or the current drag's data
+ Window target = findXdndAwareParent(req->requestor);
+ if (target) {
+ if (qt_xdnd_current_target && qt_xdnd_current_target == target)
+ at = -2;
+ else
+ at = findXdndDropTransactionByWindow(target);
+ }
+ }
+ }
+ if (at >= 0) {
+ restartXdndDropExpiryTimer();
+
+ // use the drag object from an XdndDrop tansaction
+ manager->object = X11->dndDropTransactions.at(at).object;
+ } else if (at != -2) {
+ // no transaction found, we'll have to reject the request
+ manager->object = 0;
+ }
+ if (manager->object) {
+ Atom atomFormat = req->target;
+ int dataFormat = 0;
+ QByteArray data;
+ if (X11->xdndMimeDataForAtom(req->target, manager->dragPrivate()->data,
+ &data, &atomFormat, &dataFormat)) {
+ int dataSize = data.size() / (dataFormat / 8);
+ XChangeProperty (X11->display, req->requestor, req->property,
+ atomFormat, dataFormat, PropModeReplace,
+ (unsigned char *)data.data(), dataSize);
+ evt.xselection.property = req->property;
+ evt.xselection.target = atomFormat;
+ }
+ }
+
+ // reset manager->object in case we modified it above
+ manager->object = currentObject;
+
+ // ### this can die if req->requestor crashes at the wrong
+ // ### moment
+ XSendEvent(X11->display, req->requestor, False, 0, &evt);
+}
+
+static QVariant xdndObtainData(const char *format, QVariant::Type requestedType)
+{
+ QByteArray result;
+
+ QWidget* w;
+ QDragManager *manager = QDragManager::self();
+ if (qt_xdnd_dragsource_xid && manager->object &&
+ (w=QWidget::find(qt_xdnd_dragsource_xid))
+ && (!(w->windowType() == Qt::Desktop) || w->acceptDrops()))
+ {
+ QDragPrivate * o = QDragManager::self()->dragPrivate();
+ if (o->data->hasFormat(QLatin1String(format)))
+ result = o->data->data(QLatin1String(format));
+ return result;
+ }
+
+ QList<Atom> atoms;
+ int i = 0;
+ while ((qt_xdnd_types[i])) {
+ atoms.append(qt_xdnd_types[i]);
+ ++i;
+ }
+ QByteArray encoding;
+ Atom a = X11->xdndMimeAtomForFormat(QLatin1String(format), requestedType, atoms, &encoding);
+ if (!a)
+ return result;
+
+ if (XGetSelectionOwner(X11->display, ATOM(XdndSelection)) == XNone)
+ return result; // should never happen?
+
+ QWidget* tw = qt_xdnd_current_widget;
+ if (!qt_xdnd_current_widget || (qt_xdnd_current_widget->windowType() == Qt::Desktop))
+ tw = new QWidget;
+
+ XConvertSelection(X11->display, ATOM(XdndSelection), a, ATOM(XdndSelection), tw->effectiveWinId(),
+ qt_xdnd_target_current_time);
+ XFlush(X11->display);
+
+ XEvent xevent;
+ bool got=X11->clipboardWaitForEvent(tw->effectiveWinId(), SelectionNotify, &xevent, 5000);
+ if (got) {
+ Atom type;
+
+ if (X11->clipboardReadProperty(tw->effectiveWinId(), ATOM(XdndSelection), true, &result, 0, &type, 0, false)) {
+ if (type == ATOM(INCR)) {
+ int nbytes = result.size() >= 4 ? *((int*)result.data()) : 0;
+ result = X11->clipboardReadIncrementalProperty(tw->effectiveWinId(), ATOM(XdndSelection), nbytes, false);
+ } else if (type != a && type != XNone) {
+ DEBUG("Qt clipboard: unknown atom %ld", type);
+ }
+ }
+ }
+ if (!qt_xdnd_current_widget || (qt_xdnd_current_widget->windowType() == Qt::Desktop))
+ delete tw;
+
+ return X11->xdndMimeConvertToFormat(a, result, QLatin1String(format), requestedType, encoding);
+}
+
+
+/*
+ Enable drag and drop for widget w by installing the proper
+ properties on w's toplevel widget.
+*/
+bool QX11Data::dndEnable(QWidget* w, bool on)
+{
+ w = w->window();
+
+ if (bool(((QExtraWidget*)w)->topData()->dnd) == on)
+ return true; // been there, done that
+ ((QExtraWidget*)w)->topData()->dnd = on ? 1 : 0;
+
+ motifdndEnable(w, on);
+ return xdndEnable(w, on);
+}
+
+Qt::DropAction QDragManager::drag(QDrag * o)
+{
+ if (object == o || !o || !o->d_func()->source)
+ return Qt::IgnoreAction;
+
+ if (object) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ }
+
+ if (object) {
+ // the last drag and drop operation hasn't finished, so we are going to wait
+ // for one second to see if it does... if the finish message comes after this,
+ // then we could still have problems, but this is highly unlikely
+ QApplication::flush();
+
+ QTime started = QTime::currentTime();
+ QTime now = started;
+ do {
+ XEvent event;
+ if (XCheckTypedEvent(X11->display, ClientMessage, &event))
+ qApp->x11ProcessEvent(&event);
+
+ now = QTime::currentTime();
+ if (started > now) // crossed midnight
+ started = now;
+
+ // sleep 50 ms, so we don't use up CPU cycles all the time.
+ struct timeval usleep_tv;
+ usleep_tv.tv_sec = 0;
+ usleep_tv.tv_usec = 50000;
+ select(0, 0, 0, 0, &usleep_tv);
+ } while (object && started.msecsTo(now) < 1000);
+ }
+
+ object = o;
+ object->d_func()->target = 0;
+ xdnd_data.deco = new QShapedPixmapWidget(object->source()->window());
+
+ willDrop = false;
+
+ updatePixmap();
+
+ qApp->installEventFilter(this);
+ XSetSelectionOwner(X11->display, ATOM(XdndSelection), dragPrivate()->source->window()->internalWinId(), X11->time);
+ global_accepted_action = Qt::CopyAction;
+ qt_xdnd_source_sameanswer = QRect();
+#ifndef QT_NO_CURSOR
+ // set the override cursor (must be done here, since it is updated
+ // in the call to move() below)
+ qApp->setOverrideCursor(Qt::ArrowCursor);
+ restoreCursor = true;
+#endif
+ move(QCursor::pos());
+ heartbeat = startTimer(200);
+
+ qt_xdnd_dragging = true;
+
+ if (!QWidget::mouseGrabber())
+ xdnd_data.deco->grabMouse();
+
+ eventLoop = new QEventLoop;
+ (void) eventLoop->exec();
+ delete eventLoop;
+ eventLoop = 0;
+
+#ifndef QT_NO_CURSOR
+ if (restoreCursor) {
+ qApp->restoreOverrideCursor();
+ restoreCursor = false;
+ }
+#endif
+
+ // delete cursors as they may be different next drag.
+ delete noDropCursor;
+ noDropCursor = 0;
+ delete copyCursor;
+ copyCursor = 0;
+ delete moveCursor;
+ moveCursor = 0;
+ delete linkCursor;
+ linkCursor = 0;
+
+ delete xdnd_data.deco;
+ xdnd_data.deco = 0;
+ if (heartbeat != -1)
+ killTimer(heartbeat);
+ heartbeat = -1;
+ qt_xdnd_current_screen = -1;
+ qt_xdnd_dragging = false;
+
+ return global_accepted_action;
+ // object persists until we get an xdnd_finish message
+}
+
+void QDragManager::updatePixmap()
+{
+ if (xdnd_data.deco) {
+ QPixmap pm;
+ QPoint pm_hot(default_pm_hotx,default_pm_hoty);
+ if (object) {
+ pm = dragPrivate()->pixmap;
+ if (!pm.isNull())
+ pm_hot = dragPrivate()->hotspot;
+ }
+ if (pm.isNull()) {
+ if (!defaultPm)
+ defaultPm = new QPixmap(default_pm);
+ pm = *defaultPm;
+ }
+ xdnd_data.deco->pm_hot = pm_hot;
+ xdnd_data.deco->setPixmap(pm);
+ xdnd_data.deco->move(QCursor::pos()-pm_hot);
+ xdnd_data.deco->show();
+ }
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const
+{
+ QByteArray mime = mimetype.toLatin1();
+ QVariant data = X11->motifdnd_active
+ ? X11->motifdndObtainData(mime)
+ : xdndObtainData(mime, requestedType);
+ return data;
+}
+
+bool QDropData::hasFormat_sys(const QString &format) const
+{
+ return formats().contains(format);
+}
+
+QStringList QDropData::formats_sys() const
+{
+ QStringList formats;
+ if (X11->motifdnd_active) {
+ int i = 0;
+ QByteArray fmt;
+ while (!(fmt = X11->motifdndFormat(i)).isEmpty()) {
+ formats.append(QLatin1String(fmt));
+ ++i;
+ }
+ } else {
+ int i = 0;
+ while ((qt_xdnd_types[i])) {
+ QStringList formatsForAtom = X11->xdndMimeFormatsForAtom(qt_xdnd_types[i]);
+ for (int j = 0; j < formatsForAtom.size(); ++j) {
+ if (!formats.contains(formatsForAtom.at(j)))
+ formats.append(formatsForAtom.at(j));
+ }
+ ++i;
+ }
+ }
+ return formats;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp
new file mode 100644
index 0000000000..e980d1cdbe
--- /dev/null
+++ b/src/gui/kernel/qdrag.cpp
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qwidget.h>
+#include <qdrag.h>
+#include <qpixmap.h>
+#include <qpoint.h>
+#include "qdnd_p.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDrag
+ \brief The QDrag class provides support for MIME-based drag and drop data
+ transfer.
+
+ Drag and drop is an intuitive way for users to copy or move data around in an
+ application, and is used in many desktop environments as a mechanism for copying
+ data between applications. Drag and drop support in Qt is centered around the
+ QDrag class that handles most of the details of a drag and drop operation.
+
+ The data to be transferred by the drag and drop operation is contained in a
+ QMimeData object. This is specified with the setMimeData() function in the
+ following way:
+
+ \snippet doc/src/snippets/dragging/mainwindow.cpp 1
+
+ Note that setMimeData() assigns ownership of the QMimeData object to the
+ QDrag object. The QDrag must be constructed on the heap with a parent QWidget
+ to ensure that Qt can clean up after the drag and drop operation has been
+ completed.
+
+ A pixmap can be used to represent the data while the drag is in
+ progress, and will move with the cursor to the drop target. This
+ pixmap typically shows an icon that represents the MIME type of
+ the data being transferred, but any pixmap can be set with
+ setPixmap(). The cursor's hot spot can be given a position
+ relative to the top-left corner of the pixmap with the
+ setHotSpot() function. The following code positions the pixmap so
+ that the cursor's hot spot points to the center of its bottom
+ edge:
+
+ \snippet doc/src/snippets/separations/finalwidget.cpp 2
+
+ \note On X11, the pixmap may not be able to keep up with the mouse
+ movements if the hot spot causes the pixmap to be displayed
+ directly under the cursor.
+
+ The source and target widgets can be found with source() and target().
+ These functions are often used to determine whether drag and drop operations
+ started and finished at the same widget, so that special behavior can be
+ implemented.
+
+ QDrag only deals with the drag and drop operation itself. It is up to the
+ developer to decide when a drag operation begins, and how a QDrag object should
+ be constructed and used. For a given widget, it is often necessary to
+ reimplement \l{QWidget::mousePressEvent()}{mousePressEvent()} to determine
+ whether the user has pressed a mouse button, and reimplement
+ \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} to check whether a QDrag is
+ required.
+
+ \sa {Drag and Drop}, QClipboard, QMimeData, QWindowsMime, QMacPasteboardMime,
+ {Draggable Icons Example}, {Draggable Text Example}, {Drop Site Example},
+ {Fridge Magnets Example}
+*/
+
+/*!
+ Constructs a new drag object for the widget specified by \a dragSource.
+*/
+QDrag::QDrag(QWidget *dragSource)
+ : QObject(*new QDragPrivate, dragSource)
+{
+ Q_D(QDrag);
+ d->source = dragSource;
+ d->target = 0;
+ d->data = 0;
+ d->hotspot = QPoint(-10, -10);
+ d->possible_actions = Qt::CopyAction;
+ d->executed_action = Qt::IgnoreAction;
+ d->defaultDropAction = Qt::IgnoreAction;
+}
+
+/*!
+ Destroys the drag object.
+*/
+QDrag::~QDrag()
+{
+ Q_D(QDrag);
+ delete d->data;
+ QDragManager *manager = QDragManager::self();
+ if (manager && manager->object == this)
+ manager->cancel(false);
+}
+
+/*!
+ Sets the data to be sent to the given MIME \a data. Ownership of the data is
+ transferred to the QDrag object.
+*/
+void QDrag::setMimeData(QMimeData *data)
+{
+ Q_D(QDrag);
+ if (d->data == data)
+ return;
+ if (d->data != 0)
+ delete d->data;
+ d->data = data;
+}
+
+/*!
+ Returns the MIME data that is encapsulated by the drag object.
+*/
+QMimeData *QDrag::mimeData() const
+{
+ Q_D(const QDrag);
+ return d->data;
+}
+
+/*!
+ Sets \a pixmap as the pixmap used to represent the data in a drag
+ and drop operation. You can only set a pixmap before the drag is
+ started.
+*/
+void QDrag::setPixmap(const QPixmap &pixmap)
+{
+ Q_D(QDrag);
+ d->pixmap = pixmap;
+}
+
+/*!
+ Returns the pixmap used to represent the data in a drag and drop operation.
+*/
+QPixmap QDrag::pixmap() const
+{
+ Q_D(const QDrag);
+ return d->pixmap;
+}
+
+/*!
+ Sets the position of the hot spot relative to the top-left corner of the
+ pixmap used to the point specified by \a hotspot.
+
+ \bold{Note:} on X11, the pixmap may not be able to keep up with the mouse
+ movements if the hot spot causes the pixmap to be displayed
+ directly under the cursor.
+*/
+void QDrag::setHotSpot(const QPoint& hotspot)
+{
+ Q_D(QDrag);
+ d->hotspot = hotspot;
+}
+
+/*!
+ Returns the position of the hot spot relative to the top-left corner of the
+ cursor.
+*/
+QPoint QDrag::hotSpot() const
+{
+ Q_D(const QDrag);
+ return d->hotspot;
+}
+
+/*!
+ Returns the source of the drag object. This is the widget where the drag
+ and drop operation originated.
+*/
+QWidget *QDrag::source() const
+{
+ Q_D(const QDrag);
+ return d->source;
+}
+
+/*!
+ Returns the target of the drag and drop operation. This is the widget where
+ the drag object was dropped.
+*/
+QWidget *QDrag::target() const
+{
+ Q_D(const QDrag);
+ return d->target;
+}
+
+/*!
+ \since 4.3
+
+ Starts the drag and drop operation and returns a value indicating the requested
+ drop action when it is completed. The drop actions that the user can choose
+ from are specified in \a supportedActions. The default proposed action will be selected
+ among the allowed actions in the following order: Move, Copy and Link.
+
+ \bold{Note:} On Linux and Mac OS X, the drag and drop operation
+ can take some time, but this function does not block the event
+ loop. Other events are still delivered to the application while
+ the operation is performed. On Windows, the Qt event loop is
+ blocked while during the operation.
+*/
+
+Qt::DropAction QDrag::exec(Qt::DropActions supportedActions)
+{
+ return exec(supportedActions, Qt::IgnoreAction);
+}
+
+/*!
+ \since 4.3
+
+ Starts the drag and drop operation and returns a value indicating the requested
+ drop action when it is completed. The drop actions that the user can choose
+ from are specified in \a supportedActions.
+
+ The \a defaultDropAction determines which action will be proposed when the user performs a
+ drag without using modifier keys.
+
+ \bold{Note:} On Linux and Mac OS X, the drag and drop operation
+ can take some time, but this function does not block the event
+ loop. Other events are still delivered to the application while
+ the operation is performed. On Windows, the Qt event loop is
+ blocked while during the operation.
+*/
+
+Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)
+{
+ Q_D(QDrag);
+ if (!d->data) {
+ qWarning("QDrag: No mimedata set before starting the drag");
+ return d->executed_action;
+ }
+ QDragManager *manager = QDragManager::self();
+ d->defaultDropAction = Qt::IgnoreAction;
+ d->possible_actions = supportedActions;
+
+ if (manager) {
+ if (defaultDropAction == Qt::IgnoreAction) {
+ if (supportedActions & Qt::MoveAction) {
+ d->defaultDropAction = Qt::MoveAction;
+ } else if (supportedActions & Qt::CopyAction) {
+ d->defaultDropAction = Qt::CopyAction;
+ } else if (supportedActions & Qt::LinkAction) {
+ d->defaultDropAction = Qt::LinkAction;
+ }
+ } else {
+ d->defaultDropAction = defaultDropAction;
+ }
+ d->executed_action = manager->drag(this);
+ }
+
+ return d->executed_action;
+}
+
+/*!
+ \obsolete
+
+ \bold{Note:} It is recommended to use exec() instead of this function.
+
+ Starts the drag and drop operation and returns a value indicating the requested
+ drop action when it is completed. The drop actions that the user can choose
+ from are specified in \a request. Qt::CopyAction is always allowed.
+
+ \bold{Note:} Although the drag and drop operation can take some time, this function
+ does not block the event loop. Other events are still delivered to the application
+ while the operation is performed.
+
+ \sa exec()
+*/
+Qt::DropAction QDrag::start(Qt::DropActions request)
+{
+ Q_D(QDrag);
+ if (!d->data) {
+ qWarning("QDrag: No mimedata set before starting the drag");
+ return d->executed_action;
+ }
+ QDragManager *manager = QDragManager::self();
+ d->defaultDropAction = Qt::IgnoreAction;
+ d->possible_actions = request | Qt::CopyAction;
+ if (manager)
+ d->executed_action = manager->drag(this);
+ return d->executed_action;
+}
+
+/*!
+ Sets the drag \a cursor for the \a action. This allows you
+ to override the default native cursors. To revert to using the
+ native cursor for \a action pass in a null QPixmap as \a cursor.
+
+ The \a action can only be CopyAction, MoveAction or LinkAction.
+ All other values of DropAction are ignored.
+*/
+void QDrag::setDragCursor(const QPixmap &cursor, Qt::DropAction action)
+{
+ Q_D(QDrag);
+ if (action != Qt::CopyAction && action != Qt::MoveAction && action != Qt::LinkAction)
+ return;
+ if (cursor.isNull())
+ d->customCursors.remove(action);
+ else
+ d->customCursors[action] = cursor;
+}
+
+/*!
+ \fn void QDrag::actionChanged(Qt::DropAction action)
+
+ This signal is emitted when the \a action associated with the
+ drag changes.
+
+ \sa targetChanged()
+*/
+
+/*!
+ \fn void QDrag::targetChanged(QWidget *newTarget)
+
+ This signal is emitted when the target of the drag and drop
+ operation changes, with \a newTarget the new target.
+
+ \sa target(), actionChanged()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h
new file mode 100644
index 0000000000..9f0854403b
--- /dev/null
+++ b/src/gui/kernel/qdrag.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDRAG_H
+#define QDRAG_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_DRAGANDDROP
+class QMimeData;
+class QDragPrivate;
+class QWidget;
+class QPixmap;
+class QPoint;
+class QDragManager;
+
+class Q_GUI_EXPORT QDrag : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDrag)
+public:
+ explicit QDrag(QWidget *dragSource);
+ ~QDrag();
+
+ void setMimeData(QMimeData *data);
+ QMimeData *mimeData() const;
+
+ void setPixmap(const QPixmap &);
+ QPixmap pixmap() const;
+
+ void setHotSpot(const QPoint &hotspot);
+ QPoint hotSpot() const;
+
+ QWidget *source() const;
+ QWidget *target() const;
+
+ Qt::DropAction start(Qt::DropActions supportedActions = Qt::CopyAction);
+ Qt::DropAction exec(Qt::DropActions supportedActions = Qt::MoveAction);
+ Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultAction);
+
+ void setDragCursor(const QPixmap &cursor, Qt::DropAction action);
+
+Q_SIGNALS:
+ void actionChanged(Qt::DropAction action);
+ void targetChanged(QWidget *newTarget);
+
+private:
+#ifdef Q_WS_MAC
+ friend class QWidgetPrivate;
+#endif
+ friend class QDragManager;
+ Q_DISABLE_COPY(QDrag)
+};
+
+#endif // QT_NO_DRAGANDDROP
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDRAG_H
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
new file mode 100644
index 0000000000..3f1df5e5a2
--- /dev/null
+++ b/src/gui/kernel/qevent.cpp
@@ -0,0 +1,3509 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevent.h"
+#include "qcursor.h"
+#include "qapplication.h"
+#include "private/qapplication_p.h"
+#include "private/qkeysequence_p.h"
+#include "qwidget.h"
+#include "qdebug.h"
+#include "qmime.h"
+#include "qdnd_p.h"
+#include "qevent_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QInputEvent
+ \ingroup events
+
+ \brief The QInputEvent class is the base class for events that
+ describe user input.
+*/
+
+/*!
+ \internal
+*/
+QInputEvent::QInputEvent(Type type, Qt::KeyboardModifiers modifiers)
+ : QEvent(type), modState(modifiers)
+{}
+
+/*!
+ \internal
+*/
+QInputEvent::~QInputEvent()
+{
+}
+
+/*!
+ \fn Qt::KeyboardModifiers QInputEvent::modifiers() const
+
+ Returns the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ \sa QApplication::keyboardModifiers()
+*/
+
+/*!
+ \class QMouseEvent
+ \ingroup events
+
+ \brief The QMouseEvent class contains parameters that describe a mouse event.
+
+ Mouse events occur when a mouse button is pressed or released
+ inside a widget, or when the mouse cursor is moved.
+
+ Mouse move events will occur only when a mouse button is pressed
+ down, unless mouse tracking has been enabled with
+ QWidget::setMouseTracking().
+
+ Qt automatically grabs the mouse when a mouse button is pressed
+ inside a widget; the widget will continue to receive mouse events
+ until the last mouse button is released.
+
+ A mouse event contains a special accept flag that indicates
+ whether the receiver wants the event. You should call ignore() if
+ the mouse event is not handled by your widget. A mouse event is
+ propagated up the parent widget chain until a widget accepts it
+ with accept(), or an event filter consumes it.
+
+ The state of the keyboard modifier keys can be found by calling the
+ \l{QInputEvent::modifiers()}{modifiers()} function, inhertied from
+ QInputEvent.
+
+ The functions pos(), x(), and y() give the cursor position
+ relative to the widget that receives the mouse event. If you
+ move the widget as a result of the mouse event, use the global
+ position returned by globalPos() to avoid a shaking motion.
+
+ The QWidget::setEnabled() function can be used to enable or
+ disable mouse and keyboard events for a widget.
+
+ Reimplement the QWidget event handlers, QWidget::mousePressEvent(),
+ QWidget::mouseReleaseEvent(), QWidget::mouseDoubleClickEvent(),
+ and QWidget::mouseMoveEvent() to receive mouse events in your own
+ widgets.
+
+ \sa QWidget::setMouseTracking() QWidget::grabMouse()
+ QCursor::pos()
+*/
+
+/*!
+ Constructs a mouse event object.
+
+ The \a type parameter must be one of QEvent::MouseButtonPress,
+ QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick,
+ or QEvent::MouseMove.
+
+ The \a position is the mouse cursor's position relative to the
+ receiving widget.
+ The \a button that caused the event is given as a value from
+ the Qt::MouseButton enum. If the event \a type is
+ \l MouseMove, the appropriate button for this event is Qt::NoButton.
+ The mouse and keyboard states at the time of the event are specified by
+ \a buttons and \a modifiers.
+
+ The globalPos() is initialized to QCursor::pos(), which may not
+ be appropriate. Use the other constructor to specify the global
+ position explicitly.
+*/
+
+QMouseEvent::QMouseEvent(Type type, const QPoint &position, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ : QInputEvent(type, modifiers), p(position), b(button), mouseState(buttons)
+{
+ g = QCursor::pos();
+}
+
+/*!
+ \internal
+*/
+QMouseEvent::~QMouseEvent()
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use QMouseEvent(\a type, \a pos, \a button, \c buttons, \c
+ modifiers) instead, where \c buttons is \a state &
+ Qt::MouseButtonMask and \c modifiers is \a state &
+ Qt::KeyButtonMask.
+*/
+QMouseEvent::QMouseEvent(Type type, const QPoint &pos, Qt::ButtonState button, int state)
+ : QInputEvent(type), p(pos), b((Qt::MouseButton)button)
+{
+ g = QCursor::pos();
+ mouseState = Qt::MouseButtons((state ^ b) & Qt::MouseButtonMask);
+ modState = Qt::KeyboardModifiers(state & (int)Qt::KeyButtonMask);
+}
+
+/*!
+ Use QMouseEvent(\a type, \a pos, \a globalPos, \a button,
+ \c buttons, \c modifiers) instead, where
+ \c buttons is \a state & Qt::MouseButtonMask and
+ \c modifiers is \a state & Qt::KeyButtonMask.
+*/
+QMouseEvent::QMouseEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+ Qt::ButtonState button, int state)
+ : QInputEvent(type), p(pos), g(globalPos), b((Qt::MouseButton)button)
+{
+ mouseState = Qt::MouseButtons((state ^ b) & Qt::MouseButtonMask);
+ modState = Qt::KeyboardModifiers(state & (int)Qt::KeyButtonMask);
+}
+#endif
+
+
+/*!
+ Constructs a mouse event object.
+
+ The \a type parameter must be QEvent::MouseButtonPress,
+ QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick,
+ or QEvent::MouseMove.
+
+ The \a pos is the mouse cursor's position relative to the
+ receiving widget. The cursor's position in global coordinates is
+ specified by \a globalPos. The \a button that caused the event is
+ given as a value from the \l Qt::MouseButton enum. If the event \a
+ type is \l MouseMove, the appropriate button for this event is
+ Qt::NoButton. \a buttons is the state of all buttons at the
+ time of the event, \a modifiers the state of all keyboard
+ modifiers.
+
+*/
+QMouseEvent::QMouseEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers)
+ : QInputEvent(type, modifiers), p(pos), g(globalPos), b(button), mouseState(buttons)
+{}
+
+/*!
+ \internal
+*/
+QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos,
+ const QPoint &globalPos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+{
+ return new QMouseEventEx(type, pos, globalPos, button, buttons, modifiers);
+}
+
+/*!
+ \fn bool QMouseEvent::hasExtendedInfo() const
+ \internal
+*/
+
+/*!
+ \since 4.4
+
+ Returns the position of the mouse cursor as a QPointF, relative to the
+ widget that received the event.
+
+ If you move the widget as a result of the mouse event, use the
+ global position returned by globalPos() to avoid a shaking
+ motion.
+
+ \sa x() y() pos() globalPos()
+*/
+QPointF QMouseEvent::posF() const
+{
+ return hasExtendedInfo() ? reinterpret_cast<const QMouseEventEx *>(this)->posF : QPointF(pos());
+}
+
+/*!
+ \internal
+*/
+QMouseEventEx::QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers)
+ : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos)
+{
+ d = reinterpret_cast<QEventPrivate *>(this);
+}
+
+/*!
+ \internal
+*/
+QMouseEventEx::~QMouseEventEx()
+{
+}
+
+/*!
+ \fn const QPoint &QMouseEvent::pos() const
+
+ Returns the position of the mouse cursor, relative to the widget
+ that received the event.
+
+ If you move the widget as a result of the mouse event, use the
+ global position returned by globalPos() to avoid a shaking
+ motion.
+
+ \sa x() y() globalPos()
+*/
+
+/*!
+ \fn const QPoint &QMouseEvent::globalPos() const
+
+ Returns the global position of the mouse cursor \e{at the time
+ of the event}. This is important on asynchronous window systems
+ like X11. Whenever you move your widgets around in response to
+ mouse events, globalPos() may differ a lot from the current
+ pointer position QCursor::pos(), and from
+ QWidget::mapToGlobal(pos()).
+
+ \sa globalX() globalY()
+*/
+
+/*!
+ \fn int QMouseEvent::x() const
+
+ Returns the x position of the mouse cursor, relative to the
+ widget that received the event.
+
+ \sa y() pos()
+*/
+
+/*!
+ \fn int QMouseEvent::y() const
+
+ Returns the y position of the mouse cursor, relative to the
+ widget that received the event.
+
+ \sa x() pos()
+*/
+
+/*!
+ \fn int QMouseEvent::globalX() const
+
+ Returns the global x position of the mouse cursor at the time of
+ the event.
+
+ \sa globalY() globalPos()
+*/
+
+/*!
+ \fn int QMouseEvent::globalY() const
+
+ Returns the global y position of the mouse cursor at the time of
+ the event.
+
+ \sa globalX() globalPos()
+*/
+
+/*!
+ \fn Qt::MouseButton QMouseEvent::button() const
+
+ Returns the button that caused the event.
+
+ Note that the returned value is always Qt::NoButton for mouse
+ move events.
+
+ \sa buttons() Qt::MouseButton
+*/
+
+/*!
+ \fn Qt::MouseButton QMouseEvent::buttons() const
+
+ Returns the button state when the event was generated. The button
+ state is a combination of Qt::LeftButton, Qt::RightButton,
+ Qt::MidButton using the OR operator. For mouse move events,
+ this is all buttons that are pressed down. For mouse press and
+ double click events this includes the button that caused the
+ event. For mouse release events this excludes the button that
+ caused the event.
+
+ \sa button() Qt::MouseButton
+*/
+
+
+/*!
+ \fn Qt::ButtonState QMouseEvent::state() const
+
+ Returns the button state immediately before the event was
+ generated. The button state is a combination of mouse buttons
+ (see Qt::ButtonState) and keyboard modifiers (Qt::MouseButtons).
+
+ Use buttons() and/or modifiers() instead. Be aware that buttons()
+ return the state immediately \e after the event was generated.
+*/
+
+/*!
+ \fn Qt::ButtonState QMouseEvent::stateAfter() const
+
+ Returns the button state immediately after the event was
+ generated. The button state is a combination of mouse buttons
+ (see Qt::ButtonState) and keyboard modifiers (Qt::MouseButtons).
+
+ Use buttons() and/or modifiers() instead.
+*/
+
+/*!
+ \class QHoverEvent
+ \ingroup events
+
+ \brief The QHoverEvent class contains parameters that describe a mouse event.
+
+ Mouse events occur when a mouse cursor is moved into, out of, or within a
+ widget, and if the widget has the Qt::WA_Hover attribute.
+
+ The function pos() gives the current cursor position, while oldPos() gives
+ the old mouse position.
+*/
+
+/*!
+ \fn const QPoint &QHoverEvent::pos() const
+
+ Returns the position of the mouse cursor, relative to the widget
+ that received the event.
+
+ On QEvent::HoverLeave events, this position will always be
+ QPoint(-1, -1).
+
+ \sa oldPos()
+*/
+
+/*!
+ \fn const QPoint &QHoverEvent::oldPos() const
+
+ Returns the previous position of the mouse cursor, relative to the widget
+ that received the event. If there is no previous position, oldPos() will
+ return the same position as pos().
+
+ On QEvent::HoverEnter events, this position will always be
+ QPoint(-1, -1).
+
+ \sa pos()
+*/
+
+/*!
+ Constructs a hover event object.
+
+ The \a type parameter must be QEvent::HoverEnter,
+ QEvent::HoverLeave, or QEvent::HoverMove.
+
+ The \a pos is the current mouse cursor's position relative to the
+ receiving widget, while \a oldPos is the previous mouse cursor's
+ position relative to the receiving widget.
+*/
+QHoverEvent::QHoverEvent(Type type, const QPoint &pos, const QPoint &oldPos)
+ : QEvent(type), p(pos), op(oldPos)
+{
+}
+
+/*!
+ \internal
+*/
+QHoverEvent::~QHoverEvent()
+{
+}
+
+
+/*!
+ \class QWheelEvent
+ \brief The QWheelEvent class contains parameters that describe a wheel event.
+
+ \ingroup events
+
+ Wheel events are sent to the widget under the mouse cursor, but
+ if that widget does not handle the event they are sent to the
+ focus widget. The rotation distance is provided by delta().
+ The functions pos() and globalPos() return the mouse cursor's
+ location at the time of the event.
+
+ A wheel event contains a special accept flag that indicates
+ whether the receiver wants the event. You should call ignore() if
+ you do not handle the wheel event; this ensures that it will be
+ sent to the parent widget.
+
+ The QWidget::setEnabled() function can be used to enable or
+ disable mouse and keyboard events for a widget.
+
+ The event handler QWidget::wheelEvent() receives wheel events.
+
+ \sa QMouseEvent QWidget::grabMouse()
+*/
+
+/*!
+ \fn Qt::MouseButtons QWheelEvent::buttons() const
+
+ Returns the mouse state when the event occurred.
+*/
+
+/*!
+ \fn Qt::Orientation QWheelEvent::orientation() const
+
+ Returns the wheel's orientation.
+*/
+
+/*!
+ Constructs a wheel event object.
+
+ The position, \a pos, is the location of the mouse cursor within
+ the widget. The globalPos() is initialized to QCursor::pos()
+ which is usually, but not always, correct.
+ Use the other constructor if you need to specify the global
+ position explicitly.
+
+ The \a buttons describe the state of the mouse buttons at the time
+ of the event, \a delta contains the rotation distance,
+ \a modifiers holds the keyboard modifier flags at the time of the
+ event, and \a orient holds the wheel's orientation.
+
+ \sa pos() delta() state()
+*/
+#ifndef QT_NO_WHEELEVENT
+QWheelEvent::QWheelEvent(const QPoint &pos, int delta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ Qt::Orientation orient)
+ : QInputEvent(Wheel, modifiers), p(pos), d(delta), mouseState(buttons), o(orient)
+{
+ g = QCursor::pos();
+}
+
+/*!
+ \internal
+*/
+QWheelEvent::~QWheelEvent()
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use one of the other constructors instead.
+*/
+QWheelEvent::QWheelEvent(const QPoint &pos, int delta, int state, Qt::Orientation orient)
+ : QInputEvent(Wheel), p(pos), d(delta), o(orient)
+{
+ g = QCursor::pos();
+ mouseState = Qt::MouseButtons(state & Qt::MouseButtonMask);
+ modState = Qt::KeyboardModifiers(state & (int)Qt::KeyButtonMask);
+}
+#endif
+
+/*!
+ Constructs a wheel event object.
+
+ The \a pos provides the location of the mouse cursor
+ within the widget. The position in global coordinates is specified
+ by \a globalPos. \a delta contains the rotation distance, \a modifiers
+ holds the keyboard modifier flags at the time of the event, and
+ \a orient holds the wheel's orientation.
+
+ \sa pos() globalPos() delta() state()
+*/
+QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ Qt::Orientation orient)
+ : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), d(delta), mouseState(buttons), o(orient)
+{}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use one of the other constructors instead.
+*/
+QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, int state,
+ Qt::Orientation orient)
+ : QInputEvent(Wheel), p(pos), g(globalPos), d(delta), o(orient)
+{
+ mouseState = Qt::MouseButtons(state & Qt::MouseButtonMask);
+ modState = Qt::KeyboardModifiers(state & (int) Qt::KeyButtonMask);
+}
+#endif
+#endif // QT_NO_WHEELEVENT
+
+/*!
+ \fn int QWheelEvent::delta() const
+
+ Returns the distance that the wheel is rotated, in eighths of a
+ degree. A positive value indicates that the wheel was rotated
+ forwards away from the user; a negative value indicates that the
+ wheel was rotated backwards toward the user.
+
+ Most mouse types work in steps of 15 degrees, in which case the
+ delta value is a multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
+
+ However, some mice have finer-resolution wheels and send delta values
+ that are less than 120 units (less than 15 degrees). To support this
+ possibility, you can either cumulatively add the delta values from events
+ until the value of 120 is reached, then scroll the widget, or you can
+ partially scroll the widget in response to each wheel event.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qevent.cpp 0
+*/
+
+/*!
+ \fn const QPoint &QWheelEvent::pos() const
+
+ Returns the position of the mouse cursor relative to the widget
+ that received the event.
+
+ If you move your widgets around in response to mouse events,
+ use globalPos() instead of this function.
+
+ \sa x() y() globalPos()
+*/
+
+/*!
+ \fn int QWheelEvent::x() const
+
+ Returns the x position of the mouse cursor, relative to the
+ widget that received the event.
+
+ \sa y() pos()
+*/
+
+/*!
+ \fn int QWheelEvent::y() const
+
+ Returns the y position of the mouse cursor, relative to the
+ widget that received the event.
+
+ \sa x() pos()
+*/
+
+
+/*!
+ \fn const QPoint &QWheelEvent::globalPos() const
+
+ Returns the global position of the mouse pointer \e{at the time
+ of the event}. This is important on asynchronous window systems
+ such as X11; whenever you move your widgets around in response to
+ mouse events, globalPos() can differ a lot from the current
+ cursor position returned by QCursor::pos().
+
+ \sa globalX() globalY()
+*/
+
+/*!
+ \fn int QWheelEvent::globalX() const
+
+ Returns the global x position of the mouse cursor at the time of
+ the event.
+
+ \sa globalY() globalPos()
+*/
+
+/*!
+ \fn int QWheelEvent::globalY() const
+
+ Returns the global y position of the mouse cursor at the time of
+ the event.
+
+ \sa globalX() globalPos()
+*/
+
+
+/*! \obsolete
+ \fn Qt::ButtonState QWheelEvent::state() const
+
+ Returns the keyboard modifier flags at the time of the event.
+
+ The returned value is a selection of the following values,
+ combined using the OR operator: Qt::ShiftButton,
+ Qt::ControlButton, and Qt::AltButton.
+*/
+
+
+/*!
+ \class QKeyEvent
+ \brief The QKeyEvent class describes a key event.
+
+ \ingroup events
+
+ Key events are sent to the widget with keyboard input focus
+ when keys are pressed or released.
+
+ A key event contains a special accept flag that indicates whether
+ the receiver will handle the key event. You should call ignore()
+ if the key press or release event is not handled by your widget.
+ A key event is propagated up the parent widget chain until a
+ widget accepts it with accept() or an event filter consumes it.
+ Key events for multimedia keys are ignored by default. You should
+ call accept() if your widget handles those events.
+
+ The QWidget::setEnable() function can be used to enable or disable
+ mouse and keyboard events for a widget.
+
+ The event handlers QWidget::keyPressEvent() and
+ QWidget::keyReleaseEvent() receive key events.
+
+ \sa QFocusEvent, QWidget::grabKeyboard()
+*/
+
+/*!
+ Constructs a key event object.
+
+ The \a type parameter must be QEvent::KeyPress, QEvent::KeyRelease,
+ or QEvent::ShortcutOverride.
+
+ If \a key is 0, the event is not a result of
+ a known key; for example, it may be the result of a compose
+ sequence or keyboard macro. The \a modifiers holds the keyboard
+ modifiers, and the given \a text is the Unicode text that the
+ key generated. If \a autorep is true, isAutoRepeat() will be
+ true. \a count is the number of keys involved in the event.
+*/
+QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text,
+ bool autorep, ushort count)
+ : QInputEvent(type, modifiers), txt(text), k(key), c(count), autor(autorep)
+{
+}
+
+/*!
+ \internal
+*/
+QKeyEvent::~QKeyEvent()
+{
+}
+
+/*!
+ \internal
+*/
+QKeyEvent *QKeyEvent::createExtendedKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers,
+ quint32 nativeScanCode, quint32 nativeVirtualKey,
+ quint32 nativeModifiers,
+ const QString& text, bool autorep, ushort count)
+{
+ return new QKeyEventEx(type, key, modifiers, text, autorep, count,
+ nativeScanCode, nativeVirtualKey, nativeModifiers);
+}
+
+/*!
+ \fn bool QKeyEvent::hasExtendedInfo() const
+ \internal
+*/
+
+/*!
+ \since 4.2
+
+ Returns the native scan code of the key event. If the key event
+ does not contain this data 0 is returned.
+
+ Note: The native scan code may be 0, even if the key event contains
+ extended information.
+
+ Note: On Mac OS/X, this function is not useful, because there is no
+ way to get the scan code from Carbon or Cocoa. The function always
+ returns 1 (or 0 in the case explained above).
+*/
+quint32 QKeyEvent::nativeScanCode() const
+{
+ return (reinterpret_cast<const QKeyEvent*>(d) != this
+ ? 0 : reinterpret_cast<const QKeyEventEx*>(this)->nScanCode);
+}
+
+/*!
+ \since 4.2
+
+ Returns the native virtual key, or key sym of the key event.
+ If the key event does not contain this data 0 is returned.
+
+ Note: The native virtual key may be 0, even if the key event contains extended information.
+*/
+quint32 QKeyEvent::nativeVirtualKey() const
+{
+ return (reinterpret_cast<const QKeyEvent*>(d) != this
+ ? 0 : reinterpret_cast<const QKeyEventEx*>(this)->nVirtualKey);
+}
+
+/*!
+ \since 4.2
+
+ Returns the native modifiers of a key event.
+ If the key event does not contain this data 0 is returned.
+
+ Note: The native modifiers may be 0, even if the key event contains extended information.
+*/
+quint32 QKeyEvent::nativeModifiers() const
+{
+ return (reinterpret_cast<const QKeyEvent*>(d) != this
+ ? 0 : reinterpret_cast<const QKeyEventEx*>(this)->nModifiers);
+}
+
+/*!
+ \internal
+ Creates an extended key event object, which in addition to the normal key event data, also
+ contains the native scan code, virtual key and modifiers. This extra data is used by the
+ shortcut system, to determine which shortcuts to trigger.
+*/
+QKeyEventEx::QKeyEventEx(Type type, int key, Qt::KeyboardModifiers modifiers,
+ const QString &text, bool autorep, ushort count,
+ quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers)
+ : QKeyEvent(type, key, modifiers, text, autorep, count),
+ nScanCode(nativeScanCode), nVirtualKey(nativeVirtualKey), nModifiers(nativeModifiers)
+{
+ d = reinterpret_cast<QEventPrivate*>(this);
+}
+
+/*!
+ \internal
+ Creates a copy of an other extended key event.
+*/
+QKeyEventEx::QKeyEventEx(const QKeyEventEx &other)
+ : QKeyEvent(QEvent::Type(other.t), other.k, other.modState, other.txt, other.autor, other.c),
+ nScanCode(other.nScanCode), nVirtualKey(other.nVirtualKey), nModifiers(other.nModifiers)
+{
+ d = reinterpret_cast<QEventPrivate*>(this);
+}
+
+/*!
+ \internal
+*/
+QKeyEventEx::~QKeyEventEx()
+{
+}
+
+/*!
+ \fn int QKeyEvent::key() const
+
+ Returns the code of the key that was pressed or released.
+
+ See \l Qt::Key for the list of keyboard codes. These codes are
+ independent of the underlying window system. Note that this
+ function does not distinguish between capital and non-capital
+ letters, use the text() function (returning the Unicode text the
+ key generated) for this purpose.
+
+ A value of either 0 or Qt::Key_unknown means that the event is not
+ the result of a known key; for example, it may be the result of
+ a compose sequence, a keyboard macro, or due to key event
+ compression.
+
+ \sa Qt::WA_KeyCompression
+*/
+
+/*!
+ \fn QString QKeyEvent::text() const
+
+ Returns the Unicode text that this key generated. The text
+ returned can be an empty string in cases
+ where modifier keys, such as Shift, Control, Alt, and Meta,
+ are being pressed or released. In such cases key() will contain
+ a valid value.
+
+ \sa Qt::WA_KeyCompression
+*/
+
+/*!
+ Returns the keyboard modifier flags that existed immediately
+ after the event occurred.
+
+ \warning This function cannot always be trusted. The user can
+ confuse it by pressing both \key{Shift} keys simultaneously and
+ releasing one of them, for example.
+
+ \sa QApplication::keyboardModifiers()
+*/
+//###### We must check with XGetModifierMapping
+Qt::KeyboardModifiers QKeyEvent::modifiers() const
+{
+ if (key() == Qt::Key_Shift)
+ return Qt::KeyboardModifiers(QInputEvent::modifiers()^Qt::ShiftModifier);
+ if (key() == Qt::Key_Control)
+ return Qt::KeyboardModifiers(QInputEvent::modifiers()^Qt::ControlModifier);
+ if (key() == Qt::Key_Alt)
+ return Qt::KeyboardModifiers(QInputEvent::modifiers()^Qt::AltModifier);
+ if (key() == Qt::Key_Meta)
+ return Qt::KeyboardModifiers(QInputEvent::modifiers()^Qt::MetaModifier);
+ return QInputEvent::modifiers();
+}
+
+#ifndef QT_NO_SHORTCUT
+/*!
+ \fn bool QKeyEvent::matches(QKeySequence::StandardKey key) const
+ \since 4.2
+
+ Returns true if the key event matches the given standard \a key;
+ otherwise returns false.
+*/
+bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const
+{
+ uint searchkey = (modifiers() | key()) & ~(Qt::KeypadModifier); //The keypad modifier should not make a difference
+ uint platform = QApplicationPrivate::currentPlatform();
+
+ uint N = QKeySequencePrivate::numberOfKeyBindings;
+ int first = 0;
+ int last = N - 1;
+
+ while (first <= last) {
+ int mid = (first + last) / 2;
+ QKeyBinding midVal = QKeySequencePrivate::keyBindings[mid];
+
+ if (searchkey > midVal.shortcut){
+ first = mid + 1; // Search in top half
+ }
+ else if (searchkey < midVal.shortcut){
+ last = mid - 1; // Search in bottom half
+ }
+ else {
+ //found correct shortcut value, now we must check for platform match
+ if ((midVal.platform & platform) && (midVal.standardKey == matchKey)) {
+ return true;
+ } else { //We may have several equal values for different platforms, so we must search in both directions
+
+ //search forward
+ for ( unsigned int i = mid + 1 ; i < N - 1 ; ++i) {
+ QKeyBinding current = QKeySequencePrivate::keyBindings[i];
+ if (current.shortcut != searchkey)
+ break;
+ else if (current.platform & platform && current.standardKey == matchKey)
+ return true;
+ }
+
+ //search back
+ for ( int i = mid - 1 ; i >= 0 ; --i) {
+ QKeyBinding current = QKeySequencePrivate::keyBindings[i];
+ if (current.shortcut != searchkey)
+ break;
+ else if (current.platform & platform && current.standardKey == matchKey)
+ return true;
+ }
+ return false; //we could not find it among the matching keySequences
+ }
+ }
+ }
+ return false; //we could not find matching keySequences at all
+}
+#endif // QT_NO_SHORTCUT
+
+
+/*!
+ \fn bool QKeyEvent::isAutoRepeat() const
+
+ Returns true if this event comes from an auto-repeating key;
+ returns false if it comes from an initial key press.
+
+ Note that if the event is a multiple-key compressed event that is
+ partly due to auto-repeat, this function could return either true
+ or false indeterminately.
+*/
+
+/*!
+ \fn int QKeyEvent::count() const
+
+ Returns the number of keys involved in this event. If text()
+ is not empty, this is simply the length of the string.
+
+ \sa Qt::WA_KeyCompression
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ \fn QKeyEvent::QKeyEvent(Type type, int key, int ascii,
+ int modifiers, const QString &text,
+ bool autorep, ushort count)
+
+ Use one of the other constructors instead.
+*/
+
+/*!
+ \fn int QKeyEvent::ascii() const
+
+ Use text() instead.
+*/
+
+/*!
+ \fn Qt::ButtonState QKeyEvent::state() const
+
+ Use QInputEvent::modifiers() instead.
+*/
+
+/*!
+ \fn Qt::ButtonState QKeyEvent::stateAfter() const
+
+ Use modifiers() instead.
+*/
+#endif
+
+/*!
+ \class QFocusEvent
+ \brief The QFocusEvent class contains event parameters for widget focus
+ events.
+
+ \ingroup events
+
+ Focus events are sent to widgets when the keyboard input focus
+ changes. Focus events occur due to mouse actions, key presses
+ (such as \gui{Tab} or \gui{Backtab}), the window system, popup
+ menus, keyboard shortcuts, or other application-specific reasons.
+ The reason for a particular focus event is returned by reason()
+ in the appropriate event handler.
+
+ The event handlers QWidget::focusInEvent() and
+ QWidget::focusOutEvent() receive focus events.
+
+ \sa QWidget::setFocus(), QWidget::setFocusPolicy(), {Keyboard Focus}
+*/
+
+/*!
+ Constructs a focus event object.
+
+ The \a type parameter must be either QEvent::FocusIn or
+ QEvent::FocusOut. The \a reason describes the cause of the change
+ in focus.
+*/
+QFocusEvent::QFocusEvent(Type type, Qt::FocusReason reason)
+ : QEvent(type), m_reason(reason)
+{}
+
+/*!
+ \internal
+*/
+QFocusEvent::~QFocusEvent()
+{
+}
+
+// ### Qt 5: remove
+/*!
+ \internal
+ */
+Qt::FocusReason QFocusEvent::reason()
+{
+ return m_reason;
+}
+
+/*!
+ Returns the reason for this focus event.
+ */
+Qt::FocusReason QFocusEvent::reason() const
+{
+ return m_reason;
+}
+
+/*!
+ \fn bool QFocusEvent::gotFocus() const
+
+ Returns true if type() is QEvent::FocusIn; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QFocusEvent::lostFocus() const
+
+ Returns true if type() is QEvent::FocusOut; otherwise returns
+ false.
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ \enum QFocusEvent::Reason
+ \compat
+
+ Use Qt::FocusReason instead.
+
+ \value Mouse Same as Qt::MouseFocusReason.
+ \value Tab Same as Qt::TabFocusReason.
+ \value Backtab Same as Qt::BacktabFocusReason.
+ \value MenuBar Same as Qt::MenuBarFocusReason.
+ \value ActiveWindow Same as Qt::ActiveWindowFocusReason
+ \value Other Same as Qt::OtherFocusReason
+ \value Popup Same as Qt::PopupFocusReason
+ \value Shortcut Same as Qt::ShortcutFocusReason
+*/
+#endif
+
+/*!
+ \class QPaintEvent
+ \brief The QPaintEvent class contains event parameters for paint events.
+
+ \ingroup events
+
+ Paint events are sent to widgets that need to update themselves,
+ for instance when part of a widget is exposed because a covering
+ widget was moved.
+
+ The event contains a region() that needs to be updated, and a
+ rect() that is the bounding rectangle of that region. Both are
+ provided because many widgets can't make much use of region(),
+ and rect() can be much faster than region().boundingRect().
+ Painting is clipped to region() during the processing of a paint
+ event.
+
+ \sa QPainter, QWidget::update(), QWidget::repaint(),
+ QWidget::paintEvent()
+*/
+
+/*!
+ \fn bool QPaintEvent::erased() const
+ \compat
+
+ Returns true if the paint event region (or rectangle) has been
+ erased with the widget's background; otherwise returns false.
+
+ Qt 4 \e always erases regions that require painting. The exception
+ to this rule is if the widget sets the Qt::WA_OpaquePaintEvent or
+ Qt::WA_NoSystemBackground attributes. If either one of those
+ attributes is set \e and the window system does not make use of
+ subwidget alpha composition (currently X11 and Windows, but this
+ may change), then the region is not erased.
+*/
+
+/*!
+ \fn void QPaintEvent::setErased(bool b) { m_erased = b; }
+ \internal
+*/
+
+/*!
+ Constructs a paint event object with the region that needs to
+ be updated. The region is specified by \a paintRegion.
+*/
+QPaintEvent::QPaintEvent(const QRegion& paintRegion)
+ : QEvent(Paint), m_rect(paintRegion.boundingRect()), m_region(paintRegion), m_erased(false)
+{}
+
+/*!
+ Constructs a paint event object with the rectangle that needs
+ to be updated. The region is specified by \a paintRect.
+*/
+QPaintEvent::QPaintEvent(const QRect &paintRect)
+ : QEvent(Paint), m_rect(paintRect),m_region(paintRect), m_erased(false)
+{}
+
+
+#ifdef QT3_SUPPORT
+ /*!
+ Constructs a paint event object with both a \a paintRegion and a
+ \a paintRect, both of which represent the area of the widget that
+ needs to be updated.
+
+*/
+QPaintEvent::QPaintEvent(const QRegion &paintRegion, const QRect &paintRect)
+ : QEvent(Paint), m_rect(paintRect), m_region(paintRegion), m_erased(false)
+{}
+#endif
+
+/*!
+ \internal
+*/
+QPaintEvent::~QPaintEvent()
+{
+}
+
+/*!
+ \fn const QRect &QPaintEvent::rect() const
+
+ Returns the rectangle that needs to be updated.
+
+ \sa region() QPainter::setClipRect()
+*/
+
+/*!
+ \fn const QRegion &QPaintEvent::region() const
+
+ Returns the region that needs to be updated.
+
+ \sa rect() QPainter::setClipRegion()
+*/
+
+
+QUpdateLaterEvent::QUpdateLaterEvent(const QRegion& paintRegion)
+ : QEvent(UpdateLater), m_region(paintRegion)
+{
+}
+
+QUpdateLaterEvent::~QUpdateLaterEvent()
+{
+}
+
+/*!
+ \class QMoveEvent
+ \brief The QMoveEvent class contains event parameters for move events.
+
+ \ingroup events
+
+ Move events are sent to widgets that have been moved to a new
+ position relative to their parent.
+
+ The event handler QWidget::moveEvent() receives move events.
+
+ \sa QWidget::move(), QWidget::setGeometry()
+*/
+
+/*!
+ Constructs a move event with the new and old widget positions,
+ \a pos and \a oldPos respectively.
+*/
+QMoveEvent::QMoveEvent(const QPoint &pos, const QPoint &oldPos)
+ : QEvent(Move), p(pos), oldp(oldPos)
+{}
+
+/*!
+ \internal
+*/
+QMoveEvent::~QMoveEvent()
+{
+}
+
+/*!
+ \fn const QPoint &QMoveEvent::pos() const
+
+ Returns the new position of the widget. This excludes the window
+ frame for top level widgets.
+*/
+
+/*!
+ \fn const QPoint &QMoveEvent::oldPos() const
+
+ Returns the old position of the widget.
+*/
+
+
+/*!
+ \class QResizeEvent
+ \brief The QResizeEvent class contains event parameters for resize events.
+
+ \ingroup events
+
+ Resize events are sent to widgets that have been resized.
+
+ The event handler QWidget::resizeEvent() receives resize events.
+
+ \sa QWidget::resize() QWidget::setGeometry()
+*/
+
+/*!
+ Constructs a resize event with the new and old widget sizes, \a
+ size and \a oldSize respectively.
+*/
+QResizeEvent::QResizeEvent(const QSize &size, const QSize &oldSize)
+ : QEvent(Resize), s(size), olds(oldSize)
+{}
+
+/*!
+ \internal
+*/
+QResizeEvent::~QResizeEvent()
+{
+}
+
+/*!
+ \fn const QSize &QResizeEvent::size() const
+
+ Returns the new size of the widget. This is the same as
+ QWidget::size().
+*/
+
+/*!
+ \fn const QSize &QResizeEvent::oldSize() const
+
+ Returns the old size of the widget.
+*/
+
+
+/*!
+ \class QCloseEvent
+ \brief The QCloseEvent class contains parameters that describe a close event.
+
+ \ingroup events
+
+ Close events are sent to widgets that the user wants to close,
+ usually by choosing "Close" from the window menu, or by clicking
+ the \gui{X} title bar button. They are also sent when you call
+ QWidget::close() to close a widget programmatically.
+
+ Close events contain a flag that indicates whether the receiver
+ wants the widget to be closed or not. When a widget accepts the
+ close event, it is hidden (and destroyed if it was created with
+ the Qt::WA_DeleteOnClose flag). If it refuses to accept the close
+ event nothing happens. (Under X11 it is possible that the window
+ manager will forcibly close the window; but at the time of writing
+ we are not aware of any window manager that does this.)
+
+ The event handler QWidget::closeEvent() receives close events. The
+ default implementation of this event handler accepts the close
+ event. If you do not want your widget to be hidden, or want some
+ special handing, you should reimplement the event handler and
+ ignore() the event.
+
+ The \l{mainwindows/application#close event handler}{closeEvent() in the
+ Application example} shows a close event handler that
+ asks whether to save a document before closing.
+
+ If you want the widget to be deleted when it is closed, create it
+ with the Qt::WA_DeleteOnClose flag. This is very useful for
+ independent top-level windows in a multi-window application.
+
+ \l{QObject}s emits the \l{QObject::destroyed()}{destroyed()}
+ signal when they are deleted.
+
+ If the last top-level window is closed, the
+ QApplication::lastWindowClosed() signal is emitted.
+
+ The isAccepted() function returns true if the event's receiver has
+ agreed to close the widget; call accept() to agree to close the
+ widget and call ignore() if the receiver of this event does not
+ want the widget to be closed.
+
+ \sa QWidget::close(), QWidget::hide(), QObject::destroyed(),
+ QCoreApplication::exec(), QCoreApplication::quit(),
+ QApplication::lastWindowClosed()
+*/
+
+/*!
+ Constructs a close event object.
+
+ \sa accept()
+*/
+QCloseEvent::QCloseEvent()
+ : QEvent(Close)
+{}
+
+/*! \internal
+*/
+QCloseEvent::~QCloseEvent()
+{
+}
+
+/*!
+ \class QIconDragEvent
+ \brief The QIconDragEvent class indicates that a main icon drag has begun.
+
+ \ingroup events
+
+ Icon drag events are sent to widgets when the main icon of a window
+ has been dragged away. On Mac OS X, this happens when the proxy
+ icon of a window is dragged off the title bar.
+
+ It is normal to begin using drag and drop in response to this
+ event.
+
+ \sa {Drag and Drop}, QMimeData, QDrag
+*/
+
+/*!
+ Constructs an icon drag event object with the accept flag set to
+ false.
+
+ \sa accept()
+*/
+QIconDragEvent::QIconDragEvent()
+ : QEvent(IconDrag)
+{ ignore(); }
+
+/*! \internal */
+QIconDragEvent::~QIconDragEvent()
+{
+}
+
+/*!
+ \class QContextMenuEvent
+ \brief The QContextMenuEvent class contains parameters that describe a context menu event.
+
+ \ingroup events
+
+ Context menu events are sent to widgets when a user performs
+ an action associated with opening a context menu.
+ The actions required to open context menus vary between platforms;
+ for example, on Windows, pressing the menu button or clicking the
+ right mouse button will cause this event to be sent.
+
+ When this event occurs it is customary to show a QMenu with a
+ context menu, if this is relevant to the context.
+
+ Context menu events contain a special accept flag that indicates
+ whether the receiver accepted the event. If the event handler does
+ not accept the event then, if possible, whatever triggered the event will be
+ handled as a regular input event.
+*/
+
+#ifndef QT_NO_CONTEXTMENU
+/*!
+ Constructs a context menu event object with the accept parameter
+ flag set to false.
+
+ The \a reason parameter must be QContextMenuEvent::Mouse or
+ QContextMenuEvent::Keyboard.
+
+ The \a pos parameter specifies the mouse position relative to the
+ receiving widget. \a globalPos is the mouse position in absolute
+ coordinates.
+*/
+QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos)
+ : QInputEvent(ContextMenu), p(pos), gp(globalPos), reas(reason)
+{}
+
+/*!
+ Constructs a context menu event object with the accept parameter
+ flag set to false.
+
+ The \a reason parameter must be QContextMenuEvent::Mouse or
+ QContextMenuEvent::Keyboard.
+
+ The \a pos parameter specifies the mouse position relative to the
+ receiving widget. \a globalPos is the mouse position in absolute
+ coordinates. The \a modifiers holds the keyboard modifiers.
+*/
+QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos,
+ Qt::KeyboardModifiers modifiers)
+ : QInputEvent(ContextMenu, modifiers), p(pos), gp(globalPos), reas(reason)
+{}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a context menu event with the given \a reason for the
+ position specified by \a pos in widget coordinates and \a globalPos
+ in global screen coordinates. \a dummy is ignored.
+*/
+QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos,
+ int /* dummy */)
+ : QInputEvent(ContextMenu), p(pos), gp(globalPos), reas(reason)
+{}
+#endif
+
+/*! \internal */
+QContextMenuEvent::~QContextMenuEvent()
+{
+}
+/*!
+ Constructs a context menu event object with the accept parameter
+ flag set to false.
+
+ The \a reason parameter must be QContextMenuEvent::Mouse or
+ QContextMenuEvent::Keyboard.
+
+ The \a pos parameter specifies the mouse position relative to the
+ receiving widget.
+
+ The globalPos() is initialized to QCursor::pos(), which may not be
+ appropriate. Use the other constructor to specify the global
+ position explicitly.
+*/
+QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos)
+ : QInputEvent(ContextMenu), p(pos), reas(reason)
+{
+ gp = QCursor::pos();
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a context menu event with the given \a reason for the
+ position specified by \a pos in widget coordinates. \a dummy is
+ ignored.
+*/
+QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos, int /* dummy */)
+ : QInputEvent(ContextMenu), p(pos), reas(reason)
+{
+ gp = QCursor::pos();
+}
+
+Qt::ButtonState QContextMenuEvent::state() const
+{
+ return Qt::ButtonState(int(QApplication::keyboardModifiers())|QApplication::mouseButtons());
+}
+#endif
+
+/*!
+ \fn const QPoint &QContextMenuEvent::pos() const
+
+ Returns the position of the mouse pointer relative to the widget
+ that received the event.
+
+ \sa x(), y(), globalPos()
+*/
+
+/*!
+ \fn int QContextMenuEvent::x() const
+
+ Returns the x position of the mouse pointer, relative to the
+ widget that received the event.
+
+ \sa y(), pos()
+*/
+
+/*!
+ \fn int QContextMenuEvent::y() const
+
+ Returns the y position of the mouse pointer, relative to the
+ widget that received the event.
+
+ \sa x(), pos()
+*/
+
+/*!
+ \fn const QPoint &QContextMenuEvent::globalPos() const
+
+ Returns the global position of the mouse pointer at the time of
+ the event.
+
+ \sa x(), y(), pos()
+*/
+
+/*!
+ \fn int QContextMenuEvent::globalX() const
+
+ Returns the global x position of the mouse pointer at the time of
+ the event.
+
+ \sa globalY(), globalPos()
+*/
+
+/*!
+ \fn int QContextMenuEvent::globalY() const
+
+ Returns the global y position of the mouse pointer at the time of
+ the event.
+
+ \sa globalX(), globalPos()
+*/
+#endif // QT_NO_CONTEXTMENU
+
+/*!
+ \fn Qt::ButtonState QContextMenuEvent::state() const
+
+ Returns the button state (a combination of mouse buttons
+ and keyboard modifiers) immediately before the event was
+ generated.
+
+ The returned value is a selection of the following values,
+ combined with the OR operator:
+ Qt::LeftButton, Qt::RightButton, Qt::MidButton,
+ Qt::ShiftButton, Qt::ControlButton, and Qt::AltButton.
+*/
+
+/*!
+ \enum QContextMenuEvent::Reason
+
+ This enum describes the reason why the event was sent.
+
+ \value Mouse The mouse caused the event to be sent. Normally this
+ means the right mouse button was clicked, but this is platform
+ dependent.
+
+ \value Keyboard The keyboard caused this event to be sent. On
+ Windows, this means the menu button was pressed.
+
+ \value Other The event was sent by some other means (i.e. not by
+ the mouse or keyboard).
+*/
+
+
+/*!
+ \fn QContextMenuEvent::Reason QContextMenuEvent::reason() const
+
+ Returns the reason for this context event.
+*/
+
+
+/*!
+ \class QInputMethodEvent
+ \brief The QInputMethodEvent class provides parameters for input method events.
+
+ \ingroup events
+
+ Input method events are sent to widgets when an input method is
+ used to enter text into a widget. Input methods are widely used
+ to enter text for languages with non-Latin alphabets.
+
+ Note that when creating custom text editing widgets, the
+ Qt::WA_InputMethodEnabled window attribute must be set explicitly
+ (using the QWidget::setAttribute() function) in order to receive
+ input method events.
+
+ The events are of interest to authors of keyboard entry widgets
+ who want to be able to correctly handle languages with complex
+ character input. Text input in such languages is usually a three
+ step process:
+
+ \list 1
+ \o \bold{Starting to Compose}
+
+ When the user presses the first key on a keyboard, an input
+ context is created. This input context will contain a string
+ of the typed characters.
+
+ \o \bold{Composing}
+
+ With every new key pressed, the input method will try to create a
+ matching string for the text typed so far called preedit
+ string. While the input context is active, the user can only move
+ the cursor inside the string belonging to this input context.
+
+ \o \bold{Completing}
+
+ At some point, the user will activate a user interface component
+ (perhaps using a particular key) where they can choose from a
+ number of strings matching the text they have typed so far. The
+ user can either confirm their choice cancel the input; in either
+ case the input context will be closed.
+ \endlist
+
+ QInputMethodEvent models these three stages, and transfers the
+ information needed to correctly render the intermediate result. A
+ QInputMethodEvent has two main parameters: preeditString() and
+ commitString(). The preeditString() parameter gives the currently
+ active preedit string. The commitString() parameter gives a text
+ that should get added to (or replace parts of) the text of the
+ editor widget. It usually is a result of the input operations and
+ has to be inserted to the widgets text directly before the preedit
+ string.
+
+ If the commitString() should replace parts of the of the text in
+ the editor, replacementLength() will contain the number of
+ characters to be replaced. replacementStart() contains the position
+ at which characters are to be replaced relative from the start of
+ the preedit string.
+
+ A number of attributes control the visual appearance of the
+ preedit string (the visual appearance of text outside the preedit
+ string is controlled by the widget only). The AttributeType enum
+ describes the different attributes that can be set.
+
+ A class implementing QWidget::inputMethodEvent() should at least
+ understand and honor the \l TextFormat and \l Cursor attributes.
+
+ Since input methods need to be able to query certain properties
+ from the widget, the widget must also implement
+ QWidget::inputMethodQuery().
+
+ When receiving an input method event, the text widget has to performs the
+ following steps:
+
+ \list 1
+ \o If the widget has selected text, the selected text should get
+ removed.
+
+ \o Remove the text starting at replacementStart() with length
+ replacementLength() and replace it by the commitString(). If
+ replacementLength() is 0, replacementStart() gives the insertion
+ position for the commitString().
+
+ When doing replacement the area of the preedit
+ string is ignored, thus a replacement starting at -1 with a length
+ of 2 will remove the last character before the preedit string and
+ the first character afterwards, and insert the commit string
+ directly before the preedit string.
+
+ If the widget implements undo/redo, this operation gets added to
+ the undo stack.
+
+ \o If there is no current preedit string, insert the
+ preeditString() at the current cursor position; otherwise replace
+ the previous preeditString with the one received from this event.
+
+ If the widget implements undo/redo, the preeditString() should not
+ influence the undo/redo stack in any way.
+
+ The widget should examine the list of attributes to apply to the
+ preedit string. It has to understand at least the TextFormat and
+ Cursor attributes and render them as specified.
+ \endlist
+
+ \sa QInputContext
+*/
+
+/*!
+ \enum QInputMethodEvent::AttributeType
+
+ \value TextFormat
+ A QTextCharFormat for the part of the preedit string specified by
+ start and length. value contains a QVariant of type QTextFormat
+ specifying rendering of this part of the preedit string. There
+ should be at most one format for every part of the preedit
+ string. If several are specified for any character in the string the
+ behaviour is undefined. A conforming implementation has to at least
+ honor the backgroundColor, textColor and fontUnderline properties
+ of the format.
+
+ \value Cursor If set, a cursor should be shown inside the preedit
+ string at position start. The length variable determines whether
+ the cursor is visible or not. If the length is 0 the cursor is
+ invisible. If value is a QVariant of type QColor this color will
+ be used for rendering the cursor, otherwise the color of the
+ surrounding text will be used. There should be at most one Cursor
+ attribute per event. If several are specified the behaviour is
+ undefined.
+
+ \value Language
+ The variant contains a QLocale object specifying the language of a
+ certain part of the preedit string. There should be at most one
+ language set for every part of the preedit string. If several are
+ specified for any character in the string the behaviour is undefined.
+
+ \value Ruby
+ The ruby text for a part of the preedit string. There should be at
+ most one ruby text set for every part of the preedit string. If
+ several are specified for any character in the string the behaviour
+ is undefined.
+
+ \sa Attribute
+*/
+
+/*!
+ \class QInputMethodEvent::Attribute
+ \brief The QInputMethodEvent::Attribute class stores an input method attribute.
+*/
+
+/*!
+ \fn QInputMethodEvent::Attribute::Attribute(AttributeType type, int start, int length, QVariant value)
+
+ Constructs an input method attribute. \a type specifies the type
+ of attribute, \a start and \a length the position of the
+ attribute, and \a value the value of the attribute.
+*/
+
+/*!
+ Constructs an event of type QEvent::InputMethod. The
+ attributes(), preeditString(), commitString(), replacementStart(),
+ and replacementLength() are initialized to default values.
+
+ \sa setCommitString()
+*/
+QInputMethodEvent::QInputMethodEvent()
+ : QEvent(QEvent::InputMethod), replace_from(0), replace_length(0)
+{
+}
+
+/*!
+ Construcs an event of type QEvent::InputMethod. The
+ preedit text is set to \a preeditText, the attributes to
+ \a attributes.
+
+ The commitString(), replacementStart(), and replacementLength()
+ values can be set using setCommitString().
+
+ \sa preeditString(), attributes()
+*/
+QInputMethodEvent::QInputMethodEvent(const QString &preeditText, const QList<Attribute> &attributes)
+ : QEvent(QEvent::InputMethod), preedit(preeditText), attrs(attributes),
+ replace_from(0), replace_length(0)
+{
+}
+
+/*!
+ Constructs a copy of \a other.
+*/
+QInputMethodEvent::QInputMethodEvent(const QInputMethodEvent &other)
+ : QEvent(QEvent::InputMethod), preedit(other.preedit), attrs(other.attrs),
+ commit(other.commit), replace_from(other.replace_from), replace_length(other.replace_length)
+{
+}
+
+/*!
+ Sets the commit string to \a commitString.
+
+ The commit string is the text that should get added to (or
+ replace parts of) the text of the editor widget. It usually is a
+ result of the input operations and has to be inserted to the
+ widgets text directly before the preedit string.
+
+ If the commit string should replace parts of the of the text in
+ the editor, \a replaceLength specifies the number of
+ characters to be replaced. \a replaceFrom specifies the position
+ at which characters are to be replaced relative from the start of
+ the preedit string.
+
+ \sa commitString(), replacementStart(), replacementLength()
+*/
+void QInputMethodEvent::setCommitString(const QString &commitString, int replaceFrom, int replaceLength)
+{
+ commit = commitString;
+ replace_from = replaceFrom;
+ replace_length = replaceLength;
+}
+
+/*!
+ \fn const QList<Attribute> &QInputMethodEvent::attributes() const
+
+ Returns the list of attributes passed to the QInputMethodEvent
+ constructor. The attributes control the visual appearance of the
+ preedit string (the visual appearance of text outside the preedit
+ string is controlled by the widget only).
+
+ \sa preeditString(), Attribute
+*/
+
+/*!
+ \fn const QString &QInputMethodEvent::preeditString() const
+
+ Returns the preedit text, i.e. the text before the user started
+ editing it.
+
+ \sa commitString(), attributes()
+*/
+
+/*!
+ \fn const QString &QInputMethodEvent::commitString() const
+
+ Returns the text that should get added to (or replace parts of)
+ the text of the editor widget. It usually is a result of the
+ input operations and has to be inserted to the widgets text
+ directly before the preedit string.
+
+ \sa setCommitString(), preeditString(), replacementStart(), replacementLength()
+*/
+
+/*!
+ \fn int QInputMethodEvent::replacementStart() const
+
+ Returns the position at which characters are to be replaced relative
+ from the start of the preedit string.
+
+ \sa replacementLength(), setCommitString()
+*/
+
+/*!
+ \fn int QInputMethodEvent::replacementLength() const
+
+ Returns the number of characters to be replaced in the preedit
+ string.
+
+ \sa replacementStart(), setCommitString()
+*/
+
+#ifndef QT_NO_TABLETEVENT
+
+/*!
+ \class QTabletEvent
+ \brief The QTabletEvent class contains parameters that describe a Tablet event.
+
+ \ingroup events
+
+ Tablet Events are generated from a Wacom tablet. Most of the time you will
+ want to deal with events from the tablet as if they were events from a
+ mouse; for example, you would retrieve the cursor position with x(), y(),
+ pos(), globalX(), globalY(), and globalPos(). In some situations you may
+ wish to retrieve the extra information provided by the tablet device
+ driver; for example, you might want to do subpixeling with higher
+ resolution coordinates or you may want to adjust color brightness based on
+ pressure. QTabletEvent allows you to read the pressure(), the xTilt(), and
+ yTilt(), as well as the type of device being used with device() (see
+ \l{TabletDevice}). It can also give you the minimum and maximum values for
+ each device's pressure and high resolution coordinates.
+
+ A tablet event contains a special accept flag that indicates whether the
+ receiver wants the event. You should call QTabletEvent::accept() if you
+ handle the tablet event; otherwise it will be sent to the parent widget.
+ The exception are TabletEnterProximity and TabletLeaveProximity events,
+ these are only sent to QApplication and don't check whether or not they are
+ accepted.
+
+ The QWidget::setEnabled() function can be used to enable or
+ disable mouse and keyboard events for a widget.
+
+ The event handler QWidget::tabletEvent() receives all three types of
+ tablet events. Qt will first send a tabletEvent then, if it is not
+ accepted, it will send a mouse event. This allows applications that
+ don't utilize tablets to use a tablet like a mouse, while also
+ enabling those who want to use both tablets and mouses differently.
+
+ \section1 Notes for X11 Users
+
+ Qt uses the following hard-coded names to identify tablet
+ devices from the xorg.conf file on X11 (apart from IRIX):
+ 'stylus', 'pen', and 'eraser'. If the devices have other names,
+ they will not be picked up Qt.
+*/
+
+/*!
+ \enum QTabletEvent::TabletDevice
+
+ This enum defines what type of device is generating the event.
+
+ \value NoDevice No device, or an unknown device.
+ \value Puck A Puck (a device that is similar to a flat mouse with
+ a transparent circle with cross-hairs).
+ \value Stylus A Stylus.
+ \value Airbrush An airbrush
+ \value FourDMouse A 4D Mouse.
+ \value RotationStylus A special stylus that also knows about rotation
+ (a 6D stylus). \since 4.1
+ \omitvalue XFreeEraser
+*/
+
+/*!
+ \enum QTabletEvent::PointerType
+
+ This enum defines what type of point is generating the event.
+
+ \value UnknownPointer An unknown device.
+ \value Pen Tip end of a stylus-like device (the narrow end of the pen).
+ \value Cursor Any puck-like device.
+ \value Eraser Eraser end of a stylus-like device (the broad end of the pen).
+
+ \sa pointerType()
+*/
+
+/*!
+ Construct a tablet event of the given \a type.
+
+ The \a pos parameter indicates where the event occurred in the
+ widget; \a globalPos is the corresponding position in absolute
+ coordinates. The \a hiResGlobalPos contains a high resolution
+ measurement of the position.
+
+ \a pressure contains the pressure exerted on the \a device.
+
+ \a pointerType describes the type of pen that is being used.
+
+ \a xTilt and \a yTilt contain the device's degree of tilt from the
+ x and y axes respectively.
+
+ \a keyState specifies which keyboard modifiers are pressed (e.g.,
+ \key{Ctrl}).
+
+ The \a uniqueID parameter contains the unique ID for the current device.
+
+ The \a z parameter contains the coordinate of the device on the tablet, this
+ is usually given by a wheel on 4D mouse. If the device does not support a
+ Z-axis, pass zero here.
+
+ The \a tangentialPressure paramater contins the tangential pressure of an air
+ brush. If the device does not support tangential pressure, pass 0 here.
+
+ \a rotation contains the device's rotation in degrees. 4D mice support
+ rotation. If the device does not support rotation, pass 0 here.
+
+ \sa pos() globalPos() device() pressure() xTilt() yTilt() uniqueId(), rotation(), tangentialPressure(), z()
+*/
+
+QTabletEvent::QTabletEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+ const QPointF &hiResGlobalPos, int device, int pointerType,
+ qreal pressure, int xTilt, int yTilt, qreal tangentialPressure,
+ qreal rotation, int z, Qt::KeyboardModifiers keyState, qint64 uniqueID)
+ : QInputEvent(type, keyState),
+ mPos(pos),
+ mGPos(globalPos),
+ mHiResGlobalPos(hiResGlobalPos),
+ mDev(device),
+ mPointerType(pointerType),
+ mXT(xTilt),
+ mYT(yTilt),
+ mZ(z),
+ mPress(pressure),
+ mTangential(tangentialPressure),
+ mRot(rotation),
+ mUnique(uniqueID),
+ mExtra(0)
+{
+}
+
+/*!
+ \internal
+*/
+QTabletEvent::~QTabletEvent()
+{
+}
+
+/*!
+ \fn TabletDevices QTabletEvent::device() const
+
+ Returns the type of device that generated the event.
+
+ \sa TabletDevice
+*/
+
+/*!
+ \fn PointerType QTabletEvent::pointerType() const
+
+ Returns the type of point that generated the event.
+*/
+
+/*!
+ \fn qreal QTabletEvent::tangentialPressure() const
+
+ Returns the tangential pressure for the device. This is typically given by a finger
+ wheel on an airbrush tool. The range is from -1.0 to 1.0. 0.0 indicates a
+ neutral position. Current airbrushes can only move in the positive
+ direction from the neutrual position. If the device does not support
+ tangential pressure, this value is always 0.0.
+
+ \sa pressure()
+*/
+
+/*!
+ \fn qreal QTabletEvent::rotation() const
+
+ Returns the rotation of the current device in degress. This is usually
+ given by a 4D Mouse. If the device doesn't support rotation this value is
+ always 0.0.
+
+*/
+
+/*!
+ \fn qreal QTabletEvent::pressure() const
+
+ Returns the pressure for the device. 0.0 indicates that the stylus is not
+ on the tablet, 1.0 indicates the maximum amount of pressure for the stylus.
+
+ \sa tangentialPressure()
+*/
+
+/*!
+ \fn int QTabletEvent::xTilt() const
+
+ Returns the angle between the device (a pen, for example) and the
+ perpendicular in the direction of the x axis.
+ Positive values are towards the tablet's physical right. The angle
+ is in the range -60 to +60 degrees.
+
+ \img qtabletevent-tilt.png
+
+ \sa yTilt()
+*/
+
+/*!
+ \fn int QTabletEvent::yTilt() const
+
+ Returns the angle between the device (a pen, for example) and the
+ perpendicular in the direction of the y axis.
+ Positive values are towards the bottom of the tablet. The angle is
+ within the range -60 to +60 degrees.
+
+ \sa xTilt()
+*/
+
+/*!
+ \fn const QPoint &QTabletEvent::pos() const
+
+ Returns the position of the device, relative to the widget that
+ received the event.
+
+ If you move widgets around in response to mouse events, use
+ globalPos() instead of this function.
+
+ \sa x() y() globalPos()
+*/
+
+/*!
+ \fn int QTabletEvent::x() const
+
+ Returns the x position of the device, relative to the widget that
+ received the event.
+
+ \sa y() pos()
+*/
+
+/*!
+ \fn int QTabletEvent::y() const
+
+ Returns the y position of the device, relative to the widget that
+ received the event.
+
+ \sa x() pos()
+*/
+
+/*!
+ \fn int QTabletEvent::z() const
+
+ Returns the z position of the device. Typically this is represented by a
+ wheel on a 4D Mouse. If the device does not support a Z-axis, this value is
+ always zero. This is \bold not the same as pressure.
+
+ \sa pressure()
+*/
+
+/*!
+ \fn const QPoint &QTabletEvent::globalPos() const
+
+ Returns the global position of the device \e{at the time of the
+ event}. This is important on asynchronous windows systems like X11;
+ whenever you move your widgets around in response to mouse events,
+ globalPos() can differ significantly from the current position
+ QCursor::pos().
+
+ \sa globalX() globalY() hiResGlobalPos()
+*/
+
+/*!
+ \fn int QTabletEvent::globalX() const
+
+ Returns the global x position of the mouse pointer at the time of
+ the event.
+
+ \sa globalY() globalPos() hiResGlobalX()
+*/
+
+/*!
+ \fn int QTabletEvent::globalY() const
+
+ Returns the global y position of the tablet device at the time of
+ the event.
+
+ \sa globalX() globalPos() hiResGlobalY()
+*/
+
+/*!
+ \fn qint64 QTabletEvent::uniqueId() const
+
+ Returns a unique ID for the current device, making it possible
+ to differentiate between multiple devices being used at the same
+ time on the tablet.
+
+ Support of this feature is dependent on the tablet.
+
+ Values for the same device may vary from OS to OS.
+
+ Later versions of the Wacom driver for Linux will now report
+ the ID information. If you have a tablet that supports unique ID
+ and are not getting the information on Linux, consider upgrading
+ your driver.
+
+ As of Qt 4.2, the unique ID is the same regardless of the orientation
+ of the pen. Earlier versions would report a different value when using
+ the eraser-end versus the pen-end of the stylus on some OS's.
+
+ \sa pointerType()
+*/
+
+/*!
+ \fn const QPointF &QTabletEvent::hiResGlobalPos() const
+
+ The high precision coordinates delivered from the tablet expressed.
+ Sub pixeling information is in the fractional part of the QPointF.
+
+ \sa globalPos() hiResGlobalX() hiResGlobalY()
+*/
+
+/*!
+ \fn qreal &QTabletEvent::hiResGlobalX() const
+
+ The high precision x position of the tablet device.
+*/
+
+/*!
+ \fn qreal &QTabletEvent::hiResGlobalY() const
+
+ The high precision y position of the tablet device.
+*/
+
+#endif // QT_NO_TABLETEVENT
+
+#ifndef QT_NO_DRAGANDDROP
+/*!
+ Creates a QDragMoveEvent of the required \a type indicating
+ that the mouse is at position \a pos given within a widget.
+
+ The mouse and keyboard states are specified by \a buttons and
+ \a modifiers, and the \a actions describe the types of drag
+ and drop operation that are possible.
+ The drag data is passed as MIME-encoded information in \a data.
+
+ \warning Do not attempt to create a QDragMoveEvent yourself.
+ These objects rely on Qt's internal state.
+*/
+QDragMoveEvent::QDragMoveEvent(const QPoint& pos, Qt::DropActions actions, const QMimeData *data,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type)
+ : QDropEvent(pos, actions, data, buttons, modifiers, type)
+ , rect(pos, QSize(1, 1))
+{}
+
+/*!
+ Destroys the event.
+*/
+QDragMoveEvent::~QDragMoveEvent()
+{
+}
+
+/*!
+ \fn void QDragMoveEvent::accept(bool y)
+
+ Calls setAccepted(\a y) instead.
+*/
+
+/*!
+ \fn void QDragMoveEvent::accept(const QRect &rectangle)
+
+ The same as accept(), but also notifies that future moves will
+ also be acceptable if they remain within the \a rectangle
+ given on the widget. This can improve performance, but may
+ also be ignored by the underlying system.
+
+ If the rectangle is empty, drag move events will be sent
+ continuously. This is useful if the source is scrolling in a
+ timer event.
+*/
+
+/*!
+ \fn void QDragMoveEvent::accept()
+
+ \overload
+
+ Calls QDropEvent::accept().
+*/
+
+/*!
+ \fn void QDragMoveEvent::ignore()
+
+ \overload
+
+ Calls QDropEvent::ignore().
+*/
+
+/*!
+ \fn void QDragMoveEvent::ignore(const QRect &rectangle)
+
+ The opposite of the accept(const QRect&) function.
+ Moves within the \a rectangle are not acceptable, and will be
+ ignored.
+*/
+
+/*!
+ \fn QRect QDragMoveEvent::answerRect() const
+
+ Returns the rectangle in the widget where the drop will occur if accepted.
+ You can use this information to restrict drops to certain places on the
+ widget.
+*/
+
+
+/*!
+ \class QDropEvent
+ \ingroup events
+ \ingroup draganddrop
+
+ \brief The QDropEvent class provides an event which is sent when a
+ drag and drop action is completed.
+
+ When a widget \l{QWidget::setAcceptDrops()}{accepts drop events}, it will
+ receive this event if it has accepted the most recent QDragEnterEvent or
+ QDragMoveEvent sent to it.
+
+ The drop event contains a proposed action, available from proposedAction(), for
+ the widget to either accept or ignore. If the action can be handled by the
+ widget, you should call the acceptProposedAction() function. Since the
+ proposed action can be a combination of \l Qt::DropAction values, it may be
+ useful to either select one of these values as a default action or ask
+ the user to select their preferred action.
+
+ If the proposed drop action is not suitable, perhaps because your custom
+ widget does not support that action, you can replace it with any of the
+ \l{possibleActions()}{possible drop actions} by calling setDropAction()
+ with your preferred action. If you set a value that is not present in the
+ bitwise OR combination of values returned by possibleActions(), the default
+ copy action will be used. Once a replacement drop action has been set, call
+ accept() instead of acceptProposedAction() to complete the drop operation.
+
+ The mimeData() function provides the data dropped on the widget in a QMimeData
+ object. This contains information about the MIME type of the data in addition to
+ the data itself.
+
+ \sa QMimeData, QDrag, {Drag and Drop}
+*/
+
+/*!
+ \fn const QMimeData *QDropEvent::mimeData() const
+
+ Returns the data that was dropped on the widget and its associated MIME
+ type information.
+*/
+
+/*!
+ Constructs a drop event of a certain \a type corresponding to a
+ drop at the point specified by \a pos in the destination widget's
+ coordinate system.
+
+ The \a actions indicate which types of drag and drop operation can
+ be performed, and the drag data is stored as MIME-encoded data in \a data.
+
+ The states of the mouse buttons and keyboard modifiers at the time of
+ the drop are specified by \a buttons and \a modifiers.
+*/ // ### pos is in which coordinate system?
+QDropEvent::QDropEvent(const QPoint& pos, Qt::DropActions actions, const QMimeData *data,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type)
+ : QEvent(type), p(pos), mouseState(buttons),
+ modState(modifiers), act(actions),
+ mdata(data)
+{
+ default_action = QDragManager::self()->defaultAction(act, modifiers);
+ drop_action = default_action;
+ ignore();
+}
+
+/*! \internal */
+QDropEvent::~QDropEvent()
+{
+}
+
+/*!
+ \compat
+ Returns a byte array containing the drag's data, in \a format.
+
+ data() normally needs to get the data from the drag source, which
+ is potentially very slow, so it's advisable to call this function
+ only if you're sure that you will need the data in that
+ particular \a format.
+
+ The resulting data will have a size of 0 if the format was not
+ available.
+
+ \sa format() QByteArray::size()
+*/
+
+QByteArray QDropEvent::encodedData(const char *format) const
+{
+ return mdata->data(QLatin1String(format));
+}
+
+/*!
+ \compat
+ Returns a string describing one of the available data types for
+ this drag. Common examples are "text/plain" and "image/gif".
+ If \a n is less than zero or greater than the number of available
+ data types, format() returns 0.
+
+ This function is provided mainly for debugging. Most drop targets
+ will use provides().
+
+ \sa data() provides()
+*/
+
+const char* QDropEvent::format(int n) const
+{
+ if (fmts.isEmpty()) {
+ QStringList formats = mdata->formats();
+ for (int i = 0; i < formats.size(); ++i)
+ fmts.append(formats.at(i).toLatin1());
+ }
+ if (n < 0 || n >= fmts.size())
+ return 0;
+ return fmts.at(n).constData();
+}
+
+/*!
+ \compat
+ Returns true if this event provides format \a mimeType; otherwise
+ returns false.
+
+ \sa data()
+*/
+
+bool QDropEvent::provides(const char *mimeType) const
+{
+ return mdata->formats().contains(QLatin1String(mimeType));
+}
+
+/*!
+ If the source of the drag operation is a widget in this
+ application, this function returns that source; otherwise it
+ returns 0. The source of the operation is the first parameter to
+ the QDrag object used instantiate the drag.
+
+ This is useful if your widget needs special behavior when dragging
+ to itself.
+
+ \sa QDrag::QDrag()
+*/
+QWidget* QDropEvent::source() const
+{
+ QDragManager *manager = QDragManager::self();
+ return manager ? manager->source() : 0;
+}
+
+
+void QDropEvent::setDropAction(Qt::DropAction action)
+{
+ if (!(action & act) && action != Qt::IgnoreAction)
+ action = default_action;
+ drop_action = action;
+}
+
+/*!
+ \fn const QPoint& QDropEvent::pos() const
+
+ Returns the position where the drop was made.
+*/
+
+/*!
+ \fn Qt::MouseButtons QDropEvent::mouseButtons() const
+
+ Returns the mouse buttons that are pressed..
+*/
+
+/*!
+ \fn Qt::KeyboardModifiers QDropEvent::keyboardModifiers() const
+
+ Returns the modifier keys that are pressed.
+*/
+
+/*!
+ \fn void QDropEvent::accept()
+ \internal
+*/
+
+/*!
+ \fn void QDropEvent::accept(bool accept)
+
+ Call setAccepted(\a accept) instead.
+*/
+
+/*!
+ \fn void QDropEvent::acceptAction(bool accept = true)
+
+ Call this to indicate that the action described by action() is
+ accepted (i.e. if \a accept is true, which is the default), not merely
+ the default copy action. If you call acceptAction(true), there is
+ no need to also call accept(true).
+*/
+
+/*!
+ \enum QDropEvent::Action
+ \compat
+
+ When a drag and drop action is completed, the target is expected
+ to perform an action on the data provided by the source. This
+ will be one of the following:
+
+ \value Copy The default action. The source simply uses the data
+ provided in the operation.
+ \value Link The source should somehow create a link to the
+ location specified by the data.
+ \value Move The source should somehow move the object from the
+ location specified by the data to a new location.
+ \value Private The target has special knowledge of the MIME type,
+ which the source should respond to in a similar way to
+ a Copy.
+ \value UserAction The source and target can co-operate using
+ special actions. This feature is not currently
+ supported.
+
+ The Link and Move actions only makes sense if the data is a
+ reference, for example, text/uri-list file lists (see QUriDrag).
+*/
+
+/*!
+ \fn void QDropEvent::setDropAction(Qt::DropAction action)
+
+ Sets the \a action to be performed on the data by the target.
+ Use this to override the \l{proposedAction()}{proposed action}
+ with one of the \l{possibleActions()}{possible actions}.
+
+ If you set a drop action that is not one of the possible actions, the
+ drag and drop operation will default to a copy operation.
+
+ Once you have supplied a replacement drop action, call accept()
+ instead of acceptProposedAction().
+
+ \sa dropAction()
+*/
+
+/*!
+ \fn Qt::DropAction QDropEvent::dropAction() const
+
+ Returns the action to be performed on the data by the target. This may be
+ different from the action supplied in proposedAction() if you have called
+ setDropAction() to explicitly choose a drop action.
+
+ \sa setDropAction()
+*/
+
+/*!
+ \fn Qt::DropActions QDropEvent::possibleActions() const
+
+ Returns an OR-combination of possible drop actions.
+
+ \sa dropAction()
+*/
+
+/*!
+ \fn Qt::DropAction QDropEvent::proposedAction() const
+
+ Returns the proposed drop action.
+
+ \sa dropAction()
+*/
+
+/*!
+ \fn void QDropEvent::acceptProposedAction()
+
+ Sets the drop action to be the proposed action.
+
+ \sa setDropAction(), proposedAction(), {QEvent::accept()}{accept()}
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ Use dropAction() instead.
+
+ The table below shows the correspondance between the return type
+ of action() and the return type of dropAction().
+
+ \table
+ \header \i Old enum value \i New enum value
+ \row \i QDropEvent::Copy \i Qt::CopyAction
+ \row \i QDropEvent::Move \i Qt::MoveAction
+ \row \i QDropEvent::Link \i Qt::LinkAction
+ \row \i other \i Qt::CopyAction
+ \endtable
+*/
+
+QT3_SUPPORT QDropEvent::Action QDropEvent::action() const
+{
+ switch(drop_action) {
+ case Qt::CopyAction:
+ return Copy;
+ case Qt::MoveAction:
+ return Move;
+ case Qt::LinkAction:
+ return Link;
+ default:
+ return Copy;
+ }
+}
+#endif
+
+/*!
+ \fn void QDropEvent::setPoint(const QPoint &point)
+ \compat
+
+ Sets the drop to happen at the given \a point. You do not normally
+ need to use this as it will be set internally before your widget
+ receives the drop event.
+*/ // ### here too - what coordinate system?
+
+
+/*!
+ \class QDragEnterEvent
+ \brief The QDragEnterEvent class provides an event which is sent
+ to a widget when a drag and drop action enters it.
+
+ \ingroup events
+ \ingroup draganddrop
+
+ A widget must accept this event in order to receive the \l
+ {QDragMoveEvent}{drag move events} that are sent while the drag
+ and drop action is in progress. The drag enter event is always
+ immediately followed by a drag move event.
+
+ QDragEnterEvent inherits most of its functionality from
+ QDragMoveEvent, which in turn inherits most of its functionality
+ from QDropEvent.
+
+ \sa QDragLeaveEvent, QDragMoveEvent, QDropEvent
+*/
+
+/*!
+ Constructs a QDragEnterEvent that represents a drag entering a
+ widget at the given \a point with mouse and keyboard states specified by
+ \a buttons and \a modifiers.
+
+ The drag data is passed as MIME-encoded information in \a data, and the
+ specified \a actions describe the possible types of drag and drop
+ operation that can be performed.
+
+ \warning Do not create a QDragEnterEvent yourself since these
+ objects rely on Qt's internal state.
+*/
+QDragEnterEvent::QDragEnterEvent(const QPoint& point, Qt::DropActions actions, const QMimeData *data,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+ : QDragMoveEvent(point, actions, data, buttons, modifiers, DragEnter)
+{}
+
+/*! \internal
+*/
+QDragEnterEvent::~QDragEnterEvent()
+{
+}
+
+/*!
+ Constructs a drag response event containing the \a accepted value,
+ indicating whether the drag and drop operation was accepted by the
+ recipient.
+*/
+QDragResponseEvent::QDragResponseEvent(bool accepted)
+ : QEvent(DragResponse), a(accepted)
+{}
+
+/*! \internal
+*/
+QDragResponseEvent::~QDragResponseEvent()
+{
+}
+
+/*!
+ \class QDragMoveEvent
+ \brief The QDragMoveEvent class provides an event which is sent while a drag and drop action is in progress.
+
+ \ingroup events
+ \ingroup draganddrop
+
+ A widget will receive drag move events repeatedly while the drag
+ is within its boundaries, if it accepts
+ \l{QWidget::setAcceptDrops()}{drop events} and \l
+ {QWidget::dragEnterEvent()}{enter events}. The widget should
+ examine the event to see what kind of data it
+ \l{QDragMoveEvent::provides()}{provides}, and call the accept()
+ function to accept the drop if appropriate.
+
+ The rectangle supplied by the answerRect() function can be used to restrict
+ drops to certain parts of the widget. For example, we can check whether the
+ rectangle intersects with the geometry of a certain child widget and only
+ call \l{QDropEvent::acceptProposedAction()}{acceptProposedAction()} if that
+ is the case.
+
+ Note that this class inherits most of its functionality from
+ QDropEvent.
+
+ \sa QDragEnterEvent, QDragLeaveEvent, QDropEvent
+*/
+
+/*!
+ \class QDragLeaveEvent
+ \brief The QDragLeaveEvent class provides an event that is sent to a widget when a drag and drop action leaves it.
+
+ \ingroup events
+ \ingroup draganddrop
+
+ This event is always preceded by a QDragEnterEvent and a series
+ of \l{QDragMoveEvent}s. It is not sent if a QDropEvent is sent
+ instead.
+
+ \sa QDragEnterEvent, QDragMoveEvent, QDropEvent
+*/
+
+/*!
+ Constructs a QDragLeaveEvent.
+
+ \warning Do not create a QDragLeaveEvent yourself since these
+ objects rely on Qt's internal state.
+*/
+QDragLeaveEvent::QDragLeaveEvent()
+ : QEvent(DragLeave)
+{}
+
+/*! \internal
+*/
+QDragLeaveEvent::~QDragLeaveEvent()
+{
+}
+#endif // QT_NO_DRAGANDDROP
+
+/*!
+ \class QHelpEvent
+ \brief The QHelpEvent class provides an event that is used to request helpful information
+ about a particular point in a widget.
+
+ \ingroup events
+ \ingroup helpsystem
+
+ This event can be intercepted in applications to provide tooltips
+ or "What's This?" help for custom widgets. The type() can be
+ either QEvent::ToolTip or QEvent::WhatsThis.
+
+ \sa QToolTip, QWhatsThis, QStatusTipEvent, QWhatsThisClickedEvent
+*/
+
+/*!
+ Constructs a help event with the given \a type corresponding to the
+ widget-relative position specified by \a pos and the global position
+ specified by \a globalPos.
+
+ \a type must be either QEvent::ToolTip or QEvent::WhatsThis.
+
+ \sa pos(), globalPos()
+*/
+QHelpEvent::QHelpEvent(Type type, const QPoint &pos, const QPoint &globalPos)
+ : QEvent(type), p(pos), gp(globalPos)
+{}
+
+/*!
+ \fn int QHelpEvent::x() const
+
+ Same as pos().x().
+
+ \sa y(), pos(), globalPos()
+*/
+
+/*!
+ \fn int QHelpEvent::y() const
+
+ Same as pos().y().
+
+ \sa x(), pos(), globalPos()
+*/
+
+/*!
+ \fn int QHelpEvent::globalX() const
+
+ Same as globalPos().x().
+
+ \sa x(), globalY(), globalPos()
+*/
+
+/*!
+ \fn int QHelpEvent::globalY() const
+
+ Same as globalPos().y().
+
+ \sa y(), globalX(), globalPos()
+*/
+
+/*!
+ \fn const QPoint &QHelpEvent::pos() const
+
+ Returns the mouse cursor position when the event was generated,
+ relative to the widget to which the event is dispatched.
+
+ \sa globalPos(), x(), y()
+*/
+
+/*!
+ \fn const QPoint &QHelpEvent::globalPos() const
+
+ Returns the mouse cursor position when the event was generated
+ in global coordinates.
+
+ \sa pos(), globalX(), globalY()
+*/
+
+/*! \internal
+*/
+QHelpEvent::~QHelpEvent()
+{
+}
+
+#ifndef QT_NO_STATUSTIP
+
+/*!
+ \class QStatusTipEvent
+ \brief The QStatusTipEvent class provides an event that is used to show messages in a status bar.
+
+ \ingroup events
+ \ingroup helpsystem
+
+ Status tips can be set on a widget using the
+ QWidget::setStatusTip() function. They are shown in the status
+ bar when the mouse cursor enters the widget. For example:
+
+ \table 100%
+ \row
+ \o
+ \snippet doc/src/snippets/qstatustipevent/main.cpp 1
+ \dots
+ \snippet doc/src/snippets/qstatustipevent/main.cpp 3
+ \o
+ \image qstatustipevent-widget.png Widget with status tip.
+ \endtable
+
+ Status tips can also be set on actions using the
+ QAction::setStatusTip() function:
+
+ \table 100%
+ \row
+ \o
+ \snippet doc/src/snippets/qstatustipevent/main.cpp 0
+ \snippet doc/src/snippets/qstatustipevent/main.cpp 2
+ \dots
+ \snippet doc/src/snippets/qstatustipevent/main.cpp 3
+ \o
+ \image qstatustipevent-action.png Action with status tip.
+ \endtable
+
+ Finally, status tips are supported for the item view classes
+ through the Qt::StatusTipRole enum value.
+
+ \sa QStatusBar, QHelpEvent, QWhatsThisClickedEvent
+*/
+
+/*!
+ Constructs a status tip event with the text specified by \a tip.
+
+ \sa tip()
+*/
+QStatusTipEvent::QStatusTipEvent(const QString &tip)
+ : QEvent(StatusTip), s(tip)
+{}
+
+/*! \internal
+*/
+QStatusTipEvent::~QStatusTipEvent()
+{
+}
+
+/*!
+ \fn QString QStatusTipEvent::tip() const
+
+ Returns the message to show in the status bar.
+
+ \sa QStatusBar::showMessage()
+*/
+
+#endif // QT_NO_STATUSTIP
+
+#ifndef QT_NO_WHATSTHIS
+
+/*!
+ \class QWhatsThisClickedEvent
+ \brief The QWhatsThisClickedEvent class provides an event that
+ can be used to handle hyperlinks in a "What's This?" text.
+
+ \ingroup events
+ \ingroup helpsystem
+
+ \sa QWhatsThis, QHelpEvent, QStatusTipEvent
+*/
+
+/*!
+ Constructs an event containing a URL specified by \a href when a link
+ is clicked in a "What's This?" message.
+
+ \sa href()
+*/
+QWhatsThisClickedEvent::QWhatsThisClickedEvent(const QString &href)
+ : QEvent(WhatsThisClicked), s(href)
+{}
+
+/*! \internal
+*/
+QWhatsThisClickedEvent::~QWhatsThisClickedEvent()
+{
+}
+
+/*!
+ \fn QString QWhatsThisClickedEvent::href() const
+
+ Returns the URL that was clicked by the user in the "What's
+ This?" text.
+*/
+
+#endif // QT_NO_WHATSTHIS
+
+#ifndef QT_NO_ACTION
+
+/*!
+ \class QActionEvent
+ \brief The QActionEvent class provides an event that is generated
+ when a QAction is added, removed, or changed.
+
+ \ingroup events
+
+ Actions can be added to widgets using QWidget::addAction(). This
+ generates an \l ActionAdded event, which you can handle to provide
+ custom behavior. For example, QToolBar reimplements
+ QWidget::actionEvent() to create \l{QToolButton}s for the
+ actions.
+
+ \sa QAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions()
+*/
+
+/*!
+ Constructs an action event. The \a type can be \l ActionChanged,
+ \l ActionAdded, or \l ActionRemoved.
+
+ \a action is the action that is changed, added, or removed. If \a
+ type is ActionAdded, the action is to be inserted before the
+ action \a before. If \a before is 0, the action is appended.
+*/
+QActionEvent::QActionEvent(int type, QAction *action, QAction *before)
+ : QEvent(static_cast<QEvent::Type>(type)), act(action), bef(before)
+{}
+
+/*! \internal
+*/
+QActionEvent::~QActionEvent()
+{
+}
+
+/*!
+ \fn QAction *QActionEvent::action() const
+
+ Returns the action that is changed, added, or removed.
+
+ \sa before()
+*/
+
+/*!
+ \fn QAction *QActionEvent::before() const
+
+ If type() is \l ActionAdded, returns the action that should
+ appear before action(). If this function returns 0, the action
+ should be appended to already existing actions on the same
+ widget.
+
+ \sa action(), QWidget::actions()
+*/
+
+#endif // QT_NO_ACTION
+
+/*!
+ \class QHideEvent
+ \brief The QHideEvent class provides an event which is sent after a widget is hidden.
+
+ \ingroup events
+
+ This event is sent just before QWidget::hide() returns, and also
+ when a top-level window has been hidden (iconified) by the user.
+
+ If spontaneous() is true, the event originated outside the
+ application. In this case, the user hid the window using the
+ window manager controls, either by iconifying the window or by
+ switching to another virtual desktop where the window isn't
+ visible. The window will become hidden but not withdrawn. If the
+ window was iconified, QWidget::isMinimized() returns true.
+
+ \sa QShowEvent
+*/
+
+/*!
+ Constructs a QHideEvent.
+*/
+QHideEvent::QHideEvent()
+ : QEvent(Hide)
+{}
+
+/*! \internal
+*/
+QHideEvent::~QHideEvent()
+{
+}
+
+/*!
+ \class QShowEvent
+ \brief The QShowEvent class provides an event that is sent when a widget is shown.
+
+ \ingroup events
+
+ There are two kinds of show events: show events caused by the
+ window system (spontaneous), and internal show events. Spontaneous (QEvent::spontaneous())
+ show events are sent just after the window system shows the
+ window; they are also sent when a top-level window is redisplayed
+ after being iconified. Internal show events are delivered just
+ before the widget becomes visible.
+
+ \sa QHideEvent
+*/
+
+/*!
+ Constructs a QShowEvent.
+*/
+QShowEvent::QShowEvent()
+ : QEvent(Show)
+{}
+
+/*! \internal
+*/
+QShowEvent::~QShowEvent()
+{
+}
+
+/*!
+ \fn QByteArray QDropEvent::data(const char* f) const
+
+ \obsolete
+
+ The encoded data is in \a f.
+ Use QDropEvent::encodedData().
+*/
+
+/*!
+ \class QFileOpenEvent
+ \brief The QFileOpenEvent class provides an event that will be
+ sent when there is a request to open a file.
+
+ \ingroup events
+
+ File open events will be sent to the QApplication::instance()
+ when the operating system requests that a file be opened. This is
+ a high-level event that can be caused by different user actions
+ depending on the user's desktop environment; for example, double
+ clicking on an file icon in the Finder on Mac OS X.
+
+ This event is only used to notify the application of a request.
+ It may be safely ignored.
+
+ \note This class is currently supported for Mac Os X only.
+*/
+
+/*!
+ \internal
+
+ Constructs a file open event for the given \a file.
+*/
+QFileOpenEvent::QFileOpenEvent(const QString &file)
+ : QEvent(FileOpen), f(file)
+{}
+
+/*! \internal
+*/
+QFileOpenEvent::~QFileOpenEvent()
+{
+}
+
+/*!
+ \fn QString QFileOpenEvent::file() const
+
+ Returns the file that is being opened.
+*/
+
+#ifndef QT_NO_TOOLBAR
+/*!
+ \internal
+ \class QToolBarChangeEvent
+ \brief The QToolBarChangeEvent class provides an event that is
+ sent whenever a the toolbar button is clicked on Mac OS X.
+
+ \ingroup events
+
+ The QToolBarChangeEvent is sent when the toolbar button is clicked. On Mac
+ OS X, this is the long oblong button on the right side of the window
+ title bar. The default implementation is to toggle the appearance (hidden or
+ shown) of the associated toolbars for the window.
+*/
+
+/*!
+ \internal
+
+ Construct a QToolBarChangeEvent given the current button state in \a state.
+*/
+QToolBarChangeEvent::QToolBarChangeEvent(bool t)
+ : QEvent(ToolBarChange), tog(t)
+{}
+
+/*! \internal
+*/
+QToolBarChangeEvent::~QToolBarChangeEvent()
+{
+}
+
+/*!
+ \fn bool QToolBarChangeEvent::toggle() const
+ \internal
+*/
+
+/*
+ \fn Qt::ButtonState QToolBarChangeEvent::state() const
+
+ Returns the keyboard modifier flags at the time of the event.
+
+ The returned value is a selection of the following values,
+ combined using the OR operator:
+ Qt::ShiftButton, Qt::ControlButton, Qt::MetaButton, and Qt::AltButton.
+*/
+
+#endif // QT_NO_TOOLBAR
+
+#ifndef QT_NO_SHORTCUT
+
+/*!
+ Constructs a shortcut event for the given \a key press,
+ associated with the QShortcut ID \a id.
+
+ \a ambiguous specifies whether there is more than one QShortcut
+ for the same key sequence.
+*/
+QShortcutEvent::QShortcutEvent(const QKeySequence &key, int id, bool ambiguous)
+ : QEvent(Shortcut), sequence(key), ambig(ambiguous), sid(id)
+{
+}
+
+/*!
+ Destroys the event object.
+*/
+QShortcutEvent::~QShortcutEvent()
+{
+}
+
+#endif // QT_NO_SHORTCUT
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QEvent *e) {
+#ifndef Q_BROKEN_DEBUG_STREAM
+ // More useful event output could be added here
+ if (!e)
+ return dbg << "QEvent(this = 0x0)";
+ const char *n = 0;
+ switch (e->type()) {
+ case QEvent::Timer:
+ n = "Timer";
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ {
+ const QMouseEvent *me = static_cast<const QMouseEvent*>(e);
+ switch(me->type()) {
+ case QEvent::MouseButtonPress:
+ n = "MouseButtonPress";
+ break;
+ case QEvent::MouseMove:
+ n = "MouseMove";
+ break;
+ case QEvent::MouseButtonRelease:
+ n = "MouseButtonRelease";
+ break;
+ case QEvent::MouseButtonDblClick:
+ default:
+ n = "MouseButtonDblClick";
+ break;
+ }
+ dbg.nospace() << "QMouseEvent(" << n
+ << ", " << me->button()
+ << ", " << hex << (int)me->buttons()
+ << ", " << hex << (int)me->modifiers()
+ << ")";
+ }
+ return dbg.space();
+
+#ifndef QT_NO_TOOLTIP
+ case QEvent::ToolTip:
+ n = "ToolTip";
+ break;
+#endif
+ case QEvent::WindowActivate:
+ n = "WindowActivate";
+ break;
+ case QEvent::WindowDeactivate:
+ n = "WindowDeactivate";
+ break;
+ case QEvent::ActivationChange:
+ n = "ActivationChange";
+ break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ dbg.nospace() << "QWheelEvent(" << static_cast<const QWheelEvent *>(e)->delta()
+ << ")";
+ return dbg.space();
+#endif
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::ShortcutOverride:
+ {
+ const QKeyEvent *ke = static_cast<const QKeyEvent*>(e);
+ switch(ke->type()) {
+ case QEvent::ShortcutOverride:
+ n = "ShortcutOverride";
+ break;
+ case QEvent::KeyRelease:
+ n = "KeyRelease";
+ break;
+ case QEvent::KeyPress:
+ default:
+ n = "KeyPress";
+ break;
+ }
+ dbg.nospace() << "QKeyEvent(" << n
+ << ", " << hex << ke->key()
+ << ", " << hex << (int)ke->modifiers()
+ << ", \"" << ke->text()
+ << "\", " << ke->isAutoRepeat()
+ << ", " << ke->count()
+ << ")";
+ }
+ return dbg.space();
+ case QEvent::FocusIn:
+ n = "FocusIn";
+ break;
+ case QEvent::FocusOut:
+ n = "FocusOut";
+ break;
+ case QEvent::Enter:
+ n = "Enter";
+ break;
+ case QEvent::Leave:
+ n = "Leave";
+ break;
+ case QEvent::PaletteChange:
+ n = "PaletteChange";
+ break;
+ case QEvent::PolishRequest:
+ n = "PolishRequest";
+ break;
+ case QEvent::Polish:
+ n = "Polish";
+ break;
+ case QEvent::UpdateRequest:
+ n = "UpdateRequest";
+ break;
+ case QEvent::Paint:
+ n = "Paint";
+ break;
+ case QEvent::Move:
+ n = "Move";
+ break;
+ case QEvent::Resize:
+ n = "Resize";
+ break;
+ case QEvent::Create:
+ n = "Create";
+ break;
+ case QEvent::Destroy:
+ n = "Destroy";
+ break;
+ case QEvent::Close:
+ n = "Close";
+ break;
+ case QEvent::Quit:
+ n = "Quit";
+ break;
+ case QEvent::FileOpen:
+ n = "FileOpen";
+ break;
+ case QEvent::Show:
+ n = "Show";
+ break;
+ case QEvent::ShowToParent:
+ n = "ShowToParent";
+ break;
+ case QEvent::Hide:
+ n = "Hide";
+ break;
+ case QEvent::HideToParent:
+ n = "HideToParent";
+ break;
+ case QEvent::None:
+ n = "None";
+ break;
+ case QEvent::ParentChange:
+ n = "ParentChange";
+ break;
+ case QEvent::ParentAboutToChange:
+ n = "ParentAboutToChange";
+ break;
+ case QEvent::HoverEnter:
+ n = "HoverEnter";
+ break;
+ case QEvent::HoverMove:
+ n = "HoverMove";
+ break;
+ case QEvent::HoverLeave:
+ n = "HoverLeave";
+ break;
+ case QEvent::ZOrderChange:
+ n = "ZOrderChange";
+ break;
+ case QEvent::StyleChange:
+ n = "StyleChange";
+ break;
+ case QEvent::DragEnter:
+ n = "DragEnter";
+ break;
+ case QEvent::DragMove:
+ n = "DragMove";
+ break;
+ case QEvent::DragLeave:
+ n = "DragLeave";
+ break;
+ case QEvent::Drop:
+ n = "Drop";
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ n = "GraphicsSceneMouseMove";
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ n = "GraphicsSceneMousePress";
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ n = "GraphicsSceneMouseRelease";
+ break;
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ n = "GraphicsSceneMouseDoubleClick";
+ break;
+ case QEvent::GraphicsSceneContextMenu:
+ n = "GraphicsSceneContextMenu";
+ break;
+ case QEvent::GraphicsSceneHoverEnter:
+ n = "GraphicsSceneHoverEnter";
+ break;
+ case QEvent::GraphicsSceneHoverMove:
+ n = "GraphicsSceneHoverMove";
+ break;
+ case QEvent::GraphicsSceneHoverLeave:
+ n = "GraphicsSceneHoverLeave";
+ break;
+ case QEvent::GraphicsSceneHelp:
+ n = "GraphicsSceneHelp";
+ break;
+ case QEvent::GraphicsSceneDragEnter:
+ n = "GraphicsSceneDragEnter";
+ break;
+ case QEvent::GraphicsSceneDragMove:
+ n = "GraphicsSceneDragMove";
+ break;
+ case QEvent::GraphicsSceneDragLeave:
+ n = "GraphicsSceneDragLeave";
+ break;
+ case QEvent::GraphicsSceneDrop:
+ n = "GraphicsSceneDrop";
+ break;
+ case QEvent::GraphicsSceneWheel:
+ n = "GraphicsSceneWheel";
+ break;
+ case QEvent::GraphicsSceneResize:
+ n = "GraphicsSceneResize";
+ break;
+ case QEvent::GraphicsSceneMove:
+ n = "GraphicsSceneMove";
+ break;
+ case QEvent::CursorChange:
+ n = "CursorChange";
+ break;
+ case QEvent::ToolTipChange:
+ n = "ToolTipChange";
+ break;
+ case QEvent::StatusTip:
+ n = "StatusTip";
+ break;
+ case QEvent::WhatsThis:
+ n = "WhatsThis";
+ break;
+ case QEvent::FontChange:
+ n = "FontChange";
+ break;
+ case QEvent::Style:
+ n = "Style";
+ break;
+ case QEvent::KeyboardLayoutChange:
+ n = "KeyboardLayoutChange";
+ break;
+ case QEvent::DynamicPropertyChange:
+ n = "DynamicPropertyChange";
+ break;
+ case QEvent::GrabMouse:
+ n = "GrabMouse";
+ break;
+ case QEvent::UngrabMouse:
+ n = "UngrabMouse";
+ break;
+ case QEvent::GrabKeyboard:
+ n = "GrabKeyboard";
+ break;
+ case QEvent::UngrabKeyboard:
+ n = "UngrabKeyboard";
+ break;
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ n = "ChildInsertedRequest";
+ break;
+ case QEvent::ChildInserted: n = "ChildInserted";
+#endif
+ case QEvent::ChildAdded: n = n ? n : "ChildAdded";
+ case QEvent::ChildPolished: n = n ? n : "ChildPolished";
+ case QEvent::ChildRemoved: n = n ? n : "ChildRemoved";
+ dbg.nospace() << "QChildEvent(" << n << ", " << (static_cast<const QChildEvent*>(e))->child();
+ return dbg.space();
+ default:
+ dbg.nospace() << "QEvent(" << (const void *)e << ", type = " << e->type() << ')';
+ return dbg.space();
+ }
+
+ dbg.nospace() << 'Q' << n << "Event(" << (const void *)e << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QEvent to QDebug");
+ return dbg;
+ Q_UNUSED(e);
+#endif
+}
+#endif
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \class QClipboardEvent
+ \ingroup events
+ \internal
+
+ \brief The QClipboardEvent class provides the parameters used in a clipboard event.
+
+ This class is for internal use only, and exists to aid the clipboard on various
+ platforms to get all the information it needs. Use QEvent::Clipboard instead.
+
+ \sa QClipboard
+*/
+
+QClipboardEvent::QClipboardEvent(QEventPrivate *data)
+ : QEvent(QEvent::Clipboard)
+{
+ d = data;
+}
+
+QClipboardEvent::~QClipboardEvent()
+{
+}
+#endif // QT_NO_CLIPBOARD
+
+/*!
+ \class QShortcutEvent
+ \brief The QShortcutEvent class provides an event which is generated when
+ the user presses a key combination.
+
+ \ingroup events
+
+ Normally you don't need to use this class directly; QShortcut
+ provides a higher-level interface to handle shortcut keys.
+
+ \sa QShortcut
+*/
+
+/*!
+ \fn const QKeySequence &QShortcutEvent::key() const
+
+ Returns the key sequence that triggered the event.
+*/
+
+// ### Qt 5: remove
+/*!
+ \fn const QKeySequence &QShortcutEvent::key()
+
+ \internal
+*/
+
+/*!
+ \fn int QShortcutEvent::shortcutId() const
+
+ Returns the ID of the QShortcut object for which this event was
+ generated.
+
+ \sa QShortcut::id()
+*/
+
+// ### Qt 5: remove
+/*!
+ \fn int QShortcutEvent::shortcutId()
+ \overload
+
+ \internal
+*/
+
+/*!
+ \fn bool QShortcutEvent::isAmbiguous() const
+
+ Returns true if the key sequence that triggered the event is
+ ambiguous.
+
+ \sa QShortcut::activatedAmbiguously()
+*/
+
+// ### Qt 5: remove
+/*!
+ \fn bool QShortcutEvent::isAmbiguous()
+
+ \internal
+*/
+
+/*!
+ \class QWindowStateChangeEvent
+ \ingroup events
+
+ \brief The QWindowStateChangeEvent class provides the window state before a
+ window state change.
+*/
+
+/*! \fn Qt::WindowStates QWindowStateChangeEvent::oldState() const
+
+ Returns the state of the window before the change.
+*/
+
+/*! \internal
+ */
+QWindowStateChangeEvent::QWindowStateChangeEvent(Qt::WindowStates s)
+ : QEvent(WindowStateChange), ostate(s)
+{
+}
+
+/*! \internal
+ */
+QWindowStateChangeEvent::QWindowStateChangeEvent(Qt::WindowStates s, bool isOverride)
+ : QEvent(WindowStateChange), ostate(s)
+{
+ if (isOverride)
+ d = (QEventPrivate*)(this);
+}
+
+/*! \internal
+ */
+bool QWindowStateChangeEvent::isOverride() const
+{
+ return (d != 0);
+}
+
+/*! \internal
+*/
+QWindowStateChangeEvent::~QWindowStateChangeEvent()
+{
+}
+
+#ifdef QT3_SUPPORT
+
+/*!
+ \class QMenubarUpdatedEvent
+ \internal
+ Event sent by QMenuBar to tell Q3Workspace to update itself.
+*/
+
+/*! \internal
+
+*/
+QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar)
+:QEvent(QEvent::MenubarUpdated), m_menuBar(menuBar) {}
+
+/*!
+ \fn QMenuBar *QMenubarUpdatedEvent::menuBar()
+ \internal
+*/
+
+/*!
+ \fn bool operator==(QKeyEvent *e, QKeySequence::StandardKey key)
+
+ \relates QKeyEvent
+
+ Returns true if \a key is currently bound to the key combination
+ specified by \a e.
+
+ Equivalent to \c {e->matches(key)}.
+*/
+
+/*!
+ \fn bool operator==(QKeySequence::StandardKey key, QKeyEvent *e)
+
+ \relates QKeyEvent
+
+ Returns true if \a key is currently bound to the key combination
+ specified by \a e.
+
+ Equivalent to \c {e->matches(key)}.
+*/
+
+/*!
+ \internal
+
+ \class QKeyEventEx
+ \ingroup events
+
+ \brief The QKeyEventEx class provides more extended information about a keyevent.
+
+ This class is for internal use only, and exists to aid the shortcut system on
+ various platforms to get all the information it needs.
+*/
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
new file mode 100644
index 0000000000..449730da2d
--- /dev/null
+++ b/src/gui/kernel/qevent.h
@@ -0,0 +1,726 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENT_H
+#define QEVENT_H
+
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qregion.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qkeysequence.h>
+#include <QtCore/qcoreevent.h>
+#include <QtGui/qmime.h>
+#include <QtGui/qdrag.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QAction;
+
+class Q_GUI_EXPORT QInputEvent : public QEvent
+{
+public:
+ QInputEvent(Type type, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
+ ~QInputEvent();
+ inline Qt::KeyboardModifiers modifiers() const { return modState; }
+protected:
+ Qt::KeyboardModifiers modState;
+};
+
+class Q_GUI_EXPORT QMouseEvent : public QInputEvent
+{
+public:
+ QMouseEvent(Type type, const QPoint &pos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ QMouseEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers);
+ ~QMouseEvent();
+
+ inline const QPoint &pos() const { return p; }
+ inline const QPoint &globalPos() const { return g; }
+ inline int x() const { return p.x(); }
+ inline int y() const { return p.y(); }
+ inline int globalX() const { return g.x(); }
+ inline int globalY() const { return g.y(); }
+ inline Qt::MouseButton button() const { return b; }
+ inline Qt::MouseButtons buttons() const { return mouseState; }
+
+ static QMouseEvent *createExtendedMouseEvent(Type type, const QPointF &pos,
+ const QPoint &globalPos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ inline bool hasExtendedInfo() const { return reinterpret_cast<const QMouseEvent *>(d) == this; }
+ QPointF posF() const;
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QMouseEvent(Type type, const QPoint &pos, Qt::ButtonState button, int state);
+ QT3_SUPPORT_CONSTRUCTOR QMouseEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+ Qt::ButtonState button, int state);
+ inline QT3_SUPPORT Qt::ButtonState state() const
+ { return Qt::ButtonState((mouseState^b)|int(modifiers())); }
+ inline QT3_SUPPORT Qt::ButtonState stateAfter() const
+ { return Qt::ButtonState(int(mouseState)|int(modifiers())); }
+#endif
+protected:
+ QPoint p, g;
+ Qt::MouseButton b;
+ Qt::MouseButtons mouseState;
+};
+
+class Q_GUI_EXPORT QHoverEvent : public QEvent
+{
+public:
+ QHoverEvent(Type type, const QPoint &pos, const QPoint &oldPos);
+ ~QHoverEvent();
+
+ inline const QPoint &pos() const { return p; }
+ inline const QPoint &oldPos() const { return op; }
+
+protected:
+ QPoint p, op;
+};
+
+#ifndef QT_NO_WHEELEVENT
+class Q_GUI_EXPORT QWheelEvent : public QInputEvent
+{
+public:
+ QWheelEvent(const QPoint &pos, int delta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ Qt::Orientation orient = Qt::Vertical);
+ QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ Qt::Orientation orient = Qt::Vertical);
+ ~QWheelEvent();
+
+ inline int delta() const { return d; }
+ inline const QPoint &pos() const { return p; }
+ inline const QPoint &globalPos() const { return g; }
+ inline int x() const { return p.x(); }
+ inline int y() const { return p.y(); }
+ inline int globalX() const { return g.x(); }
+ inline int globalY() const { return g.y(); }
+
+ inline Qt::MouseButtons buttons() const { return mouseState; }
+ Qt::Orientation orientation() const { return o; }
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QWheelEvent(const QPoint &pos, int delta, int state,
+ Qt::Orientation orient = Qt::Vertical);
+ QT3_SUPPORT_CONSTRUCTOR QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, int state,
+ Qt::Orientation orient = Qt::Vertical);
+ inline QT3_SUPPORT Qt::ButtonState state() const
+ { return static_cast<Qt::ButtonState>(int(buttons())|int(modifiers())); }
+#endif
+protected:
+ QPoint p;
+ QPoint g;
+ int d;
+ Qt::MouseButtons mouseState;
+ Qt::Orientation o;
+};
+#endif
+
+#ifndef QT_NO_TABLETEVENT
+class Q_GUI_EXPORT QTabletEvent : public QInputEvent
+{
+public:
+ enum TabletDevice { NoDevice, Puck, Stylus, Airbrush, FourDMouse,
+ XFreeEraser /*internal*/, RotationStylus };
+ enum PointerType { UnknownPointer, Pen, Cursor, Eraser };
+ QTabletEvent(Type t, const QPoint &pos, const QPoint &globalPos, const QPointF &hiResGlobalPos,
+ int device, int pointerType, qreal pressure, int xTilt, int yTilt,
+ qreal tangentialPressure, qreal rotation, int z,
+ Qt::KeyboardModifiers keyState, qint64 uniqueID);
+ ~QTabletEvent();
+
+ inline const QPoint &pos() const { return mPos; }
+ inline const QPoint &globalPos() const { return mGPos; }
+ inline const QPointF &hiResGlobalPos() const { return mHiResGlobalPos; }
+ inline int x() const { return mPos.x(); }
+ inline int y() const { return mPos.y(); }
+ inline int globalX() const { return mGPos.x(); }
+ inline int globalY() const { return mGPos.y(); }
+ inline qreal hiResGlobalX() const { return mHiResGlobalPos.x(); }
+ inline qreal hiResGlobalY() const { return mHiResGlobalPos.y(); }
+ inline TabletDevice device() const { return TabletDevice(mDev); }
+ inline PointerType pointerType() const { return PointerType(mPointerType); }
+ inline qint64 uniqueId() const { return mUnique; }
+ inline qreal pressure() const { return mPress; }
+ inline int z() const { return mZ; }
+ inline qreal tangentialPressure() const { return mTangential; }
+ inline qreal rotation() const { return mRot; }
+ inline int xTilt() const { return mXT; }
+ inline int yTilt() const { return mYT; }
+
+protected:
+ QPoint mPos, mGPos;
+ QPointF mHiResGlobalPos;
+ int mDev, mPointerType, mXT, mYT, mZ;
+ qreal mPress, mTangential, mRot;
+ qint64 mUnique;
+
+ // I don't know what the future holds for tablets but there could be some
+ // new devices coming along, and there seem to be "holes" in the
+ // OS-specific events for this.
+ void *mExtra;
+};
+#endif // QT_NO_TABLETEVENT
+
+class Q_GUI_EXPORT QKeyEvent : public QInputEvent
+{
+public:
+ QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text = QString(),
+ bool autorep = false, ushort count = 1);
+ ~QKeyEvent();
+
+ int key() const { return k; }
+#ifndef QT_NO_SHORTCUT
+ bool matches(QKeySequence::StandardKey key) const;
+#endif
+ Qt::KeyboardModifiers modifiers() const;
+ inline QString text() const { return txt; }
+ inline bool isAutoRepeat() const { return autor; }
+ inline int count() const { return int(c); }
+
+ // Functions for the extended key event information
+ static QKeyEvent *createExtendedKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers,
+ quint32 nativeScanCode, quint32 nativeVirtualKey,
+ quint32 nativeModifiers,
+ const QString& text = QString(), bool autorep = false,
+ ushort count = 1);
+ inline bool hasExtendedInfo() const { return reinterpret_cast<const QKeyEvent*>(d) == this; }
+ quint32 nativeScanCode() const;
+ quint32 nativeVirtualKey() const;
+ quint32 nativeModifiers() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT_CONSTRUCTOR QKeyEvent(Type type, int key, int /*ascii*/,
+ int modifiers, const QString& text = QString(),
+ bool autorep = false, ushort count = 1)
+ : QInputEvent(type, (Qt::KeyboardModifiers)(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key),
+ c(count), autor(autorep)
+ {
+ if (key >= Qt::Key_Back && key <= Qt::Key_MediaLast)
+ ignore();
+ }
+ inline QT3_SUPPORT int ascii() const
+ { return (txt.length() ? txt.unicode()->toLatin1() : 0); }
+ inline QT3_SUPPORT Qt::ButtonState state() const { return Qt::ButtonState(QInputEvent::modifiers()); }
+ inline QT3_SUPPORT Qt::ButtonState stateAfter() const { return Qt::ButtonState(modifiers()); }
+#endif
+
+protected:
+ QString txt;
+ int k;
+ ushort c;
+ uint autor:1;
+};
+
+
+class Q_GUI_EXPORT QFocusEvent : public QEvent
+{
+public:
+ QFocusEvent(Type type, Qt::FocusReason reason=Qt::OtherFocusReason);
+ ~QFocusEvent();
+
+ inline bool gotFocus() const { return type() == FocusIn; }
+ inline bool lostFocus() const { return type() == FocusOut; }
+
+#ifdef QT3_SUPPORT
+ enum Reason { Mouse=Qt::MouseFocusReason, Tab=Qt::TabFocusReason,
+ Backtab=Qt::BacktabFocusReason, MenuBar=Qt::MenuBarFocusReason,
+ ActiveWindow=Qt::ActiveWindowFocusReason, Other=Qt::OtherFocusReason,
+ Popup=Qt::PopupFocusReason, Shortcut=Qt::ShortcutFocusReason };
+#endif
+ Qt::FocusReason reason();
+ Qt::FocusReason reason() const;
+
+private:
+ Qt::FocusReason m_reason;
+};
+
+
+class Q_GUI_EXPORT QPaintEvent : public QEvent
+{
+public:
+ QPaintEvent(const QRegion& paintRegion);
+ QPaintEvent(const QRect &paintRect);
+ ~QPaintEvent();
+
+ inline const QRect &rect() const { return m_rect; }
+ inline const QRegion &region() const { return m_region; }
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QPaintEvent(const QRegion &paintRegion, const QRect &paintRect);
+ inline QT3_SUPPORT bool erased() const { return m_erased; }
+ inline QT3_SUPPORT void setErased(bool b) { m_erased = b; }
+#endif
+
+protected:
+ friend class QApplication;
+ friend class QCoreApplication;
+ QRect m_rect;
+ QRegion m_region;
+ bool m_erased;
+};
+
+class QUpdateLaterEvent : public QEvent
+{
+public:
+ QUpdateLaterEvent(const QRegion& paintRegion);
+ ~QUpdateLaterEvent();
+
+ inline const QRegion &region() const { return m_region; }
+
+protected:
+ QRegion m_region;
+};
+
+class Q_GUI_EXPORT QMoveEvent : public QEvent
+{
+public:
+ QMoveEvent(const QPoint &pos, const QPoint &oldPos);
+ ~QMoveEvent();
+
+ inline const QPoint &pos() const { return p; }
+ inline const QPoint &oldPos() const { return oldp;}
+protected:
+ QPoint p, oldp;
+ friend class QApplication;
+ friend class QCoreApplication;
+};
+
+
+class Q_GUI_EXPORT QResizeEvent : public QEvent
+{
+public:
+ QResizeEvent(const QSize &size, const QSize &oldSize);
+ ~QResizeEvent();
+
+ inline const QSize &size() const { return s; }
+ inline const QSize &oldSize()const { return olds;}
+protected:
+ QSize s, olds;
+ friend class QApplication;
+ friend class QCoreApplication;
+};
+
+
+class Q_GUI_EXPORT QCloseEvent : public QEvent
+{
+public:
+ QCloseEvent();
+ ~QCloseEvent();
+};
+
+
+class Q_GUI_EXPORT QIconDragEvent : public QEvent
+{
+public:
+ QIconDragEvent();
+ ~QIconDragEvent();
+};
+
+
+class Q_GUI_EXPORT QShowEvent : public QEvent
+{
+public:
+ QShowEvent();
+ ~QShowEvent();
+};
+
+
+class Q_GUI_EXPORT QHideEvent : public QEvent
+{
+public:
+ QHideEvent();
+ ~QHideEvent();
+};
+
+#ifndef QT_NO_CONTEXTMENU
+class Q_GUI_EXPORT QContextMenuEvent : public QInputEvent
+{
+public:
+ enum Reason { Mouse, Keyboard, Other };
+
+ QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos,
+ Qt::KeyboardModifiers modifiers);
+ QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos);
+ QContextMenuEvent(Reason reason, const QPoint &pos);
+ ~QContextMenuEvent();
+
+ inline int x() const { return p.x(); }
+ inline int y() const { return p.y(); }
+ inline int globalX() const { return gp.x(); }
+ inline int globalY() const { return gp.y(); }
+
+ inline const QPoint& pos() const { return p; }
+ inline const QPoint& globalPos() const { return gp; }
+
+ inline Reason reason() const { return Reason(reas); }
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos, int);
+ QT3_SUPPORT_CONSTRUCTOR QContextMenuEvent(Reason reason, const QPoint &pos, int);
+
+ QT3_SUPPORT Qt::ButtonState state() const;
+#endif
+protected:
+ QPoint p;
+ QPoint gp;
+ uint reas : 8;
+};
+#endif // QT_NO_CONTEXTMENU
+
+#ifndef QT_NO_INPUTMETHOD
+class Q_GUI_EXPORT QInputMethodEvent : public QEvent
+{
+public:
+ enum AttributeType {
+ TextFormat,
+ Cursor,
+ Language,
+ Ruby
+ };
+ class Attribute {
+ public:
+ Attribute(AttributeType t, int s, int l, QVariant val) : type(t), start(s), length(l), value(val) {}
+ AttributeType type;
+
+ int start;
+ int length;
+ QVariant value;
+ };
+ QInputMethodEvent();
+ QInputMethodEvent(const QString &preeditText, const QList<Attribute> &attributes);
+ void setCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0);
+
+ inline const QList<Attribute> &attributes() const { return attrs; }
+ inline const QString &preeditString() const { return preedit; }
+
+ inline const QString &commitString() const { return commit; }
+ inline int replacementStart() const { return replace_from; }
+ inline int replacementLength() const { return replace_length; }
+
+ QInputMethodEvent(const QInputMethodEvent &other);
+
+private:
+ QString preedit;
+ QList<Attribute> attrs;
+ QString commit;
+ int replace_from;
+ int replace_length;
+};
+#endif // QT_NO_INPUTMETHOD
+
+#ifndef QT_NO_DRAGANDDROP
+
+class QMimeData;
+
+class Q_GUI_EXPORT QDropEvent : public QEvent
+// QT3_SUPPORT
+ , public QMimeSource
+// END QT3_SUPPORT
+{
+public:
+ QDropEvent(const QPoint& pos, Qt::DropActions actions, const QMimeData *data,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = Drop);
+ ~QDropEvent();
+
+ inline const QPoint &pos() const { return p; }
+ inline Qt::MouseButtons mouseButtons() const { return mouseState; }
+ inline Qt::KeyboardModifiers keyboardModifiers() const { return modState; }
+
+ inline Qt::DropActions possibleActions() const { return act; }
+ inline Qt::DropAction proposedAction() const { return default_action; }
+ inline void acceptProposedAction() { drop_action = default_action; accept(); }
+
+ inline Qt::DropAction dropAction() const { return drop_action; }
+ void setDropAction(Qt::DropAction action);
+
+ QWidget* source() const;
+ inline const QMimeData *mimeData() const { return mdata; }
+
+// QT3_SUPPORT
+ const char* format(int n = 0) const;
+ QByteArray encodedData(const char*) const;
+ bool provides(const char*) const;
+// END QT3_SUPPORT
+#ifdef QT3_SUPPORT
+ inline void accept() { QEvent::accept(); }
+ inline QT3_SUPPORT void accept(bool y) { setAccepted(y); }
+ inline QT3_SUPPORT QByteArray data(const char* f) const { return encodedData(f); }
+
+ enum Action { Copy, Link, Move, Private, UserAction = Private };
+ QT3_SUPPORT Action action() const;
+ inline QT3_SUPPORT void acceptAction(bool y = true) { if (y) { drop_action = default_action; accept(); } }
+ inline QT3_SUPPORT void setPoint(const QPoint& np) { p = np; }
+#endif
+
+
+protected:
+ friend class QApplication;
+ QPoint p;
+ Qt::MouseButtons mouseState;
+ Qt::KeyboardModifiers modState;
+ Qt::DropActions act;
+ Qt::DropAction drop_action;
+ Qt::DropAction default_action;
+ const QMimeData *mdata;
+ mutable QList<QByteArray> fmts; // only used for QT3_SUPPORT
+};
+
+
+class Q_GUI_EXPORT QDragMoveEvent : public QDropEvent
+{
+public:
+ QDragMoveEvent(const QPoint &pos, Qt::DropActions actions, const QMimeData *data,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = DragMove);
+ ~QDragMoveEvent();
+
+ inline QRect answerRect() const { return rect; }
+
+ inline void accept() { QDropEvent::accept(); }
+ inline void ignore() { QDropEvent::ignore(); }
+
+ inline void accept(const QRect & r) { accept(); rect = r; }
+ inline void ignore(const QRect & r) { ignore(); rect = r; }
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void accept(bool y) { setAccepted(y); }
+#endif
+
+protected:
+ friend class QApplication;
+ QRect rect;
+};
+
+
+class Q_GUI_EXPORT QDragEnterEvent : public QDragMoveEvent
+{
+public:
+ QDragEnterEvent(const QPoint &pos, Qt::DropActions actions, const QMimeData *data,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ ~QDragEnterEvent();
+};
+
+
+/* An internal class */
+class Q_GUI_EXPORT QDragResponseEvent : public QEvent
+{
+public:
+ QDragResponseEvent(bool accepted);
+ ~QDragResponseEvent();
+
+ inline bool dragAccepted() const { return a; }
+protected:
+ bool a;
+};
+
+
+class Q_GUI_EXPORT QDragLeaveEvent : public QEvent
+{
+public:
+ QDragLeaveEvent();
+ ~QDragLeaveEvent();
+};
+#endif // QT_NO_DRAGANDDROP
+
+
+class Q_GUI_EXPORT QHelpEvent : public QEvent
+{
+public:
+ QHelpEvent(Type type, const QPoint &pos, const QPoint &globalPos);
+ ~QHelpEvent();
+
+ inline int x() const { return p.x(); }
+ inline int y() const { return p.y(); }
+ inline int globalX() const { return gp.x(); }
+ inline int globalY() const { return gp.y(); }
+
+ inline const QPoint& pos() const { return p; }
+ inline const QPoint& globalPos() const { return gp; }
+
+private:
+ QPoint p;
+ QPoint gp;
+};
+
+#ifndef QT_NO_STATUSTIP
+class Q_GUI_EXPORT QStatusTipEvent : public QEvent
+{
+public:
+ QStatusTipEvent(const QString &tip);
+ ~QStatusTipEvent();
+
+ inline QString tip() const { return s; }
+private:
+ QString s;
+};
+#endif
+
+#ifndef QT_NO_WHATSTHIS
+class Q_GUI_EXPORT QWhatsThisClickedEvent : public QEvent
+{
+public:
+ QWhatsThisClickedEvent(const QString &href);
+ ~QWhatsThisClickedEvent();
+
+ inline QString href() const { return s; }
+private:
+ QString s;
+};
+#endif
+
+#ifndef QT_NO_ACTION
+class Q_GUI_EXPORT QActionEvent : public QEvent
+{
+ QAction *act, *bef;
+public:
+ QActionEvent(int type, QAction *action, QAction *before = 0);
+ ~QActionEvent();
+
+ inline QAction *action() const { return act; }
+ inline QAction *before() const { return bef; }
+};
+#endif
+
+class Q_GUI_EXPORT QFileOpenEvent : public QEvent
+{
+public:
+ QFileOpenEvent(const QString &file);
+ ~QFileOpenEvent();
+
+ inline QString file() const { return f; }
+private:
+ QString f;
+};
+
+#ifndef QT_NO_TOOLBAR
+class Q_GUI_EXPORT QToolBarChangeEvent : public QEvent
+{
+public:
+ QToolBarChangeEvent(bool t);
+ ~QToolBarChangeEvent();
+
+ inline bool toggle() const { return tog; }
+private:
+ uint tog : 1;
+};
+#endif
+
+#ifndef QT_NO_SHORTCUT
+class Q_GUI_EXPORT QShortcutEvent : public QEvent
+{
+public:
+ QShortcutEvent(const QKeySequence &key, int id, bool ambiguous = false);
+ ~QShortcutEvent();
+
+ inline const QKeySequence &key() { return sequence; }
+ inline const QKeySequence &key() const { return sequence; }
+ inline int shortcutId() { return sid; }
+ inline int shortcutId() const { return sid; }
+ inline bool isAmbiguous() { return ambig; }
+ inline bool isAmbiguous() const { return ambig; }
+protected:
+ QKeySequence sequence;
+ bool ambig;
+ int sid;
+};
+#endif
+
+#ifndef QT_NO_CLIPBOARD
+class Q_GUI_EXPORT QClipboardEvent : public QEvent
+{
+public:
+ QClipboardEvent(QEventPrivate *data);
+ ~QClipboardEvent();
+
+ QEventPrivate *data() { return d; };
+};
+#endif
+
+class Q_GUI_EXPORT QWindowStateChangeEvent: public QEvent
+{
+public:
+ QWindowStateChangeEvent(Qt::WindowStates aOldState);
+ QWindowStateChangeEvent(Qt::WindowStates aOldState, bool isOverride);
+ ~QWindowStateChangeEvent();
+
+ inline Qt::WindowStates oldState() const { return ostate; }
+ bool isOverride() const;
+
+private:
+ Qt::WindowStates ostate;
+};
+
+#ifdef QT3_SUPPORT
+class QMenuBar;
+class Q_GUI_EXPORT QMenubarUpdatedEvent: public QEvent
+{
+public:
+ QMenubarUpdatedEvent(QMenuBar * const menBar);
+ inline QMenuBar *menuBar() { return m_menuBar; }
+private:
+ QMenuBar *m_menuBar;
+};
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *);
+#endif
+
+#ifndef QT_NO_SHORTCUT
+inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? e->matches(key) : false);}
+inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
+#endif // QT_NO_SHORTCUT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QEVENT_H
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
new file mode 100644
index 0000000000..cc94aade58
--- /dev/null
+++ b/src/gui/kernel/qevent_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENT_P_H
+#define QEVENT_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// ### Qt 5: remove
+class Q_GUI_EXPORT QKeyEventEx : public QKeyEvent
+{
+public:
+ QKeyEventEx(Type type, int key, Qt::KeyboardModifiers modifiers,
+ const QString &text, bool autorep, ushort count,
+ quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers);
+ QKeyEventEx(const QKeyEventEx &other);
+
+ ~QKeyEventEx();
+
+protected:
+ quint32 nScanCode;
+ quint32 nVirtualKey;
+ quint32 nModifiers;
+ friend class QKeyEvent;
+};
+
+// ### Qt 5: remove
+class Q_GUI_EXPORT QMouseEventEx : public QMouseEvent
+{
+public:
+ QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers);
+ ~QMouseEventEx();
+
+protected:
+ QPointF posF;
+ friend class QMouseEvent;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qeventdispatcher_glib_qws.cpp b/src/gui/kernel/qeventdispatcher_glib_qws.cpp
new file mode 100644
index 0000000000..1e740c3f69
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_glib_qws.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_glib_qws_p.h"
+
+#include "qapplication.h"
+
+#include "qplatformdefs.h"
+#include "qapplication.h"
+#include "private/qwscommand_qws_p.h"
+#include "qwsdisplay_qws.h"
+#include "qwsevent_qws.h"
+#include "qwindowsystem_qws.h"
+
+#include <glib.h>
+
+QT_BEGIN_NAMESPACE
+
+// from qapplication_qws.cpp
+extern QWSDisplay* qt_fbdpy; // QWS `display'
+
+//from qwindowsystem_qws.cpp
+extern QList<QWSCommand*> *qt_get_server_queue();
+
+struct GQWSEventSource
+{
+ GSource source;
+ QEventLoop::ProcessEventsFlags flags;
+ QWSEventDispatcherGlib *q;
+ QWSEventDispatcherGlibPrivate *d;
+};
+
+class QWSEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
+{
+ Q_DECLARE_PUBLIC(QWSEventDispatcherGlib)
+
+public:
+ QWSEventDispatcherGlibPrivate();
+ GQWSEventSource *qwsEventSource;
+ QList<QWSEvent*> queuedUserInputEvents;
+};
+
+static gboolean qwsEventSourcePrepare(GSource *s, gint *timeout)
+{
+ if (timeout)
+ *timeout = -1;
+ GQWSEventSource *source = reinterpret_cast<GQWSEventSource *>(s);
+ return qt_fbdpy->eventPending() || !source->d->queuedUserInputEvents.isEmpty()
+ || !qt_get_server_queue()->isEmpty() ;
+}
+
+static gboolean qwsEventSourceCheck(GSource *s)
+{
+ GQWSEventSource *source = reinterpret_cast<GQWSEventSource *>(s);
+ return qt_fbdpy->eventPending() || !source->d->queuedUserInputEvents.isEmpty()
+ || !qt_get_server_queue()->isEmpty() ;
+}
+
+static gboolean qwsEventSourceDispatch(GSource *s, GSourceFunc callback, gpointer user_data)
+{
+ GQWSEventSource *source = reinterpret_cast<GQWSEventSource *>(s);
+
+ //??? ulong marker = XNextRequest(X11->display);
+ do {
+ QWSEvent *event;
+ if (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ event = source->d->queuedUserInputEvents.takeFirst();
+ } else if (qt_fbdpy->eventPending()) {
+ event = qt_fbdpy->getEvent();
+
+ if (source->flags & QEventLoop::ExcludeUserInputEvents) {
+ // queue user input events
+
+ if (event->type == QWSEvent::Mouse || event->type == QWSEvent::Key) {
+ source->d->queuedUserInputEvents.append(event);
+ continue;
+ }
+ }
+ } else {
+ // no event to process
+ break;
+ }
+
+ // send through event filter
+ if (source->q->filterEvent(event)) {
+ delete event;
+ continue;
+ }
+
+ bool ret = qApp->qwsProcessEvent(event) == 1;
+ delete event;
+ if (ret) {
+ return true;
+ }
+
+ } while (qt_fbdpy->eventPending());
+
+ if (callback)
+ callback(user_data);
+ return true;
+}
+
+static GSourceFuncs qwsEventSourceFuncs = {
+ qwsEventSourcePrepare,
+ qwsEventSourceCheck,
+ qwsEventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+QWSEventDispatcherGlibPrivate::QWSEventDispatcherGlibPrivate()
+{
+ qwsEventSource = reinterpret_cast<GQWSEventSource *>(g_source_new(&qwsEventSourceFuncs,
+ sizeof(GQWSEventSource)));
+ g_source_set_can_recurse(&qwsEventSource->source, true);
+
+ qwsEventSource->flags = QEventLoop::AllEvents;
+ qwsEventSource->q = 0;
+ qwsEventSource->d = 0;
+
+ g_source_attach(&qwsEventSource->source, mainContext);
+}
+
+QWSEventDispatcherGlib::QWSEventDispatcherGlib(QObject *parent)
+ : QEventDispatcherGlib(*new QWSEventDispatcherGlibPrivate, parent)
+{
+}
+
+QWSEventDispatcherGlib::~QWSEventDispatcherGlib()
+{
+ Q_D(QWSEventDispatcherGlib);
+
+ g_source_destroy(&d->qwsEventSource->source);
+ d->qwsEventSource = 0;
+}
+
+bool QWSEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QWSEventDispatcherGlib);
+ QEventLoop::ProcessEventsFlags saved_flags = d->qwsEventSource->flags;
+ d->qwsEventSource->flags = flags;
+ bool returnValue = QEventDispatcherGlib::processEvents(flags);
+ d->qwsEventSource->flags = saved_flags;
+ return returnValue;
+}
+
+void QWSEventDispatcherGlib::startingUp()
+{
+ Q_D(QWSEventDispatcherGlib);
+ d->qwsEventSource->q = this;
+ d->qwsEventSource->d = d;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_glib_qws_p.h b/src/gui/kernel/qeventdispatcher_glib_qws_p.h
new file mode 100644
index 0000000000..1589aef687
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_glib_qws_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSEVENTDISPATCHER_GLIB_P_H
+#define QWSEVENTDISPATCHER_GLIB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qeventdispatcher_glib_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSEventDispatcherGlibPrivate;
+
+class QWSEventDispatcherGlib : public QEventDispatcherGlib
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWSEventDispatcherGlib)
+
+public:
+ explicit QWSEventDispatcherGlib(QObject *parent = 0);
+ ~QWSEventDispatcherGlib();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+
+ void startingUp();
+};
+
+QT_END_NAMESPACE
+
+#endif // QWSEVENTDISPATCHER_GLIB_P_H
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
new file mode 100644
index 0000000000..e28f170666
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -0,0 +1,926 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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 "qplatformdefs.h"
+#include "private/qt_mac_p.h"
+#include "qeventdispatcher_mac_p.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qdialog.h"
+#include "qhash.h"
+#include "qsocketnotifier.h"
+#include "private/qwidget_p.h"
+#include "private/qthread_p.h"
+#include "private/qapplication_p.h"
+
+#include <private/qcocoaapplication_mac_p.h>
+#include "private/qt_cocoa_helpers_mac_p.h"
+
+#ifndef QT_NO_THREAD
+# include "qmutex.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+#endif
+
+/*****************************************************************************
+ Externals
+ *****************************************************************************/
+extern void qt_event_request_timer(MacTimerInfo *); //qapplication_mac.cpp
+extern MacTimerInfo *qt_event_get_timer(EventRef); //qapplication_mac.cpp
+extern void qt_event_request_select(QEventDispatcherMac *); //qapplication_mac.cpp
+extern void qt_event_request_updates(); //qapplication_mac.cpp
+extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp
+extern bool qt_is_gui_used; //qapplication.cpp
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
+extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp
+
+static inline CFRunLoopRef mainRunLoop()
+{
+#ifndef QT_MAC_USE_COCOA
+ return reinterpret_cast<CFRunLoopRef>(const_cast<void *>(GetCFRunLoopFromEventLoop(GetMainEventLoop())));
+#else
+ return CFRunLoopGetMain();
+#endif
+}
+
+/*****************************************************************************
+ Timers stuff
+ *****************************************************************************/
+
+/* timer call back */
+void QEventDispatcherMacPrivate::activateTimer(CFRunLoopTimerRef, void *info)
+{
+ int timerID =
+#ifdef Q_OS_MAC64
+ qint64(info);
+#else
+ int(info);
+#endif
+
+ MacTimerInfo *tmr;
+ tmr = macTimerHash.value(timerID);
+ if (tmr == 0 || tmr->pending == true)
+ return; // Can't send another timer event if it's pending.
+
+ tmr->pending = true;
+ QTimerEvent e(tmr->id);
+ qt_sendSpontaneousEvent(tmr->obj, &e);
+
+ // Get the value again in case the timer gets unregistered during the sendEvent.
+ tmr = macTimerHash.value(timerID);
+ if (tmr != 0)
+ tmr->pending = false;
+}
+
+void QEventDispatcherMac::registerTimer(int timerId, int interval, QObject *obj)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1 || interval < 0 || !obj) {
+ qWarning("QEventDispatcherMac::registerTimer: invalid arguments");
+ return;
+ } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+#endif
+
+ MacTimerInfo *t = new MacTimerInfo();
+ t->id = timerId;
+ t->interval = interval;
+ t->obj = obj;
+ t->runLoopTimer = 0;
+ t->pending = false;
+
+ CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent();
+ CFTimeInterval cfinterval = qMax(CFTimeInterval(interval) / 1000, 0.0000001);
+ fireDate += cfinterval;
+ QEventDispatcherMacPrivate::macTimerHash.insert(timerId, t);
+ CFRunLoopTimerContext info = { 0, (void *)timerId, 0, 0, 0 };
+ t->runLoopTimer = CFRunLoopTimerCreate(0, fireDate, cfinterval, 0, 0,
+ QEventDispatcherMacPrivate::activateTimer, &info);
+ if (t->runLoopTimer == 0) {
+ qFatal("QEventDispatcherMac::registerTimer: Cannot create timer");
+ }
+ CFRunLoopAddTimer(mainRunLoop(), t->runLoopTimer, kCFRunLoopCommonModes);
+}
+
+bool QEventDispatcherMac::unregisterTimer(int identifier)
+{
+#ifndef QT_NO_DEBUG
+ if (identifier < 1) {
+ qWarning("QEventDispatcherMac::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+ if (identifier <= 0)
+ return false; // not init'd or invalid timer
+
+ MacTimerInfo *timerInfo = QEventDispatcherMacPrivate::macTimerHash.take(identifier);
+ if (timerInfo == 0)
+ return false;
+
+ if (!QObjectPrivate::get(timerInfo->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(identifier);
+ CFRunLoopTimerInvalidate(timerInfo->runLoopTimer);
+ CFRelease(timerInfo->runLoopTimer);
+ delete timerInfo;
+
+ return true;
+}
+
+bool QEventDispatcherMac::unregisterTimers(QObject *obj)
+{
+#ifndef QT_NO_DEBUG
+ if (!obj) {
+ qWarning("QEventDispatcherMac::unregisterTimers: invalid argument");
+ return false;
+ } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ MacTimerHash::iterator it = QEventDispatcherMacPrivate::macTimerHash.begin();
+ while (it != QEventDispatcherMacPrivate::macTimerHash.end()) {
+ MacTimerInfo *timerInfo = it.value();
+ if (timerInfo->obj != obj) {
+ ++it;
+ } else {
+ if (!QObjectPrivate::get(timerInfo->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(timerInfo->id);
+ CFRunLoopTimerInvalidate(timerInfo->runLoopTimer);
+ CFRelease(timerInfo->runLoopTimer);
+ delete timerInfo;
+ it = QEventDispatcherMacPrivate::macTimerHash.erase(it);
+ }
+ }
+ return true;
+}
+
+QList<QEventDispatcherMac::TimerInfo>
+QEventDispatcherMac::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherMac:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ QList<TimerInfo> list;
+
+ MacTimerHash::const_iterator it = QEventDispatcherMacPrivate::macTimerHash.constBegin();
+ while (it != QEventDispatcherMacPrivate::macTimerHash.constEnd()) {
+ MacTimerInfo *t = it.value();
+ if (t->obj == object)
+ list << TimerInfo(t->id, t->interval);
+ ++it;
+ }
+ return list;
+}
+
+/**************************************************************************
+ Socket Notifiers
+ *************************************************************************/
+void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef,
+ const void *, void *info) {
+ QEventDispatcherMacPrivate *const eventDispatcher
+ = static_cast<QEventDispatcherMacPrivate *>(info);
+ int nativeSocket = CFSocketGetNative(s);
+ MacSocketInfo *socketInfo = eventDispatcher->macSockets.value(nativeSocket);
+ QEvent notifierEvent(QEvent::SockAct);
+ if (callbackType == kCFSocketReadCallBack) {
+ Q_ASSERT(socketInfo->readNotifier);
+ QApplication::sendEvent(socketInfo->readNotifier, &notifierEvent);
+ } else if (callbackType == kCFSocketWriteCallBack) {
+ // ### Bug in Apple socket notifiers seems to send write even
+ // ### after the notifier has been disabled, need to investigate further.
+ if (socketInfo->writeNotifier)
+ QApplication::sendEvent(socketInfo->writeNotifier, &notifierEvent);
+ }
+}
+
+/*
+ Adds a loop source for the given socket to the current run loop.
+*/
+CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
+{
+ CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
+ if (!loopSource)
+ return 0;
+
+ CFRunLoopAddSource(mainRunLoop(), loopSource, kCFRunLoopCommonModes);
+ return loopSource;
+}
+
+/*
+ Removes the loop source for the given socket from the current run loop.
+*/
+void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
+{
+ Q_ASSERT(runloop);
+ CFRunLoopRemoveSource(mainRunLoop(), runloop, kCFRunLoopCommonModes);
+ CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
+ CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
+ CFRunLoopSourceInvalidate(runloop);
+}
+
+/*
+ Register a QSocketNotifier with the mac event system by creating a CFSocket with
+ with a read/write callback.
+
+ Qt has separate socket notifiers for reading and writing, but on the mac there is
+ a limitation of one CFSocket object for each native socket.
+*/
+void QEventDispatcherMac::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int nativeSocket = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherMac);
+
+ if (type == QSocketNotifier::Exception) {
+ qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
+ return;
+ }
+
+ // Check if we have a CFSocket for the native socket, create one if not.
+ MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
+ if (!socketInfo) {
+ socketInfo = new MacSocketInfo();
+
+ // Create CFSocket, specify that we want both read and write callbacks (the callbacks
+ // are enabled/disabled later on).
+ const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
+ CFSocketContext context = {0, d, 0, 0, 0};
+ socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
+ if (CFSocketIsValid(socketInfo->socket) == false) {
+ qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
+ return;
+ }
+
+ CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
+ flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write
+ flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation
+ CFSocketSetSocketFlags(socketInfo->socket, flags);
+
+ // Add CFSocket to runloop.
+ if(!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
+ qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
+ CFSocketInvalidate(socketInfo->socket);
+ CFRelease(socketInfo->socket);
+ return;
+ }
+
+ // Disable both callback types by default. This must be done after
+ // we add the CFSocket to the runloop, or else these calls will have
+ // no effect.
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
+
+ d->macSockets.insert(nativeSocket, socketInfo);
+ }
+
+ // Increment read/write counters and select enable callbacks if necessary.
+ if (type == QSocketNotifier::Read) {
+ Q_ASSERT(socketInfo->readNotifier == 0);
+ socketInfo->readNotifier = notifier;
+ CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
+ } else if (type == QSocketNotifier::Write) {
+ Q_ASSERT(socketInfo->writeNotifier == 0);
+ socketInfo->writeNotifier = notifier;
+ CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
+ }
+}
+
+/*
+ Unregister QSocketNotifer. The CFSocket correspoding to this notifier is
+ removed from the runloop of this is the last notifier that users
+ that CFSocket.
+*/
+void QEventDispatcherMac::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int nativeSocket = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherMac);
+
+ if (type == QSocketNotifier::Exception) {
+ qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
+ return;
+ }
+ MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
+ if (!socketInfo) {
+ qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
+ return;
+ }
+
+ // Decrement read/write counters and disable callbacks if necessary.
+ if (type == QSocketNotifier::Read) {
+ Q_ASSERT(notifier == socketInfo->readNotifier);
+ socketInfo->readNotifier = 0;
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
+ } else if (type == QSocketNotifier::Write) {
+ Q_ASSERT(notifier == socketInfo->writeNotifier);
+ socketInfo->writeNotifier = 0;
+ CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
+ }
+
+ // Remove CFSocket from runloop if this was the last QSocketNotifier.
+ if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) {
+ if (CFSocketIsValid(socketInfo->socket))
+ qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
+ CFRunLoopSourceInvalidate(socketInfo->runloop);
+ CFRelease(socketInfo->runloop);
+ CFSocketInvalidate(socketInfo->socket);
+ CFRelease(socketInfo->socket);
+ delete socketInfo;
+ d->macSockets.remove(nativeSocket);
+ }
+}
+
+bool QEventDispatcherMac::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount();
+ return qGlobalPostedEventsCount() || (qt_is_gui_used && GetNumEventsInQueue(GetMainEventQueue()));
+}
+
+
+static bool qt_mac_send_event(QEventLoop::ProcessEventsFlags, OSEventRef event, OSWindowRef pt)
+{
+#ifndef QT_MAC_USE_COCOA
+ if(pt && SendEventToWindow(event, pt) != eventNotHandledErr)
+ return true;
+ return !SendEventToEventTarget(event, GetEventDispatcherTarget());
+#else // QT_MAC_USE_COCOA
+ if (pt)
+ [pt sendEvent:event];
+ else
+ [NSApp sendEvent:event];
+ return true;
+#endif
+}
+
+#ifdef QT_MAC_USE_COCOA
+static bool IsMouseOrKeyEvent( NSEvent* event )
+{
+ bool result = false;
+
+ switch( [event type] )
+ {
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSMouseMoved: // ??
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSMouseEntered:
+ case NSMouseExited:
+ case NSKeyDown:
+ case NSKeyUp:
+ case NSFlagsChanged: // key modifiers changed?
+ case NSCursorUpdate: // ??
+ case NSScrollWheel:
+ case NSTabletPoint:
+ case NSTabletProximity:
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSOtherMouseDragged:
+ result = true;
+ break;
+
+ default:
+ break;
+ }
+ return result;
+}
+#endif
+
+bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherMac);
+ d->interrupt = false;
+ // In case we end up recursing while we now process events, make sure
+ // that we send remaining posted Qt events before this call returns:
+ wakeUp();
+ emit awake();
+
+#ifndef QT_MAC_NO_QUICKDRAW
+ if(!qt_mac_safe_pdev) { //create an empty widget and this can be used for a port anytime
+ QWidget *tlw = new QWidget;
+ tlw->setAttribute(Qt::WA_DeleteOnClose);
+ tlw->setObjectName(QLatin1String("empty_widget"));
+ tlw->hide();
+ qt_mac_safe_pdev = tlw;
+ }
+#endif
+
+ bool retVal = false;
+ forever {
+ if (d->interrupt)
+ break;
+
+#ifdef QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ NSEvent* event = 0;
+
+ if (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec) {
+ // The point of the CocoaRequestModal event is to make sure that a
+ // non-execed app modal window recurses into it's own dialog exec
+ // once cocoa is spinning the event loop for us (e.g on top of [NSApp run]).
+ // We expect only one event to notify us about this, regardless of how many
+ // widgets that are waiting to be modal. So we remove all other pending
+ // events, if any. And since cocoa will now take over event processing for us,
+ // we allow new app modal widgets to recurse on top of us, hence the release of
+ // the block:
+ QBoolBlocker block(d->blockCocoaRequestModal, false);
+ QCoreApplication::removePostedEvents(qApp, QEvent::CocoaRequestModal);
+
+ if (NSModalSession session = d->activeModalSession())
+ while ([NSApp runModalSession:session] == NSRunContinuesResponse) {
+ // runModalSession will not wait for events, so we do it
+ // ourselves (otherwise we would spend 100% CPU inside this loop):
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture] inMode:NSModalPanelRunLoopMode dequeue:YES];
+ if (event)
+ [NSApp postEvent:event atStart:YES];
+ }
+ else
+ [NSApp run];
+
+ d->rebuildModalSessionStack(false);
+ retVal = true;
+ } else do {
+ // Since we now are going to spin the event loop just _one_ round
+ // we need to block all incoming CocoaRequestModal events to ensure
+ // that we don't recurse into a new exec-ing event loop while doing
+ // so (and as such, 'hang' the thread inside the recursion):
+ QBoolBlocker block(d->blockCocoaRequestModal, true);
+ bool mustRelease = false;
+
+ if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ mustRelease = true;
+ event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
+ } else {
+ if (NSModalSession session = d->activeModalSession()) {
+ // There's s a modal widget showing, run it's session:
+ if (flags & QEventLoop::WaitForMoreEvents) {
+ // Wait for at least one event
+ // before spinning the session:
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture] inMode:NSModalPanelRunLoopMode dequeue:YES];
+ if (event)
+ [NSApp postEvent:event atStart:YES];
+ }
+ [NSApp runModalSession:session];
+ retVal = true;
+ break;
+ } else {
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:nil
+ inMode:NSDefaultRunLoopMode
+ dequeue: YES];
+
+ if (event != nil) {
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ if (IsMouseOrKeyEvent(event)) {
+ // retain event here?
+ [event retain];
+ d->queuedUserInputEvents.append(event);
+ continue;
+ }
+ }
+ }
+ }
+ }
+ if (event) {
+ if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
+ retVal = true;
+ if (mustRelease)
+ [event release];
+ }
+ } while(!d->interrupt && event != nil);
+
+#else
+ do {
+ EventRef event;
+ if (!(flags & QEventLoop::ExcludeUserInputEvents)
+ && !d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ event = static_cast<EventRef>(d->queuedUserInputEvents.takeFirst());
+ } else {
+ OSStatus err = ReceiveNextEvent(0,0, kEventDurationNoWait, true, &event);
+ if(err != noErr)
+ continue;
+ // else
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ UInt32 ekind = GetEventKind(event),
+ eclass = GetEventClass(event);
+ switch(eclass) {
+ case kEventClassQt:
+ if(ekind != kEventQtRequestContext)
+ break;
+ // fall through
+ case kEventClassMouse:
+ case kEventClassKeyboard:
+ d->queuedUserInputEvents.append(event);
+ continue;
+ }
+ }
+ }
+
+ if (!filterEvent(&event) && qt_mac_send_event(flags, event, 0))
+ retVal = true;
+ ReleaseEvent(event);
+ } while(!d->interrupt && GetNumEventsInQueue(GetMainEventQueue()) > 0);
+
+#endif
+
+ bool canWait = (d->threadData->canWait
+ && !retVal
+ && !d->interrupt
+ && (flags & QEventLoop::WaitForMoreEvents));
+ if (canWait) {
+ // INVARIANT: We haven't processed any events yet. And we're told
+ // to stay inside this function until at least one event is processed
+ // (WaitForMoreEvents). So we wait on the window server:
+#ifndef QT_MAC_USE_COCOA
+ while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut);
+#else
+ QMacCocoaAutoReleasePool pool;
+ NSEvent *manualEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (manualEvent)
+ [NSApp sendEvent:manualEvent];
+#endif
+ flags &= ~QEventLoop::WaitForMoreEvents;
+ } else {
+ // Done with event processing for now. Leave the function:
+ break;
+ }
+ }
+
+ // Because pending deffered-delete events are only sendt after
+ // returning from the loop level they were posted in, we schedule
+ // an extra wakup to force the _current_ run loop to process them (in
+ // case the application stands idle waiting for the delete event):
+ wakeUp();
+
+ if (d->interrupt){
+ // We restart NSApplication by first stopping it, and then call 'run'
+ // again (NSApplication is actually already stopped, hence the need
+ // for a restart, but calling stop again will also make the call
+ // return from the current recursion). When the call returns to
+ // QEventLoop (mind, not from this recursion, but from the one we're
+ // about to stop), it will just call QEventDispatcherMac::processEvents()
+ // again.
+ interrupt();
+ }
+ return retVal;
+}
+
+void QEventDispatcherMac::wakeUp()
+{
+ Q_D(QEventDispatcherMac);
+ d->serialNumber.ref();
+ CFRunLoopSourceSignal(d->postedEventsSource);
+ CFRunLoopWakeUp(mainRunLoop());
+}
+
+void QEventDispatcherMac::flush()
+{
+ if(qApp) {
+ QWidgetList tlws = QApplication::topLevelWidgets();
+ for(int i = 0; i < tlws.size(); i++) {
+ QWidget *tlw = tlws.at(i);
+ if(tlw->isVisible())
+ macWindowFlush(qt_mac_window_for(tlw));
+ }
+ }
+}
+
+/*****************************************************************************
+ QEventDispatcherMac Implementation
+ *****************************************************************************/
+MacTimerHash QEventDispatcherMacPrivate::macTimerHash;
+bool QEventDispatcherMacPrivate::blockSendPostedEvents = false;
+
+#ifdef QT_MAC_USE_COCOA
+QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack;
+bool QEventDispatcherMacPrivate::blockCocoaRequestModal = false;
+
+static void qt_mac_setChildDialogsResponsive(QWidget *widget, bool responsive)
+{
+ QList<QDialog *> dialogs = widget->findChildren<QDialog *>();
+ for (int i=0; i<dialogs.size(); ++i){
+ NSWindow *window = qt_mac_window_for(dialogs[i]);
+ if (window && [window isKindOfClass:[NSPanel class]]) {
+ [static_cast<NSPanel *>(window) setWorksWhenModal:responsive];
+ if (responsive && dialogs[i]->isVisible()){
+ [window orderFront:window];
+ }
+ }
+ }
+}
+
+NSModalSession QEventDispatcherMacPrivate::activeModalSession()
+{
+ // Create (if needed) and return the modal session
+ // for the top-most modal dialog, if any:
+ if (cocoaModalSessionStack.isEmpty())
+ return 0;
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack.last();
+ if (!info.widget)
+ return 0;
+ if (info.widget->testAttribute(Qt::WA_DontShowOnScreen)){
+ // INVARIANT: We have a modal widget, but it's not visible on screen.
+ // This will e.g. be true for native dialogs. Make the dialog children
+ // of the previous modal dialog unresponsive, so that the current dialog
+ // (native or not) is the only reponsive dialog on screen:
+ int size = cocoaModalSessionStack.size();
+ if (size > 1){
+ if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget)
+ qt_mac_setChildDialogsResponsive(prevModal, false);
+ }
+ return 0;
+ }
+
+ if (!info.session) {
+ QMacCocoaAutoReleasePool pool;
+ NSWindow *window = qt_mac_window_for(info.widget);
+ if (!window)
+ return 0;
+ // 'beginModalSessionForWindow' will give the event loop a spin, and as
+ // such, deliver Qt events. This might lead to inconsistent behaviour
+ // (especially if CocoaRequestModal is delivered), so we need to block:
+ QBoolBlocker block(blockSendPostedEvents, true);
+ info.session = [NSApp beginModalSessionForWindow:window];
+ // Make the dialog children of the current modal dialog
+ // responsive. And make the dialog children of
+ // the previous modal dialog unresponsive again:
+ qt_mac_setChildDialogsResponsive(info.widget, true);
+ int size = cocoaModalSessionStack.size();
+ if (size > 1){
+ if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget)
+ qt_mac_setChildDialogsResponsive(prevModal, false);
+ }
+ }
+ return info.session;
+}
+
+void QEventDispatcherMacPrivate::rebuildModalSessionStack(bool pop)
+{
+ // Calling [NSApp stopModal], or [NSApp stop], will stop all modal dialogs
+ // in one go. So to to not confuse cocoa, we need to stop all our modal
+ // sessions as well. QMacEventDispatcher will make them modal again
+ // in the correct order as long as they are left on the cocoaModalSessionStack
+ // and a CocoaRequestModal is posted:
+ if (cocoaModalSessionStack.isEmpty())
+ return;
+
+ QMacCocoaAutoReleasePool pool;
+ [NSApp stopModal];
+ [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ subtype:SHRT_MAX data1:0 data2:0] atStart:NO];
+
+ for (int i=0; i<cocoaModalSessionStack.size(); ++i){
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.session) {
+ [NSApp endModalSession:info.session];
+ info.session = 0;
+ }
+ }
+
+ if (pop) {
+ QCocoaModalSessionInfo info = cocoaModalSessionStack.pop();
+ if (info.widget)
+ qt_mac_setChildDialogsResponsive(info.widget, false);
+ }
+
+ if (!cocoaModalSessionStack.isEmpty()) {
+ // Since we now have pending modal sessions again, make
+ // sure that we enter modal for the one on the top later:
+ qApp->postEvent(qApp, new QEvent(QEvent::CocoaRequestModal));
+ } else {
+ QCoreApplication::removePostedEvents(qApp, QEvent::CocoaRequestModal);
+ }
+}
+
+#endif
+
+QEventDispatcherMacPrivate::QEventDispatcherMacPrivate()
+ : interrupt(false)
+{
+}
+
+QEventDispatcherMac::QEventDispatcherMac(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherMacPrivate, parent)
+{
+ Q_D(QEventDispatcherMac);
+ CFRunLoopSourceContext context;
+ bzero(&context, sizeof(CFRunLoopSourceContext));
+ context.info = d;
+ context.equal = QEventDispatcherMacPrivate::postedEventSourceEqualCallback;
+ context.perform = QEventDispatcherMacPrivate::postedEventsSourcePerformCallback;
+ d->postedEventsSource = CFRunLoopSourceCreate(0, 0, &context);
+ Q_ASSERT(d->postedEventsSource);
+ CFRunLoopAddSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes);
+
+ CFRunLoopObserverContext observerContext;
+ bzero(&observerContext, sizeof(CFRunLoopObserverContext));
+ observerContext.info = this;
+ d->waitingObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
+ kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting,
+ true, 0,
+ QEventDispatcherMacPrivate::waitingObserverCallback,
+ &observerContext);
+ CFRunLoopAddObserver(mainRunLoop(), d->waitingObserver, kCFRunLoopCommonModes);
+}
+
+void QEventDispatcherMacPrivate::waitingObserverCallback(CFRunLoopObserverRef,
+ CFRunLoopActivity activity, void *info)
+{
+ if (activity == kCFRunLoopBeforeWaiting)
+ emit static_cast<QEventDispatcherMac*>(info)->aboutToBlock();
+ else
+ emit static_cast<QEventDispatcherMac*>(info)->awake();
+}
+
+Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *info1, const void *info2)
+{
+ return info1 == info2;
+}
+
+void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
+{
+ QEventDispatcherMacPrivate *d = static_cast<QEventDispatcherMacPrivate *>(info);
+ if (blockSendPostedEvents) {
+ CFRunLoopSourceSignal(d->postedEventsSource);
+ } else {
+ if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
+ d->lastSerial = d->serialNumber;
+ QApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ }
+ }
+}
+
+#ifdef QT_MAC_USE_COCOA
+static void stopNSApp()
+{
+ QMacCocoaAutoReleasePool pool;
+ static const short NSAppShouldStopForQt = SHRT_MAX;
+ [NSApp stop:NSApp];
+ [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO];
+}
+#endif
+
+void QEventDispatcherMac::interrupt()
+{
+ Q_D(QEventDispatcherMac);
+ d->interrupt = true;
+ wakeUp();
+#ifndef QT_MAC_USE_COCOA
+ CFRunLoopStop(mainRunLoop());
+#else
+ stopNSApp();
+#endif
+}
+
+QEventDispatcherMac::~QEventDispatcherMac()
+{
+ Q_D(QEventDispatcherMac);
+ //timer cleanup
+ MacTimerHash::iterator it = QEventDispatcherMacPrivate::macTimerHash.begin();
+ while (it != QEventDispatcherMacPrivate::macTimerHash.end()) {
+ MacTimerInfo *t = it.value();
+ if (t->runLoopTimer) {
+ CFRunLoopTimerInvalidate(t->runLoopTimer);
+ CFRelease(t->runLoopTimer);
+ }
+ delete t;
+ ++it;
+ }
+ QEventDispatcherMacPrivate::macTimerHash.clear();
+
+ // Remove CFSockets from the runloop.
+ for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) {
+ MacSocketInfo *socketInfo = (*it);
+ if (CFSocketIsValid(socketInfo->socket)) {
+ qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
+ CFRunLoopSourceInvalidate(socketInfo->runloop);
+ CFRelease(socketInfo->runloop);
+ CFSocketInvalidate(socketInfo->socket);
+ CFRelease(socketInfo->socket);
+ }
+ }
+ CFRunLoopRemoveSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes);
+ CFRelease(d->postedEventsSource);
+
+ CFRunLoopObserverInvalidate(d->waitingObserver);
+ CFRelease(d->waitingObserver);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h
new file mode 100644
index 0000000000..455d4236bb
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_mac_p.h
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_MAC_P_H
+#define QEVENTDISPATCHER_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qstack.h>
+#include "private/qabstracteventdispatcher_p.h"
+#include "private/qt_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_MAC_USE_COCOA
+typedef struct _NSModalSession *NSModalSession;
+typedef struct _QCocoaModalSessionInfo {
+ QPointer<QWidget> widget;
+ NSModalSession session;
+} QCocoaModalSessionInfo;
+#endif
+
+class QEventDispatcherMacPrivate;
+
+class QEventDispatcherMac : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherMac)
+
+public:
+ explicit QEventDispatcherMac(QObject *parent = 0);
+ ~QEventDispatcherMac();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ void wakeUp();
+ void flush();
+ void interrupt();
+
+private:
+ friend void qt_mac_select_timer_callbk(__EventLoopTimer*, void*);
+ friend class QApplicationPrivate;
+};
+
+struct MacTimerInfo {
+ int id;
+ int interval;
+ QObject *obj;
+ bool pending;
+ CFRunLoopTimerRef runLoopTimer;
+ bool operator==(const MacTimerInfo &other)
+ {
+ return (id == other.id);
+ }
+};
+typedef QHash<int, MacTimerInfo *> MacTimerHash;
+
+struct MacSocketInfo {
+ MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {}
+ CFSocketRef socket;
+ CFRunLoopSourceRef runloop;
+ QObject *readNotifier;
+ QObject *writeNotifier;
+};
+typedef QHash<int, MacSocketInfo *> MacSocketHash;
+
+class QEventDispatcherMacPrivate : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherMac)
+
+public:
+ QEventDispatcherMacPrivate();
+
+ static MacTimerHash macTimerHash;
+ // Set 'blockSendPostedEvents' to true if you _really_ need
+ // to make sure that qt events are not posted while calling
+ // low-level cocoa functions (like beginModalForWindow). And
+ // use a QBoolBlocker to be safe:
+ static bool blockSendPostedEvents;
+#ifdef QT_MAC_USE_COCOA
+ // The following variables help organizing modal sessions:
+ static QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
+ static bool blockCocoaRequestModal;
+ static NSModalSession activeModalSession();
+ static void rebuildModalSessionStack(bool pop);
+#endif
+
+ MacSocketHash macSockets;
+ QList<void *> queuedUserInputEvents; // List of EventRef in Carbon, and NSEvent * in Cocoa
+ CFRunLoopSourceRef postedEventsSource;
+ CFRunLoopObserverRef waitingObserver;
+ QAtomicInt serialNumber;
+ int lastSerial;
+ bool interrupt;
+private:
+ static Boolean postedEventSourceEqualCallback(const void *info1, const void *info2);
+ static void postedEventsSourcePerformCallback(void *info);
+ static void activateTimer(CFRunLoopTimerRef, void *info);
+ static void waitingObserverCallback(CFRunLoopObserverRef observer,
+ CFRunLoopActivity activity, void *info);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_MAC_P_H
diff --git a/src/gui/kernel/qeventdispatcher_qws.cpp b/src/gui/kernel/qeventdispatcher_qws.cpp
new file mode 100644
index 0000000000..6e2cc2b4b6
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_qws.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qapplication.h"
+#include "private/qwscommand_qws_p.h"
+#include "qwsdisplay_qws.h"
+#include "qwsevent_qws.h"
+#include "qwindowsystem_qws.h"
+#include "qeventdispatcher_qws_p.h"
+#include "private/qeventdispatcher_unix_p.h"
+#ifndef QT_NO_THREAD
+# include "qmutex.h"
+#endif
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class QEventDispatcherQWSPrivate : public QEventDispatcherUNIXPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherQWS)
+public:
+ inline QEventDispatcherQWSPrivate()
+ { }
+ QList<QWSEvent*> queuedUserInputEvents;
+};
+
+
+QEventDispatcherQWS::QEventDispatcherQWS(QObject *parent)
+ : QEventDispatcherUNIX(*new QEventDispatcherQWSPrivate, parent)
+{ }
+
+QEventDispatcherQWS::~QEventDispatcherQWS()
+{ }
+
+
+
+// from qapplication_qws.cpp
+extern QWSDisplay* qt_fbdpy; // QWS `display'
+
+//#define ZERO_FOR_THE_MOMENT
+
+bool QEventDispatcherQWS::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherQWS);
+ // process events from the QWS server
+ int nevents = 0;
+
+ // handle gui and posted events
+ d->interrupt = false;
+ QApplication::sendPostedEvents();
+
+ while (!d->interrupt) { // also flushes output buffer ###can be optimized
+ QWSEvent *event;
+ if (!(flags & QEventLoop::ExcludeUserInputEvents)
+ && !d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ event = d->queuedUserInputEvents.takeFirst();
+ } else if (qt_fbdpy->eventPending()) {
+ event = qt_fbdpy->getEvent(); // get next event
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ // queue user input events
+ if (event->type == QWSEvent::Mouse || event->type == QWSEvent::Key) {
+ d->queuedUserInputEvents.append(event);
+ continue;
+ }
+ }
+ } else {
+ break;
+ }
+
+ if (filterEvent(event)) {
+ delete event;
+ continue;
+ }
+ nevents++;
+
+ bool ret = qApp->qwsProcessEvent(event) == 1;
+ delete event;
+ if (ret) {
+ return true;
+ }
+ }
+
+ if (!d->interrupt) {
+ extern QList<QWSCommand*> *qt_get_server_queue();
+ if (!qt_get_server_queue()->isEmpty()) {
+ QWSServer::processEventQueue();
+ }
+
+ if (QEventDispatcherUNIX::processEvents(flags))
+ return true;
+ }
+ return (nevents > 0);
+}
+
+bool QEventDispatcherQWS::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return qGlobalPostedEventsCount() || qt_fbdpy->eventPending();
+}
+
+void QEventDispatcherQWS::startingUp()
+{
+
+}
+
+void QEventDispatcherQWS::closingDown()
+{
+
+}
+
+void QEventDispatcherQWS::flush()
+{
+ if(qApp)
+ qApp->sendPostedEvents();
+ (void)qt_fbdpy->eventPending(); // flush
+}
+
+
+int QEventDispatcherQWS::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ return QEventDispatcherUNIX::select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_qws_p.h b/src/gui/kernel/qeventdispatcher_qws_p.h
new file mode 100644
index 0000000000..e0c00d1732
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_qws_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_QWS_P_H
+#define QEVENTDISPATCHER_QWS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qeventdispatcher_unix_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherQWSPrivate;
+
+class QEventDispatcherQWS : public QEventDispatcherUNIX
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherQWS)
+
+public:
+ explicit QEventDispatcherQWS(QObject *parent = 0);
+ ~QEventDispatcherQWS();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void flush();
+
+ void startingUp();
+ void closingDown();
+
+protected:
+ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_QWS_P_H
diff --git a/src/gui/kernel/qeventdispatcher_x11.cpp b/src/gui/kernel/qeventdispatcher_x11.cpp
new file mode 100644
index 0000000000..2d4dbba16f
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_x11.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_x11_p.h"
+
+#include "qapplication.h"
+#include "qx11info_x11.h"
+
+#include "qt_x11_p.h"
+#include <private/qeventdispatcher_unix_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherX11Private : public QEventDispatcherUNIXPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherX11)
+public:
+ inline QEventDispatcherX11Private()
+ : xfd(-1)
+ { }
+ int xfd;
+ QList<XEvent> queuedUserInputEvents;
+};
+
+QEventDispatcherX11::QEventDispatcherX11(QObject *parent)
+ : QEventDispatcherUNIX(*new QEventDispatcherX11Private, parent)
+{ }
+
+QEventDispatcherX11::~QEventDispatcherX11()
+{ }
+
+bool QEventDispatcherX11::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherX11);
+
+ d->interrupt = false;
+ QApplication::sendPostedEvents();
+
+ ulong marker = XNextRequest(X11->display);
+ int nevents = 0;
+ do {
+ while (!d->interrupt) {
+ XEvent event;
+ if (!(flags & QEventLoop::ExcludeUserInputEvents)
+ && !d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ event = d->queuedUserInputEvents.takeFirst();
+ } else if (XEventsQueued(X11->display, QueuedAlready)) {
+ // process events from the X server
+ XNextEvent(X11->display, &event);
+
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ // queue user input events
+ switch (event.type) {
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case XKeyPress:
+ case XKeyRelease:
+ case EnterNotify:
+ case LeaveNotify:
+ d->queuedUserInputEvents.append(event);
+ continue;
+
+ case ClientMessage:
+ // only keep the wm_take_focus and
+ // _qt_scrolldone protocols, queue all other
+ // client messages
+ if (event.xclient.format == 32) {
+ if (event.xclient.message_type == ATOM(WM_PROTOCOLS) ||
+ (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) {
+ break;
+ } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
+ break;
+ }
+ }
+ d->queuedUserInputEvents.append(event);
+ continue;
+
+ default:
+ break;
+ }
+ }
+ } else {
+ // no event to process
+ break;
+ }
+
+ // send through event filter
+ if (filterEvent(&event))
+ continue;
+
+ nevents++;
+ if (qApp->x11ProcessEvent(&event) == 1)
+ return true;
+
+ if (event.xany.serial >= marker) {
+ if (XEventsQueued(X11->display, QueuedAfterFlush))
+ flags &= ~QEventLoop::WaitForMoreEvents;
+ goto out;
+ }
+ }
+ } while (!d->interrupt && XEventsQueued(X11->display, QueuedAfterFlush));
+
+ out:
+ if (!d->interrupt) {
+ const uint exclude_all =
+ QEventLoop::ExcludeSocketNotifiers | QEventLoop::X11ExcludeTimers | QEventLoop::WaitForMoreEvents;
+ if (nevents > 0 && ((uint)flags & exclude_all) == exclude_all) {
+ QApplication::sendPostedEvents();
+ return nevents > 0;
+ }
+ // return true if we handled events, false otherwise
+ return QEventDispatcherUNIX::processEvents(flags) || (nevents > 0);
+ }
+ return nevents > 0;
+}
+
+bool QEventDispatcherX11::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return (qGlobalPostedEventsCount() || XPending(X11->display));
+}
+
+void QEventDispatcherX11::flush()
+{
+ XFlush(X11->display);
+}
+
+void QEventDispatcherX11::startingUp()
+{
+ Q_D(QEventDispatcherX11);
+ d->xfd = XConnectionNumber(X11->display);
+}
+
+void QEventDispatcherX11::closingDown()
+{
+ Q_D(QEventDispatcherX11);
+ d->xfd = -1;
+}
+
+int QEventDispatcherX11::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ Q_D(QEventDispatcherX11);
+ if (d->xfd > 0) {
+ nfds = qMax(nfds - 1, d->xfd) + 1;
+ FD_SET(d->xfd, readfds);
+ }
+ return QEventDispatcherUNIX::select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_x11_p.h b/src/gui/kernel/qeventdispatcher_x11_p.h
new file mode 100644
index 0000000000..1b40a84377
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_x11_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_X11_P_H
+#define QEVENTDISPATCHER_X11_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qeventdispatcher_unix_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherX11Private;
+
+class QEventDispatcherX11 : public QEventDispatcherUNIX
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherX11)
+
+public:
+ explicit QEventDispatcherX11(QObject *parent = 0);
+ ~QEventDispatcherX11();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void flush();
+
+ void startingUp();
+ void closingDown();
+
+protected:
+ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_X11_P_H
diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp
new file mode 100644
index 0000000000..e2d6108f98
--- /dev/null
+++ b/src/gui/kernel/qformlayout.cpp
@@ -0,0 +1,2080 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qdebug.h"
+#include "qformlayout.h"
+#include "qlabel.h"
+#include "qlayout_p.h"
+#include "qlayoutengine_p.h"
+#include "qrect.h"
+#include "qvector.h"
+#include "qwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+// Fixed column matrix, stores items as [i11, i12, i21, i22...],
+// with FORTRAN-style index operator(r, c).
+template <class T, int NumColumns>
+class FixedColumnMatrix {
+public:
+ typedef QVector<T> Storage;
+
+ FixedColumnMatrix() { }
+
+ void clear() { m_storage.clear(); }
+
+ const T &operator()(int r, int c) const { return m_storage[r * NumColumns + c]; }
+ T &operator()(int r, int c) { return m_storage[r * NumColumns + c]; }
+
+ int rowCount() const { return m_storage.size() / NumColumns; }
+ void addRow(const T &value);
+ void insertRow(int r, const T &value);
+ void removeRow(int r);
+
+ bool find(const T &value, int *rowPtr, int *colPtr) const ;
+ int count(const T &value) const { return m_storage.count(value); }
+
+ // Hmmpf.. Some things are faster that way.
+ const Storage &storage() const { return m_storage; }
+
+ static void storageIndexToPosition(int idx, int *rowPtr, int *colPtr);
+
+private:
+ Storage m_storage;
+};
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::addRow(const T &value)
+{
+ for (int i = 0; i < NumColumns; ++i)
+ m_storage.append(value);
+}
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::insertRow(int r, const T &value)
+{
+ Q_TYPENAME Storage::iterator it = m_storage.begin();
+ it += r * NumColumns;
+ m_storage.insert(it, NumColumns, value);
+}
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::removeRow(int r)
+{
+ m_storage.remove(r * NumColumns, NumColumns);
+}
+
+template <class T, int NumColumns>
+bool FixedColumnMatrix<T, NumColumns>::find(const T &value, int *rowPtr, int *colPtr) const
+{
+ const int idx = m_storage.indexOf(value);
+ if (idx == -1)
+ return false;
+ storageIndexToPosition(idx, rowPtr, colPtr);
+ return true;
+}
+
+template <class T, int NumColumns>
+void FixedColumnMatrix<T, NumColumns>::storageIndexToPosition(int idx, int *rowPtr, int *colPtr)
+{
+ *rowPtr = idx / NumColumns;
+ *colPtr = idx % NumColumns;
+}
+} // namespace
+
+// special values for unset fields; must not clash with values of FieldGrowthPolicy or
+// RowWrapPolicy
+const uint DefaultFieldGrowthPolicy = 255;
+const uint DefaultRowWrapPolicy = 255;
+
+enum { ColumnCount = 2 };
+
+// -- our data structure for our items
+// This owns the QLayoutItem
+struct QFormLayoutItem
+{
+ QFormLayoutItem(QLayoutItem* i) : item(i), fullRow(false), isHfw(false) { }
+ ~QFormLayoutItem() { delete item; }
+
+ // Wrappers
+ QWidget *widget() const { return item->widget(); }
+ QLayout *layout() const { return item->layout(); }
+
+ bool hasHeightForWidth() const { return item->hasHeightForWidth(); }
+ int heightForWidth(int width) const { return item->heightForWidth(width); }
+ int minimumHeightForWidth(int width) const { return item->minimumHeightForWidth(width); }
+ Qt::Orientations expandingDirections() const { return item->expandingDirections(); }
+ QSizePolicy::ControlTypes controlTypes() const { return item->controlTypes(); }
+ int vStretch() const { return widget() ? widget()->sizePolicy().verticalStretch() : 0; }
+
+ void setGeometry(const QRect& r) { item->setGeometry(r); }
+ QRect geometry() const { return item->geometry(); }
+
+ // For use with FixedColumnMatrix
+ bool operator==(const QFormLayoutItem& other) { return item == other.item; }
+
+ QLayoutItem *item;
+ bool fullRow;
+
+ // set by updateSizes
+ bool isHfw;
+ QSize minSize;
+ QSize sizeHint;
+ QSize maxSize;
+
+ // also set by updateSizes
+ int sbsHSpace; // only used for side by side, for the field item only (not label)
+ int vSpace; // This is the spacing to the item in the row above
+
+ // set by setupVerticalLayoutData
+ bool sideBySide;
+ int vLayoutIndex;
+
+ // set by setupHorizontalLayoutData
+ int layoutPos;
+ int layoutWidth;
+};
+
+class QFormLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QFormLayout)
+
+public:
+ typedef FixedColumnMatrix<QFormLayoutItem *, ColumnCount> ItemMatrix;
+
+ QFormLayoutPrivate();
+ ~QFormLayoutPrivate() { }
+
+ int insertRow(int row);
+ void insertRows(int row, int count);
+ void setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item);
+ void setLayout(int row, QFormLayout::ItemRole role, QLayout *layout);
+ void setWidget(int row, QFormLayout::ItemRole role, QWidget *widget);
+
+ void arrangeWidgets(const QVector<QLayoutStruct>& layouts, QRect &rect);
+
+ void updateSizes();
+
+ void setupVerticalLayoutData(int width);
+ void setupHorizontalLayoutData(int width);
+
+ QStyle* getStyle() const;
+
+ inline bool haveHfwCached(int width) const
+ {
+ return (hfw_width == width) || (width == sh_width && hfw_sh_height >= 0);
+ }
+
+ void recalcHFW(int w);
+ void setupHfwLayoutData();
+
+ uint fieldGrowthPolicy : 8;
+ uint rowWrapPolicy : 8;
+ uint has_hfw : 2;
+ uint dirty : 2; // have we laid out yet?
+ uint sizesDirty : 2; // have we (not) gathered layout item sizes?
+ uint expandVertical : 1; // Do we expand vertically?
+ uint expandHorizontal : 1; // Do we expand horizonally?
+ Qt::Alignment labelAlignment;
+ Qt::Alignment formAlignment;
+
+ ItemMatrix m_matrix;
+ QList<QFormLayoutItem *> m_things;
+
+ int layoutWidth; // the last width that we called setupVerticalLayoutData on (for vLayouts)
+
+ int hfw_width; // the last width we calculated HFW for
+ int hfw_height; // what that height was
+ int hfw_minheight; // what that minheight was
+
+ int hfw_sh_height; // the hfw for sh_width
+ int hfw_sh_minheight; // the minhfw for sh_width
+
+ int min_width; // the width that gets turned into minSize (from updateSizes)
+ int sh_width; // the width that gets turned into prefSize (from updateSizes)
+ int thresh_width; // the width that we start splitting label/field pairs at (from updateSizes)
+ QSize minSize;
+ QSize prefSize;
+ int formMaxWidth;
+ void calcSizeHints();
+
+ QVector<QLayoutStruct> vLayouts; // set by setupVerticalLayoutData;
+ int vLayoutCount; // Number of rows we calculated in setupVerticalLayoutData
+ int maxLabelWidth; // the label width we calculated in setupVerticalLayoutData
+
+ QVector<QLayoutStruct> hfwLayouts;
+
+ int hSpacing;
+ int vSpacing;
+};
+
+QFormLayoutPrivate::QFormLayoutPrivate()
+ : fieldGrowthPolicy(DefaultFieldGrowthPolicy),
+ rowWrapPolicy(DefaultRowWrapPolicy), has_hfw(false), dirty(true), sizesDirty(true),
+ expandVertical(0), expandHorizontal(0), labelAlignment(0), formAlignment(0),
+ hfw_width(-1), hfw_sh_height(-1), min_width(-1),
+ sh_width(-1), thresh_width(QLAYOUTSIZE_MAX), hSpacing(-1), vSpacing(-1)
+{
+}
+
+static Qt::Alignment fixedAlignment(Qt::Alignment alignment, Qt::LayoutDirection layoutDirection)
+{
+ if (layoutDirection == Qt::RightToLeft && alignment & Qt::AlignAbsolute) {
+ // swap left and right, and eliminate absolute flag
+ return Qt::Alignment((alignment & ~(Qt::AlignLeft | Qt::AlignRight | Qt::AlignAbsolute))
+ | ((alignment & Qt::AlignRight) ? Qt::AlignLeft : 0)
+ | ((alignment & Qt::AlignLeft) ? Qt::AlignRight : 0));
+ } else {
+ return alignment & ~Qt::AlignAbsolute;
+ }
+}
+
+static int storageIndexFromLayoutItem(const QFormLayoutPrivate::ItemMatrix &m,
+ QFormLayoutItem *item)
+{
+ if (item) {
+ return m.storage().indexOf(item);
+ } else {
+ return -1;
+ }
+}
+
+static void updateFormLayoutItem(QFormLayoutItem *item, int userVSpacing,
+ QFormLayout::FieldGrowthPolicy fieldGrowthPolicy,
+ bool fullRow)
+{
+ item->minSize = item->item->minimumSize();
+ item->sizeHint = item->item->sizeHint();
+ item->maxSize = item->item->maximumSize();
+
+ if (!fullRow && (fieldGrowthPolicy == QFormLayout::FieldsStayAtSizeHint
+ || (fieldGrowthPolicy == QFormLayout::ExpandingFieldsGrow
+ && !(item->item->expandingDirections() & Qt::Horizontal))))
+ item->maxSize.setWidth(item->sizeHint.width());
+
+ item->isHfw = item->item->hasHeightForWidth();
+ item->vSpace = userVSpacing;
+}
+
+/*
+ Iterate over all the controls and gather their size information
+ (min, sizeHint and max). Also work out what the spacing between
+ pairs of controls should be, and figure out the min and sizeHint
+ widths.
+*/
+void QFormLayoutPrivate::updateSizes()
+{
+ Q_Q(QFormLayout);
+
+ if (sizesDirty) {
+ QFormLayout::RowWrapPolicy wrapPolicy = q->rowWrapPolicy();
+ bool wrapAllRows = (wrapPolicy == QFormLayout::WrapAllRows);
+ bool dontWrapRows = (wrapPolicy == QFormLayout::DontWrapRows);
+ int rr = m_matrix.rowCount();
+
+ has_hfw = false;
+
+ // If any control can expand, so can this layout
+ // Wrapping doesn't affect expansion, though, just the minsize
+ bool expandH = false;
+ bool expandV = false;
+
+ QFormLayoutItem *prevLbl = 0;
+ QFormLayoutItem *prevFld = 0;
+
+ QWidget *parent = q->parentWidget();
+ QStyle *style = parent ? parent->style() : 0;
+
+ int userVSpacing = q->verticalSpacing();
+ int userHSpacing = wrapAllRows ? 0 : q->horizontalSpacing();
+
+ int maxMinLblWidth = 0;
+ int maxMinFldWidth = 0; // field with label
+ int maxMinIfldWidth = 0; // independent field
+
+ int maxShLblWidth = 0;
+ int maxShFldWidth = 0;
+ int maxShIfldWidth = 0;
+
+ for (int i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ // Skip empty rows
+ if (!label && !field)
+ continue;
+
+ if (label) {
+ updateFormLayoutItem(label, userVSpacing, q->fieldGrowthPolicy(), false);
+ if (label->isHfw)
+ has_hfw = true;
+ Qt::Orientations o = label->expandingDirections();
+
+ if (o & Qt::Vertical)
+ expandV = true;
+ if (o & Qt::Horizontal)
+ expandH = true;
+ }
+ if (field) {
+ updateFormLayoutItem(field, userVSpacing, q->fieldGrowthPolicy(), !label && field->fullRow);
+ field->sbsHSpace = (!label && field->fullRow) ? 0 : userHSpacing;
+ if (field->isHfw)
+ has_hfw = true;
+
+ Qt::Orientations o = field->expandingDirections();
+
+ if (o & Qt::Vertical)
+ expandV = true;
+ if (o & Qt::Horizontal)
+ expandH = true;
+ }
+
+ // See if we need to calculate default spacings
+ if ((userHSpacing < 0 || userVSpacing < 0) && style) {
+ QSizePolicy::ControlTypes lbltypes =
+ QSizePolicy::ControlTypes(label ? label->controlTypes() : QSizePolicy::DefaultType);
+ QSizePolicy::ControlTypes fldtypes =
+ QSizePolicy::ControlTypes(field ? field->controlTypes() : QSizePolicy::DefaultType);
+
+ // VSpacing
+ if (userVSpacing < 0) {
+ if (wrapAllRows) {
+ // label spacing is to a previous item
+ QFormLayoutItem *lbltop = prevFld ? prevFld : prevLbl;
+ // field spacing is to the label (or a previous item)
+ QFormLayoutItem *fldtop = label ? label : lbltop;
+ QSizePolicy::ControlTypes lbltoptypes =
+ QSizePolicy::ControlTypes(lbltop ? lbltop->controlTypes() : QSizePolicy::DefaultType);
+ QSizePolicy::ControlTypes fldtoptypes =
+ QSizePolicy::ControlTypes(fldtop ? fldtop->controlTypes() : QSizePolicy::DefaultType);
+ if (label && lbltop)
+ label->vSpace = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, 0, parent);
+ if (field && fldtop)
+ field->vSpace = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, 0, parent);
+ } else {
+ // Side by side.. we have to also consider the spacings to empty cells, which can strangely be more than
+ // non empty cells..
+ QFormLayoutItem *lbltop = prevLbl ? prevLbl : prevFld;
+ QFormLayoutItem *fldtop = prevFld;
+ QSizePolicy::ControlTypes lbltoptypes =
+ QSizePolicy::ControlTypes(lbltop ? lbltop->controlTypes() : QSizePolicy::DefaultType);
+ QSizePolicy::ControlTypes fldtoptypes =
+ QSizePolicy::ControlTypes(fldtop ? fldtop->controlTypes() : QSizePolicy::DefaultType);
+
+ // To be compatible to QGridLayout, we have to compare solitary labels & fields with both predecessors
+ if (label) {
+ if (!field) {
+ int lblspacing = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, 0, parent);
+ int fldspacing = style->combinedLayoutSpacing(fldtoptypes, lbltypes, Qt::Vertical, 0, parent);
+ label->vSpace = qMax(lblspacing, fldspacing);
+ } else
+ label->vSpace = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, 0, parent);
+ }
+
+ if (field) {
+ // check spacing against both the previous label and field
+ if (!label) {
+ int lblspacing = style->combinedLayoutSpacing(lbltoptypes, fldtypes, Qt::Vertical, 0, parent);
+ int fldspacing = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, 0, parent);
+ field->vSpace = qMax(lblspacing, fldspacing);
+ } else
+ field->vSpace = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, 0, parent);
+ }
+ }
+ }
+
+ // HSpacing
+ // hard-coded the left and right control types so that all the rows have the same
+ // inter-column spacing (otherwise the right column isn't always left aligned)
+ if (userHSpacing < 0 && !wrapAllRows && (label || !field->fullRow) && field)
+ field->sbsHSpace = style->combinedLayoutSpacing(QSizePolicy::Label, QSizePolicy::LineEdit, Qt::Horizontal, 0, parent);
+ }
+
+ // Now update our min/sizehint widths
+ // We choose to put the spacing in the field side in sbs, so
+ // the right edge of the labels will align, but fields may
+ // be a little ragged.. since different controls may have
+ // different appearances, a slight raggedness in the left
+ // edges of fields can be tolerated.
+ // (Note - field->sbsHSpace is 0 for WrapAllRows mode)
+ if (label) {
+ maxMinLblWidth = qMax(maxMinLblWidth, label->minSize.width());
+ maxShLblWidth = qMax(maxShLblWidth, label->sizeHint.width());
+ if (field) {
+ maxMinFldWidth = qMax(maxMinFldWidth, field->minSize.width() + field->sbsHSpace);
+ maxShFldWidth = qMax(maxShFldWidth, field->sizeHint.width() + field->sbsHSpace);
+ }
+ } else if (field) {
+ maxMinIfldWidth = qMax(maxMinIfldWidth, field->minSize.width());
+ maxShIfldWidth = qMax(maxShIfldWidth, field->sizeHint.width());
+ }
+
+ prevLbl = label;
+ prevFld = field;
+ }
+
+ // Now, finally update the min/sizeHint widths
+ if (wrapAllRows) {
+ sh_width = qMax(maxShLblWidth, qMax(maxShIfldWidth, maxShFldWidth));
+ min_width = qMax(maxMinLblWidth, qMax(maxMinIfldWidth, maxMinFldWidth));
+ // in two line, we don't care as much about the threshold width
+ thresh_width = 0;
+ } else if (dontWrapRows) {
+ // This is just the max widths glommed together
+ sh_width = qMax(maxShLblWidth + maxShFldWidth, maxShIfldWidth);
+ min_width = qMax(maxMinLblWidth + maxMinFldWidth, maxMinIfldWidth);
+ thresh_width = QWIDGETSIZE_MAX;
+ } else {
+ // This is just the max widths glommed together
+ sh_width = qMax(maxShLblWidth + maxShFldWidth, maxShIfldWidth);
+ // min width needs to be the min when everything is wrapped,
+ // otherwise we'll never get set with a width that causes wrapping
+ min_width = qMax(maxMinLblWidth, qMax(maxMinIfldWidth, maxMinFldWidth));
+ // We split a pair at label sh + field min (### for now..)
+ thresh_width = maxShLblWidth + maxMinFldWidth;
+ }
+
+ // Update the expansions
+ expandVertical = expandV;
+ expandHorizontal = expandH;
+ }
+ sizesDirty = false;
+}
+
+void QFormLayoutPrivate::recalcHFW(int w)
+{
+ setupHfwLayoutData();
+
+ int h = 0;
+ int mh = 0;
+
+ for (int r = 0; r < vLayoutCount; ++r) {
+ int spacing = hfwLayouts.at(r).spacing;
+ h += hfwLayouts.at(r).sizeHint + spacing;
+ mh += hfwLayouts.at(r).minimumSize + spacing;
+ }
+
+ if (sh_width > 0 && sh_width == w) {
+ hfw_sh_height = qMin(QLAYOUTSIZE_MAX, h);
+ hfw_sh_minheight = qMin(QLAYOUTSIZE_MAX, mh);
+ } else {
+ hfw_width = w;
+ hfw_height = qMin(QLAYOUTSIZE_MAX, h);
+ hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);
+ }
+}
+
+void QFormLayoutPrivate::setupHfwLayoutData()
+{
+ // setupVerticalLayoutData must be called before this
+ // setupHorizontalLayoutData must also be called before this
+ // copies non hfw data into hfw
+ // then updates size and min
+
+
+ // Note: QGridLayout doesn't call minimumHeightForWidth,
+ // but instead uses heightForWidth for both min and sizeHint.
+ // For the common case where minimumHeightForWidth just calls
+ // heightForWidth, we do the calculation twice, which can be
+ // very expensive for word wrapped QLabels/QTextEdits, for example.
+ // So we just use heightForWidth as well.
+ int i;
+ int rr = m_matrix.rowCount();
+
+ hfwLayouts.clear();
+ hfwLayouts.resize(vLayoutCount);
+ for (i = 0; i < vLayoutCount; ++i)
+ hfwLayouts[i] = vLayouts.at(i);
+
+ for (i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ if (label) {
+ if (label->isHfw) {
+ // We don't check sideBySide here, since a label is only
+ // ever side by side with its field
+ int hfw = label->heightForWidth(label->layoutWidth);
+ hfwLayouts[label->vLayoutIndex].minimumSize = hfw;
+ hfwLayouts[label->vLayoutIndex].sizeHint = hfw;
+ } else {
+ // Reset these here, so the field can do a qMax below (the previous value may have
+ // been the fields non-hfw values, which are often larger than hfw)
+ hfwLayouts[label->vLayoutIndex].sizeHint = label->sizeHint.height();
+ hfwLayouts[label->vLayoutIndex].minimumSize = label->minSize.height();
+ }
+ }
+
+ if (field) {
+ int hfw = field->isHfw ? field->heightForWidth(field->layoutWidth) : 0;
+ int h = field->isHfw ? hfw : field->sizeHint.height();
+ int mh = field->isHfw ? hfw : field->minSize.height();
+
+ if (field->sideBySide) {
+ int oh = hfwLayouts.at(field->vLayoutIndex).sizeHint;
+ int omh = hfwLayouts.at(field->vLayoutIndex).minimumSize;
+
+ hfwLayouts[field->vLayoutIndex].sizeHint = qMax(h, oh);
+ hfwLayouts[field->vLayoutIndex].minimumSize = qMax(mh, omh);
+ } else {
+ hfwLayouts[field->vLayoutIndex].sizeHint = h;
+ hfwLayouts[field->vLayoutIndex].minimumSize = mh;
+ }
+ }
+ }
+}
+
+/*
+ Given up to four items involved in a vertical spacing calculation
+ (two rows * two columns), return the max vertical spacing for the
+ row containing item1 (which may also include item2)
+ We assume parent and item1 are not null.
+
+ If a particular row is split, then the spacings for that row and
+ the following row are affected, and this function should be
+ called with recalculate = true for both rows (note: only rows with both
+ a label and a field can be split).
+
+ In particular:
+
+ 1) the split label's row vspace needs to be changed to qMax(label/prevLabel, label/prevField)
+ [call with item1 = label, item2 = null, prevItem1 & prevItem2 as before]
+ 2) the split field's row vspace needs to be changed to the label/field spacing
+ [call with item1 = field, item2 = null, prevItem1 = label, prevItem2 = null]
+
+ [if the next row has one item, 'item']
+ 3a) the following row's vspace needs to be changed to item/field spacing (would
+ previously been the qMax(item/label, item/field) spacings)
+ [call with item1 = item, item2 = null, prevItem1 = field, prevItem2 = null]
+
+ [if the next row has two items, 'label2' and 'field2']
+ 3b) the following row's vspace needs to be changed to be qMax(field/label2, field/field2) spacing
+ [call with item1 = label2, item2 = field2, prevItem1 = field, prevItem2 = null]
+
+ In the (common) non split case, we can just use the precalculated vspace (possibly qMaxed between
+ label and field).
+
+ If recalculate is true, we expect:
+ - parent != null
+ - item1 != null
+ - item2 can be null
+ - prevItem1 can be null
+ - if item2 is not null, prevItem2 will be null (e.g. steps 1 or 3 above)
+ - if prevItem1 is null, prevItem2 will be null
+*/
+static inline int spacingHelper(QWidget* parent, QStyle *style, int userVSpacing, bool recalculate, QFormLayoutItem* item1, QFormLayoutItem* item2, QFormLayoutItem* prevItem1, QFormLayoutItem *prevItem2)
+{
+ int spacing = userVSpacing;
+ if (spacing < 0) {
+ if (!recalculate) {
+ if (item1)
+ spacing = item1->vSpace;
+ if (item2)
+ spacing = qMax(spacing, item2->vSpace);
+ } else {
+ if (style && prevItem1) {
+ QSizePolicy::ControlTypes itemtypes =
+ QSizePolicy::ControlTypes(item1 ? item1->controlTypes() : QSizePolicy::DefaultType);
+ int spacing2 = 0;
+
+ spacing = style->combinedLayoutSpacing(itemtypes, prevItem1->controlTypes(), Qt::Vertical, 0, parent);
+
+ // At most of one of item2 and prevItem2 will be nonnull
+ if (item2)
+ spacing2 = style->combinedLayoutSpacing(item2->controlTypes(), prevItem1->controlTypes(), Qt::Vertical, 0, parent);
+ else if (prevItem2)
+ spacing2 = style->combinedLayoutSpacing(itemtypes, prevItem2->controlTypes(), Qt::Vertical, 0, parent);
+
+ spacing = qMax(spacing, spacing2);
+ }
+ }
+ } else {
+ if (prevItem1) {
+ QWidget *wid = prevItem1->item->widget();
+ if (wid)
+ spacing = qMax(spacing, prevItem1->geometry().top() - wid->geometry().top() );
+ }
+ if (prevItem2) {
+ QWidget *wid = prevItem2->item->widget();
+ if (wid)
+ spacing = qMax(spacing, prevItem2->geometry().top() - wid->geometry().top() );
+ }
+ }
+ return spacing;
+}
+
+static inline void initLayoutStruct(QLayoutStruct& sl, QFormLayoutItem* item)
+{
+ sl.init(item->vStretch(), item->minSize.height());
+ sl.sizeHint = item->sizeHint.height();
+ sl.maximumSize = item->maxSize.height();
+ sl.expansive = (item->expandingDirections() & Qt::Vertical);
+ sl.empty = false;
+}
+
+void QFormLayoutPrivate::setupVerticalLayoutData(int width)
+{
+ Q_Q(QFormLayout);
+
+ // Early out if we have no changes that would cause a change in vertical layout
+ if ((width == layoutWidth || (width >= thresh_width && layoutWidth >= thresh_width)) && !dirty && !sizesDirty)
+ return;
+
+ layoutWidth = width;
+
+ int rr = m_matrix.rowCount();
+ int vidx = 1;
+ QFormLayout::RowWrapPolicy rowWrapPolicy = q->rowWrapPolicy();
+ bool wrapAllRows = (rowWrapPolicy == QFormLayout::WrapAllRows);
+ bool addTopBottomStretch = true;
+
+ vLayouts.clear();
+ vLayouts.resize((2 * rr) + 2); // a max, some may be unused
+
+ QStyle *style = 0;
+
+ int userVSpacing = q->verticalSpacing();
+
+ if (userVSpacing < 0) {
+ if (QWidget *widget = q->parentWidget())
+ style = widget->style();
+ }
+
+ // make sure our sizes are up to date
+ updateSizes();
+
+ // Grab the widest label width here
+ // This might be different from the value computed during
+ // sizeHint/minSize, since we don't count label/field pairs that
+ // are split.
+ maxLabelWidth = 0;
+ if (!wrapAllRows) {
+ for (int i = 0; i < rr; ++i) {
+ const QFormLayoutItem *label = m_matrix(i, 0);
+ const QFormLayoutItem *field = m_matrix(i, 1);
+ if (label && (label->sizeHint.width() + (field ? field->minSize.width() : 0) <= width))
+ maxLabelWidth = qMax(maxLabelWidth, label->sizeHint.width());
+ }
+ } else {
+ maxLabelWidth = width;
+ }
+
+ QFormLayoutItem *prevItem1 = 0;
+ QFormLayoutItem *prevItem2 = 0;
+ bool prevRowSplit = false;
+
+ for (int i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ // Totally ignore empty rows...
+ if (!label && !field)
+ continue;
+
+ QSize min1;
+ QSize min2;
+ QSize sh1;
+ QSize sh2;
+ if (label) {
+ min1 = label->minSize;
+ sh1 = label->sizeHint;
+ }
+ if (field) {
+ min2 = field->minSize;
+ sh2 = field->sizeHint;
+ }
+
+ // In separate lines, we make a vLayout for everything that isn't null
+ // in side by side, we only separate label/field if we're going to wrap it
+ bool splitSideBySide = (rowWrapPolicy == QFormLayout::WrapLongRows)
+ && ((maxLabelWidth < sh1.width()) || (width < (maxLabelWidth + min2.width())));
+
+ if (wrapAllRows || splitSideBySide) {
+ if (label) {
+ initLayoutStruct(vLayouts[vidx], label);
+
+ if (vidx > 1)
+ vLayouts[vidx - 1].spacing = spacingHelper(q->parentWidget(), style, userVSpacing, splitSideBySide || prevRowSplit, label, 0, prevItem1, prevItem2);
+
+ label->vLayoutIndex = vidx;
+ label->sideBySide = false;
+
+ prevItem1 = label;
+ prevItem2 = 0;
+
+ if (vLayouts[vidx].stretch > 0)
+ addTopBottomStretch = false;
+
+ ++vidx;
+ }
+
+ if (field) {
+ initLayoutStruct(vLayouts[vidx], field);
+
+ if (vidx > 1)
+ vLayouts[vidx - 1].spacing = spacingHelper(q->parentWidget(), style, userVSpacing, splitSideBySide || prevRowSplit, field, 0, prevItem1, prevItem2);
+
+ field->vLayoutIndex = vidx;
+ field->sideBySide = false;
+
+ prevItem1 = field;
+ prevItem2 = 0;
+
+ if (vLayouts[vidx].stretch > 0)
+ addTopBottomStretch = false;
+
+ ++vidx;
+ }
+
+ prevRowSplit = splitSideBySide;
+ } else {
+ // we're in side by side mode, and we have enough space to do that
+ QSize max1(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ QSize max2(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+
+ int stretch1 = 0;
+ int stretch2 = 0;
+ bool expanding = false;
+
+ if (label) {
+ max1 = label->maxSize;
+ if (label->expandingDirections() & Qt::Vertical)
+ expanding = true;
+
+ label->sideBySide = (field != 0);
+ label->vLayoutIndex = vidx;
+ stretch1 = label->vStretch();
+ }
+
+ if (field) {
+ max2 = field->maxSize;
+ if (field->expandingDirections() & Qt::Vertical)
+ expanding = true;
+
+ field->sideBySide = (label || !field->fullRow);
+ field->vLayoutIndex = vidx;
+ stretch2 = field->vStretch();
+ }
+
+ vLayouts[vidx].init(qMax(stretch1, stretch2), qMax(min1.height(), min2.height()));
+ vLayouts[vidx].sizeHint = qMax(sh1.height(), sh2.height());
+ vLayouts[vidx].maximumSize = qMin(max1.height(), max2.height());
+ vLayouts[vidx].expansive = expanding || (vLayouts[vidx].stretch > 0);
+ vLayouts[vidx].empty = false;
+
+ if (vLayouts[vidx].stretch > 0)
+ addTopBottomStretch = false;
+
+ if (vidx > 1)
+ vLayouts[vidx - 1].spacing = spacingHelper(q->parentWidget(), style, userVSpacing, prevRowSplit, label, field, prevItem1, prevItem2);
+
+ if (label) {
+ prevItem1 = label;
+ prevItem2 = field;
+ } else {
+ prevItem1 = field;
+ prevItem2 = 0;
+ }
+
+ prevRowSplit = false;
+ ++vidx;
+ }
+ }
+
+ if (addTopBottomStretch) {
+ Qt::Alignment formAlignment = q->formAlignment();
+
+ if (!(formAlignment & Qt::AlignBottom)) {
+ // AlignTop (default if unspecified) or AlignVCenter: We add a stretch at the bottom
+ vLayouts[vidx].init(1, 0);
+ vLayouts[vidx].expansive = true;
+ ++vidx;
+ }
+
+ if (formAlignment & (Qt::AlignVCenter | Qt::AlignBottom)) {
+ // AlignVCenter or AlignBottom: We add a stretch at the top
+ vLayouts[0].init(1, 0);
+ vLayouts[0].expansive = true;
+ } else {
+ vLayouts[0].init(0, 0);
+ }
+ } else {
+ vLayouts[0].init(0, 0);
+ }
+
+ vLayoutCount = vidx;
+ dirty = false;
+}
+
+void QFormLayoutPrivate::setupHorizontalLayoutData(int width)
+{
+ Q_Q(QFormLayout);
+
+ // requires setupVerticalLayoutData to be called first
+
+ int fieldMaxWidth = 0;
+
+ int rr = m_matrix.rowCount();
+ bool wrapAllRows = (q->rowWrapPolicy() == QFormLayout::WrapAllRows);
+
+ for (int i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ // Totally ignore empty rows...
+ if (!label && !field)
+ continue;
+
+ if (label) {
+ // if there is a field, and we're side by side, we use maxLabelWidth
+ // otherwise we just use the sizehint
+ label->layoutWidth = (field && label->sideBySide) ? maxLabelWidth : label->sizeHint.width();
+ label->layoutPos = 0;
+ }
+
+ if (field) {
+ // This is the default amount allotted to fields in sbs
+ int fldwidth = width - maxLabelWidth - field->sbsHSpace;
+
+ // If we've split a row, we still decide to align
+ // the field with all the other field if it will fit
+ // Fields in sbs mode get the remnants of the maxLabelWidth
+ if (!field->sideBySide) {
+ if (wrapAllRows || (!label && field->fullRow) || field->sizeHint.width() > fldwidth) {
+ field->layoutWidth = width;
+ field->layoutPos = 0;
+ } else {
+ field->layoutWidth = fldwidth;
+ field->layoutPos = width - fldwidth;
+ }
+ } else {
+ // We're sbs, so we should have a label
+ field->layoutWidth = fldwidth;
+ field->layoutPos = width - fldwidth;
+ }
+
+ fieldMaxWidth = qMax(fieldMaxWidth, field->maxSize.width());
+ }
+ }
+
+ formMaxWidth = maxLabelWidth + fieldMaxWidth;
+}
+
+void QFormLayoutPrivate::calcSizeHints()
+{
+ Q_Q(QFormLayout);
+
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+
+ updateSizes();
+ setupVerticalLayoutData(QLAYOUTSIZE_MAX);
+ // Don't need to call setupHorizontal here
+
+ int h = topMargin + bottomMargin;
+ int mh = topMargin + bottomMargin;
+
+ // The following are set in updateSizes
+ int w = sh_width + leftMargin + rightMargin;
+ int mw = min_width + leftMargin + rightMargin;
+
+ for (int i = 0; i < vLayoutCount; ++i) {
+ int spacing = vLayouts.at(i).spacing;
+ h += vLayouts.at(i).sizeHint + spacing;
+ mh += vLayouts.at(i).minimumSize + spacing;
+ }
+
+ minSize.rwidth() = qMin(mw, QLAYOUTSIZE_MAX);
+ minSize.rheight() = qMin(mh, QLAYOUTSIZE_MAX);
+ prefSize.rwidth() = qMin(w, QLAYOUTSIZE_MAX);
+ prefSize.rheight() = qMin(h, QLAYOUTSIZE_MAX);
+}
+
+int QFormLayoutPrivate::insertRow(int row)
+{
+ int rowCnt = m_matrix.rowCount();
+ if (uint(row) > uint(rowCnt))
+ row = rowCnt;
+
+ insertRows(row, 1);
+ return row;
+}
+
+void QFormLayoutPrivate::insertRows(int row, int count)
+{
+ while (count > 0) {
+ m_matrix.insertRow(row, 0);
+ --count;
+ }
+}
+
+void QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item)
+{
+ const bool fullRow = role == QFormLayout::SpanningRole;
+ const int column = role == QFormLayout::SpanningRole ? 1 : static_cast<int>(role);
+ if (uint(row) >= uint(m_matrix.rowCount()) || uint(column) > 1U) {
+ qWarning("QFormLayoutPrivate::setItem: Invalid cell (%d, %d)", row, column);
+ return;
+ }
+
+ if (!item)
+ return;
+
+ if (m_matrix(row, column)) {
+ qWarning("QFormLayoutPrivate::setItem: Cell (%d, %d) already occupied", row, column);
+ return;
+ }
+
+ QFormLayoutItem *i = new QFormLayoutItem(item);
+ i->fullRow = fullRow;
+ m_matrix(row, column) = i;
+
+ m_things.append(i);
+}
+
+void QFormLayoutPrivate::setLayout(int row, QFormLayout::ItemRole role, QLayout *layout)
+{
+ if (layout) {
+ Q_Q(QFormLayout);
+ q->addChildLayout(layout);
+ setItem(row, role, layout);
+ }
+}
+
+void QFormLayoutPrivate::setWidget(int row, QFormLayout::ItemRole role, QWidget *widget)
+{
+ if (widget) {
+ Q_Q(QFormLayout);
+ q->addChildWidget(widget);
+ setItem(row, role, QLayoutPrivate::createWidgetItem(q, widget));
+ }
+}
+
+QStyle* QFormLayoutPrivate::getStyle() const
+{
+ Q_Q(const QFormLayout);
+
+ // ### cache
+ if (QWidget *parentWidget = q->parentWidget())
+ return parentWidget->style();
+ else
+ return QApplication::style();
+}
+
+/*!
+ \class QFormLayout
+ \since 4.4
+ \brief The QFormLayout class manages forms of input widgets and their associated labels.
+
+ \ingroup appearance
+ \ingroup geomanagement
+
+ \mainclass
+
+ QFormLayout is a convenience layout class that lays out its
+ children in a two-column form. The left column consists of labels
+ and the right column consists of "field" widgets (line editors,
+ spin boxes, etc.).
+
+ Traditionally, such two-column form layouts were achieved using
+ QGridLayout. QFormLayout is a higher-level alternative that
+ provides the following advantages:
+
+ \list
+ \o \bold{Adherence to the different platform's look and feel guidelines.}
+
+ For example, the
+ \l{Mac OS X Aqua} and KDE guidelines specify that the
+ labels should be right-aligned, whereas Windows and GNOME
+ applications normally use left-alignment.
+
+ \o \bold{Support for wrapping long rows.}
+
+ For devices with small displays, QFormLayout can be set to
+ \l{WrapLongRows}{wrap long rows}, or even to
+ \l{WrapAllRows}{wrap all rows}.
+
+ \o \bold{Convenient API for creating label--field pairs.}
+
+ The addRow() overload that takes a QString and a QWidget *
+ creates a QLabel behind the scenes and automatically set up
+ its buddy. We can then write code like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qformlayout.cpp 0
+
+ Compare this with the following code, written using QGridLayout:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qformlayout.cpp 1
+ \endlist
+
+ The table below shows the default appearance in different styles.
+
+ \table
+ \header
+ \o QCommonStyle derived styles (except QPlastiqueStyle)
+ \o QMacStyle
+ \o QPlastiqueStyle
+ \o Qt Extended styles
+ \row
+ \o \inlineimage qformlayout-win.png
+ \o \inlineimage qformlayout-mac.png
+ \o \inlineimage qformlayout-kde.png
+ \o \inlineimage qformlayout-qpe.png
+ \row
+ \o Traditional style used for Windows, GNOME, and earlier
+ versions of KDE. Labels are left aligned, and expanding
+ fields grow to fill the available space. (This normally
+ corresponds to what we would get using a two-column
+ QGridLayout.)
+ \o Style based on the
+ \l{Mac OS X Aqua} guidelines. Labels are right-aligned,
+ the fields don't grow beyond their size hint, and the
+ form is horizontally centered.
+ \o Recommended style for
+ \l{KDE applications}. Similar to MacStyle, except that the form
+ is left-aligned and all fields grow to fill the available
+ space.
+ \o Default style for Qt Extended styles. Labels are right-aligned,
+ expanding fields grow to fill the available space, and row
+ wrapping is enabled for long lines.
+ \endtable
+
+ The form styles can be also be overridden individually by calling
+ setLabelAlignment(), setFormAlignment(), setFieldGrowthPolicy(),
+ and setRowWrapPolicy(). For example, to simulate the form layout
+ appearance of QMacStyle on all platforms, but with left-aligned
+ labels, you could write:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qformlayout.cpp 2
+
+ \sa QGridLayout, QBoxLayout, QStackedLayout
+*/
+
+
+/*!
+ \enum QFormLayout::FieldGrowthPolicy
+
+ This enum specifies the different policies that can be used to
+ control the way in which the form's fields grow.
+
+ \value FieldsStayAtSizeHint
+ The fields never grow beyond their
+ \l{QWidgetItem::sizeHint()}{effective size hint}. This is
+ the default for QMacStyle.
+
+ \value ExpandingFieldsGrow
+ Fields with an horizontal \l{QSizePolicy}{size policy} of
+ \l{QSizePolicy::}{Expanding} or
+ \l{QSizePolicy::}{MinimumExpanding} will grow to fill the
+ available space. The other fields will not grow beyond
+ their effective size hint. This is the default policy for
+ Plastique.
+
+ \value AllNonFixedFieldsGrow
+ All fields with a size policy that allows them to grow
+ will grow to fill the available space. This is the default
+ policy for most styles.
+
+ \sa fieldGrowthPolicy
+*/
+
+/*!
+ \enum QFormLayout::RowWrapPolicy
+
+ This enum specifies the different policies that can be used to
+ control the way in which the form's rows wrap.
+
+ \value DontWrapRows
+ Fields are always laid out next to their label. This is
+ the default policy for all styles except Qt Extended styles.
+
+ \value WrapLongRows
+ Labels are given enough horizontal space to fit the widest label,
+ and the rest of the space is given to the fields. If the minimum
+ size of a field pair is wider than the available space, the field
+ is wrapped to the next line. This is the default policy for
+ Qt Extended styles.
+
+ \value WrapAllRows
+ Fields are always laid out below their label.
+
+ \sa rowWrapPolicy
+*/
+
+/*!
+ \enum QFormLayout::ItemRole
+
+ This enum specifies the types of widgets (or other layout items)
+ that may appear in a row.
+
+ \value LabelRole A label widget.
+ \value FieldRole A field widget.
+ \value SpanningRole A widget that spans label and field columns.
+
+ \sa itemAt(), getItemPosition()
+*/
+
+/*!
+ Constructs a new form layout with the given \a parent widget.
+
+ \sa QWidget::setLayout()
+*/
+QFormLayout::QFormLayout(QWidget *parent)
+ : QLayout(*new QFormLayoutPrivate, 0, parent)
+{
+}
+
+/*!
+ Destroys the form layout.
+*/
+QFormLayout::~QFormLayout()
+{
+ Q_D(QFormLayout);
+
+ /*
+ The clearing and destruction order here is important. We start by clearing
+ m_things so that QLayout and the rest of the world know that we don't babysit
+ the layout items anymore and don't care if they are destroyed.
+ */
+ d->m_things.clear();
+ qDeleteAll(d->m_matrix.storage());
+ d->m_matrix.clear();
+}
+
+/*!
+ Adds a new row to the bottom of this form layout, with the given
+ \a label and \a field.
+
+ \sa insertRow()
+*/
+void QFormLayout::addRow(QWidget *label, QWidget *field)
+{
+ insertRow(-1, label, field);
+}
+
+/*!
+ \overload
+*/
+void QFormLayout::addRow(QWidget *label, QLayout *field)
+{
+ insertRow(-1, label, field);
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text. The \a field is set as the new
+ QLabel's \l{QLabel::setBuddy()}{buddy}.
+*/
+void QFormLayout::addRow(const QString &labelText, QWidget *field)
+{
+ insertRow(-1, labelText, field);
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text.
+*/
+void QFormLayout::addRow(const QString &labelText, QLayout *field)
+{
+ insertRow(-1, labelText, field);
+}
+
+/*!
+ \overload
+
+ Adds the specified \a widget at the end of this form layout. The
+ \a widget spans both columns.
+*/
+void QFormLayout::addRow(QWidget *widget)
+{
+ insertRow(-1, widget);
+}
+
+/*!
+ \overload
+
+ Adds the specified \a layout at the end of this form layout. The
+ \a layout spans both columns.
+*/
+void QFormLayout::addRow(QLayout *layout)
+{
+ insertRow(-1, layout);
+}
+
+/*!
+ Inserts a new row at position \a row in this form layout, with
+ the given \a label and \a field. If \a row is out of bounds, the
+ new row is added at the end.
+
+ \sa addRow()
+*/
+void QFormLayout::insertRow(int row, QWidget *label, QWidget *field)
+{
+ Q_D(QFormLayout);
+
+ row = d->insertRow(row);
+ if (label)
+ d->setWidget(row, LabelRole, label);
+ if (field)
+ d->setWidget(row, FieldRole, field);
+ invalidate();
+}
+
+/*!
+ \overload
+*/
+void QFormLayout::insertRow(int row, QWidget *label, QLayout *field)
+{
+ Q_D(QFormLayout);
+
+ row = d->insertRow(row);
+ if (label)
+ d->setWidget(row, LabelRole, label);
+ if (field)
+ d->setLayout(row, FieldRole, field);
+ invalidate();
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text. The \a field is set as the new
+ QLabel's \l{QLabel::setBuddy()}{buddy}.
+*/
+void QFormLayout::insertRow(int row, const QString &labelText, QWidget *field)
+{
+ QLabel *label = 0;
+ if (!labelText.isEmpty()) {
+ label = new QLabel(labelText);
+#ifndef QT_NO_SHORTCUT
+ label->setBuddy(field);
+#endif
+ }
+ insertRow(row, label, field);
+}
+
+/*!
+ \overload
+
+ This overload automatically creates a QLabel behind the scenes
+ with \a labelText as its text.
+*/
+void QFormLayout::insertRow(int row, const QString &labelText, QLayout *field)
+{
+ insertRow(row, labelText.isEmpty() ? 0 : new QLabel(labelText), field);
+}
+
+/*!
+ \overload
+
+ Inserts the specified \a widget at position \a row in this form
+ layout. The \a widget spans both columns. If \a row is out of
+ bounds, the widget is added at the end.
+*/
+void QFormLayout::insertRow(int row, QWidget *widget)
+{
+ Q_D(QFormLayout);
+
+ if (!widget) {
+ qWarning("QFormLayout: Cannot add null field to %s", qPrintable(objectName()));
+ return;
+ }
+
+ row = d->insertRow(row);
+ d->setWidget(row, SpanningRole, widget);
+ invalidate();
+}
+
+/*!
+ \overload
+
+ Inserts the specified \a layout at position \a row in this form
+ layout. The \a layout spans both columns. If \a row is out of
+ bounds, the widget is added at the end.
+*/
+void QFormLayout::insertRow(int row, QLayout *layout)
+{
+ Q_D(QFormLayout);
+
+ if (!layout) {
+ qWarning("QFormLayout: Cannot add null field to %s", qPrintable(objectName()));
+ return;
+ }
+
+ row = d->insertRow(row);
+ d->setLayout(row, SpanningRole, layout);
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+void QFormLayout::addItem(QLayoutItem *item)
+{
+ Q_D(QFormLayout);
+
+ int row = d->insertRow(d->m_matrix.rowCount());
+ d->setItem(row, FieldRole, item);
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+int QFormLayout::count() const
+{
+ Q_D(const QFormLayout);
+ return d->m_things.count();
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QFormLayout::itemAt(int index) const
+{
+ Q_D(const QFormLayout);
+ if (QFormLayoutItem *formItem = d->m_things.value(index))
+ return formItem->item;
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QFormLayout::takeAt(int index)
+{
+ Q_D(QFormLayout);
+
+ const int storageIndex = storageIndexFromLayoutItem(d->m_matrix, d->m_things.value(index));
+ if (storageIndex == -1) {
+ qWarning("QFormLayout::takeAt: Invalid index %d", index);
+ return 0;
+ }
+
+ int row, col;
+ QFormLayoutPrivate::ItemMatrix::storageIndexToPosition(storageIndex, &row, &col);
+ Q_ASSERT(d->m_matrix(row, col));
+
+ QFormLayoutItem *item = d->m_matrix(row, col);
+ Q_ASSERT(item);
+ d->m_things.removeAt(index);
+ d->m_matrix(row, col) = 0;
+
+ invalidate();
+
+ // grab ownership back from the QFormLayoutItem
+ QLayoutItem *i = item->item;
+ item->item = 0;
+ delete item;
+ return i;
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QFormLayout::expandingDirections() const
+{
+ Q_D(const QFormLayout);
+ QFormLayoutPrivate *e = const_cast<QFormLayoutPrivate *>(d);
+ e->updateSizes();
+
+ Qt::Orientations o = 0;
+ if (e->expandHorizontal)
+ o = Qt::Horizontal;
+ if (e->expandVertical)
+ o |= Qt::Vertical;
+ return o;
+}
+
+/*!
+ \reimp
+*/
+bool QFormLayout::hasHeightForWidth() const
+{
+ Q_D(const QFormLayout);
+ QFormLayoutPrivate *e = const_cast<QFormLayoutPrivate *>(d);
+ e->updateSizes();
+ return (d->has_hfw || rowWrapPolicy() == WrapLongRows);
+}
+
+/*!
+ \reimp
+*/
+int QFormLayout::heightForWidth(int width) const
+{
+ Q_D(const QFormLayout);
+ if (!hasHeightForWidth())
+ return -1;
+
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+
+ int targetWidth = width - leftMargin - rightMargin;
+
+ if (!d->haveHfwCached(targetWidth)) {
+ QFormLayoutPrivate *dat = const_cast<QFormLayoutPrivate *>(d);
+ dat->setupVerticalLayoutData(targetWidth);
+ dat->setupHorizontalLayoutData(targetWidth);
+ dat->recalcHFW(targetWidth);
+ }
+ if (targetWidth == d->sh_width)
+ return d->hfw_sh_height + topMargin + bottomMargin;
+ else
+ return d->hfw_height + topMargin + bottomMargin;
+}
+
+/*!
+ \reimp
+*/
+void QFormLayout::setGeometry(const QRect &rect)
+{
+ Q_D(QFormLayout);
+ if (d->dirty || rect != geometry()) {
+ QRect cr = rect;
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ cr.adjust(+leftMargin, +topMargin, -rightMargin, -bottomMargin);
+
+ bool hfw = hasHeightForWidth();
+ d->setupVerticalLayoutData(cr.width());
+ d->setupHorizontalLayoutData(cr.width());
+ if (hfw && (!d->haveHfwCached(cr.width()) || d->hfwLayouts.size() != d->vLayoutCount))
+ d->recalcHFW(cr.width());
+ if (hfw) {
+ qGeomCalc(d->hfwLayouts, 0, d->vLayoutCount, cr.y(), cr.height());
+ d->arrangeWidgets(d->hfwLayouts, cr);
+ } else {
+ qGeomCalc(d->vLayouts, 0, d->vLayoutCount, cr.y(), cr.height());
+ d->arrangeWidgets(d->vLayouts, cr);
+ }
+ QLayout::setGeometry(rect);
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QFormLayout::sizeHint() const
+{
+ Q_D(const QFormLayout);
+ if (!d->prefSize.isValid()) {
+ QFormLayoutPrivate *dat = const_cast<QFormLayoutPrivate *>(d);
+ dat->calcSizeHints();
+ }
+ return d->prefSize;
+}
+
+/*!
+ \reimp
+*/
+QSize QFormLayout::minimumSize() const
+{
+ // ### fix minimumSize if hfw
+ Q_D(const QFormLayout);
+ if (!d->minSize.isValid()) {
+ QFormLayoutPrivate *dat = const_cast<QFormLayoutPrivate *>(d);
+ dat->calcSizeHints();
+ }
+ return d->minSize;
+}
+
+/*!
+ \reimp
+*/
+void QFormLayout::invalidate()
+{
+ Q_D(QFormLayout);
+ d->dirty = true;
+ d->sizesDirty = true;
+ d->minSize = QSize();
+ d->prefSize = QSize();
+ d->formMaxWidth = -1;
+ d->hfw_width = -1;
+ d->sh_width = -1;
+ d->layoutWidth = -1;
+ d->hfw_sh_height = -1;
+ QLayout::invalidate();
+}
+
+/*!
+ Returns the number of rows in the form.
+
+ \sa QLayout::count()
+*/
+int QFormLayout::rowCount() const
+{
+ Q_D(const QFormLayout);
+ return d->m_matrix.rowCount();
+}
+
+/*!
+ Returns the layout item in the given \a row with the specified \a
+ role (column). Returns 0 if there is no such item.
+
+ \sa QLayout::itemAt(), setItem()
+*/
+QLayoutItem *QFormLayout::itemAt(int row, ItemRole role) const
+{
+ Q_D(const QFormLayout);
+ if (uint(row) >= uint(d->m_matrix.rowCount()))
+ return 0;
+ switch (role) {
+ case SpanningRole:
+ if (QFormLayoutItem *item = d->m_matrix(row, 1))
+ if (item->fullRow)
+ return item->item;
+ break;
+ case LabelRole:
+ case FieldRole:
+ if (QFormLayoutItem *item = d->m_matrix(row, (role == LabelRole) ? 0 : 1))
+ return item->item;
+ break;
+ }
+ return 0;
+}
+
+/*!
+ Retrieves the row and role (column) of the item at the specified
+ \a index. If \a index is out of bounds, *\a rowPtr is set to -1;
+ otherwise the row is stored in *\a rowPtr and the role is stored
+ in *\a rolePtr.
+
+ \sa itemAt(), count(), getLayoutPosition(), getWidgetPosition()
+*/
+void QFormLayout::getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const
+{
+ Q_D(const QFormLayout);
+ int col = -1;
+ int row = -1;
+
+ const int storageIndex = storageIndexFromLayoutItem(d->m_matrix, d->m_things.value(index));
+ if (storageIndex != -1)
+ QFormLayoutPrivate::ItemMatrix::storageIndexToPosition(storageIndex, &row, &col);
+
+ if (rowPtr)
+ *rowPtr = row;
+ if (rolePtr && col != -1) {
+ const bool spanning = col == 1 && d->m_matrix(row, col)->fullRow;
+ if (spanning) {
+ *rolePtr = SpanningRole;
+ } else {
+ *rolePtr = ItemRole(col);
+ }
+ }
+}
+
+/*!
+ Retrieves the row and role (column) of the specified child \a
+ layout. If \a layout is not in the form layout, *\a rowPtr is set
+ to -1; otherwise the row is stored in *\a rowPtr and the role is stored
+ in *\a rolePtr.
+*/
+void QFormLayout::getLayoutPosition(QLayout *layout, int *rowPtr, ItemRole *rolePtr) const
+{
+ int n = count();
+ int index = 0;
+ while (index < n) {
+ if (itemAt(index) == layout)
+ break;
+ ++index;
+ }
+ getItemPosition(index, rowPtr, rolePtr);
+}
+
+/*!
+ Retrieves the row and role (column) of the specified \a widget in
+ the layout. If \a widget is not in the layout, *\a rowPtr is set
+ to -1; otherwise the row is stored in *\a rowPtr and the role is stored
+ in *\a rolePtr.
+
+ \sa getItemPosition(), itemAt()
+*/
+void QFormLayout::getWidgetPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const
+{
+ getItemPosition(indexOf(widget), rowPtr, rolePtr);
+}
+
+// ### eliminate labelForField()
+
+/*!
+ Returns the label associated with the given \a field.
+
+ \sa itemAt()
+*/
+QWidget *QFormLayout::labelForField(QWidget *field) const
+{
+ Q_D(const QFormLayout);
+
+ int row;
+ ItemRole role;
+
+ getWidgetPosition(field, &row, &role);
+
+ if (row != -1 && role == FieldRole) {
+ if (QFormLayoutItem *label = d->m_matrix(row, LabelRole))
+ return label->widget();
+ }
+ return 0;
+}
+
+/*!
+ \overload
+*/
+QWidget *QFormLayout::labelForField(QLayout *field) const
+{
+ Q_D(const QFormLayout);
+
+ int row;
+ ItemRole role;
+
+ getLayoutPosition(field, &row, &role);
+
+ if (row != -1 && role == FieldRole) {
+ if (QFormLayoutItem *label = d->m_matrix(row, LabelRole))
+ return label->widget();
+ }
+ return 0;
+}
+
+/*!
+ \property QFormLayout::fieldGrowthPolicy
+ \brief the way in which the form's fields grow
+
+ The default value depends on the widget or application style. For
+ QMacStyle, the default is FieldsStayAtSizeHint; for QCommonStyle
+ derived styles (like Plastique and Windows), the default
+ is ExpandingFieldsGrow; for Qt Extended styles, the default is
+ AllNonFixedFieldsGrow.
+
+ If none of the fields can grow and the form is resized, extra
+ space is distributed according to the current
+ \l{formAlignment}{form alignment}.
+
+ \sa formAlignment, rowWrapPolicy
+*/
+
+void QFormLayout::setFieldGrowthPolicy(FieldGrowthPolicy policy)
+{
+ Q_D(QFormLayout);
+ if (FieldGrowthPolicy(d->fieldGrowthPolicy) != policy) {
+ d->fieldGrowthPolicy = policy;
+ invalidate();
+ }
+}
+
+QFormLayout::FieldGrowthPolicy QFormLayout::fieldGrowthPolicy() const
+{
+ Q_D(const QFormLayout);
+ if (d->fieldGrowthPolicy == DefaultFieldGrowthPolicy) {
+ return QFormLayout::FieldGrowthPolicy(d->getStyle()->styleHint(QStyle::SH_FormLayoutFieldGrowthPolicy));
+ } else {
+ return QFormLayout::FieldGrowthPolicy(d->fieldGrowthPolicy);
+ }
+}
+
+/*!
+ \property QFormLayout::rowWrapPolicy
+ \brief the way in which the form's rows wrap
+
+ The default value depends on the widget or application style. For
+ Qt Extended styles, the default is WrapLongRows; for the other styles,
+ the default is DontWrapRows.
+
+ If you want to display each label above its associated field
+ (instead of next to it), set this property to WrapAllRows.
+
+ \sa fieldGrowthPolicy
+*/
+
+void QFormLayout::setRowWrapPolicy(RowWrapPolicy policy)
+{
+ Q_D(QFormLayout);
+ if (RowWrapPolicy(d->rowWrapPolicy) != policy) {
+ d->rowWrapPolicy = policy;
+ invalidate();
+ }
+}
+
+QFormLayout::RowWrapPolicy QFormLayout::rowWrapPolicy() const
+{
+ Q_D(const QFormLayout);
+ if (d->rowWrapPolicy == DefaultRowWrapPolicy) {
+ return QFormLayout::RowWrapPolicy(d->getStyle()->styleHint(QStyle::SH_FormLayoutWrapPolicy));
+ } else {
+ return QFormLayout::RowWrapPolicy(d->rowWrapPolicy);
+ }
+}
+
+/*!
+ \property QFormLayout::labelAlignment
+ \brief the horizontal alignment of the labels
+
+ The default value depends on the widget or application style. For
+ QCommonStyle derived styles, except for QPlastiqueStyle, the
+ default is Qt::AlignLeft; for the other styles, the default is
+ Qt::AlignRight.
+
+ \sa formAlignment
+*/
+
+void QFormLayout::setLabelAlignment(Qt::Alignment alignment)
+{
+ Q_D(QFormLayout);
+ if (d->labelAlignment != alignment) {
+ d->labelAlignment = alignment;
+ invalidate();
+ }
+}
+
+Qt::Alignment QFormLayout::labelAlignment() const
+{
+ Q_D(const QFormLayout);
+ if (!d->labelAlignment) {
+ return Qt::Alignment(d->getStyle()->styleHint(QStyle::SH_FormLayoutLabelAlignment));
+ } else {
+ return d->labelAlignment;
+ }
+}
+
+/*!
+ \property QFormLayout::formAlignment
+ \brief the alignment of the form layout's contents within the layout's geometry
+
+ The default value depends on the widget or application style. For
+ QMacStyle, the default is Qt::AlignHCenter | Qt::AlignTop; for the
+ other styles, the default is Qt::AlignLeft | Qt::AlignTop.
+
+ \sa labelAlignment, rowWrapPolicy
+*/
+
+void QFormLayout::setFormAlignment(Qt::Alignment alignment)
+{
+ Q_D(QFormLayout);
+ if (d->formAlignment != alignment) {
+ d->formAlignment = alignment;
+ invalidate();
+ }
+}
+
+Qt::Alignment QFormLayout::formAlignment() const
+{
+ Q_D(const QFormLayout);
+ if (!d->formAlignment) {
+ return Qt::Alignment(d->getStyle()->styleHint(QStyle::SH_FormLayoutFormAlignment));
+ } else {
+ return d->formAlignment;
+ }
+}
+
+/*!
+ \property QFormLayout::horizontalSpacing
+ \brief the spacing between widgets that are laid out side by side
+
+ By default, if no value is explicitly set, the layout's horizontal
+ spacing is inherited from the parent layout, or from the style settings
+ for the parent widget.
+
+ \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QFormLayout::setHorizontalSpacing(int spacing)
+{
+ Q_D(QFormLayout);
+ if (spacing != d->hSpacing) {
+ d->hSpacing = spacing;
+ invalidate();
+ }
+}
+
+int QFormLayout::horizontalSpacing() const
+{
+ Q_D(const QFormLayout);
+ if (d->hSpacing >= 0) {
+ return d->hSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
+ }
+}
+
+/*!
+ \property QFormLayout::verticalSpacing
+ \brief the spacing between widgets that are laid out vertically
+
+ By default, if no value is explicitly set, the layout's vertical spacing is
+ inherited from the parent layout, or from the style settings for the parent
+ widget.
+
+ \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QFormLayout::setVerticalSpacing(int spacing)
+{
+ Q_D(QFormLayout);
+ if (spacing != d->vSpacing) {
+ d->vSpacing = spacing;
+ invalidate();
+ }
+}
+
+int QFormLayout::verticalSpacing() const
+{
+ Q_D(const QFormLayout);
+ if (d->vSpacing >= 0) {
+ return d->vSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
+ }
+}
+
+/*!
+ This function sets both the vertical and horizontal spacing to
+ \a spacing.
+
+ \sa setVerticalSpacing(), setHorizontalSpacing()
+*/
+void QFormLayout::setSpacing(int spacing)
+{
+ Q_D(QFormLayout);
+ d->vSpacing = d->hSpacing = spacing;
+ invalidate();
+}
+
+/*!
+ If the vertical spacing is equal to the horizontal spacing,
+ this function returns that value; otherwise it returns -1.
+
+ \sa setSpacing(), verticalSpacing(), horizontalSpacing()
+*/
+int QFormLayout::spacing() const
+{
+ int hSpacing = horizontalSpacing();
+ if (hSpacing == verticalSpacing()) {
+ return hSpacing;
+ } else {
+ return -1;
+ }
+}
+
+void QFormLayoutPrivate::arrangeWidgets(const QVector<QLayoutStruct>& layouts, QRect &rect)
+{
+ Q_Q(QFormLayout);
+
+ int i;
+ const int rr = m_matrix.rowCount();
+ QWidget *w = q->parentWidget();
+ Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QApplication::layoutDirection();
+
+ Qt::Alignment formAlignment = fixedAlignment(q->formAlignment(), layoutDirection);
+ int leftOffset = 0;
+ int delta = rect.width() - formMaxWidth;
+ if (formAlignment & (Qt::AlignHCenter | Qt::AlignRight) && delta > 0) {
+ leftOffset = delta;
+ if (formAlignment & Qt::AlignHCenter)
+ leftOffset >>= 1;
+ }
+
+ for (i = 0; i < rr; ++i) {
+ QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *field = m_matrix(i, 1);
+
+ if (label) {
+ int height = layouts.at(label->vLayoutIndex).size;
+ if ((label->expandingDirections() & Qt::Vertical) == 0) {
+ /*
+ If the field on the right-hand side is tall,
+ we want the label to be top-aligned, but not too
+ much. So we introduce a 5 / 4 factor so that it
+ gets a few extra pixels at the top.
+ */
+ height = qMin(height,
+ qMin(label->sizeHint.height() * 5 / 4,
+ label->maxSize.height()));
+ }
+
+ QSize sz(qMin(label->layoutWidth, label->sizeHint.width()), height);
+ int x = leftOffset + rect.x() + label->layoutPos;
+ if (fixedAlignment(q->labelAlignment(), layoutDirection) & Qt::AlignRight)
+ x += label->layoutWidth - sz.width();
+ QPoint p(x, layouts.at(label->vLayoutIndex).pos);
+ // ### expansion & sizepolicy stuff
+
+ label->setGeometry(QStyle::visualRect(layoutDirection, rect, QRect(p, sz)));
+ }
+
+ if (field) {
+ QSize sz(field->layoutWidth, layouts.at(field->vLayoutIndex).size);
+ QPoint p(field->layoutPos + leftOffset + rect.x(), layouts.at(field->vLayoutIndex).pos);
+/*
+ if ((field->widget() && field->widget()->sizePolicy().horizontalPolicy() & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag | QSizePolicy::IgnoreFlag))
+ || (field->layout() && sz.width() < field->maxSize.width())) {
+ sz.rwidth() = field->layoutWidth;
+ }
+*/
+ if (field->maxSize.isValid())
+ sz = sz.boundedTo(field->maxSize);
+
+ field->setGeometry(QStyle::visualRect(layoutDirection, rect, QRect(p, sz)));
+ }
+ }
+}
+
+/*!
+ Sets the widget in the given \a row for the given \a role to \a widget, extending the
+ layout with empty rows if necessary.
+
+ If the cell is already occupied, the \a widget is not inserted and an error message is
+ sent to the console.
+
+ \bold{Note:} For most applications, addRow() or insertRow() should be used instead of setWidget().
+
+ \sa setLayout()
+*/
+void QFormLayout::setWidget(int row, ItemRole role, QWidget *widget)
+{
+ Q_D(QFormLayout);
+ int rowCnt = rowCount();
+ if (row >= rowCnt)
+ d->insertRows(rowCnt, row - rowCnt + 1);
+ d->setWidget(row, role, widget);
+}
+
+/*!
+ Sets the sub-layout in the given \a row for the given \a role to \a layout, extending the
+ form layout with empty rows if necessary.
+
+ If the cell is already occupied, the \a layout is not inserted and an error message is
+ sent to the console.
+
+ \bold{Note:} For most applications, addRow() or insertRow() should be used instead of setLayout().
+
+ \sa setWidget()
+*/
+void QFormLayout::setLayout(int row, ItemRole role, QLayout *layout)
+{
+ Q_D(QFormLayout);
+ int rowCnt = rowCount();
+ if (row >= rowCnt)
+ d->insertRows(rowCnt, row - rowCnt + 1);
+ d->setLayout(row, role, layout);
+}
+
+/*!
+ Sets the item in the given \a row for the given \a role to \a item, extending the
+ layout with empty rows if necessary.
+
+ If the cell is already occupied, the \a item is not inserted and an error message is
+ sent to the console.
+ The \a item spans both columns.
+
+ \warning Do not use this function to add child layouts or child
+ widget items. Use setLayout() or setWidget() instead.
+
+ \sa setLayout()
+*/
+void QFormLayout::setItem(int row, ItemRole role, QLayoutItem *item)
+{
+ Q_D(QFormLayout);
+ int rowCnt = rowCount();
+ if (row >= rowCnt)
+ d->insertRows(rowCnt, row - rowCnt + 1);
+ d->setItem(row, role, item);
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetFieldGrowthPolicy()
+{
+ Q_D(QFormLayout);
+ d->fieldGrowthPolicy = DefaultFieldGrowthPolicy;
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetRowWrapPolicy()
+{
+ Q_D(QFormLayout);
+ d->rowWrapPolicy = DefaultRowWrapPolicy;
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetFormAlignment()
+{
+ Q_D(QFormLayout);
+ d->formAlignment = 0;
+}
+
+/*!
+ \internal
+ */
+
+void QFormLayout::resetLabelAlignment()
+{
+ Q_D(QFormLayout);
+ d->labelAlignment = 0;
+}
+
+#if 0
+void QFormLayout::dump() const
+{
+ Q_D(const QFormLayout);
+ for (int i = 0; i < rowCount(); ++i) {
+ for (int j = 0; j < 2; ++j) {
+ qDebug("m_matrix(%d, %d) = %p", i, j, d->m_matrix(i, j));
+ }
+ }
+ for (int i = 0; i < d->m_things.count(); ++i)
+ qDebug("m_things[%d] = %p", i, d->m_things.at(i));
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qformlayout.h b/src/gui/kernel/qformlayout.h
new file mode 100644
index 0000000000..e787f0f810
--- /dev/null
+++ b/src/gui/kernel/qformlayout.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFORMLAYOUT_H
+#define QFORMLAYOUT_H
+
+#include <QtGui/QLayout>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QFormLayoutPrivate;
+
+class Q_GUI_EXPORT QFormLayout : public QLayout
+{
+ Q_OBJECT
+ Q_ENUMS(FormStyle FieldGrowthPolicy RowWrapPolicy ItemRole)
+ Q_DECLARE_PRIVATE(QFormLayout)
+ Q_PROPERTY(FieldGrowthPolicy fieldGrowthPolicy READ fieldGrowthPolicy WRITE setFieldGrowthPolicy RESET resetFieldGrowthPolicy)
+ Q_PROPERTY(RowWrapPolicy rowWrapPolicy READ rowWrapPolicy WRITE setRowWrapPolicy RESET resetRowWrapPolicy)
+ Q_PROPERTY(Qt::Alignment labelAlignment READ labelAlignment WRITE setLabelAlignment RESET resetLabelAlignment)
+ Q_PROPERTY(Qt::Alignment formAlignment READ formAlignment WRITE setFormAlignment RESET resetFormAlignment)
+ Q_PROPERTY(int horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ Q_PROPERTY(int verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+
+public:
+ enum FieldGrowthPolicy {
+ FieldsStayAtSizeHint,
+ ExpandingFieldsGrow,
+ AllNonFixedFieldsGrow
+ };
+
+ enum RowWrapPolicy {
+ DontWrapRows,
+ WrapLongRows,
+ WrapAllRows
+ };
+
+ enum ItemRole {
+ LabelRole = 0,
+ FieldRole = 1,
+ SpanningRole = 2
+ };
+
+ explicit QFormLayout(QWidget *parent = 0);
+ ~QFormLayout();
+
+ void setFieldGrowthPolicy(FieldGrowthPolicy policy);
+ FieldGrowthPolicy fieldGrowthPolicy() const;
+ void setRowWrapPolicy(RowWrapPolicy policy);
+ RowWrapPolicy rowWrapPolicy() const;
+ void setLabelAlignment(Qt::Alignment alignment);
+ Qt::Alignment labelAlignment() const;
+ void setFormAlignment(Qt::Alignment alignment);
+ Qt::Alignment formAlignment() const;
+
+ void setHorizontalSpacing(int spacing);
+ int horizontalSpacing() const;
+ void setVerticalSpacing(int spacing);
+ int verticalSpacing() const;
+
+ int spacing() const;
+ void setSpacing(int);
+
+ void addRow(QWidget *label, QWidget *field);
+ void addRow(QWidget *label, QLayout *field);
+ void addRow(const QString &labelText, QWidget *field);
+ void addRow(const QString &labelText, QLayout *field);
+ void addRow(QWidget *widget);
+ void addRow(QLayout *layout);
+
+ void insertRow(int row, QWidget *label, QWidget *field);
+ void insertRow(int row, QWidget *label, QLayout *field);
+ void insertRow(int row, const QString &labelText, QWidget *field);
+ void insertRow(int row, const QString &labelText, QLayout *field);
+ void insertRow(int row, QWidget *widget);
+ void insertRow(int row, QLayout *layout);
+
+ void setItem(int row, ItemRole role, QLayoutItem *item);
+ void setWidget(int row, ItemRole role, QWidget *widget);
+ void setLayout(int row, ItemRole role, QLayout *layout);
+
+ QLayoutItem *itemAt(int row, ItemRole role) const;
+ void getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const;
+ void getWidgetPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const;
+ void getLayoutPosition(QLayout *layout, int *rowPtr, ItemRole *rolePtr) const;
+ QWidget *labelForField(QWidget *field) const;
+ QWidget *labelForField(QLayout *field) const;
+
+ // reimplemented from QLayout
+ void addItem(QLayoutItem *item);
+ QLayoutItem *itemAt(int index) const;
+ QLayoutItem *takeAt(int index);
+
+ void setGeometry(const QRect &rect);
+ QSize minimumSize() const;
+ QSize sizeHint() const;
+ void invalidate();
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int width) const;
+ Qt::Orientations expandingDirections() const;
+ int count() const;
+
+ int rowCount() const;
+
+#if 0
+ void dump() const;
+#endif
+
+private:
+ void resetFieldGrowthPolicy();
+ void resetRowWrapPolicy();
+ void resetLabelAlignment();
+ void resetFormAlignment();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp
new file mode 100644
index 0000000000..f872829725
--- /dev/null
+++ b/src/gui/kernel/qgridlayout.cpp
@@ -0,0 +1,1889 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgridlayout.h"
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qlist.h"
+#include "qsizepolicy.h"
+#include "qvector.h"
+#include "qvarlengtharray.h"
+#include "qlayoutengine_p.h"
+#include "qlayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QGridLayoutSizeTriple
+{
+ QSize minS;
+ QSize hint;
+ QSize maxS;
+};
+
+/*
+ Three internal classes related to QGridLayout: (1) QGridBox is a
+ QLayoutItem with (row, column) information and (torow, tocolumn) information; (3) QGridLayoutData is
+ the internal representation of a QGridLayout.
+*/
+
+class QGridBox
+{
+public:
+ QGridBox(QLayoutItem *lit) { item_ = lit; }
+
+ QGridBox(const QLayout *l, QWidget *wid) { item_ = QLayoutPrivate::createWidgetItem(l, wid); }
+ ~QGridBox() { delete item_; }
+
+ QSize sizeHint() const { return item_->sizeHint(); }
+ QSize minimumSize() const { return item_->minimumSize(); }
+ QSize maximumSize() const { return item_->maximumSize(); }
+ Qt::Orientations expandingDirections() const { return item_->expandingDirections(); }
+ bool isEmpty() const { return item_->isEmpty(); }
+
+ bool hasHeightForWidth() const { return item_->hasHeightForWidth(); }
+ int heightForWidth(int w) const { return item_->heightForWidth(w); }
+
+ void setAlignment(Qt::Alignment a) { item_->setAlignment(a); }
+ void setGeometry(const QRect &r) { item_->setGeometry(r); }
+ Qt::Alignment alignment() const { return item_->alignment(); }
+ QLayoutItem *item() { return item_; }
+ QLayoutItem *takeItem() { QLayoutItem *i = item_; item_ = 0; return i; }
+
+ int hStretch() { return item_->widget() ?
+ item_->widget()->sizePolicy().horizontalStretch() : 0; }
+ int vStretch() { return item_->widget() ?
+ item_->widget()->sizePolicy().verticalStretch() : 0; }
+
+private:
+ friend class QGridLayoutPrivate;
+ friend class QGridLayout;
+
+ inline int toRow(int rr) const { return torow >= 0 ? torow : rr - 1; }
+ inline int toCol(int cc) const { return tocol >= 0 ? tocol : cc - 1; }
+
+ QLayoutItem *item_;
+ int row, col;
+ int torow, tocol;
+};
+
+class QGridLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QGridLayout)
+public:
+ QGridLayoutPrivate();
+
+ void add(QGridBox*, int row, int col);
+ void add(QGridBox*, int row1, int row2, int col1, int col2);
+ QSize sizeHint(int hSpacing, int vSpacing) const;
+ QSize minimumSize(int hSpacing, int vSpacing) const;
+ QSize maximumSize(int hSpacing, int vSpacing) const;
+
+ Qt::Orientations expandingDirections(int hSpacing, int vSpacing) const;
+
+ void distribute(QRect rect, int hSpacing, int vSpacing);
+ inline int numRows() const { return rr; }
+ inline int numCols() const { return cc; }
+ inline void expand(int rows, int cols)
+ { setSize(qMax(rows, rr), qMax(cols, cc)); }
+ inline void setRowStretch(int r, int s)
+ { expand(r + 1, 0); rStretch[r] = s; setDirty(); }
+ inline void setColStretch(int c, int s)
+ { expand(0, c + 1); cStretch[c] = s; setDirty(); }
+ inline int rowStretch(int r) const { return rStretch.at(r); }
+ inline int colStretch(int c) const { return cStretch.at(c); }
+ inline void setRowMinimumHeight(int r, int s)
+ { expand(r + 1, 0); rMinHeights[r] = s; setDirty(); }
+ inline void setColumnMinimumWidth(int c, int s)
+ { expand(0, c + 1); cMinWidths[c] = s; setDirty(); }
+ inline int rowSpacing(int r) const { return rMinHeights.at(r); }
+ inline int colSpacing(int c) const { return cMinWidths.at(c); }
+
+ inline void setReversed(bool r, bool c) { hReversed = c; vReversed = r; }
+ inline bool horReversed() const { return hReversed; }
+ inline bool verReversed() const { return vReversed; }
+ inline void setDirty() { needRecalc = true; hfw_width = -1; }
+ inline bool isDirty() const { return needRecalc; }
+ bool hasHeightForWidth(int hSpacing, int vSpacing);
+ int heightForWidth(int width, int hSpacing, int vSpacing);
+ int minimumHeightForWidth(int width, int hSpacing, int vSpacing);
+
+ inline void getNextPos(int &row, int &col) { row = nextR; col = nextC; }
+ inline int count() const { return things.count(); }
+ QRect cellRect(int row, int col) const;
+
+ inline QLayoutItem *itemAt(int index) const {
+ if (index < things.count())
+ return things.at(index)->item();
+ else
+ return 0;
+ }
+ inline QLayoutItem *takeAt(int index) {
+ QLayoutItem *item = 0;
+ if (index < things.count()) {
+ QGridBox *b = things.takeAt(index);
+ if (b) {
+ item = b->takeItem();
+ delete b;
+ }
+ }
+ return item;
+ }
+
+ void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) {
+ if (index < things.count()) {
+ QGridBox *b = things.at(index);
+ int toRow = b->toRow(rr);
+ int toCol = b->toCol(cc);
+ *row = b->row;
+ *column = b->col;
+ *rowSpan = toRow - *row + 1;
+ *columnSpan = toCol - *column +1;
+ }
+ }
+ void deleteAll();
+
+private:
+ void setNextPosAfter(int r, int c);
+ void recalcHFW(int w);
+ void addHfwData(QGridBox *box, int width);
+ void init();
+ QSize findSize(int QLayoutStruct::*, int hSpacing, int vSpacing) const;
+ void addData(QGridBox *b, const QGridLayoutSizeTriple &sizes, bool r, bool c);
+ void setSize(int rows, int cols);
+ void setupSpacings(QVector<QLayoutStruct> &chain, QGridBox *grid[], int fixedSpacing,
+ Qt::Orientation orientation);
+ void setupLayoutData(int hSpacing, int vSpacing);
+ void setupHfwLayoutData();
+ void effectiveMargins(int *left, int *top, int *right, int *bottom) const;
+
+ int rr;
+ int cc;
+ QVector<QLayoutStruct> rowData;
+ QVector<QLayoutStruct> colData;
+ QVector<QLayoutStruct> *hfwData;
+ QVector<int> rStretch;
+ QVector<int> cStretch;
+ QVector<int> rMinHeights;
+ QVector<int> cMinWidths;
+ QList<QGridBox *> things;
+
+ int hfw_width;
+ int hfw_height;
+ int hfw_minheight;
+ int nextR;
+ int nextC;
+
+ int horizontalSpacing;
+ int verticalSpacing;
+ int leftMargin;
+ int topMargin;
+ int rightMargin;
+ int bottomMargin;
+
+ uint hReversed : 1;
+ uint vReversed : 1;
+ uint needRecalc : 1;
+ uint has_hfw : 1;
+ uint addVertical : 1;
+};
+
+void QGridLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *bottom) const
+{
+ int l = leftMargin;
+ int t = topMargin;
+ int r = rightMargin;
+ int b = bottomMargin;
+#ifdef Q_WS_MAC
+ int leftMost = INT_MAX;
+ int topMost = INT_MAX;
+ int rightMost = 0;
+ int bottomMost = 0;
+
+ QWidget *w = 0;
+ const int n = things.count();
+ for (int i = 0; i < n; ++i) {
+ QGridBox *box = things.at(i);
+ QLayoutItem *itm = box->item();
+ w = itm->widget();
+ if (w) {
+ bool visualHReversed = hReversed != (w->layoutDirection() == Qt::RightToLeft);
+ QRect lir = itm->geometry();
+ QRect wr = w->geometry();
+ if (box->col <= leftMost) {
+ if (box->col < leftMost) {
+ // we found an item even closer to the margin, discard.
+ leftMost = box->col;
+ if (visualHReversed)
+ r = rightMargin;
+ else
+ l = leftMargin;
+ }
+ if (visualHReversed) {
+ r = qMax(r, wr.right() - lir.right());
+ } else {
+ l = qMax(l, lir.left() - wr.left());
+ }
+ }
+ if (box->row <= topMost) {
+ if (box->row < topMost) {
+ // we found an item even closer to the margin, discard.
+ topMost = box->row;
+ if (vReversed)
+ b = bottomMargin;
+ else
+ t = topMargin;
+ }
+ if (vReversed)
+ b = qMax(b, wr.bottom() - lir.bottom());
+ else
+ t = qMax(t, lir.top() - wr.top());
+ }
+ if (box->toCol(cc) >= rightMost) {
+ if (box->toCol(cc) > rightMost) {
+ // we found an item even closer to the margin, discard.
+ rightMost = box->toCol(cc);
+ if (visualHReversed)
+ l = leftMargin;
+ else
+ r = rightMargin;
+ }
+ if (visualHReversed) {
+ l = qMax(l, lir.left() - wr.left());
+ } else {
+ r = qMax(r, wr.right() - lir.right());
+ }
+
+ }
+ if (box->toRow(rr) >= bottomMost) {
+ if (box->toRow(rr) > bottomMost) {
+ // we found an item even closer to the margin, discard.
+ bottomMost = box->toRow(rr);
+ if (vReversed)
+ t = topMargin;
+ else
+ b = bottomMargin;
+ }
+ if (vReversed)
+ t = qMax(t, lir.top() - wr.top());
+ else
+ b = qMax(b, wr.bottom() - lir.bottom());
+ }
+ }
+ }
+
+#endif
+ if (left)
+ *left = l;
+ if (top)
+ *top = t;
+ if (right)
+ *right = r;
+ if (bottom)
+ *bottom = b;
+}
+
+QGridLayoutPrivate::QGridLayoutPrivate()
+{
+ addVertical = false;
+ setDirty();
+ rr = cc = 0;
+ nextR = nextC = 0;
+ hfwData = 0;
+ hReversed = false;
+ vReversed = false;
+ horizontalSpacing = -1;
+ verticalSpacing = -1;
+}
+
+#if 0
+QGridLayoutPrivate::QGridLayoutPrivate(int nRows, int nCols)
+ : rowData(0), colData(0)
+{
+ init();
+ if (nRows < 0) {
+ nRows = 1;
+ addVertical = false;
+ }
+ if (nCols < 0) {
+ nCols = 1;
+ addVertical = true;
+ }
+ setSize(nRows, nCols);
+}
+#endif
+
+void QGridLayoutPrivate::deleteAll()
+{
+ while (!things.isEmpty())
+ delete things.takeFirst();
+ delete hfwData;
+}
+
+bool QGridLayoutPrivate::hasHeightForWidth(int hSpacing, int vSpacing)
+{
+ setupLayoutData(hSpacing, vSpacing);
+ return has_hfw;
+}
+
+/*
+ Assumes that setupLayoutData() has been called, and that
+ qGeomCalc() has filled in colData with appropriate values.
+*/
+void QGridLayoutPrivate::recalcHFW(int w)
+{
+ /*
+ Go through all children, using colData and heightForWidth()
+ and put the results in hfwData.
+ */
+ if (!hfwData)
+ hfwData = new QVector<QLayoutStruct>(rr);
+ setupHfwLayoutData();
+ QVector<QLayoutStruct> &rData = *hfwData;
+
+ int h = 0;
+ int mh = 0;
+ for (int r = 0; r < rr; r++) {
+ int spacing = rData.at(r).spacing;
+ h += rData.at(r).sizeHint + spacing;
+ mh += rData.at(r).minimumSize + spacing;
+ }
+
+ hfw_width = w;
+ hfw_height = qMin(QLAYOUTSIZE_MAX, h);
+ hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);
+}
+
+int QGridLayoutPrivate::heightForWidth(int w, int hSpacing, int vSpacing)
+{
+ setupLayoutData(hSpacing, vSpacing);
+ if (!has_hfw)
+ return -1;
+ int left, top, right, bottom;
+ effectiveMargins(&left, &top, &right, &bottom);
+
+ int hMargins = left + right;
+ if (w - hMargins != hfw_width) {
+ qGeomCalc(colData, 0, cc, 0, w - hMargins);
+ recalcHFW(w - hMargins);
+ }
+ return hfw_height + top + bottom;
+}
+
+int QGridLayoutPrivate::minimumHeightForWidth(int w, int hSpacing, int vSpacing)
+{
+ (void)heightForWidth(w, hSpacing, vSpacing);
+ if (!has_hfw)
+ return -1;
+ int top, bottom;
+ effectiveMargins(0, &top, 0, &bottom);
+ return hfw_minheight + top + bottom;
+}
+
+QSize QGridLayoutPrivate::findSize(int QLayoutStruct::*size, int hSpacing, int vSpacing) const
+{
+ QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
+ that->setupLayoutData(hSpacing, vSpacing);
+
+ int w = 0;
+ int h = 0;
+
+ for (int r = 0; r < rr; r++)
+ h += rowData.at(r).*size + rowData.at(r).spacing;
+ for (int c = 0; c < cc; c++)
+ w += colData.at(c).*size + colData.at(c).spacing;
+
+ w = qMin(QLAYOUTSIZE_MAX, w);
+ h = qMin(QLAYOUTSIZE_MAX, h);
+
+ return QSize(w, h);
+}
+
+Qt::Orientations QGridLayoutPrivate::expandingDirections(int hSpacing, int vSpacing) const
+{
+ QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
+ that->setupLayoutData(hSpacing, vSpacing);
+ Qt::Orientations ret;
+
+ for (int r = 0; r < rr; r++) {
+ if (rowData.at(r).expansive) {
+ ret |= Qt::Vertical;
+ break;
+ }
+ }
+ for (int c = 0; c < cc; c++) {
+ if (colData.at(c).expansive) {
+ ret |= Qt::Horizontal;
+ break;
+ }
+ }
+ return ret;
+}
+
+QSize QGridLayoutPrivate::sizeHint(int hSpacing, int vSpacing) const
+{
+ return findSize(&QLayoutStruct::sizeHint, hSpacing, vSpacing);
+}
+
+QSize QGridLayoutPrivate::maximumSize(int hSpacing, int vSpacing) const
+{
+ return findSize(&QLayoutStruct::maximumSize, hSpacing, vSpacing);
+}
+
+QSize QGridLayoutPrivate::minimumSize(int hSpacing, int vSpacing) const
+{
+ return findSize(&QLayoutStruct::minimumSize, hSpacing, vSpacing);
+}
+
+void QGridLayoutPrivate::setSize(int r, int c)
+{
+ if ((int)rowData.size() < r) {
+ int newR = qMax(r, rr * 2);
+ rowData.resize(newR);
+ rStretch.resize(newR);
+ rMinHeights.resize(newR);
+ for (int i = rr; i < newR; i++) {
+ rowData[i].init();
+ rowData[i].maximumSize = 0;
+ rowData[i].pos = 0;
+ rowData[i].size = 0;
+ rStretch[i] = 0;
+ rMinHeights[i] = 0;
+ }
+ }
+ if ((int)colData.size() < c) {
+ int newC = qMax(c, cc * 2);
+ colData.resize(newC);
+ cStretch.resize(newC);
+ cMinWidths.resize(newC);
+ for (int i = cc; i < newC; i++) {
+ colData[i].init();
+ colData[i].maximumSize = 0;
+ colData[i].pos = 0;
+ colData[i].size = 0;
+ cStretch[i] = 0;
+ cMinWidths[i] = 0;
+ }
+ }
+
+ if (hfwData && (int)hfwData->size() < r) {
+ delete hfwData;
+ hfwData = 0;
+ hfw_width = -1;
+ }
+ rr = r;
+ cc = c;
+}
+
+void QGridLayoutPrivate::setNextPosAfter(int row, int col)
+{
+ if (addVertical) {
+ if (col > nextC || (col == nextC && row >= nextR)) {
+ nextR = row + 1;
+ nextC = col;
+ if (nextR >= rr) {
+ nextR = 0;
+ nextC++;
+ }
+ }
+ } else {
+ if (row > nextR || (row == nextR && col >= nextC)) {
+ nextR = row;
+ nextC = col + 1;
+ if (nextC >= cc) {
+ nextC = 0;
+ nextR++;
+ }
+ }
+ }
+}
+
+void QGridLayoutPrivate::add(QGridBox *box, int row, int col)
+{
+ expand(row + 1, col + 1);
+ box->row = box->torow = row;
+ box->col = box->tocol = col;
+ things.append(box);
+ setDirty();
+ setNextPosAfter(row, col);
+}
+
+void QGridLayoutPrivate::add(QGridBox *box, int row1, int row2, int col1, int col2)
+{
+ if (row2 >= 0 && row2 < row1)
+ qWarning("QGridLayout: Multi-cell fromRow greater than toRow");
+ if (col2 >= 0 && col2 < col1)
+ qWarning("QGridLayout: Multi-cell fromCol greater than toCol");
+ if (row1 == row2 && col1 == col2) {
+ add(box, row1, col1);
+ return;
+ }
+ expand(row2 + 1, col2 + 1);
+ box->row = row1;
+ box->col = col1;
+
+ box->torow = row2;
+ box->tocol = col2;
+
+ things.append(box);
+ setDirty();
+ if (col2 < 0)
+ col2 = cc - 1;
+
+ setNextPosAfter(row2, col2);
+}
+
+void QGridLayoutPrivate::addData(QGridBox *box, const QGridLayoutSizeTriple &sizes, bool r, bool c)
+{
+ const QWidget *widget = box->item()->widget();
+
+ if (box->isEmpty() && widget)
+ return;
+
+ if (c) {
+ QLayoutStruct *data = &colData[box->col];
+ if (!cStretch.at(box->col))
+ data->stretch = qMax(data->stretch, box->hStretch());
+ data->sizeHint = qMax(sizes.hint.width(), data->sizeHint);
+ data->minimumSize = qMax(sizes.minS.width(), data->minimumSize);
+
+ qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.width(),
+ box->expandingDirections() & Qt::Horizontal, box->isEmpty());
+ }
+ if (r) {
+ QLayoutStruct *data = &rowData[box->row];
+ if (!rStretch.at(box->row))
+ data->stretch = qMax(data->stretch, box->vStretch());
+ data->sizeHint = qMax(sizes.hint.height(), data->sizeHint);
+ data->minimumSize = qMax(sizes.minS.height(), data->minimumSize);
+
+ qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.height(),
+ box->expandingDirections() & Qt::Vertical, box->isEmpty());
+ }
+}
+
+static void initEmptyMultiBox(QVector<QLayoutStruct> &chain, int start, int end)
+{
+ for (int i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->empty && data->maximumSize == 0) // truly empty box
+ data->maximumSize = QWIDGETSIZE_MAX;
+ data->empty = false;
+ }
+}
+
+static void distributeMultiBox(QVector<QLayoutStruct> &chain, int start, int end, int minSize,
+ int sizeHint, QVector<int> &stretchArray, int stretch)
+{
+ int i;
+ int w = 0;
+ int wh = 0;
+ int max = 0;
+
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ w += data->minimumSize;
+ wh += data->sizeHint;
+ max += data->maximumSize;
+ if (stretchArray.at(i) == 0)
+ data->stretch = qMax(data->stretch, stretch);
+
+ if (i != end) {
+ int spacing = data->spacing;
+ w += spacing;
+ wh += spacing;
+ max += spacing;
+ }
+ }
+
+ if (max < minSize) { // implies w < minSize
+ /*
+ We must increase the maximum size of at least one of the
+ items. qGeomCalc() will put the extra space in between the
+ items. We must recover that extra space and put it
+ somewhere. It does not really matter where, since the user
+ can always specify stretch factors and avoid this code.
+ */
+ qGeomCalc(chain, start, end - start + 1, 0, minSize);
+ int pos = 0;
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ int nextPos = (i == end) ? minSize : chain.at(i + 1).pos;
+ int realSize = nextPos - pos;
+ if (i != end)
+ realSize -= data->spacing;
+ if (data->minimumSize < realSize)
+ data->minimumSize = realSize;
+ if (data->maximumSize < data->minimumSize)
+ data->maximumSize = data->minimumSize;
+ pos = nextPos;
+ }
+ } else if (w < minSize) {
+ qGeomCalc(chain, start, end - start + 1, 0, minSize);
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->minimumSize < data->size)
+ data->minimumSize = data->size;
+ }
+ }
+
+ if (wh < sizeHint) {
+ qGeomCalc(chain, start, end - start + 1, 0, sizeHint);
+ for (i = start; i <= end; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->sizeHint < data->size)
+ data->sizeHint = data->size;
+ }
+ }
+}
+
+static QGridBox *&gridAt(QGridBox *grid[], int r, int c, int cc,
+ Qt::Orientation orientation = Qt::Vertical)
+{
+ if (orientation == Qt::Horizontal)
+ qSwap(r, c);
+ return grid[(r * cc) + c];
+}
+
+void QGridLayoutPrivate::setupSpacings(QVector<QLayoutStruct> &chain,
+ QGridBox *grid[], int fixedSpacing,
+ Qt::Orientation orientation)
+{
+ Q_Q(QGridLayout);
+ int numRows = rr; // or columns if orientation is horizontal
+ int numColumns = cc; // or rows if orientation is horizontal
+
+ if (orientation == Qt::Horizontal) {
+ qSwap(numRows, numColumns);
+ }
+
+ QStyle *style = 0;
+ if (fixedSpacing < 0) {
+ if (QWidget *parentWidget = q->parentWidget())
+ style = parentWidget->style();
+ }
+
+ for (int c = 0; c < numColumns; ++c) {
+ QGridBox *previousBox = 0;
+ int previousRow = -1; // previous *non-empty* row
+
+ for (int r = 0; r < numRows; ++r) {
+ if (chain.at(r).empty)
+ continue;
+
+ QGridBox *box = gridAt(grid, r, c, cc, orientation);
+ if (previousRow != -1 && (!box || previousBox != box)) {
+ int spacing = fixedSpacing;
+ if (spacing < 0) {
+ QSizePolicy::ControlTypes controlTypes1 = QSizePolicy::DefaultType;
+ QSizePolicy::ControlTypes controlTypes2 = QSizePolicy::DefaultType;
+ if (previousBox)
+ controlTypes1 = previousBox->item()->controlTypes();
+ if (box)
+ controlTypes2 = box->item()->controlTypes();
+
+ if ((orientation == Qt::Horizontal && hReversed)
+ || (orientation == Qt::Vertical && vReversed))
+ qSwap(controlTypes1, controlTypes2);
+
+ if (style)
+ spacing = style->combinedLayoutSpacing(controlTypes1, controlTypes2,
+ orientation, 0, q->parentWidget());
+ } else {
+ if (orientation == Qt::Vertical) {
+ QGridBox *sibling = vReversed ? previousBox : box;
+ if (sibling) {
+ QWidget *wid = sibling->item()->widget();
+ if (wid)
+ spacing = qMax(spacing, sibling->item()->geometry().top() - wid->geometry().top() );
+ }
+ }
+ }
+
+ if (spacing > chain.at(previousRow).spacing)
+ chain[previousRow].spacing = spacing;
+ }
+
+ previousBox = box;
+ previousRow = r;
+ }
+ }
+}
+
+//#define QT_LAYOUT_DISABLE_CACHING
+
+void QGridLayoutPrivate::setupLayoutData(int hSpacing, int vSpacing)
+{
+ Q_Q(QGridLayout);
+
+#ifndef QT_LAYOUT_DISABLE_CACHING
+ if (!needRecalc)
+ return;
+#endif
+ has_hfw = false;
+ int i;
+
+ for (i = 0; i < rr; i++) {
+ rowData[i].init(rStretch.at(i), rMinHeights.at(i));
+ rowData[i].maximumSize = rStretch.at(i) ? QLAYOUTSIZE_MAX : rMinHeights.at(i);
+ }
+ for (i = 0; i < cc; i++) {
+ colData[i].init(cStretch.at(i), cMinWidths.at(i));
+ colData[i].maximumSize = cStretch.at(i) ? QLAYOUTSIZE_MAX : cMinWidths.at(i);
+ }
+
+ int n = things.size();
+ QVarLengthArray<QGridLayoutSizeTriple> sizes(n);
+
+ bool has_multi = false;
+
+ /*
+ Grid of items. We use it to determine which items are
+ adjacent to which and compute the spacings correctly.
+ */
+ QVarLengthArray<QGridBox *> grid(rr * cc);
+ qMemSet(grid.data(), 0, rr * cc * sizeof(QGridBox *));
+
+ /*
+ Initialize 'sizes' and 'grid' data structures, and insert
+ non-spanning items to our row and column data structures.
+ */
+ for (i = 0; i < n; ++i) {
+ QGridBox * const box = things.at(i);
+ sizes[i].minS = box->minimumSize();
+ sizes[i].hint = box->sizeHint();
+ sizes[i].maxS = box->maximumSize();
+
+ if (box->hasHeightForWidth())
+ has_hfw = true;
+
+ if (box->row == box->toRow(rr)) {
+ addData(box, sizes[i], true, false);
+ } else {
+ initEmptyMultiBox(rowData, box->row, box->toRow(rr));
+ has_multi = true;
+ }
+
+ if (box->col == box->toCol(cc)) {
+ addData(box, sizes[i], false, true);
+ } else {
+ initEmptyMultiBox(colData, box->col, box->toCol(cc));
+ has_multi = true;
+ }
+
+ for (int r = box->row; r <= box->toRow(rr); ++r) {
+ for (int c = box->col; c <= box->toCol(cc); ++c) {
+ gridAt(grid.data(), r, c, cc) = box;
+ }
+ }
+ }
+
+ setupSpacings(colData, grid.data(), hSpacing, Qt::Horizontal);
+ setupSpacings(rowData, grid.data(), vSpacing, Qt::Vertical);
+
+ /*
+ Insert multicell items to our row and column data structures.
+ This must be done after the non-spanning items to obtain a
+ better distribution in distributeMultiBox().
+ */
+ if (has_multi) {
+ for (i = 0; i < n; ++i) {
+ QGridBox * const box = things.at(i);
+
+ if (box->row != box->toRow(rr))
+ distributeMultiBox(rowData, box->row, box->toRow(rr), sizes[i].minS.height(),
+ sizes[i].hint.height(), rStretch, box->vStretch());
+ if (box->col != box->toCol(cc))
+ distributeMultiBox(colData, box->col, box->toCol(cc), sizes[i].minS.width(),
+ sizes[i].hint.width(), cStretch, box->hStretch());
+ }
+ }
+
+ for (i = 0; i < rr; i++)
+ rowData[i].expansive = rowData.at(i).expansive || rowData.at(i).stretch > 0;
+ for (i = 0; i < cc; i++)
+ colData[i].expansive = colData.at(i).expansive || colData.at(i).stretch > 0;
+
+ q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+
+ needRecalc = false;
+}
+
+void QGridLayoutPrivate::addHfwData(QGridBox *box, int width)
+{
+ QVector<QLayoutStruct> &rData = *hfwData;
+ if (box->hasHeightForWidth()) {
+ int hint = box->heightForWidth(width);
+ rData[box->row].sizeHint = qMax(hint, rData.at(box->row).sizeHint);
+ rData[box->row].minimumSize = qMax(hint, rData.at(box->row).minimumSize);
+ } else {
+ QSize hint = box->sizeHint();
+ QSize minS = box->minimumSize();
+ rData[box->row].sizeHint = qMax(hint.height(), rData.at(box->row).sizeHint);
+ rData[box->row].minimumSize = qMax(minS.height(), rData.at(box->row).minimumSize);
+ }
+}
+
+/*
+ Similar to setupLayoutData(), but uses heightForWidth(colData)
+ instead of sizeHint(). Assumes that setupLayoutData() and
+ qGeomCalc(colData) has been called.
+*/
+void QGridLayoutPrivate::setupHfwLayoutData()
+{
+ QVector<QLayoutStruct> &rData = *hfwData;
+ for (int i = 0; i < rr; i++) {
+ rData[i] = rowData.at(i);
+ rData[i].minimumSize = rData[i].sizeHint = rMinHeights.at(i);
+ }
+
+ for (int pass = 0; pass < 2; ++pass) {
+ for (int i = 0; i < things.size(); ++i) {
+ QGridBox *box = things.at(i);
+ int r1 = box->row;
+ int c1 = box->col;
+ int r2 = box->toRow(rr);
+ int c2 = box->toCol(cc);
+ int w = colData.at(c2).pos + colData.at(c2).size - colData.at(c1).pos;
+
+ if (r1 == r2) {
+ if (pass == 0)
+ addHfwData(box, w);
+ } else {
+ if (pass == 0) {
+ initEmptyMultiBox(rData, r1, r2);
+ } else {
+ QSize hint = box->sizeHint();
+ QSize min = box->minimumSize();
+ if (box->hasHeightForWidth()) {
+ int hfwh = box->heightForWidth(w);
+ if (hfwh > hint.height())
+ hint.setHeight(hfwh);
+ if (hfwh > min.height())
+ min.setHeight(hfwh);
+ }
+ distributeMultiBox(rData, r1, r2, min.height(), hint.height(),
+ rStretch, box->vStretch());
+ }
+ }
+ }
+ }
+ for (int i = 0; i < rr; i++)
+ rData[i].expansive = rData.at(i).expansive || rData.at(i).stretch > 0;
+}
+
+void QGridLayoutPrivate::distribute(QRect r, int hSpacing, int vSpacing)
+{
+ Q_Q(QGridLayout);
+ bool visualHReversed = hReversed;
+ QWidget *parent = q->parentWidget();
+ if (parent && parent->isRightToLeft())
+ visualHReversed = !visualHReversed;
+
+ setupLayoutData(hSpacing, vSpacing);
+
+ int left, top, right, bottom;
+ effectiveMargins(&left, &top, &right, &bottom);
+ r.adjust(+left, +top, -right, -bottom);
+
+ qGeomCalc(colData, 0, cc, r.x(), r.width());
+ QVector<QLayoutStruct> *rDataPtr;
+ if (has_hfw) {
+ recalcHFW(r.width());
+ qGeomCalc(*hfwData, 0, rr, r.y(), r.height());
+ rDataPtr = hfwData;
+ } else {
+ qGeomCalc(rowData, 0, rr, r.y(), r.height());
+ rDataPtr = &rowData;
+ }
+ QVector<QLayoutStruct> &rData = *rDataPtr;
+ int i;
+
+ bool reverse = ((r.bottom() > rect.bottom()) || (r.bottom() == rect.bottom()
+ && ((r.right() > rect.right()) != visualHReversed)));
+ int n = things.size();
+ for (i = 0; i < n; ++i) {
+ QGridBox *box = things.at(reverse ? n-i-1 : i);
+ int r2 = box->toRow(rr);
+ int c2 = box->toCol(cc);
+
+ int x = colData.at(box->col).pos;
+ int y = rData.at(box->row).pos;
+ int x2p = colData.at(c2).pos + colData.at(c2).size; // x2+1
+ int y2p = rData.at(r2).pos + rData.at(r2).size; // y2+1
+ int w = x2p - x;
+ int h = y2p - y;
+
+ if (visualHReversed)
+ x = r.left() + r.right() - x - w + 1;
+ if (vReversed)
+ y = r.top() + r.bottom() - y - h + 1;
+
+ box->setGeometry(QRect(x, y, w, h));
+ }
+}
+
+QRect QGridLayoutPrivate::cellRect(int row, int col) const
+{
+ if (row < 0 || row >= rr || col < 0 || col >= cc)
+ return QRect();
+
+ const QVector<QLayoutStruct> *rDataPtr;
+ if (has_hfw && hfwData)
+ rDataPtr = hfwData;
+ else
+ rDataPtr = &rowData;
+ return QRect(colData.at(col).pos, rDataPtr->at(row).pos,
+ colData.at(col).size, rDataPtr->at(row).size);
+}
+
+/*!
+ \class QGridLayout
+
+ \brief The QGridLayout class lays out widgets in a grid.
+
+ \ingroup geomanagement
+ \ingroup appearance
+ \mainclass
+
+ QGridLayout takes the space made available to it (by its parent
+ layout or by the parentWidget()), divides it up into rows and
+ columns, and puts each widget it manages into the correct cell.
+
+ Columns and rows behave identically; we will discuss columns, but
+ there are equivalent functions for rows.
+
+ Each column has a minimum width and a stretch factor. The minimum
+ width is the greatest of that set using setColumnMinimumWidth() and the
+ minimum width of each widget in that column. The stretch factor is
+ set using setColumnStretch() and determines how much of the available
+ space the column will get over and above its necessary minimum.
+
+ Normally, each managed widget or layout is put into a cell of its
+ own using addWidget(). It is also possible for a widget to occupy
+ multiple cells using the row and column spanning overloads of
+ addItem() and addWidget(). If you do this, QGridLayout will guess
+ how to distribute the size over the columns/rows (based on the
+ stretch factors).
+
+ To remove a widget from a layout, call removeWidget(). Calling
+ QWidget::hide() on a widget also effectively removes the widget
+ from the layout until QWidget::show() is called.
+
+ This illustration shows a fragment of a dialog with a five-column,
+ three-row grid (the grid is shown overlaid in magenta):
+
+ \image gridlayout.png A grid layout
+
+ Columns 0, 2 and 4 in this dialog fragment are made up of a
+ QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
+ placeholders made with setColumnMinimumWidth(). Row 0 consists of three
+ QLabel objects, row 1 of three QLineEdit objects and row 2 of
+ three QListBox objects. We used placeholder columns (1 and 3) to
+ get the right amount of space between the columns.
+
+ Note that the columns and rows are not equally wide or tall. If
+ you want two columns to have the same width, you must set their
+ minimum widths and stretch factors to be the same yourself. You do
+ this using setColumnMinimumWidth() and setColumnStretch().
+
+ If the QGridLayout is not the top-level layout (i.e. does not
+ manage all of the widget's area and children), you must add it to
+ its parent layout when you create it, but before you do anything
+ with it. The normal way to add a layout is by calling
+ addLayout() on the parent layout.
+
+ Once you have added your layout you can start putting widgets and
+ other layouts into the cells of your grid layout using
+ addWidget(), addItem(), and addLayout().
+
+ QGridLayout also includes two margin widths: the margin() and the
+ spacing(). The margin is the width of the reserved space along
+ each of the QGridLayout's four sides. The spacing is the width of
+ the automatically allocated spacing between neighboring boxes.
+
+ The default margin() and spacing() values are provided by the
+ style. The default margin Qt styles specify is 9 for child
+ widgets and 11 for windows. The spacing defaults to the same as
+ the margin width for a top-level layout, or to the same as the
+ parent layout.
+
+ \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+*/
+
+
+/*!
+ Constructs a new QGridLayout with parent widget, \a parent. The
+ layout has one row and one column initially, and will expand when
+ new items are inserted.
+*/
+QGridLayout::QGridLayout(QWidget *parent)
+ : QLayout(*new QGridLayoutPrivate, 0, parent)
+{
+ Q_D(QGridLayout);
+ d->expand(1, 1);
+}
+
+/*!
+ Constructs a new grid layout.
+
+ You must insert this grid into another layout. You can insert
+ widgets and layouts into this layout at any time, but laying out
+ will not be performed before this is inserted into another layout.
+*/
+QGridLayout::QGridLayout()
+ : QLayout(*new QGridLayoutPrivate, 0, 0)
+{
+ Q_D(QGridLayout);
+ d->expand(1, 1);
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+ Constructs a new QGridLayout with \a nRows rows, \a nCols columns
+ and parent widget, \a parent. \a parent may not be 0. The grid
+ layout is called \a name.
+
+ \a margin is the number of pixels between the edge of the widget
+ and its managed children. \a space is the default number of pixels
+ between cells. If \a space is -1, the value of \a margin is used.
+*/
+QGridLayout::QGridLayout(QWidget *parent, int nRows, int nCols, int margin,
+ int space, const char *name)
+ : QLayout(*new QGridLayoutPrivate, 0, parent)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+ setMargin(margin);
+ setSpacing(space < 0 ? margin : space);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ \obsolete
+
+ Constructs a new grid with \a nRows rows and \a nCols columns. If
+ \a spacing is -1, this QGridLayout inherits its parent's
+ spacing(); otherwise \a spacing is used. The grid layout is called
+ \a name.
+
+ You must insert this grid into another layout. You can insert
+ widgets and layouts into this layout at any time, but laying out
+ will not be performed before this is inserted into another layout.
+*/
+QGridLayout::QGridLayout(QLayout *parentLayout, int nRows, int nCols,
+ int spacing, const char *name)
+ : QLayout(*new QGridLayoutPrivate, parentLayout, 0)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+
+/*!
+ \obsolete
+
+ Constructs a new grid with \a nRows rows and \a nCols columns. If
+ \a spacing is -1, this QGridLayout inherits its parent's
+ spacing(); otherwise \a spacing is used. The grid layout is called
+ \a name.
+
+ You must insert this grid into another layout. You can insert
+ widgets and layouts into this layout at any time, but laying out
+ will not be performed before this is inserted into another layout.
+*/
+QGridLayout::QGridLayout(int nRows, int nCols, int spacing, const char *name)
+ : QLayout(*new QGridLayoutPrivate, 0, 0)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+ setSpacing(spacing);
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+
+/*!
+\internal (mostly)
+
+Sets the positioning mode used by addItem(). If \a orient is
+Qt::Horizontal, this layout is expanded to \a n columns, and items
+will be added columns-first. Otherwise it is expanded to \a n rows and
+items will be added rows-first.
+*/
+
+void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient)
+{
+ Q_D(QGridLayout);
+ if (orient == Qt::Horizontal) {
+ d->expand(1, n);
+ d->addVertical = false;
+ } else {
+ d->expand(n,1);
+ d->addVertical = true;
+ }
+}
+
+
+/*!
+ Destroys the grid layout. Geometry management is terminated if
+ this is a top-level grid.
+
+ The layout's widgets aren't destroyed.
+*/
+QGridLayout::~QGridLayout()
+{
+ Q_D(QGridLayout);
+ d->deleteAll();
+}
+
+/*!
+ \property QGridLayout::horizontalSpacing
+ \brief the spacing between widgets that are laid out side by side
+ \since 4.3
+
+ If no value is explicitly set, the layout's horizontal spacing is
+ inherited from the parent layout, or from the style settings for
+ the parent widget.
+
+ \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QGridLayout::setHorizontalSpacing(int spacing)
+{
+ Q_D(QGridLayout);
+ d->horizontalSpacing = spacing;
+ invalidate();
+}
+
+int QGridLayout::horizontalSpacing() const
+{
+ Q_D(const QGridLayout);
+ if (d->horizontalSpacing >= 0) {
+ return d->horizontalSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
+ }
+}
+
+/*!
+ \property QGridLayout::verticalSpacing
+ \brief the spacing between widgets that are laid out on top of each other
+ \since 4.3
+
+ If no value is explicitly set, the layout's vertical spacing is
+ inherited from the parent layout, or from the style settings for
+ the parent widget.
+
+ \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
+*/
+void QGridLayout::setVerticalSpacing(int spacing)
+{
+ Q_D(QGridLayout);
+ d->verticalSpacing = spacing;
+ invalidate();
+}
+
+int QGridLayout::verticalSpacing() const
+{
+ Q_D(const QGridLayout);
+ if (d->verticalSpacing >= 0) {
+ return d->verticalSpacing;
+ } else {
+ return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
+ }
+}
+
+/*!
+ This function sets both the vertical and horizontal spacing to
+ \a spacing.
+
+ \sa setVerticalSpacing(), setHorizontalSpacing()
+*/
+void QGridLayout::setSpacing(int spacing)
+{
+ Q_D(QGridLayout);
+ d->horizontalSpacing = d->verticalSpacing = spacing;
+ invalidate();
+}
+
+/*!
+ If the vertical spacing is equal to the horizontal spacing,
+ this function returns that value; otherwise it return -1.
+
+ \sa setSpacing(), verticalSpacing(), horizontalSpacing()
+*/
+int QGridLayout::spacing() const
+{
+ int hSpacing = horizontalSpacing();
+ if (hSpacing == verticalSpacing()) {
+ return hSpacing;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Returns the number of rows in this grid.
+*/
+int QGridLayout::rowCount() const
+{
+ Q_D(const QGridLayout);
+ return d->numRows();
+}
+
+/*!
+ Returns the number of columns in this grid.
+*/
+int QGridLayout::columnCount() const
+{
+ Q_D(const QGridLayout);
+ return d->numCols();
+}
+
+/*!
+ \reimp
+*/
+QSize QGridLayout::sizeHint() const
+{
+ Q_D(const QGridLayout);
+ QSize result(d->sizeHint(horizontalSpacing(), verticalSpacing()));
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ result += QSize(left + right, top + bottom);
+ return result;
+}
+
+/*!
+ \reimp
+*/
+QSize QGridLayout::minimumSize() const
+{
+ Q_D(const QGridLayout);
+ QSize result(d->minimumSize(horizontalSpacing(), verticalSpacing()));
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ result += QSize(left + right, top + bottom);
+ return result;
+}
+
+/*!
+ \reimp
+*/
+QSize QGridLayout::maximumSize() const
+{
+ Q_D(const QGridLayout);
+
+ QSize s = d->maximumSize(horizontalSpacing(), verticalSpacing());
+ int left, top, right, bottom;
+ d->effectiveMargins(&left, &top, &right, &bottom);
+ s += QSize(left + right, top + bottom);
+ s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
+ if (alignment() & Qt::AlignHorizontal_Mask)
+ s.setWidth(QLAYOUTSIZE_MAX);
+ if (alignment() & Qt::AlignVertical_Mask)
+ s.setHeight(QLAYOUTSIZE_MAX);
+ return s;
+}
+
+/*!
+ \reimp
+*/
+bool QGridLayout::hasHeightForWidth() const
+{
+ return ((QGridLayout*)this)->d_func()->hasHeightForWidth(horizontalSpacing(), verticalSpacing());
+}
+
+/*!
+ \reimp
+*/
+int QGridLayout::heightForWidth(int w) const
+{
+ Q_D(const QGridLayout);
+ QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
+ return dat->heightForWidth(w, horizontalSpacing(), verticalSpacing());
+}
+
+/*!
+ \reimp
+*/
+int QGridLayout::minimumHeightForWidth(int w) const
+{
+ Q_D(const QGridLayout);
+ QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
+ return dat->minimumHeightForWidth(w, horizontalSpacing(), verticalSpacing());
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \compat
+
+ Searches for widget \a w in this layout (not including child
+ layouts). If \a w is found, it sets \c{*}\a{row} and
+ \c{*}\a{column} to the row and column that the widget
+ occupies and returns true; otherwise returns false.
+
+ If the widget spans multiple rows/columns, the top-left cell
+ is returned.
+
+ Use indexOf() and getItemPosition() instead.
+*/
+bool QGridLayout::findWidget(QWidget* w, int *row, int *column)
+{
+ Q_D(QGridLayout);
+ int index = indexOf(w);
+ if (index < 0)
+ return false;
+ int dummy1, dummy2;
+ d->getItemPosition(index, row, column, &dummy1, &dummy2);
+ return true;
+}
+#endif
+/*!
+ \reimp
+*/
+int QGridLayout::count() const
+{
+ Q_D(const QGridLayout);
+ return d->count();
+}
+
+
+/*!
+ \reimp
+*/
+QLayoutItem *QGridLayout::itemAt(int index) const
+{
+ Q_D(const QGridLayout);
+ return d->itemAt(index);
+}
+
+/*!
+ \since 4.4
+
+ Returns the layout item that occupies cell (\a row, \a column), or 0 if
+ the cell is empty.
+
+ \sa getItemPosition(), indexOf()
+*/
+QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
+{
+ Q_D(const QGridLayout);
+ int n = d->things.count();
+ for (int i = 0; i < n; ++i) {
+ QGridBox *box = d->things.at(i);
+ if (row >= box->row && row <= box->toRow(d->rr)
+ && column >= box->col && column <= box->toCol(d->cc)) {
+ return box->item();
+ }
+ }
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QGridLayout::takeAt(int index)
+{
+ Q_D(QGridLayout);
+ return d->takeAt(index);
+}
+
+/*!
+ Returns the position information of the item with the given \a index.
+
+ The variables passed as \a row and \a column are updated with the position of the
+ item in the layout, and the \a rowSpan and \a columnSpan variables are updated
+ with the vertical and horizontal spans of the item.
+
+ \sa itemAtPosition(), itemAt()
+*/
+void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan)
+{
+ Q_D(QGridLayout);
+ d->getItemPosition(index, row, column, rowSpan, columnSpan);
+}
+
+
+/*!
+ \reimp
+*/
+void QGridLayout::setGeometry(const QRect &rect)
+{
+ Q_D(QGridLayout);
+ if (d->isDirty() || rect != geometry()) {
+ QRect cr = alignment() ? alignmentRect(rect) : rect;
+ d->distribute(cr, horizontalSpacing(), verticalSpacing());
+ QLayout::setGeometry(rect);
+ }
+}
+
+/*!
+ Returns the geometry of the cell with row \a row and column \a column
+ in the grid. Returns an invalid rectangle if \a row or \a column is
+ outside the grid.
+
+ \warning in the current version of Qt this function does not
+ return valid results until setGeometry() has been called, i.e.
+ after the parentWidget() is visible.
+*/
+QRect QGridLayout::cellRect(int row, int column) const
+{
+ Q_D(const QGridLayout);
+ return d->cellRect(row, column);
+}
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+ Expands this grid so that it will have \a nRows rows and \a nCols
+ columns. Will not shrink the grid. You should not need to call
+ this function because QGridLayout expands automatically as new
+ items are inserted.
+*/
+void QGridLayout::expand(int nRows, int nCols)
+{
+ Q_D(QGridLayout);
+ d->expand(nRows, nCols);
+}
+#endif
+
+/*!
+ \reimp
+*/
+void QGridLayout::addItem(QLayoutItem *item)
+{
+ Q_D(QGridLayout);
+ int r, c;
+ d->getNextPos(r, c);
+ addItem(item, r, c);
+}
+
+/*!
+ Adds \a item at position \a row, \a column, spanning \a rowSpan
+ rows and \a columnSpan columns, and aligns it according to \a
+ alignment. If \a rowSpan and/or \a columnSpan is -1, then the item
+ will extend to the bottom and/or right edge, respectively. The
+ layout takes ownership of the \a item.
+
+ \warning Do not use this function to add child layouts or child
+ widget items. Use addLayout() or addWidget() instead.
+*/
+void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ QGridBox *b = new QGridBox(item);
+ b->setAlignment(alignment);
+ d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
+ invalidate();
+}
+
+/*
+ Returns true if the widget \a w can be added to the layout \a l;
+ otherwise returns false.
+*/
+static bool checkWidget(QLayout *l, QWidget *w)
+{
+ if (!w) {
+ qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(),
+ l->objectName().toLocal8Bit().data());
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Adds the given \a widget to the cell grid at \a row, \a column. The
+ top-left position is (0, 0) by default.
+
+ The alignment is specified by \a alignment. The default
+ alignment is 0, which means that the widget fills the entire cell.
+
+*/
+void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
+{
+ if (!checkWidget(this, widget))
+ return;
+ if (row < 0 || column < 0) {
+ qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
+ widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
+ metaObject()->className(), objectName().toLocal8Bit().data(), row, column);
+ return;
+ }
+ addChildWidget(widget);
+ QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
+ addItem(b, row, column, 1, 1, alignment);
+}
+
+/*!
+ \overload
+
+ This version adds the given \a widget to the cell grid, spanning
+ multiple rows/columns. The cell will start at \a fromRow, \a
+ fromColumn spanning \a rowSpan rows and \a columnSpan columns. The
+ \a widget will have the given \a alignment.
+
+ If \a rowSpan and/or \a columnSpan is -1, then the widget will
+ extend to the bottom and/or right edge, respectively.
+
+*/
+void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn,
+ int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ if (!checkWidget(this, widget))
+ return;
+ int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1;
+ int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1;
+ addChildWidget(widget);
+ QGridBox *b = new QGridBox(this, widget);
+ b->setAlignment(alignment);
+ d->add(b, fromRow, toRow, fromColumn, toColumn);
+ invalidate();
+}
+
+/*!
+ \fn void QGridLayout::addWidget(QWidget *widget)
+
+ \overload
+ \internal
+*/
+
+/*!
+ Places the \a layout at position (\a row, \a column) in the grid. The
+ top-left position is (0, 0).
+
+ The alignment is specified by \a alignment. The default
+ alignment is 0, which means that the widget fills the entire cell.
+
+ A non-zero alignment indicates that the layout should not grow to
+ fill the available space but should be sized according to
+ sizeHint().
+
+
+ \a layout becomes a child of the grid layout.
+*/
+void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ addChildLayout(layout);
+ QGridBox *b = new QGridBox(layout);
+ b->setAlignment(alignment);
+ d->add(b, row, column);
+}
+
+/*!
+ \overload
+ This version adds the layout \a layout to the cell grid, spanning multiple
+ rows/columns. The cell will start at \a row, \a column spanning \a
+ rowSpan rows and \a columnSpan columns.
+
+ If \a rowSpan and/or \a columnSpan is -1, then the layout will extend to the bottom
+ and/or right edge, respectively.
+*/
+void QGridLayout::addLayout(QLayout *layout, int row, int column,
+ int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ Q_D(QGridLayout);
+ addChildLayout(layout);
+ QGridBox *b = new QGridBox(layout);
+ b->setAlignment(alignment);
+ d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
+}
+
+/*!
+ Sets the stretch factor of row \a row to \a stretch. The first row
+ is number 0.
+
+ The stretch factor is relative to the other rows in this grid.
+ Rows with a higher stretch factor take more of the available
+ space.
+
+ The default stretch factor is 0. If the stretch factor is 0 and no
+ other row in this table can grow at all, the row may still grow.
+
+ \sa rowStretch(), setRowMinimumHeight(), setColumnStretch()
+*/
+void QGridLayout::setRowStretch(int row, int stretch)
+{
+ Q_D(QGridLayout);
+ d->setRowStretch(row, stretch);
+ invalidate();
+}
+
+/*!
+ Returns the stretch factor for row \a row.
+
+ \sa setRowStretch()
+*/
+int QGridLayout::rowStretch(int row) const
+{
+ Q_D(const QGridLayout);
+ return d->rowStretch(row);
+}
+
+/*!
+ Returns the stretch factor for column \a column.
+
+ \sa setColumnStretch()
+*/
+int QGridLayout::columnStretch(int column) const
+{
+ Q_D(const QGridLayout);
+ return d->colStretch(column);
+}
+
+/*!
+ Sets the stretch factor of column \a column to \a stretch. The first
+ column is number 0.
+
+ The stretch factor is relative to the other columns in this grid.
+ Columns with a higher stretch factor take more of the available
+ space.
+
+ The default stretch factor is 0. If the stretch factor is 0 and no
+ other column in this table can grow at all, the column may still
+ grow.
+
+ An alternative approach is to add spacing using addItem() with a
+ QSpacerItem.
+
+ \sa columnStretch(), setRowStretch()
+*/
+void QGridLayout::setColumnStretch(int column, int stretch)
+{
+ Q_D(QGridLayout);
+ d->setColStretch(column, stretch);
+ invalidate();
+}
+
+
+
+/*!
+ Sets the minimum height of row \a row to \a minSize pixels.
+
+ \sa rowMinimumHeight(), setColumnMinimumWidth()
+*/
+void QGridLayout::setRowMinimumHeight(int row, int minSize)
+{
+ Q_D(QGridLayout);
+ d->setRowMinimumHeight(row, minSize);
+ invalidate();
+}
+
+/*!
+ Returns the minimum width set for row \a row.
+
+ \sa setRowMinimumHeight()
+*/
+int QGridLayout::rowMinimumHeight(int row) const
+{
+ Q_D(const QGridLayout);
+ return d->rowSpacing(row);
+}
+
+/*!
+ Sets the minimum width of column \a column to \a minSize pixels.
+
+ \sa columnMinimumWidth(), setRowMinimumHeight()
+*/
+void QGridLayout::setColumnMinimumWidth(int column, int minSize)
+{
+ Q_D(QGridLayout);
+ d->setColumnMinimumWidth(column, minSize);
+ invalidate();
+}
+
+/*!
+ Returns the column spacing for column \a column.
+
+ \sa setColumnMinimumWidth()
+*/
+int QGridLayout::columnMinimumWidth(int column) const
+{
+ Q_D(const QGridLayout);
+ return d->colSpacing(column);
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QGridLayout::expandingDirections() const
+{
+ Q_D(const QGridLayout);
+ return d->expandingDirections(horizontalSpacing(), verticalSpacing());
+}
+
+/*!
+ Sets the grid's origin corner, i.e. position (0, 0), to \a corner.
+*/
+void QGridLayout::setOriginCorner(Qt::Corner corner)
+{
+ Q_D(QGridLayout);
+ d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner,
+ corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner);
+}
+
+/*!
+ Returns the corner that's used for the grid's origin, i.e. for
+ position (0, 0).
+*/
+Qt::Corner QGridLayout::originCorner() const
+{
+ Q_D(const QGridLayout);
+ if (d->horReversed()) {
+ return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner;
+ } else {
+ return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGridLayout::invalidate()
+{
+ Q_D(QGridLayout);
+ d->setDirty();
+ QLayout::invalidate();
+}
+
+/*!
+ \fn void QGridLayout::addRowSpacing(int row, int minsize)
+
+ Use addItem(new QSpacerItem(0, minsize), row, 0) instead.
+*/
+
+/*!
+ \fn void QGridLayout::addColSpacing(int col, int minsize)
+
+ Use addItem(new QSpacerItem(minsize, 0), 0, col) instead.
+*/
+
+/*!
+ \fn void QGridLayout::addMultiCellWidget(QWidget *widget, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
+
+ Use an addWidget() overload that allows you to specify row and
+ column spans instead.
+*/
+
+/*!
+ \fn void QGridLayout::addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
+
+ Use an addItem() overload that allows you to specify row and
+ column spans instead.
+*/
+
+/*!
+ \fn void QGridLayout::addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
+
+ Use an addLayout() overload that allows you to specify row and
+ column spans instead.
+*/
+
+/*!
+ \fn int QGridLayout::numRows() const
+
+ Use rowCount() instead.
+*/
+
+/*!
+ \fn int QGridLayout::numCols() const
+
+ Use columnCount() instead.
+*/
+
+/*!
+ \fn void QGridLayout::setColStretch(int col, int stretch)
+
+ Use setColumnStretch() instead.
+*/
+
+/*!
+ \fn int QGridLayout::colStretch(int col) const
+
+ Use columnStretch() instead.
+*/
+
+/*!
+ \fn void QGridLayout::setColSpacing(int col, int minSize)
+
+ Use setColumnMinimumWidth() instead.
+*/
+
+/*!
+ \fn int QGridLayout::colSpacing(int col) const
+
+ Use columnSpacing() instead.
+*/
+
+/*!
+ \fn void QGridLayout::setRowSpacing(int row, int minSize)
+
+ Use setRowMinimumHeight(\a row, \a minSize) instead.
+*/
+
+/*!
+ \fn int QGridLayout::rowSpacing(int row) const
+
+ Use rowMinimumHeight(\a row) instead.
+*/
+
+/*!
+ \fn QRect QGridLayout::cellGeometry(int row, int column) const
+
+ Use cellRect(\a row, \a column) instead.
+*/
+
+/*!
+ \fn void QGridLayout::setOrigin(Qt::Corner corner)
+
+ Use setOriginCorner(\a corner) instead.
+*/
+
+/*!
+ \fn Qt::Corner QGridLayout::origin() const
+
+ Use originCorner() instead.
+*/
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgridlayout.h b/src/gui/kernel/qgridlayout.h
new file mode 100644
index 0000000000..8bc1570d38
--- /dev/null
+++ b/src/gui/kernel/qgridlayout.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRIDLAYOUT_H
+#define QGRIDLAYOUT_H
+
+#include <QtGui/qlayout.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <QtGui/qwidget.h>
+#endif
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGridLayoutPrivate;
+
+class Q_GUI_EXPORT QGridLayout : public QLayout
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGridLayout)
+ QDOC_PROPERTY(int horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ QDOC_PROPERTY(int verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+
+public:
+ explicit QGridLayout(QWidget *parent);
+ QGridLayout();
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QGridLayout(QWidget *parent, int nRows , int nCols = 1, int border = 0,
+ int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QGridLayout(int nRows , int nCols = 1, int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QGridLayout(QLayout *parentLayout, int nRows = 1, int nCols = 1, int spacing = -1,
+ const char *name = 0);
+#endif
+ ~QGridLayout();
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+
+ void setHorizontalSpacing(int spacing);
+ int horizontalSpacing() const;
+ void setVerticalSpacing(int spacing);
+ int verticalSpacing() const;
+ void setSpacing(int spacing);
+ int spacing() const;
+
+ void setRowStretch(int row, int stretch);
+ void setColumnStretch(int column, int stretch);
+ int rowStretch(int row) const;
+ int columnStretch(int column) const;
+
+ void setRowMinimumHeight(int row, int minSize);
+ void setColumnMinimumWidth(int column, int minSize);
+ int rowMinimumHeight(int row) const;
+ int columnMinimumWidth(int column) const;
+
+ int columnCount() const;
+ int rowCount() const;
+
+ QRect cellRect(int row, int column) const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QRect cellGeometry(int row, int column) const {return cellRect(row, column);}
+#endif
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int minimumHeightForWidth(int) const;
+
+ Qt::Orientations expandingDirections() const;
+ void invalidate();
+
+ inline void addWidget(QWidget *w) { QLayout::addWidget(w); }
+ void addWidget(QWidget *, int row, int column, Qt::Alignment = 0);
+ void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0);
+ void addLayout(QLayout *, int row, int column, Qt::Alignment = 0);
+ void addLayout(QLayout *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0);
+
+ void setOriginCorner(Qt::Corner);
+ Qt::Corner originCorner() const;
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setOrigin(Qt::Corner corner) { setOriginCorner(corner); }
+ inline QT3_SUPPORT Qt::Corner origin() const { return originCorner(); }
+#endif
+ QLayoutItem *itemAt(int index) const;
+ QLayoutItem *itemAtPosition(int row, int column) const;
+ QLayoutItem *takeAt(int index);
+ int count() const;
+ void setGeometry(const QRect&);
+
+ void addItem(QLayoutItem *item, int row, int column, int rowSpan = 1, int columnSpan = 1, Qt::Alignment = 0);
+
+ void setDefaultPositioning(int n, Qt::Orientation orient);
+ void getItemPosition(int idx, int *row, int *column, int *rowSpan, int *columnSpan);
+
+protected:
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT bool findWidget(QWidget* w, int *r, int *c);
+#endif
+ void addItem(QLayoutItem *);
+
+private:
+ Q_DISABLE_COPY(QGridLayout)
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT void expand(int rows, int cols);
+ inline QT3_SUPPORT void addRowSpacing(int row, int minsize) { addItem(new QSpacerItem(0,minsize), row, 0); }
+ inline QT3_SUPPORT void addColSpacing(int col, int minsize) { addItem(new QSpacerItem(minsize,0), 0, col); }
+ inline QT3_SUPPORT void addMultiCellWidget(QWidget *w, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment _align = 0)
+ { addWidget(w, fromRow, fromCol, (toRow < 0) ? -1 : toRow - fromRow + 1, (toCol < 0) ? -1 : toCol - fromCol + 1, _align); }
+ inline QT3_SUPPORT void addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment _align = 0)
+ { addItem(l, fromRow, fromCol, (toRow < 0) ? -1 : toRow - fromRow + 1, (toCol < 0) ? -1 : toCol - fromCol + 1, _align); }
+ inline QT3_SUPPORT void addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment _align = 0)
+ { addLayout(layout, fromRow, fromCol, (toRow < 0) ? -1 : toRow - fromRow + 1, (toCol < 0) ? -1 : toCol - fromCol + 1, _align); }
+
+ inline QT3_SUPPORT int numRows() const { return rowCount(); }
+ inline QT3_SUPPORT int numCols() const { return columnCount(); }
+ inline QT3_SUPPORT void setColStretch(int col, int stretch) {setColumnStretch(col, stretch); }
+ inline QT3_SUPPORT int colStretch(int col) const {return columnStretch(col); }
+ inline QT3_SUPPORT void setColSpacing(int col, int minSize) { setColumnMinimumWidth(col, minSize); }
+ inline QT3_SUPPORT int colSpacing(int col) const { return columnMinimumWidth(col); }
+ inline QT3_SUPPORT void setRowSpacing(int row, int minSize) {setRowMinimumHeight(row, minSize); }
+ inline QT3_SUPPORT int rowSpacing(int row) const {return rowMinimumHeight(row); }
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRIDLAYOUT_H
diff --git a/src/gui/kernel/qguieventdispatcher_glib.cpp b/src/gui/kernel/qguieventdispatcher_glib.cpp
new file mode 100644
index 0000000000..6222240a7e
--- /dev/null
+++ b/src/gui/kernel/qguieventdispatcher_glib.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qguieventdispatcher_glib_p.h"
+
+#include "qapplication.h"
+#include "qx11info_x11.h"
+
+#include "qt_x11_p.h"
+
+#include <glib.h>
+
+QT_BEGIN_NAMESPACE
+
+struct GX11EventSource
+{
+ GSource source;
+ GPollFD pollfd;
+ QEventLoop::ProcessEventsFlags flags;
+ QGuiEventDispatcherGlib *q;
+ QGuiEventDispatcherGlibPrivate *d;
+};
+
+class QGuiEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
+{
+ Q_DECLARE_PUBLIC(QGuiEventDispatcherGlib)
+
+public:
+ QGuiEventDispatcherGlibPrivate();
+ GX11EventSource *x11EventSource;
+ QList<XEvent> queuedUserInputEvents;
+};
+
+static gboolean x11EventSourcePrepare(GSource *s, gint *timeout)
+{
+ if (timeout)
+ *timeout = -1;
+ GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
+ return (XEventsQueued(X11->display, QueuedAfterFlush)
+ || (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()));
+}
+
+static gboolean x11EventSourceCheck(GSource *s)
+{
+ GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
+ return (XEventsQueued(X11->display, QueuedAfterFlush)
+ || (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()));
+}
+
+static gboolean x11EventSourceDispatch(GSource *s, GSourceFunc callback, gpointer user_data)
+{
+ GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
+
+ ulong marker = XNextRequest(X11->display);
+ do {
+ XEvent event;
+ if (!(source->flags & QEventLoop::ExcludeUserInputEvents)
+ && !source->d->queuedUserInputEvents.isEmpty()) {
+ // process a pending user input event
+ event = source->d->queuedUserInputEvents.takeFirst();
+ } else if (XEventsQueued(X11->display, QueuedAlready)) {
+ // process events from the X server
+ XNextEvent(X11->display, &event);
+
+ if (source->flags & QEventLoop::ExcludeUserInputEvents) {
+ // queue user input events
+ switch (event.type) {
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case XKeyPress:
+ case XKeyRelease:
+ case EnterNotify:
+ case LeaveNotify:
+ source->d->queuedUserInputEvents.append(event);
+ continue;
+
+ case ClientMessage:
+ // only keep the wm_take_focus and
+ // _qt_scrolldone protocols, queue all other
+ // client messages
+ if (event.xclient.format == 32) {
+ if (event.xclient.message_type == ATOM(WM_PROTOCOLS) ||
+ (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) {
+ break;
+ } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
+ break;
+ }
+ }
+ source->d->queuedUserInputEvents.append(event);
+ continue;
+
+ default:
+ break;
+ }
+ }
+ } else {
+ // no event to process
+ break;
+ }
+
+ // send through event filter
+ if (source->q->filterEvent(&event))
+ continue;
+
+ if (qApp->x11ProcessEvent(&event) == 1)
+ return true;
+
+ if (event.xany.serial >= marker)
+ goto out;
+ } while (XEventsQueued(X11->display, QueuedAfterFlush));
+
+ out:
+
+ if (callback)
+ callback(user_data);
+ return true;
+}
+
+static GSourceFuncs x11EventSourceFuncs = {
+ x11EventSourcePrepare,
+ x11EventSourceCheck,
+ x11EventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+QGuiEventDispatcherGlibPrivate::QGuiEventDispatcherGlibPrivate()
+{
+ x11EventSource = reinterpret_cast<GX11EventSource *>(g_source_new(&x11EventSourceFuncs,
+ sizeof(GX11EventSource)));
+ g_source_set_can_recurse(&x11EventSource->source, true);
+
+ memset(&x11EventSource->pollfd, 0, sizeof(GPollFD));
+ x11EventSource->flags = QEventLoop::AllEvents;
+ x11EventSource->q = 0;
+ x11EventSource->d = 0;
+
+ g_source_attach(&x11EventSource->source, mainContext);
+}
+
+QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(QObject *parent)
+ : QEventDispatcherGlib(*new QGuiEventDispatcherGlibPrivate, parent)
+{
+}
+
+QGuiEventDispatcherGlib::~QGuiEventDispatcherGlib()
+{
+ Q_D(QGuiEventDispatcherGlib);
+
+ g_source_remove_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
+ g_source_destroy(&d->x11EventSource->source);
+ d->x11EventSource = 0;
+}
+
+bool QGuiEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QGuiEventDispatcherGlib);
+ QEventLoop::ProcessEventsFlags saved_flags = d->x11EventSource->flags;
+ d->x11EventSource->flags = flags;
+ bool returnValue = QEventDispatcherGlib::processEvents(flags);
+ d->x11EventSource->flags = saved_flags;
+ return returnValue;
+}
+
+void QGuiEventDispatcherGlib::startingUp()
+{
+ Q_D(QGuiEventDispatcherGlib);
+ d->x11EventSource->pollfd.fd = XConnectionNumber(X11->display);
+ d->x11EventSource->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ d->x11EventSource->q = this;
+ d->x11EventSource->d = d;
+ g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qguieventdispatcher_glib_p.h b/src/gui/kernel/qguieventdispatcher_glib_p.h
new file mode 100644
index 0000000000..06a11c7c0e
--- /dev/null
+++ b/src/gui/kernel/qguieventdispatcher_glib_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIEVENTDISPATCHER_GLIB_P_H
+#define QGUIEVENTDISPATCHER_GLIB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qeventdispatcher_glib_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGuiEventDispatcherGlibPrivate;
+
+class QGuiEventDispatcherGlib : public QEventDispatcherGlib
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGuiEventDispatcherGlib)
+
+public:
+ explicit QGuiEventDispatcherGlib(QObject *parent = 0);
+ ~QGuiEventDispatcherGlib();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+
+ void startingUp();
+};
+
+QT_END_NAMESPACE
+
+#endif // QGUIEVENTDISPATCHER_GLIB_P_H
diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp
new file mode 100644
index 0000000000..b6f825ba4f
--- /dev/null
+++ b/src/gui/kernel/qguifunctions_wince.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qguifunctions_wince.h"
+#include <shellapi.h>
+#include <QtCore/qlibrary.h>
+
+QT_USE_NAMESPACE
+
+struct AygSHINITDLGINFO
+{
+ DWORD dwMask;
+ HWND hDlg;
+ DWORD dwFlags;
+};
+
+struct AygSIPINFO
+{
+ DWORD cbSize;
+ DWORD fdwFlags;
+ RECT rcVisibleDesktop;
+ RECT rcSipRect;
+ DWORD dwImDataSize;
+ void *pvImData;
+};
+
+#ifndef SHIDIF_CANCELBUTTON
+#define SHIDIF_CANCELBUTTON 0x0080
+#endif
+
+#ifndef SHIDIM_FLAGS
+#define SHIDIM_FLAGS 0x0001
+#endif
+
+#ifndef SHIDIF_DONEBUTTON
+#define SHIDIF_DONEBUTTON 0x0001
+#endif
+#ifndef SHIDIF_SIZEDLGFULLSCREEN
+#define SHIDIF_SIZEDLGFULLSCREEN 0x0004
+#endif
+
+#ifndef SHFS_SHOWTASKBAR
+#define SHFS_SHOWTASKBAR 0x0001
+#endif
+#ifndef SHFS_HIDETASKBAR
+#define SHFS_HIDETASKBAR 0x0002
+#endif
+#ifndef SHFS_SHOWSIPBUTTON
+#define SHFS_SHOWSIPBUTTON 0x0004
+#endif
+#ifndef SHFS_HIDESIPBUTTON
+#define SHFS_HIDESIPBUTTON 0x0008
+#endif
+#ifndef SHFS_SHOWSTARTICON
+#define SHFS_SHOWSTARTICON 0x0010
+#endif
+#ifndef SHFS_HIDESTARTICON
+#define SHFS_HIDESTARTICON 0x0020
+#endif
+
+#ifndef SIPF_OFF
+#define SIPF_OFF 0x00000000
+#endif
+#ifndef SIPF_ON
+#define SIPF_ON 0x00000001
+#endif
+
+#ifndef SPI_SETSIPINFO
+#define SPI_SETSIPINFO 224
+#endif
+#ifndef SPI_GETSIPINFO
+#define SPI_GETSIPINFO 225
+#endif
+
+typedef BOOL (*AygInitDialog)(AygSHINITDLGINFO*);
+typedef BOOL (*AygFullScreen)(HWND, DWORD);
+typedef BOOL (*AygSHSipInfo)(UINT, UINT, PVOID, UINT);
+
+static AygInitDialog ptrAygInitDialog = 0;
+static AygFullScreen ptrAygFullScreen = 0;
+static AygSHSipInfo ptrAygSHSipInfo = 0;
+static bool aygResolved = false;
+
+static void resolveAygLibs()
+{
+ if (!aygResolved) {
+ aygResolved = true;
+ QLibrary ayglib(QLatin1String("aygshell"));
+ if (!ayglib.load())
+ return;
+ ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog");
+ ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen");
+ ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo");
+ }
+}
+
+struct DIBINFO : public BITMAPINFO
+{
+ RGBQUAD arColors[255];
+
+ operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
+ operator LPBITMAPINFOHEADER() { return &bmiHeader; }
+ RGBQUAD* ColorTable() { return bmiColors; }
+};
+
+int qt_wince_GetDIBits(HDC /*hdc*/ , HBITMAP hSourceBitmap, uint, uint, LPVOID lpvBits, LPBITMAPINFO, uint)
+{
+ if (!lpvBits) {
+ qWarning("::GetDIBits(), lpvBits NULL");
+ return 0;
+ }
+ BITMAP bm;
+ GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
+ bm.bmHeight = qAbs(bm.bmHeight);
+
+ HBITMAP hTargetBitmap;
+ void *pixels;
+
+ BITMAPINFO dibInfo;
+ memset(&dibInfo, 0, sizeof(dibInfo));
+ dibInfo.bmiHeader.biBitCount = 32;
+ dibInfo.bmiHeader.biClrImportant = 0;
+ dibInfo.bmiHeader.biClrUsed = 0;
+ dibInfo.bmiHeader.biCompression = BI_RGB;;
+ dibInfo.bmiHeader.biHeight = -bm.bmHeight;
+ dibInfo.bmiHeader.biWidth = bm.bmWidth;
+ dibInfo.bmiHeader.biPlanes = 1;
+ dibInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibInfo.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
+
+ HDC displayDC = GetDC(NULL);
+ if (!displayDC) {
+ qWarning("::GetDIBits(), failed to GetDC");
+ return 0;
+ }
+
+ int ret = bm.bmHeight;
+
+ hTargetBitmap = CreateDIBSection(displayDC, (const BITMAPINFO*) &dibInfo, DIB_RGB_COLORS,
+ (void**)&pixels, NULL, 0);
+ if (!hTargetBitmap) {
+ qWarning("::GetDIBits(), failed to CreateDIBSection");
+ return 0;
+ }
+
+ HDC hdcSrc = CreateCompatibleDC(displayDC);
+ HDC hdcDst = CreateCompatibleDC(displayDC);
+
+ if (!(hdcDst && hdcSrc)) {
+ qWarning("::GetDIBits(), failed to CreateCompatibleDC");
+ ret = 0;
+ }
+
+ HBITMAP hOldBitmap1 = (HBITMAP) SelectObject(hdcSrc, hSourceBitmap);
+ HBITMAP hOldBitmap2 = (HBITMAP) SelectObject(hdcDst, hTargetBitmap);
+
+ if (!(hOldBitmap1 && hOldBitmap2)) {
+ qWarning("::GetDIBits(), failed to SelectObject for bitmaps");
+ ret = 0;
+ }
+
+ if (!BitBlt(hdcDst, 0, 0, bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, SRCCOPY)) {
+ qWarning("::GetDIBits(), BitBlt failed");
+ ret = 0;
+ }
+
+ SelectObject(hdcSrc, hOldBitmap1);
+ SelectObject(hdcDst, hOldBitmap2);
+
+ DeleteDC(hdcSrc);
+ DeleteDC(hdcDst);
+
+ ReleaseDC(NULL, displayDC);
+
+ memcpy(lpvBits, pixels, dibInfo.bmiHeader.biSizeImage);
+
+ DeleteObject(hTargetBitmap);
+ return ret;
+}
+
+bool qt_wince_TextOutW(HDC hdc, int x, int y, LPWSTR lpString, UINT c)
+{
+ return ExtTextOutW(hdc, x, y, 0, NULL, lpString, c, NULL);
+}
+
+
+HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd)
+{
+ SHELLEXECUTEINFO info;
+ info.hwnd = hwnd;
+ info.lpVerb = L"Open";
+ info.lpFile = file;
+ info.lpParameters = params;
+ info.lpDirectory = dir;
+ info.nShow = showCmd;
+ info.cbSize = sizeof(info);
+ ShellExecuteEx(&info);
+ return info.hInstApp;
+}
+
+// Clipboard --------------------------------------------------------
+BOOL qt_wince_ChangeClipboardChain( HWND /*hWndRemove*/, HWND /*hWndNewNext*/ )
+{
+ return FALSE;
+}
+
+HWND qt_wince_SetClipboardViewer( HWND /*hWndNewViewer*/ )
+{
+ return NULL;
+}
+
+
+// Graphics ---------------------------------------------------------
+COLORREF qt_wince_PALETTEINDEX( WORD /*wPaletteIndex*/)
+{
+ return 0;
+}
+
+BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString )
+{
+ return ExtTextOut( hdc, nXStart, nYStart - 16, 0, NULL, lpString, cbString, NULL );
+}
+
+// Internal Qt -----------------------------------------------------
+bool qt_wince_is_platform(const QString &platformString) {
+ TCHAR tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
+ sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
+ return true;
+ return false;
+}
+
+bool qt_wince_is_pocket_pc() {
+ return qt_wince_is_platform(QString::fromLatin1("PocketPC"));
+}
+
+bool qt_wince_is_smartphone() {
+ return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
+}
+bool qt_wince_is_mobile() {
+ return (qt_wince_is_smartphone() || qt_wince_is_pocket_pc());
+}
+
+bool qt_wince_is_high_dpi() {
+ if (!qt_wince_is_pocket_pc())
+ return false;
+ HDC deviceContext = GetDC(0);
+ int dpi = GetDeviceCaps(deviceContext, LOGPIXELSX);
+ ReleaseDC(0, deviceContext);
+ if ((dpi < 1000) && (dpi > 0))
+ return dpi > 96;
+ else
+ return false;
+}
+
+void qt_wince_maximize(QWidget *widget)
+{
+ HWND hwnd = widget->winId();
+ if (qt_wince_is_mobile()) {
+ AygSHINITDLGINFO shidi;
+ shidi.dwMask = SHIDIM_FLAGS;
+ shidi.hDlg = hwnd;
+ shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
+ if (widget->windowFlags() & Qt::WindowCancelButtonHint)
+ shidi.dwFlags |= SHIDIF_CANCELBUTTON;
+ if (widget->windowFlags() & Qt::WindowOkButtonHint)
+ shidi.dwFlags |= SHIDIF_DONEBUTTON;
+ resolveAygLibs();
+ if (ptrAygInitDialog)
+ ptrAygInitDialog(&shidi);
+ } else {
+ RECT r;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ MoveWindow(hwnd, r.top, r.left, r.right - r.left, r.bottom - r.top, true);
+ SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NODRAG);
+ }
+}
+
+void qt_wince_minimize(HWND hwnd) {
+
+ uint exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
+ uint style = GetWindowLongW(hwnd, GWL_STYLE);
+ RECT rect;
+ RECT crect = {0,0,0,0};
+ GetWindowRect(hwnd, &rect);
+ AdjustWindowRectEx(&crect, style & ~WS_OVERLAPPED, FALSE, exstyle);
+ MoveWindow(hwnd, rect.left - crect.left, rect.top - crect.top, 0, 0, true);
+ SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NODRAG);
+ ShowWindow(hwnd, SW_HIDE);
+}
+
+
+void qt_wince_hide_taskbar(HWND hwnd) {
+ if (ptrAygFullScreen)
+ ptrAygFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON);
+}
+
+void qt_wince_full_screen(HWND hwnd, bool fullScreen, UINT swpf) {
+ resolveAygLibs();
+ if (fullScreen) {
+ QRect r = qApp->desktop()->screenGeometry(QWidget::find(hwnd));
+ SetWindowPos(hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
+ if (ptrAygFullScreen)
+ ptrAygFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON);
+ if (!qt_wince_is_mobile()) {
+ HWND handle = FindWindow(L"HHTaskBar", L"");
+ if (handle) {
+ ShowWindow(handle, 0);
+ EnableWindow(handle, false);
+ }
+ }
+ } else {
+ if (ptrAygFullScreen)
+ ptrAygFullScreen(hwnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | SHFS_SHOWSTARTICON);
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0, swpf);
+ if (!qt_wince_is_mobile()) {
+ HWND handle = FindWindow(L"HHTaskBar", L"");
+ if (handle) {
+ ShowWindow(handle, 1);
+ EnableWindow(handle, true);
+ }
+ }
+ }
+}
+
+void qt_wince_show_SIP(bool show)
+{
+ resolveAygLibs();
+ if (!ptrAygSHSipInfo)
+ return;
+
+ AygSIPINFO si;
+ memset(&si, 0, sizeof(si));
+ si.cbSize = sizeof(si);
+ ptrAygSHSipInfo(SPI_GETSIPINFO, 0, &si, 0);
+ si.cbSize = sizeof(si);
+ si.fdwFlags = (show ? SIPF_ON : SIPF_OFF);
+ ptrAygSHSipInfo(SPI_SETSIPINFO, 0, &si, 0);
+}
diff --git a/src/gui/kernel/qguifunctions_wince.h b/src/gui/kernel/qguifunctions_wince.h
new file mode 100644
index 0000000000..aca2253fc9
--- /dev/null
+++ b/src/gui/kernel/qguifunctions_wince.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QGUIFUNCTIONS_WCE_H
+#define QGUIFUNCTIONS_WCE_H
+#ifdef Q_OS_WINCE
+#include <QtCore/qfunctions_wince.h>
+#define UNDER_NT
+#include <wingdi.h>
+
+#ifdef QT_BUILD_GUI_LIB
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+QT_MODULE(Gui)
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
+
+// application defines
+#define SPI_SETNONCLIENTMETRICS 72
+#define SPI_SETICONTITLELOGFONT 0x0022
+#define WM_ACTIVATEAPP 0x001c
+#define SW_PARENTCLOSING 1
+#define SW_OTHERMAXIMIZED 2
+#define SW_PARENTOPENING 3
+#define SW_OTHERRESTORED 4
+#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
+
+// drag n drop
+#ifndef CFSTR_PERFORMEDDROPEFFECT
+#define CFSTR_PERFORMEDDROPEFFECT TEXT("Performed DropEffect")
+#endif
+int qt_wince_GetDIBits(HDC, HBITMAP, uint, uint, void*, LPBITMAPINFO, uint);
+#define GetDIBits(a,b,c,d,e,f,g) qt_wince_GetDIBits(a,b,c,d,e,f,g)
+
+// QWidget
+#define SW_SHOWMINIMIZED SW_MINIMIZE
+
+// QPaintEngine
+bool qt_wince_TextOutW(HDC, int, int, LPWSTR, UINT);
+#define TextOutW(a,b,c,d,e) qt_wince_TextOutW(a,b,c,d,e)
+
+// QRegion
+#define ALTERNATE 0
+#define WINDING 1
+
+// QFontEngine
+typedef struct _FIXED {
+ WORD fract;
+ short value;
+} FIXED;
+
+typedef struct tagPOINTFX {
+ FIXED x;
+ FIXED y;
+} POINTFX;
+
+typedef struct _MAT2 {
+ FIXED eM11;
+ FIXED eM12;
+ FIXED eM21;
+ FIXED eM22;
+} MAT2;
+
+typedef struct _GLYPHMETRICS {
+ UINT gmBlackBoxX;
+ UINT gmBlackBoxY;
+ POINT gmptGlyphOrigin;
+ short gmCellIncX;
+ short gmCellIncY;
+} GLYPHMETRICS;
+
+typedef struct tagTTPOLYGONHEADER
+{
+ DWORD cb;
+ DWORD dwType;
+ POINTFX pfxStart;
+} TTPOLYGONHEADER;
+
+typedef struct tagTTPOLYCURVE
+{
+ WORD wType;
+ WORD cpfx;
+ POINTFX apfx[1];
+} TTPOLYCURVE;
+
+#define GGO_NATIVE 2
+#define GGO_GLYPH_INDEX 0x0080
+#define TT_PRIM_LINE 1
+#define TT_PRIM_QSPLINE 2
+#define TT_PRIM_CSPLINE 3
+#define ANSI_VAR_FONT 12
+
+HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd);
+#define ShellExecute(a,b,c,d,e,f) qt_wince_ShellExecute(a,b,c,d,e,f)
+
+
+// Clipboard --------------------------------------------------------
+#define WM_CHANGECBCHAIN 1
+#define WM_DRAWCLIPBOARD 2
+
+BOOL qt_wince_ChangeClipboardChain(
+ HWND hWndRemove, // handle to window to remove
+ HWND hWndNewNext // handle to next window
+);
+#define ChangeClipboardChain(a,b) qt_wince_ChangeClipboardChain(a,b);
+
+HWND qt_wince_SetClipboardViewer(
+ HWND hWndNewViewer // handle to clipboard viewer window
+);
+#define SetClipboardViewer(a) qt_wince_SetClipboardViewer(a)
+
+// Graphics ---------------------------------------------------------
+COLORREF qt_wince_PALETTEINDEX( WORD wPaletteIndex );
+#define PALETTEINDEX(a) qt_wince_PALETTEINDEX(a)
+BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString );
+#define TextOut(a,b,c,d,e) qt_wince_TextOut(a,b,c,d,e)
+
+#endif // Q_OS_WINCE
+#endif // QGUIFUNCTIONS_WCE_H
diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp
new file mode 100644
index 0000000000..7ad908f3a7
--- /dev/null
+++ b/src/gui/kernel/qguivariant.cpp
@@ -0,0 +1,669 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvariant.h"
+
+#include "qbitmap.h"
+#include "qbrush.h"
+#include "qcolor.h"
+#include "qcursor.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+#include "qfont.h"
+#include "qicon.h"
+#include "qimage.h"
+#include "qkeysequence.h"
+#include "qtransform.h"
+#include "qmatrix.h"
+#include "qpalette.h"
+#include "qpen.h"
+#include "qpixmap.h"
+#include "qpolygon.h"
+#include "qregion.h"
+#include "qsizepolicy.h"
+#include "qtextformat.h"
+
+#include "private/qvariant_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT3_SUPPORT
+extern QDataStream &qt_stream_out_qcolorgroup(QDataStream &s, const QColorGroup &g);
+extern QDataStream &qt_stream_in_qcolorgroup(QDataStream &s, QColorGroup &g);
+#endif
+
+Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
+
+static void construct(QVariant::Private *x, const void *copy)
+{
+ switch (x->type) {
+ case QVariant::Bitmap:
+ v_construct<QBitmap>(x, copy);
+ break;
+ case QVariant::Region:
+ v_construct<QRegion>(x, copy);
+ break;
+ case QVariant::Polygon:
+ v_construct<QPolygon>(x, copy);
+ break;
+ case QVariant::Font:
+ v_construct<QFont>(x, copy);
+ break;
+ case QVariant::Pixmap:
+ v_construct<QPixmap>(x, copy);
+ break;
+ case QVariant::Image:
+ v_construct<QImage>(x, copy);
+ break;
+ case QVariant::Brush:
+ v_construct<QBrush>(x, copy);
+ break;
+ case QVariant::Color:
+ v_construct<QColor>(x, copy);
+ break;
+ case QVariant::Palette:
+ v_construct<QPalette>(x, copy);
+ break;
+#ifdef QT3_SUPPORT
+ case QVariant::ColorGroup:
+ v_construct<QColorGroup>(x, copy);
+ break;
+#endif
+#ifndef QT_NO_ICON
+ case QVariant::Icon:
+ v_construct<QIcon>(x, copy);
+ break;
+#endif
+ case QVariant::Matrix:
+ v_construct<QMatrix>(x, copy);
+ break;
+ case QVariant::Transform:
+ v_construct<QTransform>(x, copy);
+ break;
+ case QVariant::TextFormat:
+ v_construct<QTextFormat>(x, copy);
+ break;
+ case QVariant::TextLength:
+ v_construct<QTextLength>(x, copy);
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence:
+ v_construct<QKeySequence>(x, copy);
+ break;
+#endif
+ case QVariant::Pen:
+ v_construct<QPen>(x, copy);
+ break;
+ case QVariant::SizePolicy:
+ v_construct<QSizePolicy>(x, copy);
+ break;
+#ifndef QT_NO_CURSOR
+ case QVariant::Cursor:
+ v_construct<QCursor>(x, copy);
+ break;
+#endif
+ case 62: {
+ // small 'trick' to let a QVariant(Qt::blue) create a variant
+ // of type QColor
+ x->type = QVariant::Color;
+ QColor color(*reinterpret_cast<const Qt::GlobalColor *>(copy));
+ v_construct<QColor>(x, &color);
+ break;
+ }
+ default:
+ qcoreVariantHandler()->construct(x, copy);
+ return;
+ }
+ x->is_null = !copy;
+}
+
+static void clear(QVariant::Private *d)
+{
+ switch (d->type) {
+ case QVariant::Bitmap:
+ v_clear<QBitmap>(d);
+ break;
+ case QVariant::Cursor:
+ v_clear<QCursor>(d);
+ break;
+ case QVariant::Region:
+ v_clear<QRegion>(d);
+ break;
+ case QVariant::Polygon:
+ v_clear<QPolygon>(d);
+ break;
+ case QVariant::Font:
+ v_clear<QFont>(d);
+ break;
+ case QVariant::Pixmap:
+ v_clear<QPixmap>(d);
+ break;
+ case QVariant::Image:
+ v_clear<QImage>(d);
+ break;
+ case QVariant::Brush:
+ v_clear<QBrush>(d);
+ break;
+ case QVariant::Color:
+ v_clear<QColor>(d);
+ break;
+ case QVariant::Palette:
+ v_clear<QPalette>(d);
+ break;
+#ifdef QT3_SUPPORT
+ case QVariant::ColorGroup:
+ v_clear<QColorGroup>(d);
+ break;
+#endif
+#ifndef QT_NO_ICON
+ case QVariant::Icon:
+ v_clear<QIcon>(d);
+ break;
+#endif
+ case QVariant::Matrix:
+ v_clear<QMatrix>(d);
+ break;
+ case QVariant::Transform:
+ v_clear<QTransform>(d);
+ break;
+ case QVariant::TextFormat:
+ v_clear<QTextFormat>(d);
+ break;
+ case QVariant::TextLength:
+ v_clear<QTextLength>(d);
+ break;
+ case QVariant::SizePolicy:
+ v_clear<QSizePolicy>(d);
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence:
+ v_clear<QKeySequence>(d);
+ break;
+#endif
+ case QVariant::Pen:
+ v_clear<QPen>(d);
+ break;
+ default:
+ qcoreVariantHandler()->clear(d);
+ return;
+ }
+
+ d->type = QVariant::Invalid;
+ d->is_null = true;
+ d->is_shared = false;
+}
+
+
+static bool isNull(const QVariant::Private *d)
+{
+ switch(d->type) {
+ case QVariant::Bitmap:
+ return v_cast<QBitmap>(d)->isNull();
+ case QVariant::Region:
+ return v_cast<QRegion>(d)->isEmpty();
+ case QVariant::Polygon:
+ return v_cast<QPolygon>(d)->isEmpty();
+ case QVariant::Pixmap:
+ return v_cast<QPixmap>(d)->isNull();
+ case QVariant::Image:
+ return v_cast<QImage>(d)->isNull();
+#ifndef QT_NO_ICON
+ case QVariant::Icon:
+ return v_cast<QIcon>(d)->isNull();
+#endif
+ case QVariant::Matrix:
+ case QVariant::TextFormat:
+ case QVariant::TextLength:
+ case QVariant::Cursor:
+ case QVariant::StringList:
+ case QVariant::Font:
+ case QVariant::Brush:
+ case QVariant::Color:
+ case QVariant::Palette:
+#ifdef QT3_SUPPORT
+ case QVariant::ColorGroup:
+#endif
+ case QVariant::SizePolicy:
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence:
+#endif
+ case QVariant::Pen:
+ break;
+ default:
+ return qcoreVariantHandler()->isNull(d);
+ }
+ return d->is_null;
+}
+
+static bool compare(const QVariant::Private *a, const QVariant::Private *b)
+{
+ Q_ASSERT(a->type == b->type);
+ switch(a->type) {
+ case QVariant::Cursor:
+#ifndef QT_NO_CURSOR
+ return v_cast<QCursor>(a)->shape() == v_cast<QCursor>(b)->shape();
+#endif
+ case QVariant::Bitmap:
+ return v_cast<QBitmap>(a)->cacheKey()
+ == v_cast<QBitmap>(b)->cacheKey();
+ case QVariant::Polygon:
+ return *v_cast<QPolygon>(a) == *v_cast<QPolygon>(b);
+ case QVariant::Region:
+ return *v_cast<QRegion>(a) == *v_cast<QRegion>(b);
+ case QVariant::Font:
+ return *v_cast<QFont>(a) == *v_cast<QFont>(b);
+ case QVariant::Pixmap:
+ return v_cast<QPixmap>(a)->cacheKey() == v_cast<QPixmap>(b)->cacheKey();
+ case QVariant::Image:
+ return *v_cast<QImage>(a) == *v_cast<QImage>(b);
+ case QVariant::Brush:
+ return *v_cast<QBrush>(a) == *v_cast<QBrush>(b);
+ case QVariant::Color:
+ return *v_cast<QColor>(a) == *v_cast<QColor>(b);
+ case QVariant::Palette:
+ return *v_cast<QPalette>(a) == *v_cast<QPalette>(b);
+#ifdef QT3_SUPPORT
+ case QVariant::ColorGroup:
+ return *v_cast<QColorGroup>(a) == *v_cast<QColorGroup>(b);
+#endif
+#ifndef QT_NO_ICON
+ case QVariant::Icon:
+ /* QIcon::operator==() cannot be reasonably implemented for QIcon,
+ * so we always return false. */
+ return false;
+#endif
+ case QVariant::Matrix:
+ return *v_cast<QMatrix>(a) == *v_cast<QMatrix>(b);
+ case QVariant::Transform:
+ return *v_cast<QTransform>(a) == *v_cast<QTransform>(b);
+ case QVariant::TextFormat:
+ return *v_cast<QTextFormat>(a) == *v_cast<QTextFormat>(b);
+ case QVariant::TextLength:
+ return *v_cast<QTextLength>(a) == *v_cast<QTextLength>(b);
+ case QVariant::SizePolicy:
+ return *v_cast<QSizePolicy>(a) == *v_cast<QSizePolicy>(b);
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence:
+ return *v_cast<QKeySequence>(a) == *v_cast<QKeySequence>(b);
+#endif
+ case QVariant::Pen:
+ return *v_cast<QPen>(a) == *v_cast<QPen>(b);
+ default:
+ break;
+ }
+ return qcoreVariantHandler()->compare(a, b);
+}
+
+
+
+static bool convert(const QVariant::Private *d, QVariant::Type t,
+ void *result, bool *ok)
+{
+ switch (t) {
+ case QVariant::ByteArray:
+ if (d->type == QVariant::Color) {
+ *static_cast<QByteArray *>(result) = v_cast<QColor>(d)->name().toLatin1();
+ return true;
+ }
+ break;
+ case QVariant::String: {
+ QString *str = static_cast<QString *>(result);
+ switch (d->type) {
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence:
+ *str = QString(*v_cast<QKeySequence>(d));
+ return true;
+#endif
+ case QVariant::Font:
+ *str = v_cast<QFont>(d)->toString();
+ return true;
+ case QVariant::Color:
+ *str = v_cast<QColor>(d)->name();
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case QVariant::Pixmap:
+ if (d->type == QVariant::Image) {
+ *static_cast<QPixmap *>(result) = QPixmap::fromImage(*v_cast<QImage>(d));
+ return true;
+ } else if (d->type == QVariant::Bitmap) {
+ *static_cast<QPixmap *>(result) = *v_cast<QBitmap>(d);
+ return true;
+ } else if (d->type == QVariant::Brush) {
+ if (v_cast<QBrush>(d)->style() == Qt::TexturePattern) {
+ *static_cast<QPixmap *>(result) = v_cast<QBrush>(d)->texture();
+ return true;
+ }
+ }
+ break;
+ case QVariant::Image:
+ if (d->type == QVariant::Pixmap) {
+ *static_cast<QImage *>(result) = v_cast<QPixmap>(d)->toImage();
+ return true;
+ } else if (d->type == QVariant::Bitmap) {
+ *static_cast<QImage *>(result) = v_cast<QBitmap>(d)->toImage();
+ return true;
+ }
+ break;
+ case QVariant::Bitmap:
+ if (d->type == QVariant::Pixmap) {
+ *static_cast<QBitmap *>(result) = *v_cast<QPixmap>(d);
+ return true;
+ } else if (d->type == QVariant::Image) {
+ *static_cast<QBitmap *>(result) = QBitmap::fromImage(*v_cast<QImage>(d));
+ return true;
+ }
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QVariant::Int:
+ if (d->type == QVariant::KeySequence) {
+ *static_cast<int *>(result) = (int)(*(v_cast<QKeySequence>(d)));
+ return true;
+ }
+ break;
+#endif
+ case QVariant::Font:
+ if (d->type == QVariant::String) {
+ QFont *f = static_cast<QFont *>(result);
+ f->fromString(*v_cast<QString>(d));
+ return true;
+ }
+ break;
+ case QVariant::Color:
+ if (d->type == QVariant::String) {
+ static_cast<QColor *>(result)->setNamedColor(*v_cast<QString>(d));
+ return static_cast<QColor *>(result)->isValid();
+ } else if (d->type == QVariant::ByteArray) {
+ static_cast<QColor *>(result)->setNamedColor(QString::fromLatin1(
+ *v_cast<QByteArray>(d)));
+ return true;
+ } else if (d->type == QVariant::Brush) {
+ if (v_cast<QBrush>(d)->style() == Qt::SolidPattern) {
+ *static_cast<QColor *>(result) = v_cast<QBrush>(d)->color();
+ return true;
+ }
+ }
+ break;
+ case QVariant::Brush:
+ if (d->type == QVariant::Color) {
+ *static_cast<QBrush *>(result) = QBrush(*v_cast<QColor>(d));
+ return true;
+ } else if (d->type == QVariant::Pixmap) {
+ *static_cast<QBrush *>(result) = QBrush(*v_cast<QPixmap>(d));
+ return true;
+ }
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence: {
+ QKeySequence *seq = static_cast<QKeySequence *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *seq = QKeySequence(*v_cast<QString>(d));
+ return true;
+ case QVariant::Int:
+ *seq = QKeySequence(d->data.i);
+ return true;
+ default:
+ break;
+ }
+ }
+#endif
+ default:
+ break;
+ }
+ return qcoreVariantHandler()->convert(d, t, result, ok);
+}
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+static void streamDebug(QDebug dbg, const QVariant &v)
+{
+ switch(v.type()) {
+ case QVariant::Cursor:
+#ifndef QT_NO_CURSOR
+// dbg.nospace() << qvariant_cast<QCursor>(v); //FIXME
+#endif
+ break;
+ case QVariant::Bitmap:
+// dbg.nospace() << qvariant_cast<QBitmap>(v); //FIXME
+ break;
+ case QVariant::Polygon:
+ dbg.nospace() << qvariant_cast<QPolygon>(v);
+ break;
+ case QVariant::Region:
+ dbg.nospace() << qvariant_cast<QRegion>(v);
+ break;
+ case QVariant::Font:
+// dbg.nospace() << qvariant_cast<QFont>(v); //FIXME
+ break;
+ case QVariant::Matrix:
+ dbg.nospace() << qvariant_cast<QMatrix>(v);
+ break;
+ case QVariant::Transform:
+ dbg.nospace() << qvariant_cast<QTransform>(v);
+ break;
+ case QVariant::Pixmap:
+// dbg.nospace() << qvariant_cast<QPixmap>(v); //FIXME
+ break;
+ case QVariant::Image:
+// dbg.nospace() << qvariant_cast<QImage>(v); //FIXME
+ break;
+ case QVariant::Brush:
+ dbg.nospace() << qvariant_cast<QBrush>(v);
+ break;
+ case QVariant::Color:
+ dbg.nospace() << qvariant_cast<QColor>(v);
+ break;
+ case QVariant::Palette:
+// dbg.nospace() << qvariant_cast<QPalette>(v); //FIXME
+ break;
+#ifndef QT_NO_ICON
+ case QVariant::Icon:
+// dbg.nospace() << qvariant_cast<QIcon>(v); // FIXME
+ break;
+#endif
+ case QVariant::SizePolicy:
+// dbg.nospace() << qvariant_cast<QSizePolicy>(v); //FIXME
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QVariant::KeySequence:
+ dbg.nospace() << qvariant_cast<QKeySequence>(v);
+ break;
+#endif
+ case QVariant::Pen:
+ dbg.nospace() << qvariant_cast<QPen>(v);
+ break;
+ default:
+ qcoreVariantHandler()->debugStream(dbg, v);
+ break;
+ }
+}
+#endif
+
+const QVariant::Handler qt_gui_variant_handler = {
+ construct,
+ clear,
+ isNull,
+#ifndef QT_NO_DATASTREAM
+ 0,
+ 0,
+#endif
+ compare,
+ convert,
+ 0,
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+ streamDebug
+#else
+ 0
+#endif
+};
+
+struct QMetaTypeGuiHelper
+{
+ QMetaType::Constructor constr;
+ QMetaType::Destructor destr;
+#ifndef QT_NO_DATASTREAM
+ QMetaType::SaveOperator saveOp;
+ QMetaType::LoadOperator loadOp;
+#endif
+};
+
+extern Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeGuiHelper;
+
+
+#ifdef QT_NO_DATASTREAM
+# define Q_DECL_METATYPE_HELPER(TYPE) \
+ typedef void *(*QConstruct##TYPE)(const TYPE *); \
+ static const QConstruct##TYPE qConstruct##TYPE = qMetaTypeConstructHelper<TYPE>; \
+ typedef void (*QDestruct##TYPE)(TYPE *); \
+ static const QDestruct##TYPE qDestruct##TYPE = qMetaTypeDeleteHelper<TYPE>;
+#else
+# define Q_DECL_METATYPE_HELPER(TYPE) \
+ typedef void *(*QConstruct##TYPE)(const TYPE *); \
+ static const QConstruct##TYPE qConstruct##TYPE = qMetaTypeConstructHelper<TYPE>; \
+ typedef void (*QDestruct##TYPE)(TYPE *); \
+ static const QDestruct##TYPE qDestruct##TYPE = qMetaTypeDeleteHelper<TYPE>; \
+ typedef void (*QSave##TYPE)(QDataStream &, const TYPE *); \
+ static const QSave##TYPE qSave##TYPE = qMetaTypeSaveHelper<TYPE>; \
+ typedef void (*QLoad##TYPE)(QDataStream &, TYPE *); \
+ static const QLoad##TYPE qLoad##TYPE = qMetaTypeLoadHelper<TYPE>;
+#endif
+
+#ifdef QT3_SUPPORT
+Q_DECL_METATYPE_HELPER(QColorGroup)
+#endif
+Q_DECL_METATYPE_HELPER(QFont)
+Q_DECL_METATYPE_HELPER(QPixmap)
+Q_DECL_METATYPE_HELPER(QBrush)
+Q_DECL_METATYPE_HELPER(QColor)
+Q_DECL_METATYPE_HELPER(QPalette)
+#ifndef QT_NO_ICON
+Q_DECL_METATYPE_HELPER(QIcon)
+#endif
+Q_DECL_METATYPE_HELPER(QImage)
+Q_DECL_METATYPE_HELPER(QPolygon)
+Q_DECL_METATYPE_HELPER(QRegion)
+Q_DECL_METATYPE_HELPER(QBitmap)
+#ifndef QT_NO_CURSOR
+Q_DECL_METATYPE_HELPER(QCursor)
+#endif
+Q_DECL_METATYPE_HELPER(QSizePolicy)
+#ifndef QT_NO_SHORTCUT
+Q_DECL_METATYPE_HELPER(QKeySequence)
+#endif
+Q_DECL_METATYPE_HELPER(QPen)
+Q_DECL_METATYPE_HELPER(QTextLength)
+Q_DECL_METATYPE_HELPER(QTextFormat)
+Q_DECL_METATYPE_HELPER(QMatrix)
+Q_DECL_METATYPE_HELPER(QTransform)
+
+#ifdef QT_NO_DATASTREAM
+# define Q_IMPL_METATYPE_HELPER(TYPE) \
+ { reinterpret_cast<QMetaType::Constructor>(qConstruct##TYPE), \
+ reinterpret_cast<QMetaType::Destructor>(qDestruct##TYPE) }
+#else
+# define Q_IMPL_METATYPE_HELPER(TYPE) \
+ { reinterpret_cast<QMetaType::Constructor>(qConstruct##TYPE), \
+ reinterpret_cast<QMetaType::Destructor>(qDestruct##TYPE), \
+ reinterpret_cast<QMetaType::SaveOperator>(qSave##TYPE), \
+ reinterpret_cast<QMetaType::LoadOperator>(qLoad##TYPE) \
+ }
+#endif
+
+static const QMetaTypeGuiHelper qVariantGuiHelper[] = {
+#ifdef QT3_SUPPORT
+ Q_IMPL_METATYPE_HELPER(QColorGroup),
+#else
+ {0, 0, 0, 0},
+#endif
+ Q_IMPL_METATYPE_HELPER(QFont),
+ Q_IMPL_METATYPE_HELPER(QPixmap),
+ Q_IMPL_METATYPE_HELPER(QBrush),
+ Q_IMPL_METATYPE_HELPER(QColor),
+ Q_IMPL_METATYPE_HELPER(QPalette),
+#ifdef QT_NO_ICON
+ {0, 0, 0, 0},
+#else
+ Q_IMPL_METATYPE_HELPER(QIcon),
+#endif
+ Q_IMPL_METATYPE_HELPER(QImage),
+ Q_IMPL_METATYPE_HELPER(QPolygon),
+ Q_IMPL_METATYPE_HELPER(QRegion),
+ Q_IMPL_METATYPE_HELPER(QBitmap),
+#ifdef QT_NO_CURSOR
+ {0, 0, 0, 0},
+#else
+ Q_IMPL_METATYPE_HELPER(QCursor),
+#endif
+ Q_IMPL_METATYPE_HELPER(QSizePolicy),
+#ifdef QT_NO_SHORTCUT
+ {0, 0, 0, 0},
+#else
+ Q_IMPL_METATYPE_HELPER(QKeySequence),
+#endif
+ Q_IMPL_METATYPE_HELPER(QPen),
+ Q_IMPL_METATYPE_HELPER(QTextLength),
+ Q_IMPL_METATYPE_HELPER(QTextFormat),
+ Q_IMPL_METATYPE_HELPER(QMatrix),
+ Q_IMPL_METATYPE_HELPER(QTransform)
+};
+
+static const QVariant::Handler *qt_guivariant_last_handler = 0;
+int qRegisterGuiVariant()
+{
+ qt_guivariant_last_handler = QVariant::handler;
+ QVariant::handler = &qt_gui_variant_handler;
+ qMetaTypeGuiHelper = qVariantGuiHelper;
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant)
+
+int qUnregisterGuiVariant()
+{
+ QVariant::handler = qt_guivariant_last_handler;
+ qMetaTypeGuiHelper = 0;
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiVariant)
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
new file mode 100644
index 0000000000..535d0094fd
--- /dev/null
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qapplication.h"
+
+#include <private/qobject_p.h>
+#include "qkeymapper_p.h"
+#include <qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QKeyMapper
+ \since 4.2
+ \ingroup application
+ \internal
+
+ \sa QObject
+*/
+
+/*!
+ Constructs a new key mapper.
+*/
+QKeyMapper::QKeyMapper()
+ : QObject(*new QKeyMapperPrivate, 0)
+{
+}
+
+/*!
+ Destroys the key mapper.
+*/
+QKeyMapper::~QKeyMapper()
+{
+}
+
+QList<int> QKeyMapper::possibleKeys(QKeyEvent *e)
+{
+ QList<int> result;
+
+ if (!e->nativeScanCode()) {
+ if (e->key() && (e->key() != Qt::Key_unknown))
+ result << int(e->key() + e->modifiers());
+ else if (!e->text().isEmpty())
+ result << int(e->text().at(0).unicode() + e->modifiers());
+ return result;
+ }
+
+ return instance()->d_func()->possibleKeys(e);
+}
+
+extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // in qapplication_*.cpp
+void QKeyMapper::changeKeyboard()
+{
+ instance()->d_func()->clearMappings();
+
+ // inform all toplevel widgets of the change
+ QEvent e(QEvent::KeyboardLayoutChange);
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ qt_sendSpontaneousEvent(w, &e);
+ }
+}
+
+Q_GLOBAL_STATIC(QKeyMapper, keymapper)
+/*!
+ Returns the pointer to the single instance of QKeyMapper in the application.
+ If none yet exists, the function ensures that one is created.
+*/
+QKeyMapper *QKeyMapper::instance()
+{
+ return keymapper();
+}
+
+QKeyMapperPrivate *qt_keymapper_private()
+{
+ return QKeyMapper::instance()->d_func();
+}
+
+Q_GUI_EXPORT QList<int> qt_keymapper_possibleKeys(QKeyEvent *e) { return QKeyMapper::instance()->possibleKeys(e); }
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp
new file mode 100644
index 0000000000..1a0fb08433
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_mac.cpp
@@ -0,0 +1,931 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qt_mac_p.h>
+#include <qdebug.h>
+#include <qevent.h>
+#include <private/qevent_p.h>
+#include <qtextcodec.h>
+#include <qapplication.h>
+#include <qinputcontext.h>
+#include <private/qkeymapper_p.h>
+#include <private/qapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+/*****************************************************************************
+ QKeyMapper debug facilities
+ *****************************************************************************/
+//#define DEBUG_KEY_BINDINGS
+//#define DEBUG_KEY_BINDINGS_MODIFIERS
+//#define DEBUG_KEY_MAPS
+
+/*****************************************************************************
+ Internal variables and functions
+ *****************************************************************************/
+bool qt_mac_eat_unicode_key = false;
+extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); //qapplication_mac.cpp
+
+Q_GUI_EXPORT void qt_mac_secure_keyboard(bool b)
+{
+ static bool secure = false;
+ if (b != secure){
+ b ? EnableSecureEventInput() : DisableSecureEventInput();
+ secure = b;
+ }
+}
+
+/*
+ \internal
+ A Mac KeyboardLayoutItem has 8 possible states:
+ 1. Unmodified
+ 2. Shift
+ 3. Control
+ 4. Control + Shift
+ 5. Alt
+ 6. Alt + Shift
+ 7. Alt + Control
+ 8. Alt + Control + Shift
+ 9. Meta
+ 10. Meta + Shift
+ 11. Meta + Control
+ 12. Meta + Control + Shift
+ 13. Meta + Alt
+ 14. Meta + Alt + Shift
+ 15. Meta + Alt + Control
+ 16. Meta + Alt + Control + Shift
+*/
+struct KeyboardLayoutItem {
+ bool dirty;
+ quint32 qtKey[16]; // Can by any Qt::Key_<foo>, or unicode character
+};
+
+// Possible modifier states.
+// NOTE: The order of these states match the order in QKeyMapperPrivate::updatePossibleKeyCodes()!
+static const Qt::KeyboardModifiers ModsTbl[] = {
+ Qt::NoModifier, // 0
+ Qt::ShiftModifier, // 1
+ Qt::ControlModifier, // 2
+ Qt::ControlModifier | Qt::ShiftModifier, // 3
+ Qt::AltModifier, // 4
+ Qt::AltModifier | Qt::ShiftModifier, // 5
+ Qt::AltModifier | Qt::ControlModifier, // 6
+ Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
+ Qt::MetaModifier, // 8
+ Qt::MetaModifier | Qt::ShiftModifier, // 9
+ Qt::MetaModifier | Qt::ControlModifier, // 10
+ Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11
+ Qt::MetaModifier | Qt::AltModifier, // 12
+ Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13
+ Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14
+ Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15
+};
+
+/* key maps */
+struct qt_mac_enum_mapper
+{
+ int mac_code;
+ int qt_code;
+#if defined(DEBUG_KEY_BINDINGS)
+# define QT_MAC_MAP_ENUM(x) x, #x
+ const char *desc;
+#else
+# define QT_MAC_MAP_ENUM(x) x
+#endif
+};
+
+//modifiers
+static qt_mac_enum_mapper qt_mac_modifier_symbols[] = {
+ { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) },
+ { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) },
+ { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) },
+ { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) },
+ { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) },
+ { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) },
+ { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) },
+ { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) },
+ { 0, QT_MAC_MAP_ENUM(0) }
+};
+Qt::KeyboardModifiers qt_mac_get_modifiers(int keys)
+{
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys);
+#endif
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
+ for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) {
+ if (keys & qt_mac_modifier_symbols[i].mac_code) {
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc);
+#endif
+ ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code);
+ }
+ }
+ return ret;
+}
+static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
+{
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys);
+#endif
+ int ret = 0;
+ for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) {
+ if (keys & qt_mac_modifier_symbols[i].qt_code) {
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc);
+#endif
+ ret |= qt_mac_modifier_symbols[i].mac_code;
+ }
+ }
+ return ret;
+}
+void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object)
+{
+ static quint32 cachedModifiers = 0;
+ quint32 lastModifiers = cachedModifiers,
+ changedModifiers = lastModifiers ^ modifiers;
+ cachedModifiers = modifiers;
+
+ //check the bits
+ static qt_mac_enum_mapper modifier_key_symbols[] = {
+ { shiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) },
+ { rightShiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) }, //???
+ { controlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) },
+ { rightControlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) }, //???
+ { cmdKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Control) },
+ { optionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) },
+ { rightOptionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) }, //???
+ { alphaLockBit, QT_MAC_MAP_ENUM(Qt::Key_CapsLock) },
+ { kEventKeyModifierNumLockBit, QT_MAC_MAP_ENUM(Qt::Key_NumLock) },
+ { 0, QT_MAC_MAP_ENUM(0) } };
+ for (int i = 0; i <= 32; i++) { //just check each bit
+ if (!(changedModifiers & (1 << i)))
+ continue;
+ QEvent::Type etype = QEvent::KeyPress;
+ if (lastModifiers & (1 << i))
+ etype = QEvent::KeyRelease;
+ int key = 0;
+ for (uint x = 0; modifier_key_symbols[x].mac_code; x++) {
+ if (modifier_key_symbols[x].mac_code == i) {
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("got modifier changed: %s", modifier_key_symbols[x].desc);
+#endif
+ key = modifier_key_symbols[x].qt_code;
+ break;
+ }
+ }
+ if (!key) {
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("could not get modifier changed: %d", i);
+#endif
+ continue;
+ }
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("KeyEvent (modif): Sending %s to %s::%s: %d - 0x%08x",
+ etype == QEvent::KeyRelease ? "KeyRelease" : "KeyPress",
+ object ? object->metaObject()->className() : "none",
+ object ? object->objectName().toLatin1().constData() : "",
+ key, (int)modifiers);
+#endif
+ QKeyEvent ke(etype, key, qt_mac_get_modifiers(modifiers ^ (1 << i)), QLatin1String(""));
+ qt_sendSpontaneousEvent(object, &ke);
+ }
+}
+
+//keyboard keys (non-modifiers)
+static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = {
+ { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) },
+ { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) },
+ { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) },
+ { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) },
+ { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) },
+ { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) },
+ { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) },
+ { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) },
+ { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) },
+ { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) },
+ { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) },
+ { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) },
+ { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) },
+ { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) },
+ { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) },
+//ascii maps, for debug
+ { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) },
+ { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) },
+ { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) },
+ { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) },
+ { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) },
+ { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) },
+ { '@', QT_MAC_MAP_ENUM(Qt::Key_At) },
+ { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) },
+ { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) },
+ { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) },
+ { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) },
+ { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) },
+ { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) },
+ { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) },
+ { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) },
+ { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) },
+ { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) },
+ { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) },
+ { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) },
+ { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) },
+ { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) },
+ { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) },
+ { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) },
+ { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) },
+ { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) },
+ { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) },
+ { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) },
+ { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) },
+ { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) },
+ { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) },
+ { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) },
+ { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) },
+ { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) },
+ { 0, QT_MAC_MAP_ENUM(0) }
+};
+
+static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes
+ { 122, QT_MAC_MAP_ENUM(Qt::Key_F1) },
+ { 120, QT_MAC_MAP_ENUM(Qt::Key_F2) },
+ { 99, QT_MAC_MAP_ENUM(Qt::Key_F3) },
+ { 118, QT_MAC_MAP_ENUM(Qt::Key_F4) },
+ { 96, QT_MAC_MAP_ENUM(Qt::Key_F5) },
+ { 97, QT_MAC_MAP_ENUM(Qt::Key_F6) },
+ { 98, QT_MAC_MAP_ENUM(Qt::Key_F7) },
+ { 100, QT_MAC_MAP_ENUM(Qt::Key_F8) },
+ { 101, QT_MAC_MAP_ENUM(Qt::Key_F9) },
+ { 109, QT_MAC_MAP_ENUM(Qt::Key_F10) },
+ { 103, QT_MAC_MAP_ENUM(Qt::Key_F11) },
+ { 111, QT_MAC_MAP_ENUM(Qt::Key_F12) },
+ { 105, QT_MAC_MAP_ENUM(Qt::Key_F13) },
+ { 107, QT_MAC_MAP_ENUM(Qt::Key_F14) },
+ { 113, QT_MAC_MAP_ENUM(Qt::Key_F15) },
+ { 106, QT_MAC_MAP_ENUM(Qt::Key_F16) },
+ { 0, QT_MAC_MAP_ENUM(0) }
+};
+
+static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
+{
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey);
+#endif
+
+ if (key == kClearCharCode && virtualKey == 0x47)
+ return Qt::Key_Clear;
+
+ if (key.isDigit()) {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("%d: got key: %d", __LINE__, key.digitValue());
+#endif
+ return key.digitValue() + Qt::Key_0;
+ }
+
+ if (key.isLetter()) {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A'));
+#endif
+ return (key.toUpper().unicode() - 'A') + Qt::Key_A;
+ }
+ if (key.isSymbol()) {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("%d: got key: %d", __LINE__, (key.unicode()));
+#endif
+ return key.unicode();
+ }
+
+ for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) {
+ if (qt_mac_keyboard_symbols[i].mac_code == key) {
+ /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */
+ if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("%d: got key: Qt::Key_Backtab", __LINE__);
+#endif
+ return Qt::Key_Backtab;
+ }
+
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc);
+#endif
+ return qt_mac_keyboard_symbols[i].qt_code;
+ }
+ }
+
+ //last ditch try to match the scan code
+ for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) {
+ if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc);
+#endif
+ return qt_mac_keyvkey_symbols[i].qt_code;
+ }
+ }
+
+ //oh well
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey);
+#endif
+ return Qt::Key_unknown;
+}
+
+static Boolean qt_KeyEventComparatorProc(EventRef inEvent, void *data)
+{
+ UInt32 ekind = GetEventKind(inEvent),
+ eclass = GetEventClass(inEvent);
+ return (eclass == kEventClassKeyboard && (void *)ekind == data);
+}
+
+static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent, int *qtKey,
+ QChar *outChar, Qt::KeyboardModifiers *outModifiers, bool *outHandled)
+{
+#if !defined(QT_MAC_USE_COCOA) || defined(Q_OS_MAC64)
+ Q_UNUSED(er);
+ Q_UNUSED(outHandled);
+#endif
+ const UInt32 ekind = GetEventKind(keyEvent);
+ {
+ UInt32 mac_modifiers = 0;
+ GetEventParameter(keyEvent, kEventParamKeyModifiers, typeUInt32, 0,
+ sizeof(mac_modifiers), 0, &mac_modifiers);
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("************ Mapping modifiers and key ***********");
+#endif
+ *outModifiers = qt_mac_get_modifiers(mac_modifiers);
+#ifdef DEBUG_KEY_BINDINGS_MODIFIERS
+ qDebug("------------ Mapping modifiers and key -----------");
+#endif
+ }
+
+ //get keycode
+ UInt32 keyCode = 0;
+ GetEventParameter(keyEvent, kEventParamKeyCode, typeUInt32, 0, sizeof(keyCode), 0, &keyCode);
+
+ //get mac mapping
+ static UInt32 tmp_unused_state = 0L;
+ const UCKeyboardLayout *uchrData = 0;
+#if defined(Q_OS_MAC32)
+ KeyboardLayoutRef keyLayoutRef = 0;
+ KLGetCurrentKeyboardLayout(&keyLayoutRef);
+ OSStatus err;
+ if (keyLayoutRef != 0) {
+ err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData,
+ (reinterpret_cast<const void **>(&uchrData)));
+ if (err != noErr) {
+ qWarning("Qt::internal::unable to get keyboardlayout %ld %s:%d",
+ long(err), __FILE__, __LINE__);
+ }
+ }
+#else
+ QCFType<TISInputSourceRef> inputSource = TISCopyCurrentKeyboardInputSource();
+ Q_ASSERT(inputSource != 0);
+ CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(inputSource,
+ kTISPropertyUnicodeKeyLayoutData));
+ uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;
+#endif
+ *qtKey = Qt::Key_unknown;
+ if (uchrData) {
+ // The easy stuff; use the unicode stuff!
+ UniChar string[4];
+ UniCharCount actualLength;
+ UInt32 currentModifiers = GetCurrentEventKeyModifiers();
+ UInt32 currentModifiersWOAltOrControl = currentModifiers & ~(controlKey | optionKey);
+ int keyAction;
+ switch (ekind) {
+ default:
+ case kEventRawKeyDown:
+ keyAction = kUCKeyActionDown;
+ break;
+ case kEventRawKeyUp:
+ keyAction = kUCKeyActionUp;
+ break;
+ case kEventRawKeyRepeat:
+ keyAction = kUCKeyActionAutoKey;
+ break;
+ }
+ OSStatus err = UCKeyTranslate(uchrData, keyCode, keyAction,
+ ((currentModifiersWOAltOrControl >> 8) & 0xff), LMGetKbdType(),
+ kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength,
+ string);
+ if (err == noErr) {
+ *outChar = QChar(string[0]);
+ *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode);
+ if (currentModifiersWOAltOrControl != currentModifiers) {
+ // Now get the real char.
+ err = UCKeyTranslate(uchrData, keyCode, keyAction,
+ ((currentModifiers >> 8) & 0xff), LMGetKbdType(),
+ kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength,
+ string);
+ if (err == noErr)
+ *outChar = QChar(string[0]);
+ }
+ } else {
+ qWarning("Qt::internal::UCKeyTranslate is returnining %ld %s:%d",
+ long(err), __FILE__, __LINE__);
+ }
+ }
+#ifdef Q_OS_MAC32
+ else {
+ // The road less travelled; use KeyTranslate
+ const void *keyboard_layout;
+ KeyboardLayoutRef keyLayoutRef = 0;
+ KLGetCurrentKeyboardLayout(&keyLayoutRef);
+ err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData,
+ reinterpret_cast<const void **>(&keyboard_layout));
+
+ int translatedChar = KeyTranslate(keyboard_layout, (GetCurrentEventKeyModifiers() &
+ (kEventKeyModifierNumLockMask|shiftKey|cmdKey|
+ rightShiftKey|alphaLock)) | keyCode,
+ &tmp_unused_state);
+ if (!translatedChar) {
+#ifdef QT_MAC_USE_COCOA
+ if (outHandled) {
+ qt_mac_eat_unicode_key = false;
+ CallNextEventHandler(er, keyEvent);
+ *outHandled = qt_mac_eat_unicode_key;
+ }
+#endif
+ return false;
+ }
+
+ //map it into qt keys
+ *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode);
+ if (*outModifiers & (Qt::AltModifier | Qt::ControlModifier)) {
+ if (translatedChar & (1 << 7)) //high ascii
+ translatedChar = 0;
+ } else { //now get the real ascii value
+ UInt32 tmp_mod = 0L;
+ static UInt32 tmp_state = 0L;
+ if (*outModifiers & Qt::ShiftModifier)
+ tmp_mod |= shiftKey;
+ if (*outModifiers & Qt::MetaModifier)
+ tmp_mod |= controlKey;
+ if (*outModifiers & Qt::ControlModifier)
+ tmp_mod |= cmdKey;
+ if (GetCurrentEventKeyModifiers() & alphaLock) //no Qt mapper
+ tmp_mod |= alphaLock;
+ if (*outModifiers & Qt::AltModifier)
+ tmp_mod |= optionKey;
+ if (*outModifiers & Qt::KeypadModifier)
+ tmp_mod |= kEventKeyModifierNumLockMask;
+ translatedChar = KeyTranslate(keyboard_layout, tmp_mod | keyCode, &tmp_state);
+ }
+ {
+ ByteCount unilen = 0;
+ if (GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, 0, &unilen, 0)
+ == noErr && unilen == 2) {
+ GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, unilen, 0, outChar);
+ } else if (translatedChar) {
+ static QTextCodec *c = 0;
+ if (!c)
+ c = QTextCodec::codecForName("Apple Roman");
+ char tmpChar = (char)translatedChar; // **sigh**
+ *outChar = c->toUnicode(&tmpChar, 1).at(0);
+ } else {
+ *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode);
+ }
+ }
+ }
+#endif
+ if (*qtKey == Qt::Key_unknown)
+ *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode);
+ return true;
+}
+
+QKeyMapperPrivate::QKeyMapperPrivate()
+{
+ memset(keyLayout, 0, sizeof(keyLayout));
+ keyboard_layout_format.unicode = 0;
+#ifdef Q_OS_MAC32
+ keyboard_mode = NullMode;
+#else
+ currentInputSource = 0;
+#endif
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+ clearMappings();
+}
+
+bool
+QKeyMapperPrivate::updateKeyboard()
+{
+ const UCKeyboardLayout *uchrData = 0;
+#ifdef Q_OS_MAC32
+ KeyboardLayoutRef keyLayoutRef = 0;
+ KLGetCurrentKeyboardLayout(&keyLayoutRef);
+
+ if (keyboard_mode != NullMode && currentKeyboardLayout == keyLayoutRef)
+ return false;
+
+ OSStatus err;
+ if (keyLayoutRef != 0) {
+ err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData,
+ const_cast<const void **>(reinterpret_cast<const void **>(&uchrData)));
+ if (err != noErr) {
+ qWarning("Qt::internal::unable to get unicode keyboardlayout %ld %s:%d",
+ long(err), __FILE__, __LINE__);
+ }
+ }
+#else
+ QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource();
+ if (keyboard_mode != NullMode && source == currentInputSource) {
+ return false;
+ }
+ Q_ASSERT(source != 0);
+ CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source,
+ kTISPropertyUnicodeKeyLayoutData));
+ uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;
+#endif
+
+ keyboard_kind = LMGetKbdType();
+ if (uchrData) {
+ keyboard_layout_format.unicode = uchrData;
+ keyboard_mode = UnicodeMode;
+ }
+#ifdef Q_OS_MAC32
+ else {
+ void *happy;
+ err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData,
+ const_cast<const void **>(reinterpret_cast<void **>(&happy)));
+ if (err != noErr) {
+ qFatal("Qt::internal::unable to get non-unicode layout, cannot procede %ld %s:%d",
+ long(err), __FILE__, __LINE__);
+ }
+ keyboard_layout_format.other = happy;
+ keyboard_mode = OtherMode;
+ }
+
+ currentKeyboardLayout = keyLayoutRef;
+#else
+ currentInputSource = source;
+#endif
+ keyboard_dead = 0;
+ CFStringRef iso639Code;
+#ifdef Q_OS_MAC32
+# ifndef kKLLanguageCode
+# define kKLLanguageCode 9
+# endif
+ KLGetKeyboardLayoutProperty(currentKeyboardLayout, kKLLanguageCode,
+ reinterpret_cast<const void **>(&iso639Code));
+#else
+ CFArrayRef array = static_cast<CFArrayRef>(TISGetInputSourceProperty(currentInputSource, kTISPropertyInputSourceLanguages));
+ iso639Code = static_cast<CFStringRef>(CFArrayGetValueAtIndex(array, 0)); // Actually a RFC3066bis, but it's close enough
+#endif
+ if (iso639Code) {
+ keyboardInputLocale = QLocale(QCFString::toQString(iso639Code));
+ QString monday = keyboardInputLocale.dayName(1);
+ bool rtl = false;
+ for (int i = 0; i < monday.length(); ++i) {
+ switch (monday.at(i).direction()) {
+ default:
+ break;
+ case QChar::DirR:
+ case QChar::DirAL:
+ case QChar::DirRLE:
+ case QChar::DirRLO:
+ rtl = true;
+ break;
+ }
+ if (rtl)
+ break;
+ }
+ keyboardInputDirection = rtl ? Qt::RightToLeft : Qt::LeftToRight;
+ } else {
+ keyboardInputLocale = QLocale::c();
+ keyboardInputDirection = Qt::LeftToRight;
+ }
+ return true;
+}
+
+void
+QKeyMapperPrivate::clearMappings()
+{
+ keyboard_mode = NullMode;
+ for (int i = 0; i < 255; ++i) {
+ if (keyLayout[i]) {
+ delete keyLayout[i];
+ keyLayout[i] = 0;
+ }
+ }
+ updateKeyboard();
+}
+
+QList<int>
+QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
+{
+ QList<int> ret;
+
+ KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()];
+ if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard)
+ return ret;
+
+ int baseKey = kbItem->qtKey[0];
+ Qt::KeyboardModifiers keyMods = e->modifiers();
+ ret << int(baseKey + keyMods); // The base key is _always_ valid, of course
+
+ for (int i = 1; i < 8; ++i) {
+ Qt::KeyboardModifiers neededMods = ModsTbl[i];
+ int key = kbItem->qtKey[i];
+ if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
+ ret << int(key + (keyMods & ~neededMods));
+ }
+
+ return ret;
+}
+
+bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef er, EventRef event,
+ void *info, bool grab)
+{
+ Q_ASSERT(GetEventClass(event) == kEventClassKeyboard);
+ bool handled_event=true;
+ UInt32 ekind = GetEventKind(event);
+
+ // unfortunately modifiers changed event looks quite different, so I have a separate
+ // code path
+ if (ekind == kEventRawKeyModifiersChanged) {
+ //figure out changed modifiers, wish Apple would just send a delta
+ UInt32 modifiers = 0;
+ GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0,
+ sizeof(modifiers), 0, &modifiers);
+ qt_mac_send_modifiers_changed(modifiers, widget);
+ return true;
+ }
+
+ if (qApp->inputContext() && qApp->inputContext()->isComposing())
+ return false;
+ //get modifiers
+ Qt::KeyboardModifiers modifiers;
+ int qtKey;
+ QChar ourChar;
+ if (translateKeyEventInternal(er, event, &qtKey, &ourChar, &modifiers,
+ &handled_event) == false)
+ return handled_event;
+ QString text(ourChar);
+ /* This is actually wrong - but unfortunatly it is the best that can be
+ done for now because of the Control/Meta mapping problems */
+ if (modifiers & (Qt::ControlModifier | Qt::MetaModifier))
+ text = QString();
+
+
+ if (widget) {
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(info);
+ // Try not to call "other" event handlers if we have a popup,
+ // However, if the key has text
+ // then we should pass it along because otherwise then people
+ // can use input method stuff.
+ if (!qApp->activePopupWidget()
+ || (qApp->activePopupWidget() && !text.isEmpty())) {
+ //Find out if someone else wants the event, namely
+ //is it of use to text services? If so we won't bother
+ //with a QKeyEvent.
+ qt_mac_eat_unicode_key = false;
+ CallNextEventHandler(er, event);
+ extern bool qt_mac_menubar_is_open();
+ if (qt_mac_eat_unicode_key || qt_mac_menubar_is_open()) {
+ return true;
+ }
+ }
+#endif
+ // Try to compress key events.
+ if (!text.isEmpty() && widget->testAttribute(Qt::WA_KeyCompression)) {
+ EventTime lastTime = GetEventTime(event);
+ for (;;) {
+ EventRef releaseEvent = FindSpecificEventInQueue(GetMainEventQueue(),
+ qt_KeyEventComparatorProc,
+ (void*)kEventRawKeyUp);
+ if (!releaseEvent)
+ break;
+ const EventTime releaseTime = GetEventTime(releaseEvent);
+ if (releaseTime < lastTime)
+ break;
+ lastTime = releaseTime;
+
+ EventRef pressEvent = FindSpecificEventInQueue(GetMainEventQueue(),
+ qt_KeyEventComparatorProc,
+ (void*)kEventRawKeyDown);
+ if (!pressEvent)
+ break;
+ const EventTime pressTime = GetEventTime(pressEvent);
+ if (pressTime < lastTime)
+ break;
+ lastTime = pressTime;
+
+ Qt::KeyboardModifiers compressMod;
+ int compressQtKey = 0;
+ QChar compressChar;
+ if (translateKeyEventInternal(er, pressEvent,
+ &compressQtKey, &compressChar, &compressMod, 0)
+ == false) {
+ break;
+ }
+ // Copied from qapplication_x11.cpp (change both).
+
+ bool stopCompression =
+ // 1) misc keys
+ (compressQtKey >= Qt::Key_Escape && compressQtKey <= Qt::Key_SysReq)
+ // 2) cursor movement
+ || (compressQtKey >= Qt::Key_Home && compressQtKey <= Qt::Key_PageDown)
+ // 3) extra keys
+ || (compressQtKey >= Qt::Key_Super_L && compressQtKey <= Qt::Key_Direction_R)
+ // 4) something that a) doesn't translate to text or b) translates
+ // to newline text
+ || (compressQtKey == 0)
+ || (compressChar == QLatin1Char('\n'))
+ || (compressQtKey == Qt::Key_unknown);
+
+ if (compressMod == modifiers && !compressChar.isNull() && !stopCompression) {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("compressing away %c", compressChar.toLatin1());
+#endif
+ text += compressChar;
+ // Clean up
+ RemoveEventFromQueue(GetMainEventQueue(), releaseEvent);
+ RemoveEventFromQueue(GetMainEventQueue(), pressEvent);
+ } else {
+#ifdef DEBUG_KEY_BINDINGS
+ qDebug("stoping compression..");
+#endif
+ break;
+ }
+ }
+ }
+
+ // There is no way to get the scan code from carbon. But we cannot use the value 0, since
+ // it indicates that the event originates from somewhere else than the keyboard
+ UInt32 macScanCode = 1;
+ UInt32 macVirtualKey = 0;
+ GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey);
+ UInt32 macModifiers = 0;
+ GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0,
+ sizeof(macModifiers), 0, &macModifiers);
+ handled_event = QKeyMapper::sendKeyEvent(widget, grab,
+ (ekind == kEventRawKeyUp) ? QEvent::KeyRelease : QEvent::KeyPress,
+ qtKey, modifiers, text, ekind == kEventRawKeyRepeat, 0,
+ macScanCode, macVirtualKey, macModifiers
+#ifdef QT_MAC_USE_COCOA
+ ,static_cast<bool *>(info)
+#endif
+ );
+ }
+ return handled_event;
+}
+
+void
+QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *)
+{
+ UInt32 macVirtualKey = 0;
+ GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey);
+ if (updateKeyboard())
+ QKeyMapper::changeKeyboard();
+ else if (keyLayout[macVirtualKey])
+ return;
+
+ UniCharCount buffer_size = 10;
+ UniChar buffer[buffer_size];
+ keyLayout[macVirtualKey] = new KeyboardLayoutItem;
+ for (int i = 0; i < 16; ++i) {
+ UniCharCount out_buffer_size = 0;
+ keyLayout[macVirtualKey]->qtKey[i] = 0;
+#ifdef Q_WS_MAC32
+ if (keyboard_mode == UnicodeMode) {
+#endif
+ const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF);
+ OSStatus err = UCKeyTranslate(keyboard_layout_format.unicode, macVirtualKey, kUCKeyActionDown, keyModifier,
+ keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer);
+ if (err == noErr && out_buffer_size) {
+ const QChar unicode(buffer[0]);
+ int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
+ if (qtkey == Qt::Key_unknown)
+ qtkey = unicode.unicode();
+ keyLayout[macVirtualKey]->qtKey[i] = qtkey;
+ }
+#ifdef Q_WS_MAC32
+ } else {
+ const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i]));
+
+ uchar translatedChar = KeyTranslate(keyboard_layout_format.other, keyModifier | macVirtualKey, &keyboard_dead);
+ if (translatedChar) {
+ static QTextCodec *c = 0;
+ if (!c)
+ c = QTextCodec::codecForName("Apple Roman");
+ const QChar unicode(c->toUnicode((const char *)&translatedChar, 1).at(0));
+ int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
+ if (qtkey == Qt::Key_unknown)
+ qtkey = unicode.unicode();
+ keyLayout[macVirtualKey]->qtKey[i] = qtkey;
+ }
+ }
+#endif
+ }
+#ifdef DEBUG_KEY_MAPS
+ qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey);
+ for (int i = 0; i < 16; ++i) {
+ qDebug(" [%d] (%d,0x%02x,'%c')", i,
+ keyLayout[macVirtualKey]->qtKey[i],
+ keyLayout[macVirtualKey]->qtKey[i],
+ keyLayout[macVirtualKey]->qtKey[i]);
+ }
+#endif
+}
+
+bool
+QKeyMapper::sendKeyEvent(QWidget *widget, bool grab,
+ QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
+ const QString &text, bool autorepeat, int count,
+ quint32 nativeScanCode, quint32 nativeVirtualKey,
+ quint32 nativeModifiers, bool *isAccepted)
+{
+ Q_UNUSED(count);
+ if (widget && widget->isEnabled()) {
+ bool key_event = true;
+#if defined(QT3_SUPPORT) && !defined(QT_NO_SHORTCUT)
+ if (type == QEvent::KeyPress && !grab
+ && QApplicationPrivate::instance()->use_compat()) {
+ QKeyEventEx accel_ev(type, code, modifiers,
+ text, autorepeat, qMax(1, int(text.length())),
+ nativeScanCode, nativeVirtualKey, nativeModifiers);
+ if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &accel_ev)) {
+#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS)
+ qDebug("KeyEvent: %s::%s consumed Accel: %s",
+ widget ? widget->metaObject()->className() : "none",
+ widget ? widget->objectName().toLatin1().constData() : "",
+ text.toLatin1().constData());
+#endif
+ key_event = false;
+ } else {
+ if (accel_ev.isAccepted()) {
+#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS)
+ qDebug("KeyEvent: %s::%s overrode Accel: %s",
+ widget ? widget->metaObject()->className() : "none",
+ widget ? widget->objectName().toLatin1().constData() : "",
+ text.toLatin1().constData());
+#endif
+ }
+ }
+ }
+#else
+Q_UNUSED(grab);
+#endif // QT3_SUPPORT && !QT_NO_SHORTCUT
+ if (key_event) {
+#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS)
+ qDebug("KeyEvent: Sending %s to %s::%s: %s 0x%08x%s",
+ type == QEvent::KeyRelease ? "KeyRelease" : "KeyPress",
+ widget ? widget->metaObject()->className() : "none",
+ widget ? widget->objectName().toLatin1().constData() : "",
+ text.toLatin1().constData(), int(modifiers),
+ autorepeat ? " Repeat" : "");
+#endif
+ QKeyEventEx ke(type, code, modifiers, text, autorepeat, qMax(1, text.length()),
+ nativeScanCode, nativeVirtualKey, nativeModifiers);
+ bool retMe = qt_sendSpontaneousEvent(widget,&ke);
+ if (isAccepted)
+ *isAccepted = ke.isAccepted();
+ return retMe;
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
new file mode 100644
index 0000000000..f1d938c170
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QKEYMAPPER_P_H
+#define QKEYMAPPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qobject.h>
+#include <private/qobject_p.h>
+#include <qkeysequence.h>
+#include <qlist.h>
+#include <qlocale.h>
+#include <qevent.h>
+
+#if defined (Q_WS_MAC64)
+# include <private/qt_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QKeyMapperPrivate;
+class QKeyMapper : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QKeyMapper();
+ ~QKeyMapper();
+
+ static QKeyMapper *instance();
+ static void changeKeyboard();
+ static bool sendKeyEvent(QWidget *widget, bool grab,
+ QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
+ const QString &text, bool autorepeat, int count,
+ quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
+ bool *unusedExceptForCocoa = 0);
+ static QList<int> possibleKeys(QKeyEvent *e);
+
+private:
+ friend QKeyMapperPrivate *qt_keymapper_private();
+ Q_DECLARE_PRIVATE(QKeyMapper)
+ Q_DISABLE_COPY(QKeyMapper)
+};
+
+
+
+#if defined(Q_OS_WIN)
+enum WindowsNativeModifiers {
+ ShiftLeft = 0x00000001,
+ ControlLeft = 0x00000002,
+ AltLeft = 0x00000004,
+ MetaLeft = 0x00000008,
+ ShiftRight = 0x00000010,
+ ControlRight = 0x00000020,
+ AltRight = 0x00000040,
+ MetaRight = 0x00000080,
+ CapsLock = 0x00000100,
+ NumLock = 0x00000200,
+ ScrollLock = 0x00000400,
+ ExtendedKey = 0x01000000,
+
+ // Convenience mappings
+ ShiftAny = 0x00000011,
+ ControlAny = 0x00000022,
+ AltAny = 0x00000044,
+ MetaAny = 0x00000088,
+ LockAny = 0x00000700
+};
+# if !defined(tagMSG)
+ typedef struct tagMSG MSG;
+# endif
+#elif defined(Q_WS_MAC)
+QT_BEGIN_INCLUDE_NAMESPACE
+# include <private/qt_mac_p.h>
+QT_END_INCLUDE_NAMESPACE
+#elif defined(Q_WS_X11)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+typedef ulong XID;
+typedef XID KeySym;
+QT_END_INCLUDE_NAMESPACE
+
+struct QXCoreDesc {
+ int min_keycode;
+ int max_keycode;
+ int keysyms_per_keycode;
+ KeySym *keysyms;
+ uchar mode_switch;
+ uchar num_lock;
+ KeySym lock_meaning;
+};
+
+#endif
+
+struct KeyboardLayoutItem;
+typedef struct __TISInputSource * TISInputSourceRef;
+class QKeyEvent;
+class QKeyMapperPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QKeyMapper)
+public:
+ QKeyMapperPrivate();
+ ~QKeyMapperPrivate();
+
+ void clearMappings();
+ QList<int> possibleKeys(QKeyEvent *e);
+
+ QLocale keyboardInputLocale;
+ Qt::LayoutDirection keyboardInputDirection;
+
+#if defined(Q_OS_WIN)
+ void clearRecordedKeys();
+ void updateKeyMap(const MSG &msg);
+ bool translateKeyEvent(QWidget *receiver, const MSG &msg, bool grab);
+ void updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode, quint32 vk_key);
+ bool isADeadKey(unsigned int vk_key, unsigned int modifiers);
+
+ KeyboardLayoutItem *keyLayout[256];
+
+#elif defined(Q_WS_X11)
+
+ QList<int> possibleKeysXKB(QKeyEvent *event);
+ QList<int> possibleKeysCore(QKeyEvent *event);
+
+ bool translateKeyEventInternal(QWidget *keywidget,
+ const XEvent *,
+ KeySym &keysym,
+ int& count,
+ QString& text,
+ Qt::KeyboardModifiers& modifiers,
+ int &code,
+ QEvent::Type &type,
+ bool statefulTranslation = true);
+ bool translateKeyEvent(QWidget *keywidget,
+ const XEvent *,
+ bool grab);
+
+ bool useXKB;
+ QXCoreDesc coreDesc;
+
+#elif defined(Q_WS_MAC)
+ bool updateKeyboard();
+ void updateKeyMap(EventHandlerCallRef, EventRef, void *);
+ bool translateKeyEvent(QWidget *, EventHandlerCallRef, EventRef, void *, bool);
+
+ enum { NullMode, UnicodeMode, OtherMode } keyboard_mode;
+ union {
+ const UCKeyboardLayout *unicode;
+ void *other;
+ } keyboard_layout_format;
+#ifdef Q_WS_MAC64
+ QCFType<TISInputSourceRef> currentInputSource;
+#else
+ KeyboardLayoutRef currentKeyboardLayout;
+#endif
+ KeyboardLayoutKind keyboard_kind;
+ UInt32 keyboard_dead;
+ KeyboardLayoutItem *keyLayout[256];
+#elif defined(Q_WS_QWS)
+#endif
+};
+
+QKeyMapperPrivate *qt_keymapper_private(); // from qkeymapper.cpp
+
+QT_END_NAMESPACE
+
+#endif // QKEYMAPPER_P_H
diff --git a/src/gui/kernel/qkeymapper_qws.cpp b/src/gui/kernel/qkeymapper_qws.cpp
new file mode 100644
index 0000000000..4bd18af7af
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_qws.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeymapper_p.h"
+#include <qdebug.h>
+#include <private/qevent_p.h>
+#include <private/qlocale_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+
+QKeyMapperPrivate::QKeyMapperPrivate()
+{
+ keyboardInputLocale = QLocale::system();
+ keyboardInputDirection = Qt::RightToLeft;
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+ // clearMappings();
+}
+
+void QKeyMapperPrivate::clearMappings()
+{
+}
+
+QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
+{
+ QList<int> result;
+ if (e->key() && (e->key() != Qt::Key_unknown))
+ result << int(e->key() + e->modifiers());
+ else if (!e->text().isEmpty())
+ result << int(e->text().at(0).unicode() + e->modifiers());
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp
new file mode 100644
index 0000000000..5f840442f7
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_win.cpp
@@ -0,0 +1,1259 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeymapper_p.h"
+
+#include <windows.h>
+#include <qdebug.h>
+#include <private/qevent_p.h>
+#include <private/qlocale_p.h>
+#include <private/qapplication_p.h>
+#include <qwidget.h>
+#include <qapplication.h>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+// Uncommend, to show debugging information for the keymapper
+//#define DEBUG_KEYMAPPER
+
+// Implemented elsewhere
+extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
+ UINT wRemoveMsg);
+extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id);
+#ifndef LANG_PASHTO
+#define LANG_PASHTO 0x63
+#endif
+#ifndef LANG_SYRIAC
+#define LANG_SYRIAC 0x5a
+#endif
+#ifndef LANG_DIVEHI
+#define LANG_DIVEHI 0x65
+#endif
+#ifndef VK_OEM_PLUS
+#define VK_OEM_PLUS 0xBB
+#endif
+#ifndef VK_OEM_3
+#define VK_OEM_3 0xC0
+#endif
+
+#if defined(Q_OS_WINCE)
+bool GetKeyboardState(unsigned char* kbuffer)
+{
+ for (int i=0; i< 256; ++i)
+ kbuffer[i] = GetAsyncKeyState(i);
+ return true;
+}
+#endif
+// Key recorder ------------------------------------------------------------------------[ start ] --
+struct KeyRecord {
+ KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {}
+ KeyRecord() {}
+
+ int code;
+ int ascii;
+ int state;
+ QString text;
+};
+
+static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers...
+struct KeyRecorder
+{
+ KeyRecorder() : nrecs(0) {}
+
+ inline KeyRecord *findKey(int code, bool remove);
+ inline void storeKey(int code, int ascii, int state, const QString& text);
+ inline void clearKeys();
+
+ int nrecs;
+ KeyRecord deleted_record; // A copy of last entry removed from records[]
+ KeyRecord records[QT_MAX_KEY_RECORDINGS];
+};
+static KeyRecorder key_recorder;
+
+KeyRecord *KeyRecorder::findKey(int code, bool remove)
+{
+ KeyRecord *result = 0;
+ for (int i = 0; i < nrecs; ++i) {
+ if (records[i].code == code) {
+ if (remove) {
+ deleted_record = records[i];
+ // Move rest down, and decrease count
+ while (i + 1 < nrecs) {
+ records[i] = records[i + 1];
+ ++i;
+ }
+ --nrecs;
+ result = &deleted_record;
+ } else {
+ result = &records[i];
+ }
+ break;
+ }
+ }
+ return result;
+}
+
+void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text)
+{
+ Q_ASSERT_X(nrecs != QT_MAX_KEY_RECORDINGS,
+ "Internal KeyRecorder",
+ "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
+
+ if (nrecs == QT_MAX_KEY_RECORDINGS) {
+ qWarning("Qt: Internal keyboard buffer overflow");
+ return;
+ }
+ records[nrecs++] = KeyRecord(code,ascii,state,text);
+}
+
+void KeyRecorder::clearKeys()
+{
+ nrecs = 0;
+}
+// Key recorder --------------------------------------------------------------------------[ end ] --
+
+
+// Key translation ---------------------------------------------------------------------[ start ] --
+// Meaning of values:
+// 0 = Character output key, needs keyboard driver mapping
+// Key_unknown = Unknown Virtual Key, no translation possible, ignore
+static const uint KeyTbl[] = { // Keyboard mapping table
+ // Dec | Hex | Windows Virtual key
+ Qt::Key_unknown, // 0 0x00
+ Qt::Key_unknown, // 1 0x01 VK_LBUTTON | Left mouse button
+ Qt::Key_unknown, // 2 0x02 VK_RBUTTON | Right mouse button
+ Qt::Key_Cancel, // 3 0x03 VK_CANCEL | Control-Break processing
+ Qt::Key_unknown, // 4 0x04 VK_MBUTTON | Middle mouse button
+ Qt::Key_unknown, // 5 0x05 VK_XBUTTON1 | X1 mouse button
+ Qt::Key_unknown, // 6 0x06 VK_XBUTTON2 | X2 mouse button
+ Qt::Key_unknown, // 7 0x07 -- unassigned --
+ Qt::Key_Backspace, // 8 0x08 VK_BACK | BackSpace key
+ Qt::Key_Tab, // 9 0x09 VK_TAB | Tab key
+ Qt::Key_unknown, // 10 0x0A -- reserved --
+ Qt::Key_unknown, // 11 0x0B -- reserved --
+ Qt::Key_Clear, // 12 0x0C VK_CLEAR | Clear key
+ Qt::Key_Return, // 13 0x0D VK_RETURN | Enter key
+ Qt::Key_unknown, // 14 0x0E -- unassigned --
+ Qt::Key_unknown, // 15 0x0F -- unassigned --
+ Qt::Key_Shift, // 16 0x10 VK_SHIFT | Shift key
+ Qt::Key_Control, // 17 0x11 VK_CONTROL | Ctrl key
+ Qt::Key_Alt, // 18 0x12 VK_MENU | Alt key
+ Qt::Key_Pause, // 19 0x13 VK_PAUSE | Pause key
+ Qt::Key_CapsLock, // 20 0x14 VK_CAPITAL | Caps-Lock
+ Qt::Key_unknown, // 21 0x15 VK_KANA / VK_HANGUL | IME Kana or Hangul mode
+ Qt::Key_unknown, // 22 0x16 -- unassigned --
+ Qt::Key_unknown, // 23 0x17 VK_JUNJA | IME Junja mode
+ Qt::Key_unknown, // 24 0x18 VK_FINAL | IME final mode
+ Qt::Key_unknown, // 25 0x19 VK_HANJA / VK_KANJI | IME Hanja or Kanji mode
+ Qt::Key_unknown, // 26 0x1A -- unassigned --
+ Qt::Key_Escape, // 27 0x1B VK_ESCAPE | Esc key
+ Qt::Key_unknown, // 28 0x1C VK_CONVERT | IME convert
+ Qt::Key_unknown, // 29 0x1D VK_NONCONVERT | IME non-convert
+ Qt::Key_unknown, // 30 0x1E VK_ACCEPT | IME accept
+ Qt::Key_Mode_switch,// 31 0x1F VK_MODECHANGE | IME mode change request
+ Qt::Key_Space, // 32 0x20 VK_SPACE | Spacebar
+ Qt::Key_PageUp, // 33 0x21 VK_PRIOR | Page Up key
+ Qt::Key_PageDown, // 34 0x22 VK_NEXT | Page Down key
+ Qt::Key_End, // 35 0x23 VK_END | End key
+ Qt::Key_Home, // 36 0x24 VK_HOME | Home key
+ Qt::Key_Left, // 37 0x25 VK_LEFT | Left arrow key
+ Qt::Key_Up, // 38 0x26 VK_UP | Up arrow key
+ Qt::Key_Right, // 39 0x27 VK_RIGHT | Right arrow key
+ Qt::Key_Down, // 40 0x28 VK_DOWN | Down arrow key
+ Qt::Key_Select, // 41 0x29 VK_SELECT | Select key
+ Qt::Key_Printer, // 42 0x2A VK_PRINT | Print key
+ Qt::Key_Execute, // 43 0x2B VK_EXECUTE | Execute key
+ Qt::Key_Print, // 44 0x2C VK_SNAPSHOT | Print Screen key
+ Qt::Key_Insert, // 45 0x2D VK_INSERT | Ins key
+ Qt::Key_Delete, // 46 0x2E VK_DELETE | Del key
+ Qt::Key_Help, // 47 0x2F VK_HELP | Help key
+ 0, // 48 0x30 (VK_0) | 0 key
+ 0, // 49 0x31 (VK_1) | 1 key
+ 0, // 50 0x32 (VK_2) | 2 key
+ 0, // 51 0x33 (VK_3) | 3 key
+ 0, // 52 0x34 (VK_4) | 4 key
+ 0, // 53 0x35 (VK_5) | 5 key
+ 0, // 54 0x36 (VK_6) | 6 key
+ 0, // 55 0x37 (VK_7) | 7 key
+ 0, // 56 0x38 (VK_8) | 8 key
+ 0, // 57 0x39 (VK_9) | 9 key
+ Qt::Key_unknown, // 58 0x3A -- unassigned --
+ Qt::Key_unknown, // 59 0x3B -- unassigned --
+ Qt::Key_unknown, // 60 0x3C -- unassigned --
+ Qt::Key_unknown, // 61 0x3D -- unassigned --
+ Qt::Key_unknown, // 62 0x3E -- unassigned --
+ Qt::Key_unknown, // 63 0x3F -- unassigned --
+ Qt::Key_unknown, // 64 0x40 -- unassigned --
+ 0, // 65 0x41 (VK_A) | A key
+ 0, // 66 0x42 (VK_B) | B key
+ 0, // 67 0x43 (VK_C) | C key
+ 0, // 68 0x44 (VK_D) | D key
+ 0, // 69 0x45 (VK_E) | E key
+ 0, // 70 0x46 (VK_F) | F key
+ 0, // 71 0x47 (VK_G) | G key
+ 0, // 72 0x48 (VK_H) | H key
+ 0, // 73 0x49 (VK_I) | I key
+ 0, // 74 0x4A (VK_J) | J key
+ 0, // 75 0x4B (VK_K) | K key
+ 0, // 76 0x4C (VK_L) | L key
+ 0, // 77 0x4D (VK_M) | M key
+ 0, // 78 0x4E (VK_N) | N key
+ 0, // 79 0x4F (VK_O) | O key
+ 0, // 80 0x50 (VK_P) | P key
+ 0, // 81 0x51 (VK_Q) | Q key
+ 0, // 82 0x52 (VK_R) | R key
+ 0, // 83 0x53 (VK_S) | S key
+ 0, // 84 0x54 (VK_T) | T key
+ 0, // 85 0x55 (VK_U) | U key
+ 0, // 86 0x56 (VK_V) | V key
+ 0, // 87 0x57 (VK_W) | W key
+ 0, // 88 0x58 (VK_X) | X key
+ 0, // 89 0x59 (VK_Y) | Y key
+ 0, // 90 0x5A (VK_Z) | Z key
+ Qt::Key_Meta, // 91 0x5B VK_LWIN | Left Windows - MS Natural kbd
+ Qt::Key_Meta, // 92 0x5C VK_RWIN | Right Windows - MS Natural kbd
+ Qt::Key_Menu, // 93 0x5D VK_APPS | Application key-MS Natural kbd
+ Qt::Key_unknown, // 94 0x5E -- reserved --
+ Qt::Key_Sleep, // 95 0x5F VK_SLEEP
+ Qt::Key_0, // 96 0x60 VK_NUMPAD0 | Numeric keypad 0 key
+ Qt::Key_1, // 97 0x61 VK_NUMPAD1 | Numeric keypad 1 key
+ Qt::Key_2, // 98 0x62 VK_NUMPAD2 | Numeric keypad 2 key
+ Qt::Key_3, // 99 0x63 VK_NUMPAD3 | Numeric keypad 3 key
+ Qt::Key_4, // 100 0x64 VK_NUMPAD4 | Numeric keypad 4 key
+ Qt::Key_5, // 101 0x65 VK_NUMPAD5 | Numeric keypad 5 key
+ Qt::Key_6, // 102 0x66 VK_NUMPAD6 | Numeric keypad 6 key
+ Qt::Key_7, // 103 0x67 VK_NUMPAD7 | Numeric keypad 7 key
+ Qt::Key_8, // 104 0x68 VK_NUMPAD8 | Numeric keypad 8 key
+ Qt::Key_9, // 105 0x69 VK_NUMPAD9 | Numeric keypad 9 key
+ Qt::Key_Asterisk, // 106 0x6A VK_MULTIPLY | Multiply key
+ Qt::Key_Plus, // 107 0x6B VK_ADD | Add key
+ Qt::Key_Comma, // 108 0x6C VK_SEPARATOR | Separator key
+ Qt::Key_Minus, // 109 0x6D VK_SUBTRACT | Subtract key
+ Qt::Key_Period, // 110 0x6E VK_DECIMAL | Decimal key
+ Qt::Key_Slash, // 111 0x6F VK_DIVIDE | Divide key
+ Qt::Key_F1, // 112 0x70 VK_F1 | F1 key
+ Qt::Key_F2, // 113 0x71 VK_F2 | F2 key
+ Qt::Key_F3, // 114 0x72 VK_F3 | F3 key
+ Qt::Key_F4, // 115 0x73 VK_F4 | F4 key
+ Qt::Key_F5, // 116 0x74 VK_F5 | F5 key
+ Qt::Key_F6, // 117 0x75 VK_F6 | F6 key
+ Qt::Key_F7, // 118 0x76 VK_F7 | F7 key
+ Qt::Key_F8, // 119 0x77 VK_F8 | F8 key
+ Qt::Key_F9, // 120 0x78 VK_F9 | F9 key
+ Qt::Key_F10, // 121 0x79 VK_F10 | F10 key
+ Qt::Key_F11, // 122 0x7A VK_F11 | F11 key
+ Qt::Key_F12, // 123 0x7B VK_F12 | F12 key
+ Qt::Key_F13, // 124 0x7C VK_F13 | F13 key
+ Qt::Key_F14, // 125 0x7D VK_F14 | F14 key
+ Qt::Key_F15, // 126 0x7E VK_F15 | F15 key
+ Qt::Key_F16, // 127 0x7F VK_F16 | F16 key
+ Qt::Key_F17, // 128 0x80 VK_F17 | F17 key
+ Qt::Key_F18, // 129 0x81 VK_F18 | F18 key
+ Qt::Key_F19, // 130 0x82 VK_F19 | F19 key
+ Qt::Key_F20, // 131 0x83 VK_F20 | F20 key
+ Qt::Key_F21, // 132 0x84 VK_F21 | F21 key
+ Qt::Key_F22, // 133 0x85 VK_F22 | F22 key
+ Qt::Key_F23, // 134 0x86 VK_F23 | F23 key
+ Qt::Key_F24, // 135 0x87 VK_F24 | F24 key
+ Qt::Key_unknown, // 136 0x88 -- unassigned --
+ Qt::Key_unknown, // 137 0x89 -- unassigned --
+ Qt::Key_unknown, // 138 0x8A -- unassigned --
+ Qt::Key_unknown, // 139 0x8B -- unassigned --
+ Qt::Key_unknown, // 140 0x8C -- unassigned --
+ Qt::Key_unknown, // 141 0x8D -- unassigned --
+ Qt::Key_unknown, // 142 0x8E -- unassigned --
+ Qt::Key_unknown, // 143 0x8F -- unassigned --
+ Qt::Key_NumLock, // 144 0x90 VK_NUMLOCK | Num Lock key
+ Qt::Key_ScrollLock, // 145 0x91 VK_SCROLL | Scroll Lock key
+ // Fujitsu/OASYS kbd --------------------
+ 0, //Qt::Key_Jisho, // 146 0x92 VK_OEM_FJ_JISHO | 'Dictionary' key /
+ // VK_OEM_NEC_EQUAL = key on numpad on NEC PC-9800 kbd
+ Qt::Key_Massyo, // 147 0x93 VK_OEM_FJ_MASSHOU | 'Unregister word' key
+ Qt::Key_Touroku, // 148 0x94 VK_OEM_FJ_TOUROKU | 'Register word' key
+ 0, //Qt::Key_Oyayubi_Left,//149 0x95 VK_OEM_FJ_LOYA | 'Left OYAYUBI' key
+ 0, //Qt::Key_Oyayubi_Right,//150 0x96 VK_OEM_FJ_ROYA | 'Right OYAYUBI' key
+ Qt::Key_unknown, // 151 0x97 -- unassigned --
+ Qt::Key_unknown, // 152 0x98 -- unassigned --
+ Qt::Key_unknown, // 153 0x99 -- unassigned --
+ Qt::Key_unknown, // 154 0x9A -- unassigned --
+ Qt::Key_unknown, // 155 0x9B -- unassigned --
+ Qt::Key_unknown, // 156 0x9C -- unassigned --
+ Qt::Key_unknown, // 157 0x9D -- unassigned --
+ Qt::Key_unknown, // 158 0x9E -- unassigned --
+ Qt::Key_unknown, // 159 0x9F -- unassigned --
+ Qt::Key_Shift, // 160 0xA0 VK_LSHIFT | Left Shift key
+ Qt::Key_Shift, // 161 0xA1 VK_RSHIFT | Right Shift key
+ Qt::Key_Control, // 162 0xA2 VK_LCONTROL | Left Ctrl key
+ Qt::Key_Control, // 163 0xA3 VK_RCONTROL | Right Ctrl key
+ Qt::Key_Alt, // 164 0xA4 VK_LMENU | Left Menu key
+ Qt::Key_Alt, // 165 0xA5 VK_RMENU | Right Menu key
+ Qt::Key_Back, // 166 0xA6 VK_BROWSER_BACK | Browser Back key
+ Qt::Key_Forward, // 167 0xA7 VK_BROWSER_FORWARD | Browser Forward key
+ Qt::Key_Refresh, // 168 0xA8 VK_BROWSER_REFRESH | Browser Refresh key
+ Qt::Key_Stop, // 169 0xA9 VK_BROWSER_STOP | Browser Stop key
+ Qt::Key_Search, // 170 0xAA VK_BROWSER_SEARCH | Browser Search key
+ Qt::Key_Favorites, // 171 0xAB VK_BROWSER_FAVORITES| Browser Favorites key
+ Qt::Key_HomePage, // 172 0xAC VK_BROWSER_HOME | Browser Start and Home key
+ Qt::Key_VolumeMute, // 173 0xAD VK_VOLUME_MUTE | Volume Mute key
+ Qt::Key_VolumeDown, // 174 0xAE VK_VOLUME_DOWN | Volume Down key
+ Qt::Key_VolumeUp, // 175 0xAF VK_VOLUME_UP | Volume Up key
+ Qt::Key_MediaNext, // 176 0xB0 VK_MEDIA_NEXT_TRACK | Next Track key
+ Qt::Key_MediaPrevious, //177 0xB1 VK_MEDIA_PREV_TRACK | Previous Track key
+ Qt::Key_MediaStop, // 178 0xB2 VK_MEDIA_STOP | Stop Media key
+ Qt::Key_MediaPlay, // 179 0xB3 VK_MEDIA_PLAY_PAUSE | Play/Pause Media key
+ Qt::Key_LaunchMail, // 180 0xB4 VK_LAUNCH_MAIL | Start Mail key
+ Qt::Key_LaunchMedia,// 181 0xB5 VK_LAUNCH_MEDIA_SELECT Select Media key
+ Qt::Key_Launch0, // 182 0xB6 VK_LAUNCH_APP1 | Start Application 1 key
+ Qt::Key_Launch1, // 183 0xB7 VK_LAUNCH_APP2 | Start Application 2 key
+ Qt::Key_unknown, // 184 0xB8 -- reserved --
+ Qt::Key_unknown, // 185 0xB9 -- reserved --
+ 0, // 186 0xBA VK_OEM_1 | ';:' for US
+ 0, // 187 0xBB VK_OEM_PLUS | '+' any country
+ 0, // 188 0xBC VK_OEM_COMMA | ',' any country
+ 0, // 189 0xBD VK_OEM_MINUS | '-' any country
+ 0, // 190 0xBE VK_OEM_PERIOD | '.' any country
+ 0, // 191 0xBF VK_OEM_2 | '/?' for US
+ 0, // 192 0xC0 VK_OEM_3 | '`~' for US
+ Qt::Key_unknown, // 193 0xC1 -- reserved --
+ Qt::Key_unknown, // 194 0xC2 -- reserved --
+ Qt::Key_unknown, // 195 0xC3 -- reserved --
+ Qt::Key_unknown, // 196 0xC4 -- reserved --
+ Qt::Key_unknown, // 197 0xC5 -- reserved --
+ Qt::Key_unknown, // 198 0xC6 -- reserved --
+ Qt::Key_unknown, // 199 0xC7 -- reserved --
+ Qt::Key_unknown, // 200 0xC8 -- reserved --
+ Qt::Key_unknown, // 201 0xC9 -- reserved --
+ Qt::Key_unknown, // 202 0xCA -- reserved --
+ Qt::Key_unknown, // 203 0xCB -- reserved --
+ Qt::Key_unknown, // 204 0xCC -- reserved --
+ Qt::Key_unknown, // 205 0xCD -- reserved --
+ Qt::Key_unknown, // 206 0xCE -- reserved --
+ Qt::Key_unknown, // 207 0xCF -- reserved --
+ Qt::Key_unknown, // 208 0xD0 -- reserved --
+ Qt::Key_unknown, // 209 0xD1 -- reserved --
+ Qt::Key_unknown, // 210 0xD2 -- reserved --
+ Qt::Key_unknown, // 211 0xD3 -- reserved --
+ Qt::Key_unknown, // 212 0xD4 -- reserved --
+ Qt::Key_unknown, // 213 0xD5 -- reserved --
+ Qt::Key_unknown, // 214 0xD6 -- reserved --
+ Qt::Key_unknown, // 215 0xD7 -- reserved --
+ Qt::Key_unknown, // 216 0xD8 -- unassigned --
+ Qt::Key_unknown, // 217 0xD9 -- unassigned --
+ Qt::Key_unknown, // 218 0xDA -- unassigned --
+ 0, // 219 0xDB VK_OEM_4 | '[{' for US
+ 0, // 220 0xDC VK_OEM_5 | '\|' for US
+ 0, // 221 0xDD VK_OEM_6 | ']}' for US
+ 0, // 222 0xDE VK_OEM_7 | ''"' for US
+ 0, // 223 0xDF VK_OEM_8
+ Qt::Key_unknown, // 224 0xE0 -- reserved --
+ Qt::Key_unknown, // 225 0xE1 VK_OEM_AX | 'AX' key on Japanese AX kbd
+ Qt::Key_unknown, // 226 0xE2 VK_OEM_102 | "<>" or "\|" on RT 102-key kbd
+ Qt::Key_unknown, // 227 0xE3 VK_ICO_HELP | Help key on ICO
+ Qt::Key_unknown, // 228 0xE4 VK_ICO_00 | 00 key on ICO
+ Qt::Key_unknown, // 229 0xE5 VK_PROCESSKEY | IME Process key
+ Qt::Key_unknown, // 230 0xE6 VK_ICO_CLEAR |
+ Qt::Key_unknown, // 231 0xE7 VK_PACKET | Unicode char as keystrokes
+ Qt::Key_unknown, // 232 0xE8 -- unassigned --
+ // Nokia/Ericsson definitions ---------------
+ Qt::Key_unknown, // 233 0xE9 VK_OEM_RESET
+ Qt::Key_unknown, // 234 0xEA VK_OEM_JUMP
+ Qt::Key_unknown, // 235 0xEB VK_OEM_PA1
+ Qt::Key_unknown, // 236 0xEC VK_OEM_PA2
+ Qt::Key_unknown, // 237 0xED VK_OEM_PA3
+ Qt::Key_unknown, // 238 0xEE VK_OEM_WSCTRL
+ Qt::Key_unknown, // 239 0xEF VK_OEM_CUSEL
+ Qt::Key_unknown, // 240 0xF0 VK_OEM_ATTN
+ Qt::Key_unknown, // 241 0xF1 VK_OEM_FINISH
+ Qt::Key_unknown, // 242 0xF2 VK_OEM_COPY
+ Qt::Key_unknown, // 243 0xF3 VK_OEM_AUTO
+ Qt::Key_unknown, // 244 0xF4 VK_OEM_ENLW
+ Qt::Key_unknown, // 245 0xF5 VK_OEM_BACKTAB
+ Qt::Key_unknown, // 246 0xF6 VK_ATTN | Attn key
+ Qt::Key_unknown, // 247 0xF7 VK_CRSEL | CrSel key
+ Qt::Key_unknown, // 248 0xF8 VK_EXSEL | ExSel key
+ Qt::Key_unknown, // 249 0xF9 VK_EREOF | Erase EOF key
+ Qt::Key_Play, // 250 0xFA VK_PLAY | Play key
+ Qt::Key_Zoom, // 251 0xFB VK_ZOOM | Zoom key
+ Qt::Key_unknown, // 252 0xFC VK_NONAME | Reserved
+ Qt::Key_unknown, // 253 0xFD VK_PA1 | PA1 key
+ Qt::Key_Clear, // 254 0xFE VK_OEM_CLEAR | Clear key
+ 0
+};
+
+// Possible modifier states.
+// NOTE: The order of these states match the order in QKeyMapperPrivate::updatePossibleKeyCodes()!
+static const Qt::KeyboardModifiers ModsTbl[] = {
+ Qt::NoModifier, // 0
+ Qt::ShiftModifier, // 1
+ Qt::ControlModifier, // 2
+ Qt::ControlModifier | Qt::ShiftModifier, // 3
+ Qt::AltModifier, // 4
+ Qt::AltModifier | Qt::ShiftModifier, // 5
+ Qt::AltModifier | Qt::ControlModifier, // 6
+ Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
+ Qt::NoModifier, // Fall-back to raw Key_*
+};
+
+#if defined(Q_OS_WINCE)
+ // Use the KeyTbl to resolve a Qt::Key out of the virtual keys.
+ // In case it is not resolvable, continue using the virtual key itself.
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+int ToUnicode(UINT vk, int /*scancode*/, unsigned char* /*kbdBuffer*/, LPWSTR unicodeBuffer, int, int)
+{
+ QT_USE_NAMESPACE
+ QChar* buf = reinterpret_cast< QChar*>(unicodeBuffer);
+ if (KeyTbl[vk] == 0) {
+ buf[0] = vk;
+ return 1;
+ }
+ return 0;
+}
+
+int ToAscii(UINT vk, int scancode, unsigned char *kbdBuffer, LPWORD unicodeBuffer, int flag)
+{
+ return ToUnicode(vk, scancode, kbdBuffer, (LPWSTR) unicodeBuffer, 0, flag);
+
+}
+QT_END_INCLUDE_NAMESPACE
+
+#endif
+
+// Translate a VK into a Qt key code, or unicode character
+static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, bool *isDeadkey = 0)
+{
+ Q_ASSERT(vk > 0 && vk < 256);
+ int code = 0;
+ QChar unicodeBuffer[5];
+ int res = 0;
+ if (QSysInfo::WindowsVersion < QSysInfo::WV_NT)
+ res = ToAscii(vk, scancode, kbdBuffer, reinterpret_cast<LPWORD>(unicodeBuffer), 0);
+ else
+ res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
+
+ if (res)
+ code = unicodeBuffer[0].toUpper().unicode();
+
+ // Qt::Key_*'s are not encoded below 0x20, so try again, and DEL keys (0x7f) is encoded with a
+ // proper Qt::Key_ code
+ if (code < 0x20 || code == 0x7f) // Handles res==0 too
+ code = KeyTbl[vk];
+
+ if (isDeadkey)
+ *isDeadkey = (res == -1);
+
+ return code == Qt::Key_unknown ? 0 : code;
+}
+
+Q_GUI_EXPORT int qt_translateKeyCode(int vk)
+{
+ int code = (vk < 0 || vk > 255) ? 0 : KeyTbl[vk];
+ return code == Qt::Key_unknown ? 0 : code;
+}
+
+static inline int asciiToKeycode(char a, int state)
+{
+ if (a >= 'a' && a <= 'z')
+ a = toupper(a);
+ if ((state & Qt::ControlModifier) != 0) {
+ if (a >= 0 && a <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_
+ a += '@'; // to @..A..Z.._
+ }
+ return a & 0xff;
+}
+
+static int inputcharset = CP_ACP;
+static inline QChar wmchar_to_unicode(DWORD c)
+{
+ // qt_winMB2QString is the generalization of this function.
+ QT_WA({
+ return QChar((ushort)c);
+ } , {
+ char mb[2];
+ mb[0] = c & 0xff;
+ mb[1] = 0;
+ WCHAR wc[1];
+ MultiByteToWideChar(inputcharset, MB_PRECOMPOSED, mb, -1, wc, 1);
+ return QChar(wc[0]);
+ });
+}
+
+static inline QChar imechar_to_unicode(DWORD c)
+{
+ // qt_winMB2QString is the generalization of this function.
+ QT_WA({
+ return QChar((ushort)c);
+ } , {
+ char mb[3];
+ mb[0] = (c >> 8) & 0xff;
+ mb[1] = c & 0xff;
+ mb[2] = 0;
+ WCHAR wc[1];
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, -1, wc, 1);
+ return QChar(wc[0]);
+ });
+}
+
+static inline bool isModifierKey(int code)
+{
+ return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock);
+}
+// Key translation -----------------------------------------------------------------------[ end ]---
+
+
+static void qt_show_system_menu(QWidget* tlw)
+{
+ Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created));
+ HMENU menu = GetSystemMenu(tlw->internalWinId(), FALSE);
+ if (!menu)
+ return; // no menu for this window
+
+#define enabled (MF_BYCOMMAND | MF_ENABLED)
+#define disabled (MF_BYCOMMAND | MF_GRAYED)
+
+#ifndef Q_OS_WINCE
+ EnableMenuItem(menu, SC_MINIMIZE, (tlw->windowFlags() & Qt::WindowMinimizeButtonHint)?enabled:disabled);
+ bool maximized = IsZoomed(tlw->internalWinId());
+
+ EnableMenuItem(menu, SC_MAXIMIZE, ! (tlw->windowFlags() & Qt::WindowMaximizeButtonHint) || maximized?disabled:enabled);
+ EnableMenuItem(menu, SC_RESTORE, maximized?enabled:disabled);
+
+ // We should _not_ check with the setFixedSize(x,y) case here, since Windows is not able to check
+ // this and our menu here would be out-of-sync with the menu produced by mouse-click on the
+ // System Menu, or right-click on the title bar.
+ EnableMenuItem(menu, SC_SIZE, (tlw->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || maximized?disabled:enabled);
+ EnableMenuItem(menu, SC_MOVE, maximized?disabled:enabled);
+ EnableMenuItem(menu, SC_CLOSE, enabled);
+ // Set bold on close menu item
+ MENUITEMINFO closeItem;
+ closeItem.cbSize = sizeof(MENUITEMINFO);
+ closeItem.fMask = MIIM_STATE;
+ closeItem.fState = MFS_DEFAULT;
+ SetMenuItemInfo(menu, SC_CLOSE, FALSE, &closeItem);
+#endif
+
+#undef enabled
+#undef disabled
+ int ret = TrackPopupMenuEx(menu,
+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
+ tlw->geometry().x(), tlw->geometry().y(),
+ tlw->internalWinId(),
+ 0);
+ if (ret)
+ QtWndProc(tlw->internalWinId(), WM_SYSCOMMAND, ret, 0);
+}
+
+
+// QETWidget class is only for accessing the sendSpontaneousEvent function in QApplication
+class QETWidget : public QWidget {
+public:
+ static bool sendSpontaneousEvent(QObject *r, QEvent *e)
+ { return QApplication::sendSpontaneousEvent(r, e); }
+};
+
+
+// Keyboard map private ----------------------------------------------------------------[ start ]---
+
+/*
+ \internal
+ A Windows KeyboardLayoutItem has 8 possible states:
+ 1. Unmodified
+ 2. Shift
+ 3. Control
+ 4. Control + Shift
+ 5. Alt
+ 6. Alt + Shift
+ 7. Alt + Control
+ 8. Alt + Control + Shift
+*/
+struct KeyboardLayoutItem {
+ bool dirty;
+ quint8 deadkeys;
+ quint32 qtKey[9]; // Can by any Qt::Key_<foo>, or unicode character
+};
+
+QKeyMapperPrivate::QKeyMapperPrivate()
+{
+ memset(keyLayout, 0, sizeof(keyLayout));
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+ clearMappings();
+}
+
+void QKeyMapperPrivate::clearMappings()
+{
+ for (int i = 0; i < 255; ++i) {
+ if (keyLayout[i]) {
+ delete keyLayout[i];
+ keyLayout[i] = 0;
+ }
+ }
+
+ /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout()
+ * returns a DWORD. */
+// LCID newLCID = MAKELCID(DWORD(GetKeyboardLayout(0)), SORT_DEFAULT);
+// keyboardInputLocale = qt_localeFromLCID(newLCID);
+ LCID newLCID = MAKELCID(
+ reinterpret_cast<long>(GetKeyboardLayout(0)),
+ SORT_DEFAULT
+ );
+ keyboardInputLocale = qt_localeFromLCID(newLCID);
+ bool bidi = false;
+#ifdef UNICODE
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000) {
+ WCHAR wchLCIDFontSig[16];
+ if (GetLocaleInfoW(newLCID,
+ LOCALE_FONTSIGNATURE,
+ &wchLCIDFontSig[0],
+ (sizeof(wchLCIDFontSig)/sizeof(WCHAR)))
+ && (wchLCIDFontSig[7] & (WCHAR)0x0800))
+ bidi = true;
+ } else
+#endif //UNICODE
+ {
+ if (newLCID == 0x0859 || //Sindhi (Arabic script)
+ newLCID == 0x0460) //Kashmiri (Arabic script)
+ bidi = true;;
+
+ switch (PRIMARYLANGID(newLCID))
+ {
+ case LANG_ARABIC:
+ case LANG_HEBREW:
+ case LANG_URDU:
+ case LANG_FARSI:
+ case LANG_PASHTO:
+ //case LANG_UIGHUR:
+ case LANG_SYRIAC:
+ case LANG_DIVEHI:
+ bidi = true;
+ }
+ }
+
+ keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
+}
+
+void QKeyMapperPrivate::clearRecordedKeys()
+{
+ key_recorder.clearKeys();
+}
+
+
+inline void setKbdState(unsigned char *kbd, bool shift, bool ctrl, bool alt)
+{
+ kbd[VK_LSHIFT ] = (shift ? 0x80 : 0);
+ kbd[VK_SHIFT ] = (shift ? 0x80 : 0);
+ kbd[VK_LCONTROL] = (ctrl ? 0x80 : 0);
+ kbd[VK_CONTROL ] = (ctrl ? 0x80 : 0);
+ kbd[VK_RMENU ] = (alt ? 0x80 : 0);
+ kbd[VK_MENU ] = (alt ? 0x80 : 0);
+}
+
+void QKeyMapperPrivate::updateKeyMap(const MSG &msg)
+{
+ unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
+ GetKeyboardState(kbdBuffer);
+ quint32 scancode = (msg.lParam >> 16) & 0xfff;
+ updatePossibleKeyCodes(kbdBuffer, scancode, msg.wParam);
+}
+
+void QKeyMapperPrivate::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode,
+ quint32 vk_key)
+{
+ if (!vk_key || (keyLayout[vk_key] && !keyLayout[vk_key]->dirty))
+ return;
+
+ if (!keyLayout[vk_key])
+ keyLayout[vk_key] = new KeyboardLayoutItem;
+
+ // Copy keyboard state, so we can modify and query output for each possible permutation
+ unsigned char buffer[256];
+ memcpy(buffer, kbdBuffer, sizeof(buffer));
+ // Always 0, as Windows doesn't treat these as modifiers;
+ buffer[VK_LWIN ] = 0;
+ buffer[VK_RWIN ] = 0;
+ buffer[VK_CAPITAL ] = 0;
+ buffer[VK_NUMLOCK ] = 0;
+ buffer[VK_SCROLL ] = 0;
+ // Always 0, since we'll only change the other versions
+ buffer[VK_RSHIFT ] = 0;
+ buffer[VK_RCONTROL] = 0;
+ buffer[VK_LMENU ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph
+
+ bool isDeadKey = false;
+ keyLayout[vk_key]->deadkeys = 0;
+ keyLayout[vk_key]->dirty = false;
+ setKbdState(buffer, false, false, false);
+ keyLayout[vk_key]->qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x01 : 0;
+ setKbdState(buffer, true, false, false);
+ keyLayout[vk_key]->qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x02 : 0;
+ setKbdState(buffer, false, true, false);
+ keyLayout[vk_key]->qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x04 : 0;
+ setKbdState(buffer, true, true, false);
+ keyLayout[vk_key]->qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x08 : 0;
+ setKbdState(buffer, false, false, true);
+ keyLayout[vk_key]->qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x10 : 0;
+ setKbdState(buffer, true, false, true);
+ keyLayout[vk_key]->qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x20 : 0;
+ setKbdState(buffer, false, true, true);
+ keyLayout[vk_key]->qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x40 : 0;
+ setKbdState(buffer, true, true, true);
+ keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0;
+ // Add a fall back key for layouts which don't do composition and show non-latin1 characters
+ int fallbackKey = KeyTbl[vk_key];
+ if (!fallbackKey || fallbackKey == Qt::Key_unknown) {
+ fallbackKey = 0;
+ if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F)
+ fallbackKey = vk_key;
+ }
+ keyLayout[vk_key]->qtKey[8] = fallbackKey;
+
+ // If this vk_key a Dead Key
+ if (MapVirtualKey(vk_key, 2) & 0x80008000) { // (High-order dead key on Win 95 is 0x8000)
+ // Push a Space, then the original key through the low-level ToAscii functions.
+ // We do this because these functions (ToAscii / ToUnicode) will alter the internal state of
+ // the keyboard driver By doing the following, we set the keyboard driver state back to what
+ // it was before we wrecked it with the code above.
+ // We need to push the space with an empty keystate map, since the driver checks the map for
+ // transitions in modifiers, so this helps us capture all possible deadkeys.
+ unsigned char emptyBuffer[256];
+ memset(emptyBuffer, 0, sizeof(emptyBuffer));
+ ::ToAscii(VK_SPACE, 0, emptyBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
+ ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
+ }
+
+#ifdef DEBUG_KEYMAPPER
+ qDebug("updatePossibleKeyCodes for virtual key = 0x%02x!", vk_key);
+ for (int i = 0; i < 9; ++i) {
+ qDebug(" [%d] (%d,0x%02x,'%c') %s", i,
+ keyLayout[vk_key]->qtKey[i],
+ keyLayout[vk_key]->qtKey[i],
+ keyLayout[vk_key]->qtKey[i] ? keyLayout[vk_key]->qtKey[i] : 0x03,
+ keyLayout[vk_key]->deadkeys & (1<<i) ? "deadkey" : "");
+ }
+#endif // DEBUG_KEYMAPPER
+}
+
+bool QKeyMapperPrivate::isADeadKey(unsigned int vk_key, unsigned int modifiers)
+{
+ if (keyLayout && (vk_key < 256) && keyLayout[vk_key]) {
+ for(register int i = 0; i < 9; ++i) {
+ if (uint(ModsTbl[i]) == modifiers)
+ return bool(keyLayout[vk_key]->deadkeys & 1<<i);
+ }
+ }
+ return false;
+}
+
+extern bool qt_use_rtl_extensions;
+
+QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
+{
+ QList<int> result;
+
+ KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()];
+ if(!kbItem)
+ return result;
+
+ quint32 baseKey = kbItem->qtKey[0];
+ Qt::KeyboardModifiers keyMods = e->modifiers();
+ if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
+ result << int(Qt::Key_Enter + keyMods);
+ return result;
+ }
+ result << int(baseKey + keyMods); // The base key is _always_ valid, of course
+
+ for(int i = 1; i < 9; ++i) {
+ Qt::KeyboardModifiers neededMods = ModsTbl[i];
+ quint32 key = kbItem->qtKey[i];
+ if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
+ result << int(key + (keyMods & ~neededMods));
+ }
+
+ return result;
+}
+
+bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool grab)
+{
+ Q_Q(QKeyMapper);
+ Q_UNUSED(q); // Strange, but the compiler complains on q not being referenced, even if it is..
+ bool k0 = false;
+ bool k1 = false;
+ int msgType = msg.message;
+
+ quint32 scancode = (msg.lParam >> 16) & 0xfff;
+ quint32 vk_key = MapVirtualKey(scancode, 1);
+ bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9);
+ quint32 nModifiers = 0;
+
+ if (QSysInfo::WindowsVersion < QSysInfo::WV_NT || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) {
+ nModifiers |= (GetKeyState(VK_SHIFT ) < 0 ? ShiftAny : 0);
+ nModifiers |= (GetKeyState(VK_CONTROL) < 0 ? ControlAny : 0);
+ nModifiers |= (GetKeyState(VK_MENU ) < 0 ? AltAny : 0);
+ nModifiers |= (GetKeyState(VK_LWIN ) < 0 ? MetaLeft : 0);
+ nModifiers |= (GetKeyState(VK_RWIN ) < 0 ? MetaRight : 0);
+ } else {
+ // Map native modifiers to some bit representation
+ nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ? ShiftLeft : 0);
+ nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ? ShiftRight : 0);
+ nModifiers |= (GetKeyState(VK_LCONTROL) & 0x80 ? ControlLeft : 0);
+ nModifiers |= (GetKeyState(VK_RCONTROL) & 0x80 ? ControlRight : 0);
+ nModifiers |= (GetKeyState(VK_LMENU ) & 0x80 ? AltLeft : 0);
+ nModifiers |= (GetKeyState(VK_RMENU ) & 0x80 ? AltRight : 0);
+ nModifiers |= (GetKeyState(VK_LWIN ) & 0x80 ? MetaLeft : 0);
+ nModifiers |= (GetKeyState(VK_RWIN ) & 0x80 ? MetaRight : 0);
+ // Add Lock keys to the same bits
+ nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0);
+ nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0);
+ nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0);
+ }
+ if (msg.lParam & ExtendedKey)
+ nModifiers |= msg.lParam & ExtendedKey;
+
+ // Get the modifier states (may be altered later, depending on key code)
+ int state = 0;
+ state |= (nModifiers & ShiftAny ? Qt::ShiftModifier : 0);
+ state |= (nModifiers & ControlAny ? Qt::ControlModifier : 0);
+ state |= (nModifiers & AltAny ? Qt::AltModifier : 0);
+ state |= (nModifiers & MetaAny ? Qt::MetaModifier : 0);
+
+ // Now we know enough to either have MapVirtualKey or our own keymap tell us if it's a deadkey
+ bool isDeadKey = isADeadKey(msg.wParam, state)
+ || MapVirtualKey(msg.wParam, 2) & 0x80008000; // High-order on 95 is 0x8000
+
+ // A multi-character key not found by our look-ahead
+ if (msgType == WM_CHAR) {
+ QString s;
+ QChar ch = wmchar_to_unicode(msg.wParam);
+ if (!ch.isNull())
+ s += ch;
+
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers);
+ k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers);
+ }
+
+ // Input method characters not found by our look-ahead
+ else if (msgType == WM_IME_CHAR) {
+ QString s;
+ QChar ch = imechar_to_unicode(msg.wParam);
+ if (!ch.isNull())
+ s += ch;
+
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers);
+ k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers);
+ }
+
+ else {
+ // handle Directionality changes (BiDi) with RTL extensions
+ if (qt_use_rtl_extensions) {
+ static int dirStatus = 0;
+ if (!dirStatus && state == Qt::ControlModifier
+ && msg.wParam == VK_CONTROL
+ && msgType == WM_KEYDOWN) {
+ if (GetKeyState(VK_LCONTROL) < 0)
+ dirStatus = VK_LCONTROL;
+ else if (GetKeyState(VK_RCONTROL) < 0)
+ dirStatus = VK_RCONTROL;
+ } else if (dirStatus) {
+ if (msgType == WM_KEYDOWN) {
+ if (msg.wParam == VK_SHIFT) {
+ if (dirStatus == VK_LCONTROL && GetKeyState(VK_LSHIFT) < 0)
+ dirStatus = VK_LSHIFT;
+ else if (dirStatus == VK_RCONTROL && GetKeyState(VK_RSHIFT) < 0)
+ dirStatus = VK_RSHIFT;
+ } else {
+ dirStatus = 0;
+ }
+ } else if (msgType == WM_KEYUP) {
+ if (dirStatus == VK_LSHIFT
+ && (msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)
+ || msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT))) {
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_L, 0,
+ QString(), false, 0,
+ scancode, msg.wParam, nModifiers);
+ k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, Qt::Key_Direction_L, 0,
+ QString(), false, 0,
+ scancode, msg.wParam, nModifiers);
+ dirStatus = 0;
+ } else if (dirStatus == VK_RSHIFT
+ && (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)
+ || msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT))) {
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_R,
+ 0, QString(), false, 0,
+ scancode, msg.wParam, nModifiers);
+ k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, Qt::Key_Direction_R,
+ 0, QString(), false, 0,
+ scancode, msg.wParam, nModifiers);
+ dirStatus = 0;
+ } else {
+ dirStatus = 0;
+ }
+ } else {
+ dirStatus = 0;
+ }
+ }
+ }
+
+ // IME will process these keys, so simply return
+ if(msg.wParam == VK_PROCESSKEY)
+ return true;
+
+ // Ignore invalid virtual keycode (see bug 127424)
+ if (msg.wParam == 0xFF)
+ return true;
+
+ // Translate VK_* (native) -> Key_* (Qt) keys
+ // If it's a dead key, we cannot use the toKeyOrUnicode() function, since that will change
+ // the internal state of the keyboard driver, resulting in that dead keys no longer works.
+ // ..also if we're typing numbers on the keypad, while holding down the Alt modifier.
+ int code = 0;
+ if (isNumpad && (nModifiers & AltAny)) {
+ code = KeyTbl[msg.wParam];
+ } else if (!isDeadKey) {
+ unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
+ GetKeyboardState(kbdBuffer);
+ code = toKeyOrUnicode(msg.wParam, scancode, kbdBuffer);
+ }
+
+ // Invert state logic:
+ // If the key actually pressed is a modifier key, then we remove its modifier key from the
+ // state, since a modifier-key can't have itself as a modifier
+ if (code == Qt::Key_Control)
+ state = state ^ Qt::ControlModifier;
+ else if (code == Qt::Key_Shift)
+ state = state ^ Qt::ShiftModifier;
+ else if (code == Qt::Key_Alt)
+ state = state ^ Qt::AltModifier;
+
+ // If the bit 24 of lParm is set you received a enter,
+ // otherwise a Return. (This is the extended key bit)
+ if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
+ code = Qt::Key_Enter;
+
+ // All cursor keys without extended bit
+ if (!(msg.lParam & 0x1000000)) {
+ switch (code) {
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_PageUp:
+ case Qt::Key_PageDown:
+ case Qt::Key_Home:
+ case Qt::Key_End:
+ case Qt::Key_Insert:
+ case Qt::Key_Delete:
+ case Qt::Key_Asterisk:
+ case Qt::Key_Plus:
+ case Qt::Key_Minus:
+ case Qt::Key_Period:
+ case Qt::Key_0:
+ case Qt::Key_1:
+ case Qt::Key_2:
+ case Qt::Key_3:
+ case Qt::Key_4:
+ case Qt::Key_5:
+ case Qt::Key_6:
+ case Qt::Key_7:
+ case Qt::Key_8:
+ case Qt::Key_9:
+ state |= ((msg.wParam >= '0' && msg.wParam <= '9')
+ || (msg.wParam >= VK_OEM_PLUS && msg.wParam <= VK_OEM_3))
+ ? 0 : Qt::KeypadModifier;
+ default:
+ if ((uint)msg.lParam == 0x004c0001 || (uint)msg.lParam == 0xc04c0001)
+ state |= Qt::KeypadModifier;
+ break;
+ }
+ }
+ // Other keys with with extended bit
+ else {
+ switch (code) {
+ case Qt::Key_Enter:
+ case Qt::Key_Slash:
+ case Qt::Key_NumLock:
+ state |= Qt::KeypadModifier;
+ default:
+ break;
+ }
+ }
+
+ // KEYDOWN ---------------------------------------------------------------------------------
+ if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) {
+ // Get the last record of this key press, so we can validate the current state
+ // The record is not removed from the list
+ KeyRecord *rec = key_recorder.findKey(msg.wParam, false);
+
+ // If rec's state doesn't match the current state, something has changed behind our back
+ // (Consumed by modal widget is one possibility) So, remove the record from the list
+ // This will stop the auto-repeat of the key, should a modifier change, for example
+ if (rec && rec->state != state) {
+ key_recorder.findKey(msg.wParam, true);
+ rec = 0;
+ }
+
+ // Find unicode character from Windows Message Queue
+ MSG wm_char;
+ UINT charType = (msgType == WM_KEYDOWN
+ ? WM_CHAR
+ : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR);
+
+ QChar uch;
+ if (winPeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) {
+ // Found a ?_CHAR
+ uch = charType == WM_IME_CHAR
+ ? imechar_to_unicode(wm_char.wParam)
+ : wmchar_to_unicode(wm_char.wParam);
+ if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN))
+ uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter
+ if (!code && !uch.row())
+ code = asciiToKeycode(uch.cell(), state);
+ }
+
+ // Special handling for the WM_IME_KEYDOWN message. Microsoft IME (Korean) will not
+ // generate a WM_IME_CHAR message corresponding to this message. We might get wrong
+ // results, if we map this virtual key-code directly (for eg '?' US layouts). So try
+ // to find the correct key using the current message parameters & keyboard state.
+ if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
+ BYTE keyState[256];
+ WCHAR newKey[3] = {0};
+ GetKeyboardState(keyState);
+ int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0);
+ if (val == 1) {
+ uch = QChar(newKey[0]);
+ } else {
+ // If we are still not able to find a unicode key, pass the WM_IME_KEYDOWN
+ // message to DefWindowProc() for generating a proper WM_KEYDOWN.
+ return false;
+ }
+ }
+
+ // If no ?_CHAR was found in the queue; deduct character from the ?_KEYDOWN parameters
+ if (uch.isNull()) {
+ if (msg.wParam == VK_DELETE) {
+ uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one.
+ } else {
+ if (msgType != WM_SYSKEYDOWN || !code) {
+ UINT map;
+ QT_WA({
+ map = MapVirtualKey(msg.wParam, 2);
+ } , {
+ map = MapVirtualKeyA(msg.wParam, 2);
+ // High-order bit is 0x8000 on '95
+ if (map & 0x8000)
+ map = (map^0x8000)|0x80000000;
+ });
+ // If the high bit of the return value is set, it's a deadkey
+ if (!(map & 0x80000000))
+ uch = wmchar_to_unicode((DWORD)map);
+ }
+ }
+ if (!code && !uch.row())
+ code = asciiToKeycode(uch.cell(), state);
+ }
+
+ // Special handling of global Windows hotkeys
+ if (state == Qt::AltModifier) {
+ switch (code) {
+ case Qt::Key_Escape:
+ case Qt::Key_Tab:
+ case Qt::Key_Enter:
+ case Qt::Key_F4:
+ return false; // Send the event on to Windows
+ case Qt::Key_Space:
+ // do not pass this key to windows, we will process it ourselves
+ qt_show_system_menu(widget->window());
+ return true;
+ default:
+ break;
+ }
+ }
+
+ // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
+ if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
+ code = Qt::Key_Backtab;
+
+ // If we have a record, it means that the key is already pressed, the state is the same
+ // so, we have an auto-repeating key
+ if (rec) {
+ if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) {
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, code,
+ Qt::KeyboardModifier(state), rec->text, true, 0,
+ scancode, msg.wParam, nModifiers);
+ k1 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, code,
+ Qt::KeyboardModifier(state), rec->text, true, 0,
+ scancode, msg.wParam, nModifiers);
+ }
+ }
+ // No record of the key being previous pressed, so we now send a QEvent::KeyPress event,
+ // and store the key data into our records.
+ else {
+ QString text;
+ if (!uch.isNull())
+ text += uch;
+ char a = uch.row() ? 0 : uch.cell();
+ key_recorder.storeKey(msg.wParam, a, state, text);
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, code, Qt::KeyboardModifier(state),
+ text, false, 0, scancode, msg.wParam, nModifiers);
+
+ bool store = true;
+ // Alt+<alphanumerical> go to the Win32 menu system if unhandled by Qt
+#if !defined(Q_OS_WINCE)
+ if (msgType == WM_SYSKEYDOWN && !k0 && a) {
+ HWND parent = GetParent(widget->internalWinId());
+ while (parent) {
+ if (GetMenu(parent)) {
+ SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU, a);
+ store = false;
+ k0 = true;
+ break;
+ }
+ parent = GetParent(parent);
+ }
+ }
+#endif
+ if (!store)
+ key_recorder.findKey(msg.wParam, true);
+ }
+ }
+
+ // KEYUP -----------------------------------------------------------------------------------
+ else {
+ // Try to locate the key in our records, and remove it if it exists.
+ // The key may not be in our records if, for example, the down event was handled by
+ // win32 natively, or our window gets focus while a key is already press, but now gets
+ // the key release event.
+ KeyRecord* rec = key_recorder.findKey(msg.wParam, true);
+ if (!rec && !(code == Qt::Key_Shift
+ || code == Qt::Key_Control
+ || code == Qt::Key_Meta
+ || code == Qt::Key_Alt)) {
+ // Someone ate the key down event
+ } else {
+ if (!code)
+ code = asciiToKeycode(rec->ascii ? rec->ascii : msg.wParam, state);
+
+ // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
+ if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
+ code = Qt::Key_Backtab;
+
+ k0 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, code, Qt::KeyboardModifier(state),
+ (rec ? rec->text : QString()), false, 0, scancode, msg.wParam, nModifiers);
+
+ // don't pass Alt to Windows unless we are embedded in a non-Qt window
+#if !defined(Q_OS_WINCE)
+ if (code == Qt::Key_Alt) {
+ k0 = true;
+ HWND parent = GetParent(widget->internalWinId());
+ while (parent) {
+ if (!QWidget::find(parent) && GetMenu(parent)) {
+ k0 = false;
+ break;
+ }
+ parent = GetParent(parent);
+ }
+ }
+#endif
+ }
+ }
+ }
+
+ // Return true, if a QKeyEvent was sent to a widget
+ return k0 || k1;
+}
+
+
+// QKeyMapper (Windows) implementation -------------------------------------------------[ start ]---
+
+bool QKeyMapper::sendKeyEvent(QWidget *widget, bool grab,
+ QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
+ const QString &text, bool autorepeat, int count,
+ quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
+ bool *)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(grab);
+#endif
+ Q_UNUSED(count);
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ if (type == QEvent::KeyPress
+ && !grab
+ && QApplicationPrivate::instance()->use_compat()) {
+ // send accel events if the keyboard is not grabbed
+ QKeyEventEx a(type, code, modifiers,
+ text, autorepeat, qMax(1, int(text.length())),
+ nativeScanCode, nativeVirtualKey, nativeModifiers);
+ if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &a))
+ return true;
+ }
+#endif
+ if (!widget->isEnabled())
+ return false;
+
+ QKeyEventEx e(type, code, modifiers,
+ text, autorepeat, qMax(1, int(text.length())),
+ nativeScanCode, nativeVirtualKey, nativeModifiers);
+ QETWidget::sendSpontaneousEvent(widget, &e);
+
+ if (!isModifierKey(code)
+ && modifiers == Qt::AltModifier
+ && ((code >= Qt::Key_A && code <= Qt::Key_Z) || (code >= Qt::Key_0 && code <= Qt::Key_9))
+ && type == QEvent::KeyPress
+ && !e.isAccepted())
+ QApplication::beep(); // Emulate windows behavior
+
+ return e.isAccepted();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp
new file mode 100644
index 0000000000..49b8566cfe
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_x11.cpp
@@ -0,0 +1,1678 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeymapper_p.h"
+
+#include "qdebug.h"
+#include "qtextcodec.h"
+#include "qwidget.h"
+
+#include "qapplication_p.h"
+#include "qevent_p.h"
+#include "qt_x11_p.h"
+
+#ifndef QT_NO_XKB
+# include <X11/XKBlib.h>
+#endif
+
+#define XK_MISCELLANY
+#define XK_LATIN1
+#define XK_KOREAN
+#define XK_XKB_KEYS
+#include <X11/keysymdef.h>
+
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_XKB
+
+// bring in the auto-generated xkbLayoutData
+#include "qkeymapper_x11_p.cpp"
+
+#ifdef QT_LINUXBASE
+// LSB's IsKeypadKey define is wrong - see
+// http://bugs.linuxbase.org/show_bug.cgi?id=2521
+#undef IsKeypadKey
+#define IsKeypadKey(keysym) \
+ (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal))
+
+#undef IsPrivateKeypadKey
+#define IsPrivateKeypadKey(keysym) \
+ (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))
+#endif
+
+static void getLocaleAndDirection(QLocale *locale,
+ Qt::LayoutDirection *direction,
+ const QByteArray &layoutName,
+ const QByteArray &variantName)
+{
+ int i = 0;
+ while (xkbLayoutData[i].layout != 0) {
+ if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant) {
+ *locale = QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country);
+ *direction = xkbLayoutData[i].direction;
+ return;
+ }
+ ++i;
+ }
+ *locale = QLocale::c();
+ *direction = Qt::LeftToRight;
+}
+#endif // QT_NO_XKB
+
+
+// from qapplication_x11.cpp
+extern uchar qt_alt_mask;
+extern uchar qt_meta_mask;
+extern uchar qt_super_mask;
+extern uchar qt_hyper_mask;
+extern uchar qt_mode_switch_mask;
+uchar qt_num_lock_mask = 0;
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+
+// ### we should really resolve conflicts with other masks by
+// ### decomposing the Qt::KeyboardModifers in possibleKeys()
+#define SETMASK(sym, mask) \
+ do { \
+ if (qt_alt_mask == 0 \
+ && qt_meta_mask != mask \
+ && qt_super_mask != mask \
+ && qt_hyper_mask != mask \
+ && (sym == XK_Alt_L || sym == XK_Alt_R)) { \
+ qt_alt_mask = mask; \
+ } \
+ if (qt_meta_mask == 0 \
+ && qt_alt_mask != mask \
+ && qt_super_mask != mask \
+ && qt_hyper_mask != mask \
+ && (sym == XK_Meta_L || sym == XK_Meta_R)) { \
+ qt_meta_mask = mask; \
+ } \
+ if (qt_super_mask == 0 \
+ && qt_alt_mask != mask \
+ && qt_meta_mask != mask \
+ && qt_hyper_mask != mask \
+ && (sym == XK_Super_L || sym == XK_Super_R)) { \
+ qt_super_mask = mask; \
+ } \
+ if (qt_hyper_mask == 0 \
+ && qt_alt_mask != mask \
+ && qt_meta_mask != mask \
+ && qt_super_mask != mask \
+ && (sym == XK_Hyper_L || sym == XK_Hyper_R)) { \
+ qt_hyper_mask = mask; \
+ } \
+ if (qt_mode_switch_mask == 0 \
+ && qt_alt_mask != mask \
+ && qt_meta_mask != mask \
+ && qt_super_mask != mask \
+ && qt_hyper_mask != mask \
+ && sym == XK_Mode_switch) { \
+ qt_mode_switch_mask = mask; \
+ } \
+ if (qt_num_lock_mask == 0 \
+ && sym == XK_Num_Lock) { \
+ qt_num_lock_mask = mask; \
+ } \
+ } while(false)
+
+// qt_XTranslateKey() is based on _XTranslateKey() taken from:
+
+/* $Xorg: KeyBind.c,v 1.4 2001/02/09 02:03:34 xorgcvs Exp $ */
+
+/*
+
+Copyright 1985, 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+static int
+qt_XTranslateKey(register QXCoreDesc *dpy,
+ KeyCode keycode,
+ register unsigned int modifiers,
+ unsigned int *modifiers_return,
+ KeySym *keysym_return)
+{
+ int per;
+ register KeySym *syms;
+ KeySym sym, lsym, usym;
+
+ if (! dpy->keysyms)
+ return 0;
+ *modifiers_return = ((ShiftMask|LockMask)
+ | dpy->mode_switch | dpy->num_lock);
+ if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
+ {
+ *keysym_return = NoSymbol;
+ return 1;
+ }
+ per = dpy->keysyms_per_keycode;
+ syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
+ while ((per > 2) && (syms[per - 1] == NoSymbol))
+ per--;
+ if ((per > 2) && (modifiers & dpy->mode_switch)) {
+ syms += 2;
+ per -= 2;
+ }
+ if ((modifiers & dpy->num_lock) &&
+ (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
+ if ((modifiers & ShiftMask) ||
+ ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
+ *keysym_return = syms[0];
+ else
+ *keysym_return = syms[1];
+ } else if (!(modifiers & ShiftMask) &&
+ (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
+ if ((per == 1) || (syms[1] == NoSymbol))
+ XConvertCase(syms[0], keysym_return, &usym);
+ else
+ *keysym_return = syms[0];
+ } else if (!(modifiers & LockMask) ||
+ (dpy->lock_meaning != XK_Caps_Lock)) {
+ if ((per == 1) || ((usym = syms[1]) == NoSymbol))
+ XConvertCase(syms[0], &lsym, &usym);
+ *keysym_return = usym;
+ } else {
+ if ((per == 1) || ((sym = syms[1]) == NoSymbol))
+ sym = syms[0];
+ XConvertCase(sym, &lsym, &usym);
+ if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
+ ((sym != usym) || (lsym == usym)))
+ XConvertCase(syms[0], &lsym, &usym);
+ *keysym_return = usym;
+ }
+ if (*keysym_return == XK_VoidSymbol)
+ *keysym_return = NoSymbol;
+ return 1;
+}
+
+
+
+
+QKeyMapperPrivate::QKeyMapperPrivate()
+ : keyboardInputDirection(Qt::LeftToRight), useXKB(false)
+{
+ memset(&coreDesc, 0, sizeof(coreDesc));
+
+#ifndef QT_NO_XKB
+ int opcode = -1;
+ int xkbEventBase = -1;
+ int xkbErrorBase = -1;
+ int xkblibMajor = XkbMajorVersion;
+ int xkblibMinor = XkbMinorVersion;
+ if (XkbQueryExtension(X11->display, &opcode, &xkbEventBase, &xkbErrorBase, &xkblibMajor, &xkblibMinor))
+ useXKB = true;
+#endif
+
+#if 0
+ qDebug() << "useXKB =" << useXKB;
+#endif
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+ if (coreDesc.keysyms)
+ XFree(coreDesc.keysyms);
+}
+
+QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *event)
+{
+#ifndef QT_NO_XKB
+ if (useXKB)
+ return possibleKeysXKB(event);
+#endif
+ return possibleKeysCore(event);
+}
+
+enum { MaxBits = sizeof(uint) * 8 };
+static QString translateKeySym(KeySym keysym, uint xmodifiers,
+ int &code, Qt::KeyboardModifiers &modifiers,
+ QByteArray &chars, int &count);
+
+QList<int> QKeyMapperPrivate::possibleKeysXKB(QKeyEvent *event)
+{
+#ifndef QT_NO_XKB
+ const int xkeycode = event->nativeScanCode();
+ const uint xmodifiers = event->nativeModifiers();
+
+ // first, translate key only using lock modifiers (there are no Qt equivalents for these, so we must
+ // always use them when determining the baseKeySym)
+ KeySym baseKeySym;
+ uint consumedModifiers;
+ if (!XkbLookupKeySym(X11->display, xkeycode, (xmodifiers & (LockMask | qt_num_lock_mask)),
+ &consumedModifiers, &baseKeySym))
+ return QList<int>();
+
+ QList<int> result;
+
+ // translate sym -> code
+ Qt::KeyboardModifiers baseModifiers = 0;
+ int baseCode = -1;
+ QByteArray chars;
+ int count = 0;
+ QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count);
+ if (baseCode == -1) {
+ if (text.isEmpty())
+ return QList<int>();
+ baseCode = text.at(0).unicode();
+ }
+
+ if (baseCode && baseCode < 0xfffe)
+ baseCode = QChar(baseCode).toUpper().unicode();
+ result += (baseCode | baseModifiers);
+
+ int pos1Bits[MaxBits];
+ int num1Bits = 0;
+
+ for (int i = 0; i < MaxBits; ++i) {
+ if (consumedModifiers & (1 << i))
+ pos1Bits[num1Bits++] = i;
+ }
+
+ const int numPerms = (1 << num1Bits);
+
+ // translate the key again using each permutation of consumedModifiers
+ for (int i = 1; i < numPerms; ++i) {
+ uint val = 0;
+ for (int j = 0; j < num1Bits; ++j) {
+ if (i & (1 << j))
+ val |= (1 << pos1Bits[j]);
+ }
+
+ if ((xmodifiers & val) != val)
+ continue;
+
+ KeySym sym;
+ uint mods;
+ if (!XkbLookupKeySym(X11->display, xkeycode, val, &mods, &sym))
+ continue;
+
+ // translate sym -> code
+ Qt::KeyboardModifiers modifiers = 0;
+ int code = -1;
+ chars.clear();
+ count = 0;
+ // mask out the modifiers needed to translate keycode
+ text = translateKeySym(sym, xmodifiers & ~val, code, modifiers, chars, count);
+ if (code == -1) {
+ if (text.isEmpty())
+ continue;
+ code = text.at(0).unicode();
+ }
+
+ if (code && code < 0xfffe)
+ code = QChar(code).toUpper().unicode();
+ if (code == baseCode)
+ continue;
+
+ result += (code | modifiers);
+ }
+
+#if 0
+ qDebug() << "possibleKeysXKB()" << hex << result;
+#endif
+ return result;
+#else
+ Q_UNUSED(event);
+ return QList<int>();
+#endif // QT_NO_XKB
+}
+
+QList<int> QKeyMapperPrivate::possibleKeysCore(QKeyEvent *event)
+{
+ const int xkeycode = event->nativeScanCode();
+ const uint xmodifiers = event->nativeModifiers();
+
+ // first, translate key only using lock modifiers (there are no Qt equivalents for these, so we must
+ // always use them when determining the baseKeySym)
+ KeySym baseKeySym;
+ uint consumedModifiers;
+ if (!qt_XTranslateKey(&coreDesc, xkeycode, (xmodifiers & (LockMask | qt_num_lock_mask)),
+ &consumedModifiers, &baseKeySym))
+ return QList<int>();
+
+ QList<int> result;
+
+ // translate sym -> code
+ Qt::KeyboardModifiers baseModifiers = 0;
+ int baseCode = -1;
+ QByteArray chars;
+ int count = 0;
+ QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count);
+ if (baseCode == -1) {
+ if (text.isEmpty())
+ return QList<int>();
+ baseCode = text.at(0).unicode();
+ }
+
+ if (baseCode && baseCode < 0xfffe)
+ baseCode = QChar(baseCode).toUpper().unicode();
+ result += (baseCode | baseModifiers);
+
+ int pos1Bits[MaxBits];
+ int num1Bits = 0;
+
+ for (int i = 0; i < MaxBits; ++i) {
+ if (consumedModifiers & (1 << i))
+ pos1Bits[num1Bits++] = i;
+ }
+
+ const int numPerms = (1 << num1Bits);
+
+ // translate the key again using each permutation of consumedModifiers
+ for (int i = 1; i < numPerms; ++i) {
+ uint val = 0;
+ for (int j = 0; j < num1Bits; ++j) {
+ if (i & (1 << j))
+ val |= (1 << pos1Bits[j]);
+ }
+
+ if ((xmodifiers & val) != val)
+ continue;
+
+ KeySym sym;
+ uint mods;
+ if (!qt_XTranslateKey(&coreDesc, xkeycode, val, &mods, &sym))
+ continue;
+
+ // translate sym -> code
+ Qt::KeyboardModifiers modifiers = 0;
+ int code = -1;
+ chars.clear();
+ count = 0;
+ // mask out the modifiers needed to translate keycode
+ text = translateKeySym(sym, xmodifiers & ~val, code, modifiers, chars, count);
+ if (code == -1) {
+ if (text.isEmpty())
+ continue;
+ code = text.at(0).unicode();
+ }
+
+ if (code && code < 0xfffe)
+ code = QChar(code).toUpper().unicode();
+ if (code == baseCode)
+ continue;
+
+ result += (code | modifiers);
+ }
+
+#if 0
+ qDebug() << "possibleKeysCore()" << hex << result;
+#endif
+ return result;
+}
+
+// for parsing the _XKB_RULES_NAMES property
+enum {
+ RulesFileIndex = 0,
+ ModelIndex = 1,
+ LayoutIndex = 2,
+ VariantIndex = 3,
+ OptionsIndex = 4
+};
+
+void QKeyMapperPrivate::clearMappings()
+{
+#ifndef QT_NO_XKB
+ if (useXKB) {
+ // try to determine the layout name and input direction by reading the _XKB_RULES_NAMES property off
+ // the root window
+ QByteArray layoutName;
+ QByteArray variantName;
+
+ Atom type = XNone;
+ int format = 0;
+ ulong nitems = 0;
+ ulong bytesAfter = 0;
+ uchar *data = 0;
+ if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024,
+ false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success
+ && type == XA_STRING && format == 8 && nitems > 2) {
+ /*
+ index 0 == rules file name
+ index 1 == model name
+ index 2 == layout name
+ index 3 == variant name
+ index 4 == options
+ */
+ char *names[5] = { 0, 0, 0, 0, 0 };
+ char *p = reinterpret_cast<char *>(data), *end = p + nitems;
+ int i = 0;
+ do {
+ names[i++] = p;
+ p += qstrlen(p) + 1;
+ } while (p < end);
+
+ layoutName = QByteArray::fromRawData(names[2], qstrlen(names[2]));
+ variantName = QByteArray::fromRawData(names[3], qstrlen(names[3]));
+ }
+
+ // ### ???
+ // if (keyboardLayoutName.isEmpty())
+ // qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ?
+
+ getLocaleAndDirection(&keyboardInputLocale,
+ &keyboardInputDirection,
+ layoutName,
+ variantName);
+
+#if 0
+ qDebug() << "keyboard input locale ="
+ << keyboardInputLocale.name()
+ << "direction ="
+ << keyboardInputDirection;
+#endif
+
+ if (data)
+ XFree(data);
+ } else
+#endif // QT_NO_XKB
+ {
+ if (coreDesc.keysyms)
+ XFree(coreDesc.keysyms);
+
+ coreDesc.min_keycode = 8;
+ coreDesc.max_keycode = 255;
+ XDisplayKeycodes(X11->display, &coreDesc.min_keycode, &coreDesc.max_keycode);
+
+ coreDesc.keysyms_per_keycode = 0;
+ coreDesc.keysyms = XGetKeyboardMapping(X11->display,
+ coreDesc.min_keycode,
+ coreDesc.max_keycode - coreDesc.min_keycode,
+ &coreDesc.keysyms_per_keycode);
+
+#if 0
+ qDebug() << "min_keycode =" << coreDesc.min_keycode;
+ qDebug() << "max_keycode =" << coreDesc.max_keycode;
+ qDebug() << "keysyms_per_keycode =" << coreDesc.keysyms_per_keycode;
+ qDebug() << "keysyms =" << coreDesc.keysyms;
+#endif
+
+ // ### cannot get/guess the locale with the core protocol
+ keyboardInputLocale = QLocale::c();
+ // ### could examine group 0 for RTL keys
+ keyboardInputDirection = Qt::LeftToRight;
+ }
+
+ qt_alt_mask = 0;
+ qt_meta_mask = 0;
+ qt_super_mask = 0;
+ qt_hyper_mask = 0;
+ qt_mode_switch_mask = 0;
+
+ // look at the modifier mapping, and get the correct masks for alt, meta, super, hyper, and mode_switch
+#ifndef QT_NO_XKB
+ if (useXKB) {
+ XkbDescPtr xkbDesc = XkbGetMap(X11->display, XkbAllClientInfoMask, XkbUseCoreKbd);
+ for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) {
+ const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0;
+ if (mask == 0) {
+ // key is not bound to a modifier
+ continue;
+ }
+
+ for (int j = 0; j < XkbKeyGroupsWidth(xkbDesc, i); ++j) {
+ KeySym keySym = XkbKeySym(xkbDesc, i, j);
+ if (keySym == NoSymbol)
+ continue;
+ SETMASK(keySym, mask);
+ }
+ }
+ XkbFreeKeyboard(xkbDesc, XkbAllComponentsMask, true);
+ } else
+#endif // QT_NO_XKB
+ {
+ coreDesc.lock_meaning = NoSymbol;
+
+ XModifierKeymap *map = XGetModifierMapping(X11->display);
+
+ if (map) {
+ int i, maskIndex = 0, mapIndex = 0;
+ for (maskIndex = 0; maskIndex < 8; maskIndex++) {
+ for (i = 0; i < map->max_keypermod; i++) {
+ if (map->modifiermap[mapIndex]) {
+ KeySym sym;
+ int x = 0;
+ do {
+ sym = XKeycodeToKeysym(X11->display, map->modifiermap[mapIndex], x++);
+ } while (sym == NoSymbol && x < coreDesc.keysyms_per_keycode);
+ const uchar mask = 1 << maskIndex;
+ SETMASK(sym, mask);
+ }
+ mapIndex++;
+ }
+ }
+
+ // determine the meaning of the Lock modifier
+ for (i = 0; i < map->max_keypermod; ++i) {
+ for (int x = 0; x < coreDesc.keysyms_per_keycode; ++x) {
+ KeySym sym = XKeycodeToKeysym(X11->display, map->modifiermap[LockMapIndex], x);
+ if (sym == XK_Caps_Lock || sym == XK_ISO_Lock) {
+ coreDesc.lock_meaning = XK_Caps_Lock;
+ break;
+ } else if (sym == XK_Shift_Lock) {
+ coreDesc.lock_meaning = XK_Shift_Lock;
+ }
+ }
+ }
+
+ XFreeModifiermap(map);
+ }
+
+ // for qt_XTranslateKey()
+ coreDesc.num_lock = qt_num_lock_mask;
+ coreDesc.mode_switch = qt_mode_switch_mask;
+
+#if 0
+ qDebug() << "lock_meaning =" << coreDesc.lock_meaning;
+ qDebug() << "num_lock =" << coreDesc.num_lock;
+ qDebug() << "mode_switch =" << coreDesc.mode_switch;
+#endif
+ }
+
+ // set default modifier masks if needed
+ if( qt_alt_mask == 0 )
+ qt_alt_mask = Mod1Mask;
+ if( qt_meta_mask == 0 )
+ qt_meta_mask = Mod4Mask;
+
+ // if we don't have a meta key (or it's hidden behind alt), use super or hyper to generate
+ // Qt::Key_Meta and Qt::MetaModifier, since most newer XFree86/Xorg installations map the Windows
+ // key to Super
+ if (qt_meta_mask == 0 || qt_meta_mask == qt_alt_mask) {
+ // no meta keys... s,meta,super,
+ qt_meta_mask = qt_super_mask;
+ if (qt_meta_mask == 0 || qt_meta_mask == qt_alt_mask) {
+ // no super keys either? guess we'll use hyper then
+ qt_meta_mask = qt_hyper_mask;
+ }
+ }
+
+#if 0
+ qDebug() << "qt_alt_mask =" << hex << qt_alt_mask;
+ qDebug() << "qt_meta_mask =" << hex << qt_meta_mask;
+ qDebug() << "qt_super_mask =" << hex << qt_super_mask;
+ qDebug() << "qt_hyper_mask =" << hex << qt_hyper_mask;
+ qDebug() << "qt_mode_switch_mask =" << hex << qt_mode_switch_mask;
+ qDebug() << "qt_num_lock_mask =" << hex << qt_num_lock_mask;
+#endif
+}
+
+extern bool qt_sm_blockUserInput;
+
+//
+// Keyboard event translation
+//
+
+#ifndef XK_ISO_Left_Tab
+#define XK_ISO_Left_Tab 0xFE20
+#endif
+
+#ifndef XK_dead_hook
+#define XK_dead_hook 0xFE61
+#endif
+
+#ifndef XK_dead_horn
+#define XK_dead_horn 0xFE62
+#endif
+
+#ifndef XK_Codeinput
+#define XK_Codeinput 0xFF37
+#endif
+
+#ifndef XK_Kanji_Bangou
+#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */
+#endif
+
+// Fix old X libraries
+#ifndef XK_KP_Home
+#define XK_KP_Home 0xFF95
+#endif
+#ifndef XK_KP_Left
+#define XK_KP_Left 0xFF96
+#endif
+#ifndef XK_KP_Up
+#define XK_KP_Up 0xFF97
+#endif
+#ifndef XK_KP_Right
+#define XK_KP_Right 0xFF98
+#endif
+#ifndef XK_KP_Down
+#define XK_KP_Down 0xFF99
+#endif
+#ifndef XK_KP_Prior
+#define XK_KP_Prior 0xFF9A
+#endif
+#ifndef XK_KP_Next
+#define XK_KP_Next 0xFF9B
+#endif
+#ifndef XK_KP_End
+#define XK_KP_End 0xFF9C
+#endif
+#ifndef XK_KP_Insert
+#define XK_KP_Insert 0xFF9E
+#endif
+#ifndef XK_KP_Delete
+#define XK_KP_Delete 0xFF9F
+#endif
+
+// the next lines are taken from XFree > 4.0 (X11/XF86keysyms.h), defining some special
+// multimedia keys. They are included here as not every system has them.
+#define XF86XK_Standby 0x1008FF10
+#define XF86XK_AudioLowerVolume 0x1008FF11
+#define XF86XK_AudioMute 0x1008FF12
+#define XF86XK_AudioRaiseVolume 0x1008FF13
+#define XF86XK_AudioPlay 0x1008FF14
+#define XF86XK_AudioStop 0x1008FF15
+#define XF86XK_AudioPrev 0x1008FF16
+#define XF86XK_AudioNext 0x1008FF17
+#define XF86XK_HomePage 0x1008FF18
+#define XF86XK_Calculator 0x1008FF1D
+#define XF86XK_Mail 0x1008FF19
+#define XF86XK_Start 0x1008FF1A
+#define XF86XK_Search 0x1008FF1B
+#define XF86XK_AudioRecord 0x1008FF1C
+#define XF86XK_Back 0x1008FF26
+#define XF86XK_Forward 0x1008FF27
+#define XF86XK_Stop 0x1008FF28
+#define XF86XK_Refresh 0x1008FF29
+#define XF86XK_Favorites 0x1008FF30
+#define XF86XK_AudioPause 0x1008FF31
+#define XF86XK_AudioMedia 0x1008FF32
+#define XF86XK_MyComputer 0x1008FF33
+#define XF86XK_OpenURL 0x1008FF38
+#define XF86XK_Launch0 0x1008FF40
+#define XF86XK_Launch1 0x1008FF41
+#define XF86XK_Launch2 0x1008FF42
+#define XF86XK_Launch3 0x1008FF43
+#define XF86XK_Launch4 0x1008FF44
+#define XF86XK_Launch5 0x1008FF45
+#define XF86XK_Launch6 0x1008FF46
+#define XF86XK_Launch7 0x1008FF47
+#define XF86XK_Launch8 0x1008FF48
+#define XF86XK_Launch9 0x1008FF49
+#define XF86XK_LaunchA 0x1008FF4A
+#define XF86XK_LaunchB 0x1008FF4B
+#define XF86XK_LaunchC 0x1008FF4C
+#define XF86XK_LaunchD 0x1008FF4D
+#define XF86XK_LaunchE 0x1008FF4E
+#define XF86XK_LaunchF 0x1008FF4F
+// end of XF86keysyms.h
+
+// Special keys used by Qtopia, mapped into the X11 private keypad range.
+#define QTOPIAXK_Select 0x11000601
+#define QTOPIAXK_Yes 0x11000602
+#define QTOPIAXK_No 0x11000603
+#define QTOPIAXK_Cancel 0x11000604
+#define QTOPIAXK_Printer 0x11000605
+#define QTOPIAXK_Execute 0x11000606
+#define QTOPIAXK_Sleep 0x11000607
+#define QTOPIAXK_Play 0x11000608
+#define QTOPIAXK_Zoom 0x11000609
+#define QTOPIAXK_Context1 0x1100060A
+#define QTOPIAXK_Context2 0x1100060B
+#define QTOPIAXK_Context3 0x1100060C
+#define QTOPIAXK_Context4 0x1100060D
+#define QTOPIAXK_Call 0x1100060E
+#define QTOPIAXK_Hangup 0x1100060F
+#define QTOPIAXK_Flip 0x11000610
+
+// keyboard mapping table
+static const unsigned int KeyTbl[] = {
+
+ // misc keys
+
+ XK_Escape, Qt::Key_Escape,
+ XK_Tab, Qt::Key_Tab,
+ XK_ISO_Left_Tab, Qt::Key_Backtab,
+ XK_BackSpace, Qt::Key_Backspace,
+ XK_Return, Qt::Key_Return,
+ XK_Insert, Qt::Key_Insert,
+ XK_Delete, Qt::Key_Delete,
+ XK_Clear, Qt::Key_Delete,
+ XK_Pause, Qt::Key_Pause,
+ XK_Print, Qt::Key_Print,
+ 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq
+ 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq
+
+ // cursor movement
+
+ XK_Home, Qt::Key_Home,
+ XK_End, Qt::Key_End,
+ XK_Left, Qt::Key_Left,
+ XK_Up, Qt::Key_Up,
+ XK_Right, Qt::Key_Right,
+ XK_Down, Qt::Key_Down,
+ XK_Prior, Qt::Key_PageUp,
+ XK_Next, Qt::Key_PageDown,
+
+ // modifiers
+
+ XK_Shift_L, Qt::Key_Shift,
+ XK_Shift_R, Qt::Key_Shift,
+ XK_Shift_Lock, Qt::Key_Shift,
+ XK_Control_L, Qt::Key_Control,
+ XK_Control_R, Qt::Key_Control,
+ XK_Meta_L, Qt::Key_Meta,
+ XK_Meta_R, Qt::Key_Meta,
+ XK_Alt_L, Qt::Key_Alt,
+ XK_Alt_R, Qt::Key_Alt,
+ XK_Caps_Lock, Qt::Key_CapsLock,
+ XK_Num_Lock, Qt::Key_NumLock,
+ XK_Scroll_Lock, Qt::Key_ScrollLock,
+ XK_Super_L, Qt::Key_Super_L,
+ XK_Super_R, Qt::Key_Super_R,
+ XK_Menu, Qt::Key_Menu,
+ XK_Hyper_L, Qt::Key_Hyper_L,
+ XK_Hyper_R, Qt::Key_Hyper_R,
+ XK_Help, Qt::Key_Help,
+ 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab
+ 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11)
+ 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12)
+
+ // numeric and function keypad keys
+
+ XK_KP_Space, Qt::Key_Space,
+ XK_KP_Tab, Qt::Key_Tab,
+ XK_KP_Enter, Qt::Key_Enter,
+ //XK_KP_F1, Qt::Key_F1,
+ //XK_KP_F2, Qt::Key_F2,
+ //XK_KP_F3, Qt::Key_F3,
+ //XK_KP_F4, Qt::Key_F4,
+ XK_KP_Home, Qt::Key_Home,
+ XK_KP_Left, Qt::Key_Left,
+ XK_KP_Up, Qt::Key_Up,
+ XK_KP_Right, Qt::Key_Right,
+ XK_KP_Down, Qt::Key_Down,
+ XK_KP_Prior, Qt::Key_PageUp,
+ XK_KP_Next, Qt::Key_PageDown,
+ XK_KP_End, Qt::Key_End,
+ XK_KP_Begin, Qt::Key_Clear,
+ XK_KP_Insert, Qt::Key_Insert,
+ XK_KP_Delete, Qt::Key_Delete,
+ XK_KP_Equal, Qt::Key_Equal,
+ XK_KP_Multiply, Qt::Key_Asterisk,
+ XK_KP_Add, Qt::Key_Plus,
+ XK_KP_Separator, Qt::Key_Comma,
+ XK_KP_Subtract, Qt::Key_Minus,
+ XK_KP_Decimal, Qt::Key_Period,
+ XK_KP_Divide, Qt::Key_Slash,
+
+ // International input method support keys
+
+ // International & multi-key character composition
+ XK_ISO_Level3_Shift, Qt::Key_AltGr,
+ XK_Multi_key, Qt::Key_Multi_key,
+ XK_Codeinput, Qt::Key_Codeinput,
+ XK_SingleCandidate, Qt::Key_SingleCandidate,
+ XK_MultipleCandidate, Qt::Key_MultipleCandidate,
+ XK_PreviousCandidate, Qt::Key_PreviousCandidate,
+
+ // Misc Functions
+ XK_Mode_switch, Qt::Key_Mode_switch,
+ XK_script_switch, Qt::Key_Mode_switch,
+
+ // Japanese keyboard support
+ XK_Kanji, Qt::Key_Kanji,
+ XK_Muhenkan, Qt::Key_Muhenkan,
+ //XK_Henkan_Mode, Qt::Key_Henkan_Mode,
+ XK_Henkan_Mode, Qt::Key_Henkan,
+ XK_Henkan, Qt::Key_Henkan,
+ XK_Romaji, Qt::Key_Romaji,
+ XK_Hiragana, Qt::Key_Hiragana,
+ XK_Katakana, Qt::Key_Katakana,
+ XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana,
+ XK_Zenkaku, Qt::Key_Zenkaku,
+ XK_Hankaku, Qt::Key_Hankaku,
+ XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku,
+ XK_Touroku, Qt::Key_Touroku,
+ XK_Massyo, Qt::Key_Massyo,
+ XK_Kana_Lock, Qt::Key_Kana_Lock,
+ XK_Kana_Shift, Qt::Key_Kana_Shift,
+ XK_Eisu_Shift, Qt::Key_Eisu_Shift,
+ XK_Eisu_toggle, Qt::Key_Eisu_toggle,
+ //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou,
+ //XK_Zen_Koho, Qt::Key_Zen_Koho,
+ //XK_Mae_Koho, Qt::Key_Mae_Koho,
+ XK_Kanji_Bangou, Qt::Key_Codeinput,
+ XK_Zen_Koho, Qt::Key_MultipleCandidate,
+ XK_Mae_Koho, Qt::Key_PreviousCandidate,
+
+#ifdef XK_KOREAN
+ // Korean keyboard support
+ XK_Hangul, Qt::Key_Hangul,
+ XK_Hangul_Start, Qt::Key_Hangul_Start,
+ XK_Hangul_End, Qt::Key_Hangul_End,
+ XK_Hangul_Hanja, Qt::Key_Hangul_Hanja,
+ XK_Hangul_Jamo, Qt::Key_Hangul_Jamo,
+ XK_Hangul_Romaja, Qt::Key_Hangul_Romaja,
+ //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput,
+ XK_Hangul_Codeinput, Qt::Key_Codeinput,
+ XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja,
+ XK_Hangul_Banja, Qt::Key_Hangul_Banja,
+ XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja,
+ XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja,
+ //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
+ //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
+ //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
+ XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate,
+ XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
+ XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
+ XK_Hangul_Special, Qt::Key_Hangul_Special,
+ //XK_Hangul_switch, Qt::Key_Hangul_switch,
+ XK_Hangul_switch, Qt::Key_Mode_switch,
+#endif // XK_KOREAN
+
+ // dead keys
+ XK_dead_grave, Qt::Key_Dead_Grave,
+ XK_dead_acute, Qt::Key_Dead_Acute,
+ XK_dead_circumflex, Qt::Key_Dead_Circumflex,
+ XK_dead_tilde, Qt::Key_Dead_Tilde,
+ XK_dead_macron, Qt::Key_Dead_Macron,
+ XK_dead_breve, Qt::Key_Dead_Breve,
+ XK_dead_abovedot, Qt::Key_Dead_Abovedot,
+ XK_dead_diaeresis, Qt::Key_Dead_Diaeresis,
+ XK_dead_abovering, Qt::Key_Dead_Abovering,
+ XK_dead_doubleacute, Qt::Key_Dead_Doubleacute,
+ XK_dead_caron, Qt::Key_Dead_Caron,
+ XK_dead_cedilla, Qt::Key_Dead_Cedilla,
+ XK_dead_ogonek, Qt::Key_Dead_Ogonek,
+ XK_dead_iota, Qt::Key_Dead_Iota,
+ XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
+ XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
+ XK_dead_belowdot, Qt::Key_Dead_Belowdot,
+ XK_dead_hook, Qt::Key_Dead_Hook,
+ XK_dead_horn, Qt::Key_Dead_Horn,
+
+ // Special multimedia keys
+ // currently only tested with MS internet keyboard
+
+ // browsing keys
+ XF86XK_Back, Qt::Key_Back,
+ XF86XK_Forward, Qt::Key_Forward,
+ XF86XK_Stop, Qt::Key_Stop,
+ XF86XK_Refresh, Qt::Key_Refresh,
+ XF86XK_Favorites, Qt::Key_Favorites,
+ XF86XK_AudioMedia, Qt::Key_LaunchMedia,
+ XF86XK_OpenURL, Qt::Key_OpenUrl,
+ XF86XK_HomePage, Qt::Key_HomePage,
+ XF86XK_Search, Qt::Key_Search,
+
+ // media keys
+ XF86XK_AudioLowerVolume, Qt::Key_VolumeDown,
+ XF86XK_AudioMute, Qt::Key_VolumeMute,
+ XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp,
+ XF86XK_AudioPlay, Qt::Key_MediaPlay,
+ XF86XK_AudioStop, Qt::Key_MediaStop,
+ XF86XK_AudioPrev, Qt::Key_MediaPrevious,
+ XF86XK_AudioNext, Qt::Key_MediaNext,
+ XF86XK_AudioRecord, Qt::Key_MediaRecord,
+
+ // launch keys
+ XF86XK_Mail, Qt::Key_LaunchMail,
+ XF86XK_MyComputer, Qt::Key_Launch0,
+ XF86XK_Calculator, Qt::Key_Launch1,
+ XF86XK_Standby, Qt::Key_Standby,
+
+ XF86XK_Launch0, Qt::Key_Launch2,
+ XF86XK_Launch1, Qt::Key_Launch3,
+ XF86XK_Launch2, Qt::Key_Launch4,
+ XF86XK_Launch3, Qt::Key_Launch5,
+ XF86XK_Launch4, Qt::Key_Launch6,
+ XF86XK_Launch5, Qt::Key_Launch7,
+ XF86XK_Launch6, Qt::Key_Launch8,
+ XF86XK_Launch7, Qt::Key_Launch9,
+ XF86XK_Launch8, Qt::Key_LaunchA,
+ XF86XK_Launch9, Qt::Key_LaunchB,
+ XF86XK_LaunchA, Qt::Key_LaunchC,
+ XF86XK_LaunchB, Qt::Key_LaunchD,
+ XF86XK_LaunchC, Qt::Key_LaunchE,
+ XF86XK_LaunchD, Qt::Key_LaunchF,
+
+ // Qtopia keys
+ QTOPIAXK_Select, Qt::Key_Select,
+ QTOPIAXK_Yes, Qt::Key_Yes,
+ QTOPIAXK_No, Qt::Key_No,
+ QTOPIAXK_Cancel, Qt::Key_Cancel,
+ QTOPIAXK_Printer, Qt::Key_Printer,
+ QTOPIAXK_Execute, Qt::Key_Execute,
+ QTOPIAXK_Sleep, Qt::Key_Sleep,
+ QTOPIAXK_Play, Qt::Key_Play,
+ QTOPIAXK_Zoom, Qt::Key_Zoom,
+ QTOPIAXK_Context1, Qt::Key_Context1,
+ QTOPIAXK_Context2, Qt::Key_Context2,
+ QTOPIAXK_Context3, Qt::Key_Context3,
+ QTOPIAXK_Context4, Qt::Key_Context4,
+ QTOPIAXK_Call, Qt::Key_Call,
+ QTOPIAXK_Hangup, Qt::Key_Hangup,
+ QTOPIAXK_Flip, Qt::Key_Flip,
+
+ 0, 0
+};
+
+static int translateKeySym(uint key)
+{
+ int code = -1;
+ int i = 0; // any other keys
+ while (KeyTbl[i]) {
+ if (key == KeyTbl[i]) {
+ code = (int)KeyTbl[i+1];
+ break;
+ }
+ i += 2;
+ }
+ if (qt_meta_mask) {
+ // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
+ if (qt_meta_mask == qt_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) {
+ code = Qt::Key_Meta;
+ } else if (qt_meta_mask == qt_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
+ code = Qt::Key_Meta;
+ }
+ }
+ return code;
+}
+
+#if !defined(QT_NO_XIM)
+static const unsigned short katakanaKeysymsToUnicode[] = {
+ 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1,
+ 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3,
+ 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
+ 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD,
+ 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC,
+ 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE,
+ 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9,
+ 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C
+};
+
+static const unsigned short cyrillicKeysymsToUnicode[] = {
+ 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f,
+ 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f,
+ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
+ 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
+ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
+ 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
+ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
+ 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
+ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
+ 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a
+};
+
+static const unsigned short greekKeysymsToUnicode[] = {
+ 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c,
+ 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015,
+ 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc,
+ 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
+ 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
+ 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short technicalKeysymsToUnicode[] = {
+ 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1,
+ 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8,
+ 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B,
+ 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000,
+ 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000,
+ 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000
+};
+
+static const unsigned short specialKeysymsToUnicode[] = {
+ 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000,
+ 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA,
+ 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C,
+ 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short publishingKeysymsToUnicode[] = {
+ 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009,
+ 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025,
+ 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a,
+ 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000,
+ 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af,
+ 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033,
+ 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae,
+ 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa,
+ 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000,
+ 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642,
+ 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000
+};
+
+static const unsigned short aplKeysymsToUnicode[] = {
+ 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000,
+ 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb,
+ 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000,
+ 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000
+};
+
+static const unsigned short koreanKeysymsToUnicode[] = {
+ 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
+ 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
+ 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
+ 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f,
+ 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157,
+ 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f,
+ 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab,
+ 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3,
+ 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb,
+ 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d,
+ 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e,
+ 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9
+};
+
+static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4)
+{
+ switch (byte3) {
+ case 0x04:
+ // katakana
+ if (byte4 > 0xa0 && byte4 < 0xe0)
+ return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]);
+ else if (byte4 == 0x7e)
+ return QChar(0x203e); // Overline
+ break;
+ case 0x06:
+ // russian, use lookup table
+ if (byte4 > 0xa0)
+ return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]);
+ break;
+ case 0x07:
+ // greek
+ if (byte4 > 0xa0)
+ return QChar(greekKeysymsToUnicode[byte4 - 0xa0]);
+ break;
+ case 0x08:
+ // technical
+ if (byte4 > 0xa0)
+ return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]);
+ break;
+ case 0x09:
+ // special
+ if (byte4 >= 0xe0)
+ return QChar(specialKeysymsToUnicode[byte4 - 0xe0]);
+ break;
+ case 0x0a:
+ // publishing
+ if (byte4 > 0xa0)
+ return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]);
+ break;
+ case 0x0b:
+ // APL
+ if (byte4 > 0xa0)
+ return QChar(aplKeysymsToUnicode[byte4 - 0xa0]);
+ break;
+ case 0x0e:
+ // Korean
+ if (byte4 > 0xa0)
+ return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]);
+ break;
+ default:
+ break;
+ }
+ return QChar(0x0);
+}
+#endif
+
+static QString translateKeySym(KeySym keysym, uint xmodifiers,
+ int &code, Qt::KeyboardModifiers &modifiers,
+ QByteArray &chars, int &count)
+{
+ // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars
+
+ extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp
+ QTextCodec *mapper = qt_input_mapper;
+ QChar converted;
+
+ if (count == 0 && keysym < 0xff00) {
+ unsigned char byte3 = (unsigned char)(keysym >> 8);
+ int mib = -1;
+ switch(byte3) {
+ case 0: // Latin 1
+ case 1: // Latin 2
+ case 2: //latin 3
+ case 3: // latin4
+ mib = byte3 + 4; break;
+ case 5: // arabic
+ mib = 82; break;
+ case 12: // Hebrew
+ mib = 85; break;
+ case 13: // Thai
+ mib = 2259; break;
+ case 4: // kana
+ case 6: // cyrillic
+ case 7: // greek
+ case 8: // technical, no mapping here at the moment
+ case 9: // Special
+ case 10: // Publishing
+ case 11: // APL
+ case 14: // Korean, no mapping
+ mib = -1; // manual conversion
+ mapper = 0;
+#if !defined(QT_NO_XIM)
+ converted = keysymToUnicode(byte3, keysym & 0xff);
+#endif
+ case 0x20:
+ // currency symbols
+ if (keysym >= 0x20a0 && keysym <= 0x20ac) {
+ mib = -1; // manual conversion
+ mapper = 0;
+ converted = (uint)keysym;
+ }
+ break;
+ default:
+ break;
+ }
+ if (mib != -1) {
+ mapper = QTextCodec::codecForMib(mib);
+ if (chars.isEmpty())
+ chars.resize(1);
+ chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later
+ count++;
+ }
+ } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) {
+ converted = (ushort) (keysym - 0x1000000);
+ mapper = 0;
+ }
+ if (count < (int)chars.size()-1)
+ chars[count] = '\0';
+
+ QString text;
+ if (!mapper && converted.unicode() != 0x0) {
+ text = converted;
+ } else if (!chars.isEmpty()) {
+ // convert chars (8bit) to text (unicode).
+ if (mapper)
+ text = mapper->toUnicode(chars.data(), count, 0);
+ if (text.isEmpty()) {
+ // no mapper, or codec couldn't convert to unicode (this
+ // can happen when running in the C locale or with no LANG
+ // set). try converting from latin-1
+ text = QString::fromLatin1(chars);
+ }
+ }
+
+ modifiers = X11->translateModifiers(xmodifiers);
+
+ // Commentary in X11/keysymdef says that X codes match ASCII, so it
+ // is safe to use the locale functions to process X codes in ISO8859-1.
+ //
+ // This is mainly for compatibility - applications should not use the
+ // Qt keycodes between 128 and 255, but should rather use the
+ // QKeyEvent::text().
+ //
+ extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp
+ if (keysym < 128 || (keysym < 256 && (!qt_input_mapper || qt_input_mapper->mibEnum()==4))) {
+ // upper-case key, if known
+ code = isprint((int)keysym) ? toupper((int)keysym) : 0;
+ } else if (keysym >= XK_F1 && keysym <= XK_F35) {
+ // function keys
+ code = Qt::Key_F1 + ((int)keysym - XK_F1);
+ } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) {
+ if (keysym >= XK_KP_0) {
+ // numeric keypad keys
+ code = Qt::Key_0 + ((int)keysym - XK_KP_0);
+ } else {
+ code = translateKeySym(keysym);
+ }
+ modifiers |= Qt::KeypadModifier;
+ } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) {
+ code = text.unicode()->toUpper().unicode();
+ } else {
+ // any other keys
+ code = translateKeySym(keysym);
+
+ if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
+ // map shift+tab to shift+backtab, QShortcutMap knows about it
+ // and will handle it.
+ code = Qt::Key_Backtab;
+ text = QString();
+ }
+ }
+
+ return text;
+}
+
+extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp
+
+bool QKeyMapperPrivate::translateKeyEventInternal(QWidget *keyWidget,
+ const XEvent *event,
+ KeySym &keysym,
+ int& count,
+ QString& text,
+ Qt::KeyboardModifiers &modifiers,
+ int& code,
+ QEvent::Type &type,
+ bool statefulTranslation)
+{
+ XKeyEvent xkeyevent = event->xkey;
+ int keycode = event->xkey.keycode;
+ // save the modifier state, we will use the keystate uint later by passing
+ // it to translateButtonState
+ uint keystate = event->xkey.state;
+
+ type = (event->type == XKeyPress) ? QEvent::KeyPress : QEvent::KeyRelease;
+
+ static int directionKeyEvent = 0;
+ static unsigned int lastWinId = 0;
+
+ // translate pending direction change
+ if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyRelease) {
+ if (directionKeyEvent == Qt::Key_Direction_R || directionKeyEvent == Qt::Key_Direction_L) {
+ type = QEvent::KeyPress;
+ code = directionKeyEvent;
+ text = QString();
+ directionKeyEvent = 0;
+ lastWinId = 0;
+ return true;
+ } else {
+ directionKeyEvent = 0;
+ lastWinId = 0;
+ }
+ }
+
+ // some XmbLookupString implementations don't return buffer overflow correctly,
+ // so we increase the input buffer to allow for long strings...
+ // 256 chars * 2 bytes + 1 null-term == 513 bytes
+ QByteArray chars;
+ chars.resize(513);
+
+ count = XLookupString(&xkeyevent, chars.data(), chars.size(), &keysym, 0);
+ if (count && !keycode) {
+ extern int qt_ximComposingKeycode; // from qapplication_x11.cpp
+ keycode = qt_ximComposingKeycode;
+ qt_ximComposingKeycode = 0;
+ }
+
+ // translate the keysym + xmodifiers to Qt::Key_* + Qt::KeyboardModifiers
+ text = translateKeySym(keysym, keystate, code, modifiers, chars, count);
+
+ // Watch for keypresses and if its a key belonging to the Ctrl-Shift
+ // direction-changing accel, remember it.
+ // We keep track of those keys instead of using the event's state
+ // (to figure out whether the Ctrl modifier is held while Shift is pressed,
+ // or Shift is held while Ctrl is pressed) since the 'state' doesn't tell
+ // us whether the modifier held is Left or Right.
+ if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyPress) {
+ if (keysym == XK_Control_L || keysym == XK_Control_R
+ || keysym == XK_Shift_L || keysym == XK_Shift_R) {
+ if (!directionKeyEvent) {
+ directionKeyEvent = keysym;
+ // This code exists in order to check that
+ // the event is occurred in the same widget.
+ lastWinId = keyWidget->internalWinId();
+ }
+ } else {
+ // this can no longer be a direction-changing accel.
+ // if any other key was pressed.
+ directionKeyEvent = Qt::Key_Space;
+ }
+
+ if (directionKeyEvent && lastWinId == keyWidget->internalWinId()) {
+ if ((keysym == XK_Shift_L && directionKeyEvent == XK_Control_L)
+ || (keysym == XK_Control_L && directionKeyEvent == XK_Shift_L)) {
+ directionKeyEvent = Qt::Key_Direction_L;
+ } else if ((keysym == XK_Shift_R && directionKeyEvent == XK_Control_R)
+ || (keysym == XK_Control_R && directionKeyEvent == XK_Shift_R)) {
+ directionKeyEvent = Qt::Key_Direction_R;
+ }
+ } else if (directionKeyEvent == Qt::Key_Direction_L
+ || directionKeyEvent == Qt::Key_Direction_R) {
+ directionKeyEvent = Qt::Key_Space; // invalid
+ }
+ }
+
+ return true;
+}
+
+
+struct qt_auto_repeat_data
+{
+ // match the window and keycode with timestamp delta of 10 ms
+ Window window;
+ KeyCode keycode;
+ Time timestamp;
+
+ // queue scanner state
+ bool release;
+ bool error;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_keypress_scanner(Display *, XEvent *event, XPointer arg)
+{
+ if (event->type != XKeyPress && event->type != XKeyRelease)
+ return false;
+
+ qt_auto_repeat_data *data = (qt_auto_repeat_data *) arg;
+ if (data->error)
+ return false;
+
+ if (event->xkey.window != data->window ||
+ event->xkey.keycode != data->keycode) {
+ // deal breakers: key events in a different window or an event
+ // with a different key code
+ data->error = true;
+ return false;
+ }
+
+ if (event->type == XKeyPress) {
+ data->error = (! data->release || event->xkey.time - data->timestamp > 10);
+ return (! data->error);
+ }
+
+ // must be XKeyRelease event
+ if (data->release) {
+ // found a second release
+ data->error = true;
+ return false;
+ }
+
+ // found a single release
+ data->release = true;
+ data->timestamp = event->xkey.time;
+
+ return false;
+}
+
+static Bool qt_keyrelease_scanner(Display *, XEvent *event, XPointer arg)
+{
+ const qt_auto_repeat_data *data = (const qt_auto_repeat_data *) arg;
+ return (event->type == XKeyRelease &&
+ event->xkey.window == data->window &&
+ event->xkey.keycode == data->keycode);
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+
+bool QKeyMapperPrivate::translateKeyEvent(QWidget *keyWidget, const XEvent *event, bool grab)
+{
+ int code = -1;
+ int count = 0;
+ Qt::KeyboardModifiers modifiers;
+
+ if (qt_sm_blockUserInput) // block user interaction during session management
+ return true;
+
+ Display *dpy = X11->display;
+
+ if (!keyWidget->isEnabled())
+ return true;
+
+ QEvent::Type type;
+ bool autor = false;
+ QString text;
+
+ KeySym keysym = 0;
+ translateKeyEventInternal(keyWidget, event, keysym, count, text, modifiers, code, type);
+
+ // was this the last auto-repeater?
+ qt_auto_repeat_data auto_repeat_data;
+ auto_repeat_data.window = event->xkey.window;
+ auto_repeat_data.keycode = event->xkey.keycode;
+ auto_repeat_data.timestamp = event->xkey.time;
+
+ static uint curr_autorep = 0;
+ if (event->type == XKeyPress) {
+ if (curr_autorep == event->xkey.keycode) {
+ autor = true;
+ curr_autorep = 0;
+ }
+ } else {
+ // look ahead for auto-repeat
+ XEvent nextpress;
+
+ auto_repeat_data.release = true;
+ auto_repeat_data.error = false;
+ if (XCheckIfEvent(dpy, &nextpress, &qt_keypress_scanner,
+ (XPointer) &auto_repeat_data)) {
+ autor = true;
+
+ // Put it back... we COULD send the event now and not need
+ // the static curr_autorep variable.
+ XPutBackEvent(dpy,&nextpress);
+ }
+ curr_autorep = autor ? event->xkey.keycode : 0;
+ }
+
+#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
+ // process accelerators before doing key compression
+ if (type == QEvent::KeyPress && !grab
+ && QApplicationPrivate::instance()->use_compat()) {
+ // send accel events if the keyboard is not grabbed
+ QKeyEventEx a(type, code, modifiers, text, autor, qMax(qMax(count,1), int(text.length())),
+ event->xkey.keycode, keysym, event->xkey.state);
+ if (QApplicationPrivate::instance()->qt_tryAccelEvent(keyWidget, &a))
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_IM
+ QInputContext *qic = keyWidget->inputContext();
+#endif
+
+ // compress keys
+ if (!text.isEmpty() && keyWidget->testAttribute(Qt::WA_KeyCompression) &&
+#ifndef QT_NO_IM
+ // Ordinary input methods require discrete key events to work
+ // properly, so key compression has to be disabled when input
+ // context exists.
+ //
+ // And further consideration, some complex input method
+ // require all key press/release events discretely even if
+ // the input method awares of key compression and compressed
+ // keys are ordinary alphabets. For example, the uim project
+ // is planning to implement "combinational shift" feature for
+ // a Japanese input method, uim-skk. It will work as follows.
+ //
+ // 1. press "r"
+ // 2. press "u"
+ // 3. release both "r" and "u" in arbitrary order
+ // 4. above key sequence generates "Ru"
+ //
+ // Of course further consideration about other participants
+ // such as key repeat mechanism is required to implement such
+ // feature.
+ !qic &&
+#endif // QT_NO_IM
+ // do not compress keys if the key event we just got above matches
+ // one of the key ranges used to compute stopCompression
+ !((code >= Qt::Key_Escape && code <= Qt::Key_SysReq)
+ || (code >= Qt::Key_Home && code <= Qt::Key_PageDown)
+ || (code >= Qt::Key_Super_L && code <= Qt::Key_Direction_R)
+ || (code == 0)
+ || (text.length() == 1 && text.unicode()->unicode() == '\n'))) {
+ // the widget wants key compression so it gets it
+
+ // sync the event queue, this makes key compress work better
+ XSync(dpy, false);
+
+ for (;;) {
+ XEvent evRelease;
+ XEvent evPress;
+ if (!XCheckTypedWindowEvent(dpy,event->xkey.window,
+ XKeyRelease,&evRelease))
+ break;
+ if (!XCheckTypedWindowEvent(dpy,event->xkey.window,
+ XKeyPress,&evPress)) {
+ XPutBackEvent(dpy, &evRelease);
+ break;
+ }
+ QString textIntern;
+ int codeIntern = -1;
+ int countIntern = 0;
+ Qt::KeyboardModifiers modifiersIntern;
+ QEvent::Type t;
+ KeySym keySymIntern;
+ translateKeyEventInternal(keyWidget, &evPress, keySymIntern, countIntern, textIntern,
+ modifiersIntern, codeIntern, t);
+ // use stopCompression to stop key compression for the following
+ // key event ranges:
+ bool stopCompression =
+ // 1) misc keys
+ (codeIntern >= Qt::Key_Escape && codeIntern <= Qt::Key_SysReq)
+ // 2) cursor movement
+ || (codeIntern >= Qt::Key_Home && codeIntern <= Qt::Key_PageDown)
+ // 3) extra keys
+ || (codeIntern >= Qt::Key_Super_L && codeIntern <= Qt::Key_Direction_R)
+ // 4) something that a) doesn't translate to text or b) translates
+ // to newline text
+ || (codeIntern == 0)
+ || (textIntern.length() == 1 && textIntern.unicode()->unicode() == '\n')
+ || (codeIntern == Qt::Key_unknown);
+
+ if (modifiersIntern == modifiers && !textIntern.isEmpty() && !stopCompression) {
+ text += textIntern;
+ count += countIntern;
+ } else {
+ XPutBackEvent(dpy, &evPress);
+ XPutBackEvent(dpy, &evRelease);
+ break;
+ }
+ }
+ }
+
+ // autorepeat compression makes sense for all widgets (Windows
+ // does it automatically ....)
+ if (event->type == XKeyPress && text.length() <= 1
+#ifndef QT_NO_IM
+ // input methods need discrete key events
+ && !qic
+#endif// QT_NO_IM
+ ) {
+ XEvent dummy;
+
+ for (;;) {
+ auto_repeat_data.release = false;
+ auto_repeat_data.error = false;
+ if (! XCheckIfEvent(dpy, &dummy, &qt_keypress_scanner,
+ (XPointer) &auto_repeat_data))
+ break;
+ if (! XCheckIfEvent(dpy, &dummy, &qt_keyrelease_scanner,
+ (XPointer) &auto_repeat_data))
+ break;
+
+ count++;
+ if (!text.isEmpty())
+ text += text[0];
+ }
+ }
+
+ return QKeyMapper::sendKeyEvent(keyWidget, grab, type, code, modifiers, text, autor,
+ qMax(qMax(count,1), int(text.length())),
+ event->xkey.keycode, keysym, event->xkey.state);
+}
+
+bool QKeyMapper::sendKeyEvent(QWidget *keyWidget, bool grab,
+ QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
+ const QString &text, bool autorepeat, int count,
+ quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
+ bool *)
+{
+ // try the menukey first
+ if (type == QEvent::KeyPress && code == Qt::Key_Menu) {
+ QVariant v = keyWidget->inputMethodQuery(Qt::ImMicroFocus);
+ QPoint globalPos;
+ QPoint pos;
+ if (v.isNull()) {
+ globalPos = QCursor::pos();
+ pos = keyWidget->mapFromGlobal(globalPos);
+ } else {
+ pos = v.toRect().center();
+ globalPos = keyWidget->mapToGlobal(pos);
+ }
+ QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, globalPos);
+ qt_sendSpontaneousEvent(keyWidget, &e);
+ if(e.isAccepted())
+ return true;
+ }
+
+ Q_UNUSED(grab);
+ QKeyEventEx e(type, code, modifiers, text, autorepeat, qMax(qMax(count,1), int(text.length())),
+ nativeScanCode, nativeVirtualKey, nativeModifiers);
+ return qt_sendSpontaneousEvent(keyWidget, &e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_x11_p.cpp b/src/gui/kernel/qkeymapper_x11_p.cpp
new file mode 100644
index 0000000000..cbf26caf6d
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_x11_p.cpp
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is auto-generated, do not edit!
+
+static struct {
+ const char *layout;
+ const char *variant; // 0 means any variant
+ Qt::LayoutDirection direction;
+ QLocale::Language language;
+ QLocale::Country country;
+} xkbLayoutData[] = {
+ // name = us, description = U.S. English
+ { "us", "", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates },
+ // name = us:intl, description = U.S. English
+ { "us", "intl", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates },
+ // name = us:alt-intl, description = U.S. English
+ { "us", "alt-intl", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates },
+ // name = us:dvorak, description = U.S. English
+ { "us", "dvorak", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates },
+ // name = us:rus, description = U.S. English
+ { "us", "rus", Qt::LeftToRight, QLocale::Russian, QLocale::UnitedStates },
+ // name = ara, description = Arabic
+ { "ara", "", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates },
+ // name = ara:azerty, description = Arabic
+ { "ara", "azerty", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates },
+ // name = ara:azerty_digits, description = Arabic
+ { "ara", "azerty_digits", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates },
+ // name = ara:digits, description = Arabic
+ { "ara", "digits", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates },
+ // name = ara:qwerty, description = Arabic
+ { "ara", "qwerty", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates },
+ // name = ara:qwerty_digits, description = Arabic
+ { "ara", "qwerty_digits", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates },
+ // name = al, description = Albania
+ { "al", "", Qt::LeftToRight, QLocale::Albanian, QLocale::Albania },
+ // name = am, description = Armenia
+ { "am", "", Qt::LeftToRight, QLocale::Armenian, QLocale::Armenia },
+ // name = am:phonetic, description = Armenia
+ { "am", "phonetic", Qt::LeftToRight, QLocale::Armenian, QLocale::Armenia },
+ // name = az, description = Azerbaijan
+ { "az", "", Qt::LeftToRight, QLocale::Azerbaijani, QLocale::Azerbaijan },
+ // name = az:cyrillic, description = Azerbaijan
+ { "az", "cyrillic", Qt::LeftToRight, QLocale::Azerbaijani, QLocale::Azerbaijan },
+ // name = by, description = Belarus
+ { "by", "", Qt::LeftToRight, QLocale::Byelorussian, QLocale::Belarus },
+ // name = by:winkeys, description = Belarus
+ { "by", "winkeys", Qt::LeftToRight, QLocale::Byelorussian, QLocale::Belarus },
+ // name = be, description = Belgium
+ { "be", "", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium },
+ // name = be:iso-alternate, description = Belgium
+ { "be", "iso-alternate", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium },
+ // name = be:nodeadkeys, description = Belgium
+ { "be", "nodeadkeys", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium },
+ // name = be:sundeadkeys, description = Belgium
+ { "be", "sundeadkeys", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium },
+ // name = bd, description = Bangladesh
+ { "bd", "", Qt::LeftToRight, QLocale::Bengali, QLocale::Bangladesh },
+ // name = bd:probhat, description = Bangladesh
+ { "bd", "probhat", Qt::LeftToRight, QLocale::Bengali, QLocale::Bangladesh },
+ // name = in, description = India
+ { "in", "", Qt::LeftToRight, QLocale::Hindi, QLocale::India },
+ // name = in:ben, description = India
+ { "in", "ben", Qt::LeftToRight, QLocale::Bengali, QLocale::India },
+ // name = in:ben_probhat, description = India
+ { "in", "ben_probhat", Qt::LeftToRight, QLocale::Bengali, QLocale::India },
+ // name = in:guj, description = India
+ { "in", "guj", Qt::LeftToRight, QLocale::Gujarati, QLocale::India },
+ // name = in:guru, description = India
+ { "in", "guru", Qt::LeftToRight, QLocale::Punjabi, QLocale::India },
+ // name = in:kan, description = India
+ { "in", "kan", Qt::LeftToRight, QLocale::Kannada, QLocale::India },
+ // name = in:mal, description = India
+ { "in", "mal", Qt::LeftToRight, QLocale::Malayalam, QLocale::India },
+ // name = in:ori, description = India
+ { "in", "ori", Qt::LeftToRight, QLocale::Oriya, QLocale::India },
+ // name = in:tam_unicode, description = India
+ { "in", "tam_unicode", Qt::LeftToRight, QLocale::Tamil, QLocale::India },
+ // name = in:tam_TAB, description = India
+ { "in", "tam_TAB", Qt::LeftToRight, QLocale::Tamil, QLocale::India },
+ // name = in:tam_TSCII, description = India
+ { "in", "tam_TSCII", Qt::LeftToRight, QLocale::Tamil, QLocale::India },
+ // name = in:tam, description = India
+ { "in", "tam", Qt::LeftToRight, QLocale::Tamil, QLocale::India },
+ // name = in:tel, description = India
+ { "in", "tel", Qt::LeftToRight, QLocale::Telugu, QLocale::India },
+ // name = in:urd, description = India
+ { "in", "urd", Qt::RightToLeft, QLocale::Urdu, QLocale::India },
+ // name = ba, description = Bosnia and Herzegovina
+ { "ba", "", Qt::LeftToRight, QLocale::Bosnian, QLocale::BosniaAndHerzegowina },
+ // name = br, description = Brazil
+ { "br", "", Qt::LeftToRight, QLocale::Portuguese, QLocale::Brazil },
+ // name = br:nodeadkeys, description = Brazil
+ { "br", "nodeadkeys", Qt::LeftToRight, QLocale::Portuguese, QLocale::Brazil },
+ // name = bg, description = Bulgaria
+ { "bg", "", Qt::LeftToRight, QLocale::Bulgarian, QLocale::Bulgaria },
+ // name = bg:phonetic, description = Bulgaria
+ { "bg", "phonetic", Qt::LeftToRight, QLocale::Bulgarian, QLocale::Bulgaria },
+ // name = mm, description = Myanmar
+ { "mm", "", Qt::LeftToRight, QLocale::Burmese, QLocale::Myanmar },
+ // name = ca, description = Canada
+ { "ca", "", Qt::LeftToRight, QLocale::English, QLocale::Canada },
+ // name = ca:fr-dvorak, description = Canada
+ { "ca", "fr-dvorak", Qt::LeftToRight, QLocale::French, QLocale::Canada },
+ // name = ca:fr-legacy, description = Canada
+ { "ca", "fr-legacy", Qt::LeftToRight, QLocale::French, QLocale::Canada },
+ // name = ca:multi, description = Canada
+ { "ca", "multi", Qt::LeftToRight, QLocale::English, QLocale::Canada },
+ // name = ca:multi-2gr, description = Canada
+ { "ca", "multi-2gr", Qt::LeftToRight, QLocale::English, QLocale::Canada },
+ // name = ca:ike, description = Canada
+ { "ca", "ike", Qt::LeftToRight, QLocale::Inuktitut, QLocale::Canada },
+ // name = hr, description = Croatia
+ { "hr", "", Qt::LeftToRight, QLocale::Croatian, QLocale::Croatia },
+ // name = hr:us, description = Croatia
+ { "hr", "us", Qt::LeftToRight, QLocale::Croatian, QLocale::Croatia },
+ // name = cz, description = Czechia
+ { "cz", "", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic },
+ // name = cz:bksl, description = Czechia
+ { "cz", "bksl", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic },
+ // name = cz:qwerty, description = Czechia
+ { "cz", "qwerty", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic },
+ // name = cz:qwerty_bksl, description = Czechia
+ { "cz", "qwerty_bksl", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic },
+ // name = dk, description = Denmark
+ { "dk", "", Qt::LeftToRight, QLocale::Danish, QLocale::Denmark },
+ // name = dk:nodeadkeys, description = Denmark
+ { "dk", "nodeadkeys", Qt::LeftToRight, QLocale::Danish, QLocale::Denmark },
+ // name = nl, description = Netherlands
+ { "nl", "", Qt::LeftToRight, QLocale::Dutch, QLocale::Netherlands },
+ // name = bt, description = Bhutan
+ { "bt", "", Qt::LeftToRight, QLocale::Bhutani, QLocale::Bhutan },
+ // name = ee, description = Estonia
+ { "ee", "", Qt::LeftToRight, QLocale::Estonian, QLocale::Estonia },
+ // name = ee:nodeadkeys, description = Estonia
+ { "ee", "nodeadkeys", Qt::LeftToRight, QLocale::Estonian, QLocale::Estonia },
+ // name = ir, description = Iran
+ { "ir", "", Qt::RightToLeft, QLocale::Persian, QLocale::Iran },
+ // name = fo, description = Faroe Islands
+ { "fo", "", Qt::LeftToRight, QLocale::Faroese, QLocale::FaroeIslands },
+ // name = fo:nodeadkeys, description = Faroe Islands
+ { "fo", "nodeadkeys", Qt::LeftToRight, QLocale::Faroese, QLocale::FaroeIslands },
+ // name = fi, description = Finland
+ { "fi", "", Qt::LeftToRight, QLocale::Finnish, QLocale::Finland },
+ // name = fi:nodeadkeys, description = Finland
+ { "fi", "nodeadkeys", Qt::LeftToRight, QLocale::Finnish, QLocale::Finland },
+ // name = fi:smi, description = Finland
+ { "fi", "smi", Qt::LeftToRight, QLocale::Finnish, QLocale::Finland },
+ // name = fr, description = France
+ { "fr", "", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = fr:nodeadkeys, description = France
+ { "fr", "nodeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = fr:sundeadkeys, description = France
+ { "fr", "sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = fr:latin9, description = France
+ { "fr", "latin9", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = fr:latin9_nodeadkeys, description = France
+ { "fr", "latin9_nodeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = fr:latin9_sundeadkeys, description = France
+ { "fr", "latin9_sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = fr:dvorak, description = France
+ { "fr", "dvorak", Qt::LeftToRight, QLocale::French, QLocale::France },
+ // name = ge, description = Georgia
+ { "ge", "", Qt::LeftToRight, QLocale::Georgian, QLocale::Georgia },
+ // name = ge:ru, description = Georgia
+ { "ge", "ru", Qt::LeftToRight, QLocale::Russian, QLocale::Georgia },
+ // name = de, description = Germany
+ { "de", "", Qt::LeftToRight, QLocale::German, QLocale::Germany },
+ // name = de:deadacute, description = Germany
+ { "de", "deadacute", Qt::LeftToRight, QLocale::German, QLocale::Germany },
+ // name = de:deadgraveacute, description = Germany
+ { "de", "deadgraveacute", Qt::LeftToRight, QLocale::German, QLocale::Germany },
+ // name = de:nodeadkeys, description = Germany
+ { "de", "nodeadkeys", Qt::LeftToRight, QLocale::German, QLocale::Germany },
+ // name = de:ro, description = Germany
+ { "de", "ro", Qt::LeftToRight, QLocale::Romanian, QLocale::Germany },
+ // name = de:ro_nodeadkeys, description = Germany
+ { "de", "ro_nodeadkeys", Qt::LeftToRight, QLocale::Romanian, QLocale::Germany },
+ // name = de:dvorak, description = Germany
+ { "de", "dvorak", Qt::LeftToRight, QLocale::German, QLocale::Germany },
+ // name = gr, description = Greece
+ { "gr", "", Qt::LeftToRight, QLocale::Greek, QLocale::Greece },
+ // name = gr:extended, description = Greece
+ { "gr", "extended", Qt::LeftToRight, QLocale::Greek, QLocale::Greece },
+ // name = gr:nodeadkeys, description = Greece
+ { "gr", "nodeadkeys", Qt::LeftToRight, QLocale::Greek, QLocale::Greece },
+ // name = gr:polytonic, description = Greece
+ { "gr", "polytonic", Qt::LeftToRight, QLocale::Greek, QLocale::Greece },
+ // name = hu, description = Hungary
+ { "hu", "", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:standard, description = Hungary
+ { "hu", "standard", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:nodeadkeys, description = Hungary
+ { "hu", "nodeadkeys", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:qwerty, description = Hungary
+ { "hu", "qwerty", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwertz_comma_dead, description = Hungary
+ { "hu", "101_qwertz_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwertz_comma_nodead, description = Hungary
+ { "hu", "101_qwertz_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwertz_dot_dead, description = Hungary
+ { "hu", "101_qwertz_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwertz_dot_nodead, description = Hungary
+ { "hu", "101_qwertz_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwerty_comma_dead, description = Hungary
+ { "hu", "101_qwerty_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwerty_comma_nodead, description = Hungary
+ { "hu", "101_qwerty_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwerty_dot_dead, description = Hungary
+ { "hu", "101_qwerty_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:101_qwerty_dot_nodead, description = Hungary
+ { "hu", "101_qwerty_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwertz_comma_dead, description = Hungary
+ { "hu", "102_qwertz_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwertz_comma_nodead, description = Hungary
+ { "hu", "102_qwertz_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwertz_dot_dead, description = Hungary
+ { "hu", "102_qwertz_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwertz_dot_nodead, description = Hungary
+ { "hu", "102_qwertz_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwerty_comma_dead, description = Hungary
+ { "hu", "102_qwerty_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwerty_comma_nodead, description = Hungary
+ { "hu", "102_qwerty_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwerty_dot_dead, description = Hungary
+ { "hu", "102_qwerty_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = hu:102_qwerty_dot_nodead, description = Hungary
+ { "hu", "102_qwerty_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary },
+ // name = is, description = Iceland
+ { "is", "", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland },
+ // name = is:Sundeadkeys, description = Iceland
+ { "is", "Sundeadkeys", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland },
+ // name = is:nodeadkeys, description = Iceland
+ { "is", "nodeadkeys", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland },
+ // name = il, description = Israel
+ { "il", "", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel },
+ // name = il:lyx, description = Israel
+ { "il", "lyx", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel },
+ // name = il:si1452, description = Israel
+ { "il", "si1452", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel },
+ // name = il:phonetic, description = Israel
+ { "il", "phonetic", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel },
+ // name = it, description = Italy
+ { "it", "", Qt::LeftToRight, QLocale::Italian, QLocale::Italy },
+ // name = it:nodeadkeys, description = Italy
+ { "it", "nodeadkeys", Qt::LeftToRight, QLocale::Italian, QLocale::Italy },
+ // name = jp, description = Japan
+ { "jp", "", Qt::LeftToRight, QLocale::Japanese, QLocale::Japan },
+ // name = kg, description = Kyrgyzstan
+ { "kg", "", Qt::LeftToRight, QLocale::Kirghiz, QLocale::Kyrgyzstan },
+ // name = la, description = Laos
+ { "la", "", Qt::LeftToRight, QLocale::Laothian, QLocale::Lao },
+ // name = latam, description = Latin American
+ { "latam", "", Qt::LeftToRight, QLocale::Spanish, QLocale::Mexico },
+ // name = latam:nodeadkeys, description = Latin American
+ { "latam", "nodeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Mexico },
+ // name = latam:sundeadkeys, description = Latin American
+ { "latam", "sundeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Mexico },
+ // name = lt, description = Lithuania
+ { "lt", "", Qt::LeftToRight, QLocale::Lithuanian, QLocale::Lithuania },
+ // name = lt:std, description = Lithuania
+ { "lt", "std", Qt::LeftToRight, QLocale::Lithuanian, QLocale::Lithuania },
+ // name = lt:us, description = Lithuania
+ { "lt", "us", Qt::LeftToRight, QLocale::Lithuanian, QLocale::Lithuania },
+ // name = lv, description = Latvia
+ { "lv", "", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia },
+ // name = lv:apostrophe, description = Latvia
+ { "lv", "apostrophe", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia },
+ // name = lv:tilde, description = Latvia
+ { "lv", "tilde", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia },
+ // name = lv:fkey, description = Latvia
+ { "lv", "fkey", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia },
+ // name = mao, description = Maori
+ { "mao", "", Qt::LeftToRight, QLocale::Maori, QLocale::NewZealand },
+ // name = mkd, description = Macedonian
+ { "mkd", "", Qt::LeftToRight, QLocale::Macedonian, QLocale::Macedonia },
+ // name = mkd:nodeadkeys, description = Macedonian
+ { "mkd", "nodeadkeys", Qt::LeftToRight, QLocale::Macedonian, QLocale::Macedonia },
+ // name = mt, description = Malta
+ { "mt", "", Qt::LeftToRight, QLocale::Maltese, QLocale::Malta },
+ // name = mt:us, description = Malta
+ { "mt", "us", Qt::LeftToRight, QLocale::Maltese, QLocale::Malta },
+ // name = mn, description = Mongolia
+ { "mn", "", Qt::LeftToRight, QLocale::Mongolian, QLocale::Mongolia },
+ // name = no, description = Norway
+ { "no", "", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway },
+ // name = no:nodeadkeys, description = Norway
+ { "no", "nodeadkeys", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway },
+ // name = no:dvorak, description = Norway
+ { "no", "dvorak", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway },
+ // name = no:smi, description = Norway
+ { "no", "smi", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway },
+ // name = no:smi_nodeadkeys, description = Norway
+ { "no", "smi_nodeadkeys", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway },
+ // name = pl, description = Poland
+ { "pl", "", Qt::LeftToRight, QLocale::Polish, QLocale::Poland },
+ // name = pl:qwertz, description = Poland
+ { "pl", "qwertz", Qt::LeftToRight, QLocale::Polish, QLocale::Poland },
+ // name = pl:dvorak, description = Poland
+ { "pl", "dvorak", Qt::LeftToRight, QLocale::Polish, QLocale::Poland },
+ // name = pl:dvorak_quotes, description = Poland
+ { "pl", "dvorak_quotes", Qt::LeftToRight, QLocale::Polish, QLocale::Poland },
+ // name = pl:dvorak_altquotes, description = Poland
+ { "pl", "dvorak_altquotes", Qt::LeftToRight, QLocale::Polish, QLocale::Poland },
+ // name = pt, description = Portugal
+ { "pt", "", Qt::LeftToRight, QLocale::Portuguese, QLocale::Portugal },
+ // name = pt:nodeadkeys, description = Portugal
+ { "pt", "nodeadkeys", Qt::LeftToRight, QLocale::Portuguese, QLocale::Portugal },
+ // name = pt:sundeadkeys, description = Portugal
+ { "pt", "sundeadkeys", Qt::LeftToRight, QLocale::Portuguese, QLocale::Portugal },
+ // name = ro, description = Romania
+ { "ro", "", Qt::LeftToRight, QLocale::Romanian, QLocale::Romania },
+ // name = ro:us, description = Romania
+ { "ro", "us", Qt::LeftToRight, QLocale::English, QLocale::Romania },
+ // name = ro:de, description = Romania
+ { "ro", "de", Qt::LeftToRight, QLocale::German, QLocale::Romania },
+ // name = ru, description = Russia
+ { "ru", "", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation },
+ // name = ru:phonetic, description = Russia
+ { "ru", "phonetic", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation },
+ // name = ru:typewriter, description = Russia
+ { "ru", "typewriter", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation },
+ // name = ru:winkeys, description = Russia
+ { "ru", "winkeys", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation },
+ // name = srp, description = Serbian
+ { "srp", "", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:yz, description = Serbian
+ { "srp", "yz", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:latin, description = Serbian
+ { "srp", "latin", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:latinunicode, description = Serbian
+ { "srp", "latinunicode", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:latinyz, description = Serbian
+ { "srp", "latinyz", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:latinunicodeyz, description = Serbian
+ { "srp", "latinunicodeyz", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:alternatequotes, description = Serbian
+ { "srp", "alternatequotes", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = srp:latinalternatequotes, description = Serbian
+ { "srp", "latinalternatequotes", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro },
+ // name = si, description = Slovenia
+ { "si", "", Qt::LeftToRight, QLocale::Slovenian, QLocale::Slovenia },
+ // name = sk, description = Slovakia
+ { "sk", "", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia },
+ // name = sk:bksl, description = Slovakia
+ { "sk", "bksl", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia },
+ // name = sk:qwerty, description = Slovakia
+ { "sk", "qwerty", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia },
+ // name = sk:qwerty_bksl, description = Slovakia
+ { "sk", "qwerty_bksl", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia },
+ // name = es, description = Spain
+ { "es", "", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain },
+ // name = es:nodeadkeys, description = Spain
+ { "es", "nodeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain },
+ // name = es:sundeadkeys, description = Spain
+ { "es", "sundeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain },
+ // name = es:dvorak, description = Spain
+ { "es", "dvorak", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain },
+ // name = se, description = Sweden
+ { "se", "", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden },
+ // name = se:nodeadkeys, description = Sweden
+ { "se", "nodeadkeys", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden },
+ // name = se:dvorak, description = Sweden
+ { "se", "dvorak", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden },
+ // name = se:rus, description = Sweden
+ { "se", "rus", Qt::LeftToRight, QLocale::Russian, QLocale::Sweden },
+ // name = se:rus_nodeadkeys, description = Sweden
+ { "se", "rus_nodeadkeys", Qt::LeftToRight, QLocale::Russian, QLocale::Sweden },
+ // name = se:smi, description = Sweden
+ { "se", "smi", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden },
+ // name = ch, description = Switzerland
+ { "ch", "", Qt::LeftToRight, QLocale::German, QLocale::Switzerland },
+ // name = ch:de_nodeadkeys, description = Switzerland
+ { "ch", "de_nodeadkeys", Qt::LeftToRight, QLocale::German, QLocale::Switzerland },
+ // name = ch:de_sundeadkeys, description = Switzerland
+ { "ch", "de_sundeadkeys", Qt::LeftToRight, QLocale::German, QLocale::Switzerland },
+ // name = ch:fr, description = Switzerland
+ { "ch", "fr", Qt::LeftToRight, QLocale::French, QLocale::Switzerland },
+ // name = ch:fr_nodeadkeys, description = Switzerland
+ { "ch", "fr_nodeadkeys", Qt::LeftToRight, QLocale::French, QLocale::Switzerland },
+ // name = ch:fr_sundeadkeys, description = Switzerland
+ { "ch", "fr_sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::Switzerland },
+ // name = sy, description = Syria
+ { "sy", "", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic },
+ // name = sy:syc, description = Syria
+ { "sy", "syc", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic },
+ // name = sy:syc_phonetic, description = Syria
+ { "sy", "syc_phonetic", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic },
+ // name = tj, description = Tajikistan
+ { "tj", "", Qt::LeftToRight, QLocale::Tajik, QLocale::Tajikistan },
+ // name = lk, description = Sri Lanka
+ { "lk", "", Qt::LeftToRight, QLocale::Singhalese, QLocale::SriLanka },
+ // name = lk:tam_unicode, description = Sri Lanka
+ { "lk", "tam_unicode", Qt::LeftToRight, QLocale::Tamil, QLocale::SriLanka },
+ // name = lk:tam_TAB, description = Sri Lanka
+ { "lk", "tam_TAB", Qt::LeftToRight, QLocale::Tamil, QLocale::SriLanka },
+ // name = lk:tam_TSCII, description = Sri Lanka
+ { "lk", "tam_TSCII", Qt::LeftToRight, QLocale::Tamil, QLocale::SriLanka },
+ // name = lk:sin_phonetic, description = Sri Lanka
+ { "lk", "sin_phonetic", Qt::LeftToRight, QLocale::Singhalese, QLocale::SriLanka },
+ // name = th, description = Thailand
+ { "th", "", Qt::LeftToRight, QLocale::Thai, QLocale::Thailand },
+ // name = th:tis, description = Thailand
+ { "th", "tis", Qt::LeftToRight, QLocale::Thai, QLocale::Thailand },
+ // name = th:pat, description = Thailand
+ { "th", "pat", Qt::LeftToRight, QLocale::Thai, QLocale::Thailand },
+ // name = tr, description = Turkish
+ { "tr", "", Qt::LeftToRight, QLocale::Turkish, QLocale::Turkey },
+ // name = tr:f, description = Turkish
+ { "tr", "f", Qt::LeftToRight, QLocale::Turkish, QLocale::Turkey },
+ // name = tr:alt, description = Turkish
+ { "tr", "alt", Qt::LeftToRight, QLocale::Turkish, QLocale::Turkey },
+ // name = ua, description = Ukraine
+ { "ua", "", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine },
+ // name = ua:phonetic, description = Ukraine
+ { "ua", "phonetic", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine },
+ // name = ua:typewriter, description = Ukraine
+ { "ua", "typewriter", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine },
+ // name = ua:winkeys, description = Ukraine
+ { "ua", "winkeys", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine },
+ // name = ua:rstu, description = Ukraine
+ { "ua", "rstu", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine },
+ // name = ua:rstu_ru, description = Ukraine
+ { "ua", "rstu_ru", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine },
+ // name = gb, description = United Kingdom
+ { "gb", "", Qt::LeftToRight, QLocale::English, QLocale::UnitedKingdom },
+ // name = gb:intl, description = United Kingdom
+ { "gb", "intl", Qt::LeftToRight, QLocale::English, QLocale::UnitedKingdom },
+ // name = gb:dvorak, description = United Kingdom
+ { "gb", "dvorak", Qt::LeftToRight, QLocale::English, QLocale::UnitedKingdom },
+ // name = uz, description = Uzbekistan
+ { "uz", "", Qt::LeftToRight, QLocale::Uzbek, QLocale::Uzbekistan },
+ // name = vn, description = Vietnam
+ { "vn", "", Qt::LeftToRight, QLocale::Vietnamese, QLocale::VietNam },
+ // name = nec_vndr/jp, description = PC-98xx Series
+ { "nec_vndr/jp", "", Qt::LeftToRight, QLocale::Japanese, QLocale::Japan },
+ // name = ie, description = Ireland
+ { "ie", "", Qt::LeftToRight, QLocale::Irish, QLocale::Ireland },
+ // name = ie:CloGaelach, description = Ireland
+ { "ie", "CloGaelach", Qt::LeftToRight, QLocale::Gaelic, QLocale::Ireland },
+ // name = ie:UnicodeExpert, description = Ireland
+ { "ie", "UnicodeExpert", Qt::LeftToRight, QLocale::Irish, QLocale::Ireland },
+ // name = ie:ogam, description = Ireland
+ { "ie", "ogam", Qt::LeftToRight, QLocale::Gaelic, QLocale::Ireland },
+ // name = ie:ogam_is434, description = Ireland
+ { "ie", "ogam_is434", Qt::LeftToRight, QLocale::Gaelic, QLocale::Ireland },
+ // name = pk, description = Pakistan
+ { "pk", "", Qt::RightToLeft, QLocale::Urdu, QLocale::Pakistan },
+ { 0, 0, Qt::LeftToRight, QLocale::C, QLocale::AnyCountry }
+};
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
new file mode 100644
index 0000000000..352d26a659
--- /dev/null
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -0,0 +1,1469 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeysequence.h"
+#include "qkeysequence_p.h"
+#include "private/qapplication_p.h"
+
+#ifndef QT_NO_SHORTCUT
+
+#include "qshortcut.h"
+#include "qdebug.h"
+#ifndef QT_NO_REGEXP
+# include "qregexp.h"
+#endif
+#ifndef QT_NO_DATASTREAM
+# include "qdatastream.h"
+#endif
+#include "qvariant.h"
+
+#ifdef Q_WS_MAC
+# include <private/qt_mac_p.h>
+
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_MAC
+static bool qt_sequence_no_mnemonics = true;
+struct MacSpecialKey {
+ int key;
+ ushort macSymbol;
+};
+
+static const int NumEntries = 21;
+static const MacSpecialKey entries[NumEntries] = {
+ { Qt::Key_Escape, 0x238B },
+ { Qt::Key_Tab, 0x21E5 },
+ { Qt::Key_Backtab, 0x21E4 },
+ { Qt::Key_Backspace, 0x232B },
+ { Qt::Key_Return, 0x21B5 },
+ { Qt::Key_Enter, 0x21B5 },
+ { Qt::Key_Delete, 0x2326 },
+ { Qt::Key_Home, 0x2196 },
+ { Qt::Key_End, 0x2198 },
+ { Qt::Key_Left, 0x2190 },
+ { Qt::Key_Up, 0x2191 },
+ { Qt::Key_Right, 0x2192 },
+ { Qt::Key_Down, 0x2193 },
+ { Qt::Key_PageUp, 0x21DE },
+ { Qt::Key_PageDown, 0x21DF },
+ { Qt::Key_Shift, kShiftUnicode },
+ { Qt::Key_Control, kCommandUnicode },
+ { Qt::Key_Meta, kControlUnicode },
+ { Qt::Key_Alt, kOptionUnicode },
+ { Qt::Key_CapsLock, 0x21EA },
+};
+
+static bool operator<(const MacSpecialKey &entry, int key)
+{
+ return entry.key < key;
+}
+
+static bool operator<(int key, const MacSpecialKey &entry)
+{
+ return key < entry.key;
+}
+
+static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
+
+static QChar macSymbolForQtKey(int key)
+{
+ const MacSpecialKey *i = qBinaryFind(entries, MacSpecialKeyEntriesEnd, key);
+ if (i == MacSpecialKeyEntriesEnd)
+ return QChar();
+ return QChar(i->macSymbol);
+}
+
+static int qtkeyForMacSymbol(const QChar ch)
+{
+ for (int i = 0; i < NumEntries; ++i) {
+ const MacSpecialKey &entry = entries[i];
+ if (entry.macSymbol == ch.unicode())
+ return entry.key;
+ }
+ return -1;
+}
+
+#else
+static bool qt_sequence_no_mnemonics = false;
+#endif
+void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; }
+
+/*!
+ \class QKeySequence
+ \brief The QKeySequence class encapsulates a key sequence as used
+ by shortcuts.
+
+ \ingroup misc
+ \ingroup shared
+ \mainclass
+
+ In its most common form, a key sequence describes a combination of
+ keys that must be used together to perform some action. Key sequences
+ are used with QAction objects to specify which keyboard shortcuts can
+ be used to trigger actions.
+
+ Key sequences can be constructed for use as keyboard shortcuts in
+ three different ways:
+
+ \list
+ \o For standard shortcuts, a \l{QKeySequence::StandardKey}{standard key}
+ can be used to request the platform-specific key sequence associated
+ with each shortcut.
+ \o For custom shortcuts, human-readable strings such as "Ctrl+X" can
+ be used, and these can be translated into the appropriate shortcuts
+ for users of different languages. Translations are made in the
+ "QShortcut" context.
+ \o For hard-coded shortcuts, integer key codes can be specified with
+ a combination of values defined by the Qt::Key and Qt::Modifier enum
+ values. Each key code consists of a single Qt::Key value and zero or
+ more modifiers, such as Qt::SHIFT, Qt::CTRL, Qt::ALT and Qt::META.
+ \endlist
+
+ For example, \gui{Ctrl P} might be a sequence used as a shortcut for
+ printing a document, and can be specified in any of the following
+ ways:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qkeysequence.cpp 0
+
+ Note that, for letters, the case used in the specification string
+ does not matter. In the above examples, the user does not need to
+ hold down the \key{Shift} key to activate a shortcut specified
+ with "Ctrl+P". However, for other keys, the use of \key{Shift} as
+ an unspecified extra modifier key can lead to confusion for users
+ of an application whose keyboards have different layouts to those
+ used by the developers. See the \l{Keyboard Layout Issues} section
+ below for more details.
+
+ It is preferable to use standard shortcuts where possible.
+ When creating key sequences for non-standard shortcuts, you should use
+ human-readable strings in preference to hard-coded integer values.
+
+ QKeySequence objects can be cast to a QString to obtain a human-readable
+ translated version of the sequence. Similarly, the toString() function
+ produces human-readable strings for use in menus. On Mac OS X, the
+ appropriate symbols are used to describe keyboard shortcuts using special
+ keys on the Macintosh keyboard.
+
+ An alternative way to specify hard-coded key codes is to use the Unicode
+ code point of the character; for example, 'A' gives the same key sequence
+ as Qt::Key_A.
+
+ \bold{Note:} On Mac OS X, references to "Ctrl", Qt::CTRL, Qt::Control
+ and Qt::ControlModifier correspond to the \key Command keys on the
+ Macintosh keyboard, and references to "Meta", Qt::META, Qt::Meta and
+ Qt::MetaModifier correspond to the \key Control keys. Developers on
+ Mac OS X can use the same shortcut descriptions across all platforms,
+ and their applications will automatically work as expected on Mac OS X.
+
+ \section1 Standard Shortcuts
+
+ QKeySequence defines many \l{QKeySequence::StandardKey} {standard
+ keyboard shortcuts} to reduce the amount of effort required when
+ setting up actions in a typical application. The table below shows
+ some common key sequences that are often used for these standard
+ shortcuts by applications on four widely-used platforms. Note
+ that on Mac OS X, the \key Ctrl value corresponds to the \key
+ Command keys on the Macintosh keyboard, and the \key Meta value
+ corresponds to the \key Control keys.
+
+ \table
+ \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME
+ \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1
+ \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1
+ \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O
+ \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W
+ \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S
+ \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S
+ \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N
+ \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D
+ \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del
+ \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins
+ \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins
+ \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14
+ \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z
+ \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left
+ \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right
+ \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5
+ \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus
+ \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus
+ \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P
+ \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T
+ \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward
+ \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back
+ \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F
+ \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3
+ \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3
+ \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H
+ \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A
+ \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B
+ \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I
+ \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U
+ \row \i MoveToNextChar \i Right \i Right \i Right \i Right
+ \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left
+ \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right
+ \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left
+ \row \i MoveToNextLine \i Down \i Down \i Down \i Down
+ \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up
+ \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown
+ \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp
+ \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home
+ \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End
+ \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none)
+ \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none)
+ \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home
+ \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End
+ \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right
+ \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift?left
+ \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right
+ \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left
+ \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down
+ \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up
+ \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown
+ \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp
+ \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home
+ \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End
+ \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none)
+ \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none)
+ \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home
+ \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End
+ \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace
+ \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del
+ \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K
+ \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter
+ \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter
+ \endtable
+
+ Note that, since the key sequences used for the standard shortcuts differ
+ between platforms, you still need to test your shortcuts on each platform
+ to ensure that you do not unintentionally assign the same key sequence to
+ many actions.
+
+ \section1 Keyboard Layout Issues
+
+ Many key sequence specifications are chosen by developers based on the
+ layout of certain types of keyboard, rather than choosing keys that
+ represent the first letter of an action's name, such as \key{Ctrl S}
+ ("Ctrl+S") or \key{Ctrl C} ("Ctrl+C").
+ Additionally, because certain symbols can only be entered with the
+ help of modifier keys on certain keyboard layouts, key sequences intended
+ for use with one keyboard layout may map to a different key, map to no
+ keys at all, or require an additional modifier key to be used on
+ different keyboard layouts.
+
+ For example, the shortcuts, \key{Ctrl plus} and \key{Ctrl minus}, are often
+ used as shortcuts for zoom operations in graphics applications, and these
+ may be specified as "Ctrl++" and "Ctrl+-" respectively. However, the way
+ these shortcuts are specified and interpreted depends on the keyboard layout.
+ Users of Norwegian keyboards will note that the \key{+} and \key{-} keys
+ are not adjacent on the keyboard, but will still be able to activate both
+ shortcuts without needing to press the \key{Shift} key. However, users
+ with British keyboards will need to hold down the \key{Shift} key
+ to enter the \key{+} symbol, making the shortcut effectively the same as
+ "Ctrl+Shift+=".
+
+ Although some developers might resort to fully specifying all the modifiers
+ they use on their keyboards to activate a shortcut, this will also result
+ in unexpected behavior for users of different keyboard layouts.
+
+ For example, a developer using a British keyboard may decide to specify
+ "Ctrl+Shift+=" as the key sequence in order to create a shortcut that
+ coincidentally behaves in the same way as \key{Ctrl plus}. However, the
+ \key{=} key needs to be accessed using the \key{Shift} key on Norwegian
+ keyboard, making the required shortcut effectively \key{Ctrl Shift Shift =}
+ (an impossible key combination).
+
+ As a result, both human-readable strings and hard-coded key codes
+ can both be problematic to use when specifying a key sequence that
+ can be used on a variety of different keyboard layouts. Only the
+ use of \l{QKeySequence::StandardKey} {standard shortcuts}
+ guarantees that the user will be able to use the shortcuts that
+ the developer intended.
+
+ Despite this, we can address this issue by ensuring that human-readable
+ strings are used, making it possible for translations of key sequences to
+ be made for users of different languages. This approach will be successful
+ for users whose keyboards have the most typical layout for the language
+ they are using.
+
+ \section1 GNU Emacs Style Key Sequences
+
+ Key sequences similar to those used in \l{GNU Emacs}, allowing up to four
+ key codes, can be created by using the multiple argument constructor,
+ or by passing a human-readable string of comma-separated key sequences.
+
+ For example, the key sequence, \key{Ctrl X} followed by \key{Ctrl C}, can
+ be specified using either of the following ways:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qkeysequence.cpp 1
+
+ \warning A QApplication instance must have been constructed before a
+ QKeySequence is created; otherwise, your application may crash.
+
+ \sa QShortcut
+*/
+
+/*!
+ \enum QKeySequence::SequenceMatch
+
+ \value NoMatch The key sequences are different; not even partially
+ matching.
+ \value PartialMatch The key sequences match partially, but are not
+ the same.
+ \value ExactMatch The key sequences are the same.
+ \omitvalue Identical
+*/
+
+/*!
+ \enum QKeySequence::SequenceFormat
+
+ \value NativeText The key sequence as a platform specific string.
+ This means that it will be shown translated and on the Mac it will
+ resemble a key sequence from the menu bar. This enum is best used when you
+ want to display the string to the user.
+
+ \value PortableText The key sequence is given in a "portable" format,
+ suitable for reading and writing to a file. In many cases, it will look
+ similar to the native text on Windows and X11.
+*/
+
+static const struct {
+ int key;
+ const char* name;
+} keyname[] = {
+ { Qt::Key_Space, QT_TRANSLATE_NOOP("QShortcut", "Space") },
+ { Qt::Key_Escape, QT_TRANSLATE_NOOP("QShortcut", "Esc") },
+ { Qt::Key_Tab, QT_TRANSLATE_NOOP("QShortcut", "Tab") },
+ { Qt::Key_Backtab, QT_TRANSLATE_NOOP("QShortcut", "Backtab") },
+ { Qt::Key_Backspace, QT_TRANSLATE_NOOP("QShortcut", "Backspace") },
+ { Qt::Key_Return, QT_TRANSLATE_NOOP("QShortcut", "Return") },
+ { Qt::Key_Enter, QT_TRANSLATE_NOOP("QShortcut", "Enter") },
+ { Qt::Key_Insert, QT_TRANSLATE_NOOP("QShortcut", "Ins") },
+ { Qt::Key_Delete, QT_TRANSLATE_NOOP("QShortcut", "Del") },
+ { Qt::Key_Pause, QT_TRANSLATE_NOOP("QShortcut", "Pause") },
+ { Qt::Key_Print, QT_TRANSLATE_NOOP("QShortcut", "Print") },
+ { Qt::Key_SysReq, QT_TRANSLATE_NOOP("QShortcut", "SysReq") },
+ { Qt::Key_Home, QT_TRANSLATE_NOOP("QShortcut", "Home") },
+ { Qt::Key_End, QT_TRANSLATE_NOOP("QShortcut", "End") },
+ { Qt::Key_Left, QT_TRANSLATE_NOOP("QShortcut", "Left") },
+ { Qt::Key_Up, QT_TRANSLATE_NOOP("QShortcut", "Up") },
+ { Qt::Key_Right, QT_TRANSLATE_NOOP("QShortcut", "Right") },
+ { Qt::Key_Down, QT_TRANSLATE_NOOP("QShortcut", "Down") },
+ { Qt::Key_PageUp, QT_TRANSLATE_NOOP("QShortcut", "PgUp") },
+ { Qt::Key_PageDown, QT_TRANSLATE_NOOP("QShortcut", "PgDown") },
+ { Qt::Key_CapsLock, QT_TRANSLATE_NOOP("QShortcut", "CapsLock") },
+ { Qt::Key_NumLock, QT_TRANSLATE_NOOP("QShortcut", "NumLock") },
+ { Qt::Key_ScrollLock, QT_TRANSLATE_NOOP("QShortcut", "ScrollLock") },
+ { Qt::Key_Menu, QT_TRANSLATE_NOOP("QShortcut", "Menu") },
+ { Qt::Key_Help, QT_TRANSLATE_NOOP("QShortcut", "Help") },
+
+ // Multimedia keys
+ { Qt::Key_Back, QT_TRANSLATE_NOOP("QShortcut", "Back") },
+ { Qt::Key_Forward, QT_TRANSLATE_NOOP("QShortcut", "Forward") },
+ { Qt::Key_Stop, QT_TRANSLATE_NOOP("QShortcut", "Stop") },
+ { Qt::Key_Refresh, QT_TRANSLATE_NOOP("QShortcut", "Refresh") },
+ { Qt::Key_VolumeDown, QT_TRANSLATE_NOOP("QShortcut", "Volume Down") },
+ { Qt::Key_VolumeMute, QT_TRANSLATE_NOOP("QShortcut", "Volume Mute") },
+ { Qt::Key_VolumeUp, QT_TRANSLATE_NOOP("QShortcut", "Volume Up") },
+ { Qt::Key_BassBoost, QT_TRANSLATE_NOOP("QShortcut", "Bass Boost") },
+ { Qt::Key_BassUp, QT_TRANSLATE_NOOP("QShortcut", "Bass Up") },
+ { Qt::Key_BassDown, QT_TRANSLATE_NOOP("QShortcut", "Bass Down") },
+ { Qt::Key_TrebleUp, QT_TRANSLATE_NOOP("QShortcut", "Treble Up") },
+ { Qt::Key_TrebleDown, QT_TRANSLATE_NOOP("QShortcut", "Treble Down") },
+ { Qt::Key_MediaPlay, QT_TRANSLATE_NOOP("QShortcut", "Media Play") },
+ { Qt::Key_MediaStop, QT_TRANSLATE_NOOP("QShortcut", "Media Stop") },
+ { Qt::Key_MediaPrevious,QT_TRANSLATE_NOOP("QShortcut", "Media Previous") },
+ { Qt::Key_MediaNext, QT_TRANSLATE_NOOP("QShortcut", "Media Next") },
+ { Qt::Key_MediaRecord, QT_TRANSLATE_NOOP("QShortcut", "Media Record") },
+ { Qt::Key_HomePage, QT_TRANSLATE_NOOP("QShortcut", "Home Page") },
+ { Qt::Key_Favorites, QT_TRANSLATE_NOOP("QShortcut", "Favorites") },
+ { Qt::Key_Search, QT_TRANSLATE_NOOP("QShortcut", "Search") },
+ { Qt::Key_Standby, QT_TRANSLATE_NOOP("QShortcut", "Standby") },
+ { Qt::Key_OpenUrl, QT_TRANSLATE_NOOP("QShortcut", "Open URL") },
+ { Qt::Key_LaunchMail, QT_TRANSLATE_NOOP("QShortcut", "Launch Mail") },
+ { Qt::Key_LaunchMedia, QT_TRANSLATE_NOOP("QShortcut", "Launch Media") },
+ { Qt::Key_Launch0, QT_TRANSLATE_NOOP("QShortcut", "Launch (0)") },
+ { Qt::Key_Launch1, QT_TRANSLATE_NOOP("QShortcut", "Launch (1)") },
+ { Qt::Key_Launch2, QT_TRANSLATE_NOOP("QShortcut", "Launch (2)") },
+ { Qt::Key_Launch3, QT_TRANSLATE_NOOP("QShortcut", "Launch (3)") },
+ { Qt::Key_Launch4, QT_TRANSLATE_NOOP("QShortcut", "Launch (4)") },
+ { Qt::Key_Launch5, QT_TRANSLATE_NOOP("QShortcut", "Launch (5)") },
+ { Qt::Key_Launch6, QT_TRANSLATE_NOOP("QShortcut", "Launch (6)") },
+ { Qt::Key_Launch7, QT_TRANSLATE_NOOP("QShortcut", "Launch (7)") },
+ { Qt::Key_Launch8, QT_TRANSLATE_NOOP("QShortcut", "Launch (8)") },
+ { Qt::Key_Launch9, QT_TRANSLATE_NOOP("QShortcut", "Launch (9)") },
+ { Qt::Key_LaunchA, QT_TRANSLATE_NOOP("QShortcut", "Launch (A)") },
+ { Qt::Key_LaunchB, QT_TRANSLATE_NOOP("QShortcut", "Launch (B)") },
+ { Qt::Key_LaunchC, QT_TRANSLATE_NOOP("QShortcut", "Launch (C)") },
+ { Qt::Key_LaunchD, QT_TRANSLATE_NOOP("QShortcut", "Launch (D)") },
+ { Qt::Key_LaunchE, QT_TRANSLATE_NOOP("QShortcut", "Launch (E)") },
+ { Qt::Key_LaunchF, QT_TRANSLATE_NOOP("QShortcut", "Launch (F)") },
+
+ // --------------------------------------------------------------
+ // More consistent namings
+ { Qt::Key_Print, QT_TRANSLATE_NOOP("QShortcut", "Print Screen") },
+ { Qt::Key_PageUp, QT_TRANSLATE_NOOP("QShortcut", "Page Up") },
+ { Qt::Key_PageDown, QT_TRANSLATE_NOOP("QShortcut", "Page Down") },
+ { Qt::Key_CapsLock, QT_TRANSLATE_NOOP("QShortcut", "Caps Lock") },
+ { Qt::Key_NumLock, QT_TRANSLATE_NOOP("QShortcut", "Num Lock") },
+ { Qt::Key_NumLock, QT_TRANSLATE_NOOP("QShortcut", "Number Lock") },
+ { Qt::Key_ScrollLock, QT_TRANSLATE_NOOP("QShortcut", "Scroll Lock") },
+ { Qt::Key_Insert, QT_TRANSLATE_NOOP("QShortcut", "Insert") },
+ { Qt::Key_Delete, QT_TRANSLATE_NOOP("QShortcut", "Delete") },
+ { Qt::Key_Escape, QT_TRANSLATE_NOOP("QShortcut", "Escape") },
+ { Qt::Key_SysReq, QT_TRANSLATE_NOOP("QShortcut", "System Request") },
+
+ // --------------------------------------------------------------
+ // Keypad navigation keys
+ { Qt::Key_Select, QT_TRANSLATE_NOOP("QShortcut", "Select") },
+ { Qt::Key_Yes, QT_TRANSLATE_NOOP("QShortcut", "Yes") },
+ { Qt::Key_No, QT_TRANSLATE_NOOP("QShortcut", "No") },
+
+ // --------------------------------------------------------------
+ // Device keys
+ { Qt::Key_Context1, QT_TRANSLATE_NOOP("QShortcut", "Context1") },
+ { Qt::Key_Context2, QT_TRANSLATE_NOOP("QShortcut", "Context2") },
+ { Qt::Key_Context3, QT_TRANSLATE_NOOP("QShortcut", "Context3") },
+ { Qt::Key_Context4, QT_TRANSLATE_NOOP("QShortcut", "Context4") },
+ { Qt::Key_Call, QT_TRANSLATE_NOOP("QShortcut", "Call") },
+ { Qt::Key_Hangup, QT_TRANSLATE_NOOP("QShortcut", "Hangup") },
+ { Qt::Key_Flip, QT_TRANSLATE_NOOP("QShortcut", "Flip") },
+
+
+ { 0, 0 }
+};
+
+//Table of key bindings. It must be sorted on key sequence.
+//A priority of 1 indicates that this is the primary key binding when multiple are defined.
+
+const QKeyBinding QKeySequencePrivate::keyBindings[] = {
+// StandardKey Priority Key Sequence Platforms
+ {QKeySequence::Back, 0, Qt::Key_Backspace, QApplicationPrivate::KB_Win},
+ {QKeySequence::InsertParagraphSeparator,0, Qt::Key_Return, QApplicationPrivate::KB_All},
+ {QKeySequence::InsertParagraphSeparator,0, Qt::Key_Enter, QApplicationPrivate::KB_All},
+ {QKeySequence::Delete, 1, Qt::Key_Delete, QApplicationPrivate::KB_All},
+ {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToStartOfDocument, 0, Qt::Key_Home, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToEndOfDocument, 0, Qt::Key_End, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToPreviousChar, 0, Qt::Key_Left, QApplicationPrivate::KB_All},
+ {QKeySequence::MoveToPreviousLine, 0, Qt::Key_Up, QApplicationPrivate::KB_All},
+ {QKeySequence::MoveToNextChar, 0, Qt::Key_Right, QApplicationPrivate::KB_All},
+ {QKeySequence::MoveToNextLine, 0, Qt::Key_Down, QApplicationPrivate::KB_All},
+ {QKeySequence::MoveToPreviousPage, 1, Qt::Key_PageUp, QApplicationPrivate::KB_All},
+ {QKeySequence::MoveToNextPage, 1, Qt::Key_PageDown, QApplicationPrivate::KB_All},
+ {QKeySequence::HelpContents, 0, Qt::Key_F1, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::FindNext, 0, Qt::Key_F3, QApplicationPrivate::KB_X11},
+ {QKeySequence::FindNext, 1, Qt::Key_F3, QApplicationPrivate::KB_Win},
+ {QKeySequence::Refresh, 0, Qt::Key_F5, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::Undo, 0, Qt::Key_F14, QApplicationPrivate::KB_X11}, //Undo on sun keyboards
+ {QKeySequence::Copy, 0, Qt::Key_F16, QApplicationPrivate::KB_X11}, //Copy on sun keyboards
+ {QKeySequence::Paste, 0, Qt::Key_F18, QApplicationPrivate::KB_X11}, //Paste on sun keyboards
+ {QKeySequence::Cut, 0, Qt::Key_F20, QApplicationPrivate::KB_X11}, //Cut on sun keyboards
+ {QKeySequence::PreviousChild, 0, Qt::Key_Back, QApplicationPrivate::KB_All},
+ {QKeySequence::NextChild, 0, Qt::Key_Forward, QApplicationPrivate::KB_All},
+ {QKeySequence::Forward, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_Win},
+ {QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Return, QApplicationPrivate::KB_All},
+ {QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Enter, QApplicationPrivate::KB_All},
+ {QKeySequence::Paste, 0, Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::Cut, 0, Qt::SHIFT | Qt::Key_Delete, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, //## Check if this should work on mac
+ {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectStartOfDocument, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectEndOfDocument, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectPreviousChar, 0, Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_All},
+ {QKeySequence::SelectPreviousLine, 0, Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_All},
+ {QKeySequence::SelectNextChar, 0, Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_All},
+ {QKeySequence::SelectNextLine, 0, Qt::SHIFT | Qt::Key_Down, QApplicationPrivate::KB_All},
+ {QKeySequence::SelectPreviousPage, 0, Qt::SHIFT | Qt::Key_PageUp, QApplicationPrivate::KB_All},
+ {QKeySequence::SelectNextPage, 0, Qt::SHIFT | Qt::Key_PageDown, QApplicationPrivate::KB_All},
+ {QKeySequence::WhatsThis, 1, Qt::SHIFT | Qt::Key_F1, QApplicationPrivate::KB_All},
+ {QKeySequence::FindPrevious, 0, Qt::SHIFT | Qt::Key_F3, QApplicationPrivate::KB_X11},
+ {QKeySequence::FindPrevious, 1, Qt::SHIFT | Qt::Key_F3, QApplicationPrivate::KB_Win},
+ {QKeySequence::ZoomIn, 1, Qt::CTRL | Qt::Key_Plus, QApplicationPrivate::KB_All},
+ {QKeySequence::NextChild, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_KDE},
+ {QKeySequence::ZoomOut, 1, Qt::CTRL | Qt::Key_Minus, QApplicationPrivate::KB_All},
+ {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::Key_Period, QApplicationPrivate::KB_KDE},
+ {QKeySequence::HelpContents, 1, Qt::CTRL | Qt::Key_Question, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectAll, 1, Qt::CTRL | Qt::Key_A, QApplicationPrivate::KB_All},
+ {QKeySequence::Bold, 1, Qt::CTRL | Qt::Key_B, QApplicationPrivate::KB_All},
+ {QKeySequence::Copy, 1, Qt::CTRL | Qt::Key_C, QApplicationPrivate::KB_All},
+ {QKeySequence::Delete, 0, Qt::CTRL | Qt::Key_D, QApplicationPrivate::KB_X11}, //emacs (line edit only)
+ {QKeySequence::Find, 0, Qt::CTRL | Qt::Key_F, QApplicationPrivate::KB_All},
+ {QKeySequence::FindNext, 1, Qt::CTRL | Qt::Key_G, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
+ {QKeySequence::FindNext, 0, Qt::CTRL | Qt::Key_G, QApplicationPrivate::KB_Win},
+ {QKeySequence::Replace, 0, Qt::CTRL | Qt::Key_H, QApplicationPrivate::KB_Win},
+ {QKeySequence::Replace, 0, Qt::CTRL | Qt::Key_H, QApplicationPrivate::KB_Gnome},
+ {QKeySequence::Italic, 0, Qt::CTRL | Qt::Key_I, QApplicationPrivate::KB_All},
+ {QKeySequence::DeleteEndOfLine, 0, Qt::CTRL | Qt::Key_K, QApplicationPrivate::KB_X11}, //emacs (line edit only)
+ {QKeySequence::New, 1, Qt::CTRL | Qt::Key_N, QApplicationPrivate::KB_All},
+ {QKeySequence::Open, 1, Qt::CTRL | Qt::Key_O, QApplicationPrivate::KB_All},
+ {QKeySequence::Print, 1, Qt::CTRL | Qt::Key_P, QApplicationPrivate::KB_All},
+ {QKeySequence::Refresh, 1, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
+ {QKeySequence::Replace, 0, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_KDE},
+ {QKeySequence::Save, 1, Qt::CTRL | Qt::Key_S, QApplicationPrivate::KB_All},
+ {QKeySequence::AddTab, 0, Qt::CTRL | Qt::Key_T, QApplicationPrivate::KB_All},
+ {QKeySequence::Underline, 1, Qt::CTRL | Qt::Key_U, QApplicationPrivate::KB_All},
+ {QKeySequence::Paste, 1, Qt::CTRL | Qt::Key_V, QApplicationPrivate::KB_All},
+ {QKeySequence::Close, 0, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Cut, 1, Qt::CTRL | Qt::Key_X, QApplicationPrivate::KB_All},
+ {QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win},
+ {QKeySequence::Redo, 0, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Mac},//different priority from above
+ {QKeySequence::Undo, 1, Qt::CTRL | Qt::Key_Z, QApplicationPrivate::KB_All},
+ {QKeySequence::Back, 1, Qt::CTRL | Qt::Key_BracketLeft, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Forward, 1, Qt::CTRL | Qt::Key_BracketRight, QApplicationPrivate::KB_Mac},
+ {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::Key_BraceLeft, QApplicationPrivate::KB_Mac},
+ {QKeySequence::NextChild, 1, Qt::CTRL | Qt::Key_BraceRight, QApplicationPrivate::KB_Mac},
+ {QKeySequence::NextChild, 1, Qt::CTRL | Qt::Key_Tab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::NextChild, 0, Qt::CTRL | Qt::Key_Tab, QApplicationPrivate::KB_Mac}, //different priority from above
+ {QKeySequence::DeleteStartOfWord, 0, Qt::CTRL | Qt::Key_Backspace, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
+ {QKeySequence::Copy, 0, Qt::CTRL | Qt::Key_Insert, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
+ {QKeySequence::DeleteEndOfWord, 0, Qt::CTRL | Qt::Key_Delete, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
+ {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::Back, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToStartOfLine, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac },
+ {QKeySequence::MoveToStartOfDocument, 1, Qt::CTRL | Qt::Key_Up, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Forward, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToEndOfLine, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac },
+ {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToEndOfDocument, 1, Qt::CTRL | Qt::Key_Down, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Win},
+ {QKeySequence::Close, 0, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Mac},
+ {QKeySequence::NextChild, 0, Qt::CTRL | Qt::Key_F6, QApplicationPrivate::KB_Win},
+ {QKeySequence::FindPrevious, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_G, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
+ {QKeySequence::FindPrevious, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_G, QApplicationPrivate::KB_Win},
+ {QKeySequence::AddTab, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_N, QApplicationPrivate::KB_KDE},
+ {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
+ {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above
+ {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above
+ {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectStartOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac },
+ {QKeySequence::SelectStartOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectEndOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac },
+ {QKeySequence::SelectEndOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Down, QApplicationPrivate::KB_Mac},
+ {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_F6, QApplicationPrivate::KB_Win},
+ {QKeySequence::Undo, 0, Qt::ALT | Qt::Key_Backspace, QApplicationPrivate::KB_Win},
+ {QKeySequence::DeleteStartOfWord, 0, Qt::ALT | Qt::Key_Backspace, QApplicationPrivate::KB_Mac},
+ {QKeySequence::DeleteEndOfWord, 0, Qt::ALT | Qt::Key_Delete, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Back, 1, Qt::ALT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToPreviousWord, 0, Qt::ALT | Qt::Key_Left, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToStartOfBlock, 0, Qt::ALT | Qt::Key_Up, QApplicationPrivate::KB_Mac}, //mac only
+ {QKeySequence::MoveToNextWord, 0, Qt::ALT | Qt::Key_Right, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Forward, 1, Qt::ALT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToEndOfBlock, 0, Qt::ALT | Qt::Key_Down, QApplicationPrivate::KB_Mac}, //mac only
+ {QKeySequence::MoveToPreviousPage, 0, Qt::ALT | Qt::Key_PageUp, QApplicationPrivate::KB_Mac },
+ {QKeySequence::MoveToNextPage, 0, Qt::ALT | Qt::Key_PageDown, QApplicationPrivate::KB_Mac },
+ {QKeySequence::Redo, 0, Qt::ALT | Qt::SHIFT | Qt::Key_Backspace,QApplicationPrivate::KB_Win},
+ {QKeySequence::SelectPreviousWord, 0, Qt::ALT | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectStartOfBlock, 0, Qt::ALT | Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_Mac}, //mac only
+ {QKeySequence::SelectNextWord, 0, Qt::ALT | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectEndOfBlock, 0, Qt::ALT | Qt::SHIFT | Qt::Key_Down, QApplicationPrivate::KB_Mac}, //mac only
+ {QKeySequence::MoveToStartOfBlock, 0, Qt::META | Qt::Key_A, QApplicationPrivate::KB_Mac},
+ {QKeySequence::Delete, 0, Qt::META | Qt::Key_D, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToEndOfBlock, 0, Qt::META | Qt::Key_E, QApplicationPrivate::KB_Mac},
+ {QKeySequence::InsertLineSeparator, 0, Qt::META | Qt::Key_Return, QApplicationPrivate::KB_Mac},
+ {QKeySequence::InsertLineSeparator, 0, Qt::META | Qt::Key_Enter, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToStartOfLine, 0, Qt::META | Qt::Key_Left, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToPreviousPage, 0, Qt::META | Qt::Key_Up, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToEndOfLine, 0, Qt::META | Qt::Key_Right, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToNextPage, 0, Qt::META | Qt::Key_Down, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToPreviousPage, 0, Qt::META | Qt::Key_PageUp, QApplicationPrivate::KB_Mac},
+ {QKeySequence::MoveToNextPage, 0, Qt::META | Qt::Key_PageDown, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectStartOfLine, 0, Qt::META | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac},
+ {QKeySequence::SelectEndOfLine, 0, Qt::META | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac}
+};
+
+const uint QKeySequencePrivate::numberOfKeyBindings = sizeof(QKeySequencePrivate::keyBindings)/(sizeof(QKeyBinding));
+
+
+/*!
+ \enum QKeySequence::StandardKey
+ \since 4.2
+
+ This enum represent standard key bindings. They can be used to
+ assign platform dependent keyboard shortcuts to a QAction.
+ QKeyEvent also provides the function QKeyEvent::standardKey() to
+ query if it matches an existing key binding.
+
+ Note that the key bindings are platform dependent. The currently
+ bound shortcuts can be queried using keyBindings().
+
+ \value AddTab Add new tab.
+ \value Back Navigate back.
+ \value Bold Bold text.
+ \value Close Close document/tab.
+ \value Copy Copy.
+ \value Cut Cut.
+ \value Delete Delete.
+ \value DeleteEndOfLine Delete end of line.
+ \value DeleteEndOfWord Delete word from the end of the cursor.
+ \value DeleteStartOfWord Delete the beginning of a word up to the cursor.
+ \value Find Find in document.
+ \value FindNext Find next result.
+ \value FindPrevious Find previous result.
+ \value Forward Navigate forward.
+ \value HelpContents Open help contents.
+ \value InsertLineSeparator Insert a new line.
+ \value InsertParagraphSeparator Insert a new paragraph.
+ \value Italic Italic text.
+ \value MoveToEndOfBlock Move cursor to end of block. This shortcut is only used on the OS X.
+ \value MoveToEndOfDocument Move cursor to end of document.
+ \value MoveToEndOfLine Move cursor to end of line.
+ \value MoveToNextChar Move cursor to next character.
+ \value MoveToNextLine Move cursor to next line.
+ \value MoveToNextPage Move cursor to next page.
+ \value MoveToNextWord Move cursor to next word.
+ \value MoveToPreviousChar Move cursor to previous character.
+ \value MoveToPreviousLine Move cursor to previous line.
+ \value MoveToPreviousPage Move cursor to previous page.
+ \value MoveToPreviousWord Move cursor to previous word.
+ \value MoveToStartOfBlock Move cursor to start of a block. This shortcut is only used on OS X.
+ \value MoveToStartOfDocument Move cursor to start of document.
+ \value MoveToStartOfLine Move cursor to start of line.
+ \value New Create new document.
+ \value NextChild Navigate to next tab or child window.
+ \value Open Open document.
+ \value Paste Paste.
+ \value PreviousChild Navigate to previous tab or child window.
+ \value Print Print document.
+ \value Redo Redo.
+ \value Refresh Refresh or reload current document.
+ \value Replace Find and replace.
+ \value SaveAs Save document after prompting the user for a file name.
+ \value Save Save document.
+ \value SelectAll Select all text.
+ \value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on OS X.
+ \value SelectEndOfDocument Extend selection to end of document.
+ \value SelectEndOfLine Extend selection to end of line.
+ \value SelectNextChar Extend selection to next character.
+ \value SelectNextLine Extend selection to next line.
+ \value SelectNextPage Extend selection to next page.
+ \value SelectNextWord Extend selection to next word.
+ \value SelectPreviousChar Extend selection to previous character.
+ \value SelectPreviousLine Extend selection to previous line.
+ \value SelectPreviousPage Extend selection to previous page.
+ \value SelectPreviousWord Extend selection to previous word.
+ \value SelectStartOfBlock Extend selection to the start of a text block. This shortcut is only used on OS X.
+ \value SelectStartOfDocument Extend selection to start of document.
+ \value SelectStartOfLine Extend selection to start of line.
+ \value Underline Underline text.
+ \value Undo Undo.
+ \value UnknownKey Unbound key.
+ \value WhatsThis Activate whats this.
+ \value ZoomIn Zoom in.
+ \value ZoomOut Zoom out.
+*/
+
+/*!
+ \since 4.2
+
+ Constructs a QKeySequence object for the given \a key.
+ The result will depend on the currently running platform.
+
+ The resulting object will be based on the first element in the
+ list of key bindings for the \a key.
+*/
+QKeySequence::QKeySequence(StandardKey key)
+{
+ const QList <QKeySequence> bindings = keyBindings(key);
+ //pick only the first/primary shortcut from current bindings
+ if (bindings.size() > 0) {
+ d = bindings.first().d;
+ d->ref.ref();
+ }
+ else
+ d = new QKeySequencePrivate();
+}
+
+
+/*!
+ Constructs an empty key sequence.
+*/
+QKeySequence::QKeySequence()
+{
+ d = new QKeySequencePrivate();
+}
+
+/*!
+ Creates a key sequence from the \a key string. For example
+ "Ctrl+O" gives CTRL+'O'. The strings "Ctrl",
+ "Shift", "Alt" and "Meta" are recognized, as well as their
+ translated equivalents in the "QShortcut" context (using
+ QObject::tr()).
+
+ Up to four key codes may be entered by separating them with
+ commas, e.g. "Alt+X,Ctrl+S,Q".
+
+ This constructor is typically used with \link QObject::tr() tr
+ \endlink(), so that shortcut keys can be replaced in
+ translations:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qkeysequence.cpp 2
+
+ Note the "File|Open" translator comment. It is by no means
+ necessary, but it provides some context for the human translator.
+*/
+QKeySequence::QKeySequence(const QString &key)
+{
+ d = new QKeySequencePrivate();
+ assign(key);
+}
+
+/*!
+ Constructs a key sequence with up to 4 keys \a k1, \a k2,
+ \a k3 and \a k4.
+
+ The key codes are listed in Qt::Key and can be combined with
+ modifiers (see Qt::Modifier) such as Qt::SHIFT, Qt::CTRL,
+ Qt::ALT, or Qt::META.
+*/
+QKeySequence::QKeySequence(int k1, int k2, int k3, int k4)
+{
+ d = new QKeySequencePrivate();
+ d->key[0] = k1;
+ d->key[1] = k2;
+ d->key[2] = k3;
+ d->key[3] = k4;
+}
+
+/*!
+ Copy constructor. Makes a copy of \a keysequence.
+ */
+QKeySequence::QKeySequence(const QKeySequence& keysequence)
+ : d(keysequence.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ \since 4.2
+
+ Returns a list of key bindings for the given \a key.
+ The result of calling this function will vary based on the target platform.
+ The first element of the list indicates the primary shortcut for the given platform.
+ If the result contains more than one result, these can
+ be considered alternative shortcuts on the same platform for the given \a key.
+*/
+QList<QKeySequence> QKeySequence::keyBindings(StandardKey key)
+{
+ uint platform = QApplicationPrivate::currentPlatform();
+ QList <QKeySequence> list;
+ for (uint i = 0; i < QKeySequencePrivate::numberOfKeyBindings ; ++i) {
+ QKeyBinding keyBinding = QKeySequencePrivate::keyBindings[i];
+ if (keyBinding.standardKey == key && (keyBinding.platform & platform)) {
+ if (keyBinding.priority > 0)
+ list.prepend(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut));
+ else
+ list.append(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut));
+ }
+ }
+ return list;
+}
+
+/*!
+ Destroys the key sequence.
+ */
+QKeySequence::~QKeySequence()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ \internal
+ KeySequences should never be modified, but rather just created.
+ Internally though we do need to modify to keep pace in event
+ delivery.
+*/
+
+void QKeySequence::setKey(int key, int index)
+{
+ Q_ASSERT_X(index >= 0 && index < 4, "QKeySequence::setKey", "index out of range");
+ qAtomicDetach(d);
+ d->key[index] = key;
+}
+
+/*!
+ Returns the number of keys in the key sequence.
+ The maximum is 4.
+ */
+uint QKeySequence::count() const
+{
+ if (!d->key[0])
+ return 0;
+ if (!d->key[1])
+ return 1;
+ if (!d->key[2])
+ return 2;
+ if (!d->key[3])
+ return 3;
+ return 4;
+}
+
+
+/*!
+ Returns true if the key sequence is empty; otherwise returns
+ false.
+*/
+bool QKeySequence::isEmpty() const
+{
+ return !d->key[0];
+}
+
+
+/*!
+ Returns the shortcut key sequence for the mnemonic in \a text,
+ or an empty key sequence if no mnemonics are found.
+
+ For example, mnemonic("E&xit") returns \c{Qt::ALT+Qt::Key_X},
+ mnemonic("&Quit") returns \c{ALT+Key_Q}, and mnemonic("Quit")
+ returns an empty QKeySequence.
+
+ We provide a \l{accelerators.html}{list of common mnemonics}
+ in English. At the time of writing, Microsoft and Open Group do
+ not appear to have issued equivalent recommendations for other
+ languages.
+
+ \sa qt_set_sequence_auto_mnemonic()
+*/
+QKeySequence QKeySequence::mnemonic(const QString &text)
+{
+ if(qt_sequence_no_mnemonics)
+ return QKeySequence();
+
+ int p = 0;
+ while (p >= 0) {
+ p = text.indexOf(QLatin1Char('&'), p) + 1;
+ if (p <= 0 || p >= (int)text.length())
+ break;
+ if (text.at(p) != QLatin1Char('&')) {
+ QChar c = text.at(p);
+ if (c.isPrint()) {
+ c = c.toUpper();
+ return QKeySequence(c.unicode() + Qt::ALT);
+ }
+ }
+ p++;
+ }
+ return QKeySequence();
+}
+
+/*!
+ \fn int QKeySequence::assign(const QString &keys)
+
+ Adds the given \a keys to the key sequence. \a keys may
+ contain up to four key codes, provided they are separated by a
+ comma; for example, "Alt+X,Ctrl+S,Z". The return value is the
+ number of key codes added.
+*/
+int QKeySequence::assign(const QString &ks)
+{
+ QString keyseq = ks;
+ QString part;
+ int n = 0;
+ int p = 0, diff = 0;
+
+ // Run through the whole string, but stop
+ // if we have 4 keys before the end.
+ while (keyseq.length() && n < 4) {
+ // We MUST use something to separate each sequence, and space
+ // does not cut it, since some of the key names have space
+ // in them.. (Let's hope no one translate with a comma in it:)
+ p = keyseq.indexOf(QLatin1Char(','));
+ if (-1 != p) {
+ if (p == keyseq.count() - 1) { // Last comma 'Ctrl+,'
+ p = -1;
+ } else {
+ if (QLatin1Char(',') == keyseq.at(p+1)) // e.g. 'Ctrl+,, Shift+,,'
+ p++;
+ if (QLatin1Char(' ') == keyseq.at(p+1)) { // Space after comma
+ diff = 1;
+ p++;
+ } else {
+ diff = 0;
+ }
+ }
+ }
+ part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
+ keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1));
+ d->key[n] = decodeString(part);
+ ++n;
+ }
+ return n;
+}
+
+struct QModifKeyName {
+ QModifKeyName() { }
+ QModifKeyName(int q, QChar n) : qt_key(q), name(n) { }
+ QModifKeyName(int q, const QString &n) : qt_key(q), name(n) { }
+ int qt_key;
+ QString name;
+};
+
+Q_GLOBAL_STATIC(QList<QModifKeyName>, globalModifs)
+Q_GLOBAL_STATIC(QList<QModifKeyName>, globalPortableModifs)
+
+/*!
+ Constructs a single key from the string \a str.
+*/
+int QKeySequence::decodeString(const QString &str)
+{
+ return QKeySequencePrivate::decodeString(str, NativeText);
+}
+
+int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::SequenceFormat format)
+{
+ int ret = 0;
+ QString accel = str.toLower();
+ bool nativeText = (format == QKeySequence::NativeText);
+
+ QList<QModifKeyName> *gmodifs;
+ if (nativeText) {
+ gmodifs = globalModifs();
+ if (gmodifs->isEmpty()) {
+#ifdef Q_WS_MAC
+ *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode));
+ *gmodifs << QModifKeyName(Qt::ALT, QChar(kOptionUnicode));
+ *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode));
+ *gmodifs << QModifKeyName(Qt::SHIFT, QChar(kShiftUnicode));
+#endif
+ *gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+"))
+ << QModifKeyName(Qt::SHIFT, QLatin1String("shift+"))
+ << QModifKeyName(Qt::ALT, QLatin1String("alt+"))
+ << QModifKeyName(Qt::META, QLatin1String("meta+"));
+ }
+ } else {
+ gmodifs = globalPortableModifs();
+ if (gmodifs->isEmpty()) {
+ *gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+"))
+ << QModifKeyName(Qt::SHIFT, QLatin1String("shift+"))
+ << QModifKeyName(Qt::ALT, QLatin1String("alt+"))
+ << QModifKeyName(Qt::META, QLatin1String("meta+"));
+ }
+ }
+ if (!gmodifs) return ret;
+
+
+ QList<QModifKeyName> modifs;
+ if (nativeText) {
+ modifs << QModifKeyName(Qt::CTRL, QShortcut::tr("Ctrl").toLower().append(QLatin1Char('+')))
+ << QModifKeyName(Qt::SHIFT, QShortcut::tr("Shift").toLower().append(QLatin1Char('+')))
+ << QModifKeyName(Qt::ALT, QShortcut::tr("Alt").toLower().append(QLatin1Char('+')))
+ << QModifKeyName(Qt::META, QShortcut::tr("Meta").toLower().append(QLatin1Char('+')));
+ }
+ modifs += *gmodifs; // Test non-translated ones last
+
+ QString sl = accel;
+#ifdef Q_WS_MAC
+ for (int i = 0; i < modifs.size(); ++i) {
+ const QModifKeyName &mkf = modifs.at(i);
+ if (sl.contains(mkf.name)) {
+ ret |= mkf.qt_key;
+ accel.remove(mkf.name);
+ sl = accel;
+ }
+ }
+#else
+ int i = 0;
+ int lastI = 0;
+ while ((i = sl.indexOf(QLatin1Char('+'), i + 1)) != -1) {
+ const QString sub = sl.mid(lastI, i - lastI + 1);
+ // Just shortcut the check here if we only have one character.
+ // Rational: A modifier will contain the name AND +, so longer than 1, a length of 1 is just
+ // the remaining part of the shortcut (ei. The 'C' in "Ctrl+C"), so no need to check that.
+ if (sub.length() > 1) {
+ for (int j = 0; j < modifs.size(); ++j) {
+ const QModifKeyName &mkf = modifs.at(j);
+ if (sub == mkf.name) {
+ ret |= mkf.qt_key;
+ break; // Shortcut, since if we find an other it would/should just be a dup
+ }
+ }
+ }
+ lastI = i + 1;
+ }
+#endif
+
+ int p = accel.lastIndexOf(QLatin1Char('+'), str.length() - 2); // -2 so that Ctrl++ works
+ if(p > 0)
+ accel = accel.mid(p + 1);
+
+ int fnum = 0;
+ if (accel.length() == 1) {
+#ifdef Q_WS_MAC
+ int qtKey = qtkeyForMacSymbol(accel[0]);
+ if (qtKey != -1) {
+ ret |= qtKey;
+ } else
+#endif
+ {
+ ret |= accel[0].toUpper().unicode();
+ }
+ } else if (accel[0] == QLatin1Char('f') && (fnum = accel.mid(1).toInt()) && (fnum >= 1) && (fnum <= 35)) {
+ ret |= Qt::Key_F1 + fnum - 1;
+ } else {
+ // For NativeText, check the traslation table first,
+ // if we don't find anything then try it out with just the untranlated stuff.
+ // PortableText will only try the untranlated table.
+ bool found = false;
+ for (int tran = 0; tran < 2; ++tran) {
+ if (!nativeText)
+ ++tran;
+ for (int i = 0; keyname[i].name; ++i) {
+ QString keyName(tran == 0
+ ? QShortcut::tr(keyname[i].name)
+ : QString::fromLatin1(keyname[i].name));
+ if (accel == keyName.toLower()) {
+ ret |= keyname[i].key;
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+#ifdef Q_WS_MAC
+#endif
+ }
+ return ret;
+}
+
+/*!
+ Creates a shortcut string for \a key. For example,
+ Qt::CTRL+Qt::Key_O gives "Ctrl+O". The strings, "Ctrl", "Shift", etc. are
+ translated (using QObject::tr()) in the "QShortcut" context.
+ */
+QString QKeySequence::encodeString(int key)
+{
+ return QKeySequencePrivate::encodeString(key, NativeText);
+}
+
+static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format)
+{
+ if (!str.isEmpty())
+ str += (format == QKeySequence::NativeText) ? QShortcut::tr("+")
+ : QString::fromLatin1("+");
+ str += theKey;
+}
+
+QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat format)
+{
+ bool nativeText = (format == QKeySequence::NativeText);
+ QString s;
+#if defined(Q_WS_MAC)
+ if (nativeText) {
+ // On MAC the order is Meta, Alt, Shift, Control.
+ if ((key & Qt::META) == Qt::META)
+ s += macSymbolForQtKey(Qt::Key_Meta);
+ if ((key & Qt::ALT) == Qt::ALT)
+ s += macSymbolForQtKey(Qt::Key_Alt);
+ if ((key & Qt::SHIFT) == Qt::SHIFT)
+ s += macSymbolForQtKey(Qt::Key_Shift);
+ if ((key & Qt::CTRL) == Qt::CTRL)
+ s += macSymbolForQtKey(Qt::Key_Control);
+ } else
+#endif
+ {
+ // On other systems the order is Meta, Control, Alt, Shift
+ if ((key & Qt::META) == Qt::META)
+ s = nativeText ? QShortcut::tr("Meta") : QString::fromLatin1("Meta");
+ if ((key & Qt::CTRL) == Qt::CTRL)
+ addKey(s, nativeText ? QShortcut::tr("Ctrl") : QString::fromLatin1("Ctrl"), format);
+ if ((key & Qt::ALT) == Qt::ALT)
+ addKey(s, nativeText ? QShortcut::tr("Alt") : QString::fromLatin1("Alt"), format);
+ if ((key & Qt::SHIFT) == Qt::SHIFT)
+ addKey(s, nativeText ? QShortcut::tr("Shift") : QString::fromLatin1("Shift"), format);
+ }
+
+
+ key &= ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier);
+ QString p;
+
+ if (key && key < Qt::Key_Escape && key != Qt::Key_Space) {
+ if (key < 0x10000) {
+ p = QChar(key & 0xffff).toUpper();
+ } else {
+ p = QChar((key-0x10000)/0x400+0xd800);
+ p += QChar((key-0x10000)%400+0xdc00);
+ }
+ } else if (key >= Qt::Key_F1 && key <= Qt::Key_F35) {
+ p = nativeText ? QShortcut::tr("F%1").arg(key - Qt::Key_F1 + 1)
+ : QString::fromLatin1("F%1").arg(key - Qt::Key_F1 + 1);
+ } else if (key) {
+ int i=0;
+#if defined(Q_WS_MAC)
+ if (nativeText) {
+ QChar ch = macSymbolForQtKey(key);
+ if (!ch.isNull())
+ p = ch;
+ else
+ goto NonSymbol;
+ } else
+#endif
+ {
+#ifdef Q_WS_MAC
+NonSymbol:
+#endif
+ while (keyname[i].name) {
+ if (key == keyname[i].key) {
+ p = nativeText ? QShortcut::tr(keyname[i].name)
+ : QString::fromLatin1(keyname[i].name);
+ break;
+ }
+ ++i;
+ }
+ // If we can't find the actual translatable keyname,
+ // fall back on the unicode representation of it...
+ // Or else characters like Qt::Key_aring may not get displayed
+ // (Really depends on you locale)
+ if (!keyname[i].name) {
+ if (key < 0x10000) {
+ p = QChar(key & 0xffff).toUpper();
+ } else {
+ p = QChar((key-0x10000)/0x400+0xd800);
+ p += QChar((key-0x10000)%400+0xdc00);
+ }
+ }
+ }
+ }
+
+#ifdef Q_WS_MAC
+ if (nativeText)
+ s += p;
+ else
+#endif
+ addKey(s, p, format);
+ return s;
+}
+/*!
+ Matches the sequence with \a seq. Returns ExactMatch if
+ successful, PartialMatch if \a seq matches incompletely,
+ and NoMatch if the sequences have nothing in common.
+ Returns NoMatch if \a seq is shorter.
+*/
+QKeySequence::SequenceMatch QKeySequence::matches(const QKeySequence &seq) const
+{
+ uint userN = count(),
+ seqN = seq.count();
+
+ if (userN > seqN)
+ return NoMatch;
+
+ // If equal in length, we have a potential ExactMatch sequence,
+ // else we already know it can only be partial.
+ SequenceMatch match = (userN == seqN ? ExactMatch : PartialMatch);
+
+ for (uint i = 0; i < userN; ++i) {
+ int userKey = (*this)[i],
+ sequenceKey = seq[i];
+ if (userKey != sequenceKey)
+ return NoMatch;
+ }
+ return match;
+}
+
+
+/*!
+ \obsolete
+
+ Use toString() instead.
+
+ Returns the key sequence as a QString. This is equivalent to
+ calling toString(QKeySequence::NativeText). Note that the
+ result is not platform independent.
+*/
+QKeySequence::operator QString() const
+{
+ return QKeySequence::toString(QKeySequence::NativeText);
+}
+
+/*!
+ Returns the key sequence as a QVariant
+*/
+QKeySequence::operator QVariant() const
+{
+ return QVariant(QVariant::KeySequence, this);
+}
+
+/*!
+ \obsolete
+ For backward compatibility: returns the first keycode
+ as integer. If the key sequence is empty, 0 is returned.
+ */
+QKeySequence::operator int () const
+{
+ if (1 <= count())
+ return d->key[0];
+ return 0;
+}
+
+
+/*!
+ Returns a reference to the element at position \a index in the key
+ sequence. This can only be used to read an element.
+ */
+int QKeySequence::operator[](uint index) const
+{
+ Q_ASSERT_X(index < 4, "QKeySequence::operator[]", "index out of range");
+ return d->key[index];
+}
+
+
+/*!
+ Assignment operator. Assigns the \a other key sequence to this
+ object.
+ */
+QKeySequence &QKeySequence::operator=(const QKeySequence &other)
+{
+ qAtomicAssign(d, other.d);
+ return *this;
+}
+
+/*!
+ \fn bool QKeySequence::operator!=(const QKeySequence &other) const
+
+ Returns true if this key sequence is not equal to the \a other
+ key sequence; otherwise returns false.
+*/
+
+
+/*!
+ Returns true if this key sequence is equal to the \a other
+ key sequence; otherwise returns false.
+ */
+bool QKeySequence::operator==(const QKeySequence &other) const
+{
+ return (d->key[0] == other.d->key[0] &&
+ d->key[1] == other.d->key[1] &&
+ d->key[2] == other.d->key[2] &&
+ d->key[3] == other.d->key[3]);
+}
+
+
+/*!
+ Provides an arbitrary comparison of this key sequence and
+ \a other key sequence. All that is guaranteed is that the
+ operator returns false if both key sequences are equal and
+ that (ks1 \< ks2) == !( ks2 \< ks1) if the key sequences
+ are not equal.
+
+ This function is useful in some circumstances, for example
+ if you want to use QKeySequence objects as keys in a QMap.
+
+ \sa operator==() operator!=() operator>() operator<=() operator>=()
+*/
+bool QKeySequence::operator< (const QKeySequence &other) const
+{
+ for (int i = 0; i < 4; ++i)
+ if (d->key[i] != other.d->key[i])
+ return d->key[i] < other.d->key[i];
+ return false;
+}
+
+/*!
+ \fn bool QKeySequence::operator> (const QKeySequence &other) const
+
+ Returns true if this key sequence is larger than the \a other key
+ sequence; otherwise returns false.
+
+ \sa operator==() operator!=() operator<() operator<=() operator>=()
+*/
+
+/*!
+ \fn bool QKeySequence::operator<= (const QKeySequence &other) const
+
+ Returns true if this key sequence is smaller or equal to the
+ \a other key sequence; otherwise returns false.
+
+ \sa operator==() operator!=() operator<() operator>() operator>=()
+*/
+
+/*!
+ \fn bool QKeySequence::operator>= (const QKeySequence &other) const
+
+ Returns true if this key sequence is larger or equal to the
+ \a other key sequence; otherwise returns false.
+
+ \sa operator==() operator!=() operator<() operator>() operator<=()
+*/
+
+/*!
+ \internal
+*/
+bool QKeySequence::isDetached() const
+{
+ return d->ref == 1;
+}
+
+/*!
+ \since 4.1
+
+ Return a string representation of the key sequence,
+ based on \a format.
+
+ For example, the value Qt::CTRL+Qt::Key_O results in "Ctrl+O".
+ If the key sequence has multiple key codes, each is separated
+ by commas in the string returned, such as "Alt+X, Ctrl+Y, Z".
+ The strings, "Ctrl", "Shift", etc. are translated using
+ QObject::tr() in the "QShortcut" context.
+
+ If the key sequence has no keys, an empty string is returned.
+
+ On Mac OS X, the string returned resembles the sequence that is
+ shown in the menu bar.
+
+ \sa fromString()
+*/
+QString QKeySequence::toString(SequenceFormat format) const
+{
+ QString finalString;
+ // A standard string, with no translation or anything like that. In some ways it will
+ // look like our latin case on Windows and X11
+ int end = count();
+ for (int i = 0; i < end; ++i) {
+ finalString += d->encodeString(d->key[i], format);
+ finalString += QLatin1String(", ");
+ }
+ finalString.truncate(finalString.length() - 2);
+ return finalString;
+}
+
+/*!
+ \since 4.1
+
+ Return a QKeySequence from the string \a str based on \a format.
+
+ \sa toString()
+*/
+QKeySequence QKeySequence::fromString(const QString &str, SequenceFormat format)
+{
+ QStringList sl = str.split(QLatin1String(", "));
+ int keys[4] = {0, 0, 0, 0};
+ int total = qMin(sl.count(), 4);
+ for (int i = 0; i < total; ++i)
+ keys[i] = QKeySequencePrivate::decodeString(sl[i], format);
+ return QKeySequence(keys[0], keys[1], keys[2], keys[3]);
+}
+
+/*****************************************************************************
+ QKeySequence stream functions
+ *****************************************************************************/
+#if !defined(QT_NO_DATASTREAM)
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QKeySequence &sequence)
+ \relates QKeySequence
+
+ Writes the key \a sequence to the \a stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator<<(QDataStream &s, const QKeySequence &keysequence)
+{
+ QList<quint32> list;
+ list << keysequence.d->key[0];
+
+ if (s.version() >= 5 && keysequence.count() > 1) {
+ list << keysequence.d->key[1];
+ list << keysequence.d->key[2];
+ list << keysequence.d->key[3];
+ }
+ s << list;
+ return s;
+}
+
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QKeySequence &sequence)
+ \relates QKeySequence
+
+ Reads a key sequence from the \a stream into the key \a sequence.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator>>(QDataStream &s, QKeySequence &keysequence)
+{
+ qAtomicDetach(keysequence.d);
+ QList<quint32> list;
+ s >> list;
+ for (int i = 0; i < 4; ++i)
+ keysequence.d->key[i] = list.value(i);
+ return s;
+}
+
+#endif //QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QKeySequence &p)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QKeySequence(" << p.toString() << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QKeySequence to QDebug");
+ return dbg;
+ Q_UNUSED(p);
+#endif
+}
+#endif
+
+#endif // QT_NO_SHORTCUT
+
+
+/*!
+ \typedef QKeySequence::DataPtr
+ \internal
+*/
+
+ /*!
+ \fn DataPtr &QKeySequence::data_ptr()
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
new file mode 100644
index 0000000000..1c4776fab8
--- /dev/null
+++ b/src/gui/kernel/qkeysequence.h
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKEYSEQUENCE_H
+#define QKEYSEQUENCE_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_SHORTCUT
+
+/*****************************************************************************
+ QKeySequence stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+class QKeySequence;
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &out, QKeySequence &ks);
+#endif
+
+#ifdef qdoc
+void qt_set_sequence_auto_mnemonic(bool b);
+#endif
+
+class QVariant;
+class QKeySequencePrivate;
+
+class Q_GUI_EXPORT QKeySequence
+{
+public:
+ enum StandardKey {
+ UnknownKey,
+ HelpContents,
+ WhatsThis,
+ Open,
+ Close,
+ Save,
+ New,
+ Delete,
+ Cut,
+ Copy,
+ Paste,
+ Undo,
+ Redo,
+ Back,
+ Forward,
+ Refresh,
+ ZoomIn,
+ ZoomOut,
+ Print,
+ AddTab,
+ NextChild,
+ PreviousChild,
+ Find,
+ FindNext,
+ FindPrevious,
+ Replace,
+ SelectAll,
+ Bold,
+ Italic,
+ Underline,
+ MoveToNextChar,
+ MoveToPreviousChar,
+ MoveToNextWord,
+ MoveToPreviousWord,
+ MoveToNextLine,
+ MoveToPreviousLine,
+ MoveToNextPage,
+ MoveToPreviousPage,
+ MoveToStartOfLine,
+ MoveToEndOfLine,
+ MoveToStartOfBlock,
+ MoveToEndOfBlock,
+ MoveToStartOfDocument,
+ MoveToEndOfDocument,
+ SelectNextChar,
+ SelectPreviousChar,
+ SelectNextWord,
+ SelectPreviousWord,
+ SelectNextLine,
+ SelectPreviousLine,
+ SelectNextPage,
+ SelectPreviousPage,
+ SelectStartOfLine,
+ SelectEndOfLine,
+ SelectStartOfBlock,
+ SelectEndOfBlock,
+ SelectStartOfDocument,
+ SelectEndOfDocument,
+ DeleteStartOfWord,
+ DeleteEndOfWord,
+ DeleteEndOfLine,
+ InsertParagraphSeparator,
+ InsertLineSeparator,
+ SaveAs
+ };
+
+ QKeySequence();
+ QKeySequence(const QString &key);
+ QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0);
+ QKeySequence(const QKeySequence &ks);
+ QKeySequence(StandardKey key);
+ ~QKeySequence();
+
+ uint count() const; // ### Qt 5: return 'int'
+ bool isEmpty() const;
+
+ enum SequenceMatch {
+ NoMatch,
+ PartialMatch,
+ ExactMatch
+#ifdef QT3_SUPPORT
+ , Identical = ExactMatch
+#endif
+ };
+
+ enum SequenceFormat {
+ NativeText,
+ PortableText
+ };
+
+ QString toString(SequenceFormat format = PortableText) const;
+ static QKeySequence fromString(const QString &str, SequenceFormat format = PortableText);
+
+ SequenceMatch matches(const QKeySequence &seq) const;
+ static QKeySequence mnemonic(const QString &text);
+ static QList<QKeySequence> keyBindings(StandardKey key);
+
+ // ### Qt 5: kill 'operator QString' - it's evil
+ operator QString() const;
+ operator QVariant() const;
+ operator int() const;
+ int operator[](uint i) const;
+ QKeySequence &operator=(const QKeySequence &other);
+ bool operator==(const QKeySequence &other) const;
+ inline bool operator!= (const QKeySequence &other) const
+ { return !(*this == other); }
+ bool operator< (const QKeySequence &ks) const;
+ inline bool operator> (const QKeySequence &other) const
+ { return other < *this; }
+ inline bool operator<= (const QKeySequence &other) const
+ { return !(other < *this); }
+ inline bool operator>= (const QKeySequence &other) const
+ { return !(*this < other); }
+
+ bool isDetached() const;
+private:
+ static int decodeString(const QString &ks);
+ static QString encodeString(int key);
+ int assign(const QString &str);
+ void setKey(int key, int index);
+
+ QKeySequencePrivate *d;
+
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QKeySequence &ks);
+ friend class Q3AccelManager;
+ friend class QShortcutMap;
+ friend class QShortcut;
+
+public:
+ typedef QKeySequencePrivate * DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+Q_DECLARE_TYPEINFO(QKeySequence, Q_MOVABLE_TYPE);
+Q_DECLARE_SHARED(QKeySequence)
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QKeySequence &);
+#endif
+
+#else
+
+class Q_GUI_EXPORT QKeySequence
+{
+public:
+ QKeySequence() {}
+ QKeySequence(int) {}
+};
+
+#endif // QT_NO_SHORTCUT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKEYSEQUENCE_H
diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h
new file mode 100644
index 0000000000..197e62a460
--- /dev/null
+++ b/src/gui/kernel/qkeysequence_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKEYSEQUENCE_P_H
+#define QKEYSEQUENCE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qkeysequence.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SHORTCUT
+struct Q_AUTOTEST_EXPORT QKeyBinding
+{
+ QKeySequence::StandardKey standardKey;
+ uchar priority;
+ uint shortcut;
+ uint platform;
+};
+
+class Q_AUTOTEST_EXPORT QKeySequencePrivate
+{
+public:
+ inline QKeySequencePrivate()
+ {
+ ref = 1;
+ key[0] = key[1] = key[2] = key[3] = 0;
+ }
+ inline QKeySequencePrivate(const QKeySequencePrivate &copy)
+ {
+ ref = 1;
+ key[0] = copy.key[0];
+ key[1] = copy.key[1];
+ key[2] = copy.key[2];
+ key[3] = copy.key[3];
+ }
+ QAtomicInt ref;
+ int key[4];
+ static QString encodeString(int key, QKeySequence::SequenceFormat format);
+ static int decodeString(const QString &keyStr, QKeySequence::SequenceFormat format);
+
+ static const QKeyBinding keyBindings[];
+ static const uint numberOfKeyBindings;
+
+};
+#endif // QT_NO_SHORTCUT
+
+QT_END_NAMESPACE
+
+#endif //QKEYSEQUENCE_P_H
diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp
new file mode 100644
index 0000000000..aa4624942d
--- /dev/null
+++ b/src/gui/kernel/qlayout.cpp
@@ -0,0 +1,1585 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+
+#include "qapplication.h"
+#include "qlayoutengine_p.h"
+#include "qmenubar.h"
+#include "qtoolbar.h"
+#include "qsizegrip.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qvariant.h"
+#include "qwidget_p.h"
+#include "qlayout_p.h"
+#include "qformlayout.h"
+
+QT_BEGIN_NAMESPACE
+
+static int menuBarHeightForWidth(QWidget *menubar, int w)
+{
+ if (menubar && !menubar->isHidden() && !menubar->isWindow()) {
+ int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth()));
+ if (result != -1)
+ return result;
+ result = menubar->sizeHint().height();
+ if (result != -1)
+ return result;
+ }
+ return 0;
+}
+
+/*!
+ \class QLayout
+ \brief The QLayout class is the base class of geometry managers.
+
+ \ingroup appearance
+ \ingroup geomanagement
+
+ This is an abstract base class inherited by the concrete classes
+ QBoxLayout, QGridLayout, QFormLayout, and QStackedLayout.
+
+ For users of QLayout subclasses or of QMainWindow there is seldom
+ any need to use the basic functions provided by QLayout, such as
+ setSizeConstraint() or setMenuBar(). See \l{Layout Classes}
+ for more information.
+
+ To make your own layout manager, implement the functions
+ addItem(), sizeHint(), setGeometry(), itemAt() and takeAt(). You
+ should also implement minimumSize() to ensure your layout isn't
+ resized to zero size if there is too little space. To support
+ children whose heights depend on their widths, implement
+ hasHeightForWidth() and heightForWidth(). See the
+ \l{layouts/borderlayout}{Border Layout} and
+ \l{layouts/flowlayout}{Flow Layout} examples for
+ more information about implementing custom layout managers.
+
+ Geometry management stops when the layout manager is deleted.
+
+ \sa QLayoutItem, {Layout Classes}, {Basic Layouts Example},
+ {Border Layout Example}, {Flow Layout Example}
+*/
+
+
+/*!
+ Constructs a new top-level QLayout, with parent \a parent.
+ \a parent may not be 0.
+
+ There can be only one top-level layout for a widget. It is
+ returned by QWidget::layout().
+*/
+QLayout::QLayout(QWidget *parent)
+ : QObject(*new QLayoutPrivate, parent)
+{
+ if (!parent)
+ return;
+ parent->setLayout(this);
+}
+
+/*!
+ Constructs a new child QLayout.
+
+ This layout has to be inserted into another layout before geometry
+ management will work.
+*/
+QLayout::QLayout()
+ : QObject(*new QLayoutPrivate, 0)
+{
+}
+
+
+/*! \internal
+ */
+QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w)
+ : QObject(dd, lay ? static_cast<QObject*>(lay) : static_cast<QObject*>(w))
+{
+ Q_D(QLayout);
+ if (lay) {
+ lay->addItem(this);
+ } else if (w) {
+ if (w->layout()) {
+ qWarning("QLayout: Attempting to add QLayout \"%s\" to %s \"%s\", which"
+ " already has a layout",
+ qPrintable(QObject::objectName()), w->metaObject()->className(),
+ w->objectName().toLocal8Bit().data());
+ setParent(0);
+ } else {
+ d->topLevel = true;
+ w->d_func()->layout = this;
+ invalidate();
+ }
+ }
+}
+
+QLayoutPrivate::QLayoutPrivate()
+ : QObjectPrivate(), insideSpacing(-1), userLeftMargin(-1), userTopMargin(-1), userRightMargin(-1),
+ userBottomMargin(-1), topLevel(false), enabled(true), activated(true), autoNewChild(false),
+ constraint(QLayout::SetDefaultConstraint), menubar(0)
+{
+}
+
+void QLayoutPrivate::getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const
+{
+ if (!result)
+ return;
+
+ Q_Q(const QLayout);
+ if (userMargin >= 0) {
+ *result = userMargin;
+ } else if (!topLevel) {
+ *result = 0;
+ } else if (QWidget *pw = q->parentWidget()) {
+ *result = pw->style()->pixelMetric(pm, 0, pw);
+ } else {
+ *result = 0;
+ }
+}
+
+// Static item factory functions that allow for hooking things in Designer
+
+QLayoutPrivate::QWidgetItemFactoryMethod QLayoutPrivate::widgetItemFactoryMethod = 0;
+QLayoutPrivate::QSpacerItemFactoryMethod QLayoutPrivate::spacerItemFactoryMethod = 0;
+
+QWidgetItem *QLayoutPrivate::createWidgetItem(const QLayout *layout, QWidget *widget)
+{
+ if (widgetItemFactoryMethod)
+ if (QWidgetItem *wi = (*widgetItemFactoryMethod)(layout, widget))
+ return wi;
+ return new QWidgetItemV2(widget);
+}
+
+QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
+{
+ if (spacerItemFactoryMethod)
+ if (QSpacerItem *si = (*spacerItemFactoryMethod)(layout, w, h, hPolicy, vPolicy))
+ return si;
+ return new QSpacerItem(w, h, hPolicy, vPolicy);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a new top-level QLayout called \a name, with parent
+ widget \a parent. \a parent may not be 0.
+
+ The \a margin is the number of pixels between the edge of the
+ widget and the managed children. The \a spacing sets the value of
+ spacing(), which gives the spacing between the managed widgets. If
+ \a spacing is -1 (the default), spacing is set to the value of \a
+ margin.
+
+ There can be only one top-level layout for a widget. It is
+ returned by QWidget::layout()
+
+ \sa QWidget::setLayout()
+*/
+QLayout::QLayout(QWidget *parent, int margin, int spacing, const char *name)
+ : QObject(*new QLayoutPrivate,parent)
+{
+ Q_D(QLayout);
+ setObjectName(QString::fromAscii(name));
+ setMargin(margin);
+ if (spacing < 0)
+ d->insideSpacing = margin;
+ else
+ d->insideSpacing = spacing;
+ if (parent) {
+ if (parent->layout()) {
+ qWarning("QLayout \"%s\" added to %s \"%s\", which already has a layout",
+ QObject::objectName().toLocal8Bit().data(), parent->metaObject()->className(),
+ parent->objectName().toLocal8Bit().data());
+ parent->layout()->setParent(0);
+ } else {
+ d->topLevel = true;
+ parent->d_func()->layout = this;
+ invalidate();
+ }
+ }
+}
+
+/*!
+ Constructs a new child QLayout called \a name, and places it
+ inside \a parentLayout by using the default placement defined by
+ addItem().
+
+ If \a spacing is -1, this QLayout inherits \a parentLayout's
+ spacing(), otherwise the value of \a spacing is used.
+*/
+QLayout::QLayout(QLayout *parentLayout, int spacing, const char *name)
+ : QObject(*new QLayoutPrivate,parentLayout)
+
+{
+ Q_D(QLayout);
+ setObjectName(QString::fromAscii(name));
+ d->insideSpacing = spacing;
+ parentLayout->addItem(this);
+}
+
+/*!
+ Constructs a new child QLayout called \a name. If \a spacing is
+ -1, this QLayout inherits its parent's spacing(); otherwise the
+ value of \a spacing is used.
+
+ This layout has to be inserted into another layout before geometry
+ management will work.
+*/
+QLayout::QLayout(int spacing, const char *name)
+ : QObject(*new QLayoutPrivate, 0)
+{
+ Q_D(QLayout);
+ setObjectName(QString::fromAscii(name));
+ d->insideSpacing = spacing;
+}
+
+/*!
+ Automatically adding widgets is deprecated. Use addWidget() or
+ addLayout() instead.
+*/
+void QLayout::setAutoAdd(bool a) { Q_D(QLayout); d->autoNewChild = a; }
+
+/*!
+ Automatically adding widgets is deprecated. Use addWidget() or
+ addLayout() instead.
+*/
+bool QLayout::autoAdd() const { Q_D(const QLayout); return d->autoNewChild; }
+#endif
+
+
+/*!
+ \fn void QLayout::addItem(QLayoutItem *item)
+
+ Implemented in subclasses to add an \a item. How it is added is
+ specific to each subclass.
+
+ This function is not usually called in application code. To add a widget
+ to a layout, use the addWidget() function; to add a child layout, use the
+ addLayout() function provided by the relevant QLayout subclass.
+
+ \bold{Note:} The ownership of \a item is transferred to the layout, and it's
+ the layout's responsibility to delete it.
+
+ \sa addWidget(), QBoxLayout::addLayout(), QGridLayout::addLayout()
+*/
+
+/*!
+ Adds widget \a w to this layout in a manner specific to the
+ layout. This function uses addItem().
+*/
+void QLayout::addWidget(QWidget *w)
+{
+ addChildWidget(w);
+ addItem(QLayoutPrivate::createWidgetItem(this, w));
+}
+
+
+
+/*!
+ Sets the alignment for widget \a w to \a alignment and returns
+ true if \a w is found in this layout (not including child
+ layouts); otherwise returns false.
+*/
+bool QLayout::setAlignment(QWidget *w, Qt::Alignment alignment)
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item->widget() == w) {
+ item->setAlignment(alignment);
+ invalidate();
+ return true;
+ }
+ ++i;
+ item = itemAt(i);
+ }
+ return false;
+}
+
+/*!
+ \overload
+
+ Sets the alignment for the layout \a l to \a alignment and
+ returns true if \a l is found in this layout (not including child
+ layouts); otherwise returns false.
+*/
+bool QLayout::setAlignment(QLayout *l, Qt::Alignment alignment)
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item->layout() == l) {
+ item->setAlignment(alignment);
+ invalidate();
+ return true;
+ }
+ ++i;
+ item = itemAt(i);
+ }
+ return false;
+}
+
+/*!
+ \fn void QLayout::setAlignment(Qt::Alignment alignment)
+
+ Sets the alignment of this item to \a alignment.
+
+ \sa QLayoutItem::setAlignment()
+*/
+
+/*!
+ \fn bool QLayout::isTopLevel() const
+
+ Returns true if this layout is a top-level layout, i.e. not a
+ child of another layout; otherwise returns false.
+*/
+
+/*!
+ \property QLayout::margin
+ \brief the width of the outside border of the layout
+ \obsolete
+
+ Use setContentsMargins() and getContentsMargins() instead.
+
+ \sa contentsRect(), spacing
+*/
+
+/*!
+ \obsolete
+*/
+int QLayout::margin() const
+{
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ if (left == top && top == right && right == bottom) {
+ return left;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ \property QLayout::spacing
+ \brief the spacing between widgets inside the layout
+
+ If no value is explicitly set, the layout's spacing is inherited
+ from the parent layout, or from the style settings for the parent
+ widget.
+
+ For QGridLayout and QFormLayout, it is possible to set different horizontal and
+ vertical spacings using \l{QGridLayout::}{setHorizontalSpacing()}
+ and \l{QGridLayout::}{setVerticalSpacing()}. In that case,
+ spacing() returns -1.
+
+ \sa contentsRect(), getContentsMargins(), QStyle::layoutSpacing(),
+ QStyle::pixelMetric()
+*/
+
+int QLayout::spacing() const
+{
+ if (const QBoxLayout* boxlayout = qobject_cast<const QBoxLayout*>(this)) {
+ return boxlayout->spacing();
+ } else if (const QGridLayout* gridlayout = qobject_cast<const QGridLayout*>(this)) {
+ return gridlayout->spacing();
+ } else if (const QFormLayout* formlayout = qobject_cast<const QFormLayout*>(this)) {
+ return formlayout->spacing();
+ } else {
+ Q_D(const QLayout);
+ if (d->insideSpacing >=0) {
+ return d->insideSpacing;
+ } else {
+ // arbitrarily prefer horizontal spacing to vertical spacing
+ return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
+ }
+ }
+}
+
+/*!
+ \obsolete
+*/
+void QLayout::setMargin(int margin)
+{
+ setContentsMargins(margin, margin, margin, margin);
+}
+
+void QLayout::setSpacing(int spacing)
+{
+ if (QBoxLayout* boxlayout = qobject_cast<QBoxLayout*>(this)) {
+ boxlayout->setSpacing(spacing);
+ } else if (QGridLayout* gridlayout = qobject_cast<QGridLayout*>(this)) {
+ gridlayout->setSpacing(spacing);
+ } else if (QFormLayout* formlayout = qobject_cast<QFormLayout*>(this)) {
+ formlayout->setSpacing(spacing);
+ } else {
+ Q_D(QLayout);
+ d->insideSpacing = spacing;
+ invalidate();
+ }
+}
+
+/*!
+ \since 4.3
+
+ Sets the \a left, \a top, \a right, and \a bottom margins to use
+ around the layout.
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa getContentsMargins(), QStyle::pixelMetric(),
+ {QStyle::}{PM_LayoutLeftMargin},
+ {QStyle::}{PM_LayoutTopMargin},
+ {QStyle::}{PM_LayoutRightMargin},
+ {QStyle::}{PM_LayoutBottomMargin}
+*/
+void QLayout::setContentsMargins(int left, int top, int right, int bottom)
+{
+ Q_D(QLayout);
+
+ if (d->userLeftMargin == left && d->userTopMargin == top &&
+ d->userRightMargin == right && d->userBottomMargin == bottom)
+ return;
+
+ d->userLeftMargin = left;
+ d->userTopMargin = top;
+ d->userRightMargin = right;
+ d->userBottomMargin = bottom;
+ invalidate();
+}
+
+/*!
+ \since 4.3
+
+ Extracts the left, top, right, and bottom margins used around the
+ layout, and assigns them to *\a left, *\a top, *\a right, and *\a
+ bottom (unless they are null pointers).
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa setContentsMargins(), QStyle::pixelMetric(),
+ {QStyle::}{PM_LayoutLeftMargin},
+ {QStyle::}{PM_LayoutTopMargin},
+ {QStyle::}{PM_LayoutRightMargin},
+ {QStyle::}{PM_LayoutBottomMargin}
+*/
+void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) const
+{
+ Q_D(const QLayout);
+ d->getMargin(left, d->userLeftMargin, QStyle::PM_LayoutLeftMargin);
+ d->getMargin(top, d->userTopMargin, QStyle::PM_LayoutTopMargin);
+ d->getMargin(right, d->userRightMargin, QStyle::PM_LayoutRightMargin);
+ d->getMargin(bottom, d->userBottomMargin, QStyle::PM_LayoutBottomMargin);
+}
+
+/*!
+ \since 4.3
+
+ Returns the layout's geometry() rectangle, but taking into account the
+ contents margins.
+
+ \sa setContentsMargins(), getContentsMargins()
+*/
+QRect QLayout::contentsRect() const
+{
+ Q_D(const QLayout);
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ return d->rect.adjusted(+left, +top, -right, -bottom);
+}
+
+#ifdef QT3_SUPPORT
+bool QLayout::isTopLevel() const
+{
+ Q_D(const QLayout);
+ return d->topLevel;
+}
+#endif
+
+/*!
+ Returns the parent widget of this layout, or 0 if this layout is
+ not installed on any widget.
+
+ If the layout is a sub-layout, this function returns the parent
+ widget of the parent layout.
+
+ \sa parent()
+*/
+QWidget *QLayout::parentWidget() const
+{
+ Q_D(const QLayout);
+ if (!d->topLevel) {
+ if (parent()) {
+ QLayout *parentLayout = qobject_cast<QLayout*>(parent());
+ if (!parentLayout) {
+ qWarning("QLayout::parentWidget: A layout can only have another layout as a parent.");
+ return 0;
+ }
+ return parentLayout->parentWidget();
+ } else {
+ return 0;
+ }
+ } else {
+ Q_ASSERT(parent() && parent()->isWidgetType());
+ return static_cast<QWidget *>(parent());
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QLayout::isEmpty() const
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (!item->isEmpty())
+ return false;
+ ++i;
+ item = itemAt(i);
+ }
+ return true;
+}
+
+/*!
+ \reimp
+*/
+void QLayout::setGeometry(const QRect &r)
+{
+ Q_D(QLayout);
+ d->rect = r;
+}
+
+/*!
+ \reimp
+*/
+QRect QLayout::geometry() const
+{
+ Q_D(const QLayout);
+ return d->rect;
+}
+
+/*!
+ \reimp
+*/
+void QLayout::invalidate()
+{
+ Q_D(QLayout);
+ d->rect = QRect();
+ update();
+}
+
+static bool removeWidgetRecursively(QLayoutItem *li, QWidget *w)
+{
+ QLayout *lay = li->layout();
+ if (!lay)
+ return false;
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = lay->itemAt(i))) {
+ if (child->widget() == w) {
+ delete lay->takeAt(i);
+ lay->invalidate();
+ return true;
+ } else if (removeWidgetRecursively(child, w)) {
+ return true;
+ } else {
+ ++i;
+ }
+ }
+ return false;
+}
+
+
+void QLayoutPrivate::doResize(const QSize &r)
+{
+ Q_Q(QLayout);
+ int mbh = menuBarHeightForWidth(menubar, r.width());
+ QWidget *mw = q->parentWidget();
+ QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect();
+ rect.setTop(rect.top() + mbh);
+ q->setGeometry(rect);
+#ifndef QT_NO_MENUBAR
+ if (menubar)
+ menubar->setGeometry(0,0,r.width(), mbh);
+#endif
+}
+
+
+/*!
+ \internal
+ Performs child widget layout when the parent widget is
+ resized. Also handles removal of widgets. \a e is the
+ event
+*/
+void QLayout::widgetEvent(QEvent *e)
+{
+ Q_D(QLayout);
+ if (!d->enabled)
+ return;
+
+ switch (e->type()) {
+ case QEvent::Resize:
+ if (d->activated) {
+ QResizeEvent *r = (QResizeEvent *)e;
+ d->doResize(r->size());
+ } else {
+ activate();
+ }
+ break;
+ case QEvent::ChildRemoved:
+ {
+ QChildEvent *c = (QChildEvent *)e;
+ if (c->child()->isWidgetType()) {
+ QWidget *w = (QWidget *)c->child();
+#ifndef QT_NO_MENUBAR
+ if (w == d->menubar)
+ d->menubar = 0;
+#endif
+ removeWidgetRecursively(this, w);
+ }
+ }
+ break;
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInserted:
+ if (d->topLevel && d->autoNewChild) {
+ QChildEvent *c = (QChildEvent *)e;
+ if (c->child()->isWidgetType()) {
+ QWidget *w = (QWidget *)c->child();
+ if (!w->isWindow()) {
+#if !defined(QT_NO_MENUBAR) && !defined(QT_NO_TOOLBAR)
+ if (qobject_cast<QMenuBar*>(w) && !qobject_cast<QToolBar*>(w->parentWidget())) {
+ d->menubar = (QMenuBar *)w;
+ invalidate();
+ } else
+#endif
+#ifndef QT_NO_SIZEGRIP
+ if (qobject_cast<QSizeGrip*>(w) ) {
+ //SizeGrip is handled by the dialog itself.
+ } else
+#endif
+ addItem(QLayoutPrivate::createWidgetItem(this, w));
+ }
+ }
+ }
+ break;
+ case QEvent::LayoutHint:
+ d->activated = false;
+ // fall through
+#endif
+ case QEvent::LayoutRequest:
+ if (static_cast<QWidget *>(parent())->isVisible())
+ activate();
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QLayout::childEvent(QChildEvent *e)
+{
+ Q_D(QLayout);
+ if (!d->enabled)
+ return;
+
+ if (e->type() == QEvent::ChildRemoved) {
+ QChildEvent *c = (QChildEvent*)e;
+ int i = 0;
+
+ QLayoutItem *item;
+ while ((item = itemAt(i))) {
+ if (item == static_cast<QLayout*>(c->child())) {
+ takeAt(i);
+ invalidate();
+ break;
+ } else {
+ ++i;
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+int QLayout::totalHeightForWidth(int w) const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *parent = parentWidget();
+ parent->ensurePolished();
+ QWidgetPrivate *wd = parent->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+ int h = heightForWidth(w - side) + top;
+#ifndef QT_NO_MENUBAR
+ h += menuBarHeightForWidth(d->menubar, w);
+#endif
+ return h;
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+QSize QLayout::totalMinimumSize() const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *pw = parentWidget();
+ pw->ensurePolished();
+ QWidgetPrivate *wd = pw->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+
+ QSize s = minimumSize();
+#ifndef QT_NO_MENUBAR
+ top += menuBarHeightForWidth(d->menubar, s.width() + side);
+#endif
+ return s + QSize(side, top);
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+QSize QLayout::totalSizeHint() const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *pw = parentWidget();
+ pw->ensurePolished();
+ QWidgetPrivate *wd = pw->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+
+ QSize s = sizeHint();
+ if (hasHeightForWidth())
+ s.setHeight(heightForWidth(s.width() + side));
+#ifndef QT_NO_MENUBAR
+ top += menuBarHeightForWidth(d->menubar, s.width());
+#endif
+ return s + QSize(side, top);
+}
+
+/*!
+ \internal
+ Also takes contentsMargins and menu bar into account.
+*/
+QSize QLayout::totalMaximumSize() const
+{
+ Q_D(const QLayout);
+ int side=0, top=0;
+ if (d->topLevel) {
+ QWidget *pw = parentWidget();
+ pw->ensurePolished();
+ QWidgetPrivate *wd = pw->d_func();
+ side += wd->leftmargin + wd->rightmargin;
+ top += wd->topmargin + wd->bottommargin;
+ }
+
+ QSize s = maximumSize();
+#ifndef QT_NO_MENUBAR
+ top += menuBarHeightForWidth(d->menubar, s.width());
+#endif
+
+ if (d->topLevel)
+ s = QSize(qMin(s.width() + side, QLAYOUTSIZE_MAX),
+ qMin(s.height() + top, QLAYOUTSIZE_MAX));
+ return s;
+}
+
+/*!
+ \internal
+ Destroys the layout, deleting all child layouts.
+ Geometry management stops when a top-level layout is deleted.
+
+ The layout classes will probably be fatally confused if you delete
+ a sublayout.
+*/
+QLayout::~QLayout()
+{
+ Q_D(QLayout);
+ /*
+ This function may be called during the QObject destructor,
+ when the parent no longer is a QWidget.
+ */
+ if (d->topLevel && parent() && parent()->isWidgetType() &&
+ ((QWidget*)parent())->layout() == this)
+ ((QWidget*)parent())->d_func()->layout = 0;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Removes and deletes all items in this layout.
+*/
+void QLayout::deleteAllItems()
+{
+ QLayoutItem *l;
+ while ((l = takeAt(0)))
+ delete l;
+}
+#endif
+
+/*!
+ This function is called from \c addLayout() or \c insertLayout() functions in
+ subclasses to add layout \a l as a sub-layout.
+
+ The only scenario in which you need to call it directly is if you
+ implement a custom layout that supports nested layouts.
+
+ \sa QBoxLayout::addLayout(), QBoxLayout::insertLayout(), QGridLayout::addLayout()
+*/
+void QLayout::addChildLayout(QLayout *l)
+{
+ if (l->parent()) {
+ qWarning("QLayout::addChildLayout: layout \"%s\" already has a parent",
+ l->objectName().toLocal8Bit().data());
+ return;
+ }
+ l->setParent(this);
+
+ if (QWidget *mw = parentWidget()) {
+ l->d_func()->reparentChildWidgets(mw);
+ }
+
+}
+
+#ifdef QT_DEBUG
+static bool layoutDebug()
+{
+ static int checked_env = -1;
+ if(checked_env == -1)
+ checked_env = !!qgetenv("QT_LAYOUT_DEBUG").toInt();
+
+ return checked_env;
+}
+#endif
+
+void QLayoutPrivate::reparentChildWidgets(QWidget *mw)
+{
+ Q_Q(QLayout);
+ int n = q->count();
+
+#ifndef QT_NO_MENUBAR
+ if (menubar && menubar->parentWidget() != mw) {
+ menubar->setParent(mw);
+ }
+#endif
+ bool mwVisible = mw && mw->isVisible();
+ for (int i = 0; i < n; ++i) {
+ QLayoutItem *item = q->itemAt(i);
+ if (QWidget *w = item->widget()) {
+ QWidget *pw = w->parentWidget();
+#ifdef QT_DEBUG
+ if (pw && pw != mw && layoutDebug()) {
+ qWarning("QLayout::addChildLayout: widget %s \"%s\" in wrong parent; moved to correct parent",
+ w->metaObject()->className(), w->objectName().toLocal8Bit().data());
+ }
+#endif
+ bool needShow = mwVisible && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ if (pw != mw)
+ w->setParent(mw);
+ if (needShow)
+ QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
+ } else if (QLayout *l = item->layout()) {
+ l->d_func()->reparentChildWidgets(mw);
+ }
+ }
+}
+
+/*!
+ This function is called from \c addWidget() functions in
+ subclasses to add \a w as a child widget.
+
+ If \a w is already in a layout, this function will give a warning
+ and remove \a w from the layout. This function must therefore be
+ called before adding \a w to the layout's data structure.
+*/
+void QLayout::addChildWidget(QWidget *w)
+{
+ QWidget *mw = parentWidget();
+ QWidget *pw = w->parentWidget();
+
+ //Qt::WA_LaidOut is never reset. It only means that the widget at some point has
+ //been in a layout.
+ if (pw && w->testAttribute(Qt::WA_LaidOut)) {
+ QLayout *l = pw->layout();
+ if (l && removeWidgetRecursively(l, w)) {
+#ifdef QT_DEBUG
+ if (layoutDebug())
+ qWarning("QLayout::addChildWidget: %s \"%s\" is already in a layout; moved to new layout",
+ w->metaObject()->className(), w->objectName().toLocal8Bit().data());
+#endif
+ }
+ }
+ if (pw && mw && pw != mw) {
+#ifdef QT_DEBUG
+ if (layoutDebug())
+ qWarning("QLayout::addChildWidget: %s \"%s\" in wrong parent; moved to correct parent",
+ w->metaObject()->className(), w->objectName().toLocal8Bit().data());
+#endif
+ pw = 0;
+ }
+ bool needShow = mw && mw->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ if (!pw && mw)
+ w->setParent(mw);
+ w->setAttribute(Qt::WA_LaidOut);
+ if (needShow)
+ QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \compat
+
+ Sets this layout's parent widget to a fixed size with width \a w
+ and height \a h, stopping the user from resizing it, and also
+ prevents the layout from resizing it, even if the layout's size
+ hint should change. Does nothing if this is not a top-level
+ layout (i.e., if parent()->isWidgetType()).
+
+ As a special case, if both \a w and \a h are 0, then the layout's
+ current sizeHint() is used.
+
+ Use \c setResizeMode(Fixed) to stop the widget from being resized
+ by the user, while still allowing the layout to resize it when
+ the sizeHint() changes.
+
+ Use \c setResizeMode(FreeResize) to allow the user to resize the
+ widget, while preventing the layout from resizing it.
+
+*/
+void QLayout::freeze(int w, int h)
+{
+ Q_D(QLayout);
+ if (!d->topLevel)
+ return;
+ if (w <= 0 || h <= 0) {
+ QSize s = totalSizeHint();
+ w = s.width();
+ h = s.height();
+ }
+ setSizeConstraint(SetNoConstraint); // layout will not change min/max size
+ QWidget *parent = parentWidget();
+ if (parent)
+ parent->setFixedSize(w, h);
+}
+
+#endif
+
+
+
+
+
+
+
+/*!
+ Tells the geometry manager to place the menu bar \a widget at the
+ top of parentWidget(), outside QWidget::contentsMargins(). All
+ child widgets are placed below the bottom edge of the menu bar.
+*/
+void QLayout::setMenuBar(QWidget *widget)
+{
+ Q_D(QLayout);
+ if (widget)
+ addChildWidget(widget);
+ d->menubar = widget;
+}
+
+/*!
+ Returns the menu bar set for this layout, or 0 if no menu bar is
+ set.
+*/
+
+QWidget *QLayout::menuBar() const
+{
+ Q_D(const QLayout);
+ return d->menubar;
+}
+
+
+/*!
+ Returns the minimum size of this layout. This is the smallest
+ size that the layout can have while still respecting the
+ specifications.
+
+ The returned value doesn't include the space required by
+ QWidget::setContentsMargins() or menuBar().
+
+ The default implementation allows unlimited resizing.
+*/
+QSize QLayout::minimumSize() const
+{
+ return QSize(0, 0);
+}
+
+/*!
+ Returns the maximum size of this layout. This is the largest size
+ that the layout can have while still respecting the
+ specifications.
+
+ The returned value doesn't include the space required by
+ QWidget::setContentsMargins() or menuBar().
+
+ The default implementation allows unlimited resizing.
+*/
+QSize QLayout::maximumSize() const
+{
+ return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
+}
+
+/*!
+ Returns whether this layout can make use of more space than
+ sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
+ it wants to grow in only one dimension, whereas Qt::Vertical |
+ Qt::Horizontal means that it wants to grow in both dimensions.
+
+ The default implementation returns Qt::Horizontal | Qt::Vertical.
+ Subclasses reimplement it to return a meaningful value based on
+ their child widgets's \l{QSizePolicy}{size policies}.
+
+ \sa sizeHint()
+*/
+Qt::Orientations QLayout::expandingDirections() const
+{
+ return Qt::Horizontal | Qt::Vertical;
+}
+
+void QLayout::activateRecursiveHelper(QLayoutItem *item)
+{
+ item->invalidate();
+ QLayout *layout = item->layout();
+ if (layout) {
+ QLayoutItem *child;
+ int i=0;
+ while ((child = layout->itemAt(i++)))
+ activateRecursiveHelper(child);
+ layout->d_func()->activated = true;
+ }
+}
+
+/*!
+ Updates the layout for parentWidget().
+
+ You should generally not need to call this because it is
+ automatically called at the most appropriate times.
+
+ \sa activate(), invalidate()
+*/
+
+void QLayout::update()
+{
+ QLayout *layout = this;
+ while (layout && layout->d_func()->activated) {
+ layout->d_func()->activated = false;
+ if (layout->d_func()->topLevel) {
+ Q_ASSERT(layout->parent()->isWidgetType());
+ QWidget *mw = static_cast<QWidget*>(layout->parent());
+ QApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest));
+ break;
+ }
+ layout = static_cast<QLayout*>(layout->parent());
+ }
+}
+
+/*!
+ Redoes the layout for parentWidget() if necessary.
+
+ You should generally not need to call this because it is
+ automatically called at the most appropriate times. It returns
+ true if the layout was redone.
+
+ \sa update(), QWidget::updateGeometry()
+*/
+bool QLayout::activate()
+{
+ Q_D(QLayout);
+ if (!d->enabled || !parent())
+ return false;
+ if (!d->topLevel)
+ return static_cast<QLayout*>(parent())->activate();
+ if (d->activated)
+ return false;
+ QWidget *mw = static_cast<QWidget*>(parent());
+ if (mw == 0) {
+ qWarning("QLayout::activate: %s \"%s\" does not have a main widget",
+ QObject::metaObject()->className(), QObject::objectName().toLocal8Bit().data());
+ return false;
+ }
+ activateRecursiveHelper(this);
+
+ QWidgetPrivate *md = mw->d_func();
+ uint explMin = md->extra ? md->extra->explicitMinSize : 0;
+ uint explMax = md->extra ? md->extra->explicitMaxSize : 0;
+
+ switch (d->constraint) {
+ case SetFixedSize:
+ // will trigger resize
+ mw->setFixedSize(totalSizeHint());
+ break;
+ case SetMinimumSize:
+ mw->setMinimumSize(totalMinimumSize());
+ break;
+ case SetMaximumSize:
+ mw->setMaximumSize(totalMaximumSize());
+ break;
+ case SetMinAndMaxSize:
+ mw->setMinimumSize(totalMinimumSize());
+ mw->setMaximumSize(totalMaximumSize());
+ break;
+ case SetDefaultConstraint: {
+ bool widthSet = explMin & Qt::Horizontal;
+ bool heightSet = explMin & Qt::Vertical;
+ if (mw->isWindow()) {
+ QSize ms = totalMinimumSize();
+ if (widthSet)
+ ms.setWidth(mw->minimumSize().width());
+ if (heightSet)
+ ms.setHeight(mw->minimumSize().height());
+ if ((!heightSet || !widthSet) && hasHeightForWidth()) {
+ int h = minimumHeightForWidth(ms.width());
+ if (h > ms.height()) {
+ if (!heightSet)
+ ms.setHeight(0);
+ if (!widthSet)
+ ms.setWidth(0);
+ }
+ }
+ mw->setMinimumSize(ms);
+ } else if (!widthSet || !heightSet) {
+ QSize ms = mw->minimumSize();
+ if (!widthSet)
+ ms.setWidth(0);
+ if (!heightSet)
+ ms.setHeight(0);
+ mw->setMinimumSize(ms);
+ }
+ break;
+ }
+ case SetNoConstraint:
+ break;
+ }
+
+ d->doResize(mw->size());
+
+ if (md->extra) {
+ md->extra->explicitMinSize = explMin;
+ md->extra->explicitMaxSize = explMax;
+ }
+ // ideally only if sizeHint() or sizePolicy() has changed
+ mw->updateGeometry();
+ return true;
+}
+
+/*!
+ \fn QLayoutItem *QLayout::itemAt(int index) const
+
+ Must be implemented in subclasses to return the layout item at \a
+ index. If there is no such item, the function must return 0.
+ Items are numbered consecutively from 0. If an item is deleted, other items will be renumbered.
+
+ This function can be used to iterate over a layout. The following
+ code will draw a rectangle for each layout item in the layout structure of the widget.
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 0
+
+ \sa count(), takeAt()
+*/
+
+/*!
+ \fn QLayoutItem *QLayout::takeAt(int index)
+
+ Must be implemented in subclasses to remove the layout item at \a
+ index from the layout, and return the item. If there is no such
+ item, the function must do nothing and return 0. Items are numbered
+ consecutively from 0. If an item is deleted, other items will be
+ renumbered.
+
+ The following code fragment shows a safe way to remove all items
+ from a layout:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 1
+
+ \sa itemAt(), count()
+*/
+
+/*!
+ \fn int *QLayout::count() const
+
+ Must be implemented in subclasses to return the number of items
+ in the layout.
+
+ \sa itemAt()
+*/
+
+/*!
+ Searches for widget \a widget in this layout (not including child
+ layouts).
+
+ Returns the index of \a widget, or -1 if \a widget is not found.
+
+ The default implementation iterates over all items using itemAt()
+*/
+int QLayout::indexOf(QWidget *widget) const
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item->widget() == widget)
+ return i;
+ ++i;
+ item = itemAt(i);
+ }
+ return -1;
+}
+
+/*!
+ \enum QLayout::SizeConstraint
+
+ The possible values are:
+
+ \value SetDefaultConstraint The main widget's minimum size is set
+ to minimumSize(), unless the widget already has
+ a minimum size.
+
+ \value SetFixedSize The main widget's size is set to sizeHint(); it
+ cannot be resized at all.
+ \value SetMinimumSize The main widget's minimum size is set to
+ minimumSize(); it cannot be smaller.
+
+ \value SetMaximumSize The main widget's maximum size is set to
+ maximumSize(); it cannot be larger.
+
+ \value SetMinAndMaxSize The main widget's minimum size is set to
+ minimumSize() and its maximum size is set to
+ maximumSize().
+
+ \value SetNoConstraint The widget is not constrained.
+
+ \omitvalue Auto
+ \omitvalue FreeResize
+ \omitvalue Minimum
+ \omitvalue Fixed
+
+ \sa setSizeConstraint()
+*/
+
+/*!
+ \property QLayout::sizeConstraint
+ \brief the resize mode of the layout
+
+ The default mode is \l {QLayout::SetDefaultConstraint}
+ {SetDefaultConstraint}.
+*/
+void QLayout::setSizeConstraint(SizeConstraint constraint)
+{
+ Q_D(QLayout);
+ if (constraint == d->constraint)
+ return;
+
+ d->constraint = constraint;
+ invalidate();
+}
+
+QLayout::SizeConstraint QLayout::sizeConstraint() const
+{
+ Q_D(const QLayout);
+ return d->constraint;
+}
+
+/*!
+ Returns the rectangle that should be covered when the geometry of
+ this layout is set to \a r, provided that this layout supports
+ setAlignment().
+
+ The result is derived from sizeHint() and expanding(). It is never
+ larger than \a r.
+*/
+QRect QLayout::alignmentRect(const QRect &r) const
+{
+ QSize s = sizeHint();
+ Qt::Alignment a = alignment();
+
+ /*
+ This is a hack to obtain the real maximum size, not
+ QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX), the value consistently
+ returned by QLayoutItems that have an alignment.
+ */
+ QLayout *that = const_cast<QLayout *>(this);
+ that->setAlignment(0);
+ QSize ms = that->maximumSize();
+ that->setAlignment(a);
+
+ if ((expandingDirections() & Qt::Horizontal) ||
+ !(a & Qt::AlignHorizontal_Mask)) {
+ s.setWidth(qMin(r.width(), ms.width()));
+ }
+ if ((expandingDirections() & Qt::Vertical) ||
+ !(a & Qt::AlignVertical_Mask)) {
+ s.setHeight(qMin(r.height(), ms.height()));
+ } else if (hasHeightForWidth()) {
+ int hfw = heightForWidth(s.width());
+ if (hfw < s.height())
+ s.setHeight(qMin(hfw, ms.height()));
+ }
+
+ s = s.boundedTo(r.size());
+ int x = r.x();
+ int y = r.y();
+
+ if (a & Qt::AlignBottom)
+ y += (r.height() - s.height());
+ else if (!(a & Qt::AlignTop))
+ y += (r.height() - s.height()) / 2;
+
+ QWidget *parent = parentWidget();
+ a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QApplication::layoutDirection(), a);
+ if (a & Qt::AlignRight)
+ x += (r.width() - s.width());
+ else if (!(a & Qt::AlignLeft))
+ x += (r.width() - s.width()) / 2;
+
+ return QRect(x, y, s.width(), s.height());
+}
+
+/*!
+ Removes the widget \a widget from the layout. After this call, it
+ is the caller's responsibility to give the widget a reasonable
+ geometry or to put the widget back into a layout.
+
+ \bold{Note:} The ownership of \a widget remains the same as
+ when it was added.
+
+ \sa removeItem(), QWidget::setGeometry(), addWidget()
+*/
+void QLayout::removeWidget(QWidget *widget)
+{
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = itemAt(i))) {
+ if (child->widget() == widget) {
+ delete takeAt(i);
+ invalidate();
+ } else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ Removes the layout item \a item from the layout. It is the
+ caller's responsibility to delete the item.
+
+ Notice that \a item can be a layout (since QLayout inherits
+ QLayoutItem).
+
+ \sa removeWidget(), addItem()
+*/
+void QLayout::removeItem(QLayoutItem *item)
+{
+ int i = 0;
+ QLayoutItem *child;
+ while ((child = itemAt(i))) {
+ if (child == item) {
+ takeAt(i);
+ invalidate();
+ } else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ Enables this layout if \a enable is true, otherwise disables it.
+
+ An enabled layout adjusts dynamically to changes; a disabled
+ layout acts as if it did not exist.
+
+ By default all layouts are enabled.
+
+ \sa isEnabled()
+*/
+void QLayout::setEnabled(bool enable)
+{
+ Q_D(QLayout);
+ d->enabled = enable;
+}
+
+/*!
+ Returns true if the layout is enabled; otherwise returns false.
+
+ \sa setEnabled()
+*/
+bool QLayout::isEnabled() const
+{
+ Q_D(const QLayout);
+ return d->enabled;
+}
+
+/*!
+ Returns a size that satisfies all size constraints on \a widget,
+ including heightForWidth() and that is as close as possible to \a
+ size.
+*/
+
+QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size)
+{
+ QSize result = size.boundedTo(qSmartMaxSize(widget));
+ result = result.expandedTo(qSmartMinSize(widget));
+ QLayout *l = widget->layout();
+ if (l && l->hasHeightForWidth() && result.height() < l->minimumHeightForWidth(result.width()) ) {
+ QSize current = widget->size();
+ int currentHfw = l->minimumHeightForWidth(current.width());
+ int newHfw = l->minimumHeightForWidth(result.width());
+ if (current.height() < currentHfw || currentHfw == newHfw) {
+ //handle the constant hfw case and the vertical-only case, as well as the
+ // current-size-is-not-correct case
+ result.setHeight(newHfw);
+ } else {
+ // binary search; assume hfw is decreasing ###
+
+ int maxw = qMax(widget->width(),result.width());
+ int maxh = qMax(widget->height(), result.height());
+ int minw = qMin(widget->width(),result.width());
+ int minh = qMin(widget->height(), result.height());
+
+ int minhfw = l->minimumHeightForWidth(minw);
+ int maxhfw = l->minimumHeightForWidth(maxw);
+ while (minw < maxw) {
+ if (minhfw > maxh) { //assume decreasing
+ minw = maxw - (maxw-minw)/2;
+ minhfw = l->minimumHeightForWidth(minw);
+ } else if (maxhfw < minh ) { //assume decreasing
+ maxw = minw + (maxw-minw)/2;
+ maxhfw = l->minimumHeightForWidth(maxw);
+ } else {
+ break;
+ }
+ }
+ result = result.expandedTo(QSize(minw, minhfw));
+ }
+ }
+ return result;
+}
+
+/*!
+ \fn void QLayout::setResizeMode(SizeConstraint constraint)
+
+ Use setSizeConstraint(\a constraint) instead.
+*/
+
+/*!
+ \fn QLayout::SizeConstraint QLayout::resizeMode() const
+
+ Use sizeConstraint() instead.
+*/
+
+void QSizePolicy::setControlType(ControlType type)
+{
+ /*
+ The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
+ etc. In memory, we pack it onto the available bits (CTSize) in
+ setControlType(), and unpack it here.
+
+ Example:
+
+ 0x00000001 maps to 0x00000000
+ 0x00000002 maps to 0x00000200
+ 0x00000004 maps to 0x00000400
+ 0x00000008 maps to 0x00000600
+ etc.
+ */
+
+ int i = 0;
+ while (true) {
+ if (type & (0x1 << i)) {
+ data = (data & ~CTMask) | (i << CTShift);
+ return;
+ }
+ ++i;
+ }
+}
+
+QSizePolicy::ControlType QSizePolicy::controlType() const
+{
+ return QSizePolicy::ControlType(0x1 << ((data & CTMask) >> CTShift));
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QSizePolicy
+ \since 4.2
+
+ Writes the size \a policy to the data stream \a stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
+{
+ return stream << policy.data;
+}
+
+/*!
+ \relates QSizePolicy
+ \since 4.2
+
+ Reads the size \a policy from the data stream \a stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
+{
+ return stream >> policy.data;
+}
+
+#endif
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qlayout.h b/src/gui/kernel/qlayout.h
new file mode 100644
index 0000000000..a68a96c214
--- /dev/null
+++ b/src/gui/kernel/qlayout.h
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUT_H
+#define QLAYOUT_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qlayoutitem.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtCore/qrect.h>
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QLayout;
+class QSize;
+
+#ifdef QT3_SUPPORT
+class Q_GUI_EXPORT QLayoutIterator
+{
+public:
+ inline QT3_SUPPORT_CONSTRUCTOR QLayoutIterator(QLayout *i) : layout(i), index(0) {}
+ inline QLayoutIterator(const QLayoutIterator &i)
+ : layout(i.layout), index(i.index) {}
+ inline QLayoutIterator &operator=(const QLayoutIterator &i) {
+ layout = i.layout;
+ index = i.index;
+ return *this;
+ }
+ inline QT3_SUPPORT QLayoutItem *operator++();
+ inline QT3_SUPPORT QLayoutItem *current();
+ inline QT3_SUPPORT QLayoutItem *takeCurrent();
+ inline QT3_SUPPORT void deleteCurrent();
+
+private:
+ // hack to avoid deprecated warning
+ friend class QLayout;
+ inline QLayoutIterator(QLayout *i, bool) : layout(i), index(0) {}
+ QLayout *layout;
+ int index;
+};
+#endif
+
+class QLayoutPrivate;
+
+class Q_GUI_EXPORT QLayout : public QObject, public QLayoutItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QLayout)
+
+ Q_ENUMS(SizeConstraint)
+ Q_PROPERTY(int margin READ margin WRITE setMargin)
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(SizeConstraint sizeConstraint READ sizeConstraint WRITE setSizeConstraint)
+public:
+ enum SizeConstraint {
+ SetDefaultConstraint,
+ SetNoConstraint,
+ SetMinimumSize,
+ SetFixedSize,
+ SetMaximumSize,
+ SetMinAndMaxSize
+#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN)
+ , Auto = SetDefaultConstraint,
+ FreeResize = SetNoConstraint,
+ Minimum = SetMinimumSize,
+ Fixed = SetFixedSize
+#endif
+ };
+
+ QLayout(QWidget *parent);
+ QLayout();
+ ~QLayout();
+
+ int margin() const;
+ int spacing() const;
+
+ void setMargin(int);
+ void setSpacing(int);
+
+ void setContentsMargins(int left, int top, int right, int bottom);
+ void getContentsMargins(int *left, int *top, int *right, int *bottom) const;
+ QRect contentsRect() const;
+
+ bool setAlignment(QWidget *w, Qt::Alignment alignment);
+ bool setAlignment(QLayout *l, Qt::Alignment alignment);
+#ifdef Q_NO_USING_KEYWORD
+ inline void setAlignment(Qt::Alignment alignment) { QLayoutItem::setAlignment(alignment); }
+#else
+ using QLayoutItem::setAlignment;
+#endif
+
+ void setSizeConstraint(SizeConstraint);
+ SizeConstraint sizeConstraint() const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT void setResizeMode(SizeConstraint s) {setSizeConstraint(s);}
+ inline QT3_SUPPORT SizeConstraint resizeMode() const {return sizeConstraint();}
+#endif
+ void setMenuBar(QWidget *w);
+ QWidget *menuBar() const;
+
+ QWidget *parentWidget() const;
+
+ void invalidate();
+ QRect geometry() const;
+ bool activate();
+ void update();
+
+ void addWidget(QWidget *w);
+ virtual void addItem(QLayoutItem *) = 0;
+
+ void removeWidget(QWidget *w);
+ void removeItem(QLayoutItem *);
+
+ Qt::Orientations expandingDirections() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ virtual void setGeometry(const QRect&);
+ virtual QLayoutItem *itemAt(int index) const = 0;
+ virtual QLayoutItem *takeAt(int index) = 0;
+ virtual int indexOf(QWidget *) const;
+ virtual int count() const = 0;
+ bool isEmpty() const;
+
+ int totalHeightForWidth(int w) const;
+ QSize totalMinimumSize() const;
+ QSize totalMaximumSize() const;
+ QSize totalSizeHint() const;
+ QLayout *layout();
+
+ void setEnabled(bool);
+ bool isEnabled() const;
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT void freeze(int w=0, int h=0);
+ QT3_SUPPORT bool isTopLevel() const;
+#endif
+
+ static QSize closestAcceptableSize(const QWidget *w, const QSize &s);
+
+protected:
+ void widgetEvent(QEvent *);
+ void childEvent(QChildEvent *e);
+ void addChildLayout(QLayout *l);
+ void addChildWidget(QWidget *w);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT void deleteAllItems();
+#endif
+
+ QRect alignmentRect(const QRect&) const;
+protected:
+ QLayout(QLayoutPrivate &d, QLayout*, QWidget*);
+
+private:
+ Q_DISABLE_COPY(QLayout)
+
+ static void activateRecursiveHelper(QLayoutItem *item);
+
+ friend class QApplicationPrivate;
+ friend class QWidget;
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QLayout(QWidget *parent, int margin, int spacing = -1,
+ const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QLayout(QLayout *parentLayout, int spacing = -1, const char *name = 0);
+ QT3_SUPPORT_CONSTRUCTOR QLayout(int spacing, const char *name = 0);
+ inline QT3_SUPPORT QWidget *mainWidget() const { return parentWidget(); }
+ inline QT3_SUPPORT void remove(QWidget *w) { removeWidget(w); }
+ inline QT3_SUPPORT void add(QWidget *w) { addWidget(w); }
+
+ QT3_SUPPORT void setAutoAdd(bool a);
+ QT3_SUPPORT bool autoAdd() const;
+ inline QT3_SUPPORT QLayoutIterator iterator() { return QLayoutIterator(this,true); }
+
+ inline QT3_SUPPORT int defaultBorder() const { return spacing(); }
+#endif
+};
+
+#ifdef QT3_SUPPORT
+inline QLayoutItem *QLayoutIterator::operator++() { return layout->itemAt(++index); }
+inline QLayoutItem *QLayoutIterator::current() { return layout->itemAt(index); }
+inline QLayoutItem *QLayoutIterator::takeCurrent() { return layout->takeAt(index); }
+inline void QLayoutIterator::deleteCurrent() { delete layout->takeAt(index); }
+#endif
+
+//### support old includes
+#if 1 //def QT3_SUPPORT
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qgridlayout.h>
+QT_END_INCLUDE_NAMESPACE
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLAYOUT_H
diff --git a/src/gui/kernel/qlayout_p.h b/src/gui/kernel/qlayout_p.h
new file mode 100644
index 0000000000..5c2546da16
--- /dev/null
+++ b/src/gui/kernel/qlayout_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUT_P_H
+#define QLAYOUT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qlayout*.cpp, and qabstractlayout.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+#include "qstyle.h"
+#include "qsizepolicy.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidgetItem;
+class QSpacerItem;
+
+class Q_GUI_EXPORT QLayoutPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QLayout)
+
+public:
+ typedef QWidgetItem * (*QWidgetItemFactoryMethod)(const QLayout *layout, QWidget *widget);
+ typedef QSpacerItem * (*QSpacerItemFactoryMethod)(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy);
+
+ QLayoutPrivate();
+
+ void getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const;
+ void doResize(const QSize &);
+ void reparentChildWidgets(QWidget *mw);
+
+ static QWidgetItem *createWidgetItem(const QLayout *layout, QWidget *widget);
+ static QSpacerItem *createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum, QSizePolicy::Policy vPolicy = QSizePolicy::Minimum);
+
+ static QWidgetItemFactoryMethod widgetItemFactoryMethod;
+ static QSpacerItemFactoryMethod spacerItemFactoryMethod;
+
+ int insideSpacing;
+ int userLeftMargin;
+ int userTopMargin;
+ int userRightMargin;
+ int userBottomMargin;
+ uint topLevel : 1;
+ uint enabled : 1;
+ uint activated : 1;
+ uint autoNewChild : 1;
+ QLayout::SizeConstraint constraint;
+ QRect rect;
+ QWidget *menubar;
+};
+
+QT_END_NAMESPACE
+
+#endif // QLAYOUT_P_H
diff --git a/src/gui/kernel/qlayoutengine.cpp b/src/gui/kernel/qlayoutengine.cpp
new file mode 100644
index 0000000000..fbaa388bf7
--- /dev/null
+++ b/src/gui/kernel/qlayoutengine.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+#include "private/qlayoutengine_p.h"
+
+#include "qvector.h"
+#include "qwidget.h"
+
+#include <qlist.h>
+#include <qalgorithms.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define QLAYOUT_EXTRA_DEBUG
+
+typedef qint64 Fixed64;
+static inline Fixed64 toFixed(int i) { return (Fixed64)i * 256; }
+static inline int fRound(Fixed64 i) {
+ return (i % 256 < 128) ? i / 256 : 1 + i / 256;
+}
+
+/*
+ This is the main workhorse of the QGridLayout. It portions out
+ available space to the chain's children.
+
+ The calculation is done in fixed point: "fixed" variables are
+ scaled by a factor of 256.
+
+ If the layout runs "backwards" (i.e. RightToLeft or Up) the layout
+ is computed mirror-reversed, and it's the caller's responsibility
+ do reverse the values before use.
+
+ chain contains input and output parameters describing the geometry.
+ count is the count of items in the chain; pos and space give the
+ interval (relative to parentWidget topLeft).
+*/
+void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count,
+ int pos, int space, int spacer)
+{
+ int cHint = 0;
+ int cMin = 0;
+ int cMax = 0;
+ int sumStretch = 0;
+ int sumSpacing = 0;
+
+ bool wannaGrow = false; // anyone who really wants to grow?
+ // bool canShrink = false; // anyone who could be persuaded to shrink?
+
+ bool allEmptyNonstretch = true;
+ int pendingSpacing = -1;
+ int spacerCount = 0;
+ int i;
+
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+
+ data->done = false;
+ cHint += data->smartSizeHint();
+ cMin += data->minimumSize;
+ cMax += data->maximumSize;
+ sumStretch += data->stretch;
+ if (!data->empty) {
+ /*
+ Using pendingSpacing, we ensure that the spacing for the last
+ (non-empty) item is ignored.
+ */
+ if (pendingSpacing >= 0) {
+ sumSpacing += pendingSpacing;
+ ++spacerCount;
+ }
+ pendingSpacing = data->effectiveSpacer(spacer);
+ }
+ wannaGrow = wannaGrow || data->expansive || data->stretch > 0;
+ allEmptyNonstretch = allEmptyNonstretch && !wannaGrow && data->empty;
+ }
+
+ int extraspace = 0;
+
+ if (space < cMin + sumSpacing) {
+ /*
+ Less space than minimumSize; take from the biggest first
+ */
+
+ int minSize = cMin + sumSpacing;
+
+ // shrink the spacers proportionally
+ if (spacer >= 0) {
+ spacer = minSize > 0 ? spacer * space / minSize : 0;
+ sumSpacing = spacer * spacerCount;
+ }
+
+ QList<int> list;
+
+ for (i = start; i < start + count; i++)
+ list << chain.at(i).minimumSize;
+
+ qSort(list);
+
+ int space_left = space - sumSpacing;
+
+ int sum = 0;
+ int idx = 0;
+ int space_used=0;
+ int current = 0;
+ while (idx < count && space_used < space_left) {
+ current = list.at(idx);
+ space_used = sum + current * (count - idx);
+ sum += current;
+ ++idx;
+ }
+ --idx;
+ int deficit = space_used - space_left;
+
+ int items = count - idx;
+ /*
+ * If we truncate all items to "current", we would get "deficit" too many pixels. Therefore, we have to remove
+ * deficit/items from each item bigger than maxval. The actual value to remove is deficitPerItem + remainder/items
+ * "rest" is the accumulated error from using integer arithmetic.
+ */
+ int deficitPerItem = deficit/items;
+ int remainder = deficit % items;
+ int maxval = current - deficitPerItem;
+
+ int rest = 0;
+ for (i = start; i < start + count; i++) {
+ int maxv = maxval;
+ rest += remainder;
+ if (rest >= items) {
+ maxv--;
+ rest-=items;
+ }
+ QLayoutStruct *data = &chain[i];
+ data->size = qMin(data->minimumSize, maxv);
+ data->done = true;
+ }
+ } else if (space < cHint + sumSpacing) {
+ /*
+ Less space than smartSizeHint(), but more than minimumSize.
+ Currently take space equally from each, as in Qt 2.x.
+ Commented-out lines will give more space to stretchier
+ items.
+ */
+ int n = count;
+ int space_left = space - sumSpacing;
+ int overdraft = cHint - space_left;
+
+ // first give to the fixed ones:
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done
+ && data->minimumSize >= data->smartSizeHint()) {
+ data->size = data->smartSizeHint();
+ data->done = true;
+ space_left -= data->smartSizeHint();
+ // sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ bool finished = n == 0;
+ while (!finished) {
+ finished = true;
+ Fixed64 fp_over = toFixed(overdraft);
+ Fixed64 fp_w = 0;
+
+ for (i = start; i < start+count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->done)
+ continue;
+ // if (sumStretch <= 0)
+ fp_w += fp_over / n;
+ // else
+ // fp_w += (fp_over * data->stretch) / sumStretch;
+ int w = fRound(fp_w);
+ data->size = data->smartSizeHint() - w;
+ fp_w -= toFixed(w); // give the difference to the next
+ if (data->size < data->minimumSize) {
+ data->done = true;
+ data->size = data->minimumSize;
+ finished = false;
+ overdraft -= data->smartSizeHint() - data->minimumSize;
+ // sumStretch -= data->stretch;
+ n--;
+ break;
+ }
+ }
+ }
+ } else { // extra space
+ int n = count;
+ int space_left = space - sumSpacing;
+ // first give to the fixed ones, and handle non-expansiveness
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done
+ && (data->maximumSize <= data->smartSizeHint()
+ || (wannaGrow && !data->expansive && data->stretch == 0)
+ || (!allEmptyNonstretch && data->empty &&
+ !data->expansive && data->stretch == 0))) {
+ data->size = data->smartSizeHint();
+ data->done = true;
+ space_left -= data->size;
+ sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ extraspace = space_left;
+
+ /*
+ Do a trial distribution and calculate how much it is off.
+ If there are more deficit pixels than surplus pixels, give
+ the minimum size items what they need, and repeat.
+ Otherwise give to the maximum size items, and repeat.
+
+ Paul Olav Tvete has a wonderful mathematical proof of the
+ correctness of this principle, but unfortunately this
+ comment is too small to contain it.
+ */
+ int surplus, deficit;
+ do {
+ surplus = deficit = 0;
+ Fixed64 fp_space = toFixed(space_left);
+ Fixed64 fp_w = 0;
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (data->done)
+ continue;
+ extraspace = 0;
+ if (sumStretch <= 0)
+ fp_w += fp_space / n;
+ else
+ fp_w += (fp_space * data->stretch) / sumStretch;
+ int w = fRound(fp_w);
+ data->size = w;
+ fp_w -= toFixed(w); // give the difference to the next
+ if (w < data->smartSizeHint()) {
+ deficit += data->smartSizeHint() - w;
+ } else if (w > data->maximumSize) {
+ surplus += w - data->maximumSize;
+ }
+ }
+ if (deficit > 0 && surplus <= deficit) {
+ // give to the ones that have too little
+ for (i = start; i < start+count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done && data->size < data->smartSizeHint()) {
+ data->size = data->smartSizeHint();
+ data->done = true;
+ space_left -= data->smartSizeHint();
+ sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ }
+ if (surplus > 0 && surplus >= deficit) {
+ // take from the ones that have too much
+ for (i = start; i < start + count; i++) {
+ QLayoutStruct *data = &chain[i];
+ if (!data->done && data->size > data->maximumSize) {
+ data->size = data->maximumSize;
+ data->done = true;
+ space_left -= data->maximumSize;
+ sumStretch -= data->stretch;
+ n--;
+ }
+ }
+ }
+ } while (n > 0 && surplus != deficit);
+ if (n == 0)
+ extraspace = space_left;
+ }
+
+ /*
+ As a last resort, we distribute the unwanted space equally
+ among the spacers (counting the start and end of the chain). We
+ could, but don't, attempt a sub-pixel allocation of the extra
+ space.
+ */
+ int extra = extraspace / (spacerCount + 2);
+ int p = pos + extra;
+ for (i = start; i < start+count; i++) {
+ QLayoutStruct *data = &chain[i];
+ data->pos = p;
+ p += data->size;
+ if (!data->empty)
+ p += data->effectiveSpacer(spacer) + extra;
+ }
+
+#ifdef QLAYOUT_EXTRA_DEBUG
+ qDebug() << "qGeomCalc" << "start" << start << "count" << count << "pos" << pos
+ << "space" << space << "spacer" << spacer;
+ for (i = start; i < start + count; ++i) {
+ qDebug() << i << ":" << chain[i].minimumSize << chain[i].smartSizeHint()
+ << chain[i].maximumSize << "stretch" << chain[i].stretch
+ << "empty" << chain[i].empty << "expansive" << chain[i].expansive
+ << "spacing" << chain[i].spacing;
+ qDebug() << "result pos" << chain[i].pos << "size" << chain[i].size;
+ }
+#endif
+}
+
+Q_GUI_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy)
+{
+ QSize s(0, 0);
+
+ if (sizePolicy.horizontalPolicy() != QSizePolicy::Ignored) {
+ if (sizePolicy.horizontalPolicy() & QSizePolicy::ShrinkFlag)
+ s.setWidth(minSizeHint.width());
+ else
+ s.setWidth(qMax(sizeHint.width(), minSizeHint.width()));
+ }
+
+ if (sizePolicy.verticalPolicy() != QSizePolicy::Ignored) {
+ if (sizePolicy.verticalPolicy() & QSizePolicy::ShrinkFlag) {
+ s.setHeight(minSizeHint.height());
+ } else {
+ s.setHeight(qMax(sizeHint.height(), minSizeHint.height()));
+ }
+ }
+
+ s = s.boundedTo(maxSize);
+ if (minSize.width() > 0)
+ s.setWidth(minSize.width());
+ if (minSize.height() > 0)
+ s.setHeight(minSize.height());
+
+ return s.expandedTo(QSize(0,0));
+}
+
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidgetItem *i)
+{
+ QWidget *w = ((QWidgetItem *)i)->widget();
+ return qSmartMinSize(w->sizeHint(), w->minimumSizeHint(),
+ w->minimumSize(), w->maximumSize(),
+ w->sizePolicy());
+}
+
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidget *w)
+{
+ return qSmartMinSize(w->sizeHint(), w->minimumSizeHint(),
+ w->minimumSize(), w->maximumSize(),
+ w->sizePolicy());
+}
+
+Q_GUI_EXPORT QSize qSmartMaxSize(const QSize &sizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy, Qt::Alignment align)
+{
+ if (align & Qt::AlignHorizontal_Mask && align & Qt::AlignVertical_Mask)
+ return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
+ QSize s = maxSize;
+ QSize hint = sizeHint.expandedTo(minSize);
+ if (s.width() == QWIDGETSIZE_MAX && !(align & Qt::AlignHorizontal_Mask))
+ if (!(sizePolicy.horizontalPolicy() & QSizePolicy::GrowFlag))
+ s.setWidth(hint.width());
+
+ if (s.height() == QWIDGETSIZE_MAX && !(align & Qt::AlignVertical_Mask))
+ if (!(sizePolicy.verticalPolicy() & QSizePolicy::GrowFlag))
+ s.setHeight(hint.height());
+
+ if (align & Qt::AlignHorizontal_Mask)
+ s.setWidth(QLAYOUTSIZE_MAX);
+ if (align & Qt::AlignVertical_Mask)
+ s.setHeight(QLAYOUTSIZE_MAX);
+ return s;
+}
+
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align)
+{
+ QWidget *w = ((QWidgetItem*)i)->widget();
+
+ return qSmartMaxSize(w->sizeHint().expandedTo(w->minimumSizeHint()), w->minimumSize(), w->maximumSize(),
+ w->sizePolicy(), align);
+}
+
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align)
+{
+ return qSmartMaxSize(w->sizeHint().expandedTo(w->minimumSizeHint()), w->minimumSize(), w->maximumSize(),
+ w->sizePolicy(), align);
+}
+
+Q_GUI_EXPORT int qSmartSpacing(const QLayout *layout, QStyle::PixelMetric pm)
+{
+ QObject *parent = layout->parent();
+ if (!parent) {
+ return -1;
+ } else if (parent->isWidgetType()) {
+ QWidget *pw = static_cast<QWidget *>(parent);
+ return pw->style()->pixelMetric(pm, 0, pw);
+ } else {
+ return static_cast<QLayout *>(parent)->spacing();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qlayoutengine_p.h b/src/gui/kernel/qlayoutengine_p.h
new file mode 100644
index 0000000000..4a6b8bd865
--- /dev/null
+++ b/src/gui/kernel/qlayoutengine_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUTENGINE_P_H
+#define QLAYOUTENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qlayoutitem.h"
+#include "QtGui/qstyle.h"
+
+QT_BEGIN_NAMESPACE
+
+template <typename T> class QVector;
+
+struct QLayoutStruct
+{
+ inline void init(int stretchFactor = 0, int minSize = 0) {
+ stretch = stretchFactor;
+ minimumSize = sizeHint = minSize;
+ maximumSize = QLAYOUTSIZE_MAX;
+ expansive = false;
+ empty = true;
+ spacing = 0;
+ }
+
+ int smartSizeHint() {
+ return (stretch > 0) ? minimumSize : sizeHint;
+ }
+ int effectiveSpacer(int uniformSpacer) const {
+ Q_ASSERT(uniformSpacer >= 0 || spacing >= 0);
+ return (uniformSpacer >= 0) ? uniformSpacer : spacing;
+ }
+
+ // parameters
+ int stretch;
+ int sizeHint;
+ int maximumSize;
+ int minimumSize;
+ bool expansive;
+ bool empty;
+ int spacing;
+
+ // temporary storage
+ bool done;
+
+ // result
+ int pos;
+ int size;
+};
+
+
+Q_GUI_EXPORT void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count,
+ int pos, int space, int spacer = -1);
+Q_GUI_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy);
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidgetItem *i);
+Q_GUI_EXPORT QSize qSmartMinSize(const QWidget *w);
+Q_GUI_EXPORT QSize qSmartMaxSize(const QSize &sizeHint,
+ const QSize &minSize, const QSize &maxSize,
+ const QSizePolicy &sizePolicy, Qt::Alignment align = 0);
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align = 0);
+Q_GUI_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align = 0);
+
+Q_GUI_EXPORT int qSmartSpacing(const QLayout *layout, QStyle::PixelMetric pm);
+
+/*
+ Modify total maximum (max), total expansion (exp), and total empty
+ when adding boxmax/boxexp.
+
+ Expansive boxes win over non-expansive boxes.
+ Non-empty boxes win over empty boxes.
+*/
+static inline void qMaxExpCalc(int & max, bool &exp, bool &empty,
+ int boxmax, bool boxexp, bool boxempty)
+{
+ if (exp) {
+ if (boxexp)
+ max = qMax(max, boxmax);
+ } else {
+ if (boxexp || (empty && (!boxempty || max == 0)))
+ max = boxmax;
+ else if (empty == boxempty)
+ max = qMin(max, boxmax);
+ }
+ exp = exp || boxexp;
+ empty = empty && boxempty;
+}
+
+QT_END_NAMESPACE
+
+#endif // QLAYOUTENGINE_P_H
diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp
new file mode 100644
index 0000000000..0fd73b8f88
--- /dev/null
+++ b/src/gui/kernel/qlayoutitem.cpp
@@ -0,0 +1,837 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+
+#include "qapplication.h"
+#include "qlayoutengine_p.h"
+#include "qmenubar.h"
+#include "qtoolbar.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qvariant.h"
+#include "qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
+{
+ return priv->fromOrToLayoutItemRect(rect, -1);
+}
+
+inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
+{
+ return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
+}
+
+inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
+{
+ return priv->fromOrToLayoutItemRect(rect, +1);
+}
+
+inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
+{
+ return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
+}
+
+/*!
+ Returns a QVariant storing this QSizePolicy.
+*/
+QSizePolicy::operator QVariant() const
+{
+ return QVariant(QVariant::SizePolicy, this);
+}
+
+/*!
+ \class QLayoutItem
+ \brief The QLayoutItem class provides an abstract item that a
+ QLayout manipulates.
+
+ \ingroup appearance
+ \ingroup geomanagement
+
+ This is used by custom layouts.
+
+ Pure virtual functions are provided to return information about
+ the layout, including, sizeHint(), minimumSize(), maximumSize()
+ and expanding().
+
+ The layout's geometry can be set and retrieved with setGeometry()
+ and geometry(), and its alignment with setAlignment() and
+ alignment().
+
+ isEmpty() returns whether the layout item is empty. If the
+ concrete item is a QWidget, it can be retrieved using widget().
+ Similarly for layout() and spacerItem().
+
+ Some layouts have width and height interdependencies. These can
+ be expressed using hasHeightForWidth(), heightForWidth(), and
+ minimumHeightForWidth(). For more explanation see the \e{Qt
+ Quarterly} article
+ \l{http://doc.trolltech.com/qq/qq04-height-for-width.html}{Trading
+ Height for Width}.
+
+ \sa QLayout
+*/
+
+/*!
+ \class QSpacerItem
+ \ingroup appearance
+ \ingroup geomanagement
+ \brief The QSpacerItem class provides blank space in a layout.
+
+ Normally, you don't need to use this class directly. Qt's
+ built-in layout managers provide the following functions for
+ manipulating empty space in layouts:
+
+ \table
+ \header \o Class
+ \o Functions
+ \row \o QHBoxLayout
+ \o \l{QBoxLayout::addSpacing()}{addSpacing()},
+ \l{QBoxLayout::addStretch()}{addStretch()},
+ \l{QBoxLayout::insertSpacing()}{insertSpacing()},
+ \l{QBoxLayout::insertStretch()}{insertStretch()}
+ \row \o QGridLayout
+ \o \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()},
+ \l{QGridLayout::setRowStretch()}{setRowStretch()},
+ \l{QGridLayout::setColumnMinimumWidth()}{setColumnMinimumWidth()},
+ \l{QGridLayout::setColumnStretch()}{setColumnStretch()}
+ \endtable
+
+ \sa QLayout, QWidgetItem, QLayoutItem::spacerItem()
+*/
+
+/*!
+ \class QWidgetItem
+ \ingroup appearance
+ \ingroup geomanagement
+ \brief The QWidgetItem class is a layout item that represents a widget.
+
+ Normally, you don't need to use this class directly. Qt's
+ built-in layout managers provide the following functions for
+ manipulating widgets in layouts:
+
+ \table
+ \header \o Class
+ \o Functions
+ \row \o QBoxLayout
+ \o \l{QBoxLayout::addWidget()}{addWidget()},
+ \l{QBoxLayout::insertWidget()}{insertWidget()},
+ \l{QBoxLayout::setStretchFactor()}{setStretchFactor()}
+ \row \o QGridLayout
+ \o \l{QGridLayout::addWidget()}{addWidget()}
+ \row \o QStackedLayout
+ \o \l{QStackedLayout::addWidget()}{addWidget()},
+ \l{QStackedLayout::insertWidget()}{insertWidget()},
+ \l{QStackedLayout::currentWidget()}{currentWidget()},
+ \l{QStackedLayout::setCurrentWidget()}{setCurrentWidget()},
+ \l{QStackedLayout::widget()}{widget()}
+ \endtable
+
+ \sa QLayout, QSpacerItem, QLayoutItem::widget()
+*/
+
+/*!
+ \fn QLayoutItem::QLayoutItem(Qt::Alignment alignment)
+
+ Constructs a layout item with an \a alignment.
+ Not all subclasses support alignment.
+*/
+
+/*!
+ \fn Qt::Alignment QLayoutItem::alignment() const
+
+ Returns the alignment of this item.
+*/
+
+/*!
+ Sets the alignment of this item to \a alignment.
+
+ \bold{Note:} Item alignment is only supported by QLayoutItem subclasses
+ where it would have a visual effect. Except for QSpacerItem, which provides
+ blank space for layouts, all public Qt classes that inherit QLayoutItem
+ support item alignment.
+*/
+void QLayoutItem::setAlignment(Qt::Alignment alignment)
+{
+ align = alignment;
+}
+
+/*!
+ \fn QSize QLayoutItem::maximumSize() const
+
+ Implemented in subclasses to return the maximum size of this item.
+*/
+
+/*!
+ \fn QSize QLayoutItem::minimumSize() const
+
+ Implemented in subclasses to return the minimum size of this item.
+*/
+
+/*!
+ \fn QSize QLayoutItem::sizeHint() const
+
+ Implemented in subclasses to return the preferred size of this item.
+*/
+
+/*!
+ \fn Qt::Orientations QLayoutItem::expandingDirections() const
+
+ Returns whether this layout item can make use of more space than
+ sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
+ it wants to grow in only one dimension, whereas Qt::Vertical |
+ Qt::Horizontal means that it wants to grow in both dimensions.
+*/
+
+/*!
+ \fn void QLayoutItem::setGeometry(const QRect &r)
+
+ Implemented in subclasses to set this item's geometry to \a r.
+
+ \sa geometry()
+*/
+
+/*!
+ \fn QRect QLayoutItem::geometry() const
+
+ Returns the rectangle covered by this layout item.
+
+ \sa setGeometry()
+*/
+
+/*!
+ \fn virtual bool QLayoutItem::isEmpty() const
+
+ Implemented in subclasses to return whether this item is empty,
+ i.e. whether it contains any widgets.
+*/
+
+/*!
+ \fn QSpacerItem::QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
+
+ Constructs a spacer item with preferred width \a w, preferred
+ height \a h, horizontal size policy \a hPolicy and vertical size
+ policy \a vPolicy.
+
+ The default values provide a gap that is able to stretch if
+ nothing else wants the space.
+*/
+
+/*!
+ Changes this spacer item to have preferred width \a w, preferred
+ height \a h, horizontal size policy \a hPolicy and vertical size
+ policy \a vPolicy.
+
+ The default values provide a gap that is able to stretch if
+ nothing else wants the space.
+
+ Note that if changeSize() is called after the spacer item has been added
+ to a layout, it is necessary to invalidate the layout in order for the
+ spacer item's new size to take effect.
+
+ \sa QSpacerItem::invalidate()
+*/
+void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
+ QSizePolicy::Policy vPolicy)
+{
+ width = w;
+ height = h;
+ sizeP = QSizePolicy(hPolicy, vPolicy);
+}
+
+/*!
+ \fn QWidgetItem::QWidgetItem(QWidget *widget)
+
+ Creates an item containing the given \a widget.
+*/
+
+/*!
+ Destroys the QLayoutItem.
+*/
+QLayoutItem::~QLayoutItem()
+{
+}
+
+/*!
+ Invalidates any cached information in this layout item.
+*/
+void QLayoutItem::invalidate()
+{
+}
+
+/*!
+ If this item is a QLayout, it is returned as a QLayout; otherwise
+ 0 is returned. This function provides type-safe casting.
+*/
+QLayout * QLayoutItem::layout()
+{
+ return 0;
+}
+
+/*!
+ If this item is a QSpacerItem, it is returned as a QSpacerItem;
+ otherwise 0 is returned. This function provides type-safe casting.
+*/
+QSpacerItem * QLayoutItem::spacerItem()
+{
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayout * QLayout::layout()
+{
+ return this;
+}
+
+/*!
+ Returns a pointer to this object.
+*/
+QSpacerItem * QSpacerItem::spacerItem()
+{
+ return this;
+}
+
+/*!
+ If this item is a QWidget, it is returned as a QWidget; otherwise
+ 0 is returned. This function provides type-safe casting.
+*/
+QWidget * QLayoutItem::widget()
+{
+ return 0;
+}
+
+/*!
+ Returns the widget managed by this item.
+*/
+QWidget *QWidgetItem::widget()
+{
+ return wid;
+}
+
+/*!
+ Returns true if this layout's preferred height depends on its
+ width; otherwise returns false. The default implementation returns
+ false.
+
+ Reimplement this function in layout managers that support height
+ for width.
+
+ \sa heightForWidth(), QWidget::heightForWidth()
+*/
+bool QLayoutItem::hasHeightForWidth() const
+{
+ return false;
+}
+
+/*!
+ Returns the minimum height this widget needs for the given width,
+ \a w. The default implementation simply returns heightForWidth(\a
+ w).
+*/
+int QLayoutItem::minimumHeightForWidth(int w) const
+{
+ return heightForWidth(w);
+}
+
+
+/*!
+ Returns the preferred height for this layout item, given the width
+ \a w.
+
+ The default implementation returns -1, indicating that the
+ preferred height is independent of the width of the item. Using
+ the function hasHeightForWidth() will typically be much faster
+ than calling this function and testing for -1.
+
+ Reimplement this function in layout managers that support height
+ for width. A typical implementation will look like this:
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayoutitem.cpp 0
+
+ Caching is strongly recommended; without it layout will take
+ exponential time.
+
+ \sa hasHeightForWidth()
+*/
+int QLayoutItem::heightForWidth(int /* w */) const
+{
+ return -1;
+}
+
+/*!
+ Returns the control type(s) for the layout item. For a
+ QWidgetItem, the control type comes from the widget's size
+ policy; for a QLayoutItem, the control types is derived from the
+ layout's contents.
+
+ \sa QSizePolicy::controlType()
+*/
+QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
+{
+ // ### Qt 5: This function should probably be virtual instead
+ if (const QWidget *widget = const_cast<QLayoutItem*>(this)->widget()) {
+ return widget->sizePolicy().controlType();
+ } else if (const QLayout *layout = const_cast<QLayoutItem*>(this)->layout()) {
+ if (layout->count() == 0)
+ return QSizePolicy::DefaultType;
+ QSizePolicy::ControlTypes types;
+ for (int i = layout->count() - 1; i >= 0; --i)
+ types |= layout->itemAt(i)->controlTypes();
+ return types;
+ }
+ return QSizePolicy::DefaultType;
+}
+
+/*!
+ \reimp
+*/
+void QSpacerItem::setGeometry(const QRect &r)
+{
+ rect = r;
+}
+
+/*!
+ \reimp
+*/
+void QWidgetItem::setGeometry(const QRect &rect)
+{
+ if (isEmpty())
+ return;
+
+ QRect r = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? fromLayoutItemRect(wid->d_func(), rect)
+ : rect;
+ const QSize widgetRectSurplus = r.size() - rect.size();
+
+ /*
+ For historical reasons, this code is done using widget rect
+ coordinates, not layout item rect coordinates. However,
+ QWidgetItem's sizeHint(), maximumSize(), and heightForWidth()
+ all work in terms of layout item rect coordinates, so we have to
+ add or subtract widgetRectSurplus here and there. The code could
+ be much simpler if we did everything using layout item rect
+ coordinates and did the conversion right before the call to
+ QWidget::setGeometry().
+ */
+
+ QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);
+ int x = r.x();
+ int y = r.y();
+ if (align & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)) {
+ QSize pref(sizeHint());
+ QSizePolicy sp = wid->sizePolicy();
+ if (sp.horizontalPolicy() == QSizePolicy::Ignored)
+ pref.setWidth(wid->sizeHint().expandedTo(wid->minimumSize()).width());
+ if (sp.verticalPolicy() == QSizePolicy::Ignored)
+ pref.setHeight(wid->sizeHint().expandedTo(wid->minimumSize()).height());
+ pref += widgetRectSurplus;
+ if (align & Qt::AlignHorizontal_Mask)
+ s.setWidth(qMin(s.width(), pref.width()));
+ if (align & Qt::AlignVertical_Mask) {
+ if (hasHeightForWidth())
+ s.setHeight(qMin(s.height(),
+ heightForWidth(s.width() - widgetRectSurplus.width())
+ + widgetRectSurplus.height()));
+ else
+ s.setHeight(qMin(s.height(), pref.height()));
+ }
+ }
+ Qt::Alignment alignHoriz = QStyle::visualAlignment(wid->layoutDirection(), align);
+ if (alignHoriz & Qt::AlignRight)
+ x = x + (r.width() - s.width());
+ else if (!(alignHoriz & Qt::AlignLeft))
+ x = x + (r.width() - s.width()) / 2;
+
+ if (align & Qt::AlignBottom)
+ y = y + (r.height() - s.height());
+ else if (!(align & Qt::AlignTop))
+ y = y + (r.height() - s.height()) / 2;
+
+ wid->setGeometry(x, y, s.width(), s.height());
+}
+
+/*!
+ \reimp
+*/
+QRect QSpacerItem::geometry() const
+{
+ return rect;
+}
+
+/*!
+ \reimp
+*/
+QRect QWidgetItem::geometry() const
+{
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemRect(wid->d_func(), wid->geometry())
+ : wid->geometry();
+}
+
+
+/*!
+ \reimp
+*/
+bool QWidgetItem::hasHeightForWidth() const
+{
+ if (isEmpty())
+ return false;
+ if (wid->layout())
+ return wid->layout()->hasHeightForWidth();
+ return wid->sizePolicy().hasHeightForWidth();
+}
+
+/*!
+ \reimp
+*/
+int QWidgetItem::heightForWidth(int w) const
+{
+ if (isEmpty())
+ return -1;
+
+ w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
+ : w;
+
+ int hfw;
+ if (wid->layout())
+ hfw = wid->layout()->totalHeightForWidth(w);
+ else
+ hfw = wid->heightForWidth(w);
+
+ if (hfw > wid->maximumHeight())
+ hfw = wid->maximumHeight();
+ if (hfw < wid->minimumHeight())
+ hfw = wid->minimumHeight();
+
+ hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
+ : hfw;
+
+ if (hfw < 0)
+ hfw = 0;
+ return hfw;
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QSpacerItem::expandingDirections() const
+{
+ return sizeP.expandingDirections();
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QWidgetItem::expandingDirections() const
+{
+ if (isEmpty())
+ return Qt::Orientations(0);
+
+ Qt::Orientations e = wid->sizePolicy().expandingDirections();
+ /*
+ ### Qt 4.0:
+ If the layout is expanding, we make the widget expanding, even if
+ its own size policy isn't expanding. This behavior should be
+ reconsidered.
+ */
+ if (wid->layout()) {
+ if (wid->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag
+ && (wid->layout()->expandingDirections() & Qt::Horizontal))
+ e |= Qt::Horizontal;
+ if (wid->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag
+ && (wid->layout()->expandingDirections() & Qt::Vertical))
+ e |= Qt::Vertical;
+ }
+
+ if (align & Qt::AlignHorizontal_Mask)
+ e &= ~Qt::Horizontal;
+ if (align & Qt::AlignVertical_Mask)
+ e &= ~Qt::Vertical;
+ return e;
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::minimumSize() const
+{
+ return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
+ sizeP.verticalPolicy() & QSizePolicy::ShrinkFlag ? 0 : height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::minimumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
+ : qSmartMinSize(this);
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::maximumSize() const
+{
+ return QSize(sizeP.horizontalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : width,
+ sizeP.verticalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::maximumSize() const
+{
+ if (isEmpty()) {
+ return QSize(0, 0);
+ } else {
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
+ : qSmartMaxSize(this, align);
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::sizeHint() const
+{
+ return QSize(width, height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::sizeHint() const
+{
+ QSize s(0, 0);
+ if (!isEmpty()) {
+ s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
+ s = s.boundedTo(wid->maximumSize())
+ .expandedTo(wid->minimumSize());
+ s = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), s)
+ : s;
+
+ if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ s.setWidth(0);
+ if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ s.setHeight(0);
+ }
+ return s;
+}
+
+/*!
+ Returns true.
+*/
+bool QSpacerItem::isEmpty() const
+{
+ return true;
+}
+
+/*!
+ Returns true if the widget is hidden; otherwise returns false.
+
+ \sa QWidget::isHidden()
+*/
+bool QWidgetItem::isEmpty() const
+{
+ return wid->isHidden() || wid->isWindow();
+}
+
+/*!
+ \class QWidgetItemV2
+ \internal
+*/
+
+inline bool QWidgetItemV2::useSizeCache() const
+{
+ return wid->d_func()->widgetItem == this;
+}
+
+void QWidgetItemV2::updateCacheIfNecessary() const
+{
+ if (q_cachedMinimumSize.width() != Dirty)
+ return;
+
+ const QSize sizeHint(wid->sizeHint());
+ const QSize minimumSizeHint(wid->minimumSizeHint());
+ const QSize minimumSize(wid->minimumSize());
+ const QSize maximumSize(wid->maximumSize());
+ const QSizePolicy sizePolicy(wid->sizePolicy());
+ const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
+
+ const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
+ const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
+
+ const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+ q_cachedMinimumSize = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), smartMinSize)
+ : smartMinSize;
+
+ q_cachedSizeHint = expandedSizeHint;
+ q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
+ .expandedTo(minimumSize);
+ q_cachedSizeHint = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
+ : q_cachedSizeHint;
+
+ if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ q_cachedSizeHint.setWidth(0);
+ if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ q_cachedSizeHint.setHeight(0);
+
+ q_cachedMaximumSize = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), smartMaxSize)
+ : smartMaxSize;
+}
+
+QWidgetItemV2::QWidgetItemV2(QWidget *widget)
+ : QWidgetItem(widget),
+ q_cachedMinimumSize(Dirty, Dirty),
+ q_cachedSizeHint(Dirty, Dirty),
+ q_cachedMaximumSize(Dirty, Dirty),
+ q_firstCachedHfw(0),
+ q_hfwCacheSize(0),
+ d(0)
+{
+ QWidgetPrivate *wd = wid->d_func();
+ if (!wd->widgetItem)
+ wd->widgetItem = this;
+}
+
+QWidgetItemV2::~QWidgetItemV2()
+{
+ if (wid) {
+ QWidgetPrivate *wd = wid->d_func();
+ if (wd->widgetItem == this)
+ wd->widgetItem = 0;
+ }
+}
+
+QSize QWidgetItemV2::sizeHint() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedSizeHint;
+ } else {
+ return QWidgetItem::sizeHint();
+ }
+}
+
+QSize QWidgetItemV2::minimumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedMinimumSize;
+ } else {
+ return QWidgetItem::minimumSize();
+ }
+}
+
+QSize QWidgetItemV2::maximumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedMaximumSize;
+ } else {
+ return QWidgetItem::maximumSize();
+ }
+}
+
+/*
+ The height-for-width cache is organized as a circular buffer. The entries
+
+ q_hfwCachedHfws[q_firstCachedHfw],
+ ...,
+ q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
+
+ contain the last cached values. When the cache is full, the first entry to
+ be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
+ values are looked up, we try to move q_firstCachedHfw to point to that new
+ entry (unless the cache is not full, in which case it would leave the cache
+ in a broken state), so that the most recently used entry is also the last
+ to be erased.
+*/
+
+int QWidgetItemV2::heightForWidth(int width) const
+{
+ if (isEmpty())
+ return -1;
+
+ for (int i = 0; i < q_hfwCacheSize; ++i) {
+ int offset = q_firstCachedHfw + i;
+ const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
+ if (size.width() == width) {
+ if (q_hfwCacheSize == HfwCacheMaxSize)
+ q_firstCachedHfw = offset;
+ return size.height();
+ }
+ }
+
+ if (q_hfwCacheSize < HfwCacheMaxSize)
+ ++q_hfwCacheSize;
+ q_firstCachedHfw = (q_firstCachedHfw + HfwCacheMaxSize - 1) % HfwCacheMaxSize;
+
+ int height = QWidgetItem::heightForWidth(width);
+ q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
+ return height;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qlayoutitem.h b/src/gui/kernel/qlayoutitem.h
new file mode 100644
index 0000000000..d913472ab8
--- /dev/null
+++ b/src/gui/kernel/qlayoutitem.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUTITEM_H
+#define QLAYOUTITEM_H
+
+#include <QtGui/qsizepolicy.h>
+#include <QtCore/qrect.h>
+
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+static const int QLAYOUTSIZE_MAX = INT_MAX/256/16;
+
+class QLayout;
+class QLayoutItem;
+class QSpacerItem;
+class QWidget;
+class QSize;
+
+class Q_GUI_EXPORT QLayoutItem
+{
+public:
+ inline explicit QLayoutItem(Qt::Alignment alignment = 0);
+ virtual ~QLayoutItem();
+ virtual QSize sizeHint() const = 0;
+ virtual QSize minimumSize() const = 0;
+ virtual QSize maximumSize() const = 0;
+ virtual Qt::Orientations expandingDirections() const = 0;
+ virtual void setGeometry(const QRect&) = 0;
+ virtual QRect geometry() const = 0;
+ virtual bool isEmpty() const = 0;
+ virtual bool hasHeightForWidth() const;
+ virtual int heightForWidth(int) const;
+ virtual int minimumHeightForWidth(int) const;
+ virtual void invalidate();
+
+ virtual QWidget *widget();
+ virtual QLayout *layout();
+ virtual QSpacerItem *spacerItem();
+
+ Qt::Alignment alignment() const { return align; }
+ void setAlignment(Qt::Alignment a);
+ QSizePolicy::ControlTypes controlTypes() const;
+
+protected:
+ Qt::Alignment align;
+};
+
+inline QLayoutItem::QLayoutItem(Qt::Alignment aalignment)
+ : align(aalignment) { }
+
+class Q_GUI_EXPORT QSpacerItem : public QLayoutItem
+{
+public:
+ QSpacerItem(int w, int h,
+ QSizePolicy::Policy hData = QSizePolicy::Minimum,
+ QSizePolicy::Policy vData = QSizePolicy::Minimum)
+ : width(w), height(h), sizeP(hData, vData) { }
+ void changeSize(int w, int h,
+ QSizePolicy::Policy hData = QSizePolicy::Minimum,
+ QSizePolicy::Policy vData = QSizePolicy::Minimum);
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ Qt::Orientations expandingDirections() const;
+ bool isEmpty() const;
+ void setGeometry(const QRect&);
+ QRect geometry() const;
+ QSpacerItem *spacerItem();
+
+private:
+ int width;
+ int height;
+ QSizePolicy sizeP;
+ QRect rect;
+};
+
+class Q_GUI_EXPORT QWidgetItem : public QLayoutItem
+{
+ Q_DISABLE_COPY(QWidgetItem)
+
+public:
+ explicit QWidgetItem(QWidget *w) : wid(w) { }
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ Qt::Orientations expandingDirections() const;
+ bool isEmpty() const;
+ void setGeometry(const QRect&);
+ QRect geometry() const;
+ virtual QWidget *widget();
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+
+protected:
+ QWidget *wid;
+};
+
+class Q_GUI_EXPORT QWidgetItemV2 : public QWidgetItem
+{
+public:
+ explicit QWidgetItemV2(QWidget *widget);
+ ~QWidgetItemV2();
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ int heightForWidth(int width) const;
+
+private:
+ enum { Dirty = -123, HfwCacheMaxSize = 3 };
+
+ inline bool useSizeCache() const;
+ void updateCacheIfNecessary() const;
+ inline void invalidateSizeCache() {
+ q_cachedMinimumSize.setWidth(Dirty);
+ q_hfwCacheSize = 0;
+ }
+
+ mutable QSize q_cachedMinimumSize;
+ mutable QSize q_cachedSizeHint;
+ mutable QSize q_cachedMaximumSize;
+ mutable QSize q_cachedHfws[HfwCacheMaxSize];
+ mutable short q_firstCachedHfw;
+ mutable short q_hfwCacheSize;
+ void *d;
+
+ friend class QWidgetPrivate;
+
+ Q_DISABLE_COPY(QWidgetItemV2)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLAYOUTITEM_H
diff --git a/src/gui/kernel/qmacdefines_mac.h b/src/gui/kernel/qmacdefines_mac.h
new file mode 100644
index 0000000000..97ec544493
--- /dev/null
+++ b/src/gui/kernel/qmacdefines_mac.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+**
+****************************************************************************/
+
+/*
+ * qmacdefines_mac_p.h
+ * All the defines you'll ever need for Qt/Mac :-)
+ */
+
+/* This is just many defines. Therefore it doesn't need things like:
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+Yes, it is an informative comment ;-)
+*/
+
+#include <QtCore/qglobal.h>
+
+#undef OLD_DEBUG
+#ifdef DEBUG
+# define OLD_DEBUG DEBUG
+# undef DEBUG
+#endif
+#define DEBUG 0
+#ifdef qDebug
+# define old_qDebug qDebug
+# undef qDebug
+#endif
+
+#if __LP64__
+typedef signed int OSStatus;
+#else
+typedef signed long OSStatus;
+#endif
+
+#ifdef __OBJC__
+# ifdef slots
+# define old_slots slots
+# undef slots
+# endif
+#include <Cocoa/Cocoa.h>
+# ifdef old_slots
+# undef slots
+# define slots
+# undef old_slots
+# endif
+#endif
+#ifdef QT_MAC_USE_COCOA
+ typedef struct OpaqueEventHandlerCallRef * EventHandlerCallRef;
+ typedef struct OpaqueEventRef * EventRef;
+ typedef struct OpaqueMenuRef * MenuRef;
+ typedef struct OpaquePasteboardRef* PasteboardRef;
+ typedef struct OpaqueRgnHandle * RgnHandle;
+ typedef const struct __HIShape *HIShapeRef;
+ typedef struct __HIShape *HIMutableShapeRef;
+ typedef struct CGRect CGRect;
+ typedef struct CGImage *CGImageRef;
+ typedef struct CGContext *CGContextRef;
+ typedef struct GDevice * GDPtr;
+ typedef GDPtr * GDHandle;
+ typedef struct OpaqueIconRef * IconRef;
+# ifdef __OBJC__
+ typedef NSWindow* OSWindowRef;
+ typedef NSView *OSViewRef;
+ typedef NSMenu *OSMenuRef;
+ typedef NSEvent *OSEventRef;
+# else
+ typedef void *OSWindowRef;
+ typedef void *OSViewRef;
+ typedef void *OSMenuRef;
+ typedef void *OSEventRef;
+# endif
+#else // Carbon
+ typedef struct OpaqueEventHandlerCallRef * EventHandlerCallRef;
+ typedef struct OpaqueEventRef * EventRef;
+ typedef struct OpaqueMenuRef * MenuRef;
+ typedef struct OpaquePasteboardRef* PasteboardRef;
+ typedef struct OpaqueRgnHandle * RgnHandle;
+ typedef const struct __HIShape *HIShapeRef;
+ typedef struct __HIShape *HIMutableShapeRef;
+ typedef struct CGRect CGRect;
+ typedef struct CGImage *CGImageRef;
+ typedef struct CGContext *CGContextRef;
+ typedef struct GDevice * GDPtr;
+ typedef GDPtr * GDHandle;
+ typedef struct OpaqueIconRef * IconRef;
+ typedef struct OpaqueWindowPtr * WindowRef;
+ typedef struct OpaqueControlRef * HIViewRef;
+ typedef WindowRef OSWindowRef;
+ typedef HIViewRef OSViewRef;
+ typedef MenuRef OSMenuRef;
+ typedef EventRef OSEventRef;
+#endif // QT_MAC_USE_COCOA
+
+typedef PasteboardRef OSPasteboardRef;
+typedef struct AEDesc AEDescList;
+typedef AEDescList AERecord;
+typedef AERecord AppleEvent;
+
+#ifdef check
+#undef check
+#endif
+
+#undef DEBUG
+#ifdef OLD_DEBUG
+# define DEBUG OLD_DEBUG
+# undef OLD_DEBUG
+#endif
+
+#ifdef old_qDebug
+# undef qDebug
+# define qDebug QT_NO_QDEBUG_MACRO
+# undef old_qDebug
+#endif
diff --git a/src/gui/kernel/qmime.cpp b/src/gui/kernel/qmime.cpp
new file mode 100644
index 0000000000..1f071a7a7b
--- /dev/null
+++ b/src/gui/kernel/qmime.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmime.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMimeSource
+ \brief The QMimeSource class is an abstraction of objects that
+ provided formatted data of a certain MIME type.
+
+ \obsolete
+
+ The preferred approach to drag and drop is to use QDrag in
+ conjunction with QMimeData. See \l{Drag and Drop} for details.
+
+ \sa QMimeData, QDrag
+*/
+
+/*!
+ Destroys the MIME source.
+*/
+QMimeSource::~QMimeSource()
+{
+}
+
+/*!
+ \fn const char *QMimeSource::format(int i) const
+
+ Returns the (\a i - 1)-th supported MIME format, or 0.
+*/
+
+/*!
+ \fn QByteArray QMimeSource::encodedData(const char *format) const
+
+ Returns the encoded data of this object in the specified MIME
+ \a format.
+*/
+
+/*!
+ Returns true if the object can provide the data in format \a
+ mimeType; otherwise returns false.
+
+ If you inherit from QMimeSource, for consistency reasons it is
+ better to implement the more abstract canDecode() functions such
+ as QTextDrag::canDecode() and QImageDrag::canDecode().
+*/
+bool QMimeSource::provides(const char* mimeType) const
+{
+ const char* fmt;
+ for (int i=0; (fmt = format(i)); i++) {
+ if (!qstricmp(mimeType,fmt))
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qmime.h b/src/gui/kernel/qmime.h
new file mode 100644
index 0000000000..42347a5282
--- /dev/null
+++ b/src/gui/kernel/qmime.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIME_H
+#define QMIME_H
+
+#include <QtCore/qmimedata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QMimeSource
+{
+public:
+ virtual ~QMimeSource();
+ virtual const char* format(int n = 0) const = 0;
+ virtual bool provides(const char*) const;
+ virtual QByteArray encodedData(const char*) const = 0;
+};
+
+
+#if defined(Q_WS_WIN)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+typedef struct tagFORMATETC FORMATETC;
+typedef struct tagSTGMEDIUM STGMEDIUM;
+struct IDataObject;
+
+#include <QtCore/qvariant.h>
+QT_END_INCLUDE_NAMESPACE
+
+/*
+ Encapsulation of conversion between MIME and Windows CLIPFORMAT.
+ Not need on X11, as the underlying protocol uses the MIME standard
+ directly.
+*/
+
+class Q_GUI_EXPORT QWindowsMime
+{
+public:
+ QWindowsMime();
+ virtual ~QWindowsMime();
+
+ // for converting from Qt
+ virtual bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const = 0;
+ virtual bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const = 0;
+ virtual QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const = 0;
+
+ // for converting to Qt
+ virtual bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const = 0;
+ virtual QVariant convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const = 0;
+ virtual QString mimeForFormat(const FORMATETC &formatetc) const = 0;
+
+ static int registerMimeType(const QString &mime);
+
+private:
+ friend class QClipboardWatcher;
+ friend class QDragManager;
+ friend class QDropData;
+ friend class QOleDataObject;
+
+ static QWindowsMime *converterToMime(const QString &mimeType, IDataObject *pDataObj);
+ static QStringList allMimesForFormats(IDataObject *pDataObj);
+ static QWindowsMime *converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData);
+ static QVector<FORMATETC> allFormatsForMime(const QMimeData *mimeData);
+};
+
+#endif
+#if defined(Q_WS_MAC)
+
+/*
+ Encapsulation of conversion between MIME and Mac flavor.
+ Not needed on X11, as the underlying protocol uses the MIME standard
+ directly.
+*/
+
+class Q_GUI_EXPORT QMacMime { //Obsolete
+ char type;
+public:
+ enum QMacMimeType { MIME_DND=0x01, MIME_CLIP=0x02, MIME_QT_CONVERTOR=0x04, MIME_ALL=MIME_DND|MIME_CLIP };
+ explicit QMacMime(char) { }
+ virtual ~QMacMime() { }
+
+ static void initialize() { }
+
+ static QList<QMacMime*> all(QMacMimeType) { return QList<QMacMime*>(); }
+ static QMacMime *convertor(QMacMimeType, const QString &, int) { return 0; }
+ static QString flavorToMime(QMacMimeType, int) { return QString(); }
+
+ virtual QString convertorName()=0;
+ virtual int countFlavors()=0;
+ virtual int flavor(int index)=0;
+ virtual bool canConvert(const QString &mime, int flav)=0;
+ virtual QString mimeFor(int flav)=0;
+ virtual int flavorFor(const QString &mime)=0;
+ virtual QVariant convertToMime(const QString &mime, QList<QByteArray> data, int flav)=0;
+ virtual QList<QByteArray> convertFromMime(const QString &mime, QVariant data, int flav)=0;
+};
+
+class Q_GUI_EXPORT QMacPasteboardMime {
+ char type;
+public:
+ enum QMacPasteboardMimeType { MIME_DND=0x01,
+ MIME_CLIP=0x02,
+ MIME_QT_CONVERTOR=0x04,
+ MIME_QT3_CONVERTOR=0x08,
+ MIME_ALL=MIME_DND|MIME_CLIP
+ };
+ explicit QMacPasteboardMime(char);
+ virtual ~QMacPasteboardMime();
+
+ static void initialize();
+
+ static QList<QMacPasteboardMime*> all(uchar);
+ static QMacPasteboardMime *convertor(uchar, const QString &mime, QString flav);
+ static QString flavorToMime(uchar, QString flav);
+
+ virtual QString convertorName() = 0;
+
+ virtual bool canConvert(const QString &mime, QString flav) = 0;
+ virtual QString mimeFor(QString flav) = 0;
+ virtual QString flavorFor(const QString &mime) = 0;
+ virtual QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav) = 0;
+ virtual QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav) = 0;
+};
+
+// ### Qt 5: Add const QStringList& QMacPasteboardMime::supportedFlavours()
+Q_GUI_EXPORT void qRegisterDraggedTypes(const QStringList &types);
+#endif // Q_WS_MAC
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMIME_H
diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp
new file mode 100644
index 0000000000..cf1d74749b
--- /dev/null
+++ b/src/gui/kernel/qmime_mac.cpp
@@ -0,0 +1,1181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmime.h"
+
+//#define USE_INTERNET_CONFIG
+
+#ifndef USE_INTERNET_CONFIG
+# include "qfile.h"
+# include "qfileinfo.h"
+# include "qtextstream.h"
+# include "qdir.h"
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/fcntl.h>
+#endif
+
+#include "qdebug.h"
+#include "qpixmap.h"
+#include "qimagewriter.h"
+#include "qimagereader.h"
+#include "qdatastream.h"
+#include "qbuffer.h"
+#include "qdatetime.h"
+#include "qapplication_p.h"
+#include "qtextcodec.h"
+#include "qregexp.h"
+#include "qurl.h"
+#include "qmap.h"
+#include <private/qt_mac_p.h>
+
+#ifdef Q_WS_MAC32
+#include <QuickTime/QuickTime.h>
+#include "qlibrary.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp
+
+typedef QList<QMacPasteboardMime*> MimeList;
+Q_GLOBAL_STATIC(MimeList, globalMimeList)
+
+static void cleanup_mimes()
+{
+ MimeList *mimes = globalMimeList();
+ while (!mimes->isEmpty())
+ delete mimes->takeFirst();
+}
+
+Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
+
+/*!
+ \fn void qRegisterDraggedTypes(const QStringList &types)
+ \relates QMacPasteboardMime
+
+ Registers the given \a types as custom pasteboard types.
+
+ This function should be called to enable the Drag and Drop events
+ for custom pasteboard types on Cocoa implementations. This is required
+ in addition to a QMacPasteboardMime subclass implementation. By default
+ drag and drop is enabled for all standard pasteboard types.
+
+ \sa QMacPasteboardMime
+*/
+Q_GUI_EXPORT void qRegisterDraggedTypes(const QStringList &types)
+{
+ (*globalDraggedTypesList()) += types;
+}
+
+const QStringList& qEnabledDraggedTypes()
+{
+ return (*globalDraggedTypesList());
+}
+
+
+/*****************************************************************************
+ QDnD debug facilities
+ *****************************************************************************/
+//#define DEBUG_MIME_MAPS
+
+//functions
+extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
+extern void qt_mac_from_pascal_string(QString, Str255, TextEncoding encoding=0, int len=-1); //qglobal.cpp
+
+ScrapFlavorType qt_mac_mime_type = 'CUTE';
+CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
+
+/*!
+ \class QMacPasteboardMime
+ \brief The QMacPasteboardMime class maps open-standard MIME to Mac flavors.
+ \since 4.2
+ \ingroup io
+ \ingroup draganddrop
+ \ingroup misc
+
+ Qt's drag and drop support and clipboard facilities use the MIME
+ standard. On X11, this maps trivially to the Xdnd protocol, but on
+ Mac although some applications use MIME types to describe clipboard
+ formats, others use arbitrary non-standardized naming conventions,
+ or unnamed built-in Mac formats.
+
+ By instantiating subclasses of QMacPasteboardMime that provide conversions
+ between Mac flavors and MIME formats, you can convert proprietary
+ clipboard formats to MIME formats.
+
+ Qt has predefined support for the following Mac flavors:
+ \list
+ \i kScrapFlavorTypeUnicode - converted to "text/plain;charset=ISO-10646-UCS-2"
+ \i kScrapFlavorTypeText - converted to "text/plain;charset=system" or "text/plain"
+ \i kScrapFlavorTypePicture - converted to "application/x-qt-image"
+ \i typeFileURL - converted to "text/uri-list"
+ \endlist
+
+ You can check if a MIME type is convertible using canConvert() and
+ can perform conversions with convertToMime() and convertFromMime().
+*/
+
+/*! \enum QMacPasteboardMime::QMacPasteboardMimeType
+ \internal
+*/
+
+/*!
+ Constructs a new conversion object of type \a t, adding it to the
+ globally accessed list of available convertors.
+*/
+QMacPasteboardMime::QMacPasteboardMime(char t) : type(t)
+{
+ globalMimeList()->append(this);
+}
+
+/*!
+ Destroys a conversion object, removing it from the global
+ list of available convertors.
+*/
+QMacPasteboardMime::~QMacPasteboardMime()
+{
+ if(!QApplication::closingDown())
+ globalMimeList()->removeAll(this);
+}
+
+class QMacPasteboardMimeAny : public QMacPasteboardMime {
+private:
+
+public:
+ QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
+ }
+ ~QMacPasteboardMimeAny() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeAny::convertorName()
+{
+ return QLatin1String("Any-Mime");
+}
+
+QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
+{
+ // do not handle the mime type name in the drag pasteboard
+ if(mime == QLatin1String("application/x-qt-mime-type-name"))
+ return QString();
+ QString ret = QLatin1String("com.trolltech.anymime.") + mime;
+ return ret.replace(QLatin1String("/"), QLatin1String("--"));
+}
+
+QString QMacPasteboardMimeAny::mimeFor(QString flav)
+{
+ const QString any_prefix = QLatin1String("com.trolltech.anymime.");
+ if(flav.size() > any_prefix.length() && flav.startsWith(any_prefix))
+ return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/"));
+ return QString();
+}
+
+bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ if(data.count() > 1)
+ qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data");
+ QVariant ret;
+ if (mime == QLatin1String("text/plain"))
+ ret = QString::fromUtf8(data.first());
+ else
+ ret = data.first();
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ else
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacPasteboardMimeTypeName : public QMacPasteboardMime {
+private:
+
+public:
+ QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
+ }
+ ~QMacPasteboardMimeTypeName() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTypeName::convertorName()
+{
+ return QLatin1String("Qt-Mime-Type");
+}
+
+QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime)
+{
+ if(mime == QLatin1String("application/x-qt-mime-type-name"))
+ return QLatin1String("com.trolltech.qt.MimeTypeName");
+ return QString();
+}
+
+QString QMacPasteboardMimeTypeName::mimeFor(QString)
+{
+ return QString();
+}
+
+bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString)
+{
+ return false;
+}
+
+QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString)
+{
+ QVariant ret;
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString)
+{
+ QList<QByteArray> ret;
+ ret.append(QString("x-qt-mime-type-name").toUtf8());
+ return ret;
+}
+
+class QMacPasteboardMimePlainText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimePlainText::convertorName()
+{
+ return QLatin1String("PlainText");
+}
+
+QString QMacPasteboardMimePlainText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/plain"))
+ return QLatin1String("com.apple.traditional-mac-plain-text");
+ return QString();
+}
+
+QString QMacPasteboardMimePlainText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("com.apple.traditional-mac-plain-text"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
+{
+ if(data.count() > 1)
+ qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ QVariant ret;
+ if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) {
+ QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), CFStringGetSystemEncoding(), false));
+ ret = QString(str);
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text")))
+ ret.append(string.toLatin1());
+ return ret;
+}
+
+class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUnicodeText::convertorName()
+{
+ return QLatin1String("UnicodeText");
+}
+
+QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/plain"))
+ return QLatin1String("public.utf16-plain-text");
+ int i = mime.indexOf(QLatin1String("charset="));
+ if (i >= 0) {
+ QString cs(mime.mid(i+8).toLower());
+ i = cs.indexOf(QLatin1String(";"));
+ if (i>=0)
+ cs = cs.left(i);
+ if (cs == QLatin1String("system"))
+ return QLatin1String("public.utf8-plain-text");
+ else if (cs == QLatin1String("iso-10646-ucs-2")
+ || cs == QLatin1String("utf16"))
+ return QLatin1String("public.utf16-plain-text");
+ }
+ return QString();
+}
+
+QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
+{
+ if(data.count() > 1)
+ qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ // I can only handle two types (system and unicode) so deal with them that way
+ QVariant ret;
+ if(flavor == QLatin1String("public.utf8-plain-text")) {
+ QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), CFStringGetSystemEncoding(), false));
+ ret = QString(str);
+ } else if (flavor == QLatin1String("public.utf16-plain-text")) {
+ ret = QString::fromUtf16(reinterpret_cast<const ushort *>(firstData.constData()),
+ firstData.size() / sizeof(ushort));
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if(flavor == QLatin1String("public.utf8-plain-text"))
+ ret.append(string.toUtf8());
+ else if (flavor == QLatin1String("public.utf16-plain-text"))
+ ret.append(QByteArray((char*)string.utf16(), string.length()*2));
+ return ret;
+}
+
+class QMacPasteboardMimeHTMLText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeHTMLText::convertorName()
+{
+ return QLatin1String("HTML");
+}
+
+QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/html"))
+ return QLatin1String("public.html");
+ return QString();
+}
+
+QString QMacPasteboardMimeHTMLText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.html"))
+ return QLatin1String("text/html");
+ return QString();
+}
+
+bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
+{
+ if (!canConvert(mimeType, flavor))
+ return QVariant();
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
+ return data.first();
+}
+
+QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flavor))
+ return ret;
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+
+#ifdef Q_WS_MAC32
+
+typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle);
+typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32);
+typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef);
+typedef ComponentResult (*PtrGraphicsExportSetOutputHandle)(GraphicsExportComponent, Handle);
+typedef ComponentResult (*PtrGraphicsExportDoExport)(GraphicsExportComponent, unsigned long *);
+
+static PtrGraphicsImportSetDataHandle ptrGraphicsImportSetDataHandle = 0;
+static PtrGraphicsImportCreateCGImage ptrGraphicsImportCreateCGImage = 0;
+static PtrGraphicsExportSetInputCGImage ptrGraphicsExportSetInputCGImage = 0;
+static PtrGraphicsExportSetOutputHandle ptrGraphicsExportSetOutputHandle = 0;
+static PtrGraphicsExportDoExport ptrGraphicsExportDoExport = 0;
+
+static bool resolveMimeQuickTimeSymbols()
+{
+ if (ptrGraphicsImportSetDataHandle == 0) {
+ QLibrary library(QLatin1String("/System/Library/Frameworks/QuickTime.framework/QuickTime"));
+ ptrGraphicsImportSetDataHandle = reinterpret_cast<PtrGraphicsImportSetDataHandle>(library.resolve("GraphicsImportSetDataHandle"));
+ ptrGraphicsImportCreateCGImage = reinterpret_cast<PtrGraphicsImportCreateCGImage>(library.resolve("GraphicsImportCreateCGImage"));
+ ptrGraphicsExportSetInputCGImage = reinterpret_cast<PtrGraphicsExportSetInputCGImage>(library.resolve("GraphicsExportSetInputCGImage"));
+ ptrGraphicsExportSetOutputHandle = reinterpret_cast<PtrGraphicsExportSetOutputHandle>(library.resolve("GraphicsExportSetOutputHandle"));
+ ptrGraphicsExportDoExport = reinterpret_cast<PtrGraphicsExportDoExport>(library.resolve("GraphicsExportDoExport"));
+ }
+
+ return ptrGraphicsImportSetDataHandle != 0
+ && ptrGraphicsImportCreateCGImage != 0 && ptrGraphicsExportSetInputCGImage != 0
+ && ptrGraphicsExportSetOutputHandle != 0 && ptrGraphicsExportDoExport != 0;
+}
+
+class QMacPasteboardMimePict : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimePict() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimePict::convertorName()
+{
+ return QLatin1String("Pict");
+}
+
+QString QMacPasteboardMimePict::flavorFor(const QString &mime)
+{
+ if(mime.startsWith(QLatin1String("application/x-qt-image")))
+ return QLatin1String("com.apple.pict");
+ return QString();
+}
+
+QString QMacPasteboardMimePict::mimeFor(QString flav)
+{
+ if(flav == QLatin1String("com.apple.pict"))
+ return QLatin1String("application/x-qt-image");
+ return QString();
+}
+
+bool QMacPasteboardMimePict::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("com.apple.pict")
+ && mime == QLatin1String("application/x-qt-image");
+}
+
+
+QVariant QMacPasteboardMimePict::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if(data.count() > 1)
+ qWarning("QMacPasteboardMimePict: Cannot handle multiple member data");
+ QVariant ret;
+ if (!resolveMimeQuickTimeSymbols())
+ return ret;
+
+ if(!canConvert(mime, flav))
+ return ret;
+ const QByteArray &a = data.first();
+
+ // This function expects the 512 header (just to skip it, so create the extra space for it).
+ Handle pic = NewHandle(a.size() + 512);
+ memcpy(*pic + 512, a.constData(), a.size());
+
+ GraphicsImportComponent graphicsImporter;
+ ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType,
+ kQTFileTypePicture, &graphicsImporter);
+ QCFType<CGImageRef> cgImage;
+ if (!result)
+ result = ptrGraphicsImportSetDataHandle(graphicsImporter, pic);
+ if (!result)
+ result = ptrGraphicsImportCreateCGImage(graphicsImporter, &cgImage,
+ kGraphicsImportCreateCGImageUsingCurrentSettings);
+ if (!result)
+ ret = QVariant(QPixmap::fromMacCGImageRef(cgImage).toImage());
+ CloseComponent(graphicsImporter);
+ DisposeHandle(pic);
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimePict::convertFromMime(const QString &mime, QVariant variant,
+ QString flav)
+{
+ QList<QByteArray> ret;
+ if (!resolveMimeQuickTimeSymbols())
+ return ret;
+
+ if (!canConvert(mime, flav))
+ return ret;
+ QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(qvariant_cast<QImage>(variant));
+ Handle pic = NewHandle(0);
+ GraphicsExportComponent graphicsExporter;
+ ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
+ kQTFileTypePicture, &graphicsExporter);
+ if (!result) {
+ unsigned long sizeWritten;
+ result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
+ if (!result)
+ result = ptrGraphicsExportSetOutputHandle(graphicsExporter, pic);
+ if (!result)
+ result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);
+
+ CloseComponent(graphicsExporter);
+ }
+
+ int size = GetHandleSize((Handle)pic);
+ // Skip the Picture File header (512 bytes) and feed the raw data
+ QByteArray ar(reinterpret_cast<char *>(*pic + 512), size - 512);
+ ret.append(ar);
+ DisposeHandle(pic);
+ return ret;
+}
+#endif
+
+class QMacPasteboardMimeTiff : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTiff::convertorName()
+{
+ return QLatin1String("Tiff");
+}
+
+QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
+{
+ if(mime.startsWith(QLatin1String("application/x-qt-image")))
+ return QLatin1String("public.tiff");
+ return QString();
+}
+
+QString QMacPasteboardMimeTiff::mimeFor(QString flav)
+{
+ if(flav == QLatin1String("public.tiff"))
+ return QLatin1String("application/x-qt-image");
+ return QString();
+}
+
+bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
+}
+
+QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if(data.count() > 1)
+ qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
+ QVariant ret;
+ if (!canConvert(mime, flav))
+ return ret;
+ const QByteArray &a = data.first();
+ QCFType<CGImageRef> image;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ QCFType<CFDataRef> data = CFDataCreateWithBytesNoCopy(0,
+ reinterpret_cast<const UInt8 *>(a.constData()),
+ a.size(), kCFAllocatorNull);
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(data, 0);
+ image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
+ } else
+#endif
+ {
+#ifdef Q_WS_MAC32
+ if (resolveMimeQuickTimeSymbols()) {
+ Handle tiff = NewHandle(a.size());
+ memcpy(*tiff, a.constData(), a.size());
+ GraphicsImportComponent graphicsImporter;
+ ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType,
+ kQTFileTypeTIFF, &graphicsImporter);
+ if (!result)
+ result = ptrGraphicsImportSetDataHandle(graphicsImporter, tiff);
+ if (!result)
+ result = ptrGraphicsImportCreateCGImage(graphicsImporter, &image,
+ kGraphicsImportCreateCGImageUsingCurrentSettings);
+ CloseComponent(graphicsImporter);
+ DisposeHandle(tiff);
+ }
+#endif
+ }
+
+ if (image != 0)
+ ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage());
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QImage img = qvariant_cast<QImage>(variant);
+ QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img);
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
+ QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
+ if (imageDestination != 0) {
+ CFTypeRef keys[2];
+ QCFType<CFTypeRef> values[2];
+ QCFType<CFDictionaryRef> options;
+ keys[0] = kCGImagePropertyPixelWidth;
+ keys[1] = kCGImagePropertyPixelHeight;
+ int width = img.width();
+ int height = img.height();
+ values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
+ values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
+ options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
+ reinterpret_cast<const void **>(values), 2,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CGImageDestinationAddImage(imageDestination, cgimage, options);
+ CGImageDestinationFinalize(imageDestination);
+ }
+ QByteArray ar(CFDataGetLength(data), 0);
+ CFDataGetBytes(data,
+ CFRangeMake(0, ar.size()),
+ reinterpret_cast<UInt8 *>(ar.data()));
+ ret.append(ar);
+ } else
+#endif
+ {
+#ifdef Q_WS_MAC32
+ Handle tiff = NewHandle(0);
+ if (resolveMimeQuickTimeSymbols()) {
+ GraphicsExportComponent graphicsExporter;
+ ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
+ kQTFileTypeTIFF, &graphicsExporter);
+ if (!result) {
+ unsigned long sizeWritten;
+ result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
+ if (!result)
+ result = ptrGraphicsExportSetOutputHandle(graphicsExporter, tiff);
+ if (!result)
+ result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);
+
+ CloseComponent(graphicsExporter);
+ }
+ }
+ int size = GetHandleSize((Handle)tiff);
+ QByteArray ar(reinterpret_cast<char *>(*tiff), size);
+ ret.append(ar);
+ DisposeHandle(tiff);
+#endif
+ }
+ return ret;
+}
+
+
+class QMacPasteboardMimeFileUri : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeFileUri::convertorName()
+{
+ return QLatin1String("FileURL");
+}
+
+QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/uri-list"))
+ return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
+ return QString();
+}
+
+QString QMacPasteboardMimeFileUri::mimeFor(QString flav)
+{
+ if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav)
+{
+ return mime == QLatin1String("text/uri-list")
+ && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
+}
+
+QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if(!canConvert(mime, flav))
+ return QVariant();
+ QList<QVariant> ret;
+ for(int i = 0; i < data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+ QList<QVariant> urls = data.toList();
+ for(int i = 0; i < urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+#ifdef QT3_SUPPORT
+class QMacPasteboardMimeQt3Any : public QMacPasteboardMime {
+private:
+ int current_max;
+ QFile library_file;
+ QDateTime mime_registry_loaded;
+ QMap<QString, int> mime_registry;
+ int registerMimeType(const QString &mime);
+ bool loadMimeRegistry();
+
+public:
+ QMacPasteboardMimeQt3Any() : QMacPasteboardMime(MIME_QT3_CONVERTOR) {
+ current_max = 'QT00';
+ }
+ ~QMacPasteboardMimeQt3Any() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+static bool qt_mac_openMimeRegistry(bool global, QIODevice::OpenMode mode, QFile &file)
+{
+ QString dir = QLatin1String("/Library/Qt");
+ if(!global)
+ dir.prepend(QDir::homePath());
+ file.setFileName(dir + QLatin1String("/.mime_types"));
+ if(mode != QIODevice::ReadOnly) {
+ if(!QFile::exists(dir)) {
+ // Do it with a system call as I don't see much worth in
+ // doing it with QDir since we have to chmod anyway.
+ bool success = ::mkdir(dir.toLocal8Bit().constData(), S_IRUSR | S_IWUSR | S_IXUSR) == 0;
+ if (success)
+ success = ::chmod(dir.toLocal8Bit().constData(), S_IRUSR | S_IWUSR | S_IXUSR
+ | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH) == 0;
+ if (!success)
+ return false;
+ }
+ if (!file.exists()) {
+ // Create the file and chmod it so that everyone can write to it.
+ int fd = ::open(file.fileName().toLocal8Bit().constData(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ bool success = fd != -1;
+ if (success)
+ success = ::fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0;
+ if (fd != -1)
+ ::close(fd);
+ if(!success)
+ return false;
+ }
+ }
+ return file.open(mode);
+}
+
+static void qt_mac_loadMimeRegistry(QFile &file, QMap<QString, int> &registry, int &max)
+{
+ file.reset();
+ QTextStream stream(&file);
+ while(!stream.atEnd()) {
+ QString mime = stream.readLine();
+ int mactype = stream.readLine().toInt();
+ if(mactype > max)
+ max = mactype;
+ registry.insert(mime, mactype);
+ }
+}
+
+bool QMacPasteboardMimeQt3Any::loadMimeRegistry()
+{
+ if(!library_file.isOpen()) {
+ if(!qt_mac_openMimeRegistry(true, QIODevice::ReadWrite, library_file)) {
+ QFile global;
+ if(qt_mac_openMimeRegistry(true, QIODevice::ReadOnly, global)) {
+ qt_mac_loadMimeRegistry(global, mime_registry, current_max);
+ global.close();
+ }
+ if(!qt_mac_openMimeRegistry(false, QIODevice::ReadWrite, library_file)) {
+ qWarning("QMacPasteboardMimeAnyQt3Mime: Failure to open mime resources %s -- %s", library_file.fileName().toLatin1().constData(),
+ library_file.errorString().toLatin1().constData());
+ return false;
+ }
+ }
+ }
+
+ QFileInfo fi(library_file);
+ if(!mime_registry_loaded.isNull() && mime_registry_loaded == fi.lastModified())
+ return true;
+ mime_registry_loaded = fi.lastModified();
+ qt_mac_loadMimeRegistry(library_file, mime_registry, current_max);
+ return true;
+}
+
+int QMacPasteboardMimeQt3Any::registerMimeType(const QString &mime)
+{
+ if(!mime_registry.contains(mime)) {
+ if(!loadMimeRegistry()) {
+ qWarning("QMacPasteboardMimeAnyQt3Mime: Internal error");
+ return 0;
+ }
+ if(!mime_registry.contains(mime)) {
+ if(!library_file.isOpen()) {
+ if(!library_file.open(QIODevice::WriteOnly)) {
+ qWarning("QMacPasteboardMimeAnyQt3Mime: Failure to open %s -- %s", library_file.fileName().toLatin1().constData(),
+ library_file.errorString().toLatin1().constData());
+ return false;
+ }
+ }
+ int ret = ++current_max;
+ mime_registry_loaded = QFileInfo(library_file).lastModified();
+ QTextStream stream(&library_file);
+ stream << mime << endl;
+ stream << ret << endl;
+ mime_registry.insert(mime, ret);
+ library_file.flush(); //flush and set mtime
+ return ret;
+ }
+ }
+ return mime_registry[mime];
+}
+
+QString QMacPasteboardMimeQt3Any::convertorName()
+{
+ return QLatin1String("Qt3-Any-Mime");
+}
+
+QString QMacPasteboardMimeQt3Any::flavorFor(const QString &mime)
+{
+ const int os_flav = registerMimeType(mime);
+ QCFType<CFArrayRef> ids = UTTypeCreateAllIdentifiersForTag(0, kUTTagClassOSType,
+ QCFString(UTCreateStringForOSType(os_flav)));
+ if(ids) {
+ const int type_count = CFArrayGetCount(ids);
+ if(type_count) {
+ if(type_count > 1)
+ qDebug("Can't happen!");
+ return QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(ids, 0));
+ }
+ }
+ return QString();
+}
+
+QString QMacPasteboardMimeQt3Any::mimeFor(QString flav)
+{
+ loadMimeRegistry();
+ const int os_flav = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(QCFString(flav), kUTTagClassOSType));
+ for(QMap<QString, int>::const_iterator it = mime_registry.constBegin();
+ it != mime_registry.constEnd(); ++it) {
+ if(it.value() == os_flav)
+ return QString::fromLatin1(it.key().toLatin1());
+ }
+ return QString();
+}
+
+bool QMacPasteboardMimeQt3Any::canConvert(const QString &mime, QString flav)
+{
+ loadMimeRegistry();
+ const int os_flav = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(QCFString(flav), kUTTagClassOSType));
+ if(mime_registry.contains(mime) && mime_registry[mime] == os_flav)
+ return true;
+ return false;
+}
+
+QVariant QMacPasteboardMimeQt3Any::convertToMime(const QString &, QList<QByteArray>, QString)
+{
+ qWarning("QMacPasteboardMimeAnyQt3Mime: Cannot write anything!");
+ return QVariant();
+}
+
+QList<QByteArray> QMacPasteboardMimeQt3Any::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain")) {
+ ret.append(data.toString().toUtf8());
+ } else {
+ ret.append(data.toByteArray());
+ }
+ return ret;
+}
+#endif
+
+/*!
+ \internal
+
+ This is an internal function.
+*/
+void QMacPasteboardMime::initialize()
+{
+ if(globalMimeList()->isEmpty()) {
+ qAddPostRoutine(cleanup_mimes);
+
+ //standard types that we wrap
+ new QMacPasteboardMimeTiff;
+#ifdef Q_WS_MAC32
+ new QMacPasteboardMimePict;
+#endif
+ new QMacPasteboardMimeUnicodeText;
+ new QMacPasteboardMimePlainText;
+ new QMacPasteboardMimeHTMLText;
+ new QMacPasteboardMimeFileUri;
+ new QMacPasteboardMimeTypeName;
+ //make sure our "non-standard" types are always last! --Sam
+ new QMacPasteboardMimeAny;
+#ifdef QT3_SUPPORT
+ new QMacPasteboardMimeQt3Any;
+#endif
+ }
+}
+
+/*!
+ Returns the most-recently created QMacPasteboardMime of type \a t that can convert
+ between the \a mime and \a flav formats. Returns 0 if no such convertor
+ exists.
+*/
+QMacPasteboardMime*
+QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav)
+{
+ MimeList *mimes = globalMimeList();
+ for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]",
+ (*it)->convertorName().toLatin1().constData(),
+ (*it)->type & t, mime.toLatin1().constData(),
+ flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
+ (*it)->canConvert(mime,flav));
+ for(int i = 0; i < (*it)->countFlavors(); ++i) {
+ int f = (*it)->flavor(i);
+ qDebug(" %d) %d[%c%c%c%c] [%s]", i, f,
+ (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF,
+ (*it)->convertorName().toLatin1().constData());
+ }
+#endif
+ if(((*it)->type & t) && (*it)->canConvert(mime, flav))
+ return (*it);
+ }
+ return 0;
+}
+/*!
+ Returns a MIME type of type \a t for \a flav, or 0 if none exists.
+*/
+QString QMacPasteboardMime::flavorToMime(uchar t, QString flav)
+{
+ MimeList *mimes = globalMimeList();
+ for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]",
+ (*it)->convertorName().toLatin1().constData(),
+ (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
+ (*it)->mimeFor(flav).toLatin1().constData());
+
+#endif
+ if((*it)->type & t) {
+ QString mimeType = (*it)->mimeFor(flav);
+ if(!mimeType.isNull())
+ return mimeType;
+ }
+ }
+ return QString();
+}
+
+/*!
+ Returns a list of all currently defined QMacPasteboardMime objects of type \a t.
+*/
+QList<QMacPasteboardMime*> QMacPasteboardMime::all(uchar t)
+{
+ MimeList ret;
+ MimeList *mimes = globalMimeList();
+ for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+ if((*it)->type & t)
+ ret.append((*it));
+ }
+ return ret;
+}
+
+
+/*!
+ \fn QString QMacPasteboardMime::convertorName()
+
+ Returns a name for the convertor.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav)
+
+ Returns true if the convertor can convert (both ways) between
+ \a mime and \a flav; otherwise returns false.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QMacPasteboardMime::mimeFor(QString flav)
+
+ Returns the MIME UTI used for Mac flavor \a flav, or 0 if this
+ convertor does not support \a flav.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QMacPasteboardMime::flavorFor(const QString &mime)
+
+ Returns the Mac UTI used for MIME type \a mime, or 0 if this
+ convertor does not support \a mime.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+
+ Returns \a data converted from Mac UTI \a flav to MIME type \a
+ mime.
+
+ Note that Mac flavors must all be self-terminating. The input \a
+ data may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav)
+
+ Returns \a data converted from MIME type \a mime
+ to Mac UTI \a flav.
+
+ Note that Mac flavors must all be self-terminating. The return
+ value may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp
new file mode 100644
index 0000000000..cd0aae6ddb
--- /dev/null
+++ b/src/gui/kernel/qmime_win.cpp
@@ -0,0 +1,1594 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmime.h"
+
+#include "qimagereader.h"
+#include "qimagewriter.h"
+#include "qdatastream.h"
+#include "qbuffer.h"
+#include "qt_windows.h"
+#include "qapplication_p.h"
+#include "qtextcodec.h"
+#include "qregexp.h"
+#include "qalgorithms.h"
+#include "qmap.h"
+#include "qdnd_p.h"
+#include <shlobj.h>
+#include "qurl.h"
+#include "qvariant.h"
+#include "qtextdocument.h"
+#include "qdir.h"
+
+#if defined(Q_OS_WINCE)
+#include "qguifunctions_wince.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_IMAGEFORMAT_BMP
+#ifndef CF_DIBV5
+#define CF_DIBV5 17
+#endif
+/* The MSVC compilers allows multi-byte characters, that has the behavior of
+ * that each character gets shifted into position. 0x73524742 below is for MSVC
+ * equivalent to doing 'sRGB', but this does of course not work
+ * on conformant C++ compilers. */
+#define BMP_LCS_sRGB 0x73524742
+#define BMP_LCS_GM_IMAGES 0x00000004L
+
+struct _CIEXYZ {
+ long ciexyzX, ciexyzY, ciexyzZ;
+};
+
+struct _CIEXYZTRIPLE {
+ _CIEXYZ ciexyzRed, ciexyzGreen, ciexyzBlue;
+};
+
+struct BMP_BITMAPV5HEADER {
+ DWORD bV5Size;
+ LONG bV5Width;
+ LONG bV5Height;
+ WORD bV5Planes;
+ WORD bV5BitCount;
+ DWORD bV5Compression;
+ DWORD bV5SizeImage;
+ LONG bV5XPelsPerMeter;
+ LONG bV5YPelsPerMeter;
+ DWORD bV5ClrUsed;
+ DWORD bV5ClrImportant;
+ DWORD bV5RedMask;
+ DWORD bV5GreenMask;
+ DWORD bV5BlueMask;
+ DWORD bV5AlphaMask;
+ DWORD bV5CSType;
+ _CIEXYZTRIPLE bV5Endpoints;
+ DWORD bV5GammaRed;
+ DWORD bV5GammaGreen;
+ DWORD bV5GammaBlue;
+ DWORD bV5Intent;
+ DWORD bV5ProfileData;
+ DWORD bV5ProfileSize;
+ DWORD bV5Reserved;
+};
+static const int BMP_BITFIELDS = 3;
+
+extern bool qt_read_dib(QDataStream&, QImage&); // qimage.cpp
+extern bool qt_write_dib(QDataStream&, QImage); // qimage.cpp
+static bool qt_write_dibv5(QDataStream &s, QImage image);
+static bool qt_read_dibv5(QDataStream &s, QImage &image);
+#endif
+
+//#define QMIME_DEBUG
+
+
+// helpers for using global memory
+
+static int getCf(const FORMATETC &formatetc)
+{
+ return formatetc.cfFormat;
+}
+
+static FORMATETC setCf(int cf)
+{
+ FORMATETC formatetc;
+ formatetc.cfFormat = cf;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.lindex = -1;
+ formatetc.ptd = NULL;
+ formatetc.tymed = TYMED_HGLOBAL;
+ return formatetc;
+}
+
+static bool setData(const QByteArray &data, STGMEDIUM *pmedium)
+{
+ HGLOBAL hData = GlobalAlloc(0, data.size());
+ if (!hData)
+ return false;
+
+ void *out = GlobalLock(hData);
+ memcpy(out, data.data(), data.size());
+ GlobalUnlock(hData);
+ pmedium->tymed = TYMED_HGLOBAL;
+ pmedium->hGlobal = hData;
+ pmedium->pUnkForRelease = 0;
+ return true;
+}
+
+static QByteArray getData(int cf, IDataObject *pDataObj)
+{
+ QByteArray data;
+ FORMATETC formatetc = setCf(cf);
+ STGMEDIUM s;
+ if (pDataObj->GetData(&formatetc, &s) == S_OK) {
+ DWORD * val = (DWORD*)GlobalLock(s.hGlobal);
+ data = QByteArray::fromRawData((char*)val, GlobalSize(s.hGlobal));
+ data.detach();
+ GlobalUnlock(s.hGlobal);
+ ReleaseStgMedium(&s);
+ } else {
+ //Try reading IStream data
+ formatetc.tymed = TYMED_ISTREAM;
+ if (pDataObj->GetData(&formatetc, &s) == S_OK) {
+ char szBuffer[4096];
+ ULONG actualRead = 0;
+ LARGE_INTEGER pos = {0, 0};
+ //Move to front (can fail depending on the data model implemented)
+ HRESULT hr = s.pstm->Seek(pos, STREAM_SEEK_SET, NULL);
+ while(SUCCEEDED(hr)){
+ hr = s.pstm->Read(szBuffer, sizeof(szBuffer), &actualRead);
+ if (SUCCEEDED(hr) && actualRead > 0) {
+ data += QByteArray::fromRawData(szBuffer, actualRead);
+ }
+ if (actualRead != sizeof(szBuffer))
+ break;
+ }
+ data.detach();
+ ReleaseStgMedium(&s);
+ }
+ }
+ return data;
+}
+
+static bool canGetData(int cf, IDataObject * pDataObj)
+{
+ FORMATETC formatetc = setCf(cf);
+ if (pDataObj->QueryGetData(&formatetc) != S_OK){
+ formatetc.tymed = TYMED_ISTREAM;
+ return pDataObj->QueryGetData(&formatetc) == S_OK;
+ }
+ return true;
+}
+
+class QWindowsMimeList
+{
+public:
+ QWindowsMimeList();
+ ~QWindowsMimeList();
+ void addWindowsMime(QWindowsMime * mime);
+ void removeWindowsMime(QWindowsMime * mime);
+ QList<QWindowsMime*> windowsMimes();
+
+private:
+ void init();
+ bool initialized;
+ QList<QWindowsMime*> mimes;
+};
+
+Q_GLOBAL_STATIC(QWindowsMimeList, theMimeList);
+
+
+/*!
+ \class QWindowsMime
+ \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
+ \ingroup io
+ \ingroup draganddrop
+ \ingroup misc
+
+ Qt's drag-and-drop and clipboard facilities use the MIME standard.
+ On X11, this maps trivially to the Xdnd protocol, but on Windows
+ although some applications use MIME types to describe clipboard
+ formats, others use arbitrary non-standardized naming conventions,
+ or unnamed built-in formats of Windows.
+
+ By instantiating subclasses of QWindowsMime that provide conversions
+ between Windows Clipboard and MIME formats, you can convert
+ proprietary clipboard formats to MIME formats.
+
+ Qt has predefined support for the following Windows Clipboard formats:
+
+ \table
+ \header \o Windows Format \o Equivalent MIME type
+ \row \o \c CF_UNICODETEXT \o \c text/plain
+ \row \o \c CF_TEXT \o \c text/plain
+ \row \o \c CF_DIB \o \c{image/xyz}, where \c xyz is
+ a \l{QImageWriter::supportedImageFormats()}{Qt image format}
+ \row \o \c CF_HDROP \o \c text/uri-list
+ \row \o \c CF_INETURL \o \c text/uri-list
+ \row \o \c CF_HTML \o \c text/html
+ \endtable
+
+ An example use of this class would be to map the Windows Metafile
+ clipboard format (\c CF_METAFILEPICT) to and from the MIME type
+ \c{image/x-wmf}. This conversion might simply be adding or removing
+ a header, or even just passing on the data. See \l{Drag and Drop}
+ for more information on choosing and definition MIME types.
+
+ You can check if a MIME type is convertible using canConvertFromMime() and
+ can perform conversions with convertToMime() and convertFromMime().
+*/
+
+/*!
+Constructs a new conversion object, adding it to the globally accessed
+list of available converters.
+*/
+QWindowsMime::QWindowsMime()
+{
+ theMimeList()->addWindowsMime(this);
+}
+
+/*!
+Destroys a conversion object, removing it from the global
+list of available converters.
+*/
+QWindowsMime::~QWindowsMime()
+{
+ theMimeList()->removeWindowsMime(this);
+}
+
+
+/*!
+ Registers the MIME type \a mime, and returns an ID number
+ identifying the format on Windows.
+*/
+int QWindowsMime::registerMimeType(const QString &mime)
+{
+#ifdef Q_OS_WINCE
+ int f = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (mime.utf16()));
+#else
+ int f = RegisterClipboardFormatA(mime.toLocal8Bit());
+#endif
+ if (!f)
+ qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format");
+
+ return f;
+}
+
+
+/*!
+\fn bool QWindowsMime::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+
+ Returns true if the converter can convert from the \a mimeData to
+ the format specified in \a formatetc.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn bool QWindowsMime::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+
+ Returns true if the converter can convert to the \a mimeType from
+ the available formats in \a pDataObj.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+\fn QString QWindowsMime::mimeForFormat(const FORMATETC &formatetc) const
+
+ Returns the mime type that will be created form the format specified
+ in \a formatetc, or an empty string if this converter does not support
+ \a formatetc.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+\fn QVector<FORMATETC> QWindowsMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+
+ Returns a QVector of FORMATETC structures representing the different windows clipboard
+ formats that can be provided for the \a mimeType from the \a mimeData.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QVariant QWindowsMime::convertToMime(const QString &mimeType, IDataObject *pDataObj,
+ QVariant::Type preferredType) const
+
+ Returns a QVariant containing the converted data for \a mimeType from \a pDataObj.
+ If possible the QVariant should be of the \a preferredType to avoid needless conversions.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+\fn bool QWindowsMime::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
+
+ Convert the \a mimeData to the format specified in \a formatetc.
+ The converted data should then be placed in \a pmedium structure.
+
+ Return true if the conversion was successful.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+
+QWindowsMime *QWindowsMime::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData)
+{
+ QList<QWindowsMime*> mimes = theMimeList()->windowsMimes();
+ for (int i=mimes.size()-1; i>=0; --i) {
+ if (mimes.at(i)->canConvertFromMime(formatetc, mimeData))
+ return mimes.at(i);
+ }
+ return 0;
+}
+
+QWindowsMime *QWindowsMime::converterToMime(const QString &mimeType, IDataObject *pDataObj)
+{
+ QList<QWindowsMime*> mimes = theMimeList()->windowsMimes();
+ for (int i=mimes.size()-1; i>=0; --i) {
+ if (mimes.at(i)->canConvertToMime(mimeType, pDataObj))
+ return mimes.at(i);
+ }
+ return 0;
+}
+
+QVector<FORMATETC> QWindowsMime::allFormatsForMime(const QMimeData *mimeData)
+{
+ QList<QWindowsMime*> mimes = theMimeList()->windowsMimes();
+ QVector<FORMATETC> formatics;
+ formatics.reserve(20);
+#ifndef QT_NO_DRAGANDDROP
+ QStringList formats = QInternalMimeData::formatsHelper(mimeData);
+ for (int f=0; f<formats.size(); ++f) {
+ for (int i=mimes.size()-1; i>=0; --i)
+ formatics += mimes.at(i)->formatsForMime(formats.at(f), mimeData);
+ }
+#else
+ Q_UNUSED(mimeData);
+#endif //QT_NO_DRAGANDDROP
+ return formatics;
+}
+
+QStringList QWindowsMime::allMimesForFormats(IDataObject *pDataObj)
+{
+ QList<QWindowsMime*> mimes = theMimeList()->windowsMimes();
+ QStringList formats;
+ LPENUMFORMATETC FAR fmtenum;
+ HRESULT hr = pDataObj->EnumFormatEtc(DATADIR_GET, &fmtenum);
+
+ if (hr == NOERROR) {
+ FORMATETC fmtetc;
+ while (S_OK == fmtenum->Next(1, &fmtetc, 0)) {
+#if defined(QMIME_DEBUG) && !defined(Q_OS_WINCE)
+ qDebug("QWindowsMime::allMimesForFormats()");
+ char buf[256] = {0};
+ GetClipboardFormatNameA(fmtetc.cfFormat, buf, 255);
+ qDebug("CF = %d : %s", fmtetc.cfFormat, buf);
+#endif
+ for (int i=mimes.size()-1; i>=0; --i) {
+ QString format = mimes.at(i)->mimeForFormat(fmtetc);
+ if (!format.isEmpty() && !formats.contains(format)) {
+ formats += format;
+ }
+ }
+ // as documented in MSDN to avoid possible memleak
+ if (fmtetc.ptd)
+ CoTaskMemFree(fmtetc.ptd);
+ }
+ fmtenum->Release();
+ }
+
+ return formats;
+}
+
+
+class QWindowsMimeText : public QWindowsMime
+{
+public:
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const;
+ QString mimeForFormat(const FORMATETC &formatetc) const;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+};
+
+bool QWindowsMimeText::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+{
+ int cf = getCf(formatetc);
+ return (cf == CF_UNICODETEXT || cf == CF_TEXT) && mimeData->hasText();
+}
+
+/*
+text/plain is defined as using CRLF, but so many programs don't,
+and programmers just look for '\n' in strings.
+Windows really needs CRLF, so we ensure it here.
+*/
+bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const
+{
+ if (canConvertFromMime(formatetc, mimeData)) {
+ QByteArray data;
+ int cf = getCf(formatetc);
+ if (cf == CF_TEXT) {
+ data = mimeData->text().toLocal8Bit();
+ // Anticipate required space for CRLFs at 1/40
+ int maxsize=data.size()+data.size()/40+3;
+ QByteArray r(maxsize, '\0');
+ char* o = r.data();
+ const char* d = data.data();
+ const int s = data.size();
+ bool cr=false;
+ int j=0;
+ for (int i=0; i<s; i++) {
+ char c = d[i];
+ if (c=='\r')
+ cr=true;
+ else {
+ if (c=='\n') {
+ if (!cr)
+ o[j++]='\r';
+ }
+ cr=false;
+ }
+ o[j++]=c;
+ if (j+3 >= maxsize) {
+ maxsize += maxsize/4;
+ r.resize(maxsize);
+ o = r.data();
+ }
+ }
+ o[j]=0;
+ return setData(r, pmedium);
+ } else if (cf == CF_UNICODETEXT) {
+ QString str = mimeData->text();
+ const QChar *u = str.unicode();
+ QString res;
+ const int s = str.length();
+ int maxsize = s + s/40 + 3;
+ res.resize(maxsize);
+ int ri = 0;
+ bool cr = false;
+ for (int i=0; i < s; ++i) {
+ if (*u == QLatin1Char('\r'))
+ cr = true;
+ else {
+ if (*u == QLatin1Char('\n') && !cr)
+ res[ri++] = QLatin1Char('\r');
+ cr = false;
+ }
+ res[ri++] = *u;
+ if (ri+3 >= maxsize) {
+ maxsize += maxsize/4;
+ res.resize(maxsize);
+ }
+ ++u;
+ }
+ res.truncate(ri);
+ const int byteLength = res.length()*2;
+ QByteArray r(byteLength + 2, '\0');
+ memcpy(r.data(), res.unicode(), byteLength);
+ r[byteLength] = 0;
+ r[byteLength+1] = 0;
+ return setData(r, pmedium);
+ }
+ }
+ return false;
+}
+
+bool QWindowsMimeText::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+{
+ return mimeType.startsWith(QLatin1String("text/plain"))
+ && (canGetData(CF_UNICODETEXT, pDataObj)
+ || canGetData(CF_TEXT, pDataObj));
+}
+
+QString QWindowsMimeText::mimeForFormat(const FORMATETC &formatetc) const
+{
+ int cf = getCf(formatetc);
+ if (cf == CF_UNICODETEXT || cf == CF_TEXT)
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+
+QVector<FORMATETC> QWindowsMimeText::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+{
+ QVector<FORMATETC> formatics;
+ if (mimeType.startsWith(QLatin1String("text/plain")) && mimeData->hasText()) {
+ formatics += setCf(CF_UNICODETEXT);
+ formatics += setCf(CF_TEXT);
+ }
+ return formatics;
+}
+
+QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const
+{
+ QVariant ret;
+
+ if (canConvertToMime(mime, pDataObj)) {
+ QString str;
+ QByteArray data = getData(CF_UNICODETEXT, pDataObj);
+ if (!data.isEmpty()) {
+ str = QString::fromUtf16((const unsigned short *)data.data());
+ str.replace(QLatin1String("\r\n"), QLatin1String("\n"));
+ } else {
+ data = getData(CF_TEXT, pDataObj);
+ if (!data.isEmpty()) {
+ const char* d = data.data();
+ const int s = qstrlen(d);
+ QByteArray r(data.size()+1, '\0');
+ char* o = r.data();
+ int j=0;
+ for (int i=0; i<s; i++) {
+ char c = d[i];
+ if (c!='\r')
+ o[j++]=c;
+ }
+ o[j]=0;
+ str = QString::fromLocal8Bit(r);
+ }
+ }
+ if (preferredType == QVariant::String)
+ ret = str;
+ else
+ ret = str.toUtf8();
+ }
+
+ return ret;
+}
+
+class QWindowsMimeURI : public QWindowsMime
+{
+public:
+ QWindowsMimeURI();
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const;
+ QString mimeForFormat(const FORMATETC &formatetc) const;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+private:
+ int CF_INETURL_W; // wide char version
+ int CF_INETURL;
+};
+
+QWindowsMimeURI::QWindowsMimeURI()
+{
+ CF_INETURL_W = QWindowsMime::registerMimeType(QLatin1String("UniformResourceLocatorW"));
+ CF_INETURL = QWindowsMime::registerMimeType(QLatin1String("UniformResourceLocator"));
+}
+
+bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+{
+ if (getCf(formatetc) == CF_HDROP) {
+ QList<QUrl> urls = mimeData->urls();
+ for (int i=0; i<urls.size(); i++) {
+ if (!urls.at(i).toLocalFile().isEmpty())
+ return true;
+ }
+ }
+ return (getCf(formatetc) == CF_INETURL_W || getCf(formatetc) == CF_INETURL) && mimeData->hasFormat(QLatin1String("text/uri-list"));
+}
+
+bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const
+{
+ if (canConvertFromMime(formatetc, mimeData)) {
+ if (getCf(formatetc) == CF_HDROP) {
+ QList<QUrl> urls = mimeData->urls();
+ QStringList fileNames;
+ int size = sizeof(DROPFILES)+2;
+ for (int i=0; i<urls.size(); i++) {
+ QString fn = QDir::toNativeSeparators(urls.at(i).toLocalFile());
+ if (!fn.isEmpty()) {
+ QT_WA({
+ size += sizeof(TCHAR)*(fn.length()+1);
+ } , {
+ size += fn.toLocal8Bit().length()+1;
+ });
+ fileNames.append(fn);
+ }
+ }
+
+ QByteArray result(size, '\0');
+ DROPFILES* d = (DROPFILES*)result.data();
+ d->pFiles = sizeof(DROPFILES);
+ GetCursorPos(&d->pt); // try
+ d->fNC = true;
+ char* files = ((char*)d) + d->pFiles;
+
+ QT_WA({
+ d->fWide = true;
+ TCHAR* f = (TCHAR*)files;
+ for (int i=0; i<fileNames.size(); i++) {
+ int l = fileNames.at(i).length();
+ memcpy(f, fileNames.at(i).utf16(), l*sizeof(TCHAR));
+ f += l;
+ *f++ = 0;
+ }
+ *f = 0;
+ } , {
+ d->fWide = false;
+ char* f = files;
+ for (int i=0; i<fileNames.size(); i++) {
+ QByteArray c = fileNames.at(i).toLocal8Bit();
+ if (!c.isEmpty()) {
+ int l = c.length();
+ memcpy(f, c.constData(), l);
+ f += l;
+ *f++ = 0;
+ }
+ }
+ *f = 0;
+ });
+ return setData(result, pmedium);
+ } else if (getCf(formatetc) == CF_INETURL_W) {
+ QList<QUrl> urls = mimeData->urls();
+ QByteArray result;
+ QString url = urls.at(0).toString();
+ result = QByteArray((const char *)url.utf16(), url.length() * 2);
+ result.append('\0');
+ result.append('\0');
+ return setData(result, pmedium);
+ } else if (getCf(formatetc) == CF_INETURL) {
+ QList<QUrl> urls = mimeData->urls();
+ QByteArray result = urls.at(0).toString().toLocal8Bit();
+ return setData(result, pmedium);
+ }
+ }
+
+ return false;
+}
+
+bool QWindowsMimeURI::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+{
+ return mimeType == QLatin1String("text/uri-list")
+ && (canGetData(CF_HDROP, pDataObj) || canGetData(CF_INETURL_W, pDataObj) || canGetData(CF_INETURL, pDataObj));
+}
+
+QString QWindowsMimeURI::mimeForFormat(const FORMATETC &formatetc) const
+{
+ QString format;
+ if (getCf(formatetc) == CF_HDROP || getCf(formatetc) == CF_INETURL_W || getCf(formatetc) == CF_INETURL)
+ format = QLatin1String("text/uri-list");
+ return format;
+}
+
+QVector<FORMATETC> QWindowsMimeURI::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+{
+ QVector<FORMATETC> formatics;
+ if (mimeType == QLatin1String("text/uri-list")) {
+ if (canConvertFromMime(setCf(CF_HDROP), mimeData))
+ formatics += setCf(CF_HDROP);
+ if (canConvertFromMime(setCf(CF_INETURL_W), mimeData))
+ formatics += setCf(CF_INETURL_W);
+ if (canConvertFromMime(setCf(CF_INETURL), mimeData))
+ formatics += setCf(CF_INETURL);
+ }
+ return formatics;
+}
+
+QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const
+{
+ if (mimeType == QLatin1String("text/uri-list")) {
+ if (canGetData(CF_HDROP, pDataObj)) {
+ QByteArray texturi;
+ QList<QVariant> urls;
+
+ QByteArray data = getData(CF_HDROP, pDataObj);
+ if (data.isEmpty())
+ return QVariant();
+
+ LPDROPFILES hdrop = (LPDROPFILES)data.data();
+ if (hdrop->fWide) {
+ const ushort* filesw = (const ushort*)(data.data() + hdrop->pFiles);
+ int i=0;
+ while (filesw[i]) {
+ QString fileurl = QString::fromUtf16(filesw+i);
+ urls += QUrl::fromLocalFile(fileurl);
+ i += fileurl.length()+1;
+ }
+ } else {
+ const char* files = (const char*)data.data() + hdrop->pFiles;
+ int i=0;
+ while (files[i]) {
+ urls += QUrl::fromLocalFile(QString::fromLocal8Bit(files+i));
+ i += int(strlen(files+i))+1;
+ }
+ }
+
+ if (preferredType == QVariant::Url && urls.size() == 1)
+ return urls.at(0);
+ else if (!urls.isEmpty())
+ return urls;
+ } else if (canGetData(CF_INETURL_W, pDataObj)) {
+ QByteArray data = getData(CF_INETURL_W, pDataObj);
+ if (data.isEmpty())
+ return QVariant();
+ return QUrl(QString::fromUtf16((const unsigned short *)data.constData()));
+ } else if (canGetData(CF_INETURL, pDataObj)) {
+ QByteArray data = getData(CF_INETURL, pDataObj);
+ if (data.isEmpty())
+ return QVariant();
+ return QUrl(QString::fromLocal8Bit(data.constData()));
+ }
+ }
+ return QVariant();
+}
+
+class QWindowsMimeHtml : public QWindowsMime
+{
+public:
+ QWindowsMimeHtml();
+
+ // for converting from Qt
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+
+ // for converting to Qt
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
+ QString mimeForFormat(const FORMATETC &formatetc) const;
+
+private:
+ int CF_HTML;
+};
+
+QWindowsMimeHtml::QWindowsMimeHtml()
+{
+ CF_HTML = QWindowsMime::registerMimeType(QLatin1String("HTML Format"));
+}
+
+QVector<FORMATETC> QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+{
+ QVector<FORMATETC> formatetcs;
+ if (mimeType == QLatin1String("text/html") && (!mimeData->html().isEmpty()))
+ formatetcs += setCf(CF_HTML);
+ return formatetcs;
+}
+
+QString QWindowsMimeHtml::mimeForFormat(const FORMATETC &formatetc) const
+{
+ if (getCf(formatetc) == CF_HTML)
+ return QLatin1String("text/html");
+ return QString();
+}
+
+bool QWindowsMimeHtml::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+{
+ return mimeType == QLatin1String("text/html") && canGetData(CF_HTML, pDataObj);
+}
+
+
+bool QWindowsMimeHtml::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+{
+ return getCf(formatetc) == CF_HTML && (!mimeData->html().isEmpty());
+}
+
+/*
+The windows HTML clipboard format is as follows (xxxxxxxxxx is a 10 integer number giving the positions
+in bytes). Charset used is mostly utf8, but can be different, ie. we have to look for the <meta> charset tag
+
+ Version: 1.0
+ StartHTML:xxxxxxxxxx
+ EndHTML:xxxxxxxxxx
+ StartFragment:xxxxxxxxxx
+ EndFragment:xxxxxxxxxx
+ ...html...
+
+*/
+QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const
+{
+ Q_UNUSED(preferredType);
+ QVariant result;
+ if (canConvertToMime(mime, pDataObj)) {
+ QByteArray html = getData(CF_HTML, pDataObj);
+#ifdef QMIME_DEBUG
+ qDebug("QWindowsMimeHtml::convertToMime");
+ qDebug("raw :");
+ qDebug(html);
+#endif
+ int start = html.indexOf("StartFragment:");
+ int end = html.indexOf("EndFragment:");
+
+ if (start != -1) {
+ int startOffset = start + 14;
+ int i = startOffset;
+ while (html.at(i) != '\r' && html.at(i) != '\n')
+ ++i;
+ QByteArray bytecount = html.mid(startOffset, i - startOffset);
+ start = bytecount.toInt();
+ }
+
+ if (end != -1) {
+ int endOffset = end + 12;
+ int i = endOffset ;
+ while (html.at(i) != '\r' && html.at(i) != '\n')
+ ++i;
+ QByteArray bytecount = html.mid(endOffset , i - endOffset);
+ end = bytecount.toInt();
+ }
+
+ if (end > start && start > 0) {
+ html = "<!--StartFragment-->" + html.mid(start, end - start);
+ html += "<!--EndFragment-->";
+ html.replace("\r", "");
+ result = QString::fromUtf8(html);
+ }
+ }
+ return result;
+}
+
+bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
+{
+ if (canConvertFromMime(formatetc, mimeData)) {
+ QByteArray data = mimeData->html().toUtf8();
+ QByteArray result =
+ "Version:1.0\r\n" // 0-12
+ "StartHTML:0000000105\r\n" // 13-35
+ "EndHTML:0000000000\r\n" // 36-55
+ "StartFragment:0000000000\r\n" // 58-86
+ "EndFragment:0000000000\r\n\r\n"; // 87-105
+
+ if (data.indexOf("<!--StartFragment-->") == -1)
+ result += "<!--StartFragment-->";
+ result += data;
+ if (data.indexOf("<!--EndFragment-->") == -1)
+ result += "<!--EndFragment-->";
+
+ // set the correct number for EndHTML
+ QByteArray pos = QString::number(result.size()).toLatin1();
+ memcpy((char *)(result.data() + 53 - pos.length()), pos.constData(), pos.length());
+
+ // set correct numbers for StartFragment and EndFragment
+ pos = QString::number(result.indexOf("<!--StartFragment-->") + 20).toLatin1();
+ memcpy((char *)(result.data() + 79 - pos.length()), pos.constData(), pos.length());
+ pos = QString::number(result.indexOf("<!--EndFragment-->")).toLatin1();
+ memcpy((char *)(result.data() + 103 - pos.length()), pos.constData(), pos.length());
+
+ return setData(result, pmedium);
+ }
+ return false;
+}
+
+
+#ifndef QT_NO_IMAGEFORMAT_BMP
+class QWindowsMimeImage : public QWindowsMime
+{
+public:
+ QWindowsMimeImage();
+ // for converting from Qt
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+
+ // for converting to Qt
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
+ QString mimeForFormat(const FORMATETC &formatetc) const;
+private:
+ bool hasOriginalDIBV5(IDataObject *pDataObj) const;
+ UINT CF_PNG;
+};
+
+QWindowsMimeImage::QWindowsMimeImage()
+{
+#ifdef Q_OS_WINCE
+ CF_PNG = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (QString::fromLatin1("PNG").utf16()));
+#else
+ CF_PNG = RegisterClipboardFormatA("PNG");
+#endif
+}
+
+QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+{
+ QVector<FORMATETC> formatetcs;
+ if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
+ //add DIBV5 if image has alpha channel
+ QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ if (!image.isNull() && image.hasAlphaChannel())
+ formatetcs += setCf(CF_DIBV5);
+ formatetcs += setCf(CF_DIB);
+ }
+ return formatetcs;
+}
+
+QString QWindowsMimeImage::mimeForFormat(const FORMATETC &formatetc) const
+{
+ int cf = getCf(formatetc);
+ if (cf == CF_DIB || cf == CF_DIBV5 || cf == int(CF_PNG))
+ return QLatin1String("application/x-qt-image");
+ return QString();
+}
+
+bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+{
+ if ((mimeType == QLatin1String("application/x-qt-image")) &&
+ (canGetData(CF_DIB, pDataObj) || canGetData(CF_PNG, pDataObj)))
+ return true;
+ return false;
+}
+
+bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+{
+ int cf = getCf(formatetc);
+ if (mimeData->hasImage()) {
+ if (cf == CF_DIB)
+ return true;
+ else if (cf == CF_DIBV5) {
+ //support DIBV5 conversion only if the image has alpha channel
+ QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ if (!image.isNull() && image.hasAlphaChannel())
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
+{
+ int cf = getCf(formatetc);
+ if ((cf == CF_DIB || cf == CF_DIBV5) && mimeData->hasImage()) {
+ QImage img = qvariant_cast<QImage>(mimeData->imageData());
+ if (img.isNull())
+ return false;
+ QByteArray ba;
+ QDataStream s(&ba, QIODevice::WriteOnly);
+ s.setByteOrder(QDataStream::LittleEndian);// Intel byte order ####
+ if (cf == CF_DIB) {
+ if (qt_write_dib(s, img))
+ return setData(ba, pmedium);
+ } else {
+ if (qt_write_dibv5(s, img))
+ return setData(ba, pmedium);
+ }
+ }
+ return false;
+}
+
+bool QWindowsMimeImage::hasOriginalDIBV5(IDataObject *pDataObj) const
+{
+ bool isSynthesized = true;
+ IEnumFORMATETC *pEnum =NULL;
+ HRESULT res = pDataObj->EnumFormatEtc(1, &pEnum);
+ if (res == S_OK && pEnum) {
+ FORMATETC fc;
+ while ((res = pEnum->Next(1, &fc, 0)) == S_OK) {
+ if (fc.ptd)
+ CoTaskMemFree(fc.ptd);
+ if (fc.cfFormat == CF_DIB)
+ break;
+ else if (fc.cfFormat == CF_DIBV5) {
+ isSynthesized = false;
+ break;
+ }
+ }
+ pEnum->Release();
+ }
+ return !isSynthesized;
+}
+
+QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const
+{
+ Q_UNUSED(preferredType);
+ QVariant result;
+ if (mimeType != QLatin1String("application/x-qt-image"))
+ return result;
+ //Try to convert from a format which has more data
+ //DIBV5, use only if its is not synthesized
+ if (canGetData(CF_DIBV5, pDataObj) && hasOriginalDIBV5(pDataObj)) {
+ QImage img;
+ QByteArray data = getData(CF_DIBV5, pDataObj);
+ QDataStream s(&data, QIODevice::ReadOnly);
+ s.setByteOrder(QDataStream::LittleEndian);
+ if (qt_read_dibv5(s, img)) { // #### supports only 32bit DIBV5
+ return img;
+ }
+ }
+ //PNG, MS Office place this (undocumented)
+ if (canGetData(CF_PNG, pDataObj)) {
+ QImage img;
+ QByteArray data = getData(CF_PNG, pDataObj);
+ if (img.loadFromData(data, "PNG")) {
+ return img;
+ }
+ }
+ //Fallback to DIB
+ if (canGetData(CF_DIB, pDataObj)) {
+ QImage img;
+ QByteArray data = getData(CF_DIB, pDataObj);
+ QDataStream s(&data, QIODevice::ReadOnly);
+ s.setByteOrder(QDataStream::LittleEndian);// Intel byte order ####
+ if (qt_read_dib(s, img)) { // ##### encaps "-14"
+ return img;
+ }
+ }
+ // Failed
+ return result;
+}
+#endif
+
+class QBuiltInMimes : public QWindowsMime
+{
+public:
+ QBuiltInMimes();
+
+ // for converting from Qt
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+
+ // for converting to Qt
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
+ QString mimeForFormat(const FORMATETC &formatetc) const;
+
+private:
+ QMap<int, QString> outFormats;
+ QMap<int, QString> inFormats;
+};
+
+QBuiltInMimes::QBuiltInMimes()
+: QWindowsMime()
+{
+ outFormats.insert(QWindowsMime::registerMimeType(QLatin1String("application/x-color")), QLatin1String("application/x-color"));
+ inFormats.insert(QWindowsMime::registerMimeType(QLatin1String("application/x-color")), QLatin1String("application/x-color"));
+}
+
+bool QBuiltInMimes::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+{
+ // really check
+ return formatetc.tymed & TYMED_HGLOBAL
+ && outFormats.contains(formatetc.cfFormat)
+ && mimeData->formats().contains(outFormats.value(formatetc.cfFormat));
+}
+
+bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
+{
+ if (canConvertFromMime(formatetc, mimeData)) {
+ QByteArray data;
+ if (outFormats.value(getCf(formatetc)) == QLatin1String("text/html")) {
+ // text/html is in wide chars on windows (compatible with mozillia)
+ QString html = mimeData->html();
+ // same code as in the text converter up above
+ const QChar *u = html.unicode();
+ QString res;
+ const int s = html.length();
+ int maxsize = s + s/40 + 3;
+ res.resize(maxsize);
+ int ri = 0;
+ bool cr = false;
+ for (int i=0; i < s; ++i) {
+ if (*u == QLatin1Char('\r'))
+ cr = true;
+ else {
+ if (*u == QLatin1Char('\n') && !cr)
+ res[ri++] = QLatin1Char('\r');
+ cr = false;
+ }
+ res[ri++] = *u;
+ if (ri+3 >= maxsize) {
+ maxsize += maxsize/4;
+ res.resize(maxsize);
+ }
+ ++u;
+ }
+ res.truncate(ri);
+ const int byteLength = res.length()*2;
+ QByteArray r(byteLength + 2, '\0');
+ memcpy(r.data(), res.unicode(), byteLength);
+ r[byteLength] = 0;
+ r[byteLength+1] = 0;
+ data = r;
+ } else {
+#ifndef QT_NO_DRAGANDDROP
+ data = QInternalMimeData::renderDataHelper(outFormats.value(getCf(formatetc)), mimeData);
+#endif //QT_NO_DRAGANDDROP
+ }
+ return setData(data, pmedium);
+ }
+ return false;
+}
+
+QVector<FORMATETC> QBuiltInMimes::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+{
+ QVector<FORMATETC> formatetcs;
+ if (!outFormats.keys(mimeType).isEmpty() && mimeData->formats().contains(mimeType))
+ formatetcs += setCf(outFormats.key(mimeType));
+ return formatetcs;
+}
+
+bool QBuiltInMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+{
+ return (!inFormats.keys(mimeType).isEmpty())
+ && canGetData(inFormats.key(mimeType), pDataObj);
+}
+
+QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const
+{
+ QVariant val;
+ if (canConvertToMime(mimeType, pDataObj)) {
+ QByteArray data = getData(inFormats.key(mimeType), pDataObj);
+ if (!data.isEmpty()) {
+#ifdef QMIME_DEBUG
+ qDebug("QBuiltInMimes::convertToMime()");
+#endif
+ if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) {
+ // text/html is in wide chars on windows (compatible with mozillia)
+ val = QString::fromUtf16((const unsigned short *)data.data());
+ } else {
+ val = data; // it should be enough to return the data and let QMimeData do the rest.
+ }
+ }
+ }
+ return val;
+}
+
+QString QBuiltInMimes::mimeForFormat(const FORMATETC &formatetc) const
+{
+ return inFormats.value(getCf(formatetc));
+}
+
+
+class QLastResortMimes : public QWindowsMime
+{
+public:
+
+ QLastResortMimes();
+ // for converting from Qt
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+
+ // for converting to Qt
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
+ QString mimeForFormat(const FORMATETC &formatetc) const;
+
+private:
+ QMap<int, QString> formats;
+ static QStringList ianaTypes;
+ static QStringList excludeList;
+};
+
+QStringList QLastResortMimes::ianaTypes;
+QStringList QLastResortMimes::excludeList;
+
+QLastResortMimes::QLastResortMimes()
+{
+ //MIME Media-Types
+ if (!ianaTypes.size()) {
+ ianaTypes.append(QLatin1String("application/"));
+ ianaTypes.append(QLatin1String("audio/"));
+ ianaTypes.append(QLatin1String("example/"));
+ ianaTypes.append(QLatin1String("image/"));
+ ianaTypes.append(QLatin1String("message/"));
+ ianaTypes.append(QLatin1String("model/"));
+ ianaTypes.append(QLatin1String("multipart/"));
+ ianaTypes.append(QLatin1String("text/"));
+ ianaTypes.append(QLatin1String("video/"));
+ }
+ //Types handled by other classes
+ if (!excludeList.size()) {
+ excludeList.append(QLatin1String("HTML Format"));
+ excludeList.append(QLatin1String("UniformResourceLocator"));
+ excludeList.append(QLatin1String("text/html"));
+ excludeList.append(QLatin1String("text/plain"));
+ excludeList.append(QLatin1String("text/uri-list"));
+ excludeList.append(QLatin1String("application/x-qt-image"));
+ excludeList.append(QLatin1String("application/x-color"));
+ }
+}
+
+bool QLastResortMimes::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+{
+ // really check
+#ifndef QT_NO_DRAGANDDROP
+ return formatetc.tymed & TYMED_HGLOBAL
+ && (formats.contains(formatetc.cfFormat)
+ && QInternalMimeData::hasFormatHelper(formats.value(formatetc.cfFormat), mimeData));
+#else
+ Q_UNUSED(mimeData);
+ Q_UNUSED(formatetc);
+ return formatetc.tymed & TYMED_HGLOBAL
+ && formats.contains(formatetc.cfFormat);
+#endif //QT_NO_DRAGANDDROP
+}
+
+bool QLastResortMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
+{
+#ifndef QT_NO_DRAGANDDROP
+ return canConvertFromMime(formatetc, mimeData)
+ && setData(QInternalMimeData::renderDataHelper(formats.value(getCf(formatetc)), mimeData), pmedium);
+#else
+ Q_UNUSED(mimeData);
+ Q_UNUSED(formatetc);
+ Q_UNUSED(pmedium);
+ return false;
+#endif //QT_NO_DRAGANDDROP
+}
+
+QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, const QMimeData * /*mimeData*/) const
+{
+ QVector<FORMATETC> formatetcs;
+ if (!formats.keys(mimeType).isEmpty()) {
+ formatetcs += setCf(formats.key(mimeType));
+ } else if (!excludeList.contains(mimeType, Qt::CaseInsensitive)){
+ // register any other available formats
+ int cf = QWindowsMime::registerMimeType(mimeType);
+ QLastResortMimes *that = const_cast<QLastResortMimes *>(this);
+ that->formats.insert(cf, mimeType);
+ formatetcs += setCf(cf);
+ }
+ return formatetcs;
+}
+static const char *x_qt_windows_mime = "application/x-qt-windows-mime;value=\"";
+
+bool isCustomMimeType(const QString &mimeType)
+{
+ return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive);
+}
+
+QString customMimeType(const QString &mimeType)
+{
+ int len = QString(QLatin1String(x_qt_windows_mime)).length();
+ int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len;
+ return mimeType.mid(len, n);
+}
+
+bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+{
+ if (isCustomMimeType(mimeType)) {
+ QString clipFormat = customMimeType(mimeType);
+#ifdef Q_OS_WINCE
+ int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16()));
+#else
+ int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit());
+#endif
+ return canGetData(cf, pDataObj);
+ } else if (formats.keys(mimeType).isEmpty()) {
+ // if it is not in there then register it an see if we can get it
+ int cf = QWindowsMime::registerMimeType(mimeType);
+ return canGetData(cf, pDataObj);
+ } else {
+ return canGetData(formats.key(mimeType), pDataObj);
+ }
+ return false;
+}
+
+QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const
+{
+ Q_UNUSED(preferredType);
+ QVariant val;
+ if (canConvertToMime(mimeType, pDataObj)) {
+ QByteArray data;
+ if (isCustomMimeType(mimeType)) {
+ QString clipFormat = customMimeType(mimeType);
+#ifdef Q_OS_WINCE
+ int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16()));
+#else
+ int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit());
+#endif
+ data = getData(cf, pDataObj);
+ } else if (formats.keys(mimeType).isEmpty()) {
+ int cf = QWindowsMime::registerMimeType(mimeType);
+ data = getData(cf, pDataObj);
+ } else {
+ data = getData(formats.key(mimeType), pDataObj);
+ }
+ if (!data.isEmpty())
+ val = data; // it should be enough to return the data and let QMimeData do the rest.
+ }
+ return val;
+}
+
+QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
+{
+ QString format = formats.value(getCf(formatetc));
+ if (format.isEmpty()) {
+ QByteArray ba;
+ QString clipFormat;
+ int len;
+ QT_WA({
+ ba.resize(256*2);
+ len = GetClipboardFormatNameW(getCf(formatetc), (TCHAR*)ba.data(), 255);
+ if (len)
+ clipFormat = QString::fromUtf16((ushort *)ba.data(), len);
+ } , {
+ ba.resize(256);
+ len = GetClipboardFormatNameA(getCf(formatetc), ba.data(), 255);
+ if (len)
+ clipFormat = QString::fromLocal8Bit(ba.data(), len);
+ });
+ if (len) {
+#ifndef QT_NO_DRAGANDDROP
+ if (QInternalMimeData::canReadData(clipFormat))
+ format = clipFormat;
+ else if((formatetc.cfFormat >= 0xC000)){
+ //create the mime as custom. not registered.
+ if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) {
+ //check if this is a mime type
+ bool ianaType = false;
+ int sz = ianaTypes.size();
+ for (int i = 0; i < sz; i++) {
+ if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) {
+ ianaType = true;
+ break;
+ }
+ }
+ if (!ianaType)
+ format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"');
+ else
+ format = clipFormat;
+ }
+ }
+#endif //QT_NO_DRAGANDDROP
+ }
+ }
+ return format;
+}
+
+QWindowsMimeList::QWindowsMimeList()
+ : initialized(false)
+{
+}
+
+QWindowsMimeList::~QWindowsMimeList()
+{
+ while (mimes.size())
+ delete mimes.first();
+}
+
+
+void QWindowsMimeList::init()
+{
+ if (!initialized) {
+ initialized = true;
+#ifndef QT_NO_IMAGEFORMAT_BMP
+ new QWindowsMimeImage;
+#endif
+ new QLastResortMimes;
+ new QWindowsMimeText;
+ new QWindowsMimeURI;
+
+ new QWindowsMimeHtml;
+ new QBuiltInMimes;
+ }
+}
+
+void QWindowsMimeList::addWindowsMime(QWindowsMime * mime)
+{
+ init();
+ mimes.append(mime);
+}
+
+void QWindowsMimeList::removeWindowsMime(QWindowsMime * mime)
+{
+ init();
+ mimes.removeAll(mime);
+}
+
+QList<QWindowsMime*> QWindowsMimeList::windowsMimes()
+{
+ init();
+ return mimes;
+}
+
+#ifndef QT_NO_IMAGEFORMAT_BMP
+static bool qt_write_dibv5(QDataStream &s, QImage image)
+{
+ QIODevice* d = s.device();
+ if (!d->isWritable())
+ return false;
+
+ //depth will be always 32
+ int bpl_bmp = image.width()*4;
+
+ BMP_BITMAPV5HEADER bi ={0};
+ bi.bV5Size = sizeof(BMP_BITMAPV5HEADER);
+ bi.bV5Width = image.width();
+ bi.bV5Height = image.height();
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ bi.bV5SizeImage = bpl_bmp*image.height();
+ bi.bV5XPelsPerMeter = 0;
+ bi.bV5YPelsPerMeter = 0;
+ bi.bV5ClrUsed = 0;
+ bi.bV5ClrImportant = 0;
+ bi.bV5BlueMask = 0x000000ff;
+ bi.bV5GreenMask = 0x0000ff00;
+ bi.bV5RedMask = 0x00ff0000;
+ bi.bV5AlphaMask = 0xff000000;
+ bi.bV5CSType = BMP_LCS_sRGB; //LCS_sRGB
+ bi.bV5Intent = BMP_LCS_GM_IMAGES; //LCS_GM_IMAGES
+
+ d->write(reinterpret_cast<const char*>(&bi), bi.bV5Size);
+ if (s.status() != QDataStream::Ok)
+ return false;
+
+ DWORD colorSpace[3] = {0x00ff0000,0x0000ff00,0x000000ff};
+ d->write(reinterpret_cast<const char*>(colorSpace), sizeof(colorSpace));
+ if (s.status() != QDataStream::Ok)
+ return false;
+
+ if (image.format() != QImage::Format_ARGB32)
+ image = image.convertToFormat(QImage::Format_ARGB32);
+
+ uchar *buf = new uchar[bpl_bmp];
+ uchar *b;
+
+ memset(buf, 0, bpl_bmp);
+ for (int y=image.height()-1; y>=0; y--) {
+ // write the image bits
+ QRgb *p = (QRgb *)image.scanLine(y);
+ QRgb *end = p + image.width();
+ b = buf;
+ while (p < end) {
+ int alpha = qAlpha(*p);
+ if (alpha) {
+ *b++ = qBlue(*p);
+ *b++ = qGreen(*p);
+ *b++ = qRed(*p);
+ } else {
+ //white for fully transparent pixels.
+ *b++ = 0xff;
+ *b++ = 0xff;
+ *b++ = 0xff;
+ }
+ *b++ = alpha;
+ p++;
+ }
+ d->write((char*)buf, bpl_bmp);
+ if (s.status() != QDataStream::Ok) {
+ delete[] buf;
+ return false;
+ }
+ }
+ delete[] buf;
+ return true;
+}
+
+static int calc_shift(int mask)
+{
+ int result = 0;
+ while (!(mask & 1)) {
+ result++;
+ mask >>= 1;
+ }
+ return result;
+}
+
+//Supports only 32 bit DIBV5
+static bool qt_read_dibv5(QDataStream &s, QImage &image)
+{
+ BMP_BITMAPV5HEADER bi;
+ QIODevice* d = s.device();
+ if (d->atEnd())
+ return false;
+
+ d->read((char *)&bi, sizeof(bi)); // read BITMAPV5HEADER header
+ if (s.status() != QDataStream::Ok)
+ return false;
+
+ int nbits = bi.bV5BitCount;
+ int comp = bi.bV5Compression;
+ if (nbits != 32 || bi.bV5Planes != 1 || comp != BMP_BITFIELDS)
+ return false; //Unsupported DIBV5 format
+
+ int w = bi.bV5Width, h = bi.bV5Height;
+ int red_mask = bi.bV5RedMask;
+ int green_mask = bi.bV5GreenMask;
+ int blue_mask = bi.bV5BlueMask;
+ int alpha_mask = bi.bV5AlphaMask;
+ int red_shift = 0;
+ int green_shift = 0;
+ int blue_shift = 0;
+ int alpha_shift = 0;
+ QImage::Format format = QImage::Format_ARGB32;
+
+ if (bi.bV5Height < 0)
+ h = -h; // support images with negative height
+ if (image.size() != QSize(w, h) || image.format() != format) {
+ image = QImage(w, h, format);
+ if (image.isNull()) // could not create image
+ return false;
+ }
+ image.setDotsPerMeterX(bi.bV5XPelsPerMeter);
+ image.setDotsPerMeterY(bi.bV5YPelsPerMeter);
+ // read color table
+ DWORD colorSpace[3];
+ if (d->read((char *)colorSpace, sizeof(colorSpace)) != sizeof(colorSpace))
+ return false;
+
+ red_shift = calc_shift(red_mask);
+ green_shift = calc_shift(green_mask);
+ blue_shift = calc_shift(blue_mask);
+ if (alpha_mask) {
+ alpha_shift = calc_shift(alpha_mask);
+ }
+
+ int bpl = image.bytesPerLine();
+ uchar *data = image.bits();
+ register QRgb *p;
+ QRgb *end;
+ uchar *buf24 = new uchar[bpl];
+ int bpl24 = ((w*nbits+31)/32)*4;
+ uchar *b;
+ unsigned int c;
+
+ while (--h >= 0) {
+ p = (QRgb *)(data + h*bpl);
+ end = p + w;
+ if (d->read((char *)buf24,bpl24) != bpl24)
+ break;
+ b = buf24;
+ while (p < end) {
+ c = *b | (*(b+1))<<8 | (*(b+2))<<16 | (*(b+3))<<24;
+ *p++ = qRgba(((c & red_mask) >> red_shift) ,
+ ((c & green_mask) >> green_shift),
+ ((c & blue_mask) >> blue_shift),
+ ((c & alpha_mask) >> alpha_shift));
+ b += 4;
+ }
+ }
+ delete[] buf24;
+
+ if (bi.bV5Height < 0) {
+ // Flip the image
+ uchar *buf = new uchar[bpl];
+ h = -bi.bV5Height;
+ for (int y = 0; y < h/2; ++y) {
+ memcpy(buf, data + y*bpl, bpl);
+ memcpy(data + y*bpl, data + (h-y-1)*bpl, bpl);
+ memcpy(data + (h-y-1)*bpl, buf, bpl);
+ }
+ delete [] buf;
+ }
+
+ return true;
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qmotifdnd_x11.cpp b/src/gui/kernel/qmotifdnd_x11.cpp
new file mode 100644
index 0000000000..5c6790419a
--- /dev/null
+++ b/src/gui/kernel/qmotifdnd_x11.cpp
@@ -0,0 +1,1028 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* The following copyright notice pertains to the code as contributed
+to Trolltech, not to Trolltech's modifications. It is replicated
+in doc/dnd.doc, where the documentation system can see it. */
+
+/* Copyright 1996 Daniel Dardailler.
+
+ Permission to use, copy, modify, distribute, and sell this software
+ for any purpose is hereby granted without fee, provided that the above
+ copyright notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting documentation,
+ and that the name of Daniel Dardailler not be used in advertising or
+ publicity pertaining to distribution of the software without specific,
+ written prior permission. Daniel Dardailler makes no representations
+ about the suitability of this software for any purpose. It is
+ provided "as is" without express or implied warranty.
+
+ Modifications Copyright 1999 Matt Koss, under the same license as
+ above.
+************************************************************/
+
+/***********************************************************/
+/* Motif Drag&Drop Dynamic Protocol messaging API code */
+/* Only requires Xlib layer - not MT safe */
+/* Author: Daniel Dardailler, daniel@x.org */
+/* Adapted by: Matt Koss, koss@napri.sk */
+/* Further adaptions by: Nokia Corporation and/or its subsidiary(-ies) */
+/***********************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qapplication.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+#include "qdebug.h"
+#include "qtextcodec.h"
+#include "qwidget.h"
+#include "qevent.h"
+#include "qt_x11_p.h"
+#include "qx11info_x11.h"
+#include "qiodevice.h"
+#include "qdnd_p.h"
+
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+static Window sourceWindow = XNone;
+static QWidget *dropWidget = 0;
+static Qt::DropAction lastAcceptedAction = Qt::IgnoreAction;
+
+static Atom Dnd_selection = 0;
+static Time Dnd_selection_time;
+
+static Atom * src_targets ;
+static ushort num_src_targets ;
+
+// Motif definitions
+#define DndVersion 1
+#define DndRevision 0
+#define DndIncludeVersion (DndVersion * 10 + DndRevision)
+
+/* The following values are used in the DndData structure */
+
+/* protocol style */
+#define DND_DRAG_NONE 0
+#define DND_DRAG_DROP_ONLY 1
+#define DND_DRAG_DYNAMIC 5
+
+/* message type */
+#define DND_TOP_LEVEL_ENTER 0
+#define DND_TOP_LEVEL_LEAVE 1
+#define DND_DRAG_MOTION 2
+#define DND_DROP_SITE_ENTER 3
+#define DND_DROP_SITE_LEAVE 4
+#define DND_DROP_START 5
+#define DND_OPERATION_CHANGED 8
+
+/* operation(s) */
+#define DND_NOOP 0L
+#define DND_MOVE (1L << 0)
+#define DND_COPY (1L << 1)
+#define DND_LINK (1L << 2)
+
+static Qt::DropActions DndOperationsToQtDropActions(uchar op)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ if (op | DND_MOVE)
+ actions |= Qt::MoveAction;
+ if (op | DND_COPY)
+ actions |= Qt::CopyAction;
+ if (op | DND_LINK)
+ actions |= Qt::LinkAction;
+ return actions;
+}
+
+static uchar QtDropActionToDndOperation(Qt::DropAction action)
+{
+ switch (action & Qt::ActionMask) {
+ case Qt::CopyAction:
+ default:
+ return DND_COPY;
+ case Qt::MoveAction:
+ return DND_MOVE;
+ case Qt::LinkAction:
+ return DND_LINK;
+ }
+}
+
+
+/* status */
+#define DND_NO_DROP_SITE 1
+#define DND_INVALID_DROP_SITE 2
+#define DND_VALID_DROP_SITE 3
+
+/* completion */
+#define DND_DROP 0
+#define DND_DROP_HELP 1
+#define DND_DROP_CANCEL 2
+
+#define BYTE unsigned char
+#define CARD32 unsigned int
+#define CARD16 unsigned short
+#define INT16 signed short
+
+/* Client side structure used in the API */
+typedef struct {
+ unsigned char reason; /* message type: DND_TOP_LEVEL_ENTER, etc */
+ Time time ;
+ unsigned char operation;
+ unsigned char operations;
+ unsigned char status;
+ unsigned char completion;
+ short x ;
+ short y ;
+ Window src_window ;
+ Atom property ;
+} DndData ;
+
+
+typedef struct _DndSrcProp {
+ BYTE byte_order ;
+ BYTE protocol_version ;
+ CARD16 target_index ;
+ CARD32 selection ;
+} DndSrcProp ;
+
+typedef struct _DndReceiverProp {
+ BYTE byte_order ;
+ BYTE protocol_version ;
+ BYTE protocol_style ;
+ BYTE pad1;
+ CARD32 proxy_window;
+ CARD16 num_drop_sites ;
+ CARD16 pad2;
+ CARD32 total_size;
+} DndReceiverProp ;
+
+/* need to use some union hack since window and property are in
+ different order depending on the message ... */
+typedef struct _DndTop {
+ CARD32 src_window;
+ CARD32 property;
+} DndTop ;
+
+typedef struct _DndPot {
+ INT16 x;
+ INT16 y;
+ CARD32 property;
+ CARD32 src_window;
+} DndPot ;
+
+typedef struct _DndMessage {
+ BYTE reason;
+ BYTE byte_order;
+ CARD16 flags;
+ CARD32 time;
+ union {
+ DndTop top ;
+ DndPot pot ;
+ } data ;
+} DndMessage ;
+
+typedef struct {
+ BYTE byte_order;
+ BYTE protocol_version;
+ CARD16 num_target_lists;
+ CARD32 data_size;
+ /* then come series of CARD16,CARD32,CARD32,CARD32... */
+} DndTargets;
+
+
+/* protocol version */
+#define DND_PROTOCOL_VERSION 0
+
+
+#define DND_EVENT_TYPE_MASK ((BYTE)0x80)
+#define DND_EVENT_TYPE_SHIFT 7
+#define DND_CLEAR_EVENT_TYPE ((BYTE)0x7F)
+
+/* message_type is data[0] of the client_message
+ this return 1 (receiver bit up) or 0 (initiator) */
+#define DND_GET_EVENT_TYPE(message_type) \
+((char) (((message_type) & DND_EVENT_TYPE_MASK) >> DND_EVENT_TYPE_SHIFT))
+
+/* event_type can be 0 (initiator) or 1 (receiver) */
+#define DND_SET_EVENT_TYPE(event_type) \
+(((BYTE)(event_type) << DND_EVENT_TYPE_SHIFT) & DND_EVENT_TYPE_MASK)
+
+
+#define DND_OPERATION_MASK ((CARD16) 0x000F)
+#define DND_OPERATION_SHIFT 0
+#define DND_STATUS_MASK ((CARD16) 0x00F0)
+#define DND_STATUS_SHIFT 4
+#define DND_OPERATIONS_MASK ((CARD16) 0x0F00)
+#define DND_OPERATIONS_SHIFT 8
+#define DND_COMPLETION_MASK ((CARD16) 0xF000)
+#define DND_COMPLETION_SHIFT 12
+
+#define DND_GET_OPERATION(flags) \
+((unsigned char) \
+(((flags) & DND_OPERATION_MASK) >> DND_OPERATION_SHIFT))
+
+#define DND_SET_OPERATION(operation) \
+(((CARD16)(operation) << DND_OPERATION_SHIFT)\
+& DND_OPERATION_MASK)
+
+#define DND_GET_STATUS(flags) \
+((unsigned char) \
+(((flags) & DND_STATUS_MASK) >> DND_STATUS_SHIFT))
+
+#define DND_SET_STATUS(status) \
+(((CARD16)(status) << DND_STATUS_SHIFT)\
+& DND_STATUS_MASK)
+
+#define DND_GET_OPERATIONS(flags) \
+((unsigned char) \
+(((flags) & DND_OPERATIONS_MASK) >> DND_OPERATIONS_SHIFT))
+
+#define DND_SET_OPERATIONS(operation) \
+(((CARD16)(operation) << DND_OPERATIONS_SHIFT)\
+& DND_OPERATIONS_MASK)
+
+#define DND_GET_COMPLETION(flags) \
+((unsigned char) \
+(((flags) & DND_COMPLETION_MASK) >> DND_COMPLETION_SHIFT))
+
+#define DND_SET_COMPLETION(completion) \
+(((CARD16)(completion) << DND_COMPLETION_SHIFT)\
+& DND_COMPLETION_MASK)
+
+
+#define SWAP4BYTES(l) {\
+struct { unsigned t :32;} bit32;\
+char n, *tp = (char *) &bit32;\
+bit32.t = l;\
+n = tp[0]; tp[0] = tp[3]; tp[3] = n;\
+n = tp[1]; tp[1] = tp[2]; tp[2] = n;\
+l = bit32.t;\
+}
+
+#define SWAP2BYTES(s) {\
+struct { unsigned t :16; } bit16;\
+char n, *tp = (char *) &bit16;\
+bit16.t = s;\
+n = tp[0]; tp[0] = tp[1]; tp[1] = n;\
+s = bit16.t;\
+}
+
+
+/** Private extern functions */
+
+static unsigned char DndByteOrder ();
+
+
+/***** Targets/Index stuff */
+
+typedef struct {
+ int num_targets;
+ Atom *targets;
+} DndTargetsTableEntryRec, * DndTargetsTableEntry;
+
+typedef struct {
+ int num_entries;
+ DndTargetsTableEntry entries;
+} DndTargetsTableRec, * DndTargetsTable;
+
+
+static ushort _DndIndexToTargets(Display * display,
+ int index,
+ Atom ** targets);
+
+extern void qt_x11_intern_atom(const char *, Atom *);
+
+/////////////////////////////////////////////////////////////////
+
+static unsigned char DndByteOrder ()
+{
+ static unsigned char byte_order = 0;
+
+ if (!byte_order) {
+ unsigned int endian = 1;
+ byte_order = (*((char *)&endian))?'l':'B';
+ }
+ return byte_order ;
+}
+
+
+
+static void DndReadSourceProperty(Display * dpy,
+ Window window, Atom dnd_selection,
+ Atom ** targets, unsigned short * num_targets)
+{
+ unsigned char *retval = 0;
+ Atom type ;
+ int format ;
+ unsigned long bytesafter, lengthRtn;
+
+ if ((XGetWindowProperty (dpy, window, dnd_selection, 0L, 100000L,
+ False, ATOM(_MOTIF_DRAG_INITIATOR_INFO), &type,
+ &format, &lengthRtn, &bytesafter,
+ &retval) != Success)
+ || (type == XNone)) {
+ *num_targets = 0;
+ return ;
+ }
+
+ DndSrcProp * src_prop = (DndSrcProp *)retval;
+
+ if (src_prop->byte_order != DndByteOrder()) {
+ SWAP2BYTES(src_prop->target_index);
+ SWAP4BYTES(src_prop->selection);
+ }
+
+ *num_targets = _DndIndexToTargets(dpy, src_prop->target_index, targets);
+
+ XFree((char*)src_prop);
+}
+
+
+/* Position the _MOTIF_DRAG_RECEIVER_INFO property on the dropsite window.
+ Called by the receiver of the drop to indicate the
+ supported protocol style : dynamic, drop_only or none */
+static void DndWriteReceiverProperty(Display * dpy, Window window,
+ unsigned char protocol_style)
+{
+ DndReceiverProp receiver_prop ;
+
+ receiver_prop.byte_order = DndByteOrder() ;
+ receiver_prop.protocol_version = DND_PROTOCOL_VERSION;
+ receiver_prop.protocol_style = protocol_style ;
+ receiver_prop.proxy_window = XNone ;
+ receiver_prop.num_drop_sites = 0 ;
+ receiver_prop.total_size = sizeof(DndReceiverProp);
+
+ /* write the buffer to the property */
+ XChangeProperty (dpy, window, ATOM(_MOTIF_DRAG_RECEIVER_INFO), ATOM(_MOTIF_DRAG_RECEIVER_INFO),
+ 8, PropModeReplace,
+ (unsigned char *)&receiver_prop,
+ sizeof(DndReceiverProp));
+}
+
+
+/* protocol style equiv (preregister stuff really) */
+#define DND_DRAG_DROP_ONLY_EQUIV 3
+#define DND_DRAG_DYNAMIC_EQUIV1 2
+#define DND_DRAG_DYNAMIC_EQUIV2 4
+
+
+/* Produce a client message to be sent by the caller */
+static void DndFillClientMessage(Display * dpy, Window window,
+ XClientMessageEvent *cm,
+ DndData * dnd_data,
+ char receiver)
+{
+ DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ;
+
+ cm->display = dpy;
+ cm->type = ClientMessage;
+ cm->serial = LastKnownRequestProcessed(dpy);
+ cm->send_event = True;
+ cm->window = window;
+ cm->format = 8;
+ cm->message_type = ATOM(_MOTIF_DRAG_AND_DROP_MESSAGE);
+
+ dnd_message->reason = dnd_data->reason | DND_SET_EVENT_TYPE(receiver);
+
+ dnd_message->byte_order = DndByteOrder();
+
+ /* we're filling in flags with more stuff that necessary,
+ depending on the reason, but it doesn't matter */
+ dnd_message->flags = 0 ;
+ dnd_message->flags |= DND_SET_STATUS(dnd_data->status) ;
+ dnd_message->flags |= DND_SET_OPERATION(dnd_data->operation) ;
+ dnd_message->flags |= DND_SET_OPERATIONS(dnd_data->operations) ;
+ dnd_message->flags |= DND_SET_COMPLETION(dnd_data->completion) ;
+
+ dnd_message->time = dnd_data->time ;
+
+ switch(dnd_data->reason) {
+ case DND_DROP_SITE_LEAVE: break ;
+ case DND_TOP_LEVEL_ENTER:
+ case DND_TOP_LEVEL_LEAVE:
+ dnd_message->data.top.src_window = dnd_data->src_window ;
+ dnd_message->data.top.property = dnd_data->property ;
+ break ; /* cannot fall through since the byte layout is different in
+ both set of messages, see top and pot union stuff */
+
+ case DND_DRAG_MOTION:
+ case DND_OPERATION_CHANGED:
+ case DND_DROP_SITE_ENTER:
+ case DND_DROP_START:
+ dnd_message->data.pot.x = dnd_data->x ; /* mouse position */
+ dnd_message->data.pot.y = dnd_data->y ;
+ dnd_message->data.pot.src_window = dnd_data->src_window ;
+ dnd_message->data.pot.property = dnd_data->property ;
+ break ;
+ default:
+ break ;
+ }
+
+}
+
+static Bool DndParseClientMessage(XClientMessageEvent *cm, DndData * dnd_data,
+ char * receiver)
+{
+ DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ;
+
+ if (cm->message_type != ATOM(_MOTIF_DRAG_AND_DROP_MESSAGE)) {
+ return False ;
+ }
+
+ if (dnd_message->byte_order != DndByteOrder()) {
+ SWAP2BYTES(dnd_message->flags);
+ SWAP4BYTES(dnd_message->time);
+ } /* do the rest in the switch */
+
+ dnd_data->reason = dnd_message->reason ;
+ if (DND_GET_EVENT_TYPE(dnd_data->reason))
+ *receiver = 1 ;
+ else
+ *receiver = 0 ;
+ dnd_data->reason &= DND_CLEAR_EVENT_TYPE ;
+
+ dnd_data->time = dnd_message->time ;
+
+ /* we're reading in more stuff that necessary. but who cares */
+ dnd_data->status = DND_GET_STATUS(dnd_message->flags) ;
+ dnd_data->operation = DND_GET_OPERATION(dnd_message->flags) ;
+ dnd_data->operations = DND_GET_OPERATIONS(dnd_message->flags) ;
+ dnd_data->completion = DND_GET_COMPLETION(dnd_message->flags) ;
+
+ switch(dnd_data->reason) {
+ case DND_TOP_LEVEL_ENTER:
+ case DND_TOP_LEVEL_LEAVE:
+ if (dnd_message->byte_order != DndByteOrder()) {
+ SWAP4BYTES(dnd_message->data.top.src_window);
+ SWAP4BYTES(dnd_message->data.top.property);
+ }
+ dnd_data->src_window = dnd_message->data.top.src_window ;
+ dnd_data->property = dnd_message->data.top.property ;
+ break ; /* cannot fall through, see above comment in write msg */
+
+ case DND_DRAG_MOTION:
+ case DND_OPERATION_CHANGED:
+ case DND_DROP_SITE_ENTER:
+ case DND_DROP_START:
+ if (dnd_message->byte_order != DndByteOrder()) {
+ SWAP2BYTES(dnd_message->data.pot.x);
+ SWAP2BYTES(dnd_message->data.pot.y);
+ SWAP4BYTES(dnd_message->data.pot.property);
+ SWAP4BYTES(dnd_message->data.pot.src_window);
+ }
+ dnd_data->x = dnd_message->data.pot.x ;
+ dnd_data->y = dnd_message->data.pot.y ;
+ dnd_data->property = dnd_message->data.pot.property ;
+ dnd_data->src_window = dnd_message->data.pot.src_window ;
+ break ;
+
+ case DND_DROP_SITE_LEAVE:
+ break;
+ default:
+ break ;
+ }
+
+ return True ;
+}
+
+
+static Window MotifWindow(Display *display)
+{
+ Atom type;
+ int format;
+ unsigned long size;
+ unsigned long bytes_after;
+ unsigned char *property = 0;
+ Window motif_window ;
+
+ /* this version does no caching, so it's slow: round trip each time */
+
+ if ((XGetWindowProperty (display, RootWindow(display, 0),
+ ATOM(_MOTIF_DRAG_WINDOW),
+ 0L, 100000L, False, AnyPropertyType,
+ &type, &format, &size, &bytes_after,
+ &property) == Success) &&
+ (type != XNone)) {
+ motif_window = *(Window *)property;
+ } else {
+ XSetWindowAttributes sAttributes;
+
+ /* really, this should be done on a separate connection,
+ with XSetCloseDownMode (RetainPermanent), so that
+ others don't have to recreate it; hopefully, some real
+ Motif application will be around to do it */
+
+ sAttributes.override_redirect = True;
+ sAttributes.event_mask = PropertyChangeMask;
+ motif_window = XCreateWindow (display,
+ RootWindow (display, 0),
+ -170, -560, 1, 1, 0, 0,
+ InputOnly, CopyFromParent,
+ (CWOverrideRedirect |CWEventMask),
+ &sAttributes);
+ XMapWindow (display, motif_window);
+ }
+
+ if (property) {
+ XFree ((char *)property);
+ }
+
+ return (motif_window);
+}
+
+
+static DndTargetsTable TargetsTable(Display *display)
+{
+ Atom type;
+ int format;
+ unsigned long size;
+ unsigned long bytes_after;
+ Window motif_window = MotifWindow(display) ;
+ unsigned char *retval;
+ DndTargetsTable targets_table ;
+ int i,j ;
+ char * target_data ;
+
+ /* this version does no caching, so it's slow: round trip each time */
+ /* ideally, register for property notify on this target_list
+ atom and update when necessary only */
+
+ if ((XGetWindowProperty (display, motif_window,
+ ATOM(_MOTIF_DRAG_TARGETS), 0L, 100000L,
+ False, ATOM(_MOTIF_DRAG_TARGETS),
+ &type, &format, &size, &bytes_after,
+ &retval) != Success) ||
+ type == XNone) {
+ qWarning("QMotifDND: Cannot get property on Motif window");
+ return 0;
+ }
+
+ DndTargets * target_prop = (DndTargets *)retval;
+
+ if (target_prop->protocol_version != DND_PROTOCOL_VERSION) {
+ qWarning("QMotifDND: Protocol mismatch");
+ }
+
+ if (target_prop->byte_order != DndByteOrder()) {
+ /* need to swap num_target_lists and size */
+ SWAP2BYTES(target_prop->num_target_lists);
+ SWAP4BYTES(target_prop->data_size);
+ }
+
+ /* now parse DndTarget prop data in a TargetsTable */
+
+ targets_table = (DndTargetsTable)malloc(sizeof(DndTargetsTableRec));
+ targets_table->num_entries = target_prop->num_target_lists ;
+ targets_table->entries = (DndTargetsTableEntry)
+ malloc(sizeof(DndTargetsTableEntryRec) * target_prop->num_target_lists);
+
+ target_data = (char*)target_prop + sizeof(*target_prop) ;
+
+ for (i = 0 ; i < targets_table->num_entries; i++) {
+ CARD16 num_targets ;
+ CARD32 atom ;
+
+ memcpy(&num_targets, target_data, 2);
+ target_data += 2;
+
+ /* potential swap needed here */
+ if (target_prop->byte_order != DndByteOrder())
+ SWAP2BYTES(num_targets);
+
+ targets_table->entries[i].num_targets = num_targets ;
+ targets_table->entries[i].targets = (Atom *)
+ malloc(sizeof(Atom) * targets_table->entries[i].num_targets);
+
+
+ for (j = 0; j < num_targets; j++) {
+ memcpy(&atom, target_data, 4);
+ target_data += 4;
+
+ /* another potential swap needed here */
+ if (target_prop->byte_order != DndByteOrder())
+ SWAP4BYTES(atom);
+
+ targets_table->entries[i].targets[j] = (Atom) atom ;
+ }
+ }
+
+ if (target_prop) {
+ XFree((char *)target_prop);
+ }
+
+ return targets_table ;
+}
+
+
+static ushort _DndIndexToTargets(Display * display,
+ int index,
+ Atom ** targets)
+{
+ DndTargetsTable targets_table;
+ int i ;
+
+ /* again, slow: no caching here, alloc/free each time */
+
+ if (!(targets_table = TargetsTable (display)) ||
+ (index >= targets_table->num_entries)) {
+ if (targets_table)
+ XFree((char*)targets_table);
+ return 0;
+ }
+
+ /* transfer the correct target list index */
+ *targets = (Atom*)malloc(sizeof(Atom)*targets_table->
+ entries[index].num_targets);
+ memcpy((char*)*targets,
+ (char*)targets_table->entries[index].targets,
+ sizeof(Atom)*targets_table->entries[index].num_targets);
+
+ /* free the target table and its guts */
+ for (i=0 ; i < targets_table->num_entries; i++)
+ XFree((char*)targets_table->entries[i].targets);
+
+ int tmp = targets_table->entries[index].num_targets;
+ XFree((char*)targets_table);
+
+ return tmp; // targets_table->entries[index].num_targets;
+}
+
+
+QByteArray QX11Data::motifdndFormat(int n)
+{
+ if (!motifdnd_active)
+ return 0; // should not happen
+
+ if (n >= num_src_targets)
+ return 0;
+
+ Atom target = src_targets[n];
+
+ if (target == XA_STRING)
+ return "text/plain;charset=ISO-8859-1";
+ if (target == ATOM(UTF8_STRING))
+ return "text/plain;charset=UTF-8";
+ if (target == ATOM(COMPOUND_TEXT))
+ return QByteArray("text/plain;charset=") + QTextCodec::codecForLocale()->name();
+ if (target == ATOM(TEXT))
+ return "text/plain";
+
+ return ("x-motif-dnd/" + X11->xdndAtomToString(target));
+}
+
+
+QVariant QX11Data::motifdndObtainData(const char *mimeType)
+{
+ QByteArray result;
+
+ if (Dnd_selection == 0 || !dropWidget)
+ return result;
+
+ // try to convert the selection to the requested property
+ // qDebug("trying to convert to '%s'", mimeType);
+
+ int n=0;
+ QByteArray f;
+ do {
+ f = motifdndFormat(n);
+ if (f.isEmpty())
+ return result;
+ n++;
+ } while(qstricmp(mimeType, f.data()));
+
+ Atom conversion_type = XNone;
+ if (f == "text/plain;charset=ISO-8859-1") {
+ conversion_type = XA_STRING;
+ } else if (f == "text/plain;charset=UTF-8") {
+ conversion_type = ATOM(UTF8_STRING);
+ } else if (f == (QByteArray("text/plain;charset=") + QTextCodec::codecForLocale()->name())) {
+ conversion_type = ATOM(COMPOUND_TEXT);
+ } else if (f == "text/plain") {
+ conversion_type = ATOM(TEXT);
+ } else if (f.startsWith("x-motif-dnd/")) {
+ // strip off the "x-motif-dnd/" prefix
+ conversion_type = X11->xdndStringToAtom(f.remove(0, 12));
+ }
+
+ if (XGetSelectionOwner(X11->display, Dnd_selection) == XNone) {
+ return result; // should never happen?
+ }
+
+ QWidget* tw = dropWidget;
+ if ((dropWidget->windowType() == Qt::Desktop)) {
+ tw = new QWidget;
+ }
+
+ // convert selection to the appropriate type
+ XConvertSelection (X11->display, Dnd_selection, conversion_type,
+ Dnd_selection, tw->internalWinId(), Dnd_selection_time);
+
+ XFlush(X11->display);
+
+ XEvent xevent;
+ bool got=X11->clipboardWaitForEvent(tw->internalWinId(), SelectionNotify, &xevent, 5000);
+ if (got) {
+ Atom type;
+
+ if (X11->clipboardReadProperty(tw->internalWinId(), Dnd_selection, true, &result, 0, &type, 0, false)) {
+ }
+ }
+
+ // we have to convert selection in order to indicate success to the initiator
+ XConvertSelection (X11->display, Dnd_selection, ATOM(XmTRANSFER_SUCCESS),
+ Dnd_selection, tw->internalWinId(), Dnd_selection_time);
+
+ // wait again for SelectionNotify event
+ X11->clipboardWaitForEvent(tw->internalWinId(), SelectionNotify, &xevent, 5000);
+
+ if ((dropWidget->windowType() == Qt::Desktop)) {
+ delete tw;
+ }
+
+ return result;
+}
+
+
+void QX11Data::motifdndEnable(QWidget *widget, bool)
+{
+ DndWriteReceiverProperty(display, widget->internalWinId(), DND_DRAG_DYNAMIC);
+}
+
+
+void QX11Data::motifdndHandle(QWidget *widget, const XEvent * xe, bool /* passive */)
+{
+ XEvent event = *xe;
+ XClientMessageEvent cm ;
+ DndData dnd_data ;
+ char receiver ;
+
+ if (!(DndParseClientMessage ((XClientMessageEvent*)&event,
+ &dnd_data, &receiver))) {
+ return;
+ }
+
+ switch (dnd_data.reason) {
+
+ case DND_DRAG_MOTION:
+ {
+ QPoint p = widget->mapFromGlobal(QPoint(dnd_data.x, dnd_data.y));
+ QWidget *c = widget->childAt(p);
+
+ if (!c || !c->acceptDrops()) {
+ // not over a drop site
+ if (dropWidget) {
+ QDragLeaveEvent dragLeaveEvent;
+ QApplication::sendEvent(dropWidget, &dragLeaveEvent);
+
+ dropWidget = 0;
+ lastAcceptedAction = Qt::IgnoreAction;
+
+ dnd_data.reason = DND_DROP_SITE_LEAVE;
+ dnd_data.time = X11->time;
+ DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver);
+ XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ;
+ } else {
+ dnd_data.reason = DND_DRAG_MOTION;
+ dnd_data.status = DND_NO_DROP_SITE;
+ dnd_data.time = X11->time;
+ dnd_data.operation = DND_NOOP;
+ dnd_data.operations = DND_NOOP;
+ DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver);
+ XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ;
+ }
+ } else {
+ Q_ASSERT(c != 0);
+ p = c->mapFrom(widget, p);
+
+ if (dropWidget != c) {
+ if (dropWidget) {
+ QDragLeaveEvent le;
+ QApplication::sendEvent(dropWidget, &le);
+ }
+
+ dropWidget = c;
+ lastAcceptedAction = Qt::IgnoreAction;
+
+ const Qt::DropActions possibleActions =
+ DndOperationsToQtDropActions(dnd_data.operations);
+ QDragEnterEvent de(p, possibleActions, QDragManager::self()->dropData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ QApplication::sendEvent(dropWidget, &de);
+
+ dnd_data.reason = DND_DROP_SITE_ENTER;
+ dnd_data.time = X11->time;
+ if (de.isAccepted()) {
+ lastAcceptedAction = de.dropAction();
+
+ dnd_data.status = DND_VALID_DROP_SITE;
+ dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction);
+ } else {
+ dnd_data.status = DND_INVALID_DROP_SITE;
+ dnd_data.operation = DND_NOOP;
+ dnd_data.operations = DND_NOOP;
+ }
+ DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver);
+ XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm);
+ } else {
+ const Qt::DropActions possibleActions =
+ DndOperationsToQtDropActions(dnd_data.operations);
+ QDragMoveEvent me(p, possibleActions, QDragManager::self()->dropData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ if (lastAcceptedAction != Qt::IgnoreAction) {
+ me.setDropAction(lastAcceptedAction);
+ me.accept();
+ }
+ QApplication::sendEvent(dropWidget, &me);
+
+ dnd_data.reason = DND_DRAG_MOTION;
+ dnd_data.time = X11->time;
+
+ if (me.isAccepted()) {
+ lastAcceptedAction = me.dropAction();
+
+ dnd_data.status = DND_VALID_DROP_SITE;
+ dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction);
+ } else {
+ dnd_data.status = DND_INVALID_DROP_SITE;
+ dnd_data.operation = DND_NOOP;
+ dnd_data.operations = DND_NOOP;
+ }
+
+ DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver);
+ XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm);
+ }
+ }
+
+ break;
+ }
+
+ case DND_TOP_LEVEL_ENTER:
+ {
+ /* get the size of our drop site for later use */
+
+ motifdnd_active = true;
+ sourceWindow = dnd_data.src_window;
+
+ /* no answer needed, just read source property */
+ DndReadSourceProperty (event.xclient.display,
+ sourceWindow,
+ dnd_data.property,
+ &src_targets, &num_src_targets);
+
+ break;
+ }
+
+ case DND_TOP_LEVEL_LEAVE:
+ {
+ XEvent nextEvent;
+ if (XCheckTypedWindowEvent(X11->display, widget->winId(), ClientMessage, &nextEvent)) {
+ // we just want to check, not eat (should use XPeekIfEvent)
+ XPutBackEvent(X11->display, &nextEvent);
+
+ if (DndParseClientMessage (&nextEvent.xclient, &dnd_data, &receiver)
+ && dnd_data.reason == DND_DROP_START) {
+ // expecting drop next, keeping DnD alive
+ break;
+ }
+ }
+
+ // not expecting drop, need to send drag leave events and such here
+ if (dropWidget) {
+ QDragLeaveEvent le;
+ QApplication::sendEvent(dropWidget, &le);
+ }
+
+ sourceWindow = XNone;
+ dropWidget = 0;
+ lastAcceptedAction = Qt::IgnoreAction;
+
+ motifdnd_active = false;
+
+ break;
+ }
+
+ case DND_OPERATION_CHANGED:
+ // ### need to echo
+ break;
+
+ case DND_DROP_START:
+ {
+ Q_ASSERT(motifdnd_active);
+ Q_ASSERT(sourceWindow == dnd_data.src_window);
+
+ if (!dropWidget || lastAcceptedAction == Qt::IgnoreAction) {
+ // echo DROP_START
+ dnd_data.reason = DND_DROP_START;
+ dnd_data.status = DND_NO_DROP_SITE;
+ dnd_data.operation = DND_NOOP;
+ dnd_data.operations = DND_NOOP;
+ DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0);
+ XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm);
+
+ // we have to convert selection in order to indicate failure to the initiator
+ XConvertSelection (X11->display, dnd_data.property, ATOM(XmTRANSFER_FAILURE),
+ dnd_data.property, dnd_data.src_window, dnd_data.time);
+
+ if (dropWidget) {
+ QDragLeaveEvent e;
+ QApplication::sendEvent(dropWidget, &e);
+ }
+
+ motifdnd_active = false;
+ sourceWindow = XNone;
+ dropWidget = 0;
+ lastAcceptedAction = Qt::IgnoreAction;
+
+ return;
+ }
+
+ // store selection and its time
+ Dnd_selection = dnd_data.property;
+ Dnd_selection_time = dnd_data.time;
+
+ QPoint p(dnd_data.x, dnd_data.y);
+ QDropEvent de(dropWidget->mapFromGlobal(p), Qt::CopyAction, QDragManager::self()->dropData,
+ QApplication::mouseButtons(), QApplication::keyboardModifiers());
+ if (lastAcceptedAction != Qt::IgnoreAction) {
+ de.setDropAction(lastAcceptedAction);
+ de.accept();
+ }
+ QApplication::sendEvent(dropWidget, &de);
+
+ // reset
+ Dnd_selection = XNone;
+ Dnd_selection_time = 0;
+
+ // echo DROP_START depending on the result of the dropEvent
+ if (de.isAccepted()) {
+ dnd_data.reason = DND_DROP_START;
+ dnd_data.status = DND_VALID_DROP_SITE;
+ dnd_data.operation = QtDropActionToDndOperation(de.dropAction());
+ } else {
+ dnd_data.reason = DND_DROP_START;
+ dnd_data.status = DND_NO_DROP_SITE;
+ dnd_data.operation = DND_NOOP;
+ dnd_data.operations = DND_NOOP;
+ }
+ DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0);
+ XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm);
+
+ sourceWindow = XNone;
+ dropWidget = 0;
+ lastAcceptedAction = Qt::IgnoreAction;
+
+ motifdnd_active = false;
+
+ break;
+ }
+
+ default:
+ break;
+ } // end of switch (dnd_data.reason)
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qnsframeview_mac_p.h b/src/gui/kernel/qnsframeview_mac_p.h
new file mode 100644
index 0000000000..14e8763eab
--- /dev/null
+++ b/src/gui/kernel/qnsframeview_mac_p.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Private AppKit class (dumped from classdump).
+
+#import <Cocoa/Cocoa.h>
+
+@interface NSFrameView : NSView
+{
+ unsigned int styleMask;
+ NSString *_title;
+ NSCell *titleCell;
+ NSButton *closeButton;
+ NSButton *zoomButton;
+ NSButton *minimizeButton;
+ char resizeByIncrement;
+ char frameNeedsDisplay;
+ unsigned char tabViewCount;
+ NSSize resizeParameter;
+ int shadowState;
+}
+
++ (void)initialize;
++ (void)initTitleCell:fp8 styleMask:(unsigned int)fp12;
++ (struct _NSRect)frameRectForContentRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24;
++ (struct _NSRect)contentRectForFrameRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24;
++ (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16;
++ (struct _NSSize)minContentSizeForMinFrameSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16;
++ (float)minFrameWidthWithTitle:fp8 styleMask:(unsigned int)fp12;
++ (unsigned int)_validateStyleMask:(unsigned int)fp8;
+- initWithFrame:(struct _NSRect)fp8 styleMask:(unsigned int)fp24 owner:fp28;
+- initWithFrame:(struct _NSRect)fp8;
+- (void)dealloc;
+- (void)shapeWindow;
+- (void)tileAndSetWindowShape:(char)fp8;
+- (void)tile;
+- (void)drawRect:(struct _NSRect)fp8;
+- (void)_drawFrameRects:(struct _NSRect)fp8;
+- (void)drawFrame:(struct _NSRect)fp8;
+- (void)drawThemeContentFill:(struct _NSRect)fp8 inView:fp24;
+- (void)drawWindowBackgroundRect:(struct _NSRect)fp8;
+- (void)drawWindowBackgroundRegion:(void *)fp8;
+- (float)contentAlpha;
+- (void)_windowChangedKeyState;
+- (void)_updateButtonState;
+- (char)_isSheet;
+- (char)_isUtility;
+- (void)setShadowState:(int)fp8;
+- (int)shadowState;
+- (char)_canHaveToolbar;
+- (char)_toolbarIsInTransition;
+- (char)_toolbarIsShown;
+- (char)_toolbarIsHidden;
+- (void)_showToolbarWithAnimation:(char)fp8;
+- (void)_hideToolbarWithAnimation:(char)fp8;
+- (float)_distanceFromToolbarBaseToTitlebar;
+- (int)_shadowType;
+- (unsigned int)_shadowFlags;
+- (void)_setShadowParameters;
+- (void)_drawFrameShadowAndFlushContext:fp8;
+- (void)setUpGState;
+- (void)adjustHalftonePhase;
+- (void)systemColorsDidChange:fp8;
+- frameColor;
+- contentFill;
+- (void)tabViewAdded;
+- (void)tabViewRemoved;
+- title;
+- (void)setTitle:fp8;
+- titleCell;
+- (void)initTitleCell:fp8;
+- (void)setResizeIncrements:(struct _NSSize)fp8;
+- (struct _NSSize)resizeIncrements;
+- (void)setAspectRatio:(struct _NSSize)fp8;
+- (struct _NSSize)aspectRatio;
+- (unsigned int)styleMask;
+- representedFilename;
+- (void)setRepresentedFilename:fp8;
+- (void)setDocumentEdited:(char)fp8;
+- (void)_setFrameNeedsDisplay:(char)fp8;
+- (char)frameNeedsDisplay;
+- titleFont;
+- (struct _NSRect)_maxTitlebarTitleRect;
+- (struct _NSRect)titlebarRect;
+- (void)_setUtilityWindow:(char)fp8;
+- (void)_setNonactivatingPanel:(char)fp8;
+- (void)setIsClosable:(char)fp8;
+- (void)setIsResizable:(char)fp8;
+- closeButton;
+- minimizeButton;
+- zoomButton;
+- (struct _NSSize)miniaturizedSize;
+- (void)_clearDragMargins;
+- (void)_resetDragMargins;
+- (void)setTitle:fp8 andDefeatWrap:(char)fp12;
+- (struct _NSRect)frameRectForContentRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24;
+- (struct _NSRect)contentRectForFrameRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24;
+- (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16;
+- (struct _NSRect)dragRectForFrameRect:(struct _NSRect)fp8;
+- (struct _NSRect)contentRect;
+- (struct _NSSize)minFrameSize;
+- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(struct _NSRect)fp8 isVisibleRect:(char)fp24 rectIsVisibleRectForView:fp28 topView:(char)fp32;
+
+@end
diff --git a/src/gui/kernel/qnsthemeframe_mac_p.h b/src/gui/kernel/qnsthemeframe_mac_p.h
new file mode 100644
index 0000000000..785a6a862f
--- /dev/null
+++ b/src/gui/kernel/qnsthemeframe_mac_p.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Private AppKit class (dumped from classdump).
+
+#import <Cocoa/Cocoa.h>
+#import "qnstitledframe_mac_p.h"
+
+@interface NSThemeFrame : NSTitledFrame
+{
+ NSButton *toolbarButton;
+ int toolbarVisibleStatus;
+ NSImage *showToolbarTransitionImage;
+ NSSize showToolbarPreWindowSize;
+ NSButton *modeButton;
+ int leftGroupTrackingTagNum;
+ int rightGroupTrackingTagNum;
+ char mouseInsideLeftGroup;
+ char mouseInsideRightGroup;
+ int widgetState;
+ NSString *displayName;
+}
+
++ (void)initialize;
++ (float)_windowBorderThickness:(unsigned int)fp8;
++ (float)_minXWindowBorderWidth:(unsigned int)fp8;
++ (float)_maxXWindowBorderWidth:(unsigned int)fp8;
++ (float)_minYWindowBorderHeight:(unsigned int)fp8;
++ (float)_windowTitlebarButtonSpacingWidth:(unsigned int)fp8;
++ (float)_windowFileButtonSpacingWidth:(unsigned int)fp8;
++ (float)_minXTitlebarWidgetInset:(unsigned int)fp8;
++ (float)_maxXTitlebarWidgetInset:(unsigned int)fp8;
++ (float)minFrameWidthWithTitle:fp8 styleMask:(unsigned int)fp12;
++ (float)_windowSideTitlebarTitleMinWidth:(unsigned int)fp8;
++ (float)_windowTitlebarTitleMinHeight:(unsigned int)fp8;
++ (float)_sideTitlebarWidth:(unsigned int)fp8;
++ (float)_titlebarHeight:(unsigned int)fp8;
++ (float)_resizeHeight:(unsigned int)fp8;
++ (char)_resizeFromEdge;
++ (struct _NSSize)sizeOfTitlebarButtons:(unsigned int)fp8;
++ (float)_contentToFrameMinXWidth:(unsigned int)fp8;
++ (float)_contentToFrameMaxXWidth:(unsigned int)fp8;
++ (float)_contentToFrameMinYHeight:(unsigned int)fp8;
++ (float)_contentToFrameMaxYHeight:(unsigned int)fp8;
++ (unsigned int)_validateStyleMask:(unsigned int)fp8;
+- (struct _NSSize)_topCornerSize;
+- (struct _NSSize)_bottomCornerSize;
+- (void *)_createWindowOpaqueShape;
+- (void)shapeWindow;
+- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)fp8 isVisibleRect:(char)fp24 rectIsVisibleRectForView:fp28 topView:(char)fp32;
+- (void *)_regionForOpaqueDescendants:(NSRect)fp8 forMove:(char)fp24;
+- (void)_drawFrameInterior:(NSRect *)fp8 clip:(NSRect)fp12;
+- (void)_setTextShadow:(char)fp8;
+- (void)_drawTitleBar:(NSRect)fp8;
+- (void)_drawResizeIndicators:(NSRect)fp8;
+- (void)_drawFrameRects:(NSRect)fp8;
+- (void)drawFrame:(NSRect)fp8;
+- contentFill;
+- (void)viewDidEndLiveResize;
+- (float)contentAlpha;
+- (void)setThemeFrameWidgetState:(int)fp8;
+- (char)constrainResizeEdge:(int *)fp8 withDelta:(struct _NSSize)fp12 elapsedTime:(float)fp20;
+- (void)addFileButton:fp8;
+- (void)_updateButtons;
+- (void)_updateButtonState;
+- newCloseButton;
+- newZoomButton;
+- newMiniaturizeButton;
+- newToolbarButton;
+- newFileButton;
+- (void)_resetTitleBarButtons;
+- (void)setDocumentEdited:(char)fp8;
+- toolbarButton;
+- modeButton;
+- initWithFrame:(NSRect)fp8 styleMask:(unsigned int)fp24 owner:fp28;
+- (void)dealloc;
+- (void)setFrameSize:(struct _NSSize)fp8;
+- (char)_canHaveToolbar;
+- (char)_toolbarIsInTransition;
+- (char)_toolbarIsShown;
+- (char)_toolbarIsHidden;
+- _toolbarView;
+- _toolbar;
+- (float)_distanceFromToolbarBaseToTitlebar;
+- (unsigned int)_shadowFlags;
+- (NSRect)frameRectForContentRect:(NSRect)fp8 styleMask:(unsigned int)fp24;
+- (NSRect)contentRectForFrameRect:(NSRect)fp8 styleMask:(unsigned int)fp24;
+- (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16;
+- (NSRect)contentRect;
+- (NSRect)_contentRectExcludingToolbar;
+- (NSRect)_contentRectIncludingToolbarAtHome;
+- (void)_setToolbarShowHideResizeWeightingOptimizationOn:(char)fp8;
+- (char)_usingToolbarShowHideWeightingOptimization;
+- (void)handleSetFrameCommonRedisplay;
+- (void)_startLiveResizeAsTopLevel;
+- (void)_endLiveResizeAsTopLevel;
+- (void)_growContentReshapeContentAndToolbarView:(int)fp8 animate:(char)fp12;
+- (char)_growWindowReshapeContentAndToolbarView:(int)fp8 animate:(char)fp12;
+- (void)_reshapeContentAndToolbarView:(int)fp8 resizeWindow:(char)fp12 animate:(char)fp16;
+- (void)_toolbarFrameSizeChanged:fp8 oldSize:(struct _NSSize)fp12;
+- (void)_syncToolbarPosition;
+- (void)_showHideToolbar:(int)fp8 resizeWindow:(char)fp12 animate:(char)fp16;
+- (void)_showToolbarWithAnimation:(char)fp8;
+- (void)_hideToolbarWithAnimation:(char)fp8;
+- (void)_drawToolbarTransitionIfNecessary;
+- (void)drawRect:(NSRect)fp8;
+- (void)resetCursorRects;
+- (char)shouldBeTreatedAsInkEvent:fp8;
+- (char)_shouldBeTreatedAsInkEventInInactiveWindow:fp8;
+- hitTest:(struct _NSPoint)fp8;
+- (NSRect)_leftGroupRect;
+- (NSRect)_rightGroupRect;
+- (void)_updateWidgets;
+- (void)_updateMouseTracking;
+- (void)mouseEntered:fp8;
+- (void)mouseExited:fp8;
+- (void)_setMouseEnteredGroup:(char)fp8 entered:(char)fp12;
+- (char)_mouseInGroup:fp8;
+- (struct _NSSize)miniaturizedSize;
+- (float)_minXTitlebarDecorationMinWidth;
+- (float)_maxXTitlebarDecorationMinWidth;
+- (struct _NSSize)minFrameSize;
+- (float)_windowBorderThickness;
+- (float)_windowTitlebarXResizeBorderThickness;
+- (float)_windowTitlebarYResizeBorderThickness;
+- (float)_windowResizeBorderThickness;
+- (float)_minXWindowBorderWidth;
+- (float)_maxXWindowBorderWidth;
+- (float)_minYWindowBorderHeight;
+- (float)_maxYWindowBorderHeight;
+- (float)_minYTitlebarButtonsOffset;
+- (float)_minYTitlebarTitleOffset;
+- (float)_sideTitlebarWidth;
+- (float)_titlebarHeight;
+- (NSRect)_titlebarTitleRect;
+- (NSRect)titlebarRect;
+- (float)_windowTitlebarTitleMinHeight;
+- (struct _NSSize)_sizeOfTitlebarFileButton;
+- (struct _NSSize)sizeOfTitlebarToolbarButton;
+- (float)_windowTitlebarButtonSpacingWidth;
+- (float)_windowFileButtonSpacingWidth;
+- (float)_minXTitlebarWidgetInset;
+- (float)_maxXTitlebarWidgetInset;
+- (float)_minXTitlebarButtonsWidth;
+- (float)_maxXTitlebarButtonsWidth;
+- (struct _NSPoint)_closeButtonOrigin;
+- (struct _NSPoint)_zoomButtonOrigin;
+- (struct _NSPoint)_collapseButtonOrigin;
+- (struct _NSPoint)_toolbarButtonOrigin;
+- (struct _NSPoint)_fileButtonOrigin;
+- (void)_tileTitlebar;
+- (NSRect)_commandPopupRect;
+- (void)_resetDragMargins;
+- (float)_maxYTitlebarDragHeight;
+- (float)_minXTitlebarDragWidth;
+- (float)_maxXTitlebarDragWidth;
+- (float)_contentToFrameMinXWidth;
+- (float)_contentToFrameMaxXWidth;
+- (float)_contentToFrameMinYHeight;
+- (float)_contentToFrameMaxYHeight;
+- (float)_windowResizeCornerThickness;
+- (NSRect)_minYResizeRect;
+- (NSRect)_minYminXResizeRect;
+- (NSRect)_minYmaxXResizeRect;
+- (NSRect)_minXResizeRect;
+- (NSRect)_minXminYResizeRect;
+- (NSRect)_minXmaxYResizeRect;
+- (NSRect)_maxYResizeRect;
+- (NSRect)_maxYminXResizeRect;
+- (NSRect)_maxYmaxXResizeRect;
+- (NSRect)_maxXResizeRect;
+- (NSRect)_maxXminYResizeRect;
+- (NSRect)_maxXmaxYResizeRect;
+- (NSRect)_minXTitlebarResizeRect;
+- (NSRect)_maxXTitlebarResizeRect;
+- (NSRect)_minXBorderRect;
+- (NSRect)_maxXBorderRect;
+- (NSRect)_maxYBorderRect;
+- (NSRect)_minYBorderRect;
+- (void)_setUtilityWindow:(char)fp8;
+- (char)_isUtility;
+- (float)_sheetHeightAdjustment;
+- (void)_setSheet:(char)fp8;
+- (char)_isSheet;
+- (char)_isResizable;
+- (char)_isClosable;
+- (char)_isMiniaturizable;
+- (char)_hasToolbar;
+- (NSRect)_growBoxRect;
+- (void)_drawGrowBoxWithClip:(NSRect)fp8;
+- (char)_inactiveButtonsNeedMask;
+- (void)mouseDown:fp8;
+- _displayName;
+- (void)_setDisplayName:fp8;
+
+@end
diff --git a/src/gui/kernel/qnstitledframe_mac_p.h b/src/gui/kernel/qnstitledframe_mac_p.h
new file mode 100644
index 0000000000..0eb431ecec
--- /dev/null
+++ b/src/gui/kernel/qnstitledframe_mac_p.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Private AppKit class (dumped from classdump).
+
+#import <Cocoa/Cocoa.h>
+#import "qnsframeview_mac_p.h"
+
+
+@interface NSTitledFrame : NSFrameView
+{
+ int resizeFlags;
+ id fileButton; /* NSDocumentDragButton* */
+ NSSize titleCellSize;
+}
+
++ (float)_windowBorderThickness:(unsigned int)fp8;
++ (float)_minXWindowBorderWidth:(unsigned int)fp8;
++ (float)_maxXWindowBorderWidth:(unsigned int)fp8;
++ (float)_minYWindowBorderHeight:(unsigned int)fp8;
++ (char)_resizeFromEdge;
++ (NSRect)frameRectForContentRect:(NSRect)fp8 styleMask:(unsigned int)fp24;
++ (NSRect)contentRectForFrameRect:(NSRect)fp8 styleMask:(unsigned int)fp24;
++ (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16;
++ (struct _NSSize)minContentSizeForMinFrameSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16;
++ (float)minFrameWidthWithTitle:fp8 styleMask:(unsigned int)fp12;
++ (struct _NSSize)_titleCellSizeForTitle:fp8 styleMask:(unsigned int)fp12;
++ (float)_titleCellHeight:(unsigned int)fp8;
++ (float)_windowTitlebarTitleMinHeight:(unsigned int)fp8;
++ (float)_titlebarHeight:(unsigned int)fp8;
++ (struct _NSSize)sizeOfTitlebarButtons:(unsigned int)fp8;
++ (float)windowTitlebarLinesSpacingWidth:(unsigned int)fp8;
++ (float)windowTitlebarTitleLinesSpacingWidth:(unsigned int)fp8;
++ (float)_contentToFrameMinXWidth:(unsigned int)fp8;
++ (float)_contentToFrameMaxXWidth:(unsigned int)fp8;
++ (float)_contentToFrameMinYHeight:(unsigned int)fp8;
++ (float)_contentToFrameMaxYHeight:(unsigned int)fp8;
+- initWithFrame:(NSRect)fp8 styleMask:(unsigned int)fp24 owner:fp28;
+- (void)dealloc;
+- (void)setIsClosable:(char)fp8;
+- (void)setIsResizable:(char)fp8;
+- (void)_resetTitleFont;
+- (void)_setUtilityWindow:(char)fp8;
+- (char)isOpaque;
+- (char)worksWhenModal;
+- (void)propagateFrameDirtyRects:(NSRect)fp8;
+- (void)_showDrawRect:(NSRect)fp8;
+- (void)_drawFrameInterior:(NSRect *)fp8 clip:(NSRect)fp12;
+- (void)drawFrame:(NSRect)fp8;
+- (void)_drawFrameRects:(NSRect)fp8;
+- (void)_drawTitlebar:(NSRect)fp8;
+- (void)_drawTitlebarPattern:(int)fp8 inRect:(NSRect)fp12 clippedByRect:(NSRect)fp28 forKey:(char)fp44 alignment:(int)fp48;
+- (void)_drawTitlebarLines:(int)fp8 inRect:(NSRect)fp12 clippedByRect:(NSRect)fp28;
+- frameHighlightColor;
+- frameShadowColor;
+- (void)setFrameSize:(struct _NSSize)fp8;
+- (void)setFrameOrigin:(struct _NSPoint)fp8;
+- (void)tileAndSetWindowShape:(char)fp8;
+- (void)tile;
+- (void)_tileTitlebar;
+- (void)setTitle:fp8;
+- (char)_shouldRepresentFilename;
+- (void)setRepresentedFilename:fp8;
+- (void)_drawTitleStringIn:(NSRect)fp8 withColor:fp24;
+- titleFont;
+- (void)_drawResizeIndicators:(NSRect)fp8;
+- titleButtonOfClass:(Class)fp8;
+- initTitleButton:fp8;
+- newCloseButton;
+- newZoomButton;
+- newMiniaturizeButton;
+- newFileButton;
+- fileButton;
+- (void)_removeButtons;
+- (void)_updateButtons;
+- (char)_eventInTitlebar:fp8;
+- (char)acceptsFirstMouse:fp8;
+- (void)mouseDown:fp8;
+- (void)mouseUp:fp8;
+- (void)rightMouseDown:fp8;
+- (void)rightMouseUp:fp8;
+- (int)resizeEdgeForEvent:fp8;
+- (struct _NSSize)_resizeDeltaFromPoint:(struct _NSPoint)fp8 toEvent:fp16;
+- (NSRect)_validFrameForResizeFrame:(NSRect)fp8 fromResizeEdge:(int)fp24;
+- (NSRect)frame:(NSRect)fp8 resizedFromEdge:(int)fp24 withDelta:(struct _NSSize)fp28;
+- (char)constrainResizeEdge:(int *)fp8 withDelta:(struct _NSSize)fp12 elapsedTime:(float)fp20;
+- (void)resizeWithEvent:fp8;
+- (int)resizeFlags;
+- (void)resetCursorRects;
+- (void)setDocumentEdited:(char)fp8;
+- (struct _NSSize)miniaturizedSize;
+- (struct _NSSize)minFrameSize;
+- (float)_windowBorderThickness;
+- (float)_windowTitlebarXResizeBorderThickness;
+- (float)_windowTitlebarYResizeBorderThickness;
+- (float)_windowResizeBorderThickness;
+- (float)_minXWindowBorderWidth;
+- (float)_maxXWindowBorderWidth;
+- (float)_minYWindowBorderHeight;
+- (void)_invalidateTitleCellSize;
+- (void)_invalidateTitleCellWidth;
+- (float)_titleCellHeight;
+- (struct _NSSize)_titleCellSize;
+- (float)_titlebarHeight;
+- (NSRect)titlebarRect;
+- (NSRect)_maxTitlebarTitleRect;
+- (NSRect)_titlebarTitleRect;
+- (float)_windowTitlebarTitleMinHeight;
+- (NSRect)dragRectForFrameRect:(NSRect)fp8;
+- (struct _NSSize)sizeOfTitlebarButtons;
+- (struct _NSSize)_sizeOfTitlebarFileButton;
+- (float)_windowTitlebarButtonSpacingWidth;
+- (float)_minXTitlebarButtonsWidth;
+- (float)_maxXTitlebarButtonsWidth;
+- (int)_numberOfTitlebarLines;
+- (float)windowTitlebarLinesSpacingWidth;
+- (float)windowTitlebarTitleLinesSpacingWidth;
+- (float)_minLinesWidthWithSpace;
+- (NSRect)_minXTitlebarLinesRectWithTitleCellRect:(NSRect)fp8;
+- (NSRect)_maxXTitlebarLinesRectWithTitleCellRect:(NSRect)fp8;
+- (float)_minXTitlebarDecorationMinWidth;
+- (float)_maxXTitlebarDecorationMinWidth;
+- (struct _NSPoint)_closeButtonOrigin;
+- (struct _NSPoint)_zoomButtonOrigin;
+- (struct _NSPoint)_collapseButtonOrigin;
+- (struct _NSPoint)_fileButtonOrigin;
+- (float)_maxYTitlebarDragHeight;
+- (float)_minXTitlebarDragWidth;
+- (float)_maxXTitlebarDragWidth;
+- (float)_contentToFrameMinXWidth;
+- (float)_contentToFrameMaxXWidth;
+- (float)_contentToFrameMinYHeight;
+- (float)_contentToFrameMaxYHeight;
+- (NSRect)contentRect;
+- (float)_windowResizeCornerThickness;
+- (NSRect)_minYResizeRect;
+- (NSRect)_minYminXResizeRect;
+- (NSRect)_minYmaxXResizeRect;
+- (NSRect)_minXResizeRect;
+- (NSRect)_minXminYResizeRect;
+- (NSRect)_minXmaxYResizeRect;
+- (NSRect)_maxYResizeRect;
+- (NSRect)_maxYminXResizeRect;
+- (NSRect)_maxYmaxXResizeRect;
+- (NSRect)_maxXResizeRect;
+- (NSRect)_maxXminYResizeRect;
+- (NSRect)_maxXmaxYResizeRect;
+- (NSRect)_minXTitlebarResizeRect;
+- (NSRect)_maxXTitlebarResizeRect;
+- (NSRect)_minXBorderRect;
+- (NSRect)_maxXBorderRect;
+- (NSRect)_maxYBorderRect;
+- (NSRect)_minYBorderRect;
+
+@end
diff --git a/src/gui/kernel/qole_win.cpp b/src/gui/kernel/qole_win.cpp
new file mode 100644
index 0000000000..143b9316ec
--- /dev/null
+++ b/src/gui/kernel/qole_win.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdnd_p.h"
+
+#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
+
+#if defined(Q_OS_WINCE)
+#include <shlobj.h>
+#include "qguifunctions_wince.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QOleEnumFmtEtc::QOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
+{
+ m_isNull = false;
+ m_dwRefs = 1;
+ m_nIndex = 0;
+
+ for (int idx = 0; idx < fmtetcs.count(); ++idx) {
+ LPFORMATETC destetc = new FORMATETC();
+ if (copyFormatEtc(destetc, (LPFORMATETC)&(fmtetcs.at(idx)))) {
+ m_lpfmtetcs.append(destetc);
+ } else {
+ m_isNull = true;
+ delete destetc;
+ break;
+ }
+ }
+}
+
+QOleEnumFmtEtc::QOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs)
+{
+ m_isNull = false;
+ m_dwRefs = 1;
+ m_nIndex = 0;
+
+ for (int idx = 0; idx < lpfmtetcs.count(); ++idx) {
+ LPFORMATETC srcetc = lpfmtetcs.at(idx);
+ LPFORMATETC destetc = new FORMATETC();
+ if (copyFormatEtc(destetc, srcetc)) {
+ m_lpfmtetcs.append(destetc);
+ } else {
+ m_isNull = true;
+ delete destetc;
+ break;
+ }
+ }
+}
+
+QOleEnumFmtEtc::~QOleEnumFmtEtc()
+{
+ LPMALLOC pmalloc;
+
+#if !defined(Q_OS_WINCE)
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) == NOERROR) {
+#else
+ if (SHGetMalloc(&pmalloc) == NOERROR) {
+#endif
+ for (int idx = 0; idx < m_lpfmtetcs.count(); ++idx) {
+ LPFORMATETC tmpetc = m_lpfmtetcs.at(idx);
+ if (tmpetc->ptd)
+ pmalloc->Free(tmpetc->ptd);
+ delete tmpetc;
+ }
+
+ pmalloc->Release();
+ }
+ m_lpfmtetcs.clear();
+}
+
+bool QOleEnumFmtEtc::isNull() const
+{
+ return m_isNull;
+}
+
+// IUnknown methods
+STDMETHODIMP
+QOleEnumFmtEtc::QueryInterface(REFIID riid, void FAR* FAR* ppvObj)
+{
+ if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) {
+ *ppvObj = this;
+ AddRef();
+ return NOERROR;
+ }
+ *ppvObj = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG)
+QOleEnumFmtEtc::AddRef(void)
+{
+ return ++m_dwRefs;
+}
+
+STDMETHODIMP_(ULONG)
+QOleEnumFmtEtc::Release(void)
+{
+ if (--m_dwRefs == 0) {
+ delete this;
+ return 0;
+ }
+ return m_dwRefs;
+}
+
+// IEnumFORMATETC methods
+STDMETHODIMP
+QOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched)
+{
+ ULONG i=0;
+ ULONG nOffset;
+
+ if (rgelt == NULL)
+ return ResultFromScode(E_INVALIDARG);
+
+ while (i < celt) {
+ nOffset = m_nIndex + i;
+
+ if (nOffset < ULONG(m_lpfmtetcs.count())) {
+ copyFormatEtc((LPFORMATETC)&(rgelt[i]), m_lpfmtetcs.at(nOffset));
+ i++;
+ } else {
+ break;
+ }
+ }
+
+ m_nIndex += (WORD)i;
+
+ if (pceltFetched != NULL)
+ *pceltFetched = i;
+
+ if (i != celt)
+ return ResultFromScode(S_FALSE);
+
+ return NOERROR;
+}
+
+STDMETHODIMP
+QOleEnumFmtEtc::Skip(ULONG celt)
+{
+ ULONG i=0;
+ ULONG nOffset;
+
+ while (i < celt) {
+ nOffset = m_nIndex + i;
+
+ if (nOffset < ULONG(m_lpfmtetcs.count())) {
+ i++;
+ } else {
+ break;
+ }
+ }
+
+ m_nIndex += (WORD)i;
+
+ if (i != celt)
+ return ResultFromScode(S_FALSE);
+
+ return NOERROR;
+}
+
+STDMETHODIMP
+QOleEnumFmtEtc::Reset()
+{
+ m_nIndex = 0;
+ return NOERROR;
+}
+
+STDMETHODIMP
+QOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum)
+{
+ if (newEnum == NULL)
+ return ResultFromScode(E_INVALIDARG);
+
+ QOleEnumFmtEtc *result = new QOleEnumFmtEtc(m_lpfmtetcs);
+ result->m_nIndex = m_nIndex;
+
+ if (result->isNull()) {
+ delete result;
+ return ResultFromScode(E_OUTOFMEMORY);
+ } else {
+ *newEnum = result;
+ }
+
+ return NOERROR;
+}
+
+bool QOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const
+{
+ if (dest == NULL || src == NULL)
+ return false;
+
+ *dest = *src;
+
+ if (src->ptd) {
+ LPVOID pout;
+ LPMALLOC pmalloc;
+
+#if !defined(Q_OS_WINCE)
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR)
+#else
+ if (SHGetMalloc(&pmalloc) != NOERROR)
+#endif
+ return false;
+
+ pout = (LPVOID)pmalloc->Alloc(src->ptd->tdSize);
+ memcpy(dest->ptd, src->ptd, size_t(src->ptd->tdSize));
+
+ pmalloc->Release();
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
new file mode 100644
index 0000000000..6541510e6f
--- /dev/null
+++ b/src/gui/kernel/qpalette.cpp
@@ -0,0 +1,1396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpalette.h"
+#include "qapplication.h"
+#include "qdatastream.h"
+#include "qvariant.h"
+
+QT_BEGIN_NAMESPACE
+
+static int qt_palette_count = 1;
+
+class QPalettePrivate {
+public:
+ QPalettePrivate() : ref(1), ser_no(qt_palette_count++), detach_no(0) { }
+ QAtomicInt ref;
+ QBrush br[QPalette::NColorGroups][QPalette::NColorRoles];
+ int ser_no;
+ int detach_no;
+};
+
+static QColor qt_mix_colors(QColor a, QColor b)
+{
+ return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
+ (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
+}
+
+#ifdef QT3_SUPPORT
+
+#ifndef QT_NO_DATASTREAM
+QDataStream &qt_stream_out_qcolorgroup(QDataStream &s, const QColorGroup &g)
+{
+ if(s.version() == 1) {
+ // Qt 1.x
+ s << g.color(QPalette::Foreground) << g.color(QPalette::Background)
+ << g.color(QPalette::Light) << g.color(QPalette::Dark)
+ << g.color(QPalette::Mid) << g.color(QPalette::Text) << g.color(QPalette::Base);
+ } else {
+ int max = QPalette::NColorRoles;
+ if (s.version() <= QDataStream::Qt_2_1)
+ max = QPalette::HighlightedText + 1;
+ else if (s.version() <= QDataStream::Qt_4_3)
+ max = QPalette::AlternateBase + 1;
+ for(int r = 0 ; r < max ; r++)
+ s << g.brush((QPalette::ColorRole)r);
+ }
+ return s;
+}
+
+QDataStream &qt_stream_in_qcolorgroup(QDataStream &s, QColorGroup &g)
+{
+ if(s.version() == 1) { // Qt 1.x
+ QColor fg, bg, light, dark, mid, text, base;
+ s >> fg >> bg >> light >> dark >> mid >> text >> base;
+ QPalette p(bg);
+ p.setColor(QPalette::Active, QPalette::Foreground, fg);
+ p.setColor(QPalette::Active, QPalette::Light, light);
+ p.setColor(QPalette::Active, QPalette::Dark, dark);
+ p.setColor(QPalette::Active, QPalette::Mid, mid);
+ p.setColor(QPalette::Active, QPalette::Text, text);
+ p.setColor(QPalette::Active, QPalette::Base, base);
+ g = p;
+ g.setCurrentColorGroup(QPalette::Active);
+ } else {
+ int max = QPalette::NColorRoles;
+ if (s.version() <= QDataStream::Qt_2_1)
+ max = QPalette::HighlightedText + 1;
+ else if (s.version() <= QDataStream::Qt_3_0)
+ max = QPalette::LinkVisited + 1;
+ else if (s.version() <= QDataStream::Qt_4_3)
+ max = QPalette::AlternateBase + 1;
+ QBrush tmp;
+ for(int r = 0 ; r < max; r++) {
+ s >> tmp;
+ g.setBrush((QPalette::ColorRole)r, tmp);
+ }
+ }
+ return s;
+}
+
+QDataStream &operator<<(QDataStream &s, const QColorGroup &g)
+{
+ return qt_stream_out_qcolorgroup(s, g);
+}
+
+QDataStream &operator>>(QDataStream &s, QColorGroup &g)
+{
+ return qt_stream_in_qcolorgroup(s, g);
+}
+#endif
+
+/*!
+ Constructs a palette with the specified \a active, \a disabled and
+ \a inactive color groups.
+*/
+QPalette::QPalette(const QColorGroup &active, const QColorGroup &disabled,
+ const QColorGroup &inactive)
+{
+ Q_ASSERT(QPalette::NColorRoles == QPalette::ToolTipText + 1);
+ init();
+ setColorGroup(Active, active);
+ setColorGroup(Disabled, disabled);
+ setColorGroup(Inactive, inactive);
+}
+
+QColorGroup QPalette::createColorGroup(ColorGroup cr) const
+{
+ QColorGroup ret(*this);
+ ret.setCurrentColorGroup(cr);
+ return ret;
+}
+
+void QPalette::setColorGroup(ColorGroup cg, const QColorGroup &g)
+{
+ setColorGroup(cg, g.brush(WindowText), g.brush(Button), g.brush(Light),
+ g.brush(Dark), g.brush(Mid), g.brush(Text), g.brush(BrightText),
+ g.brush(Base), g.brush(AlternateBase), g.brush(Window),
+ g.brush(Midlight), g.brush(ButtonText), g.brush(Shadow),
+ g.brush(Highlight), g.brush(HighlightedText), g.brush(Link),
+ g.brush(LinkVisited), g.brush(ToolTipBase), g.brush(ToolTipText));
+}
+
+#endif
+
+/*!
+ \fn const QColor &QPalette::color(ColorRole role) const
+
+ \overload
+
+ Returns the color that has been set for the given color \a role in
+ the current ColorGroup.
+
+ \sa brush() ColorRole
+ */
+
+/*!
+ \fn const QBrush &QPalette::brush(ColorRole role) const
+
+ \overload
+
+ Returns the brush that has been set for the given color \a role in
+ the current ColorGroup.
+
+ \sa color() setBrush() ColorRole
+*/
+
+/*!
+ \fn void QPalette::setColor(ColorRole role, const QColor &color)
+
+ \overload
+
+ Sets the color used for the given color \a role, in all color
+ groups, to the specified solid \a color.
+
+ \sa brush() setColor() ColorRole
+*/
+
+/*!
+ \fn void QPalette::setBrush(ColorRole role, const QBrush &brush)
+
+ Sets the brush for the given color \a role to the specified \a
+ brush for all groups in the palette.
+
+ \sa brush() setColor() ColorRole
+*/
+
+/*!
+ \fn const QBrush & QPalette::foreground() const
+ \obsolete
+
+ Use windowText() instead.
+*/
+
+/*!
+ \fn const QBrush & QPalette::windowText() const
+
+ Returns the window text (general foreground) brush of the
+ current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::button() const
+
+ Returns the button brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::light() const
+
+ Returns the light brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush& QPalette::midlight() const
+
+ Returns the midlight brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::dark() const
+
+ Returns the dark brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::mid() const
+
+ Returns the mid brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::text() const
+
+ Returns the text foreground brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::brightText() const
+
+ Returns the bright text foreground brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::buttonText() const
+
+ Returns the button text foreground brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::base() const
+
+ Returns the base brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::alternateBase() const
+
+ Returns the alternate base brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::toolTipBase() const
+ \since 4.4
+
+ Returns the tool tip base brush of the current color group. This brush is
+ used by QToolTip and QWhatsThis.
+
+ \note Tool tips use the Inactive color group of QPalette, because tool
+ tips are not active windows.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::toolTipText() const
+ \since 4.4
+
+ Returns the tool tip text brush of the current color group. This brush is
+ used by QToolTip and QWhatsThis.
+
+ \note Tool tips use the Inactive color group of QPalette, because tool
+ tips are not active windows.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::background() const
+ \obsolete
+
+ Use window() instead.
+*/
+
+/*!
+ \fn const QBrush & QPalette::window() const
+
+ Returns the window (general background) brush of the current
+ color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::shadow() const
+
+ Returns the shadow brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::highlight() const
+
+ Returns the highlight brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::highlightedText() const
+
+ Returns the highlighted text brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::link() const
+
+ Returns the unvisited link text brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn const QBrush & QPalette::linkVisited() const
+
+ Returns the visited link text brush of the current color group.
+
+ \sa ColorRole brush()
+*/
+
+/*!
+ \fn ColorGroup QPalette::currentColorGroup() const
+
+ Returns the palette's current color group.
+*/
+
+/*!
+ \fn void QPalette::setCurrentColorGroup(ColorGroup cg)
+
+ Set the palette's current color group to \a cg.
+*/
+
+/*!
+ \class QPalette
+
+ \brief The QPalette class contains color groups for each widget state.
+
+ \ingroup appearance
+ \ingroup shared
+ \ingroup multimedia
+ \mainclass
+
+ A palette consists of three color groups: \e Active, \e Disabled,
+ and \e Inactive. All widgets in Qt contain a palette and
+ use their palette to draw themselves. This makes the user
+ interface easily configurable and easier to keep consistent.
+
+
+ If you create a new widget we strongly recommend that you use the
+ colors in the palette rather than hard-coding specific colors.
+
+ The color groups:
+ \list
+ \i The Active group is used for the window that has keyboard focus.
+ \i The Inactive group is used for other windows.
+ \i The Disabled group is used for widgets (not windows) that are
+ disabled for some reason.
+ \endlist
+
+ Both active and inactive windows can contain disabled widgets.
+ (Disabled widgets are often called \e inaccessible or \e{grayed
+ out}.)
+
+ In most styles, Active and Inactive look the same.
+
+ Colors and brushes can be set for particular roles in any of a palette's
+ color groups with setColor() and setBrush(). A color group contains a
+ group of colors used by widgets for drawing themselves. We recommend that
+ widgets use color group roles from the palette such as "foreground" and
+ "base" rather than literal colors like "red" or "turquoise". The color
+ roles are enumerated and defined in the \l ColorRole documentation.
+
+ We strongly recommend that you use the default palette of the
+ current style (returned by QApplication::palette()) and
+ modify that as necessary. This is done by Qt's widgets when they
+ are drawn.
+
+ To modify a color group you call the functions
+ setColor() and setBrush(), depending on whether you want a pure
+ color or a pixmap pattern.
+
+ There are also corresponding color() and brush() getters, and a
+ commonly used convenience function to get the ColorRole for the current ColorGroup:
+ window(), windowText(), base(), etc.
+
+
+ You can copy a palette using the copy constructor and test to see
+ if two palettes are \e identical using isCopyOf().
+
+ QPalette is optimized by the use of \l{implicit sharing},
+ so it is very efficient to pass QPalette objects as arguments.
+
+ \warning Some styles do not use the palette for all drawing, for
+ instance, if they make use of native theme engines. This is the
+ case for both the Windows XP, Windows Vista, and the Mac OS X
+ styles.
+
+ \sa QApplication::setPalette(), QWidget::setPalette(), QColor
+*/
+
+/*!
+ \enum QPalette::ColorGroup
+
+ \value Disabled
+ \value Active
+ \value Inactive
+ \value Normal synonym for Active
+
+ \omitvalue All
+ \omitvalue NColorGroups
+ \omitvalue Current
+*/
+
+/*!
+ \enum QPalette::ColorRole
+
+ \img palette.png Color Roles
+
+ The ColorRole enum defines the different symbolic color roles used
+ in current GUIs.
+
+ The central roles are:
+
+ \value Window A general background color.
+
+ \value Background This value is obsolete. Use Window instead.
+
+ \value WindowText A general foreground color.
+
+ \value Foreground This value is obsolete. Use WindowText instead.
+
+ \value Base Used mostly as the background color for text entry widgets,
+ but can also be used for other painting - such as the
+ background of combobox drop down lists and toolbar handles.
+ It is usually white or another light color.
+
+ \value AlternateBase Used as the alternate background color in views with
+ alternating row colors (see
+ QAbstractItemView::setAlternatingRowColors()).
+
+ \value ToolTipBase Used as the background color for QToolTip and
+ QWhatsThis. Tool tips use the Inactive color group
+ of QPalette, because tool tips are not active
+ windows.
+
+ \value ToolTipText Used as the foreground color for QToolTip and
+ QWhatsThis. Tool tips use the Inactive color group
+ of QPalette, because tool tips are not active
+ windows.
+
+ \value Text The foreground color used with \c Base. This is usually
+ the same as the \c WindowText, in which case it must provide
+ good contrast with \c Window and \c Base.
+
+ \value Button The general button background color. This background can be different from
+ \c Window as some styles require a different background color for buttons.
+
+ \value ButtonText A foreground color used with the \c Button color.
+
+ \value BrightText A text color that is very different from
+ \c WindowText, and contrasts well with e.g. \c
+ Dark. Typically used for text that needs to be
+ drawn where \c Text or \c WindowText would give
+ poor contrast, such as on pressed push buttons.
+ Note that text colors can be used for things
+ other than just words; text colors are \e
+ usually used for text, but it's quite common to
+ use the text color roles for lines, icons, etc.
+
+
+ There are some color roles used mostly for 3D bevel and shadow effects.
+ All of these are normally derived from \c Window, and used in ways that
+ depend on that relationship. For example, buttons depend on it to make the
+ bevels look attractive, and Motif scroll bars depend on \c Mid to be
+ slightly different from \c Window.
+
+ \value Light Lighter than \c Button color.
+
+ \value Midlight Between \c Button and \c Light.
+
+ \value Dark Darker than \c Button.
+
+ \value Mid Between \c Button and \c Dark.
+
+ \value Shadow A very dark color. By default, the shadow color is
+ Qt::black.
+
+
+ Selected (marked) items have two roles:
+
+ \value Highlight A color to indicate a selected item or the current
+ item. By default, the highlight color is
+ Qt::darkBlue.
+
+ \value HighlightedText A text color that contrasts with \c Highlight.
+ By default, the highlighted text color is Qt::white.
+
+ There are two color roles related to hyperlinks:
+
+ \value Link A text color used for unvisited hyperlinks.
+ By default, the link color is Qt::blue.
+
+ \value LinkVisited A text color used for already visited hyperlinks.
+ By default, the linkvisited color is Qt::magenta.
+
+ Note that we do not use the \c Link and \c LinkVisited roles when
+ rendering rich text in Qt, and that we recommend that you use CSS
+ and the QTextDocument::setDefaultStyleSheet() function to alter
+ the appearance of links. For example:
+
+ \snippet doc/src/snippets/textdocument-css/main.cpp 0
+
+ \value NoRole No role; this special role is often used to indicate that a
+ role has not been assigned.
+
+ \omitvalue NColorRoles
+*/
+
+/*!
+ Constructs a palette object that uses the application's default palette.
+
+ \sa QApplication::setPalette(), QApplication::palette()
+*/
+QPalette::QPalette()
+ : d(QApplication::palette().d),
+ current_group(Active),
+ resolve_mask(0)
+{
+ d->ref.ref();
+}
+
+static void qt_palette_from_color(QPalette &pal, const QColor & button)
+{
+ QColor bg = button,
+ btn = button,
+ fg, base;
+ int h, s, v;
+ bg.getHsv(&h, &s, &v);
+ if(v > 128) {
+ fg = Qt::black;
+ base = Qt::white;
+ } else {
+ fg = Qt::white;
+ base = Qt::black;
+ }
+ //inactive and active are the same..
+ pal.setColorGroup(QPalette::Active, QBrush(fg), QBrush(btn), QBrush(btn.lighter(150)),
+ QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(fg), QBrush(Qt::white),
+ QBrush(base), QBrush(bg));
+ pal.setColorGroup(QPalette::Inactive, QBrush(fg), QBrush(btn), QBrush(btn.lighter(150)),
+ QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(fg), QBrush(Qt::white),
+ QBrush(base), QBrush(bg));
+ pal.setColorGroup(QPalette::Disabled, QBrush(btn.darker()), QBrush(btn), QBrush(btn.lighter(150)),
+ QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(btn.darker()),
+ QBrush(Qt::white), QBrush(bg), QBrush(bg));
+}
+
+
+/*!
+ Constructs a palette from the \a button color. The other colors are
+ automatically calculated, based on this color. \c Window will be
+ the button color as well.
+*/
+QPalette::QPalette(const QColor &button)
+{
+ init();
+ qt_palette_from_color(*this, button);
+}
+
+/*!
+ Constructs a palette from the \a button color. The other colors are
+ automatically calculated, based on this color. \c Window will be
+ the button color as well.
+*/
+QPalette::QPalette(Qt::GlobalColor button)
+{
+ init();
+ qt_palette_from_color(*this, button);
+}
+
+/*!
+ Constructs a palette. You can pass either brushes, pixmaps or
+ plain colors for \a windowText, \a button, \a light, \a dark, \a
+ mid, \a text, \a bright_text, \a base and \a window.
+
+ \sa QBrush
+*/
+QPalette::QPalette(const QBrush &windowText, const QBrush &button,
+ const QBrush &light, const QBrush &dark,
+ const QBrush &mid, const QBrush &text,
+ const QBrush &bright_text, const QBrush &base,
+ const QBrush &window)
+{
+ init();
+ setColorGroup(All, windowText, button, light, dark, mid, text, bright_text,
+ base, window);
+}
+
+
+/*!\obsolete
+
+ Constructs a palette with the specified \a windowText, \a
+ window, \a light, \a dark, \a mid, \a text, and \a base colors.
+ The button color will be set to the window color.
+*/
+QPalette::QPalette(const QColor &windowText, const QColor &window,
+ const QColor &light, const QColor &dark, const QColor &mid,
+ const QColor &text, const QColor &base)
+{
+ init();
+ setColorGroup(All, QBrush(windowText), QBrush(window), QBrush(light),
+ QBrush(dark), QBrush(mid), QBrush(text), QBrush(light),
+ QBrush(base), QBrush(window));
+}
+
+/*!
+ Constructs a palette from a \a button color and a \a window.
+ The other colors are automatically calculated, based on these
+ colors.
+*/
+QPalette::QPalette(const QColor &button, const QColor &window)
+{
+ init();
+ QColor bg = window, btn = button, fg, base, disfg;
+ int h, s, v;
+ bg.getHsv(&h, &s, &v);
+ if(v > 128) {
+ fg = Qt::black;
+ base = Qt::white;
+ disfg = Qt::darkGray;
+ } else {
+ fg = Qt::white;
+ base = Qt::black;
+ disfg = Qt::darkGray;
+ }
+ //inactive and active are identical
+ setColorGroup(Inactive, QBrush(fg), QBrush(btn), QBrush(btn.lighter(150)), QBrush(btn.darker()),
+ QBrush(btn.darker(150)), QBrush(fg), QBrush(Qt::white), QBrush(base),
+ QBrush(bg));
+ setColorGroup(Active, QBrush(fg), QBrush(btn), QBrush(btn.lighter(150)), QBrush(btn.darker()),
+ QBrush(btn.darker(150)), QBrush(fg), QBrush(Qt::white), QBrush(base),
+ QBrush(bg));
+ setColorGroup(Disabled, QBrush(disfg), QBrush(btn), QBrush(btn.lighter(150)),
+ QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(disfg),
+ QBrush(Qt::white), QBrush(base), QBrush(bg));
+}
+
+/*!
+ Constructs a copy of \a p.
+
+ This constructor is fast thanks to \l{implicit sharing}.
+*/
+QPalette::QPalette(const QPalette &p)
+{
+ d = p.d;
+ d->ref.ref();
+ resolve_mask = p.resolve_mask;
+ current_group = p.current_group;
+}
+
+/*!
+ Destroys the palette.
+*/
+QPalette::~QPalette()
+{
+ if(!d->ref.deref())
+ delete d;
+}
+
+/*!\internal*/
+void QPalette::init() {
+ d = new QPalettePrivate;
+ resolve_mask = 0;
+ current_group = Active; //as a default..
+}
+
+/*!
+ Assigns \a p to this palette and returns a reference to this
+ palette.
+
+ This operation is fast thanks to \l{implicit sharing}.
+*/
+QPalette &QPalette::operator=(const QPalette &p)
+{
+ p.d->ref.ref();
+ resolve_mask = p.resolve_mask;
+ current_group = p.current_group;
+ if(!d->ref.deref())
+ delete d;
+ d = p.d;
+ return *this;
+}
+
+/*!
+ Returns the palette as a QVariant
+*/
+QPalette::operator QVariant() const
+{
+ return QVariant(QVariant::Palette, this);
+}
+
+/*!
+ \fn const QColor &QPalette::color(ColorGroup group, ColorRole role) const
+
+ Returns the color in the specified color \a group, used for the
+ given color \a role.
+
+ \sa brush() setColor() ColorRole
+*/
+
+/*!
+ \fn const QBrush &QPalette::brush(ColorGroup group, ColorRole role) const
+
+ Returns the brush in the specified color \a group, used for the
+ given color \a role.
+
+ \sa color() setBrush() ColorRole
+*/
+const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const
+{
+ Q_ASSERT(cr < NColorRoles);
+ if(gr >= (int)NColorGroups) {
+ if(gr == Current) {
+ gr = (ColorGroup)current_group;
+ } else {
+ qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr);
+ gr = Active;
+ }
+ }
+ return d->br[gr][cr];
+}
+
+/*!
+ \fn void QPalette::setColor(ColorGroup group, ColorRole role, const QColor &color)
+
+ Sets the brush in the specified color \a group, used for the given
+ color \a role, to the specified solid \a color.
+
+ \sa setBrush() color() ColorRole
+*/
+
+/*!
+ \fn void QPalette::setBrush(ColorGroup group, ColorRole role, const QBrush &brush)
+ \overload
+
+ Sets the brush in the specified color \a group, used for the given
+ color \a role, to \a brush.
+
+ \sa brush() setColor() ColorRole
+*/
+void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
+{
+ Q_ASSERT(cr < NColorRoles);
+ detach();
+ if(cg >= (int)NColorGroups) {
+ if(cg == All) {
+ for(int i = 0; i < (int)NColorGroups; i++)
+ d->br[i][cr] = b;
+ resolve_mask |= (1<<cr);
+ return;
+ } else if(cg == Current) {
+ cg = (ColorGroup)current_group;
+ } else {
+ qWarning("QPalette::setBrush: Unknown ColorGroup: %d", (int)cg);
+ cg = Active;
+ }
+ }
+ d->br[cg][cr] = b;
+ resolve_mask |= (1<<cr);
+}
+
+/*!
+ \since 4.2
+
+ Returns true if the ColorGroup \a cg and ColorRole \a cr has been
+ set previously on this palette; otherwise returns false.
+
+ \sa setBrush()
+*/
+bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
+{
+ Q_UNUSED(cg);
+ return (resolve_mask & (1<<cr));
+}
+
+/*!
+ \internal
+*/
+void QPalette::detach()
+{
+ if (d->ref != 1) {
+ QPalettePrivate *x = new QPalettePrivate;
+ for(int grp = 0; grp < (int)NColorGroups; grp++) {
+ for(int role = 0; role < (int)NColorRoles; role++)
+ x->br[grp][role] = d->br[grp][role];
+ }
+ if(!d->ref.deref())
+ delete d;
+ d = x;
+ }
+ ++d->detach_no;
+}
+
+/*!
+ \fn bool QPalette::operator!=(const QPalette &p) const
+
+ Returns true (slowly) if this palette is different from \a p;
+ otherwise returns false (usually quickly).
+*/
+
+/*!
+ Returns true (usually quickly) if this palette is equal to \a p;
+ otherwise returns false (slowly).
+*/
+bool QPalette::operator==(const QPalette &p) const
+{
+ if (isCopyOf(p))
+ return true;
+ for(int grp = 0; grp < (int)NColorGroups; grp++) {
+ for(int role = 0; role < (int)NColorRoles; role++) {
+ if(d->br[grp][role] != p.d->br[grp][role])
+ return false;
+ }
+ }
+ return true;
+}
+
+#ifdef QT3_SUPPORT
+bool QColorGroup::operator==(const QColorGroup &other) const
+{
+ if (isCopyOf(other))
+ return true;
+ for (int role = 0; role < int(NColorRoles); role++) {
+ if(d->br[current_group][role] != other.d->br[other.current_group][role])
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Returns the color group as a QVariant
+*/
+QColorGroup::operator QVariant() const
+{
+ return QVariant(QVariant::ColorGroup, this);
+}
+#endif
+
+/*!
+ \fn bool QPalette::isEqual(ColorGroup cg1, ColorGroup cg2) const
+
+ Returns true (usually quickly) if color group \a cg1 is equal to
+ \a cg2; otherwise returns false.
+*/
+bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) const
+{
+ if(group1 >= (int)NColorGroups) {
+ if(group1 == Current) {
+ group1 = (ColorGroup)current_group;
+ } else {
+ qWarning("QPalette::brush: Unknown ColorGroup(1): %d", (int)group1);
+ group1 = Active;
+ }
+ }
+ if(group2 >= (int)NColorGroups) {
+ if(group2 == Current) {
+ group2 = (ColorGroup)current_group;
+ } else {
+ qWarning("QPalette::brush: Unknown ColorGroup(2): %d", (int)group2);
+ group2 = Active;
+ }
+ }
+ if(group1 == group2)
+ return true;
+ for(int role = 0; role < (int)NColorRoles; role++) {
+ if(d->br[group1][role] != d->br[group2][role])
+ return false;
+ }
+ return true;
+}
+
+/*! \obsolete
+
+ Returns a number that identifies the contents of this QPalette
+ object. Distinct QPalette objects can only have the same serial
+ number if they refer to the same contents (but they don't have
+ to). Also, the serial number of a QPalette may change during the
+ lifetime of the object.
+
+ Use cacheKey() instead.
+
+ \warning The serial number doesn't necessarily change when the
+ palette is altered. This means that it may be dangerous to use it
+ as a cache key.
+
+ \sa operator==()
+*/
+int QPalette::serialNumber() const
+{
+ return d->ser_no;
+}
+
+/*!
+ Returns a number that identifies the contents of this QPalette
+ object. Distinct QPalette objects can have the same key if
+ they refer to the same contents.
+
+ The cacheKey() will change when the palette is altered.
+*/
+qint64 QPalette::cacheKey() const
+{
+ return (((qint64) d->ser_no) << 32) | ((qint64) (d->detach_no));
+}
+
+/*!
+ Returns a new QPalette that has attributes copied from \a other.
+*/
+QPalette QPalette::resolve(const QPalette &other) const
+{
+ if ((*this == other && resolve_mask == other.resolve_mask)
+ || resolve_mask == 0) {
+ QPalette o = other;
+ o.resolve_mask = resolve_mask;
+ return o;
+ }
+
+ QPalette palette(*this);
+ palette.detach();
+
+ for(int role = 0; role < (int)NColorRoles; role++)
+ if (!(resolve_mask & (1<<role)))
+ for(int grp = 0; grp < (int)NColorGroups; grp++)
+ palette.d->br[grp][role] = other.d->br[grp][role];
+
+ return palette;
+}
+
+/*!
+ \fn uint QPalette::resolve() const
+ \internal
+*/
+
+/*!
+ \fn void QPalette::resolve(uint mask)
+ \internal
+*/
+
+
+/*****************************************************************************
+ QPalette stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+
+static const int NumOldRoles = 7;
+static const int oldRoles[7] = { QPalette::Foreground, QPalette::Background, QPalette::Light,
+ QPalette::Dark, QPalette::Mid, QPalette::Text, QPalette::Base };
+
+/*!
+ \relates QPalette
+
+ Writes the palette, \a p to the stream \a s and returns a
+ reference to the stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QDataStream &operator<<(QDataStream &s, const QPalette &p)
+{
+ for (int grp = 0; grp < (int)QPalette::NColorGroups; grp++) {
+ if (s.version() == 1) {
+ // Qt 1.x
+ for (int i = 0; i < NumOldRoles; ++i)
+ s << p.d->br[grp][oldRoles[i]].color();
+ } else {
+ int max = QPalette::ToolTipText + 1;
+ if (s.version() <= QDataStream::Qt_2_1)
+ max = QPalette::HighlightedText + 1;
+ else if (s.version() <= QDataStream::Qt_4_3)
+ max = QPalette::AlternateBase + 1;
+ for (int r = 0; r < max; r++)
+ s << p.d->br[grp][r];
+ }
+ }
+ return s;
+}
+
+static void readV1ColorGroup(QDataStream &s, QPalette &pal, QPalette::ColorGroup grp)
+{
+ for (int i = 0; i < NumOldRoles; ++i) {
+ QColor col;
+ s >> col;
+ pal.setColor(grp, (QPalette::ColorRole)oldRoles[i], col);
+ }
+}
+
+/*!
+ \relates QPalette
+
+ Reads a palette from the stream, \a s into the palette \a p, and
+ returns a reference to the stream.
+
+ \sa \link datastreamformat.html Format of the QDataStream operators \endlink
+*/
+
+QDataStream &operator>>(QDataStream &s, QPalette &p)
+{
+ if(s.version() == 1) {
+ p = QPalette();
+ readV1ColorGroup(s, p, QPalette::Active);
+ readV1ColorGroup(s, p, QPalette::Disabled);
+ readV1ColorGroup(s, p, QPalette::Inactive);
+ } else {
+ int max = QPalette::NColorRoles;
+ if (s.version() <= QDataStream::Qt_2_1) {
+ p = QPalette();
+ max = QPalette::HighlightedText + 1;
+ } else if (s.version() <= QDataStream::Qt_4_3) {
+ p = QPalette();
+ max = QPalette::AlternateBase + 1;
+ }
+
+ QBrush tmp;
+ for(int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
+ for(int role = 0; role < max; ++role) {
+ s >> tmp;
+ p.setBrush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role, tmp);
+ }
+ }
+ }
+ return s;
+}
+#endif //QT_NO_DATASTREAM
+
+/*!
+ Returns true if this palette and \a p are copies of each other,
+ i.e. one of them was created as a copy of the other and neither
+ was subsequently modified; otherwise returns false. This is much
+ stricter than equality.
+
+ \sa operator=() operator==()
+*/
+
+bool QPalette::isCopyOf(const QPalette &p) const
+{
+ return d == p.d;
+}
+
+/*!
+
+ Sets a the group at \a cg. You can pass either brushes, pixmaps or
+ plain colors for \a windowText, \a button, \a light, \a dark, \a
+ mid, \a text, \a bright_text, \a base and \a window.
+
+ \sa QBrush
+*/
+void QPalette::setColorGroup(ColorGroup cg, const QBrush &windowText, const QBrush &button,
+ const QBrush &light, const QBrush &dark, const QBrush &mid,
+ const QBrush &text, const QBrush &bright_text, const QBrush &base,
+ const QBrush &window)
+{
+ QBrush alt_base = QBrush(qt_mix_colors(base.color(), button.color()));
+ QBrush mid_light = QBrush(qt_mix_colors(button.color(), light.color()));
+ QColor toolTipBase(255, 255, 220);
+ QColor toolTipText(0, 0, 0);
+
+ setColorGroup(cg, windowText, button, light, dark, mid, text, bright_text, base,
+ alt_base, window, mid_light, text,
+ QBrush(Qt::black), QBrush(Qt::darkBlue), QBrush(Qt::white),
+ QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase),
+ QBrush(toolTipText));
+
+ resolve_mask &= ~(1 << Highlight);
+ resolve_mask &= ~(1 << HighlightedText);
+ resolve_mask &= ~(1 << LinkVisited);
+ resolve_mask &= ~(1 << Link);
+}
+
+
+/*!\internal*/
+void
+QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBrush &button,
+ const QBrush &light, const QBrush &dark, const QBrush &mid,
+ const QBrush &text, const QBrush &bright_text,
+ const QBrush &base, const QBrush &alternate_base,
+ const QBrush &background, const QBrush &midlight,
+ const QBrush &button_text, const QBrush &shadow,
+ const QBrush &highlight, const QBrush &highlighted_text,
+ const QBrush &link, const QBrush &link_visited)
+{
+ setColorGroup(cg, foreground, button, light, dark, mid,
+ text, bright_text, base, alternate_base, background,
+ midlight, button_text, shadow, highlight, highlighted_text,
+ link, link_visited, background, foreground);
+}
+
+/*!\internal*/
+void QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBrush &button,
+ const QBrush &light, const QBrush &dark, const QBrush &mid,
+ const QBrush &text, const QBrush &bright_text,
+ const QBrush &base, const QBrush &alternate_base,
+ const QBrush &background, const QBrush &midlight,
+ const QBrush &button_text, const QBrush &shadow,
+ const QBrush &highlight, const QBrush &highlighted_text,
+ const QBrush &link, const QBrush &link_visited,
+ const QBrush &toolTipBase, const QBrush &toolTipText)
+{
+ detach();
+ setBrush(cg, WindowText, foreground);
+ setBrush(cg, Button, button);
+ setBrush(cg, Light, light);
+ setBrush(cg, Dark, dark);
+ setBrush(cg, Mid, mid);
+ setBrush(cg, Text, text);
+ setBrush(cg, BrightText, bright_text);
+ setBrush(cg, Base, base);
+ setBrush(cg, AlternateBase, alternate_base);
+ setBrush(cg, Window, background);
+ setBrush(cg, Midlight, midlight);
+ setBrush(cg, ButtonText, button_text);
+ setBrush(cg, Shadow, shadow);
+ setBrush(cg, Highlight, highlight);
+ setBrush(cg, HighlightedText, highlighted_text);
+ setBrush(cg, Link, link);
+ setBrush(cg, LinkVisited, link_visited);
+ setBrush(cg, ToolTipBase, toolTipBase);
+ setBrush(cg, ToolTipText, toolTipText);
+}
+
+/*!
+ \fn QPalette QPalette::copy() const
+
+ Use simple assignment instead.
+*/
+
+/*!
+ \fn QColorGroup QPalette::normal() const
+ \obsolete
+
+ Returns the active color group. Use active() instead.
+
+ Use createColorGroup(Active) instead.
+*/
+
+/*!
+ \fn void QPalette::setNormal(const QColorGroup &colorGroup)
+
+ Sets the normal color group to \a colorGroup.
+
+ \sa QColorGroup
+*/
+
+/*!
+ \fn QColorGroup QPalette::active() const
+
+ Returns the active color group.
+ \sa QColorGroup
+*/
+
+/*!
+ \fn QColorGroup QPalette::disabled() const
+
+ Returns the disabled color group.
+ \sa QColorGroup
+*/
+
+/*!
+ \fn QColorGroup QPalette::inactive() const
+
+ Returns the inactive color group.
+ \sa QColorGroup
+*/
+
+/*!
+ \fn void QPalette::setActive(const QColorGroup &colorGroup)
+
+ Sets the active color group to \a colorGroup.
+ \sa QColorGroup
+*/
+
+/*!
+ \fn void QPalette::setDisabled(const QColorGroup &colorGroup)
+
+ Sets the disabled color group to \a colorGroup.
+ \sa QColorGroup
+*/
+
+/*!
+ \fn void QPalette::setInactive(const QColorGroup &colorGroup)
+
+ Sets the inactive color group.
+ \sa QColorGroup
+*/
+
+/*! \class QColorGroup
+ \brief The QColorGroup class contains color groups for each widget state.
+ \compat
+*/
+
+/*! \fn QColorGroup::QColorGroup()
+
+ Use QPalette() instead.
+*/
+
+/*! \fn QColorGroup::QColorGroup(const QBrush &foreground, const QBrush &button, \
+ const QBrush &light, const QBrush &dark, const QBrush &mid, \
+ const QBrush &text, const QBrush &bright_text,
+ const QBrush &base, const QBrush &background)
+
+ Use QPalette(\a foreground, \a button, \a light, \a dark, \a mid,
+ \a text, \a bright_text, \a base, \a background) instead.
+*/
+
+/*! \fn QColorGroup::QColorGroup(const QColor &foreground, const QColor &background, \
+ const QColor &light, const QColor &dark, const QColor &mid, \
+ const QColor &text, const QColor &base)
+
+ Use QColorGroup(\a foreground, \a background, \a light, \a dark,
+ \a mid, \a text, \a base) instead.
+*/
+
+/*! \fn QColorGroup::QColorGroup(const QColorGroup &other)
+
+ Use QPalette(\a other) instead.
+*/
+
+/*! \fn QColorGroup::QColorGroup(const QPalette &pal)
+
+ Use QPalette(\a pal) instead.
+*/
+
+/*! \fn const QColor &QColorGroup::foreground() const
+
+ Use QPalette::windowText().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::button() const
+
+ Use QPalette::button().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::light() const
+
+ Use QPalette::light().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::dark() const
+
+ Use QPalette::dark().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::mid() const
+
+ Use QPalette::mid().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::text() const
+
+ Use QPalette::text().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::base() const
+
+ Use QPalette::base().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::background() const
+
+ Use QPalette::window().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::midlight() const
+
+ Use QPalette::midlight().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::brightText() const
+
+ Use QPalette::brightText().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::buttonText() const
+
+ Use QPalette::buttonText().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::shadow() const
+
+ Use QPalette::shadow().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::highlight() const
+
+ Use QPalette::highlight().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::highlightedText() const
+
+ Use QPalette::highlightedText().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::link() const
+
+ Use QPalette::link().color() instead.
+*/
+
+/*! \fn const QColor &QColorGroup::linkVisited() const
+
+ Use QPalette::linkVisited().color() instead.
+*/
+
+/*! \fn QDataStream &operator<<(QDataStream &ds, const QColorGroup &colorGroup)
+ \relates QColorGroup
+ \compat
+*/
+
+/*! \fn QDataStream &operator>>(QDataStream &ds, QColorGroup &colorGroup)
+ \relates QColorGroup
+ \compat
+*/
+
+/*! \fn bool QColorGroup::operator==(const QColorGroup &other) const
+
+ Returns true if this color group is equal to \a other; otherwise
+ returns false.
+*/
+
+/*! \fn bool QColorGroup::operator!=(const QColorGroup &other) const
+
+ Returns true if this color group is not equal to \a other;
+ otherwise returns false.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h
new file mode 100644
index 0000000000..e9534c3180
--- /dev/null
+++ b/src/gui/kernel/qpalette.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPALETTE_H
+#define QPALETTE_H
+
+#include <QtGui/qwindowdefs.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qbrush.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifdef QT3_SUPPORT
+class QColorGroup;
+#endif
+class QPalettePrivate;
+class QVariant;
+
+class Q_GUI_EXPORT QPalette
+{
+ Q_GADGET
+ Q_ENUMS(ColorGroup ColorRole)
+public:
+ QPalette();
+ QPalette(const QColor &button);
+ QPalette(Qt::GlobalColor button);
+ QPalette(const QColor &button, const QColor &window);
+ QPalette(const QBrush &windowText, const QBrush &button, const QBrush &light,
+ const QBrush &dark, const QBrush &mid, const QBrush &text,
+ const QBrush &bright_text, const QBrush &base, const QBrush &window);
+ QPalette(const QColor &windowText, const QColor &window, const QColor &light,
+ const QColor &dark, const QColor &mid, const QColor &text, const QColor &base);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QPalette(const QColorGroup &active, const QColorGroup &disabled, const QColorGroup &inactive);
+#endif
+ QPalette(const QPalette &palette);
+ ~QPalette();
+ QPalette &operator=(const QPalette &palette);
+ operator QVariant() const;
+
+ // Do not change the order, the serialization format depends on it
+ enum ColorGroup { Active, Disabled, Inactive, NColorGroups, Current, All, Normal = Active };
+ enum ColorRole { WindowText, Button, Light, Midlight, Dark, Mid,
+ Text, BrightText, ButtonText, Base, Window, Shadow,
+ Highlight, HighlightedText,
+ Link, LinkVisited, // ### Qt 5: remove
+ AlternateBase,
+ NoRole, // ### Qt 5: value should be 0 or -1
+ ToolTipBase, ToolTipText,
+ NColorRoles = ToolTipText + 1,
+ Foreground = WindowText, Background = Window // ### Qt 5: remove
+ };
+
+ inline ColorGroup currentColorGroup() const { return static_cast<ColorGroup>(current_group); }
+ inline void setCurrentColorGroup(ColorGroup cg) { current_group = cg; }
+
+ inline const QColor &color(ColorGroup cg, ColorRole cr) const
+ { return brush(cg, cr).color(); }
+ const QBrush &brush(ColorGroup cg, ColorRole cr) const;
+ inline void setColor(ColorGroup cg, ColorRole cr, const QColor &color);
+ inline void setColor(ColorRole cr, const QColor &color);
+ inline void setBrush(ColorRole cr, const QBrush &brush);
+ bool isBrushSet(ColorGroup cg, ColorRole cr) const;
+ void setBrush(ColorGroup cg, ColorRole cr, const QBrush &brush);
+ void setColorGroup(ColorGroup cr, const QBrush &windowText, const QBrush &button,
+ const QBrush &light, const QBrush &dark, const QBrush &mid,
+ const QBrush &text, const QBrush &bright_text, const QBrush &base,
+ const QBrush &window);
+ bool isEqual(ColorGroup cr1, ColorGroup cr2) const;
+
+ inline const QColor &color(ColorRole cr) const { return color(Current, cr); }
+ inline const QBrush &brush(ColorRole cr) const { return brush(Current, cr); }
+ inline const QBrush &foreground() const { return brush(WindowText); }
+ inline const QBrush &windowText() const { return brush(WindowText); }
+ inline const QBrush &button() const { return brush(Button); }
+ inline const QBrush &light() const { return brush(Light); }
+ inline const QBrush &dark() const { return brush(Dark); }
+ inline const QBrush &mid() const { return brush(Mid); }
+ inline const QBrush &text() const { return brush(Text); }
+ inline const QBrush &base() const { return brush(Base); }
+ inline const QBrush &alternateBase() const { return brush(AlternateBase); }
+ inline const QBrush &toolTipBase() const { return brush(ToolTipBase); }
+ inline const QBrush &toolTipText() const { return brush(ToolTipText); }
+ inline const QBrush &background() const { return brush(Window); }
+ inline const QBrush &window() const { return brush(Window); }
+ inline const QBrush &midlight() const { return brush(Midlight); }
+ inline const QBrush &brightText() const { return brush(BrightText); }
+ inline const QBrush &buttonText() const { return brush(ButtonText); }
+ inline const QBrush &shadow() const { return brush(Shadow); }
+ inline const QBrush &highlight() const { return brush(Highlight); }
+ inline const QBrush &highlightedText() const { return brush(HighlightedText); }
+ inline const QBrush &link() const { return brush(Link); }
+ inline const QBrush &linkVisited() const { return brush(LinkVisited); }
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QPalette copy() const { QPalette p = *this; p.detach(); return p; }
+ QT3_SUPPORT QColorGroup normal() const;
+ inline QT3_SUPPORT void setNormal(const QColorGroup &cg) { setColorGroup(Active, cg); }
+
+ QT3_SUPPORT QColorGroup active() const;
+ QT3_SUPPORT QColorGroup disabled() const;
+ QT3_SUPPORT QColorGroup inactive() const;
+ inline QT3_SUPPORT void setActive(const QColorGroup &cg) { setColorGroup(Active, cg); }
+ inline QT3_SUPPORT void setDisabled(const QColorGroup &cg) { setColorGroup(Disabled, cg); }
+ inline QT3_SUPPORT void setInactive(const QColorGroup &cg) { setColorGroup(Inactive, cg); }
+#endif
+
+ bool operator==(const QPalette &p) const;
+ inline bool operator!=(const QPalette &p) const { return !(operator==(p)); }
+ bool isCopyOf(const QPalette &p) const;
+
+ int serialNumber() const;
+ qint64 cacheKey() const;
+
+ QPalette resolve(const QPalette &) const;
+ inline uint resolve() const { return resolve_mask; }
+ inline void resolve(uint mask) { resolve_mask = mask; }
+
+private:
+ void setColorGroup(ColorGroup cr, const QBrush &windowText, const QBrush &button,
+ const QBrush &light, const QBrush &dark, const QBrush &mid,
+ const QBrush &text, const QBrush &bright_text,
+ const QBrush &base, const QBrush &alternate_base,
+ const QBrush &window, const QBrush &midlight,
+ const QBrush &button_text, const QBrush &shadow,
+ const QBrush &highlight, const QBrush &highlighted_text,
+ const QBrush &link, const QBrush &link_visited);
+ void setColorGroup(ColorGroup cr, const QBrush &windowText, const QBrush &button,
+ const QBrush &light, const QBrush &dark, const QBrush &mid,
+ const QBrush &text, const QBrush &bright_text,
+ const QBrush &base, const QBrush &alternate_base,
+ const QBrush &window, const QBrush &midlight,
+ const QBrush &button_text, const QBrush &shadow,
+ const QBrush &highlight, const QBrush &highlighted_text,
+ const QBrush &link, const QBrush &link_visited,
+ const QBrush &toolTipBase, const QBrush &toolTipText);
+#ifdef QT3_SUPPORT
+ friend class QColorGroup;
+ void setColorGroup(ColorGroup, const QColorGroup &);
+ QColorGroup createColorGroup(ColorGroup) const;
+#endif
+ void init();
+ void detach();
+
+ QPalettePrivate *d;
+ uint current_group : 4;
+ uint resolve_mask : 28;
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const QPalette &p);
+};
+
+inline void QPalette::setColor(ColorGroup acg, ColorRole acr,
+ const QColor &acolor)
+{ setBrush(acg, acr, QBrush(acolor)); }
+inline void QPalette::setColor(ColorRole acr, const QColor &acolor)
+{ setColor(All, acr, acolor); }
+inline void QPalette::setBrush(ColorRole acr, const QBrush &abrush)
+{ setBrush(All, acr, abrush); }
+
+#ifdef QT3_SUPPORT
+class Q_GUI_EXPORT QColorGroup : public QPalette
+{
+public:
+ inline QColorGroup() : QPalette() {}
+ inline QColorGroup(const QBrush &foreground, const QBrush &button, const QBrush &light,
+ const QBrush &dark, const QBrush &mid, const QBrush &text,
+ const QBrush &bright_text, const QBrush &base, const QBrush &background)
+ : QPalette(foreground, button, light, dark, mid, text, bright_text, base, background)
+ {}
+ inline QColorGroup(const QColor &foreground, const QColor &background, const QColor &light,
+ const QColor &dark, const QColor &mid, const QColor &text, const QColor &base)
+ : QPalette(foreground, background, light, dark, mid, text, base) {}
+ inline QColorGroup(const QColorGroup &cg) : QPalette(cg) {}
+ inline QColorGroup(const QPalette &pal) : QPalette(pal) {}
+ bool operator==(const QColorGroup &other) const;
+ inline bool operator!=(const QColorGroup &other) const { return !(operator==(other)); }
+ operator QVariant() const;
+
+ inline QT3_SUPPORT const QColor &foreground() const { return color(WindowText); }
+ inline QT3_SUPPORT const QColor &button() const { return color(Button); }
+ inline QT3_SUPPORT const QColor &light() const { return color(Light); }
+ inline QT3_SUPPORT const QColor &dark() const { return color(Dark); }
+ inline QT3_SUPPORT const QColor &mid() const { return color(Mid); }
+ inline QT3_SUPPORT const QColor &text() const { return color(Text); }
+ inline QT3_SUPPORT const QColor &base() const { return color(Base); }
+ inline QT3_SUPPORT const QColor &background() const { return color(Window); }
+ inline QT3_SUPPORT const QColor &midlight() const { return color(Midlight); }
+ inline QT3_SUPPORT const QColor &brightText() const { return color(BrightText); }
+ inline QT3_SUPPORT const QColor &buttonText() const { return color(ButtonText); }
+ inline QT3_SUPPORT const QColor &shadow() const { return color(Shadow); }
+ inline QT3_SUPPORT const QColor &highlight() const { return color(Highlight); }
+ inline QT3_SUPPORT const QColor &highlightedText() const { return color(HighlightedText); }
+ inline QT3_SUPPORT const QColor &link() const { return color(Link); }
+ inline QT3_SUPPORT const QColor &linkVisited() const { return color(LinkVisited); }
+};
+
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QT3_SUPPORT QDataStream &operator<<(QDataStream &ds, const QColorGroup &cg);
+Q_GUI_EXPORT QT3_SUPPORT QDataStream &operator>>(QDataStream &ds, QColorGroup &cg);
+#endif
+
+inline QColorGroup QPalette::inactive() const { return createColorGroup(Inactive); }
+inline QColorGroup QPalette::disabled() const { return createColorGroup(Disabled); }
+inline QColorGroup QPalette::active() const { return createColorGroup(Active); }
+inline QColorGroup QPalette::normal() const { return createColorGroup(Active); }
+
+#endif
+
+/*****************************************************************************
+ QPalette stream functions
+ *****************************************************************************/
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &ds, const QPalette &p);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &ds, QPalette &p);
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPALETTE_H
diff --git a/src/gui/kernel/qsessionmanager.h b/src/gui/kernel/qsessionmanager.h
new file mode 100644
index 0000000000..560741d662
--- /dev/null
+++ b/src/gui/kernel/qsessionmanager.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSESSIONMANAGER_H
+#define QSESSIONMANAGER_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+
+#ifndef QT_NO_SESSIONMANAGER
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QSessionManagerPrivate;
+
+class Q_GUI_EXPORT QSessionManager : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSessionManager)
+ QSessionManager(QApplication *app, QString &id, QString &key);
+ ~QSessionManager();
+public:
+ QString sessionId() const;
+ QString sessionKey() const;
+#if defined(Q_WS_X11) || defined(Q_WS_MAC)
+ void *handle() const;
+#endif
+
+ bool allowsInteraction();
+ bool allowsErrorInteraction();
+ void release();
+
+ void cancel();
+
+ enum RestartHint {
+ RestartIfRunning,
+ RestartAnyway,
+ RestartImmediately,
+ RestartNever
+ };
+ void setRestartHint(RestartHint);
+ RestartHint restartHint() const;
+
+ void setRestartCommand(const QStringList&);
+ QStringList restartCommand() const;
+ void setDiscardCommand(const QStringList&);
+ QStringList discardCommand() const;
+
+ void setManagerProperty(const QString& name, const QString& value);
+ void setManagerProperty(const QString& name, const QStringList& value);
+
+ bool isPhase2() const;
+ void requestPhase2();
+
+private:
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QBaseApplication;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_SESSIONMANAGER
+
+#endif // QSESSIONMANAGER_H
diff --git a/src/gui/kernel/qsessionmanager_qws.cpp b/src/gui/kernel/qsessionmanager_qws.cpp
new file mode 100644
index 0000000000..ae521bb204
--- /dev/null
+++ b/src/gui/kernel/qsessionmanager_qws.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qsessionmanager.h>
+
+#ifndef QT_NO_SESSIONMANAGER
+
+QT_BEGIN_NAMESPACE
+
+class QSessionManagerPrivate : public QObjectPrivate
+{
+public:
+ QSessionManagerPrivate(QSessionManager *m, const QString &id,
+ const QString &key);
+
+ QStringList restartCommand;
+ QStringList discardCommand;
+ const QString sessionId;
+ const QString sessionKey;
+ QSessionManager::RestartHint restartHint;
+};
+
+QSessionManagerPrivate::QSessionManagerPrivate(QSessionManager*,
+ const QString &id,
+ const QString &key)
+ : QObjectPrivate(), sessionId(id), sessionKey(key)
+{
+}
+
+QSessionManager::QSessionManager(QApplication *app, QString &id, QString &key)
+ : QObject(*new QSessionManagerPrivate(this, id, key), app)
+{
+ Q_D(QSessionManager);
+ d->restartHint = RestartIfRunning;
+}
+
+QSessionManager::~QSessionManager()
+{
+}
+
+QString QSessionManager::sessionId() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionId;
+}
+
+QString QSessionManager::sessionKey() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionKey;
+}
+
+
+bool QSessionManager::allowsInteraction()
+{
+ return false;
+}
+
+bool QSessionManager::allowsErrorInteraction()
+{
+ return false;
+}
+
+void QSessionManager::release()
+{
+}
+
+void QSessionManager::cancel()
+{
+}
+
+void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
+{
+ Q_D(QSessionManager);
+ d->restartHint = hint;
+}
+
+QSessionManager::RestartHint QSessionManager::restartHint() const
+{
+ Q_D(const QSessionManager);
+ return d->restartHint;
+}
+
+void QSessionManager::setRestartCommand(const QStringList &command)
+{
+ Q_D(QSessionManager);
+ d->restartCommand = command;
+}
+
+QStringList QSessionManager::restartCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->restartCommand;
+}
+
+void QSessionManager::setDiscardCommand(const QStringList &command)
+{
+ Q_D(QSessionManager);
+ d->discardCommand = command;
+}
+
+QStringList QSessionManager::discardCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->discardCommand;
+}
+
+void QSessionManager::setManagerProperty(const QString &name,
+ const QString &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+
+void QSessionManager::setManagerProperty(const QString &name,
+ const QStringList &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+
+bool QSessionManager::isPhase2() const
+{
+ return false;
+}
+
+void QSessionManager::requestPhase2()
+{
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SESSIONMANAGER
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp
new file mode 100644
index 0000000000..50b6e59cd4
--- /dev/null
+++ b/src/gui/kernel/qshortcut.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshortcut.h"
+#include "private/qwidget_p.h"
+
+#ifndef QT_NO_SHORTCUT
+#include <qevent.h>
+#include <qwhatsthis.h>
+#include <qmenu.h>
+#include <qapplication.h>
+#include <private/qapplication_p.h>
+#include <private/qshortcutmap_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QAPP_CHECK(functionName) \
+ if (!qApp) { \
+ qWarning("QShortcut: Initialize QApplication before calling '" functionName "'."); \
+ return; \
+ }
+
+/*!
+ \class QShortcut
+ \brief The QShortcut class is used to create keyboard shortcuts.
+
+ \ingroup events
+ \mainclass
+
+ The QShortcut class provides a way of connecting keyboard
+ shortcuts to Qt's \l{signals and slots} mechanism, so that
+ objects can be informed when a shortcut is executed. The shortcut
+ can be set up to contain all the key presses necessary to
+ describe a keyboard shortcut, including the states of modifier
+ keys such as \gui Shift, \gui Ctrl, and \gui Alt.
+
+ \target mnemonic
+
+ On certain widgets, using '&' in front of a character will
+ automatically create a mnemonic (a shortcut) for that character,
+ e.g. "E&xit" will create the shortcut \gui Alt+X (use '&&' to
+ display an actual ampersand). The widget might consume and perform
+ an action on a given shortcut. On X11 the ampersand will not be
+ shown and the character will be underlined. On Windows, shortcuts
+ are normally not displayed until the user presses the \gui Alt
+ key, but this is a setting the user can change. On Mac, shortcuts
+ are disabled by default. Call qt_set_sequence_auto_mnemonic() to
+ enable them. However, because mnemonic shortcuts do not fit in
+ with Aqua's guidelines, Qt will not show the shortcut character
+ underlined.
+
+ For applications that use menus, it may be more convenient to
+ use the convenience functions provided in the QMenu class to
+ assign keyboard shortcuts to menu items as they are created.
+ Alternatively, shortcuts may be associated with other types of
+ actions in the QAction class.
+
+ The simplest way to create a shortcut for a particular widget is
+ to construct the shortcut with a key sequence. For example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qshortcut.cpp 0
+
+ When the user types the \l{QKeySequence}{key sequence}
+ for a given shortcut, the shortcut's activated() signal is
+ emitted. (In the case of ambiguity, the activatedAmbiguously()
+ signal is emitted.) A shortcut is "listened for" by Qt's event
+ loop when the shortcut's parent widget is receiving events.
+
+ A shortcut's key sequence can be set with setKey() and retrieved
+ with key(). A shortcut can be enabled or disabled with
+ setEnabled(), and can have "What's This?" help text set with
+ setWhatsThis().
+
+ \sa QShortcutEvent, QKeySequence, QAction
+*/
+
+/*!
+ \fn QWidget *QShortcut::parentWidget() const
+
+ Returns the shortcut's parent widget.
+*/
+
+/*!
+ \fn void QShortcut::activated()
+
+ This signal is emitted when the user types the shortcut's key
+ sequence.
+
+ \sa activatedAmbiguously()
+*/
+
+/*!
+ \fn void QShortcut::activatedAmbiguously()
+
+ When a key sequence is being typed at the keyboard, it is said to
+ be ambiguous as long as it matches the start of more than one
+ shortcut.
+
+ When a shortcut's key sequence is completed,
+ activatedAmbiguously() is emitted if the key sequence is still
+ ambiguous (i.e., it is the start of one or more other shortcuts).
+ The activated() signal is not emitted in this case.
+
+ \sa activated()
+*/
+
+/*
+ \internal
+ Private data accessed through d-pointer.
+*/
+class QShortcutPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QShortcut)
+public:
+ QShortcutPrivate() : sc_context(Qt::WindowShortcut), sc_enabled(true), sc_autorepeat(true), sc_id(0) {}
+ QKeySequence sc_sequence;
+ Qt::ShortcutContext sc_context;
+ bool sc_enabled;
+ bool sc_autorepeat;
+ int sc_id;
+ QString sc_whatsthis;
+ void redoGrab(QShortcutMap &map);
+};
+
+void QShortcutPrivate::redoGrab(QShortcutMap &map)
+{
+ Q_Q(QShortcut);
+ QWidget *parent = q->parentWidget();
+ if (!parent) {
+ qWarning("QShortcut: No widget parent defined");
+ return;
+ }
+
+ if (sc_id)
+ map.removeShortcut(sc_id, q);
+ if (sc_sequence.isEmpty())
+ return;
+ sc_id = map.addShortcut(q, sc_sequence, sc_context);
+ if (!sc_enabled)
+ map.setShortcutEnabled(false, sc_id, q);
+ if (!sc_autorepeat)
+ map.setShortcutAutoRepeat(false, sc_id, q);
+}
+
+/*!
+ Constructs a QShortcut object for the \a parent widget. Since no
+ shortcut key sequence is specified, the shortcut will not emit any
+ signals.
+
+ \sa setKey()
+*/
+QShortcut::QShortcut(QWidget *parent)
+ : QObject(*new QShortcutPrivate, parent)
+{
+ Q_ASSERT(parent != 0);
+}
+
+/*!
+ Constructs a QShortcut object for the \a parent widget. The shortcut
+ operates on its parent, listening for \l{QShortcutEvent}s that
+ match the \a key sequence. Depending on the ambiguity of the
+ event, the shortcut will call the \a member function, or the \a
+ ambiguousMember function, if the key press was in the shortcut's
+ \a context.
+*/
+QShortcut::QShortcut(const QKeySequence &key, QWidget *parent,
+ const char *member, const char *ambiguousMember,
+ Qt::ShortcutContext context)
+ : QObject(*new QShortcutPrivate, parent)
+{
+ QAPP_CHECK("QShortcut");
+
+ Q_D(QShortcut);
+ Q_ASSERT(parent != 0);
+ d->sc_context = context;
+ d->sc_sequence = key;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+ if (member)
+ connect(this, SIGNAL(activated()), parent, member);
+ if (ambiguousMember)
+ connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember);
+}
+
+/*!
+ Destroys the shortcut.
+*/
+QShortcut::~QShortcut()
+{
+ Q_D(QShortcut);
+ if (qApp)
+ qApp->d_func()->shortcutMap.removeShortcut(d->sc_id, this);
+}
+
+/*!
+ \property QShortcut::key
+ \brief the shortcut's key sequence
+
+ This is a key sequence with an optional combination of Shift, Ctrl,
+ and Alt. The key sequence may be supplied in a number of ways:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qshortcut.cpp 1
+
+ By default, this property contains an empty key sequence.
+*/
+void QShortcut::setKey(const QKeySequence &key)
+{
+ Q_D(QShortcut);
+ if (d->sc_sequence == key)
+ return;
+ QAPP_CHECK("setKey");
+ d->sc_sequence = key;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+}
+
+QKeySequence QShortcut::key() const
+{
+ Q_D(const QShortcut);
+ return d->sc_sequence;
+}
+
+/*!
+ \property QShortcut::enabled
+ \brief whether the shortcut is enabled
+
+ An enabled shortcut emits the activated() or activatedAmbiguously()
+ signal when a QShortcutEvent occurs that matches the shortcut's
+ key() sequence.
+
+ If the application is in \c WhatsThis mode the shortcut will not emit
+ the signals, but will show the "What's This?" text instead.
+
+ By default, this property is true.
+
+ \sa whatsThis
+*/
+void QShortcut::setEnabled(bool enable)
+{
+ Q_D(QShortcut);
+ if (d->sc_enabled == enable)
+ return;
+ QAPP_CHECK("setEnabled");
+ d->sc_enabled = enable;
+ qApp->d_func()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this);
+}
+
+bool QShortcut::isEnabled() const
+{
+ Q_D(const QShortcut);
+ return d->sc_enabled;
+}
+
+/*!
+ \property QShortcut::context
+ \brief the context in which the shortcut is valid
+
+ A shortcut's context decides in which circumstances a shortcut is
+ allowed to be triggered. The normal context is Qt::WindowShortcut,
+ which allows the shortcut to trigger if the parent (the widget
+ containing the shortcut) is a subwidget of the active top-level
+ window.
+
+ By default, this property is set to Qt::WindowShortcut.
+*/
+void QShortcut::setContext(Qt::ShortcutContext context)
+{
+ Q_D(QShortcut);
+ if(d->sc_context == context)
+ return;
+ QAPP_CHECK("setContext");
+ d->sc_context = context;
+ d->redoGrab(qApp->d_func()->shortcutMap);
+}
+
+Qt::ShortcutContext QShortcut::context()
+{
+ Q_D(QShortcut);
+ return d->sc_context;
+}
+
+/*!
+ \property QShortcut::whatsThis
+ \brief the shortcut's "What's This?" help text
+
+ The text will be shown when the application is in "What's
+ This?" mode and the user types the shortcut key() sequence.
+
+ To set "What's This?" help on a menu item (with or without a
+ shortcut key), set the help on the item's action.
+
+ By default, this property contains an empty string.
+
+ \sa QWhatsThis::inWhatsThisMode(), QAction::setWhatsThis()
+*/
+void QShortcut::setWhatsThis(const QString &text)
+{
+ Q_D(QShortcut);
+ d->sc_whatsthis = text;
+}
+
+QString QShortcut::whatsThis() const
+{
+ Q_D(const QShortcut);
+ return d->sc_whatsthis;
+}
+
+/*!
+ \property QShortcut::autoRepeat
+ \brief whether the shortcut can auto repeat
+ \since 4.2
+
+ If true, the shortcut will auto repeat when the keyboard shortcut
+ combination is held down, provided that keyboard auto repeat is
+ enabled on the system.
+ The default value is true.
+*/
+void QShortcut::setAutoRepeat(bool on)
+{
+ Q_D(QShortcut);
+ if (d->sc_autorepeat == on)
+ return;
+ QAPP_CHECK("setAutoRepeat");
+ d->sc_autorepeat = on;
+ qApp->d_func()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this);
+}
+
+bool QShortcut::autoRepeat() const
+{
+ Q_D(const QShortcut);
+ return d->sc_autorepeat;
+}
+
+/*!
+ Returns the shortcut's ID.
+
+ \sa QShortcutEvent::shortcutId()
+*/
+int QShortcut::id() const
+{
+ Q_D(const QShortcut);
+ return d->sc_id;
+}
+
+/*!
+ \internal
+*/
+bool QShortcut::event(QEvent *e)
+{
+ Q_D(QShortcut);
+ bool handled = false;
+ if (d->sc_enabled && e->type() == QEvent::Shortcut) {
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
+ if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){
+#ifndef QT_NO_WHATSTHIS
+ if (QWhatsThis::inWhatsThisMode()) {
+ QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis);
+ handled = true;
+ } else
+#endif
+ if (se->isAmbiguous())
+ emit activatedAmbiguously();
+ else
+ emit activated();
+ handled = true;
+ }
+ }
+ return handled;
+}
+#endif // QT_NO_SHORTCUT
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qshortcut.h b/src/gui/kernel/qshortcut.h
new file mode 100644
index 0000000000..1219f5af40
--- /dev/null
+++ b/src/gui/kernel/qshortcut.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHORTCUT_H
+#define QSHORTCUT_H
+
+#include <QtGui/qwidget.h>
+#include <QtGui/qkeysequence.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_SHORTCUT
+
+class QShortcutPrivate;
+class Q_GUI_EXPORT QShortcut : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QShortcut)
+ Q_PROPERTY(QKeySequence key READ key WRITE setKey)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
+ Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext)
+public:
+ explicit QShortcut(QWidget *parent);
+ QShortcut(const QKeySequence& key, QWidget *parent,
+ const char *member = 0, const char *ambiguousMember = 0,
+ Qt::ShortcutContext context = Qt::WindowShortcut);
+ ~QShortcut();
+
+ void setKey(const QKeySequence& key);
+ QKeySequence key() const;
+
+ void setEnabled(bool enable);
+ bool isEnabled() const;
+
+ void setContext(Qt::ShortcutContext context);
+ Qt::ShortcutContext context();
+
+ void setWhatsThis(const QString &text);
+ QString whatsThis() const;
+
+ void setAutoRepeat(bool on);
+ bool autoRepeat() const;
+
+ int id() const;
+
+ inline QWidget *parentWidget() const
+ { return static_cast<QWidget *>(QObject::parent()); }
+
+Q_SIGNALS:
+ void activated();
+ void activatedAmbiguously();
+
+protected:
+ bool event(QEvent *e);
+};
+
+#endif // QT_NO_SHORTCUT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSHORTCUT_H
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
new file mode 100644
index 0000000000..ed9654b425
--- /dev/null
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -0,0 +1,901 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshortcutmap_p.h"
+#include "private/qobject_p.h"
+#include "qkeysequence.h"
+#include "qgraphicsscene.h"
+#include "qgraphicsview.h"
+#include "qdebug.h"
+#include "qevent.h"
+#include "qwidget.h"
+#include "qapplication.h"
+#include "qvector.h"
+#include "qmenu.h"
+#include "qmenubar.h"
+#include "qshortcut.h"
+#include "qapplication_p.h"
+#include <private/qaction_p.h>
+#include <private/qkeymapper_p.h>
+#include <private/qwidget_p.h>
+
+#ifndef QT_NO_SHORTCUT
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_mac_no_native_menubar; // qmenu_mac.cpp
+
+// To enable verbose output uncomment below
+//#define DEBUG_QSHORTCUTMAP
+
+/* \internal
+ Entry data for QShortcutMap
+ Contains:
+ Keysequence for entry
+ Pointer to parent owning the sequence
+*/
+struct QShortcutEntry
+{
+ QShortcutEntry()
+ : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0)
+ {}
+
+ QShortcutEntry(const QKeySequence &k)
+ : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0)
+ {}
+
+ QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i)
+ : keyseq(k), context(c), enabled(true), autorepeat(1), id(i), owner(o)
+ {}
+
+ QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a)
+ : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o)
+ {}
+
+ bool operator<(const QShortcutEntry &f) const
+ { return keyseq < f.keyseq; }
+
+ QKeySequence keyseq;
+ Qt::ShortcutContext context;
+ bool enabled : 1;
+ bool autorepeat : 1;
+ signed int id;
+ QObject *owner;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+/*! \internal
+ QDebug operator<< for easy debug output of the shortcut entries.
+*/
+QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) {
+ if (!se)
+ return dbg << "QShortcutEntry(0x0)";
+ dbg.nospace()
+ << "QShortcutEntry(" << se->keyseq
+ << "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat
+ << "), owner(" << se->owner << ")";
+ return dbg.space();
+}
+#endif // QT_NO_DEBUGSTREAM
+
+/* \internal
+ Private data for QShortcutMap
+*/
+class QShortcutMapPrivate
+{
+ Q_DECLARE_PUBLIC(QShortcutMap)
+
+public:
+ QShortcutMapPrivate(QShortcutMap* parent)
+ : q_ptr(parent), currentId(0), ambigCount(0), currentState(QKeySequence::NoMatch)
+ {
+ identicals.reserve(10);
+ currentSequences.reserve(10);
+ }
+ QShortcutMap *q_ptr; // Private's parent
+
+ QList<QShortcutEntry> sequences; // All sequences!
+
+ int currentId; // Global shortcut ID number
+ int ambigCount; // Index of last enabled ambiguous dispatch
+ QKeySequence::SequenceMatch currentState;
+ QVector<QKeySequence> currentSequences; // Sequence for the current state
+ QVector<QKeySequence> newEntries;
+ QKeySequence prevSequence; // Sequence for the previous identical match
+ QVector<const QShortcutEntry*> identicals; // Last identical matches
+};
+
+
+/*! \internal
+ QShortcutMap constructor.
+*/
+QShortcutMap::QShortcutMap()
+{
+ d_ptr = new QShortcutMapPrivate(this);
+ Q_ASSERT(d_ptr != 0);
+ resetState();
+}
+
+/*! \internal
+ QShortcutMap destructor.
+*/
+QShortcutMap::~QShortcutMap()
+{
+ delete d_ptr;
+ d_ptr = 0;
+}
+
+/*! \internal
+ Adds a shortcut to the global map.
+ Returns the id of the newly added shortcut.
+*/
+int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context)
+{
+ Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner");
+ Q_ASSERT_X(!key.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map");
+ Q_D(QShortcutMap);
+
+ QShortcutEntry newEntry(owner, key, context, --(d->currentId), true);
+ QList<QShortcutEntry>::iterator it = qUpperBound(d->sequences.begin(), d->sequences.end(), newEntry);
+ d->sequences.insert(it, newEntry); // Insert sorted
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace()
+ << "QShortcutMap::addShortcut(" << owner << ", "
+ << key << ", " << context << ") = " << d->currentId;
+#endif
+ return d->currentId;
+}
+
+/*! \internal
+ Removes a shortcut from the global map.
+ If \a owner is 0, all entries in the map with the key sequence specified
+ is removed. If \a key is null, all sequences for \a owner is removed from
+ the map. If \a id is 0, any identical \a key sequences owned by \a owner
+ are removed.
+ Returns the number of sequences removed from the map.
+*/
+
+int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key)
+{
+ Q_D(QShortcutMap);
+ int itemsRemoved = 0;
+ bool allOwners = (owner == 0);
+ bool allKeys = key.isEmpty();
+ bool allIds = id == 0;
+
+ // Special case, remove everything
+ if (allOwners && allKeys && id == 0) {
+ itemsRemoved = d->sequences.size();
+ d->sequences.clear();
+ return itemsRemoved;
+ }
+
+ int i = d->sequences.size()-1;
+ while (i>=0)
+ {
+ const QShortcutEntry &entry = d->sequences.at(i);
+ int entryId = entry.id;
+ if ((allOwners || entry.owner == owner)
+ && (allIds || entry.id == id)
+ && (allKeys || entry.keyseq == key)) {
+ d->sequences.removeAt(i);
+ ++itemsRemoved;
+ }
+ if (id == entryId)
+ return itemsRemoved;
+ --i;
+ }
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace()
+ << "QShortcutMap::removeShortcut(" << id << ", " << owner << ", "
+ << key << ") = " << itemsRemoved;
+#endif
+ return itemsRemoved;
+}
+
+/*! \internal
+ Changes the enable state of a shortcut to \a enable.
+ If \a owner is 0, all entries in the map with the key sequence specified
+ is removed. If \a key is null, all sequences for \a owner is removed from
+ the map. If \a id is 0, any identical \a key sequences owned by \a owner
+ are changed.
+ Returns the number of sequences which are matched in the map.
+*/
+int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key)
+{
+ Q_D(QShortcutMap);
+ int itemsChanged = 0;
+ bool allOwners = (owner == 0);
+ bool allKeys = key.isEmpty();
+ bool allIds = id == 0;
+
+ int i = d->sequences.size()-1;
+ while (i>=0)
+ {
+ QShortcutEntry entry = d->sequences.at(i);
+ if ((allOwners || entry.owner == owner)
+ && (allIds || entry.id == id)
+ && (allKeys || entry.keyseq == key)) {
+ d->sequences[i].enabled = enable;
+ ++itemsChanged;
+ }
+ if (id == entry.id)
+ return itemsChanged;
+ --i;
+ }
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace()
+ << "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", "
+ << owner << ", " << key << ") = " << itemsChanged;
+#endif
+ return itemsChanged;
+}
+
+/*! \internal
+ Changes the auto repeat state of a shortcut to \a enable.
+ If \a owner is 0, all entries in the map with the key sequence specified
+ is removed. If \a key is null, all sequences for \a owner is removed from
+ the map. If \a id is 0, any identical \a key sequences owned by \a owner
+ are changed.
+ Returns the number of sequences which are matched in the map.
+*/
+int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key)
+{
+ Q_D(QShortcutMap);
+ int itemsChanged = 0;
+ bool allOwners = (owner == 0);
+ bool allKeys = key.isEmpty();
+ bool allIds = id == 0;
+
+ int i = d->sequences.size()-1;
+ while (i>=0)
+ {
+ QShortcutEntry entry = d->sequences.at(i);
+ if ((allOwners || entry.owner == owner)
+ && (allIds || entry.id == id)
+ && (allKeys || entry.keyseq == key)) {
+ d->sequences[i].autorepeat = on;
+ ++itemsChanged;
+ }
+ if (id == entry.id)
+ return itemsChanged;
+ --i;
+ }
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace()
+ << "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", "
+ << owner << ", " << key << ") = " << itemsChanged;
+#endif
+ return itemsChanged;
+}
+
+/*! \internal
+ Resets the state of the statemachine to NoMatch
+*/
+void QShortcutMap::resetState()
+{
+ Q_D(QShortcutMap);
+ d->currentState = QKeySequence::NoMatch;
+ clearSequence(d->currentSequences);
+}
+
+/*! \internal
+ Returns the current state of the statemachine
+*/
+QKeySequence::SequenceMatch QShortcutMap::state()
+{
+ Q_D(QShortcutMap);
+ return d->currentState;
+}
+
+/*! \internal
+ Uses ShortcutOverride event to see if any widgets want to override
+ the event. If not, uses nextState(QKeyEvent) to check for a grabbed
+ Shortcut, and dispatchEvent() is found an identical.
+ \sa nextState dispatchEvent
+*/
+bool QShortcutMap::tryShortcutEvent(QObject *o, QKeyEvent *e)
+{
+ Q_D(QShortcutMap);
+
+ bool wasAccepted = e->isAccepted();
+ bool wasSpontaneous = e->spont;
+ if (d->currentState == QKeySequence::NoMatch) {
+ ushort orgType = e->t;
+ e->t = QEvent::ShortcutOverride;
+ e->ignore();
+ QApplication::sendEvent(o, e);
+ e->t = orgType;
+ e->spont = wasSpontaneous;
+ if (e->isAccepted()) {
+ if (!wasAccepted)
+ e->ignore();
+ return false;
+ }
+ }
+
+ QKeySequence::SequenceMatch result = nextState(e);
+ bool stateWasAccepted = e->isAccepted();
+ if (wasAccepted)
+ e->accept();
+ else
+ e->ignore();
+
+ int identicalMatches = d->identicals.count();
+
+ switch(result) {
+ case QKeySequence::NoMatch:
+ return stateWasAccepted;
+ case QKeySequence::ExactMatch:
+ resetState();
+ dispatchEvent(e);
+ default:
+ break;
+ }
+ // If nextState is QKeySequence::ExactMatch && identicals.count == 0
+ // we've only found disabled shortcuts
+ return identicalMatches > 0 || result == QKeySequence::PartialMatch;
+}
+
+/*! \internal
+ Returns the next state of the statemachine
+ If return value is SequenceMatch::ExactMatch, then a call to matches()
+ will return a QObjects* list of all matching objects for the last matching
+ sequence.
+*/
+QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
+{
+ Q_D(QShortcutMap);
+ // Modifiers can NOT be shortcuts...
+ if (e->key() >= Qt::Key_Shift &&
+ e->key() <= Qt::Key_Alt)
+ return d->currentState;
+
+ QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
+
+ // We start fresh each time..
+ d->identicals.resize(0);
+
+ result = find(e);
+ if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) {
+ // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab
+ if (e->key() == Qt::Key_Backtab) {
+ QKeyEvent pe = QKeyEvent(e->type(), Qt::Key_Tab, e->modifiers(), e->text());
+ result = find(&pe);
+ }
+ }
+
+ // Should we eat this key press?
+ if (d->currentState == QKeySequence::PartialMatch
+ || (d->currentState == QKeySequence::ExactMatch && d->identicals.count()))
+ e->accept();
+ // Does the new state require us to clean up?
+ if (result == QKeySequence::NoMatch)
+ clearSequence(d->currentSequences);
+ d->currentState = result;
+
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace() << "QShortcutMap::nextState(" << e << ") = " << result;
+#endif
+ return result;
+}
+
+
+/*! \internal
+ Determines if an enabled shortcut has a matcing key sequence.
+*/
+bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const
+{
+ Q_D(const QShortcutMap);
+ QShortcutEntry entry(seq); // needed for searching
+ QList<QShortcutEntry>::ConstIterator itEnd = d->sequences.constEnd();
+ QList<QShortcutEntry>::ConstIterator it = qLowerBound(d->sequences.constBegin(), itEnd, entry);
+
+ for (;it != itEnd; ++it) {
+ if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch && correctContext(*it) && (*it).enabled) {
+ return true;
+ }
+ }
+
+ //end of the loop: we didn't find anything
+ return false;
+}
+
+/*! \internal
+ Returns the next state of the statemachine, based
+ on the new key event \a e.
+ Matches are appended to the vector of identicals,
+ which can be access through matches().
+ \sa matches
+*/
+QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e)
+{
+ Q_D(QShortcutMap);
+ if (!d->sequences.count())
+ return QKeySequence::NoMatch;
+
+ createNewSequences(e, d->newEntries);
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug() << "Possible shortcut key sequences:" << d->newEntries;
+#endif
+
+ // Should never happen
+ if (d->newEntries == d->currentSequences) {
+ Q_ASSERT_X(e->key() != Qt::Key_unknown || e->text().length(),
+ "QShortcutMap::find", "New sequence to find identical to previous");
+ return QKeySequence::NoMatch;
+ }
+
+ // Looking for new identicals, scrap old
+ d->identicals.resize(0);
+
+ bool partialFound = false;
+ bool identicalDisabledFound = false;
+ QVector<QKeySequence> okEntries;
+ int result = QKeySequence::NoMatch;
+ for (int i = d->newEntries.count()-1; i >= 0 ; --i) {
+ QShortcutEntry entry(d->newEntries.at(i)); // needed for searching
+ QList<QShortcutEntry>::ConstIterator itEnd = d->sequences.constEnd();
+ QList<QShortcutEntry>::ConstIterator it =
+ qLowerBound(d->sequences.constBegin(), itEnd, entry);
+
+ int oneKSResult = QKeySequence::NoMatch;
+ int tempRes = QKeySequence::NoMatch;
+ do {
+ if (it == itEnd)
+ break;
+ tempRes = matches(entry.keyseq, (*it).keyseq);
+ oneKSResult = qMax(oneKSResult, tempRes);
+ if (tempRes != QKeySequence::NoMatch && correctContext(*it)) {
+ if (tempRes == QKeySequence::ExactMatch) {
+ if ((*it).enabled)
+ d->identicals.append(&*it);
+ else
+ identicalDisabledFound = true;
+ } else if (tempRes == QKeySequence::PartialMatch) {
+ // We don't need partials, if we have identicals
+ if (d->identicals.size())
+ break;
+ // We only care about enabled partials, so we don't consume
+ // key events when all partials are disabled!
+ partialFound |= (*it).enabled;
+ }
+ }
+ ++it;
+ // If we got a valid match on this run, there might still be more keys to check against,
+ // so we'll loop once more. If we get NoMatch, there's guaranteed no more possible
+ // matches in the shortcutmap.
+ } while (tempRes != QKeySequence::NoMatch);
+
+ // If the type of match improves (ergo, NoMatch->Partial, or Partial->Exact), clear the
+ // previous list. If this match is equal or better than the last match, append to the list
+ if (oneKSResult > result) {
+ okEntries.clear();
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug() << "Found better match (" << d->newEntries << "), clearing key sequence list";
+#endif
+ }
+ if (oneKSResult && oneKSResult >= result) {
+ okEntries << d->newEntries.at(i);
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug() << "Added ok key sequence" << d->newEntries;
+#endif
+ }
+ }
+
+ if (d->identicals.size()) {
+ result = QKeySequence::ExactMatch;
+ } else if (partialFound) {
+ result = QKeySequence::PartialMatch;
+ } else if (identicalDisabledFound) {
+ result = QKeySequence::ExactMatch;
+ } else {
+ clearSequence(d->currentSequences);
+ result = QKeySequence::NoMatch;
+ }
+ if (result != QKeySequence::NoMatch)
+ d->currentSequences = okEntries;
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug() << "Returning shortcut match == " << result;
+#endif
+ return QKeySequence::SequenceMatch(result);
+}
+
+/*! \internal
+ Clears \a seq to an empty QKeySequence.
+ Same as doing (the slower)
+ \snippet doc/src/snippets/code/src_gui_kernel_qshortcutmap.cpp 0
+*/
+void QShortcutMap::clearSequence(QVector<QKeySequence> &ksl)
+{
+ ksl.clear();
+ d_func()->newEntries.clear();
+}
+
+/*! \internal
+ Alters \a seq to the new sequence state, based on the
+ current sequence state, and the new key event \a e.
+*/
+void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl)
+{
+ Q_D(QShortcutMap);
+ QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
+ int pkTotal = possibleKeys.count();
+ if (!pkTotal)
+ return;
+
+ int ssActual = d->currentSequences.count();
+ int ssTotal = qMax(1, ssActual);
+ // Resize to possible permutations of the current sequence(s).
+ ksl.resize(pkTotal * ssTotal);
+
+ int index = ssActual ? d->currentSequences.at(0).count() : 0;
+ for (int pkNum = 0; pkNum < pkTotal; ++pkNum) {
+ for (int ssNum = 0; ssNum < ssTotal; ++ssNum) {
+ int i = (pkNum * ssTotal) + ssNum;
+ QKeySequence &curKsl = ksl[i];
+ if (ssActual) {
+ const QKeySequence &curSeq = d->currentSequences.at(ssNum);
+ curKsl.setKey(curSeq[0], 0);
+ curKsl.setKey(curSeq[1], 1);
+ curKsl.setKey(curSeq[2], 2);
+ curKsl.setKey(curSeq[3], 3);
+ } else {
+ curKsl.setKey(0, 0);
+ curKsl.setKey(0, 1);
+ curKsl.setKey(0, 2);
+ curKsl.setKey(0, 3);
+ }
+ // Filtering keycode here with 0xdfffffff to ignore the Keypad modifier
+ curKsl.setKey(possibleKeys.at(pkNum) & 0xdfffffff, index);
+ }
+ }
+}
+
+/*! \internal
+ Basically the same function as QKeySequence::matches(const QKeySequence &seq) const
+ only that is specially handles Key_hyphen as Key_Minus, as people mix these up all the time and
+ they conceptually the same.
+*/
+QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1,
+ const QKeySequence &seq2) const
+{
+ uint userN = seq1.count(),
+ seqN = seq2.count();
+
+ if (userN > seqN)
+ return QKeySequence::NoMatch;
+
+ // If equal in length, we have a potential ExactMatch sequence,
+ // else we already know it can only be partial.
+ QKeySequence::SequenceMatch match = (userN == seqN
+ ? QKeySequence::ExactMatch
+ : QKeySequence::PartialMatch);
+
+ for (uint i = 0; i < userN; ++i) {
+ int userKey = seq1[i],
+ sequenceKey = seq2[i];
+ if ((userKey & Qt::Key_unknown) == Qt::Key_hyphen)
+ userKey = (userKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
+ if ((sequenceKey & Qt::Key_unknown) == Qt::Key_hyphen)
+ sequenceKey = (sequenceKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
+ if (userKey != sequenceKey)
+ return QKeySequence::NoMatch;
+ }
+ return match;
+}
+
+/*! \internal
+ Returns true if the widget \a w is a logical sub window of the current
+ top-level widget.
+*/
+bool QShortcutMap::correctContext(const QShortcutEntry &item) const {
+ Q_ASSERT_X(item.owner, "QShortcutMap", "Shortcut has no owner. Illegal map state!");
+
+ QWidget *active_window = qApp->activeWindow();
+
+ // popups do not become the active window,
+ // so we fake it here to get the correct context
+ // for the shortcut system.
+ if (qApp->activePopupWidget())
+ active_window = qApp->activePopupWidget();
+
+ if (!active_window)
+ return false;
+#ifndef QT_NO_ACTION
+ if (QAction *a = qobject_cast<QAction *>(item.owner))
+ return correctContext(item.context, a, active_window);
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsWidget *gw = qobject_cast<QGraphicsWidget *>(item.owner))
+ return correctGraphicsWidgetContext(item.context, gw, active_window);
+#endif
+ QWidget *w = qobject_cast<QWidget *>(item.owner);
+ if (!w) {
+ QShortcut *s = qobject_cast<QShortcut *>(item.owner);
+ w = s->parentWidget();
+ }
+ return correctWidgetContext(item.context, w, active_window);
+}
+
+bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) const
+{
+ bool visible = w->isVisible();
+#ifdef Q_WS_MAC
+ if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w))
+ visible = true;
+#endif
+
+ if (!visible || !w->isEnabled())
+ return false;
+
+ if (context == Qt::ApplicationShortcut)
+ return QApplicationPrivate::tryModalHelper(w, 0); // true, unless w is shadowed by a modal dialog
+
+ if (context == Qt::WidgetShortcut)
+ return w == QApplication::focusWidget();
+
+ if (context == Qt::WidgetWithChildrenShortcut) {
+ const QWidget *tw = QApplication::focusWidget();
+ while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup))
+ tw = tw->parentWidget();
+ return tw == w;
+ }
+
+ // Below is Qt::WindowShortcut context
+ QWidget *tlw = w->window();
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *topData = tlw->d_func()->extra) {
+ if (topData->proxyWidget) {
+ bool res = correctGraphicsWidgetContext(context, (QGraphicsWidget *)topData->proxyWidget, active_window);
+ return res;
+ }
+ }
+#endif
+
+ /* if a floating tool window is active, keep shortcuts on the
+ * parent working */
+ if (active_window != tlw && active_window && active_window->windowType() == Qt::Tool && active_window->parentWidget()) {
+ active_window = active_window->parentWidget()->window();
+ }
+
+ if (active_window != tlw)
+ return false;
+
+ /* if we live in a MDI subwindow, ignore the event if we are
+ not the active document window */
+ const QWidget* sw = w;
+ while (sw && !(sw->windowType() == Qt::SubWindow) && !sw->isWindow())
+ sw = sw->parentWidget();
+ if (sw && (sw->windowType() == Qt::SubWindow)) {
+ QWidget *focus_widget = QApplication::focusWidget();
+ while (focus_widget && focus_widget != sw)
+ focus_widget = focus_widget->parentWidget();
+ return sw == focus_widget;
+ }
+
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace() << "..true [Pass-through]";
+#endif
+ return true;
+}
+
+#ifndef QT_NO_GRAPHICSVIEW
+bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) const
+{
+ bool visible = w->isVisible();
+#ifdef Q_WS_MAC
+ if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w))
+ visible = true;
+#endif
+
+ if (!visible || !w->isEnabled() || !w->scene())
+ return false;
+
+ if (context == Qt::ApplicationShortcut) {
+ // Applicationwide shortcuts are always reachable unless their owner
+ // is shadowed by modality. In QGV there's no modality concept, but we
+ // must still check if all views are shadowed.
+ QList<QGraphicsView *> views = w->scene()->views();
+ for (int i = 0; i < views.size(); ++i) {
+ if (QApplicationPrivate::tryModalHelper(views.at(i), 0))
+ return true;
+ }
+ return false;
+ }
+
+ if (context == Qt::WidgetShortcut)
+ return static_cast<QGraphicsItem *>(w) == w->scene()->focusItem();
+
+ if (context == Qt::WidgetWithChildrenShortcut) {
+ const QGraphicsItem *ti = w->scene()->focusItem();
+ if (ti && ti->isWidget()) {
+ const QGraphicsWidget *tw = static_cast<const QGraphicsWidget *>(ti);
+ while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup))
+ tw = tw->parentWidget();
+ return tw == w;
+ }
+ }
+
+ // Below is Qt::WindowShortcut context
+
+ // Find the active view (if any).
+ QList<QGraphicsView *> views = w->scene()->views();
+ QGraphicsView *activeView = 0;
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsView *view = views.at(i);
+ if (view->window() == active_window) {
+ activeView = view;
+ break;
+ }
+ }
+ if (!activeView)
+ return false;
+
+ // The shortcut is reachable if owned by a windowless widget, or if the
+ // widget's window is the same as the focus item's window.
+ QGraphicsWidget *a = w->scene()->activeWindow();
+ return !w->window() || a == w->window();
+}
+#endif
+
+#ifndef QT_NO_ACTION
+bool QShortcutMap::correctContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) const
+{
+ const QList<QWidget *> &widgets = a->d_func()->widgets;
+#if defined(DEBUG_QSHORTCUTMAP)
+ if (widgets.isEmpty())
+ qDebug() << a << "not connected to any widgets; won't trigger";
+#endif
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *w = widgets.at(i);
+#ifndef QT_NO_MENU
+ if (QMenu *menu = qobject_cast<QMenu *>(w)) {
+ QAction *a = menu->menuAction();
+ if (correctContext(context, a, active_window))
+ return true;
+ } else
+#endif
+ if (correctWidgetContext(context, w, active_window))
+ return true;
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ const QList<QGraphicsWidget *> &graphicsWidgets = a->d_func()->graphicsWidgets;
+#if defined(DEBUG_QSHORTCUTMAP)
+ if (graphicsWidgets.isEmpty())
+ qDebug() << a << "not connected to any widgets; won't trigger";
+#endif
+ for (int i = 0; i < graphicsWidgets.size(); ++i) {
+ QGraphicsWidget *w = graphicsWidgets.at(i);
+ if (correctGraphicsWidgetContext(context, w, active_window))
+ return true;
+ }
+#endif
+ return false;
+}
+#endif // QT_NO_ACTION
+
+/*! \internal
+ Converts keyboard button states into modifier states
+*/
+int QShortcutMap::translateModifiers(Qt::KeyboardModifiers modifiers)
+{
+ int result = 0;
+ if (modifiers & Qt::ShiftModifier)
+ result |= Qt::SHIFT;
+ if (modifiers & Qt::ControlModifier)
+ result |= Qt::CTRL;
+ if (modifiers & Qt::MetaModifier)
+ result |= Qt::META;
+ if (modifiers & Qt::AltModifier)
+ result |= Qt::ALT;
+ return result;
+}
+
+/*! \internal
+ Returns the vector of QShortcutEntry's matching the last Identical state.
+*/
+QVector<const QShortcutEntry*> QShortcutMap::matches() const
+{
+ Q_D(const QShortcutMap);
+ return d->identicals;
+}
+
+/*! \internal
+ Dispatches QShortcutEvents to widgets who grabbed the matched key sequence.
+*/
+void QShortcutMap::dispatchEvent(QKeyEvent *e)
+{
+ Q_D(QShortcutMap);
+ if (!d->identicals.size())
+ return;
+
+ const QKeySequence &curKey = d->identicals.at(0)->keyseq;
+ if (d->prevSequence != curKey) {
+ d->ambigCount = 0;
+ d->prevSequence = curKey;
+ }
+ // Find next
+ const QShortcutEntry *current = 0, *next = 0;
+ int i = 0, enabledShortcuts = 0;
+ while(i < d->identicals.size()) {
+ current = d->identicals.at(i);
+ if (current->enabled || !next){
+ ++enabledShortcuts;
+ if (enabledShortcuts > d->ambigCount + 1)
+ break;
+ next = current;
+ }
+ ++i;
+ }
+ d->ambigCount = (d->identicals.size() == i ? 0 : d->ambigCount + 1);
+ // Don't trigger shortcut if we're autorepeating and the shortcut is
+ // grabbed with not accepting autorepeats.
+ if (!next || (e->isAutoRepeat() && !next->autorepeat))
+ return;
+ // Dispatch next enabled
+#if defined(DEBUG_QSHORTCUTMAP)
+ qDebug().nospace()
+ << "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
+ << (QString)next->keyseq << "\", " << next->id << ", "
+ << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ")";
+#endif
+ QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);
+ QApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
+}
+
+/* \internal
+ QShortcutMap dump function, only available when DEBUG_QSHORTCUTMAP is
+ defined.
+*/
+#if defined(Dump_QShortcutMap)
+void QShortcutMap::dumpMap() const
+{
+ Q_D(const QShortcutMap);
+ for (int i = 0; i < d->sequences.size(); ++i)
+ qDebug().nospace() << &(d->sequences.at(i));
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHORTCUT
diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h
new file mode 100644
index 0000000000..3fe954630f
--- /dev/null
+++ b/src/gui/kernel/qshortcutmap_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHORTCUTMAP_P_H
+#define QSHORTCUTMAP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qkeysequence.h"
+#include "QtCore/qvector.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SHORTCUT
+
+// To enable dump output uncomment below
+//#define Dump_QShortcutMap
+
+class QKeyEvent;
+struct QShortcutEntry;
+class QShortcutMapPrivate;
+class QGraphicsWidget;
+class QWidget;
+class QAction;
+class QObject;
+
+class QShortcutMap
+{
+ Q_DECLARE_PRIVATE(QShortcutMap)
+public:
+ QShortcutMap();
+ ~QShortcutMap();
+
+ int addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context);
+ int removeShortcut(int id, QObject *owner, const QKeySequence &key = QKeySequence());
+ int setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key = QKeySequence());
+ int setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key = QKeySequence());
+
+ void resetState();
+ QKeySequence::SequenceMatch nextState(QKeyEvent *e);
+ QKeySequence::SequenceMatch state();
+ void dispatchEvent(QKeyEvent *e);
+ bool tryShortcutEvent(QObject *o, QKeyEvent *e);
+
+#ifdef Dump_QShortcutMap
+ void dumpMap() const;
+#endif
+
+ bool hasShortcutForKeySequence(const QKeySequence &seq) const;
+
+
+private:
+ bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) const;
+#ifndef QT_NO_GRAPHICSVIEW
+ bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) const;
+#endif
+#ifndef QT_NO_ACTION
+ bool correctContext(Qt::ShortcutContext context,QAction *a, QWidget *active_window) const;
+#endif
+ QShortcutMapPrivate *d_ptr;
+
+ QKeySequence::SequenceMatch find(QKeyEvent *e);
+ QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const;
+ QVector<const QShortcutEntry *> matches() const;
+ void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl);
+ void clearSequence(QVector<QKeySequence> &ksl);
+ bool correctContext(const QShortcutEntry &item) const;
+ int translateModifiers(Qt::KeyboardModifiers modifiers);
+};
+
+#endif // QT_NO_SHORTCUT
+
+QT_END_NAMESPACE
+
+#endif // QSHORTCUTMAP_P_H
diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h
new file mode 100644
index 0000000000..652fda178d
--- /dev/null
+++ b/src/gui/kernel/qsizepolicy.h
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIZEPOLICY_H
+#define QSIZEPOLICY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QVariant;
+
+class Q_GUI_EXPORT QSizePolicy
+{
+ Q_GADGET
+ Q_ENUMS(Policy)
+
+private:
+ enum SizePolicyMasks {
+ HSize = 4,
+ HMask = 0x0f,
+ VMask = HMask << HSize,
+ CTShift = 9,
+ CTSize = 5,
+ CTMask = ((0x1 << CTSize) - 1) << CTShift,
+ UnusedShift = CTShift + CTSize,
+ UnusedSize = 2
+ };
+
+public:
+ enum PolicyFlag {
+ GrowFlag = 1,
+ ExpandFlag = 2,
+ ShrinkFlag = 4,
+ IgnoreFlag = 8
+ };
+
+ enum Policy {
+ Fixed = 0,
+ Minimum = GrowFlag,
+ Maximum = ShrinkFlag,
+ Preferred = GrowFlag | ShrinkFlag,
+ MinimumExpanding = GrowFlag | ExpandFlag,
+ Expanding = GrowFlag | ShrinkFlag | ExpandFlag,
+ Ignored = ShrinkFlag | GrowFlag | IgnoreFlag
+ };
+
+ enum ControlType {
+ DefaultType = 0x00000001,
+ ButtonBox = 0x00000002,
+ CheckBox = 0x00000004,
+ ComboBox = 0x00000008,
+ Frame = 0x00000010,
+ GroupBox = 0x00000020,
+ Label = 0x00000040,
+ Line = 0x00000080,
+ LineEdit = 0x00000100,
+ PushButton = 0x00000200,
+ RadioButton = 0x00000400,
+ Slider = 0x00000800,
+ SpinBox = 0x00001000,
+ TabWidget = 0x00002000,
+ ToolButton = 0x00004000
+ };
+ Q_DECLARE_FLAGS(ControlTypes, ControlType)
+
+ QSizePolicy() : data(0) { }
+
+ // ### Qt 5: merge these two constructors (with type == DefaultType)
+ QSizePolicy(Policy horizontal, Policy vertical)
+ : data(horizontal | (vertical << HSize)) { }
+ QSizePolicy(Policy horizontal, Policy vertical, ControlType type)
+ : data(horizontal | (vertical << HSize)) { setControlType(type); }
+
+ Policy horizontalPolicy() const { return static_cast<Policy>(data & HMask); }
+ Policy verticalPolicy() const { return static_cast<Policy>((data & VMask) >> HSize); }
+ ControlType controlType() const;
+
+ void setHorizontalPolicy(Policy d) { data = (data & ~HMask) | d; }
+ void setVerticalPolicy(Policy d) { data = (data & ~(HMask << HSize)) | (d << HSize); }
+ void setControlType(ControlType type);
+
+ Qt::Orientations expandingDirections() const {
+ Qt::Orientations result;
+ if (verticalPolicy() & ExpandFlag)
+ result |= Qt::Vertical;
+ if (horizontalPolicy() & ExpandFlag)
+ result |= Qt::Horizontal;
+ return result;
+ }
+
+ void setHeightForWidth(bool b) { data = b ? (data | (1 << 2*HSize)) : (data & ~(1 << 2*HSize)); }
+ bool hasHeightForWidth() const { return data & (1 << 2*HSize); }
+
+ bool operator==(const QSizePolicy& s) const { return data == s.data; }
+ bool operator!=(const QSizePolicy& s) const { return data != s.data; }
+ operator QVariant() const; // implemented in qabstractlayout.cpp
+
+ int horizontalStretch() const { return data >> 24; }
+ int verticalStretch() const { return (data >> 16) & 0xff; }
+ void setHorizontalStretch(uchar stretchFactor) { data = (data&0x00ffffff) | (uint(stretchFactor)<<24); }
+ void setVerticalStretch(uchar stretchFactor) { data = (data&0xff00ffff) | (uint(stretchFactor)<<16); }
+
+ void transpose();
+
+#ifdef QT3_SUPPORT
+ typedef Policy SizeType;
+#ifndef qdoc
+ typedef Qt::Orientations ExpandData;
+ enum {
+ NoDirection = 0,
+ Horizontally = 1,
+ Vertically = 2,
+ BothDirections = Horizontally | Vertically
+ };
+#else
+ enum ExpandData {
+ NoDirection = 0x0,
+ Horizontally = 0x1,
+ Vertically = 0x2,
+ BothDirections = 0x3
+ };
+#endif // qdoc
+
+ inline QT3_SUPPORT bool mayShrinkHorizontally() const
+ { return horizontalPolicy() & ShrinkFlag; }
+ inline QT3_SUPPORT bool mayShrinkVertically() const { return verticalPolicy() & ShrinkFlag; }
+ inline QT3_SUPPORT bool mayGrowHorizontally() const { return horizontalPolicy() & GrowFlag; }
+ inline QT3_SUPPORT bool mayGrowVertically() const { return verticalPolicy() & GrowFlag; }
+ inline QT3_SUPPORT Qt::Orientations expanding() const { return expandingDirections(); }
+
+ QT3_SUPPORT_CONSTRUCTOR QSizePolicy(Policy hor, Policy ver, bool hfw)
+ : data(hor | (ver<<HSize) | (hfw ? (1U<<2*HSize) : 0)) { }
+
+ QT3_SUPPORT_CONSTRUCTOR QSizePolicy(Policy hor, Policy ver, uchar hors, uchar vers, bool hfw = false)
+ : data(hor | (ver<<HSize) | (hfw ? (1U<<2*HSize) : 0)) {
+ setHorizontalStretch(hors);
+ setVerticalStretch(vers);
+ }
+
+ inline QT3_SUPPORT Policy horData() const { return static_cast<Policy>(data & HMask); }
+ inline QT3_SUPPORT Policy verData() const { return static_cast<Policy>((data & VMask) >> HSize); }
+ inline QT3_SUPPORT void setHorData(Policy d) { setHorizontalPolicy(d); }
+ inline QT3_SUPPORT void setVerData(Policy d) { setVerticalPolicy(d); }
+
+ inline QT3_SUPPORT uint horStretch() const { return horizontalStretch(); }
+ inline QT3_SUPPORT uint verStretch() const { return verticalStretch(); }
+ inline QT3_SUPPORT void setHorStretch(uchar sf) { setHorizontalStretch(sf); }
+ inline QT3_SUPPORT void setVerStretch(uchar sf) { setVerticalStretch(sf); }
+#endif
+
+private:
+#ifndef QT_NO_DATASTREAM
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
+#endif
+ QSizePolicy(int i) : data(i) { }
+
+ quint32 data;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
+
+// implemented in qlayout.cpp
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
+
+inline void QSizePolicy::transpose() {
+ Policy hData = horizontalPolicy();
+ Policy vData = verticalPolicy();
+ uchar hStretch = horizontalStretch();
+ uchar vStretch = verticalStretch();
+ setHorizontalPolicy(vData);
+ setVerticalPolicy(hData);
+ setHorizontalStretch(vStretch);
+ setVerticalStretch(hStretch);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSIZEPOLICY_H
diff --git a/src/gui/kernel/qsound.cpp b/src/gui/kernel/qsound.cpp
new file mode 100644
index 0000000000..fb152cfa40
--- /dev/null
+++ b/src/gui/kernel/qsound.cpp
@@ -0,0 +1,386 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsound.h"
+
+#ifndef QT_NO_SOUND
+
+#include "qlist.h"
+#include <private/qobject_p.h>
+#include "qsound_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QList<QAuServer*> *servers=0;
+
+QAuServer::QAuServer(QObject* parent)
+ : QObject(parent)
+{
+ if (!servers)
+ servers = new QList<QAuServer*>;
+ servers->prepend(this);
+}
+
+QAuServer::~QAuServer()
+{
+ servers->removeAll(this);
+ if (servers->count() == 0) {
+ delete servers;
+ servers = 0;
+ }
+}
+
+void QAuServer::play(const QString& filename)
+{
+ QSound s(filename);
+ play(&s);
+}
+
+extern QAuServer* qt_new_audio_server();
+
+static QAuServer& server()
+{
+ if (!servers) qt_new_audio_server();
+ return *servers->first();
+}
+
+class QSoundPrivate : public QObjectPrivate
+{
+public:
+ QSoundPrivate(const QString& fname)
+ : filename(fname), bucket(0), looprem(0), looptotal(1)
+ {
+ }
+
+ ~QSoundPrivate()
+ {
+ delete bucket;
+ }
+
+ QString filename;
+ QAuBucket* bucket;
+ int looprem;
+ int looptotal;
+};
+
+/*!
+ \class QSound
+ \brief The QSound class provides access to the platform audio facilities.
+
+ \ingroup multimedia
+ \mainclass
+
+ Qt provides the most commonly required audio operation in GUI
+ applications: asynchronously playing a sound file. This is most
+ easily accomplished using the static play() function:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qsound.cpp 0
+
+ Alternatively, create a QSound object from the sound file first
+ and then call the play() slot:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qsound.cpp 1
+
+ Once created a QSound object can be queried for its fileName() and
+ total number of loops() (i.e. the number of times the sound will
+ play). The number of repetitions can be altered using the
+ setLoops() function. While playing the sound, the loopsRemaining()
+ function returns the remaining number of repetitions. Use the
+ isFinished() function to determine whether the sound has finished
+ playing.
+
+ Sounds played using a QSound object may use more memory than the
+ static play() function, but it may also play more immediately
+ (depending on the underlying platform audio facilities). Use the
+ static isAvailable() function to determine whether sound
+ facilities exist on the platform. Which facilities that are
+ actually used varies:
+
+ \table
+ \header \o Platform \o Audio Facility
+ \row
+ \o Microsoft Windows
+ \o The underlying multimedia system is used; only WAVE format sound files
+ are supported.
+ \row
+ \o X11
+ \o The \l{ftp://ftp.x.org/contrib/audio/nas/}{Network Audio System}
+ is used if available, otherwise all operations work silently. NAS
+ supports WAVE and AU files.
+ \row
+ \o Mac OS X
+ \o NSSound is used. All formats that NSSound supports, including QuickTime formats,
+ are supported by Qt for Mac OS X.
+ \row
+ \o Qt for Embedded Linux
+ \o A built-in mixing sound server is used, accessing \c /dev/dsp
+ directly. Only the WAVE format is supported.
+ \endtable
+
+ Note that QSound does not support \l{resources.html}{resources}.
+ This might be fixed in a future Qt version.
+*/
+
+/*!
+ Plays the sound stored in the file specified by the given \a filename.
+
+ \sa stop(), loopsRemaining(), isFinished()
+*/
+void QSound::play(const QString& filename)
+{
+ server().play(filename);
+}
+
+/*!
+ Constructs a QSound object from the file specified by the given \a
+ filename and with the given \a parent.
+
+ This may use more memory than the static play() function, but it
+ may also play more immediately (depending on the underlying
+ platform audio facilities).
+
+ \sa play()
+*/
+QSound::QSound(const QString& filename, QObject* parent)
+ : QObject(*new QSoundPrivate(filename), parent)
+{
+ server().init(this);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+
+ Constructs a QSound object from the file specified by the given \a
+ filename and with the given \a parent and \a name. Use the
+ QSound() construcor and QObject::setObjectName() instead.
+
+ \oldcode
+ QSound *mySound = new QSound(filename, parent, name);
+ \newcode
+ QSounc *mySound = new QSound(filename, parent);
+ mySound->setObjectName(name);
+ \endcode
+*/
+QSound::QSound(const QString& filename, QObject* parent, const char* name)
+ : QObject(*new QSoundPrivate(filename), parent)
+{
+ setObjectName(QString::fromAscii(name));
+ server().init(this);
+}
+#endif
+
+/*!
+ Destroys this sound object. If the sound is not finished playing,
+ the stop() function is called before the sound object is
+ destructed.
+
+ \sa stop(), isFinished()
+*/
+QSound::~QSound()
+{
+ if (!isFinished())
+ stop();
+}
+
+/*!
+ Returns true if the sound has finished playing; otherwise returns false.
+
+ \warning On Windows this function always returns true for unlooped sounds.
+*/
+bool QSound::isFinished() const
+{
+ Q_D(const QSound);
+ return d->looprem == 0;
+}
+
+/*!
+ \overload
+
+ Starts playing the sound specified by this QSound object.
+
+ The function returns immediately. Depending on the platform audio
+ facilities, other sounds may stop or be mixed with the new
+ sound. The sound can be played again at any time, possibly mixing
+ or replacing previous plays of the sound.
+
+ \sa fileName()
+*/
+void QSound::play()
+{
+ Q_D(QSound);
+ d->looprem = d->looptotal;
+ server().play(this);
+}
+
+/*!
+ Returns the number of times the sound will play.
+
+ \sa loopsRemaining(), setLoops()
+*/
+int QSound::loops() const
+{
+ Q_D(const QSound);
+ return d->looptotal;
+}
+
+/*!
+ Returns the remaining number of times the sound will loop (this
+ value decreases each time the sound is played).
+
+ \sa loops(), isFinished()
+*/
+int QSound::loopsRemaining() const
+{
+ Q_D(const QSound);
+ return d->looprem;
+}
+
+/*!
+ \fn void QSound::setLoops(int number)
+
+ Sets the sound to repeat the given \a number of times when it is
+ played.
+
+ Note that passing the value -1 will cause the sound to loop
+ indefinitely.
+
+ \sa loops()
+*/
+void QSound::setLoops(int n)
+{
+ Q_D(QSound);
+ d->looptotal = n;
+}
+
+/*!
+ Returns the filename associated with this QSound object.
+
+ \sa QSound()
+*/
+QString QSound::fileName() const
+{
+ Q_D(const QSound);
+ return d->filename;
+}
+
+/*!
+ Stops the sound playing.
+
+ Note that on Windows the current loop will finish if a sound is
+ played in a loop.
+
+ \sa play()
+*/
+void QSound::stop()
+{
+ Q_D(QSound);
+ server().stop(this);
+ d->looprem = 0;
+}
+
+
+/*!
+ Returns true if sound facilities exist on the platform; otherwise
+ returns false.
+
+ If no sound is available, all QSound operations work silently and
+ quickly. An application may choose either to notify the user if
+ sound is crucial to the application or to operate silently without
+ bothering the user.
+
+ Note: On Windows this always returns true because some sound card
+ drivers do not implement a way to find out whether it is available
+ or not.
+*/
+bool QSound::isAvailable()
+{
+ return server().okay();
+}
+
+/*!
+ Sets the internal bucket record of sound \a s to \a b, deleting
+ any previous setting.
+*/
+void QAuServer::setBucket(QSound* s, QAuBucket* b)
+{
+ delete s->d_func()->bucket;
+ s->d_func()->bucket = b;
+}
+
+/*!
+ Returns the internal bucket record of sound \a s.
+*/
+QAuBucket* QAuServer::bucket(QSound* s)
+{
+ return s->d_func()->bucket;
+}
+
+/*!
+ Decrements the QSound::loopRemaining() value for sound \a s,
+ returning the result.
+*/
+int QAuServer::decLoop(QSound* s)
+{
+ if (s->d_func()->looprem > 0)
+ --s->d_func()->looprem;
+ return s->d_func()->looprem;
+}
+
+/*!
+ Initializes the sound. The default implementation does nothing.
+*/
+void QAuServer::init(QSound*)
+{
+}
+
+QAuBucket::~QAuBucket()
+{
+}
+/*!
+ \fn bool QSound::available()
+
+ Use the isAvailable() function instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SOUND
diff --git a/src/gui/kernel/qsound.h b/src/gui/kernel/qsound.h
new file mode 100644
index 0000000000..3a9465313c
--- /dev/null
+++ b/src/gui/kernel/qsound.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOUND_H
+#define QSOUND_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_SOUND
+
+class QSoundPrivate;
+
+class Q_GUI_EXPORT QSound : public QObject
+{
+ Q_OBJECT
+
+public:
+ static bool isAvailable();
+ static void play(const QString& filename);
+
+ explicit QSound(const QString& filename, QObject* parent = 0);
+ ~QSound();
+
+ int loops() const;
+ int loopsRemaining() const;
+ void setLoops(int);
+ QString fileName() const;
+
+ bool isFinished() const;
+
+public Q_SLOTS:
+ void play();
+ void stop();
+
+public:
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QSound(const QString& filename, QObject* parent, const char* name);
+ static inline QT3_SUPPORT bool available() { return isAvailable(); }
+#endif
+private:
+ Q_DECLARE_PRIVATE(QSound)
+ friend class QAuServer;
+};
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSOUND_H
diff --git a/src/gui/kernel/qsound_mac.mm b/src/gui/kernel/qsound_mac.mm
new file mode 100644
index 0000000000..a58d48bf25
--- /dev/null
+++ b/src/gui/kernel/qsound_mac.mm
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qapplication.h>
+#include "qsound.h"
+#include "qsound_p.h"
+#include <private/qt_mac_p.h>
+#include <qhash.h>
+#include <qdebug.h>
+#import <AppKit/AppKit.h>
+
+#include <AppKit/NSSound.h>
+
+QT_BEGIN_NAMESPACE
+
+void qt_mac_beep()
+{
+ NSBeep();
+}
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_SOUND
+
+QT_BEGIN_NAMESPACE
+
+typedef QHash<QSound *, NSSound const *> Sounds;
+static Sounds sounds;
+
+class QAuServerMac : public QAuServer
+{
+ Q_OBJECT
+public:
+ QAuServerMac(QObject* parent) : QAuServer(parent) { }
+ void play(const QString& filename);
+ void play(QSound *s);
+ void stop(QSound*);
+ bool okay() { return true; }
+ using QAuServer::decLoop; // promote to public.
+protected:
+ NSSound *createNSSound(const QString &filename, QSound *qSound);
+};
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+@interface QMacSoundDelegate : NSObject {
+ QSound *qSound; // may be null.
+ QAuServerMac* server;
+}
+-(id)initWithQSound:(QSound*)sound:(QAuServerMac*)server;
+-(void)sound:(NSSound *)sound didFinishPlaying:(BOOL)aBool;
+@end
+
+@implementation QMacSoundDelegate
+-(id)initWithQSound:(QSound*)s:(QAuServerMac*)serv {
+ self = [super init];
+ if(self) {
+ qSound = s;
+ server = serv;
+ }
+ return self;
+}
+
+// Delegate function that gets called each time a sound finishes.
+-(void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finishedOk
+{
+ // qSound is null if this sound was started by play(QString),
+ // in which case there is no corresponding QSound object.
+ if (qSound == 0) {
+ [sound release];
+ [self release];
+ return;
+ }
+
+ // finishedOk is false if the sound cold not be played or
+ // if it was interrupted by stop().
+ if (finishedOk == false) {
+ sounds.remove(qSound);
+ [sound release];
+ [self release];
+ return;
+ }
+
+ // Check if the sound should loop "forever" (until stop).
+ if (qSound->loops() == -1) {
+ [sound play];
+ return;
+ }
+
+ const int remainingIterations = server->decLoop(qSound);
+ if (remainingIterations > 0) {
+ [sound play];
+ } else {
+ sounds.remove(qSound);
+ [sound release];
+ [self release];
+ }
+}
+@end
+
+QT_BEGIN_NAMESPACE
+
+void QAuServerMac::play(const QString &fileName)
+{
+ QMacCocoaAutoReleasePool pool;
+ NSSound * const nsSound = createNSSound(fileName, 0);
+ [nsSound play];
+}
+
+void QAuServerMac::play(QSound *qSound)
+{
+ QMacCocoaAutoReleasePool pool;
+ NSSound * const nsSound = createNSSound(qSound->fileName(), qSound);
+ [nsSound play];
+ // Keep track of the nsSound object so we can find it again in stop().
+ sounds[qSound] = nsSound;
+}
+
+void QAuServerMac::stop(QSound *qSound)
+{
+ Sounds::const_iterator it = sounds.constFind(qSound);
+ if (it != sounds.constEnd())
+ [*it stop];
+}
+
+// Creates an NSSound object and installs a "sound finished" callack delegate on it.
+NSSound *QAuServerMac::createNSSound(const QString &fileName, QSound *qSound)
+{
+ NSString *nsFileName = const_cast<NSString *>(reinterpret_cast<const NSString *>(QCFString::toCFStringRef(fileName)));
+ NSSound * const nsSound = [[NSSound alloc] initWithContentsOfFile: nsFileName byReference:YES];
+ QMacSoundDelegate * const delegate = [[QMacSoundDelegate alloc] initWithQSound:qSound:this];
+ [nsSound setDelegate:delegate];
+ return nsSound;
+}
+
+QAuServer* qt_new_audio_server()
+{
+ return new QAuServerMac(qApp);
+}
+
+QT_END_NAMESPACE
+
+#include "qsound_mac.moc"
+
+#endif // QT_NO_SOUND
diff --git a/src/gui/kernel/qsound_p.h b/src/gui/kernel/qsound_p.h
new file mode 100644
index 0000000000..44f5c033e0
--- /dev/null
+++ b/src/gui/kernel/qsound_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOUND_P_H
+#define QSOUND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SOUND
+
+class QSound;
+/*
+ QAuServer is an INTERNAL class. If you wish to provide support for
+ additional audio servers, you can make a subclass of QAuServer to do
+ so, HOWEVER, your class may need to be re-engineered to some degree
+ with each new Qt release, including minor releases.
+
+ QAuBucket is whatever you want.
+*/
+
+class QAuBucket {
+public:
+ virtual ~QAuBucket();
+};
+
+class QAuServer : public QObject {
+ Q_OBJECT
+
+public:
+ explicit QAuServer(QObject* parent);
+ ~QAuServer();
+
+ virtual void init(QSound*);
+ virtual void play(const QString& filename);
+ virtual void play(QSound*)=0;
+ virtual void stop(QSound*)=0;
+ virtual bool okay()=0;
+
+protected:
+ void setBucket(QSound*, QAuBucket*);
+ QAuBucket* bucket(QSound*);
+ int decLoop(QSound*);
+};
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
+
+#endif // QSOUND_P_H
diff --git a/src/gui/kernel/qsound_qws.cpp b/src/gui/kernel/qsound_qws.cpp
new file mode 100644
index 0000000000..e83935fce0
--- /dev/null
+++ b/src/gui/kernel/qsound_qws.cpp
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+
+#ifndef QT_NO_SOUND
+
+#include "qsound.h"
+#include "qpaintdevice.h"
+#include "qwsdisplay_qws.h"
+#include "qsound_p.h"
+
+#include "qsoundqss_qws.h"
+
+#include "qhash.h"
+#include "qfileinfo.h"
+
+#ifdef MEDIA_SERVER
+#include "qbytearray.h"
+#include "quuid.h"
+#include "qdatastream.h"
+#include "qcopchannel_qws.h"
+#include "qbuffer.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#define SERVER_CHANNEL "QPE/MediaServer"
+
+class QCopMessage : public QDataStream
+{
+public:
+ QCopMessage( const QString& channel, const QString& message )
+ : QDataStream( new QBuffer ), m_channel( channel ), m_message( message )
+ {
+ device()->open( QIODevice::WriteOnly );
+ }
+
+ ~QCopMessage()
+ {
+ QCopChannel::send( m_channel, m_message, ((QBuffer*)device())->buffer() );
+ delete device();
+ }
+
+private:
+ QString m_channel;
+ QString m_message;
+};
+
+#endif // MEDIA_SERVER
+
+class QAuServerQWS;
+
+class QAuBucketQWS : public QObject, public QAuBucket
+{
+ Q_OBJECT
+public:
+ QAuBucketQWS( QAuServerQWS*, QSound*, QObject* parent = 0 );
+
+ ~QAuBucketQWS();
+
+#ifndef MEDIA_SERVER
+ int id() const { return id_; }
+#endif
+
+ QSound* sound() const { return sound_; }
+
+#ifdef MEDIA_SERVER
+ void play();
+
+ void stop();
+#endif
+
+signals:
+ // Only for Media Server
+ void done( QAuBucketQWS* );
+
+private slots:
+ // Only for Media Server
+ void processMessage( const QString& msg, const QByteArray& data );
+
+private:
+#ifdef MEDIA_SERVER
+ QCopChannel *m_channel;
+ QUuid m_id;
+#endif
+
+#ifndef MEDIA_SERVER
+ int id_;
+#endif
+ QSound *sound_;
+ QAuServerQWS *server_;
+
+ static int next;
+};
+
+int QAuBucketQWS::next = 0;
+
+class QAuServerQWS : public QAuServer
+{
+ Q_OBJECT
+public:
+ QAuServerQWS( QObject* parent );
+
+ void init( QSound* s )
+ {
+ QAuBucketQWS *bucket = new QAuBucketQWS( this, s );
+#ifdef MEDIA_SERVER
+ connect( bucket, SIGNAL(done(QAuBucketQWS*)),
+ this, SLOT(complete(QAuBucketQWS*)) );
+#endif
+ setBucket( s, bucket );
+ }
+
+#ifndef MEDIA_SERVER
+ // Register bucket
+ void insert( QAuBucketQWS *bucket )
+ {
+ buckets.insert( bucket->id(), bucket );
+ }
+
+ // Remove bucket from register
+ void remove( QAuBucketQWS *bucket )
+ {
+ buckets.remove( bucket->id() );
+ }
+#endif
+
+ void play( QSound* s )
+ {
+ QString filepath = QFileInfo( s->fileName() ).absoluteFilePath();
+#if defined(QT_NO_QWS_SOUNDSERVER)
+ server->playFile( bucket( s )->id(), filepath );
+#elif defined(MEDIA_SERVER)
+ bucket( s )->play();
+#else
+ client->play( bucket( s )->id(), filepath );
+#endif
+ }
+
+ void stop( QSound* s )
+ {
+#if defined(QT_NO_QWS_SOUNDSERVER)
+ server->stopFile( bucket( s )->id() );
+#elif defined(MEDIA_SERVER)
+ bucket( s )->stop();
+#else
+ client->stop( bucket( s )->id() );
+#endif
+ }
+
+ bool okay() { return true; }
+
+private slots:
+ // Continue playing sound if loops remain
+ void complete( int id )
+ {
+#ifndef MEDIA_SERVER
+ QAuBucketQWS *bucket = find( id );
+ if( bucket ) {
+ QSound *sound = bucket->sound();
+ if( decLoop( sound ) ) {
+ play( sound );
+ }
+ }
+#else
+ Q_UNUSED(id);
+#endif
+ }
+
+ // Only for Media Server
+ void complete( QAuBucketQWS* bucket )
+ {
+#ifndef MEDIA_SERVER
+ Q_UNUSED(bucket);
+#else
+ QSound *sound = bucket->sound();
+ if( decLoop( sound ) ) {
+ play( sound );
+ }
+#endif
+ }
+
+protected:
+ QAuBucketQWS* bucket( QSound *s )
+ {
+ return (QAuBucketQWS*)QAuServer::bucket( s );
+ }
+
+private:
+#ifndef MEDIA_SERVER
+ // Find registered bucket with given id, return null if none found
+ QAuBucketQWS* find( int id )
+ {
+ QHash<int, QAuBucketQWS*>::Iterator it = buckets.find( id );
+ if( it != buckets.end() ) {
+ return it.value();
+ }
+
+ return 0;
+ }
+
+ QHash<int, QAuBucketQWS*> buckets; // ### possible problem with overlapping keys
+
+#ifdef QT_NO_QWS_SOUNDSERVER
+ QWSSoundServer *server;
+#else
+ QWSSoundClient *client;
+#endif
+
+#endif // MEDIA_SERVER
+};
+
+QAuServerQWS::QAuServerQWS(QObject* parent) :
+ QAuServer(parent)
+{
+#ifndef MEDIA_SERVER
+ setObjectName(QLatin1String("qauserverqws"));
+
+#ifdef QT_NO_QWS_SOUNDSERVER
+ server = new QWSSoundServer( this ); // ### only suitable for single application
+
+ connect( server, SIGNAL(soundCompleted(int)),
+ this, SLOT(complete(int)) );
+#else
+ client = new QWSSoundClient( this ); // ### requires successful connection
+
+ connect( client, SIGNAL(soundCompleted(int)),
+ this, SLOT(complete(int)) );
+#endif
+
+#endif // MEDIA_SERVER
+}
+
+QAuBucketQWS::QAuBucketQWS( QAuServerQWS *server, QSound *sound, QObject* parent )
+ : QObject( parent ), sound_( sound ), server_( server )
+{
+#ifdef MEDIA_SERVER
+ m_id = QUuid::createUuid();
+
+ sound->setObjectName( m_id.toString() );
+
+ m_channel = new QCopChannel(QString( QLatin1String("QPE/QSound/") ).append( m_id ), this );
+ connect( m_channel, SIGNAL(received(QString,QByteArray)),
+ this, SLOT(processMessage(QString,QByteArray)) );
+
+ {
+ QCopMessage message( QLatin1String(SERVER_CHANNEL), QLatin1String("subscribe(QUuid)") );
+ message << m_id;
+ }
+
+ {
+ QString filepath = QFileInfo( sound_->fileName() ).absoluteFilePath();
+ QCopMessage message( QLatin1String(SERVER_CHANNEL), QLatin1String("open(QUuid,QString)") );
+ message << m_id << filepath;
+ }
+#else
+ id_ = next++;
+ server_->insert( this );
+#endif
+}
+
+#ifdef MEDIA_SERVER
+void QAuBucketQWS::play()
+{
+ QString filepath = QFileInfo( sound_->fileName() ).absoluteFilePath();
+
+ QCopMessage message( QLatin1String(SERVER_CHANNEL), QLatin1String("play(QUuid)") );
+ message << m_id;
+}
+
+void QAuBucketQWS::stop()
+{
+ QCopMessage message( QLatin1String(SERVER_CHANNEL), QLatin1String("stop(QUuid)") );
+ message << m_id;
+}
+#endif // MEDIA_SERVER
+
+void QAuBucketQWS::processMessage( const QString& msg, const QByteArray& data )
+{
+ Q_UNUSED(data);
+#ifndef MEDIA_SERVER
+ Q_UNUSED(msg);
+#else
+ if( msg == QLatin1String("done()") ) {
+ emit done( this );
+ }
+#endif
+}
+
+QAuBucketQWS::~QAuBucketQWS()
+{
+#ifdef MEDIA_SERVER
+ QCopMessage message( QLatin1String(SERVER_CHANNEL), QLatin1String("revoke(QUuid)") );
+ message << m_id;
+#else
+ server_->remove( this );
+#endif
+}
+
+
+QAuServer* qt_new_audio_server()
+{
+ return new QAuServerQWS(qApp);
+}
+
+#include "qsound_qws.moc"
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qsound_win.cpp b/src/gui/kernel/qsound_win.cpp
new file mode 100644
index 0000000000..9d03d18435
--- /dev/null
+++ b/src/gui/kernel/qsound_win.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsound.h"
+
+#ifndef QT_NO_SOUND
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include <qfile.h>
+#include "qpointer.h"
+#include "qsound_p.h"
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAuServerWindows : public QAuServer {
+ Q_OBJECT
+
+public:
+ QAuServerWindows(QObject* parent);
+ ~QAuServerWindows();
+
+ void playHelper(const QString &filename, int loop, QSound *snd);
+ void play(const QString& filename, int loop);
+ void play(QSound*);
+
+ void stop(QSound*);
+ bool okay();
+
+ int decLoop(QSound *snd) { return QAuServer::decLoop(snd); }
+
+ HANDLE current;
+ HANDLE mutex;
+ HANDLE event;
+};
+
+QAuServerWindows::QAuServerWindows(QObject* parent) :
+ QAuServer(parent), current(0)
+{
+ QT_WA({
+ mutex = CreateMutexW(0, 0, 0);
+ event = CreateEventW(0, FALSE, FALSE, 0);
+ } , {
+ mutex = CreateMutexA(0, 0, 0);
+ event = CreateEventA(0, FALSE, FALSE, 0);
+ });
+}
+
+QAuServerWindows::~QAuServerWindows()
+{
+ HANDLE mtx = mutex;
+ WaitForSingleObject(mtx, INFINITE);
+ mutex = 0;
+
+ ReleaseMutex(mtx);
+ CloseHandle(mtx);
+ CloseHandle(event);
+}
+
+struct SoundInfo
+{
+ SoundInfo(const QString &fn, int lp, QSound *snd, QAuServerWindows *srv)
+ : sound(snd), server(srv), filename(fn), loops(lp)
+ {
+ }
+
+ QSound *sound;
+ QAuServerWindows *server;
+ QString filename;
+ int loops;
+};
+
+DWORD WINAPI SoundPlayProc(LPVOID param)
+{
+ SoundInfo *info = (SoundInfo*)param;
+
+ // copy data before waking up GUI thread
+ QAuServerWindows *server = info->server;
+ QSound *sound = info->sound;
+ int loops = info->loops;
+ QString filename = info->filename;
+ HANDLE mutex = server->mutex;
+ HANDLE event = server->event;
+ info = 0;
+
+ // server must not be destroyed until thread finishes
+ // and all other sounds have to wait
+ WaitForSingleObject(mutex, INFINITE);
+
+ if (loops <= 1) {
+ server->current = 0;
+ int flags = SND_FILENAME|SND_ASYNC;
+ if (loops == -1)
+ flags |= SND_LOOP;
+
+ QT_WA({
+ PlaySoundW((TCHAR*)filename.utf16(), 0, flags);
+ } , {
+ PlaySoundA(QFile::encodeName(filename).data(), 0, flags);
+ });
+ if (sound && loops == 1)
+ server->decLoop(sound);
+
+ // GUI thread continues, but we are done as well.
+ SetEvent(event);
+ } else {
+ // signal GUI thread to continue - sound might be reset!
+ QPointer<QSound> guarded_sound = sound;
+ SetEvent(event);
+
+ for (int l = 0; l < loops && server->current; ++l) {
+ QT_WA( {
+ PlaySoundW( (TCHAR*)filename.utf16(), 0, SND_FILENAME|SND_SYNC );
+ } , {
+ PlaySoundA( QFile::encodeName(filename).data(), 0,
+ SND_FILENAME|SND_SYNC );
+ } );
+
+ if (guarded_sound)
+ server->decLoop(guarded_sound);
+ }
+ server->current = 0;
+ }
+ ReleaseMutex(mutex);
+
+ return 0;
+}
+
+void QAuServerWindows::playHelper(const QString &filename, int loop, QSound *snd)
+{
+ if (loop == 0)
+ return;
+ // busy?
+ if (WaitForSingleObject(mutex, 0) == WAIT_TIMEOUT)
+ return;
+ ReleaseMutex(mutex);
+
+ DWORD threadid = 0;
+ SoundInfo info(filename, loop, snd, this);
+ current = CreateThread(0, 0, SoundPlayProc, &info, 0, &threadid);
+ CloseHandle(current);
+
+ WaitForSingleObject(event, INFINITE);
+}
+
+void QAuServerWindows::play(const QString& filename, int loop)
+{
+ playHelper(filename, loop, 0);
+}
+
+void QAuServerWindows::play(QSound* s)
+{
+ playHelper(s->fileName(), s->loops(), s);
+}
+
+void QAuServerWindows::stop(QSound*)
+{
+ // stop unlooped sound
+ if (!current)
+ PlaySound(0, 0, 0);
+ // stop after loop is done
+ current = 0;
+}
+
+bool QAuServerWindows::okay()
+{
+ return true;
+}
+
+QAuServer* qt_new_audio_server()
+{
+ return new QAuServerWindows(qApp);
+}
+
+QT_END_NAMESPACE
+
+#include "qsound_win.moc"
+
+#endif // QT_NO_SOUND
diff --git a/src/gui/kernel/qsound_x11.cpp b/src/gui/kernel/qsound_x11.cpp
new file mode 100644
index 0000000000..f2aeea8291
--- /dev/null
+++ b/src/gui/kernel/qsound_x11.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsound.h"
+
+#ifndef QT_NO_SOUND
+
+#include "qhash.h"
+#include "qsocketnotifier.h"
+#include "qapplication.h"
+#include "qsound_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_NAS
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <audio/audiolib.h>
+#include <audio/soundlib.h>
+QT_END_INCLUDE_NAMESPACE
+
+static AuServer *nas=0;
+
+static AuBool eventPred(AuServer *, AuEvent *e, AuPointer p)
+{
+ if (e && (e->type == AuEventTypeElementNotify)) {
+ if (e->auelementnotify.flow == *((AuFlowID *)p))
+ return true;
+ }
+ return false;
+}
+
+class QAuBucketNAS : public QAuBucket {
+public:
+ QAuBucketNAS(AuBucketID b, AuFlowID f = 0) : id(b), flow(f), stopped(true), numplaying(0) { }
+ ~QAuBucketNAS()
+ {
+ if (nas) {
+ AuSync(nas, false);
+ AuDestroyBucket(nas, id, NULL);
+
+ AuEvent ev;
+ while (AuScanEvents(nas, AuEventsQueuedAfterFlush, true, eventPred, &flow, &ev))
+ ;
+ }
+ }
+
+ AuBucketID id;
+ AuFlowID flow;
+ bool stopped;
+ int numplaying;
+};
+
+class QAuServerNAS : public QAuServer {
+ Q_OBJECT
+
+ QSocketNotifier* sn;
+
+public:
+ QAuServerNAS(QObject* parent);
+ ~QAuServerNAS();
+
+ void init(QSound*);
+ void play(const QString& filename);
+ void play(QSound*);
+ void stop(QSound*);
+ bool okay();
+ void setDone(QSound*);
+
+public slots:
+ void dataReceived();
+ void soundDestroyed(QObject *o);
+
+private:
+ QAuBucketNAS* bucket(QSound* s)
+ {
+ return (QAuBucketNAS*)QAuServer::bucket(s);
+ }
+};
+
+QAuServerNAS::QAuServerNAS(QObject* parent) :
+ QAuServer(parent)
+{
+ setObjectName(QLatin1String("Network Audio System"));
+ nas = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL);
+ if (nas) {
+ AuSetCloseDownMode(nas, AuCloseDownDestroy, NULL);
+ // Ask Qt for async messages...
+ sn=new QSocketNotifier(AuServerConnectionNumber(nas),
+ QSocketNotifier::Read);
+ QObject::connect(sn, SIGNAL(activated(int)),
+ this, SLOT(dataReceived()));
+ } else {
+ sn = 0;
+ }
+}
+
+QAuServerNAS::~QAuServerNAS()
+{
+ if (nas)
+ AuCloseServer(nas);
+ delete sn;
+ nas = 0;
+}
+
+typedef QHash<void*,QAuServerNAS*> AuServerHash;
+static AuServerHash *inprogress=0;
+
+void QAuServerNAS::soundDestroyed(QObject *o)
+{
+ if (inprogress) {
+ QSound *so = static_cast<QSound *>(o);
+ while (inprogress->remove(so))
+ ; // Loop while remove returns true
+ }
+}
+
+void QAuServerNAS::play(const QString& filename)
+{
+ if (nas) {
+ int iv=100;
+ AuFixedPoint volume=AuFixedPointFromFraction(iv,100);
+ AuSoundPlayFromFile(nas, filename.toLocal8Bit().constData(), AuNone, volume,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ AuFlush(nas);
+ dataReceived();
+ AuFlush(nas);
+ qApp->flush();
+ }
+}
+
+static void callback(AuServer*, AuEventHandlerRec*, AuEvent* e, AuPointer p)
+{
+ if (inprogress->contains(p) && e) {
+ if (e->type==AuEventTypeElementNotify &&
+ e->auelementnotify.kind==AuElementNotifyKindState) {
+ if (e->auelementnotify.cur_state == AuStateStop) {
+ AuServerHash::Iterator it = inprogress->find(p);
+ if (it != inprogress->end())
+ (*it)->setDone((QSound*)p);
+ }
+ }
+ }
+}
+
+void QAuServerNAS::setDone(QSound* s)
+{
+ if (nas) {
+ decLoop(s);
+ if (s->loopsRemaining() && !bucket(s)->stopped) {
+ bucket(s)->stopped = true;
+ play(s);
+ } else {
+ if (--(bucket(s)->numplaying) == 0)
+ bucket(s)->stopped = true;
+ inprogress->remove(s);
+ }
+ }
+}
+
+void QAuServerNAS::play(QSound* s)
+{
+ if (nas) {
+ ++(bucket(s)->numplaying);
+ if (!bucket(s)->stopped) {
+ stop(s);
+ }
+
+ bucket(s)->stopped = false;
+ if (!inprogress)
+ inprogress = new AuServerHash;
+ inprogress->insert(s,this);
+ int iv=100;
+ AuFixedPoint volume=AuFixedPointFromFraction(iv,100);
+ QAuBucketNAS *b = bucket(s);
+ AuSoundPlayFromBucket(nas, b->id, AuNone, volume,
+ callback, s, 0, &b->flow, NULL, NULL, NULL);
+ AuFlush(nas);
+ dataReceived();
+ AuFlush(nas);
+ qApp->flush();
+ }
+}
+
+void QAuServerNAS::stop(QSound* s)
+{
+ if (nas && !bucket(s)->stopped) {
+ bucket(s)->stopped = true;
+ AuStopFlow(nas, bucket(s)->flow, NULL);
+ AuFlush(nas);
+ dataReceived();
+ AuFlush(nas);
+ qApp->flush();
+ }
+}
+
+void QAuServerNAS::init(QSound* s)
+{
+ connect(s, SIGNAL(destroyed(QObject*)),
+ this, SLOT(soundDestroyed(QObject*)));
+
+ if (nas) {
+ AuBucketID b_id =
+ AuSoundCreateBucketFromFile(nas, s->fileName().toLocal8Bit().constData(),
+ 0 /*AuAccessAllMasks*/, NULL, NULL);
+ setBucket(s, new QAuBucketNAS(b_id));
+ }
+}
+
+bool QAuServerNAS::okay()
+{
+ return !!nas;
+}
+
+void QAuServerNAS::dataReceived()
+{
+ AuHandleEvents(nas);
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qsound_x11.moc"
+QT_END_INCLUDE_NAMESPACE
+
+#endif
+
+
+class QAuServerNull : public QAuServer
+{
+public:
+ QAuServerNull(QObject* parent);
+
+ void play(const QString&) { }
+ void play(QSound*s) { while(decLoop(s) > 0) /* nothing */ ; }
+ void stop(QSound*) { }
+ bool okay() { return false; }
+};
+
+QAuServerNull::QAuServerNull(QObject* parent)
+ : QAuServer(parent)
+{
+}
+
+
+QAuServer* qt_new_audio_server()
+{
+#ifndef QT_NO_NAS
+ QAuServer* s = new QAuServerNAS(qApp);
+ if (s->okay())
+ return s;
+ else
+ delete s;
+#endif
+ return new QAuServerNull(qApp);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SOUND
diff --git a/src/gui/kernel/qstackedlayout.cpp b/src/gui/kernel/qstackedlayout.cpp
new file mode 100644
index 0000000000..eb985b2dd9
--- /dev/null
+++ b/src/gui/kernel/qstackedlayout.cpp
@@ -0,0 +1,545 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstackedlayout.h"
+#include "qlayout_p.h"
+
+#include <qlist.h>
+#include <qwidget.h>
+#include "private/qlayoutengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QStackedLayoutPrivate : public QLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QStackedLayout)
+public:
+ QStackedLayoutPrivate() : index(-1), stackingMode(QStackedLayout::StackOne) {}
+ QList<QLayoutItem *> list;
+ int index;
+ QStackedLayout::StackingMode stackingMode;
+};
+
+/*!
+ \class QStackedLayout
+
+ \brief The QStackedLayout class provides a stack of widgets where
+ only one widget is visible at a time.
+
+ \ingroup geomanagement
+ \ingroup appearance
+ \mainclass
+
+ QStackedLayout can be used to create a user interface similar to
+ the one provided by QTabWidget. There is also a convenience
+ QStackedWidget class built on top of QStackedLayout.
+
+ A QStackedLayout can be populated with a number of child widgets
+ ("pages"). For example:
+
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 0
+ \codeline
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 2
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 3
+
+ QStackedLayout provides no intrinsic means for the user to switch
+ page. This is typically done through a QComboBox or a QListWidget
+ that stores the titles of the QStackedLayout's pages. For
+ example:
+
+ \snippet doc/src/snippets/qstackedlayout/main.cpp 1
+
+ When populating a layout, the widgets are added to an internal
+ list. The indexOf() function returns the index of a widget in that
+ list. The widgets can either be added to the end of the list using
+ the addWidget() function, or inserted at a given index using the
+ insertWidget() function. The removeWidget() function removes the
+ widget at the given index from the layout. The number of widgets
+ contained in the layout, can be obtained using the count()
+ function.
+
+ The widget() function returns the widget at a given index
+ position. The index of the widget that is shown on screen is given
+ by currentIndex() and can be changed using setCurrentIndex(). In a
+ similar manner, the currently shown widget can be retrieved using
+ the currentWidget() function, and altered using the
+ setCurrentWidget() function.
+
+ Whenever the current widget in the layout changes or a widget is
+ removed from the layout, the currentChanged() and widgetRemoved()
+ signals are emitted respectively.
+
+ \sa QStackedWidget, QTabWidget
+*/
+
+/*!
+ \fn void QStackedLayout::currentChanged(int index)
+
+ This signal is emitted whenever the current widget in the layout
+ changes. The \a index specifies the index of the new current
+ widget, or -1 if there isn't a new one (for example, if there
+ are no widgets in the QStackedLayout)
+
+ \sa currentWidget(), setCurrentWidget()
+*/
+
+/*!
+ \fn void QStackedLayout::widgetRemoved(int index)
+
+ This signal is emitted whenever a widget is removed from the
+ layout. The widget's \a index is passed as parameter.
+
+ \sa removeWidget()
+*/
+
+/*!
+ \fn QWidget *QStackedLayout::widget()
+ \internal
+*/
+
+/*!
+ Constructs a QStackedLayout with no parent.
+
+ This QStackedLayout must be installed on a widget later on to
+ become effective.
+
+ \sa addWidget(), insertWidget()
+*/
+QStackedLayout::QStackedLayout()
+ : QLayout(*new QStackedLayoutPrivate, 0, 0)
+{
+}
+
+/*!
+ Constructs a new QStackedLayout with the given \a parent.
+
+ This layout will install itself on the \a parent widget and
+ manage the geometry of its children.
+*/
+QStackedLayout::QStackedLayout(QWidget *parent)
+ : QLayout(*new QStackedLayoutPrivate, 0, parent)
+{
+}
+
+/*!
+ Constructs a new QStackedLayout and inserts it into
+ the given \a parentLayout.
+*/
+QStackedLayout::QStackedLayout(QLayout *parentLayout)
+ : QLayout(*new QStackedLayoutPrivate, parentLayout, 0)
+{
+}
+
+/*!
+ Destroys this QStackedLayout. Note that the layout's widgets are
+ \e not destroyed.
+*/
+QStackedLayout::~QStackedLayout()
+{
+ Q_D(QStackedLayout);
+ qDeleteAll(d->list);
+}
+
+/*!
+ Adds the given \a widget to the end of this layout and returns the
+ index position of the \a widget.
+
+ If the QStackedLayout is empty before this function is called,
+ the given \a widget becomes the current widget.
+
+ \sa insertWidget(), removeWidget(), setCurrentWidget()
+*/
+int QStackedLayout::addWidget(QWidget *widget)
+{
+ Q_D(QStackedLayout);
+ return insertWidget(d->list.count(), widget);
+}
+
+/*!
+ Inserts the given \a widget at the given \a index in this
+ QStackedLayout. If \a index is out of range, the widget is
+ appended (in which case it is the actual index of the \a widget
+ that is returned).
+
+ If the QStackedLayout is empty before this function is called, the
+ given \a widget becomes the current widget.
+
+ Inserting a new widget at an index less than or equal to the current index
+ will increment the current index, but keep the current widget.
+
+ \sa addWidget(), removeWidget(), setCurrentWidget()
+*/
+int QStackedLayout::insertWidget(int index, QWidget *widget)
+{
+ Q_D(QStackedLayout);
+ addChildWidget(widget);
+ index = qMin(index, d->list.count());
+ if (index < 0)
+ index = d->list.count();
+ QWidgetItem *wi = QLayoutPrivate::createWidgetItem(this, widget);
+ d->list.insert(index, wi);
+ invalidate();
+ if (d->index < 0) {
+ setCurrentIndex(index);
+ } else {
+ if (index <= d->index)
+ ++d->index;
+ if (d->stackingMode == StackOne)
+ widget->hide();
+ widget->lower();
+ }
+ return index;
+}
+
+/*!
+ \reimp
+*/
+QLayoutItem *QStackedLayout::itemAt(int index) const
+{
+ Q_D(const QStackedLayout);
+ return d->list.value(index);
+}
+
+// Code that enables proper handling of the case that takeAt() is
+// called somewhere inside QObject destructor (can't call hide()
+// on the object then)
+
+class QtFriendlyLayoutWidget : public QWidget
+{
+public:
+ inline bool wasDeleted() const { return d_ptr->wasDeleted; }
+};
+
+static bool qt_wasDeleted(const QWidget *w) { return static_cast<const QtFriendlyLayoutWidget*>(w)->wasDeleted(); }
+
+
+/*!
+ \reimp
+*/
+QLayoutItem *QStackedLayout::takeAt(int index)
+{
+ Q_D(QStackedLayout);
+ if (index <0 || index >= d->list.size())
+ return 0;
+ QLayoutItem *item = d->list.takeAt(index);
+ if (index == d->index) {
+ d->index = -1;
+ if ( d->list.count() > 0 ) {
+ int newIndex = (index == d->list.count()) ? index-1 : index;
+ setCurrentIndex(newIndex);
+ } else {
+ emit currentChanged(-1);
+ }
+ } else if (index < d->index) {
+ --d->index;
+ }
+ emit widgetRemoved(index);
+ if (item->widget() && !qt_wasDeleted(item->widget()))
+ item->widget()->hide();
+ return item;
+}
+
+/*!
+ \property QStackedLayout::currentIndex
+ \brief the index position of the widget that is visible
+
+ The current index is -1 if there is no current widget.
+
+ \sa currentWidget(), indexOf()
+*/
+void QStackedLayout::setCurrentIndex(int index)
+{
+ Q_D(QStackedLayout);
+ QWidget *prev = currentWidget();
+ QWidget *next = widget(index);
+ if (!next || next == prev)
+ return;
+
+ bool reenableUpdates = false;
+ QWidget *parent = parentWidget();
+
+ if (parent && parent->updatesEnabled()) {
+ reenableUpdates = true;
+ parent->setUpdatesEnabled(false);
+ }
+
+ QWidget *fw = parent ? parent->window()->focusWidget() : 0;
+ if (prev) {
+ prev->clearFocus();
+ if (d->stackingMode == StackOne)
+ prev->hide();
+ }
+
+ d->index = index;
+ next->raise();
+ next->show();
+
+ // try to move focus onto the incoming widget if focus
+ // was somewhere on the outgoing widget.
+
+ if (parent) {
+ if (fw && (prev && prev->isAncestorOf(fw))) { // focus was on old page
+ // look for the best focus widget we can find
+ if (QWidget *nfw = next->focusWidget())
+ nfw->setFocus();
+ else {
+ // second best: first child widget in the focus chain
+ QWidget *i = fw;
+ while ((i = i->nextInFocusChain()) != fw) {
+ if (((i->focusPolicy() & Qt::TabFocus) == Qt::TabFocus)
+ && !i->focusProxy() && i->isVisibleTo(next) && i->isEnabled()
+ && next->isAncestorOf(i)) {
+ i->setFocus();
+ break;
+ }
+ }
+ // third best: incoming widget
+ if (i == fw )
+ next->setFocus();
+ }
+ }
+ }
+ if (reenableUpdates)
+ parent->setUpdatesEnabled(true);
+ emit currentChanged(index);
+}
+
+int QStackedLayout::currentIndex() const
+{
+ Q_D(const QStackedLayout);
+ return d->index;
+}
+
+
+/*!
+ \fn void QStackedLayout::setCurrentWidget(QWidget *widget)
+
+ Sets the current widget to be the specified \a widget. The new
+ current widget must already be contained in this stacked layout.
+
+ \sa setCurrentIndex(), currentWidget()
+ */
+void QStackedLayout::setCurrentWidget(QWidget *widget)
+{
+ int index = indexOf(widget);
+ if (index == -1) {
+ qWarning("QStackedLayout::setCurrentWidget: Widget %p not contained in stack", widget);
+ return;
+ }
+ setCurrentIndex(index);
+}
+
+
+/*!
+ Returns the current widget, or 0 if there are no widgets in this
+ layout.
+
+ \sa currentIndex(), setCurrentWidget()
+*/
+QWidget *QStackedLayout::currentWidget() const
+{
+ Q_D(const QStackedLayout);
+ return d->index >= 0 ? d->list.at(d->index)->widget() : 0;
+}
+
+/*!
+ Returns the widget at the given \a index, or 0 if there is no
+ widget at the given position.
+
+ \sa currentWidget(), indexOf()
+*/
+QWidget *QStackedLayout::widget(int index) const
+{
+ Q_D(const QStackedLayout);
+ if (index < 0 || index >= d->list.size())
+ return 0;
+ return d->list.at(index)->widget();
+}
+
+/*!
+ \property QStackedLayout::count
+ \brief the number of widgets contained in the layout
+
+ \sa currentIndex(), widget()
+*/
+int QStackedLayout::count() const
+{
+ Q_D(const QStackedLayout);
+ return d->list.size();
+}
+
+
+/*!
+ \reimp
+*/
+void QStackedLayout::addItem(QLayoutItem *item)
+{
+ QWidget *widget = item->widget();
+ if (widget) {
+ addWidget(widget);
+ delete item;
+ } else {
+ qWarning("QStackedLayout::addItem: Only widgets can be added");
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QStackedLayout::sizeHint() const
+{
+ Q_D(const QStackedLayout);
+ QSize s(0, 0);
+ int n = d->list.count();
+
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget()) {
+ QSize ws(widget->sizeHint());
+ if (widget->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ ws.setWidth(0);
+ if (widget->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ ws.setHeight(0);
+ s = s.expandedTo(ws);
+ }
+ return s;
+}
+
+/*!
+ \reimp
+*/
+QSize QStackedLayout::minimumSize() const
+{
+ Q_D(const QStackedLayout);
+ QSize s(0, 0);
+ int n = d->list.count();
+
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget())
+ s = s.expandedTo(qSmartMinSize(widget));
+ return s;
+}
+
+/*!
+ \reimp
+*/
+void QStackedLayout::setGeometry(const QRect &rect)
+{
+ Q_D(QStackedLayout);
+ switch (d->stackingMode) {
+ case StackOne:
+ if (QWidget *widget = currentWidget())
+ widget->setGeometry(rect);
+ break;
+ case StackAll:
+ if (const int n = d->list.count())
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget())
+ widget->setGeometry(rect);
+ break;
+ }
+}
+
+/*!
+ \enum QStackedLayout::StackingMode
+ \since 4.4
+
+ This enum specifies how the layout handles its child widgets
+ regarding their visibility.
+
+ \value StackOne
+ Only the current widget is visible. This is the default.
+
+ \value StackAll
+ All widgets are visible. The current widget is merely raised.
+*/
+
+
+/*!
+ \property QStackedLayout::stackingMode
+ \brief determines the way visibility of child widgets are handled.
+ \since 4.4
+
+ The default value is StackOne. Setting the property to StackAll
+ allows you to make use of the layout for overlay widgets
+ that do additional drawing on top of other widgets, for example,
+ graphical editors.
+*/
+
+QStackedLayout::StackingMode QStackedLayout::stackingMode() const
+{
+ Q_D(const QStackedLayout);
+ return d->stackingMode;
+}
+
+void QStackedLayout::setStackingMode(StackingMode stackingMode)
+{
+ Q_D(QStackedLayout);
+ if (d->stackingMode == stackingMode)
+ return;
+ d->stackingMode = stackingMode;
+
+ const int n = d->list.count();
+ if (n == 0)
+ return;
+
+ switch (d->stackingMode) {
+ case StackOne:
+ if (const int idx = currentIndex())
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget())
+ widget->setVisible(i == idx);
+ break;
+ case StackAll: { // Turn overlay on: Make sure all widgets are the same size
+ QRect geometry;
+ if (const QWidget *widget = currentWidget())
+ geometry = widget->geometry();
+ for (int i = 0; i < n; ++i)
+ if (QWidget *widget = d->list.at(i)->widget()) {
+ if (!geometry.isNull())
+ widget->setGeometry(geometry);
+ widget->setVisible(true);
+ }
+ }
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstackedlayout.h b/src/gui/kernel/qstackedlayout.h
new file mode 100644
index 0000000000..668c1cc7dc
--- /dev/null
+++ b/src/gui/kernel/qstackedlayout.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTACKEDLAYOUT_H
+#define QSTACKEDLAYOUT_H
+
+#include <QtGui/qlayout.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QStackedLayoutPrivate;
+
+class Q_GUI_EXPORT QStackedLayout : public QLayout
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QStackedLayout)
+ Q_ENUMS(StackingMode)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentChanged)
+ Q_PROPERTY(StackingMode stackingMode READ stackingMode WRITE setStackingMode)
+ QDOC_PROPERTY(int count READ count)
+
+public:
+ enum StackingMode {
+ StackOne,
+ StackAll
+ };
+
+ QStackedLayout();
+ explicit QStackedLayout(QWidget *parent);
+ explicit QStackedLayout(QLayout *parentLayout);
+ ~QStackedLayout();
+
+ int addWidget(QWidget *w);
+ int insertWidget(int index, QWidget *w);
+
+ QWidget *currentWidget() const;
+ int currentIndex() const;
+#ifdef Q_NO_USING_KEYWORD
+ inline QWidget *widget() { return QLayout::widget(); }
+#else
+ using QLayout::widget;
+#endif
+ QWidget *widget(int) const;
+ int count() const;
+
+ StackingMode stackingMode() const;
+ void setStackingMode(StackingMode stackingMode);
+
+ // abstract virtual functions:
+ void addItem(QLayoutItem *item);
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QLayoutItem *itemAt(int) const;
+ QLayoutItem *takeAt(int);
+ void setGeometry(const QRect &rect);
+
+Q_SIGNALS:
+ void widgetRemoved(int index);
+ void currentChanged(int index);
+
+public Q_SLOTS:
+ void setCurrentIndex(int index);
+ void setCurrentWidget(QWidget *w);
+
+private:
+ Q_DISABLE_COPY(QStackedLayout)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTACKEDLAYOUT_H
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
new file mode 100644
index 0000000000..9c381b4362
--- /dev/null
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -0,0 +1,1096 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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/qcore_mac_p.h>
+#include <qwidget.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <private/qevent_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qt_mac_p.h>
+#include <private/qapplication_p.h>
+#include <private/qcocoawindow_mac_p.h>
+#include <private/qcocoaview_mac_p.h>
+#include <private/qkeymapper_p.h>
+#include <private/qwidget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
+extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
+extern QWidget * mac_mouse_grabber;
+
+void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
+{
+ OSWindowRef wnd = static_cast<OSWindowRef>(window);
+ if( wnd ) {
+#if QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ [NSAnimationContext beginGrouping];
+ [[wnd animator] setAlphaValue:0.0];
+ if (durationSeconds > 0) {
+ [[NSAnimationContext currentContext] setDuration:NSTimeInterval(durationSeconds)];
+ } else {
+ durationSeconds = [[NSAnimationContext currentContext] duration];
+ }
+ [NSAnimationContext endGrouping];
+ QTimer::singleShot(qRound(durationSeconds * 1000), [wnd QT_MANGLE_NAMESPACE(qt_qwidget)], SLOT(hide()));
+#else
+ if (durationSeconds <= 0)
+ durationSeconds = 0.15;
+ TransitionWindowOptions options = {0, durationSeconds, 0, 0};
+ TransitionWindowWithOptions(wnd, kWindowFadeTransitionEffect, kWindowHideTransitionAction, 0, 1, &options);
+#endif
+ }
+}
+
+
+
+bool macWindowIsTextured( void * /*OSWindowRef*/ window )
+{
+ OSWindowRef wnd = static_cast<OSWindowRef>(window);
+#if QT_MAC_USE_COCOA
+ return ( [wnd styleMask] & NSTexturedBackgroundWindowMask ) ? true : false;
+#else
+ WindowAttributes currentAttributes;
+ GetWindowAttributes(wnd, &currentAttributes);
+ return (currentAttributes & kWindowMetalAttribute) ? true : false;
+#endif
+}
+
+void macWindowToolbarShow(const QWidget *widget, bool show )
+{
+ OSWindowRef wnd = qt_mac_window_for(widget);
+#if QT_MAC_USE_COCOA
+ NSToolbar *toolbar = [wnd toolbar];
+ if (toolbar) {
+ QMacCocoaAutoReleasePool pool;
+ if (show != [toolbar isVisible]) {
+ [wnd toggleToolbarShown:wnd];
+ } else {
+ // The toolbar may be in sync, but we are not, update our framestrut.
+ qt_widget_private(const_cast<QWidget *>(widget))->updateFrameStrut();
+ }
+ }
+#else
+ ShowHideWindowToolbar(wnd, show, false);
+#endif
+}
+
+
+void macWindowToolbarSet( void * /*OSWindowRef*/ window, void *toolbarRef )
+{
+ OSWindowRef wnd = static_cast<OSWindowRef>(window);
+#if QT_MAC_USE_COCOA
+ [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)];
+#else
+ SetWindowToolbar(wnd, static_cast<HIToolbarRef>(toolbarRef));
+#endif
+}
+
+bool macWindowToolbarVisible( void * /*OSWindowRef*/ window )
+{
+ OSWindowRef wnd = static_cast<OSWindowRef>(window);
+#if QT_MAC_USE_COCOA
+ NSToolbar *toolbar = [wnd toolbar];
+ if (toolbar)
+ return [toolbar isVisible];
+ return false;
+#else
+ return IsWindowToolbarVisible(wnd);
+#endif
+}
+
+void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow )
+{
+ OSWindowRef wnd = static_cast<OSWindowRef>(window);
+#if QT_MAC_USE_COCOA
+ [wnd setHasShadow:BOOL(hasShadow)];
+#else
+ if (hasShadow)
+ ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute);
+ else
+ ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0);
+#endif
+}
+
+void macWindowFlush(void * /*OSWindowRef*/ window)
+{
+ OSWindowRef wnd = static_cast<OSWindowRef>(window);
+#if QT_MAC_USE_COCOA
+ [wnd flushWindowIfNeeded];
+#else
+ HIWindowFlush(wnd);
+#endif
+}
+
+void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm)
+{
+ QMacCocoaAutoReleasePool pool;
+ if(QCFType<CGImageRef> image = pm.toMacCGImageRef()) {
+ NSImage *newImage = 0;
+ NSRect imageRect = NSMakeRect(0.0, 0.0, CGImageGetWidth(image), CGImageGetHeight(image));
+ newImage = [[NSImage alloc] initWithSize:imageRect.size];
+ [newImage lockFocus];
+ {
+ CGContextRef imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ CGContextDrawImage(imageContext, *(CGRect*)&imageRect, image);
+ }
+ [newImage unlockFocus];
+ return newImage;
+ }
+ return 0;
+}
+
+void qt_mac_update_mouseTracking(QWidget *widget)
+{
+#ifdef QT_MAC_USE_COCOA
+ [qt_mac_nativeview_for(widget) updateTrackingAreas];
+#else
+ Q_UNUSED(widget);
+#endif
+}
+
+OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
+{
+ // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev)
+ OSStatus err = noErr;
+
+ require_action(inContext != NULL, InvalidContext, err = paramErr);
+ require_action(inBounds != NULL, InvalidBounds, err = paramErr);
+ require_action(inImage != NULL, InvalidImage, err = paramErr);
+
+ CGContextSaveGState( inContext );
+ CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds));
+ CGContextScaleCTM(inContext, 1, -1);
+
+ CGContextDrawImage(inContext, *inBounds, inImage);
+
+ CGContextRestoreGState(inContext);
+InvalidImage:
+InvalidBounds:
+InvalidContext:
+ return err;
+}
+
+bool qt_mac_checkForNativeSizeGrip(const QWidget *widget)
+{
+#ifndef QT_MAC_USE_COCOA
+ OSViewRef nativeSizeGrip = 0;
+ HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(widget->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip);
+ return (nativeSizeGrip != 0);
+#else
+ return [[reinterpret_cast<NSView *>(widget->winId()) window] showsResizeIndicator];
+#endif
+}
+struct qt_mac_enum_mapper
+{
+ int mac_code;
+ int qt_code;
+#if defined(DEBUG_MOUSE_MAPS)
+# define QT_MAC_MAP_ENUM(x) x, #x
+ const char *desc;
+#else
+# define QT_MAC_MAP_ENUM(x) x
+#endif
+};
+
+//mouse buttons
+static qt_mac_enum_mapper qt_mac_mouse_symbols[] = {
+{ kEventMouseButtonPrimary, QT_MAC_MAP_ENUM(Qt::LeftButton) },
+{ kEventMouseButtonSecondary, QT_MAC_MAP_ENUM(Qt::RightButton) },
+{ kEventMouseButtonTertiary, QT_MAC_MAP_ENUM(Qt::MidButton) },
+{ 4, QT_MAC_MAP_ENUM(Qt::XButton1) },
+{ 5, QT_MAC_MAP_ENUM(Qt::XButton2) },
+{ 0, QT_MAC_MAP_ENUM(0) }
+};
+Qt::MouseButtons qt_mac_get_buttons(int buttons)
+{
+#ifdef DEBUG_MOUSE_MAPS
+ qDebug("Qt: internal: **Mapping buttons: %d (0x%04x)", buttons, buttons);
+#endif
+ Qt::MouseButtons ret = Qt::NoButton;
+ for(int i = 0; qt_mac_mouse_symbols[i].qt_code; i++) {
+ if (buttons & (0x01<<(qt_mac_mouse_symbols[i].mac_code-1))) {
+#ifdef DEBUG_MOUSE_MAPS
+ qDebug("Qt: internal: got button: %s", qt_mac_mouse_symbols[i].desc);
+#endif
+ ret |= Qt::MouseButtons(qt_mac_mouse_symbols[i].qt_code);
+ }
+ }
+ return ret;
+}
+Qt::MouseButton qt_mac_get_button(EventMouseButton button)
+{
+#ifdef DEBUG_MOUSE_MAPS
+ qDebug("Qt: internal: **Mapping button: %d (0x%04x)", button, button);
+#endif
+ Qt::MouseButtons ret = 0;
+ for(int i = 0; qt_mac_mouse_symbols[i].qt_code; i++) {
+ if (button == qt_mac_mouse_symbols[i].mac_code) {
+#ifdef DEBUG_MOUSE_MAPS
+ qDebug("Qt: internal: got button: %s", qt_mac_mouse_symbols[i].desc);
+#endif
+ return Qt::MouseButton(qt_mac_mouse_symbols[i].qt_code);
+ }
+ }
+ return Qt::NoButton;
+}
+
+Q_GLOBAL_STATIC(QMacTabletHash, tablet_hash)
+QMacTabletHash *qt_mac_tablet_hash()
+{
+ return tablet_hash();
+}
+
+#ifdef QT_MAC_USE_COCOA
+void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent)
+{
+ NSEvent *proximityEvent = static_cast<NSEvent *>(tabletEvent);
+ // simply construct a Carbon proximity record and handle it all in one spot.
+ TabletProximityRec carbonProximityRec = { [proximityEvent vendorID],
+ [proximityEvent tabletID],
+ [proximityEvent pointingDeviceID],
+ [proximityEvent deviceID],
+ [proximityEvent systemTabletID],
+ [proximityEvent vendorPointingDeviceType],
+ [proximityEvent pointingDeviceSerialNumber],
+ [proximityEvent uniqueID],
+ [proximityEvent capabilityMask],
+ [proximityEvent pointingDeviceType],
+ [proximityEvent isEnteringProximity] };
+ qt_dispatchTabletProximityEvent(carbonProximityRec);
+}
+#endif // QT_MAC_USE_COCOA
+
+void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec)
+{
+ QTabletDeviceData proximityDevice;
+ proximityDevice.tabletUniqueID = proxRec.uniqueID;
+ proximityDevice.capabilityMask = proxRec.capabilityMask;
+
+ switch (proxRec.pointerType) {
+ case NSUnknownPointingDevice:
+ default:
+ proximityDevice.tabletPointerType = QTabletEvent::UnknownPointer;
+ break;
+ case NSPenPointingDevice:
+ proximityDevice.tabletPointerType = QTabletEvent::Pen;
+ break;
+ case NSCursorPointingDevice:
+ proximityDevice.tabletPointerType = QTabletEvent::Cursor;
+ break;
+ case NSEraserPointingDevice:
+ proximityDevice.tabletPointerType = QTabletEvent::Eraser;
+ break;
+ }
+ uint bits = proxRec.vendorPointerType;
+ if (bits == 0 && proximityDevice.tabletUniqueID != 0) {
+ // Fallback. It seems that the driver doesn't always include all the information.
+ // High-End Wacom devices store their "type" in the uper bits of the Unique ID.
+ // I'm not sure how to handle it for consumer devices, but I'll test that in a bit.
+ bits = proximityDevice.tabletUniqueID >> 32;
+ }
+ // Defined in the "EN0056-NxtGenImpGuideX"
+ // on Wacom's Developer Website (www.wacomeng.com)
+ if (((bits & 0x0006) == 0x0002) && ((bits & 0x0F06) != 0x0902)) {
+ proximityDevice.tabletDeviceType = QTabletEvent::Stylus;
+ } else {
+ switch (bits & 0x0F06) {
+ case 0x0802:
+ proximityDevice.tabletDeviceType = QTabletEvent::Stylus;
+ break;
+ case 0x0902:
+ proximityDevice.tabletDeviceType = QTabletEvent::Airbrush;
+ break;
+ case 0x0004:
+ proximityDevice.tabletDeviceType = QTabletEvent::FourDMouse;
+ break;
+ case 0x0006:
+ proximityDevice.tabletDeviceType = QTabletEvent::Puck;
+ break;
+ case 0x0804:
+ proximityDevice.tabletDeviceType = QTabletEvent::RotationStylus;
+ break;
+ default:
+ proximityDevice.tabletDeviceType = QTabletEvent::NoDevice;
+ }
+ }
+ // The deviceID is "unique" while in the proximity, it's a key that we can use for
+ // linking up TabletDeviceData to an event (especially if there are two devices in action).
+ bool entering = proxRec.enterProximity;
+ if (entering) {
+ qt_mac_tablet_hash()->insert(proxRec.deviceID, proximityDevice);
+ } else {
+ qt_mac_tablet_hash()->remove(proxRec.deviceID);
+ }
+
+ QTabletEvent qtabletProximity(entering ? QEvent::TabletEnterProximity
+ : QEvent::TabletLeaveProximity,
+ QPoint(), QPoint(), QPointF(), proximityDevice.tabletDeviceType,
+ proximityDevice.tabletPointerType, 0., 0, 0, 0., 0., 0, 0,
+ proximityDevice.tabletUniqueID);
+
+ qt_sendSpontaneousEvent(qApp, &qtabletProximity);
+}
+
+#ifdef QT_MAC_USE_COCOA
+// Use this method to keep all the information in the TextSegment. As long as it is ordered
+// we are in OK shape, and we can influence that ourselves.
+struct KeyPair
+{
+ QChar cocoaKey;
+ Qt::Key qtKey;
+};
+
+bool operator==(const KeyPair &entry, QChar qchar)
+{
+ return entry.cocoaKey == qchar;
+}
+
+bool operator<(const KeyPair &entry, QChar qchar)
+{
+ return entry.cocoaKey < qchar;
+}
+
+bool operator<(QChar qchar, const KeyPair &entry)
+{
+ return qchar < entry.cocoaKey;
+}
+
+static Qt::Key cocoaKey2QtKey(QChar keyCode)
+{
+ static const int NumEntries = 57;
+ static const KeyPair entries[NumEntries] = {
+ { NSEnterCharacter, Qt::Key_Enter },
+ { NSTabCharacter, Qt::Key_Tab },
+ { NSCarriageReturnCharacter, Qt::Key_Return },
+ { NSBackTabCharacter, Qt::Key_Backtab },
+ { kEscapeCharCode, Qt::Key_Escape },
+ { NSDeleteCharacter, Qt::Key_Backspace },
+ { NSUpArrowFunctionKey, Qt::Key_Up },
+ { NSDownArrowFunctionKey, Qt::Key_Down },
+ { NSLeftArrowFunctionKey, Qt::Key_Left },
+ { NSRightArrowFunctionKey, Qt::Key_Right },
+ { NSF1FunctionKey, Qt::Key_F1 },
+ { NSF2FunctionKey, Qt::Key_F2 },
+ { NSF3FunctionKey, Qt::Key_F3 },
+ { NSF4FunctionKey, Qt::Key_F4 },
+ { NSF5FunctionKey, Qt::Key_F5 },
+ { NSF6FunctionKey, Qt::Key_F6 },
+ { NSF7FunctionKey, Qt::Key_F7 },
+ { NSF8FunctionKey, Qt::Key_F8 },
+ { NSF9FunctionKey, Qt::Key_F8 },
+ { NSF10FunctionKey, Qt::Key_F10 },
+ { NSF11FunctionKey, Qt::Key_F11 },
+ { NSF12FunctionKey, Qt::Key_F12 },
+ { NSF13FunctionKey, Qt::Key_F13 },
+ { NSF14FunctionKey, Qt::Key_F14 },
+ { NSF15FunctionKey, Qt::Key_F15 },
+ { NSF16FunctionKey, Qt::Key_F16 },
+ { NSF17FunctionKey, Qt::Key_F17 },
+ { NSF18FunctionKey, Qt::Key_F18 },
+ { NSF19FunctionKey, Qt::Key_F19 },
+ { NSF20FunctionKey, Qt::Key_F20 },
+ { NSF21FunctionKey, Qt::Key_F21 },
+ { NSF22FunctionKey, Qt::Key_F22 },
+ { NSF23FunctionKey, Qt::Key_F23 },
+ { NSF24FunctionKey, Qt::Key_F24 },
+ { NSF25FunctionKey, Qt::Key_F25 },
+ { NSF26FunctionKey, Qt::Key_F26 },
+ { NSF27FunctionKey, Qt::Key_F27 },
+ { NSF28FunctionKey, Qt::Key_F28 },
+ { NSF29FunctionKey, Qt::Key_F29 },
+ { NSF30FunctionKey, Qt::Key_F30 },
+ { NSF31FunctionKey, Qt::Key_F31 },
+ { NSF32FunctionKey, Qt::Key_F32 },
+ { NSF33FunctionKey, Qt::Key_F33 },
+ { NSF34FunctionKey, Qt::Key_F34 },
+ { NSF35FunctionKey, Qt::Key_F35 },
+ { NSInsertFunctionKey, Qt::Key_Insert },
+ { NSDeleteFunctionKey, Qt::Key_Delete },
+ { NSHomeFunctionKey, Qt::Key_Home },
+ { NSEndFunctionKey, Qt::Key_End },
+ { NSPageUpFunctionKey, Qt::Key_PageUp },
+ { NSPageDownFunctionKey, Qt::Key_PageDown },
+ { NSPrintScreenFunctionKey, Qt::Key_Print },
+ { NSScrollLockFunctionKey, Qt::Key_ScrollLock },
+ { NSPauseFunctionKey, Qt::Key_Pause },
+ { NSSysReqFunctionKey, Qt::Key_SysReq },
+ { NSMenuFunctionKey, Qt::Key_Menu },
+ { NSHelpFunctionKey, Qt::Key_Help },
+ };
+ static const KeyPair * const end = entries + NumEntries;
+ const KeyPair *i = qBinaryFind(entries, end, keyCode);
+ if (i == end)
+ return Qt::Key(keyCode.unicode());
+ return i->qtKey;
+}
+
+Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags)
+{
+ Qt::KeyboardModifiers qtMods =Qt::NoModifier;
+ if (modifierFlags & NSShiftKeyMask)
+ qtMods |= Qt::ShiftModifier;
+ if (modifierFlags & NSControlKeyMask)
+ qtMods |= Qt::MetaModifier;
+ if (modifierFlags & NSAlternateKeyMask)
+ qtMods |= Qt::AltModifier;
+ if (modifierFlags & NSCommandKeyMask)
+ qtMods |= Qt::ControlModifier;
+ if (modifierFlags & NSNumericPadKeyMask)
+ qtMods |= Qt::KeypadModifier;
+ return qtMods;
+}
+
+static inline QEvent::Type cocoaEvent2QtEvent(NSUInteger eventType)
+{
+ // Handle the trivial cases that can be determined from the type.
+ switch (eventType) {
+ case NSKeyDown:
+ return QEvent::KeyPress;
+ case NSKeyUp:
+ return QEvent::KeyRelease;
+ case NSLeftMouseDown:
+ case NSRightMouseDown:
+ case NSOtherMouseDown:
+ return QEvent::MouseButtonPress;
+ case NSLeftMouseUp:
+ case NSRightMouseUp:
+ case NSOtherMouseUp:
+ return QEvent::MouseButtonRelease;
+ case NSMouseMoved:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ return QEvent::MouseMove;
+ case NSScrollWheel:
+ return QEvent::Wheel;
+ }
+ return QEvent::None;
+}
+
+static bool mustUseCocoaKeyEvent()
+{
+ QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource();
+ return TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData) == 0;
+}
+
+bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent)
+{
+ NSEvent *event = static_cast<NSEvent *>(keyEvent);
+ NSString *keyChars = [event charactersIgnoringModifiers];
+ int keyLength = [keyChars length];
+ if (keyLength == 0)
+ return false; // Dead Key, nothing to do!
+ Qt::Key qtKey = Qt::Key_unknown;
+ if (keyLength == 1) {
+ QChar ch([keyChars characterAtIndex:0]);
+ if (ch.isLower())
+ ch = ch.toUpper();
+ qtKey = cocoaKey2QtKey(ch);
+ }
+ Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([event modifierFlags]);
+ QString text;
+
+ // To quote from the Carbon port: This is actually wrong--but it is the best that
+ // can be done for now because of the Control/Meta mapping issues
+ // (we always get text on the Mac)
+ if (!(keyMods & (Qt::ControlModifier | Qt::MetaModifier)))
+ text = QCFString::toQString(reinterpret_cast<CFStringRef>(keyChars));
+
+ UInt32 macScanCode = 1;
+ QKeyEventEx ke(cocoaEvent2QtEvent([event type]), qtKey, keyMods, text, [event isARepeat], qMax(1, keyLength),
+ macScanCode, [event keyCode], [event modifierFlags]);
+ qt_sendSpontaneousEvent(widgetToGetEvent, &ke);
+ return ke.isAccepted();
+}
+#endif
+
+// Helper to share code between QCocoaWindow and QCocoaView
+bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(keyEvent);
+ Q_UNUSED(widgetToGetEvent);
+ return false;
+#else
+ NSEvent *event = static_cast<NSEvent *>(keyEvent);
+ EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef]));
+ Q_ASSERT(key_event);
+ if ([event type] == NSKeyDown) {
+ qt_keymapper_private()->updateKeyMap(0, key_event, 0);
+ }
+ if (widgetToGetEvent == 0)
+ return false;
+
+ if (qt_mac_sendMacEventToWidget(widgetToGetEvent, key_event))
+ return true;
+
+ if (mustUseCocoaKeyEvent())
+ return qt_dispatchKeyEventWithCocoa(keyEvent, widgetToGetEvent);
+ bool isAccepted;
+ qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &isAccepted, true);
+ return isAccepted;
+#endif
+}
+
+void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(flagsChangedEvent);
+ Q_UNUSED(widgetToGetEvent);
+#else
+ UInt32 modifiers = 0;
+ // Sync modifiers with Qt
+ NSEvent *event = static_cast<NSEvent *>(flagsChangedEvent);
+ EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef]));
+ Q_ASSERT(key_event);
+ GetEventParameter(key_event, kEventParamKeyModifiers, typeUInt32, 0,
+ sizeof(modifiers), 0, &modifiers);
+ extern void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object);
+ qt_mac_send_modifiers_changed(modifiers, widgetToGetEvent);
+#endif
+}
+
+
+QPointF flipPoint(const NSPoint &p)
+{
+ return QPointF(p.x, flipYCoordinate(p.y));
+}
+
+NSPoint flipPoint(const QPoint &p)
+{
+ return NSMakePoint(p.x(), flipYCoordinate(p.y()));
+}
+
+NSPoint flipPoint(const QPointF &p)
+{
+ return NSMakePoint(p.x(), flipYCoordinate(p.y()));
+}
+
+void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* NSEvent* */mouseEvent,
+ QWidget *widgetToGetEvent, bool &leftButtonIsRightButton)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(eventWindow);
+ Q_UNUSED(mouseEvent);
+ Q_UNUSED(widgetToGetEvent);
+ Q_UNUSED(leftButtonIsRightButton);
+#else
+ if (widgetToGetEvent == 0)
+ return;
+ NSWindow *window = static_cast<NSWindow *>(eventWindow);
+ NSEvent *event = static_cast<NSEvent *>(mouseEvent);
+ NSEventType evtType = [event type];
+
+ QPoint qlocalPoint;
+ QPoint qglobalPoint;
+ bool processThisEvent = false;
+ bool fakeNCEvents = false;
+ bool fakeMouseEvents = false;
+
+ // Check if this is a mouse event.
+ if (evtType == NSLeftMouseDown || evtType == NSLeftMouseUp
+ || evtType == NSRightMouseDown || evtType == NSRightMouseUp
+ || evtType == NSOtherMouseDown || evtType == NSOtherMouseUp
+ || evtType == NSMouseMoved || evtType == NSLeftMouseDragged
+ || evtType == NSRightMouseDragged || evtType == NSOtherMouseDragged) {
+ // Check if we want to pass this message to another window
+ if (mac_mouse_grabber && mac_mouse_grabber != widgetToGetEvent) {
+ NSWindow *grabWindow = static_cast<NSWindow *>(qt_mac_window_for(mac_mouse_grabber));
+ if (window != grabWindow) {
+ window = grabWindow;
+ widgetToGetEvent = mac_mouse_grabber;
+ fakeNCEvents = true;
+ }
+ }
+ // Dont generate normal NC mouse events for Left Button dragged
+ if(evtType != NSLeftMouseDragged || fakeNCEvents) {
+ NSPoint windowPoint = [event locationInWindow];
+ NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint];
+ NSRect frameRect = [window frame];
+ if (fakeNCEvents || NSMouseInRect(globalPoint, frameRect, NO)) {
+ NSRect contentRect = [window contentRectForFrameRect:frameRect];
+ if (fakeNCEvents || !NSMouseInRect(globalPoint, contentRect, NO)) {
+ qglobalPoint = QPoint(flipPoint(globalPoint).toPoint());
+ qlocalPoint = widgetToGetEvent->mapFromGlobal(qglobalPoint);
+ processThisEvent = true;
+ }
+ }
+ }
+ }
+ // This is not an NC area mouse message.
+ if (!processThisEvent)
+ return;
+ // If the window is frame less, generate fake mouse events instead. (floating QToolBar)
+ if (fakeNCEvents && (widgetToGetEvent->window()->windowFlags() & Qt::FramelessWindowHint))
+ fakeMouseEvents = true;
+
+ Qt::MouseButton button;
+ QEvent::Type eventType;
+ // Convert to Qt::Event type
+ switch (evtType) {
+ case NSLeftMouseDown:
+ button = Qt::LeftButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonPress
+ : QEvent::MouseButtonPress;
+ break;
+ case NSLeftMouseUp:
+ button = Qt::LeftButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonRelease
+ : QEvent::MouseButtonRelease;
+ break;
+ case NSRightMouseDown:
+ button = Qt::RightButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonPress
+ : QEvent::MouseButtonPress;
+ break;
+ case NSRightMouseUp:
+ button = Qt::RightButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonRelease
+ : QEvent::MouseButtonRelease;
+ break;
+ case NSOtherMouseDown:
+ button = cocoaButton2QtButton([event buttonNumber]);
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonPress
+ : QEvent::MouseButtonPress;
+ break;
+ case NSOtherMouseUp:
+ button = cocoaButton2QtButton([event buttonNumber]);
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonRelease
+ : QEvent::MouseButtonRelease;
+ break;
+ case NSMouseMoved:
+ button = Qt::NoButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove
+ : QEvent::MouseMove;
+ break;
+ case NSLeftMouseDragged:
+ button = Qt::LeftButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove
+ : QEvent::MouseMove;
+ break;
+ case NSRightMouseDragged:
+ button = Qt::RightButton;
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove
+ : QEvent::MouseMove;
+ break;
+ case NSOtherMouseDragged:
+ button = cocoaButton2QtButton([event buttonNumber]);
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove
+ : QEvent::MouseMove;
+ break;
+ default:
+ qWarning("not handled! Non client area mouse message");
+ return;
+ }
+
+ Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([event modifierFlags]);
+ if (eventType == QEvent::NonClientAreaMouseButtonPress || eventType == QEvent::MouseButtonPress) {
+ NSInteger clickCount = [event clickCount];
+ if (clickCount % 2 == 0)
+ eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonDblClick
+ : QEvent::MouseButtonDblClick;
+ if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) {
+ button = Qt::RightButton;
+ leftButtonIsRightButton = true;
+ }
+ } else if (eventType == QEvent::NonClientAreaMouseButtonRelease || eventType == QEvent::MouseButtonRelease) {
+ if (button == Qt::LeftButton && leftButtonIsRightButton) {
+ button = Qt::RightButton;
+ leftButtonIsRightButton = false;
+ }
+ }
+ QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, button, keyMods);
+ qt_sendSpontaneousEvent(widgetToGetEvent, &qme);
+#endif
+}
+
+bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */event, QEvent::Type eventType, Qt::MouseButton button)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(view);
+ Q_UNUSED(event);
+ Q_UNUSED(eventType);
+ Q_UNUSED(button);
+ return false;
+#else
+ QT_MANGLE_NAMESPACE(QCocoaView) *theView = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view);
+ NSEvent *theEvent = static_cast<NSEvent *>(event);
+
+ // Give the Input Manager a chance to process the mouse events.
+ NSInputManager *currentIManager = [NSInputManager currentInputManager];
+ if (currentIManager && [currentIManager wantsToHandleMouseEvents]) {
+ [currentIManager handleMouseEvent:theEvent];
+ }
+
+ // Handle tablet events (if any) first.
+ if (qt_mac_handleTabletEvent(theView, theEvent)) {
+ // Tablet event was handled. In Qt we aren't supposed to send the mouse event.
+ return true;
+ }
+
+ NSPoint windowPoint = [theEvent locationInWindow];
+ NSPoint globalPoint = [[theEvent window] convertBaseToScreen:windowPoint];
+
+ // Find the widget that *should* get the event (e.g., maybe it was a pop-up,
+ // they always get the mouse event).
+ QWidget *qwidget = [theView qt_qwidget];
+ QWidget *widgetToGetMouse = qwidget;
+ QWidget *popup = qAppInstance()->activePopupWidget();
+ if (popup && popup != qwidget->window())
+ widgetToGetMouse = popup;
+ NSView *tmpView = theView;
+ if (widgetToGetMouse != qwidget) {
+ tmpView = qt_mac_nativeview_for(widgetToGetMouse);
+ windowPoint = [[tmpView window] convertScreenToBase:globalPoint];
+ }
+ NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil];
+ QPoint qlocalPoint(localPoint.x, localPoint.y);
+
+ if (widgetToGetMouse->testAttribute(Qt::WA_TransparentForMouseEvents)) {
+ // Simulate passing the event through since Cocoa doesn't do that for us.
+ // Start by building a tree up.
+ NSView *candidateView = [theView viewUnderTransparentForMouseView:tmpView
+ widget:widgetToGetMouse
+ withWindowPoint:windowPoint];
+ if (candidateView != nil) {
+ // Fast-track our views, since dispatching trough the normal ways
+ // would just end up going through here anyway.
+ if ([candidateView isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
+ return qt_mac_handleMouseEvent(candidateView, theEvent, eventType, button);
+ } else {
+ switch (eventType) {
+ default:
+ qWarning("not handled! %d", eventType);
+ break;
+ case QEvent::MouseMove:
+ [candidateView mouseMoved:theEvent];
+ break;
+ case QEvent::MouseButtonPress:
+ if (button == Qt::LeftButton)
+ [candidateView mouseDown:theEvent];
+ else if (button == Qt::RightButton)
+ [candidateView rightMouseDown:theEvent];
+ else
+ [candidateView otherMouseDown:theEvent];
+ break;
+ case QEvent::MouseButtonRelease:
+ if (button == Qt::LeftButton)
+ [candidateView mouseUp:theEvent];
+ else if (button == Qt::RightButton)
+ [candidateView rightMouseUp:theEvent];
+ else
+ [candidateView otherMouseUp:theEvent];
+ break;
+ }
+ return true; // We've done the dispatching, no need go further.
+ }
+ }
+ // Nothing below me return false
+ return false;
+ }
+
+
+ EventRef carbonEvent = static_cast<EventRef>(const_cast<void *>([theEvent eventRef]));
+ if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent))
+ return true;
+
+ // Yay! All the special cases are handled, it really is just a normal mouse event.
+ Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]);
+ NSInteger clickCount = [theEvent clickCount];
+ Qt::MouseButtons buttons = 0;
+ {
+ UInt32 mac_buttons;
+ if (GetEventParameter(carbonEvent, kEventParamMouseChord, typeUInt32, 0,
+ sizeof(mac_buttons), 0, &mac_buttons) == noErr)
+ buttons = qt_mac_get_buttons(mac_buttons);
+ }
+ switch (eventType) {
+ default:
+ qWarning("not handled! %d", eventType);
+ break;
+ case QEvent::MouseMove:
+ break;
+ case QEvent::MouseButtonPress:
+ [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = theView;
+ [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = theEvent;
+#ifndef QT_NAMESPACE
+ Q_ASSERT(clickCount > 0);
+#endif
+ if (clickCount % 2 == 0)
+ eventType = QEvent::MouseButtonDblClick;
+ if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) {
+ button = Qt::RightButton;
+ [theView qt_setLeftButtonIsRightButton: true];
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if (button == Qt::LeftButton && [theView qt_leftButtonIsRightButton]) {
+ button = Qt::RightButton;
+ [theView qt_setLeftButtonIsRightButton: false];
+ }
+ break;
+ }
+ [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->localPoint = localPoint;
+ QPoint qglobalPoint(flipPoint(globalPoint).toPoint());
+ QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods);
+ qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
+ if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) {
+ QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods);
+ qt_sendSpontaneousEvent(widgetToGetMouse, &qcme);
+ }
+ return qme.isAccepted();
+#endif
+}
+
+bool qt_mac_handleTabletEvent(void * /*QCocoaView * */view, void * /*NSEvent * */tabletEvent)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(view);
+ Q_UNUSED(tabletEvent);
+ return false;
+#else
+ QT_MANGLE_NAMESPACE(QCocoaView) *theView = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view);
+ NSView *theNSView = static_cast<NSView *>(view);
+ NSEvent *theTabletEvent = static_cast<NSEvent *>(tabletEvent);
+
+ NSEventType eventType = [theTabletEvent type];
+ if (eventType != NSTabletPoint && [theTabletEvent subtype] != NSTabletPointEventSubtype)
+ return false; // Not a tablet event.
+
+ NSPoint windowPoint = [theTabletEvent locationInWindow];
+ NSPoint globalPoint = [[theTabletEvent window] convertBaseToScreen:windowPoint];
+
+ QWidget *qwidget = [theView qt_qwidget];
+ QWidget *widgetToGetMouse = qwidget;
+ QWidget *popup = qAppInstance()->activePopupWidget();
+ if (popup && popup != qwidget->window())
+ widgetToGetMouse = popup;
+
+ if (qt_mac_sendMacEventToWidget(widgetToGetMouse,
+ static_cast<EventRef>(const_cast<void *>([theTabletEvent eventRef]))))
+ return true;
+ if (widgetToGetMouse != qwidget) {
+ theNSView = qt_mac_nativeview_for(widgetToGetMouse);
+ windowPoint = [[theNSView window] convertScreenToBase:globalPoint];
+ }
+ NSPoint localPoint = [theNSView convertPoint:windowPoint fromView:nil];
+ // Tablet events do not handle WA_TransparentForMouseEvents ATM
+ // In theory, people who set the WA_TransparentForMouseEvents attribute won't handle
+ // tablet events either in which case they will fall into the mouse event case and get
+ // them passed on. This will NOT handle the raw events, but that might not be a big problem.
+
+ const QMacTabletHash *tabletHash = qt_mac_tablet_hash();
+ if (!tabletHash->contains([theTabletEvent deviceID])) {
+ qWarning("QCocoaView handleTabletEvent: This tablet device is unknown"
+ " (received no proximity event for it). Discarding event.");
+ return false;
+ }
+ const QTabletDeviceData &deviceData = tabletHash->value([theTabletEvent deviceID]);
+
+
+ QEvent::Type qType;
+ switch (eventType) {
+ case NSLeftMouseDown:
+ case NSRightMouseDown:
+ qType = QEvent::TabletPress;
+ break;
+ case NSLeftMouseUp:
+ case NSRightMouseUp:
+ qType = QEvent::TabletRelease;
+ break;
+ case NSMouseMoved:
+ case NSTabletPoint:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ default:
+ qType = QEvent::TabletMove;
+ break;
+ }
+
+ qreal pressure;
+ if (eventType != NSMouseMoved) {
+ pressure = [theTabletEvent pressure];
+ } else {
+ pressure = 0.0;
+ }
+
+ NSPoint tilt = [theTabletEvent tilt];
+ int xTilt = qRound(tilt.x * 60.0);
+ int yTilt = qRound(tilt.y * -60.0);
+ qreal tangentialPressure = 0;
+ qreal rotation = 0;
+ int z = 0;
+ if (deviceData.capabilityMask & 0x0200)
+ z = [theTabletEvent absoluteZ];
+
+ if (deviceData.capabilityMask & 0x0800)
+ tangentialPressure = [theTabletEvent tangentialPressure];
+
+ rotation = [theTabletEvent rotation];
+ QPointF hiRes = flipPoint(globalPoint);
+ QTabletEvent qtabletEvent(qType, QPoint(localPoint.x, localPoint.y),
+ hiRes.toPoint(), hiRes,
+ deviceData.tabletDeviceType, deviceData.tabletPointerType,
+ pressure, xTilt, yTilt, tangentialPressure, rotation, z,
+ qt_cocoaModifiers2QtModifiers([theTabletEvent modifierFlags]),
+ deviceData.tabletUniqueID);
+
+ qt_sendSpontaneousEvent(widgetToGetMouse, &qtabletEvent);
+ return qtabletEvent.isAccepted();
+#endif
+}
+
+void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics)
+{
+ OSWindowRef theWindow = static_cast<OSWindowRef>(window);
+#if !defined(QT_MAC_USE_COCOA)
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
+ ::HIWindowSetContentBorderThickness(theWindow, &metrics);
+ }
+# else
+ Q_UNUSED(window);
+ Q_UNUSED(metrics);
+# endif
+#else
+ if ([theWindow styleMask] & NSTexturedBackgroundWindowMask)
+ [theWindow setContentBorderThickness:metrics.top forEdge:NSMaxYEdge];
+ [theWindow setContentBorderThickness:metrics.bottom forEdge:NSMinYEdge];
+#endif
+}
+
+QStringList qt_mac_NSArrayToQStringList(void *nsarray)
+{
+ QStringList result;
+ NSArray *array = static_cast<NSArray *>(nsarray);
+ for (NSUInteger i=0; i<[array count]; ++i)
+ result << qt_mac_NSStringToQString([array objectAtIndex:i]);
+ return result;
+}
+
+void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list)
+{
+ NSMutableArray *result = [NSMutableArray arrayWithCapacity:list.size()];
+ for (int i=0; i<list.size(); ++i){
+ [result addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(list[i]))];
+ }
+ return result;
+}
+
+void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow)
+{
+ if (!widgetForWindow)
+ return;
+
+ Qt::WindowFlags flags = widgetForWindow->windowFlags();
+ bool customize = flags & Qt::CustomizeWindowHint;
+
+ NSButton *btn = [window standardWindowButton:NSWindowZoomButton];
+ // BOOL is not an int, so the bitwise AND doesn't work.
+ bool go = uint(customize && !(flags & Qt::WindowMaximizeButtonHint)) == 0;
+ [btn setEnabled:go];
+
+ btn = [window standardWindowButton:NSWindowMiniaturizeButton];
+ go = uint(customize && !(flags & Qt::WindowMinimizeButtonHint)) == 0;
+ [btn setEnabled:go];
+
+ btn = [window standardWindowButton:NSWindowCloseButton];
+ go = uint(customize && !(flags & Qt::WindowSystemMenuHint
+ || flags & Qt::WindowCloseButtonHint)) == 0;
+ [btn setEnabled:go];
+
+ [window setShowsToolbarButton:uint(flags & Qt::MacWindowToolBarButtonHint) != 0];
+}
+
+// Carbon: Make sure you call QDEndContext on the context when done with it.
+CGContextRef qt_mac_graphicsContextFor(QWidget *widget)
+{
+ if (!widget)
+ return 0;
+
+#ifndef QT_MAC_USE_COCOA
+ CGContextRef context;
+ CGrafPtr port = GetWindowPort(qt_mac_window_for(widget));
+ QDBeginCGContext(port, &context);
+#else
+ CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort];
+#endif
+ return context;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
new file mode 100644
index 0000000000..ef55aa44c4
--- /dev/null
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp
+// and many other. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qt_mac_p.h>
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qwidget.h>
+#include <qevent.h>
+#include <qhash.h>
+#include <qlabel.h>
+#include <qpointer.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qstylepainter.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <private/qeffects_p.h>
+#include <qtextdocument.h>
+#include <qdebug.h>
+#include <qpoint.h>
+#include "private/qt_mac_p.h"
+
+#ifdef Q_WS_MAC32
+typedef struct _NSPoint NSPoint; // Just redefine here so I don't have to pull in all of Cocoa.
+#else
+typedef struct CGPoint NSPoint;
+#endif
+
+QT_BEGIN_NAMESPACE
+Qt::MouseButtons qt_mac_get_buttons(int buttons);
+Qt::MouseButton qt_mac_get_button(EventMouseButton button);
+void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0);
+bool macWindowIsTextured(void * /*OSWindowRef*/ window);
+void macWindowToolbarShow(const QWidget *widget, bool show );
+void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef );
+bool macWindowToolbarVisible( void * /*OSWindowRef*/ window );
+void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow );
+void macWindowFlush(void * /*OSWindowRef*/ window);
+struct HIContentBorderMetrics;
+void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics);
+void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm);
+void qt_mac_update_mouseTracking(QWidget *widget);
+OSStatus qt_mac_drawCGImage(CGContextRef cg, const CGRect *inbounds, CGImageRef);
+bool qt_mac_checkForNativeSizeGrip(const QWidget *widget);
+void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent);
+#ifdef QT_MAC_USE_COCOA
+bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent);
+#endif
+bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent);
+void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent);
+void qt_mac_dispatchNCMouseMessage(void */* NSWindow* */eventWindow, void */* NSEvent* */mouseEvent,
+ QWidget *widgetToGetEvent, bool &leftButtonIsRightButton);
+bool qt_mac_handleMouseEvent(void * /*QCocoaView * */view, void * /*NSEvent * */event, QEvent::Type eventType, Qt::MouseButton button);
+bool qt_mac_handleTabletEvent(void * /*QCocoaView * */view, void * /*NSEvent * */event);
+inline QApplication *qAppInstance() { return static_cast<QApplication *>(QCoreApplication::instance()); }
+struct ::TabletProximityRec;
+void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec);
+Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags);
+inline int flipYCoordinate(int y)
+{
+ return QApplication::desktop()->screenGeometry(0).height() - y;
+}
+
+inline qreal flipYCoordinate(qreal y)
+{
+ return QApplication::desktop()->screenGeometry(0).height() - y;
+}
+
+QPointF flipPoint(const NSPoint &p);
+NSPoint flipPoint(const QPoint &p);
+NSPoint flipPoint(const QPointF &p);
+
+QStringList qt_mac_NSArrayToQStringList(void *nsarray);
+void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list);
+
+void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow);
+
+#ifdef __OBJC__
+inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist)
+{ return reinterpret_cast<NSMutableArray *>(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); }
+
+inline QString qt_mac_NSStringToQString(const NSString *nsstr)
+{ return QCFString::toQString(reinterpret_cast<const CFStringRef>(nsstr)); }
+
+inline NSString *qt_mac_QStringToNSString(const QString &qstr)
+{ return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; }
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_gui_pch.h b/src/gui/kernel/qt_gui_pch.h
new file mode 100644
index 0000000000..9ce1a9281f
--- /dev/null
+++ b/src/gui/kernel/qt_gui_pch.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * This is a precompiled header file for use in Xcode / Mac GCC /
+ * GCC >= 3.4 / VC to greatly speed the building of Qt. It may also be
+ * of use to people developing their own project, but it is probably
+ * better to define your own header. Use of this header is currently
+ * UNSUPPORTED.
+ */
+
+// from corelib/global/qt_pch.h
+#if defined __cplusplus
+#include <qglobal.h>
+
+
+#ifdef Q_WS_WIN
+# define _POSIX_
+# include <limits.h>
+# undef _POSIX_
+#endif
+
+#include <qcoreapplication.h>
+#include <qlist.h>
+#include <qvariant.h> // All moc genereated code has this include
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qcursor.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <qimage.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <stdlib.h>
+
+#endif
diff --git a/src/gui/kernel/qt_mac.cpp b/src/gui/kernel/qt_mac.cpp
new file mode 100644
index 0000000000..b462b13480
--- /dev/null
+++ b/src/gui/kernel/qt_mac.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+#include <private/qt_mac_p.h>
+#include <private/qpixmap_mac_p.h>
+#include <private/qnativeimage_p.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+#ifdef QT_MAC_USE_COCOA
+static CTFontRef CopyCTThemeFont(ThemeFontID themeID)
+{
+ CTFontUIFontType ctID = HIThemeGetUIFontType(themeID);
+ return CTFontCreateUIFontForLanguage(ctID, 0, 0);
+}
+#endif
+
+QFont qfontForThemeFont(ThemeFontID themeID)
+{
+#ifndef QT_MAC_USE_COCOA
+ static const ScriptCode Script = smRoman;
+ Str255 f_name;
+ SInt16 f_size;
+ Style f_style;
+ GetThemeFont(themeID, Script, f_name, &f_size, &f_style);
+ extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
+ return QFont(qt_mac_from_pascal_string(f_name), f_size,
+ (f_style & ::bold) ? QFont::Bold : QFont::Normal,
+ (bool)(f_style & ::italic));
+#else
+ QCFType<CTFontRef> ctfont = CopyCTThemeFont(themeID);
+ QString familyName = QCFString(CTFontCopyFamilyName(ctfont));
+ QCFType<CFDictionaryRef> dict = CTFontCopyTraits(ctfont);
+ CFNumberRef num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontWeightTrait));
+ float fW;
+ CFNumberGetValue(num, kCFNumberFloat32Type, &fW);
+ QFont::Weight wght = fW > 0. ? QFont::Bold : QFont::Normal;
+ num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontSlantTrait));
+ CFNumberGetValue(num, kCFNumberFloatType, &fW);
+ bool italic = (fW != 0.0);
+ return QFont(familyName, CTFontGetSize(ctfont), wght, italic);
+#endif
+}
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+static QColor qcolorFromCGColor(CGColorRef cgcolor)
+{
+ QColor pc;
+ CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
+ const CGFloat *components = CGColorGetComponents(cgcolor);
+ if (model == kCGColorSpaceModelRGB) {
+ pc.setRgbF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelCMYK) {
+ pc.setCmykF(components[0], components[1], components[2], components[3]);
+ } else {
+ // Colorspace we can't deal with.
+ qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
+ Q_ASSERT(false);
+ }
+ return pc;
+}
+
+static inline QColor leopardBrush(ThemeBrush brush)
+{
+ QCFType<CGColorRef> cgClr = 0;
+ HIThemeBrushCreateCGColor(brush, &cgClr);
+ return qcolorFromCGColor(cgClr);
+}
+#endif
+
+QColor qcolorForTheme(ThemeBrush brush)
+{
+#ifndef QT_MAC_USE_COCOA
+# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
+ return leopardBrush(brush);
+ } else
+# endif
+ {
+ RGBColor rgbcolor;
+ GetThemeBrushAsColor(brush, 32, true, &rgbcolor);
+ return QColor(rgbcolor.red / 256, rgbcolor.green / 256, rgbcolor.blue / 256);
+ }
+#else
+ return leopardBrush(brush);
+#endif
+}
+
+QColor qcolorForThemeTextColor(ThemeTextColor themeColor)
+{
+#ifndef QT_MAC_USE_COCOA
+ RGBColor c;
+ GetThemeTextColor(themeColor, 32, true, &c);
+ return QColor(c.red / 265, c.green / 256, c.blue / 256);
+#else
+ QNativeImage nativeImage(16,16, QNativeImage::systemFormat());
+ CGRect cgrect = CGRectMake(0, 0, 16, 16);
+ HIThemeSetTextFill(themeColor, 0, nativeImage.cg, kHIThemeOrientationNormal);
+ CGContextFillRect(nativeImage.cg, cgrect);
+ return QColor(nativeImage.image.pixel(0 , 0));
+#endif
+}
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h
new file mode 100644
index 0000000000..3aec23fcf3
--- /dev/null
+++ b/src/gui/kernel/qt_mac_p.h
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_MAC_P_H
+#define QT_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qmacdefines_mac.h"
+
+#ifdef __OBJC__
+#include <Cocoa/Cocoa.h>
+#endif
+
+#include <CoreServices/CoreServices.h>
+
+#include "QtCore/qglobal.h"
+#include "QtCore/qvariant.h"
+#include "QtCore/qmimedata.h"
+#include "QtCore/qpointer.h"
+#include "private/qcore_mac_p.h"
+
+
+#include "QtGui/qpainter.h"
+
+#include <Carbon/Carbon.h>
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+class QDragMoveEvent;
+
+/* Event masks */
+// internal Qt types
+
+ // Event class for our own Carbon events.
+#if defined(QT_NAMESPACE) && defined(QT_NAMESPACE_MAC_CRC)
+// Take the CRC we generated at configure time. This *may* result in a
+// collision with another value If that is the case, please change the value
+// here to something other than 'Cute'.
+const UInt32 kEventClassQt = QT_NAMESPACE_MAC_CRC;
+#else
+const UInt32 kEventClassQt = 'Cute';
+#endif
+
+enum {
+ //AE types
+ typeAEClipboardChanged = 1,
+ //types
+ typeQWidget = 1, /* QWidget * */
+ //params
+ kEventParamQWidget = 'qwid', /* typeQWidget */
+ //events
+ kEventQtRequestContext = 13,
+ kEventQtRequestMenubarUpdate = 14,
+ kEventQtRequestShowSheet = 17,
+ kEventQtRequestActivate = 18,
+ kEventQtRequestWindowChange = 20
+};
+
+// Simple class to manage short-lived regions
+class QMacSmartQuickDrawRegion
+{
+ RgnHandle qdRgn;
+ Q_DISABLE_COPY(QMacSmartQuickDrawRegion)
+public:
+ explicit QMacSmartQuickDrawRegion(RgnHandle rgn) : qdRgn(rgn) {}
+ ~QMacSmartQuickDrawRegion() {
+ extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp
+ qt_mac_dispose_rgn(qdRgn);
+ }
+ operator RgnHandle() {
+ return qdRgn;
+ }
+};
+
+class Q_GUI_EXPORT QMacCocoaAutoReleasePool
+{
+private:
+ void *pool;
+public:
+ QMacCocoaAutoReleasePool();
+ ~QMacCocoaAutoReleasePool();
+
+ inline void *handle() const { return pool; }
+};
+
+QString qt_mac_removeMnemonics(const QString &original); //implemented in qmacstyle_mac.cpp
+
+class Q_GUI_EXPORT QMacWindowChangeEvent
+{
+private:
+ static QList<QMacWindowChangeEvent*> *change_events;
+public:
+ QMacWindowChangeEvent() {
+ }
+ virtual ~QMacWindowChangeEvent() {
+ }
+ static inline void exec(bool ) {
+ }
+protected:
+ virtual void windowChanged() = 0;
+ virtual void flushWindowChanged() = 0;
+};
+
+class QMacCGContext
+{
+ CGContextRef context;
+public:
+ QMacCGContext(QPainter *p); //qpaintengine_mac.cpp
+ inline QMacCGContext() { context = 0; }
+ inline QMacCGContext(const QPaintDevice *pdev) {
+ extern CGContextRef qt_mac_cg_context(const QPaintDevice *);
+ context = qt_mac_cg_context(pdev);
+ }
+ inline QMacCGContext(CGContextRef cg, bool takeOwnership=false) {
+ context = cg;
+ if(!takeOwnership)
+ CGContextRetain(context);
+ }
+ inline QMacCGContext(const QMacCGContext &copy) : context(0) { *this = copy; }
+ inline ~QMacCGContext() {
+ if(context)
+ CGContextRelease(context);
+ }
+ inline bool isNull() const { return context; }
+ inline operator CGContextRef() { return context; }
+ inline QMacCGContext &operator=(const QMacCGContext &copy) {
+ if(context)
+ CGContextRelease(context);
+ context = copy.context;
+ CGContextRetain(context);
+ return *this;
+ }
+ inline QMacCGContext &operator=(CGContextRef cg) {
+ if(context)
+ CGContextRelease(context);
+ context = cg;
+ CGContextRetain(context); //we do not take ownership
+ return *this;
+ }
+};
+
+class QMacPasteboardMime;
+class QMimeData;
+
+class QMacPasteboard
+{
+ struct Promise {
+ Promise() : itemId(0), convertor(0) { }
+ Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
+ int itemId, offset;
+ QMacPasteboardMime *convertor;
+ QString mime;
+ QVariant data;
+ };
+ QList<Promise> promises;
+
+ OSPasteboardRef paste;
+ uchar mime_type;
+ mutable QPointer<QMimeData> mime;
+ mutable bool mac_mime_source;
+ static OSStatus promiseKeeper(OSPasteboardRef, PasteboardItemID, CFStringRef, void *);
+ void clear_helper();
+public:
+ QMacPasteboard(OSPasteboardRef p, uchar mime_type=0);
+ QMacPasteboard(uchar mime_type);
+ QMacPasteboard(CFStringRef name=0, uchar mime_type=0);
+ ~QMacPasteboard();
+
+ bool hasFlavor(QString flavor) const;
+ bool hasOSType(int c_flavor) const;
+
+ OSPasteboardRef pasteBoard() const;
+ QMimeData *mimeData() const;
+ void setMimeData(QMimeData *mime);
+
+ QStringList formats() const;
+ bool hasFormat(const QString &format) const;
+ QVariant retrieveData(const QString &format, QVariant::Type) const;
+
+ void clear();
+ bool sync() const;
+};
+
+extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp
+
+extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.mm
+extern OSViewRef qt_mac_nativeview_for(const QWidget *); //qwidget_mac.mm
+
+#ifdef check
+# undef check
+#endif
+
+QFont qfontForThemeFont(ThemeFontID themeID);
+
+QColor qcolorForTheme(ThemeBrush brush);
+
+QColor qcolorForThemeTextColor(ThemeTextColor themeColor);
+
+struct QMacDndAnswerRecord {
+ QRect rect;
+ Qt::KeyboardModifiers modifiers;
+ Qt::MouseButtons buttons;
+ Qt::DropAction lastAction;
+ void clear() {
+ rect = QRect();
+ modifiers = Qt::NoModifier;
+ buttons = Qt::NoButton;
+ lastAction = Qt::IgnoreAction;
+ }
+};
+extern QMacDndAnswerRecord qt_mac_dnd_answer_rec;
+void qt_mac_copy_answer_rect(const QDragMoveEvent &event);
+bool qt_mac_mouse_inside_answer_rect(QPoint mouse);
+
+QT_END_NAMESPACE
+
+#endif // QT_MAC_P_H
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
new file mode 100644
index 0000000000..563b7e96e3
--- /dev/null
+++ b/src/gui/kernel/qt_x11_p.h
@@ -0,0 +1,723 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_X11_P_H
+#define QT_X11_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qwindowdefs.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qvariant.h"
+
+// the following is necessary to work around breakage in many versions
+// of XFree86's Xlib.h still in use
+// ### which versions?
+#if defined(_XLIB_H_) // crude hack, but...
+#error "cannot include <X11/Xlib.h> before this file"
+#endif
+#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback
+#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback
+#define XSetIMValues qt_XSetIMValues
+#include <X11/Xlib.h>
+#undef XRegisterIMInstantiateCallback
+#undef XUnregisterIMInstantiateCallback
+#undef XSetIMValues
+
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#ifdef index
+# undef index
+#endif
+#ifdef rindex
+# undef rindex
+#endif
+#include <X11/Xatom.h>
+
+//#define QT_NO_SHAPE
+#ifdef QT_NO_SHAPE
+# define XShapeCombineRegion(a,b,c,d,e,f,g)
+# define XShapeCombineMask(a,b,c,d,e,f,g)
+#else
+# include <X11/extensions/shape.h>
+#endif // QT_NO_SHAPE
+
+
+#if !defined (QT_NO_TABLET)
+# include <X11/extensions/XInput.h>
+#if defined (Q_OS_IRIX)
+# include <X11/extensions/SGIMisc.h>
+# include <wacom.h>
+#endif
+#endif // QT_NO_TABLET
+
+
+// #define QT_NO_XINERAMA
+#ifndef QT_NO_XINERAMA
+# if 0 // ### Xsun, but how to detect it?
+// Xinerama is only supported in Solaris 7 with patches 107648/108376 and
+// Solaris 8 or above which introduce the X11R6.4 Xserver.
+// To switch the Xinerama functionality on, you need to add the "+xinerama"
+// argument to the Xsun start line.
+// At least Solaris 7 and 8 are missing Xinerama system headers and function
+// declarations (bug 4284701).
+// The Xinerama API is not documented. In theory it could change but it
+// probably won't because Sun are using it in at least dtlogin (bug 4221829).
+extern "C" Bool XPanoramiXQueryExtension(
+ Display*,
+ int*,
+ int*
+);
+extern "C" Status XPanoramiXQueryVersion(
+ Display*,
+ int*,
+ int*
+);
+extern "C" Status XPanoramiXGetState(
+ Display*,
+ Drawable,
+ XPanoramiXInfo*
+);
+extern "C" Status XPanoramiXGetScreenCount(
+ Display *,
+ Drawable,
+ XPanoramiXInfo*
+);
+extern "C" Status XPanoramiXGetScreenSize(
+ Display*,
+ Drawable,
+ int,
+ XPanoramiXInfo*
+);
+# else // XFree86
+// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3).
+extern "C" {
+# include <X11/extensions/Xinerama.h>
+}
+# endif
+#endif // QT_NO_XINERAMA
+
+// #define QT_NO_XRANDR
+#ifndef QT_NO_XRANDR
+# include <X11/extensions/Xrandr.h>
+#endif // QT_NO_XRANDR
+
+// #define QT_NO_XRENDER
+#ifndef QT_NO_XRENDER
+# include <X11/extensions/Xrender.h>
+#endif // QT_NO_XRENDER
+
+// #define QT_NO_XKB
+#ifndef QT_NO_XKB
+# include <X11/XKBlib.h>
+#endif // QT_NO_XKB
+
+
+#if !defined(XlibSpecificationRelease)
+# define X11R4
+typedef char *XPointer;
+#else
+# undef X11R4
+#endif
+
+// #define QT_NO_XIM
+#if defined(X11R4)
+// X11R4 does not have XIM
+#define QT_NO_XIM
+#elif defined(Q_OS_OSF) && (XlibSpecificationRelease < 6)
+// broken in Xlib up to OSF/1 3.2
+#define QT_NO_XIM
+#elif defined(Q_OS_AIX)
+// broken in Xlib up to what version of AIX?
+#define QT_NO_XIM
+#elif defined(QT_NO_DEBUG) && defined(Q_OS_IRIX)
+// XmbLookupString broken on IRIX
+// XCreateIC broken when compiling -64 on IRIX 6.5.2
+#define QT_NO_XIM
+#elif defined(Q_OS_HPUX) && defined(__LP64__)
+// XCreateIC broken when compiling 64-bit ELF on HP-UX 11.0
+#define QT_NO_XIM
+#elif defined(Q_OS_SCO)
+// ### suggested by user...
+// ### #define QT_NO_XIM
+#endif // QT_NO_XIM
+
+#ifndef QT_NO_XFIXES
+typedef Bool (*PtrXFixesQueryExtension)(Display *, int *, int *);
+typedef Status (*PtrXFixesQueryVersion)(Display *, int *, int *);
+typedef void (*PtrXFixesSetCursorName)(Display *dpy, Cursor cursor, const char *name);
+typedef void (*PtrXFixesSelectSelectionInput)(Display *dpy, Window win, Atom selection, unsigned long eventMask);
+#endif // QT_NO_XFIXES
+
+#ifndef QT_NO_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+typedef Cursor (*PtrXcursorLibraryLoadCursor)(Display *, const char *);
+#endif // QT_NO_XCURSOR
+
+#ifndef QT_NO_XINERAMA
+typedef Bool (*PtrXineramaQueryExtension)(Display *dpy, int *event_base, int *error_base);
+typedef Bool (*PtrXineramaIsActive)(Display *dpy);
+typedef XineramaScreenInfo *(*PtrXineramaQueryScreens)(Display *dpy, int *number);
+#endif // QT_NO_XINERAMA
+
+#ifndef QT_NO_XRANDR
+typedef void (*PtrXRRSelectInput)(Display *, Window, int);
+typedef int (*PtrXRRUpdateConfiguration)(XEvent *);
+typedef int (*PtrXRRRootToScreen)(Display *, Window);
+typedef Bool (*PtrXRRQueryExtension)(Display *, int *, int *);
+#endif // QT_NO_XRANDR
+
+#ifndef QT_NO_XINPUT
+typedef int (*PtrXCloseDevice)(Display *, XDevice *);
+typedef XDeviceInfo* (*PtrXListInputDevices)(Display *, int *);
+typedef XDevice* (*PtrXOpenDevice)(Display *, XID);
+typedef void (*PtrXFreeDeviceList)(XDeviceInfo *);
+typedef int (*PtrXSelectExtensionEvent)(Display *, Window, XEventClass *, int);
+#endif // QT_NO_XINPUT
+
+/*
+ * Solaris patch 108652-47 and higher fixes crases in
+ * XRegisterIMInstantiateCallback, but the function doesn't seem to
+ * work.
+ *
+ * Instead, we disabled R6 input, and open the input method
+ * immediately at application start.
+ */
+#if !defined(QT_NO_XIM) && (XlibSpecificationRelease >= 6) && \
+ !defined(Q_OS_SOLARIS)
+#define USE_X11R6_XIM
+
+//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback
+//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2.
+//######### Many old X11R6 header files lack XSetIMValues.
+//######### Therefore, we have to declare these functions ourselves.
+
+extern "C" Bool XRegisterIMInstantiateCallback(
+ Display*,
+ struct _XrmHashBucketRec*,
+ char*,
+ char*,
+ XIMProc, //XFree86 has XIDProc, which has to be wrong
+ XPointer
+);
+
+extern "C" Bool XUnregisterIMInstantiateCallback(
+ Display*,
+ struct _XrmHashBucketRec*,
+ char*,
+ char*,
+ XIMProc, //XFree86 has XIDProc, which has to be wrong
+ XPointer
+);
+
+extern "C" char *XSetIMValues(XIM /* im */, ...);
+
+#endif
+
+#ifndef QT_NO_FONTCONFIG
+#include <fontconfig/fontconfig.h>
+#endif
+
+#ifndef QT_NO_XIM
+// some platforms (eg. Solaris 2.51) don't have these defines in Xlib.h
+#ifndef XNResetState
+#define XNResetState "resetState"
+#endif
+#ifndef XIMPreserveState
+#define XIMPreserveState (1L<<1)
+#endif
+#endif
+
+
+#ifndef X11R4
+# include <X11/Xlocale.h>
+#endif // X11R4
+
+
+#ifndef QT_NO_MITSHM
+# include <X11/extensions/XShm.h>
+#endif // QT_NO_MITSHM
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+
+struct QX11InfoData {
+ uint ref;
+ int screen;
+ int dpiX;
+ int dpiY;
+ int depth;
+ int cells;
+ Colormap colormap;
+ Visual *visual;
+ bool defaultColormap;
+ bool defaultVisual;
+ int subpixel;
+};
+
+class QDrag;
+struct QXdndDropTransaction
+{
+ Time timestamp;
+ Window target;
+ Window proxy_target;
+ QWidget *targetWidget;
+ QWidget *embedding_widget;
+ QDrag *object;
+};
+
+class QMimeData;
+
+struct QX11Data;
+extern QX11Data *qt_x11Data;
+
+enum DesktopEnvironment {
+ DE_UNKNOWN,
+ DE_KDE,
+ DE_GNOME,
+ DE_CDE,
+ DE_4DWM
+};
+
+struct QX11Data
+{
+ static Qt::KeyboardModifiers translateModifiers(int s);
+
+ Window findClientWindow(Window, Atom, bool);
+
+ // from qclipboard_x11.cpp
+ bool clipboardWaitForEvent(Window win, int type, XEvent *event, int timeout);
+ bool clipboardReadProperty(Window win, Atom property, bool deleteProperty,
+ QByteArray *buffer, int *size, Atom *type, int *format, bool nullterm);
+ QByteArray clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm);
+
+ // from qdnd_x11.cpp
+ bool dndEnable(QWidget* w, bool on);
+ static void xdndSetup();
+ void xdndHandleEnter(QWidget *, const XEvent *, bool);
+ void xdndHandlePosition(QWidget *, const XEvent *, bool);
+ void xdndHandleStatus(QWidget *, const XEvent *, bool);
+ void xdndHandleLeave(QWidget *, const XEvent *, bool);
+ void xdndHandleDrop(QWidget *, const XEvent *, bool);
+ void xdndHandleFinished(QWidget *, const XEvent *, bool);
+ void xdndHandleSelectionRequest(const XSelectionRequestEvent *);
+ static bool xdndHandleBadwindow();
+ QByteArray xdndAtomToString(Atom a);
+ Atom xdndStringToAtom(const char *);
+
+ QString xdndMimeAtomToString(Atom a);
+ Atom xdndMimeStringToAtom(const QString &mimeType);
+ QStringList xdndMimeFormatsForAtom(Atom a);
+ bool xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat);
+ QList<Atom> xdndMimeAtomsForFormat(const QString &format);
+ QVariant xdndMimeConvertToFormat(Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding);
+ Atom xdndMimeAtomForFormat(const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding);
+
+ QList<QXdndDropTransaction> dndDropTransactions;
+
+ // from qmotifdnd_x11.cpp
+ void motifdndHandle(QWidget *, const XEvent *, bool);
+ void motifdndEnable(QWidget *, bool);
+ QVariant motifdndObtainData(const char *format);
+ QByteArray motifdndFormat(int n);
+ bool motifdnd_active;
+
+ Display *display;
+ char *displayName;
+ bool foreignDisplay;
+ // current focus model
+ enum {
+ FM_Unknown = -1,
+ FM_Other = 0,
+ FM_PointerRoot = 1
+ };
+ int focus_model;
+
+ // true if Qt is compiled w/ RANDR support and RANDR is supported on the connected Display
+ bool use_xrandr;
+ int xrandr_major;
+ int xrandr_eventbase;
+ int xrandr_errorbase;
+
+ // true if Qt is compiled w/ RENDER support and RENDER is supported on the connected Display
+ bool use_xrender;
+ int xrender_major;
+ int xrender_version;
+
+ // true if Qt is compiled w/ XFIXES support and XFIXES is supported on the connected Display
+ bool use_xfixes;
+ int xfixes_major;
+ int xfixes_eventbase;
+ int xfixes_errorbase;
+
+#ifndef QT_NO_XFIXES
+ PtrXFixesQueryExtension ptrXFixesQueryExtension;
+ PtrXFixesQueryVersion ptrXFixesQueryVersion;
+ PtrXFixesSetCursorName ptrXFixesSetCursorName;
+ PtrXFixesSelectSelectionInput ptrXFixesSelectSelectionInput;
+#endif
+
+#ifndef QT_NO_XINPUT
+ PtrXCloseDevice ptrXCloseDevice;
+ PtrXListInputDevices ptrXListInputDevices;
+ PtrXOpenDevice ptrXOpenDevice;
+ PtrXFreeDeviceList ptrXFreeDeviceList;
+ PtrXSelectExtensionEvent ptrXSelectExtensionEvent;
+#endif // QT_NO_XINPUT
+
+
+ // true if Qt is compiled w/ MIT-SHM support and MIT-SHM is supported on the connected Display
+ bool use_mitshm;
+ int mitshm_major;
+
+ // true if Qt is compiled w/ Tablet support and we have a tablet.
+ bool use_xinput;
+ int xinput_major;
+ int xinput_eventbase;
+ int xinput_errorbase;
+
+ QList<QWidget *> deferred_map;
+ struct ScrollInProgress {
+ long id;
+ QWidget* scrolled_widget;
+ int dx, dy;
+ };
+ long sip_serial;
+ QList<ScrollInProgress> sip_list;
+
+ // window managers list of supported "stuff"
+ Atom *net_supported_list;
+ // list of virtual root windows
+ Window *net_virtual_root_list;
+ // client leader window
+ Window wm_client_leader;
+
+ QX11InfoData *screens;
+ Visual **argbVisuals;
+ Colormap *argbColormaps;
+ int screenCount;
+ int defaultScreen;
+
+ Time time;
+ Time userTime;
+
+ QString default_im;
+
+ // starts to ignore bad window errors from X
+ static inline void ignoreBadwindow() {
+ qt_x11Data->ignore_badwindow = true;
+ qt_x11Data->seen_badwindow = false;
+ }
+
+ // ends ignoring bad window errors and returns whether an error had happened.
+ static inline bool badwindow() {
+ qt_x11Data->ignore_badwindow = false;
+ return qt_x11Data->seen_badwindow;
+ }
+
+ bool ignore_badwindow;
+ bool seen_badwindow;
+
+ // options
+ int visual_class;
+ int visual_id;
+ int color_count;
+ bool custom_cmap;
+
+ // outside visual/colormap
+ Visual *visual;
+ Colormap colormap;
+
+#ifndef QT_NO_XRENDER
+ enum { solid_fill_count = 16 };
+ struct SolidFills {
+ XRenderColor color;
+ int screen;
+ Picture picture;
+ } solid_fills[solid_fill_count];
+ enum { pattern_fill_count = 16 };
+ struct PatternFills {
+ XRenderColor color;
+ XRenderColor bg_color;
+ int screen;
+ int style;
+ bool opaque;
+ Picture picture;
+ } pattern_fills[pattern_fill_count];
+ Picture getSolidFill(int screen, const QColor &c);
+ XRenderColor preMultiply(const QColor &c);
+#endif
+
+ bool has_fontconfig;
+ qreal fc_scale;
+ bool fc_antialias;
+ int fc_hint_style;
+
+ char *startupId;
+ char *originalStartupId;
+
+ DesktopEnvironment desktopEnvironment;
+
+ /* Warning: if you modify this list, modify the names of atoms in qapplication_x11.cpp as well! */
+ enum X11Atom {
+ // window-manager <-> client protocols
+ WM_PROTOCOLS,
+ WM_DELETE_WINDOW,
+ WM_TAKE_FOCUS,
+ _NET_WM_PING,
+ _NET_WM_CONTEXT_HELP,
+
+ // ICCCM window state
+ WM_STATE,
+ WM_CHANGE_STATE,
+
+ // Session management
+ WM_CLIENT_LEADER,
+ WM_WINDOW_ROLE,
+ SM_CLIENT_ID,
+
+ // Clipboard
+ CLIPBOARD,
+ INCR,
+ TARGETS,
+ MULTIPLE,
+ TIMESTAMP,
+ CLIP_TEMPORARY,
+ _QT_SELECTION,
+ _QT_CLIPBOARD_SENTINEL,
+ _QT_SELECTION_SENTINEL,
+
+ RESOURCE_MANAGER,
+
+ _XSETROOT_ID,
+
+ _QT_SCROLL_DONE,
+ _QT_INPUT_ENCODING,
+
+ _MOTIF_WM_HINTS,
+
+ DTWM_IS_RUNNING,
+ KDE_FULL_SESSION,
+ KWIN_RUNNING,
+ KWM_RUNNING,
+ GNOME_BACKGROUND_PROPERTIES,
+ ENLIGHTENMENT_DESKTOP,
+ _SGI_DESKS_MANAGER,
+
+ // EWMH (aka NETWM)
+ _NET_SUPPORTED,
+ _NET_VIRTUAL_ROOTS,
+ _NET_WORKAREA,
+
+ _NET_MOVERESIZE_WINDOW,
+ _NET_WM_MOVERESIZE,
+
+ _NET_WM_NAME,
+ _NET_WM_ICON_NAME,
+ _NET_WM_ICON,
+
+ _NET_WM_PID,
+
+ _NET_WM_WINDOW_OPACITY,
+
+ _NET_WM_STATE,
+ _NET_WM_STATE_ABOVE,
+ _NET_WM_STATE_BELOW,
+ _NET_WM_STATE_FULLSCREEN,
+ _NET_WM_STATE_MAXIMIZED_HORZ,
+ _NET_WM_STATE_MAXIMIZED_VERT,
+ _NET_WM_STATE_MODAL,
+ _NET_WM_STATE_STAYS_ON_TOP,
+ _NET_WM_STATE_DEMANDS_ATTENTION,
+
+ _NET_WM_USER_TIME,
+ _NET_WM_USER_TIME_WINDOW,
+ _NET_WM_FULL_PLACEMENT,
+
+ _NET_WM_WINDOW_TYPE,
+ _NET_WM_WINDOW_TYPE_DESKTOP,
+ _NET_WM_WINDOW_TYPE_DOCK,
+ _NET_WM_WINDOW_TYPE_TOOLBAR,
+ _NET_WM_WINDOW_TYPE_MENU,
+ _NET_WM_WINDOW_TYPE_UTILITY,
+ _NET_WM_WINDOW_TYPE_SPLASH,
+ _NET_WM_WINDOW_TYPE_DIALOG,
+ _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
+ _NET_WM_WINDOW_TYPE_POPUP_MENU,
+ _NET_WM_WINDOW_TYPE_TOOLTIP,
+ _NET_WM_WINDOW_TYPE_NOTIFICATION,
+ _NET_WM_WINDOW_TYPE_COMBO,
+ _NET_WM_WINDOW_TYPE_DND,
+ _NET_WM_WINDOW_TYPE_NORMAL,
+ _KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
+
+ _KDE_NET_WM_FRAME_STRUT,
+
+ _NET_STARTUP_INFO,
+ _NET_STARTUP_INFO_BEGIN,
+
+ _NET_SUPPORTING_WM_CHECK,
+
+ _NET_WM_CM_S0,
+
+ _NET_SYSTEM_TRAY_VISUAL,
+
+ // Property formats
+ COMPOUND_TEXT,
+ TEXT,
+ UTF8_STRING,
+
+ // Xdnd
+ XdndEnter,
+ XdndPosition,
+ XdndStatus,
+ XdndLeave,
+ XdndDrop,
+ XdndFinished,
+ XdndTypelist,
+ XdndActionList,
+
+ XdndSelection,
+
+ XdndAware,
+ XdndProxy,
+
+ XdndActionCopy,
+ XdndActionLink,
+ XdndActionMove,
+ XdndActionPrivate,
+
+ // Motif DND
+ _MOTIF_DRAG_AND_DROP_MESSAGE,
+ _MOTIF_DRAG_INITIATOR_INFO,
+ _MOTIF_DRAG_RECEIVER_INFO,
+ _MOTIF_DRAG_WINDOW,
+ _MOTIF_DRAG_TARGETS,
+
+ XmTRANSFER_SUCCESS,
+ XmTRANSFER_FAILURE,
+
+ // Xkb
+ _XKB_RULES_NAMES,
+
+ // XEMBED
+ _XEMBED,
+ _XEMBED_INFO,
+
+ NPredefinedAtoms,
+
+ _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
+ NAtoms
+ };
+ Atom atoms[NAtoms];
+
+ bool isSupportedByWM(Atom atom);
+
+ bool compositingManagerRunning;
+
+#ifndef QT_NO_XCURSOR
+ PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor;
+#endif // QT_NO_XCURSOR
+
+#ifndef QT_NO_XINERAMA
+ PtrXineramaQueryExtension ptrXineramaQueryExtension;
+ PtrXineramaIsActive ptrXineramaIsActive;
+ PtrXineramaQueryScreens ptrXineramaQueryScreens;
+#endif // QT_NO_XINERAMA
+
+#ifndef QT_NO_XRANDR
+ PtrXRRSelectInput ptrXRRSelectInput;
+ PtrXRRUpdateConfiguration ptrXRRUpdateConfiguration;
+ PtrXRRRootToScreen ptrXRRRootToScreen;
+ PtrXRRQueryExtension ptrXRRQueryExtension;
+#endif // QT_NO_XRANDR
+};
+
+extern QX11Data *qt_x11Data;
+#define ATOM(x) qt_x11Data->atoms[QX11Data::x]
+#define X11 qt_x11Data
+
+// rename a couple of X defines to get rid of name clashes
+// resolve the conflict between X11's FocusIn and QEvent::FocusIn
+enum {
+ XFocusOut = FocusOut,
+ XFocusIn = FocusIn,
+ XKeyPress = KeyPress,
+ XKeyRelease = KeyRelease,
+ XNone = None,
+ XRevertToParent = RevertToParent,
+ XGrayScale = GrayScale,
+ XCursorShape = CursorShape
+};
+#undef FocusOut
+#undef FocusIn
+#undef KeyPress
+#undef KeyRelease
+#undef None
+#undef RevertToParent
+#undef GrayScale
+#undef CursorShape
+
+#ifdef FontChange
+#undef FontChange
+#endif
+
+Q_DECLARE_TYPEINFO(XPoint, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(XRectangle, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(XChar2b, Q_PRIMITIVE_TYPE);
+#ifndef QT_NO_XRENDER
+Q_DECLARE_TYPEINFO(XGlyphElt32, Q_PRIMITIVE_TYPE);
+#endif
+
+
+QT_END_NAMESPACE
+
+#endif // QT_X11_P_H
diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp
new file mode 100644
index 0000000000..15a3dd24e2
--- /dev/null
+++ b/src/gui/kernel/qtooltip.cpp
@@ -0,0 +1,609 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef Q_WS_MAC
+# include <private/qcore_mac_p.h>
+#endif
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <qhash.h>
+#include <qlabel.h>
+#include <qpointer.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qstylepainter.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <private/qeffects_p.h>
+#include <qtextdocument.h>
+#include <qdebug.h>
+#include <private/qstylesheetstyle_p.h>
+#ifndef QT_NO_TOOLTIP
+
+#ifdef Q_WS_MAC
+# include <private/qcore_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QToolTip
+
+ \brief The QToolTip class provides tool tips (balloon help) for any
+ widget.
+
+ \ingroup helpsystem
+ \mainclass
+
+ The tip is a short piece of text reminding the user of the
+ widget's function. It is drawn immediately below the given
+ position in a distinctive black-on-yellow color combination. The
+ tip can be any \l{QTextEdit}{rich text} formatted string.
+
+ Rich text displayed in a tool tip is implicitly word-wrapped unless
+ specified differently with \c{<p style='white-space:pre'>}.
+
+ The simplest and most common way to set a widget's tool tip is by
+ calling its QWidget::setToolTip() function.
+
+ It is also possible to show different tool tips for different
+ regions of a widget, by using a QHelpEvent of type
+ QEvent::ToolTip. Intercept the help event in your widget's \l
+ {QWidget::}{event()} function and call QToolTip::showText() with
+ the text you want to display. The \l{widgets/tooltips}{Tooltips}
+ example illustrates this technique.
+
+ If you are calling QToolTip::hideText(), or QToolTip::showText()
+ with an empty string, as a result of a \l{QEvent::}{ToolTip}-event you
+ should also call \l{QEvent::}{ignore()} on the event, to signal
+ that you don't want to start any tooltip specific modes.
+
+ Note that, if you want to show tooltips in an item view, the
+ model/view architecture provides functionality to set an item's
+ tool tip; e.g., the QTableWidgetItem::setToolTip() function.
+ However, if you want to provide custom tool tips in an item view,
+ you must intercept the help event in the
+ QAbstractItemView::viewportEvent() function and handle it yourself.
+
+ The default tool tip color and font can be customized with
+ setPalette() and setFont(). When a tooltip is currently on
+ display, isVisible() returns true and text() the currently visible
+ text.
+
+ \note Tool tips use the inactive color group of QPalette, because tool
+ tips are not active windows.
+
+ \sa QWidget::toolTip, QAction::toolTip, {Tool Tips Example}
+*/
+
+class QTipLabel : public QLabel
+{
+ Q_OBJECT
+public:
+ QTipLabel(const QString &text, QWidget *w);
+ ~QTipLabel();
+ static QTipLabel *instance;
+
+ bool eventFilter(QObject *, QEvent *);
+
+ QBasicTimer hideTimer;
+ bool fadingOut;
+
+ void reuseTip(const QString &text);
+ void hideTip();
+ void hideTipImmediately();
+ void setTipRect(QWidget *w, const QRect &r);
+ void restartHideTimer();
+ bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
+ void placeTip(const QPoint &pos, QWidget *w);
+
+ static int getTipScreen(const QPoint &pos, QWidget *w);
+protected:
+ void timerEvent(QTimerEvent *e);
+ void paintEvent(QPaintEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void resizeEvent(QResizeEvent *e);
+
+#ifndef QT_NO_STYLE_STYLESHEET
+public slots:
+ /** \internal
+ Cleanup the _q_stylesheet_parent propery.
+ */
+ void styleSheetParentDestroyed() {
+ setProperty("_q_stylesheet_parent", QVariant());
+ styleSheetParent = 0;
+ }
+
+private:
+ QWidget *styleSheetParent;
+#endif
+
+private:
+ QWidget *widget;
+ QRect rect;
+};
+
+QTipLabel *QTipLabel::instance = 0;
+
+QTipLabel::QTipLabel(const QString &text, QWidget *w)
+#ifndef QT_NO_STYLE_STYLESHEET
+ : QLabel(w, Qt::ToolTip), styleSheetParent(0), widget(0)
+#else
+ : QLabel(w, Qt::ToolTip), widget(0)
+#endif
+{
+ delete instance;
+ instance = this;
+ setForegroundRole(QPalette::ToolTipText);
+ setBackgroundRole(QPalette::ToolTipBase);
+ setPalette(QToolTip::palette());
+ ensurePolished();
+ setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
+ setFrameStyle(QFrame::NoFrame);
+ setAlignment(Qt::AlignLeft);
+ setIndent(1);
+ setWordWrap(Qt::mightBeRichText(text));
+ qApp->installEventFilter(this);
+ setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
+ setMouseTracking(true);
+ fadingOut = false;
+ reuseTip(text);
+}
+
+void QTipLabel::restartHideTimer()
+{
+ int time = 10000 + 40 * qMax(0, text().length()-100);
+ hideTimer.start(time, this);
+}
+
+void QTipLabel::reuseTip(const QString &text)
+{
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (styleSheetParent) {
+ disconnect(styleSheetParent, SIGNAL(destroyed()),
+ QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
+ styleSheetParent = 0;
+ }
+#endif
+
+ setText(text);
+ QFontMetrics fm(font());
+ QSize extra(1, 0);
+ // Make it look good with the default ToolTip font on Mac, which has a small descent.
+ if (fm.descent() == 2 && fm.ascent() >= 11)
+ ++extra.rheight();
+ resize(sizeHint() + extra);
+ restartHideTimer();
+}
+
+void QTipLabel::paintEvent(QPaintEvent *ev)
+{
+ QStylePainter p(this);
+ QStyleOptionFrame opt;
+ opt.init(this);
+ p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
+ p.end();
+
+ QLabel::paintEvent(ev);
+}
+
+void QTipLabel::resizeEvent(QResizeEvent *e)
+{
+ QStyleHintReturnMask frameMask;
+ QStyleOption option;
+ option.init(this);
+ if (style()->styleHint(QStyle::SH_ToolTip_Mask, &option, this, &frameMask))
+ setMask(frameMask.region);
+
+ QLabel::resizeEvent(e);
+}
+
+void QTipLabel::mouseMoveEvent(QMouseEvent *e)
+{
+ if (rect.isNull())
+ return;
+ QPoint pos = e->globalPos();
+ if (widget)
+ pos = widget->mapFromGlobal(pos);
+ if (!rect.contains(pos))
+ hideTip();
+ QLabel::mouseMoveEvent(e);
+}
+
+QTipLabel::~QTipLabel()
+{
+ instance = 0;
+}
+
+void QTipLabel::hideTip()
+{
+ hideTimer.start(300, this);
+}
+
+void QTipLabel::hideTipImmediately()
+{
+ close(); // to trigger QEvent::Close which stops the animation
+ deleteLater();
+}
+
+void QTipLabel::setTipRect(QWidget *w, const QRect &r)
+{
+ if (!rect.isNull() && !w)
+ qWarning("QToolTip::setTipRect: Cannot pass null widget if rect is set");
+ else{
+ widget = w;
+ rect = r;
+ }
+}
+
+void QTipLabel::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == hideTimer.timerId()){
+ hideTimer.stop();
+#if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS)
+ if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){
+ // Fade out tip on mac (makes it invisible).
+ // The tip will not be deleted until a new tip is shown.
+
+ // DRSWAT - Cocoa
+ macWindowFade(qt_mac_window_for(this));
+ QTipLabel::instance->fadingOut = true; // will never be false again.
+ }
+ else
+ hideTipImmediately();
+#else
+ hideTipImmediately();
+#endif
+ }
+}
+
+bool QTipLabel::eventFilter(QObject *o, QEvent *e)
+{
+ switch (e->type()) {
+#ifdef Q_WS_MAC
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: {
+ int key = static_cast<QKeyEvent *>(e)->key();
+ Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(e)->modifiers();
+ if (!(mody & Qt::KeyboardModifierMask)
+ && key != Qt::Key_Shift && key != Qt::Key_Control
+ && key != Qt::Key_Alt && key != Qt::Key_Meta)
+ hideTip();
+ break;
+ }
+#endif
+ case QEvent::Leave:
+ hideTip();
+ break;
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ case QEvent::Wheel:
+ hideTipImmediately();
+ break;
+
+ case QEvent::MouseMove:
+ if (o == widget && !rect.isNull() && !rect.contains(static_cast<QMouseEvent*>(e)->pos()))
+ hideTip();
+ default:
+ break;
+ }
+ return false;
+}
+
+int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w)
+{
+ if (QApplication::desktop()->isVirtualDesktop())
+ return QApplication::desktop()->screenNumber(pos);
+ else
+ return QApplication::desktop()->screenNumber(w);
+}
+
+void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
+{
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) {
+ //the stylesheet need to know the real parent
+ QTipLabel::instance->setProperty("_q_stylesheet_parent", qVariantFromValue(w));
+ //we force the style to be the QStyleSheetStyle, and force to clear the cache as well.
+ QTipLabel::instance->setStyleSheet(QLatin1String("/* */"));
+
+ // Set up for cleaning up this later...
+ QTipLabel::instance->styleSheetParent = w;
+ if (w) {
+ connect(w, SIGNAL(destroyed()),
+ QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
+ }
+ }
+#endif //QT_NO_STYLE_STYLESHEET
+
+
+#ifdef Q_WS_MAC
+ QRect screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w));
+#else
+ QRect screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
+#endif
+
+ QPoint p = pos;
+ p += QPoint(2,
+#ifdef Q_WS_WIN
+ 21
+#else
+ 16
+#endif
+ );
+ if (p.x() + this->width() > screen.x() + screen.width())
+ p.rx() -= 4 + this->width();
+ if (p.y() + this->height() > screen.y() + screen.height())
+ p.ry() -= 24 + this->height();
+ if (p.y() < screen.y())
+ p.setY(screen.y());
+ if (p.x() + this->width() > screen.x() + screen.width())
+ p.setX(screen.x() + screen.width() - this->width());
+ if (p.x() < screen.x())
+ p.setX(screen.x());
+ if (p.y() + this->height() > screen.y() + screen.height())
+ p.setY(screen.y() + screen.height() - this->height());
+ this->move(p);
+}
+
+bool QTipLabel::tipChanged(const QPoint &pos, const QString &text, QObject *o)
+{
+ if (QTipLabel::instance->text() != text)
+ return true;
+
+ if (o != widget)
+ return true;
+
+ if (!rect.isNull())
+ return !rect.contains(pos);
+ else
+ return false;
+}
+
+/*!
+ Shows \a text as a tool tip, with the global position \a pos as
+ the point of interest. The tool tip will be shown with a platform
+ specific offset from this point of interest.
+
+ If you specify a non-empty rect the tip will be hidden as soon
+ as you move your cursor out of this area.
+
+ The \a rect is in the coordinates of the widget you specify with
+ \a w. If the \a rect is not empty you must specify a widget.
+ Otherwise this argument can be 0 but it is used to determine the
+ appropriate screen on multi-head systems.
+
+ If \a text is empty the tool tip is hidden. If the text is the
+ same as the currently shown tooltip, the tip will \e not move.
+ You can force moving by first hiding the tip with an empty text,
+ and then showing the new tip at the new position.
+*/
+
+void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect)
+{
+ if (QTipLabel::instance){ // a tip does already exist
+ if (text.isEmpty()){ // empty text means hide current tip
+ QTipLabel::instance->hideTip();
+ return;
+ }
+ else if (!QTipLabel::instance->fadingOut){
+ // If the tip has changed, reuse the one
+ // that is showing (removes flickering)
+ QPoint localPos = pos;
+ if (w)
+ localPos = w->mapFromGlobal(pos);
+ if (QTipLabel::instance->tipChanged(localPos, text, w)){
+ QTipLabel::instance->reuseTip(text);
+ QTipLabel::instance->setTipRect(w, rect);
+ QTipLabel::instance->placeTip(pos, w);
+ }
+ return;
+ }
+ }
+
+ if (!text.isEmpty()){ // no tip can be reused, create new tip:
+#ifndef Q_WS_WIN
+ new QTipLabel(text, w); // sets QTipLabel::instance to itself
+#else
+ // On windows, we can't use the widget as parent otherwise the window will be
+ // raised when the tooltip will be shown
+ new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)));
+#endif
+ QTipLabel::instance->setTipRect(w, rect);
+ QTipLabel::instance->placeTip(pos, w);
+ QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label"));
+
+
+#if !defined(QT_NO_EFFECTS) && !defined(Q_WS_MAC)
+ if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip))
+ qFadeEffect(QTipLabel::instance);
+ else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip))
+ qScrollEffect(QTipLabel::instance);
+ else
+ QTipLabel::instance->show();
+#else
+ QTipLabel::instance->show();
+#endif
+ }
+}
+
+/*!
+ \overload
+
+ This is analogous to calling QToolTip::showText(\a pos, \a text, \a w, QRect())
+*/
+
+void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w)
+{
+ QToolTip::showText(pos, text, w, QRect());
+}
+
+
+/*!
+ \fn void QToolTip::hideText()
+ \since 4.2
+
+ Hides the tool tip. This is the same as calling showText() with an
+ empty string.
+
+ \sa showText()
+*/
+
+
+/*!
+ \since 4.4
+
+ Returns true if this tooltip is currently shown.
+
+ \sa showText()
+ */
+bool QToolTip::isVisible()
+{
+ return (QTipLabel::instance != 0 && QTipLabel::instance->isVisible());
+}
+
+/*!
+ \since 4.4
+
+ Returns the tooltip text, if a tooltip is visible, or an
+ empty string if a tooltip is not visible.
+ */
+QString QToolTip::text()
+{
+ if (QTipLabel::instance)
+ return QTipLabel::instance->text();
+ return QString();
+}
+
+
+Q_GLOBAL_STATIC(QPalette, tooltip_palette)
+
+/*!
+ Returns the palette used to render tooltips.
+
+ \note Tool tips use the inactive color group of QPalette, because tool
+ tips are not active windows.
+*/
+QPalette QToolTip::palette()
+{
+ return *tooltip_palette();
+}
+
+/*!
+ \since 4.2
+
+ Returns the font used to render tooltips.
+*/
+QFont QToolTip::font()
+{
+ return QApplication::font("QTipLabel");
+}
+
+/*!
+ \since 4.2
+
+ Sets the \a palette used to render tooltips.
+
+ \note Tool tips use the inactive color group of QPalette, because tool
+ tips are not active windows.
+*/
+void QToolTip::setPalette(const QPalette &palette)
+{
+ *tooltip_palette() = palette;
+ if (QTipLabel::instance)
+ QTipLabel::instance->setPalette(palette);
+}
+
+/*!
+ \since 4.2
+
+ Sets the \a font used to render tooltips.
+*/
+void QToolTip::setFont(const QFont &font)
+{
+ QApplication::setFont(font, "QTipLabel");
+}
+
+
+/*!
+ \fn void QToolTip::add(QWidget *widget, const QString &text)
+
+ Use QWidget::setToolTip() instead.
+
+ \oldcode
+ tip->add(widget, text);
+ \newcode
+ widget->setToolTip(text);
+ \endcode
+*/
+
+/*!
+ \fn void QToolTip::add(QWidget *widget, const QRect &rect, const QString &text)
+
+ Intercept the QEvent::ToolTip events in your widget's
+ QWidget::event() function and call QToolTip::showText() with the
+ text you want to display. The \l{widgets/tooltips}{Tooltips}
+ example illustrates this technique.
+*/
+
+/*!
+ \fn void QToolTip::remove(QWidget *widget)
+
+ Use QWidget::setToolTip() instead.
+
+ \oldcode
+ tip->remove(widget);
+ \newcode
+ widget->setToolTip("");
+ \endcode
+*/
+
+QT_END_NAMESPACE
+
+#include "qtooltip.moc"
+#endif // QT_NO_TOOLTIP
diff --git a/src/gui/kernel/qtooltip.h b/src/gui/kernel/qtooltip.h
new file mode 100644
index 0000000000..464a8adf06
--- /dev/null
+++ b/src/gui/kernel/qtooltip.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTOOLTIP_H
+#define QTOOLTIP_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_TOOLTIP
+
+class Q_GUI_EXPORT QToolTip
+{
+ QToolTip();
+public:
+ static void showText(const QPoint &pos, const QString &text, QWidget *w = 0);
+ static void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect);
+ static inline void hideText() { showText(QPoint(), QString()); }
+
+ static bool isVisible();
+ static QString text();
+
+ static QPalette palette();
+ static void setPalette(const QPalette &);
+ static QFont font();
+ static void setFont(const QFont &);
+#ifdef QT3_SUPPORT
+ static inline QT3_SUPPORT void add(QWidget *w, const QString &s) { w->setToolTip(s); }
+ static inline QT3_SUPPORT void add(QWidget *w, const QRect &, const QString &s)
+ { w->setToolTip(s); }
+ static inline QT3_SUPPORT void remove(QWidget *w) { w->setToolTip(QString()); }
+#endif
+};
+
+#endif // QT_NO_TOOLTIP
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTOOLTIP_H
diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp
new file mode 100644
index 0000000000..4024777bf3
--- /dev/null
+++ b/src/gui/kernel/qwhatsthis.cpp
@@ -0,0 +1,772 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwhatsthis.h"
+#ifndef QT_NO_WHATSTHIS
+#include "qpointer.h"
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qpixmap.h"
+#include "qpainter.h"
+#include "qtimer.h"
+#include "qhash.h"
+#include "qaction.h"
+#include "qcursor.h"
+#include "qbitmap.h"
+#include "qtextdocument.h"
+#include "../text/qtextdocumentlayout_p.h"
+#include "qtoolbutton.h"
+#include "qdebug.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#if defined(Q_WS_WIN)
+#include "qt_windows.h"
+#ifndef SPI_GETDROPSHADOW
+#define SPI_GETDROPSHADOW 0x1024
+#endif
+#endif
+#if defined(Q_WS_X11)
+#include "qx11info_x11.h"
+#include <qwidget.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWhatsThis
+ \brief The QWhatsThis class provides a simple description of any
+ widget, i.e. answering the question "What's This?".
+
+ \ingroup helpsystem
+ \mainclass
+
+ "What's This?" help is part of an application's online help
+ system, and provides users with information about the
+ functionality and usage of a particular widget. "What's This?"
+ help texts are typically longer and more detailed than \link
+ QToolTip tooltips\endlink, but generally provide less information
+ than that supplied by separate help windows.
+
+ QWhatsThis provides a single window with an explanatory text that
+ pops up when the user asks "What's This?". The default way for
+ users to ask the question is to move the focus to the relevant
+ widget and press Shift+F1. The help text appears immediately; it
+ goes away as soon as the user does something else.
+ (Note that if there is a shortcut for Shift+F1, this mechanism
+ will not work.) Some dialogs provide a "?" button that users can
+ click to enter "What's This?" mode; they then click the relevant
+ widget to pop up the "What's This?" window. It is also possible to
+ provide a a menu option or toolbar button to switch into "What's
+ This?" mode.
+
+ To add "What's This?" text to a widget or an action, you simply
+ call QWidget::setWhatsThis() or QAction::setWhatsThis().
+
+ The text can be either rich text or plain text. If you specify a
+ rich text formatted string, it will be rendered using the default
+ stylesheet, making it possible to embed images in the displayed
+ text. To be as fast as possible, the default stylesheet uses a
+ simple method to determine whether the text can be rendered as
+ plain text. See Qt::mightBeRichText() for details.
+
+ \snippet doc/src/snippets/whatsthis/whatsthis.cpp 0
+
+ An alternative way to enter "What's This?" mode is to call
+ createAction(), and add the returned QAction to either a menu or
+ a tool bar. By invoking this context help action (in the picture
+ below, the button with the arrow and question mark icon) the user
+ switches into "What's This?" mode. If they now click on a widget
+ the appropriate help text is shown. The mode is left when help is
+ given or when the user presses Esc.
+
+ \img whatsthis.png
+
+ You can enter "What's This?" mode programmatically with
+ enterWhatsThisMode(), check the mode with inWhatsThisMode(), and
+ return to normal mode with leaveWhatsThisMode().
+
+ If you want to control the "What's This?" behavior of a widget
+ manually see Qt::WA_CustomWhatsThis.
+
+ It is also possible to show different help texts for different
+ regions of a widget, by using a QHelpEvent of type
+ QEvent::WhatsThis. Intercept the help event in your widget's
+ QWidget::event() function and call QWhatsThis::showText() with the
+ text you want to display for the position specified in
+ QHelpEvent::pos(). If the text is rich text and the user clicks
+ on a link, the widget also receives a QWhatsThisClickedEvent with
+ the link's reference as QWhatsThisClickedEvent::href(). If a
+ QWhatsThisClickedEvent is handled (i.e. QWidget::event() returns
+ true), the help window remains visible. Call
+ QWhatsThis::hideText() to hide it explicitly.
+
+ \sa QToolTip
+*/
+
+extern void qDeleteInEventHandler(QObject *o);
+
+class QWhatsThat : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor);
+ ~QWhatsThat() ;
+
+ static QWhatsThat *instance;
+
+protected:
+ void showEvent(QShowEvent *e);
+ void mousePressEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent*);
+ void mouseMoveEvent(QMouseEvent*);
+ void keyPressEvent(QKeyEvent*);
+ void paintEvent(QPaintEvent*);
+
+private:
+ QPointer<QWidget>widget;
+ bool pressed;
+ QString text;
+ QTextDocument* doc;
+ QString anchor;
+ QPixmap background;
+};
+
+QWhatsThat *QWhatsThat::instance = 0;
+
+// shadowWidth not const, for XP drop-shadow-fu turns it to 0
+static int shadowWidth = 6; // also used as '5' and '6' and even '8' below
+static const int vMargin = 8;
+static const int hMargin = 12;
+
+QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor)
+ : QWidget(parent, Qt::Popup),
+ widget(showTextFor), pressed(false), text(txt)
+{
+ delete instance;
+ instance = this;
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ if (parent)
+ setPalette(parent->palette());
+ setMouseTracking(true);
+ setFocusPolicy(Qt::StrongFocus);
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::ArrowCursor);
+#endif
+
+ QRect r;
+ doc = 0;
+ if (Qt::mightBeRichText(text)) {
+ doc = new QTextDocument();
+ doc->setUndoRedoEnabled(false);
+ doc->setDefaultFont(QApplication::font(this));
+#ifdef QT_NO_TEXTHTMLPARSER
+ doc->setPlainText(text);
+#else
+ doc->setHtml(text);
+#endif
+ doc->setUndoRedoEnabled(false);
+ doc->adjustSize();
+ r.setTop(0);
+ r.setLeft(0);
+ r.setSize(doc->size().toSize());
+ }
+ else
+ {
+ int sw = QApplication::desktop()->width() / 3;
+ if (sw < 200)
+ sw = 200;
+ else if (sw > 300)
+ sw = 300;
+
+ r = fontMetrics().boundingRect(0, 0, sw, 1000,
+ Qt::AlignLeft + Qt::AlignTop
+ + Qt::TextWordWrap + Qt::TextExpandTabs,
+ text);
+ }
+#if defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) {
+ BOOL shadow;
+ SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
+ shadowWidth = shadow ? 0 : 6;
+ }
+#endif
+ resize(r.width() + 2*hMargin + shadowWidth, r.height() + 2*vMargin + shadowWidth);
+}
+
+QWhatsThat::~QWhatsThat()
+{
+ instance = 0;
+ if (doc)
+ delete doc;
+}
+
+void QWhatsThat::showEvent(QShowEvent *)
+{
+ background = QPixmap::grabWindow(QApplication::desktop()->internalWinId(),
+ x(), y(), width(), height());
+}
+
+void QWhatsThat::mousePressEvent(QMouseEvent* e)
+{
+ pressed = true;
+ if (e->button() == Qt::LeftButton && rect().contains(e->pos())) {
+ if (doc)
+ anchor = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
+ return;
+ }
+ close();
+}
+
+void QWhatsThat::mouseReleaseEvent(QMouseEvent* e)
+{
+ if (!pressed)
+ return;
+ if (widget && e->button() == Qt::LeftButton && doc && rect().contains(e->pos())) {
+ QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
+ QString href;
+ if (anchor == a)
+ href = a;
+ anchor.clear();
+ if (!href.isEmpty()) {
+ QWhatsThisClickedEvent e(href);
+ if (QApplication::sendEvent(widget, &e))
+ return;
+ }
+ }
+ close();
+}
+
+void QWhatsThat::mouseMoveEvent(QMouseEvent* e)
+{
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(e);
+#else
+ if (!doc)
+ return;
+ QString a = doc->documentLayout()->anchorAt(e->pos() - QPoint(hMargin, vMargin));
+ if (!a.isEmpty())
+ setCursor(Qt::PointingHandCursor);
+ else
+ setCursor(Qt::ArrowCursor);
+#endif
+}
+
+void QWhatsThat::keyPressEvent(QKeyEvent*)
+{
+ close();
+}
+
+void QWhatsThat::paintEvent(QPaintEvent*)
+{
+ bool drawShadow = true;
+#if defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) {
+ BOOL shadow;
+ SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
+ drawShadow = !shadow;
+ }
+#elif defined(Q_WS_MAC) || defined(Q_WS_QWS)
+ drawShadow = false; // never draw it on OS X or QWS, as we get it for free
+#endif
+
+ QRect r = rect();
+ r.adjust(0, 0, -1, -1);
+ if (drawShadow)
+ r.adjust(0, 0, -shadowWidth, -shadowWidth);
+ QPainter p(this);
+ p.drawPixmap(0, 0, background);
+ p.setPen(QPen(palette().toolTipText(), 0));
+ p.setBrush(palette().toolTipBase());
+ p.drawRect(r);
+ int w = r.width();
+ int h = r.height();
+ p.setPen(palette().brush(QPalette::Dark).color());
+ p.drawRect(1, 1, w-2, h-2);
+ if (drawShadow) {
+ p.setPen(palette().shadow().color());
+ p.drawPoint(w + 5, 6);
+ p.drawLine(w + 3, 6, w + 5, 8);
+ p.drawLine(w + 1, 6, w + 5, 10);
+ int i;
+ for(i=7; i < h; i += 2)
+ p.drawLine(w, i, w + 5, i + 5);
+ for(i = w - i + h; i > 6; i -= 2)
+ p.drawLine(i, h, i + 5, h + 5);
+ for(; i > 0 ; i -= 2)
+ p.drawLine(6, h + 6 - i, i + 5, h + 5);
+ }
+ r.adjust(0, 0, 1, 1);
+ p.setPen(palette().toolTipText().color());
+ r.adjust(hMargin, vMargin, -hMargin, -vMargin);
+
+ if (doc) {
+ p.translate(r.x(), r.y());
+ QRect rect = r;
+ rect.translate(-r.x(), -r.y());
+ p.setClipRect(rect);
+ QAbstractTextDocumentLayout::PaintContext context;
+ doc->documentLayout()->draw(&p, context);
+ }
+ else
+ {
+ p.drawText(r, Qt::AlignLeft + Qt::AlignTop + Qt::TextWordWrap + Qt::TextExpandTabs, text);
+ }
+}
+
+static const char * const button_image[] = {
+"16 16 3 1",
+" c None",
+"o c #000000",
+"a c #000080",
+"o aaaaa ",
+"oo aaa aaa ",
+"ooo aaa aaa",
+"oooo aa aa",
+"ooooo aa aa",
+"oooooo a aaa",
+"ooooooo aaa ",
+"oooooooo aaa ",
+"ooooooooo aaa ",
+"ooooo aaa ",
+"oo ooo ",
+"o ooo aaa ",
+" ooo aaa ",
+" ooo ",
+" ooo ",
+" ooo "};
+
+class QWhatsThisPrivate : public QObject
+{
+ public:
+ QWhatsThisPrivate();
+ ~QWhatsThisPrivate();
+ static QWhatsThisPrivate *instance;
+ bool eventFilter(QObject *, QEvent *);
+ QPointer<QAction> action;
+#ifdef QT3_SUPPORT
+ QPointer<QToolButton> button;
+#endif
+ static void say(QWidget *, const QString &, int x = 0, int y = 0);
+ static void notifyToplevels(QEvent *e);
+ bool leaveOnMouseRelease;
+};
+
+void QWhatsThisPrivate::notifyToplevels(QEvent *e)
+{
+ QWidgetList toplevels = QApplication::topLevelWidgets();
+ for (int i = 0; i < toplevels.count(); ++i) {
+ register QWidget *w = toplevels.at(i);
+ QApplication::sendEvent(w, e);
+ }
+}
+
+QWhatsThisPrivate *QWhatsThisPrivate::instance = 0;
+
+QWhatsThisPrivate::QWhatsThisPrivate()
+ : leaveOnMouseRelease(false)
+{
+ instance = this;
+ qApp->installEventFilter(this);
+
+ QPoint pos = QCursor::pos();
+ if (QWidget *w = QApplication::widgetAt(pos)) {
+ QHelpEvent e(QEvent::QueryWhatsThis, w->mapFromGlobal(pos), pos);
+ bool sentEvent = QApplication::sendEvent(w, &e);
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(sentEvent);
+#else
+ QApplication::setOverrideCursor((!sentEvent || !e.isAccepted())?
+ Qt::ForbiddenCursor:Qt::WhatsThisCursor);
+ } else {
+ QApplication::setOverrideCursor(Qt::WhatsThisCursor);
+#endif
+ }
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpStart);
+#endif
+}
+
+QWhatsThisPrivate::~QWhatsThisPrivate()
+{
+ if (action)
+ action->setChecked(false);
+#ifdef QT3_SUPPORT
+ if (button)
+ button->setChecked(false);
+#endif
+#ifndef QT_NO_CURSOR
+ QApplication::restoreOverrideCursor();
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::ContextHelpEnd);
+#endif
+ instance = 0;
+}
+
+bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e)
+{
+ if (!o->isWidgetType())
+ return false;
+ QWidget * w = static_cast<QWidget *>(o);
+ bool customWhatsThis = w->testAttribute(Qt::WA_CustomWhatsThis);
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (me->button() == Qt::RightButton || customWhatsThis)
+ return false;
+ QHelpEvent e(QEvent::WhatsThis, me->pos(), me->globalPos());
+ if (!QApplication::sendEvent(w, &e) || !e.isAccepted())
+ leaveOnMouseRelease = true;
+
+ } break;
+
+ case QEvent::MouseMove:
+ {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QHelpEvent e(QEvent::QueryWhatsThis, me->pos(), me->globalPos());
+ bool sentEvent = QApplication::sendEvent(w, &e);
+#ifdef QT_NO_CURSOR
+ Q_UNUSED(sentEvent);
+#else
+ QApplication::changeOverrideCursor((!sentEvent || !e.isAccepted())?
+ Qt::ForbiddenCursor:Qt::WhatsThisCursor);
+#endif
+ }
+ // fall through
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ if (leaveOnMouseRelease && e->type() == QEvent::MouseButtonRelease)
+ QWhatsThis::leaveWhatsThisMode();
+ if (static_cast<QMouseEvent*>(e)->button() == Qt::RightButton || customWhatsThis)
+ return false; // ignore RMB release
+ break;
+ case QEvent::KeyPress:
+ {
+ QKeyEvent* kev = (QKeyEvent*)e;
+
+ if (kev->key() == Qt::Key_Escape) {
+ QWhatsThis::leaveWhatsThisMode();
+ return true;
+ } else if (customWhatsThis) {
+ return false;
+ } else if (kev->key() == Qt::Key_Menu ||
+ (kev->key() == Qt::Key_F10 &&
+ kev->modifiers() == Qt::ShiftModifier)) {
+ // we don't react to these keys, they are used for context menus
+ return false;
+ } else if (kev->key() != Qt::Key_Shift && kev->key() != Qt::Key_Alt // not a modifier key
+ && kev->key() != Qt::Key_Control && kev->key() != Qt::Key_Meta) {
+ QWhatsThis::leaveWhatsThisMode();
+ }
+ } break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+class QWhatsThisAction: public QAction
+{
+ Q_OBJECT
+
+public:
+ explicit QWhatsThisAction(QObject* parent = 0);
+
+private slots:
+ void actionTriggered();
+};
+
+QWhatsThisAction::QWhatsThisAction(QObject *parent) : QAction(tr("What's This?"), parent)
+{
+#ifndef QT_NO_IMAGEFORMAT_XPM
+ QPixmap p((const char**)button_image);
+ setIcon(p);
+#endif
+ setCheckable(true);
+ connect(this, SIGNAL(triggered()), this, SLOT(actionTriggered()));
+#ifndef QT_NO_SHORTCUT
+ setShortcut(Qt::ShiftModifier + Qt::Key_F1);
+#endif
+}
+
+void QWhatsThisAction::actionTriggered()
+{
+ if (isChecked()) {
+ QWhatsThis::enterWhatsThisMode();
+ QWhatsThisPrivate::instance->action = this;
+ }
+}
+
+QWhatsThis::QWhatsThis()
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+
+ Sets the What's This text \a s for the widget \a w.
+
+ Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
+*/
+void QWhatsThis::add(QWidget *w, const QString &s)
+{
+ w->setWhatsThis(s);
+}
+
+/*!
+ \obsolete
+
+ Remove's the What's This text for the widget \a w.
+
+ Use QWidget::setWhatsThis() or QAction::setWhatsThis() instead.
+*/
+void QWhatsThis::remove(QWidget *w)
+{
+ w->setWhatsThis(QString());
+}
+
+class QWhatsThisButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ QWhatsThisButton(QWidget *p) : QToolButton(p) {
+ setCheckable(true);
+ QPixmap pix( const_cast<const char**>(button_image) );
+ setIcon( pix );
+ QObject::connect(this, SIGNAL(toggled(bool)), this, SLOT(whatToggled(bool)));
+ setAutoRaise(true);
+ setFocusPolicy(Qt::NoFocus);
+ }
+
+public slots:
+ void whatToggled(bool b) {
+ if (b) {
+ QWhatsThis::enterWhatsThisMode();
+ QWhatsThisPrivate::instance->button = this;
+ }
+ }
+};
+
+/*!
+ Returns a new "What's This?" QToolButton with the given \a
+ parent. To do this now, create your own QToolButton and a
+ QWhatsThis object and call the QWhatsThis object's showText()
+ function when the QToolButton is invoked.
+
+ Use createAction() instead.
+*/
+QToolButton * QWhatsThis::whatsThisButton(QWidget * parent)
+{
+ return new QWhatsThisButton(parent);
+}
+#endif
+
+/*!
+ This function switches the user interface into "What's This?"
+ mode. The user interface can be switched back into normal mode by
+ the user (e.g. by them clicking or pressing Esc), or
+ programmatically by calling leaveWhatsThisMode().
+
+ When entering "What's This?" mode, a QEvent of type
+ Qt::EnterWhatsThisMode is sent to all toplevel widgets.
+
+ \sa inWhatsThisMode() leaveWhatsThisMode()
+*/
+void QWhatsThis::enterWhatsThisMode()
+{
+ if (QWhatsThisPrivate::instance)
+ return;
+ (void) new QWhatsThisPrivate;
+ QEvent e(QEvent::EnterWhatsThisMode);
+ QWhatsThisPrivate::notifyToplevels(&e);
+ }
+
+/*!
+ Returns true if the user interface is in "What's This?" mode;
+ otherwise returns false.
+
+ \sa enterWhatsThisMode()
+*/
+bool QWhatsThis::inWhatsThisMode()
+{
+ return (QWhatsThisPrivate::instance != 0);
+}
+
+/*!
+ If the user interface is in "What's This?" mode, this function
+ switches back to normal mode; otherwise it does nothing.
+
+ When leaving "What's This?" mode, a QEvent of type
+ Qt::LeaveWhatsThisMode is sent to all toplevel widgets.
+
+ \sa enterWhatsThisMode() inWhatsThisMode()
+*/
+void QWhatsThis::leaveWhatsThisMode()
+{
+ delete QWhatsThisPrivate::instance;
+ QEvent e(QEvent::LeaveWhatsThisMode);
+ QWhatsThisPrivate::notifyToplevels(&e);
+}
+
+void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y)
+{
+ if (text.size() == 0)
+ return;
+ // make a fresh widget, and set it up
+ QWhatsThat *whatsThat = new QWhatsThat(
+ text,
+#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
+ QApplication::desktop()->screen(widget ? widget->x11Info().screen() : QCursor::x11Screen()),
+#else
+ 0,
+#endif
+ widget
+ );
+
+
+ // okay, now to find a suitable location
+
+ int scr = (widget ?
+ QApplication::desktop()->screenNumber(widget) :
+#if defined(Q_WS_X11) && !defined(QT_NO_CURSOR)
+ QCursor::x11Screen()
+#else
+ QApplication::desktop()->screenNumber(QPoint(x,y))
+#endif // Q_WS_X11
+ );
+ QRect screen = QApplication::desktop()->screenGeometry(scr);
+
+ int w = whatsThat->width();
+ int h = whatsThat->height();
+ int sx = screen.x();
+ int sy = screen.y();
+
+ // first try locating the widget immediately above/below,
+ // with nice alignment if possible.
+ QPoint pos;
+ if (widget)
+ pos = widget->mapToGlobal(QPoint(0,0));
+
+ if (widget && w > widget->width() + 16)
+ x = pos.x() + widget->width()/2 - w/2;
+ else
+ x = x - w/2;
+
+ // squeeze it in if that would result in part of what's this
+ // being only partially visible
+ if (x + w + shadowWidth > sx+screen.width())
+ x = (widget? (qMin(screen.width(),
+ pos.x() + widget->width())
+ ) : screen.width())
+ - w;
+
+ if (x < sx)
+ x = sx;
+
+ if (widget && h > widget->height() + 16) {
+ y = pos.y() + widget->height() + 2; // below, two pixels spacing
+ // what's this is above or below, wherever there's most space
+ if (y + h + 10 > sy+screen.height())
+ y = pos.y() + 2 - shadowWidth - h; // above, overlap
+ }
+ y = y + 2;
+
+ // squeeze it in if that would result in part of what's this
+ // being only partially visible
+ if (y + h + shadowWidth > sy+screen.height())
+ y = (widget ? (qMin(screen.height(),
+ pos.y() + widget->height())
+ ) : screen.height())
+ - h;
+ if (y < sy)
+ y = sy;
+
+ whatsThat->move(x, y);
+ whatsThat->show();
+ whatsThat->grabKeyboard();
+}
+
+/*!
+ Shows \a text as a "What's This?" window, at global position \a
+ pos. The optional widget argument, \a w, is used to determine the
+ appropriate screen on multi-head systems.
+
+ \sa hideText()
+*/
+void QWhatsThis::showText(const QPoint &pos, const QString &text, QWidget *w)
+{
+ leaveWhatsThisMode();
+ QWhatsThisPrivate::say(w, text, pos.x(), pos.y());
+}
+
+/*!
+ If a "What's This?" window is showing, this destroys it.
+
+ \sa showText()
+*/
+void QWhatsThis::hideText()
+{
+ qDeleteInEventHandler(QWhatsThat::instance);
+}
+
+/*!
+ Returns a ready-made QAction, used to invoke "What's This?" context
+ help, with the given \a parent.
+
+ The returned QAction provides a convenient way to let users enter
+ "What's This?" mode.
+*/
+QAction *QWhatsThis::createAction(QObject *parent)
+{
+ return new QWhatsThisAction(parent);
+}
+
+QT_END_NAMESPACE
+
+#include "qwhatsthis.moc"
+
+#endif // QT_NO_WHATSTHIS
diff --git a/src/gui/kernel/qwhatsthis.h b/src/gui/kernel/qwhatsthis.h
new file mode 100644
index 0000000000..5011c54ae0
--- /dev/null
+++ b/src/gui/kernel/qwhatsthis.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWHATSTHIS_H
+#define QWHATSTHIS_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qcursor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_WHATSTHIS
+
+class QAction;
+#ifdef QT3_SUPPORT
+class QToolButton;
+#endif
+
+class Q_GUI_EXPORT QWhatsThis
+{
+ QWhatsThis();
+
+public:
+ static void enterWhatsThisMode();
+ static bool inWhatsThisMode();
+ static void leaveWhatsThisMode();
+
+ static void showText(const QPoint &pos, const QString &text, QWidget *w = 0);
+ static void hideText();
+
+ static QAction *createAction(QObject *parent = 0);
+
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT void add(QWidget *w, const QString &s);
+ static QT3_SUPPORT void remove(QWidget *);
+ static QT3_SUPPORT QToolButton *whatsThisButton(QWidget *parent);
+#endif
+};
+
+#endif // QT_NO_WHATSTHIS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWHATSTHIS_H
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
new file mode 100644
index 0000000000..06810e0947
--- /dev/null
+++ b/src/gui/kernel/qwidget.cpp
@@ -0,0 +1,11398 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qbrush.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qhash.h"
+#include "qlayout.h"
+#include "qmenu.h"
+#include "qmetaobject.h"
+#include "qpixmap.h"
+#include "qpointer.h"
+#include "qstack.h"
+#include "qstyle.h"
+#include "qstylefactory.h"
+#include "qvariant.h"
+#include "qwidget.h"
+#include "qstyleoption.h"
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
+#if defined(Q_WS_WIN)
+# include "qt_windows.h"
+#endif
+#ifdef Q_WS_MAC
+# include "qt_mac_p.h"
+# include "qt_cocoa_helpers_mac_p.h"
+#endif
+#if defined(Q_WS_QWS)
+# include "qwsdisplay_qws.h"
+# include "qwsmanager_qws.h"
+# include "qpaintengine.h" // for PorterDuff
+# include "private/qwindowsurface_qws_p.h"
+#endif
+#include "qpainter.h"
+#include "qtooltip.h"
+#include "qwhatsthis.h"
+#include "qdebug.h"
+#include "private/qstylesheetstyle_p.h"
+#include "private/qstyle_p.h"
+#include "private/qinputcontext_p.h"
+#include "qfileinfo.h"
+
+#if defined (Q_WS_WIN)
+# include <private/qwininputcontext_p.h>
+#endif
+
+#if defined(Q_WS_X11)
+# include <private/qpaintengine_x11_p.h>
+# include "qx11info_x11.h"
+#endif
+
+#include <private/qwindowsurface_p.h>
+#include <private/qbackingstore_p.h>
+#ifdef Q_WS_MAC
+# include <private/qpaintengine_mac_p.h>
+#endif
+#include <private/qpaintengine_raster_p.h>
+
+#include "qwidget_p.h"
+#include "qaction_p.h"
+#include "qlayout_p.h"
+#include "QtGui/qgraphicsproxywidget.h"
+#include "QtGui/qgraphicsscene.h"
+#include "private/qgraphicsproxywidget_p.h"
+#include "QtGui/qabstractscrollarea.h"
+#include "private/qabstractscrollarea_p.h"
+
+#include "private/qgraphicssystem_p.h"
+
+// widget/widget data creation count
+//#define QWIDGET_EXTRA_DEBUG
+//#define ALIEN_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_WS_QWS)
+static bool qt_enable_backingstore = true;
+#endif
+#ifdef Q_WS_X11
+// for compatibility with Qt 4.0
+Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable)
+{
+ qt_enable_backingstore = enable;
+}
+#endif
+
+static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
+{
+ return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
+ qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
+}
+
+static inline bool hasBackingStoreSupport()
+{
+#ifdef Q_WS_MAC
+ return QApplicationPrivate::graphicsSystem() != 0;
+#else
+ return true;
+#endif
+}
+
+/*!
+ \internal
+
+ Returns true if \a p or any of its parents enable the
+ Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and
+ QWidget::setParent() to determine whether it's necessary to embed the
+ widget into a QGraphicsProxyWidget or not.
+*/
+static inline bool bypassGraphicsProxyWidget(QWidget *p)
+{
+ while (p) {
+ if (p->windowFlags() & Qt::BypassGraphicsProxyWidget)
+ return true;
+ p = p->parentWidget();
+ }
+ return false;
+}
+
+#ifdef Q_WS_MAC
+# define QT_NO_PAINT_DEBUG
+#endif
+
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
+
+QWidgetPrivate::QWidgetPrivate(int version) :
+ QObjectPrivate(version), extra(0), focus_child(0)
+ ,layout(0), widgetItem(0)
+ ,leftmargin(0), topmargin(0), rightmargin(0), bottommargin(0)
+ ,leftLayoutItemMargin(0), topLayoutItemMargin(0), rightLayoutItemMargin(0)
+ ,bottomLayoutItemMargin(0)
+ ,fg_role(QPalette::NoRole)
+ ,bg_role(QPalette::NoRole)
+ ,hd(0)
+ ,dirty(0)
+ ,needsFlush(0)
+ ,dirtyOpaqueChildren(1)
+ ,isOpaque(0)
+ ,inDirtyList(0)
+ ,isScrolled(0)
+ ,isMoved(0)
+#ifdef Q_WS_WIN
+ ,noPaintOnScreen(0)
+#endif
+ ,inheritedFontResolveMask(0)
+ ,inheritedPaletteResolveMask(0)
+#if defined(Q_WS_X11)
+ ,picture(0)
+#endif
+#ifdef Q_WS_MAC
+ ,needWindowChange(0)
+ ,isGLWidget(0)
+#endif
+ ,polished(0)
+
+ , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
+ , redirectDev(0)
+{
+ if (!qApp) {
+ qFatal("QWidget: Must construct a QApplication before a QPaintDevice");
+ return;
+ }
+
+ if (version != QObjectPrivateVersion)
+ qFatal("Cannot mix incompatible Qt libraries");
+
+ isWidget = true;
+ memset(high_attributes, 0, sizeof(high_attributes));
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int count = 0;
+ qDebug() << "widgets" << ++count;
+#endif
+}
+
+
+QWidgetPrivate::~QWidgetPrivate()
+{
+ if (widgetItem)
+ widgetItem->wid = 0;
+
+ if (extra)
+ deleteExtra();
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface()
+{
+ Q_Q(QWidget);
+ if (QApplicationPrivate::graphicsSystem())
+ return QApplicationPrivate::graphicsSystem()->createWindowSurface(q);
+ return createDefaultWindowSurface_sys();
+}
+
+/*!
+ \internal
+ This is an internal function, you should never call this.
+
+ This function is called to focus associated input context. The
+ code intends to eliminate duplicate focus for the context even if
+ the context is shared between widgets
+
+ \sa QInputContext::setFocus()
+ */
+void QWidgetPrivate::focusInputContext()
+{
+#ifndef QT_NO_IM
+ Q_Q(QWidget);
+ QInputContext *qic = q->inputContext();
+ if (qic) {
+ if(qic->focusWidget() != q)
+ qic->setFocusWidget(q);
+ }
+#endif // QT_NO_IM
+}
+
+/*!
+ \internal
+*/
+void QWidgetPrivate::scrollChildren(int dx, int dy)
+{
+ Q_Q(QWidget);
+ if (q->children().size() > 0) { // scroll children
+ QPoint pd(dx, dy);
+ QObjectList childObjects = q->children();
+ for (int i = 0; i < childObjects.size(); ++i) { // move all children
+ QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
+ if (w && !w->isWindow()) {
+ QPoint oldp = w->pos();
+ QRect r(w->pos() + pd, w->size());
+ w->data->crect = r;
+#ifndef Q_WS_QWS
+ if (w->testAttribute(Qt::WA_WState_Created))
+ w->d_func()->setWSGeometry();
+#endif
+ w->d_func()->setDirtyOpaqueRegion();
+ QMoveEvent e(r.topLeft(), oldp);
+ QApplication::sendEvent(w, &e);
+ }
+ }
+ }
+}
+
+QInputContext *QWidgetPrivate::inputContext() const
+{
+#ifndef QT_NO_IM
+ if (ic)
+ return ic;
+#endif
+ return qApp->inputContext();
+}
+
+/*!
+ This function returns the QInputContext for this widget. By
+ default the input context is inherited from the widgets
+ parent. For toplevels it is inherited from QApplication.
+
+ You can override this and set a special input context for this
+ widget by using the setInputContext() method.
+
+ \sa setInputContext()
+*/
+QInputContext *QWidget::inputContext()
+{
+ Q_D(QWidget);
+ if (!testAttribute(Qt::WA_InputMethodEnabled))
+ return 0;
+
+ return d->inputContext();
+}
+
+/*!
+ This function sets the input context \a context
+ on this widget.
+
+ \sa inputContext()
+*/
+void QWidget::setInputContext(QInputContext *context)
+{
+ Q_D(QWidget);
+ if (!testAttribute(Qt::WA_InputMethodEnabled))
+ return;
+#ifndef QT_NO_IM
+ if (d->ic)
+ delete d->ic;
+ d->ic = context;
+#endif
+}
+
+
+/*!
+ This function can be called on the widget that currently has focus
+ to reset the input method operating on it.
+
+ \sa QInputContext, QInputContext::reset()
+*/
+void QWidget::resetInputContext()
+{
+ if (!hasFocus())
+ return;
+#ifndef QT_NO_IM
+ if (!d_func()->ic)
+ return;
+ QInputContext *qic = this->inputContext();
+ if( qic )
+ qic->reset();
+#endif // QT_NO_IM
+}
+
+#ifdef QT_KEYPAD_NAVIGATION
+QPointer<QWidget> QWidgetPrivate::editingWidget;
+
+/*!
+ Returns true if this widget currently has edit focus; otherwise false.
+
+ This feature is only available in Qt for Embedded Linux.
+
+ \sa setEditFocus(), QApplication::keypadNavigationEnabled()
+*/
+bool QWidget::hasEditFocus() const
+{
+ const QWidget* w = this;
+ while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
+ w = w->d_func()->extra->focus_proxy;
+ return QWidgetPrivate::editingWidget == w;
+}
+
+/*!
+ \fn void QWidget::setEditFocus(bool enable)
+
+ If \a enable is true, make this widget have edit focus, in which
+ case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
+ normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
+ change focus.
+
+ This feature is only available in Qt for Embedded Linux.
+
+ \sa hasEditFocus(), QApplication::keypadNavigationEnabled()
+*/
+void QWidget::setEditFocus(bool on)
+{
+ QWidget *f = this;
+ while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
+ f = f->d_func()->extra->focus_proxy;
+
+ if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
+ QWidgetPrivate::editingWidget->setEditFocus(false);
+
+ if (on && !f->hasFocus())
+ f->setFocus();
+
+ if ((!on && !QWidgetPrivate::editingWidget)
+ || (on && QWidgetPrivate::editingWidget == f)) {
+ return;
+ }
+
+ if (!on && QWidgetPrivate::editingWidget == f) {
+ QWidgetPrivate::editingWidget = 0;
+ QEvent event(QEvent::LeaveEditFocus);
+ QApplication::sendEvent(f, &event);
+ QApplication::sendEvent(f->style(), &event);
+ } else if (on) {
+ QWidgetPrivate::editingWidget = f;
+ QEvent event(QEvent::EnterEditFocus);
+ QApplication::sendEvent(f, &event);
+ QApplication::sendEvent(f->style(), &event);
+ }
+}
+#endif
+
+/*!
+ \property QWidget::autoFillBackground
+ \brief whether the widget background is filled automatically
+ \since 4.1
+
+ If enabled, this property will cause Qt to fill the background of the
+ widget before invoking the paint event. The color used is defined by the
+ QPalette::Window color role from the widget's \l{QPalette}{palette}.
+
+ In addition, Windows are always filled with QPalette::Window, unless the
+ WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
+
+ This property cannot be turned off (i.e., set to false) if a widget's
+ parent has a static gradient for its background.
+
+ \warning Use this property with caution in conjunction with
+ \l{Qt Style Sheets}. When a widget has a style sheet with a valid
+ background or a border-image, this property is automatically disabled.
+
+ By default, this property is false.
+
+ \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
+ {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
+*/
+bool QWidget::autoFillBackground() const
+{
+ Q_D(const QWidget);
+ return d->extra && d->extra->autoFillBackground;
+}
+
+void QWidget::setAutoFillBackground(bool enabled)
+{
+ Q_D(QWidget);
+ if (!d->extra)
+ d->createExtra();
+ if (d->extra->autoFillBackground == enabled)
+ return;
+
+ d->extra->autoFillBackground = enabled;
+ d->updateIsOpaque();
+ update();
+ d->updateIsOpaque();
+}
+
+/*!
+ \class QWidget
+ \brief The QWidget class is the base class of all user interface objects.
+
+ \ingroup basicwidgets
+ \mainclass
+
+ The widget is the atom of the user interface: it receives mouse, keyboard
+ and other events from the window system, and paints a representation of
+ itself on the screen. Every widget is rectangular, and they are sorted in a
+ Z-order. A widget is clipped by its parent and by the widgets in front of
+ it.
+
+ A widget that is not embedded in a parent widget is called a window.
+ Usually, windows have a frame and a title bar, although it is also possible
+ to create windows without such decoration using suitable
+ \l{Qt::WindowFlags}{window flags}). In Qt, QMainWindow and the various
+ subclasses of QDialog are the most common window types.
+
+ Every widget's constructor accepts one or two standard arguments:
+
+ \list 1
+ \i \c{QWidget *parent = 0} is the parent of the new widget. If it is 0
+ (the default), the new widget will be a window. If not, it will be
+ a child of \e parent, and be constrained by \e parent's geometry
+ (unless you specify Qt::Window as window flag).
+ \i \c{Qt::WindowFlags f = 0} (where available) sets the window flags;
+ the default is suitable for almost all widgets, but to get, for
+ example, a window without a window system frame, you must use
+ special flags.
+ \endlist
+
+ QWidget has many member functions, but some of them have little direct
+ functionality; for example, QWidget has a font property, but never uses
+ this itself. There are many subclasses which provide real functionality,
+ such as QLabel, QPushButton, QListWidget, and QTabWidget.
+
+
+ \section1 Top-Level and Child Widgets
+
+ A widget without a parent widget is always an independent window (top-level
+ widget). For these widgets, setWindowTitle() and setWindowIcon() set the
+ title bar and icon respectively.
+
+ Non-window widgets are child widgets, displayed within their parent
+ widgets. Most widgets in Qt are mainly useful as child widgets. For
+ example, it is possible to display a button as a top-level window, but most
+ people prefer to put their buttons inside other widgets, such as QDialog.
+
+ \image parent-child-widgets.png A parent widget containing various child widgets.
+
+ The diagram above shows a QGroupBox widget being used to hold various child
+ widgets in a layout provided by QGridLayout. The QLabel child widgets have
+ been outlined to indicate their full sizes.
+
+ If you want to use a QWidget to hold child widgets you will usually want to
+ add a layout to the parent QWidget. See \l{Layout Classes} for more
+ information.
+
+
+ \section1 Composite Widgets
+
+ When a widget is used as a container to group a number of child widgets, it
+ is known as a composite widget. These can be created by constructing a
+ widget with the required visual properties - a QFrame, for example - and
+ adding child widgets to it, usually managed by a layout. The above diagram
+ shows such a composite widget that was created using \l{Qt Designer}.
+
+ Composite widgets can also be created by subclassing a standard widget,
+ such as QWidget or QFrame, and adding the necessary layout and child
+ widgets in the constructor of the subclass. Many of the \l{Qt Examples}
+ {examples provided with Qt} use this approach, and it is also covered in
+ the Qt \l{Tutorials}.
+
+
+ \section1 Custom Widgets and Painting
+
+ Since QWidget is a subclass of QPaintDevice, subclasses can be used to
+ display custom content that is composed using a series of painting
+ operations with an instance of the QPainter class. This approach contrasts
+ with the canvas-style approach used by the \l{Graphics View}
+ {Graphics View Framework} where items are added to a scene by the
+ application and are rendered by the framework itself.
+
+ Each widget performs all painting operations from within its paintEvent()
+ function. This is called whenever the widget needs to be redrawn, either
+ as a result of some external change or when requested by the application.
+
+ The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
+ can handle paint events.
+
+
+ \section1 Size Hints and Size Policies
+
+ When implementing a new widget, it is almost always useful to reimplement
+ sizeHint() to provide a reasonable default size for the widget and to set
+ the correct size policy with setSizePolicy().
+
+ By default, composite widgets which do not provide a size hint will be
+ sized according to the space requirements of their child widgets.
+
+ The size policy lets you supply good default behavior for the layout
+ management system, so that other widgets can contain and manage yours
+ easily. The default size policy indicates that the size hint represents
+ the preferred size of the widget, and this is often good enough for many
+ widgets.
+
+ \note The size of top-level widgets are constrained to 2/3 of the desktop's
+ height and width. You can resize() the widget manually if these bounds are
+ inadequate.
+
+
+ \section1 Events
+
+ Widgets respond to events that are typically caused by user actions. Qt
+ delivers events to widgets by calling specific event handler functions with
+ instances of QEvent subclasses containing information about each event.
+
+ If your widget only contains child widgets, you probably do not need to
+ implement any event handlers. If you want to detect a mouse click in a
+ child widget call the child's underMouse() function inside the widget's
+ mousePressEvent().
+
+ The \l{widgets/scribble}{Scribble example} implements a wider set of
+ events to handle mouse movement, button presses, and window resizing.
+
+ You will need to supply the behavior and content for your own widgets, but
+ here is a brief overview of the events that are relevant to QWidget,
+ starting with the most common ones:
+
+ \list
+ \i paintEvent() is called whenever the widget needs to be repainted.
+ Every widget displaying custom content must implement it. Painting
+ using a QPainter can only take place in a paintEvent() or a
+ function called by a paintEvent().
+ \i resizeEvent() is called when the widget has been resized.
+ \i mousePressEvent() is called when a mouse button is pressed while
+ the mouse cursor is inside the widget, or when the widget has
+ grabbed the mouse using grabMouse(). Pressing the mouse without
+ releasing it is effectively the same as calling grabMouse().
+ \i mouseReleaseEvent() is called when a mouse button is released. A
+ widget receives mouse release events when it has received the
+ corresponding mouse press event. This means that if the user
+ presses the mouse inside \e your widget, then drags the mouse
+ somewhere else before releasing the mouse button, \e your widget
+ receives the release event. There is one exception: if a popup menu
+ appears while the mouse button is held down, this popup immediately
+ steals the mouse events.
+ \i mouseDoubleClickEvent() is called when the user double-clicks in
+ the widget. If the user double-clicks, the widget receives a mouse
+ press event, a mouse release event and finally this event instead
+ of a second mouse press event. (Some mouse move events may also be
+ received if the mouse is not held steady during this operation.) It
+ is \e{not possible} to distinguish a click from a double-click
+ until the second click arrives. (This is one reason why most GUI
+ books recommend that double-clicks be an extension of
+ single-clicks, rather than trigger a different action.)
+ \endlist
+
+ Widgets that accept keyboard input need to reimplement a few more event
+ handlers:
+
+ \list
+ \i keyPressEvent() is called whenever a key is pressed, and again when
+ a key has been held down long enough for it to auto-repeat. The
+ \key Tab and \key Shift+Tab keys are only passed to the widget if
+ they are not used by the focus-change mechanisms. To force those
+ keys to be processed by your widget, you must reimplement
+ QWidget::event().
+ \i focusInEvent() is called when the widget gains keyboard focus
+ (assuming you have called setFocusPolicy()). Well-behaved widgets
+ indicate that they own the keyboard focus in a clear but discreet
+ way.
+ \i focusOutEvent() is called when the widget loses keyboard focus.
+ \endlist
+
+ You may be required to also reimplement some of the less common event
+ handlers:
+
+ \list
+ \i mouseMoveEvent() is called whenever the mouse moves while a mouse
+ button is held down. This can be useful during drag and drop
+ operations. If you call setMouseTracking(true), you get mouse move
+ events even when no buttons are held down. (See also the \l{Drag
+ and Drop} guide.)
+ \i keyReleaseEvent() is called whenever a key is released and while it
+ is held down (if the key is auto-repeating). In that case, the
+ widget will receive a pair of key release and key press event for
+ every repeat. The \key Tab and \key Shift+Tab keys are only passed
+ to the widget if they are not used by the focus-change mechanisms.
+ To force those keys to be processed by your widget, you must
+ reimplement QWidget::event().
+ \i wheelEvent() is called whenever the user turns the mouse wheel
+ while the widget has the focus.
+ \i enterEvent() is called when the mouse enters the widget's screen
+ space. (This excludes screen space owned by any of the widget's
+ children.)
+ \i leaveEvent() is called when the mouse leaves the widget's screen
+ space. If the mouse enters a child widget it will not cause a
+ leaveEvent().
+ \i moveEvent() is called when the widget has been moved relative to
+ its parent.
+ \i closeEvent() is called when the user closes the widget (or when
+ close() is called).
+ \endlist
+
+ There are also some rather obscure events described in the documentation
+ for QEvent::Type. To handle these events, you need to reimplement event()
+ directly.
+
+ The default implementation of event() handles \key Tab and \key Shift+Tab
+ (to move the keyboard focus), and passes on most of the other events to
+ one of the more specialized handlers above.
+
+ Events and the mechanism used to deliver them are covered in the
+ \l{Events and Event Filters} document.
+
+ \section1 Groups of Functions and Properties
+
+ \table
+ \header \i Context \i Functions and Properties
+
+ \row \i Window functions \i
+ show(),
+ hide(),
+ raise(),
+ lower(),
+ close().
+
+ \row \i Top-level windows \i
+ \l windowModified, \l windowTitle, \l windowIcon, \l windowIconText,
+ \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
+ \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
+ showNormal().
+
+ \row \i Window contents \i
+ update(),
+ repaint(),
+ scroll().
+
+ \row \i Geometry \i
+ \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
+ \l sizePolicy, sizeHint(), minimumSizeHint(),
+ updateGeometry(), layout(),
+ \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
+ adjustSize(),
+ mapFromGlobal(), mapToGlobal(),
+ mapFromParent(), mapToParent(),
+ \l maximumSize, \l minimumSize, \l sizeIncrement,
+ \l baseSize, setFixedSize()
+
+ \row \i Mode \i
+ \l visible, isVisibleTo(),
+ \l enabled, isEnabledTo(),
+ \l modal,
+ isWindow(),
+ \l mouseTracking,
+ \l updatesEnabled,
+ visibleRegion().
+
+ \row \i Look and feel \i
+ style(),
+ setStyle(),
+ \l styleSheet,
+ \l cursor,
+ \l font,
+ \l palette,
+ backgroundRole(), setBackgroundRole(),
+ fontInfo(), fontMetrics().
+
+ \row \i Keyboard focus functions \i
+ \l focus, \l focusPolicy,
+ setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
+ focusNextChild(), focusPreviousChild().
+
+ \row \i Mouse and keyboard grabbing \i
+ grabMouse(), releaseMouse(),
+ grabKeyboard(), releaseKeyboard(),
+ mouseGrabber(), keyboardGrabber().
+
+ \row \i Event handlers \i
+ event(),
+ mousePressEvent(),
+ mouseReleaseEvent(),
+ mouseDoubleClickEvent(),
+ mouseMoveEvent(),
+ keyPressEvent(),
+ keyReleaseEvent(),
+ focusInEvent(),
+ focusOutEvent(),
+ wheelEvent(),
+ enterEvent(),
+ leaveEvent(),
+ paintEvent(),
+ moveEvent(),
+ resizeEvent(),
+ closeEvent(),
+ dragEnterEvent(),
+ dragMoveEvent(),
+ dragLeaveEvent(),
+ dropEvent(),
+ childEvent(),
+ showEvent(),
+ hideEvent(),
+ customEvent().
+ changeEvent(),
+
+ \row \i System functions \i
+ parentWidget(), window(), setParent(), winId(),
+ find(), metric().
+
+ \row \i Interactive help \i
+ setToolTip(), setWhatsThis()
+
+ \endtable
+
+
+ \section1 Widget Style Sheets
+
+ In addition to the standard widget styles for each platform, widgets can
+ also be styled according to rules specified in a \l{styleSheet}
+ {style sheet}. This feature enables you to customize the appearance of
+ specific widgets to provide visual cues to users about their purpose. For
+ example, a button could be styled in a particular way to indicate that it
+ performs a destructive action.
+
+ The use of widget style sheets is described in more detail in the
+ \l{Qt Style Sheets} document.
+
+
+ \section1 Transparency and Double Buffering
+
+ Since Qt 4.0, QWidget automatically double-buffers its painting, so there
+ is no need to write double-buffering code in paintEvent() to avoid
+ flicker.
+
+ Since Qt 4.1, the Qt::WA_ContentsPropagated widget attribute has been
+ deprecated. Instead, the contents of parent widgets are propagated by
+ default to each of their children as long as Qt::WA_PaintOnScreen is not
+ set. Custom widgets can be written to take advantage of this feature by
+ updating irregular regions (to create non-rectangular child widgets), or
+ painting with colors that have less than full alpha component. The
+ following diagram shows how attributes and properties of a custom widget
+ can be fine-tuned to achieve different effects.
+
+ \image propagation-custom.png
+
+ In the above diagram, a semi-transparent rectangular child widget with an
+ area removed is constructed and added to a parent widget (a QLabel showing
+ a pixmap). Then, different properties and widget attributes are set to
+ achieve different effects:
+
+ \list
+ \i The left widget has no additional properties or widget attributes
+ set. This default state suits most custom widgets using
+ transparency, are irregularly-shaped, or do not paint over their
+ entire area with an opaque brush.
+ \i The center widget has the \l autoFillBackground property set. This
+ property is used with custom widgets that rely on the widget to
+ supply a default background, and do not paint over their entire
+ area with an opaque brush.
+ \i The right widget has the Qt::WA_OpaquePaintEvent widget attribute
+ set. This indicates that the widget will paint over its entire area
+ with opaque colors. The widget's area will initially be
+ \e{uninitialized}, represented in the diagram with a red diagonal
+ grid pattern that shines through the overpainted area. The
+ Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
+ paint their own specialized contents quickly and do not need a
+ default filled background.
+ \endlist
+
+ To rapidly update custom widgets with simple background colors, such as
+ real-time plotting or graphing widgets, it is better to define a suitable
+ background color (using setBackgroundRole() with the
+ QPalette::Window role), set the \l autoFillBackground property, and only
+ implement the necessary drawing functionality in the widget's paintEvent().
+
+ To rapidly update custom widgets that constantly paint over their entire
+ areas with opaque content, e.g., video streaming widgets, it is better to
+ set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
+ associated with repainting the widget's background.
+
+ If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
+ the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
+ attribute takes precedence. Depending on your requirements, you should
+ choose either one of them.
+
+ Since Qt 4.1, the contents of parent widgets are also propagated to
+ standard Qt widgets. This can lead to some unexpected results if the
+ parent widget is decorated in a non-standard way, as shown in the diagram
+ below.
+
+ \image propagation-standard.png
+
+ The scope for customizing the painting behavior of standard Qt widgets,
+ without resorting to subclassing, is slightly less than that possible for
+ custom widgets. Usually, the desired appearance of a standard widget can be
+ achieved by setting its \l autoFillBackground property.
+
+
+ \section1 Creating Translucent Windows
+
+ Since Qt 4.5, it has been possible to create windows with translucent regions
+ on window systems that support compositing.
+
+ To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
+ attribute with setAttribute() and ensure that its background is painted with
+ non-opaque colors in the regions you want to be partially transparent.
+
+ Platform notes:
+
+ \list
+ \o X11: This feature relies on the use of an X server that supports ARGB visuals
+ and a compositing window manager.
+ \o Windows: This feature requires Windows 2000 or later. The widget needs to have
+ the Qt::FramelessWindowHint window flag set for the translucency to work.
+ \endlist
+
+
+ \section1 Native Widgets vs Alien Widgets
+
+ Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
+ system. They do not have a native window handle associated with them. This
+ feature significantly speeds up widget painting, resizing, and removes flicker.
+
+ Should you require the old behavior with native windows, you can choose
+ one of the following options:
+
+ \list 1
+ \i Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
+ \i Set the Qt::AA_NativeWindows attribute on your application. All
+ widgets will be native widgets.
+ \i Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
+ and all of its ancestors will become native (unless
+ Qt::WA_DontCreateNativeAncestors is set).
+ \i Call QWidget::winId to enforce a native window (this implies 3).
+ \i Set the Qt::WA_PaintOnScreen attribute to enforce a native window
+ (this implies 3).
+ \endlist
+
+ \sa QEvent, QPainter, QGridLayout, QBoxLayout
+*/
+
+QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
+QWidgetSet *QWidgetPrivate::uncreatedWidgets = 0; // widgets with no wid
+
+
+/*****************************************************************************
+ QWidget utility functions
+ *****************************************************************************/
+
+QRegion qt_dirtyRegion(QWidget *widget)
+{
+ if (!widget)
+ return QRegion();
+
+ QWidgetBackingStore *bs = qt_widget_private(widget)->maybeBackingStore();
+ if (!bs)
+ return QRegion();
+
+ return bs->dirtyRegion(widget);
+}
+
+/*****************************************************************************
+ QWidget member functions
+ *****************************************************************************/
+
+/*
+ Widget state flags:
+ \list
+ \i Qt::WA_WState_Created The widget has a valid winId().
+ \i Qt::WA_WState_Visible The widget is currently visible.
+ \i Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
+ become visible unless you call show() on it. Qt::WA_WState_Hidden
+ implies !Qt::WA_WState_Visible.
+ \i Qt::WA_WState_CompressKeys Compress keyboard events.
+ \i Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
+ \i Qt::WA_WState_InPaintEvent Currently processing a paint event.
+ \i Qt::WA_WState_Reparented The widget has been reparented.
+ \i Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
+ \i Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops().
+ \endlist
+*/
+
+/*!
+ Constructs a widget which is a child of \a parent, with widget
+ flags set to \a f.
+
+ If \a parent is 0, the new widget becomes a window. If
+ \a parent is another widget, this widget becomes a child window
+ inside \a parent. The new widget is deleted when its \a parent is
+ deleted.
+
+ The widget flags argument, \a f, is normally 0, but it can be set
+ to customize the frame of a window (i.e. \a
+ parent must be 0). To customize the frame, use a value composed
+ from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
+
+ If you add a child widget to an already visible widget you must
+ explicitly show the child to make it visible.
+
+ Note that the X11 version of Qt may not be able to deliver all
+ combinations of style flags on all systems. This is because on
+ X11, Qt can only ask the window manager, and the window manager
+ can override the application's settings. On Windows, Qt can set
+ whatever flags you want.
+
+ \sa windowFlags
+*/
+
+QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
+ : QObject(*new QWidgetPrivate, 0), QPaintDevice()
+{
+ d_func()->init(parent, f);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload
+ \obsolete
+ */
+QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
+ : QObject(*new QWidgetPrivate, 0), QPaintDevice()
+{
+ d_func()->init(parent , f);
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*! \internal
+*/
+QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
+ : QObject(dd, 0), QPaintDevice()
+{
+ d_func()->init(parent, f);
+}
+
+/*!
+ \internal
+*/
+int QWidget::devType() const
+{
+ return QInternal::Widget;
+}
+
+
+//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
+void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
+{
+ bool customize = (flags & (Qt::CustomizeWindowHint
+ | Qt::FramelessWindowHint
+ | Qt::WindowTitleHint
+ | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint
+ | Qt::WindowMaximizeButtonHint
+ | Qt::WindowCloseButtonHint
+ | Qt::WindowContextHelpButtonHint));
+
+ uint type = (flags & Qt::WindowType_Mask);
+
+ if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
+ type = Qt::Window;
+ flags |= Qt::Window;
+ }
+
+ if (flags & Qt::CustomizeWindowHint) {
+ // modify window flags to make them consistent.
+ // Only enable this on non-Mac platforms. Since the old way of doing this would
+ // interpret WindowSystemMenuHint as a close button and we can't change that behavior
+ // we can't just add this in.
+#ifndef Q_WS_MAC
+ if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) {
+ flags |= Qt::WindowSystemMenuHint;
+#else
+ if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
+ | Qt::WindowSystemMenuHint)) {
+#endif
+ flags |= Qt::WindowTitleHint;
+ flags &= ~Qt::FramelessWindowHint;
+ }
+ } else if (customize && !(flags & Qt::FramelessWindowHint)) {
+ // if any of the window hints that affect the titlebar are set
+ // and the window is supposed to have frame, we add a titlebar
+ // and system menu by default.
+ flags |= Qt::WindowSystemMenuHint;
+ flags |= Qt::WindowTitleHint;
+ }
+ if (customize)
+ ; // don't modify window flags if the user explicitely set them.
+ else if (type == Qt::Dialog || type == Qt::Sheet)
+#ifndef Q_OS_WINCE
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
+#else
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+#endif
+ else if (type == Qt::Tool)
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+ else
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint;
+
+
+}
+
+void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+ if (qApp->type() == QApplication::Tty)
+ qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
+
+ Q_ASSERT(uncreatedWidgets);
+ uncreatedWidgets->insert(q);
+
+ QWidget *desktopWidget = 0;
+ if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
+ desktopWidget = parentWidget;
+ parentWidget = 0;
+ }
+
+ q->data = &data;
+
+#ifndef QT_NO_THREAD
+ if (!q->parent()) {
+ Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
+ "Widgets must be created in the GUI thread.");
+ }
+#endif
+
+#if defined(Q_WS_X11)
+ if (desktopWidget) {
+ // make sure the widget is created on the same screen as the
+ // programmer specified desktop widget
+ xinfo = desktopWidget->d_func()->xinfo;
+ }
+#else
+ Q_UNUSED(desktopWidget);
+#endif
+
+ data.fstrut_dirty = true;
+
+ data.winid = 0;
+ data.widget_attributes = 0;
+ data.window_flags = f;
+ data.window_state = 0;
+ data.focus_policy = 0;
+ data.context_menu_policy = Qt::DefaultContextMenu;
+ data.window_modality = Qt::NonModal;
+
+ data.sizehint_forced = 0;
+ data.is_closing = 0;
+ data.in_show = 0;
+ data.in_set_window_state = 0;
+ data.in_destructor = false;
+
+ // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
+ if (f & Qt::MSWindowsOwnDC)
+ q->setAttribute(Qt::WA_NativeWindow);
+
+#ifdef Q_OS_WINCE
+ data.window_state_internal = 0;
+#endif
+
+ q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
+ adjustQuitOnCloseAttribute();
+
+ q->setAttribute(Qt::WA_WState_Hidden);
+
+ //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later
+ data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
+
+ focus_next = focus_prev = q;
+
+ if ((f & Qt::WindowType_Mask) == Qt::Desktop)
+ q->create();
+ else if (parentWidget)
+ q->setParent(parentWidget, data.window_flags);
+ else {
+ adjustFlags(data.window_flags, q);
+ resolveLayoutDirection();
+ // opaque system background?
+ const QBrush &background = q->palette().brush(QPalette::Window);
+ setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
+ }
+ data.fnt = QFont(data.fnt, q);
+#if defined(Q_WS_X11)
+ data.fnt.x11SetScreen(xinfo.screen());
+#endif // Q_WS_X11
+
+ q->setAttribute(Qt::WA_PendingMoveEvent);
+ q->setAttribute(Qt::WA_PendingResizeEvent);
+
+ if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
+ QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
+
+ if (QApplicationPrivate::app_compile_version < 0x040200
+ || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
+ q->create();
+
+
+ QEvent e(QEvent::Create);
+ QApplication::sendEvent(q, &e);
+ QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
+
+ extraPaintEngine = 0;
+}
+
+
+
+void QWidgetPrivate::createRecursively()
+{
+ Q_Q(QWidget);
+ q->create(0, true, true);
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
+ child->d_func()->createRecursively();
+ }
+}
+
+
+
+
+/*!
+ Creates a new widget window if \a window is 0, otherwise sets the
+ widget's window to \a window.
+
+ Initializes the window (sets the geometry etc.) if \a
+ initializeWindow is true. If \a initializeWindow is false, no
+ initialization is performed. This parameter only makes sense if \a
+ window is a valid window.
+
+ Destroys the old window if \a destroyOldWindow is true. If \a
+ destroyOldWindow is false, you are responsible for destroying the
+ window yourself (using platform native code).
+
+ The QWidget constructor calls create(0,true,true) to create a
+ window for this widget.
+*/
+
+void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_D(QWidget);
+ if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
+ return;
+
+ if (d->data.in_destructor)
+ return;
+
+ Qt::WindowType type = windowType();
+ Qt::WindowFlags &flags = data->window_flags;
+
+ if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
+ type = Qt::Window;
+ flags |= Qt::Window;
+ }
+
+ if (QWidget *parent = parentWidget()) {
+ if (type & Qt::Window) {
+ if (!parent->testAttribute(Qt::WA_WState_Created))
+ parent->createWinId();
+ } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
+ && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
+ // We're about to create a native child widget that doesn't have a native parent;
+ // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
+ // attribute is set.
+ d->createWinId(window);
+ // Nothing more to do.
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ Q_ASSERT(internalWinId());
+ return;
+ }
+ }
+
+#ifdef QT3_SUPPORT
+ if (flags & Qt::WStaticContents)
+ setAttribute(Qt::WA_StaticContents);
+ if (flags & Qt::WDestructiveClose)
+ setAttribute(Qt::WA_DeleteOnClose);
+ if (flags & Qt::WShowModal)
+ setWindowModality(Qt::ApplicationModal);
+ if (flags & Qt::WMouseNoMask)
+ setAttribute(Qt::WA_MouseNoMask);
+ if (flags & Qt::WGroupLeader)
+ setAttribute(Qt::WA_GroupLeader);
+ if (flags & Qt::WNoMousePropagation)
+ setAttribute(Qt::WA_NoMousePropagation);
+#endif
+
+ static int paintOnScreenEnv = -1;
+ if (paintOnScreenEnv == -1)
+ paintOnScreenEnv = qgetenv("QT_ONSCREEN_PAINT").toInt() > 0 ? 1 : 0;
+ if (paintOnScreenEnv == 1)
+ setAttribute(Qt::WA_PaintOnScreen);
+
+ if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
+ setAttribute(Qt::WA_NativeWindow);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
+ << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
+#endif
+
+#if defined (Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
+ // Unregister the dropsite (if already registered) before we
+ // re-create the widget with a native window.
+ if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow)
+ && d->extra && d->extra->dropTarget) {
+ d->registerDropSite(false);
+ }
+#endif // defined (Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
+
+ d->updateIsOpaque();
+
+ setAttribute(Qt::WA_WState_Created); // set created flag
+ d->create_sys(window, initializeWindow, destroyOldWindow);
+
+ // a real toplevel window needs a backing store
+ if (isWindow()) {
+ delete d->topData()->backingStore;
+ // QWidgetBackingStore will check this variable, hence it must be 0
+ d->topData()->backingStore = 0;
+ if (hasBackingStoreSupport())
+ d->topData()->backingStore = new QWidgetBackingStore(this);
+ }
+
+ d->setModal_sys();
+
+ if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
+ setAttribute(Qt::WA_DropSiteRegistered, true);
+
+#ifdef QT_EVAL
+ extern void qt_eval_init_widget(QWidget *w);
+ qt_eval_init_widget(this);
+#endif
+
+ // need to force the resting of the icon after changing parents
+ if (testAttribute(Qt::WA_SetWindowIcon))
+ d->setWindowIcon_sys(true);
+ if (isWindow() && !d->topData()->iconText.isEmpty())
+ d->setWindowIconText_helper(d->topData()->iconText);
+ if (windowType() != Qt::Desktop) {
+ d->updateSystemBackground();
+
+ if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
+ d->setWindowIcon_sys();
+ }
+}
+
+/*!
+ Destroys the widget.
+
+ All this widget's children are deleted first. The application
+ exits if this widget is the main widget.
+*/
+
+QWidget::~QWidget()
+{
+ Q_D(QWidget);
+ d->data.in_destructor = true;
+
+#if defined (QT_CHECK_STATE)
+ if (paintingActive())
+ qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
+#endif
+
+ // force acceptDrops false before winId is destroyed.
+ d->registerDropSite(false);
+
+#ifndef QT_NO_ACTION
+ // remove all actions from this widget
+ for (int i = 0; i < d->actions.size(); ++i) {
+ QActionPrivate *apriv = d->actions.at(i)->d_func();
+ apriv->widgets.removeAll(this);
+ }
+ d->actions.clear();
+#endif
+
+#ifndef QT_NO_SHORTCUT
+ // Remove all shortcuts grabbed by this
+ // widget, unless application is closing
+ if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
+ qApp->d_func()->shortcutMap.removeShortcut(0, this, QKeySequence());
+#endif
+
+ // delete layout while we still are a valid widget
+ delete d->layout;
+ // Remove myself from focus list
+
+ Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
+ Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
+
+ if (d->focus_next != this) {
+ d->focus_next->d_func()->focus_prev = d->focus_prev;
+ d->focus_prev->d_func()->focus_next = d->focus_next;
+ d->focus_next = d->focus_prev = 0;
+ }
+
+#ifdef QT3_SUPPORT
+ if (QApplicationPrivate::main_widget == this) { // reset main widget
+ QApplicationPrivate::main_widget = 0;
+ qApp->quit();
+ }
+#endif
+
+ clearFocus();
+
+ d->setDirtyOpaqueRegion();
+
+ if (isWindow() && isVisible() && internalWinId())
+ hide();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ else if (!internalWinId() && isVisible())
+ qApp->d_func()->sendSyntheticEnterLeave(this);
+#endif
+
+ if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
+ bs->removeDirtyWidget(this);
+ if (testAttribute(Qt::WA_StaticContents))
+ bs->removeStaticWidget(this);
+ }
+
+ delete d->needsFlush;
+ d->needsFlush = 0;
+
+ // set all QPointers for this object to zero
+ QObjectPrivate::clearGuards(this);
+
+ if (!d->children.isEmpty())
+ d->deleteChildren();
+
+ QApplication::removePostedEvents(this);
+
+ destroy(); // platform-dependent cleanup
+
+ --QWidgetPrivate::instanceCounter;
+
+ if (QWidgetPrivate::uncreatedWidgets) // might have been deleted by ~QApplication
+ QWidgetPrivate::uncreatedWidgets->remove(this);
+
+ QEvent e(QEvent::Destroy);
+ QCoreApplication::sendEvent(this, &e);
+}
+
+int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
+int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
+
+void QWidgetPrivate::setWinId(WId id) // set widget identifier
+{
+ Q_Q(QWidget);
+ if (mapper && data.winid) {
+ mapper->remove(data.winid);
+ uncreatedWidgets->insert(q);
+ }
+
+ data.winid = id;
+#if defined(Q_WS_X11)
+ hd = id; // X11: hd == ident
+#endif
+ if (mapper && id) {
+ mapper->insert(data.winid, q);
+ uncreatedWidgets->remove(q);
+ }
+}
+
+void QWidgetPrivate::createTLExtra()
+{
+ if (!extra)
+ createExtra();
+ if (!extra->topextra) {
+ QTLWExtra* x = extra->topextra = new QTLWExtra;
+ x->windowSurface = 0;
+ x->opacity = 255;
+ x->posFromMove = false;
+ x->sizeAdjusted = false;
+ x->inTopLevelResize = false;
+ x->inRepaint = false;
+ x->backingStore = 0;
+ x->icon = 0;
+ x->iconPixmap = 0;
+ x->frameStrut.setCoords(0, 0, 0, 0);
+ x->incw = x->inch = 0;
+ x->basew = x->baseh = 0;
+ x->normalGeometry = QRect(0,0,-1,-1);
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC)
+ x->embedded = 0;
+#endif
+#if defined(Q_WS_X11)
+ x->parentWinId = 0;
+ x->spont_unmapped = 0;
+ x->dnd = 0;
+#endif
+ x->savedFlags = 0;
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+ x->qwsManager = 0;
+#endif
+ x->sharedPainter = 0;
+ createTLSysExtra();
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int count = 0;
+ qDebug() << "tlextra" << ++count;
+#endif
+ }
+}
+
+/*!
+ \internal
+ Creates the widget extra data.
+*/
+
+void QWidgetPrivate::createExtra()
+{
+ if (!extra) { // if not exists
+ extra = new QWExtra;
+ extra->minw = extra->minh = 0;
+ extra->maxw = extra->maxh = QWIDGETSIZE_MAX;
+ extra->explicitMinSize = 0;
+ extra->explicitMaxSize = 0;
+ extra->autoFillBackground = 0;
+ extra->nativeChildrenForced = 0;
+ extra->inRenderWithPainter = 0;
+ extra->hasMask = 0;
+#ifndef QT_NO_CURSOR
+ extra->curs = 0;
+#endif
+ extra->style = 0;
+ extra->topextra = 0;
+ extra->proxyWidget = 0;
+ extra->glContext = 0;
+ extra->customDpiX = 0;
+ extra->customDpiY = 0;
+ createSysExtra();
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int count = 0;
+ qDebug() << "extra" << ++count;
+#endif
+ }
+}
+
+
+/*!
+ \internal
+ Deletes the widget extra data.
+*/
+
+void QWidgetPrivate::deleteExtra()
+{
+ if (extra) { // if exists
+#ifndef QT_NO_CURSOR
+ delete extra->curs;
+#endif
+ deleteSysExtra();
+#ifndef QT_NO_STYLE_STYLESHEET
+ // dereference the stylesheet style
+ if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(extra->style))
+ proxy->deref();
+#endif
+ if (extra->topextra) {
+ deleteTLSysExtra();
+ delete extra->topextra->backingStore;
+ delete extra->topextra->icon;
+ delete extra->topextra->iconPixmap;
+#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
+ delete extra->topextra->qwsManager;
+#endif
+ delete extra->topextra->windowSurface;
+ delete extra->topextra;
+ }
+ delete extra;
+ // extra->xic destroyed in QWidget::destroy()
+ extra = 0;
+ }
+}
+
+/*
+ Returns true if the background is inherited; otherwise returns
+ false.
+
+ Mainly used in the paintOnScreen case.
+*/
+
+bool QWidgetPrivate::isBackgroundInherited() const
+{
+ Q_Q(const QWidget);
+
+ // windows do not inherit their background
+ if (q->isWindow() || q->windowType() == Qt::SubWindow)
+ return false;
+
+ if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
+ return false;
+
+ const QPalette &pal = q->palette();
+ QPalette::ColorRole bg = q->backgroundRole();
+ QBrush brush = pal.brush(bg);
+
+ // non opaque brushes leaves us no choice, we must inherit
+ if (!q->autoFillBackground() || !brush.isOpaque())
+ return true;
+
+ if (brush.style() == Qt::SolidPattern) {
+ // the background is just a solid color. If there is no
+ // propagated contents, then we claim as performance
+ // optimization that it was not inheritet. This is the normal
+ // case in standard Windows or Motif style.
+ const QWidget *w = q->parentWidget();
+ if (!w->d_func()->isBackgroundInherited())
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ Returns true if there are widgets above this which overlap with
+ \a rect, which is in parent's coordinate system (same as crect).
+*/
+
+bool QWidgetPrivate::isOverlapped(const QRect &rect) const
+{
+ Q_Q(const QWidget);
+
+ const QWidget *w = q;
+ QRect r = rect;
+ while (w) {
+ if (w->isWindow())
+ return false;
+ QWidgetPrivate *pd = w->parentWidget()->d_func();
+ bool above = false;
+ for (int i = 0; i < pd->children.size(); ++i) {
+ QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
+ if (!sibling || !sibling->isVisible() || sibling->isWindow())
+ continue;
+ if (!above) {
+ above = (sibling == w);
+ continue;
+ }
+
+ if (qRectIntersects(sibling->data->crect, r)) {
+ const QWExtra *siblingExtra = sibling->d_func()->extra;
+ if (siblingExtra && siblingExtra->hasMask
+ && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
+ continue;
+ }
+ return true;
+ }
+ }
+ w = w->parentWidget();
+ r.translate(pd->data.crect.topLeft());
+ }
+ return false;
+}
+
+void QWidgetPrivate::syncBackingStore()
+{
+ if (paintOnScreen()) {
+ repaint_sys(dirty);
+ dirty = QRegion();
+ } else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+ bs->sync();
+ }
+}
+
+void QWidgetPrivate::syncBackingStore(const QRegion &region)
+{
+ if (paintOnScreen())
+ repaint_sys(region);
+ else if (QWidgetBackingStore *bs = maybeBackingStore())
+ bs->sync(q_func(), region);
+}
+
+void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
+{
+ Q_Q(QWidget);
+
+ if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
+ return; // nothing we can do
+
+ if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
+ return; // nothing to do
+
+ q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
+ if (enable)
+ q->update();
+
+ Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->isWindow() && !w->testAttribute(attribute))
+ w->d_func()->setUpdatesEnabled_helper(enable);
+ }
+}
+
+/*!
+ \internal
+
+ Propagate this widget's palette to all children, except style sheet
+ widgets, and windows that don't enable window propagation (palettes don't
+ normally propagate to windows).
+*/
+void QWidgetPrivate::propagatePaletteChange()
+{
+ Q_Q(QWidget);
+ // Propagate a new inherited mask to all children.
+ if (!q->parentWidget() && extra && extra->proxyWidget) {
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *p = extra->proxyWidget;
+ inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
+#endif //QT_NO_GRAPHICSVIEW
+ } else if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
+ inheritedPaletteResolveMask = 0;
+ }
+ int mask = data.pal.resolve() | inheritedPaletteResolveMask;
+
+ QEvent pc(QEvent::PaletteChange);
+ QApplication::sendEvent(q, &pc);
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (w && !w->testAttribute(Qt::WA_StyleSheet)
+ && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
+ QWidgetPrivate *wd = w->d_func();
+ wd->inheritedPaletteResolveMask = mask;
+ wd->resolvePalette();
+ }
+ }
+#if defined(QT3_SUPPORT)
+ q->paletteChange(q->palette()); // compatibility
+#endif
+}
+
+/*
+ Returns the widget's clipping rectangle.
+*/
+QRect QWidgetPrivate::clipRect() const
+{
+ Q_Q(const QWidget);
+ const QWidget * w = q;
+ if (!w->isVisible())
+ return QRect();
+ QRect r = q->rect();
+ int ox = 0;
+ int oy = 0;
+ while (w
+ && w->isVisible()
+ && !w->isWindow()
+ && w->parentWidget()) {
+ ox -= w->x();
+ oy -= w->y();
+ w = w->parentWidget();
+ r &= QRect(ox, oy, w->width(), w->height());
+ }
+ return r;
+}
+
+/*
+ Returns the widget's clipping region (without siblings).
+*/
+QRegion QWidgetPrivate::clipRegion() const
+{
+ Q_Q(const QWidget);
+ if (!q->isVisible())
+ return QRegion();
+ QRegion r(q->rect());
+ const QWidget * w = q;
+ const QWidget *ignoreUpTo;
+ int ox = 0;
+ int oy = 0;
+ while (w
+ && w->isVisible()
+ && !w->isWindow()
+ && w->parentWidget()) {
+ ox -= w->x();
+ oy -= w->y();
+ ignoreUpTo = w;
+ w = w->parentWidget();
+ r &= QRegion(ox, oy, w->width(), w->height());
+
+ int i = 0;
+ while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
+ ;
+ for ( ; i < w->d_func()->children.size(); ++i) {
+ if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
+ if(sibling->isVisible() && !sibling->isWindow()) {
+ QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
+ sibling->width(), sibling->height());
+ if (qRectIntersects(siblingRect, q->rect()))
+ r -= QRegion(siblingRect);
+ }
+ }
+ }
+ }
+ return r;
+}
+
+void QWidgetPrivate::setDirtyOpaqueRegion()
+{
+ Q_Q(QWidget);
+
+ dirtyOpaqueChildren = true;
+
+ if (q->isWindow())
+ return;
+
+ QWidget *parent = q->parentWidget();
+ if (!parent)
+ return;
+
+ // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
+ QWidgetPrivate *pd = parent->d_func();
+ if (!pd->dirtyOpaqueChildren)
+ pd->setDirtyOpaqueRegion();
+}
+
+QRegion QWidgetPrivate::getOpaqueRegion() const
+{
+ Q_Q(const QWidget);
+
+ QRegion r = isOpaque ? q->rect() : getOpaqueChildren();
+ if (extra && extra->hasMask)
+ r &= extra->mask;
+ if (r.isEmpty())
+ return r;
+ return r & clipRect();
+}
+
+const QRegion &QWidgetPrivate::getOpaqueChildren() const
+{
+ if (!dirtyOpaqueChildren)
+ return opaqueChildren;
+
+ QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
+ that->opaqueChildren = QRegion();
+
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (!child || !child->isVisible() || child->isWindow())
+ continue;
+
+ const QPoint offset = child->geometry().topLeft();
+ that->opaqueChildren += child->d_func()->getOpaqueRegion().translated(offset);
+ }
+
+ that->dirtyOpaqueChildren = false;
+
+ return that->opaqueChildren;
+}
+
+void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
+{
+ if (children.isEmpty() || clipRect.isEmpty())
+ return;
+
+ const QRegion &r = getOpaqueChildren();
+ if (!r.isEmpty())
+ source -= (r & clipRect);
+}
+
+//subtract any relatives that are higher up than me --- this is too expensive !!!
+void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
+ bool alsoNonOpaque) const
+{
+ Q_Q(const QWidget);
+ static int disableSubtractOpaqueSiblings = qgetenv("QT_NO_SUBTRACTOPAQUESIBLINGS").toInt();
+ if (disableSubtractOpaqueSiblings || q->isWindow())
+ return;
+
+ QRect clipBoundingRect;
+ bool dirtyClipBoundingRect = true;
+
+ QRegion parentClip;
+ bool dirtyParentClip = true;
+
+ QPoint parentOffset = data.crect.topLeft();
+
+ const QWidget *w = q;
+
+ while (w) {
+ if (w->isWindow())
+ break;
+ QWidgetPrivate *pd = w->parentWidget()->d_func();
+ const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
+ for (int i = myIndex + 1; i < pd->children.size(); ++i) {
+ QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
+ if (!sibling || !sibling->isVisible() || sibling->isWindow())
+ continue;
+
+ if (!qRectIntersects(sibling->data->crect, w->data->crect))
+ continue;
+
+ if (dirtyClipBoundingRect) {
+ clipBoundingRect = sourceRegion.boundingRect();
+ dirtyClipBoundingRect = false;
+ }
+
+ if (!qRectIntersects(sibling->data->crect, clipBoundingRect.translated(parentOffset)))
+ continue;
+
+ if (dirtyParentClip) {
+ parentClip = sourceRegion.translated(parentOffset);
+ dirtyParentClip = false;
+ }
+
+ const QPoint siblingPos(sibling->data->crect.topLeft());
+ const QRect siblingClipRect(sibling->d_func()->clipRect());
+ QRegion siblingDirty(parentClip);
+ siblingDirty &= (siblingClipRect.translated(siblingPos));
+ const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask;
+ if (hasMask)
+ siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
+ if (siblingDirty.isEmpty())
+ continue;
+
+ if (sibling->d_func()->isOpaque || alsoNonOpaque) {
+ if (hasMask) {
+ siblingDirty.translate(-parentOffset);
+ sourceRegion -= siblingDirty;
+ } else {
+ sourceRegion -= sibling->data->crect.translated(-parentOffset);
+ }
+ } else {
+ if (hasDirtySiblingsAbove)
+ *hasDirtySiblingsAbove = true;
+ if (sibling->d_func()->children.isEmpty())
+ continue;
+ QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
+ opaqueSiblingChildren.translate(-parentOffset + siblingPos);
+ sourceRegion -= opaqueSiblingChildren;
+ }
+ if (sourceRegion.isEmpty())
+ return;
+
+ dirtyClipBoundingRect = true;
+ dirtyParentClip = true;
+ }
+
+ w = w->parentWidget();
+ parentOffset += pd->data.crect.topLeft();
+ dirtyParentClip = true;
+ }
+}
+
+void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
+{
+ Q_Q(const QWidget);
+
+ const QWidget *w = q;
+ QPoint offset;
+
+ while (w) {
+ const QWidgetPrivate *wd = w->d_func();
+ if (wd->extra && wd->extra->hasMask)
+ region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
+ if (w->isWindow())
+ return;
+ offset -= wd->data.crect.topLeft();
+ w = w->parentWidget();
+ }
+}
+
+bool QWidgetPrivate::hasBackground() const
+{
+ Q_Q(const QWidget);
+ if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_PaintOnScreen))
+ return true;
+ if (q->testAttribute(Qt::WA_PaintOnScreen))
+ return true;
+ if (!q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
+ const QPalette &pal = q->palette();
+ QPalette::ColorRole bg = q->backgroundRole();
+ QBrush bgBrush = pal.brush(bg);
+ return (bgBrush.style() != Qt::NoBrush &&
+ ((q->isWindow() || q->windowType() == Qt::SubWindow)
+ || (QPalette::ColorRole(bg_role) != QPalette::NoRole || (pal.resolve() & (1<<bg)))));
+ }
+ return false;
+}
+
+bool QWidgetPrivate::paintOnScreen() const
+{
+#if defined(Q_WS_QWS)
+ return false;
+#elif defined(QT_NO_BACKINGSTORE)
+ return true;
+#else
+ Q_Q(const QWidget);
+ if (q->testAttribute(Qt::WA_PaintOnScreen)
+ || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
+ return true;
+ }
+
+ return !qt_enable_backingstore;
+#endif
+}
+
+void QWidgetPrivate::updateIsOpaque()
+{
+ // hw: todo: only needed if opacity actually changed
+ setDirtyOpaqueRegion();
+
+ Q_Q(QWidget);
+#ifdef Q_WS_X11
+ if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
+ setOpaque(false);
+ return;
+ }
+#endif
+
+ if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
+ setOpaque(true);
+ return;
+ }
+
+ const QPalette &pal = q->palette();
+
+ if (q->autoFillBackground()) {
+ const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
+ if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
+ setOpaque(true);
+ return;
+ }
+ }
+
+ if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
+ const QBrush &windowBrush = q->palette().brush(QPalette::Window);
+ if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
+ setOpaque(true);
+ return;
+ }
+ }
+ setOpaque(false);
+}
+
+void QWidgetPrivate::setOpaque(bool opaque)
+{
+ if (isOpaque == opaque)
+ return;
+ isOpaque = opaque;
+#ifdef Q_WS_MAC
+ macUpdateIsOpaque();
+#endif
+#ifdef Q_WS_X11
+ x11UpdateIsOpaque();
+#endif
+#ifdef Q_WS_WIN
+ winUpdateIsOpaque();
+#endif
+}
+
+void QWidgetPrivate::updateIsTranslucent()
+{
+#ifdef Q_WS_MAC
+ macUpdateIsOpaque();
+#endif
+#ifdef Q_WS_X11
+ x11UpdateIsOpaque();
+#endif
+#ifdef Q_WS_WIN
+ winUpdateIsOpaque();
+#endif
+}
+
+/*!
+ \fn void QPixmap::fill(const QWidget *widget, const QPoint &offset)
+
+ Fills the pixmap with the \a widget's background color or pixmap
+ according to the given offset.
+
+ The QPoint \a offset defines a point in widget coordinates to
+ which the pixmap's top-left pixel will be mapped to. This is only
+ significant if the widget has a background pixmap; otherwise the
+ pixmap will simply be filled with the background color of the
+ widget.
+*/
+
+void QPixmap::fill( const QWidget *widget, const QPoint &off )
+{
+ QPainter p(this);
+ p.translate(-off);
+ widget->d_func()->paintBackground(&p, QRect(off, size()));
+
+}
+
+static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush)
+{
+ Q_ASSERT(painter);
+
+ if (brush.style() == Qt::TexturePattern) {
+#ifdef Q_WS_MAC
+ // Optimize pattern filling on mac by using HITheme directly
+ // when filling with the standard widget background.
+ // Defined in qmacstyle_mac.cpp
+ extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush);
+ qt_mac_fill_background(painter, rgn, offset, brush);
+#else
+ const QRegion translated = rgn.translated(offset);
+ const QRect rect(translated.boundingRect());
+ painter->setClipRegion(translated);
+ painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
+#endif
+ } else {
+ const QVector<QRect> &rects = rgn.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ painter->fillRect(rects.at(i).translated(offset), brush);
+ }
+}
+
+
+void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, const QPoint &offset, int flags) const
+{
+ Q_Q(const QWidget);
+
+ const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
+
+ if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
+ const QBrush bg = q->palette().brush(QPalette::Window);
+#ifdef Q_WS_QWS
+ if (!(flags & DontSetCompositionMode) && painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ painter->setCompositionMode(QPainter::CompositionMode_Source); //copy alpha straight in
+#endif
+ fillRegion(painter, rgn, offset, bg);
+ }
+
+ if (q->autoFillBackground())
+ fillRegion(painter, rgn, offset, autoFillBrush);
+
+ if (q->testAttribute(Qt::WA_StyledBackground)) {
+ painter->setClipRegion(rgn.translated(offset));
+ QStyleOption opt;
+ opt.initFrom(q);
+ q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
+ }
+}
+
+/*
+ \internal
+ This function is called when a widget is hidden or destroyed.
+ It resets some application global pointers that should only refer active,
+ visible widgets.
+*/
+
+#ifdef Q_WS_MAC
+ extern QPointer<QWidget> qt_button_down;
+#else
+ extern QWidget *qt_button_down;
+#endif
+
+void QWidgetPrivate::deactivateWidgetCleanup()
+{
+ Q_Q(QWidget);
+ // If this was the active application window, reset it
+ if (qApp->activeWindow() == q)
+ qApp->setActiveWindow(0);
+ // If the is the active mouse press widget, reset it
+ if (q == qt_button_down)
+ qt_button_down = 0;
+}
+
+
+/*!
+ Returns a pointer to the widget with window identifer/handle \a
+ id.
+
+ The window identifier type depends on the underlying window
+ system, see \c qwindowdefs.h for the actual definition. If there
+ is no widget with this identifier, 0 is returned.
+*/
+
+QWidget *QWidget::find(WId id)
+{
+ return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : 0;
+}
+
+
+
+/*!
+ \fn WId QWidget::internalWinId() const
+ \internal
+ Returns the window system identifier of the widget, or 0 if the widget is not created yet.
+
+*/
+
+/*!
+ \fn WId QWidget::winId() const
+
+ Returns the window system identifier of the widget.
+
+ Portable in principle, but if you use it you are probably about to
+ do something non-portable. Be careful.
+
+ If a widget is non-native (alien) and winId() is invoked on it, that widget
+ will be provided a native handle.
+
+ \note We recommend that you do not store this value as it is likely to
+ change at run-time.
+
+ \sa find()
+*/
+WId QWidget::winId() const
+{
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ QWidget *that = const_cast<QWidget*>(this);
+ that->setAttribute(Qt::WA_NativeWindow);
+ that->d_func()->createWinId();
+ return that->data->winid;
+ }
+ return data->winid;
+}
+
+
+void QWidgetPrivate::createWinId(WId winid)
+{
+ Q_Q(QWidget);
+ const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
+ if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
+ if (!q->isWindow()) {
+ QWidget *parent = q->parentWidget();
+ QWidgetPrivate *pd = parent->d_func();
+ if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
+ parent->setAttribute(Qt::WA_NativeWindow);
+ if (!parent->internalWinId()) {
+ pd->createWinId();
+ }
+
+ for (int i = 0; i < pd->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
+ if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
+ || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
+ if (w!=q) {
+ w->create();
+ } else {
+ w->create(winid);
+ // if the window has already been created, we
+ // need to raise it to its proper stacking position
+ if (winid)
+ w->raise();
+ }
+ }
+ }
+ } else {
+ q->create();
+ }
+ }
+}
+
+
+/*!
+\internal
+Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
+
+*/
+
+void QWidget::createWinId()
+{
+ Q_D(QWidget);
+// qWarning("QWidget::createWinId is obsolete, please fix your code.");
+ d->createWinId();
+}
+
+/*!
+ \since 4.4
+
+ Returns the effective window system identifier of the widget, i.e. the
+ native parent's window system identifier.
+
+ If the widget is native, this function returns the native widget ID.
+ Otherwise, the window ID of the first native parent widget, i.e., the
+ top-level widget that contains this widget, is returned.
+
+ \note We recommend that you do not store this value as it is likely to
+ change at run-time.
+
+ \sa nativeParentWidget()
+*/
+WId QWidget::effectiveWinId() const
+{
+ WId id = internalWinId();
+ if (id || !testAttribute(Qt::WA_WState_Created))
+ return id;
+ QWidget *realParent = nativeParentWidget();
+ Q_ASSERT(realParent);
+ Q_ASSERT(realParent->internalWinId());
+ return realParent->internalWinId();
+}
+
+#ifndef QT_NO_STYLE_STYLESHEET
+
+/*!
+ \property QWidget::styleSheet
+ \brief the widget's style sheet
+ \since 4.2
+
+ The style sheet contains a textual description of customizations to the
+ widget's style, as described in the \l{Qt Style Sheets} document.
+
+ \note Qt style sheets are currently not supported for QMacStyle
+ (the default style on Mac OS X). We plan to address this in some future
+ release.
+
+ \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
+*/
+QString QWidget::styleSheet() const
+{
+ Q_D(const QWidget);
+ if (!d->extra)
+ return QString();
+ return d->extra->styleSheet;
+}
+
+void QWidget::setStyleSheet(const QString& styleSheet)
+{
+ Q_D(QWidget);
+ d->createExtra();
+
+ QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style);
+ d->extra->styleSheet = styleSheet;
+ if (styleSheet.isEmpty()) { // stylesheet removed
+ if (!proxy)
+ return;
+
+ d->inheritStyle();
+ return;
+ }
+
+ if (proxy) { // style sheet update
+ proxy->repolish(this);
+ return;
+ }
+
+ if (testAttribute(Qt::WA_SetStyle)) {
+ d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
+ } else {
+ d->setStyle_helper(new QStyleSheetStyle(0), true);
+ }
+}
+
+#endif // QT_NO_STYLE_STYLESHEET
+
+/*!
+ \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
+*/
+
+QStyle *QWidget::style() const
+{
+ Q_D(const QWidget);
+
+ if (d->extra && d->extra->style)
+ return d->extra->style;
+ return qApp->style();
+}
+
+/*!
+ Sets the widget's GUI style to \a style. The ownership of the style
+ object is not transferred.
+
+ If no style is set, the widget uses the application's style,
+ QApplication::style() instead.
+
+ Setting a widget's style has no effect on existing or future child
+ widgets.
+
+ \warning This function is particularly useful for demonstration
+ purposes, where you want to show Qt's styling capabilities. Real
+ applications should avoid it and use one consistent GUI style
+ instead.
+
+ \warning Qt style sheets are currently not supported for custom QStyle
+ subclasses. We plan to address this in some future release.
+
+ \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
+*/
+
+void QWidget::setStyle(QStyle *style)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetStyle, style != 0);
+ d->createExtra();
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(style)) {
+ //if for some reason someone try to set a QStyleSheetStyle, ref it
+ //(this may happen for exemple in QButtonDialogBox which propagates its style)
+ proxy->ref();
+ d->setStyle_helper(style, false);
+ } else if (qobject_cast<QStyleSheetStyle *>(d->extra->style) || !qApp->styleSheet().isEmpty()) {
+ // if we have an application stylesheet or have a proxy already, propagate
+ d->setStyle_helper(new QStyleSheetStyle(style), true);
+ } else
+#endif
+ d->setStyle_helper(style, false);
+}
+
+void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool
+#ifdef Q_WS_MAC
+ metalHack
+#endif
+ )
+{
+ Q_Q(QWidget);
+ createExtra();
+
+ QStyle *oldStyle = q->style();
+#ifndef QT_NO_STYLE_STYLESHEET
+ QStyle *origStyle = extra->style;
+#endif
+ extra->style = newStyle;
+
+ // repolish
+ if (q->windowType() != Qt::Desktop) {
+ if (polished) {
+ oldStyle->unpolish(q);
+#ifdef Q_WS_MAC
+ if (metalHack)
+ macUpdateMetalAttribute();
+#endif
+ q->style()->polish(q);
+#ifdef Q_WS_MAC
+ } else if (metalHack) {
+ macUpdateMetalAttribute();
+#endif
+ }
+ }
+
+ if (propagate) {
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *c = qobject_cast<QWidget*>(children.at(i));
+ if (c)
+ c->d_func()->inheritStyle();
+ }
+ }
+
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(q, &e);
+#ifdef QT3_SUPPORT
+ q->styleChange(*oldStyle);
+#endif
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (!qobject_cast<QStyleSheetStyle*>(newStyle)) {
+ if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle)) {
+ cssStyle->clearWidgetFont(q);
+ }
+ }
+#endif
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ // dereference the old stylesheet style
+ if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle))
+ proxy->deref();
+#endif
+}
+
+// Inherits style from the current parent and propagates it as necessary
+void QWidgetPrivate::inheritStyle()
+{
+#ifndef QT_NO_STYLE_STYLESHEET
+ Q_Q(QWidget);
+
+ QStyleSheetStyle *proxy = extra ? qobject_cast<QStyleSheetStyle *>(extra->style) : 0;
+
+ if (!q->styleSheet().isEmpty()) {
+ Q_ASSERT(proxy);
+ proxy->repolish(q);
+ return;
+ }
+
+ QStyle *origStyle = proxy ? proxy->base : (extra ? (QStyle*)extra->style : 0);
+ QWidget *parent = q->parentWidget();
+ QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0;
+ // If we have stylesheet on app or parent has stylesheet style, we need
+ // to be running a proxy
+ if (!qApp->styleSheet().isEmpty() || qobject_cast<QStyleSheetStyle *>(parentStyle)) {
+ QStyle *newStyle = parentStyle;
+ if (q->testAttribute(Qt::WA_SetStyle))
+ newStyle = new QStyleSheetStyle(origStyle);
+ else if (QStyleSheetStyle *newProxy = qobject_cast<QStyleSheetStyle *>(parentStyle))
+ newProxy->ref();
+
+ setStyle_helper(newStyle, true);
+ return;
+ }
+
+ // So, we have no stylesheet on parent/app and we have an empty stylesheet
+ // we just need our original style back
+ if (origStyle == (extra ? (QStyle*)extra->style : 0)) // is it any different?
+ return;
+
+ // We could have inherited the proxy from our parent (which has a custom style)
+ // In such a case we need to start following the application style (i.e revert
+ // the propagation behavior of QStyleSheetStyle)
+ if (!q->testAttribute(Qt::WA_SetStyle))
+ origStyle = 0;
+
+ setStyle_helper(origStyle, true);
+#endif // QT_NO_STYLE_STYLESHEET
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload
+
+ Sets the widget's GUI style to \a style using the QStyleFactory.
+*/
+QStyle* QWidget::setStyle(const QString &style)
+{
+ QStyle *s = QStyleFactory::create(style);
+ setStyle(s);
+ return s;
+}
+#endif
+
+/*!
+ \fn bool QWidget::isWindow() const
+
+ Returns true if the widget is an independent window, otherwise
+ returns false.
+
+ A window is a widget that isn't visually the child of any other
+ widget and that usually has a frame and a
+ \l{QWidget::setWindowTitle()}{window title}.
+
+ A window can have a \l{QWidget::parentWidget()}{parent widget}.
+ It will then be grouped with its parent and deleted when the
+ parent is deleted, minimized when the parent is minimized etc. If
+ supported by the window manager, it will also have a common
+ taskbar entry with its parent.
+
+ QDialog and QMainWindow widgets are by default windows, even if a
+ parent widget is specified in the constructor. This behavior is
+ specified by the Qt::Window flag.
+
+ \sa window(), isModal(), parentWidget()
+*/
+
+/*!
+ \property QWidget::modal
+ \brief whether the widget is a modal widget
+
+ This property only makes sense for windows. A modal widget
+ prevents widgets in all other windows from getting any input.
+
+ By default, this property is false.
+
+ \sa isWindow(), windowModality, QDialog
+*/
+
+/*!
+ \property QWidget::windowModality
+ \brief which windows are blocked by the modal widget
+ \since 4.1
+
+ This property only makes sense for windows. A modal widget
+ prevents widgets in other windows from getting input. The value of
+ this property controls which windows are blocked when the widget
+ is visible. Changing this property while the window is visible has
+ no effect; you must hide() the widget first, then show() it again.
+
+ By default, this property is Qt::NonModal.
+
+ \sa isWindow(), QWidget::modal, QDialog
+*/
+
+Qt::WindowModality QWidget::windowModality() const
+{
+ return static_cast<Qt::WindowModality>(data->window_modality);
+}
+
+void QWidget::setWindowModality(Qt::WindowModality windowModality)
+{
+ data->window_modality = windowModality;
+ // setModal_sys() will be called by setAttribute()
+ setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
+ setAttribute(Qt::WA_SetWindowModality, true);
+}
+
+/*!
+ \fn bool QWidget::underMouse() const
+
+ Returns true if the widget is under the mouse cursor; otherwise
+ returns false.
+
+ This value is not updated properly during drag and drop
+ operations.
+
+ \sa enterEvent(), leaveEvent()
+*/
+
+/*!
+ \property QWidget::minimized
+ \brief whether this widget is minimized (iconified)
+
+ This property is only relevant for windows.
+
+ By default, this property is false.
+
+ \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
+*/
+bool QWidget::isMinimized() const
+{ return data->window_state & Qt::WindowMinimized; }
+
+/*!
+ Shows the widget minimized, as an icon.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
+ isMinimized()
+*/
+void QWidget::showMinimized()
+{
+ bool isMin = isMinimized();
+ if (isMin && isVisible())
+ return;
+
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ if (!isMin)
+ setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
+ show();
+}
+
+/*!
+ \property QWidget::maximized
+ \brief whether this widget is maximized
+
+ This property is only relevant for windows.
+
+ \note Due to limitations on some window systems, this does not always
+ report the expected results (e.g., if the user on X11 maximizes the
+ window via the window manager, Qt has no way of distinguishing this
+ from any other resize). This is expected to improve as window manager
+ protocols evolve.
+
+ By default, this property is false.
+
+ \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
+*/
+bool QWidget::isMaximized() const
+{ return data->window_state & Qt::WindowMaximized; }
+
+
+
+/*!
+ Returns the current window state. The window state is a OR'ed
+ combination of Qt::WindowState: Qt::WindowMinimized,
+ Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
+
+ \sa Qt::WindowState setWindowState()
+ */
+Qt::WindowStates QWidget::windowState() const
+{
+ return (Qt::WindowStates)data->window_state;
+}
+
+/*!\internal
+
+ The function sets the window state on child widgets similar to
+ setWindowState(). The difference is that the window state changed
+ event has the isOverride() flag set. It exists mainly to keep
+ Q3Workspace working.
+ */
+void QWidget::overrideWindowState(Qt::WindowStates newstate)
+{
+ QWindowStateChangeEvent e((Qt::WindowStates)data->window_state, true);
+ data->window_state = newstate;
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ \fn void QWidget::setWindowState(Qt::WindowStates windowState)
+
+ Sets the window state to \a windowState. The window state is a OR'ed
+ combination of Qt::WindowState: Qt::WindowMinimized,
+ Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
+
+ If the window is not visible (i.e. isVisible() returns false), the
+ window state will take effect when show() is called. For visible
+ windows, the change is immediate. For example, to toggle between
+ full-screen and normal mode, use the following code:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 0
+
+ In order to restore and activate a minimized window (while
+ preserving its maximized and/or full-screen state), use the following:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 1
+
+ Calling this function will hide the widget. You must call show() to make
+ the widget visible again.
+
+ \note On some window systems Qt::WindowActive is not immediate, and may be
+ ignored in certain cases.
+
+ When the window state changes, the widget receives a changeEvent()
+ of type QEvent::WindowStateChange.
+
+ \sa Qt::WindowState windowState()
+*/
+
+/*!
+ \property QWidget::fullScreen
+ \brief whether the widget is shown in full screen mode
+
+ A widget in full screen mode occupies the whole screen area and does not
+ display window decorations, such as a title bar.
+
+ By default, this property is false.
+
+ \sa windowState(), minimized, maximized
+*/
+bool QWidget::isFullScreen() const
+{ return data->window_state & Qt::WindowFullScreen; }
+
+/*!
+ Shows the widget in full-screen mode.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ To return from full-screen mode, call showNormal().
+
+ Full-screen mode works fine under Windows, but has certain
+ problems under X. These problems are due to limitations of the
+ ICCCM protocol that specifies the communication between X11
+ clients and the window manager. ICCCM simply does not understand
+ the concept of non-decorated full-screen windows. Therefore, the
+ best we can do is to request a borderless window and place and
+ resize it to fill the entire screen. Depending on the window
+ manager, this may or may not work. The borderless window is
+ requested using MOTIF hints, which are at least partially
+ supported by virtually all modern window managers.
+
+ An alternative would be to bypass the window manager entirely and
+ create a window with the Qt::X11BypassWindowManagerHint flag. This
+ has other severe problems though, like totally broken keyboard focus
+ and very strange effects on desktop changes or when the user raises
+ other windows.
+
+ X11 window managers that follow modern post-ICCCM specifications
+ support full-screen mode properly.
+
+ \sa showNormal(), showMaximized(), show(), hide(), isVisible()
+*/
+void QWidget::showFullScreen()
+{
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
+ | Qt::WindowFullScreen);
+ show();
+ activateWindow();
+}
+
+/*!
+ Shows the widget maximized.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ On X11, this function may not work properly with certain window
+ managers. See \l{geometry.html}{Window Geometry} for an explanation.
+
+ \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
+*/
+void QWidget::showMaximized()
+{
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
+ | Qt::WindowMaximized);
+ show();
+}
+
+/*!
+ Restores the widget after it has been maximized or minimized.
+
+ Calling this function only affects \l{isWindow()}{windows}.
+
+ \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
+*/
+void QWidget::showNormal()
+{
+ ensurePolished();
+#ifdef QT3_SUPPORT
+ if (parent())
+ QApplication::sendPostedEvents(parent(), QEvent::ChildInserted);
+#endif
+
+ setWindowState(windowState() & ~(Qt::WindowMinimized
+ | Qt::WindowMaximized
+ | Qt::WindowFullScreen));
+ show();
+}
+
+/*!
+ Returns true if this widget would become enabled if \a ancestor is
+ enabled; otherwise returns false.
+
+
+
+ This is the case if neither the widget itself nor every parent up
+ to but excluding \a ancestor has been explicitly disabled.
+
+ isEnabledTo(0) is equivalent to isEnabled().
+
+ \sa setEnabled() enabled
+*/
+
+bool QWidget::isEnabledTo(QWidget* ancestor) const
+{
+ const QWidget * w = this;
+ while (w && !w->testAttribute(Qt::WA_ForceDisabled)
+ && !w->isWindow()
+ && w->parentWidget()
+ && w->parentWidget() != ancestor)
+ w = w->parentWidget();
+ return !w->testAttribute(Qt::WA_ForceDisabled);
+}
+
+#ifndef QT_NO_ACTION
+/*!
+ Appends the action \a action to this widget's list of actions.
+
+ All QWidgets have a list of \l{QAction}s, however they can be
+ represented graphically in many different ways. The default use of
+ the QAction list (as returned by actions()) is to create a context
+ QMenu.
+
+ A QWidget should only have one of each action and adding an action
+ it already has will not cause the same action to be in the widget twice.
+
+ The ownership of \a action is not transferred to this QWidget.
+
+ \sa removeAction(), insertAction(), actions(), QMenu
+*/
+void QWidget::addAction(QAction *action)
+{
+ insertAction(0, action);
+}
+
+/*!
+ Appends the actions \a actions to this widget's list of actions.
+
+ \sa removeAction(), QMenu, addAction()
+*/
+void QWidget::addActions(QList<QAction*> actions)
+{
+ for(int i = 0; i < actions.count(); i++)
+ insertAction(0, actions.at(i));
+}
+
+/*!
+ Inserts the action \a action to this widget's list of actions,
+ before the action \a before. It appends the action if \a before is 0 or
+ \a before is not a valid action for this widget.
+
+ A QWidget should only have one of each action.
+
+ \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
+*/
+void QWidget::insertAction(QAction *before, QAction *action)
+{
+ if(!action) {
+ qWarning("QWidget::insertAction: Attempt to insert null action");
+ return;
+ }
+
+ Q_D(QWidget);
+ if(d->actions.contains(action))
+ removeAction(action);
+
+ int pos = d->actions.indexOf(before);
+ if (pos < 0) {
+ before = 0;
+ pos = d->actions.size();
+ }
+ d->actions.insert(pos, action);
+
+ QActionPrivate *apriv = action->d_func();
+ apriv->widgets.append(this);
+
+ QActionEvent e(QEvent::ActionAdded, action, before);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ Inserts the actions \a actions to this widget's list of actions,
+ before the action \a before. It appends the action if \a before is 0 or
+ \a before is not a valid action for this widget.
+
+ A QWidget can have at most one of each action.
+
+ \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
+*/
+void QWidget::insertActions(QAction *before, QList<QAction*> actions)
+{
+ for(int i = 0; i < actions.count(); ++i)
+ insertAction(before, actions.at(i));
+}
+
+/*!
+ Removes the action \a action from this widget's list of actions.
+ \sa insertAction(), actions(), insertAction()
+*/
+void QWidget::removeAction(QAction *action)
+{
+ if (!action)
+ return;
+
+ Q_D(QWidget);
+
+ QActionPrivate *apriv = action->d_func();
+ apriv->widgets.removeAll(this);
+
+ if (d->actions.removeAll(action)) {
+ QActionEvent e(QEvent::ActionRemoved, action);
+ QApplication::sendEvent(this, &e);
+ }
+}
+
+/*!
+ Returns the (possibly empty) list of this widget's actions.
+
+ \sa contextMenuPolicy, insertAction(), removeAction()
+*/
+QList<QAction*> QWidget::actions() const
+{
+ Q_D(const QWidget);
+ return d->actions;
+}
+#endif // QT_NO_ACTION
+
+/*!
+ \fn bool QWidget::isEnabledToTLW() const
+ \obsolete
+
+ This function is deprecated. It is equivalent to isEnabled()
+*/
+
+/*!
+ \property QWidget::enabled
+ \brief whether the widget is enabled
+
+ An enabled widget handles keyboard and mouse events; a disabled
+ widget does not.
+
+ Some widgets display themselves differently when they are
+ disabled. For example a button might draw its label grayed out. If
+ your widget needs to know when it becomes enabled or disabled, you
+ can use the changeEvent() with type QEvent::EnabledChange.
+
+ Disabling a widget implicitly disables all its children. Enabling
+ respectively enables all child widgets unless they have been
+ explicitly disabled.
+
+ By default, this property is true.
+
+ \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
+*/
+void QWidget::setEnabled(bool enable)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_ForceDisabled, !enable);
+ d->setEnabled_helper(enable);
+}
+
+void QWidgetPrivate::setEnabled_helper(bool enable)
+{
+ Q_Q(QWidget);
+
+ if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
+ return; // nothing we can do
+
+ if (enable != q->testAttribute(Qt::WA_Disabled))
+ return; // nothing to do
+
+ q->setAttribute(Qt::WA_Disabled, !enable);
+ updateSystemBackground();
+
+ if (!enable && q->window()->focusWidget() == q) {
+ bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
+ if (!parentIsEnabled || !q->focusNextChild())
+ q->clearFocus();
+ }
+
+ Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->testAttribute(attribute))
+ w->d_func()->setEnabled_helper(enable);
+ }
+#if defined(Q_WS_X11)
+ if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
+ // enforce the windows behavior of clearing the cursor on
+ // disabled widgets
+ extern void qt_x11_enforce_cursor(QWidget * w); // defined in qwidget_x11.cpp
+ qt_x11_enforce_cursor(q);
+ }
+#endif
+#if defined(Q_WS_MAC)
+ setEnabled_helper_sys(enable);
+#endif
+#if defined (Q_WS_WIN)
+ if (q->hasFocus())
+ QInputContextPrivate::updateImeStatus(q, true);
+#endif
+ QEvent e(QEvent::EnabledChange);
+ QApplication::sendEvent(q, &e);
+#ifdef QT3_SUPPORT
+ q->enabledChange(!enable); // compatibility
+#endif
+}
+
+/*!
+ \property QWidget::acceptDrops
+ \brief whether drop events are enabled for this widget
+
+ Setting this property to true announces to the system that this
+ widget \e may be able to accept drop events.
+
+ If the widget is the desktop (windowType() == Qt::Desktop), this may
+ fail if another application is using the desktop; you can call
+ acceptDrops() to test if this occurs.
+
+ \warning Do not modify this property in a drag and drop event handler.
+
+ By default, this property is false.
+
+ \sa {Drag and Drop}
+*/
+bool QWidget::acceptDrops() const
+{
+ return testAttribute(Qt::WA_AcceptDrops);
+}
+
+void QWidget::setAcceptDrops(bool on)
+{
+ setAttribute(Qt::WA_AcceptDrops, on);
+
+}
+
+/*!
+ \fn void QWidget::enabledChange(bool)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::paletteChange(const QPalette &)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::fontChange(const QFont &)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::windowActivationChange(bool)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::languageChange()
+
+ \obsolete
+*/
+
+/*!
+ \fn void QWidget::styleChange(QStyle& style)
+
+ \internal
+ \obsolete
+*/
+
+/*!
+ Disables widget input events if \a disable is true; otherwise
+ enables input events.
+
+ See the \l enabled documentation for more information.
+
+ \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
+*/
+void QWidget::setDisabled(bool disable)
+{
+ setEnabled(!disable);
+}
+
+/*!
+ \property QWidget::frameGeometry
+ \brief geometry of the widget relative to its parent including any
+ window frame
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of geometry issues with windows.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa geometry() x() y() pos()
+*/
+QRect QWidget::frameGeometry() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup)) {
+ QRect fs = d->frameStrut();
+ return QRect(data->crect.x() - fs.left(),
+ data->crect.y() - fs.top(),
+ data->crect.width() + fs.left() + fs.right(),
+ data->crect.height() + fs.top() + fs.bottom());
+ }
+ return data->crect;
+}
+
+/*!
+ \property QWidget::x
+
+ \brief the x coordinate of the widget relative to its parent including
+ any window frame
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ By default, this property has a value of 0.
+
+ \sa frameGeometry, y, pos
+*/
+int QWidget::x() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup))
+ return data->crect.x() - d->frameStrut().left();
+ return data->crect.x();
+}
+
+/*!
+ \property QWidget::y
+ \brief the y coordinate of the widget relative to its parent and
+ including any window frame
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ By default, this property has a value of 0.
+
+ \sa frameGeometry, x, pos
+*/
+int QWidget::y() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup))
+ return data->crect.y() - d->frameStrut().top();
+ return data->crect.y();
+}
+
+/*!
+ \property QWidget::pos
+ \brief the position of the widget within its parent widget
+
+ If the widget is a window, the position is that of the widget on
+ the desktop, including its frame.
+
+ When changing the position, the widget, if visible, receives a
+ move event (moveEvent()) immediately. If the widget is not
+ currently visible, it is guaranteed to receive an event before it
+ is shown.
+
+ By default, this property contains a position that refers to the
+ origin.
+
+ \warning Calling move() or setGeometry() inside moveEvent() can
+ lead to infinite recursion.
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ \sa frameGeometry, size x(), y()
+*/
+QPoint QWidget::pos() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && ! (windowType() == Qt::Popup)) {
+ QRect fs = d->frameStrut();
+ return QPoint(data->crect.x() - fs.left(), data->crect.y() - fs.top());
+ }
+ return data->crect.topLeft();
+}
+
+/*!
+ \property QWidget::geometry
+ \brief the geometry of the widget relative to its parent and
+ excluding the window frame
+
+ When changing the geometry, the widget, if visible, receives a
+ move event (moveEvent()) and/or a resize event (resizeEvent())
+ immediately. If the widget is not currently visible, it is
+ guaranteed to receive appropriate events before it is shown.
+
+ The size component is adjusted if it lies outside the range
+ defined by minimumSize() and maximumSize().
+
+ \warning Calling setGeometry() inside resizeEvent() or moveEvent()
+ can lead to infinite recursion.
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
+ resizeEvent(), minimumSize(), maximumSize()
+*/
+
+/*!
+ \property QWidget::normalGeometry
+
+ \brief the geometry of the widget as it will appear when shown as
+ a normal (not maximized or full screen) top-level widget
+
+ For child widgets this property always holds an empty rectangle.
+
+ By default, this property contains an empty rectangle.
+
+ \sa QWidget::windowState(), QWidget::geometry
+*/
+
+/*!
+ \property QWidget::size
+ \brief the size of the widget excluding any window frame
+
+ If the widget is visible when it is being resized, it receives a resize event
+ (resizeEvent()) immediately. If the widget is not currently
+ visible, it is guaranteed to receive an event before it is shown.
+
+ The size is adjusted if it lies outside the range defined by
+ minimumSize() and maximumSize().
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \warning Calling resize() or setGeometry() inside resizeEvent() can
+ lead to infinite recursion.
+
+ \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
+ appear on screen. This also applies to windows.
+
+ \sa pos, geometry, minimumSize, maximumSize, resizeEvent()
+*/
+
+/*!
+ \property QWidget::width
+ \brief the width of the widget excluding any window frame
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ \note Do not use this function to find the width of a screen on
+ a \l{QDesktopWidget}{multiple screen desktop}. Read
+ \l{multiple screens note}{this note} for details.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa geometry, height, size
+*/
+
+/*!
+ \property QWidget::height
+ \brief the height of the widget excluding any window frame
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ \note Do not use this function to find the height of a screen
+ on a \l {QDesktopWidget} {multiple screen desktop}. Read
+ \l {multiple screens note} {this note} for details.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa geometry, width, size
+*/
+
+/*!
+ \property QWidget::rect
+ \brief the internal geometry of the widget excluding any window
+ frame
+
+ The rect property equals QRect(0, 0, width(), height()).
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of window geometry.
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+
+ \sa size
+*/
+
+
+QRect QWidget::normalGeometry() const
+{
+ Q_D(const QWidget);
+ if (!d->extra || !d->extra->topextra)
+ return QRect();
+
+ if (!isMaximized() && !isFullScreen())
+ return geometry();
+
+ return d->topData()->normalGeometry;
+}
+
+
+/*!
+ \property QWidget::childrenRect
+ \brief the bounding rectangle of the widget's children
+
+ Hidden children are excluded.
+
+ By default, for a widget with no children, this property contains a
+ rectangle with zero width and height located at the origin.
+
+ \sa childrenRegion() geometry()
+*/
+
+QRect QWidget::childrenRect() const
+{
+ Q_D(const QWidget);
+ QRect r(0, 0, 0, 0);
+ for (int i = 0; i < d->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden())
+ r |= w->geometry();
+ }
+ return r;
+}
+
+/*!
+ \property QWidget::childrenRegion
+ \brief the combined region occupied by the widget's children
+
+ Hidden children are excluded.
+
+ By default, for a widget with no children, this property contains an
+ empty region.
+
+ \sa childrenRect() geometry() mask()
+*/
+
+QRegion QWidget::childrenRegion() const
+{
+ Q_D(const QWidget);
+ QRegion r;
+ for (int i = 0; i < d->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden()) {
+ QRegion mask = w->mask();
+ if (mask.isEmpty())
+ r |= w->geometry();
+ else
+ r |= mask.translated(w->pos());
+ }
+ }
+ return r;
+}
+
+
+/*!
+ \property QWidget::minimumSize
+ \brief the widget's minimum size
+
+ The widget cannot be resized to a smaller size than the minimum
+ widget size. The widget's size is forced to the minimum size if
+ the current size is smaller.
+
+ The minimum size set by this function will override the minimum size
+ defined by QLayout. In order to unset the minimum size, use a
+ value of \c{QSize(0, 0)}.
+
+ By default, this property contains a size with zero width and height.
+
+ \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
+*/
+
+QSize QWidget::minimumSize() const
+{
+ Q_D(const QWidget);
+ return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
+}
+
+/*!
+ \property QWidget::maximumSize
+ \brief the widget's maximum size in pixels
+
+ The widget cannot be resized to a larger size than the maximum
+ widget size.
+
+ By default, this property contains a size in which both width and height
+ have values of 16777215.
+
+ \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
+ of widgets.
+
+ \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
+*/
+
+QSize QWidget::maximumSize() const
+{
+ Q_D(const QWidget);
+ return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
+ : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+}
+
+
+/*!
+ \property QWidget::minimumWidth
+ \brief the widget's minimum width in pixels
+
+ This property corresponds to the width held by the \l minimumSize property.
+
+ By default, this property has a value of 0.
+
+ \sa minimumSize, minimumHeight
+*/
+
+/*!
+ \property QWidget::minimumHeight
+ \brief the widget's minimum height in pixels
+
+ This property corresponds to the height held by the \l minimumSize property.
+
+ By default, this property has a value of 0.
+
+ \sa minimumSize, minimumWidth
+*/
+
+/*!
+ \property QWidget::maximumWidth
+ \brief the widget's maximum width in pixels
+
+ This property corresponds to the width held by the \l maximumSize property.
+
+ By default, this property contains a value of 16777215.
+
+ \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
+ of widgets.
+
+ \sa maximumSize, maximumHeight
+*/
+
+/*!
+ \property QWidget::maximumHeight
+ \brief the widget's maximum height in pixels
+
+ This property corresponds to the height held by the \l maximumSize property.
+
+ By default, this property contains a value of 16777215.
+
+ \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
+ of widgets.
+
+ \sa maximumSize, maximumWidth
+*/
+
+/*!
+ \property QWidget::sizeIncrement
+ \brief the size increment of the widget
+
+ When the user resizes the window, the size will move in steps of
+ sizeIncrement().width() pixels horizontally and
+ sizeIncrement.height() pixels vertically, with baseSize() as the
+ basis. Preferred widget sizes are for non-negative integers \e i
+ and \e j:
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 2
+
+ Note that while you can set the size increment for all widgets, it
+ only affects windows.
+
+ By default, this property contains a size with zero width and height.
+
+ \warning The size increment has no effect under Windows, and may
+ be disregarded by the window manager on X11.
+
+ \sa size, minimumSize, maximumSize
+*/
+QSize QWidget::sizeIncrement() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra)
+ ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
+ : QSize(0, 0);
+}
+
+/*!
+ \property QWidget::baseSize
+ \brief the base size of the widget
+
+ The base size is used to calculate a proper widget size if the
+ widget defines sizeIncrement().
+
+ By default, for a newly-created widget, this property contains a size with
+ zero width and height.
+
+ \sa setSizeIncrement()
+*/
+
+QSize QWidget::baseSize() const
+{
+ Q_D(const QWidget);
+ return (d->extra != 0 && d->extra->topextra != 0)
+ ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
+ : QSize(0, 0);
+}
+
+bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
+{
+ Q_Q(QWidget);
+
+#ifdef Q_WS_QWS
+ if (q->isWindow()) {
+ const QRect maxWindowRect = QApplication::desktop()->availableGeometry(QApplication::desktop()->screenNumber(q));
+ if (!maxWindowRect.isEmpty()) {
+ // ### This is really just a work-around. Layout shouldn't be
+ // asking for minimum sizes bigger than the screen.
+ if (minw > maxWindowRect.width())
+ minw = maxWindowRect.width();
+ if (minh > maxWindowRect.height())
+ minh = maxWindowRect.height();
+ }
+ }
+#endif
+ if (minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX) {
+ qWarning("QWidget::setMinimumSize: (%s/%s) "
+ "The largest allowed size is (%d,%d)",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX);
+ minw = qMin<int>(minw, QWIDGETSIZE_MAX);
+ minh = qMin<int>(minh, QWIDGETSIZE_MAX);
+ }
+ if (minw < 0 || minh < 0) {
+ qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
+ "are not possible",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
+ minw = qMax(minw, 0);
+ minh = qMax(minh, 0);
+ }
+ createExtra();
+ if (extra->minw == minw && extra->minh == minh)
+ return false;
+ extra->minw = minw;
+ extra->minh = minh;
+ extra->explicitMinSize = (minw ? Qt::Horizontal : 0) | (minh ? Qt::Vertical : 0);
+ return true;
+}
+
+/*!
+ \overload
+
+ This function corresponds to setMinimumSize(QSize(minw, minh)).
+ Sets the minimum width to \a minw and the minimum height to \a
+ minh.
+*/
+
+void QWidget::setMinimumSize(int minw, int minh)
+{
+ Q_D(QWidget);
+ if (!d->setMinimumSize_helper(minw, minh))
+ return;
+
+ if (isWindow())
+ d->setConstraints_sys();
+ if (minw > width() || minh > height()) {
+ bool resized = testAttribute(Qt::WA_Resized);
+ bool maximized = isMaximized();
+ resize(qMax(minw,width()), qMax(minh,height()));
+ setAttribute(Qt::WA_Resized, resized); //not a user resize
+ if (maximized)
+ data->window_state = data->window_state | Qt::WindowMaximized;
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ if (d->extra) {
+ if (d->extra->proxyWidget)
+ d->extra->proxyWidget->setMinimumSize(minw, minh);
+ }
+#endif
+ d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
+}
+
+bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
+{
+ Q_Q(QWidget);
+ if (maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX) {
+ qWarning("QWidget::setMaximumSize: (%s/%s) "
+ "The largest allowed size is (%d,%d)",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX);
+ maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
+ maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
+ }
+ if (maxw < 0 || maxh < 0) {
+ qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
+ "are not possible",
+ q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
+ maxw = qMax(maxw, 0);
+ maxh = qMax(maxh, 0);
+ }
+ createExtra();
+ if (extra->maxw == maxw && extra->maxh == maxh)
+ return false;
+ extra->maxw = maxw;
+ extra->maxh = maxh;
+ extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) | (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
+ return true;
+}
+
+/*!
+ \overload
+
+ This function corresponds to setMaximumSize(QSize(\a maxw, \a
+ maxh)). Sets the maximum width to \a maxw and the maximum height
+ to \a maxh.
+*/
+void QWidget::setMaximumSize(int maxw, int maxh)
+{
+ Q_D(QWidget);
+ if (!d->setMaximumSize_helper(maxw, maxh))
+ return;
+
+ if (isWindow())
+ d->setConstraints_sys();
+ if (maxw < width() || maxh < height()) {
+ bool resized = testAttribute(Qt::WA_Resized);
+ resize(qMin(maxw,width()), qMin(maxh,height()));
+ setAttribute(Qt::WA_Resized, resized); //not a user resize
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (d->extra) {
+ if (d->extra->proxyWidget)
+ d->extra->proxyWidget->setMaximumSize(maxw, maxh);
+ }
+#endif
+
+ d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
+}
+
+/*!
+ \overload
+
+ Sets the x (width) size increment to \a w and the y (height) size
+ increment to \a h.
+*/
+void QWidget::setSizeIncrement(int w, int h)
+{
+ Q_D(QWidget);
+ d->createTLExtra();
+ QTLWExtra* x = d->topData();
+ if (x->incw == w && x->inch == h)
+ return;
+ x->incw = w;
+ x->inch = h;
+ if (isWindow())
+ d->setConstraints_sys();
+}
+
+/*!
+ \overload
+
+ This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
+ the widgets base size to width \a basew and height \a baseh.
+*/
+void QWidget::setBaseSize(int basew, int baseh)
+{
+ Q_D(QWidget);
+ d->createTLExtra();
+ QTLWExtra* x = d->topData();
+ if (x->basew == basew && x->baseh == baseh)
+ return;
+ x->basew = basew;
+ x->baseh = baseh;
+ if (isWindow())
+ d->setConstraints_sys();
+}
+
+/*!
+ Sets both the minimum and maximum sizes of the widget to \a s,
+ thereby preventing it from ever growing or shrinking.
+
+ This will override the default size constraints set by QLayout.
+
+ Alternatively, if you want the widget to have a
+ fixed size based on its contents, you can call
+ QLayout::setSizeConstraint(QLayout::SetFixedSize);
+
+ \sa maximumSize, minimumSize
+*/
+
+void QWidget::setFixedSize(const QSize & s)
+{
+ setFixedSize(s.width(), s.height());
+}
+
+
+/*!
+ \fn void QWidget::setFixedSize(int w, int h)
+ \overload
+
+ Sets the width of the widget to \a w and the height to \a h.
+*/
+
+void QWidget::setFixedSize(int w, int h)
+{
+ Q_D(QWidget);
+#ifdef Q_WS_QWS
+ // temporary fix for 4.3.x.
+ // Should move the embedded spesific contraints in setMinimumSize_helper into QLayout
+ int tmpW = w;
+ int tmpH = h;
+ bool minSizeSet = d->setMinimumSize_helper(tmpW, tmpH);
+#else
+ bool minSizeSet = d->setMinimumSize_helper(w, h);
+#endif
+ bool maxSizeSet = d->setMaximumSize_helper(w, h);
+ if (!minSizeSet && !maxSizeSet)
+ return;
+
+ if (isWindow())
+ d->setConstraints_sys();
+ else
+ d->updateGeometry_helper(true);
+
+ resize(w, h);
+}
+
+void QWidget::setMinimumWidth(int w)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
+ setMinimumSize(w, minimumSize().height());
+ d->extra->explicitMinSize = expl;
+}
+
+void QWidget::setMinimumHeight(int h)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
+ setMinimumSize(minimumSize().width(), h);
+ d->extra->explicitMinSize = expl;
+}
+
+void QWidget::setMaximumWidth(int w)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
+ setMaximumSize(w, maximumSize().height());
+ d->extra->explicitMaxSize = expl;
+}
+
+void QWidget::setMaximumHeight(int h)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
+ setMaximumSize(maximumSize().width(), h);
+ d->extra->explicitMaxSize = expl;
+}
+
+/*!
+ Sets both the minimum and maximum width of the widget to \a w
+ without changing the heights. Provided for convenience.
+
+ \sa sizeHint() minimumSize() maximumSize() setFixedSize()
+*/
+
+void QWidget::setFixedWidth(int w)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
+ uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
+ setMinimumSize(w, minimumSize().height());
+ setMaximumSize(w, maximumSize().height());
+ d->extra->explicitMinSize = explMin;
+ d->extra->explicitMaxSize = explMax;
+}
+
+
+/*!
+ Sets both the minimum and maximum heights of the widget to \a h
+ without changing the widths. Provided for convenience.
+
+ \sa sizeHint() minimumSize() maximumSize() setFixedSize()
+*/
+
+void QWidget::setFixedHeight(int h)
+{
+ Q_D(QWidget);
+ d->createExtra();
+ uint explMin = d->extra->explicitMinSize | Qt::Vertical;
+ uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
+ setMinimumSize(minimumSize().width(), h);
+ setMaximumSize(maximumSize().width(), h);
+ d->extra->explicitMinSize = explMin;
+ d->extra->explicitMaxSize = explMax;
+}
+
+
+/*!
+ Translates the widget coordinate \a pos to the coordinate system
+ of \a parent. The \a parent must not be 0 and must be a parent
+ of the calling widget.
+
+ \sa mapFrom() mapToParent() mapToGlobal() underMouse()
+*/
+
+QPoint QWidget::mapTo(QWidget * parent, const QPoint & pos) const
+{
+ QPoint p = pos;
+ if (parent) {
+ const QWidget * w = this;
+ while (w != parent) {
+ Q_ASSERT_X(w, "QWidget::mapTo(QWidget *parent, const QPoint &pos)",
+ "parent must be in parent hierarchy");
+ p = w->mapToParent(p);
+ w = w->parentWidget();
+ }
+ }
+ return p;
+}
+
+
+/*!
+ Translates the widget coordinate \a pos from the coordinate system
+ of \a parent to this widget's coordinate system. The \a parent
+ must not be 0 and must be a parent of the calling widget.
+
+ \sa mapTo() mapFromParent() mapFromGlobal() underMouse()
+*/
+
+QPoint QWidget::mapFrom(QWidget * parent, const QPoint & pos) const
+{
+ QPoint p(pos);
+ if (parent) {
+ const QWidget * w = this;
+ while (w != parent) {
+ Q_ASSERT_X(w, "QWidget::mapFrom(QWidget *parent, const QPoint &pos)",
+ "parent must be in parent hierarchy");
+
+ p = w->mapFromParent(p);
+ w = w->parentWidget();
+ }
+ }
+ return p;
+}
+
+
+/*!
+ Translates the widget coordinate \a pos to a coordinate in the
+ parent widget.
+
+ Same as mapToGlobal() if the widget has no parent.
+
+ \sa mapFromParent() mapTo() mapToGlobal() underMouse()
+*/
+
+QPoint QWidget::mapToParent(const QPoint &pos) const
+{
+ return pos + data->crect.topLeft();
+}
+
+/*!
+ Translates the parent widget coordinate \a pos to widget
+ coordinates.
+
+ Same as mapFromGlobal() if the widget has no parent.
+
+ \sa mapToParent() mapFrom() mapFromGlobal() underMouse()
+*/
+
+QPoint QWidget::mapFromParent(const QPoint &pos) const
+{
+ return pos - data->crect.topLeft();
+}
+
+
+/*!
+ Returns the window for this widget, i.e. the next ancestor widget
+ that has (or could have) a window-system frame.
+
+ If the widget is a window, the widget itself is returned.
+
+ Typical usage is changing the window title:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 3
+
+ \sa isWindow()
+*/
+
+QWidget *QWidget::window() const
+{
+ QWidget *w = (QWidget *)this;
+ QWidget *p = w->parentWidget();
+ while (!w->isWindow() && p) {
+ w = p;
+ p = p->parentWidget();
+ }
+ return w;
+}
+
+/*!
+ \since 4.4
+
+ Returns the native parent for this widget, i.e. the next ancestor widget
+ that has a system identifier, or 0 if it does not have any native parent.
+
+ \sa effectiveWinId()
+*/
+QWidget *QWidget::nativeParentWidget() const
+{
+ QWidget *parent = parentWidget();
+ while (parent && !parent->internalWinId())
+ parent = parent->parentWidget();
+ return parent;
+}
+
+/*! \fn QWidget *QWidget::topLevelWidget() const
+ \obsolete
+
+ Use window() instead.
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ Returns the color role used for painting the widget's background.
+
+ Use QPalette(backgroundRole(()) instead.
+*/
+Qt::BackgroundMode QWidget::backgroundMode() const
+{
+ if (testAttribute(Qt::WA_NoSystemBackground))
+ return Qt::NoBackground;
+ switch(backgroundRole()) {
+ case QPalette::WindowText:
+ return Qt::PaletteForeground;
+ case QPalette::Button:
+ return Qt::PaletteButton;
+ case QPalette::Light:
+ return Qt::PaletteLight;
+ case QPalette::Midlight:
+ return Qt::PaletteMidlight;
+ case QPalette::Dark:
+ return Qt::PaletteDark;
+ case QPalette::Mid:
+ return Qt::PaletteMid;
+ case QPalette::Text:
+ return Qt::PaletteText;
+ case QPalette::BrightText:
+ return Qt::PaletteBrightText;
+ case QPalette::Base:
+ return Qt::PaletteBase;
+ case QPalette::Window:
+ return Qt::PaletteBackground;
+ case QPalette::Shadow:
+ return Qt::PaletteShadow;
+ case QPalette::Highlight:
+ return Qt::PaletteHighlight;
+ case QPalette::HighlightedText:
+ return Qt::PaletteHighlightedText;
+ case QPalette::ButtonText:
+ return Qt::PaletteButtonText;
+ case QPalette::Link:
+ return Qt::PaletteLink;
+ case QPalette::LinkVisited:
+ return Qt::PaletteLinkVisited;
+ default:
+ break;
+ }
+ return Qt::NoBackground;
+}
+
+/*!
+ \fn void QWidget::setBackgroundMode(Qt::BackgroundMode
+ widgetBackground, Qt::BackgroundMode paletteBackground)
+
+ Sets the color role used for painting the widget's background to
+ background mode \a widgetBackground. The \a paletteBackground mode
+ parameter is ignored.
+*/
+void QWidget::setBackgroundMode(Qt::BackgroundMode m, Qt::BackgroundMode)
+{
+ Q_D(QWidget);
+ if(m == Qt::NoBackground) {
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ return;
+ }
+ setAttribute(Qt::WA_NoSystemBackground, false);
+ d->fg_role = QPalette::NoRole;
+ QPalette::ColorRole role = d->bg_role;
+ switch(m) {
+ case Qt::FixedColor:
+ case Qt::FixedPixmap:
+ break;
+ case Qt::PaletteForeground:
+ role = QPalette::WindowText;
+ break;
+ case Qt::PaletteButton:
+ role = QPalette::Button;
+ break;
+ case Qt::PaletteLight:
+ role = QPalette::Light;
+ break;
+ case Qt::PaletteMidlight:
+ role = QPalette::Midlight;
+ break;
+ case Qt::PaletteDark:
+ role = QPalette::Dark;
+ break;
+ case Qt::PaletteMid:
+ role = QPalette::Mid;
+ break;
+ case Qt::PaletteText:
+ role = QPalette::Text;
+ break;
+ case Qt::PaletteBrightText:
+ role = QPalette::BrightText;
+ break;
+ case Qt::PaletteBase:
+ role = QPalette::Base;
+ break;
+ case Qt::PaletteBackground:
+ role = QPalette::Window;
+ break;
+ case Qt::PaletteShadow:
+ role = QPalette::Shadow;
+ break;
+ case Qt::PaletteHighlight:
+ role = QPalette::Highlight;
+ break;
+ case Qt::PaletteHighlightedText:
+ role = QPalette::HighlightedText;
+ break;
+ case Qt::PaletteButtonText:
+ role = QPalette::ButtonText;
+ break;
+ case Qt::PaletteLink:
+ role = QPalette::Link;
+ break;
+ case Qt::PaletteLinkVisited:
+ role = QPalette::LinkVisited;
+ break;
+ case Qt::X11ParentRelative:
+ d->fg_role = role = QPalette::NoRole;
+ default:
+ break;
+ }
+ setBackgroundRole(role);
+}
+
+/*!
+ The widget mapper is no longer part of the public API.
+*/
+QT3_SUPPORT QWidgetMapper *QWidget::wmapper() { return QWidgetPrivate::mapper; }
+
+#endif
+
+
+/*!
+ Returns the background role of the widget.
+
+ The background role defines the brush from the widget's \l palette that
+ is used to render the background.
+
+ If no explicit background role is set, the widget inherts its parent
+ widget's background role.
+
+ \sa setBackgroundRole(), foregroundRole()
+ */
+QPalette::ColorRole QWidget::backgroundRole() const
+{
+
+ const QWidget *w = this;
+ do {
+ QPalette::ColorRole role = w->d_func()->bg_role;
+ if (role != QPalette::NoRole)
+ return role;
+ if (w->isWindow() || w->windowType() == Qt::SubWindow)
+ break;
+ w = w->parentWidget();
+ } while (w);
+ return QPalette::Window;
+}
+
+/*!
+ Sets the background role of the widget to \a role.
+
+ The background role defines the brush from the widget's \l palette that
+ is used to render the background.
+
+ If \a role is QPalette::NoRole, then the widget inherits its
+ parent's background role.
+
+ \sa backgroundRole(), foregroundRole()
+ */
+
+void QWidget::setBackgroundRole(QPalette::ColorRole role)
+{
+ Q_D(QWidget);
+ d->bg_role = role;
+ d->updateSystemBackground();
+ d->propagatePaletteChange();
+ d->updateIsOpaque();
+}
+
+/*!
+ Returns the foreground role.
+
+ The foreground role defines the color from the widget's \l palette that
+ is used to draw the foreground.
+
+ If no explicit foreground role is set, the function returns a role
+ that contrasts with the background role.
+
+ \sa setForegroundRole(), backgroundRole()
+ */
+QPalette::ColorRole QWidget::foregroundRole() const
+{
+ Q_D(const QWidget);
+ QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
+ if (rl != QPalette::NoRole)
+ return rl;
+ QPalette::ColorRole role = QPalette::WindowText;
+ switch (backgroundRole()) {
+ case QPalette::Button:
+ role = QPalette::ButtonText;
+ break;
+ case QPalette::Base:
+ role = QPalette::Text;
+ break;
+ case QPalette::Dark:
+ case QPalette::Shadow:
+ role = QPalette::Light;
+ break;
+ case QPalette::Highlight:
+ role = QPalette::HighlightedText;
+ break;
+ case QPalette::ToolTipBase:
+ role = QPalette::ToolTipText;
+ break;
+ default:
+ ;
+ }
+ return role;
+}
+
+/*!
+ Sets the foreground role of the widget to \a role.
+
+ The foreground role defines the color from the widget's \l palette that
+ is used to draw the foreground.
+
+ If \a role is QPalette::NoRole, the widget uses a foreground role
+ that contrasts with the background role.
+
+ \sa foregroundRole(), backgroundRole()
+ */
+void QWidget::setForegroundRole(QPalette::ColorRole role)
+{
+ Q_D(QWidget);
+ d->fg_role = role;
+ d->updateSystemBackground();
+ d->propagatePaletteChange();
+}
+
+/*!
+ \property QWidget::palette
+ \brief the widget's palette
+
+ This property describes the widget's palette. The palette is used by the
+ widget's style when rendering standard components, and is available as a
+ means to ensure that custom widgets can maintain consistency with the
+ native platform's look and feel. It's common that different platforms, or
+ different styles, have different palettes.
+
+ When you assign a new palette to a widget, the color roles from this
+ palette are combined with the widget's default palette to form the
+ widget's final palette. The palette entry for the widget's background role
+ is used to fill the widget's background (see QWidget::autoFillBackground),
+ and the foreground role initializes QPainter's pen.
+
+ The default depends on the system environment. QApplication maintains a
+ system/theme palette which serves as a default for all widgets. There may
+ also be special palette defaults for certain types of widgets (e.g., on
+ Windows XP and Vista, all classes that derive from QMenuBar have a special
+ default palette). You can also define default palettes for widgets
+ yourself by passing a custom palette and the name of a widget to
+ QApplication::setPalette(). Finally, the style always has the option of
+ polishing the palette as it's assigned (see QStyle::polish()).
+
+ QWidget propagates explicit palette roles from parent to child. If you
+ assign a brush or color to a specific role on a palette and assign that
+ palette to a widget, that role will propagate to all the widget's
+ children, overriding any system defaults for that role. Note that palettes
+ by default don't propagate to windows (see isWindow()) unless the
+ Qt::WA_WindowPropagation attribute is enabled.
+
+ QWidget's palette propagation is similar to its font propagation.
+
+ The current style, which is used to render the content of all standard Qt
+ widgets, is free to choose colors and brushes from the widget palette, or
+ in some cases, to ignore the palette (partially, or completely). In
+ particular, certain styles like GTK style, Mac style, Windows XP, and
+ Vista style, depend on third party APIs to render the content of widgets,
+ and these styles typically do not follow the palette. Because of this,
+ assigning roles to a widget's palette is not guaranteed to change the
+ appearance of the widget. Instead, you may choose to apply a \l
+ styleSheet. You can refer to our Knowledge Base article
+ \l{http://qtsoftware.com/developer/knowledgebase/22}{here} for more
+ information.
+
+ \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
+ When using style sheets, the palette of a widget can be customized using
+ the "color", "background-color", "selection-color",
+ "selection-background-color" and "alternate-background-color".
+
+ \sa QApplication::palette(), QWidget::font()
+*/
+const QPalette &QWidget::palette() const
+{
+ if (!isEnabled()) {
+ data->pal.setCurrentColorGroup(QPalette::Disabled);
+ } else if ((!isVisible() || isActiveWindow())
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
+#endif
+ ) {
+ data->pal.setCurrentColorGroup(QPalette::Active);
+ } else {
+#ifdef Q_WS_MAC
+ extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
+ if (qt_mac_can_clickThrough(this))
+ data->pal.setCurrentColorGroup(QPalette::Active);
+ else
+#endif
+ data->pal.setCurrentColorGroup(QPalette::Inactive);
+ }
+ return data->pal;
+}
+
+void QWidget::setPalette(const QPalette &palette)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
+
+ // Determine which palette is inherited from this widget's ancestors and
+ // QApplication::palette, resolve this against \a palette (attributes from
+ // the inherited palette are copied over this widget's palette). Then
+ // propagate this palette to this widget's children.
+ QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
+ QPalette resolvedPalette = palette.resolve(naturalPalette);
+ d->setPalette_helper(resolvedPalette);
+}
+
+/*!
+ \internal
+
+ Returns the palette that the widget \a w inherits from its ancestors and
+ QApplication::palette. \a inheritedMask is the combination of the widget's
+ ancestors palette request masks (i.e., which attributes from the parent
+ widget's palette are implicitly imposed on this widget by the user). Note
+ that this font does not take into account the palette set on \a w itself.
+*/
+QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const
+{
+ Q_Q(const QWidget);
+ QPalette naturalPalette = QApplication::palette(q);
+ if (!q->testAttribute(Qt::WA_StyleSheet)
+ && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation) || (extra && extra->proxyWidget))) {
+ if (QWidget *p = q->parentWidget()) {
+ if (!p->testAttribute(Qt::WA_StyleSheet)) {
+ if (!naturalPalette.isCopyOf(QApplication::palette())) {
+ QPalette inheritedPalette = p->palette();
+ inheritedPalette.resolve(inheritedMask);
+ naturalPalette = inheritedPalette.resolve(naturalPalette);
+ } else {
+ naturalPalette = p->palette();
+ }
+ }
+ } else if (extra && extra->proxyWidget) {
+#ifndef QT_NO_GRAPHICSVIEW
+ QPalette inheritedPalette = extra->proxyWidget->palette();
+ inheritedPalette.resolve(inheritedMask);
+ naturalPalette = inheritedPalette.resolve(naturalPalette);
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ }
+ naturalPalette.resolve(0);
+ return naturalPalette;
+}
+/*!
+ \internal
+
+ Determine which palette is inherited from this widget's ancestors and
+ QApplication::palette, resolve this against this widget's palette
+ (attributes from the inherited palette are copied over this widget's
+ palette). Then propagate this palette to this widget's children.
+*/
+void QWidgetPrivate::resolvePalette()
+{
+ QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
+ QPalette resolvedPalette = data.pal.resolve(naturalPalette);
+ setPalette_helper(resolvedPalette);
+}
+
+void QWidgetPrivate::setPalette_helper(const QPalette &palette)
+{
+ Q_Q(QWidget);
+ if (data.pal == palette && data.pal.resolve() == palette.resolve())
+ return;
+ data.pal = palette;
+ updateSystemBackground();
+ propagatePaletteChange();
+ updateIsOpaque();
+ q->update();
+ updateIsOpaque();
+}
+
+/*!
+ \property QWidget::font
+ \brief the font currently set for the widget
+
+ This property describes the widget's requested font. The font is used by
+ the widget's style when rendering standard components, and is available as
+ a means to ensure that custom widgets can maintain consistency with the
+ native platform's look and feel. It's common that different platforms, or
+ different styles, define different fonts for an application.
+
+ When you assign a new font to a widget, the properties from this font are
+ combined with the widget's default font to form the widget's final
+ font. You can call fontInfo() to get a copy of the widget's final
+ font. The final font is also used to initialize QPainter's font.
+
+ The default depends on the system environment. QApplication maintains a
+ system/theme font which serves as a default for all widgets. There may
+ also be special font defaults for certain types of widgets. You can also
+ define default fonts for widgets yourself by passing a custom font and the
+ name of a widget to QApplication::setFont(). Finally, the font is matched
+ against Qt's font database to find the best match.
+
+ QWidget propagates explicit font properties from parent to child. If you
+ change a specific property on a font and assign that font to a widget,
+ that property will propagate to all the widget's children, overriding any
+ system defaults for that property. Note that fonts by default don't
+ propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
+ attribute is enabled.
+
+ QWidget's font propagation is similar to its palette propagation.
+
+ The current style, which is used to render the content of all standard Qt
+ widgets, is free to choose to use the widget font, or in some cases, to
+ ignore it (partially, or completely). In particular, certain styles like
+ GTK style, Mac style, Windows XP, and Vista style, apply special
+ modifications to the widget font to match the platform's native look and
+ feel. Because of this, assigning properties to a widget's font is not
+ guaranteed to change the appearance of the widget. Instead, you may choose
+ to apply a \l styleSheet.
+
+ \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
+ style sheets will take precedence if the settings conflict.
+
+ \sa fontInfo(), fontMetrics()
+*/
+
+void QWidget::setFont(const QFont &font)
+{
+ Q_D(QWidget);
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ const QStyleSheetStyle* style;
+ if (d->extra && (style = qobject_cast<const QStyleSheetStyle*>(d->extra->style))) {
+ style->saveWidgetFont(this, font);
+ }
+#endif
+
+ setAttribute(Qt::WA_SetFont, font.resolve() != 0);
+
+ // Determine which font is inherited from this widget's ancestors and
+ // QApplication::font, resolve this against \a font (attributes from the
+ // inherited font are copied over). Then propagate this font to this
+ // widget's children.
+ QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
+ QFont resolvedFont = font.resolve(naturalFont);
+ d->setFont_helper(resolvedFont);
+}
+
+/*
+ \internal
+
+ Returns the font that the widget \a w inherits from its ancestors and
+ QApplication::font. \a inheritedMask is the combination of the widget's
+ ancestors font request masks (i.e., which attributes from the parent
+ widget's font are implicitly imposed on this widget by the user). Note
+ that this font does not take into account the font set on \a w itself.
+
+ ### Stylesheet has a different font propagation mechanism. When a stylesheet
+ is applied, fonts are not propagated anymore
+*/
+QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
+{
+ Q_Q(const QWidget);
+ QFont naturalFont = QApplication::font(q);
+ if (!q->testAttribute(Qt::WA_StyleSheet)
+ && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation) || (extra && extra->proxyWidget))) {
+ if (QWidget *p = q->parentWidget()) {
+ if (!p->testAttribute(Qt::WA_StyleSheet)) {
+ if (!naturalFont.isCopyOf(QApplication::font())) {
+ QFont inheritedFont = p->font();
+ inheritedFont.resolve(inheritedMask);
+ naturalFont = inheritedFont.resolve(naturalFont);
+ } else {
+ naturalFont = p->font();
+ }
+ }
+ } else if (extra && extra->proxyWidget) {
+#ifndef QT_NO_GRAPHICSVIEW
+ QFont inheritedFont = extra->proxyWidget->font();
+ inheritedFont.resolve(inheritedMask);
+ naturalFont = inheritedFont.resolve(naturalFont);
+#endif //QT_NO_GRAPHICSVIEW
+ }
+ }
+ naturalFont.resolve(0);
+ return naturalFont;
+}
+
+/*!
+ \internal
+
+ Determine which font is implicitly imposed on this widget by its ancestors
+ and QApplication::font, resolve this against its own font (attributes from
+ the implicit font are copied over). Then propagate this font to this
+ widget's children.
+*/
+void QWidgetPrivate::resolveFont()
+{
+ QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
+ QFont resolvedFont = data.fnt.resolve(naturalFont);
+ setFont_helper(resolvedFont);
+}
+
+/*!
+ \internal
+
+ Assign \a font to this widget, and propagate it to all children, except
+ style sheet widgets (handled differently) and windows that don't enable
+ window propagation. \a implicitMask is the union of all ancestor widgets'
+ font request masks, and determines which attributes from this widget's
+ font should propagate.
+*/
+void QWidgetPrivate::updateFont(const QFont &font)
+{
+ Q_Q(QWidget);
+#ifndef QT_NO_STYLE_STYLESHEET
+ const QStyleSheetStyle* cssStyle;
+ cssStyle = extra ? qobject_cast<const QStyleSheetStyle*>(extra->style) : 0;
+#endif
+
+#ifdef QT3_SUPPORT
+ QFont old = data.fnt;
+#endif
+ data.fnt = QFont(font, q);
+#if defined(Q_WS_X11)
+ // make sure the font set on this widget is associated with the correct screen
+ data.fnt.x11SetScreen(xinfo.screen());
+#endif
+ // Combine new mask with natural mask and propagate to children.
+ if (!q->parentWidget() && extra && extra->proxyWidget) {
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *p = extra->proxyWidget;
+ inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolve();
+#endif //QT_NO_GRAPHICSVIEW
+ } else if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
+ inheritedFontResolveMask = 0;
+ }
+ uint newMask = data.fnt.resolve() | inheritedFontResolveMask;
+
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (w) {
+ if (0) {
+#ifndef QT_NO_STYLE_STYLESHEET
+ } else if (w->testAttribute(Qt::WA_StyleSheet)) {
+ // Style sheets follow a different font propagation scheme.
+ if (cssStyle)
+ cssStyle->updateStyleSheetFont(w);
+#endif
+ } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
+ // Propagate font changes.
+ QWidgetPrivate *wd = w->d_func();
+ wd->inheritedFontResolveMask = newMask;
+ wd->resolveFont();
+ }
+ }
+ }
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (cssStyle) {
+ cssStyle->updateStyleSheetFont(q);
+ }
+#endif
+
+ QEvent e(QEvent::FontChange);
+ QApplication::sendEvent(q, &e);
+#ifdef QT3_SUPPORT
+ q->fontChange(old);
+#endif
+}
+
+void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
+{
+ Q_Q(QWidget);
+
+ if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
+ return;
+ q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
+ if (!children.isEmpty()) {
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
+ w->d_func()->setLayoutDirection_helper(direction);
+ }
+ }
+ QEvent e(QEvent::LayoutDirectionChange);
+ QApplication::sendEvent(q, &e);
+}
+
+void QWidgetPrivate::resolveLayoutDirection()
+{
+ Q_Q(const QWidget);
+ if (!q->testAttribute(Qt::WA_SetLayoutDirection))
+ setLayoutDirection_helper(q->isWindow() ? QApplication::layoutDirection() : q->parentWidget()->layoutDirection());
+}
+
+/*!
+ \property QWidget::layoutDirection
+
+ \brief the layout direction for this widget
+
+ By default, this property is set to Qt::LeftToRight.
+
+ When the layout direction is set on a widget, it will propagate to
+ the widget's children. Children added after the call to \c
+ setLayoutDirection() will not inherit the parent's layout
+ direction.
+
+ \sa QApplication::layoutDirection
+*/
+void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
+{
+ Q_D(QWidget);
+
+ setAttribute(Qt::WA_SetLayoutDirection);
+ d->setLayoutDirection_helper(direction);
+}
+
+Qt::LayoutDirection QWidget::layoutDirection() const
+{
+ return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
+}
+
+void QWidget::unsetLayoutDirection()
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetLayoutDirection, false);
+ d->resolveLayoutDirection();
+}
+
+/*!
+ \fn QFontMetrics QWidget::fontMetrics() const
+
+ Returns the font metrics for the widget's current font.
+ Equivalent to QFontMetrics(widget->font()).
+
+ \sa font(), fontInfo(), setFont()
+*/
+
+/*!
+ \fn QFontInfo QWidget::fontInfo() const
+
+ Returns the font info for the widget's current font.
+ Equivalent to QFontInto(widget->font()).
+
+ \sa font(), fontMetrics(), setFont()
+*/
+
+
+/*!
+ \property QWidget::cursor
+ \brief the cursor shape for this widget
+
+ The mouse cursor will assume this shape when it's over this
+ widget. See the \link Qt::CursorShape list of predefined cursor
+ objects\endlink for a range of useful shapes.
+
+ An editor widget might use an I-beam cursor:
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 6
+
+ If no cursor has been set, or after a call to unsetCursor(), the
+ parent's cursor is used.
+
+ By default, this property contains a cursor with the Qt::ArrowCursor
+ shape.
+
+ \sa QApplication::setOverrideCursor()
+*/
+
+#ifndef QT_NO_CURSOR
+QCursor QWidget::cursor() const
+{
+ Q_D(const QWidget);
+ if (testAttribute(Qt::WA_SetCursor))
+ return (d->extra && d->extra->curs)
+ ? *d->extra->curs
+ : QCursor(Qt::ArrowCursor);
+ if (isWindow() || !parentWidget())
+ return QCursor(Qt::ArrowCursor);
+ return parentWidget()->cursor();
+}
+
+void QWidget::setCursor(const QCursor &cursor)
+{
+ Q_D(QWidget);
+// On Mac we must set the cursor even if it is the ArrowCursor.
+#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS)
+ if (cursor.shape() != Qt::ArrowCursor
+ || (d->extra && d->extra->curs))
+#endif
+ {
+ d->createExtra();
+ delete d->extra->curs;
+ d->extra->curs = new QCursor(cursor);
+ }
+ setAttribute(Qt::WA_SetCursor);
+ d->setCursor_sys(cursor);
+
+ QEvent event(QEvent::CursorChange);
+ QApplication::sendEvent(this, &event);
+}
+
+void QWidget::unsetCursor()
+{
+ Q_D(QWidget);
+ if (d->extra) {
+ delete d->extra->curs;
+ d->extra->curs = 0;
+ }
+ if (!isWindow())
+ setAttribute(Qt::WA_SetCursor, false);
+ d->unsetCursor_sys();
+
+ QEvent event(QEvent::CursorChange);
+ QApplication::sendEvent(this, &event);
+}
+
+#endif
+
+/*!
+ \enum QWidget::RenderFlag
+
+ This enum describes how to render the widget when calling QWidget::render().
+
+ \value DrawWindowBackground If you enable this option, the widget's background
+ is rendered into the target even if autoFillBackground is not set. By default,
+ this option is enabled.
+
+ \value DrawChildren If you enable this option, the widget's children
+ are rendered recursively into the target. By default, this option is enabled.
+
+ \value IgnoreMask If you enable this option, the widget's QWidget::mask()
+ is ignored when rendering into the target. By default, this option is disabled.
+
+ \since 4.3
+*/
+
+/*!
+ \since 4.3
+
+ Renders the \a sourceRegion of this widget into the \a target
+ using \a renderFlags to determine how to render. Rendering
+ starts at \a targetOffset in the \a target. For example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 7
+
+ If \a sourceRegion is a null region, this function will use QWidget::rect() as
+ the region, i.e. the entire widget.
+
+ Ensure that you call QPainter::end() for the \a target device's
+ active painter (if any) before rendering. For example:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 8
+
+ \note To obtain the contents of an OpenGL widget, use QGLWidget::grabFrameBuffer()
+ or QGLWidget::renderPixmap() instead.
+*/
+void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
+ const QRegion &sourceRegion, RenderFlags renderFlags)
+{
+ Q_D(QWidget);
+ if (!target) {
+ qWarning("QWidget::render: null pointer to paint device");
+ return;
+ }
+
+ const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
+ QRegion paintRegion = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (paintRegion.isEmpty())
+ return;
+
+#ifndef Q_WS_MAC
+ QPainter *oldSharedPainter = inRenderWithPainter ? d->sharedPainter() : 0;
+
+ // Use the target's shared painter if set (typically set when doing
+ // "other->render(widget);" in the widget's paintEvent.
+ if (target->devType() == QInternal::Widget) {
+ QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
+ if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
+ QPainter *targetPainter = targetPrivate->sharedPainter();
+ if (targetPainter && targetPainter->isActive())
+ d->setSharedPainter(targetPainter);
+ }
+ }
+#endif
+
+ // Use the target's redirected device if set and adjust offset and paint
+ // region accordingly. This is typically the case when people call render
+ // from the paintEvent.
+ QPoint offset = targetOffset;
+ offset -= paintRegion.boundingRect().topLeft();
+ QPoint redirectionOffset;
+ QPaintDevice *redirected = 0;
+
+ if (target->devType() == QInternal::Widget)
+ redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
+ if (!redirected)
+ redirected = QPainter::redirected(target, &redirectionOffset);
+
+ if (redirected) {
+ target = redirected;
+ offset -= redirectionOffset;
+ if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
+ const QRegion redirectedSystemClip = redirected->paintEngine()->systemClip();
+ if (!redirectedSystemClip.isEmpty())
+ paintRegion &= redirectedSystemClip.translated(-offset);
+ }
+ }
+
+ // Set backingstore flags.
+ int flags = QWidgetPrivate::DrawPaintOnScreen | QWidgetPrivate::DrawInvisible;
+ if (renderFlags & DrawWindowBackground)
+ flags |= QWidgetPrivate::DrawAsRoot;
+
+ if (renderFlags & DrawChildren)
+ flags |= QWidgetPrivate::DrawRecursive;
+ else
+ flags |= QWidgetPrivate::DontSubtractOpaqueChildren;
+
+#ifdef Q_WS_QWS
+ flags |= QWidgetPrivate::DontSetCompositionMode;
+#endif
+
+ if (target->devType() == QInternal::Printer) {
+ QPainter p(target);
+ d->render_helper(&p, targetOffset, paintRegion, renderFlags);
+ return;
+ }
+
+#ifndef Q_WS_MAC
+ // Render via backingstore.
+ d->drawWidget(target, paintRegion, offset, flags, d->sharedPainter());
+
+ // Restore shared painter.
+ if (oldSharedPainter)
+ d->setSharedPainter(oldSharedPainter);
+#else
+ // Render via backingstore (no shared painter).
+ d->drawWidget(target, paintRegion, offset, flags, 0);
+#endif
+}
+
+/*!
+ \overload
+
+ Renders the widget into the \a painter's QPainter::device().
+
+ Transformations and settings applied to the \a painter will be used
+ when rendering.
+
+ \note The \a painter must be active. On Mac OS X the widget will be
+ rendered into a QPixmap and then drawn by the \a painter.
+
+ \sa QPainter::device()
+*/
+void QWidget::render(QPainter *painter, const QPoint &targetOffset,
+ const QRegion &sourceRegion, RenderFlags renderFlags)
+{
+ if (!painter) {
+ qWarning("QWidget::render: Null pointer to painter");
+ return;
+ }
+
+ if (!painter->isActive()) {
+ qWarning("QWidget::render: Cannot render with an inactive painter");
+ return;
+ }
+
+ const qreal opacity = painter->opacity();
+ if (qFuzzyCompare(opacity + 1, qreal(1.0)))
+ return; // Fully transparent.
+
+ Q_D(QWidget);
+ const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
+ const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (toBePainted.isEmpty())
+ return;
+
+ if (!d->extra)
+ d->createExtra();
+ d->extra->inRenderWithPainter = true;
+
+#ifdef Q_WS_MAC
+ d->render_helper(painter, targetOffset, toBePainted, renderFlags);
+#else
+ QPaintEngine *engine = painter->paintEngine();
+ Q_ASSERT(engine);
+ QPaintEnginePrivate *enginePriv = engine->d_func();
+ Q_ASSERT(enginePriv);
+ QPaintDevice *target = painter->worldMatrixEnabled() ? engine->paintDevice() : painter->device();
+ Q_ASSERT(target);
+
+ // Render via a pixmap when dealing with non-opaque painters or printers.
+ if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
+ d->render_helper(painter, targetOffset, toBePainted, renderFlags);
+ d->extra->inRenderWithPainter = false;
+ return;
+ }
+
+ // Set new shared painter.
+ QPainter *oldPainter = d->sharedPainter();
+ d->setSharedPainter(painter);
+
+ // Save current system clip, viewport and transform,
+ const QTransform oldTransform = enginePriv->systemTransform;
+ const QRegion oldSystemClip = enginePriv->systemClip;
+ const QRegion oldSystemViewport = enginePriv->systemViewport;
+
+ // This ensures that transformed system clips are inside the current system clip.
+ enginePriv->setSystemViewport(oldSystemClip);
+
+ render(target, targetOffset, toBePainted, renderFlags);
+
+ // Restore system clip, viewport and transform.
+ enginePriv->systemClip = oldSystemClip;
+ enginePriv->setSystemViewport(oldSystemViewport);
+ enginePriv->setSystemTransform(oldTransform);
+
+ // Restore shared painter.
+ d->setSharedPainter(oldPainter);
+#endif
+
+ d->extra->inRenderWithPainter = false;
+}
+
+bool QWidgetPrivate::isAboutToShow() const
+{
+ if (data.in_show)
+ return true;
+
+ Q_Q(const QWidget);
+ if (q->isHidden())
+ return false;
+
+ // The widget will be shown if any of its ancestors are about to show.
+ QWidget *parent = q->parentWidget();
+ return parent ? parent->d_func()->isAboutToShow() : false;
+}
+
+QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
+{
+ Q_Q(QWidget);
+ const bool isVisible = q->isVisible();
+
+ // Make sure the widget is laid out correctly.
+ if (!isVisible && !isAboutToShow()) {
+ QWidget *topLevel = q->window();
+ (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
+ topLevel->ensurePolished();
+
+ // Invalidate the layout of hidden ancestors (incl. myself) and pretend
+ // they're not explicitly hidden.
+ QWidget *widget = q;
+ QWidgetList hiddenWidgets;
+ while (widget) {
+ if (widget->isHidden()) {
+ widget->setAttribute(Qt::WA_WState_Hidden, false);
+ hiddenWidgets.append(widget);
+ if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
+ widget->d_func()->updateGeometry_helper(true);
+ }
+ widget = widget->parentWidget();
+ }
+
+ // Activate top-level layout.
+ if (topLevel->d_func()->layout)
+ topLevel->d_func()->layout->activate();
+
+ // Adjust size if necessary.
+ QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
+ if (topLevelExtra && !topLevelExtra->sizeAdjusted
+ && !topLevel->testAttribute(Qt::WA_Resized)) {
+ topLevel->adjustSize();
+ topLevel->setAttribute(Qt::WA_Resized, false);
+ }
+
+ // Activate child layouts.
+ topLevel->d_func()->activateChildLayoutsRecursively();
+
+ // We're not cheating with WA_WState_Hidden anymore.
+ for (int i = 0; i < hiddenWidgets.size(); ++i) {
+ QWidget *widget = hiddenWidgets.at(i);
+ widget->setAttribute(Qt::WA_WState_Hidden);
+ if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
+ widget->parentWidget()->d_func()->layout->invalidate();
+ }
+ } else if (isVisible) {
+ q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
+ }
+
+ // Calculate the region to be painted.
+ QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
+ if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
+ toBePainted &= extra->mask;
+ return toBePainted;
+}
+
+void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
+ QWidget::RenderFlags renderFlags)
+{
+ Q_ASSERT(painter);
+ Q_ASSERT(!toBePainted.isEmpty());
+
+ Q_Q(QWidget);
+#ifndef Q_WS_MAC
+ const QTransform originalTransform = painter->worldTransform();
+ const bool useDeviceCoordinates = originalTransform.isScaling();
+ if (!useDeviceCoordinates) {
+#endif
+ // Render via a pixmap.
+ const QRect rect = toBePainted.boundingRect();
+ const QSize size = rect.size();
+ if (size.isNull())
+ return;
+
+ QPixmap pixmap(size);
+ if (!(renderFlags & QWidget::DrawWindowBackground))
+ pixmap.fill(Qt::transparent);
+ q->render(&pixmap, QPoint(), toBePainted, renderFlags);
+
+ const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
+ painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
+
+ painter->drawPixmap(targetOffset, pixmap);
+
+ if (restore)
+ painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
+
+#ifndef Q_WS_MAC
+ } else {
+ // Render via a pixmap in device coordinates (to avoid pixmap scaling).
+ QTransform transform = originalTransform;
+ transform.translate(targetOffset.x(), targetOffset.y());
+
+ QPaintDevice *device = painter->device();
+ Q_ASSERT(device);
+
+ // Calculate device rect.
+ const QRectF rect(toBePainted.boundingRect());
+ QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
+ deviceRect &= QRect(0, 0, device->width(), device->height());
+
+ QPixmap pixmap(deviceRect.size());
+ pixmap.fill(Qt::transparent);
+
+ // Create a pixmap device coordinate painter.
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setRenderHints(painter->renderHints());
+ transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+ pixmapPainter.setTransform(transform);
+
+ q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
+ pixmapPainter.end();
+
+ // And then draw the pixmap.
+ painter->setTransform(QTransform());
+ painter->drawPixmap(deviceRect.topLeft(), pixmap);
+ painter->setTransform(originalTransform);
+ }
+#endif
+}
+
+void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
+ QPainter *sharedPainter, QWidgetBackingStore *backingStore)
+{
+ if (rgn.isEmpty())
+ return;
+
+ Q_Q(QWidget);
+ const bool asRoot = flags & DrawAsRoot;
+ const bool alsoOnScreen = flags & DrawPaintOnScreen;
+ const bool recursive = flags & DrawRecursive;
+ const bool alsoInvisible = flags & DrawInvisible;
+
+ Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
+
+ QRegion toBePainted(rgn);
+ if (asRoot && !alsoInvisible)
+ toBePainted &= clipRect(); //(rgn & visibleRegion());
+ if (!(flags & DontSubtractOpaqueChildren))
+ subtractOpaqueChildren(toBePainted, q->rect());
+
+ if (!toBePainted.isEmpty()) {
+ bool onScreen = paintOnScreen();
+ if (!onScreen || alsoOnScreen) {
+ //update the "in paint event" flag
+ if (q->testAttribute(Qt::WA_WState_InPaintEvent))
+ qWarning("QWidget::repaint: Recursive repaint detected");
+ q->setAttribute(Qt::WA_WState_InPaintEvent);
+
+ //clip away the new area
+#ifndef QT_NO_PAINT_DEBUG
+ bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted);
+#endif
+ QPaintEngine *paintEngine = pdev->paintEngine();
+ if (paintEngine) {
+ setRedirected(pdev, -offset);
+
+ if (sharedPainter)
+ paintEngine->d_func()->systemClip = toBePainted;
+ else
+ paintEngine->setSystemRect(q->data->crect);
+
+ //paint the background
+ if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
+ && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
+
+ QPainter p(q);
+ QPoint scrollAreaOffset;
+
+#ifndef QT_NO_SCROLLAREA
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent());
+ if (scrollArea && scrollArea->viewport() == q) {
+ QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr;
+ QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
+ scrollAreaOffset = priv->contentsOffset();
+ p.translate(-scrollAreaOffset);
+ }
+#endif // QT_NO_SCROLLAREA
+
+ paintBackground(&p, toBePainted, scrollAreaOffset, (asRoot || onScreen) ? flags | DrawAsRoot : 0);
+ }
+
+ if (!sharedPainter)
+ paintEngine->d_func()->systemClip = toBePainted.translated(offset);
+
+ if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
+ QPainter p(q);
+ QColor tint = q->palette().window().color();
+ tint.setAlphaF(qreal(.6));
+ p.fillRect(toBePainted.boundingRect(), tint);
+ }
+ }
+
+#if 0
+ qDebug() << "painting" << q << "opaque ==" << isOpaque();
+ qDebug() << "clipping to" << toBePainted << "location == " << offset
+ << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
+#endif
+
+ //actually send the paint event
+ QPaintEvent e(toBePainted);
+ QCoreApplication::sendSpontaneousEvent(q, &e);
+#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS)
+ if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
+ backingStore->markDirtyOnScreen(toBePainted, q, offset);
+#endif
+
+ //restore
+ if (paintEngine) {
+ restoreRedirected();
+ if (!sharedPainter)
+ paintEngine->setSystemRect(QRect());
+ else
+ paintEngine->d_func()->currentClipWidget = 0;
+ paintEngine->d_func()->systemClip = QRegion();
+ }
+ q->setAttribute(Qt::WA_WState_InPaintEvent, false);
+ if (q->paintingActive() && !q->testAttribute(Qt::WA_PaintOutsidePaintEvent))
+ qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
+
+ if (paintEngine && paintEngine->autoDestruct()) {
+ delete paintEngine;
+ }
+
+#ifndef QT_NO_PAINT_DEBUG
+ if (flushed)
+ QWidgetBackingStore::unflushPaint(q, toBePainted);
+#endif
+ } else if (q->isWindow()) {
+ QPaintEngine *engine = pdev->paintEngine();
+ if (engine) {
+ QPainter p(pdev);
+ p.setClipRegion(toBePainted);
+ const QBrush bg = q->palette().brush(QPalette::Window);
+ if (bg.style() == Qt::TexturePattern)
+ p.drawTiledPixmap(q->rect(), bg.texture());
+ else
+ p.fillRect(q->rect(), bg);
+
+ if (engine->autoDestruct())
+ delete engine;
+ }
+ }
+ }
+
+ if (recursive && !children.isEmpty()) {
+ paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , q->windowSurface()
+#endif
+ , sharedPainter, backingStore);
+ }
+}
+
+void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
+ const QPoint &offset, int flags
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , const QWindowSurface *currentSurface
+#endif
+ , QPainter *sharedPainter, QWidgetBackingStore *backingStore)
+{
+ QWidget *w = 0;
+ QRect boundingRect;
+ bool dirtyBoundingRect = true;
+ const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
+
+ do {
+ QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
+ if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()) {
+ if (dirtyBoundingRect) {
+ boundingRect = rgn.boundingRect();
+ dirtyBoundingRect = false;
+ }
+
+ if (qRectIntersects(boundingRect, x->data->crect)) {
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ if (x->windowSurface() == currentSurface)
+#endif
+ {
+ w = x;
+ break;
+ }
+ }
+ }
+ --index;
+ } while (index >= 0);
+
+ if (!w)
+ return;
+
+ QWidgetPrivate *wd = w->d_func();
+ const QPoint widgetPos(w->data->crect.topLeft());
+ const bool hasMask = wd->extra && wd->extra->hasMask;
+
+ if (index > 0) {
+ QRegion wr(rgn);
+ if (wd->isOpaque)
+ wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
+ paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , currentSurface
+#endif
+ , sharedPainter, backingStore);
+ }
+
+ if (w->updatesEnabled() && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)) {
+ QRegion wRegion(rgn);
+ wRegion &= w->data->crect;
+ wRegion.translate(-widgetPos);
+ if (hasMask)
+ wRegion &= wd->extra->mask;
+ wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, backingStore);
+ }
+}
+
+/*!
+ \internal
+
+ Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
+ widget and its ancestors. The search starts at \a origin (inclusive).
+ If successful, the function returns the proxy that embeds the widget, or 0 if no embedded
+ widget was found.
+*/
+QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(QWidget *origin)
+{
+ if (origin) {
+ QWExtra *extra = origin->d_func()->extra;
+ if (extra && extra->proxyWidget)
+ return extra->proxyWidget;
+ return nearestGraphicsProxyWidget(origin->parentWidget());
+ }
+ return 0;
+}
+
+/*!
+ \property QWidget::locale
+ \brief the widget's locale
+ \since 4.3
+
+ As long as no special locale has been set, this is either
+ the parent's locale or (if this widget is a top level widget),
+ the default locale.
+
+ If the widget displays dates or numbers, these should be formatted
+ using the widget's locale.
+
+ \sa QLocale QLocale::setDefault()
+*/
+
+void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
+{
+ Q_Q(QWidget);
+ if (locale == loc && !forceUpdate)
+ return;
+
+ locale = loc;
+
+ if (!children.isEmpty()) {
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget*>(children.at(i));
+ if (!w)
+ continue;
+ if (w->testAttribute(Qt::WA_SetLocale))
+ continue;
+ if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
+ continue;
+ w->d_func()->setLocale_helper(loc, forceUpdate);
+ }
+ }
+ QEvent e(QEvent::LocaleChange);
+ QApplication::sendEvent(q, &e);
+}
+
+void QWidget::setLocale(const QLocale &locale)
+{
+ Q_D(QWidget);
+
+ setAttribute(Qt::WA_SetLocale);
+ d->setLocale_helper(locale);
+}
+
+QLocale QWidget::locale() const
+{
+ Q_D(const QWidget);
+
+ return d->locale;
+}
+
+void QWidgetPrivate::resolveLocale()
+{
+ Q_Q(const QWidget);
+
+ if (!q->testAttribute(Qt::WA_SetLocale)) {
+ setLocale_helper(q->isWindow()
+ ? QLocale()
+ : q->parentWidget()->locale());
+ }
+}
+
+void QWidget::unsetLocale()
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_SetLocale, false);
+ d->resolveLocale();
+}
+
+static QString constructWindowTitleFromFilePath(const QString &filePath)
+{
+ QFileInfo fi(filePath);
+ QString windowTitle = fi.fileName() + QLatin1String("[*]");
+#ifndef Q_WS_MAC
+ QString appName = QApplication::applicationName();
+ if (!appName.isEmpty())
+ windowTitle += QLatin1String(" ") + QChar(0x2014) + QLatin1String(" ") + appName;
+#endif
+ return windowTitle;
+}
+
+/*!
+ \property QWidget::windowTitle
+ \brief the window title (caption)
+
+ This property only makes sense for top-level widgets, such as
+ windows and dialogs. If no caption has been set, the title is based of the
+ \l windowFilePath. If neither of these is set, then the title is
+ an empty string.
+
+ If you use the \l windowModified mechanism, the window title must
+ contain a "[*]" placeholder, which indicates where the '*' should
+ appear. Normally, it should appear right after the file name
+ (e.g., "document1.txt[*] - Text Editor"). If the \l
+ windowModified property is false (the default), the placeholder
+ is simply removed.
+
+ \sa windowIcon, windowIconText, windowModified, windowFilePath
+*/
+QString QWidget::windowTitle() const
+{
+ Q_D(const QWidget);
+ if (d->extra && d->extra->topextra) {
+ if (!d->extra->topextra->caption.isEmpty())
+ return d->extra->topextra->caption;
+ if (!d->extra->topextra->filePath.isEmpty())
+ return constructWindowTitleFromFilePath(d->extra->topextra->filePath);
+ }
+ return QString();
+}
+
+QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
+{
+ Q_ASSERT(widget);
+
+#ifdef QT_EVAL
+ extern QString qt_eval_adapt_window_title(const QString &title);
+ QString cap = qt_eval_adapt_window_title(title);
+#else
+ QString cap = title;
+#endif
+
+ QString placeHolder(QLatin1String("[*]"));
+
+ int index = cap.indexOf(placeHolder);
+
+ while (index != -1) {
+ index += placeHolder.length();
+ int count = 1;
+ while (cap.indexOf(placeHolder, index) == index) {
+ ++count;
+ index += placeHolder.length();
+ }
+
+ if (count%2) { // odd number of [*] -> replace last one
+ int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
+ if (widget->isWindowModified()
+ && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, widget))
+ cap.replace(lastIndex, 3, QWidget::tr("*"));
+ else
+ cap.replace(lastIndex, 3, QLatin1String(""));
+ }
+
+ index = cap.indexOf(placeHolder, index);
+ }
+
+ cap.replace(QLatin1String("[*][*]"), QLatin1String("[*]"));
+
+ return cap;
+}
+
+void QWidgetPrivate::setWindowTitle_helper(const QString &title)
+{
+ Q_Q(QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created))
+ createWinId();
+ setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
+}
+
+void QWidgetPrivate::setWindowIconText_helper(const QString &title)
+{
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
+}
+
+void QWidget::setWindowIconText(const QString &iconText)
+{
+ if (QWidget::windowIconText() == iconText)
+ return;
+
+ Q_D(QWidget);
+ d->topData()->iconText = iconText;
+ d->setWindowIconText_helper(iconText);
+
+ QEvent e(QEvent::IconTextChange);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidget::setWindowTitle(const QString &title)
+{
+ if (QWidget::windowTitle() == title)
+ return;
+
+ Q_D(QWidget);
+ d->topData()->caption = title;
+ d->setWindowTitle_helper(title);
+
+ QEvent e(QEvent::WindowTitleChange);
+ QApplication::sendEvent(this, &e);
+}
+
+
+/*!
+ \property QWidget::windowIcon
+ \brief the widget's icon
+
+ This property only makes sense for windows. If no icon
+ has been set, windowIcon() returns the application icon
+ (QApplication::windowIcon()).
+
+ \sa windowIconText, windowTitle
+*/
+QIcon QWidget::windowIcon() const
+{
+ const QWidget *w = this;
+ while (w) {
+ const QWidgetPrivate *d = w->d_func();
+ if (d->extra && d->extra->topextra && d->extra->topextra->icon)
+ return *d->extra->topextra->icon;
+ w = w->parentWidget();
+ }
+ return qApp->windowIcon();
+}
+
+void QWidgetPrivate::setWindowIcon_helper()
+{
+ QEvent e(QEvent::WindowIconChange);
+ QApplication::sendEvent(q_func(), &e);
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->isWindow())
+ QApplication::sendEvent(w, &e);
+ }
+}
+
+void QWidget::setWindowIcon(const QIcon &icon)
+{
+ Q_D(QWidget);
+
+ setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
+ d->createTLExtra();
+
+ if (!d->extra->topextra->icon)
+ d->extra->topextra->icon = new QIcon();
+ *d->extra->topextra->icon = icon;
+
+ delete d->extra->topextra->iconPixmap;
+ d->extra->topextra->iconPixmap = 0;
+
+ d->setWindowIcon_sys();
+ d->setWindowIcon_helper();
+}
+
+
+/*!
+ \property QWidget::windowIconText
+ \brief the widget's icon text
+
+ This property only makes sense for windows. If no icon
+ text has been set, this functions returns an empty string.
+
+ \sa windowIcon, windowTitle
+*/
+
+QString QWidget::windowIconText() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
+}
+
+/*!
+ \property QWidget::windowFilePath
+ \since 4.4
+ \brief the file path associated with a widget
+
+ This property only makes sense for windows. It associates a file path with
+ a window. If you set the file path, but have not set the window title, Qt
+ sets the window title to contain a string created using the following
+ components.
+
+ On Mac OS X:
+
+ \list
+ \o The file name of the specified path, obtained using QFileInfo::fileName().
+ \o An optional \c{*} character, if the \l windowModified property is set,
+ as per the Apple Human Interface Guidelines.
+ \endlist
+
+ On Windows and X11:
+
+ \list
+ \o The file name of the specified path, obtained using QFileInfo::fileName().
+ \o An optional \c{*} character, if the \l windowModified property is set.
+ \o The \c{0x2014} unicode character, padded either side by spaces.
+ \o The application name, obtained from the application's
+ \l{QCoreApplication::}{applicationName} property.
+ \endlist
+
+ If the window title is set at any point, then the window title takes precedence and
+ will be shown instead of the file path string.
+
+ Additionally, on Mac OS X, this has an added benefit that it sets the
+ \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
+ for the window, assuming that the file path exists.
+
+ If no file path is set, this property contains an empty string.
+
+ By default, this property contains an empty string.
+
+ \sa windowTitle, windowIcon
+*/
+
+QString QWidget::windowFilePath() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
+}
+
+void QWidget::setWindowFilePath(const QString &filePath)
+{
+ if (filePath == windowFilePath())
+ return;
+
+ Q_D(QWidget);
+
+ d->createTLExtra();
+ d->extra->topextra->filePath = filePath;
+ d->setWindowFilePath_helper(filePath);
+}
+
+void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
+{
+ if (extra->topextra && extra->topextra->caption.isEmpty()) {
+#ifdef Q_WS_MAC
+ setWindowTitle_helper(filePath);
+#else
+ Q_Q(QWidget);
+ Q_UNUSED(filePath);
+ setWindowTitle_helper(q->windowTitle());
+#endif
+ }
+#ifdef Q_WS_MAC
+ setWindowFilePath_sys(filePath);
+#endif
+}
+
+/*!
+ Returns the window's role, or an empty string.
+
+ \sa windowIcon, windowTitle
+*/
+
+QString QWidget::windowRole() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
+}
+
+/*!
+ Sets the window's role to \a role. This only makes sense for
+ windows on X11.
+*/
+void QWidget::setWindowRole(const QString &role)
+{
+#if defined(Q_WS_X11)
+ Q_D(QWidget);
+ d->topData()->role = role;
+ d->setWindowRole();
+#else
+ Q_UNUSED(role)
+#endif
+}
+
+/*!
+ \property QWidget::mouseTracking
+ \brief whether mouse tracking is enabled for the widget
+
+ If mouse tracking is disabled (the default), the widget only
+ receives mouse move events when at least one mouse button is
+ pressed while the mouse is being moved.
+
+ If mouse tracking is enabled, the widget receives mouse move
+ events even if no buttons are pressed.
+
+ \sa mouseMoveEvent()
+*/
+
+
+/*!
+ Sets the widget's focus proxy to widget \a w. If \a w is 0, the
+ function resets this widget to have no focus proxy.
+
+ Some widgets can "have focus", but create a child widget, such as
+ QLineEdit, to actually handle the focus. In this case, the widget
+ can set the line edit to be its focus proxy.
+
+ setFocusProxy() sets the widget which will actually get focus when
+ "this widget" gets it. If there is a focus proxy, setFocus() and
+ hasFocus() operate on the focus proxy.
+
+ \sa focusProxy()
+*/
+
+void QWidget::setFocusProxy(QWidget * w)
+{
+ Q_D(QWidget);
+ if (!w && !d->extra)
+ return;
+
+ for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
+ if (fp == this) {
+ qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
+ return;
+ }
+ }
+
+ d->createExtra();
+ d->extra->focus_proxy = w;
+}
+
+
+/*!
+ Returns the focus proxy, or 0 if there is no focus proxy.
+
+ \sa setFocusProxy()
+*/
+
+QWidget * QWidget::focusProxy() const
+{
+ Q_D(const QWidget);
+ return d->extra ? (QWidget *)d->extra->focus_proxy : 0;
+}
+
+
+/*!
+ \property QWidget::focus
+ \brief whether this widget (or its focus proxy) has the keyboard
+ input focus
+
+ By default, this property is false.
+
+ \note Obtaining the value of this property for a widget is effectively equivalent
+ to checking whether QApplication::focusWidget() refers to the widget.
+
+ \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
+*/
+bool QWidget::hasFocus() const
+{
+ const QWidget* w = this;
+ while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
+ w = w->d_func()->extra->focus_proxy;
+ if (QWidget *window = w->window()) {
+#ifndef QT_NO_GRAPHICSVIEW
+ QWExtra *e = window->d_func()->extra;
+ if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
+ return true;
+#endif
+ }
+ return (QApplication::focusWidget() == w);
+}
+
+/*!
+ Gives the keyboard input focus to this widget (or its focus
+ proxy) if this widget or one of its parents is the \link
+ isActiveWindow() active window\endlink. The \a reason argument will
+ be passed into any focus event sent from this function, it is used
+ to give an explanation of what caused the widget to get focus.
+
+ First, a focus out event is sent to the focus widget (if any) to
+ tell it that it is about to lose the focus. Then a focus in event
+ is sent to this widget to tell it that it just received the focus.
+ (Nothing happens if the focus in and focus out widgets are the
+ same.)
+
+ setFocus() gives focus to a widget regardless of its focus policy,
+ but does not clear any keyboard grab (see grabKeyboard()).
+
+ Be aware that if the widget is hidden, it will not accept focus
+ until it is shown.
+
+ \warning If you call setFocus() in a function which may itself be
+ called from focusOutEvent() or focusInEvent(), you may get an
+ infinite recursion.
+
+ \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
+ setFocusPolicy(), QApplication::focusWidget(), grabKeyboard(),
+ grabMouse(), {Keyboard Focus}
+*/
+
+void QWidget::setFocus(Qt::FocusReason reason)
+{
+ if (!isEnabled())
+ return;
+
+ QWidget *f = this;
+ while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
+ f = f->d_func()->extra->focus_proxy;
+
+ if (QApplication::focusWidget() == f
+#if defined(Q_WS_WIN)
+ && GetFocus() == f->internalWinId()
+#endif
+ )
+ return;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ QWidget *previousProxyFocus = 0;
+ if (QWExtra *topData = window()->d_func()->extra) {
+ if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
+ previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
+ if (previousProxyFocus && previousProxyFocus->focusProxy())
+ previousProxyFocus = previousProxyFocus->focusProxy();
+ }
+ }
+#endif
+
+ QWidget *w = f;
+ if (isHidden()) {
+ while (w && w->isHidden()) {
+ w->d_func()->focus_child = f;
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ } else {
+ while (w) {
+ w->d_func()->focus_child = f;
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ }
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Update proxy state
+ if (QWExtra *topData = window()->d_func()->extra) {
+ if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
+ topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
+ topData->proxyWidget->setFocus(reason);
+ topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
+ }
+ }
+#endif
+
+ if (f->isActiveWindow()) {
+ QApplicationPrivate::setFocusWidget(f, reason);
+#ifndef QT_NO_ACCESSIBILITY
+# ifdef Q_OS_WIN
+ // The negation of the condition in setFocus_sys
+ if (!(testAttribute(Qt::WA_WState_Created) && window()->windowType() != Qt::Popup && internalWinId()))
+ //setFocusWidget will already post a focus event for us (that the AT client receives) on Windows
+# endif
+ QAccessible::updateAccessibility(f, 0, QAccessible::Focus);
+#endif
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *topData = window()->d_func()->extra) {
+ if (topData->proxyWidget) {
+ if (previousProxyFocus && previousProxyFocus != f) {
+ // Send event to self
+ QFocusEvent event(QEvent::FocusOut, reason);
+ QPointer<QWidget> that = previousProxyFocus;
+ QApplication::sendEvent(previousProxyFocus, &event);
+ if (that)
+ QApplication::sendEvent(that->style(), &event);
+ }
+ if (!isHidden()) {
+ // Send event to self
+ QFocusEvent event(QEvent::FocusIn, reason);
+ QPointer<QWidget> that = f;
+ QApplication::sendEvent(f, &event);
+ if (that)
+ QApplication::sendEvent(that->style(), &event);
+ }
+ }
+ }
+#endif
+ }
+}
+
+/*!
+ \fn void QWidget::setFocus()
+ \overload
+
+ Gives the keyboard input focus to this widget (or its focus
+ proxy) if this widget or one of its parents is the
+ \l{isActiveWindow()}{active window}.
+*/
+
+/*!
+ Takes keyboard input focus from the widget.
+
+ If the widget has active focus, a \link focusOutEvent() focus out
+ event\endlink is sent to this widget to tell it that it is about
+ to lose the focus.
+
+ This widget must enable focus setting in order to get the keyboard
+ input focus, i.e. it must call setFocusPolicy().
+
+ \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
+ setFocusPolicy(), QApplication::focusWidget()
+*/
+
+void QWidget::clearFocus()
+{
+ QWidget *w = this;
+ while (w && w->d_func()->focus_child == this) {
+ w->d_func()->focus_child = 0;
+ w = w->parentWidget();
+ }
+#ifndef QT_NO_GRAPHICSVIEW
+ QWExtra *topData = d_func()->extra;
+ if (topData && topData->proxyWidget)
+ topData->proxyWidget->clearFocus();
+#endif
+
+ if (hasFocus()) {
+ // Update proxy state
+ QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
+#if defined(Q_WS_WIN)
+ if (!(windowType() == Qt::Popup) && GetFocus() == internalWinId())
+ SetFocus(0);
+ else
+#endif
+ {
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::Focus);
+#endif
+ }
+ }
+}
+
+
+/*!
+ \fn bool QWidget::focusNextChild()
+
+ Finds a new widget to give the keyboard focus to, as appropriate
+ for \key Tab, and returns true if it can find a new widget, or
+ false if it can't.
+
+ \sa focusPreviousChild()
+*/
+
+/*!
+ \fn bool QWidget::focusPreviousChild()
+
+ Finds a new widget to give the keyboard focus to, as appropriate
+ for \key Shift+Tab, and returns true if it can find a new widget,
+ or false if it can't.
+
+ \sa focusNextChild()
+*/
+
+/*!
+ Finds a new widget to give the keyboard focus to, as appropriate
+ for Tab and Shift+Tab, and returns true if it can find a new
+ widget, or false if it can't.
+
+ If \a next is true, this function searches forward, if \a next
+ is false, it searches backward.
+
+ Sometimes, you will want to reimplement this function. For
+ example, a web browser might reimplement it to move its "current
+ active link" forward or backward, and call
+ focusNextPrevChild() only when it reaches the last or
+ first link on the "page".
+
+ Child widgets call focusNextPrevChild() on their parent widgets,
+ but only the window that contains the child widgets decides where
+ to redirect focus. By reimplementing this function for an object,
+ you thus gain control of focus traversal for all child widgets.
+
+ \sa focusNextChild(), focusPreviousChild()
+*/
+
+bool QWidget::focusNextPrevChild(bool next)
+{
+ Q_D(QWidget);
+ QWidget* p = parentWidget();
+ bool isSubWindow = (windowType() == Qt::SubWindow);
+ if (!isWindow() && !isSubWindow && p)
+ return p->focusNextPrevChild(next);
+#ifndef QT_NO_GRAPHICSVIEW
+ if (d->extra && d->extra->proxyWidget)
+ return d->extra->proxyWidget->focusNextPrevChild(next);
+#endif
+ QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next);
+ if (!w) return false;
+
+ w->setFocus(next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+}
+
+/*!
+ Returns the last child of this widget that setFocus had been
+ called on. For top level widgets this is the widget that will get
+ focus in case this window gets activated
+
+ This is not the same as QApplication::focusWidget(), which returns
+ the focus widget in the currently active window.
+*/
+
+QWidget *QWidget::focusWidget() const
+{
+ return const_cast<QWidget *>(d_func()->focus_child);
+}
+
+/*!
+ Returns the next widget in this widget's focus chain.
+*/
+QWidget *QWidget::nextInFocusChain() const
+{
+ return const_cast<QWidget *>(d_func()->focus_next);
+}
+
+/*!
+ \property QWidget::isActiveWindow
+ \brief whether this widget's window is the active window
+
+ The active window is the window that contains the widget that has
+ keyboard focus (The window may still have focus if it has no
+ widgets or none of its widgets accepts keyboard focus).
+
+ When popup windows are visible, this property is true for both the
+ active window \e and for the popup.
+
+ By default, this property is false.
+
+ \sa activateWindow(), QApplication::activeWindow()
+*/
+bool QWidget::isActiveWindow() const
+{
+ QWidget *tlw = window();
+ if(tlw == qApp->activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
+ return true;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *tlwExtra = tlw->d_func()->extra) {
+ if (isVisible() && tlwExtra->proxyWidget)
+ return tlwExtra->proxyWidget->isActiveWindow();
+ }
+#endif
+
+#ifdef Q_WS_MAC
+ extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
+ if(qt_mac_is_macdrawer(tlw) &&
+ tlw->parentWidget() && tlw->parentWidget()->isActiveWindow())
+ return true;
+#endif
+ if(style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, this)) {
+ if(tlw->windowType() == Qt::Tool &&
+ !tlw->isModal() &&
+ (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
+ return true;
+ QWidget *w = qApp->activeWindow();
+ while(w && tlw->windowType() == Qt::Tool &&
+ !w->isModal() && w->parentWidget()) {
+ w = w->parentWidget()->window();
+ if(w == tlw)
+ return true;
+ }
+ }
+#if defined(Q_WS_WIN32)
+ HWND active = GetActiveWindow();
+ if (!tlw->testAttribute(Qt::WA_WState_Created))
+ return false;
+ return active == tlw->internalWinId() || ::IsChild(active, tlw->internalWinId());
+#else
+ return false;
+#endif
+}
+
+/*!
+ Puts the \a second widget after the \a first widget in the focus order.
+
+ Note that since the tab order of the \a second widget is changed, you
+ should order a chain like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 9
+
+ \e not like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 10
+
+ If \a first or \a second has a focus proxy, setTabOrder()
+ correctly substitutes the proxy.
+
+ \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus}
+*/
+void QWidget::setTabOrder(QWidget* first, QWidget *second)
+{
+ if (!first || !second || first->focusPolicy() == Qt::NoFocus || second->focusPolicy() == Qt::NoFocus)
+ return;
+
+ if (first->window() != second->window()) {
+ qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
+ return;
+ }
+
+ QWidget *fp = first->focusProxy();
+ if (fp) {
+ // If first is redirected, set first to the last child of first
+ // that can take keyboard focus so that second is inserted after
+ // that last child, and the focus order within first is (more
+ // likely to be) preserved.
+ QList<QWidget *> l = qFindChildren<QWidget *>(first);
+ for (int i = l.size()-1; i >= 0; --i) {
+ QWidget * next = l.at(i);
+ if (next->window() == fp->window()) {
+ fp = next;
+ if (fp->focusPolicy() != Qt::NoFocus)
+ break;
+ }
+ }
+ first = fp;
+ }
+
+
+ if (QWidget *sp = second->focusProxy())
+ second = sp;
+
+// QWidget *fp = first->d_func()->focus_prev;
+ QWidget *fn = first->d_func()->focus_next;
+
+ if (fn == second)
+ return;
+
+ QWidget *sp = second->d_func()->focus_prev;
+ QWidget *sn = second->d_func()->focus_next;
+
+ fn->d_func()->focus_prev = second;
+ first->d_func()->focus_next = second;
+
+ second->d_func()->focus_next = fn;
+ second->d_func()->focus_prev = first;
+
+ sp->d_func()->focus_next = sn;
+ sn->d_func()->focus_prev = sp;
+
+
+ Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first);
+ Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first);
+
+ Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second);
+ Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second);
+}
+
+/*!\internal
+
+ Moves the relevant subwidgets of this widget from the \a oldtlw's
+ tab chain to that of the new parent, if there's anything to move and
+ we're really moving
+
+ This function is called from QWidget::reparent() *after* the widget
+ has been reparented.
+
+ \sa reparent()
+*/
+
+void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
+{
+ Q_Q(QWidget);
+ if (oldtlw == q->window())
+ return; // nothing to do
+
+ if(focus_child)
+ focus_child->clearFocus();
+
+ // separate the focus chain into new (children of myself) and old (the rest)
+ QWidget *firstOld = 0;
+ //QWidget *firstNew = q; //invariant
+ QWidget *o = 0; // last in the old list
+ QWidget *n = q; // last in the new list
+
+ bool prevWasNew = true;
+ QWidget *w = focus_next;
+
+ //Note: for efficiency, we do not maintain the list invariant inside the loop
+ //we append items to the relevant list, and we optimize by not changing pointers
+ //when subsequent items are going into the same list.
+ while (w != q) {
+ bool currentIsNew = q->isAncestorOf(w);
+ if (currentIsNew) {
+ if (!prevWasNew) {
+ //prev was old -- append to new list
+ n->d_func()->focus_next = w;
+ w->d_func()->focus_prev = n;
+ }
+ n = w;
+ } else {
+ if (prevWasNew) {
+ //prev was new -- append to old list, if there is one
+ if (o) {
+ o->d_func()->focus_next = w;
+ w->d_func()->focus_prev = o;
+ } else {
+ // "create" the old list
+ firstOld = w;
+ }
+ }
+ o = w;
+ }
+ w = w->d_func()->focus_next;
+ prevWasNew = currentIsNew;
+ }
+
+ //repair the old list:
+ if (firstOld) {
+ o->d_func()->focus_next = firstOld;
+ firstOld->d_func()->focus_prev = o;
+ }
+
+ if (!q->isWindow()) {
+ QWidget *topLevel = q->window();
+ //insert new chain into toplevel's chain
+
+ QWidget *prev = topLevel->d_func()->focus_prev;
+
+ topLevel->d_func()->focus_prev = n;
+ prev->d_func()->focus_next = q;
+
+ focus_prev = prev;
+ n->d_func()->focus_next = topLevel;
+ } else {
+ //repair the new list
+ n->d_func()->focus_next = q;
+ focus_prev = n;
+ }
+
+}
+
+/*!\internal
+
+ Measures the shortest distance from a point to a rect.
+
+ This function is called from QDesktopwidget::screen(QPoint) to find the
+ closest screen for a point.
+*/
+int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r)
+{
+ int dx = 0;
+ int dy = 0;
+ if (p.x() < r.left())
+ dx = r.left() - p.x();
+ else if (p.x() > r.right())
+ dx = p.x() - r.right();
+ if (p.y() < r.top())
+ dy = r.top() - p.y();
+ else if (p.y() > r.bottom())
+ dy = p.y() - r.bottom();
+ return dx + dy;
+}
+
+QRect QWidgetPrivate::fromOrToLayoutItemRect(const QRect &rect, int sign) const
+{
+ QRect r = rect;
+ r.adjust(-sign * leftLayoutItemMargin, -sign * topLayoutItemMargin,
+ +sign * rightLayoutItemMargin, +sign * bottomLayoutItemMargin);
+ return r;
+}
+
+/*!
+ \property QWidget::frameSize
+ \brief the size of the widget including any window frame
+
+ By default, this property contains a value that depends on the user's
+ platform and screen geometry.
+*/
+QSize QWidget::frameSize() const
+{
+ Q_D(const QWidget);
+ if (isWindow() && !(windowType() == Qt::Popup)) {
+ QRect fs = d->frameStrut();
+ return QSize(data->crect.width() + fs.left() + fs.right(),
+ data->crect.height() + fs.top() + fs.bottom());
+ }
+ return data->crect.size();
+}
+
+/*! \fn void QWidget::move(int x, int y)
+
+ \overload
+
+ This corresponds to move(QPoint(\a x, \a y)).
+*/
+
+void QWidget::move(const QPoint &p)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_Moved);
+ if (isWindow())
+ d->topData()->posFromMove = true;
+ if (testAttribute(Qt::WA_WState_Created)) {
+ d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
+ p.y() + geometry().y() - QWidget::y(),
+ width(), height(), true);
+ d->setDirtyOpaqueRegion();
+ } else {
+ data->crect.moveTopLeft(p); // no frame yet
+ setAttribute(Qt::WA_PendingMoveEvent);
+ }
+}
+
+/*! \fn void QWidget::resize(int w, int h)
+ \overload
+
+ This corresponds to resize(QSize(\a w, \a h)).
+*/
+
+void QWidget::resize(const QSize &s)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_Resized);
+ if (testAttribute(Qt::WA_WState_Created)) {
+ d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
+ d->setDirtyOpaqueRegion();
+ } else {
+ data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
+ setAttribute(Qt::WA_PendingResizeEvent);
+ }
+}
+
+void QWidget::setGeometry(const QRect &r)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_Resized);
+ setAttribute(Qt::WA_Moved);
+ if (isWindow())
+ d->topData()->posFromMove = false;
+ if (testAttribute(Qt::WA_WState_Created)) {
+ d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
+ d->setDirtyOpaqueRegion();
+ } else {
+ data->crect.setTopLeft(r.topLeft());
+ data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
+ setAttribute(Qt::WA_PendingMoveEvent);
+ setAttribute(Qt::WA_PendingResizeEvent);
+ }
+}
+
+/*!
+ \since 4.2
+ Saves the current geometry and state for top-level widgets.
+
+ To save the geometry when the window closes, you can
+ implement a close event like this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 11
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of geometry issues with windows.
+
+ Use QMainWindow::saveState() to save the geometry and the state of
+ toolbars and dock widgets.
+
+ \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
+*/
+QByteArray QWidget::saveGeometry() const
+{
+ QByteArray array;
+ QDataStream stream(&array, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_4_0);
+ const quint32 magicNumber = 0x1D9D0CB;
+ quint16 majorVersion = 1;
+ quint16 minorVersion = 0;
+ stream << magicNumber
+ << majorVersion
+ << minorVersion
+ << frameGeometry()
+ << normalGeometry()
+ << qint32(QApplication::desktop()->screenNumber(this))
+ << quint8(windowState() & Qt::WindowMaximized)
+ << quint8(windowState() & Qt::WindowFullScreen);
+ return array;
+}
+
+/*!
+ \since 4.2
+
+ Restores the geometry and state top-level widgets stored in the
+ byte array \a geometry. Returns true on success; otherwise
+ returns false.
+
+ If the restored geometry is off-screen, it will be modified to be
+ inside the the available screen geometry.
+
+ To restore geometry saved using QSettings, you can use code like
+ this:
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 12
+
+ See the \link geometry.html Window Geometry documentation\endlink
+ for an overview of geometry issues with windows.
+
+ Use QMainWindow::restoreState() to restore the geometry and the
+ state of toolbars and dock widgets.
+
+ \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
+*/
+bool QWidget::restoreGeometry(const QByteArray &geometry)
+{
+ if (geometry.size() < 4)
+ return false;
+ QDataStream stream(geometry);
+ stream.setVersion(QDataStream::Qt_4_0);
+
+ const quint32 magicNumber = 0x1D9D0CB;
+ quint32 storedMagicNumber;
+ stream >> storedMagicNumber;
+ if (storedMagicNumber != magicNumber)
+ return false;
+
+ const quint16 currentMajorVersion = 1;
+ quint16 majorVersion = 0;
+ quint16 minorVersion = 0;
+
+ stream >> majorVersion >> minorVersion;
+
+ if (majorVersion != currentMajorVersion)
+ return false;
+ // (Allow all minor versions.)
+
+ QRect restoredFrameGeometry;
+ QRect restoredNormalGeometry;
+ qint32 restoredScreenNumber;
+ quint8 maximized;
+ quint8 fullScreen;
+
+ stream >> restoredFrameGeometry
+ >> restoredNormalGeometry
+ >> restoredScreenNumber
+ >> maximized
+ >> fullScreen;
+
+ const int frameHeight = 20;
+ if (!restoredFrameGeometry.isValid())
+ restoredFrameGeometry = QRect(QPoint(0,0), sizeHint());
+
+ if (!restoredNormalGeometry.isValid())
+ restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
+ if (!restoredNormalGeometry.isValid()) {
+ // use the widget's adjustedSize if the sizeHint() doesn't help
+ restoredNormalGeometry.setSize(restoredNormalGeometry
+ .size()
+ .expandedTo(d_func()->adjustedSize()));
+ }
+
+ const QDesktopWidget * const desktop = QApplication::desktop();
+ if (restoredScreenNumber >= desktop->numScreens())
+ restoredScreenNumber = desktop->primaryScreen();
+
+ const QRect availableGeometry = desktop->availableGeometry(restoredScreenNumber);
+
+ // Modify the restored geometry if we are about to restore to coordinates
+ // that would make the window "lost". This happens if:
+ // - The restored geometry is completely oustside the available geometry
+ // - The title bar is outside the available geometry.
+ // - (Mac only) The window is higher than the available geometry. It must
+ // be possible to bring the size grip on screen by moving the window.
+#ifdef Q_WS_MAC
+ restoredFrameGeometry.setHeight(qMin(restoredFrameGeometry.height(), availableGeometry.height()));
+ restoredNormalGeometry.setHeight(qMin(restoredNormalGeometry.height(), availableGeometry.height() - frameHeight));
+#endif
+
+ if (!restoredFrameGeometry.intersects(availableGeometry)) {
+ restoredFrameGeometry.moveBottom(qMin(restoredFrameGeometry.bottom(), availableGeometry.bottom()));
+ restoredFrameGeometry.moveLeft(qMax(restoredFrameGeometry.left(), availableGeometry.left()));
+ restoredFrameGeometry.moveRight(qMin(restoredFrameGeometry.right(), availableGeometry.right()));
+ }
+ restoredFrameGeometry.moveTop(qMax(restoredFrameGeometry.top(), availableGeometry.top()));
+
+ if (!restoredNormalGeometry.intersects(availableGeometry)) {
+ restoredNormalGeometry.moveBottom(qMin(restoredNormalGeometry.bottom(), availableGeometry.bottom()));
+ restoredNormalGeometry.moveLeft(qMax(restoredNormalGeometry.left(), availableGeometry.left()));
+ restoredNormalGeometry.moveRight(qMin(restoredNormalGeometry.right(), availableGeometry.right()));
+ }
+ restoredNormalGeometry.moveTop(qMax(restoredNormalGeometry.top(), availableGeometry.top() + frameHeight));
+
+ if (maximized || fullScreen) {
+ // set geomerty before setting the window state to make
+ // sure the window is maximized to the right screen.
+ setGeometry(restoredNormalGeometry);
+ Qt::WindowStates ws = windowState();
+ if (maximized)
+ ws |= Qt::WindowMaximized;
+ if (fullScreen)
+ ws |= Qt::WindowFullScreen;
+ setWindowState(ws);
+ d_func()->topData()->normalGeometry = restoredNormalGeometry;
+ } else {
+ QPoint offset;
+#ifdef Q_WS_X11
+ if (isFullScreen())
+ offset = d_func()->topData()->fullScreenOffset;
+#endif
+ setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
+ move(restoredFrameGeometry.topLeft() + offset);
+ resize(restoredNormalGeometry.size());
+ }
+ return true;
+}
+
+/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
+ \overload
+
+ This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
+*/
+
+/*!
+ Sets the margins around the contents of the widget to have the
+ sizes \a left, \a top, \a right, and \a bottom. The margins are
+ used by the layout system, and may be used by subclasses to
+ specify the area to draw in (e.g. excluding the frame).
+
+ Changing the margins will trigger a resizeEvent().
+
+ \sa contentsRect(), getContentsMargins()
+*/
+void QWidget::setContentsMargins(int left, int top, int right, int bottom)
+{
+ Q_D(QWidget);
+ if (left == d->leftmargin && top == d->topmargin
+ && right == d->rightmargin && bottom == d->bottommargin)
+ return;
+ d->leftmargin = left;
+ d->topmargin = top;
+ d->rightmargin = right;
+ d->bottommargin = bottom;
+
+ if (QLayout *l=d->layout)
+ l->update(); //force activate; will do updateGeometry
+ else
+ updateGeometry();
+
+ // ### Qt 5: compat, remove
+ if (isVisible()) {
+ update();
+ QResizeEvent e(data->crect.size(), data->crect.size());
+ QApplication::sendEvent(this, &e);
+ } else {
+ setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+
+ QEvent e(QEvent::ContentsRectChange);
+ QApplication::sendEvent(this, &e);
+}
+
+/*! Returns the widget's contents margins for \a left, \a top, \a
+ right, and \a bottom.
+
+ \sa setContentsMargins(), contentsRect()
+ */
+void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) const
+{
+ Q_D(const QWidget);
+ if (left)
+ *left = d->leftmargin;
+ if (top)
+ *top = d->topmargin;
+ if (right)
+ *right = d->rightmargin;
+ if (bottom)
+ *bottom = d->bottommargin;
+}
+
+/*!
+ Returns the area inside the widget's margins.
+
+ \sa setContentsMargins(), getContentsMargins()
+*/
+QRect QWidget::contentsRect() const
+{
+ Q_D(const QWidget);
+ return QRect(QPoint(d->leftmargin, d->topmargin),
+ QPoint(data->crect.width() - 1 - d->rightmargin,
+ data->crect.height() - 1 - d->bottommargin));
+
+}
+
+
+
+/*!
+ \fn void QWidget::customContextMenuRequested(const QPoint &pos)
+
+ This signal is emitted when the widget's \l contextMenuPolicy is
+ Qt::CustomContextMenu, and the user has requested a context menu on
+ the widget. The position \a pos is the position of the context menu
+ event that the widget receives. Normally this is in widget
+ coordinates. The exception to this rule is QAbstractScrollArea and
+ its subclasses that map the context menu event to coordinates of the
+ \link QAbstractScrollArea::viewport() viewport() \endlink .
+
+
+ \sa mapToGlobal() QMenu contextMenuPolicy
+*/
+
+
+/*!
+ \property QWidget::contextMenuPolicy
+ \brief how the widget shows a context menu
+
+ The default value of this property is Qt::DefaultContextMenu,
+ which means the contextMenuEvent() handler is called. Other values
+ are Qt::NoContextMenu, Qt::PreventContextMenu,
+ Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
+ Qt::CustomContextMenu, the signal customContextMenuRequested() is
+ emitted.
+
+ \sa contextMenuEvent(), customContextMenuRequested(), actions()
+*/
+
+Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
+{
+ return (Qt::ContextMenuPolicy)data->context_menu_policy;
+}
+
+void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
+{
+ data->context_menu_policy = (uint) policy;
+}
+
+/*!
+ \property QWidget::focusPolicy
+ \brief the way the widget accepts keyboard focus
+
+ The policy is Qt::TabFocus if the widget accepts keyboard
+ focus by tabbing, Qt::ClickFocus if the widget accepts
+ focus by clicking, Qt::StrongFocus if it accepts both, and
+ Qt::NoFocus (the default) if it does not accept focus at
+ all.
+
+ You must enable keyboard focus for a widget if it processes
+ keyboard events. This is normally done from the widget's
+ constructor. For instance, the QLineEdit constructor calls
+ setFocusPolicy(Qt::StrongFocus).
+
+ If the widget has a focus proxy, then the focus policy will
+ be propagated to it.
+
+ \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
+*/
+
+
+Qt::FocusPolicy QWidget::focusPolicy() const
+{
+ return (Qt::FocusPolicy)data->focus_policy;
+}
+
+void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
+{
+ data->focus_policy = (uint) policy;
+ Q_D(QWidget);
+ if (d->extra && d->extra->focus_proxy)
+ d->extra->focus_proxy->setFocusPolicy(policy);
+}
+
+/*!
+ \property QWidget::updatesEnabled
+ \brief whether updates are enabled
+
+ An updates enabled widget receives paint events and has a system
+ background; a disabled widget does not. This also implies that
+ calling update() and repaint() has no effect if updates are
+ disabled.
+
+ By default, this property is true.
+
+ setUpdatesEnabled() is normally used to disable updates for a
+ short period of time, for instance to avoid screen flicker during
+ large changes. In Qt, widgets normally do not generate screen
+ flicker, but on X11 the server might erase regions on the screen
+ when widgets get hidden before they can be replaced by other
+ widgets. Disabling updates solves this.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 13
+
+ Disabling a widget implicitly disables all its children. Enabling a widget
+ enables all child widgets \e except top-level widgets or those that
+ have been explicitly disabled. Re-enabling updates implicitly calls
+ update() on the widget.
+
+ \sa paintEvent()
+*/
+void QWidget::setUpdatesEnabled(bool enable)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
+ d->setUpdatesEnabled_helper(enable);
+}
+
+/*! \fn void QWidget::show()
+
+ Shows the widget and its child widgets. This function is
+ equivalent to setVisible(true).
+
+ \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
+ showNormal(), isVisible()
+*/
+
+
+/*! \internal
+
+ Makes the widget visible in the isVisible() meaning of the word.
+ It is only called for toplevels or widgets with visible parents.
+ */
+void QWidgetPrivate::show_recursive()
+{
+ Q_Q(QWidget);
+ // polish if necessary
+
+ if (!q->testAttribute(Qt::WA_WState_Created))
+ createRecursively();
+ q->ensurePolished();
+
+#ifdef QT3_SUPPORT
+ if(sendChildEvents)
+ QApplication::sendPostedEvents(q, QEvent::ChildInserted);
+#endif
+ if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
+ q->parentWidget()->d_func()->layout->activate();
+ // activate our layout before we and our children become visible
+ if (layout)
+ layout->activate();
+
+ show_helper();
+}
+
+void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
+{
+ Q_Q(QWidget);
+
+ disableUpdates = disableUpdates && q->updatesEnabled();
+ if (disableUpdates)
+ q->setAttribute(Qt::WA_UpdatesDisabled);
+
+ if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
+ QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
+ QApplication::sendEvent(q, &e);
+ q->setAttribute(Qt::WA_PendingMoveEvent, false);
+ }
+
+ if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
+ QResizeEvent e(data.crect.size(), QSize());
+ QApplication::sendEvent(q, &e);
+ q->setAttribute(Qt::WA_PendingResizeEvent, false);
+ }
+
+ if (disableUpdates)
+ q->setAttribute(Qt::WA_UpdatesDisabled, false);
+
+ if (!recursive)
+ return;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
+ child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
+ }
+}
+
+void QWidgetPrivate::activateChildLayoutsRecursively()
+{
+ sendPendingMoveAndResizeEvents(false, true);
+
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget *>(children.at(i));
+ if (!child || child->isHidden() || child->isWindow())
+ continue;
+
+ child->ensurePolished();
+
+ // Activate child's layout
+ QWidgetPrivate *childPrivate = child->d_func();
+ if (childPrivate->layout)
+ childPrivate->layout->activate();
+
+ // Pretend we're visible.
+ const bool wasVisible = child->isVisible();
+ if (!wasVisible)
+ child->setAttribute(Qt::WA_WState_Visible);
+
+ // Do the same for all my children.
+ childPrivate->activateChildLayoutsRecursively();
+
+ // We're not cheating anymore.
+ if (!wasVisible)
+ child->setAttribute(Qt::WA_WState_Visible, false);
+ }
+}
+
+void QWidgetPrivate::show_helper()
+{
+ Q_Q(QWidget);
+ data.in_show = true; // qws optimization
+ // make sure we receive pending move and resize events
+ sendPendingMoveAndResizeEvents();
+
+ // become visible before showing all children
+ q->setAttribute(Qt::WA_WState_Visible);
+
+ // finally show all children recursively
+ showChildren(false);
+
+#ifdef QT3_SUPPORT
+ if (q->parentWidget() && sendChildEvents)
+ QApplication::sendPostedEvents(q->parentWidget(),
+ QEvent::ChildInserted);
+#endif
+
+
+ // popup handling: new popups and tools need to be raised, and
+ // existing popups must be closed. Also propagate the current
+ // windows's KeyboardFocusChange status.
+ if (q->isWindow()) {
+ if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
+ q->raise();
+ if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
+ q->setAttribute(Qt::WA_KeyboardFocusChange);
+ } else {
+ while (QApplication::activePopupWidget()) {
+ if (!QApplication::activePopupWidget()->close())
+ break;
+ }
+ }
+ }
+
+ // Automatic embedding of child windows of widgets already embedded into
+ // QGraphicsProxyWidget when they are shown the first time.
+ bool isEmbedded = false;
+#ifndef QT_NO_GRAPHICSVIEW
+ if (q->isWindow()) {
+ isEmbedded = q->graphicsProxyWidget() ? true : false;
+ if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
+ QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
+ if (ancestorProxy) {
+ isEmbedded = true;
+ ancestorProxy->d_func()->embedSubWindow(q);
+ }
+ }
+ }
+#else
+ Q_UNUSED(isEmbedded);
+#endif
+
+ // On Windows, show the popup now so that our own focus handling
+ // stores the correct old focus widget even if it's stolen in the
+ // showevent
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+ if (!isEmbedded && q->windowType() == Qt::Popup)
+ qApp->d_func()->openPopup(q);
+#endif
+
+ // send the show event before showing the window
+ QShowEvent showEvent;
+ QApplication::sendEvent(q, &showEvent);
+
+ if (!isEmbedded && q->isModal() && q->isWindow())
+ // QApplicationPrivate::enterModal *before* show, otherwise the initial
+ // stacking might be wrong
+ QApplicationPrivate::enterModal(q);
+
+
+ show_sys();
+
+#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+ if (!isEmbedded && q->windowType() == Qt::Popup)
+ qApp->d_func()->openPopup(q);
+#endif
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (q->windowType() != Qt::ToolTip) // Tooltips are read aloud twice in MS narrator.
+ QAccessible::updateAccessibility(q, 0, QAccessible::ObjectShow);
+#endif
+
+ if (QApplicationPrivate::hidden_focus_widget == q) {
+ QApplicationPrivate::hidden_focus_widget = 0;
+ q->setFocus(Qt::OtherFocusReason);
+ }
+
+ // Process events when showing a Qt::SplashScreen widget before the event loop
+ // is spinnning; otherwise it might not show up on particular platforms.
+ // This makes QSplashScreen behave the same on all platforms.
+ if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
+ QApplication::processEvents();
+
+ data.in_show = false; // reset qws optimization
+}
+
+/*! \fn void QWidget::hide()
+
+ Hides the widget. This function is equivalent to
+ setVisible(false).
+
+
+ \note If you are working with QDialog or its subclasses and you invoke
+ the show() function after this function, the dialog will be displayed in
+ its original position.
+
+ \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
+*/
+
+/*!\internal
+ */
+void QWidgetPrivate::hide_helper()
+{
+ Q_Q(QWidget);
+
+ bool isEmbedded = false;
+#if !defined QT_NO_GRAPHICSVIEW
+ isEmbedded = q->isWindow() && nearestGraphicsProxyWidget(q->parentWidget()) != 0;
+#else
+ Q_UNUSED(isEmbedded);
+#endif
+
+ if (!isEmbedded && (q->windowType() == Qt::Popup))
+ qApp->d_func()->closePopup(q);
+
+ // Move test modal here. Otherwise, a modal dialog could get
+ // destroyed and we lose all access to its parent because we haven't
+ // left modality. (Eg. modal Progress Dialog)
+ if (!isEmbedded && q->isModal() && q->isWindow())
+ QApplicationPrivate::leaveModal(q);
+
+#if defined(Q_WS_WIN)
+ if (q->isWindow() && !(q->windowType() == Qt::Popup) && q->parentWidget()
+ && !q->parentWidget()->isHidden() && q->isActiveWindow())
+ q->parentWidget()->activateWindow(); // Activate parent
+#endif
+
+ q->setAttribute(Qt::WA_Mapped, false);
+ hide_sys();
+
+ bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
+
+ if (wasVisible) {
+ q->setAttribute(Qt::WA_WState_Visible, false);
+
+ }
+
+ QHideEvent hideEvent;
+ QApplication::sendEvent(q, &hideEvent);
+ hideChildren(false);
+
+ // next bit tries to move the focus if the focus widget is now
+ // hidden.
+ if (wasVisible) {
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ qApp->d_func()->sendSyntheticEnterLeave(q);
+#endif
+
+ QWidget *fw = QApplication::focusWidget();
+ while (fw && !fw->isWindow()) {
+ if (fw == q) {
+ q->focusNextPrevChild(true);
+ break;
+ }
+ fw = fw->parentWidget();
+ }
+ }
+
+ if (QWidgetBackingStore *bs = maybeBackingStore())
+ bs->removeDirtyWidget(q);
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (wasVisible)
+ QAccessible::updateAccessibility(q, 0, QAccessible::ObjectHide);
+#endif
+}
+
+/*!
+ \fn bool QWidget::isHidden() const
+
+ Returns true if the widget is hidden, otherwise returns false.
+
+ A hidden widget will only become visible when show() is called on
+ it. It will not be automatically shown when the parent is shown.
+
+ To check visiblity, use !isVisible() instead (notice the exclamation mark).
+
+ isHidden() implies !isVisible(), but a widget can be not visible
+ and not hidden at the same time. This is the case for widgets that are children of
+ widgets that are not visible.
+
+
+ Widgets are hidden if they were created as independent
+ windows or as children of visible widgets, or if hide() or setVisible(false) was called.
+
+*/
+
+
+void QWidget::setVisible(bool visible)
+{
+ if (visible) { // show
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+ Q_D(QWidget);
+
+ // Designer uses a trick to make grabWidget work without showing
+ if (!isWindow() && parentWidget() && parentWidget()->isVisible()
+ && !parentWidget()->testAttribute(Qt::WA_WState_Created))
+ parentWidget()->window()->d_func()->createRecursively();
+
+ //we have to at least create toplevels before applyX11SpecificCommandLineArguments
+ //but not children of non-visible parents
+ QWidget *pw = parentWidget();
+ if (!testAttribute(Qt::WA_WState_Created)
+ && (isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
+ create();
+ }
+
+#if defined(Q_WS_X11)
+ if (windowType() == Qt::Window)
+ QApplicationPrivate::applyX11SpecificCommandLineArguments(this);
+#elif defined(Q_WS_QWS)
+ if (windowType() == Qt::Window)
+ QApplicationPrivate::applyQWSSpecificCommandLineArguments(this);
+#endif
+
+ bool wasResized = testAttribute(Qt::WA_Resized);
+ Qt::WindowStates initialWindowState = windowState();
+
+ // polish if necessary
+ ensurePolished();
+
+ // remember that show was called explicitly
+ setAttribute(Qt::WA_WState_ExplicitShowHide);
+ // whether we need to inform the parent widget immediately
+ bool needUpdateGeometry = !isWindow() && testAttribute(Qt::WA_WState_Hidden);
+ // we are no longer hidden
+ setAttribute(Qt::WA_WState_Hidden, false);
+
+ if (needUpdateGeometry)
+ d->updateGeometry_helper(true);
+
+#ifdef QT3_SUPPORT
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+#endif
+ // activate our layout before we and our children become visible
+ if (d->layout)
+ d->layout->activate();
+
+ if (!isWindow()) {
+ QWidget *parent = parentWidget();
+ while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
+ parent->d_func()->layout->activate();
+ if (parent->isWindow())
+ break;
+ parent = parent->parentWidget();
+ }
+ if (parent && !d->getOpaqueRegion().isEmpty())
+ parent->d_func()->setDirtyOpaqueRegion();
+ }
+
+ // adjust size if necessary
+ if (!wasResized
+ && (isWindow() || !parentWidget()->d_func()->layout)) {
+ if (isWindow()) {
+ adjustSize();
+ if (windowState() != initialWindowState)
+ setWindowState(initialWindowState);
+ } else {
+ adjustSize();
+ }
+ setAttribute(Qt::WA_Resized, false);
+ }
+
+ setAttribute(Qt::WA_KeyboardFocusChange, false);
+
+ if (isWindow() || parentWidget()->isVisible()) {
+ // remove posted quit events when showing a new window
+ QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
+
+ d->show_helper();
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ qApp->d_func()->sendSyntheticEnterLeave(this);
+#endif
+ }
+
+ QEvent showToParentEvent(QEvent::ShowToParent);
+ QApplication::sendEvent(this, &showToParentEvent);
+ } else { // hide
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ return;
+#if defined(Q_WS_WIN)
+ // reset WS_DISABLED style in a Blocked window
+ if(isWindow() && testAttribute(Qt::WA_WState_Created)
+ && QApplicationPrivate::isBlockedByModal(this))
+ {
+ LONG dwStyle = GetWindowLong(winId(), GWL_STYLE);
+ dwStyle &= ~WS_DISABLED;
+ SetWindowLong(winId(), GWL_STYLE, dwStyle);
+ }
+#endif
+ if (QApplicationPrivate::hidden_focus_widget == this)
+ QApplicationPrivate::hidden_focus_widget = 0;
+
+ Q_D(QWidget);
+
+ // hw: The test on getOpaqueRegion() needs to be more intelligent
+ // currently it doesn't work if the widget is hidden (the region will
+ // be clipped). The real check should be testing the cached region
+ // (and dirty flag) directly.
+ if (!isWindow() && parentWidget()) // && !d->getOpaqueRegion().isEmpty())
+ parentWidget()->d_func()->setDirtyOpaqueRegion();
+
+ setAttribute(Qt::WA_WState_Hidden);
+ setAttribute(Qt::WA_WState_ExplicitShowHide);
+ if (testAttribute(Qt::WA_WState_Created))
+ d->hide_helper();
+
+ // invalidate layout similar to updateGeometry()
+ if (!isWindow() && parentWidget()) {
+ if (parentWidget()->d_func()->layout)
+ parentWidget()->d_func()->layout->invalidate();
+ else if (parentWidget()->isVisible())
+ QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest));
+ }
+
+ QEvent hideToParentEvent(QEvent::HideToParent);
+ QApplication::sendEvent(this, &hideToParentEvent);
+ }
+}
+
+/*!\fn void QWidget::setHidden(bool hidden)
+
+ Convenience function, equivalent to setVisible(!\a hidden).
+*/
+
+/*!\fn void QWidget::setShown(bool shown)
+
+ Use setVisible(\a shown) instead.
+*/
+
+
+void QWidgetPrivate::_q_showIfNotHidden()
+{
+ Q_Q(QWidget);
+ if ( !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide)) )
+ q->setVisible(true);
+}
+
+void QWidgetPrivate::showChildren(bool spontaneous)
+{
+ QList<QObject*> childList = children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
+ if (!widget
+ || widget->isWindow()
+ || widget->testAttribute(Qt::WA_WState_Hidden))
+ continue;
+ if (spontaneous) {
+ widget->setAttribute(Qt::WA_Mapped);
+ widget->d_func()->showChildren(true);
+ QShowEvent e;
+ QApplication::sendSpontaneousEvent(widget, &e);
+ } else {
+ if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ widget->d_func()->show_recursive();
+ else
+ widget->show();
+ }
+ }
+}
+
+void QWidgetPrivate::hideChildren(bool spontaneous)
+{
+ QList<QObject*> childList = children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
+ if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
+ continue;
+ if (spontaneous)
+ widget->setAttribute(Qt::WA_Mapped, false);
+ else
+ widget->setAttribute(Qt::WA_WState_Visible, false);
+ widget->d_func()->hideChildren(spontaneous);
+ QHideEvent e;
+ if (spontaneous) {
+ QApplication::sendSpontaneousEvent(widget, &e);
+ } else {
+ QApplication::sendEvent(widget, &e);
+ if (widget->internalWinId()
+ && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
+ // hide_sys() on an ancestor won't have any affect on this
+ // widget, so it needs an explicit hide_sys() of its own
+ widget->d_func()->hide_sys();
+ }
+ }
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ qApp->d_func()->sendSyntheticEnterLeave(widget);
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ if (!spontaneous)
+ QAccessible::updateAccessibility(widget, 0, QAccessible::ObjectHide);
+#endif
+ }
+}
+
+bool QWidgetPrivate::close_helper(CloseMode mode)
+{
+ if (data.is_closing)
+ return true;
+
+ Q_Q(QWidget);
+ data.is_closing = 1;
+
+ QPointer<QWidget> that = q;
+ QPointer<QWidget> parentWidget = q->parentWidget();
+
+#ifdef QT3_SUPPORT
+ bool isMain = (QApplicationPrivate::main_widget == q);
+#endif
+ bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose);
+ if (mode != CloseNoEvent) {
+ QCloseEvent e;
+ if (mode == CloseWithSpontaneousEvent)
+ QApplication::sendSpontaneousEvent(q, &e);
+ else
+ QApplication::sendEvent(q, &e);
+ if (!that.isNull() && !e.isAccepted()) {
+ data.is_closing = 0;
+ return false;
+ }
+ }
+
+ if (!that.isNull() && !q->isHidden())
+ q->hide();
+
+#ifdef QT3_SUPPORT
+ if (isMain)
+ qApp->quit();
+#endif
+ // Attempt to close the application only if this widget has the
+ // WA_QuitOnClose flag set set and has a non-visible parent
+ quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible() || parentWidget->testAttribute(Qt::WA_DontShowOnScreen));
+
+ if (quitOnClose) {
+ // If there is no non-withdrawn primary window left (except
+ // the ones without QuitOnClose or with WA_DontShowOnScreen),
+ // we emit the lastWindowClosed signal
+ QWidgetList list = QApplication::topLevelWidgets();
+ bool lastWindowClosed = true;
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if ((w->isVisible() && !w->testAttribute(Qt::WA_DontShowOnScreen))
+ && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose)) {
+ lastWindowClosed = false;
+ break;
+ }
+ }
+ if (lastWindowClosed)
+ QApplicationPrivate::emitLastWindowClosed();
+ }
+
+ if (!that.isNull()) {
+ data.is_closing = 0;
+ if (q->testAttribute(Qt::WA_DeleteOnClose)) {
+ q->setAttribute(Qt::WA_DeleteOnClose, false);
+ q->deleteLater();
+ }
+ }
+ return true;
+}
+
+
+/*!
+ Closes this widget. Returns true if the widget was closed;
+ otherwise returns false.
+
+ First it sends the widget a QCloseEvent. The widget is \link
+ hide() hidden\endlink if it \link QCloseEvent::accept()
+ accepts\endlink the close event. If it \link QCloseEvent::ignore()
+ ignores\endlink the event, nothing happens. The default
+ implementation of QWidget::closeEvent() accepts the close event.
+
+ If the widget has the Qt::WA_DeleteOnClose flag, the widget
+ is also deleted. A close events is delivered to the widget no
+ matter if the widget is visible or not.
+
+ The \l QApplication::lastWindowClosed() signal is emitted when the
+ last visible primary window (i.e. window with no parent) with the
+ Qt::WA_QuitOnClose attribute set is closed. By default this
+ attribute is set for all widgets except transient windows such as
+ splash screens, tool windows, and popup menus.
+
+*/
+
+bool QWidget::close()
+{
+ return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
+}
+
+/*!
+ \property QWidget::visible
+ \brief whether the widget is visible
+
+ Calling setVisible(true) or show() sets the widget to visible
+ status if all its parent widgets up to the window are visible. If
+ an ancestor is not visible, the widget won't become visible until
+ all its ancestors are shown. If its size or position has changed,
+ Qt guarantees that a widget gets move and resize events just
+ before it is shown. If the widget has not been resized yet, Qt
+ will adjust the widget's size to a useful default using
+ adjustSize().
+
+ Calling setVisible(false) or hide() hides a widget explicitly. An
+ explicitly hidden widget will never become visible, even if all
+ its ancestors become visible, unless you show it.
+
+ A widget receives show and hide events when its visibility status
+ changes. Between a hide and a show event, there is no need to
+ waste CPU cycles preparing or displaying information to the user.
+ A video application, for example, might simply stop generating new
+ frames.
+
+ A widget that happens to be obscured by other windows on the
+ screen is considered to be visible. The same applies to iconified
+ windows and windows that exist on another virtual
+ desktop (on platforms that support this concept). A widget
+ receives spontaneous show and hide events when its mapping status
+ is changed by the window system, e.g. a spontaneous hide event
+ when the user minimizes the window, and a spontaneous show event
+ when the window is restored again.
+
+ You almost never have to reimplement the setVisible() function. If
+ you need to change some settings before a widget is shown, use
+ showEvent() instead. If you need to do some delayed initialization
+ use the Polish event delivered to the event() function.
+
+ \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
+ showEvent(), hideEvent()
+*/
+
+
+/*!
+ Returns true if this widget would become visible if \a ancestor is
+ shown; otherwise returns false.
+
+ The true case occurs if neither the widget itself nor any parent
+ up to but excluding \a ancestor has been explicitly hidden.
+
+ This function will still return true if the widget is obscured by
+ other windows on the screen, but could be physically visible if it
+ or they were to be moved.
+
+ isVisibleTo(0) is identical to isVisible().
+
+ \sa show() hide() isVisible()
+*/
+
+bool QWidget::isVisibleTo(QWidget* ancestor) const
+{
+ if (!ancestor)
+ return isVisible();
+ const QWidget * w = this;
+ while (w
+ && !w->isHidden()
+ && !w->isWindow()
+ && w->parentWidget()
+ && w->parentWidget() != ancestor)
+ w = w->parentWidget();
+ return !w->isHidden();
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use visibleRegion() instead.
+*/
+QRect QWidget::visibleRect() const
+{
+ return d_func()->clipRect();
+}
+#endif
+
+/*!
+ Returns the unobscured region where paint events can occur.
+
+ For visible widgets, this is an approximation of the area not
+ covered by other widgets; otherwise, this is an empty region.
+
+ The repaint() function calls this function if necessary, so in
+ general you do not need to call it.
+
+*/
+QRegion QWidget::visibleRegion() const
+{
+ Q_D(const QWidget);
+
+ QRect clipRect = d->clipRect();
+ if (clipRect.isEmpty())
+ return QRegion();
+ QRegion r(clipRect);
+ d->subtractOpaqueChildren(r, clipRect);
+ d->subtractOpaqueSiblings(r);
+#ifdef Q_WS_QWS
+ const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(windowSurface());
+ if (surface) {
+ const QPoint offset = mapTo(surface->window(), QPoint());
+ r &= surface->clipRegion().translated(-offset);
+ }
+#endif
+ return r;
+}
+
+
+QSize QWidgetPrivate::adjustedSize() const
+{
+ Q_Q(const QWidget);
+
+ QSize s = q->sizeHint();
+
+ if (q->isWindow()) {
+ Qt::Orientations exp;
+ if (QLayout *l = q->layout()) {
+ if (l->hasHeightForWidth())
+ s.setHeight(l->totalHeightForWidth(s.width()));
+ exp = l->expandingDirections();
+ } else
+ {
+ if (q->sizePolicy().hasHeightForWidth())
+ s.setHeight(q->heightForWidth(s.width()));
+ exp = q->sizePolicy().expandingDirections();
+ }
+ if (exp & Qt::Horizontal)
+ s.setWidth(qMax(s.width(), 200));
+ if (exp & Qt::Vertical)
+ s.setHeight(qMax(s.height(), 100));
+#if defined(Q_WS_X11)
+ QRect screen = QApplication::desktop()->screenGeometry(q->x11Info().screen());
+#else // all others
+ QRect screen = QApplication::desktop()->screenGeometry(q->pos());
+#endif
+#if defined (Q_OS_WINCE)
+ s.setWidth(qMin(s.width(), screen.width()));
+ s.setHeight(qMin(s.height(), screen.height()));
+#else
+ s.setWidth(qMin(s.width(), screen.width()*2/3));
+ s.setHeight(qMin(s.height(), screen.height()*2/3));
+#endif
+ if (QTLWExtra *extra = maybeTopData())
+ extra->sizeAdjusted = true;
+ }
+
+ if (!s.isValid()) {
+ QRect r = q->childrenRect(); // get children rectangle
+ if (r.isNull())
+ return s;
+ s = r.size() + QSize(2 * r.x(), 2 * r.y());
+ }
+
+ return s;
+}
+
+/*!
+ Adjusts the size of the widget to fit its contents.
+
+ This function uses sizeHint() if it is valid, i.e., the size hint's width
+ and height are \>= 0. Otherwise, it sets the size to the children
+ rectangle that covers all child widgets (the union of all child widget
+ rectangles).
+
+ For windows, the screen size is also taken into account. If the sizeHint()
+ is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
+ {expanding}, the window will be at least (200, 100). The maximum size of
+ a window is 2/3 of the screen's width and height.
+
+ \sa sizeHint(), childrenRect()
+*/
+
+void QWidget::adjustSize()
+{
+ Q_D(QWidget);
+ ensurePolished();
+ QSize s = d->adjustedSize();
+ if (s.isValid())
+ resize(s);
+}
+
+
+/*!
+ \property QWidget::sizeHint
+ \brief the recommended size for the widget
+
+ If the value of this property is an invalid size, no size is
+ recommended.
+
+ The default implementation of sizeHint() returns an invalid size
+ if there is no layout for this widget, and returns the layout's
+ preferred size otherwise.
+
+ \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
+ setMinimumSize(), updateGeometry()
+*/
+
+QSize QWidget::sizeHint() const
+{
+ Q_D(const QWidget);
+ if (d->layout)
+ return d->layout->totalSizeHint();
+ return QSize(-1, -1);
+}
+
+/*!
+ \property QWidget::minimumSizeHint
+ \brief the recommended minimum size for the widget
+
+ If the value of this property is an invalid size, no minimum size
+ is recommended.
+
+ The default implementation of minimumSizeHint() returns an invalid
+ size if there is no layout for this widget, and returns the
+ layout's minimum size otherwise. Most built-in widgets reimplement
+ minimumSizeHint().
+
+ \l QLayout will never resize a widget to a size smaller than the
+ minimum size hint unless minimumSize() is set or the size policy is
+ set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
+ size hint will be ignored.
+
+ \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
+*/
+QSize QWidget::minimumSizeHint() const
+{
+ Q_D(const QWidget);
+ if (d->layout)
+ return d->layout->totalMinimumSize();
+ return QSize(-1, -1);
+}
+
+
+/*!
+ \fn QWidget *QWidget::parentWidget() const
+
+ Returns the parent of this widget, or 0 if it does not have any
+ parent widget.
+*/
+
+
+/*!
+ Returns true if this widget is a parent, (or grandparent and so on
+ to any level), of the given \a child, and both widgets are within
+ the same window; otherwise returns false.
+*/
+
+bool QWidget::isAncestorOf(const QWidget *child) const
+{
+ while (child) {
+ if (child == this)
+ return true;
+ if (child->isWindow())
+ return false;
+ child = child->parentWidget();
+ }
+ return false;
+}
+
+#if defined(Q_WS_WIN)
+inline void setDisabledStyle(QWidget *w, bool setStyle)
+{
+ // set/reset WS_DISABLED style.
+ if(w && w->isWindow() && w->isVisible() && w->isEnabled()) {
+ LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE);
+ if (setStyle)
+ dwStyle |= WS_DISABLED;
+ else
+ dwStyle &= ~WS_DISABLED;
+ SetWindowLong(w->winId(), GWL_STYLE, dwStyle);
+ // we might need to repaint in some situations (eg. menu)
+ w->repaint();
+ }
+}
+#endif
+
+/*****************************************************************************
+ QWidget event handling
+ *****************************************************************************/
+
+/*!
+ This is the main event handler; it handles event \a event. You can
+ reimplement this function in a subclass, but we recommend using
+ one of the specialized event handlers instead.
+
+ Key press and release events are treated differently from other
+ events. event() checks for Tab and Shift+Tab and tries to move the
+ focus appropriately. If there is no widget to move the focus to
+ (or the key press is not Tab or Shift+Tab), event() calls
+ keyPressEvent().
+
+ Mouse and tablet event handling is also slightly special: only
+ when the widget is \l enabled, event() will call the specialized
+ handlers such as mousePressEvent(); otherwise it will discard the
+ event.
+
+ This function returns true if the event was recognized, otherwise
+ it returns false. If the recognized event was accepted (see \l
+ QEvent::accepted), any further processing such as event
+ propagation to the parent widget stops.
+
+ \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
+ keyPressEvent(), keyReleaseEvent(), leaveEvent(),
+ mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
+ mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
+ QObject::event(), QObject::timerEvent()
+*/
+
+bool QWidget::event(QEvent *event)
+{
+ Q_D(QWidget);
+
+ // ignore mouse events when disabled
+ if (!isEnabled()) {
+ switch(event->type()) {
+ case QEvent::TabletPress:
+ case QEvent::TabletRelease:
+ case QEvent::TabletMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::ContextMenu:
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+#endif
+ return false;
+ default:
+ break;
+ }
+ }
+ switch (event->type()) {
+ case QEvent::MouseMove:
+ mouseMoveEvent((QMouseEvent*)event);
+ break;
+
+ case QEvent::MouseButtonPress:
+ // Don't reset input context here. Whether reset or not is
+ // a responsibility of input method. reset() will be
+ // called by mouseHandler() of input method if necessary
+ // via mousePressEvent() of text widgets.
+#if 0
+ resetInputContext();
+#endif
+ mousePressEvent((QMouseEvent*)event);
+ break;
+
+ case QEvent::MouseButtonRelease:
+ mouseReleaseEvent((QMouseEvent*)event);
+ break;
+
+ case QEvent::MouseButtonDblClick:
+ mouseDoubleClickEvent((QMouseEvent*)event);
+ break;
+#ifndef QT_NO_WHEELEVENT
+ case QEvent::Wheel:
+ wheelEvent((QWheelEvent*)event);
+ break;
+#endif
+#ifndef QT_NO_TABLETEVENT
+ case QEvent::TabletMove:
+ case QEvent::TabletPress:
+ case QEvent::TabletRelease:
+ tabletEvent((QTabletEvent*)event);
+ break;
+#endif
+#ifdef QT3_SUPPORT
+ case QEvent::Accel:
+ event->ignore();
+ return false;
+#endif
+ case QEvent::KeyPress: {
+ QKeyEvent *k = (QKeyEvent *)event;
+ bool res = false;
+ if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
+ if (k->key() == Qt::Key_Backtab
+ || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
+ res = focusNextPrevChild(false);
+ else if (k->key() == Qt::Key_Tab)
+ res = focusNextPrevChild(true);
+ if (res)
+ break;
+ }
+ keyPressEvent(k);
+#ifdef QT_KEYPAD_NAVIGATION
+ if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
+ && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
+ if (k->key() == Qt::Key_Up)
+ res = focusNextPrevChild(false);
+ else if (k->key() == Qt::Key_Down)
+ res = focusNextPrevChild(true);
+ if (res) {
+ k->accept();
+ break;
+ }
+ }
+#endif
+#ifndef QT_NO_WHATSTHIS
+ if (!k->isAccepted()
+ && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
+ && d->whatsThis.size()) {
+ QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImMicroFocus).toRect().center()), d->whatsThis, this);
+ k->accept();
+ }
+#endif
+ }
+ break;
+
+ case QEvent::KeyRelease:
+ keyReleaseEvent((QKeyEvent*)event);
+ // fall through
+ case QEvent::ShortcutOverride:
+ break;
+
+ case QEvent::InputMethod:
+ inputMethodEvent((QInputMethodEvent *) event);
+ break;
+
+ case QEvent::PolishRequest:
+ ensurePolished();
+ break;
+
+ case QEvent::Polish: {
+ style()->polish(this);
+ setAttribute(Qt::WA_WState_Polished);
+ if (!QApplication::font(this).isCopyOf(QApplication::font()))
+ d->resolveFont();
+ if (!QApplication::palette(this).isCopyOf(QApplication::palette()))
+ d->resolvePalette();
+#ifdef QT3_SUPPORT
+ if(d->sendChildEvents)
+ QApplication::sendPostedEvents(this, QEvent::ChildInserted);
+#endif
+ }
+ break;
+
+ case QEvent::ApplicationWindowIconChange:
+ if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
+ d->setWindowIcon_sys();
+ d->setWindowIcon_helper();
+ }
+ break;
+ case QEvent::FocusIn:
+#if defined(Q_WS_WIN)
+ QInputContextPrivate::updateImeStatus(this, true);
+#endif
+ focusInEvent((QFocusEvent*)event);
+ break;
+
+ case QEvent::FocusOut:
+#if defined(Q_WS_WIN)
+ QInputContextPrivate::updateImeStatus(this, false);
+#endif
+ focusOutEvent((QFocusEvent*)event);
+ break;
+
+ case QEvent::Enter:
+#ifndef QT_NO_STATUSTIP
+ if (d->statusTip.size()) {
+ QStatusTipEvent tip(d->statusTip);
+ QApplication::sendEvent(const_cast<QWidget *>(this), &tip);
+ }
+#endif
+ enterEvent(event);
+ break;
+
+ case QEvent::Leave:
+#ifndef QT_NO_STATUSTIP
+ if (d->statusTip.size()) {
+ QString empty;
+ QStatusTipEvent tip(empty);
+ QApplication::sendEvent(const_cast<QWidget *>(this), &tip);
+ }
+#endif
+ leaveEvent(event);
+ break;
+
+ case QEvent::HoverEnter:
+ case QEvent::HoverLeave:
+ update();
+ break;
+
+ case QEvent::Paint:
+ // At this point the event has to be delivered, regardless
+ // whether the widget isVisible() or not because it
+ // already went through the filters
+ paintEvent((QPaintEvent*)event);
+ break;
+
+ case QEvent::Move:
+ moveEvent((QMoveEvent*)event);
+ break;
+
+ case QEvent::Resize:
+ resizeEvent((QResizeEvent*)event);
+ break;
+
+ case QEvent::Close:
+ closeEvent((QCloseEvent *)event);
+ break;
+
+#ifndef QT_NO_CONTEXTMENU
+ case QEvent::ContextMenu:
+ switch (data->context_menu_policy) {
+ case Qt::PreventContextMenu:
+ break;
+ case Qt::DefaultContextMenu:
+ contextMenuEvent(static_cast<QContextMenuEvent *>(event));
+ break;
+ case Qt::CustomContextMenu:
+ emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
+ break;
+#ifndef QT_NO_MENU
+ case Qt::ActionsContextMenu:
+ if (d->actions.count()) {
+ QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
+ 0, this);
+ break;
+ }
+ // fall through
+#endif
+ default:
+ event->ignore();
+ break;
+ }
+ break;
+#endif // QT_NO_CONTEXTMENU
+
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::Drop:
+ dropEvent((QDropEvent*) event);
+ break;
+
+ case QEvent::DragEnter:
+ dragEnterEvent((QDragEnterEvent*) event);
+ break;
+
+ case QEvent::DragMove:
+ dragMoveEvent((QDragMoveEvent*) event);
+ break;
+
+ case QEvent::DragLeave:
+ dragLeaveEvent((QDragLeaveEvent*) event);
+ break;
+#endif
+
+ case QEvent::Show:
+ showEvent((QShowEvent*) event);
+ break;
+
+ case QEvent::Hide:
+ hideEvent((QHideEvent*) event);
+ break;
+
+ case QEvent::ShowWindowRequest:
+ if (!isHidden())
+ d->show_sys();
+ break;
+
+ case QEvent::ApplicationFontChange:
+ d->resolveFont();
+ break;
+ case QEvent::ApplicationPaletteChange:
+ if (!(windowType() == Qt::Desktop))
+ d->resolvePalette();
+ break;
+
+ case QEvent::ToolBarChange:
+ case QEvent::ActivationChange:
+ case QEvent::EnabledChange:
+ case QEvent::FontChange:
+ case QEvent::StyleChange:
+ case QEvent::PaletteChange:
+ case QEvent::WindowTitleChange:
+ case QEvent::IconTextChange:
+ case QEvent::ModifiedChange:
+ case QEvent::MouseTrackingChange:
+ case QEvent::ParentChange:
+ case QEvent::WindowStateChange:
+ case QEvent::LocaleChange:
+ case QEvent::MacSizeChange:
+ case QEvent::ContentsRectChange:
+ changeEvent(event);
+ break;
+
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate: {
+#ifdef QT3_SUPPORT
+ windowActivationChange(event->type() != QEvent::WindowActivate);
+#endif
+ if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
+ update();
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(childList.at(i));
+ if (w && w->isVisible() && !w->isWindow())
+ QApplication::sendEvent(w, event);
+ }
+ break; }
+
+ case QEvent::LanguageChange:
+#ifdef QT3_SUPPORT
+ languageChange();
+#endif
+ changeEvent(event);
+ {
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ QApplication::sendEvent(o, event);
+ }
+ }
+ update();
+ break;
+
+ case QEvent::ApplicationLayoutDirectionChange:
+ d->resolveLayoutDirection();
+ break;
+
+ case QEvent::LayoutDirectionChange:
+ if (d->layout)
+ d->layout->invalidate();
+ update();
+ changeEvent(event);
+ break;
+ case QEvent::UpdateRequest:
+ d->syncBackingStore();
+ break;
+ case QEvent::UpdateLater:
+ update(static_cast<QUpdateLaterEvent*>(event)->region());
+ break;
+
+ case QEvent::WindowBlocked:
+ case QEvent::WindowUnblocked:
+ {
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QObject *o = childList.at(i);
+ if (o != qApp->activeModalWidget()) {
+ if (qobject_cast<QWidget *>(o) && static_cast<QWidget *>(o)->isWindow()) {
+ // do not forward the event to child windows,
+ // QApplication does this for us
+ continue;
+ }
+ QApplication::sendEvent(o, event);
+ }
+ }
+#if defined(Q_WS_WIN)
+ setDisabledStyle(this, (event->type() == QEvent::WindowBlocked));
+#endif
+ }
+ break;
+#ifndef QT_NO_TOOLTIP
+ case QEvent::ToolTip:
+ if (!d->toolTip.isEmpty())
+ QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this);
+ else
+ event->ignore();
+ break;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ case QEvent::WhatsThis:
+ if (d->whatsThis.size())
+ QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
+ else
+ event->ignore();
+ break;
+ case QEvent::QueryWhatsThis:
+ if (d->whatsThis.isEmpty())
+ event->ignore();
+ break;
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ case QEvent::AccessibilityDescription:
+ case QEvent::AccessibilityHelp: {
+ QAccessibleEvent *ev = static_cast<QAccessibleEvent *>(event);
+ if (ev->child())
+ return false;
+ switch (ev->type()) {
+#ifndef QT_NO_TOOLTIP
+ case QEvent::AccessibilityDescription:
+ ev->setValue(d->toolTip);
+ break;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ case QEvent::AccessibilityHelp:
+ ev->setValue(d->whatsThis);
+ break;
+#endif
+ default:
+ return false;
+ }
+ break; }
+#endif
+ case QEvent::EmbeddingControl:
+ d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
+ data->fstrut_dirty = false;
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ d->topData()->embedded = 1;
+#endif
+ break;
+#ifndef QT_NO_ACTION
+ case QEvent::ActionAdded:
+ case QEvent::ActionRemoved:
+ case QEvent::ActionChanged:
+ actionEvent((QActionEvent*)event);
+ break;
+#endif
+
+ case QEvent::KeyboardLayoutChange:
+ {
+ changeEvent(event);
+
+ // inform children of the change
+ QList<QObject*> childList = d->children;
+ for (int i = 0; i < childList.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(childList.at(i));
+ if (w && w->isVisible() && !w->isWindow())
+ QApplication::sendEvent(w, event);
+ }
+ break;
+ }
+#ifdef Q_WS_MAC
+ case QEvent::MacGLWindowChange:
+ d->needWindowChange = false;
+ break;
+#endif
+#ifndef QT_NO_PROPERTIES
+ case QEvent::DynamicPropertyChange: {
+ const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
+ if (!qstrncmp(propName, "_q_customDpi", 12) && propName.length() == 13) {
+ uint value = property(propName.constData()).toUInt();
+ if (!d->extra)
+ d->createExtra();
+ const char axis = propName.at(12);
+ if (axis == 'X')
+ d->extra->customDpiX = value;
+ else if (axis == 'Y')
+ d->extra->customDpiY = value;
+ d->updateFont(d->data.fnt);
+ }
+ // fall through
+ }
+#endif
+ default:
+ return QObject::event(event);
+ }
+ return true;
+}
+
+/*!
+ This event handler can be reimplemented to handle state changes.
+
+ The state being changed in this event can be retrieved through event \a
+ event.
+
+ Change events include: QEvent::ToolBarChange,
+ QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
+ QEvent::StyleChange, QEvent::PaletteChange,
+ QEvent::WindowTitleChange, QEvent::IconTextChange,
+ QEvent::ModifiedChange, QEvent::MouseTrackingChange,
+ QEvent::ParentChange, QEvent::WindowStateChange,
+ QEvent::LanguageChange, QEvent::LocaleChange,
+ QEvent::LayoutDirectionChange.
+
+*/
+void QWidget::changeEvent(QEvent * event)
+{
+ switch(event->type()) {
+ case QEvent::EnabledChange:
+ update();
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
+#endif
+ break;
+
+ case QEvent::FontChange:
+ case QEvent::StyleChange: {
+ update();
+ updateGeometry();
+#ifdef Q_WS_QWS
+ Q_D(QWidget);
+ if (isWindow())
+ d->data.fstrut_dirty = true;
+#endif
+ break;
+ }
+
+ case QEvent::PaletteChange:
+ update();
+ break;
+
+#ifdef Q_WS_MAC
+ case QEvent::MacSizeChange:
+ updateGeometry();
+ break;
+ case QEvent::ToolTipChange:
+ case QEvent::MouseTrackingChange:
+ qt_mac_update_mouseTracking(this);
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse move events for the widget.
+
+ If mouse tracking is switched off, mouse move events only occur if
+ a mouse button is pressed while the mouse is being moved. If mouse
+ tracking is switched on, mouse move events occur even if no mouse
+ button is pressed.
+
+ QMouseEvent::pos() reports the position of the mouse cursor,
+ relative to this widget. For press and release events, the
+ position is usually the same as the position of the last mouse
+ move event, but it might be different if the user's hand shakes.
+ This is a feature of the underlying window system, not Qt.
+
+ If you want to show a tooltip immediately, while the mouse is
+ moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
+ and show them as a tooltip), you must first enable mouse tracking
+ as described above. Then, to ensure that the tooltip is updated
+ immediately, you must call QToolTip::showText() instead of
+ setToolTip() in your implementation of mouseMoveEvent().
+
+ \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
+ mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
+*/
+
+void QWidget::mouseMoveEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse press events for the widget.
+
+ If you create new widgets in the mousePressEvent() the
+ mouseReleaseEvent() may not end up where you expect, depending on
+ the underlying window system (or X11 window manager), the widgets'
+ location and maybe more.
+
+ The default implementation implements the closing of popup widgets
+ when you click outside the window. For other widget types it does
+ nothing.
+
+ \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
+ mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
+*/
+
+void QWidget::mousePressEvent(QMouseEvent *event)
+{
+ event->ignore();
+ if ((windowType() == Qt::Popup)) {
+ event->accept();
+ QWidget* w;
+ while ((w = qApp->activePopupWidget()) && w != this){
+ w->close();
+ if (qApp->activePopupWidget() == w) // widget does not want to dissappear
+ w->hide(); // hide at least
+ }
+ if (!rect().contains(event->pos())){
+ close();
+ }
+ }
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse release events for the widget.
+
+ \sa mousePressEvent(), mouseDoubleClickEvent(),
+ mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
+*/
+
+void QWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive mouse double click events for the widget.
+
+ The default implementation generates a normal mouse press event.
+
+ Note that the widgets gets a mousePressEvent() and a
+ mouseReleaseEvent() before the mouseDoubleClickEvent().
+
+ \sa mousePressEvent(), mouseReleaseEvent() mouseMoveEvent(),
+ event(), QMouseEvent
+*/
+
+void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ mousePressEvent(event); // try mouse press event
+}
+
+#ifndef QT_NO_WHEELEVENT
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive wheel events for the widget.
+
+ If you reimplement this handler, it is very important that you
+ \link QWheelEvent ignore()\endlink the event if you do not handle
+ it, so that the widget's parent can interpret it.
+
+ The default implementation ignores the event.
+
+ \sa QWheelEvent::ignore(), QWheelEvent::accept(), event(),
+ QWheelEvent
+*/
+
+void QWidget::wheelEvent(QWheelEvent *event)
+{
+ event->ignore();
+}
+#endif // QT_NO_WHEELEVENT
+
+#ifndef QT_NO_TABLETEVENT
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive tablet events for the widget.
+
+ If you reimplement this handler, it is very important that you
+ \link QTabletEvent ignore()\endlink the event if you do not handle
+ it, so that the widget's parent can interpret it.
+
+ The default implementation ignores the event.
+
+ \sa QTabletEvent::ignore(), QTabletEvent::accept(), event(),
+ QTabletEvent
+*/
+
+void QWidget::tabletEvent(QTabletEvent *event)
+{
+ event->ignore();
+}
+#endif // QT_NO_TABLETEVENT
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive key press events for the widget.
+
+ A widget must call setFocusPolicy() to accept focus initially and
+ have focus in order to receive a key press event.
+
+ If you reimplement this handler, it is very important that you
+ call the base class implementation if you do not act upon the key.
+
+ The default implementation closes popup widgets if the user
+ presses Esc. Otherwise the event is ignored, so that the widget's
+ parent can interpret it.
+
+ Note that QKeyEvent starts with isAccepted() == true, so you do not
+ need to call QKeyEvent::accept() - just do not call the base class
+ implementation if you act upon the key.
+
+ \sa keyReleaseEvent(), setFocusPolicy(),
+ focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}
+*/
+
+void QWidget::keyPressEvent(QKeyEvent *event)
+{
+ if ((windowType() == Qt::Popup) && event->key() == Qt::Key_Escape) {
+ event->accept();
+ close();
+ } else {
+ event->ignore();
+ }
+}
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive key release events for the widget.
+
+ A widget must \link setFocusPolicy() accept focus\endlink
+ initially and \link hasFocus() have focus\endlink in order to
+ receive a key release event.
+
+ If you reimplement this handler, it is very important that you
+ call the base class implementation if you do not act upon the key.
+
+ The default implementation ignores the event, so that the widget's
+ parent can interpret it.
+
+ Note that QKeyEvent starts with isAccepted() == true, so you do not
+ need to call QKeyEvent::accept() - just do not call the base class
+ implementation if you act upon the key.
+
+ \sa keyPressEvent(), QKeyEvent::ignore(), setFocusPolicy(),
+ focusInEvent(), focusOutEvent(), event(), QKeyEvent
+*/
+
+void QWidget::keyReleaseEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ \fn void QWidget::focusInEvent(QFocusEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ keyboard focus events (focus received) for the widget. The event
+ is passed in the \a event parameter
+
+ A widget normally must setFocusPolicy() to something other than
+ Qt::NoFocus in order to receive focus events. (Note that the
+ application programmer can call setFocus() on any widget, even
+ those that do not normally accept focus.)
+
+ The default implementation updates the widget (except for windows
+ that do not specify a focusPolicy()).
+
+ \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
+ keyReleaseEvent(), event(), QFocusEvent
+*/
+
+void QWidget::focusInEvent(QFocusEvent *)
+{
+ if (focusPolicy() != Qt::NoFocus || !isWindow()) {
+ update();
+ }
+}
+
+/*!
+ \fn void QWidget::focusOutEvent(QFocusEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ keyboard focus events (focus lost) for the widget. The events is
+ passed in the \a event parameter.
+
+ A widget normally must setFocusPolicy() to something other than
+ Qt::NoFocus in order to receive focus events. (Note that the
+ application programmer can call setFocus() on any widget, even
+ those that do not normally accept focus.)
+
+ The default implementation updates the widget (except for windows
+ that do not specify a focusPolicy()).
+
+ \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
+ keyReleaseEvent(), event(), QFocusEvent
+*/
+
+void QWidget::focusOutEvent(QFocusEvent *)
+{
+ if (focusPolicy() != Qt::NoFocus || !isWindow())
+ update();
+}
+
+/*!
+ \fn void QWidget::enterEvent(QEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget enter events which are passed in the \a event parameter.
+
+ An event is sent to the widget when the mouse cursor enters the
+ widget.
+
+ \sa leaveEvent(), mouseMoveEvent(), event()
+*/
+
+void QWidget::enterEvent(QEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::leaveEvent(QEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget leave events which are passed in the \a event parameter.
+
+ A leave event is sent to the widget when the mouse cursor leaves
+ the widget.
+
+ \sa enterEvent(), mouseMoveEvent(), event()
+*/
+
+void QWidget::leaveEvent(QEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::paintEvent(QPaintEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive paint
+ events passed in \a event.
+
+ A paint event is a request to repaint all or part of a widget. It can
+ happen for one of the following reasons:
+
+ \list
+ \o repaint() or update() was invoked,
+ \o the widget was obscured and has now been uncovered, or
+ \o many other reasons.
+ \endlist
+
+ Many widgets can simply repaint their entire surface when asked to, but
+ some slow widgets need to optimize by painting only the requested region:
+ QPaintEvent::region(). This speed optimization does not change the result,
+ as painting is clipped to that region during event processing. QListView
+ and QTableView do this, for example.
+
+ Qt also tries to speed up painting by merging multiple paint events into
+ one. When update() is called several times or the window system sends
+ several paint events, Qt merges these events into one event with a larger
+ region (see QRegion::united()). The repaint() function does not permit this
+ optimization, so we suggest using update() whenever possible.
+
+ When the paint event occurs, the update region has normally been erased, so
+ you are painting on the widget's background.
+
+ The background can be set using setBackgroundRole() and setPalette().
+
+ Since Qt 4.0, QWidget automatically double-buffers its painting, so there
+ is no need to write double-buffering code in paintEvent() to avoid flicker.
+
+ \bold{Note for the X11 platform}: It is possible to toggle global double
+ buffering by calling \c qt_x11_set_global_double_buffer(). For example,
+
+ \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 14
+
+ \note Generally, you should refrain from calling update() or repaint()
+ \bold{inside} a paintEvent(). For example, calling update() or repaint() on
+ children inside a paintevent() results in undefined behavior; the child may
+ or may not get a paint event.
+
+ \warning If you are using a custom paint engine without Qt's backingstore,
+ Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
+ never be called; the backingstore will be used instead.
+
+ \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
+ {Analog Clock Example}
+*/
+
+void QWidget::paintEvent(QPaintEvent *)
+{
+}
+
+
+/*!
+ \fn void QWidget::moveEvent(QMoveEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget move events which are passed in the \a event parameter.
+ When the widget receives this event, it is already at the new
+ position.
+
+ The old position is accessible through QMoveEvent::oldPos().
+
+ \sa resizeEvent(), event(), move(), QMoveEvent
+*/
+
+void QWidget::moveEvent(QMoveEvent *)
+{
+}
+
+
+/*!
+ This event handler can be reimplemented in a subclass to receive
+ widget resize events which are passed in the \a event parameter.
+ When resizeEvent() is called, the widget already has its new
+ geometry. The old size is accessible through
+ QResizeEvent::oldSize().
+
+ The widget will be erased and receive a paint event immediately
+ after processing the resize event. No drawing need be (or should
+ be) done inside this handler.
+
+
+ \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
+ {Scribble Example}
+*/
+
+void QWidget::resizeEvent(QResizeEvent * /* event */)
+{
+}
+
+#ifndef QT_NO_ACTION
+/*!
+ \fn void QWidget::actionEvent(QActionEvent *event)
+
+ This event handler is called with the given \a event whenever the
+ widget's actions are changed.
+
+ \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
+*/
+void QWidget::actionEvent(QActionEvent *)
+{
+
+}
+#endif
+
+/*!
+ This event handler is called with the given \a event when Qt receives a window
+ close request for a top-level widget from the window system.
+
+ By default, the event is accepted and the widget is closed. You can reimplement
+ this function to change the way the widget responds to window close requests.
+ For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
+ on all events.
+
+ Main window applications typically use reimplementations of this function to check
+ whether the user's work has been saved and ask for permission before closing.
+ For example, the \l{Application Example} uses a helper function to determine whether
+ or not to close the window:
+
+ \snippet mainwindows/application/mainwindow.cpp 3
+ \snippet mainwindows/application/mainwindow.cpp 4
+
+ \sa event(), hide(), close(), QCloseEvent, {Application Example}
+*/
+
+void QWidget::closeEvent(QCloseEvent *event)
+{
+ event->accept();
+}
+
+#ifndef QT_NO_CONTEXTMENU
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive widget context menu events.
+
+ The handler is called when the widget's \l contextMenuPolicy is
+ Qt::DefaultContextMenu.
+
+ The default implementation ignores the context event.
+ See the \l QContextMenuEvent documentation for more details.
+
+ \sa event(), QContextMenuEvent customContextMenuRequested()
+*/
+
+void QWidget::contextMenuEvent(QContextMenuEvent *event)
+{
+ event->ignore();
+}
+#endif // QT_NO_CONTEXTMENU
+
+
+/*!
+ This event handler, for event \a event, can be reimplemented in a
+ subclass to receive Input Method composition events. This handler
+ is called when the state of the input method changes.
+
+ Note that when creating custom text editing widgets, the
+ Qt::WA_InputMethodEnabled window attribute must be set explicitly
+ (using the setAttribute() function) in order to receive input
+ method events.
+
+ The default implementation calls event->ignore(), which rejects the
+ Input Method event. See the \l QInputMethodEvent documentation for more
+ details.
+
+ \sa event(), QInputMethodEvent
+*/
+void QWidget::inputMethodEvent(QInputMethodEvent *event)
+{
+ event->ignore();
+}
+
+/*!
+ This method is only relevant for input widgets. It is used by the
+ input method to query a set of properties of the widget to be
+ able to support complex input method operations as support for
+ surrounding text and reconversions.
+
+ \a query specifies which property is queried.
+
+ \sa inputMethodEvent(), QInputMethodEvent, QInputContext
+*/
+QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ switch(query) {
+ case Qt::ImMicroFocus:
+ return QRect(width()/2, 0, 1, height());
+ case Qt::ImFont:
+ return font();
+ default:
+ return QVariant();
+ }
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+/*!
+ \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
+
+ This event handler is called when a drag is in progress and the
+ mouse enters this widget. The event is passed in the \a event parameter.
+
+ If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
+ move events}.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDragEnterEvent
+*/
+void QWidget::dragEnterEvent(QDragEnterEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
+
+ This event handler is called if a drag is in progress, and when
+ any of the following conditions occur: the cursor enters this widget,
+ the cursor moves within this widget, or a modifier key is pressed on
+ the keyboard while this widget has the focus. The event is passed
+ in the \a event parameter.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDragMoveEvent
+*/
+void QWidget::dragMoveEvent(QDragMoveEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
+
+ This event handler is called when a drag is in progress and the
+ mouse leaves this widget. The event is passed in the \a event
+ parameter.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDragLeaveEvent
+*/
+void QWidget::dragLeaveEvent(QDragLeaveEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::dropEvent(QDropEvent *event)
+
+ This event handler is called when the drag is dropped on this
+ widget. The event is passed in the \a event parameter.
+
+ See the \link dnd.html Drag-and-drop documentation\endlink for an
+ overview of how to provide drag-and-drop in your application.
+
+ \sa QDrag, QDropEvent
+*/
+void QWidget::dropEvent(QDropEvent *)
+{
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+/*!
+ \fn void QWidget::showEvent(QShowEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget show events which are passed in the \a event parameter.
+
+ Non-spontaneous show events are sent to widgets immediately
+ before they are shown. The spontaneous show events of windows are
+ delivered afterwards.
+
+ Note: A widget receives spontaneous show and hide events when its
+ mapping status is changed by the window system, e.g. a spontaneous
+ hide event when the user minimizes the window, and a spontaneous
+ show event when the window is restored again. After receiving a
+ spontaneous hide event, a widget is still considered visible in
+ the sense of isVisible().
+
+ \sa visible, event(), QShowEvent
+*/
+void QWidget::showEvent(QShowEvent *)
+{
+}
+
+/*!
+ \fn void QWidget::hideEvent(QHideEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ widget hide events. The event is passed in the \a event parameter.
+
+ Hide events are sent to widgets immediately after they have been
+ hidden.
+
+ Note: A widget receives spontaneous show and hide events when its
+ mapping status is changed by the window system, e.g. a spontaneous
+ hide event when the user minimizes the window, and a spontaneous
+ show event when the window is restored again. After receiving a
+ spontaneous hide event, a widget is still considered visible in
+ the sense of isVisible().
+
+ \sa visible, event(), QHideEvent
+*/
+void QWidget::hideEvent(QHideEvent *)
+{
+}
+
+/*
+ \fn QWidget::x11Event(MSG *)
+
+ This special event handler can be reimplemented in a subclass to receive
+ native X11 events.
+
+ In your reimplementation of this function, if you want to stop Qt from
+ handling the event, return true. If you return false, this native event
+ is passed back to Qt, which translates it into a Qt event and sends it to
+ the widget.
+
+ \note Events are only delivered to this event handler if the widget is
+ native.
+
+ \warning This function is not portable.
+
+ \sa QApplication::x11EventFilter(), QWidget::winId()
+*/
+
+
+#if defined(Q_WS_MAC)
+
+/*!
+ \fn bool QWidget::macEvent(EventHandlerCallRef caller, EventRef event)
+
+ This special event handler can be reimplemented in a subclass to
+ receive native Macintosh events.
+
+ The parameters are a bit different depending if Qt is build against Carbon
+ or Cocoa. In Carbon, \a caller and \a event are the corresponding
+ EventHandlerCallRef and EventRef that correspond to the Carbon event
+ handlers that are installed. In Cocoa, \a caller is always 0 and the
+ EventRef is the EventRef generated from the NSEvent.
+
+ In your reimplementation of this function, if you want to stop the
+ event being handled by Qt, return true. If you return false, this
+ native event is passed back to Qt, which translates the event into
+ a Qt event and sends it to the widget.
+
+ \warning This function is not portable.
+
+ \warning This function was not called inside of Qt until Qt 4.4.
+ If you need compatibility with earlier versions of Qt, consider QApplication::macEventFilter() instead.
+
+ \sa QApplication::macEventFilter()
+*/
+
+bool QWidget::macEvent(EventHandlerCallRef, EventRef)
+{
+ return false;
+}
+
+#endif
+#if defined(Q_WS_WIN)
+
+/*!
+ This special event handler can be reimplemented in a subclass to
+ receive native Windows events which are passed in the \a message
+ parameter.
+
+ In your reimplementation of this function, if you want to stop the
+ event being handled by Qt, return true and set \a result to the value
+ that the window procedure should return. If you return false, this
+ native event is passed back to Qt, which translates the event into
+ a Qt event and sends it to the widget.
+
+ \warning This function is not portable.
+
+ \sa QApplication::winEventFilter()
+*/
+bool QWidget::winEvent(MSG *message, long *result)
+{
+ Q_UNUSED(message);
+ Q_UNUSED(result);
+ return false;
+}
+
+#endif
+#if defined(Q_WS_X11)
+
+/*!
+ \fn bool QWidget::x11Event(XEvent *event)
+
+ This special event handler can be reimplemented in a subclass to receive
+ native X11 events passed in the \a event parameter.
+
+ In your reimplementation of this function, if you want to stop Qt from
+ handling the event, return true. If you return false, this native event
+ is passed back to Qt, which translates it into a Qt event and sends it to
+ the widget.
+
+ \note Events are only delivered to this event handler if the widget is
+ native.
+
+ \warning This function is not portable.
+
+ \sa QApplication::x11EventFilter(), QWidget::winId()
+*/
+bool QWidget::x11Event(XEvent *)
+{
+ return false;
+}
+
+#endif
+#if defined(Q_WS_QWS)
+
+/*!
+ \fn bool QWidget::qwsEvent(QWSEvent *event)
+
+ This special event handler can be reimplemented in a subclass to
+ receive native Qt for Embedded Linux events which are passed in the
+ \a event parameter.
+
+ In your reimplementation of this function, if you want to stop the
+ event being handled by Qt, return true. If you return false, this
+ native event is passed back to Qt, which translates the event into
+ a Qt event and sends it to the widget.
+
+ \warning This function is not portable.
+
+ \sa QApplication::qwsEventFilter()
+*/
+bool QWidget::qwsEvent(QWSEvent *)
+{
+ return false;
+}
+
+#endif
+
+
+/*!
+ Ensures that the widget has been polished by QStyle (i.e., has a
+ proper font and palette).
+
+ QWidget calls this function after it has been fully constructed
+ but before it is shown the very first time. You can call this
+ function if you want to ensure that the widget is polished before
+ doing an operation, e.g., the correct font size might be needed in
+ the widget's sizeHint() reimplementation. Note that this function
+ \e is called from the default implementation of sizeHint().
+
+ Polishing is useful for final initialization that must happen after
+ all constructors (from base classes as well as from subclasses)
+ have been called.
+
+ If you need to change some settings when a widget is polished,
+ reimplement event() and handle the QEvent::Polish event type.
+
+ \bold{Note:} The function is declared const so that it can be called from
+ other const functions (e.g., sizeHint()).
+
+ \sa event()
+*/
+void QWidget::ensurePolished() const
+{
+ Q_D(const QWidget);
+
+ const QMetaObject *m = metaObject();
+ if (m == d->polished)
+ return;
+ d->polished = m;
+
+ QEvent e(QEvent::Polish);
+ QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
+
+ // polish children after 'this'
+ QList<QObject*> children = d->children;
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *o = children.at(i);
+ if(!o->isWidgetType())
+ continue;
+ if (QWidget *w = qobject_cast<QWidget *>(o))
+ w->ensurePolished();
+ }
+
+ if (d->parent && d->sendChildEvents) {
+ QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
+ QCoreApplication::sendEvent(d->parent, &e);
+ }
+}
+
+/*!
+ Returns the mask currently set on a widget. If no mask is set the
+ return value will be an empty region.
+
+ \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
+*/
+QRegion QWidget::mask() const
+{
+ Q_D(const QWidget);
+ return d->extra ? d->extra->mask : QRegion();
+}
+
+/*!
+ Returns the layout manager that is installed on this widget, or 0
+ if no layout manager is installed.
+
+ The layout manager sets the geometry of the widget's children
+ that have been added to the layout.
+
+ \sa setLayout(), sizePolicy(), {Layout Classes}
+*/
+QLayout *QWidget::layout() const
+{
+ return d_func()->layout;
+}
+
+
+/*!
+ \fn void QWidget::setLayout(QLayout *layout)
+
+ Sets the layout manager for this widget to \a layout.
+
+ If there already is a layout manager installed on this widget,
+ QWidget won't let you install another. You must first delete the
+ existing layout manager (returned by layout()) before you can
+ call setLayout() with the new layout.
+
+ If \a layout is the layout manger on a different widget, setLayout()
+ will reparent the layout and make it the layout manager for this widget.
+
+ Example:
+
+ \snippet examples/uitools/textfinder/textfinder.cpp 3b
+
+ An alternative to calling this function is to pass this widget to
+ the layout's constructor.
+
+ The QWidget will take ownership of \a layout.
+
+ \sa layout(), {Layout Classes}
+*/
+
+void QWidget::setLayout(QLayout *l)
+{
+ if (!l) {
+ qWarning("QWidget::setLayout: Cannot set layout to 0");
+ return;
+ }
+ if (layout()) {
+ if (layout() != l)
+ qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
+ " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
+ objectName().toLocal8Bit().data());
+ return;
+ }
+
+ QObject *oldParent = l->parent();
+ if (oldParent && oldParent != this) {
+ if (oldParent->isWidgetType()) {
+ // Steal the layout off a widget parent. Takes effect when
+ // morphing laid-out container widgets in Designer.
+ QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
+ oldParentWidget->takeLayout();
+ } else {
+ qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
+ l->objectName().toLocal8Bit().data(), metaObject()->className(),
+ objectName().toLocal8Bit().data());
+ return;
+ }
+ }
+
+ Q_D(QWidget);
+ l->d_func()->topLevel = true;
+ d->layout = l;
+ if (oldParent != this) {
+ l->setParent(this);
+ l->d_func()->reparentChildWidgets(this);
+ l->invalidate();
+ }
+
+ if (isWindow() && d->maybeTopData())
+ d->topData()->sizeAdjusted = false;
+}
+
+/*!
+ \fn QLayout *QWidget::takeLayout()
+
+ Remove the layout from the widget.
+ \since 4.5
+*/
+
+QLayout *QWidget::takeLayout()
+{
+ Q_D(QWidget);
+ QLayout *l = layout();
+ if (!l)
+ return 0;
+ d->layout = 0;
+ l->setParent(0);
+ return l;
+}
+
+/*!
+ \property QWidget::sizePolicy
+ \brief the default layout behavior of the widget
+
+ If there is a QLayout that manages this widget's children, the
+ size policy specified by that layout is used. If there is no such
+ QLayout, the result of this function is used.
+
+ The default policy is Preferred/Preferred, which means that the
+ widget can be freely resized, but prefers to be the size
+ sizeHint() returns. Button-like widgets set the size policy to
+ specify that they may stretch horizontally, but are fixed
+ vertically. The same applies to lineedit controls (such as
+ QLineEdit, QSpinBox or an editable QComboBox) and other
+ horizontally orientated widgets (such as QProgressBar).
+ QToolButton's are normally square, so they allow growth in both
+ directions. Widgets that support different directions (such as
+ QSlider, QScrollBar or QHeader) specify stretching in the
+ respective direction only. Widgets that can provide scroll bars
+ (usually subclasses of QScrollArea) tend to specify that they can
+ use additional space, and that they can make do with less than
+ sizeHint().
+
+ \sa sizeHint() QLayout QSizePolicy updateGeometry()
+*/
+QSizePolicy QWidget::sizePolicy() const
+{
+ Q_D(const QWidget);
+ return d->size_policy;
+}
+
+void QWidget::setSizePolicy(QSizePolicy policy)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_WState_OwnSizePolicy);
+ if (policy == d->size_policy)
+ return;
+ d->size_policy = policy;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QWExtra *extra = d->extra) {
+ if (extra->proxyWidget)
+ extra->proxyWidget->setSizePolicy(policy);
+ }
+#endif
+
+ updateGeometry();
+
+ if (isWindow() && d->maybeTopData())
+ d->topData()->sizeAdjusted = false;
+}
+
+/*!
+ \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
+ \overload
+
+ Sets the size policy of the widget to \a horizontal and \a
+ vertical, with standard stretch and no height-for-width.
+
+ \sa QSizePolicy::QSizePolicy()
+*/
+
+/*!
+ Returns the preferred height for this widget, given the width \a w.
+
+ If this widget has a layout, the default implementation returns
+ the layout's preferred height. if there is no layout, the default
+ implementation returns -1 indicating that the preferred height
+ does not depend on the width.
+*/
+
+int QWidget::heightForWidth(int w) const
+{
+ if (layout() && layout()->hasHeightForWidth())
+ return layout()->totalHeightForWidth(w);
+ return -1;
+}
+
+/*!
+ \fn QWidget *QWidget::childAt(int x, int y) const
+
+ Returns the visible child widget at the position (\a{x}, \a{y})
+ in the widget's coordinate system. If there is no visible child
+ widget at the specified position, the function returns 0.
+*/
+
+/*!
+ \overload
+
+ Returns the visible child widget at point \a p in the widget's own
+ coordinate system.
+*/
+
+QWidget *QWidget::childAt(const QPoint &p) const
+{
+ return d_func()->childAt_helper(p, false);
+}
+
+QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
+{
+ Q_Q(const QWidget);
+ if (!q->rect().contains(p))
+ return 0;
+ for (int i = children.size(); i > 0 ;) {
+ --i;
+ QWidget *w = qobject_cast<QWidget *>(children.at(i));
+ if (w && !w->isWindow() && !w->isHidden() && w->geometry().contains(p)) {
+ if (ignoreChildrenInDestructor && w->data->in_destructor)
+ continue;
+ if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
+ continue;
+ QPoint childPoint = w->mapFromParent(p);
+ if (QWidget *t = w->d_func()->childAt_helper(childPoint, ignoreChildrenInDestructor))
+ return t;
+ // if WMouseNoMask is set the widget mask is ignored, if
+ // the widget has no mask then the WMouseNoMask flag has no
+ // effect
+ if (w->testAttribute(Qt::WA_MouseNoMask) || w->mask().contains(childPoint)
+ || w->mask().isEmpty())
+ return w;
+ }
+ }
+ return 0;
+}
+
+void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
+{
+ Q_Q(QWidget);
+ if (widgetItem)
+ widgetItem->invalidateSizeCache();
+ QWidget *parent;
+ if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
+ if (!q->isWindow() && !q->isHidden() && (parent = q->parentWidget())) {
+ if (parent->d_func()->layout)
+ parent->d_func()->layout->invalidate();
+ else if (parent->isVisible())
+ QApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
+ }
+ }
+}
+
+/*!
+ Notifies the layout system that this widget has changed and may
+ need to change geometry.
+
+ Call this function if the sizeHint() or sizePolicy() have changed.
+
+ For explicitly hidden widgets, updateGeometry() is a no-op. The
+ layout system will be notified as soon as the widget is shown.
+*/
+
+void QWidget::updateGeometry()
+{
+ Q_D(QWidget);
+ d->updateGeometry_helper(false);
+}
+
+/*! \property QWidget::windowFlags
+
+ Window flags are a combination of a type (e.g. Qt::Dialog) and
+ zero or more hints to the window system (e.g.
+ Qt::FramelessWindowHint).
+
+ If the widget had type Qt::Widget or Qt::SubWindow and becomes a
+ window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
+ 0) on the desktop. If the widget is a window and becomes a
+ Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
+ relative to its parent widget.
+
+ \note This function calls setParent() when changing the flags for
+ a window, causing the widget to be hidden. You must call show() to make
+ the widget visible again..
+
+ \sa windowType(), {Window Flags Example}
+*/
+void QWidget::setWindowFlags(Qt::WindowFlags flags)
+{
+ if (data->window_flags == flags)
+ return;
+
+ Q_D(QWidget);
+
+ if ((data->window_flags | flags) & Qt::Window) {
+ // the old type was a window and/or the new type is a window
+ QPoint oldPos = pos();
+ bool visible = isVisible();
+ setParent(parentWidget(), flags);
+
+ // if both types are windows or neither of them are, we restore
+ // the old position
+ if (!((data->window_flags ^ flags) & Qt::Window)
+ && (visible || testAttribute(Qt::WA_Moved))) {
+ move(oldPos);
+ }
+ // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
+ d->adjustQuitOnCloseAttribute();
+ } else {
+ data->window_flags = flags;
+ }
+}
+
+/*!
+ Sets the window flags for the widget to \a flags,
+ \e without telling the window system.
+
+ \warning Do not call this function unless you really know what
+ you're doing.
+
+ \sa setWindowFlags()
+*/
+void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
+{
+ data->window_flags = flags;
+}
+
+/*!
+ \fn Qt::WindowType QWidget::windowType() const
+
+ Returns the window type of this widget. This is identical to
+ windowFlags() & Qt::WindowType_Mask.
+
+ \sa windowFlags
+*/
+
+/*!
+ Sets the parent of the widget to \a parent, and resets the window
+ flags. The widget is moved to position (0, 0) in its new parent.
+
+ If the new parent widget is in a different window, the
+ reparented widget and its children are appended to the end of the
+ \l{setFocusPolicy()}{tab chain} of the new parent
+ widget, in the same internal order as before. If one of the moved
+ widgets had keyboard focus, setParent() calls clearFocus() for that
+ widget.
+
+ If the new parent widget is in the same window as the
+ old parent, setting the parent doesn't change the tab order or
+ keyboard focus.
+
+ If the "new" parent widget is the old parent widget, this function
+ does nothing.
+
+ \note The widget becomes invisible as part of changing its parent,
+ even if it was previously visible. You must call show() to make the
+ widget visible again.
+
+ \warning It is very unlikely that you will ever need this
+ function. If you have a widget that changes its content
+ dynamically, it is far easier to use \l QStackedWidget.
+
+ \sa setWindowFlags()
+*/
+void QWidget::setParent(QWidget *parent)
+{
+ if (parent == parentWidget())
+ return;
+ setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
+}
+
+/*!
+ \overload
+
+ This function also takes widget flags, \a f as an argument.
+*/
+
+void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
+{
+ Q_D(QWidget);
+ bool resized = testAttribute(Qt::WA_Resized);
+ bool wasCreated = testAttribute(Qt::WA_WState_Created);
+ QWidget *oldtlw = window();
+
+ QWidget *desktopWidget = 0;
+ if (parent && parent->windowType() == Qt::Desktop)
+ desktopWidget = parent;
+ bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
+
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ if (newParent && parent && !desktopWidget) {
+ if (testAttribute(Qt::WA_NativeWindow) && !qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
+ parent->d_func()->enforceNativeChildren();
+ else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
+ setAttribute(Qt::WA_NativeWindow);
+ }
+#endif
+
+ if (wasCreated) {
+ if (!testAttribute(Qt::WA_WState_Hidden)) {
+ hide();
+ setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ }
+ if (newParent) {
+ QEvent e(QEvent::ParentAboutToChange);
+ QApplication::sendEvent(this, &e);
+ }
+ }
+ if (newParent && isAncestorOf(focusWidget()))
+ focusWidget()->clearFocus();
+
+ d->setParent_sys(parent, f);
+ if (desktopWidget)
+ parent = 0;
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ QTLWExtra *extra = d->maybeTopData();
+ QWindowSurface *windowSurface = (extra ? extra->windowSurface : 0);
+ if (newParent && windowSurface) {
+ QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore();
+ if (oldBs)
+ oldBs->subSurfaces.removeAll(windowSurface);
+
+ if (parent) {
+ QWidgetBackingStore *newBs = parent->d_func()->maybeBackingStore();
+ if (newBs)
+ newBs->subSurfaces.append(windowSurface);
+ }
+ }
+#endif
+
+ if (newParent) {
+ if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
+ oldBs->removeDirtyWidget(this);
+ // Move the widget and all its static children from
+ // the old backing store to the new one.
+ oldBs->moveStaticWidgets(this);
+ }
+ }
+
+ if ((QApplicationPrivate::app_compile_version < 0x040200
+ || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
+ && !testAttribute(Qt::WA_WState_Created))
+ create();
+
+ d->reparentFocusWidgets(oldtlw);
+ setAttribute(Qt::WA_Resized, resized);
+ if (!testAttribute(Qt::WA_StyleSheet)
+ && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
+ d->resolveFont();
+ d->resolvePalette();
+ }
+ d->resolveLayoutDirection();
+ d->resolveLocale();
+
+ // Note: GL widgets under Windows will always need a ParentChange
+ // event to handle recreation/rebinding of the GL context, hence
+ // the (f & Qt::MSWindowsOwnDC) clause
+ if (newParent
+#ifdef Q_WS_WIN
+ || (f & Qt::MSWindowsOwnDC)
+#endif
+ ) {
+ // propagate enabled updates enabled state to non-windows
+ if (!isWindow()) {
+ if (!testAttribute(Qt::WA_ForceDisabled))
+ d->setEnabled_helper(parent ? parent->isEnabled() : true);
+ if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
+ d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
+ }
+ d->inheritStyle();
+
+ // send and post remaining QObject events
+ if (parent && d->sendChildEvents) {
+ QChildEvent e(QEvent::ChildAdded, this);
+ QApplication::sendEvent(parent, &e);
+#ifdef QT3_SUPPORT
+ if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
+ QApplication::postEvent(parent,
+ new QEvent(QEvent::ChildInsertedRequest),
+ Qt::HighEventPriority);
+ }
+ parent->d_func()->pendingChildInsertedEvents.append(this);
+#endif
+ }
+
+//### already hidden above ---> must probably do something smart on the mac
+// #ifdef Q_WS_MAC
+// extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
+// if(!qt_mac_is_macdrawer(q)) //special case
+// q->setAttribute(Qt::WA_WState_Hidden);
+// #else
+// q->setAttribute(Qt::WA_WState_Hidden);
+//#endif
+
+ if (parent && d->sendChildEvents && d->polished) {
+ QChildEvent e(QEvent::ChildPolished, this);
+ QCoreApplication::sendEvent(parent, &e);
+ }
+
+ QEvent e(QEvent::ParentChange);
+ QApplication::sendEvent(this, &e);
+ }
+
+ if (!wasCreated) {
+ if (isWindow() || parentWidget()->isVisible())
+ setAttribute(Qt::WA_WState_Hidden, true);
+ else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
+ setAttribute(Qt::WA_WState_Hidden, false);
+ }
+
+ d->updateIsOpaque();
+
+#ifndef QT_NO_GRAPHICSVIEW
+ // Embed the widget into a proxy if the parent is embedded.
+ // ### Doesn't handle reparenting out of an embedded widget.
+ if (oldtlw->graphicsProxyWidget()) {
+ if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
+ ancestorProxy->d_func()->unembedSubWindow(this);
+ }
+ if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
+ if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
+ ancestorProxy->d_func()->embedSubWindow(this);
+ }
+#endif
+}
+
+/*!
+ Scrolls the widget including its children \a dx pixels to the
+ right and \a dy downward. Both \a dx and \a dy may be negative.
+
+ After scrolling, the widgets will receive paint events for
+ the areas that need to be repainted. For widgets that Qt knows to
+ be opaque, this is only the newly exposed parts.
+ For example, if an opaque widget is scrolled 8 pixels to the left,
+ only an 8-pixel wide stripe at the right edge needs updating.
+
+ Since widgets propagate the contents of their parents by default,
+ you need to set the \l autoFillBackground property, or use
+ setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
+ a widget opaque.
+
+ For widgets that use contents propagation, a scroll will cause an
+ update of the entire scroll area.
+
+ \sa {Transparency and Double Buffering}
+*/
+
+void QWidget::scroll(int dx, int dy)
+{
+ if ((!updatesEnabled() && children().size() == 0) || !isVisible())
+ return;
+ if (dx == 0 && dy == 0)
+ return;
+ Q_D(QWidget);
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
+ // Graphics View maintains its own dirty region as a list of rects;
+ // until we can connect item updates directly to the view, we must
+ // separately add a translated dirty region.
+ if (!d->dirty.isEmpty()) {
+ foreach (const QRect &rect, (d->dirty.translated(dx, dy)).rects())
+ proxy->update(rect);
+ }
+ proxy->scroll(dx, dy, proxy->subWidgetRect(this));
+ return;
+ }
+#endif
+ d->setDirtyOpaqueRegion();
+ d->scroll_sys(dx, dy);
+}
+
+/*!
+ \overload
+
+ This version only scrolls \a r and does not move the children of
+ the widget.
+
+ If \a r is empty or invalid, the result is undefined.
+
+ \sa QScrollArea
+*/
+void QWidget::scroll(int dx, int dy, const QRect &r)
+{
+
+ if ((!updatesEnabled() && children().size() == 0) || !isVisible())
+ return;
+ if (dx == 0 && dy == 0)
+ return;
+ Q_D(QWidget);
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
+ // Graphics View maintains its own dirty region as a list of rects;
+ // until we can connect item updates directly to the view, we must
+ // separately add a translated dirty region.
+ if (!d->dirty.isEmpty()) {
+ foreach (const QRect &rect, (d->dirty.translated(dx, dy) & r).rects())
+ proxy->update(rect);
+ }
+ proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
+ return;
+ }
+#endif
+ d->scroll_sys(dx, dy, r);
+}
+
+/*!
+ Repaints the widget directly by calling paintEvent() immediately,
+ unless updates are disabled or the widget is hidden.
+
+ We suggest only using repaint() if you need an immediate repaint,
+ for example during animation. In almost all circumstances update()
+ is better, as it permits Qt to optimize for speed and minimize
+ flicker.
+
+ \warning If you call repaint() in a function which may itself be
+ called from paintEvent(), you may get infinite recursion. The
+ update() function never causes recursion.
+
+ \sa update(), paintEvent(), setUpdatesEnabled()
+*/
+
+void QWidget::repaint()
+{
+ repaint(rect());
+}
+
+/*! \overload
+
+ This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
+ the widget.
+
+ If \a w is negative, it is replaced with \c{width() - x}, and if
+ \a h is negative, it is replaced width \c{height() - y}.
+*/
+void QWidget::repaint(int x, int y, int w, int h)
+{
+ if (x > data->crect.width() || y > data->crect.height())
+ return;
+
+ if (w < 0)
+ w = data->crect.width() - x;
+ if (h < 0)
+ h = data->crect.height() - y;
+
+ repaint(QRect(x, y, w, h));
+}
+
+/*! \overload
+
+ This version repaints a rectangle \a rect inside the widget.
+*/
+void QWidget::repaint(const QRect &rect)
+{
+ Q_D(QWidget);
+
+ if (testAttribute(Qt::WA_WState_ConfigPending)) {
+ update(rect);
+ return;
+ }
+
+ if (!isVisible() || !updatesEnabled() || rect.isEmpty())
+ return;
+
+ QTLWExtra *tlwExtra = !d->paintOnScreen() ? window()->d_func()->maybeTopData() : 0;
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) {
+ tlwExtra->inRepaint = true;
+ tlwExtra->backingStore->markDirty(rect, this, true);
+ tlwExtra->inRepaint = false;
+ } else {
+ d->repaint_sys(rect);
+ }
+}
+
+/*!
+ \overload
+
+ This version repaints a region \a rgn inside the widget.
+*/
+void QWidget::repaint(const QRegion &rgn)
+{
+ Q_D(QWidget);
+
+ if (testAttribute(Qt::WA_WState_ConfigPending)) {
+ update(rgn);
+ return;
+ }
+
+ if (!isVisible() || !updatesEnabled() || rgn.isEmpty())
+ return;
+
+ QTLWExtra *tlwExtra = !d->paintOnScreen() ? window()->d_func()->maybeTopData() : 0;
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) {
+ tlwExtra->inRepaint = true;
+ tlwExtra->backingStore->markDirty(rgn, this, true);
+ tlwExtra->inRepaint = false;
+ } else {
+ d->repaint_sys(rgn);
+ }
+}
+
+/*!
+ Updates the widget unless updates are disabled or the widget is
+ hidden.
+
+ This function does not cause an immediate repaint; instead it
+ schedules a paint event for processing when Qt returns to the main
+ event loop. This permits Qt to optimize for more speed and less
+ flicker than a call to repaint() does.
+
+ Calling update() several times normally results in just one
+ paintEvent() call.
+
+ Qt normally erases the widget's area before the paintEvent() call.
+ If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
+ responsible for painting all its pixels with an opaque color.
+
+ \sa repaint() paintEvent(), setUpdatesEnabled(), {Analog Clock Example}
+*/
+void QWidget::update()
+{
+ update(rect());
+}
+
+/*! \fn void QWidget::update(int x, int y, int w, int h)
+ \overload
+
+ This version updates a rectangle (\a x, \a y, \a w, \a h) inside
+ the widget.
+*/
+
+/*!
+ \overload
+
+ This version updates a rectangle \a rect inside the widget.
+*/
+void QWidget::update(const QRect &rect)
+{
+ if (!isVisible() || !updatesEnabled() || rect.isEmpty())
+ return;
+
+ if (testAttribute(Qt::WA_WState_InPaintEvent)) {
+ QApplication::postEvent(this, new QUpdateLaterEvent(rect));
+ return;
+ }
+
+ if (hasBackingStoreSupport()) {
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore)
+ tlwExtra->backingStore->markDirty(rect, this);
+ } else {
+ d_func()->repaint_sys(rect);
+ }
+}
+
+/*!
+ \overload
+
+ This version repaints a region \a rgn inside the widget.
+*/
+void QWidget::update(const QRegion &rgn)
+{
+ if (!isVisible() || !updatesEnabled() || rgn.isEmpty())
+ return;
+
+ if (testAttribute(Qt::WA_WState_InPaintEvent)) {
+ QApplication::postEvent(this, new QUpdateLaterEvent(rgn));
+ return;
+ }
+
+ if (hasBackingStoreSupport()) {
+ QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
+ if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore)
+ tlwExtra->backingStore->markDirty(rgn, this);
+ } else {
+ d_func()->repaint_sys(rgn);
+ }
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Clear the rectangle at point (\a x, \a y) of width \a w and height
+ \a h.
+
+ \warning This is best done in a paintEvent().
+*/
+void QWidget::erase_helper(int x, int y, int w, int h)
+{
+ if (testAttribute(Qt::WA_NoSystemBackground) || testAttribute(Qt::WA_UpdatesDisabled) || !testAttribute(Qt::WA_WState_Visible))
+ return;
+ if (w < 0)
+ w = data->crect.width() - x;
+ if (h < 0)
+ h = data->crect.height() - y;
+ if (w != 0 && h != 0) {
+ QPainter p(this);
+ p.eraseRect(QRect(x, y, w, h));
+ }
+}
+
+/*!
+ \overload
+
+ Clear the given region, \a rgn.
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+void QWidget::erase(const QRegion& rgn)
+{
+ if (testAttribute(Qt::WA_NoSystemBackground) || testAttribute(Qt::WA_UpdatesDisabled) || !testAttribute(Qt::WA_WState_Visible))
+ return;
+
+ QPainter p(this);
+ p.setClipRegion(rgn);
+ p.eraseRect(rgn.boundingRect());
+}
+
+void QWidget::drawText_helper(int x, int y, const QString &str)
+{
+ if(!testAttribute(Qt::WA_WState_Visible))
+ return;
+ QPainter paint(this);
+ paint.drawText(x, y, str);
+}
+
+
+/*!
+ Closes the widget.
+
+ Use the no-argument overload instead.
+*/
+bool QWidget::close(bool alsoDelete)
+{
+ QPointer<QWidget> that = this;
+ bool accepted = close();
+ if (alsoDelete && accepted && that)
+ deleteLater();
+ return accepted;
+}
+
+void QWidget::setIcon(const QPixmap &i)
+{
+ setWindowIcon(i);
+}
+
+/*!
+ Return's the widget's icon.
+
+ Use windowIcon() instead.
+*/
+const QPixmap *QWidget::icon() const
+{
+ Q_D(const QWidget);
+ return (d->extra && d->extra->topextra) ? d->extra->topextra->iconPixmap : 0;
+}
+
+#endif // QT3_SUPPORT
+
+/*!
+ Sets the attribute \a attribute on this widget if \a on is true;
+ otherwise clears the attribute.
+
+ \sa testAttribute()
+*/
+void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
+{
+ if (testAttribute(attribute) == on)
+ return;
+
+ Q_D(QWidget);
+ Q_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
+ "QWidget::setAttribute(WidgetAttribute, bool)",
+ "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
+
+#ifdef Q_WS_WIN
+ if (attribute == Qt::WA_PaintOnScreen && on) {
+ // see qwidget_win.cpp, ::paintEngine for details
+ paintEngine();
+ if (d->noPaintOnScreen)
+ return;
+ }
+#endif
+
+ if (attribute < int(8*sizeof(uint))) {
+ if (on)
+ data->widget_attributes |= (1<<attribute);
+ else
+ data->widget_attributes &= ~(1<<attribute);
+ } else {
+ const int x = attribute - 8*sizeof(uint);
+ const int int_off = x / (8*sizeof(uint));
+ if (on)
+ d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
+ else
+ d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
+ }
+
+ switch (attribute) {
+
+#ifndef QT_NO_DRAGANDDROP
+ case Qt::WA_AcceptDrops: {
+ if (on && !testAttribute(Qt::WA_DropSiteRegistered))
+ setAttribute(Qt::WA_DropSiteRegistered, true);
+ else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
+ setAttribute(Qt::WA_DropSiteRegistered, false);
+ QEvent e(QEvent::AcceptDropsChange);
+ QApplication::sendEvent(this, &e);
+ break;
+ }
+ case Qt::WA_DropSiteRegistered: {
+ d->registerDropSite(on);
+ for (int i = 0; i < d->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
+ if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
+ w->setAttribute(Qt::WA_DropSiteRegistered, on);
+ }
+ break;
+ }
+#endif
+
+ case Qt::WA_NoChildEventsForParent:
+ d->sendChildEvents = !on;
+ break;
+ case Qt::WA_NoChildEventsFromChildren:
+ d->receiveChildEvents = !on;
+ break;
+ case Qt::WA_MacBrushedMetal:
+#ifdef Q_WS_MAC
+ d->setStyle_helper(style(), false, true); // Make sure things get unpolished/polished correctly.
+ // fall through since changing the metal attribute affects the opaque size grip.
+ case Qt::WA_MacOpaqueSizeGrip:
+ d->macUpdateOpaqueSizeGrip();
+ break;
+ case Qt::WA_MacShowFocusRect:
+ if (hasFocus()) {
+ clearFocus();
+ setFocus();
+ }
+ break;
+ case Qt::WA_Hover:
+ qt_mac_update_mouseTracking(this);
+ break;
+#endif
+ case Qt::WA_MacAlwaysShowToolWindow:
+#ifdef Q_WS_MAC
+ d->macUpdateHideOnSuspend();
+#endif
+ break;
+ case Qt::WA_MacNormalSize:
+ case Qt::WA_MacSmallSize:
+ case Qt::WA_MacMiniSize:
+#ifdef Q_WS_MAC
+ {
+ // We can only have one of these set at a time
+ static const int MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
+ Qt::WA_MacMiniSize, 0 };
+ for (int i = 0; MacSizes[i] != 0; ++i) {
+ if (MacSizes[i] == attribute)
+ continue;
+ int macsize_x = MacSizes[i] - 8*sizeof(uint);
+ int macsize_int_off = macsize_x / (8*sizeof(uint));
+ d->high_attributes[macsize_int_off] &= ~(1<<(macsize_x-(macsize_int_off*8*sizeof(uint))));
+ }
+ d->macUpdateSizeAttribute();
+ }
+#endif
+ break;
+ case Qt::WA_ShowModal:
+ if (!on) {
+ if (isVisible())
+ QApplicationPrivate::leaveModal(this);
+ // reset modality type to Modeless when clearing WA_ShowModal
+ data->window_modality = Qt::NonModal;
+ } else if (data->window_modality == Qt::NonModal) {
+ // determine the modality type if it hasn't been set prior
+ // to setting WA_ShowModal. set the default to WindowModal
+ // if we are the child of a group leader; otherwise use
+ // ApplicationModal.
+ QWidget *w = parentWidget();
+ if (w)
+ w = w->window();
+ while (w && !w->testAttribute(Qt::WA_GroupLeader)) {
+ w = w->parentWidget();
+ if (w)
+ w = w->window();
+ }
+ data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader))
+ ? Qt::WindowModal
+ : Qt::ApplicationModal;
+ }
+ if (testAttribute(Qt::WA_WState_Created)) {
+ // don't call setModal_sys() before create_sys()
+ d->setModal_sys();
+ }
+ break;
+ case Qt::WA_MouseTracking: {
+ QEvent e(QEvent::MouseTrackingChange);
+ QApplication::sendEvent(this, &e);
+ break; }
+#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
+ case Qt::WA_MSWindowsUseDirect3D:
+ if (!qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) {
+ if (on) {
+ if (!d->extra)
+ d->createExtra();
+ d->extra->had_auto_fill_bg = d->extra->autoFillBackground;
+ d->extra->had_no_system_bg = testAttribute(Qt::WA_NoSystemBackground);
+ d->extra->had_paint_on_screen = testAttribute(Qt::WA_PaintOnScreen);
+ // enforce the opaque widget state D3D needs
+ d->extra->autoFillBackground = true;
+ setAttribute(Qt::WA_PaintOnScreen);
+ setAttribute(Qt::WA_NoSystemBackground);
+ } else if (d->extra) {
+ d->extra->autoFillBackground = d->extra->had_auto_fill_bg;
+ setAttribute(Qt::WA_PaintOnScreen, d->extra->had_paint_on_screen);
+ setAttribute(Qt::WA_NoSystemBackground, d->extra->had_no_system_bg);
+ }
+ }
+ break;
+#endif
+ case Qt::WA_NativeWindow:
+ if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
+ parentWidget()->d_func()->enforceNativeChildren();
+ if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
+ d->createWinId();
+ break;
+ case Qt::WA_PaintOnScreen:
+ d->updateIsOpaque();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ // Recreate the widget if it's already created as an alien widget and
+ // WA_PaintOnScreen is enabled. Paint on screen widgets must have win id.
+ // So must their children.
+ if (on) {
+ setAttribute(Qt::WA_NativeWindow);
+ d->enforceNativeChildren();
+ }
+#endif
+ // fall through
+ case Qt::WA_OpaquePaintEvent:
+ d->updateIsOpaque();
+ break;
+ case Qt::WA_NoSystemBackground:
+ d->updateIsOpaque();
+ // fall through...
+ case Qt::WA_UpdatesDisabled:
+ d->updateSystemBackground();
+ break;
+ case Qt::WA_TransparentForMouseEvents:
+#ifdef Q_WS_MAC
+ d->macUpdateIgnoreMouseEvents();
+#endif
+ break;
+ case Qt::WA_InputMethodEnabled: {
+#if defined(Q_WS_WIN) || (defined(Q_WS_QWS) && !defined(QT_NO_QWS_INPUTMETHODS))
+ if (hasFocus())
+ QInputContextPrivate::updateImeStatus(this, true);
+#endif
+ QInputContext *ic = d->ic;
+ if (!ic) {
+ // implicitly create input context only if we have a focus
+ if (hasFocus())
+ ic = d->inputContext();
+ }
+ if (ic) {
+ if (on && hasFocus() && ic->focusWidget() != this) {
+ ic->setFocusWidget(this);
+ } else if (!on && ic->focusWidget() == this) {
+ ic->reset();
+ ic->setFocusWidget(0);
+ }
+ }
+ break;
+ }
+ case Qt::WA_WindowPropagation:
+ d->resolvePalette();
+ d->resolveFont();
+ d->resolveLocale();
+ break;
+#ifdef Q_WS_X11
+ case Qt::WA_NoX11EventCompression:
+ if (!d->extra)
+ d->createExtra();
+ d->extra->compress_events = on;
+ break;
+ case Qt::WA_X11OpenGLOverlay:
+ d->updateIsOpaque();
+ break;
+#endif
+ case Qt::WA_DontShowOnScreen: {
+ if (on && isVisible()) {
+ // Make sure we keep the current state and only hide the widget
+ // from the desktop. show_sys will only update platform specific
+ // attributes at this point.
+ d->hide_sys();
+#ifdef Q_WS_QWS
+ // Release the region for this window from qws if the widget has
+ // been shown before the attribute was set.
+ if (QWSWindowSurface *surface = static_cast<QWSWindowSurface *>(windowSurface())) {
+ QWidget::qwsDisplay()->requestRegion(surface->winId(), surface->key(),
+ surface->permanentState(), QRegion());
+ }
+#endif
+ d->show_sys();
+ }
+ break;
+ }
+
+#ifdef Q_WS_X11
+ case Qt::WA_X11NetWmWindowTypeDesktop:
+ case Qt::WA_X11NetWmWindowTypeDock:
+ case Qt::WA_X11NetWmWindowTypeToolBar:
+ case Qt::WA_X11NetWmWindowTypeMenu:
+ case Qt::WA_X11NetWmWindowTypeUtility:
+ case Qt::WA_X11NetWmWindowTypeSplash:
+ case Qt::WA_X11NetWmWindowTypeDialog:
+ case Qt::WA_X11NetWmWindowTypeDropDownMenu:
+ case Qt::WA_X11NetWmWindowTypePopupMenu:
+ case Qt::WA_X11NetWmWindowTypeToolTip:
+ case Qt::WA_X11NetWmWindowTypeNotification:
+ case Qt::WA_X11NetWmWindowTypeCombo:
+ case Qt::WA_X11NetWmWindowTypeDND:
+ if (testAttribute(Qt::WA_WState_Created))
+ d->setNetWmWindowTypes();
+ break;
+#endif
+
+ case Qt::WA_StaticContents:
+ if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
+ if (on)
+ bs->addStaticWidget(this);
+ else
+ bs->removeStaticWidget(this);
+ }
+ break;
+ case Qt::WA_TranslucentBackground:
+ if (on) {
+ setAttribute(Qt::WA_NoSystemBackground);
+ d->updateIsTranslucent();
+ }
+
+ break;
+ default:
+ break;
+ }
+}
+
+/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
+
+ Returns true if attribute \a attribute is set on this widget;
+ otherwise returns false.
+
+ \sa setAttribute()
+ */
+bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
+{
+ Q_D(const QWidget);
+ const int x = attribute - 8*sizeof(uint);
+ const int int_off = x / (8*sizeof(uint));
+ return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
+}
+
+/*!
+ \property QWidget::windowOpacity
+
+ \brief The level of opacity for the window.
+
+ The valid range of opacity is from 1.0 (completely opaque) to
+ 0.0 (completely transparent).
+
+ By default the value of this property is 1.0.
+
+ This feature is available on Embedded Linux, Mac OS X, X11 platforms that
+ support the Composite extension, and Windows 2000 and later.
+
+ This feature is not available on Windows CE.
+
+ Note that under X11 you need to have a composite manager running,
+ and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
+ supported by the window manager you are using.
+
+ \warning Changing this property from opaque to transparent might issue a
+ paint event that needs to be processed before the window is displayed
+ correctly. This affects mainly the use of QPixmap::grabWindow(). Also note
+ that semi-transparent windows update and resize significantly slower than
+ opaque windows.
+
+ \sa setMask()
+*/
+qreal QWidget::windowOpacity() const
+{
+ Q_D(const QWidget);
+ return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
+}
+
+void QWidget::setWindowOpacity(qreal opacity)
+{
+ Q_D(QWidget);
+ if (!isWindow())
+ return;
+
+ opacity = qBound(qreal(0.0), opacity, qreal(1.0));
+ QTLWExtra *extra = d->topData();
+ extra->opacity = uint(opacity * 255);
+ setAttribute(Qt::WA_WState_WindowOpacitySet);
+
+#ifndef Q_WS_QWS
+ if (!testAttribute(Qt::WA_WState_Created))
+ return;
+#endif
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
+ // Avoid invalidating the cache if set.
+ if (proxy->cacheMode() == QGraphicsItem::NoCache)
+ proxy->update();
+ else if (QGraphicsScene *scene = proxy->scene())
+ scene->update(proxy->sceneBoundingRect());
+ return;
+ }
+#endif
+
+ d->setWindowOpacity_sys(opacity);
+}
+
+/*!
+ \property QWidget::windowModified
+ \brief whether the document shown in the window has unsaved changes
+
+ A modified window is a window whose content has changed but has
+ not been saved to disk. This flag will have different effects
+ varied by the platform. On Mac OS X the close button will have a
+ modified look; on other platforms, the window title will have an
+ '*' (asterisk).
+
+ The window title must contain a "[*]" placeholder, which
+ indicates where the '*' should appear. Normally, it should appear
+ right after the file name (e.g., "document1.txt[*] - Text
+ Editor"). If the window isn't modified, the placeholder is simply
+ removed.
+
+ Note that if a widget is set as modified, all its ancestors will
+ also be set as modified. However, if you call \c
+ {setWindowModified(false)} on a widget, this will not propagate to
+ its parent because other children of the parent might have been
+ modified.
+
+ \sa windowTitle, {Application Example}, {SDI Example}, {MDI Example}
+*/
+bool QWidget::isWindowModified() const
+{
+ return testAttribute(Qt::WA_WindowModified);
+}
+
+void QWidget::setWindowModified(bool mod)
+{
+ Q_D(QWidget);
+ setAttribute(Qt::WA_WindowModified, mod);
+
+#ifndef Q_WS_MAC
+ if (!windowTitle().contains(QLatin1String("[*]")) && mod)
+ qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
+#endif
+ d->setWindowTitle_helper(windowTitle());
+ d->setWindowIconText_helper(windowIconText());
+#ifdef Q_WS_MAC
+ d->setWindowModified_sys(mod);
+#endif
+
+ QEvent e(QEvent::ModifiedChange);
+ QApplication::sendEvent(this, &e);
+}
+
+#ifndef QT_NO_TOOLTIP
+/*!
+ \property QWidget::toolTip
+
+ \brief the widget's tooltip
+
+ Note that by default tooltips are only shown for widgets that are
+ children of the active window. You can change this behavior by
+ setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
+ not on the widget with the tooltip.
+
+ If you want to control a tooltip's behavior, you can intercept the
+ event() function and catch the QEvent::ToolTip event (e.g., if you
+ want to customize the area for which the tooltip should be shown).
+
+ By default, this property contains an empty string.
+
+ \sa QToolTip statusTip whatsThis
+*/
+void QWidget::setToolTip(const QString &s)
+{
+ Q_D(QWidget);
+ d->toolTip = s;
+
+ QEvent event(QEvent::ToolTipChange);
+ QApplication::sendEvent(this, &event);
+}
+
+QString QWidget::toolTip() const
+{
+ Q_D(const QWidget);
+ return d->toolTip;
+}
+#endif // QT_NO_TOOLTIP
+
+
+#ifndef QT_NO_STATUSTIP
+/*!
+ \property QWidget::statusTip
+ \brief the widget's status tip
+
+ By default, this property contains an empty string.
+
+ \sa toolTip whatsThis
+*/
+void QWidget::setStatusTip(const QString &s)
+{
+ Q_D(QWidget);
+ d->statusTip = s;
+}
+
+QString QWidget::statusTip() const
+{
+ Q_D(const QWidget);
+ return d->statusTip;
+}
+#endif // QT_NO_STATUSTIP
+
+#ifndef QT_NO_WHATSTHIS
+/*!
+ \property QWidget::whatsThis
+
+ \brief the widget's What's This help text.
+
+ By default, this property contains an empty string.
+
+ \sa QWhatsThis QWidget::toolTip QWidget::statusTip
+*/
+void QWidget::setWhatsThis(const QString &s)
+{
+ Q_D(QWidget);
+ d->whatsThis = s;
+}
+
+QString QWidget::whatsThis() const
+{
+ Q_D(const QWidget);
+ return d->whatsThis;
+}
+#endif // QT_NO_WHATSTHIS
+
+#ifndef QT_NO_ACCESSIBILITY
+/*!
+ \property QWidget::accessibleName
+
+ \brief the widget's name as seen by assistive technologies
+
+ This property is used by accessible clients to identify, find, or announce
+ the widget for accessible clients.
+
+ By default, this property contains an empty string.
+
+ \sa QAccessibleInterface::text()
+*/
+void QWidget::setAccessibleName(const QString &name)
+{
+ Q_D(QWidget);
+ d->accessibleName = name;
+}
+
+QString QWidget::accessibleName() const
+{
+ Q_D(const QWidget);
+ return d->accessibleName;
+}
+
+/*!
+ \property QWidget::accessibleDescription
+
+ \brief the widget's description as seen by assistive technologies
+
+ By default, this property contains an empty string.
+
+ \sa QAccessibleInterface::text()
+*/
+void QWidget::setAccessibleDescription(const QString &description)
+{
+ Q_D(QWidget);
+ d->accessibleDescription = description;
+}
+
+QString QWidget::accessibleDescription() const
+{
+ Q_D(const QWidget);
+ return d->accessibleDescription;
+}
+#endif // QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_SHORTCUT
+/*!
+ Adds a shortcut to Qt's shortcut system that watches for the given
+ \a key sequence in the given \a context. If the \a context is
+ Qt::ApplicationShortcut, the shortcut applies to the application as a
+ whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
+ or to the window itself, Qt::WindowShortcut.
+
+ If the same \a key sequence has been grabbed by several widgets,
+ when the \a key sequence occurs a QEvent::Shortcut event is sent
+ to all the widgets to which it applies in a non-deterministic
+ order, but with the ``ambiguous'' flag set to true.
+
+ \warning You should not normally need to use this function;
+ instead create \l{QAction}s with the shortcut key sequences you
+ require (if you also want equivalent menu options and toolbar
+ buttons), or create \l{QShortcut}s if you just need key sequences.
+ Both QAction and QShortcut handle all the event filtering for you,
+ and provide signals which are triggered when the user triggers the
+ key sequence, so are much easier to use than this low-level
+ function.
+
+ \sa releaseShortcut() setShortcutEnabled()
+*/
+int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
+{
+ Q_ASSERT(qApp);
+ if (key.isEmpty())
+ return 0;
+ setAttribute(Qt::WA_GrabbedShortcut);
+ return qApp->d_func()->shortcutMap.addShortcut(this, key, context);
+}
+
+/*!
+ Removes the shortcut with the given \a id from Qt's shortcut
+ system. The widget will no longer receive QEvent::Shortcut events
+ for the shortcut's key sequence (unless it has other shortcuts
+ with the same key sequence).
+
+ \warning You should not normally need to use this function since
+ Qt's shortcut system removes shortcuts automatically when their
+ parent widget is destroyed. It is best to use QAction or
+ QShortcut to handle shortcuts, since they are easier to use than
+ this low-level function. Note also that this is an expensive
+ operation.
+
+ \sa grabShortcut() setShortcutEnabled()
+*/
+void QWidget::releaseShortcut(int id)
+{
+ Q_ASSERT(qApp);
+ if (id)
+ qApp->d_func()->shortcutMap.removeShortcut(id, this, 0);
+}
+
+/*!
+ If \a enable is true, the shortcut with the given \a id is
+ enabled; otherwise the shortcut is disabled.
+
+ \warning You should not normally need to use this function since
+ Qt's shortcut system enables/disables shortcuts automatically as
+ widgets become hidden/visible and gain or lose focus. It is best
+ to use QAction or QShortcut to handle shortcuts, since they are
+ easier to use than this low-level function.
+
+ \sa grabShortcut() releaseShortcut()
+*/
+void QWidget::setShortcutEnabled(int id, bool enable)
+{
+ Q_ASSERT(qApp);
+ if (id)
+ qApp->d_func()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
+}
+
+/*!
+ \since 4.2
+
+ If \a enable is true, auto repeat of the shortcut with the
+ given \a id is enabled; otherwise it is disabled.
+
+ \sa grabShortcut() releaseShortcut()
+*/
+void QWidget::setShortcutAutoRepeat(int id, bool enable)
+{
+ Q_ASSERT(qApp);
+ if (id)
+ qApp->d_func()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
+}
+#endif // QT_NO_SHORTCUT
+/*!
+ Updates the widget's micro focus.
+
+ \sa QInputContext
+*/
+void QWidget::updateMicroFocus()
+{
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS))
+ Q_D(QWidget);
+ // and optimisation to update input context only it has already been created.
+ if (d->ic || qApp->d_func()->inputContext) {
+ QInputContext *ic = inputContext();
+ if (ic)
+ ic->update();
+ }
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ // ##### is this correct
+ QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
+#endif
+}
+
+
+#if defined (Q_WS_WIN)
+/*!
+ Returns the window system handle of the widget, for low-level
+ access. Using this function is not portable.
+
+ An HDC acquired with getDC() has to be released with releaseDC().
+
+ \warning Using this function is not portable.
+*/
+HDC QWidget::getDC() const
+{
+ Q_D(const QWidget);
+ if (d->hd)
+ return (HDC) d->hd;
+ return GetDC(winId());
+}
+
+/*!
+ Releases the HDC \a hdc acquired by a previous call to getDC().
+
+ \warning Using this function is not portable.
+*/
+void QWidget::releaseDC(HDC hdc) const
+{
+ Q_D(const QWidget);
+ // If its the widgets own dc, it will be released elsewhere. If
+ // its a different HDC we release it and issue a warning if it
+ // fails.
+ if (hdc != d->hd && !ReleaseDC(winId(), hdc))
+ qErrnoWarning("QWidget::releaseDC(): failed to release HDC");
+}
+#else
+/*!
+ Returns the window system handle of the widget, for low-level
+ access. Using this function is not portable.
+
+ The HANDLE type varies with platform; see \c qwindowdefs.h for
+ details.
+*/
+Qt::HANDLE QWidget::handle() const
+{
+ Q_D(const QWidget);
+ if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
+ (void)winId(); // enforce native window
+ return d->hd;
+}
+#endif
+
+
+/*!
+ Raises this widget to the top of the parent widget's stack.
+
+ After this call the widget will be visually in front of any
+ overlapping sibling widgets.
+
+ \note When using activateWindow(), you can call this function to
+ ensure that the window is stacked on top.
+
+ \sa lower(), stackUnder()
+*/
+
+void QWidget::raise()
+{
+ Q_D(QWidget);
+ if (!isWindow()) {
+ QWidget *p = parentWidget();
+ const int parentChildCount = p->d_func()->children.size();
+ if (parentChildCount < 2)
+ return;
+ const int from = p->d_func()->children.indexOf(this);
+ Q_ASSERT(from >= 0);
+ // Do nothing if the widget is already in correct stacking order _and_ created.
+ if (from != parentChildCount -1)
+ p->d_func()->children.move(from, parentChildCount - 1);
+ if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
+ create();
+ else if (from == parentChildCount - 1)
+ return;
+
+ QRegion region(rect());
+ d->subtractOpaqueSiblings(region);
+ d->invalidateBuffer(region);
+ }
+ if (testAttribute(Qt::WA_WState_Created))
+ d->raise_sys();
+
+ QEvent e(QEvent::ZOrderChange);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ Lowers the widget to the bottom of the parent widget's stack.
+
+ After this call the widget will be visually behind (and therefore
+ obscured by) any overlapping sibling widgets.
+
+ \sa raise(), stackUnder()
+*/
+
+void QWidget::lower()
+{
+ Q_D(QWidget);
+ if (!isWindow()) {
+ QWidget *p = parentWidget();
+ const int parentChildCount = p->d_func()->children.size();
+ if (parentChildCount < 2)
+ return;
+ const int from = p->d_func()->children.indexOf(this);
+ Q_ASSERT(from >= 0);
+ // Do nothing if the widget is already in correct stacking order _and_ created.
+ if (from != 0)
+ p->d_func()->children.move(from, 0);
+ if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
+ create();
+ else if (from == 0)
+ return;
+ }
+ if (testAttribute(Qt::WA_WState_Created))
+ d->lower_sys();
+
+ QEvent e(QEvent::ZOrderChange);
+ QApplication::sendEvent(this, &e);
+}
+
+
+/*!
+ Places the widget under \a w in the parent widget's stack.
+
+ To make this work, the widget itself and \a w must be siblings.
+
+ \sa raise(), lower()
+*/
+void QWidget::stackUnder(QWidget* w)
+{
+ Q_D(QWidget);
+ QWidget *p = parentWidget();
+ if (!w || isWindow() || p != w->parentWidget() || this == w)
+ return;
+ if (p) {
+ int from = p->d_func()->children.indexOf(this);
+ int to = p->d_func()->children.indexOf(w);
+ Q_ASSERT(from >= 0);
+ Q_ASSERT(to >= 0);
+ if (from < to)
+ --to;
+ // Do nothing if the widget is already in correct stacking order _and_ created.
+ if (from != to)
+ p->d_func()->children.move(from, to);
+ if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
+ create();
+ else if (from == to)
+ return;
+ }
+ if (testAttribute(Qt::WA_WState_Created))
+ d->stackUnder_sys(w);
+
+ QEvent e(QEvent::ZOrderChange);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidget::styleChange(QStyle&) { }
+void QWidget::enabledChange(bool) { } // compat
+void QWidget::paletteChange(const QPalette &) { } // compat
+void QWidget::fontChange(const QFont &) { } // compat
+void QWidget::windowActivationChange(bool) { } // compat
+void QWidget::languageChange() { } // compat
+
+
+/*!
+ \enum QWidget::BackgroundOrigin
+
+ \compat
+
+ \value WidgetOrigin
+ \value ParentOrigin
+ \value WindowOrigin
+ \value AncestorOrigin
+
+*/
+
+/*!
+ \fn bool QWidget::isVisibleToTLW() const
+
+ Use isVisible() instead.
+*/
+
+/*!
+ \fn void QWidget::iconify()
+
+ Use showMinimized() instead.
+*/
+
+/*!
+ \fn void QWidget::constPolish() const
+
+ Use ensurePolished() instead.
+*/
+
+/*!
+ \fn void QWidget::reparent(QWidget *parent, Qt::WindowFlags f, const QPoint &p, bool showIt)
+
+ Use setParent() to change the parent or the widget's widget flags;
+ use move() to move the widget, and use show() to show the widget.
+*/
+
+/*!
+ \fn void QWidget::reparent(QWidget *parent, const QPoint &p, bool showIt)
+
+ Use setParent() to change the parent; use move() to move the
+ widget, and use show() to show the widget.
+*/
+
+/*!
+ \fn void QWidget::recreate(QWidget *parent, Qt::WindowFlags f, const QPoint & p, bool showIt)
+
+ Use setParent() to change the parent or the widget's widget flags;
+ use move() to move the widget, and use show() to show the widget.
+*/
+
+/*!
+ \fn bool QWidget::hasMouse() const
+
+ Use testAttribute(Qt::WA_UnderMouse) instead.
+*/
+
+/*!
+ \fn bool QWidget::ownCursor() const
+
+ Use testAttribute(Qt::WA_SetCursor) instead.
+*/
+
+/*!
+ \fn bool QWidget::ownFont() const
+
+ Use testAttribute(Qt::WA_SetFont) instead.
+*/
+
+/*!
+ \fn void QWidget::unsetFont()
+
+ Use setFont(QFont()) instead.
+*/
+
+/*!
+ \fn bool QWidget::ownPalette() const
+
+ Use testAttribute(Qt::WA_SetPalette) instead.
+*/
+
+/*!
+ \fn void QWidget::unsetPalette()
+
+ Use setPalette(QPalette()) instead.
+*/
+
+/*!
+ \fn void QWidget::setEraseColor(const QColor &color)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setEraseColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->backgroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setErasePixmap(const QPixmap &pixmap)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setErasePixmap(pixmap);
+ \newcode
+ QPalette palette;
+ palette.setBrush(widget->backgroundRole(), QBrush(pixmap));
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setPaletteForegroundColor(const QColor &color)
+
+ Use the palette directly.
+
+ \oldcode
+ widget->setPaletteForegroundColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->foregroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setPaletteBackgroundColor(const QColor &color)
+
+ Use the palette directly.
+
+ \oldcode
+ widget->setPaletteBackgroundColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->backgroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setPaletteBackgroundPixmap(const QPixmap &pixmap)
+
+ Use the palette directly.
+
+ \oldcode
+ widget->setPaletteBackgroundPixmap(pixmap);
+ \newcode
+ QPalette palette;
+ palette.setBrush(widget->backgroundRole(), QBrush(pixmap));
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setBackgroundPixmap(const QPixmap &pixmap)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setBackgroundPixmap(pixmap);
+ \newcode
+ QPalette palette;
+ palette.setBrush(widget->backgroundRole(), QBrush(pixmap));
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setBackgroundColor(const QColor &color)
+
+ Use the palette instead.
+
+ \oldcode
+ widget->setBackgroundColor(color);
+ \newcode
+ QPalette palette;
+ palette.setColor(widget->backgroundRole(), color);
+ widget->setPalette(palette);
+ \endcode
+*/
+
+/*!
+ \fn QColorGroup QWidget::colorGroup() const
+
+ Use QColorGroup(palette()) instead.
+*/
+
+/*!
+ \fn QWidget *QWidget::parentWidget(bool sameWindow) const
+
+ Use the no-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setKeyCompression(bool b)
+
+ Use setAttribute(Qt::WA_KeyCompression, b) instead.
+*/
+
+/*!
+ \fn void QWidget::setFont(const QFont &f, bool b)
+
+ Use the single-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setPalette(const QPalette &p, bool b)
+
+ Use the single-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setBackgroundOrigin(BackgroundOrigin background)
+
+ \obsolete
+*/
+
+/*!
+ \fn BackgroundOrigin QWidget::backgroundOrigin() const
+
+ \obsolete
+
+ Always returns \c WindowOrigin.
+*/
+
+/*!
+ \fn QPoint QWidget::backgroundOffset() const
+
+ \obsolete
+
+ Always returns QPoint().
+*/
+
+/*!
+ \fn void QWidget::repaint(bool b)
+
+ The boolean parameter \a b is ignored. Use the no-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::repaint(int x, int y, int w, int h, bool b)
+
+ The boolean parameter \a b is ignored. Use the four-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::repaint(const QRect &r, bool b)
+
+ The boolean parameter \a b is ignored. Use the single rect-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::repaint(const QRegion &rgn, bool b)
+
+ The boolean parameter \a b is ignored. Use the single region-argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::erase()
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::erase(int x, int y, int w, int h)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::erase(const QRect &rect)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your erasing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::drawText(const QPoint &p, const QString &s)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your drawing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn void QWidget::drawText(int x, int y, const QString &s)
+
+ Drawing may only take place in a QPaintEvent. Overload
+ paintEvent() to do your drawing and call update() to schedule a
+ replaint whenever necessary. See also QPainter.
+*/
+
+/*!
+ \fn QWidget *QWidget::childAt(const QPoint &p, bool includeThis) const
+
+ Use the single point argument overload instead.
+*/
+
+/*!
+ \fn void QWidget::setCaption(const QString &c)
+
+ Use setWindowTitle() instead.
+*/
+
+/*!
+ \fn void QWidget::setIcon(const QPixmap &i)
+
+ Use setWindowIcon() instead.
+*/
+
+/*!
+ \fn void QWidget::setIconText(const QString &it)
+
+ Use setWindowIconText() instead.
+*/
+
+/*!
+ \fn QString QWidget::caption() const
+
+ Use windowTitle() instead.
+*/
+
+/*!
+ \fn QString QWidget::iconText() const
+
+ Use windowIconText() instead.
+*/
+
+/*!
+ \fn bool QWidget::isTopLevel() const
+ \obsolete
+
+ Use isWindow() instead.
+*/
+
+/*!
+ \fn bool QWidget::isRightToLeft() const
+ \internal
+*/
+
+/*!
+ \fn bool QWidget::isLeftToRight() const
+ \internal
+*/
+
+/*!
+ \fn void QWidget::setInputMethodEnabled(bool enabled)
+
+ Use setAttribute(Qt::WA_InputMethodEnabled, \a enabled) instead.
+*/
+
+/*!
+ \fn bool QWidget::isInputMethodEnabled() const
+
+ Use testAttribute(Qt::WA_InputMethodEnabled) instead.
+*/
+
+/*!
+ \fn void QWidget::setActiveWindow()
+
+ Use activateWindow() instead.
+*/
+
+/*!
+ \fn bool QWidget::isShown() const
+
+ Use !isHidden() instead (notice the exclamation mark), or use isVisible() to check whether the widget is visible.
+*/
+
+/*!
+ \fn bool QWidget::isDialog() const
+
+ Use windowType() == Qt::Dialog instead.
+*/
+
+/*!
+ \fn bool QWidget::isPopup() const
+
+ Use windowType() == Qt::Popup instead.
+*/
+
+/*!
+ \fn bool QWidget::isDesktop() const
+
+ Use windowType() == Qt::Desktop instead.
+*/
+
+/*!
+ \fn void QWidget::polish()
+
+ Use ensurePolished() instead.
+*/
+
+/*!
+ \fn QWidget *QWidget::childAt(int x, int y, bool includeThis) const
+
+ Use the childAt() overload that doesn't have an \a includeThis parameter.
+
+ \oldcode
+ return widget->childAt(x, y, true);
+ \newcode
+ QWidget *child = widget->childAt(x, y, true);
+ if (child)
+ return child;
+ if (widget->rect().contains(x, y))
+ return widget;
+ \endcode
+*/
+
+/*!
+ \fn void QWidget::setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver, bool hfw)
+ \compat
+
+ Use the \l sizePolicy property and heightForWidth() function instead.
+*/
+
+/*!
+ \fn bool QWidget::isUpdatesEnabled() const
+ \compat
+
+ Use the \l updatesEnabled property instead.
+*/
+
+/*!
+ \macro QWIDGETSIZE_MAX
+ \relates QWidget
+
+ Defines the maximum size for a QWidget object.
+
+ The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
+
+ \sa QWidget::setMaximumSize()
+*/
+
+QRect QWidgetPrivate::frameStrut() const
+{
+ Q_Q(const QWidget);
+ if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ // x2 = x1 + w - 1, so w/h = 1
+ return QRect(0, 0, 1, 1);
+ }
+
+ if (data.fstrut_dirty
+#ifndef Q_WS_WIN
+ // ### Fix properly for 4.3
+ && q->isVisible()
+#endif
+ && q->testAttribute(Qt::WA_WState_Created))
+ const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
+
+ return maybeTopData() ? maybeTopData()->frameStrut : QRect();
+}
+
+/*!
+ \preliminary
+ \since 4.2
+ \obsolete
+
+ Sets the window surface to be the \a surface specified.
+ The QWidget takes will ownership of the \a surface.
+ widget itself is deleted.
+*/
+void QWidget::setWindowSurface(QWindowSurface *surface)
+{
+ // ### createWinId() ??
+
+#ifndef Q_BACKINGSTORE_SUBSURFACES
+ if (!isTopLevel())
+ return;
+#endif
+
+ Q_D(QWidget);
+
+ QTLWExtra *topData = d->topData();
+ if (topData->windowSurface == surface)
+ return;
+
+ QWindowSurface *oldSurface = topData->windowSurface;
+ delete topData->windowSurface;
+ topData->windowSurface = surface;
+
+ QWidgetBackingStore *bs = d->maybeBackingStore();
+ if (!bs)
+ return;
+
+ if (isTopLevel()) {
+ if (bs->windowSurface != oldSurface && bs->windowSurface != surface)
+ delete bs->windowSurface;
+ bs->windowSurface = surface;
+ }
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ else {
+ bs->subSurfaces.append(surface);
+ }
+ bs->subSurfaces.removeOne(oldSurface);
+#endif
+}
+
+/*!
+ \preliminary
+ \since 4.2
+
+ Returns the QWindowSurface this widget will be drawn into.
+*/
+QWindowSurface *QWidget::windowSurface() const
+{
+ Q_D(const QWidget);
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra && extra->windowSurface)
+ return extra->windowSurface;
+
+ QWidgetBackingStore *bs = d->maybeBackingStore();
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ if (bs && bs->subSurfaces.isEmpty())
+ return bs->windowSurface;
+
+ if (!isTopLevel()) {
+ const QWidget *w = parentWidget();
+ while (w) {
+ QTLWExtra *extra = w->d_func()->maybeTopData();
+ if (extra && extra->windowSurface)
+ return extra->windowSurface;
+ if (w->isTopLevel())
+ break;
+ w = w->parentWidget();
+ }
+ }
+#endif // Q_BACKINGSTORE_SUBSURFACES
+
+ return bs ? bs->windowSurface : 0;
+}
+
+void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
+{
+ if (left)
+ *left = (int)leftLayoutItemMargin;
+ if (top)
+ *top = (int)topLayoutItemMargin;
+ if (right)
+ *right = (int)rightLayoutItemMargin;
+ if (bottom)
+ *bottom = (int)bottomLayoutItemMargin;
+}
+
+void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
+{
+ if (leftLayoutItemMargin == left
+ && topLayoutItemMargin == top
+ && rightLayoutItemMargin == right
+ && bottomLayoutItemMargin == bottom)
+ return;
+
+ Q_Q(QWidget);
+ leftLayoutItemMargin = (signed char)left;
+ topLayoutItemMargin = (signed char)top;
+ rightLayoutItemMargin = (signed char)right;
+ bottomLayoutItemMargin = (signed char)bottom;
+ q->updateGeometry();
+}
+
+void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
+{
+ Q_Q(QWidget);
+ QStyleOption myOpt;
+ if (!opt) {
+ myOpt.initFrom(q);
+ myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
+ opt = &myOpt;
+ }
+
+ QRect liRect = q->style()->subElementRect(element, opt, q);
+ if (liRect.isValid()) {
+ leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
+ topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
+ rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
+ bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
+ } else {
+ leftLayoutItemMargin = 0;
+ topLayoutItemMargin = 0;
+ rightLayoutItemMargin = 0;
+ bottomLayoutItemMargin = 0;
+ }
+}
+// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
+void QWidgetPrivate::adjustQuitOnCloseAttribute()
+{
+ Q_Q(QWidget);
+
+ if (!q->parentWidget()) {
+ Qt::WindowType type = q->windowType();
+ if (type == Qt::Widget || type == Qt::SubWindow)
+ type = Qt::Window;
+ if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
+ q->setAttribute(Qt::WA_QuitOnClose, false);
+ }
+}
+
+
+
+Q_GUI_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
+{
+ return widget->data;
+}
+
+Q_GUI_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
+{
+ return widget->d_func();
+}
+
+
+
+
+#ifndef QT_NO_GRAPHICSVIEW
+/*!
+ \since 4.5
+
+ Returns the proxy widget for the corresponding embedded widget in a graphics
+ view; otherwise returns 0.
+
+ \sa QGraphicsProxyWidget::createProxyForChildWidget(),
+ QGraphicsScene::addWidget()
+ */
+QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
+{
+ Q_D(const QWidget);
+ if (d->extra) {
+ return d->extra->proxyWidget;
+ }
+ return 0;
+}
+#endif
+
+
+/*!
+ \typedef QWidgetList
+ \relates QWidget
+
+ Synonym for QList<QWidget *>.
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qwidget.cpp"
+
+/*!
+ \typedef WId
+ \relates QWidget
+
+ Platform dependent window identifier.
+*/
+
+/*!
+ \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+
+ Frees up window system resources. Destroys the widget window if \a
+ destroyWindow is true.
+
+ destroy() calls itself recursively for all the child widgets,
+ passing \a destroySubWindows for the \a destroyWindow parameter.
+ To have more control over destruction of subwidgets, destroy
+ subwidgets selectively first.
+
+ This function is usually called from the QWidget destructor.
+*/
+
+/*!
+ \fn QPaintEngine *QWidget::paintEngine() const
+
+ Returns the widget's paint engine.
+
+ Note that this function should not be called explicitly by the
+ user, since it's meant for reimplementation purposes only. The
+ function is called by Qt internally, and the default
+ implementation may not always return a valid pointer.
+*/
+
+/*!
+ \fn QPoint QWidget::mapToGlobal(const QPoint &pos) const
+
+ Translates the widget coordinate \a pos to global screen
+ coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give
+ the global coordinates of the top-left pixel of the widget.
+
+ \sa mapFromGlobal() mapTo() mapToParent()
+*/
+
+/*!
+ \fn QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+
+ Translates the global screen coordinate \a pos to widget
+ coordinates.
+
+ \sa mapToGlobal() mapFrom() mapFromParent()
+*/
+
+/*!
+ \fn void QWidget::grabMouse()
+
+ Grabs the mouse input.
+
+ This widget receives all mouse events until releaseMouse() is
+ called; other widgets get no mouse events at all. Keyboard
+ events are not affected. Use grabKeyboard() if you want to grab
+ that.
+
+ \warning Bugs in mouse-grabbing applications very often lock the
+ terminal. Use this function with extreme caution, and consider
+ using the \c -nograb command line option while debugging.
+
+ It is almost never necessary to grab the mouse when using Qt, as
+ Qt grabs and releases it sensibly. In particular, Qt grabs the
+ mouse when a mouse button is pressed and keeps it until the last
+ button is released.
+
+ Note that only visible widgets can grab mouse input. If
+ isVisible() returns false for a widget, that widget cannot call
+ grabMouse().
+
+ \sa releaseMouse() grabKeyboard() releaseKeyboard() grabKeyboard()
+ focusWidget()
+*/
+
+/*!
+ \fn void QWidget::grabMouse(const QCursor &cursor)
+ \overload
+
+ Grabs the mouse input and changes the cursor shape.
+
+ The cursor will assume shape \a cursor (for as long as the mouse
+ focus is grabbed) and this widget will be the only one to receive
+ mouse events until releaseMouse() is called().
+
+ \warning Grabbing the mouse might lock the terminal.
+
+ \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
+*/
+
+/*!
+ \fn void QWidget::releaseMouse()
+
+ Releases the mouse grab.
+
+ \sa grabMouse(), grabKeyboard(), releaseKeyboard()
+*/
+
+/*!
+ \fn void QWidget::grabKeyboard()
+
+ Grabs the keyboard input.
+
+ This widget receives all keyboard events until releaseKeyboard()
+ is called; other widgets get no keyboard events at all. Mouse
+ events are not affected. Use grabMouse() if you want to grab that.
+
+ The focus widget is not affected, except that it doesn't receive
+ any keyboard events. setFocus() moves the focus as usual, but the
+ new focus widget receives keyboard events only after
+ releaseKeyboard() is called.
+
+ If a different widget is currently grabbing keyboard input, that
+ widget's grab is released first.
+
+ \sa releaseKeyboard() grabMouse() releaseMouse() focusWidget()
+*/
+
+/*!
+ \fn void QWidget::releaseKeyboard()
+
+ Releases the keyboard grab.
+
+ \sa grabKeyboard(), grabMouse(), releaseMouse()
+*/
+
+/*!
+ \fn QWidget *QWidget::mouseGrabber()
+
+ Returns the widget that is currently grabbing the mouse input.
+
+ If no widget in this application is currently grabbing the mouse,
+ 0 is returned.
+
+ \sa grabMouse(), keyboardGrabber()
+*/
+
+/*!
+ \fn QWidget *QWidget::keyboardGrabber()
+
+ Returns the widget that is currently grabbing the keyboard input.
+
+ If no widget in this application is currently grabbing the
+ keyboard, 0 is returned.
+
+ \sa grabMouse(), mouseGrabber()
+*/
+
+/*!
+ \fn void QWidget::activateWindow()
+
+ Sets the top-level widget containing this widget to be the active
+ window.
+
+ An active window is a visible top-level window that has the
+ keyboard input focus.
+
+ This function performs the same operation as clicking the mouse on
+ the title bar of a top-level window. On X11, the result depends on
+ the Window Manager. If you want to ensure that the window is
+ stacked on top as well you should also call raise(). Note that the
+ window must be visible, otherwise activateWindow() has no effect.
+
+ On Windows, if you are calling this when the application is not
+ currently the active one then it will not make it the active
+ window. It will change the color of the taskbar entry to indicate
+ that the window has changed in some way. This is because Microsoft
+ does not allow an application to interrupt what the user is currently
+ doing in another application.
+
+ \sa isActiveWindow(), window(), show()
+*/
+
+/*!
+ \fn int QWidget::metric(PaintDeviceMetric m) const
+
+ Internal implementation of the virtual QPaintDevice::metric()
+ function.
+
+ \a m is the metric to get.
+*/
+
+/*!
+ \fn void QWidget::setMask(const QRegion &region)
+ \overload
+
+ Causes only the parts of the widget which overlap \a region to be
+ visible. If the region includes pixels outside the rect() of the
+ widget, window system controls in that area may or may not be
+ visible, depending on the platform.
+
+ Note that this effect can be slow if the region is particularly
+ complex.
+
+ \sa windowOpacity
+*/
+void QWidget::setMask(const QRegion &newMask)
+{
+ Q_D(QWidget);
+
+ d->createExtra();
+ if (newMask == d->extra->mask)
+ return;
+
+#ifndef QT_NO_BACKINGSTORE
+ const QRegion oldMask(d->extra->mask);
+#endif
+
+ d->extra->mask = newMask;
+ d->extra->hasMask = !newMask.isEmpty();
+
+#ifndef QT_MAC_USE_COCOA
+ if (!testAttribute(Qt::WA_WState_Created))
+ return;
+#endif
+
+ d->setMask_sys(newMask);
+
+#ifndef QT_NO_BACKINGSTORE
+ if (!isVisible())
+ return;
+
+ if (!d->extra->hasMask) {
+ // Mask was cleared; update newly exposed area.
+ QRegion expose(rect());
+ expose -= oldMask;
+ if (!expose.isEmpty()) {
+ d->setDirtyOpaqueRegion();
+ update(expose);
+ }
+ return;
+ }
+
+ if (!isWindow()) {
+ // Update newly exposed area on the parent widget.
+ QRegion parentExpose(rect());
+ parentExpose -= newMask;
+ if (!parentExpose.isEmpty()) {
+ d->setDirtyOpaqueRegion();
+ parentExpose.translate(data->crect.topLeft());
+ parentWidget()->update(parentExpose);
+ }
+
+ // Update newly exposed area on this widget
+ if (!oldMask.isEmpty())
+ update(newMask - oldMask);
+ }
+#endif
+}
+
+/*!
+ \fn void QWidget::setMask(const QBitmap &bitmap)
+
+ Causes only the pixels of the widget for which \a bitmap has a
+ corresponding 1 bit to be visible. If the region includes pixels
+ outside the rect() of the widget, window system controls in that
+ area may or may not be visible, depending on the platform.
+
+ Note that this effect can be slow if the region is particularly
+ complex.
+
+ The following code shows how an image with an alpha channel can be
+ used to generate a mask for a widget:
+
+ \snippet doc/src/snippets/widget-mask/main.cpp 0
+
+ The label shown by this code is masked using the image it contains,
+ giving the appearance that an irregularly-shaped image is being drawn
+ directly onto the screen.
+
+ Masked widgets receive mouse events only on their visible
+ portions.
+
+ \sa clearMask(), windowOpacity(), {Shaped Clock Example}
+*/
+void QWidget::setMask(const QBitmap &bitmap)
+{
+ setMask(QRegion(bitmap));
+}
+
+/*!
+ \fn void QWidget::clearMask()
+
+ Removes any mask set by setMask().
+
+ \sa setMask()
+*/
+void QWidget::clearMask()
+{
+ setMask(QRegion());
+}
+
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
new file mode 100644
index 0000000000..f54ebf9e09
--- /dev/null
+++ b/src/gui/kernel/qwidget.h
@@ -0,0 +1,1045 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGET_H
+#define QWIDGET_H
+
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qfont.h>
+#include <QtGui/qfontmetrics.h>
+#include <QtGui/qfontinfo.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qbrush.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qkeysequence.h>
+
+#ifdef QT_INCLUDE_COMPAT
+#include <QtGui/qevent.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QLayout;
+class QWSRegionManager;
+class QStyle;
+class QAction;
+class QVariant;
+
+class QActionEvent;
+class QMouseEvent;
+class QWheelEvent;
+class QHoverEvent;
+class QKeyEvent;
+class QFocusEvent;
+class QPaintEvent;
+class QMoveEvent;
+class QResizeEvent;
+class QCloseEvent;
+class QContextMenuEvent;
+class QInputMethodEvent;
+class QTabletEvent;
+class QDragEnterEvent;
+class QDragMoveEvent;
+class QDragLeaveEvent;
+class QDropEvent;
+class QShowEvent;
+class QHideEvent;
+class QInputContext;
+class QIcon;
+class QWindowSurface;
+class QLocale;
+class QGraphicsProxyWidget;
+#if defined(Q_WS_X11)
+class QX11Info;
+#endif
+
+class QWidgetData
+{
+public:
+ WId winid;
+ uint widget_attributes;
+ Qt::WindowFlags window_flags;
+ uint window_state : 4;
+ uint focus_policy : 4;
+ uint sizehint_forced :1;
+ uint is_closing :1;
+ uint in_show : 1;
+ uint in_set_window_state : 1;
+ mutable uint fstrut_dirty : 1;
+ uint context_menu_policy : 3;
+ uint window_modality : 2;
+ uint in_destructor : 1;
+ uint unused : 13;
+ QRect crect;
+ mutable QPalette pal;
+ QFont fnt;
+#if defined(Q_WS_QWS)
+// QRegion req_region; // Requested region
+// mutable QRegion paintable_region; // Paintable region
+// mutable bool paintable_region_dirty;// needs to be recalculated
+// mutable QRegion alloc_region; // Allocated region
+// mutable bool alloc_region_dirty; // needs to be recalculated
+// mutable int overlapping_children; // Handle overlapping children
+
+ int alloc_region_index;
+// int alloc_region_revision;
+#endif
+#if defined(Q_OS_WINCE)
+ uint window_state_internal : 4;
+#endif
+ QRect wrect;
+};
+
+class QWidgetPrivate;
+
+class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWidget)
+
+ Q_PROPERTY(bool modal READ isModal)
+ Q_PROPERTY(Qt::WindowModality windowModality READ windowModality WRITE setWindowModality)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(QRect frameGeometry READ frameGeometry)
+ Q_PROPERTY(QRect normalGeometry READ normalGeometry)
+ Q_PROPERTY(int x READ x)
+ Q_PROPERTY(int y READ y)
+ Q_PROPERTY(QPoint pos READ pos WRITE move DESIGNABLE false STORED false)
+ Q_PROPERTY(QSize frameSize READ frameSize)
+ Q_PROPERTY(QSize size READ size WRITE resize DESIGNABLE false STORED false)
+ Q_PROPERTY(int width READ width)
+ Q_PROPERTY(int height READ height)
+ Q_PROPERTY(QRect rect READ rect)
+ Q_PROPERTY(QRect childrenRect READ childrenRect)
+ Q_PROPERTY(QRegion childrenRegion READ childrenRegion)
+ Q_PROPERTY(QSizePolicy sizePolicy READ sizePolicy WRITE setSizePolicy)
+ Q_PROPERTY(QSize minimumSize READ minimumSize WRITE setMinimumSize)
+ Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize)
+ Q_PROPERTY(int minimumWidth READ minimumWidth WRITE setMinimumWidth STORED false DESIGNABLE false)
+ Q_PROPERTY(int minimumHeight READ minimumHeight WRITE setMinimumHeight STORED false DESIGNABLE false)
+ Q_PROPERTY(int maximumWidth READ maximumWidth WRITE setMaximumWidth STORED false DESIGNABLE false)
+ Q_PROPERTY(int maximumHeight READ maximumHeight WRITE setMaximumHeight STORED false DESIGNABLE false)
+ Q_PROPERTY(QSize sizeIncrement READ sizeIncrement WRITE setSizeIncrement)
+ Q_PROPERTY(QSize baseSize READ baseSize WRITE setBaseSize)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
+ Q_PROPERTY(QFont font READ font WRITE setFont)
+#ifndef QT_NO_CURSOR
+ Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)
+#endif
+ Q_PROPERTY(bool mouseTracking READ hasMouseTracking WRITE setMouseTracking)
+ Q_PROPERTY(bool isActiveWindow READ isActiveWindow)
+ Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
+ Q_PROPERTY(bool focus READ hasFocus)
+ Q_PROPERTY(Qt::ContextMenuPolicy contextMenuPolicy READ contextMenuPolicy WRITE setContextMenuPolicy)
+ Q_PROPERTY(bool updatesEnabled READ updatesEnabled WRITE setUpdatesEnabled DESIGNABLE false)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible DESIGNABLE false)
+ Q_PROPERTY(bool minimized READ isMinimized)
+ Q_PROPERTY(bool maximized READ isMaximized)
+ Q_PROPERTY(bool fullScreen READ isFullScreen)
+ Q_PROPERTY(QSize sizeHint READ sizeHint)
+ Q_PROPERTY(QSize minimumSizeHint READ minimumSizeHint)
+ Q_PROPERTY(bool acceptDrops READ acceptDrops WRITE setAcceptDrops)
+ Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle DESIGNABLE isWindow)
+ Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon DESIGNABLE isWindow)
+ Q_PROPERTY(QString windowIconText READ windowIconText WRITE setWindowIconText DESIGNABLE isWindow)
+ Q_PROPERTY(double windowOpacity READ windowOpacity WRITE setWindowOpacity DESIGNABLE isWindow)
+ Q_PROPERTY(bool windowModified READ isWindowModified WRITE setWindowModified DESIGNABLE isWindow)
+#ifndef QT_NO_TOOLTIP
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
+#endif
+#ifndef QT_NO_STATUSTIP
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
+#endif
+#ifndef QT_NO_WHATSTHIS
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ Q_PROPERTY(QString accessibleName READ accessibleName WRITE setAccessibleName)
+ Q_PROPERTY(QString accessibleDescription READ accessibleDescription WRITE setAccessibleDescription)
+#endif
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
+ QDOC_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
+ Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
+#ifndef QT_NO_STYLE_STYLESHEET
+ Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
+#endif
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET unsetLocale)
+ Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath DESIGNABLE isWindow)
+
+public:
+ enum RenderFlag {
+ DrawWindowBackground = 0x1,
+ DrawChildren = 0x2,
+ IgnoreMask = 0x4
+ };
+ Q_DECLARE_FLAGS(RenderFlags, RenderFlag)
+
+ explicit QWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QWidget(QWidget* parent, const char *name, Qt::WindowFlags f = 0);
+#endif
+ ~QWidget();
+
+ int devType() const;
+
+ WId winId() const;
+ void createWinId(); // internal, going away
+ inline WId internalWinId() const { return data->winid; }
+ WId effectiveWinId() const;
+
+ // GUI style setting
+ QStyle *style() const;
+ void setStyle(QStyle *);
+ // Widget types and states
+
+ bool isTopLevel() const;
+ bool isWindow() const;
+
+ bool isModal() const;
+ Qt::WindowModality windowModality() const;
+ void setWindowModality(Qt::WindowModality windowModality);
+
+ bool isEnabled() const;
+ bool isEnabledTo(QWidget*) const;
+ bool isEnabledToTLW() const;
+
+public Q_SLOTS:
+ void setEnabled(bool);
+ void setDisabled(bool);
+ void setWindowModified(bool);
+
+ // Widget coordinates
+
+public:
+ QRect frameGeometry() const;
+ const QRect &geometry() const;
+ QRect normalGeometry() const;
+
+ int x() const;
+ int y() const;
+ QPoint pos() const;
+ QSize frameSize() const;
+ QSize size() const;
+ inline int width() const;
+ inline int height() const;
+ inline QRect rect() const;
+ QRect childrenRect() const;
+ QRegion childrenRegion() const;
+
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ int minimumWidth() const;
+ int minimumHeight() const;
+ int maximumWidth() const;
+ int maximumHeight() const;
+ void setMinimumSize(const QSize &);
+ void setMinimumSize(int minw, int minh);
+ void setMaximumSize(const QSize &);
+ void setMaximumSize(int maxw, int maxh);
+ void setMinimumWidth(int minw);
+ void setMinimumHeight(int minh);
+ void setMaximumWidth(int maxw);
+ void setMaximumHeight(int maxh);
+
+ QSize sizeIncrement() const;
+ void setSizeIncrement(const QSize &);
+ void setSizeIncrement(int w, int h);
+ QSize baseSize() const;
+ void setBaseSize(const QSize &);
+ void setBaseSize(int basew, int baseh);
+
+ void setFixedSize(const QSize &);
+ void setFixedSize(int w, int h);
+ void setFixedWidth(int w);
+ void setFixedHeight(int h);
+
+ // Widget coordinate mapping
+
+ QPoint mapToGlobal(const QPoint &) const;
+ QPoint mapFromGlobal(const QPoint &) const;
+ QPoint mapToParent(const QPoint &) const;
+ QPoint mapFromParent(const QPoint &) const;
+ QPoint mapTo(QWidget *, const QPoint &) const;
+ QPoint mapFrom(QWidget *, const QPoint &) const;
+
+ QWidget *window() const;
+ QWidget *nativeParentWidget() const;
+ inline QWidget *topLevelWidget() const { return window(); }
+
+ // Widget appearance functions
+ const QPalette &palette() const;
+ void setPalette(const QPalette &);
+
+ void setBackgroundRole(QPalette::ColorRole);
+ QPalette::ColorRole backgroundRole() const;
+
+ void setForegroundRole(QPalette::ColorRole);
+ QPalette::ColorRole foregroundRole() const;
+
+ const QFont &font() const;
+ void setFont(const QFont &);
+ QFontMetrics fontMetrics() const;
+ QFontInfo fontInfo() const;
+
+#ifndef QT_NO_CURSOR
+ QCursor cursor() const;
+ void setCursor(const QCursor &);
+ void unsetCursor();
+#endif
+
+ void setMouseTracking(bool enable);
+ bool hasMouseTracking() const;
+ bool underMouse() const;
+
+ void setMask(const QBitmap &);
+ void setMask(const QRegion &);
+ QRegion mask() const;
+ void clearMask();
+
+ void render(QPaintDevice *target, const QPoint &targetOffset = QPoint(),
+ const QRegion &sourceRegion = QRegion(),
+ RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
+
+ void render(QPainter *painter, const QPoint &targetOffset = QPoint(),
+ const QRegion &sourceRegion = QRegion(),
+ RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
+
+public Q_SLOTS:
+ void setWindowTitle(const QString &);
+#ifndef QT_NO_STYLE_STYLESHEET
+ void setStyleSheet(const QString& styleSheet);
+#endif
+public:
+#ifndef QT_NO_STYLE_STYLESHEET
+ QString styleSheet() const;
+#endif
+ QString windowTitle() const;
+ void setWindowIcon(const QIcon &icon);
+ QIcon windowIcon() const;
+ void setWindowIconText(const QString &);
+ QString windowIconText() const;
+ void setWindowRole(const QString &);
+ QString windowRole() const;
+ void setWindowFilePath(const QString &filePath);
+ QString windowFilePath() const;
+
+ void setWindowOpacity(qreal level);
+ qreal windowOpacity() const;
+
+ bool isWindowModified() const;
+#ifndef QT_NO_TOOLTIP
+ void setToolTip(const QString &);
+ QString toolTip() const;
+#endif
+#ifndef QT_NO_STATUSTIP
+ void setStatusTip(const QString &);
+ QString statusTip() const;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ void setWhatsThis(const QString &);
+ QString whatsThis() const;
+#endif
+#ifndef QT_NO_ACCESSIBILITY
+ QString accessibleName() const;
+ void setAccessibleName(const QString &name);
+ QString accessibleDescription() const;
+ void setAccessibleDescription(const QString &description);
+#endif
+
+ void setLayoutDirection(Qt::LayoutDirection direction);
+ Qt::LayoutDirection layoutDirection() const;
+ void unsetLayoutDirection();
+
+ void setLocale(const QLocale &locale);
+ QLocale locale() const;
+ void unsetLocale();
+
+ inline bool isRightToLeft() const { return layoutDirection() == Qt::RightToLeft; }
+ inline bool isLeftToRight() const { return layoutDirection() == Qt::LeftToRight; }
+
+public Q_SLOTS:
+ inline void setFocus() { setFocus(Qt::OtherFocusReason); }
+
+public:
+ bool isActiveWindow() const;
+ void activateWindow();
+ void clearFocus();
+
+ void setFocus(Qt::FocusReason reason);
+ Qt::FocusPolicy focusPolicy() const;
+ void setFocusPolicy(Qt::FocusPolicy policy);
+ bool hasFocus() const;
+ static void setTabOrder(QWidget *, QWidget *);
+ void setFocusProxy(QWidget *);
+ QWidget *focusProxy() const;
+ Qt::ContextMenuPolicy contextMenuPolicy() const;
+ void setContextMenuPolicy(Qt::ContextMenuPolicy policy);
+
+ // Grab functions
+ void grabMouse();
+#ifndef QT_NO_CURSOR
+ void grabMouse(const QCursor &);
+#endif
+ void releaseMouse();
+ void grabKeyboard();
+ void releaseKeyboard();
+#ifndef QT_NO_SHORTCUT
+ int grabShortcut(const QKeySequence &key, Qt::ShortcutContext context = Qt::WindowShortcut);
+ void releaseShortcut(int id);
+ void setShortcutEnabled(int id, bool enable = true);
+ void setShortcutAutoRepeat(int id, bool enable = true);
+#endif
+ static QWidget *mouseGrabber();
+ static QWidget *keyboardGrabber();
+
+ // Update/refresh functions
+ inline bool updatesEnabled() const;
+ void setUpdatesEnabled(bool enable);
+
+#if 0 //def Q_WS_QWS
+ void repaintUnclipped(const QRegion &, bool erase = true);
+#endif
+
+#ifndef QT_NO_GRAPHICSVIEW
+ QGraphicsProxyWidget *graphicsProxyWidget() const;
+#endif
+
+public Q_SLOTS:
+ void update();
+ void repaint();
+
+public:
+ inline void update(int x, int y, int w, int h);
+ void update(const QRect&);
+ void update(const QRegion&);
+
+ void repaint(int x, int y, int w, int h);
+ void repaint(const QRect &);
+ void repaint(const QRegion &);
+
+public Q_SLOTS:
+ // Widget management functions
+
+ virtual void setVisible(bool visible);
+ inline void setHidden(bool hidden) { setVisible(!hidden); }
+#ifndef Q_OS_WINCE
+ inline void show() { setVisible(true); }
+#else
+ void show();
+#endif
+ inline void hide() { setVisible(false); }
+ inline QT_MOC_COMPAT void setShown(bool shown) { setVisible(shown); }
+
+ void showMinimized();
+ void showMaximized();
+ void showFullScreen();
+ void showNormal();
+
+ bool close();
+ void raise();
+ void lower();
+
+public:
+ void stackUnder(QWidget*);
+ void move(int x, int y);
+ void move(const QPoint &);
+ void resize(int w, int h);
+ void resize(const QSize &);
+ inline void setGeometry(int x, int y, int w, int h);
+ void setGeometry(const QRect &);
+ QByteArray saveGeometry() const;
+ bool restoreGeometry(const QByteArray &geometry);
+ void adjustSize();
+ bool isVisible() const;
+ bool isVisibleTo(QWidget*) const;
+ // ### Qt 5: bool isVisibleTo(_const_ QWidget *) const
+ inline bool isHidden() const;
+
+ bool isMinimized() const;
+ bool isMaximized() const;
+ bool isFullScreen() const;
+
+ Qt::WindowStates windowState() const;
+ void setWindowState(Qt::WindowStates state);
+ void overrideWindowState(Qt::WindowStates state);
+
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+ QSizePolicy sizePolicy() const;
+ void setSizePolicy(QSizePolicy);
+ inline void setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical);
+ virtual int heightForWidth(int) const;
+
+ QRegion visibleRegion() const;
+
+ void setContentsMargins(int left, int top, int right, int bottom);
+ void getContentsMargins(int *left, int *top, int *right, int *bottom) const;
+ QRect contentsRect() const;
+
+public:
+ QLayout *layout() const;
+ void setLayout(QLayout *);
+ void updateGeometry();
+
+ void setParent(QWidget *parent);
+ void setParent(QWidget *parent, Qt::WindowFlags f);
+
+ void scroll(int dx, int dy);
+ void scroll(int dx, int dy, const QRect&);
+
+ // Misc. functions
+
+ QWidget *focusWidget() const;
+ QWidget *nextInFocusChain() const;
+
+ // drag and drop
+ bool acceptDrops() const;
+ void setAcceptDrops(bool on);
+
+#ifndef QT_NO_ACTION
+ //actions
+ void addAction(QAction *action);
+ void addActions(QList<QAction*> actions);
+ void insertAction(QAction *before, QAction *action);
+ void insertActions(QAction *before, QList<QAction*> actions);
+ void removeAction(QAction *action);
+ QList<QAction*> actions() const;
+#endif
+
+ QWidget *parentWidget() const;
+
+ void setWindowFlags(Qt::WindowFlags type);
+ inline Qt::WindowFlags windowFlags() const;
+ void overrideWindowFlags(Qt::WindowFlags type);
+
+ inline Qt::WindowType windowType() const;
+
+ static QWidget *find(WId);
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT QWidgetMapper *wmapper();
+#endif
+ inline QWidget *childAt(int x, int y) const;
+ QWidget *childAt(const QPoint &p) const;
+
+#if defined(Q_WS_X11)
+ const QX11Info &x11Info() const;
+ Qt::HANDLE x11PictureHandle() const;
+#endif
+
+#if defined(Q_WS_MAC)
+ Qt::HANDLE macQDHandle() const;
+ Qt::HANDLE macCGHandle() const;
+#endif
+
+#if defined(Q_WS_WIN)
+ HDC getDC() const;
+ void releaseDC(HDC) const;
+#else
+ Qt::HANDLE handle() const;
+#endif
+
+ void setAttribute(Qt::WidgetAttribute, bool on = true);
+ inline bool testAttribute(Qt::WidgetAttribute) const;
+
+ QPaintEngine *paintEngine() const;
+
+ void ensurePolished() const;
+
+ QInputContext *inputContext();
+ void setInputContext(QInputContext *);
+
+ bool isAncestorOf(const QWidget *child) const;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ bool hasEditFocus() const;
+ void setEditFocus(bool on);
+#endif
+
+ bool autoFillBackground() const;
+ void setAutoFillBackground(bool enabled);
+
+ void setWindowSurface(QWindowSurface *surface);
+ QWindowSurface *windowSurface() const;
+
+Q_SIGNALS:
+ void customContextMenuRequested(const QPoint &pos);
+
+protected:
+ // Event handlers
+ bool event(QEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelEvent(QWheelEvent *);
+#endif
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void focusOutEvent(QFocusEvent *);
+ virtual void enterEvent(QEvent *);
+ virtual void leaveEvent(QEvent *);
+ virtual void paintEvent(QPaintEvent *);
+ virtual void moveEvent(QMoveEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void closeEvent(QCloseEvent *);
+#ifndef QT_NO_CONTEXTMENU
+ virtual void contextMenuEvent(QContextMenuEvent *);
+#endif
+#ifndef QT_NO_TABLETEVENT
+ virtual void tabletEvent(QTabletEvent *);
+#endif
+#ifndef QT_NO_ACTION
+ virtual void actionEvent(QActionEvent *);
+#endif
+
+#ifndef QT_NO_DRAGANDDROP
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragMoveEvent(QDragMoveEvent *);
+ virtual void dragLeaveEvent(QDragLeaveEvent *);
+ virtual void dropEvent(QDropEvent *);
+#endif
+
+ virtual void showEvent(QShowEvent *);
+ virtual void hideEvent(QHideEvent *);
+
+#if defined(Q_WS_MAC)
+ virtual bool macEvent(EventHandlerCallRef, EventRef);
+#endif
+#if defined(Q_WS_WIN)
+ virtual bool winEvent(MSG *message, long *result);
+#endif
+#if defined(Q_WS_X11)
+ virtual bool x11Event(XEvent *);
+#endif
+#if defined(Q_WS_QWS)
+ virtual bool qwsEvent(QWSEvent *);
+#endif
+
+ // Misc. protected functions
+ virtual void changeEvent(QEvent *);
+
+ int metric(PaintDeviceMetric) const;
+
+ virtual void inputMethodEvent(QInputMethodEvent *);
+public:
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const;
+protected:
+ void resetInputContext();
+protected Q_SLOTS:
+ void updateMicroFocus();
+protected:
+
+ void create(WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true);
+ void destroy(bool destroyWindow = true,
+ bool destroySubWindows = true);
+
+ virtual bool focusNextPrevChild(bool next);
+ inline bool focusNextChild() { return focusNextPrevChild(true); }
+ inline bool focusPreviousChild() { return focusNextPrevChild(false); }
+
+protected:
+ QWidget(QWidgetPrivate &d, QWidget* parent, Qt::WindowFlags f);
+private:
+
+ bool testAttribute_helper(Qt::WidgetAttribute) const;
+
+ QLayout *takeLayout();
+
+ friend class QBackingStoreDevice;
+ friend class QWidgetBackingStore;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QBaseApplication;
+ friend class QPainter;
+ friend class QPainterPrivate;
+ friend class QPixmap; // for QPixmap::fill()
+ friend class QFontMetrics;
+ friend class QFontInfo;
+ friend class QETWidget;
+ friend class QLayout;
+ friend class QWidgetItem;
+ friend class QWidgetItemV2;
+ friend class QGLContext;
+ friend class QGLWidget;
+ friend class QGLWindowSurface;
+ friend class QVGWindowSurface;
+ friend class QX11PaintEngine;
+ friend class QWin32PaintEngine;
+ friend class QShortcutPrivate;
+ friend class QShortcutMap;
+ friend class QWindowSurface;
+ friend class QD3DWindowSurface;
+ friend class QGraphicsProxyWidget;
+ friend class QGraphicsProxyWidgetPrivate;
+ friend class QStyleSheetStyle;
+
+#ifdef Q_WS_MAC
+ friend class QCoreGraphicsPaintEnginePrivate;
+ friend QPoint qt_mac_posInWindow(const QWidget *w);
+ friend OSWindowRef qt_mac_window_for(const QWidget *w);
+ friend bool qt_mac_is_metal(const QWidget *w);
+ friend OSViewRef qt_mac_nativeview_for(const QWidget *w);
+ friend void qt_event_request_window_change(QWidget *widget);
+ friend bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref);
+#endif
+#ifdef Q_WS_QWS
+ friend class QWSBackingStore;
+ friend class QWSManager;
+ friend class QWSManagerPrivate;
+ friend class QDecoration;
+ friend class QWSWindowSurface;
+ friend class QScreen;
+ friend class QVNCScreen;
+ friend bool isWidgetOpaque(const QWidget *);
+ friend class QGLWidgetPrivate;
+#endif
+#ifdef Q_WS_X11
+ friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
+ friend void qt_net_remove_user_time(QWidget *tlw);
+#endif
+
+ friend Q_GUI_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget);
+ friend Q_GUI_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget);
+
+private:
+ Q_DISABLE_COPY(QWidget)
+ Q_PRIVATE_SLOT(d_func(), void _q_showIfNotHidden())
+
+ QWidgetData *data;
+
+#ifdef QT3_SUPPORT
+public:
+ inline QT3_SUPPORT bool isUpdatesEnabled() const { return updatesEnabled(); }
+ QT3_SUPPORT QStyle *setStyle(const QString&);
+ inline QT3_SUPPORT bool isVisibleToTLW() const;
+ QT3_SUPPORT QRect visibleRect() const;
+ inline QT3_SUPPORT void iconify() { showMinimized(); }
+ inline QT3_SUPPORT void constPolish() const { ensurePolished(); }
+ inline QT3_SUPPORT void polish() { ensurePolished(); }
+ inline QT3_SUPPORT void reparent(QWidget *parent, Qt::WindowFlags f, const QPoint &p, bool showIt=false)
+ { setParent(parent, f); setGeometry(p.x(),p.y(),width(),height()); if (showIt) show(); }
+ inline QT3_SUPPORT void reparent(QWidget *parent, const QPoint &p, bool showIt=false)
+ { setParent(parent, windowFlags() & ~Qt::WindowType_Mask); setGeometry(p.x(),p.y(),width(),height()); if (showIt) show(); }
+ inline QT3_SUPPORT void recreate(QWidget *parent, Qt::WindowFlags f, const QPoint & p, bool showIt=false)
+ { setParent(parent, f); setGeometry(p.x(),p.y(),width(),height()); if (showIt) show(); }
+ inline QT3_SUPPORT void setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver, bool hfw)
+ { QSizePolicy sp(hor, ver); sp.setHeightForWidth(hfw); setSizePolicy(sp);}
+ inline QT3_SUPPORT bool hasMouse() const { return testAttribute(Qt::WA_UnderMouse); }
+#ifndef QT_NO_CURSOR
+ inline QT3_SUPPORT bool ownCursor() const { return testAttribute(Qt::WA_SetCursor); }
+#endif
+ inline QT3_SUPPORT bool ownFont() const { return testAttribute(Qt::WA_SetFont); }
+ inline QT3_SUPPORT void unsetFont() { setFont(QFont()); }
+ inline QT3_SUPPORT bool ownPalette() const { return testAttribute(Qt::WA_SetPalette); }
+ inline QT3_SUPPORT void unsetPalette() { setPalette(QPalette()); }
+ Qt::BackgroundMode QT3_SUPPORT backgroundMode() const;
+ void QT3_SUPPORT setBackgroundMode(Qt::BackgroundMode, Qt::BackgroundMode = Qt::PaletteBackground);
+ const QT3_SUPPORT QColor &eraseColor() const;
+ void QT3_SUPPORT setEraseColor(const QColor &);
+ const QT3_SUPPORT QColor &foregroundColor() const;
+ const QT3_SUPPORT QPixmap *erasePixmap() const;
+ void QT3_SUPPORT setErasePixmap(const QPixmap &);
+ const QT3_SUPPORT QColor &paletteForegroundColor() const;
+ void QT3_SUPPORT setPaletteForegroundColor(const QColor &);
+ const QT3_SUPPORT QColor &paletteBackgroundColor() const;
+ void QT3_SUPPORT setPaletteBackgroundColor(const QColor &);
+ const QT3_SUPPORT QPixmap *paletteBackgroundPixmap() const;
+ void QT3_SUPPORT setPaletteBackgroundPixmap(const QPixmap &);
+ const QT3_SUPPORT QBrush& backgroundBrush() const;
+ const QT3_SUPPORT QColor &backgroundColor() const;
+ const QT3_SUPPORT QPixmap *backgroundPixmap() const;
+ void QT3_SUPPORT setBackgroundPixmap(const QPixmap &);
+ QT3_SUPPORT void setBackgroundColor(const QColor &);
+ QT3_SUPPORT QColorGroup colorGroup() const;
+ QT3_SUPPORT QWidget *parentWidget(bool sameWindow) const;
+ inline QT3_SUPPORT void setKeyCompression(bool b) { setAttribute(Qt::WA_KeyCompression, b); }
+ inline QT3_SUPPORT void setFont(const QFont &f, bool) { setFont(f); }
+ inline QT3_SUPPORT void setPalette(const QPalette &p, bool) { setPalette(p); }
+ enum BackgroundOrigin { WidgetOrigin, ParentOrigin, WindowOrigin, AncestorOrigin };
+ inline QT3_SUPPORT void setBackgroundOrigin(BackgroundOrigin){};
+ inline QT3_SUPPORT BackgroundOrigin backgroundOrigin() const { return WindowOrigin; }
+ inline QT3_SUPPORT QPoint backgroundOffset() const { return QPoint(); }
+ inline QT3_SUPPORT void repaint(bool) { repaint(); }
+ inline QT3_SUPPORT void repaint(int x, int y, int w, int h, bool) { repaint(x,y,w,h); }
+ inline QT3_SUPPORT void repaint(const QRect &r, bool) { repaint(r); }
+ inline QT3_SUPPORT void repaint(const QRegion &rgn, bool) { repaint(rgn); }
+ QT3_SUPPORT void erase();
+ inline QT3_SUPPORT void erase(int x, int y, int w, int h) { erase_helper(x, y, w, h); }
+ QT3_SUPPORT void erase(const QRect &);
+ QT3_SUPPORT void erase(const QRegion &);
+ QT3_SUPPORT void drawText(const QPoint &p, const QString &s)
+ { drawText_helper(p.x(), p.y(), s); }
+ inline QT3_SUPPORT void drawText(int x, int y, const QString &s)
+ { drawText_helper(x, y, s); }
+ QT3_SUPPORT bool close(bool);
+ inline QT3_SUPPORT QWidget *childAt(int x, int y, bool includeThis) const
+ {
+ QWidget *w = childAt(x, y);
+ return w ? w : ((includeThis && rect().contains(x,y))?const_cast<QWidget*>(this):0);
+ }
+ inline QT3_SUPPORT QWidget *childAt(const QPoint &p, bool includeThis) const
+ {
+ QWidget *w = childAt(p);
+ return w ? w : ((includeThis && rect().contains(p))?const_cast<QWidget*>(this):0);
+ }
+ inline QT3_SUPPORT void setCaption(const QString &c) { setWindowTitle(c); }
+ QT3_SUPPORT void setIcon(const QPixmap &i);
+ inline QT3_SUPPORT void setIconText(const QString &it) { setWindowIconText(it); }
+ inline QT3_SUPPORT QString caption() const { return windowTitle(); }
+ QT3_SUPPORT const QPixmap *icon() const;
+ inline QT3_SUPPORT QString iconText() const { return windowIconText(); }
+ inline QT3_SUPPORT void setInputMethodEnabled(bool b) { setAttribute(Qt::WA_InputMethodEnabled, b); }
+ inline QT3_SUPPORT bool isInputMethodEnabled() const { return testAttribute(Qt::WA_InputMethodEnabled); }
+ inline QT3_SUPPORT void setActiveWindow() { activateWindow(); }
+ inline QT3_SUPPORT bool isShown() const { return !isHidden(); }
+ inline QT3_SUPPORT bool isDialog() const { return windowType() == Qt::Dialog; }
+ inline QT3_SUPPORT bool isPopup() const { return windowType() == Qt::Popup; }
+ inline QT3_SUPPORT bool isDesktop() const { return windowType() == Qt::Desktop; }
+
+
+private:
+ void drawText_helper(int x, int y, const QString &);
+ void erase_helper(int x, int y, int w, int h);
+#endif // QT3_SUPPORT
+
+protected:
+ virtual void styleChange(QStyle&); // compat
+ virtual void enabledChange(bool); // compat
+ virtual void paletteChange(const QPalette &); // compat
+ virtual void fontChange(const QFont &); // compat
+ virtual void windowActivationChange(bool); // compat
+ virtual void languageChange(); // compat
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWidget::RenderFlags)
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QWidget *qobject_cast_helper<QWidget*>(QObject *o, QWidget *)
+{
+ if (!o || !o->isWidgetType()) return 0;
+ return (QWidget*)(o);
+}
+#else
+template <> inline QWidget *qobject_cast<QWidget*>(QObject *o)
+{
+ if (!o || !o->isWidgetType()) return 0;
+ return static_cast<QWidget*>(o);
+}
+template <> inline const QWidget *qobject_cast<const QWidget*>(const QObject *o)
+{
+ if (!o || !o->isWidgetType()) return 0;
+ return static_cast<const QWidget*>(o);
+}
+#endif
+
+inline QWidget *QWidget::childAt(int ax, int ay) const
+{ return childAt(QPoint(ax, ay)); }
+
+inline Qt::WindowType QWidget::windowType() const
+{ return static_cast<Qt::WindowType>(int(data->window_flags & Qt::WindowType_Mask)); }
+inline Qt::WindowFlags QWidget::windowFlags() const
+{ return data->window_flags; }
+
+inline bool QWidget::isTopLevel() const
+{ return (windowType() & Qt::Window); }
+
+inline bool QWidget::isWindow() const
+{ return (windowType() & Qt::Window); }
+
+inline bool QWidget::isEnabled() const
+{ return !testAttribute(Qt::WA_Disabled); }
+
+inline bool QWidget::isModal() const
+{ return data->window_modality != Qt::NonModal; }
+
+inline bool QWidget::isEnabledToTLW() const
+{ return isEnabled(); }
+
+inline int QWidget::minimumWidth() const
+{ return minimumSize().width(); }
+
+inline int QWidget::minimumHeight() const
+{ return minimumSize().height(); }
+
+inline int QWidget::maximumWidth() const
+{ return maximumSize().width(); }
+
+inline int QWidget::maximumHeight() const
+{ return maximumSize().height(); }
+
+inline void QWidget::setMinimumSize(const QSize &s)
+{ setMinimumSize(s.width(),s.height()); }
+
+inline void QWidget::setMaximumSize(const QSize &s)
+{ setMaximumSize(s.width(),s.height()); }
+
+inline void QWidget::setSizeIncrement(const QSize &s)
+{ setSizeIncrement(s.width(),s.height()); }
+
+inline void QWidget::setBaseSize(const QSize &s)
+{ setBaseSize(s.width(),s.height()); }
+
+inline const QFont &QWidget::font() const
+{ return data->fnt; }
+
+inline QFontMetrics QWidget::fontMetrics() const
+{ return QFontMetrics(data->fnt); }
+
+inline QFontInfo QWidget::fontInfo() const
+{ return QFontInfo(data->fnt); }
+
+inline void QWidget::setMouseTracking(bool enable)
+{ setAttribute(Qt::WA_MouseTracking, enable); }
+
+inline bool QWidget::hasMouseTracking() const
+{ return testAttribute(Qt::WA_MouseTracking); }
+
+inline bool QWidget::underMouse() const
+{ return testAttribute(Qt::WA_UnderMouse); }
+
+inline bool QWidget::updatesEnabled() const
+{ return !testAttribute(Qt::WA_UpdatesDisabled); }
+
+inline void QWidget::update(int ax, int ay, int aw, int ah)
+{ update(QRect(ax, ay, aw, ah)); }
+
+inline bool QWidget::isVisible() const
+{ return testAttribute(Qt::WA_WState_Visible); }
+
+inline bool QWidget::isHidden() const
+{ return testAttribute(Qt::WA_WState_Hidden); }
+
+inline void QWidget::move(int ax, int ay)
+{ move(QPoint(ax, ay)); }
+
+inline void QWidget::resize(int w, int h)
+{ resize(QSize(w, h)); }
+
+inline void QWidget::setGeometry(int ax, int ay, int aw, int ah)
+{ setGeometry(QRect(ax, ay, aw, ah)); }
+
+inline QRect QWidget::rect() const
+{ return QRect(0,0,data->crect.width(),data->crect.height()); }
+
+inline const QRect &QWidget::geometry() const
+{ return data->crect; }
+
+inline QSize QWidget::size() const
+{ return data->crect.size(); }
+
+inline int QWidget::width() const
+{ return data->crect.width(); }
+
+inline int QWidget::height() const
+{ return data->crect.height(); }
+
+inline QWidget *QWidget::parentWidget() const
+{ return static_cast<QWidget *>(QObject::parent()); }
+
+inline void QWidget::setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver)
+{ setSizePolicy(QSizePolicy(hor, ver)); }
+
+inline bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
+{
+ if (attribute < int(8*sizeof(uint)))
+ return data->widget_attributes & (1<<attribute);
+ return testAttribute_helper(attribute);
+}
+
+#ifdef QT3_SUPPORT
+inline bool QWidget::isVisibleToTLW() const
+{ return isVisible(); }
+inline QWidget *QWidget::parentWidget(bool sameWindow) const
+{
+ if (sameWindow && isWindow())
+ return 0;
+ return static_cast<QWidget *>(QObject::parent());
+}
+inline QColorGroup QWidget::colorGroup() const
+{ return QColorGroup(palette()); }
+inline void QWidget::setPaletteForegroundColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(foregroundRole(), c); setPalette(p); }
+inline const QBrush& QWidget::backgroundBrush() const { return palette().brush(backgroundRole()); }
+inline void QWidget::setBackgroundPixmap(const QPixmap &pm)
+{ QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); }
+inline const QPixmap *QWidget::backgroundPixmap() const { return 0; }
+inline void QWidget::setBackgroundColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(backgroundRole(), c); setPalette(p); }
+inline const QColor & QWidget::backgroundColor() const { return palette().color(backgroundRole()); }
+inline const QColor &QWidget::foregroundColor() const { return palette().color(foregroundRole());}
+inline const QColor &QWidget::eraseColor() const { return palette().color(backgroundRole()); }
+inline void QWidget::setEraseColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(backgroundRole(), c); setPalette(p); }
+inline const QPixmap *QWidget::erasePixmap() const { return 0; }
+inline void QWidget::setErasePixmap(const QPixmap &pm)
+{ QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); }
+inline const QColor &QWidget::paletteForegroundColor() const { return palette().color(foregroundRole());}
+inline const QColor &QWidget::paletteBackgroundColor() const { return palette().color(backgroundRole()); }
+inline void QWidget::setPaletteBackgroundColor(const QColor &c)
+{ QPalette p = palette(); p.setColor(backgroundRole(), c); setPalette(p); }
+inline const QPixmap *QWidget::paletteBackgroundPixmap() const
+{ return 0; }
+inline void QWidget::setPaletteBackgroundPixmap(const QPixmap &pm)
+{ QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); }
+inline QT3_SUPPORT void QWidget::erase() { erase_helper(0, 0, data->crect.width(), data->crect.height()); }
+inline QT3_SUPPORT void QWidget::erase(const QRect &r) { erase_helper(r.x(), r.y(), r.width(), r.height()); }
+#endif
+
+#define QWIDGETSIZE_MAX ((1<<24)-1)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWIDGET_H
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
new file mode 100644
index 0000000000..f599b7cf25
--- /dev/null
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -0,0 +1,4842 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $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.
+**
+****************************************************************************/
+//#define QT_RASTER_PAINTENGINE
+
+#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 "qimage.h"
+#include "qlayout.h"
+#include "qmenubar.h"
+#include <private/qbackingstore_p.h>
+#ifdef QT_RASTER_PAINTENGINE
+# include <private/qpaintengine_raster_p.h>
+#endif
+#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 "qdnd_p.h"
+#include <QtGui/qgraphicsproxywidget.h>
+
+QT_BEGIN_NAMESPACE
+
+#define XCOORD_MAX 16383
+#define WRECT_MAX 8191
+
+#ifndef QT_MAC_USE_COCOA
+
+extern "C" {
+ extern OSStatus _HIViewScrollRectWithOptions(HIViewRef, const HIRect *, CGFloat, CGFloat,
+ OptionBits);
+}
+#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;
+
+#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;
+ if (modality == Qt::WindowModal || w->windowType() == Qt::Sheet)
+ return true;
+ return false;
+}
+
+bool qt_mac_is_macdrawer(const QWidget *w)
+{
+ return (w && w->parentWidget() && w->windowType() == Qt::Drawer);
+}
+
+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.cpp
+ if(qt_mac_app_fullscreen == b)
+ return;
+ qt_mac_app_fullscreen = b;
+#if QT_MAC_USE_COCOA
+ if(b)
+ SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
+ else
+ SetSystemUIMode(kUIModeNormal, 0);
+#else
+ if(b)
+ HideMenuBar();
+ else
+ ShowMenuBar();
+#endif
+}
+
+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)
+{
+ return window && qt_isGenuineQWidget(OSViewRef(window->winId()));
+}
+
+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)) {
+ w->window()->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;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ CGWindowLevel tmpLevel;
+ GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel);
+ group_level = tmpLevel;
+ } else
+#endif
+ {
+ GetWindowGroupLevel(GetWindowGroupOfClass(wclass), &group_level);
+ }
+ 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
+
+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;
+}
+
+// window events
+static EventTypeSpec window_events[] = {
+ { kEventClassWindow, kEventWindowClose },
+ { kEventClassWindow, kEventWindowExpanded },
+ { kEventClassWindow, kEventWindowZoomed },
+ { kEventClassWindow, kEventWindowCollapsed },
+ { kEventClassWindow, kEventWindowToolbarSwitchMode },
+ { kEventClassWindow, kEventWindowProxyBeginDrag },
+ { kEventClassWindow, kEventWindowProxyEndDrag },
+ { kEventClassWindow, kEventWindowResizeCompleted },
+ { kEventClassWindow, kEventWindowBoundsChanging },
+ { kEventClassWindow, kEventWindowBoundsChanged },
+ { kEventClassWindow, kEventWindowGetRegion },
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ { kEventClassWindow, kEventWindowGetClickModality },
+#endif
+ { kEventClassWindow, kEventWindowTransitionCompleted },
+ { 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;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ } 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;
+ QWidget *top = 0;
+ if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && top != widget){
+ if(!qt_mac_is_macsheet(top) || top->parentWidget() != widget) {
+ handled_event = true;
+ WindowPtr topWindowRef = qt_mac_window_for(top);
+ SetEventParameter(event, kEventParamModalWindow, typeWindowRef, sizeof(topWindowRef), &topWindowRef);
+ HIModalClickResult clickResult = kHIModalClickIsModal;
+ SetEventParameter(event, kEventParamModalClickResult, typeModalClickResult, sizeof(clickResult), &clickResult);
+ }
+ }
+#endif
+ } 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 == 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);
+ }
+ extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+ 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);
+ extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+ qt_button_down = 0;
+ } else if(ekind == kEventWindowToolbarSwitchMode) {
+ QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey));
+ QApplication::sendSpontaneousEvent(widget, &ev);
+ 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 || ekind == kEventWindowBoundsChanged) {
+ // Panther doesn't send Changing for sheets, only changed, so only
+ // bother handling Changed event if we are on 10.3 and we are a
+ // sheet.
+ if (ekind == kEventWindowBoundsChanged
+ && (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4
+ || !(widget->windowFlags() & Qt::Sheet))) {
+ handled_event = false;
+ } else {
+ 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 {
+ 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; }
+ 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;
+#ifndef QT_MAC_NO_QUICKDRAW
+ {
+ if(GetEventParameter(event, kEventParamGrafPort, typeGrafPtr, 0, sizeof(qd), 0, &qd) != noErr) {
+ GDHandle dev = 0;
+ GetGWorld(&qd, &dev); //just use the global port..
+ }
+ }
+ bool end_cg_context = false;
+ if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr && qd) {
+ end_cg_context = true;
+ QDBeginCGContext(qd, &cg);
+ }
+#else
+ if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) {
+ Q_ASSERT(false);
+ }
+#endif
+ 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");
+
+ 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);
+
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(widget->parent());
+ QPoint scrollAreaOffset;
+ if (scrollArea && scrollArea->viewport() == widget) {
+ QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(static_cast<QWidget *>(scrollArea)->d_ptr);
+ scrollAreaOffset = priv->contentsOffset();
+ p.translate(-scrollAreaOffset);
+ }
+
+ widget->d_func()->paintBackground(&p, qrgn, scrollAreaOffset, 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).translated(scrollAreaOffset), tint);
+ }
+ p.end();
+ if (!redirectionOffset.isNull())
+ widget->d_func()->restoreRedirected();
+ }
+
+ 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()));
+ }
+
+
+ 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();
+#ifdef QT_RASTER_PAINTENGINE
+ if(engine && engine->type() == QPaintEngine::Raster)
+ static_cast<QRasterPaintEngine*>(engine)->flush(widget,
+ qrgn.boundingRect().topLeft());
+#endif
+
+ //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);
+#ifndef QT_MAC_NO_QUICKDRAW
+ if(end_cg_context)
+ QDEndCGContext(qd, &cg);
+#endif
+ } 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;
+ }
+ }
+ }
+
+ // 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()))) {
+ extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+ if (widget == qt_button_down)
+ qt_button_down = 0;
+ }
+ }
+ }
+ break; }
+ case kEventClassMouse: {
+ bool send_to_app = false;
+ extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+ 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)) {
+ if(visible) {
+ if (!widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ widget->show();
+ } else {
+ widget->hide();
+ widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ QWidgetPrivate member functions
+ *****************************************************************************/
+bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up)
+{
+ if(!w || !w->isWindow())
+ return false;
+
+ QTLWExtra *topData = w->d_func()->topData();
+ QWExtra *extraData = w->d_func()->extraData();
+ 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_recreate_root_win()
+{
+ if(!qt_root_win) //sanity check
+ return false;
+ //store old
+ OSWindowRef old_root_win = qt_root_win;
+ //recreate
+ qt_root_win = 0;
+ qt_create_root_win();
+ //cleanup old window
+#ifdef QT_MAC_USE_COCOA
+ [old_root_win release];
+#else
+ CFRelease(old_root_win);
+#endif
+ 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);
+#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) {
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
+ wattr |= kWindowNoTitleBarAttribute;
+ else
+ wclass = kPlainWindowClass;
+ } else if(wclass == kFloatingWindowClass) {
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
+ wattr |= kWindowNoTitleBarAttribute;
+ else
+ wclass = kToolbarWindowClass;
+ } 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(q->testAttribute(Qt::WA_ShowModal) || 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
+ 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;
+ 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
+
+#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 (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ if (wattr & kWindowHideOnSuspendAttribute)
+ HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0);
+ else
+ HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden);
+ }
+#endif
+ 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);
+}
+#else // QT_MAC_USE_COCOA
+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];
+ [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();
+ }
+
+ 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);
+ }
+
+ 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);
+}
+
+#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 = qobject_cast<QMainWindowLayout *>(q->layout())) {
+ 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 Trolltech 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
+ 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 (!topLevel && initializeWindow)
+ setWSGeometry();
+
+ if (destroyid)
+ qt_mac_destructView(destroyid);
+}
+
+/*!
+ 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);
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(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(acceptDrops())
+ setAcceptDrops(false);
+
+ 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);
+ }
+ }
+ d->setWinId(0);
+ }
+}
+
+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(q) addSubview:qt_mac_nativeview_for(w)];
+ w->setAttribute(Qt::WA_DropSiteRegistered, oldRegistered);
+#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(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];
+ oldToolbarVisible = [oldToolbar isVisible];
+ }
+#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);
+ QPoint pt = q->pos();
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+ if (wasCreated && !qt_isGenuineQWidget(q))
+ return;
+
+ if ((data.window_flags & Qt::Sheet) && topData && topData->opacity == 242)
+ q->setWindowOpacity(1.0f);
+
+ 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)
+ if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) {
+ createWinId();
+ if (q->isWindow()) {
+#ifndef QT_MAC_USE_COCOA
+ if (QMainWindowLayout *mwl = qobject_cast<QMainWindowLayout *>(q->layout())) {
+ mwl->updateHIToolBarStatus();
+ }
+#else
+ if (oldToolbar && !(f & Qt::FramelessWindowHint)) {
+ OSWindowRef newWindow = qt_mac_window_for(q);
+ [newWindow setToolbar:oldToolbar];
+ [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();
+ 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)) {
+ 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)) {
+ 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 &)
+{
+ qt_mac_update_cursor();
+}
+
+void QWidgetPrivate::unsetCursor_sys()
+{
+ qt_mac_update_cursor();
+}
+
+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:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(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;
+ [qt_mac_window_for(q) setRepresentedFilename:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(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 (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ if (validRef) {
+ status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref);
+ } else {
+ status = RemoveWindowProxy(qt_mac_window_for(q));
+ }
+ } else {
+ // Convert to an FSSpec and set it. It's deprecated but it works for where we don't have the other call.
+ if (validRef) {
+ FSSpec fsspec;
+ FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, 0, &fsspec, 0);
+ status = SetWindowProxyFSSpec(qt_mac_window_for(q), &fsspec);
+ } 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 (icon.isNull()) {
+ [iconButton setImage:nil];
+ } else {
+ NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(*pm));
+ [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:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(iconText)))];
+#endif
+ }
+}
+
+void QWidget::grabMouse()
+{
+ if(isVisible() && !qt_nograb()) {
+ if(mac_mouse_grabber)
+ mac_mouse_grabber->releaseMouse();
+ mac_mouse_grabber=this;
+ }
+}
+
+void QWidget::grabMouse(const QCursor &)
+{
+ if(isVisible() && !qt_nograb()) {
+ if(mac_mouse_grabber)
+ mac_mouse_grabber->releaseMouse();
+ mac_mouse_grabber=this;
+ }
+}
+
+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);
+#else
+ [win makeKeyWindow];
+#endif
+ qApp->setActiveWindow(tlw);
+ } 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_nativeview_for(q) setNeedsDisplay:YES];
+#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
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ dirtyOnWidget += updateRect;
+ HIRect r = CGRectMake(x, y, w, h);
+ HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true);
+ } else
+ #endif
+ {
+ q->update(QRegion(updateRect));
+ }
+#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
+ HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgn.toQDRgn()), true);
+#else
+ // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect.
+ const QRect &boundingRect = rgn.boundingRect();
+ [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(boundingRect.x(),
+ boundingRect.y(), boundingRect.width(),
+ boundingRect.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();
+ if (realWindow && !q->testAttribute(Qt::WA_Moved)) {
+ q->createWinId();
+ if (QWidget *p = q->parentWidget()) {
+ p->createWinId();
+#ifndef QT_MAC_USE_COCOA
+ RepositionWindow(qt_mac_window_for(q), qt_mac_window_for(p), kWindowCenterOnParentWindow);
+#else
+ CGRect parentFrame = NSRectToCGRect([qt_mac_window_for(p) frame]);
+ OSWindowRef windowRef = qt_mac_window_for(q);
+ NSRect windowFrame = [windowRef frame];
+ NSPoint parentCenter = NSMakePoint(CGRectGetMidX(parentFrame), CGRectGetMidY(parentFrame));
+ [windowRef setFrameTopLeftPoint:NSMakePoint(parentCenter.x - (windowFrame.size.width / 2),
+ (parentCenter.y + (windowFrame.size.height / 2)))];
+#endif
+ } else {
+#ifndef QT_MAC_USE_COCOA
+ RepositionWindow(qt_mac_window_for(q), 0, kWindowCenterOnMainScreen);
+#else
+ // Ideally we would do a "center" here, but NSWindow's center is more equivalent to
+ // kWindowAlertPositionOnMainScreen instead of kWindowCenterOnMainScreen.
+ QRect availGeo = QApplication::desktop()->availableGeometry(q);
+ // Center the content only.
+ data.crect.moveCenter(availGeo.center());
+ QRect fStrut = frameStrut();
+ QRect frameRect(data.crect.x() - fStrut.left(), data.crect.y() - fStrut.top(),
+ fStrut.left() + fStrut.right() + data.crect.width(),
+ fStrut.top() + fStrut.bottom() + data.crect.height());
+ NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), frameRect.width(), frameRect.height());
+ [qt_mac_window_for(q) setFrame:cocoaFrameRect display:NO];
+#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
+ 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()];
+
+ [window makeKeyAndOrderFront:window];
+ if (data.window_modality == Qt::ApplicationModal)
+ QCoreApplication::postEvent(qApp, new QEvent(QEvent::CocoaRequestModal));
+#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)) {
+ qt_event_request_activate(q);
+#ifdef QT_MAC_USE_COCOA
+ if (q->windowModality() == Qt::ApplicationModal) {
+ // We call 'activeModalSession' early to force creation of q's modal
+ // session. This seems neccessary for child dialogs to pop to front:
+ QEventDispatcherMacPrivate::activeModalSession();
+ }
+#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);
+}
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ if((q->windowType() == Qt::Desktop)) //you can't hide the desktop!
+ return;
+
+ QMacCocoaAutoReleasePool pool;
+ if(q->isWindow()) {
+ 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];
+#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
+ }
+ if(q->isActiveWindow() && !(q->windowType() == Qt::Popup)) {
+ QWidget *w = 0;
+ if(q->parentWidget())
+ w = q->parentWidget()->window();
+ if(!w || (!w->isVisible() && !w->isMinimized())) {
+#ifndef QT_MAC_USE_COCOA
+ 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;
+ }
+ }
+#else
+ NSArray *windows = [NSApp windows];
+ NSUInteger totalWindows = [windows count];
+ for (NSUInteger i = 0; i < totalWindows; ++i) {
+ OSWindowRef wp = [windows objectAtIndex:i];
+ if ((w = qt_mac_find_window(wp)))
+ break;
+ }
+#endif
+ }
+ if(w && w->isVisible() && !w->isMinimized())
+ qt_event_request_activate(w);
+ }
+ } 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());
+ 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();
+ setParent(parentWidget(), d->topData()->savedFlags);
+ setGeometry(d->topData()->normalGeometry);
+ if(!qApp->desktop()->screenNumber(this))
+ qt_mac_set_fullscreen_mode(false);
+ 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) {
+#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
+ }
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ if((q->windowType() == Qt::Desktop))
+ return;
+
+#if QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ if (isRealWindow()) {
+ // Calling orderFront shows the window on Cocoa too.
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ [qt_mac_window_for(q) orderFront: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 {
+ // Cocoa doesn't really have an idea of Z-ordering, but you can
+ // fake it by changing the order of it.
+ NSView *view = qt_mac_nativeview_for(q);
+ NSView *parentView = [view superview];
+ [view removeFromSuperview];
+ [parentView addSubview: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
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ if((q->windowType() == Qt::Desktop))
+ return;
+#ifdef QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ if (isRealWindow()) {
+ OSWindowRef window = qt_mac_window_for(q);
+ [window orderBack:window];
+ } else {
+ // Cocoa doesn't really have an idea of Z-ordering, but you can
+ // fake it by changing the order of it. In this case
+ // we put the item at the beginning of the list, but that means
+ // we must re-insert everything since we cannot modify the list directly.
+ NSView *myview = qt_mac_nativeview_for(q);
+ NSView *parentView = [myview superview];
+ NSArray *tmpViews = [parentView subviews];
+ NSMutableArray *subviews = [[NSMutableArray alloc] initWithCapacity:[tmpViews count]];
+ [subviews addObjectsFromArray:tmpViews];
+ // Implicit assumption that myViewIndex is included in subviews, that's why I'm not checking
+ // myViewIndex.
+ NSUInteger index = 0;
+ NSUInteger myViewIndex = 0;
+ bool foundMyView = false;
+ for (NSView *subview in subviews) {
+ [subview removeFromSuperview];
+ if (subview == myview) {
+ foundMyView = true;
+ myViewIndex = index;
+ }
+ ++index;
+ }
+ [parentView addSubview:myview];
+ if (foundMyView)
+ [subviews removeObjectAtIndex:myViewIndex];
+ for (NSView *subview in subviews)
+ [parentView addSubview:subview];
+ [subviews release];
+ }
+#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
+}
+
+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.
+ QMacCocoaAutoReleasePool pool;
+ NSView *myview = qt_mac_nativeview_for(q);
+ NSView *wView = qt_mac_nativeview_for(w);
+ NSView *parentView = [myview superview];
+ NSArray *tmpViews = [parentView subviews];
+ NSMutableArray *subviews = [[NSMutableArray alloc] initWithCapacity:[tmpViews count]];
+ [subviews addObjectsFromArray:tmpViews];
+ // Implicit assumption that myViewIndex and wViewIndex is included in subviews,
+ // that's why I'm not checking myViewIndex.
+ NSUInteger index = 0;
+ NSUInteger myViewIndex = 0;
+ NSUInteger wViewIndex = 0;
+ for (NSView *subview in subviews) {
+ [subview removeFromSuperview];
+ if (subview == myview)
+ myViewIndex = index;
+ else if (subview == wView)
+ wViewIndex = index;
+ ++index;
+ }
+
+ index = 0;
+ for (NSView *subview in subviews) {
+ if (index == myViewIndex)
+ continue;
+ if (index == wViewIndex)
+ [parentView addSubview:myview];
+ [parentView addSubview:subview];
+ ++index;
+ }
+ [subviews release];
+#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
+ and QWidgetPrivate::isOpaque flags.
+*/
+static void qt_mac_update_widget_posisiton(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 (
+ // move-by-scroll requires QWidgetPrivate::isOpaque set
+ (isMove && qd->isOpaque == false) ||
+
+ // 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
+ ){
+ 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 validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
+ QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
+ 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;
+ if (q->isWindow() && topData()->embedded) {
+#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 {
+ 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)) {
+ 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;
+ }
+ }
+
+ if (!validRange.contains(xrect)) {
+ // we are too big, and must clip
+ xrect &=wrectRange;
+ wrect = xrect;
+ wrect.translate(-data.crect.topLeft());
+ //parent's X coord system is equal to parent's Qt coord
+ //sys, so we don't need to map xrect.
+ }
+
+ }
+
+ // 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_posisiton(q, oldRect, xrect);
+
+ if (jump) {
+ updateSystemBackground();
+ 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::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();
+ if (realWindow && !(w == 0 && h == 0) && !q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ topData()->isSetGeometry = 1;
+ topData()->isMove = isMove;
+#ifndef QT_MAC_USE_COCOA
+ Rect r; SetRect(&r, x, y, x + w, y + h);
+ SetWindowBounds(qt_mac_window_for(q), kWindowContentRgn, &r);
+#else
+ 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());
+ [window setFrame:cocoaFrameRect display:NO];
+#endif
+ topData()->isSetGeometry = 0;
+ } 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();
+ if(QWExtra *extra = extraData()) { // any size restrictions?
+ if(realWindow) {
+ qt_mac_update_sizer(q);
+ if(q->windowFlags() & Qt::WindowMaximizeButtonHint) {
+#ifndef QT_MAC_USE_COCOA
+ 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);
+ }
+#endif
+ }
+ }
+
+ 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 (realWindow) {
+ w = qMax(0, w);
+ h = qMax(0, h);
+ }
+
+ QPoint oldp = q->pos();
+ QSize olds = q->size();
+ const bool isResize = (olds != QSize(w, h));
+ if(!realWindow && !isResize && QPoint(x, y) == oldp)
+ return;
+ if(isResize && q->isMaximized())
+ data.window_state = data.window_state & ~Qt::WindowMaximized;
+ const bool visible = q->isVisible();
+ data.crect = QRect(x, y, w, h);
+
+ if(realWindow) {
+ if(QWExtra *extra = extraData()) { //set constraints
+ 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) setMinSize:min];
+ [qt_mac_window_for(q) setMaxSize:max];
+#endif
+ }
+#ifndef QT_MAC_USE_COCOA
+ 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 && !extra->mask.isEmpty()) {
+ QRegion oldRegion(extra->mask.translated(oldp));
+ oldRegion &= oldRect;
+ q->parentWidget()->d_func()->invalidateBuffer(oldRegion);
+ } else {
+ q->parentWidget()->d_func()->invalidateBuffer(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();
+}
+
+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 = qt_widget_private(w)->isOpaque;
+
+ 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());
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ 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 {
+ if (HIViewGetNeedsDisplay(view)) {
+ q->update(valid_rect ? r : q->rect());
+ return;
+ }
+ HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height());
+ OSStatus err = HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy);
+ 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()));
+ HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy);
+ }
+ }
+# endif
+#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;
+ }
+ [view scrollRect:scrollRect by:NSMakeSize(dx, dy)];
+ // Yes, we potentially send a duplicate area, but I think Cocoa can handle it.
+ [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->wclass = 0;
+ extra->topextra->group = 0;
+ extra->topextra->windowIcon = 0;
+ extra->topextra->resizer = 0;
+ extra->topextra->isSetGeometry = 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;
+ }
+#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
+ NSView *view = qt_mac_nativeview_for(q);
+ if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) registerDragTypes:on];
+ }
+#endif
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ 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
+}
+
+extern "C" {
+ typedef struct CGSConnection *CGSConnectionRef;
+ typedef struct CGSWindow *CGSWindowRef;
+ extern OSStatus CGSSetWindowAlpha(CGSConnectionRef, CGSWindowRef, float);
+ extern CGSWindowRef GetNativeWindowFromWindowRef(WindowRef);
+ extern CGSConnectionRef _CGSDefaultConnection();
+}
+
+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;
+
+#if QT_MAC_USE_COCOA
+ OSWindowRef oswindow = qt_mac_window_for(q);
+ [oswindow setAlphaValue:level];
+#else
+ CGSSetWindowAlpha(_CGSDefaultConnection(),
+ GetNativeWindowFromWindowRef(qt_mac_window_for(q)), 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 && 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_nativeview_for(q) setNeedsDisplay:YES];
+}
+#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;
+#ifdef QT_RASTER_PAINTENGINE
+ if (!pe) {
+ if(qgetenv("QT_MAC_USE_COREGRAPHICS").isNull())
+ pe = new QRasterPaintEngine();
+ else
+ pe = new QCoreGraphicsPaintEngine();
+ }
+ if (pe->isActive()) {
+ QPaintEngine *engine =
+ qgetenv("QT_MAC_USE_COREGRAPHICS").isNull()
+ ? (QPaintEngine*)new QRasterPaintEngine() : (QPaintEngine*)new QCoreGraphicsPaintEngine();
+ engine->setAutoDestruct(true);
+ return engine;
+ }
+#else
+ if (!pe)
+ pe = new QCoreGraphicsPaintEngine();
+ if (pe->isActive()) {
+ QPaintEngine *engine = new QCoreGraphicsPaintEngine();
+ engine->setAutoDestruct(true);
+ return engine;
+ }
+#endif
+ 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
+ bool windowIsSheet = [windowRef styleMask] & NSDocModalWindowMask;
+
+ if (q->windowModality() == Qt::WindowModal){
+ // Window should be window-modal, which implies a sheet.
+ if (!windowIsSheet)
+ recreateMacWindow();
+ 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 {
+ // Window shold not be window-modal, and as such, not a sheet.
+ if (windowIsSheet){
+ // NB: the following call will call setModal_sys recursivly:
+ recreateMacWindow();
+ windowRef = qt_mac_window_for(q);
+ }
+ if (q->windowModality() == Qt::ApplicationModal) {
+ [windowRef setLevel:NSModalPanelWindowLevel];
+ } else if (primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) {
+ // INVARIANT: Our window is a dialog that has a dialog parent that is
+ // application modal, or . This means that q is supposed to be on top of this
+ // dialog and not be modally shaddowed:
+ [windowRef setLevel:NSModalPanelWindowLevel];
+ if ([windowRef isKindOfClass:[NSPanel class]])
+ [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
+ } else {
+ // INVARIANT: q should not be modal.
+ 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) {
+ winLevel = NSModalPanelWindowLevel;
+ }
+
+ // 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;
+ [windowRef setLevel:winLevel];
+ }
+ }
+
+#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 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 = qobject_cast<QMainWindowLayout *>(q->layout());
+ if (q->testAttribute(Qt::WA_MacBrushedMetal)) {
+ if (layout)
+ layout->updateHIToolBarStatus();
+ ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0);
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
+ ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0);
+ } else {
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
+ 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
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
new file mode 100644
index 0000000000..f254c4ac73
--- /dev/null
+++ b/src/gui/kernel/qwidget_p.h
@@ -0,0 +1,712 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGET_P_H
+#define QWIDGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qwidget.h"
+#include "private/qobject_p.h"
+#include "QtCore/qrect.h"
+#include "QtCore/qlocale.h"
+#include "QtGui/qregion.h"
+#include "QtGui/qsizepolicy.h"
+#include "QtGui/qstyle.h"
+
+#ifdef Q_WS_WIN
+#include "QtCore/qt_windows.h"
+#include <private/qdnd_p.h>
+#endif // Q_WS_WIN
+
+#ifdef Q_WS_X11
+#include "QtGui/qx11info_x11.h"
+#endif
+
+#ifdef Q_WS_MAC
+#include <private/qt_mac_p.h>
+#endif
+
+#if defined(Q_WS_QWS)
+#include "QtGui/qinputcontext.h"
+#include "QtGui/qscreen_qws.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// Extra QWidget data
+// - to minimize memory usage for members that are seldom used.
+// - top-level widgets have extra extra data to reduce cost further
+#if defined(Q_WS_QWS)
+class QWSManager;
+#endif
+#if defined(Q_WS_MAC)
+class QCoreGraphicsPaintEnginePrivate;
+#endif
+class QPaintEngine;
+class QPixmap;
+class QWidgetBackingStore;
+class QGraphicsProxyWidget;
+class QWidgetItemV2;
+
+class QStyle;
+
+struct QTLWExtra {
+ QString caption; // widget caption
+ QString iconText; // widget icon text
+ QString role; // widget role
+ QString filePath; // widget file path
+ QIcon *icon; // widget icon
+ QPixmap *iconPixmap;
+ short incw, inch; // size increments
+ // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead.
+ QRect frameStrut;
+ uint opacity : 8;
+ uint posFromMove : 1;
+ uint sizeAdjusted : 1;
+ uint inTopLevelResize : 1;
+ uint inRepaint : 1;
+ QWidgetBackingStore *backingStore;
+#if defined(Q_WS_WIN)
+ ulong savedFlags; // Save window flags while showing fullscreen
+ uint embedded : 1; // window is embedded in another application
+#else
+ Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
+#endif
+ short basew, baseh; // base sizes
+#if defined(Q_WS_X11)
+ WId parentWinId; // parent window Id (valid after reparenting)
+ uint embedded : 1; // window is embedded in another Qt application
+ uint spont_unmapped: 1; // window was spontaneously unmapped
+ uint dnd : 1; // DND properties installed
+ uint validWMState : 1; // is WM_STATE valid?
+ uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet
+ WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom
+ QPoint fullScreenOffset;
+#endif
+#if defined(Q_WS_MAC)
+ quint32 wattr;
+ quint32 wclass;
+ WindowGroupRef group;
+ IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys.
+ quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys()
+ uint resizer : 4;
+ uint isSetGeometry : 1;
+ uint isMove : 1;
+ uint embedded : 1;
+#endif
+#if defined(Q_WS_QWS) && !defined (QT_NO_QWS_MANAGER)
+ QWSManager *qwsManager;
+#endif
+#if defined(Q_WS_WIN)
+ HICON winIconBig; // internal big Windows icon
+ HICON winIconSmall; // internal small Windows icon
+#endif
+ QRect normalGeometry; // used by showMin/maximized/FullScreen
+ QWindowSurface *windowSurface;
+ QPainter *sharedPainter;
+};
+
+struct QWExtra {
+ qint32 minw, minh; // minimum size
+ qint32 maxw, maxh; // maximum size
+ QPointer<QWidget> focus_proxy;
+#ifndef QT_NO_CURSOR
+ QCursor *curs;
+#endif
+ QTLWExtra *topextra; // only useful for TLWs
+ QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
+ void *glContext; // if the widget is hijacked by QGLWindowSurface
+#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
+ QOleDropTarget *dropTarget; // drop target
+ QList<QPointer<QWidget> > oleDropWidgets;
+#endif
+#if defined(Q_WS_X11)
+ WId xDndProxy; // XDND forwarding to embedded windows
+#endif
+ QRegion mask; // widget mask
+ QSize staticContentsSize;
+
+//bit flags at the end to improve packing
+#if defined(Q_WS_WIN)
+ uint shown_mode : 8; // widget show mode
+#ifndef QT_NO_DIRECT3D
+ uint had_paint_on_screen : 1;
+ uint had_no_system_bg : 1;
+ uint had_auto_fill_bg : 1;
+#endif
+#endif
+#if defined(Q_WS_X11)
+ uint compress_events : 1;
+#endif
+ uint explicitMinSize : 2;
+ uint explicitMaxSize : 2;
+ uint autoFillBackground : 1;
+ uint nativeChildrenForced : 1;
+ uint inRenderWithPainter : 1;
+ uint hasMask : 1;
+
+ QPointer<QStyle> style;
+ QString styleSheet;
+
+ quint16 customDpiX;
+ quint16 customDpiY;
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ // Cocoa Mask stuff
+ QImage maskBits;
+ CGImageRef imageMask;
+#endif
+};
+
+class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QWidget)
+
+public:
+ explicit QWidgetPrivate(int version = QObjectPrivateVersion);
+ ~QWidgetPrivate();
+
+ QWExtra *extraData() const;
+ QTLWExtra *topData() const;
+ QTLWExtra *maybeTopData() const;
+ QPainter *sharedPainter() const;
+ void setSharedPainter(QPainter *painter);
+ QWidgetBackingStore *maybeBackingStore() const;
+#ifdef Q_WS_QWS
+ void setMaxWindowState_helper();
+ void setFullScreenSize_helper();
+#endif
+ void init(QWidget *desktopWidget, Qt::WindowFlags f);
+ void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
+ void createRecursively();
+ void createWinId(WId id = 0);
+
+ void createTLExtra();
+ void createExtra();
+ void deleteExtra();
+ void createSysExtra();
+ void deleteSysExtra();
+ void createTLSysExtra();
+ void deleteTLSysExtra();
+ void updateSystemBackground();
+ void propagatePaletteChange();
+
+ void setPalette_helper(const QPalette &);
+ void resolvePalette();
+ QPalette naturalWidgetPalette(uint inheritedMask) const;
+
+ void setMask_sys(const QRegion &);
+#ifdef Q_WS_WIN
+ bool shouldShowMaximizeButton();
+ void winUpdateIsOpaque();
+#endif
+
+#ifdef Q_WS_MAC
+ void macUpdateSizeAttribute();
+ void macUpdateHideOnSuspend();
+ void macUpdateOpaqueSizeGrip();
+ void macUpdateIgnoreMouseEvents();
+ void macUpdateMetalAttribute();
+ void macUpdateIsOpaque();
+ void setEnabled_helper_sys(bool enable);
+ bool isRealWindow() const;
+#endif
+
+ void raise_sys();
+ void lower_sys();
+ void stackUnder_sys(QWidget *);
+
+ void setFocus_sys();
+
+ void updateFont(const QFont &);
+ inline void setFont_helper(const QFont &font) {
+ if (data.fnt == font && data.fnt.resolve() == font.resolve())
+ return;
+ updateFont(font);
+ }
+ void resolveFont();
+ QFont naturalWidgetFont(uint inheritedMask) const;
+
+ void setLayoutDirection_helper(Qt::LayoutDirection);
+ void resolveLayoutDirection();
+
+ void setLocale_helper(const QLocale &l, bool forceUpdate = false);
+ void resolveLocale();
+
+ void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false);
+ void inheritStyle();
+
+ bool isBackgroundInherited() const;
+
+ void setUpdatesEnabled_helper(bool );
+
+ void paintBackground(QPainter *, const QRegion &, const QPoint & = QPoint(), int flags = DrawAsRoot) const;
+ enum DrawWidgetFlags {
+ DrawAsRoot = 0x01,
+ DrawPaintOnScreen = 0x02,
+ DrawRecursive = 0x04,
+ DrawInvisible = 0x08,
+ DontSubtractOpaqueChildren = 0x10,
+ DontSetCompositionMode = 0x20,
+ DontDrawOpaqueChildren = 0x40
+ };
+ bool isAboutToShow() const;
+ QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
+ void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
+ QWidget::RenderFlags renderFlags);
+ void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
+ QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
+
+
+ void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index,
+ const QRegion &rgn, const QPoint &offset, int flags
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ , const QWindowSurface *currentSurface
+#endif
+ , QPainter *sharedPainter, QWidgetBackingStore *backingStore);
+
+
+ QPainter *beginSharedPainter();
+ bool endSharedPainter();
+ static QGraphicsProxyWidget * nearestGraphicsProxyWidget(QWidget *origin);
+ QWindowSurface *createDefaultWindowSurface();
+ QWindowSurface *createDefaultWindowSurface_sys();
+ void repaint_sys(const QRegion &rgn);
+#ifdef Q_WS_MAC
+ void update_sys(const QRect &rect);
+ void update_sys(const QRegion &rgn);
+#endif
+
+ QRect clipRect() const;
+ QRegion clipRegion() const;
+ void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
+ void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
+ bool alsoNonOpaque = false) const;
+ void clipToEffectiveMask(QRegion &region) const;
+ void updateIsOpaque();
+ void setOpaque(bool opaque);
+ void updateIsTranslucent();
+ bool hasBackground() const;
+ bool paintOnScreen() const;
+
+ QRegion getOpaqueRegion() const;
+ const QRegion &getOpaqueChildren() const;
+ void setDirtyOpaqueRegion();
+
+ QRegion opaqueChildren;
+
+ enum CloseMode {
+ CloseNoEvent,
+ CloseWithEvent,
+ CloseWithSpontaneousEvent
+ };
+ bool close_helper(CloseMode mode);
+
+ bool compositeEvent(QEvent *e);
+ void setWindowIcon_helper();
+ void setWindowIcon_sys(bool forceReset = false);
+ void setWindowOpacity_sys(qreal opacity);
+
+ void focusInputContext();
+
+ void adjustQuitOnCloseAttribute();
+
+#if defined(Q_WS_X11)
+ void setWindowRole();
+ void sendStartupMessage(const char *message) const;
+ void setNetWmWindowTypes();
+ void x11UpdateIsOpaque();
+#endif
+
+#if defined (Q_WS_WIN)
+ void reparentChildren();
+#endif
+
+ void scrollChildren(int dx, int dy);
+
+ void moveRect(const QRect &, int dx, int dy);
+ void scrollRect(const QRect &, int dx, int dy);
+ void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
+ // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+ void invalidateBuffer(const QRegion &);
+ void invalidateBuffer(const QRect &);
+ bool isOverlapped(const QRect&) const;
+ void syncBackingStore();
+ void syncBackingStore(const QRegion &region);
+
+ void reparentFocusWidgets(QWidget *oldtlw);
+
+ static int pointToRect(const QPoint &p, const QRect &r);
+ QRect fromOrToLayoutItemRect(const QRect &rect, int sign) const;
+
+ void setWinId(WId);
+ void showChildren(bool spontaneous);
+ void hideChildren(bool spontaneous);
+ void setParent_sys(QWidget *parent, Qt::WindowFlags);
+ void scroll_sys(int dx, int dy);
+ void scroll_sys(int dx, int dy, const QRect &r);
+ void deactivateWidgetCleanup();
+ void setGeometry_sys(int, int, int, int, bool);
+#ifdef Q_WS_MAC
+ void setGeometry_sys_helper(int, int, int, int, bool);
+#endif
+ void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false);
+ void activateChildLayoutsRecursively();
+ void show_recursive();
+ void show_helper();
+ void show_sys();
+ void hide_sys();
+ void hide_helper();
+ void _q_showIfNotHidden();
+
+ void setEnabled_helper(bool);
+ void registerDropSite(bool);
+#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
+ QOleDropTarget *registerOleDnd(QWidget *widget);
+ void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
+#endif
+ static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0);
+
+ void updateFrameStrut();
+ QRect frameStrut() const;
+
+ void setWindowIconText_sys(const QString &cap);
+ void setWindowIconText_helper(const QString &cap);
+ void setWindowTitle_sys(const QString &cap);
+
+#ifdef Q_OS_WIN
+ void grabMouseWhileInWindow();
+#endif
+
+#ifndef QT_NO_CURSOR
+ void setCursor_sys(const QCursor &cursor);
+ void unsetCursor_sys();
+#endif
+
+#ifdef Q_WS_MAC
+ void setWindowModified_sys(bool b);
+ void updateMaximizeButton_sys();
+ void setWindowFilePath_sys(const QString &filePath);
+ void createWindow_sys();
+ void recreateMacWindow();
+#ifndef QT_MAC_USE_COCOA
+ void initWindowPtr();
+ void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
+#else
+ void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
+ void syncCocoaMask();
+ void finishCocoaMaskSetup();
+#endif
+ void determineWindowClass();
+ void transferChildren();
+#endif
+ void setWindowTitle_helper(const QString &cap);
+ void setWindowFilePath_helper(const QString &filePath);
+
+ bool setMinimumSize_helper(int &minw, int &minh);
+ bool setMaximumSize_helper(int &maxw, int &maxh);
+ void setConstraints_sys();
+ QWidget *childAt_helper(const QPoint &, bool) const;
+ void updateGeometry_helper(bool forceUpdate);
+
+ void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const;
+ void setLayoutItemMargins(int left, int top, int right, int bottom);
+ void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
+
+ QInputContext *inputContext() const;
+
+#if defined(Q_WS_QWS)
+ void moveSurface(QWindowSurface *surface, const QPoint &offset);
+
+ QRegion localRequestedRegion() const;
+ QRegion localAllocatedRegion() const;
+
+ void blitToScreen(const QRegion &globalrgn);
+#ifndef QT_NO_CURSOR
+ void updateCursor() const;
+#endif
+
+ QScreen* getScreen() const;
+
+ friend class QWSManager;
+ friend class QWSManagerPrivate;
+ friend class QDecoration;
+#endif
+
+ static int instanceCounter; // Current number of widget instances
+ static int maxInstances; // Maximum number of widget instances
+
+#ifdef QT_KEYPAD_NAVIGATION
+ static QPointer<QWidget> editingWidget;
+#endif
+
+ QWidgetData data;
+
+ QWExtra *extra;
+ QWidget *focus_next;
+ QWidget *focus_prev;
+ QWidget *focus_child;
+#ifndef QT_NO_ACTION
+ QList<QAction*> actions;
+#endif
+ QLayout *layout;
+ QWidgetItemV2 *widgetItem;
+#if !defined(QT_NO_IM)
+ QPointer<QInputContext> ic;
+#endif
+ // All widgets are initially added into the uncreatedWidgets set. Once
+ // they receive a window id they are removed and added to the mapper
+ static QWidgetMapper *mapper;
+ static QWidgetSet *uncreatedWidgets;
+
+ short leftmargin, topmargin, rightmargin, bottommargin;
+
+ signed char leftLayoutItemMargin;
+ signed char topLayoutItemMargin;
+ signed char rightLayoutItemMargin;
+ signed char bottomLayoutItemMargin;
+
+ // ### TODO: reorganize private/extra/topextra to save memory
+ QPointer<QWidget> compositeChildGrab;
+#ifndef QT_NO_TOOLTIP
+ QString toolTip;
+#endif
+#ifndef QT_NO_STATUSTIP
+ QString statusTip;
+#endif
+#ifndef QT_NO_WHATSTHIS
+ QString whatsThis;
+#endif
+ QString accessibleName, accessibleDescription;
+
+ QPalette::ColorRole fg_role : 8;
+ QPalette::ColorRole bg_role : 8;
+ uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
+ Qt::HANDLE hd;
+ QRegion dirty;
+ QRegion *needsFlush;
+ uint dirtyOpaqueChildren : 1;
+ uint isOpaque : 1;
+ uint inDirtyList : 1;
+ uint isScrolled : 1;
+ uint isMoved : 1;
+
+#ifdef Q_WS_WIN
+ uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
+#endif
+
+ uint inheritedFontResolveMask;
+ uint inheritedPaletteResolveMask;
+#if defined(Q_WS_X11)
+ QX11Info xinfo;
+ Qt::HANDLE picture;
+#endif
+#if defined(Q_WS_MAC)
+ enum PaintChildrenOPs {
+ PC_None = 0x00,
+ PC_Now = 0x01,
+ PC_NoPaint = 0x04,
+ PC_Later = 0x10
+ };
+ EventHandlerRef window_event;
+ bool qt_mac_dnd_event(uint, DragRef);
+ void toggleDrawers(bool);
+ //mac event functions
+ static bool qt_create_root_win();
+ static void qt_clean_root_win();
+ static bool qt_recreate_root_win();
+ static bool qt_mac_update_sizer(QWidget *, int up = 0);
+ static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
+ static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
+ static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
+ static bool qt_widget_shape(QWidget *, short, HIMutableShapeRef, bool);
+
+ // Each wiget keeps a list of all its child and grandchild OpenGL widgets.
+ // This list is used to update the gl context whenever a parent and a granparent
+ // moves, and also to check for intersections with gl widgets within the window
+ // when a widget moves.
+ struct GlWidgetInfo
+ {
+ GlWidgetInfo(QWidget *widget) : widget(widget), lastUpdateWidget(0) { }
+ bool operator==(const GlWidgetInfo &other) const { return (widget == other.widget); }
+ QWidget * widget;
+ QWidget * lastUpdateWidget;
+ };
+ QList<GlWidgetInfo> glWidgets;
+
+ // dirtyOnWidget contains the areas in the widget that needs to be repained,
+ // in the same way as dirtyOnScreen does for the window. Areas are added in
+ // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use
+ // this information repaint invalid areas when widgets are scrolled.
+ QRegion dirtyOnWidget;
+
+ //these are here just for code compat (HIViews)
+ Qt::HANDLE qd_hd;
+
+ // This is new stuff
+ uint needWindowChange : 1;
+ uint isGLWidget : 1;
+#endif
+
+#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC)
+#ifdef Q_WS_MAC
+ void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());
+#else
+ void setWSGeometry(bool dontShow=false);
+#endif
+
+ inline QPoint mapToWS(const QPoint &p) const
+ { return p - data.wrect.topLeft(); }
+
+ inline QPoint mapFromWS(const QPoint &p) const
+ { return p + data.wrect.topLeft(); }
+
+ inline QRect mapToWS(const QRect &r) const
+ { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; }
+
+ inline QRect mapFromWS(const QRect &r) const
+ { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+#endif
+
+ QPaintEngine *extraPaintEngine;
+
+ mutable const QMetaObject *polished;
+
+ void setModal_sys();
+ QSizePolicy size_policy;
+ QLocale locale;
+
+#ifdef Q_WS_X11
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+#endif
+ QPaintDevice *redirectDev;
+ QPoint redirectOffset;
+
+ inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
+ {
+ Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
+ redirectDev = replacement;
+ redirectOffset = offset;
+ }
+
+ inline QPaintDevice *redirected(QPoint *offset) const
+ {
+ if (offset)
+ *offset = redirectDev ? redirectOffset : QPoint();
+ return redirectDev;
+ }
+
+ inline void restoreRedirected()
+ { redirectDev = 0; }
+
+ inline void enforceNativeChildren()
+ {
+ if (!extra)
+ createExtra();
+
+ if (extra->nativeChildrenForced)
+ return;
+ extra->nativeChildrenForced = 1;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
+ child->setAttribute(Qt::WA_NativeWindow);
+ }
+ }
+
+ inline bool nativeChildrenForced() const
+ {
+ return extra ? extra->nativeChildrenForced : false;
+ }
+
+ QSize adjustedSize() const;
+};
+
+inline QWExtra *QWidgetPrivate::extraData() const
+{
+ return extra;
+}
+
+inline QTLWExtra *QWidgetPrivate::topData() const
+{
+ const_cast<QWidgetPrivate *>(this)->createTLExtra();
+ return extra->topextra;
+}
+
+inline QTLWExtra *QWidgetPrivate::maybeTopData() const
+{
+ return extra ? extra->topextra : 0;
+}
+
+inline QPainter *QWidgetPrivate::sharedPainter() const
+{
+ Q_Q(const QWidget);
+ QTLWExtra *x = q->window()->d_func()->maybeTopData();
+ return x ? x->sharedPainter : 0;
+}
+
+inline void QWidgetPrivate::setSharedPainter(QPainter *painter)
+{
+ Q_Q(QWidget);
+ QTLWExtra *x = q->window()->d_func()->topData();
+ x->sharedPainter = painter;
+}
+
+inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
+{
+ Q_Q(const QWidget);
+ QTLWExtra *x = q->window()->d_func()->maybeTopData();
+ return x ? x->backingStore : 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // QWIDGET_P_H
diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp
new file mode 100644
index 0000000000..1445f57ae4
--- /dev/null
+++ b/src/gui/kernel/qwidget_qws.cpp
@@ -0,0 +1,1198 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcursor.h"
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qpainter.h"
+#include "qbitmap.h"
+#include "qimage.h"
+#include "qhash.h"
+#include "qstack.h"
+#include "qlayout.h"
+#include "qtextcodec.h"
+#include "qinputcontext.h"
+#include "qdesktopwidget.h"
+
+#include "qwsdisplay_qws.h"
+#include "private/qwsdisplay_qws_p.h"
+#include "qscreen_qws.h"
+#include "qwsmanager_qws.h"
+#include <private/qwsmanager_p.h>
+#include <private/qbackingstore_p.h>
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qwslock_p.h>
+#include "qpaintengine.h"
+
+#include "qdebug.h"
+
+#include "qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+extern int *qt_last_x;
+extern int *qt_last_y;
+extern WId qt_last_cursor;
+extern bool qws_overrideCursor;
+extern QWidget *qt_pressGrab;
+extern QWidget *qt_mouseGrb;
+
+static QWidget *keyboardGrb = 0;
+
+static int takeLocalId()
+{
+ static int n=-1000;
+ return --n;
+}
+
+class QWSServer;
+extern QWSServer *qwsServer;
+
+static inline bool isServerProcess()
+{
+ return (qwsServer != 0);
+}
+
+/*****************************************************************************
+ QWidget member functions
+ *****************************************************************************/
+
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destroyOldWindow*/)
+{
+ Q_Q(QWidget);
+ Qt::WindowType type = q->windowType();
+
+ // Make sure the WindowTitleHint is on if any of the title bar hints are set
+ // Note: This might be moved to cross-platform QWidgetPrivate::adjustFlags()
+ if ( !(data.window_flags & Qt::CustomizeWindowHint) && (
+ (data.window_flags & Qt::WindowSystemMenuHint) ||
+ (data.window_flags & Qt::WindowContextHelpButtonHint) ||
+ (data.window_flags & Qt::WindowMinimizeButtonHint) ||
+ (data.window_flags & Qt::WindowMaximizeButtonHint) ||
+ (data.window_flags & Qt::WindowCloseButtonHint) ) ) {
+ data.window_flags |= Qt::WindowTitleHint;
+ }
+
+ // Decoration plugins on QWS don't support switching on the close button on its own
+ if (data.window_flags & Qt::WindowCloseButtonHint)
+ data.window_flags |= Qt::WindowSystemMenuHint;
+
+ Qt::WindowFlags flags = data.window_flags;
+
+ data.alloc_region_index = -1;
+
+ // we don't have a "Drawer" window type
+ if (type == Qt::Drawer) {
+ type = Qt::Widget;
+ flags &= ~Qt::WindowType_Mask;
+ }
+
+
+ bool topLevel = (flags & Qt::Window);
+ bool popup = (type == Qt::Popup);
+ bool dialog = (type == Qt::Dialog
+ || type == Qt::Sheet
+ || (flags & Qt::MSWindowsFixedSizeDialogHint));
+ bool desktop = (type == Qt::Desktop);
+ bool tool = (type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip);
+
+
+#ifndef QT_NO_WARNING_OUTPUT
+ static bool toolWarningShown = false;
+ if (!toolWarningShown && type == Qt::Tool && !(flags & Qt::FramelessWindowHint)) {
+ qWarning("Qt for Embedded Linux " QT_VERSION_STR " does not support tool windows with frames.\n"
+ "This behavior will change in a later release. To ensure compatibility with\n"
+ "future versions, use (Qt::Tool | Qt::FramelessWindowHint).");
+ toolWarningShown = true;
+ }
+#endif
+
+ WId id;
+ QWSDisplay* dpy = QWidget::qwsDisplay();
+
+ if (!window) // always initialize
+ initializeWindow = true;
+
+ // use the size of the primary screen to determine the default window size
+ QList<QScreen *> screens = qt_screen->subScreens();
+ if (screens.isEmpty())
+ screens.append(qt_screen);
+ int sw = screens[0]->width();
+ int sh = screens[0]->height();
+
+ if (desktop) { // desktop widget
+ dialog = popup = false; // force these flags off
+ data.crect.setRect(0, 0, sw, sh);
+ } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
+ int width = sw / 2;
+ int height = 4 * sh / 10;
+ if (extra) {
+ width = qMax(qMin(width, extra->maxw), extra->minw);
+ height = qMax(qMin(height, extra->maxh), extra->minh);
+ }
+ data.crect.setSize(QSize(width, height));
+ }
+
+ if (window) { // override the old window
+ id = window;
+ setWinId(window);
+ } else if (desktop) { // desktop widget
+ id = (WId)-2; // id = root window
+#if 0
+ QWidget *otherDesktop = q->find(id); // is there another desktop?
+ if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
+ otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
+ setWinId(id); // make sure otherDesktop is
+ otherDesktop->d_func()->setWinId(id); // found first
+ } else
+#endif
+ {
+ setWinId(id);
+ }
+ } else {
+ id = topLevel ? dpy->takeId() : takeLocalId();
+ setWinId(id); // set widget id/handle + hd
+ }
+
+
+ bool hasFrame = true;
+ if (topLevel) {
+ if (desktop || popup || tool || q->testAttribute(Qt::WA_DontShowOnScreen))
+ hasFrame = false;
+ else
+ hasFrame = !(flags & Qt::FramelessWindowHint);
+ }
+ if (desktop) {
+ q->setAttribute(Qt::WA_WState_Visible);
+ } else if (topLevel) { // set X cursor
+ //QCursor *oc = QApplication::overrideCursor();
+ if (initializeWindow) {
+ //XXX XDefineCursor(dpy, winid, oc ? oc->handle() : cursor().handle());
+ }
+ QWidget::qwsDisplay()->nameRegion(q->internalWinId(), q->objectName(), q->windowTitle());
+ }
+
+ if (topLevel) {
+ createTLExtra();
+ QTLWExtra *topextra = extra->topextra;
+#ifndef QT_NO_QWS_MANAGER
+ if (hasFrame) {
+ // get size of wm decoration and make the old crect the new frect
+ QRect cr = data.crect;
+ QRegion r = QApplication::qwsDecoration().region(q, cr) | cr;
+ QRect br(r.boundingRect());
+ topextra->frameStrut.setCoords(cr.x() - br.x(),
+ cr.y() - br.y(),
+ br.right() - cr.right(),
+ br.bottom() - cr.bottom());
+ if (!q->testAttribute(Qt::WA_Moved) || topextra->posFromMove)
+ data.crect.translate(topextra->frameStrut.left(), topextra->frameStrut.top());
+ if (!topData()->qwsManager) {
+ topData()->qwsManager = new QWSManager(q);
+ if((q->data->window_state & ~Qt::WindowActive) == Qt::WindowMaximized)
+ topData()->qwsManager->maximize();
+ }
+
+ } else if (topData()->qwsManager) {
+ delete topData()->qwsManager;
+ topData()->qwsManager = 0;
+ data.crect.translate(-topextra->frameStrut.left(), -topextra->frameStrut.top());
+ topextra->frameStrut.setCoords(0, 0, 0, 0);
+ }
+#endif
+ if (!topextra->caption.isEmpty())
+ setWindowTitle_helper(topextra->caption);
+
+ //XXX If we are session managed, inform the window manager about it
+ } else {
+ if (extra && extra->topextra) { // already allocated due to reparent?
+ extra->topextra->frameStrut.setCoords(0, 0, 0, 0);
+ }
+ //updateRequestedRegion(mapToGlobal(QPoint(0,0)));
+ }
+}
+
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(geometry());
+
+ d->deactivateWidgetCleanup();
+ if (testAttribute(Qt::WA_WState_Created)) {
+ setAttribute(Qt::WA_WState_Created, false);
+ QObjectList childObjects = children();
+ for (int i = 0; i < childObjects.size(); ++i) {
+ QObject *obj = childObjects.at(i);
+ if (obj->isWidgetType())
+ static_cast<QWidget*>(obj)->destroy(destroySubWindows,
+ destroySubWindows);
+ }
+ releaseMouse();
+ if (qt_pressGrab == this)
+ qt_pressGrab = 0;
+
+ if (keyboardGrb == 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 (d->ic) {
+ delete d->ic;
+ d->ic =0;
+ } else {
+ // release previous focus information participating with
+ // preedit preservation of qic -- while we still have a winId
+ QInputContext *qic = inputContext();
+ if (qic)
+ qic->widgetDestroyed(this);
+ }
+
+ if ((windowType() == Qt::Desktop)) {
+ } else {
+ if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
+ d->hide_sys();
+ }
+ if (destroyWindow && isWindow()) {
+ d->extra->topextra->backingStore->windowSurface->setGeometry(QRect());
+ qwsDisplay()->destroyRegion(internalWinId());
+ }
+ }
+ d->setWinId(0);
+ }
+}
+
+
+void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+ if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
+ q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+#ifndef QT_NO_CURSOR
+ QCursor oldcurs;
+ bool setcurs=q->testAttribute(Qt::WA_SetCursor);
+ if (setcurs) {
+ oldcurs = q->cursor();
+ q->unsetCursor();
+ }
+#endif
+
+ WId old_winid = data.winid;
+ if ((q->windowType() == Qt::Desktop))
+ old_winid = 0;
+
+ if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_WState_Created))
+ hide_sys();
+
+ setWinId(0);
+
+ if (parent != newparent) {
+ QWidget *oldparent = q->parentWidget();
+ QObjectPrivate::setParent_helper(newparent);
+ if (oldparent) {
+// oldparent->d_func()->setChildrenAllocatedDirty();
+// oldparent->data->paintable_region_dirty = true;
+ }
+ if (newparent) {
+// newparent->d_func()->setChildrenAllocatedDirty();
+// newparent->data->paintable_region_dirty = true;
+ //@@@@@@@
+ }
+ }
+ Qt::FocusPolicy fp = q->focusPolicy();
+ QSize s = q->size();
+ //QBrush bgc = background(); // save colors
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ 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)
+ if (wasCreated || (!q->isWindow() && newparent->testAttribute(Qt::WA_WState_Created)))
+ createWinId();
+ if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ if (q->isWindow()) {
+ QRect fs = frameStrut();
+ data.crect = QRect(fs.left(), fs.top(), s.width(), s.height());
+ if ((data.window_flags & Qt::FramelessWindowHint) && extra && extra->topextra)
+ extra->topextra->frameStrut.setCoords(0, 0, 0, 0);
+ } else {
+ data.crect = QRect(0, 0, s.width(), s.height());
+ }
+
+ q->setFocusPolicy(fp);
+ if (extra && !extra->mask.isEmpty()) {
+ QRegion r = extra->mask;
+ extra->mask = QRegion();
+ q->setMask(r);
+ }
+ if ((int)old_winid > 0) {
+ QWidget::qwsDisplay()->destroyRegion(old_winid);
+ extra->topextra->backingStore->windowSurface->setGeometry(QRect());
+ }
+#ifndef QT_NO_CURSOR
+ if (setcurs) {
+ q->setCursor(oldcurs);
+ }
+#endif
+}
+
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ int x=pos.x(), y=pos.y();
+ const QWidget* w = this;
+ while (w) {
+ x += w->data->crect.x();
+ y += w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ int x=pos.x(), y=pos.y();
+ const QWidget* w = this;
+ while (w) {
+ x -= w->data->crect.x();
+ y -= w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+#if 0 // #####
+void QWidget::setMicroFocusHint(int x, int y, int width, int height,
+ bool text, QFont *)
+{
+ if (QRect(x, y, width, height) != microFocusHint()) {
+ d->createExtra();
+ d->extra->micro_focus_hint.setRect(x, y, width, height);
+ }
+#ifndef QT_NO_QWS_INPUTMETHODS
+ if (text) {
+ QWidget *tlw = window();
+ int winid = tlw->internalWinId();
+ QPoint p(x, y + height);
+ QPoint gp = mapToGlobal(p);
+
+ QRect r = QRect(mapToGlobal(QPoint(0,0)),
+ size());
+
+ r.setBottom(tlw->geometry().bottom());
+
+ //qDebug("QWidget::setMicroFocusHint %d %d %d %d", r.x(),
+ // r.y(), r.width(), r.height());
+ QInputContext::setMicroFocusWidget(this);
+
+ qwsDisplay()->setIMInfo(winid, gp.x(), gp.y(), r);
+
+ //send font info, ###if necessary
+ qwsDisplay()->setInputFont(winid, font());
+ }
+#endif
+}
+#endif
+
+void QWidgetPrivate::updateSystemBackground() {}
+
+#ifndef QT_NO_CURSOR
+void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+ Q_Q(QWidget);
+ if (q->isVisible())
+ updateCursor();
+}
+
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ if (q->isVisible())
+ updateCursor();
+}
+#endif //QT_NO_CURSOR
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ QWidget::qwsDisplay()->setWindowCaption(q, caption);
+}
+
+void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/)
+{
+#if 0
+ QTLWExtra* x = d->topData();
+ delete x->icon;
+ x->icon = 0;
+ QBitmap mask;
+ if (unscaledPixmap.isNull()) {
+ } else {
+ QImage unscaledIcon = unscaledPixmap.toImage();
+ QPixmap pixmap =
+ QPixmap::fromImage(unscaledIcon.scale(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ x->icon = new QPixmap(pixmap);
+ mask = pixmap.mask() ? *pixmap.mask() : pixmap.createHeuristicMask();
+ }
+#endif
+}
+
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_UNUSED(iconText);
+}
+
+void QWidget::grabMouse()
+{
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ qwsDisplay()->grabMouse(this,true);
+
+ qt_mouseGrb = this;
+ qt_pressGrab = 0;
+}
+
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ qwsDisplay()->grabMouse(this,true);
+ qwsDisplay()->selectCursor(this, cursor.handle());
+ qt_mouseGrb = this;
+ qt_pressGrab = 0;
+}
+#endif
+
+void QWidget::releaseMouse()
+{
+ if (qt_mouseGrb == this) {
+ qwsDisplay()->grabMouse(this,false);
+ qt_mouseGrb = 0;
+ }
+}
+
+void QWidget::grabKeyboard()
+{
+ if (keyboardGrb)
+ keyboardGrb->releaseKeyboard();
+ qwsDisplay()->grabKeyboard(this, true);
+ keyboardGrb = this;
+}
+
+void QWidget::releaseKeyboard()
+{
+ if (keyboardGrb == this) {
+ qwsDisplay()->grabKeyboard(this, false);
+ keyboardGrb = 0;
+ }
+}
+
+
+QWidget *QWidget::mouseGrabber()
+{
+ if (qt_mouseGrb)
+ return qt_mouseGrb;
+ return qt_pressGrab;
+}
+
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
+
+void QWidget::activateWindow()
+{
+ QWidget *tlw = window();
+ if (tlw->isVisible()) {
+ Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created));
+ qwsDisplay()->requestFocus(tlw->internalWinId(), true);
+ }
+}
+
+/*
+ Should we require that q is a toplevel window ???
+
+ Used by QWSManager
+ */
+void QWidgetPrivate::blitToScreen(const QRegion &globalrgn)
+{
+ Q_Q(QWidget);
+ QWidget *win = q->window();
+ QBrush bgBrush = win->palette().brush(win->backgroundRole());
+ bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque();
+ QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn);
+}
+
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+ if (q->isWindow()) {
+
+ if (QWindowSurface *surface = q->windowSurface()) {
+ const QRect frameRect = q->frameGeometry();
+ if (surface->geometry() != frameRect)
+ surface->setGeometry(frameRect);
+ }
+
+ QRegion r = localRequestedRegion();
+#ifndef QT_NO_QWS_MANAGER
+ if (extra && extra->topextra && extra->topextra->qwsManager) {
+ r.translate(data.crect.topLeft());
+ r += extra->topextra->qwsManager->region();
+ r.translate(-data.crect.topLeft());
+ }
+#endif
+ data.fstrut_dirty = true;
+ invalidateBuffer(r);
+ if (!q->testAttribute(Qt::WA_ShowWithoutActivating)
+ && q->windowType() != Qt::Popup
+ && q->windowType() != Qt::Tool
+ && q->windowType() != Qt::ToolTip) {
+ QWidget::qwsDisplay()->requestFocus(data.winid,true);
+ }
+ bool staysontop =
+ (q->windowFlags() & Qt::WindowStaysOnTopHint)
+ || q->windowType() == Qt::Popup;
+ if (!staysontop && q->parentWidget()) { // if our parent stays on top, so must we
+ QWidget *ptl = q->parentWidget()->window();
+ if (ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
+ staysontop = true;
+ }
+
+ QWSChangeAltitudeCommand::Altitude altitude;
+ altitude = staysontop ? QWSChangeAltitudeCommand::StaysOnTop : QWSChangeAltitudeCommand::Raise;
+ QWidget::qwsDisplay()->setAltitude(data.winid, altitude, true);
+ if (!q->objectName().isEmpty()) {
+ QWidget::qwsDisplay()->setWindowCaption(q, q->windowTitle());
+ }
+ }
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ else if ( extra && extra->topextra && extra->topextra->windowSurface) {
+ QWSWindowSurface *surface;
+ surface = static_cast<QWSWindowSurface*>(q->windowSurface());
+ const QPoint p = q->mapToGlobal(QPoint());
+ surface->setGeometry(QRect(p, q->size()));
+ }
+#endif
+
+ if (!q->window()->data->in_show) {
+ invalidateBuffer(q->rect());
+ }
+}
+
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ deactivateWidgetCleanup();
+
+ if (q->isWindow()) {
+ q->releaseMouse();
+// requestWindowRegion(QRegion());
+
+ extra->topextra->backingStore->releaseBuffer();
+
+
+ QWidget::qwsDisplay()->requestFocus(data.winid,false);
+ } else {
+ QWidget *p = q->parentWidget();
+ if (p &&p->isVisible()) {
+ invalidateBuffer(q->rect());
+ }
+ }
+}
+
+
+
+static Qt::WindowStates effectiveState(Qt::WindowStates state)
+ {
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+ }
+
+void QWidgetPrivate::setMaxWindowState_helper()
+{
+ // in_set_window_state is usually set in setWindowState(), but this
+ // function is used in other functions as well
+ // (e.g QApplicationPrivate::setMaxWindowRect())
+ const uint old_state = data.in_set_window_state;
+ data.in_set_window_state = 1;
+
+#ifndef QT_NO_QWS_MANAGER
+ if (extra && extra->topextra && extra->topextra->qwsManager)
+ extra->topextra->qwsManager->maximize();
+ else
+#endif
+ {
+ Q_Q(QWidget);
+ const QDesktopWidget *desktop = QApplication::desktop();
+ const int screen = desktop->screenNumber(q);
+ const QRect maxWindowRect = desktop->availableGeometry(screen);
+ q->setGeometry(maxWindowRect);
+ }
+ data.in_set_window_state = old_state;
+}
+
+void QWidgetPrivate::setFullScreenSize_helper()
+{
+ Q_Q(QWidget);
+
+ const uint old_state = data.in_set_window_state;
+ data.in_set_window_state = 1;
+
+ const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q));
+ q->move(screen.topLeft());
+ q->resize(screen.size());
+
+ data.in_set_window_state = old_state;
+}
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+ if (isWindow() && !testAttribute(Qt::WA_WState_Created))
+ create();
+
+ data->window_state = newstate;
+ data->in_set_window_state = 1;
+ bool needShow = false;
+ Qt::WindowStates newEffectiveState = effectiveState(newstate);
+ Qt::WindowStates oldEffectiveState = effectiveState(oldstate);
+ if (isWindow() && newEffectiveState != oldEffectiveState) {
+ d->createTLExtra();
+ if (oldEffectiveState == Qt::WindowNoState) { //normal
+ d->topData()->normalGeometry = geometry();
+ } else if (oldEffectiveState == Qt::WindowFullScreen) {
+ setParent(0, d->topData()->savedFlags);
+ needShow = true;
+ } else if (oldEffectiveState == Qt::WindowMinimized) {
+ needShow = true;
+ }
+
+ if (newEffectiveState == Qt::WindowMinimized) {
+ //### not ideal...
+ hide();
+ needShow = false;
+ } else if (newEffectiveState == Qt::WindowFullScreen) {
+ d->topData()->savedFlags = windowFlags();
+ setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
+ d->setFullScreenSize_helper();
+ raise();
+ needShow = true;
+ } else if (newEffectiveState == Qt::WindowMaximized) {
+ createWinId();
+ d->setMaxWindowState_helper();
+ } else { //normal
+ QRect r = d->topData()->normalGeometry;
+ if (r.width() >= 0) {
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ setGeometry(r);
+ }
+ }
+ }
+ data->in_set_window_state = 0;
+
+ if (needShow)
+ show();
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidgetPrivate::setFocus_sys()
+{
+
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ //@@@ transaction
+ if (q->isWindow()) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QWidget::qwsDisplay()->setAltitude(q->internalWinId(),
+ QWSChangeAltitudeCommand::Raise);
+ // XXX: subsurfaces?
+#ifdef QT_NO_WINDOWGROUPHINT
+#else
+ QObjectList childObjects = q->children();
+ if (!childObjects.isEmpty()) {
+ QWidgetList toraise;
+ for (int i = 0; i < childObjects.size(); ++i) {
+ QObject *obj = childObjects.at(i);
+ if (obj->isWidgetType()) {
+ QWidget* w = static_cast<QWidget*>(obj);
+ if (w->isWindow())
+ toraise.append(w);
+ }
+ }
+
+ for (int i = 0; i < toraise.size(); ++i) {
+ QWidget *w = toraise.at(i);
+ if (w->isVisible())
+ w->raise();
+ }
+ }
+#endif // QT_NO_WINDOWGROUPHINT
+ }
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QWidget::qwsDisplay()->setAltitude(data.winid,
+ QWSChangeAltitudeCommand::Lower);
+ } else if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(q->geometry());
+ }
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget*)
+{
+ Q_Q(QWidget);
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(q->geometry());
+ }
+}
+
+void QWidgetPrivate::moveSurface(QWindowSurface *surface, const QPoint &offset)
+{
+ QWSWindowSurface *s = static_cast<QWSWindowSurface*>(surface);
+ if (!s->move(offset))
+ s->invalidateBuffer();
+
+ QWSDisplay::instance()->moveRegion(s->winId(), offset.x(), offset.y());
+}
+
+void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
+{
+ Q_Q(QWidget);
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+
+ QPoint oldp = q->geometry().topLeft();
+ QSize olds = q->size();
+ QRect r(x, y, w, h);
+
+ bool isResize = olds != r.size();
+ isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
+
+ // We only care about stuff that changes the geometry, or may
+ // cause the window manager to change its state
+ if (r.size() == olds && oldp == r.topLeft())
+ return;
+
+ if (!data.in_set_window_state) {
+ q->data->window_state &= ~Qt::WindowMaximized;
+ q->data->window_state &= ~Qt::WindowFullScreen;
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ }
+ QPoint oldPos = q->pos();
+ data.crect = r;
+
+ if ((q->windowType() == Qt::Desktop))
+ return;
+
+ if (q->isVisible()) {
+
+ bool toplevelMove = false;
+ QWSWindowSurface *surface = 0;
+
+ if (q->isWindow()) {
+ //### ConfigPending not implemented, do we need it?
+ //setAttribute(Qt::WA_WState_ConfigPending);
+ const QWidgetBackingStore *bs = maybeBackingStore();
+ if (bs)
+ surface = static_cast<QWSWindowSurface*>(bs->windowSurface);
+ if (isMove && !isResize && surface) {
+ const QPoint offset(x - oldp.x(), y - oldp.y());
+ moveSurface(surface, offset);
+ toplevelMove = true; //server moves window, but we must send moveEvent, which might trigger painting
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ QList<QWindowSurface*> surfaces = bs->subSurfaces;
+ for (int i = 0; i < surfaces.size(); ++i)
+ moveSurface(surfaces.at(i), offset);
+#endif
+ } else {
+ updateFrameStrut();
+ }
+ }
+
+ if (!toplevelMove) {
+ if (q->isWindow()) {
+ if (surface)
+ surface->setGeometry(q->frameGeometry());
+ else
+ invalidateBuffer(q->rect()); //###
+
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ // XXX: should not resize subsurfaces. Children within a layout
+ // will be resized automatically while children with a static
+ // geometry should get a new clip region instead.
+ const QRect clipRect = q->geometry();
+ QWidgetBackingStore *bs = maybeBackingStore();
+ QList<QWindowSurface*> surfaces = bs->subSurfaces;
+ for (int i = 0; i < surfaces.size(); ++i) {
+ QWSWindowSurface *s = static_cast<QWSWindowSurface*>(surfaces.at(i));
+ QRect srect = s->geometry();
+ s->setGeometry(clipRect & srect);
+ }
+#endif
+ }
+#ifdef Q_BACKINGSTORE_SUBSURFACES
+ // XXX: merge this case with the isWindow() case
+ else if (maybeTopData() && maybeTopData()->windowSurface) {
+ QWSWindowSurface *surface;
+ surface = static_cast<QWSWindowSurface*>(q->windowSurface());
+ if (isMove && !isResize) {
+ moveSurface(surface, QPoint(x - oldp.x(), y - oldp.y()));
+ } else {
+ const QPoint p = q->mapToGlobal(QPoint());
+ surface->setGeometry(QRect(p, QSize(w, h)));
+ }
+ }
+#endif
+ else {
+ if (isMove && !isResize)
+ moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, olds);
+ }
+ }
+
+ //### must have frame geometry correct before sending move/resize events
+ if (isMove) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ QResizeEvent e(r.size(), olds);
+ QApplication::sendEvent(q, &e);
+ }
+
+ } else { // not visible
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+}
+
+QScreen* QWidgetPrivate::getScreen() const
+{
+ Q_Q(const QWidget);
+
+ const QList<QScreen*> subScreens = qt_screen->subScreens();
+ if (subScreens.isEmpty() || q->windowType() == Qt::Desktop)
+ return qt_screen;
+
+ const int screen = QApplication::desktop()->screenNumber(q);
+
+ return qt_screen->subScreens().at(screen < 0 ? 0 : screen);
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+ scrollChildren(dx, dy);
+ scrollRect(q->rect(), dx, dy);
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ scrollRect(r, dx, dy);
+}
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmWidthMM) {
+ const QScreen *screen = d->getScreen();
+ val = data->crect.width() * screen->physicalWidth() / screen->width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else if (m == PdmHeightMM) {
+ const QScreen *screen = d->getScreen();
+ val = data->crect.height() * screen->physicalHeight() / screen->height();
+ } else if (m == PdmDepth) {
+ return qwsDisplay()->depth();
+ } else if (m == PdmDpiX || m == PdmPhysicalDpiX) {
+ if (d->extra && d->extra->customDpiX)
+ return d->extra->customDpiX;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ const QScreen *screen = d->getScreen();
+ return qRound(screen->width() / double(screen->physicalWidth() / 25.4));
+ } else if (m == PdmDpiY || m == PdmPhysicalDpiY) {
+ if (d->extra && d->extra->customDpiY)
+ return d->extra->customDpiY;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ const QScreen *screen = d->getScreen();
+ return qRound(screen->height() / double(screen->physicalHeight() / 25.4));
+ } else {
+ val = QPaintDevice::metric(m);// XXX
+ }
+ return val;
+}
+
+void QWidgetPrivate::createSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+}
+
+void QWidgetPrivate::createTLSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+}
+
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_UNUSED(on);
+}
+
+QRegion QWidgetPrivate::localRequestedRegion() const
+{
+ Q_Q(const QWidget);
+ QRegion r(q->rect());
+ if (extra && !extra->mask.isEmpty())
+ r &= extra->mask;
+
+ return r;
+}
+
+QRegion QWidgetPrivate::localAllocatedRegion() const
+{
+ Q_Q(const QWidget);
+
+ QWidgetBackingStore *wbs = q->window()->d_func()->maybeBackingStore();
+
+ QWindowSurface *ws = wbs ? wbs->windowSurface : 0;
+ if (!ws)
+ return QRegion();
+ QRegion r = static_cast<QWSWindowSurface*>(ws)->clipRegion();
+ if (!q->isWindow()) {
+ QPoint off = q->mapTo(q->window(), QPoint());
+ r &= localRequestedRegion().translated(off);
+ r.translate(-off);
+ }
+ return r;
+}
+
+inline bool QRect::intersects(const QRect &r) const
+{
+ return (qMax(x1, r.x1) <= qMin(x2, r.x2) &&
+ qMax(y1, r.y1) <= qMin(y2, r.y2));
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_UNUSED(region);
+ Q_Q(QWidget);
+
+ if (!q->isVisible() || !q->isWindow())
+ return;
+
+ data.fstrut_dirty = true;
+ invalidateBuffer(q->rect());
+ QWindowSurface *surface = extra->topextra->backingStore->windowSurface;
+ if (surface) {
+ // QWSWindowSurface::setGeometry() returns without doing anything
+ // if old geom == new geom. Therefore, we need to reset the old value.
+ surface->QWindowSurface::setGeometry(QRect());
+ surface->setGeometry(q->frameGeometry());
+ }
+}
+
+void QWidgetPrivate::updateFrameStrut()
+{
+ Q_Q(QWidget);
+
+ if(!q->isVisible() || (q->windowType() == Qt::Desktop)) {
+ data.fstrut_dirty = q->isVisible();
+ return;
+ }
+
+#ifndef QT_NO_QWS_MANAGER
+ if (extra && extra->topextra && extra->topextra->qwsManager) {
+ QTLWExtra *topextra = extra->topextra;
+ const QRect oldFrameStrut = topextra->frameStrut;
+ const QRect contents = data.crect;
+ QRegion r = localRequestedRegion().translated(contents.topLeft());
+ r += extra->topextra->qwsManager->region();
+ const QRect frame = r.boundingRect();
+
+ topextra->frameStrut.setCoords(contents.left() - frame.left(),
+ contents.top() - frame.top(),
+ frame.right() - contents.right(),
+ frame.bottom() - contents.bottom());
+ topextra->qwsManager->repaintRegion(QDecoration::All, QDecoration::Normal);
+ }
+#endif
+ data.fstrut_dirty = false;
+}
+
+#ifndef QT_NO_CURSOR
+void QWidgetPrivate::updateCursor() const
+{
+ Q_Q(const QWidget);
+
+ if (QApplication::overrideCursor())
+ return;
+
+ if (qt_last_x
+ && (!QWidget::mouseGrabber() || QWidget::mouseGrabber() == q)
+ && qt_last_cursor != (WId)q->cursor().handle())
+ {
+ const QPoint pos(*qt_last_x, *qt_last_y);
+ const QPoint offset = q->mapToGlobal(QPoint());
+ if (!localAllocatedRegion().contains(pos - offset))
+ return;
+
+ const QWidget *w = q->childAt(q->mapFromGlobal(pos));
+ if (!w || w->cursor().handle() == q->cursor().handle())
+ QWidget::qwsDisplay()->selectCursor(const_cast<QWidget*>(q),
+ q->cursor().handle());
+ }
+}
+#endif
+
+void QWidgetPrivate::setWindowOpacity_sys(qreal level)
+{
+ Q_Q(QWidget);
+ Q_UNUSED(level);
+ createWinId();
+ QWidget::qwsDisplay()->setOpacity(q->data->winid, topData()->opacity);
+}
+
+//static QSingleCleanupHandler<QWSPaintEngine> qt_paintengine_cleanup_handler;
+//static QWSPaintEngine *qt_widget_paintengine = 0;
+QPaintEngine *QWidget::paintEngine() const
+{
+ qWarning("QWidget::paintEngine: Should no longer be called");
+ return 0; //##### @@@
+// if (!qt_widget_paintengine) {
+// qt_widget_paintengine = new QRasterPaintEngine();
+// qt_paintengine_cleanup_handler.set(&qt_widget_paintengine);
+// }
+// if (qt_widget_paintengine->isActive()) {
+// if (d->extraPaintEngine)
+// return d->extraPaintEngine;
+// const_cast<QWidget *>(this)->d_func()->extraPaintEngine = new QRasterPaintEngine();
+// return d->extraPaintEngine;
+// }
+// return qt_widget_paintengine;
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ Q_Q(QWidget);
+ if (q->windowType() == Qt::Desktop)
+ return 0;
+ q->ensurePolished();
+ return qt_screen->createSurface(q);
+}
+
+void QWidgetPrivate::setModal_sys()
+{
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
new file mode 100644
index 0000000000..ffbb34146f
--- /dev/null
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -0,0 +1,2124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qimage.h"
+#include "qlayout.h"
+#include "qlibrary.h"
+#include "qpainter.h"
+#include "qstack.h"
+#include "qt_windows.h"
+#include "qwidget.h"
+#include "qwidget_p.h"
+#include "private/qbackingstore_p.h"
+#include "private/qwindowsurface_raster_p.h"
+
+#ifndef QT_NO_DIRECT3D
+#include "private/qpaintengine_d3d_p.h"
+#include "private/qwindowsurface_d3d_p.h"
+#endif
+
+
+#include <qdebug.h>
+
+#include <private/qapplication_p.h>
+#include <private/qwininputcontext_p.h>
+#include <private/qpaintengine_raster_p.h>
+
+#if defined(Q_OS_WINCE)
+#include "qguifunctions_wince.h"
+QT_USE_NAMESPACE
+extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp
+extern void qt_wince_minimize(HWND hwnd); //defined in qguifunctions_wince.cpp
+extern void qt_wince_full_screen(HWND hwnd, bool fullScreen, UINT swpf); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
+#endif
+
+typedef BOOL (WINAPI *PtrSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
+static PtrSetLayeredWindowAttributes ptrSetLayeredWindowAttributes = 0;
+
+#ifndef QT_NO_DIRECTDRAW
+#include <ddraw.h>
+#include <private/qimage_p.h>
+static IDirectDraw *qt_ddraw_object;
+static IDirectDrawSurface *qt_ddraw_primary;
+#endif
+
+
+
+#if defined(QT_NON_COMMERCIAL)
+#include "qnc_win.h"
+#endif
+
+#if !defined(WS_EX_TOOLWINDOW)
+#define WS_EX_TOOLWINDOW 0x00000080
+#endif
+
+#if !defined(GWLP_WNDPROC)
+#define GWLP_WNDPROC GWL_WNDPROC
+#endif
+
+//#define TABLET_DEBUG
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
+ | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#define PACKETMODE 0
+#include <wintab.h>
+#include <pktdef.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
+typedef BOOL (API *PtrWTClose)(HCTX);
+typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
+typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
+typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
+typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
+typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
+typedef int (API *PtrWTQueueSizeGet)(HCTX);
+typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
+
+static PtrWTOpen ptrWTOpen = 0;
+static PtrWTClose ptrWTClose = 0;
+static PtrWTInfo ptrWTInfo = 0;
+static PtrWTQueueSizeGet ptrWTQueueSizeGet = 0;
+static PtrWTQueueSizeSet ptrWTQueueSizeSet = 0;
+static void init_wintab_functions();
+static void qt_tablet_init();
+static void qt_tablet_cleanup();
+extern HCTX qt_tablet_context;
+extern bool qt_tablet_tilt_support;
+
+static QWidget *qt_tablet_widget = 0;
+QWidget* qt_get_tablet_widget()
+{
+ return qt_tablet_widget;
+}
+
+extern bool qt_is_gui_used;
+static void init_wintab_functions()
+{
+#if defined(Q_OS_WINCE)
+ return;
+#else
+ if (!qt_is_gui_used)
+ return;
+ QLibrary library(QLatin1String("wintab32"));
+ QT_WA({
+ ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW");
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
+ } , {
+ ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenA");
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA");
+ });
+
+ ptrWTClose = (PtrWTClose)library.resolve("WTClose");
+ ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet");
+ ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet");
+#endif // Q_OS_WINCE
+}
+
+static void qt_tablet_init()
+{
+ static bool firstTime = true;
+ if (!firstTime)
+ return;
+ firstTime = false;
+ qt_tablet_widget = new QWidget(0);
+ qt_tablet_widget->createWinId();
+ qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget"));
+ LOGCONTEXT lcMine;
+ qAddPostRoutine(qt_tablet_cleanup);
+ struct tagAXIS tpOri[3];
+ init_wintab_functions();
+ if (ptrWTInfo && ptrWTOpen && ptrWTQueueSizeGet && ptrWTQueueSizeSet) {
+ // make sure we have WinTab
+ if (!ptrWTInfo(0, 0, NULL)) {
+#ifdef TABLET_DEBUG
+ qWarning("QWidget: Wintab services not available");
+#endif
+ return;
+ }
+
+ // some tablets don't support tilt, check if it is possible,
+ qt_tablet_tilt_support = ptrWTInfo(WTI_DEVICES, DVC_ORIENTATION, &tpOri);
+ if (qt_tablet_tilt_support) {
+ // check for azimuth and altitude
+ qt_tablet_tilt_support = tpOri[0].axResolution && tpOri[1].axResolution;
+ }
+ // build our context from the default context
+ ptrWTInfo(WTI_DEFSYSCTX, 0, &lcMine);
+ // Go for the raw coordinates, the tablet event will return good stuff
+ lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
+ lcMine.lcPktData = PACKETDATA;
+ lcMine.lcPktMode = PACKETMODE;
+ lcMine.lcMoveMask = PACKETDATA;
+ lcMine.lcOutOrgX = 0;
+ lcMine.lcOutExtX = lcMine.lcInExtX;
+ lcMine.lcOutOrgY = 0;
+ lcMine.lcOutExtY = -lcMine.lcInExtY;
+ qt_tablet_context = ptrWTOpen(qt_tablet_widget->winId(), &lcMine, true);
+#ifdef TABLET_DEBUG
+ qDebug("Tablet is %p", qt_tablet_context);
+#endif
+ if (!qt_tablet_context) {
+#ifdef TABLET_DEBUG
+ qWarning("QWidget: Failed to open the tablet");
+#endif
+ return;
+ }
+ // Set the size of the Packet Queue to the correct size...
+ int currSize = ptrWTQueueSizeGet(qt_tablet_context);
+ if (!ptrWTQueueSizeSet(qt_tablet_context, QT_TABLET_NPACKETQSIZE)) {
+ // Ideally one might want to use a smaller
+ // multiple, but for now, since we managed to destroy
+ // the existing Q with the previous call, set it back
+ // to the other size, which should work. If not,
+ // there will be trouble.
+ if (!ptrWTQueueSizeSet(qt_tablet_context, currSize)) {
+ Q_ASSERT_X(0, "Qt::Internal", "There is no packet queue for"
+ " the tablet. The tablet will not work");
+ }
+ }
+ }
+}
+
+static void qt_tablet_cleanup()
+{
+ if (ptrWTClose)
+ ptrWTClose(qt_tablet_context);
+ delete qt_tablet_widget;
+ qt_tablet_widget = 0;
+}
+
+const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp
+
+#ifndef QT_NO_DRAGANDDROP
+void qt_olednd_unregister(QWidget* widget, QOleDropTarget *dst); // dnd_win
+QOleDropTarget* qt_olednd_register(QWidget* widget);
+#endif
+
+extern bool qt_nograb();
+extern HRGN qt_win_bitmapToRegion(const QBitmap& bitmap);
+
+static QWidget *mouseGrb = 0;
+static QCursor *mouseGrbCur = 0;
+static QWidget *keyboardGrb = 0;
+static HHOOK journalRec = 0;
+
+extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+
+#define XCOORD_MAX 16383
+#define WRECT_MAX 16383
+
+/*****************************************************************************
+ QWidget member functions
+ *****************************************************************************/
+
+#ifndef Q_OS_WINCE
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+ static int sw = -1, sh = -1;
+
+ Qt::WindowType type = q->windowType();
+ Qt::WindowFlags flags = data.window_flags;
+
+ bool topLevel = (flags & Qt::Window);
+ bool popup = (type == Qt::Popup);
+ bool dialog = (type == Qt::Dialog
+ || type == Qt::Sheet
+ || (flags & Qt::MSWindowsFixedSizeDialogHint));
+ bool desktop = (type == Qt::Desktop);
+ bool tool = (type == Qt::Tool || type == Qt::Drawer);
+
+ HINSTANCE appinst = qWinAppInst();
+ HWND parentw, destroyw = 0;
+ WId id;
+
+ QString windowClassName = qt_reg_winclass(q);
+
+ if (!window) // always initialize
+ initializeWindow = true;
+
+ if (popup)
+ flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
+
+ if (sw < 0) { // get the (primary) screen size
+ sw = GetSystemMetrics(SM_CXSCREEN);
+ sh = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
+ popup = false; // force this flags off
+ if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95)
+ data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */),
+ GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */));
+ else
+ data.crect.setRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
+ }
+
+ parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0;
+
+#ifdef UNICODE
+ QString title;
+ const TCHAR *ttitle = 0;
+#endif
+ QByteArray title95;
+ int style = WS_CHILD;
+ int exsty = 0;
+
+ if (window) {
+ style = GetWindowLongA(window, GWL_STYLE);
+ if (!style)
+ qErrnoWarning("QWidget::create: GetWindowLong failed");
+ topLevel = false; // #### needed for some IE plugins??
+ } else if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
+ style = WS_POPUP;
+ } else if (topLevel && !desktop) {
+ if (flags & Qt::FramelessWindowHint)
+ style = WS_POPUP; // no border
+ else if (flags & Qt::WindowTitleHint)
+ style = WS_OVERLAPPED;
+ else
+ style = 0;
+ }
+ if (!desktop) {
+ // if (!testAttribute(Qt::WA_PaintUnclipped))
+ // ### Commented out for now as it causes some problems, but
+ // this should be correct anyway, so dig some more into this
+#ifndef Q_FLATTEN_EXPOSE
+ style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+#endif
+ if (topLevel) {
+ if ((type == Qt::Window || dialog || tool)) {
+ if (!(flags & Qt::FramelessWindowHint)) {
+ if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) {
+ style |= WS_THICKFRAME;
+ if(!(flags &
+ ( Qt::WindowSystemMenuHint
+ | Qt::WindowTitleHint
+ | Qt::WindowMinMaxButtonsHint
+ | Qt::WindowCloseButtonHint
+ | Qt::WindowContextHelpButtonHint)))
+ style |= WS_POPUP;
+ } else {
+ style |= WS_POPUP | WS_DLGFRAME;
+ }
+ }
+ if (flags & Qt::WindowTitleHint)
+ style |= WS_CAPTION;
+ if (flags & Qt::WindowSystemMenuHint)
+ style |= WS_SYSMENU;
+ if (flags & Qt::WindowMinimizeButtonHint)
+ style |= WS_MINIMIZEBOX;
+ if (shouldShowMaximizeButton())
+ style |= WS_MAXIMIZEBOX;
+ if (tool)
+ exsty |= WS_EX_TOOLWINDOW;
+ if (flags & Qt::WindowContextHelpButtonHint)
+ exsty |= WS_EX_CONTEXTHELP;
+ } else {
+ exsty |= WS_EX_TOOLWINDOW;
+ }
+ }
+ }
+
+ if (flags & Qt::WindowTitleHint) {
+ QT_WA({
+ title = q->isWindow() ? qAppName() : q->objectName();
+ ttitle = (TCHAR*)title.utf16();
+ } , {
+ title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1();
+ });
+ }
+
+ // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
+ // qapplication_win.cpp. We switch it off temporarily to avoid move
+ // and resize events during creationt
+ q->setAttribute(Qt::WA_WState_Created, false);
+
+ if (window) { // override the old window
+ if (destroyOldWindow)
+ destroyw = data.winid;
+ id = window;
+ setWinId(window);
+ LONG res = SetWindowLongA(window, GWL_STYLE, style);
+ if (!res)
+ qErrnoWarning("QWidget::create: Failed to set window style");
+#ifdef _WIN64
+ res = SetWindowLongPtrA( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
+#else
+ res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc );
+#endif
+ if (!res)
+ qErrnoWarning("QWidget::create: Failed to set window procedure");
+ } else if (desktop) { // desktop widget
+ id = GetDesktopWindow();
+// QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
+// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
+// otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
+// d->setWinId(id); // make sure otherDesktop is
+// otherDesktop->d_func()->setWinId(id); // found first
+// } else {
+ setWinId(id);
+// }
+ } else if (topLevel) { // create top-level widget
+ if (popup)
+ parentw = 0;
+
+ const bool wasMoved = q->testAttribute(Qt::WA_Moved);
+ int x = wasMoved ? data.crect.left() : CW_USEDEFAULT;
+ int y = wasMoved ? data.crect.top() : CW_USEDEFAULT;
+ int w = CW_USEDEFAULT;
+ int h = CW_USEDEFAULT;
+
+ // Adjust for framestrut when needed
+ RECT rect = {0,0,0,0};
+ bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
+ if (isVisibleOnScreen && AdjustWindowRectEx(&rect, style & ~WS_OVERLAPPED, FALSE, exsty)) {
+ QTLWExtra *td = maybeTopData();
+ if (wasMoved && (td && !td->posFromMove)) {
+ x = data.crect.x() + rect.left;
+ y = data.crect.y() + rect.top;
+ }
+
+ if (q->testAttribute(Qt::WA_Resized)) {
+ w = data.crect.width() + (rect.right - rect.left);
+ h = data.crect.height() + (rect.bottom - rect.top);
+ }
+ }
+ //update position & initial size of POPUP window
+ if (isVisibleOnScreen && topLevel && initializeWindow && (style & WS_POPUP)) {
+ if (!q->testAttribute(Qt::WA_Resized)) {
+ w = sw/2;
+ h = 4*sh/10;
+ }
+ if (!wasMoved) {
+ x = sw/2 - w/2;
+ y = sh/2 - h/2;
+ }
+ }
+
+ QT_WA({
+ const TCHAR *cname = (TCHAR*)windowClassName.utf16();
+ id = CreateWindowEx(exsty, cname, ttitle, style,
+ x, y, w, h,
+ parentw, 0, appinst, 0);
+ } , {
+ id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
+ x, y, w, h,
+ parentw, 0, appinst, 0);
+ });
+ if (!id)
+ qErrnoWarning("QWidget::create: Failed to create window");
+ setWinId(id);
+ if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
+ SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+ if (flags & Qt::WindowStaysOnBottomHint)
+ qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
+ } else if (flags & Qt::WindowStaysOnBottomHint)
+ SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+ winUpdateIsOpaque();
+ } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
+ QT_WA({
+ const TCHAR *cname = (TCHAR*)windowClassName.utf16();
+ id = CreateWindowEx(exsty, cname, ttitle, style,
+ data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
+ parentw, NULL, appinst, NULL);
+ } , {
+ id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
+ data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
+ parentw, NULL, appinst, NULL);
+ });
+ if (!id)
+ qErrnoWarning("QWidget::create: Failed to create window");
+ SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ setWinId(id);
+ }
+
+ if (desktop) {
+ q->setAttribute(Qt::WA_WState_Visible);
+ } else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ RECT cr;
+ GetClientRect(id, &cr);
+ // one cannot trust cr.left and cr.top, use a correction POINT instead
+ POINT pt;
+ pt.x = 0;
+ pt.y = 0;
+ ClientToScreen(id, &pt);
+
+ if (data.crect.width() == 0 || data.crect.height() == 0) {
+ data.crect = QRect(pt.x, pt.y, data.crect.width(), data.crect.height());
+ } else {
+ data.crect = QRect(QPoint(pt.x, pt.y),
+ QPoint(pt.x + cr.right - 1, pt.y + cr.bottom - 1));
+ }
+
+ if (data.fstrut_dirty) {
+ // be nice to activeqt
+ updateFrameStrut();
+ }
+ }
+
+ q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
+ hd = 0; // no display context
+
+ if (window) { // got window from outside
+ if (IsWindowVisible(window))
+ q->setAttribute(Qt::WA_WState_Visible);
+ else
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ }
+
+ if (extra && !extra->mask.isEmpty())
+ setMask_sys(extra->mask);
+
+#if defined(QT_NON_COMMERCIAL)
+ QT_NC_WIDGET_CREATE
+#endif
+
+ if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->inputContext()->setFocusWidget(q);
+
+ if (destroyw) {
+ DestroyWindow(destroyw);
+ }
+
+ if (q != qt_tablet_widget && QWidgetPrivate::mapper)
+ qt_tablet_init();
+
+ if (q->testAttribute(Qt::WA_DropSiteRegistered))
+ registerDropSite(true);
+
+ if (maybeTopData() && maybeTopData()->opacity != 255)
+ q->setWindowOpacity(maybeTopData()->opacity/255.);
+
+ if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ }
+
+ if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
+ Q_ASSERT(q->internalWinId());
+ ShowWindow(q->internalWinId(), SW_SHOW);
+ }
+}
+
+#endif //Q_OS_WINCE
+
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(geometry());
+ d->deactivateWidgetCleanup();
+ if (testAttribute(Qt::WA_WState_Created)) {
+ setAttribute(Qt::WA_WState_Created, false);
+ for(int i = 0; i < d->children.size(); ++i) { // destroy all widget children
+ register QObject *obj = d->children.at(i);
+ if (obj->isWidgetType())
+ ((QWidget*)obj)->destroy(destroySubWindows,
+ destroySubWindows);
+ }
+ if (mouseGrb == this)
+ releaseMouse();
+ if (keyboardGrb == 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 && !(windowType() == Qt::Desktop) && internalWinId()) {
+ DestroyWindow(internalWinId());
+ }
+#ifdef Q_OS_WINCE
+ if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) {
+ DestroyWindow(internalWinId());
+ }
+
+#endif
+ d->setWinId(0);
+ }
+}
+
+void QWidgetPrivate::reparentChildren()
+{
+ Q_Q(QWidget);
+ QObjectList chlist = q->children();
+ for(int i = 0; i < chlist.size(); ++i) { // reparent children
+ QObject *obj = chlist.at(i);
+ if (obj->isWidgetType()) {
+ QWidget *w = (QWidget *)obj;
+ if ((w->windowType() == Qt::Popup)) {
+ ;
+ } else if (w->isWindow()) {
+ bool showIt = w->isVisible();
+ QPoint old_pos = w->pos();
+ w->setParent(q, w->windowFlags());
+ w->move(old_pos);
+ if (showIt)
+ w->show();
+ } else {
+ w->d_func()->invalidateBuffer(w->rect());
+ SetParent(w->effectiveWinId(), q->effectiveWinId());
+ w->d_func()->reparentChildren();
+ }
+ }
+ }
+}
+
+void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+ if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
+ q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+
+ WId old_winid = data.winid;
+ // hide and reparent our own window away. Otherwise we might get
+ // destroyed when emitting the child remove event below. See QWorkspace.
+ if (q->isVisible() && data.winid) {
+ ShowWindow(data.winid, SW_HIDE);
+ SetParent(data.winid, 0);
+ }
+ bool dropSiteWasRegistered = false;
+ if (q->testAttribute(Qt::WA_DropSiteRegistered)) {
+ dropSiteWasRegistered = true;
+ q->setAttribute(Qt::WA_DropSiteRegistered, false); // ole dnd unregister (we will register again below)
+ }
+
+ if ((q->windowType() == Qt::Desktop))
+ old_winid = 0;
+ setWinId(0);
+
+ QObjectPrivate::setParent_helper(parent);
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ data.window_flags = f;
+ data.fstrut_dirty = true;
+ 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)
+ if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
+ createWinId();
+ if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ if (wasCreated) {
+ reparentChildren();
+ }
+
+ if (extra && !extra->mask.isEmpty()) {
+ QRegion r = extra->mask;
+ extra->mask = QRegion();
+ q->setMask(r);
+ }
+ if (extra && extra->topextra && !extra->topextra->caption.isEmpty()) {
+ setWindowIcon_sys(true);
+ setWindowTitle_helper(extra->topextra->caption);
+ }
+ if (old_winid)
+ DestroyWindow(old_winid);
+
+ if (q->testAttribute(Qt::WA_AcceptDrops) || dropSiteWasRegistered
+ || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
+ q->setAttribute(Qt::WA_DropSiteRegistered, true);
+
+
+ if (data.window_flags & Qt::CustomizeWindowHint
+ && data.window_flags & Qt::WindowTitleHint) {
+ HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE);
+ if (data.window_flags & Qt::WindowCloseButtonHint)
+ EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
+ else
+ EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
+ }
+
+#ifdef Q_OS_WINCE
+ // Show borderless toplevel windows in tasklist & NavBar
+ if (!parent) {
+ QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle();
+ SetWindowText(q->internalWinId(), (TCHAR*)txt.utf16());
+ }
+#endif
+ invalidateBuffer(q->rect());
+}
+
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ QWidget *parentWindow = window();
+ QWExtra *extra = parentWindow->d_func()->extra;
+ if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
+ || (extra && extra->proxyWidget)) {
+ if (extra && extra->topextra && extra->topextra->embedded) {
+ QPoint pt = mapTo(parentWindow, pos);
+ POINT p = {pt.x(), pt.y()};
+ ClientToScreen(parentWindow->effectiveWinId(), &p);
+ return QPoint(p.x, p.y);
+ } else {
+ QPoint toGlobal = mapTo(parentWindow, pos) + parentWindow->pos();
+ // Adjust for window decorations
+ toGlobal += parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft();
+ return toGlobal;
+ }
+ }
+ POINT p;
+ QPoint tmp = d->mapToWS(pos);
+ p.x = tmp.x();
+ p.y = tmp.y();
+ ClientToScreen(internalWinId(), &p);
+ return QPoint(p.x, p.y);
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ QWidget *parentWindow = window();
+ QWExtra *extra = parentWindow->d_func()->extra;
+ if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
+ || (extra && extra->proxyWidget)) {
+ if (extra && extra->topextra && extra->topextra->embedded) {
+ POINT p = {pos.x(), pos.y()};
+ ScreenToClient(parentWindow->effectiveWinId(), &p);
+ return mapFrom(parentWindow, QPoint(p.x, p.y));
+ } else {
+ QPoint fromGlobal = mapFrom(parentWindow, pos - parentWindow->pos());
+ // Adjust for window decorations
+ fromGlobal -= parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft();
+ return fromGlobal;
+ }
+ }
+ POINT p;
+ p.x = pos.x();
+ p.y = pos.y();
+ ScreenToClient(internalWinId(), &p);
+ return d->mapFromWS(QPoint(p.x, p.y));
+}
+
+void QWidgetPrivate::updateSystemBackground() {}
+
+extern void qt_win_set_cursor(QWidget *, bool); // qapplication_win.cpp
+
+#ifndef QT_NO_CURSOR
+void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+ Q_Q(QWidget);
+ qt_win_set_cursor(q, false);
+}
+
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ qt_win_set_cursor(q, false);
+}
+#endif
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QT_WA({
+ SetWindowText(q->internalWinId(), (TCHAR*)caption.utf16());
+ } , {
+ SetWindowTextA(q->internalWinId(), caption.toLocal8Bit());
+ });
+}
+
+/*
+ Create an icon mask the way Windows wants it using CreateBitmap.
+*/
+
+HBITMAP qt_createIconMask(const QBitmap &bitmap)
+{
+ QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono);
+ int w = bm.width();
+ int h = bm.height();
+ int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment
+ uchar *bits = new uchar[bpl*h];
+ bm.invertPixels();
+ for (int y=0; y<h; y++)
+ memcpy(bits+y*bpl, bm.scanLine(y), bpl);
+ HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits);
+ delete [] bits;
+ return hbm;
+}
+
+HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache)
+{
+ HICON result = 0;
+ if (!icon.isNull()) { // valid icon
+ QSize size = icon.actualSize(QSize(xSize, ySize));
+ QPixmap pm = icon.pixmap(size);
+ if (pm.isNull())
+ return 0;
+
+ QBitmap mask = pm.mask();
+ if (mask.isNull()) {
+ mask = QBitmap(pm.size());
+ mask.fill(Qt::color1);
+ }
+
+ HBITMAP im = qt_createIconMask(mask);
+ ICONINFO ii;
+ ii.fIcon = true;
+ ii.hbmMask = im;
+ ii.hbmColor = pm.toWinHBITMAP(QPixmap::Alpha);
+ ii.xHotspot = 0;
+ ii.yHotspot = 0;
+ result = CreateIconIndirect(&ii);
+
+ if (cache) {
+ delete *cache;
+ *cache = new QPixmap(pm);;
+ }
+ DeleteObject(ii.hbmColor);
+ DeleteObject(im);
+ }
+ return result;
+}
+
+void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
+{
+ Q_Q(QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow())
+ return;
+ QTLWExtra* x = topData();
+ if (x->iconPixmap && !forceReset)
+ // already been set
+ return;
+
+ if (x->winIconBig) {
+ DestroyIcon(x->winIconBig);
+ x->winIconBig = 0;
+ }
+ if (x->winIconSmall) {
+ DestroyIcon(x->winIconSmall);
+ x->winIconSmall = 0;
+ }
+
+ x->winIconSmall = qt_createIcon(q->windowIcon(),
+ GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
+ &(x->iconPixmap));
+ x->winIconBig = qt_createIcon(q->windowIcon(),
+ GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
+ &(x->iconPixmap));
+ if (x->winIconBig) {
+ SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
+ SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig);
+ } else {
+ SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
+ SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall);
+ }
+}
+
+
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_UNUSED(iconText);
+}
+
+
+QCursor *qt_grab_cursor()
+{
+ return mouseGrbCur;
+}
+
+// The procedure does nothing, but is required for mousegrabbing to work
+#ifndef Q_OS_WINCE
+LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ return CallNextHookEx(journalRec, nCode, wParam, lParam);
+}
+#endif //Q_OS_WINCE
+
+/* Works only as long as pointer is inside the application's window,
+ which is good enough for QDockWidget.
+
+ Doesn't call SetWindowsHookExA() - this function causes a system-wide
+ freeze if any other app on the system installs a hook and fails to
+ process events. */
+void QWidgetPrivate::grabMouseWhileInWindow()
+{
+ Q_Q(QWidget);
+ if (!qt_nograb()) {
+ if (mouseGrb)
+ mouseGrb->releaseMouse();
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ SetCapture(q->effectiveWinId());
+ mouseGrb = q;
+#ifndef QT_NO_CURSOR
+ mouseGrbCur = new QCursor(mouseGrb->cursor());
+#endif
+ }
+}
+
+#ifndef Q_OS_WINCE
+void QWidget::grabMouse()
+{
+ if (!qt_nograb()) {
+ if (mouseGrb)
+ mouseGrb->releaseMouse();
+ journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0);
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ SetCapture(effectiveWinId());
+ mouseGrb = this;
+ mouseGrbCur = new QCursor(mouseGrb->cursor());
+ }
+}
+
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ if (!qt_nograb()) {
+ if (mouseGrb)
+ mouseGrb->releaseMouse();
+ journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0);
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ SetCapture(effectiveWinId());
+ mouseGrbCur = new QCursor(cursor);
+ SetCursor(mouseGrbCur->handle());
+ mouseGrb = this;
+ }
+}
+
+void QWidget::releaseMouse()
+{
+ if (!qt_nograb() && mouseGrb == this) {
+ ReleaseCapture();
+ if (journalRec) {
+ UnhookWindowsHookEx(journalRec);
+ journalRec = 0;
+ }
+ if (mouseGrbCur) {
+ delete mouseGrbCur;
+ mouseGrbCur = 0;
+ }
+ mouseGrb = 0;
+ }
+}
+#endif
+
+void QWidget::grabKeyboard()
+{
+ if (!qt_nograb()) {
+ if (keyboardGrb)
+ keyboardGrb->releaseKeyboard();
+ keyboardGrb = this;
+ }
+}
+
+void QWidget::releaseKeyboard()
+{
+ if (!qt_nograb() && keyboardGrb == this)
+ keyboardGrb = 0;
+}
+
+
+QWidget *QWidget::mouseGrabber()
+{
+ return mouseGrb;
+}
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
+
+void QWidget::activateWindow()
+{
+ window()->createWinId();
+ SetForegroundWindow(window()->internalWinId());
+}
+
+#ifndef Q_OS_WINCE
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+
+ int max = SW_MAXIMIZE;
+ int min = SW_MINIMIZE;
+
+ int normal = SW_SHOWNOACTIVATE;
+ if (newstate & Qt::WindowActive) {
+ max = SW_SHOWMAXIMIZED;
+ min = SW_SHOWMINIMIZED;
+ normal = SW_SHOWNORMAL;
+ }
+
+ if (isWindow()) {
+ createWinId();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+
+ // Ensure the initial size is valid, since we store it as normalGeometry below.
+ if (!testAttribute(Qt::WA_Resized) && !isVisible())
+ adjustSize();
+
+ if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
+ if (newstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen))
+ d->topData()->normalGeometry = geometry();
+ if (isVisible() && !(newstate & Qt::WindowMinimized)) {
+ ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
+ if (!(newstate & Qt::WindowFullScreen)) {
+ QRect r = d->topData()->normalGeometry;
+ if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) {
+ if (pos() != r.topLeft() || size() !=r.size()) {
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ setGeometry(r);
+ }
+ }
+ } else {
+ d->updateFrameStrut();
+ }
+ }
+ }
+
+ if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
+ if (newstate & Qt::WindowFullScreen) {
+ if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
+ d->topData()->normalGeometry = geometry();
+ d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE);
+#ifndef Q_FLATTEN_EXPOSE
+ UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
+#else
+ UINT style = WS_POPUP;
+#endif
+ if (d->topData()->savedFlags & WS_SYSMENU)
+ style |= WS_SYSMENU;
+ if (isVisible())
+ style |= WS_VISIBLE;
+ SetWindowLongA(internalWinId(), GWL_STYLE, style);
+ QRect r = qApp->desktop()->screenGeometry(this);
+ UINT swpf = SWP_FRAMECHANGED;
+ if (newstate & Qt::WindowActive)
+ swpf |= SWP_NOACTIVATE;
+
+ SetWindowPos(internalWinId(), HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
+ d->updateFrameStrut();
+ } else {
+ UINT style = d->topData()->savedFlags;
+ if (isVisible())
+ style |= WS_VISIBLE;
+ SetWindowLongA(internalWinId(), GWL_STYLE, style);
+
+ UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
+ if (newstate & Qt::WindowActive)
+ swpf |= SWP_NOACTIVATE;
+ SetWindowPos(internalWinId(), 0, 0, 0, 0, 0, swpf);
+ d->updateFrameStrut();
+
+ // preserve maximized state
+ if (isVisible())
+ ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
+
+ if (!(newstate & Qt::WindowMaximized)) {
+ QRect r = d->topData()->normalGeometry;
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ if (r.isValid())
+ setGeometry(r);
+ }
+ }
+ }
+
+ if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
+ if (isVisible())
+ ShowWindow(internalWinId(), (newstate & Qt::WindowMinimized) ? min :
+ (newstate & Qt::WindowMaximized) ? max : normal);
+ }
+ }
+ data->window_state = newstate;
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+#endif //Q_OS_WINCE
+
+
+/*
+ \internal
+ Platform-specific part of QWidget::hide().
+*/
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ deactivateWidgetCleanup();
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+#ifdef Q_OS_WINCE
+ if (!qt_wince_is_mobile() && q->isFullScreen()) {
+ HWND handle = FindWindow(L"HHTaskBar", L"");
+ if (handle) {
+ ShowWindow(handle, 1);
+ EnableWindow(handle, true);
+ }
+ }
+#endif
+ if (q->windowFlags() != Qt::Desktop) {
+ if ((q->windowFlags() & Qt::Popup) && q->internalWinId())
+ ShowWindow(q->internalWinId(), SW_HIDE);
+ else if (q->internalWinId())
+ SetWindowPos(q->internalWinId(),0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
+ }
+ if (q->isWindow()) {
+ if (QWidgetBackingStore *bs = maybeBackingStore())
+ bs->releaseBuffer();
+ } else {
+ invalidateBuffer(q->rect());
+ }
+ q->setAttribute(Qt::WA_Mapped, false);
+}
+
+
+/*
+ \internal
+ Platform-specific part of QWidget::show().
+*/
+#ifndef Q_OS_WINCE
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+#if defined(QT_NON_COMMERCIAL)
+ QT_NC_SHOW_WINDOW
+#endif
+ if (q->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+ q->setAttribute(Qt::WA_Mapped);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+ int sm = SW_SHOWNORMAL;
+ bool fakedMaximize = false;
+ if (q->isWindow()) {
+ if (q->isMinimized()) {
+ sm = SW_SHOWMINIMIZED;
+ if (!IsWindowVisible(q->internalWinId()))
+ sm = SW_SHOWMINNOACTIVE;
+ } else if (q->isMaximized()) {
+ sm = SW_SHOWMAXIMIZED;
+ // Windows will not behave correctly when we try to maximize a window which does not
+ // have minimize nor maximize buttons in the window frame. Windows would then ignore
+ // non-available geometry, and rather maximize the widget to the full screen, minus the
+ // window frame (caption). So, we do a trick here, by adding a maximize button before
+ // maximizing the widget, and then remove the maximize button afterwards.
+ Qt::WindowFlags &flags = data.window_flags;
+ if (flags & Qt::WindowTitleHint &&
+ !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
+ fakedMaximize = TRUE;
+ int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
+ SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX);
+ }
+ }
+ }
+ if (q->testAttribute(Qt::WA_ShowWithoutActivating)
+ || (q->windowType() == Qt::Popup)
+ || (q->windowType() == Qt::ToolTip)
+ || (q->windowType() == Qt::Tool)) {
+ sm = SW_SHOWNOACTIVATE;
+ }
+
+
+ if (q->internalWinId())
+ ShowWindow(q->internalWinId(), sm);
+
+ if (fakedMaximize) {
+ int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
+ SetWindowLong(q->internalWinId(), GWL_STYLE, style & ~WS_MAXIMIZEBOX);
+ SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
+ | SWP_FRAMECHANGED);
+ }
+
+ if (q->internalWinId()) {
+ if (IsIconic(q->internalWinId()))
+ data.window_state |= Qt::WindowMinimized;
+ if (IsZoomed(q->internalWinId()))
+ data.window_state |= Qt::WindowMaximized;
+ }
+
+ invalidateBuffer(q->rect());
+}
+#endif //Q_OS_WINCE
+
+void QWidgetPrivate::setFocus_sys()
+{
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
+ SetFocus(q->effectiveWinId());
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (q->internalWinId())
+ SetWindowPos(q->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (q->internalWinId())
+ SetWindowPos(q->internalWinId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget* w)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (q->internalWinId() && w->internalWinId())
+ SetWindowPos(q->internalWinId(), w->internalWinId() , 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ invalidateBuffer(q->rect());
+}
+
+
+/*
+ Helper function for non-toplevel widgets. Helps to map Qt's 32bit
+ coordinate system to Windpws's 16bit coordinate system.
+
+ This code is duplicated from the X11 code, so any changes there
+ should also (most likely) be reflected here.
+
+ (In all comments below: s/X/Windows/g)
+ */
+
+void QWidgetPrivate::setWSGeometry(bool dontShow)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ /*
+ 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 validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
+ QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
+ 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;
+
+ const QWidget *const parent = q->parentWidget();
+ QRect parentWRect = parent->data->wrect;
+
+ if (parentWRect.isValid()) {
+ // parent is clipped, and we have to clip to the same limit as parent
+ if (!parentWRect.contains(xrect)) {
+ 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 & parent->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());
+ if (q->internalWinId())
+ MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), true);
+ return;
+ }
+ }
+
+ if (!validRange.contains(xrect)) {
+ // we are too big, and must clip
+ xrect &=wrectRange;
+ wrect = xrect;
+ wrect.translate(-data.crect.topLeft());
+ //parent's X coord system is equal to parent's Qt coord
+ //sys, so we don't need to map xrect.
+ }
+
+ }
+
+
+ // 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) {
+ if (q->internalWinId())
+ ShowWindow(q->internalWinId(), SW_HIDE);
+ 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...
+ 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();
+ }
+ }
+
+ // move ourselves to the new position and map (if necessary) after
+ // the movement. Rationale: moving unmapped windows is much faster
+ // than moving mapped windows
+ if (q->internalWinId()) {
+ if (!parent->internalWinId())
+ xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
+ MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), !jump);
+ }
+ if (mapWindow && !dontShow) {
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->internalWinId())
+ ShowWindow(q->internalWinId(), SW_SHOWNOACTIVATE);
+ }
+
+ if (jump && q->internalWinId())
+ InvalidateRect(q->internalWinId(), 0, false);
+
+}
+
+//
+// The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move,
+// resize and setGeometry requests for a widget that is already
+// processing a config event. The purpose is to avoid recursion.
+//
+void qWinRequestConfig(WId, int, int, int, int, int);
+
+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 (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+
+ QSize oldSize(q->size());
+ QPoint oldPos(q->pos());
+
+ if (!q->isWindow())
+ isMove = (data.crect.topLeft() != QPoint(x, y));
+ bool isResize = w != oldSize.width() || h != oldSize.height();
+
+ if (!isMove && !isResize)
+ return;
+
+ if (isResize && !q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
+ ValidateRgn(q->internalWinId(), 0);
+
+ if (isResize)
+ data.window_state &= ~Qt::WindowMaximized;
+
+ if (data.window_state & Qt::WindowFullScreen) {
+ QTLWExtra *top = topData();
+
+ if (q->isWindow()) {
+ // We need to update these flags when we remove the full screen state
+ // or the frame will not be updated
+ UINT style = top->savedFlags;
+ if (q->isVisible())
+ style |= WS_VISIBLE;
+ SetWindowLongA(q->internalWinId(), GWL_STYLE, style);
+
+ UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
+ if (data.window_state & Qt::WindowActive)
+ swpf |= SWP_NOACTIVATE;
+ SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, swpf);
+ updateFrameStrut();
+ }
+ data.window_state &= ~Qt::WindowFullScreen;
+ topData()->savedFlags = 0;
+ }
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
+ const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)
+ && GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED;
+
+ if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event
+ if (q->internalWinId())
+ qWinRequestConfig(q->internalWinId(), isMove ? 2 : 1, x, y, w, h);
+ } else {
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen))
+ q->setAttribute(Qt::WA_WState_ConfigPending);
+ if (q->windowType() == Qt::Desktop) {
+ data.crect.setRect(x, y, w, h);
+ } else if (q->isWindow()) {
+ QRect fs(frameStrut());
+ if (extra) {
+ fs.setLeft(x - fs.left());
+ fs.setTop(y - fs.top());
+ fs.setRight((x + w - 1) + fs.right());
+ fs.setBottom((y + h - 1) + fs.bottom());
+ }
+ if (w == 0 || h == 0) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ data.crect = QRect(x, y, w, h);
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+
+ // put the window in its place and show it
+ MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true);
+ RECT rect;
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ GetClientRect(q->internalWinId(), &rect);
+ data.crect.setRect(x, y, rect.right - rect.left, rect.bottom - rect.top);
+ } else {
+ data.crect.setRect(x, y, w, h);
+ }
+
+ show_sys();
+ } else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+#ifndef Q_OS_WINCE
+ // If the window is hidden and in maximized state or minimized, instead of moving the
+ // window, set the normal position of the window.
+ WINDOWPLACEMENT wndpl;
+ GetWindowPlacement(q->internalWinId(), &wndpl);
+ if ((wndpl.showCmd == SW_MAXIMIZE && !IsWindowVisible(q->internalWinId())) || wndpl.showCmd == SW_SHOWMINIMIZED) {
+ RECT normal = {fs.x(), fs.y(), fs.x()+fs.width(), fs.y()+fs.height()};
+ wndpl.rcNormalPosition = normal;
+ wndpl.showCmd = wndpl.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
+ SetWindowPlacement(q->internalWinId(), &wndpl);
+ } else {
+#else
+ if (data.window_state_internal & Qt::WindowMaximized) {
+ qt_wince_maximize(q);
+ } else {
+#endif
+ if (!isTranslucentWindow)
+ MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true);
+ else if (isMove && !isResize)
+ SetWindowPos(q->internalWinId(), 0, fs.x(), fs.y(), 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
+ }
+ if (!q->isVisible())
+ InvalidateRect(q->internalWinId(), 0, FALSE);
+ RECT rect;
+ // If the layout has heightForWidth, the MoveWindow() above can
+ // change the size/position, so refresh them.
+
+ if (isTranslucentWindow) {
+ data.crect.setRect(x, y, w, h);
+ } else {
+ GetClientRect(q->internalWinId(), &rect);
+ RECT rcNormalPosition ={0};
+ // Use (0,0) as window position for embedded ActiveQt controls.
+ if (!tlwExtra || !tlwExtra->embedded)
+ GetWindowRect(q->internalWinId(), &rcNormalPosition);
+ QRect fStrut(frameStrut());
+ data.crect.setRect(rcNormalPosition.left + fStrut.left(),
+ rcNormalPosition.top + fStrut.top(),
+ rect.right - rect.left,
+ rect.bottom - rect.top);
+ isResize = data.crect.size() != oldSize;
+ }
+ } else {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+ data.crect.setRect(x, y, w, h);
+ }
+ } else {
+ QRect oldGeom(data.crect);
+ data.crect.setRect(x, y, w, h);
+ if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
+ // Top-level resize optimization does not work for native child widgets;
+ // disable it for this particular widget.
+ if (inTopLevelResize)
+ tlwExtra->inTopLevelResize = false;
+
+ if (!isResize)
+ moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, oldSize);
+
+ if (inTopLevelResize)
+ tlwExtra->inTopLevelResize = true;
+ }
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWSGeometry();
+ }
+ q->setAttribute(Qt::WA_WState_ConfigPending, false);
+ }
+
+ if (q->isWindow() && q->isVisible() && isResize && !inTopLevelResize) {
+ invalidateBuffer(q->rect()); //after the resize
+ }
+
+ // Process events immediately rather than in translateConfigEvent to
+ // avoid windows message process delay.
+ if (q->isVisible()) {
+ if (isMove && q->pos() != oldPos) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ // If we have a backing store with static contents, we have to disable the top-level
+ // resize optimization in order to get invalidated regions for resized widgets.
+ // The optimization discards all invalidateBuffer() calls since we're going to
+ // repaint everything anyways, but that's not the case with static contents.
+ const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
+ && !extra->topextra->inTopLevelResize
+ && (!extra->topextra->backingStore
+ || !extra->topextra->backingStore->hasStaticContents());
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = true;
+ QResizeEvent e(q->size(), oldSize);
+ QApplication::sendEvent(q, &e);
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = false;
+ }
+ } else {
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+}
+
+bool QWidgetPrivate::shouldShowMaximizeButton()
+{
+ if (data.window_flags & Qt::MSWindowsFixedSizeDialogHint)
+ return false;
+ if (extra) {
+ if ((extra->maxw && extra->maxw != QWIDGETSIZE_MAX && extra->maxw != QLAYOUTSIZE_MAX)
+ || (extra->maxh && extra->maxh != QWIDGETSIZE_MAX && extra->maxh != QLAYOUTSIZE_MAX))
+ return false;
+ }
+ return data.window_flags & Qt::WindowMaximizeButtonHint;
+}
+
+void QWidgetPrivate::winUpdateIsOpaque()
+{
+#ifndef Q_OS_WINCE
+ Q_Q(QWidget);
+
+ if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground))
+ return;
+
+ if ((data.window_flags & Qt::FramelessWindowHint) == 0)
+ return;
+
+ if (!isOpaque && ptrUpdateLayeredWindowIndirect) {
+ SetWindowLongA(q->internalWinId(), GWL_EXSTYLE,
+ GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED);
+ } else {
+ SetWindowLongA(q->internalWinId(), GWL_EXSTYLE,
+ GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED);
+ }
+#endif
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+#ifndef Q_OS_WINCE_WM
+ Q_Q(QWidget);
+ if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) {
+ int style = GetWindowLongA(q->internalWinId(), GWL_STYLE);
+ if (shouldShowMaximizeButton())
+ style |= WS_MAXIMIZEBOX;
+ else
+ style &= ~WS_MAXIMIZEBOX;
+ SetWindowLongA(q->internalWinId(), GWL_STYLE, style);
+ }
+#endif
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+ scrollChildren(dx, dy);
+
+ if (!paintOnScreen()) {
+ scrollRect(q->rect(), dx, dy);
+ } else {
+ UINT flags = SW_INVALIDATE;
+ if (!q->testAttribute(Qt::WA_OpaquePaintEvent))
+ flags |= SW_ERASE;
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ ScrollWindowEx(q->internalWinId(), dx, dy, 0, 0, 0, 0, flags);
+ UpdateWindow(q->internalWinId());
+ }
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ Q_Q(QWidget);
+
+ if (!paintOnScreen()) {
+ scrollRect(r, dx, dy);
+ } else {
+ RECT wr;
+ wr.top = r.top();
+ wr.left = r.left();
+ wr.bottom = r.bottom()+1;
+ wr.right = r.right()+1;
+
+ UINT flags = SW_INVALIDATE;
+ if (!q->testAttribute(Qt::WA_OpaquePaintEvent))
+ flags |= SW_ERASE;
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ ScrollWindowEx(q->internalWinId(), dx, dy, &wr, &wr, 0, 0, flags);
+ UpdateWindow(q->internalWinId());
+ }
+}
+
+extern Q_GUI_EXPORT HDC qt_win_display_dc();
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else {
+ HDC gdc = qt_win_display_dc();
+ switch (m) {
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ if (d->extra && d->extra->customDpiX)
+ val = d->extra->customDpiX;
+ else if (d->parent)
+ val = static_cast<QWidget *>(d->parent)->metric(m);
+ else
+ val = GetDeviceCaps(gdc, LOGPIXELSX);
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ if (d->extra && d->extra->customDpiY)
+ val = d->extra->customDpiY;
+ else if (d->parent)
+ val = static_cast<QWidget *>(d->parent)->metric(m);
+ else
+ val = GetDeviceCaps(gdc, LOGPIXELSY);
+ break;
+ case PdmWidthMM:
+ val = data->crect.width()
+ * GetDeviceCaps(gdc, HORZSIZE)
+ / GetDeviceCaps(gdc, HORZRES);
+ break;
+ case PdmHeightMM:
+ val = data->crect.height()
+ * GetDeviceCaps(gdc, VERTSIZE)
+ / GetDeviceCaps(gdc, VERTRES);
+ break;
+ case PdmNumColors:
+ if (GetDeviceCaps(gdc, RASTERCAPS) & RC_PALETTE)
+ val = GetDeviceCaps(gdc, SIZEPALETTE);
+ else {
+ HDC hd = d->hd ? HDC(d->hd) : gdc;
+ int bpp = GetDeviceCaps(hd, BITSPIXEL);
+ if (bpp == 32)
+ val = INT_MAX; // ### this is bogus, it should be 2^24 colors for 32 bit as well
+ else if(bpp<=8)
+ val = GetDeviceCaps(hd, NUMCOLORS);
+ else
+ val = 1 << (bpp * GetDeviceCaps(hd, PLANES));
+ }
+ break;
+ case PdmDepth:
+ val = GetDeviceCaps(gdc, BITSPIXEL);
+ break;
+ default:
+ val = 0;
+ qWarning("QWidget::metric: Invalid metric command");
+ }
+ }
+ return val;
+}
+
+#ifndef Q_OS_WINCE
+void QWidgetPrivate::createSysExtra()
+{
+#ifndef QT_NO_DRAGANDDROP
+ extra->dropTarget = 0;
+#endif
+#ifndef QT_NO_DIRECT3D
+ extra->had_auto_fill_bg = 0;
+ extra->had_paint_on_screen = 0;
+ extra->had_no_system_bg = 0;
+#endif
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+}
+#endif //Q_OS_WINCE
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ extra->topextra->winIconSmall = 0;
+ extra->topextra->winIconBig = 0;
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ if (extra->topextra->winIconSmall)
+ DestroyIcon(extra->topextra->winIconSmall);
+ if (extra->topextra->winIconBig)
+ DestroyIcon(extra->topextra->winIconBig);
+}
+
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_Q(QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created))
+ return;
+ // Enablement is defined by d->extra->dropTarget != 0.
+ if (on) {
+ // Turn on.
+ createExtra();
+#ifndef QT_NO_DRAGANDDROP
+ if (!q->internalWinId())
+ q->nativeParentWidget()->d_func()->createExtra();
+ QWExtra *extra = extraData();
+ if (!extra->dropTarget)
+ extra->dropTarget = registerOleDnd(q);
+#endif
+ } else {
+ // Turn off.
+ QWExtra *extra = extraData();
+#ifndef QT_NO_DRAGANDDROP
+ if (extra && extra->dropTarget) {
+ unregisterOleDnd(q, extra->dropTarget);
+ extra->dropTarget = 0;
+ }
+#endif
+ }
+}
+
+#ifndef QT_NO_DRAGANDDROP
+QOleDropTarget* QWidgetPrivate::registerOleDnd(QWidget *widget)
+{
+ QOleDropTarget *dropTarget = new QOleDropTarget(widget);
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ if (!widget->internalWinId()) {
+ QWidget *nativeParent = widget->nativeParentWidget();
+ Q_ASSERT(nativeParent);
+ QWExtra *nativeExtra = nativeParent->d_func()->extra;
+ Q_ASSERT(nativeExtra);
+ if (!nativeParent->acceptDrops())
+ nativeParent->setAcceptDrops(true);
+ if (!nativeExtra->oleDropWidgets.contains(widget))
+ nativeExtra->oleDropWidgets.append(widget);
+ if (!nativeExtra->dropTarget) {
+ nativeExtra->dropTarget = registerOleDnd(nativeParent);
+ Q_ASSERT(nativeExtra->dropTarget);
+#ifndef Q_OS_WINCE
+ CoLockObjectExternal(nativeExtra->dropTarget, false, true);
+#endif
+ RegisterDragDrop(nativeParent->internalWinId(), nativeExtra->dropTarget);
+ }
+ } else {
+ RegisterDragDrop(widget->internalWinId(), dropTarget);
+#ifndef Q_OS_WINCE
+ CoLockObjectExternal(dropTarget, true, true);
+#endif
+ }
+ return dropTarget;
+}
+
+void QWidgetPrivate::unregisterOleDnd(QWidget *widget, QOleDropTarget *dropTarget)
+{
+ dropTarget->releaseQt();
+ dropTarget->Release();
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ if (!widget->internalWinId()) {
+ QWidget *nativeParent = widget->nativeParentWidget();
+ Q_ASSERT(nativeParent);
+ QWExtra *nativeExtra = nativeParent->d_func()->extra;
+ Q_ASSERT(nativeExtra);
+ nativeExtra->oleDropWidgets.removeAll(widget);
+ nativeExtra->oleDropWidgets.removeAll(static_cast<QWidget *>(0));
+ if (nativeExtra->oleDropWidgets.isEmpty() && nativeExtra->dropTarget
+ && !nativeParent->testAttribute(Qt::WA_DropSiteRegistered)) {
+#ifndef Q_OS_WINCE
+ CoLockObjectExternal(nativeExtra->dropTarget, false, true);
+#endif
+ RevokeDragDrop(nativeParent->internalWinId());
+ nativeExtra->dropTarget = 0;
+ }
+ } else {
+#ifndef Q_OS_WINCE
+ CoLockObjectExternal(dropTarget, false, true);
+#endif
+ RevokeDragDrop(widget->internalWinId());
+ }
+}
+
+#endif //QT_NO_DRAGANDDROP
+
+// from qregion_win.cpp
+extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom);
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_Q(QWidget);
+ if (!q->internalWinId())
+ return;
+
+ if (region.isEmpty()) {
+ SetWindowRgn(q->internalWinId(), 0, true);
+ return;
+ }
+
+ // Since SetWindowRegion takes ownership, and we need to translate,
+ // we take a copy.
+ HRGN wr = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0);
+ CombineRgn(wr, region.handle(), 0, RGN_COPY);
+
+ QPoint offset = (q->isWindow()
+ ? frameStrut().topLeft()
+ : QPoint(0, 0));
+ OffsetRgn(wr, offset.x(), offset.y());
+
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ SetWindowRgn(data.winid, wr, true);
+}
+
+void QWidgetPrivate::updateFrameStrut()
+{
+ Q_Q(QWidget);
+
+ if (!q->testAttribute(Qt::WA_WState_Created))
+ return;
+
+ if (!q->internalWinId()) {
+ data.fstrut_dirty = false;
+ return;
+ }
+
+ RECT rect = {0,0,0,0};
+
+ QTLWExtra *top = topData();
+ uint exstyle = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_EXSTYLE),
+ GetWindowLongA(q->internalWinId(), GWL_EXSTYLE));
+ uint style = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_STYLE),
+ GetWindowLongA(q->internalWinId(), GWL_STYLE));
+#ifndef Q_OS_WINCE
+ if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) {
+#else
+ if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) {
+#endif
+ top->frameStrut.setCoords(-rect.left, -rect.top, rect.right, rect.bottom);
+ data.fstrut_dirty = false;
+ }
+}
+
+#ifndef Q_OS_WINCE
+void QWidgetPrivate::setWindowOpacity_sys(qreal level)
+{
+ Q_Q(QWidget);
+
+ if (!isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)) {
+ if (GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) {
+ Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), Q_AC_SRC_ALPHA};
+ Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA, NULL};
+ (*ptrUpdateLayeredWindowIndirect)(q->internalWinId(), &info);
+ }
+ return;
+ }
+
+ static bool function_resolved = false;
+ if (!function_resolved) {
+ ptrSetLayeredWindowAttributes =
+ (PtrSetLayeredWindowAttributes) QLibrary::resolve(QLatin1String("user32"),
+ "SetLayeredWindowAttributes");
+ function_resolved = true;
+ }
+
+ if (!ptrSetLayeredWindowAttributes)
+ return;
+
+ int wl = GetWindowLongA(q->internalWinId(), GWL_EXSTYLE);
+
+ if (level != 1.0) {
+ if ((wl&Q_WS_EX_LAYERED) == 0)
+ SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl|Q_WS_EX_LAYERED);
+ } else if (wl&Q_WS_EX_LAYERED) {
+ SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED);
+ }
+ (*ptrSetLayeredWindowAttributes)(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA);
+}
+#endif //Q_OS_WINCE
+
+// class QGlobalRasterPaintEngine: public QRasterPaintEngine
+// {
+// public:
+// inline QGlobalRasterPaintEngine() : QRasterPaintEngine() { setFlushOnEnd(false); }
+// };
+// Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine)
+
+#ifndef QT_NO_DIRECT3D
+static void cleanup_d3d_engine();
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QDirect3DPaintEngine, _qt_d3dEngine,
+ {
+ qAddPostRoutine(cleanup_d3d_engine);
+ })
+static void cleanup_d3d_engine()
+{
+ _qt_d3dEngine()->cleanup();
+}
+QDirect3DPaintEngine* qt_d3dEngine()
+{
+ return _qt_d3dEngine();
+}
+#endif
+
+
+#ifndef QT_NO_DIRECTDRAW
+static uchar *qt_primary_surface_bits;
+static int qt_primary_surface_stride;
+static QImage::Format qt_primary_surface_format;
+
+void qt_win_initialize_directdraw()
+{
+ HRESULT res;
+
+ // Some initialization...
+ if (!qt_ddraw_object) {
+ res = DirectDrawCreate(0, &qt_ddraw_object, 0);
+
+ if (res != DD_OK)
+ qWarning("DirectDrawCreate failed: %d", res);
+
+ qt_ddraw_object->SetCooperativeLevel(0, DDSCL_NORMAL);
+
+ DDSURFACEDESC surfaceDesc;
+ memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC));
+
+ surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ surfaceDesc.dwFlags = DDSD_CAPS;
+ surfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ res = qt_ddraw_object->CreateSurface(&surfaceDesc, &qt_ddraw_primary, 0);
+ if (res != DD_OK)
+ qWarning("CreateSurface failed: %d", res);
+
+ memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC));
+ surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ res = qt_ddraw_primary->Lock(0, &surfaceDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0);
+ if (res != DD_OK)
+ qWarning("Locking surface failed: %d", res);
+
+ if (surfaceDesc.ddpfPixelFormat.dwFlags == DDPF_RGB) {
+ qt_primary_surface_bits = (uchar *) surfaceDesc.lpSurface;
+ qt_primary_surface_stride = surfaceDesc.lPitch;
+ qt_primary_surface_format = QImage::Format_RGB32;
+ } else {
+ qWarning("QWidget painting: unsupported device depth for onscreen painting...\n");
+ }
+
+ qt_ddraw_primary->Unlock(0);
+ }
+}
+
+class QOnScreenRasterPaintEngine : public QRasterPaintEngine
+{
+public:
+ // The image allocated here leaks... Fix if this code is ifdef'ed
+ // in
+ QOnScreenRasterPaintEngine()
+ : QRasterPaintEngine(new QImage(qt_primary_surface_bits,
+ qApp->desktop()->width(),
+ qApp->desktop()->height(),
+ qt_primary_surface_stride,
+ qt_primary_surface_format))
+ {
+ device = static_cast<QImage *>(d_func()->device);
+ }
+
+ bool begin(QPaintDevice *)
+ {
+ QRegion clip = systemClip();
+ originalSystemClip = clip;
+ clip.translate(widget->mapToGlobal(QPoint(0, 0)));
+ setSystemClip(clip);
+
+ QRect bounds = clip.boundingRect();
+ DDSURFACEDESC surface;
+ surface.dwSize = sizeof(DDSURFACEDESC);
+ HRESULT res = qt_ddraw_primary->Lock((RECT *) &bounds, &surface, DDLOCK_WAIT, 0);
+ if (res != DD_OK) {
+ qWarning("QWidget painting: locking onscreen bits failed: %d\n", res);
+ return false;
+ }
+
+ if (surface.lpSurface == qt_primary_surface_bits) {
+ qt_primary_surface_bits = (uchar *) surface.lpSurface;
+ device->data_ptr()->data = qt_primary_surface_bits;
+ }
+
+ return QRasterPaintEngine::begin(device);
+ }
+
+ bool end()
+ {
+ HRESULT res = qt_ddraw_primary->Unlock(0);
+ if (res != DD_OK)
+ qWarning("QWidget::paint, failed to unlock DirectDraw surface: %d", res);
+ bool ok = QRasterPaintEngine::end();
+ setSystemClip(originalSystemClip);
+ return ok;
+ }
+
+ QPoint coordinateOffset() const {
+ return -widget->mapToGlobal(QPoint(0, 0));
+ }
+
+ const QWidget *widget;
+ QImage *device;
+ QRegion originalSystemClip;
+};
+Q_GLOBAL_STATIC(QOnScreenRasterPaintEngine, onScreenPaintEngine)
+#else
+void qt_win_initialize_directdraw() { }
+#endif
+
+QPaintEngine *QWidget::paintEngine() const
+{
+#ifndef QT_NO_DIRECT3D
+ if ((qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)
+ || testAttribute(Qt::WA_MSWindowsUseDirect3D))
+ && qt_d3dEngine()->hasDirect3DSupport())
+ {
+ QDirect3DPaintEngine *engine = qt_d3dEngine();
+ if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault))
+ engine->setFlushOnEnd(false);
+ else
+ engine->setFlushOnEnd(true);
+ return engine;
+ }
+#endif
+#ifndef QT_NO_DIRECTDRAW
+ QOnScreenRasterPaintEngine *pe = onScreenPaintEngine();
+ pe->widget = this;
+ return pe;
+#endif
+
+ // We set this bit which is checked in setAttribute for
+ // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
+ //
+ // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
+ // windows which would mean suddenly their widgets stop working.
+ //
+ // 2. Users set paint on screen and subclass paintEngine() to
+ // return 0, in which case we have a "hole" in the backingstore
+ // allowing use of GDI or DirectX directly.
+ //
+ // 1 is WRONG, but to minimize silent failures, we have set this
+ // bit to ignore the setAttribute call. 2. needs to be
+ // supported because its our only means of embeddeding native
+ // graphics stuff.
+ const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
+
+ return 0;
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ Q_Q(QWidget);
+#ifndef QT_NO_DIRECT3D
+ extern QDirect3DPaintEngine *qt_d3dEngine();
+ if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) && (q->windowOpacity() == 1.0f)
+ && qt_d3dEngine()->hasDirect3DSupport()) {
+ return new QD3DWindowSurface(q);
+ }
+#endif
+ return new QRasterWindowSurface(q);
+}
+
+void QWidgetPrivate::setModal_sys()
+{
+}
+
+
+
+
+QT_END_NAMESPACE
+
+#ifdef Q_OS_WINCE
+# include "qwidget_wince.cpp"
+#endif
diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp
new file mode 100644
index 0000000000..bb9681e486
--- /dev/null
+++ b/src/gui/kernel/qwidget_wince.cpp
@@ -0,0 +1,707 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef Q_OS_WINCE
+
+#include "qguifunctions_wince.h"
+
+QT_BEGIN_NAMESPACE
+
+const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp
+extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+
+//#define TABLET_DEBUG
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
+ | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#define PACKETMODE 0
+
+typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
+typedef BOOL (API *PtrWTClose)(HCTX);
+typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
+typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
+typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
+typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
+typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
+typedef int (API *PtrWTQueueSizeGet)(HCTX);
+typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
+
+static void qt_tablet_init_wce();
+static void qt_tablet_cleanup_wce();
+
+static void qt_tablet_init_wce() {
+ static bool firstTime = true;
+ if (!firstTime)
+ return;
+ firstTime = false;
+ qt_tablet_widget = new QWidget(0);
+ qt_tablet_widget->createWinId();
+ qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget"));
+ LOGCONTEXT lcMine;
+ qAddPostRoutine(qt_tablet_cleanup_wce);
+ struct tagAXIS tpOri[3];
+ if (ptrWTInfo && ptrWTOpen && ptrWTQueueSizeGet && ptrWTQueueSizeSet) {
+ // make sure we have WinTab
+ if (!ptrWTInfo(0, 0, NULL)) {
+#ifdef TABLET_DEBUG
+ qWarning("QWidget: Wintab services not available");
+#endif
+ return;
+ }
+
+ // some tablets don't support tilt, check if it is possible,
+ qt_tablet_tilt_support = ptrWTInfo(WTI_DEVICES, DVC_ORIENTATION, &tpOri);
+ if (qt_tablet_tilt_support) {
+ // check for azimuth and altitude
+ qt_tablet_tilt_support = tpOri[0].axResolution && tpOri[1].axResolution;
+ }
+ // build our context from the default context
+ ptrWTInfo(WTI_DEFSYSCTX, 0, &lcMine);
+ // Go for the raw coordinates, the tablet event will return good stuff
+ lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
+ lcMine.lcPktData = PACKETDATA;
+ lcMine.lcPktMode = PACKETMODE;
+ lcMine.lcMoveMask = PACKETDATA;
+ lcMine.lcOutOrgX = 0;
+ lcMine.lcOutExtX = lcMine.lcInExtX;
+ lcMine.lcOutOrgY = 0;
+ lcMine.lcOutExtY = -lcMine.lcInExtY;
+ qt_tablet_context = ptrWTOpen(qt_tablet_widget->winId(), &lcMine, true);
+#ifdef TABLET_DEBUG
+ qDebug("Tablet is %p", qt_tablet_context);
+#endif
+ if (!qt_tablet_context) {
+#ifdef TABLET_DEBUG
+ qWarning("QWidget: Failed to open the tablet");
+#endif
+ return;
+ }
+ // Set the size of the Packet Queue to the correct size...
+ int currSize = ptrWTQueueSizeGet(qt_tablet_context);
+ if (!ptrWTQueueSizeSet(qt_tablet_context, QT_TABLET_NPACKETQSIZE)) {
+ // Ideally one might want to use a smaller
+ // multiple, but for now, since we managed to destroy
+ // the existing Q with the previous call, set it back
+ // to the other size, which should work. If not,
+ // there will be trouble.
+ if (!ptrWTQueueSizeSet(qt_tablet_context, currSize)) {
+ Q_ASSERT_X(0, "Qt::Internal", "There is no packet queue for"
+ " the tablet. The tablet will not work");
+ }
+ }
+ }
+}
+
+static void qt_tablet_cleanup_wce() {
+ if (ptrWTClose)
+ ptrWTClose(qt_tablet_context);
+ delete qt_tablet_widget;
+ qt_tablet_widget = 0;
+}
+
+
+// The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move,
+// resize and setGeometry requests for a widget that is already
+// processing a config event. The purpose is to avoid recursion.
+//
+void qWinRequestConfig(WId, int, int, int, int, int);
+
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) {
+ Q_Q(QWidget);
+ static int sw = -1, sh = -1;
+
+ Qt::WindowType type = q->windowType();
+ Qt::WindowFlags flags = data.window_flags;
+
+ bool topLevel = (flags & Qt::Window);
+ bool popup = (type == Qt::Popup);
+ bool dialog = (type == Qt::Dialog
+ || type == Qt::Sheet
+ || (flags & Qt::MSWindowsFixedSizeDialogHint));
+ bool desktop = (type == Qt::Desktop);
+ bool tool = (type == Qt::Tool || type == Qt::Drawer);
+
+ HINSTANCE appinst = qWinAppInst();
+ HWND parentw, destroyw = 0;
+ WId id;
+
+ QString windowClassName = qt_reg_winclass(q);
+
+ if (!window) // always initialize
+ initializeWindow = true;
+
+ if (popup)
+ flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
+
+ if (flags & (Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowContextHelpButtonHint)) {
+ flags |= Qt::WindowSystemMenuHint;
+ flags |= Qt::WindowTitleHint;
+ flags &= ~Qt::FramelessWindowHint;
+ }
+
+ if (sw < 0) { // get the (primary) screen size
+ sw = GetSystemMetrics(SM_CXSCREEN);
+ sh = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ if (desktop) { // desktop widget
+ popup = false; // force this flags off
+ data.crect.setRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
+ }
+
+ parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0;
+
+#ifdef UNICODE
+ QString title;
+ const TCHAR *ttitle = 0;
+#endif
+ QByteArray title95;
+ int style = WS_CHILD;
+ int exsty = WS_EX_NOPARENTNOTIFY;
+
+ if (topLevel) {
+ if (!(flags & Qt::FramelessWindowHint) && !tool)
+ style = (WS_OVERLAPPED) | WS_SYSMENU;
+ else
+ style = WS_POPUP;
+ if ((type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
+ style = WS_POPUP;
+ exsty |= WS_EX_NOANIMATION;
+ } else {
+ if (flags & Qt::WindowTitleHint)
+ style |= WS_CAPTION;
+ if (flags & Qt::WindowSystemMenuHint)
+ style |= WS_SYSMENU;
+ if (flags & Qt::WindowContextHelpButtonHint)
+ exsty |= WS_EX_CONTEXTHELP;
+#ifndef Q_OS_WINCE_WM
+ if (flags & Qt::WindowMinimizeButtonHint)
+ style |= WS_MINIMIZEBOX;
+ if (shouldShowMaximizeButton())
+ style |= WS_MAXIMIZEBOX;
+#endif
+ if (tool)
+ exsty |= WS_EX_TOOLWINDOW;
+ }
+ }
+ if (dialog) {
+ style = WS_BORDER | WS_CAPTION;
+ if (flags & Qt::WindowOkButtonHint)
+ exsty |= WS_EX_CAPTIONOKBTN;
+ if (flags & Qt::WindowCancelButtonHint || flags & Qt::WA_DeleteOnClose)
+ style |= WS_SYSMENU;
+ if (flags & Qt::WindowContextHelpButtonHint)
+ exsty |= WS_EX_CONTEXTHELP;
+ }
+ if (popup) {
+ style = WS_POPUP;
+ exsty |= WS_EX_NOANIMATION;
+ }
+
+ if (flags & Qt::WindowTitleHint) {
+ QT_WA({
+ title = q->isWindow() ? qAppName() : q->objectName();
+ ttitle = (TCHAR*)title.utf16();
+ } , {
+ title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1();
+ });
+ }
+
+ // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
+ // qapplication_win.cpp. We switch it off temporarily to avoid move
+ // and resize events during creationt
+ q->setAttribute(Qt::WA_WState_Created, false);
+
+ if (window) { // override the old window
+ if (destroyOldWindow)
+ destroyw = data.winid;
+ id = window;
+ setWinId(window);
+ LONG res = SetWindowLongA(window, GWL_STYLE, style);
+ if (!res)
+ qErrnoWarning("QWidget::create: Failed to set window style");
+
+ res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc );
+
+ if (!res)
+ qErrnoWarning("QWidget::create: Failed to set window procedure");
+ } else if (desktop) { // desktop widget
+ id = GetDesktopWindow();
+ if (!id) { //Create a dummy desktop
+ RECT r;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+ const TCHAR *cname = reinterpret_cast<const TCHAR *> (windowClassName.utf16());
+ id = CreateWindow(cname, ttitle, style,
+ r.left, r.top, r.right - r.left, r.bottom - r.top,
+ 0, 0, appinst, 0);
+ }
+ setWinId(id);
+ } else if (topLevel) { // create top-level widget
+ const bool wasMoved = q->testAttribute(Qt::WA_Moved);
+
+ int x, y;
+ if (qt_wince_is_mobile()) {
+ x = wasMoved ? data.crect.left() : CW_USEDEFAULT;
+ y = wasMoved ? data.crect.top() : CW_USEDEFAULT;
+ } else {
+ x = wasMoved ? data.crect.left() : 100;
+ y = wasMoved ? data.crect.top() : 100;
+ }
+
+ int w = CW_USEDEFAULT;
+ int h = CW_USEDEFAULT;
+
+ // Adjust for framestrut when needed
+ RECT rect = {0,0,0,0};
+ if (AdjustWindowRectEx(&rect, style, FALSE, exsty)) {
+ QTLWExtra *td = maybeTopData();
+ if (wasMoved && (td && !td->posFromMove)) {
+ x = data.crect.x() + rect.left;
+ y = data.crect.y() + rect.top;
+ }
+
+ if (q->testAttribute(Qt::WA_Resized)) {
+ w = data.crect.width() + (rect.right - rect.left);
+ h = data.crect.height() + (rect.bottom - rect.top);
+ }
+ }
+
+ const TCHAR *cname = reinterpret_cast<const TCHAR *> (windowClassName.utf16());
+ id = CreateWindowEx(exsty, cname, ttitle, style,
+ x, y, w, h,
+ 0, 0, appinst, 0);
+
+ if (!id)
+ qErrnoWarning("QWidget::create: Failed to create window");
+ setWinId(id);
+ if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip))
+ SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+ } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
+ QT_WA({
+ const TCHAR *cname = (TCHAR*)windowClassName.utf16();
+ id = CreateWindowEx(exsty, cname, ttitle, style,
+ data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
+ parentw, NULL, appinst, NULL);
+ } , {
+ id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
+ data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
+ parentw, NULL, appinst, NULL);
+ });
+ if (!id)
+ qErrnoWarning("QWidget::create: Failed to create window");
+ SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ setWinId(id);
+ }
+
+ if (desktop) {
+ q->setAttribute(Qt::WA_WState_Visible);
+ } else if (topLevel) {
+ RECT cr;
+ GetClientRect(id, &cr);
+ // one cannot trust cr.left and cr.top, use a correction POINT instead
+ POINT pt;
+ pt.x = 0;
+ pt.y = 0;
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen) || q->testAttribute(Qt::WA_Moved))
+ ClientToScreen(id, &pt);
+ data.crect = QRect(QPoint(pt.x, pt.y),
+ QPoint(pt.x + cr.right - 1, pt.y + cr.bottom - 1));
+
+ if (data.fstrut_dirty) {
+ // be nice to activeqt
+ updateFrameStrut();
+ }
+ }
+
+ q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
+ hd = 0; // no display context
+
+ if (window) { // got window from outside
+ if (IsWindowVisible(window))
+ q->setAttribute(Qt::WA_WState_Visible);
+ else
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ }
+
+ if (extra && !extra->mask.isEmpty())
+ setMask_sys(extra->mask);
+
+#if defined(QT_NON_COMMERCIAL)
+ QT_NC_WIDGET_CREATE
+#endif
+
+ if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->inputContext()->setFocusWidget(q);
+
+ if (destroyw) {
+ DestroyWindow(destroyw);
+ }
+
+ if (q != qt_tablet_widget && QWidgetPrivate::mapper)
+ qt_tablet_init_wce();
+
+ if (q->testAttribute(Qt::WA_DropSiteRegistered))
+ registerDropSite(true);
+
+ if (maybeTopData() && maybeTopData()->opacity != 255)
+ q->setWindowOpacity(maybeTopData()->opacity/255.);
+
+ if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
+ Q_ASSERT(q->internalWinId());
+ ShowWindow(q->internalWinId(), SW_SHOW);
+ }
+}
+
+/*
+ \internal
+ Platform-specific part of QWidget::show().
+*/
+void QWidgetPrivate::show_sys() {
+ Q_Q(QWidget);
+#if defined(QT_NON_COMMERCIAL)
+ QT_NC_SHOW_WINDOW
+#endif
+ if (q->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+
+ q->setAttribute(Qt::WA_Mapped);
+
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+
+ int sm = SW_SHOW;
+ bool fakedMaximize = false;
+ if (q->isWindow()) {
+#ifndef Q_OS_WINCE_WM
+ if (q->isMinimized()) {
+ sm = SW_SHOWMINIMIZED;
+ } else if (q->isMaximized()) {
+ sm = SW_SHOWMAXIMIZED;
+ // Windows will not behave correctly when we try to maximize a window which does not
+ // have minimize nor maximize buttons in the window frame. Windows would then ignore
+ // non-available geometry, and rather maximize the widget to the full screen, minus the
+ // window frame (caption). So, we do a trick here, by adding a maximize button before
+ // maximizing the widget, and then remove the maximize button afterwards.
+ Qt::WindowFlags &flags = data.window_flags;
+ if (flags & Qt::WindowTitleHint &&
+ !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
+ fakedMaximize = TRUE;
+ int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
+ SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX);
+ }
+ } else
+#endif
+ if (q->isHidden()) {
+ sm = SW_HIDE;
+ }
+ }
+ if (q->testAttribute(Qt::WA_ShowWithoutActivating)
+ || (q->windowType() == Qt::Popup)
+ || (q->windowType() == Qt::ToolTip)
+ || (q->windowType() == Qt::Tool)) {
+ sm = SW_SHOWNOACTIVATE;
+ }
+
+ if (!(data.window_state & Qt::WindowMinimized))
+ ShowWindow(q->internalWinId(), sm);
+
+ if (q->isMaximized() && q->isWindow())
+ qt_wince_maximize(q);
+
+#ifndef Q_OS_WINCE_WM
+ if (!qt_wince_is_mobile() && q->isFullScreen()) {
+ HWND handle = FindWindow(L"HHTaskBar", L"");
+ if (handle) {
+ ShowWindow(handle, 0);
+ EnableWindow(handle, false);
+ }
+ }
+
+ if (fakedMaximize) {
+ int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
+ SetWindowLong(q->internalWinId(), GWL_STYLE, style & ~WS_MAXIMIZEBOX);
+ SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
+ | SWP_FRAMECHANGED);
+ }
+#else
+ Q_UNUSED(fakedMaximize);
+#endif
+
+ if (q->isWindow() && sm == SW_SHOW)
+ SetForegroundWindow(q->internalWinId());
+
+ invalidateBuffer(q->rect());
+}
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+
+ int max = SW_SHOWNORMAL;
+ int min = SW_SHOWNOACTIVATE;
+
+ int normal = SW_SHOWNOACTIVATE;
+
+ if ((oldstate & Qt::WindowMinimized) && !(newstate & Qt::WindowMinimized))
+ newstate |= Qt::WindowActive;
+ if (newstate & Qt::WindowActive) {
+ max = SW_SHOWNORMAL;
+ min = SW_SHOWNORMAL;
+ normal = SW_SHOWNORMAL;
+ }
+ if (isWindow()) {
+ createWinId();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ data->window_state_internal = newstate;
+ // Ensure the initial size is valid, since we store it as normalGeometry below.
+ if ((!testAttribute(Qt::WA_Resized) && !isVisible()))
+ adjustSize();
+ if (!d->topData()->normalGeometry.isValid()) {
+ if (newstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen))
+ d->topData()->normalGeometry = geometry();
+ if (newstate & Qt::WindowMinimized && !(oldstate & Qt::WindowFullScreen))
+ d->topData()->normalGeometry = geometry();
+ }
+ if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
+ if (!(newstate & Qt::WindowMaximized)) {
+ int style = GetWindowLongW(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION;
+ SetWindowLong(internalWinId(), GWL_STYLE, style);
+ SetWindowLong(internalWinId(), GWL_EXSTYLE, GetWindowLong (internalWinId(), GWL_EXSTYLE) & ~ WS_EX_NODRAG);
+ }
+ if (isVisible() && newstate & Qt::WindowMaximized)
+ qt_wince_maximize(this);
+ if (isVisible() && !(newstate & Qt::WindowMinimized)) {
+ ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
+ if (!(newstate & Qt::WindowFullScreen)) {
+ QRect r = d->topData()->normalGeometry;
+ if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) {
+ if (pos() != r.topLeft() || size() !=r.size()) {
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ setGeometry(r);
+ }
+ }
+ } else {
+ d->updateFrameStrut();
+ }
+ }
+ }
+ if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
+ if (newstate & Qt::WindowFullScreen) {
+ if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
+ d->topData()->normalGeometry = geometry();
+ d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE);
+ UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
+ if (isVisible())
+ style |= WS_VISIBLE;
+ SetWindowLongA(internalWinId(), GWL_STYLE, style);
+ QRect r = qApp->desktop()->screenGeometry(this);
+ UINT swpf = SWP_FRAMECHANGED;
+ if (newstate & Qt::WindowActive)
+ swpf |= SWP_NOACTIVATE;
+ qt_wince_full_screen(internalWinId(), true, swpf);
+ d->updateFrameStrut();
+ } else {
+ UINT style = d->topData()->savedFlags;
+ if (isVisible())
+ style |= WS_VISIBLE;
+ SetWindowLongA(internalWinId(), GWL_STYLE, style);
+ UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
+ if (newstate & Qt::WindowActive)
+ swpf |= SWP_NOACTIVATE;
+ qt_wince_full_screen(internalWinId(), false, swpf);
+ d->updateFrameStrut();
+
+ // preserve maximized state
+ if (isVisible()) {
+ ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
+ if (newstate & Qt::WindowMaximized)
+ qt_wince_maximize(this);
+ }
+ if (!(newstate & Qt::WindowMaximized)) {
+ QRect r = d->topData()->normalGeometry;
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ if (r.isValid())
+ setGeometry(r);
+ }
+ }
+ }
+ if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
+ if (isVisible()) {
+ ShowWindow(internalWinId(), (newstate & Qt::WindowMinimized) ? min :
+ (newstate & Qt::WindowMaximized) ? max : normal);
+ if (newstate & Qt::WindowMaximized)
+ qt_wince_maximize(this);
+ if (newstate & Qt::WindowMinimized)
+ qt_wince_minimize(internalWinId());
+ }
+ }
+ if ((newstate & Qt::WindowMaximized) && !(newstate & Qt::WindowFullScreen)) {
+ QRect r = d->topData()->normalGeometry;
+#ifdef Q_OS_WINCE_WM
+ if (!inherits("QDialog") && !inherits("QMdiArea") && !isVisible()) {
+ d->data.crect.setRect(0, 0, -1, -1);
+ }
+#else
+ qt_wince_maximize(this);
+#endif
+ }
+ }
+ data->window_state = newstate;
+ data->window_state_internal = newstate;
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+
+void QWidgetPrivate::createSysExtra() {
+#ifndef QT_NO_DRAGANDDROP
+ extra->dropTarget = 0;
+#endif
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+ Q_Q(QWidget);
+ if (!qt_wince_is_mobile() && q->isFullScreen()) {
+ HWND handle = FindWindow(L"HHTaskBar", L"");
+ if (handle) {
+ ShowWindow(handle, 1);
+ EnableWindow(handle, true);
+ }
+ }
+}
+
+void QWidgetPrivate::setWindowOpacity_sys(qreal level) {
+ Q_UNUSED(level);
+ return;
+}
+
+// The procedure does nothing, but is required for mousegrabbing to work
+LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) {
+ Q_UNUSED(nCode);
+ Q_UNUSED(wParam);
+ Q_UNUSED(lParam);
+ return 0;
+}
+
+void QWidget::grabMouse() {
+ if (!qt_nograb()) {
+ if (mouseGrb)
+ mouseGrb->releaseMouse();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ SetCapture(internalWinId());
+ mouseGrb = this;
+ }
+}
+
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor) {
+ if (!qt_nograb()) {
+ if (mouseGrb)
+ mouseGrb->releaseMouse();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ SetCapture(internalWinId());
+ mouseGrbCur = new QCursor(cursor);
+ SetCursor(mouseGrbCur->handle());
+ mouseGrb = this;
+ }
+}
+#endif
+
+void QWidget::releaseMouse() {
+ if (!qt_nograb() && mouseGrb == this) {
+ ReleaseCapture();
+ if (journalRec) {
+ journalRec = 0;
+ }
+ if (mouseGrbCur) {
+ delete mouseGrbCur;
+ mouseGrbCur = 0;
+ }
+ mouseGrb = 0;
+ }
+}
+
+void QWidget::show()
+{
+ Qt::WindowFlags flags = windowFlags() & 0xff;
+ int threshold = qApp->autoMaximizeThreshold();
+ if ((threshold < 0) || (windowState() & Qt::WindowFullScreen) || (windowState() & Qt::WindowMaximized)) {
+ setVisible(true);
+ return;
+ }
+ int height = sizeHint().height();
+ int screenHeight = (qreal(threshold) / 100.0f * qApp->desktop()->screenGeometry(this).height());
+ bool maximize = height > screenHeight;
+ if (!maximize) {
+ // If we do not maximize yet we check the widget and its child widgets whether they are
+ //vertically expanding. If one of the widgets is expanding we maximize.
+ QList<QWidget *> list = findChildren<QWidget *>();
+ bool expandingChild = sizePolicy().verticalPolicy () == QSizePolicy::Expanding;
+ for (int i = 0; (i < list.size()) && !expandingChild; ++i) {
+ expandingChild = list.at(i)->sizePolicy().verticalPolicy () == QSizePolicy::Expanding;
+ }
+ maximize = expandingChild;
+ }
+ if ((minimumSizeHint().height() > qApp->desktop()->screenGeometry(this).height()) || (minimumSizeHint().width() > qApp->desktop()->screenGeometry(this).width()))
+ maximize = false;
+
+ if ((flags == Qt::Window || flags == Qt::Dialog) && maximize) {
+ setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
+ | Qt::WindowMaximized);
+ setVisible(true);
+ }
+ else {
+ setVisible(true);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif Q_OS_WINCE
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
new file mode 100644
index 0000000000..a12b50c2e8
--- /dev/null
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -0,0 +1,2891 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevent.h"
+#include "qwidget.h"
+#include "qdesktopwidget.h"
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qnamespace.h"
+#include "qpainter.h"
+#include "qbitmap.h"
+#include "qlayout.h"
+#include "qtextcodec.h"
+#include "qdatetime.h"
+#include "qcursor.h"
+#include "qstack.h"
+#include "qcolormap.h"
+#include "qdebug.h"
+#include "qmenu.h"
+#include "private/qmenu_p.h"
+#include "private/qbackingstore_p.h"
+#include "private/qwindowsurface_x11_p.h"
+
+//extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp
+
+#include <private/qpixmap_x11_p.h>
+#include <private/qpaintengine_x11_p.h>
+#include "qt_x11_p.h"
+#include "qx11info_x11.h"
+
+#include <stdlib.h>
+
+//#define ALIEN_DEBUG
+
+// defined in qapplication_x11.cpp
+//bool qt_wstate_iconified(WId);
+//void qt_updated_rootinfo();
+
+
+#if !defined(QT_NO_IM)
+#include "qinputcontext.h"
+#include "qinputcontextfactory.h"
+#endif
+
+#include "qwidget_p.h"
+
+#define XCOORD_MAX 16383
+#define WRECT_MAX 8191
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_nograb();
+
+QWidget *QWidgetPrivate::mouseGrabber = 0;
+QWidget *QWidgetPrivate::keyboardGrabber = 0;
+
+void qt_net_remove_user_time(QWidget *tlw);
+void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
+
+int qt_x11_create_desktop_on_screen = -1;
+
+extern void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
+
+// MWM support
+struct QtMWMHints {
+ ulong flags, functions, decorations;
+ long input_mode;
+ ulong status;
+};
+
+enum {
+ MWM_HINTS_FUNCTIONS = (1L << 0),
+
+ MWM_FUNC_ALL = (1L << 0),
+ MWM_FUNC_RESIZE = (1L << 1),
+ MWM_FUNC_MOVE = (1L << 2),
+ MWM_FUNC_MINIMIZE = (1L << 3),
+ MWM_FUNC_MAXIMIZE = (1L << 4),
+ MWM_FUNC_CLOSE = (1L << 5),
+
+ MWM_HINTS_DECORATIONS = (1L << 1),
+
+ MWM_DECOR_ALL = (1L << 0),
+ MWM_DECOR_BORDER = (1L << 1),
+ MWM_DECOR_RESIZEH = (1L << 2),
+ MWM_DECOR_TITLE = (1L << 3),
+ MWM_DECOR_MENU = (1L << 4),
+ MWM_DECOR_MINIMIZE = (1L << 5),
+ MWM_DECOR_MAXIMIZE = (1L << 6),
+
+ MWM_HINTS_INPUT_MODE = (1L << 2),
+
+ MWM_INPUT_MODELESS = 0L,
+ MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
+ MWM_INPUT_FULL_APPLICATION_MODAL = 3L
+};
+
+
+static QtMWMHints GetMWMHints(Display *display, Window window)
+{
+ QtMWMHints mwmhints;
+
+ Atom type;
+ int format;
+ ulong nitems, bytesLeft;
+ uchar *data = 0;
+ if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
+ ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
+ &data) == Success)
+ && (type == ATOM(_MOTIF_WM_HINTS)
+ && format == 32
+ && nitems >= 5)) {
+ mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
+ } else {
+ mwmhints.flags = 0L;
+ mwmhints.functions = MWM_FUNC_ALL;
+ mwmhints.decorations = MWM_DECOR_ALL;
+ mwmhints.input_mode = 0L;
+ mwmhints.status = 0L;
+ }
+
+ if (data)
+ XFree(data);
+
+ return mwmhints;
+}
+
+static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints)
+{
+ if (mwmhints.flags != 0l) {
+ XChangeProperty(display, window, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
+ PropModeReplace, (unsigned char *) &mwmhints, 5);
+ } else {
+ XDeleteProperty(display, window, ATOM(_MOTIF_WM_HINTS));
+ }
+}
+
+// Returns true if we should set WM_TRANSIENT_FOR on \a w
+static inline bool isTransient(const QWidget *w)
+{
+ return ((w->windowType() == Qt::Dialog
+ || w->windowType() == Qt::Sheet
+ || w->windowType() == Qt::Tool
+ || w->windowType() == Qt::SplashScreen
+ || w->windowType() == Qt::ToolTip
+ || w->windowType() == Qt::Drawer
+ || w->windowType() == Qt::Popup)
+ && !w->testAttribute(Qt::WA_X11BypassTransientForHint));
+}
+
+static void do_size_hints(QWidget* widget, QWExtra *x);
+
+/*****************************************************************************
+ QWidget member functions
+ *****************************************************************************/
+
+const uint stdWidgetEventMask = // X event mask
+ (uint)(
+ KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ KeymapStateMask |
+ ButtonMotionMask | PointerMotionMask |
+ EnterWindowMask | LeaveWindowMask |
+ FocusChangeMask |
+ ExposureMask |
+ PropertyChangeMask |
+ StructureNotifyMask
+ );
+
+const uint stdDesktopEventMask = // X event mask
+ (uint)(
+ KeymapStateMask |
+ EnterWindowMask | LeaveWindowMask |
+ PropertyChangeMask
+ );
+
+
+/*
+ The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
+*/
+
+Window qt_XCreateWindow(const QWidget *creator,
+ Display *display, Window parent,
+ int x, int y, uint w, uint h,
+ int borderwidth, int depth,
+ uint windowclass, Visual *visual,
+ ulong valuemask, XSetWindowAttributes *attributes);
+Window qt_XCreateSimpleWindow(const QWidget *creator,
+ Display *display, Window parent,
+ int x, int y, uint w, uint h, int borderwidth,
+ ulong border, ulong background);
+void qt_XDestroyWindow(const QWidget *destroyer,
+ Display *display, Window window);
+
+
+static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
+{
+ if (!scrolled_widget->isWindow() && !scrolled_widget->internalWinId())
+ return;
+ QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
+ X11->sip_list.append(sip);
+
+ XClientMessageEvent client_message;
+ client_message.type = ClientMessage;
+ client_message.window = scrolled_widget->internalWinId();
+ client_message.format = 32;
+ client_message.message_type = ATOM(_QT_SCROLL_DONE);
+ client_message.data.l[0] = sip.id;
+
+ XSendEvent(X11->display, scrolled_widget->internalWinId(), False, NoEventMask,
+ (XEvent*)&client_message);
+}
+
+static int qt_sip_count(QWidget* scrolled_widget)
+{
+ int sips=0;
+
+ for (int i = 0; i < X11->sip_list.size(); ++i) {
+ const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
+ if (sip.scrolled_widget == scrolled_widget)
+ sips++;
+ }
+
+ return sips;
+}
+
+static void create_wm_client_leader()
+{
+ if (X11->wm_client_leader) return;
+
+ X11->wm_client_leader =
+ XCreateSimpleWindow(X11->display,
+ QX11Info::appRootWindow(),
+ 0, 0, 1, 1, 0, 0, 0);
+
+ // set client leader property to itself
+ XChangeProperty(X11->display,
+ X11->wm_client_leader, ATOM(WM_CLIENT_LEADER),
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)&X11->wm_client_leader, 1);
+
+#ifndef QT_NO_SESSIONMANAGER
+ // If we are session managed, inform the window manager about it
+ QByteArray session = qApp->sessionId().toLatin1();
+ if (!session.isEmpty()) {
+ XChangeProperty(X11->display,
+ X11->wm_client_leader, ATOM(SM_CLIENT_ID),
+ XA_STRING, 8, PropModeReplace,
+ (unsigned char *)session.data(), session.size());
+ }
+#endif
+}
+
+/*!
+ \internal
+ Update the X11 cursor of the widget w.
+ \a force is true if this function is called from dispatchEnterLeave, it means that the
+ mouse is actually directly under this widget.
+ */
+void qt_x11_enforce_cursor(QWidget * w, bool force)
+{
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ return;
+
+ static QPointer<QWidget> lastUnderMouse = 0;
+ if (force) {
+ lastUnderMouse = w;
+ } else if (lastUnderMouse && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
+ w = lastUnderMouse;
+ } else if (!w->internalWinId()) {
+ return; //the mouse is not under this widget, and it's not native, so don't change it
+ }
+
+ while (!w->internalWinId() && w->parentWidget() && !w->isWindow() && !w->testAttribute(Qt::WA_SetCursor))
+ w = w->parentWidget();
+
+ QWidget *nativeParent = w;
+ if (!w->internalWinId())
+ nativeParent = w->nativeParentWidget();
+ // This does the same as effectiveWinId(), but since it is possible
+ // to not have a native parent widget due to a special hack in
+ // qwidget for reparenting widgets to a different X11 screen,
+ // added additional check to make sure native parent widget exists.
+ if (!nativeParent || !nativeParent->internalWinId())
+ return;
+ WId winid = nativeParent->internalWinId();
+
+ if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
+#ifndef QT_NO_CURSOR
+ QCursor *oc = QApplication::overrideCursor();
+ if (oc) {
+ XDefineCursor(X11->display, winid, oc->handle());
+ } else if (w->isEnabled()) {
+ XDefineCursor(X11->display, winid, w->cursor().handle());
+ } else {
+ // enforce the windows behavior of clearing the cursor on
+ // disabled widgets
+ XDefineCursor(X11->display, winid, XNone);
+ }
+#endif
+ } else {
+ XDefineCursor(X11->display, winid, XNone);
+ }
+}
+
+Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
+{
+ qt_x11_enforce_cursor(w, false);
+}
+
+
+Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
+{
+ if (!w || (!w->isWindow() && !w->internalWinId()))
+ return;
+ QApplication::flush();
+ XEvent ev;
+ QTime t;
+ t.start();
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ return;
+ while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) {
+ if (XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev))
+ break;
+ if (t.elapsed() > 500)
+ return; // give up, no event available
+ qApp->syncX(); // non-busy wait
+ }
+ qApp->x11ProcessEvent(&ev);
+ if (XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ConfigureNotify, &ev))
+ qApp->x11ProcessEvent(&ev);
+}
+
+void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
+{
+ if (!w->isVisible()) // not managed by the window manager
+ return;
+
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = ATOM(_NET_WM_STATE);
+ e.xclient.display = X11->display;
+ e.xclient.window = w->internalWinId();
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = set ? 1 : 0;
+ e.xclient.data.l[1] = one;
+ e.xclient.data.l[2] = two;
+ e.xclient.data.l[3] = 0;
+ e.xclient.data.l[4] = 0;
+ XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()),
+ false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
+}
+
+struct QX11WindowAttributes {
+ const XWindowAttributes *att;
+};
+
+void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a)
+{
+ QX11WindowAttributes att;
+ att.att = &a;
+ qt_x11_getX11InfoForWindow(xinfo,att);
+}
+
+
+static QVector<Atom> getNetWmState(QWidget *w)
+{
+ QVector<Atom> returnValue;
+
+ // Don't read anything, just get the size of the property data
+ Atom actualType;
+ int actualFormat;
+ ulong propertyLength;
+ ulong bytesLeft;
+ uchar *propertyData = 0;
+ if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, 0,
+ False, XA_ATOM, &actualType, &actualFormat,
+ &propertyLength, &bytesLeft, &propertyData) == Success
+ && actualType == XA_ATOM && actualFormat == 32) {
+ returnValue.resize(bytesLeft / 4);
+ XFree((char*) propertyData);
+
+ // fetch all data
+ if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0,
+ returnValue.size(), False, XA_ATOM, &actualType, &actualFormat,
+ &propertyLength, &bytesLeft, &propertyData) != Success) {
+ returnValue.clear();
+ } else if (propertyLength != (ulong)returnValue.size()) {
+ returnValue.resize(propertyLength);
+ }
+
+ // put it into netWmState
+ if (!returnValue.isEmpty()) {
+ memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
+ }
+ XFree((char*) propertyData);
+ }
+
+ return returnValue;
+}
+
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+ Qt::WindowType type = q->windowType();
+ Qt::WindowFlags &flags = data.window_flags;
+ QWidget *parentWidget = q->parentWidget();
+
+ if (type == Qt::ToolTip)
+ flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
+ if (type == Qt::Popup)
+ flags |= Qt::X11BypassWindowManagerHint;
+
+ bool topLevel = (flags & Qt::Window);
+ bool popup = (type == Qt::Popup);
+ bool dialog = (type == Qt::Dialog
+ || type == Qt::Sheet);
+ bool desktop = (type == Qt::Desktop);
+ bool tool = (type == Qt::Tool || type == Qt::SplashScreen
+ || type == Qt::ToolTip || type == Qt::Drawer);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::create_sys START:" << q << "topLevel?" << topLevel << "WId:"
+ << window << "initializeWindow:" << initializeWindow << "destroyOldWindow" << destroyOldWindow;
+#endif
+ if (topLevel) {
+ if (parentWidget) { // if our parent stays on top, so must we
+ QWidget *ptl = parentWidget->window();
+ if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
+ flags |= Qt::WindowStaysOnTopHint;
+ }
+
+ if (type == Qt::SplashScreen) {
+ if (X11->isSupportedByWM(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
+ flags &= ~Qt::X11BypassWindowManagerHint;
+ } else {
+ flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
+ }
+ }
+ // All these buttons depend on the system menu, so we enable it
+ if (flags & (Qt::WindowMinimizeButtonHint
+ | Qt::WindowMaximizeButtonHint
+ | Qt::WindowContextHelpButtonHint))
+ flags |= Qt::WindowSystemMenuHint;
+ }
+
+
+ Window parentw, destroyw = 0;
+ WId id = 0;
+
+ // always initialize
+ if (!window)
+ initializeWindow = true;
+
+ if (desktop &&
+ qt_x11_create_desktop_on_screen >= 0 &&
+ qt_x11_create_desktop_on_screen != xinfo.screen()) {
+ // desktop on a certain screen other than the default requested
+ QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen];
+ xinfo.setX11Data(xd);
+ } else if (parentWidget && parentWidget->d_func()->xinfo.screen() != xinfo.screen()) {
+ xinfo = parentWidget->d_func()->xinfo;
+ }
+
+ //get display, screen number, root window and desktop geometry for
+ //the current screen
+ Display *dpy = X11->display;
+ int scr = xinfo.screen();
+ Window root_win = RootWindow(dpy, scr);
+ int sw = DisplayWidth(dpy,scr);
+ int sh = DisplayHeight(dpy,scr);
+
+ if (desktop) { // desktop widget
+ dialog = popup = false; // force these flags off
+ data.crect.setRect(0, 0, sw, sh);
+ } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
+ int width = sw / 2;
+ int height = 4 * sh / 10;
+ if (extra) {
+ width = qMax(qMin(width, extra->maxw), extra->minw);
+ height = qMax(qMin(height, extra->maxh), extra->minh);
+ }
+ data.crect.setSize(QSize(width, height));
+ }
+
+ parentw = topLevel ? root_win : parentWidget->effectiveWinId();
+
+ XSetWindowAttributes wsa;
+
+ if (window) { // override the old window
+ if (destroyOldWindow) {
+ if (topLevel)
+ X11->dndEnable(q, false);
+ destroyw = data.winid;
+ }
+ id = window;
+ setWinId(window);
+ XWindowAttributes a;
+ XGetWindowAttributes(dpy, window, &a);
+ data.crect.setRect(a.x, a.y, a.width, a.height);
+
+ if (a.map_state == IsUnmapped)
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ else
+ q->setAttribute(Qt::WA_WState_Visible);
+
+ qt_x11_getX11InfoForWindow(&xinfo,a);
+
+ } else if (desktop) { // desktop widget
+#ifdef QWIDGET_EXTRA_DEBUG
+ qDebug() << "create desktop";
+#endif
+ id = (WId)parentw; // id = root window
+// QWidget *otherDesktop = find(id); // is there another desktop?
+// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
+// otherDesktop->d->setWinId(0); // remove id from widget mapper
+// d->setWinId(id); // make sure otherDesktop is
+// otherDesktop->d->setWinId(id); // found first
+// } else {
+ setWinId(id);
+// }
+ } else if (topLevel || q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) {
+#ifdef QWIDGET_EXTRA_DEBUG
+ static int topLevels = 0;
+ static int children = 0;
+ if (parentw == root_win)
+ qDebug() << "create toplevel" << ++topLevels;
+ else
+ qDebug() << "create child" << ++children;
+#endif
+ QRect safeRect = data.crect; //##### must handle huge sizes as well.... i.e. wrect
+ if (safeRect.width() < 1|| safeRect.height() < 1) {
+ if (topLevel) {
+ // top-levels must be at least 1x1
+ safeRect.setSize(safeRect.size().expandedTo(QSize(1, 1)));
+ } else {
+ // create it way off screen, and rely on
+ // setWSGeometry() to do the right thing with it later
+ safeRect = QRect(-1000,-1000,1,1);
+ }
+ }
+#ifndef QT_NO_XRENDER
+ int screen = xinfo.screen();
+ if (topLevel && X11->use_xrender
+ && xinfo.depth() != 32 && X11->argbVisuals[screen]
+ && q->testAttribute(Qt::WA_TranslucentBackground))
+ {
+ QX11InfoData *xd = xinfo.getX11Data(true);
+
+ xd->screen = screen;
+ xd->visual = X11->argbVisuals[screen];
+ xd->colormap = X11->argbColormaps[screen];
+ xd->depth = 32;
+ xd->defaultVisual = false;
+ xd->defaultColormap = false;
+ xd->cells = xd->visual->map_entries;
+ xinfo.setX11Data(xd);
+ }
+#endif
+ if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
+ id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
+ safeRect.left(), safeRect.top(),
+ safeRect.width(), safeRect.height(),
+ 0,
+ BlackPixel(dpy, xinfo.screen()),
+ WhitePixel(dpy, xinfo.screen()));
+ } else {
+ wsa.background_pixel = WhitePixel(dpy, xinfo.screen());
+ wsa.border_pixel = BlackPixel(dpy, xinfo.screen());
+ wsa.colormap = xinfo.colormap();
+ id = (WId)qt_XCreateWindow(q, dpy, parentw,
+ safeRect.left(), safeRect.top(),
+ safeRect.width(), safeRect.height(),
+ 0, xinfo.depth(), InputOutput,
+ (Visual *) xinfo.visual(),
+ CWBackPixel|CWBorderPixel|CWColormap,
+ &wsa);
+ }
+
+ setWinId(id); // set widget id/handle + hd
+ }
+
+#ifndef QT_NO_XRENDER
+ if (picture) {
+ XRenderFreePicture(X11->display, picture);
+ picture = 0;
+ }
+
+ if (X11->use_xrender && !desktop && q->internalWinId()) {
+ XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual());
+ if (format)
+ picture = XRenderCreatePicture(dpy, id, format, 0, 0);
+ }
+#endif // QT_NO_XRENDER
+
+ QtMWMHints mwmhints;
+ mwmhints.flags = 0L;
+ mwmhints.functions = 0L;
+ mwmhints.decorations = 0;
+ mwmhints.input_mode = 0L;
+ mwmhints.status = 0L;
+
+ if (topLevel) {
+ ulong wsa_mask = 0;
+ if (type != Qt::SplashScreen) { // && customize) {
+ mwmhints.flags |= MWM_HINTS_DECORATIONS;
+
+ bool customize = flags & Qt::CustomizeWindowHint;
+ if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
+ mwmhints.decorations |= MWM_DECOR_BORDER;
+ mwmhints.decorations |= MWM_DECOR_RESIZEH;
+
+ if (flags & Qt::WindowTitleHint)
+ mwmhints.decorations |= MWM_DECOR_TITLE;
+
+ if (flags & Qt::WindowSystemMenuHint)
+ mwmhints.decorations |= MWM_DECOR_MENU;
+
+ if (flags & Qt::WindowMinimizeButtonHint) {
+ mwmhints.decorations |= MWM_DECOR_MINIMIZE;
+ mwmhints.functions |= MWM_FUNC_MINIMIZE;
+ }
+
+ if (flags & Qt::WindowMaximizeButtonHint) {
+ mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
+ mwmhints.functions |= MWM_FUNC_MAXIMIZE;
+ }
+
+ if (flags & Qt::WindowCloseButtonHint)
+ mwmhints.functions |= MWM_FUNC_CLOSE;
+ }
+ } else {
+ // if type == Qt::SplashScreen
+ mwmhints.decorations = MWM_DECOR_ALL;
+ }
+
+ if (tool) {
+ wsa.save_under = True;
+ wsa_mask |= CWSaveUnder;
+ }
+
+ if (flags & Qt::X11BypassWindowManagerHint) {
+ wsa.override_redirect = True;
+ wsa_mask |= CWOverrideRedirect;
+ }
+
+ if (wsa_mask && initializeWindow) {
+ Q_ASSERT(id);
+ XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
+ }
+
+ if (mwmhints.functions != 0) {
+ mwmhints.flags |= MWM_HINTS_FUNCTIONS;
+ mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
+ } else {
+ mwmhints.functions = MWM_FUNC_ALL;
+ }
+
+ if (!(flags & Qt::FramelessWindowHint)
+ && flags & Qt::CustomizeWindowHint
+ && flags & Qt::WindowTitleHint
+ && !(flags &
+ (Qt::WindowMinimizeButtonHint
+ | Qt::WindowMaximizeButtonHint
+ | Qt::WindowCloseButtonHint))) {
+ // a special case - only the titlebar without any button
+ mwmhints.flags = MWM_HINTS_FUNCTIONS;
+ mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
+ mwmhints.decorations = 0;
+ }
+ }
+
+ if (!initializeWindow) {
+ // do no initialization
+ } else if (popup) { // popup widget
+ // set EWMH window types
+ setNetWmWindowTypes();
+
+ wsa.override_redirect = True;
+ wsa.save_under = True;
+ Q_ASSERT(id);
+ XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
+ &wsa);
+ } else if (topLevel && !desktop) { // top-level widget
+ if (!X11->wm_client_leader)
+ create_wm_client_leader();
+
+ // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys()
+
+ XSizeHints size_hints;
+ size_hints.flags = USSize | PSize | PWinGravity;
+ size_hints.x = data.crect.left();
+ size_hints.y = data.crect.top();
+ size_hints.width = data.crect.width();
+ size_hints.height = data.crect.height();
+ size_hints.win_gravity =
+ QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
+
+ XWMHints wm_hints; // window manager hints
+ memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+ wm_hints.flags = InputHint | StateHint | WindowGroupHint;
+ wm_hints.input = True;
+ wm_hints.initial_state = NormalState;
+ wm_hints.window_group = X11->wm_client_leader;
+
+ XClassHint class_hint;
+ QByteArray appName = qAppName().toLatin1();
+ class_hint.res_name = appName.data(); // application name
+ class_hint.res_class = const_cast<char *>(QX11Info::appClass()); // application class
+
+ XSetWMProperties(dpy, id, 0, 0,
+ qApp->d_func()->argv, qApp->d_func()->argc,
+ &size_hints, &wm_hints, &class_hint);
+
+ XResizeWindow(dpy, id,
+ qBound(1, data.crect.width(), XCOORD_MAX),
+ qBound(1, data.crect.height(), XCOORD_MAX));
+ XStoreName(dpy, id, appName.data());
+ Atom protocols[4];
+ int n = 0;
+ protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
+ protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
+ protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
+ if (flags & Qt::WindowContextHelpButtonHint)
+ protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
+ XSetWMProtocols(dpy, id, protocols, n);
+
+ // set mwm hints
+ SetMWMHints(dpy, id, mwmhints);
+
+ // set EWMH window types
+ setNetWmWindowTypes();
+
+ // set _NET_WM_PID
+ long curr_pid = getpid();
+ XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &curr_pid, 1);
+
+ // when we create a toplevel widget, the frame strut should be dirty
+ data.fstrut_dirty = 1;
+
+ // declare the widget's window role
+ if (QTLWExtra *topData = maybeTopData()) {
+ if (!topData->role.isEmpty()) {
+ QByteArray windowRole = topData->role.toUtf8();
+ XChangeProperty(dpy, id,
+ ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
+ (unsigned char *)windowRole.constData(), windowRole.length());
+ }
+ }
+
+ // set client leader property
+ XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)&X11->wm_client_leader, 1);
+ } else {
+ // non-toplevel widgets don't have a frame, so no need to
+ // update the strut
+ data.fstrut_dirty = 0;
+ }
+
+ if (initializeWindow && q->internalWinId()) {
+ // don't erase when resizing
+ wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
+ Q_ASSERT(id);
+ XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
+ }
+
+ // set X11 event mask
+ if (desktop) {
+// QWidget* main_desktop = find(id);
+// if (main_desktop->testWFlags(Qt::WPaintDesktop))
+// XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
+// else
+ XSelectInput(dpy, id, stdDesktopEventMask);
+ } else if (q->internalWinId()) {
+ XSelectInput(dpy, id, stdWidgetEventMask);
+#if !defined (QT_NO_TABLET)
+ QTabletDeviceDataList *tablet_list = qt_tablet_devices();
+ if (X11->ptrXSelectExtensionEvent) {
+ for (int i = 0; i < tablet_list->size(); ++i) {
+ QTabletDeviceData tablet = tablet_list->at(i);
+ X11->ptrXSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList),
+ tablet.eventCount);
+ }
+ }
+#endif
+ }
+
+ if (desktop) {
+ q->setAttribute(Qt::WA_WState_Visible);
+ } else if (topLevel) { // set X cursor
+ if (initializeWindow) {
+ qt_x11_enforce_cursor(q);
+
+ if (QTLWExtra *topData = maybeTopData())
+ if (!topData->caption.isEmpty())
+ setWindowTitle_helper(topData->caption);
+
+ //always enable dnd: it's not worth the effort to maintain the state
+ // NOTE: this always creates topData()
+ X11->dndEnable(q, true);
+
+ if (maybeTopData() && maybeTopData()->opacity != 255)
+ q->setWindowOpacity(maybeTopData()->opacity/255.);
+
+ }
+ } else if (q->testAttribute(Qt::WA_SetCursor) && q->internalWinId()) {
+ qt_x11_enforce_cursor(q);
+ }
+
+ if (extra && !extra->mask.isEmpty() && q->internalWinId())
+ XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
+ extra->mask.handle(), ShapeSet);
+
+ if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
+ QInputContext *inputContext = q->inputContext();
+ if (inputContext)
+ inputContext->setFocusWidget(q);
+ }
+
+ if (destroyw)
+ qt_XDestroyWindow(q, dpy, destroyw);
+
+ // newly created windows are positioned at the window system's
+ // (0,0) position. If the parent uses wrect mapping to expand the
+ // coordinate system, we must also adjust this widget's window
+ // system position
+ if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
+ setWSGeometry();
+ else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0))
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+
+ if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
+ Q_ASSERT(q->internalWinId());
+ XMapWindow(X11->display, q->internalWinId());
+ // Ensure that mapped alien widgets are flushed immediately when re-created as native widgets.
+ if (QWindowSurface *surface = q->windowSurface())
+ surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint()));
+ }
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::create_sys END:" << q;
+#endif
+}
+
+void QWidgetPrivate::x11UpdateIsOpaque()
+{
+#ifndef QT_NO_XRENDER
+ Q_Q(QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
+ return;
+
+ bool topLevel = (data.window_flags & Qt::Window);
+ int screen = xinfo.screen();
+ if (topLevel && X11->use_xrender
+ && X11->argbVisuals[screen] && xinfo.depth() != 32) {
+ // recreate widget
+ QPoint pos = q->pos();
+ bool visible = q->isVisible();
+ if (visible)
+ q->hide();
+ q->setParent(q->parentWidget(), q->windowFlags() & ~Qt::WindowType_Mask);
+ q->move(pos);
+ if (visible)
+ q->show();
+ }
+#endif
+}
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(geometry());
+ d->deactivateWidgetCleanup();
+ if (testAttribute(Qt::WA_WState_Created)) {
+ setAttribute(Qt::WA_WState_Created, false);
+ QObjectList childList = children();
+ for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
+ register QObject *obj = childList.at(i);
+ if (obj->isWidgetType())
+ static_cast<QWidget*>(obj)->destroy(destroySubWindows,
+ destroySubWindows);
+ }
+ if (QWidgetPrivate::mouseGrabber == this)
+ releaseMouse();
+ if (QWidgetPrivate::keyboardGrabber == this)
+ releaseKeyboard();
+ if (isWindow())
+ X11->deferred_map.removeAll(this);
+ if (isModal()) {
+ // just be sure we leave modal
+ QApplicationPrivate::leaveModal(this);
+ }
+ else if ((windowType() == Qt::Popup))
+ qApp->d_func()->closePopup(this);
+
+#ifndef QT_NO_XRENDER
+ if (d->picture) {
+ if (destroyWindow)
+ XRenderFreePicture(X11->display, d->picture);
+ d->picture = 0;
+ }
+#endif // QT_NO_XRENDER
+
+ // delete the _NET_WM_USER_TIME_WINDOW
+ qt_net_remove_user_time(this);
+
+ if ((windowType() == Qt::Desktop)) {
+ if (acceptDrops())
+ X11->dndEnable(this, false);
+ } else {
+ if (isWindow())
+ X11->dndEnable(this, false);
+ if (destroyWindow)
+ qt_XDestroyWindow(this, X11->display, data->winid);
+ }
+ d->setWinId(0);
+
+ extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
+ if (testAttribute(Qt::WA_WState_Reparented))
+ qPRCleanup(this);
+
+ if(d->ic) {
+ delete d->ic;
+ } else {
+ // release previous focus information participating with
+ // preedit preservation of qic
+ QInputContext *qic = inputContext();
+ if (qic)
+ qic->widgetDestroyed(this);
+ }
+ }
+}
+
+void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent;
+#endif
+ QX11Info old_xinfo = xinfo;
+ if (parent && parent->windowType() == Qt::Desktop) {
+ // make sure the widget is created on the same screen as the
+ // programmer specified desktop widget
+ xinfo = parent->d_func()->xinfo;
+ parent = 0;
+ }
+
+ QTLWExtra *topData = maybeTopData();
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+ if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
+ q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+ extern void qPRCreate(const QWidget *, Window);
+#ifndef QT_NO_CURSOR
+ QCursor oldcurs;
+#endif
+
+ // dnd unregister (we will register again below)
+ if (q->testAttribute(Qt::WA_DropSiteRegistered))
+ q->setAttribute(Qt::WA_DropSiteRegistered, false);
+
+ // if we are a top then remove our dnd prop for now
+ // it will get rest later
+ if (q->isWindow() && wasCreated)
+ X11->dndEnable(q, false);
+
+ if (topData)
+ qt_net_remove_user_time(q);
+
+// QWidget *oldparent = q->parentWidget();
+ WId old_winid = wasCreated ? data.winid : 0;
+ if ((q->windowType() == Qt::Desktop))
+ old_winid = 0;
+ setWinId(0);
+
+#ifndef QT_NO_XRENDER
+ if (picture) {
+ XRenderFreePicture(X11->display, picture);
+ picture = 0;
+ }
+#endif
+
+ // hide and reparent our own window away. Otherwise we might get
+ // destroyed when emitting the child remove event below. See QWorkspace.
+ if (wasCreated && old_winid) {
+ XUnmapWindow(X11->display, old_winid);
+ if (!old_xinfo.screen() != xinfo.screen())
+ XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
+ }
+ if (topData) {
+ topData->parentWinId = 0;
+ // zero the frame strut and mark it dirty
+ topData->frameStrut.setCoords(0, 0, 0, 0);
+
+ // reparenting from top-level, make sure show() works again
+ topData->waitingForMapNotify = 0;
+ topData->validWMState = 0;
+ }
+ data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
+
+ QObjectPrivate::setParent_helper(parent);
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ 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)
+ if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
+ createWinId();
+ if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ if (wasCreated) {
+ QObjectList chlist = q->children();
+ for (int i = 0; i < chlist.size(); ++i) { // reparent children
+ QObject *obj = chlist.at(i);
+ if (obj->isWidgetType()) {
+ QWidget *w = (QWidget *)obj;
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ continue;
+ if (xinfo.screen() != w->d_func()->xinfo.screen()) {
+ // ### force setParent() to not shortcut out (because
+ // ### we're setting the parent to the current parent)
+ // ### setParent will add child back to the list
+ // ### of children so we need to make sure the
+ // ### widget won't be added twice.
+ w->d_func()->parent = 0;
+ this->children.removeOne(w);
+ w->setParent(q);
+ } else if (!w->isWindow()) {
+ w->d_func()->invalidateBuffer(w->rect());
+ if (w->internalWinId()) {
+ if (w->testAttribute(Qt::WA_NativeWindow)) {
+ QWidget *nativeParentWidget = w->nativeParentWidget();
+ // Qt::WA_NativeWindow ensures that we always have a nativeParentWidget
+ Q_ASSERT(nativeParentWidget != 0);
+ QPoint p = w->mapTo(nativeParentWidget, QPoint());
+ XReparentWindow(X11->display,
+ w->internalWinId(),
+ nativeParentWidget->internalWinId(),
+ p.x(), p.y());
+ } else {
+ w->d_func()->setParent_sys(q, w->data->window_flags);
+ }
+ }
+ } else if (isTransient(w)) {
+ /*
+ when reparenting toplevel windows with toplevel-transient children,
+ we need to make sure that the window manager gets the updated
+ WM_TRANSIENT_FOR information... unfortunately, some window managers
+ don't handle changing WM_TRANSIENT_FOR before the toplevel window is
+ visible, so we unmap and remap all toplevel-transient children *after*
+ the toplevel parent has been mapped. thankfully, this is easy in Qt :)
+
+ note that the WM_TRANSIENT_FOR hint is actually updated in
+ QWidgetPrivate::show_sys()
+ */
+ if (w->internalWinId())
+ XUnmapWindow(X11->display, w->internalWinId());
+ QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
+ }
+ }
+ }
+ qPRCreate(q, old_winid);
+ updateSystemBackground();
+
+ if (old_winid) {
+ Window *cmwret;
+ int count;
+ if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) {
+ Window *cmw;
+ int cmw_size = sizeof(Window)*count;
+ cmw = new Window[count];
+ memcpy((char *)cmw, (char *)cmwret, cmw_size);
+ XFree((char *)cmwret);
+ int i;
+ for (i=0; i<count; i++) {
+ if (cmw[i] == old_winid) {
+ cmw[i] = q->internalWinId();
+ break;
+ }
+ }
+ int top_count;
+ if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(),
+ &cmwret, &top_count))
+ {
+ Window *merged_cmw = new Window[count + top_count];
+ memcpy((char *)merged_cmw, (char *)cmw, cmw_size);
+ memcpy((char *)merged_cmw + cmw_size, (char *)cmwret, sizeof(Window)*top_count);
+ delete [] cmw;
+ XFree((char *)cmwret);
+ cmw = merged_cmw;
+ count += top_count;
+ }
+
+ XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count);
+ delete [] cmw;
+ }
+
+ qt_XDestroyWindow(q, X11->display, old_winid);
+ }
+ }
+
+ // check if we need to register our dropsite
+ if (q->testAttribute(Qt::WA_AcceptDrops)
+ || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) {
+ q->setAttribute(Qt::WA_DropSiteRegistered, true);
+ }
+#if !defined(QT_NO_IM)
+ ic = 0;
+#endif
+ invalidateBuffer(q->rect());
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::setParent_sys END" << q;
+#endif
+}
+
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ QPoint p = pos + data->crect.topLeft();
+ //cannot trust that !isWindow() implies parentWidget() before create
+ return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
+ }
+ int x, y;
+ Window child;
+ QPoint p = d->mapToWS(pos);
+ XTranslateCoordinates(X11->display, internalWinId(),
+ QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
+ p.x(), p.y(), &x, &y, &child);
+ return QPoint(x, y);
+}
+
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ //cannot trust that !isWindow() implies parentWidget() before create
+ QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
+ return p - data->crect.topLeft();
+ }
+ int x, y;
+ Window child;
+ XTranslateCoordinates(X11->display,
+ QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
+ internalWinId(), pos.x(), pos.y(), &x, &y, &child);
+ return d->mapFromWS(QPoint(x, y));
+}
+
+void QWidgetPrivate::updateSystemBackground()
+{
+ Q_Q(QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId())
+ return;
+ QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole());
+ Qt::WindowType type = q->windowType();
+ if (brush.style() == Qt::NoBrush
+ || q->testAttribute(Qt::WA_NoSystemBackground)
+ || q->testAttribute(Qt::WA_UpdatesDisabled)
+ || type == Qt::Popup || type == Qt::ToolTip
+ )
+ XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
+ else if (brush.style() == Qt::SolidPattern && brush.isOpaque())
+ XSetWindowBackground(X11->display, q->internalWinId(),
+ QColormap::instance(xinfo.screen()).pixel(brush.color()));
+ else if (isBackgroundInherited())
+ XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative);
+ else if (brush.style() == Qt::TexturePattern) {
+ extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
+ XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
+ static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data)->x11ConvertToDefaultDepth());
+ } else
+ XSetWindowBackground(X11->display, q->internalWinId(),
+ QColormap::instance(xinfo.screen()).pixel(brush.color()));
+}
+
+#ifndef QT_NO_CURSOR
+void QWidgetPrivate::setCursor_sys(const QCursor &)
+{
+ Q_Q(QWidget);
+ qt_x11_enforce_cursor(q);
+ XFlush(X11->display);
+}
+
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ qt_x11_enforce_cursor(q);
+ XFlush(X11->display);
+}
+#endif
+
+static XTextProperty*
+qstring_to_xtp(const QString& s)
+{
+ static XTextProperty tp = { 0, 0, 0, 0 };
+ static bool free_prop = true; // we can't free tp.value in case it references
+ // the data of the static QCString below.
+ if (tp.value) {
+ if (free_prop)
+ XFree(tp.value);
+ tp.value = 0;
+ free_prop = true;
+ }
+
+ static const QTextCodec* mapper = QTextCodec::codecForLocale();
+ int errCode = 0;
+ if (mapper) {
+ QByteArray mapped = mapper->fromUnicode(s);
+ char* tl[2];
+ tl[0] = mapped.data();
+ tl[1] = 0;
+ errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
+#if defined(QT_DEBUG)
+ if (errCode < 0)
+ qDebug("qstring_to_xtp result code %d", errCode);
+#endif
+ }
+ if (!mapper || errCode < 0) {
+ static QByteArray qcs;
+ qcs = s.toAscii();
+ tp.value = (uchar*)qcs.data();
+ tp.encoding = XA_STRING;
+ tp.format = 8;
+ tp.nitems = qcs.length();
+ free_prop = false;
+ }
+
+ // ### If we knew WM could understand unicode, we could use
+ // ### a much simpler, cheaper encoding...
+ /*
+ tp.value = (XChar2b*)s.unicode();
+ tp.encoding = XA_UNICODE; // wish
+ tp.format = 16;
+ tp.nitems = s.length();
+ */
+
+ return &tp;
+}
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (!q->internalWinId())
+ return;
+ XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
+
+ QByteArray net_wm_name = caption.toUtf8();
+ XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
+ PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
+}
+
+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 been set
+ return;
+
+ XWMHints *h = 0;
+ if (q->internalWinId())
+ h = XGetWMHints(X11->display, q->internalWinId());
+ XWMHints wm_hints;
+ if (!h) {
+ memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+ h = &wm_hints;
+ }
+
+ // preparing images to set the _NET_WM_ICON property
+ QIcon icon = q->windowIcon();
+ if (!icon.isNull()) {
+ QList<QSize> availableSizes = icon.availableSizes();
+ if(availableSizes.isEmpty()) {
+ // try to use default sizes since the icon can be a scalable image like svg.
+ availableSizes.push_back(QSize(16,16));
+ availableSizes.push_back(QSize(32,32));
+ availableSizes.push_back(QSize(64,64));
+ availableSizes.push_back(QSize(128,128));
+ }
+ QVector<long> icon_data;
+ for(int i = 0; i < availableSizes.size(); ++i) {
+ QSize size = availableSizes.at(i);
+ QPixmap pixmap = icon.pixmap(size);
+ if (!pixmap.isNull()) {
+ QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ int pos = icon_data.size();
+ icon_data.resize(pos + 2 + image.width()*image.height());
+ icon_data[pos++] = image.width();
+ icon_data[pos++] = image.height();
+ if (sizeof(long) == sizeof(quint32)) {
+ memcpy(icon_data.data() + pos, image.scanLine(0), image.numBytes());
+ } else {
+ for (int y = 0; y < image.height(); ++y) {
+ uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y));
+ for (int x = 0; x < image.width(); ++x)
+ icon_data[pos + y*image.width() + x] = scanLine[x];
+ }
+ }
+ }
+ }
+ if (!icon_data.isEmpty()) {
+ if (q->internalWinId()) {
+ XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *) icon_data.data(),
+ icon_data.size());
+ }
+ extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
+ /*
+ if the app is running on an unknown desktop, or it is not
+ using the default visual, convert the icon to 1bpp as stated
+ in the ICCCM section 4.1.2.4; otherwise, create the icon pixmap
+ in the default depth (even though this violates the ICCCM)
+ */
+ if (X11->desktopEnvironment == DE_UNKNOWN
+ || !QX11Info::appDefaultVisual(xinfo.screen())
+ || !QX11Info::appDefaultColormap(xinfo.screen())) {
+ // unknown DE or non-default visual/colormap, use 1bpp bitmap
+ if (!forceReset || !topData->iconPixmap)
+ topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
+ h->icon_pixmap = topData->iconPixmap->handle();
+ } else {
+ // default depth, use a normal pixmap (even though this
+ // violates the ICCCM), since this works on all DEs known to Qt
+ if (!forceReset || !topData->iconPixmap)
+ topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
+ h->icon_pixmap = static_cast<QX11PixmapData*>(topData->iconPixmap->data)->x11ConvertToDefaultDepth();
+ }
+ h->flags |= IconPixmapHint;
+ } else {
+ h->flags &= ~(IconPixmapHint | IconMaskHint);
+ }
+ }
+
+ if (q->internalWinId())
+ XSetWMHints(X11->display, q->internalWinId(), h);
+ if (h != &wm_hints)
+ XFree((char *)h);
+}
+
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_Q(QWidget);
+ if (!q->internalWinId())
+ return;
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
+
+ QByteArray icon_name = iconText.toUtf8();
+ XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
+ PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
+}
+
+
+void QWidget::grabMouse()
+{
+ if (isVisible() && !qt_nograb()) {
+ if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
+ QWidgetPrivate::mouseGrabber->releaseMouse();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+#ifndef QT_NO_DEBUG
+ int status =
+#endif
+ XGrabPointer(X11->display, effectiveWinId(), False,
+ (uint)(ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask |
+ LeaveWindowMask),
+ GrabModeAsync, GrabModeAsync,
+ XNone, XNone, X11->time);
+#ifndef QT_NO_DEBUG
+ if (status) {
+ const char *s =
+ status == GrabNotViewable ? "\"GrabNotViewable\"" :
+ status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
+ status == GrabFrozen ? "\"GrabFrozen\"" :
+ status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
+ "<?>";
+ qWarning("QWidget::grabMouse: Failed with %s", s);
+ }
+#endif
+ QWidgetPrivate::mouseGrabber = this;
+ }
+}
+
+
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ if (!qt_nograb()) {
+ if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
+ QWidgetPrivate::mouseGrabber->releaseMouse();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+#ifndef QT_NO_DEBUG
+ int status =
+#endif
+ XGrabPointer(X11->display, effectiveWinId(), False,
+ (uint)(ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask | LeaveWindowMask),
+ GrabModeAsync, GrabModeAsync,
+ XNone, cursor.handle(), X11->time);
+#ifndef QT_NO_DEBUG
+ if (status) {
+ const char *s =
+ status == GrabNotViewable ? "\"GrabNotViewable\"" :
+ status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
+ status == GrabFrozen ? "\"GrabFrozen\"" :
+ status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
+ "<?>";
+ qWarning("QWidget::grabMouse: Failed with %s", s);
+ }
+#endif
+ QWidgetPrivate::mouseGrabber = this;
+ }
+}
+#endif
+
+
+void QWidget::releaseMouse()
+{
+ if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
+ XUngrabPointer(X11->display, X11->time);
+ XFlush(X11->display);
+ QWidgetPrivate::mouseGrabber = 0;
+ }
+}
+
+
+void QWidget::grabKeyboard()
+{
+ if (!qt_nograb()) {
+ if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
+ QWidgetPrivate::keyboardGrabber->releaseKeyboard();
+ XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync,
+ X11->time);
+ QWidgetPrivate::keyboardGrabber = this;
+ }
+}
+
+
+void QWidget::releaseKeyboard()
+{
+ if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
+ XUngrabKeyboard(X11->display, X11->time);
+ QWidgetPrivate::keyboardGrabber = 0;
+ }
+}
+
+
+QWidget *QWidget::mouseGrabber()
+{
+ return QWidgetPrivate::mouseGrabber;
+}
+
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return QWidgetPrivate::keyboardGrabber;
+}
+
+void QWidget::activateWindow()
+{
+ Q_D(QWidget);
+ QWidget *tlw = window();
+ if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
+ if (X11->userTime == 0)
+ X11->userTime = X11->time;
+ qt_net_update_user_time(tlw, X11->userTime);
+ XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
+ d->focusInputContext();
+ }
+}
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ bool needShow = false;
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+ if (isWindow()) {
+ // Ensure the initial size is valid, since we store it as normalGeometry below.
+ if (!testAttribute(Qt::WA_Resized) && !isVisible())
+ adjustSize();
+
+ QTLWExtra *top = d->topData();
+
+ if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
+ if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
+ && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
+ if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
+ top->normalGeometry = geometry();
+ qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
+ ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
+ ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
+ } else if (! (newstate & Qt::WindowFullScreen)) {
+ if (newstate & Qt::WindowMaximized) {
+ // save original geometry
+ const QRect normalGeometry = geometry();
+
+ if (isVisible()) {
+ data->fstrut_dirty = true;
+ const QRect maxRect = QApplication::desktop()->availableGeometry(this);
+ const QRect r = top->normalGeometry;
+ const QRect fs = d->frameStrut();
+ setGeometry(maxRect.x() + fs.left(),
+ maxRect.y() + fs.top(),
+ maxRect.width() - fs.left() - fs.right(),
+ maxRect.height() - fs.top() - fs.bottom());
+ top->normalGeometry = r;
+ }
+
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ } else {
+ // restore original geometry
+ setGeometry(top->normalGeometry);
+ }
+ }
+ }
+
+ if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
+ if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
+ if (newstate & Qt::WindowFullScreen) {
+ top->normalGeometry = geometry();
+ top->fullScreenOffset = d->frameStrut().topLeft();
+ }
+ qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
+ ATOM(_NET_WM_STATE_FULLSCREEN));
+ } else {
+ needShow = isVisible();
+
+ if (newstate & Qt::WindowFullScreen) {
+ data->fstrut_dirty = true;
+ const QRect normalGeometry = geometry();
+ const QPoint fullScreenOffset = d->frameStrut().topLeft();
+
+ top->savedFlags = windowFlags();
+ setParent(0, Qt::Window | Qt::FramelessWindowHint);
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->screenGeometry(this));
+ top->normalGeometry = r;
+
+ if (top->normalGeometry.width() < 0) {
+ top->normalGeometry = normalGeometry;
+ top->fullScreenOffset = fullScreenOffset;
+ }
+ } else {
+ setParent(0, top->savedFlags);
+
+ if (newstate & Qt::WindowMaximized) {
+ // from fullscreen to maximized
+ data->fstrut_dirty = true;
+ const QRect maxRect = QApplication::desktop()->availableGeometry(this);
+ const QRect r = top->normalGeometry;
+ const QRect fs = d->frameStrut();
+ setGeometry(maxRect.x() + fs.left(),
+ maxRect.y() + fs.top(),
+ maxRect.width() - fs.left() - fs.right(),
+ maxRect.height() - fs.top() - fs.bottom());
+ top->normalGeometry = r;
+ } else {
+ // restore original geometry
+ setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
+ -top->fullScreenOffset.y(),
+ -top->fullScreenOffset.x(),
+ -top->fullScreenOffset.y()));
+ }
+ }
+ }
+ }
+
+ createWinId();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
+ if (isVisible()) {
+ if (newstate & Qt::WindowMinimized) {
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = ATOM(WM_CHANGE_STATE);
+ e.xclient.display = X11->display;
+ e.xclient.window = data->winid;
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = IconicState;
+ e.xclient.data.l[1] = 0;
+ e.xclient.data.l[2] = 0;
+ e.xclient.data.l[3] = 0;
+ e.xclient.data.l[4] = 0;
+ XSendEvent(X11->display,
+ RootWindow(X11->display,d->xinfo.screen()),
+ False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
+ } else {
+ setAttribute(Qt::WA_Mapped);
+ XMapWindow(X11->display, effectiveWinId());
+ }
+ }
+
+ needShow = false;
+ }
+ }
+
+ data->window_state = newstate;
+
+ if (needShow)
+ show();
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ \internal
+ Platform-specific part of QWidget::show().
+*/
+
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ q->setAttribute(Qt::WA_Mapped);
+ if (QTLWExtra *tlwExtra = maybeTopData())
+ tlwExtra->waitingForMapNotify = 0;
+ return;
+ }
+
+ if (q->isWindow()) {
+ XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
+ XWMHints wm_hints;
+ bool got_hints = h != 0;
+ if (!got_hints) {
+ memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+ h = &wm_hints;
+ }
+ h->initial_state = q->isMinimized() ? IconicState : NormalState;
+ h->flags |= StateHint;
+ XSetWMHints(X11->display, q->internalWinId(), h);
+ if (got_hints)
+ XFree((char *)h);
+
+ // update WM_NORMAL_HINTS
+ do_size_hints(q, extra);
+
+ // udpate WM_TRANSIENT_FOR
+ if (isTransient(q)) {
+ QWidget *p = q->parentWidget();
+
+#ifndef QT_NO_MENU
+ // hackish ... try to find the main window related to this QMenu
+ if (qobject_cast<QMenu *>(q)) {
+ p = static_cast<QMenuPrivate*>(this)->causedPopup.widget;
+ if (!p)
+ p = q->parentWidget();
+ if (!p)
+ p = QApplication::widgetAt(q->pos());
+ if (!p)
+ p = qApp->activeWindow();
+ }
+#endif
+ if (p)
+ p = p->window();
+ if (p) {
+ // transient for window
+ XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
+ } else {
+ // transient for group
+ XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
+ }
+ }
+
+ // update _MOTIF_WM_HINTS
+ QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
+
+ if (data.window_modality != Qt::NonModal) {
+ switch (data.window_modality) {
+ case Qt::WindowModal:
+ mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
+ break;
+ case Qt::ApplicationModal:
+ default:
+ mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
+ break;
+ }
+ mwmhints.flags |= MWM_HINTS_INPUT_MODE;
+ } else {
+ mwmhints.input_mode = MWM_INPUT_MODELESS;
+ mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
+ }
+
+ if (q->minimumSize() == q->maximumSize()) {
+ // fixed size, remove the resize handle (since mwm/dtwm
+ // isn't smart enough to do it itself)
+ mwmhints.flags |= MWM_HINTS_FUNCTIONS;
+ if (mwmhints.functions == MWM_FUNC_ALL) {
+ mwmhints.functions = MWM_FUNC_MOVE;
+ } else {
+ mwmhints.functions &= ~MWM_FUNC_RESIZE;
+ }
+
+ mwmhints.flags |= MWM_HINTS_DECORATIONS;
+ if (mwmhints.decorations == MWM_DECOR_ALL) {
+ mwmhints.decorations = (MWM_DECOR_BORDER
+ | MWM_DECOR_TITLE
+ | MWM_DECOR_MENU);
+ } else {
+ mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
+ }
+
+ if (q->windowFlags() & Qt::WindowMinimizeButtonHint) {
+ mwmhints.decorations |= MWM_DECOR_MINIMIZE;
+ mwmhints.functions |= MWM_FUNC_MINIMIZE;
+ }
+ if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
+ mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
+ mwmhints.functions |= MWM_FUNC_MAXIMIZE;
+ }
+ if (q->windowFlags() & Qt::WindowCloseButtonHint)
+ mwmhints.functions |= MWM_FUNC_CLOSE;
+ }
+
+ SetMWMHints(X11->display, q->internalWinId(), mwmhints);
+
+ // update _NET_WM_STATE
+ QVector<Atom> netWmState = getNetWmState(q);
+
+ Qt::WindowFlags flags = q->windowFlags();
+ if (flags & Qt::WindowStaysOnTopHint) {
+ if (flags & Qt::WindowStaysOnBottomHint)
+ qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
+ netWmState.append(ATOM(_NET_WM_STATE_ABOVE));
+ netWmState.append(ATOM(_NET_WM_STATE_STAYS_ON_TOP));
+ } else if (flags & Qt::WindowStaysOnBottomHint) {
+ netWmState.append(ATOM(_NET_WM_STATE_BELOW));
+ }
+ if (q->isFullScreen()) {
+ netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN));
+ }
+ if (q->isMaximized()) {
+ netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ));
+ netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
+ }
+ if (data.window_modality != Qt::NonModal) {
+ netWmState.append(ATOM(_NET_WM_STATE_MODAL));
+ }
+
+ if (!netWmState.isEmpty()) {
+ XChangeProperty(X11->display, q->internalWinId(),
+ ATOM(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) netWmState.data(), netWmState.size());
+ } else {
+ XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
+ }
+
+ // set _NET_WM_USER_TIME
+ Time userTime = X11->userTime;
+ bool setUserTime = false;
+ if (q->testAttribute(Qt::WA_ShowWithoutActivating)) {
+ userTime = 0;
+ setUserTime = true;
+ } else if (userTime != CurrentTime) {
+ setUserTime = true;
+ }
+ if (setUserTime)
+ qt_net_update_user_time(q, userTime);
+
+ if (!topData()->embedded
+ && (topData()->validWMState || topData()->waitingForMapNotify)
+ && !q->isMinimized()) {
+ X11->deferred_map.append(q);
+ return;
+ }
+
+ if (q->isMaximized() && !q->isFullScreen()
+ && !(X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
+ && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
+ XMapWindow(X11->display, q->internalWinId());
+ data.fstrut_dirty = true;
+ qt_x11_wait_for_window_manager(q);
+
+ // if the wm was not smart enough to adjust our size, do that manually
+ QRect maxRect = QApplication::desktop()->availableGeometry(q);
+
+ QTLWExtra *top = topData();
+ QRect normalRect = top->normalGeometry;
+ const QRect fs = frameStrut();
+
+ q->setGeometry(maxRect.x() + fs.left(),
+ maxRect.y() + fs.top(),
+ maxRect.width() - fs.left() - fs.right(),
+ maxRect.height() - fs.top() - fs.bottom());
+
+ // restore the original normalGeometry
+ top->normalGeometry = normalRect;
+ // internalSetGeometry() clears the maximized flag... make sure we set it back
+ data.window_state = data.window_state | Qt::WindowMaximized;
+ q->setAttribute(Qt::WA_Mapped);
+ return;
+ }
+
+ if (q->isFullScreen() && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
+ XMapWindow(X11->display, q->internalWinId());
+ qt_x11_wait_for_window_manager(q);
+ q->setAttribute(Qt::WA_Mapped);
+ return;
+ }
+ }
+
+ invalidateBuffer(q->rect());
+
+ if (q->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->isWindow())
+ topData()->waitingForMapNotify = 1;
+
+ if (!q->isWindow()
+ && (!q->autoFillBackground()
+ || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
+ if (q->internalWinId()) {
+ XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
+ XMapWindow(X11->display, q->internalWinId());
+ updateSystemBackground();
+ }
+ return;
+ }
+
+ if (q->internalWinId())
+ XMapWindow(X11->display, q->internalWinId());
+
+ // Freedesktop.org Startup Notification
+ if (X11->startupId && q->isWindow()) {
+ QByteArray message("remove: ID=");
+ message.append(X11->startupId);
+ sendStartupMessage(message.constData());
+ X11->startupId = 0;
+ }
+}
+
+/*!
+ \internal
+ Platform-specific part of QWidget::show().
+*/
+
+void QWidgetPrivate::sendStartupMessage(const char *message) const
+{
+ Q_Q(const QWidget);
+
+ if (!message)
+ return;
+
+ XEvent xevent;
+ xevent.xclient.type = ClientMessage;
+ xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN);
+ xevent.xclient.display = X11->display;
+ xevent.xclient.window = q->internalWinId();
+ xevent.xclient.format = 8;
+
+ Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
+ uint sent = 0;
+ uint length = strlen(message) + 1;
+ do {
+ if (sent == 20)
+ xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
+
+ for (uint i = 0; i < 20 && i + sent <= length; i++)
+ xevent.xclient.data.b[i] = message[i + sent++];
+
+ XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
+ } while (sent <= length);
+}
+
+void QWidgetPrivate::setNetWmWindowTypes()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ if (!q->isWindow()) {
+ if (q->internalWinId())
+ XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE));
+ return;
+ }
+
+ QVector<long> windowTypes;
+
+ // manual selection 1 (these are never set by Qt and take precedence)
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DESKTOP));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DOCK));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NOTIFICATION));
+
+ // manual selection 2 (Qt uses these during auto selection);
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
+
+ // manual selection 3 (these can be set by Qt, but don't have a
+ // corresponding Qt::WindowType). note that order of the *MENU
+ // atoms is important
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_MENU));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_COMBO));
+ if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DND));
+
+ // automatic selection
+ switch (q->windowType()) {
+ case Qt::Dialog:
+ case Qt::Sheet:
+ // dialog netwm type
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
+ break;
+
+ case Qt::Tool:
+ case Qt::Drawer:
+ // utility netwm type
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
+ break;
+
+ case Qt::ToolTip:
+ // tooltip netwm type
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
+ break;
+
+ case Qt::SplashScreen:
+ // splash netwm type
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
+ break;
+
+ default:
+ break;
+ }
+
+ if (q->windowFlags() & Qt::FramelessWindowHint) {
+ // override netwm type - quick and easy for KDE noborder
+ windowTypes.append(ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+ }
+
+ // normal netwm type - default
+ windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL));
+
+ if (!windowTypes.isEmpty()) {
+ XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32,
+ PropModeReplace, (unsigned char *) windowTypes.constData(),
+ windowTypes.count());
+ } else {
+ XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE));
+ }
+}
+
+/*!
+ \internal
+ Platform-specific part of QWidget::hide().
+*/
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ deactivateWidgetCleanup();
+ if (q->isWindow()) {
+ X11->deferred_map.removeAll(q);
+ if (q->internalWinId()) // in nsplugin, may be 0
+ XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen());
+ XFlush(X11->display);
+ } else {
+ invalidateBuffer(q->rect());
+ if (q->internalWinId()) // in nsplugin, may be 0
+ XUnmapWindow(X11->display, q->internalWinId());
+ }
+ q->setAttribute(Qt::WA_Mapped, false);
+}
+
+void QWidgetPrivate::setFocus_sys()
+{
+
+}
+
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (q->internalWinId())
+ XRaiseWindow(X11->display, q->internalWinId());
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (q->internalWinId())
+ XLowerWindow(X11->display, q->internalWinId());
+ if(!q->isWindow())
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget* w)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ if (q->internalWinId() && w->internalWinId()) {
+ Window stack[2];
+ stack[0] = w->internalWinId();;
+ stack[1] = q->internalWinId();
+ XRestackWindows(X11->display, stack, 2);
+ }
+ if(!q->isWindow() || !w->internalWinId())
+ invalidateBuffer(q->rect());
+}
+
+
+static void do_size_hints(QWidget* widget, QWExtra *x)
+{
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ XSizeHints s;
+ s.flags = 0;
+ if (x) {
+ QRect g = widget->geometry();
+ s.x = g.x();
+ s.y = g.y();
+ s.width = g.width();
+ s.height = g.height();
+ if (x->minw > 0 || x->minh > 0) {
+ // add minimum size hints
+ s.flags |= PMinSize;
+ s.min_width = qMin(XCOORD_MAX, x->minw);
+ s.min_height = qMin(XCOORD_MAX, x->minh);
+ }
+ if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
+ // add maximum size hints
+ s.flags |= PMaxSize;
+ s.max_width = qMin(XCOORD_MAX, x->maxw);
+ s.max_height = qMin(XCOORD_MAX, x->maxh);
+ }
+ if (x->topextra &&
+ (x->topextra->incw > 0 || x->topextra->inch > 0)) {
+ // add resize increment hints
+ s.flags |= PResizeInc | PBaseSize;
+ s.width_inc = x->topextra->incw;
+ s.height_inc = x->topextra->inch;
+ s.base_width = x->topextra->basew;
+ s.base_height = x->topextra->baseh;
+ }
+ }
+ if (widget->testAttribute(Qt::WA_Moved)) {
+ // user (i.e. command-line) specified position
+ s.flags |= USPosition;
+ s.flags |= PPosition;
+ }
+ if (widget->testAttribute(Qt::WA_Resized)) {
+ // user (i.e. command-line) specified size
+ s.flags |= USSize;
+ s.flags |= PSize;
+ }
+ s.flags |= PWinGravity;
+ if (widget->testAttribute(Qt::WA_Moved) && x && x->topextra && !x->topextra->posFromMove) {
+ // position came from setGeometry(), tell the WM that we don't
+ // want our window gravity-shifted
+ s.win_gravity = StaticGravity;
+ } else {
+ // position came from move()
+ s.x = widget->x();
+ s.y = widget->y();
+ s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
+ }
+ if (widget->internalWinId())
+ XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
+}
+
+
+/*
+ Helper function for non-toplevel widgets. Helps to map Qt's 32bit
+ coordinate system to X11's 16bit coordinate system.
+
+ Sets the geometry of the widget to data.crect, but clipped to sizes
+ that X can handle. Unmaps widgets that are completely outside the
+ valid range.
+
+ Maintains data.wrect, which is the geometry of the 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 X rect, measured in
+ parent's coord sys
+ */
+void QWidgetPrivate::setWSGeometry(bool dontShow)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ /*
+ 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).
+ */
+ Display *dpy = xinfo.display();
+ QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
+ QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
+ 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;
+
+ const QWidget *const parent = q->parentWidget();
+ QRect parentWRect = parent->data->wrect;
+
+ if (parentWRect.isValid()) {
+ // parent is clipped, and we have to clip to the same limit as parent
+ if (!parentWRect.contains(xrect)) {
+ 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 & parent->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());
+ if (data.winid)
+ XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
+ return;
+ }
+ }
+
+ if (!validRange.contains(xrect)) {
+ // we are too big, and must clip
+ xrect &=wrectRange;
+ wrect = xrect;
+ wrect.translate(-data.crect.topLeft());
+ //parent's X coord system is equal to parent's Qt coord
+ //sys, so we don't need to map xrect.
+ }
+
+ }
+
+ // 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) {
+ if (data.winid)
+ XUnmapWindow(dpy, data.winid);
+ 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(jump);
+ }
+ }
+
+ if (data.winid) {
+ // move ourselves to the new position and map (if necessary) after
+ // the movement. Rationale: moving unmapped windows is much faster
+ // than moving mapped windows
+ if (jump) //avoid flicker when jumping
+ XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
+ if (!parent->internalWinId())
+ xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
+ XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
+ }
+
+ //to avoid flicker, we have to show children after the helper widget has moved
+ if (jump) {
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *object = children.at(i);
+ if (object->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(object);
+ if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
+ w->setAttribute(Qt::WA_Mapped);
+ if (w->internalWinId())
+ XMapWindow(dpy, w->data->winid);
+ }
+ }
+ }
+ }
+
+
+ if (jump && data.winid)
+ XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
+
+ if (mapWindow && !dontShow) {
+ q->setAttribute(Qt::WA_Mapped);
+ if (data.winid)
+ XMapWindow(dpy, data.winid);
+ }
+}
+
+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));
+ Display *dpy = X11->display;
+
+ if ((q->windowType() == Qt::Desktop))
+ return;
+ if (q->isWindow()) {
+ if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
+ && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
+ data.window_state &= ~Qt::WindowMaximized;
+ if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
+ data.window_state &= ~Qt::WindowFullScreen;
+ if (QTLWExtra *topData = maybeTopData())
+ topData->normalGeometry = QRect(0,0,-1,-1);
+ } else {
+ uint s = data.window_state;
+ s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
+ data.window_state = s;
+ }
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+ QPoint oldPos(q->pos());
+ QSize oldSize(q->size());
+ QRect oldGeom(data.crect);
+ QRect r(x, y, w, h);
+
+ // We only care about stuff that changes the geometry, or may
+ // cause the window manager to change its state
+ if (!q->isWindow() && oldGeom == r)
+ return;
+
+ data.crect = r;
+ bool isResize = q->size() != oldSize;
+
+ if (q->isWindow()) {
+ if (w == 0 || h == 0) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+
+ // put the window in its place and show it
+ if (data.winid)
+ XMoveResizeWindow(dpy, data.winid, x, y, w, h);
+ topData()->posFromMove = false; // force StaticGravity
+ do_size_hints(q, extra);
+ show_sys();
+ } else {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+ if (!q->isVisible())
+ do_size_hints(q, extra);
+ if (isMove) {
+ if ((data.window_flags & Qt::X11BypassWindowManagerHint) == Qt::X11BypassWindowManagerHint
+ // work around 4Dwm's incompliance with ICCCM 4.1.5
+ || X11->desktopEnvironment == DE_4DWM) {
+ if (data.winid)
+ XMoveResizeWindow(dpy, data.winid, x, y, w, h);
+ } else if (q->isVisible()
+ && topData()->validWMState
+ && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) {
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = ATOM(_NET_MOVERESIZE_WINDOW);
+ e.xclient.display = X11->display;
+ e.xclient.window = q->internalWinId();
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = StaticGravity | 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12;
+ e.xclient.data.l[1] = x;
+ e.xclient.data.l[2] = y;
+ e.xclient.data.l[3] = w;
+ e.xclient.data.l[4] = h;
+ XSendEvent(X11->display, RootWindow(X11->display, q->x11Info().screen()),
+ false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
+ } else if (data.winid) {
+ // pos() is right according to ICCCM 4.1.5
+ XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
+ }
+ } else if (isResize && data.winid) {
+ if (!q->isVisible()
+ && topData()->validWMState
+ && !q->testAttribute(Qt::WA_PendingMoveEvent)) {
+ /*
+ even though we've not visible, we could be in a
+ race w/ the window manager, and it may ignore
+ our ConfigureRequest. setting posFromMove to
+ false makes sure that doDeferredMap() in
+ qapplication_x11.cpp keeps the window in the
+ right place
+ */
+ topData()->posFromMove = false;
+ }
+ XResizeWindow(dpy, data.winid, w, h);
+ }
+ }
+ if (isResize && !q->testAttribute(Qt::WA_DontShowOnScreen)) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
+ q->setAttribute(Qt::WA_WState_ConfigPending);
+
+ } else {
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
+ const bool disableInTopLevelResize = inTopLevelResize && q->internalWinId();
+ if (disableInTopLevelResize) {
+ // Top-level resize optimization does not work for native child widgets;
+ // disable it for this particular widget.
+ tlwExtra->inTopLevelResize = false;
+ }
+
+ if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) {
+ moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
+ }
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWSGeometry();
+
+ if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible())
+ invalidateBuffer_resizeHelper(oldPos, oldSize);
+
+ if (disableInTopLevelResize)
+ tlwExtra->inTopLevelResize = true;
+ }
+
+ if (q->isVisible()) {
+ if (isMove && q->pos() != oldPos) {
+ if (X11->desktopEnvironment != DE_4DWM) {
+ // pos() is right according to ICCCM 4.1.5
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ } else {
+ // work around 4Dwm's incompliance with ICCCM 4.1.5
+ QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
+ QApplication::sendEvent(q, &e);
+ }
+ }
+ if (isResize) {
+ static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ // If we have a backing store with static contents, we have to disable the top-level
+ // resize optimization in order to get invalidated regions for resized widgets.
+ // The optimization discards all invalidateBuffer() calls since we're going to
+ // repaint everything anyways, but that's not the case with static contents.
+ const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
+ && !extra->topextra->inTopLevelResize
+ && (!extra->topextra->backingStore
+ || !extra->topextra->backingStore->hasStaticContents());
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = true;
+ QResizeEvent e(q->size(), oldSize);
+ QApplication::sendEvent(q, &e);
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = false;
+ }
+ } else {
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+ Q_Q(QWidget);
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::setConstraints_sys START" << q;
+#endif
+ if (q->testAttribute(Qt::WA_WState_Created))
+ do_size_hints(q, extra);
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::setConstraints_sys END" << q;
+#endif
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+
+ scrollChildren(dx, dy);
+ if (!paintOnScreen()) {
+ scrollRect(q->rect(), dx, dy);
+ } else {
+ scroll_sys(dx, dy, QRect());
+ }
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ Q_Q(QWidget);
+
+ if (!paintOnScreen()) {
+ scrollRect(r, dx, dy);
+ return;
+ }
+ bool valid_rect = r.isValid();
+ bool just_update = qAbs(dx) > q->width() || qAbs(dy) > q->height();
+ QRect sr = valid_rect ? r : clipRect();
+ if (just_update)
+ q->update();
+
+ int x1, y1, x2, y2, w = sr.width(), h = sr.height();
+ if (dx > 0) {
+ x1 = sr.x();
+ x2 = x1+dx;
+ w -= dx;
+ } else {
+ x2 = sr.x();
+ x1 = x2-dx;
+ w += dx;
+ }
+ if (dy > 0) {
+ y1 = sr.y();
+ y2 = y1+dy;
+ h -= dy;
+ } else {
+ y2 = sr.y();
+ y1 = y2-dy;
+ h += dy;
+ }
+
+ if (dx == 0 && dy == 0)
+ return;
+
+ Display *dpy = X11->display;
+ // Want expose events
+ if (w > 0 && h > 0 && !just_update && q->internalWinId()) {
+ GC gc = XCreateGC(dpy, q->internalWinId(), 0, 0);
+ XSetGraphicsExposures(dpy, gc, True);
+ XCopyArea(dpy, q->internalWinId(), q->internalWinId(), gc, x1, y1, w, h, x2, y2);
+ XFreeGC(dpy, gc);
+ }
+
+ if (!valid_rect && !children.isEmpty()) { // scroll children
+ QPoint pd(dx, dy);
+ for (int i = 0; i < children.size(); ++i) { // move all children
+ register QObject *object = children.at(i);
+ if (object->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(object);
+ if (!w->isWindow())
+ w->move(w->pos() + pd);
+ }
+ }
+ }
+
+ if (just_update)
+ return;
+
+ // Don't let the server be bogged-down with repaint events
+ bool repaint_immediately = (qt_sip_count(q) < 3 && !q->testAttribute(Qt::WA_WState_InPaintEvent));
+
+ if (dx) {
+ int x = x2 == sr.x() ? sr.x()+w : sr.x();
+ if (repaint_immediately)
+ q->repaint(x, sr.y(), qAbs(dx), sr.height());
+ else if (q->internalWinId())
+ XClearArea(dpy, data.winid, x, sr.y(), qAbs(dx), sr.height(), True);
+ }
+ if (dy) {
+ int y = y2 == sr.y() ? sr.y()+h : sr.y();
+ if (repaint_immediately)
+ q->repaint(sr.x(), y, sr.width(), qAbs(dy));
+ else if (q->internalWinId())
+ XClearArea(dpy, data.winid, sr.x(), y, sr.width(), qAbs(dy), True);
+ }
+
+ qt_insert_sip(q, dx, dy); // #### ignores r
+}
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else {
+ Display *dpy = X11->display;
+ int scr = d->xinfo.screen();
+ switch (m) {
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ if (d->extra && d->extra->customDpiX)
+ val = d->extra->customDpiX;
+ else if (d->parent)
+ val = static_cast<QWidget *>(d->parent)->metric(m);
+ else
+ val = QX11Info::appDpiX(scr);
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ if (d->extra && d->extra->customDpiY)
+ val = d->extra->customDpiY;
+ else if (d->parent)
+ val = static_cast<QWidget *>(d->parent)->metric(m);
+ else
+ val = QX11Info::appDpiY(scr);
+ break;
+ case PdmWidthMM:
+ val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
+ DisplayWidth(dpy,scr);
+ break;
+ case PdmHeightMM:
+ val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
+ DisplayHeight(dpy,scr);
+ break;
+ case PdmNumColors:
+ val = d->xinfo.cells();
+ break;
+ case PdmDepth:
+ val = d->xinfo.depth();
+ break;
+ default:
+ val = 0;
+ qWarning("QWidget::metric: Invalid metric command");
+ }
+ }
+ return val;
+}
+
+void QWidgetPrivate::createSysExtra()
+{
+ extra->xDndProxy = 0;
+ extra->compress_events = true;
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+}
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ extra->topextra->validWMState = 0;
+ extra->topextra->waitingForMapNotify = 0;
+ extra->topextra->userTimeWindow = 0;
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ // don't destroy input context here. it will be destroyed in
+ // QWidget::destroy() destroyInputContext();
+}
+
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_UNUSED(on);
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_Q(QWidget);
+ if (!q->internalWinId())
+ return;
+
+ if (region.isEmpty()) {
+ XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
+ XNone, ShapeSet);
+ } else {
+ XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
+ region.handle(), ShapeSet);
+ }
+}
+
+/*!
+ \internal
+
+ Computes the frame rectangle when needed. This is an internal function, you
+ should never call this.
+*/
+
+void QWidgetPrivate::updateFrameStrut()
+{
+ Q_Q(QWidget);
+
+ QTLWExtra *top = topData();
+ if (!top->validWMState) {
+ return;
+ }
+ if (!q->isWindow() && !q->internalWinId()) {
+ data.fstrut_dirty = false;
+ return;
+ }
+
+ Atom type_ret;
+ Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root
+ Window *c;
+ int i_unused;
+ unsigned int nc;
+ unsigned char *data_ret;
+ unsigned long l_unused;
+
+ while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
+ if (c && nc > 0)
+ XFree(c);
+
+ if (! p) {
+ qWarning("QWidget::updateFrameStrut: No parent");
+ return;
+ }
+
+ // if the parent window is the root window, an Enlightenment virtual root or
+ // a NET WM virtual root window, stop here
+ data_ret = 0;
+ if (p == r ||
+ (XGetWindowProperty(X11->display, p,
+ ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
+ &type_ret, &i_unused, &l_unused, &l_unused,
+ &data_ret) == Success &&
+ type_ret == XA_CARDINAL)) {
+ if (data_ret)
+ XFree(data_ret);
+
+ break;
+ } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
+ int i = 0;
+ while (X11->net_virtual_root_list[i] != 0) {
+ if (X11->net_virtual_root_list[i++] == p)
+ break;
+ }
+ }
+
+ l = w;
+ w = p;
+ }
+
+ // we have our window
+ int transx, transy;
+ XWindowAttributes wattr;
+ if (XTranslateCoordinates(X11->display, l, w,
+ 0, 0, &transx, &transy, &p) &&
+ XGetWindowAttributes(X11->display, w, &wattr)) {
+ top->frameStrut.setCoords(transx,
+ transy,
+ wattr.width - data.crect.width() - transx,
+ wattr.height - data.crect.height() - transy);
+
+ // add the border_width for the window managers frame... some window managers
+ // do not use a border_width of zero for their frames, and if we the left and
+ // top strut, we ensure that pos() is absolutely correct. frameGeometry()
+ // will still be incorrect though... perhaps i should have foffset as well, to
+ // indicate the frame offset (equal to the border_width on X).
+ // - Brad
+ top->frameStrut.adjust(wattr.border_width,
+ wattr.border_width,
+ wattr.border_width,
+ wattr.border_width);
+ }
+
+ data.fstrut_dirty = false;
+}
+
+void QWidgetPrivate::setWindowOpacity_sys(qreal opacity)
+{
+ Q_Q(QWidget);
+ ulong value = ulong(opacity * 0xffffffff);
+ XChangeProperty(QX11Info::display(), q->internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL,
+ 32, PropModeReplace, (uchar*)&value, 1);
+}
+
+/*!
+ Returns information about the configuration of the X display used to display
+ the widget.
+
+ \warning This function is only available on X11.
+*/
+const QX11Info &QWidget::x11Info() const
+{
+ Q_D(const QWidget);
+ return d->xinfo;
+}
+
+void QWidgetPrivate::setWindowRole()
+{
+ Q_Q(QWidget);
+ if (!q->internalWinId())
+ return;
+ QByteArray windowRole = topData()->role.toUtf8();
+ XChangeProperty(X11->display, q->internalWinId(),
+ ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
+ (unsigned char *)windowRole.constData(), windowRole.length());
+}
+
+Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
+QPaintEngine *QWidget::paintEngine() const
+{
+ Q_D(const QWidget);
+ if (qt_widget_paintengine()->isActive()) {
+ if (d->extraPaintEngine)
+ return d->extraPaintEngine;
+ QWidget *self = const_cast<QWidget *>(this);
+ self->d_func()->extraPaintEngine = new QX11PaintEngine();
+ return d->extraPaintEngine;
+ }
+ return qt_widget_paintengine();
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ return new QX11WindowSurface(q_func());
+}
+
+/*!
+ Returns the X11 Picture handle of the widget for XRender
+ support. Use of this function is not portable. This function will
+ return 0 if XRender support is not compiled into Qt, if the
+ XRender extension is not supported on the X11 display, or if the
+ handle could not be created.
+*/
+Qt::HANDLE QWidget::x11PictureHandle() const
+{
+#ifndef QT_NO_XRENDER
+ Q_D(const QWidget);
+ if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
+ (void)winId(); // enforce native window
+ return d->picture;
+#else
+ return 0;
+#endif // QT_NO_XRENDER
+}
+
+#ifndef QT_NO_XRENDER
+XRenderColor QX11Data::preMultiply(const QColor &c)
+{
+ XRenderColor color;
+ const uint A = c.alpha(),
+ R = c.red(),
+ G = c.green(),
+ B = c.blue();
+ color.alpha = (A | A << 8);
+ color.red = (R | R << 8) * color.alpha / 0x10000;
+ color.green = (G | G << 8) * color.alpha / 0x10000;
+ color.blue = (B | B << 8) * color.alpha / 0x10000;
+ return color;
+}
+Picture QX11Data::getSolidFill(int screen, const QColor &c)
+{
+ if (!X11->use_xrender)
+ return XNone;
+
+ XRenderColor color = preMultiply(c);
+ for (int i = 0; i < X11->solid_fill_count; ++i) {
+ if (X11->solid_fills[i].screen == screen
+ && X11->solid_fills[i].color.alpha == color.alpha
+ && X11->solid_fills[i].color.red == color.red
+ && X11->solid_fills[i].color.green == color.green
+ && X11->solid_fills[i].color.blue == color.blue)
+ return X11->solid_fills[i].picture;
+ }
+ // none found, replace one
+ int i = rand() % 16;
+
+ if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
+ XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
+ X11->solid_fills[i].picture = 0;
+ }
+
+ if (!X11->solid_fills[i].picture) {
+ Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
+ XRenderPictureAttributes attrs;
+ attrs.repeat = True;
+ X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
+ XRenderFindStandardFormat(X11->display, PictStandardARGB32),
+ CPRepeat, &attrs);
+ XFreePixmap (X11->display, pixmap);
+ }
+
+ X11->solid_fills[i].color = color;
+ X11->solid_fills[i].screen = screen;
+ XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
+ return X11->solid_fills[i].picture;
+}
+#endif
+
+void QWidgetPrivate::setModal_sys()
+{
+}
+
+void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att)
+{
+ QX11InfoData* xd = xinfo->getX11Data(true);
+ const XWindowAttributes &a = *(att.att);
+ // find which screen the window is on...
+ xd->screen = QX11Info::appScreen(); // by default, use the default :)
+ int i;
+ for (i = 0; i < ScreenCount(X11->display); i++) {
+ if (RootWindow(X11->display, i) == a.root) {
+ xd->screen = i;
+ break;
+ }
+ }
+
+ xd->depth = a.depth;
+ xd->cells = DisplayCells(X11->display, xd->screen);
+ xd->visual = a.visual;
+ xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
+ XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo->screen())));
+ xd->colormap = a.colormap;
+ xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo->screen()));
+ xinfo->setX11Data(xd);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp
new file mode 100644
index 0000000000..efdde5e1e6
--- /dev/null
+++ b/src/gui/kernel/qwidgetaction.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidgetaction.h"
+#include "qdebug.h"
+
+#ifndef QT_NO_ACTION
+#include "qwidgetaction_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWidgetAction
+ \since 4.2
+ \brief The QWidgetAction class extends QAction by an interface
+ for inserting custom widgets into action based containers, such
+ as toolbars.
+
+ Most actions in an application are represented as items in menus or
+ buttons in toolbars. However sometimes more complex widgets are
+ necessary. For example a zoom action in a word processor may be
+ realized using a QComboBox in a QToolBar, presenting a range
+ of different zoom levels. QToolBar provides QToolBar::insertWidget()
+ as convenience function for inserting a single widget.
+ However if you want to implement an action that uses custom
+ widgets for visualization in multiple containers then you have to
+ subclass QWidgetAction.
+
+ If a QWidgetAction is added for example to a QToolBar then
+ QWidgetAction::createWidget() is called. Reimplementations of that
+ function should create a new custom widget with the specified parent.
+
+ If the action is removed from a container widget then
+ QWidgetAction::deleteWidget() is called with the previously created custom
+ widget as argument. The default implementation hides the widget and deletes
+ it using QObject::deleteLater().
+
+ If you have only one single custom widget then you can set it as default
+ widget using setDefaultWidget(). That widget will then be used if the
+ action is added to a QToolBar, or in general to an action container that
+ supports QWidgetAction. If a QWidgetAction with only a default widget is
+ added to two toolbars at the same time then the default widget is shown
+ only in the first toolbar the action was added to. QWidgetAction takes
+ over ownership of the default widget.
+
+ Note that it is up to the widget to activate the action, for example by
+ reimplementing mouse event handlers and calling QAction::trigger().
+
+ \bold {Mac OS X}: If you add a widget to a menu in the application's menu
+ bar on Mac OS X, the widget will be added and it will function but with some
+ limitations:
+ \list 1
+ \o The widget is reparented away from the QMenu to the native menu
+ view. If you show the menu in some other place (e.g. as a popup menu),
+ the widget will not be there.
+ \o Focus/Keyboard handling of the widget is not possible.
+ \o Due to Apple's design, mouse tracking on the widget currently does
+ not work.
+ \o Connecting the triggered() signal to a slot that opens a modal
+ dialog will cause a crash in Mac OS X 10.4 (known bug acknowledged
+ by Apple), a workaround is to use a QueuedConnection instead of a
+ DirectConnection.
+ \endlist
+
+ \ingroup application
+ \mainclass
+
+ \sa QAction, QActionGroup, QWidget
+*/
+
+/*!
+ Constructs an action with \a parent.
+*/
+QWidgetAction::QWidgetAction(QObject *parent)
+ : QAction(*(new QWidgetActionPrivate), parent)
+{
+}
+
+/*!
+ Destroys the object and frees allocated resources.
+*/
+QWidgetAction::~QWidgetAction()
+{
+ Q_D(QWidgetAction);
+ for (int i = 0; i < d->createdWidgets.count(); ++i)
+ disconnect(d->createdWidgets.at(i), SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_widgetDestroyed(QObject*)));
+ QList<QWidget *> widgetsToDelete = d->createdWidgets;
+ d->createdWidgets.clear();
+ qDeleteAll(widgetsToDelete);
+ delete d->defaultWidget;
+}
+
+/*!
+ Sets \a widget to be the default widget. The ownership is
+ transferred to QWidgetAction. Unless createWidget() is
+ reimplemented by a subclass to return a new widget the default
+ widget is used when a container widget requests a widget through
+ requestWidget().
+*/
+void QWidgetAction::setDefaultWidget(QWidget *widget)
+{
+ Q_D(QWidgetAction);
+ if (widget == d->defaultWidget || d->defaultWidgetInUse)
+ return;
+ delete d->defaultWidget;
+ d->defaultWidget = widget;
+ if (!widget)
+ return;
+
+ setVisible(!(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide)));
+ d->defaultWidget->hide();
+ d->defaultWidget->setParent(0);
+ d->defaultWidgetInUse = false;
+ if (!isEnabled())
+ d->defaultWidget->setEnabled(false);
+}
+
+/*!
+ Returns the default widget.
+*/
+QWidget *QWidgetAction::defaultWidget() const
+{
+ Q_D(const QWidgetAction);
+ return d->defaultWidget;
+}
+
+/*!
+ Returns a widget that represents the action, with the given \a
+ parent.
+
+ Container widgets that support actions can call this function to
+ request a widget as visual representation of the action.
+
+ \sa releaseWidget(), createWidget(), defaultWidget()
+*/
+QWidget *QWidgetAction::requestWidget(QWidget *parent)
+{
+ Q_D(QWidgetAction);
+
+ QWidget *w = createWidget(parent);
+ if (!w) {
+ if (d->defaultWidgetInUse || !d->defaultWidget)
+ return 0;
+ d->defaultWidget->setParent(parent);
+ d->defaultWidgetInUse = true;
+ return d->defaultWidget;
+ }
+
+ connect(w, SIGNAL(destroyed(QObject*)),
+ this, SLOT(_q_widgetDestroyed(QObject*)));
+ d->createdWidgets.append(w);
+ return w;
+}
+
+/*!
+ Releases the specified \a widget.
+
+ Container widgets that support actions call this function when a widget
+ action is removed.
+
+ \sa requestWidget(), deleteWidget(), defaultWidget()
+*/
+void QWidgetAction::releaseWidget(QWidget *widget)
+{
+ Q_D(QWidgetAction);
+
+ if (widget == d->defaultWidget) {
+ d->defaultWidget->hide();
+ d->defaultWidget->setParent(0);
+ d->defaultWidgetInUse = false;
+ return;
+ }
+
+ if (!d->createdWidgets.contains(widget))
+ return;
+
+ disconnect(widget, SIGNAL(destroyed(QObject *)),
+ this, SLOT(_q_widgetDestroyed(QObject *)));
+ d->createdWidgets.removeAll(widget);
+ deleteWidget(widget);
+}
+
+/*!
+ \reimp
+*/
+bool QWidgetAction::event(QEvent *event)
+{
+ Q_D(QWidgetAction);
+ if (event->type() == QEvent::ActionChanged) {
+ if (d->defaultWidget)
+ d->defaultWidget->setEnabled(isEnabled());
+ foreach (QWidget *w, d->createdWidgets)
+ w->setEnabled(isEnabled());
+ }
+ return QAction::event(event);
+}
+
+/*!
+ \reimp
+ */
+bool QWidgetAction::eventFilter(QObject *obj, QEvent *event)
+{
+ return QAction::eventFilter(obj,event);
+}
+
+/*!
+ This function is called whenever the action is added to a container widget
+ that supports custom widgets. If you don't want a custom widget to be
+ used as representation of the action in the specified \a parent widget then
+ 0 should be returned.
+
+ \sa deleteWidget()
+*/
+QWidget *QWidgetAction::createWidget(QWidget *parent)
+{
+ Q_UNUSED(parent)
+ return 0;
+}
+
+/*!
+ This function is called whenever the action is removed from a
+ container widget that displays the action using a custom \a
+ widget previously created using createWidget(). The default
+ implementation hides the \a widget and schedules it for deletion
+ using QObject::deleteLater().
+
+ \sa createWidget()
+*/
+void QWidgetAction::deleteWidget(QWidget *widget)
+{
+ widget->hide();
+ widget->deleteLater();
+}
+
+/*!
+ Returns the list of widgets that have been using createWidget() and
+ are currently in use by widgets the action has been added to.
+*/
+QList<QWidget *> QWidgetAction::createdWidgets() const
+{
+ Q_D(const QWidgetAction);
+ return d->createdWidgets;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qwidgetaction.cpp"
+
+#endif // QT_NO_ACTION
diff --git a/src/gui/kernel/qwidgetaction.h b/src/gui/kernel/qwidgetaction.h
new file mode 100644
index 0000000000..a76222153d
--- /dev/null
+++ b/src/gui/kernel/qwidgetaction.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGETACTION_H
+#define QWIDGETACTION_H
+
+#include <QtGui/qaction.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACTION
+
+class QWidgetActionPrivate;
+
+class Q_GUI_EXPORT QWidgetAction : public QAction
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWidgetAction)
+
+public:
+ explicit QWidgetAction(QObject *parent);
+ virtual ~QWidgetAction();
+
+ void setDefaultWidget(QWidget *w);
+ QWidget *defaultWidget() const;
+
+ QWidget *requestWidget(QWidget *parent);
+ void releaseWidget(QWidget *widget);
+
+protected:
+ virtual bool event(QEvent *);
+ virtual bool eventFilter(QObject *, QEvent *);
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual void deleteWidget(QWidget *widget);
+ QList<QWidget *> createdWidgets() const;
+
+private:
+ Q_DISABLE_COPY(QWidgetAction)
+ Q_PRIVATE_SLOT(d_func(), void _q_widgetDestroyed(QObject *))
+ friend class QToolBar;
+};
+
+#endif // QT_NO_ACTION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWIDGETACTION_H
diff --git a/src/gui/kernel/qwidgetaction_p.h b/src/gui/kernel/qwidgetaction_p.h
new file mode 100644
index 0000000000..8099f9f05c
--- /dev/null
+++ b/src/gui/kernel/qwidgetaction_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIDGETACTION_P_H
+#define QWIDGETACTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qaction_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidgetActionPrivate : public QActionPrivate
+{
+ Q_DECLARE_PUBLIC(QWidgetAction)
+public:
+ inline QWidgetActionPrivate() : defaultWidgetInUse(false), autoCreated(false) {}
+ QPointer<QWidget> defaultWidget;
+ QList<QWidget *> createdWidgets;
+ uint defaultWidgetInUse : 1;
+ uint autoCreated : 1; // created by QToolBar::addWidget and the like
+
+ inline void _q_widgetDestroyed(QObject *o) {
+ createdWidgets.removeAll(static_cast<QWidget *>(o));
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/kernel/qwidgetcreate_x11.cpp b/src/gui/kernel/qwidgetcreate_x11.cpp
new file mode 100644
index 0000000000..40546f123d
--- /dev/null
+++ b/src/gui/kernel/qwidgetcreate_x11.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidget.h"
+#include "qt_x11_p.h"
+
+/*
+ Internal Qt functions to create X windows. We have put them in
+ separate functions to allow the programmer to reimplement them by
+ custom versions.
+*/
+
+QT_BEGIN_NAMESPACE
+
+Window qt_XCreateWindow(const QWidget *, Display *display, Window parent,
+ int x, int y, uint w, uint h,
+ int borderwidth, int depth,
+ uint windowclass, Visual *visual,
+ ulong valuemask, XSetWindowAttributes *attributes)
+{
+ return XCreateWindow(display, parent, x, y, w, h, borderwidth, depth,
+ windowclass, visual, valuemask, attributes);
+}
+
+
+Window qt_XCreateSimpleWindow(const QWidget *, Display *display, Window parent,
+ int x, int y, uint w, uint h, int borderwidth,
+ ulong border, ulong background)
+{
+ return XCreateSimpleWindow(display, parent, x, y, w, h, borderwidth,
+ border, background);
+}
+
+
+void qt_XDestroyWindow(const QWidget *, Display *display, Window window)
+{
+ if (window)
+ XDestroyWindow(display, window);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h
new file mode 100644
index 0000000000..85980300d4
--- /dev/null
+++ b/src/gui/kernel/qwindowdefs.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWDEFS_H
+#define QWINDOWDEFS_H
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+// Class forward definitions
+
+class QPaintDevice;
+class QWidget;
+class QDialog;
+class QColor;
+class QPalette;
+#ifdef QT3_SUPPORT
+class QColorGroup;
+#endif
+class QCursor;
+class QPoint;
+class QSize;
+class QRect;
+class QPolygon;
+class QPainter;
+class QRegion;
+class QFont;
+class QFontMetrics;
+class QFontInfo;
+class QPen;
+class QBrush;
+class QMatrix;
+class QPixmap;
+class QBitmap;
+class QMovie;
+class QImage;
+class QPicture;
+class QPrinter;
+class QTimer;
+class QTime;
+class QClipboard;
+class QString;
+class QByteArray;
+class QApplication;
+
+template<typename T> class QList;
+typedef QList<QWidget *> QWidgetList;
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// Window system dependent definitions
+
+#if defined(Q_WS_MAC) && !defined(Q_WS_QWS)
+
+#include <QtGui/qmacdefines_mac.h>
+
+#ifdef Q_WS_MAC32
+typedef int WId;
+#else
+typedef long WId;
+#endif
+
+#endif // Q_WS_MAC
+
+#if defined(Q_WS_WIN)
+#include <QtGui/qwindowdefs_win.h>
+#endif // Q_WS_WIN
+
+#if defined(Q_WS_X11)
+
+typedef struct _XDisplay Display;
+typedef union _XEvent XEvent;
+typedef struct _XGC *GC;
+typedef struct _XRegion *Region;
+typedef unsigned long WId;
+
+#endif // Q_WS_X11
+
+#if defined(Q_WS_QWS)
+
+typedef unsigned long WId;
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+struct QWSEvent;
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // Q_WS_QWS
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+template<class K, class V> class QHash;
+typedef QHash<WId, QWidget *> QWidgetMapper;
+
+template<class V> class QSet;
+typedef QSet<QWidget *> QWidgetSet;
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#if defined(QT_NEEDS_QMAIN)
+#define main qMain
+#endif
+
+// Global platform-independent types and functions
+
+#endif // QWINDOWDEFS_H
diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h
new file mode 100644
index 0000000000..3899c23aa6
--- /dev/null
+++ b/src/gui/kernel/qwindowdefs_win.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWDEFS_WIN_H
+#define QWINDOWDEFS_WIN_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+QT_END_NAMESPACE
+
+#if !defined(Q_NOWINSTRICT)
+#define Q_WINSTRICT
+#endif
+
+#if defined(Q_WINSTRICT)
+
+#if !defined(STRICT)
+#define STRICT
+#endif
+#undef NO_STRICT
+#define Q_DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
+
+#else
+
+#if !defined(NO_STRICT)
+#define NO_STRICT
+#endif
+#undef STRICT
+#define Q_DECLARE_HANDLE(name) typedef HANDLE name
+
+#endif
+
+#ifndef HINSTANCE
+Q_DECLARE_HANDLE(HINSTANCE);
+#endif
+#ifndef HDC
+Q_DECLARE_HANDLE(HDC);
+#endif
+#ifndef HWND
+Q_DECLARE_HANDLE(HWND);
+#endif
+#ifndef HFONT
+Q_DECLARE_HANDLE(HFONT);
+#endif
+#ifndef HPEN
+Q_DECLARE_HANDLE(HPEN);
+#endif
+#ifndef HBRUSH
+Q_DECLARE_HANDLE(HBRUSH);
+#endif
+#ifndef HBITMAP
+Q_DECLARE_HANDLE(HBITMAP);
+#endif
+#ifndef HICON
+Q_DECLARE_HANDLE(HICON);
+#endif
+#ifndef HCURSOR
+typedef HICON HCURSOR;
+#endif
+#ifndef HPALETTE
+Q_DECLARE_HANDLE(HPALETTE);
+#endif
+#ifndef HRGN
+Q_DECLARE_HANDLE(HRGN);
+#endif
+#ifndef HMONITOR
+Q_DECLARE_HANDLE(HMONITOR);
+#endif
+#ifndef HRESULT
+typedef long HRESULT;
+#endif
+
+typedef struct tagMSG MSG;
+typedef HWND WId;
+
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT HINSTANCE qWinAppInst();
+Q_CORE_EXPORT HINSTANCE qWinAppPrevInst();
+Q_GUI_EXPORT int qWinAppCmdShow();
+Q_GUI_EXPORT HDC qt_win_display_dc();
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWINDOWDEFS_WIN_H
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
new file mode 100644
index 0000000000..e49c4d65b3
--- /dev/null
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -0,0 +1,1807 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qx11embed_x11.h"
+#include <qapplication.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qdatetime.h>
+#include <qpointer.h>
+#include <qdebug.h>
+#include <qx11info_x11.h>
+#include <private/qt_x11_p.h>
+#include <private/qwidget_p.h>
+
+#define XK_MISCELLANY
+#define XK_LATIN1
+#define None 0
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/keysymdef.h>
+#include <X11/X.h>
+
+#ifndef XK_ISO_Left_Tab
+#define XK_ISO_Left_Tab 0xFE20
+#endif
+
+//#define QX11EMBED_DEBUG
+#ifdef QX11EMBED_DEBUG
+#include <qdebug.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QX11EmbedWidget
+ \ingroup advanced
+
+ \brief The QX11EmbedWidget class provides an XEmbed client widget.
+
+ XEmbed is an X11 protocol that supports the embedding of a widget
+ from one application into another application.
+
+ An XEmbed \e{client widget} is a window that is embedded into a
+ \e container. A container is the graphical location that embeds
+ (or \e swallows) an external application.
+
+ QX11EmbedWidget is a widget used for writing XEmbed applets or
+ plugins. When it has been embedded and the container receives tab
+ focus, focus is passed on to the widget. When the widget reaches
+ the end of its focus chain, focus is passed back to the
+ container. Window activation, accelerator support, modality and
+ drag and drop (XDND) are also handled.
+
+ The widget and container can both initiate the embedding. If the
+ widget is the initiator, the X11 window ID of the container that
+ it wants to embed itself into must be passed to embedInto().
+
+ If the container initiates the embedding, the window ID of the
+ embedded widget must be known. The container calls embed(),
+ passing the window ID.
+
+ This example shows an application that embeds a QX11EmbedWidget
+ subclass into the window whose ID is passed as a command-line
+ argument:
+
+ \snippet doc/src/snippets/qx11embedwidget/main.cpp 0
+
+ The problem of obtaining the window IDs is often solved by the
+ container invoking the application that provides the widget as a
+ separate process (as a panel invokes a docked applet), passing
+ its window ID to the new process as a command-line argument. The
+ new process can then call embedInto() with the container's window
+ ID, as shown in the example code above. Similarly, the new
+ process can report its window ID to the container through IPC, in
+ which case the container can embed the widget.
+
+ When the widget has been embedded, it emits the signal
+ embedded(). If it is closed by the container, the widget emits
+ containerClosed(). If an error occurs when embedding, error() is
+ emitted.
+
+ There are XEmbed widgets available for KDE and GTK+. The GTK+
+ equivalent of QX11EmbedWidget is GtkPlug. The KDE widget is called
+ QXEmbed.
+
+ \sa QX11EmbedContainer, {XEmbed Specification}
+*/
+
+/*!
+ \class QX11EmbedContainer
+ \ingroup advanced
+
+ \brief The QX11EmbedContainer class provides an XEmbed container
+ widget.
+
+ XEmbed is an X11 protocol that supports the embedding of a widget
+ from one application into another application.
+
+ An XEmbed \e container is the graphical location that embeds an
+ external \e {client widget}. A client widget is a window that is
+ embedded into a container.
+
+ When a widget has been embedded and the container receives tab
+ focus, focus is passed on to the widget. When the widget reaches
+ the end of its focus chain, focus is passed back to the
+ container. Window activation, accelerator support, modality and
+ drag and drop (XDND) are also handled.
+
+ QX11EmbedContainer is commonly used for writing panels or
+ toolbars that hold applets, or for \e swallowing X11
+ applications. When writing a panel application, one container
+ widget is created on the toolbar, and it can then either swallow
+ another widget using embed(), or allow an XEmbed widget to be
+ embedded into itself. The container's X11 window ID, which is
+ retrieved with winId(), must then be known to the client widget.
+ After embedding, the client's window ID can be retrieved with
+ clientWinId().
+
+ In the following example, a container widget is created as the
+ main widget. It then invokes an application called "playmovie",
+ passing its window ID as a command line argument. The "playmovie"
+ program is an XEmbed client widget. The widget embeds itself into
+ the container using the container's window ID.
+
+ \snippet doc/src/snippets/qx11embedcontainer/main.cpp 0
+
+ When the client widget is embedded, the container emits the
+ signal clientIsEmbedded(). The signal clientClosed() is emitted
+ when a widget is closed.
+
+ It is possible for QX11EmbedContainer to embed XEmbed widgets
+ from toolkits other than Qt, such as GTK+. Arbitrary (non-XEmbed)
+ X11 widgets can also be embedded, but the XEmbed-specific
+ features such as window activation and focus handling are then
+ lost.
+
+ The GTK+ equivalent of QX11EmbedContainer is GtkSocket. The KDE
+ widget is called QXEmbed.
+
+ \sa QX11EmbedWidget, {XEmbed Specification}
+*/
+
+/*! \fn void QX11EmbedWidget::embedded()
+
+ This signal is emitted by the widget that has been embedded by an
+ XEmbed container.
+*/
+
+/*! \fn void QX11EmbedWidget::containerClosed()
+
+ This signal is emitted by the client widget when the container
+ closes the widget. This can happen if the container itself
+ closes, or if the widget is rejected.
+
+ The container can reject a widget for any reason, but the most
+ common cause of a rejection is when an attempt is made to embed a
+ widget into a container that already has an embedded widget.
+*/
+
+/*! \fn void QX11EmbedContainer::clientIsEmbedded()
+
+ This signal is emitted by the container when a client widget has
+ been embedded.
+*/
+
+/*! \fn void QX11EmbedContainer::clientClosed()
+
+ This signal is emitted by the container when the client widget
+ closes.
+*/
+
+/*!
+ \fn void QX11EmbedWidget::error(QX11EmbedWidget::Error error)
+
+ This signal is emitted if an error occurred as a result of
+ embedding into or communicating with a container. The specified
+ \a error describes the problem that occurred.
+
+ \sa QX11EmbedWidget::Error
+*/
+
+/*!
+ \fn QX11EmbedContainer::Error QX11EmbedContainer::error() const
+
+ Returns the last error that occurred.
+*/
+
+/*! \fn void QX11EmbedContainer::error(QX11EmbedContainer::Error error)
+
+ This signal is emitted if an error occurred when embedding or
+ communicating with a client. The specified \a error describes the
+ problem that occurred.
+
+ \sa QX11EmbedContainer::Error
+*/
+
+/*!
+ \enum QX11EmbedWidget::Error
+
+ \value Unknown An unrecognized error occurred.
+
+ \value InvalidWindowID The X11 window ID of the container was
+ invalid. This error is usually triggered by passing an invalid
+ window ID to embedInto().
+
+ \omitvalue Internal
+*/
+
+/*!
+ \enum QX11EmbedContainer::Error
+
+ \value Unknown An unrecognized error occurred.
+
+ \value InvalidWindowID The X11 window ID of the container was
+ invalid. This error is usually triggered by passing an invalid
+ window ID to embed().
+
+ \omitvalue Internal
+*/
+
+const int XButtonPress = ButtonPress;
+const int XButtonRelease = ButtonRelease;
+#undef ButtonPress
+#undef ButtonRelease
+
+// This is a hack to move topData() out from QWidgetPrivate to public. We
+// need to to inspect window()'s embedded state.
+class QHackWidget : public QWidget
+{
+ Q_DECLARE_PRIVATE(QWidget)
+public:
+ QTLWExtra* topData() { return d_func()->topData(); }
+};
+
+static unsigned int XEMBED_VERSION = 0;
+
+enum QX11EmbedMessageType {
+ XEMBED_EMBEDDED_NOTIFY = 0,
+ XEMBED_WINDOW_ACTIVATE = 1,
+ XEMBED_WINDOW_DEACTIVATE = 2,
+ XEMBED_REQUEST_FOCUS = 3,
+ XEMBED_FOCUS_IN = 4,
+ XEMBED_FOCUS_OUT = 5,
+ XEMBED_FOCUS_NEXT = 6,
+ XEMBED_FOCUS_PREV = 7,
+ XEMBED_MODALITY_ON = 10,
+ XEMBED_MODALITY_OFF = 11,
+ XEMBED_REGISTER_ACCELERATOR = 12,
+ XEMBED_UNREGISTER_ACCELERATOR = 13,
+ XEMBED_ACTIVATE_ACCELERATOR = 14
+};
+
+enum QX11EmbedFocusInDetail {
+ XEMBED_FOCUS_CURRENT = 0,
+ XEMBED_FOCUS_FIRST = 1,
+ XEMBED_FOCUS_LAST = 2
+};
+
+enum QX11EmbedFocusInFlags {
+ XEMBED_FOCUS_OTHER = (0 << 0),
+ XEMBED_FOCUS_WRAPAROUND = (1 << 0)
+};
+
+enum QX11EmbedInfoFlags {
+ XEMBED_MAPPED = (1 << 0)
+};
+
+enum QX11EmbedAccelModifiers {
+ XEMBED_MODIFIER_SHIFT = (1 << 0),
+ XEMBED_MODIFIER_CONTROL = (1 << 1),
+ XEMBED_MODIFIER_ALT = (1 << 2),
+ XEMBED_MODIFIER_SUPER = (1 << 3),
+ XEMBED_MODIFIER_HYPER = (1 << 4)
+};
+
+enum QX11EmbedAccelFlags {
+ XEMBED_ACCELERATOR_OVERLOADED = (1 << 0)
+};
+
+// Silence the default X11 error handler.
+static int x11ErrorHandler(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+// Returns the X11 timestamp. Maintained mainly by qapplication
+// internals, but also updated by the XEmbed widgets.
+static Time x11Time()
+{
+ return qt_x11Data->time;
+}
+
+// Gives the version and flags of the supported XEmbed protocol.
+static unsigned int XEmbedVersion()
+{
+ return 0;
+}
+
+// Sends an XEmbed message.
+static void sendXEmbedMessage(WId window, Display *display, long message,
+ long detail = 0, long data1 = 0, long data2 = 0)
+{
+ XClientMessageEvent c;
+ memset(&c, 0, sizeof(c));
+ c.type = ClientMessage;
+ c.message_type = ATOM(_XEMBED);
+ c.format = 32;
+ c.display = display;
+ c.window = window;
+
+ c.data.l[0] = x11Time();
+ c.data.l[1] = message;
+ c.data.l[2] = detail;
+ c.data.l[3] = data1;
+ c.data.l[4] = data2;
+
+ XSendEvent(display, window, false, NoEventMask, (XEvent *) &c);
+}
+
+// From qapplication_x11.cpp
+static XKeyEvent lastKeyEvent;
+
+static QCoreApplication::EventFilter oldX11EventFilter;
+
+// The purpose of this global x11 filter is for one to capture the key
+// events in their original state, but most importantly this is the
+// only way to get the WM_TAKE_FOCUS message from WM_PROTOCOLS.
+static bool x11EventFilter(void *message, long *result)
+{
+ XEvent *event = reinterpret_cast<XEvent *>(message);
+ if (event->type == XKeyPress || event->type == XKeyRelease)
+ lastKeyEvent = event->xkey;
+
+ if (oldX11EventFilter && oldX11EventFilter != &x11EventFilter)
+ return oldX11EventFilter(message, result);
+ else
+ return false;
+}
+
+//
+struct functorData
+{
+ Window id, rootWindow;
+ bool clearedWmState;
+ bool reparentedToRoot;
+};
+
+static Bool functor(Display *display, XEvent *event, XPointer arg)
+{
+ functorData *data = (functorData *) arg;
+
+ if (!data->reparentedToRoot && event->type == ReparentNotify
+ && event->xreparent.window == data->id
+ && event->xreparent.parent == data->rootWindow) {
+ data->reparentedToRoot = true;
+ return true;
+ }
+
+ if (!data->clearedWmState
+ && event->type == PropertyNotify
+ && event->xproperty.window == data->id
+ && event->xproperty.atom == ATOM(WM_STATE)) {
+ if (event->xproperty.state == PropertyDelete) {
+ data->clearedWmState = true;
+ return true;
+ }
+
+ Atom ret;
+ int format, status;
+ unsigned char *retval;
+ unsigned long nitems, after;
+ status = XGetWindowProperty(display, data->id, ATOM(WM_STATE), 0, 2, False, ATOM(WM_STATE),
+ &ret, &format, &nitems, &after, &retval );
+ if (status == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) {
+ long *state = (long *)retval;
+ if (state[0] == WithdrawnState) {
+ data->clearedWmState = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+class QX11EmbedWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QX11EmbedWidget)
+public:
+ inline QX11EmbedWidgetPrivate()
+ {
+ lastError = QX11EmbedWidget::Unknown;
+ container = 0;
+ }
+
+ void setEmbedded();
+
+ void emitError(QX11EmbedWidget::Error error) {
+ Q_Q(QX11EmbedWidget);
+
+ lastError = error;
+ emit q->error(error);
+ }
+
+ enum FocusWidgets {
+ FirstFocusWidget,
+ LastFocusWidget
+ };
+
+ int focusOriginator;
+ QWidget *getFocusWidget(FocusWidgets fw);
+ void checkActivateWindow(QObject *o);
+ QX11EmbedWidget *xEmbedWidget(QObject *o) const;
+ void clearFocus();
+
+ WId container;
+ QPointer<QWidget> currentFocus;
+
+ QX11EmbedWidget::Error lastError;
+
+};
+
+/*!
+ Constructs a QX11EmbedWidget object with the given \a parent.
+*/
+QX11EmbedWidget::QX11EmbedWidget(QWidget *parent)
+ : QWidget(*new QX11EmbedWidgetPrivate, parent, 0)
+{
+ XSetErrorHandler(x11ErrorHandler);
+
+ setAttribute(Qt::WA_NativeWindow);
+ setAttribute(Qt::WA_DontCreateNativeAncestors);
+ createWinId();
+ XSelectInput(x11Info().display(), internalWinId(),
+ KeyPressMask | KeyReleaseMask | ButtonPressMask
+ | ButtonReleaseMask
+ | KeymapStateMask | ButtonMotionMask | PointerMotionMask
+ | FocusChangeMask
+ | ExposureMask | StructureNotifyMask
+ | SubstructureNotifyMask | PropertyChangeMask);
+
+ unsigned int data[] = {XEMBED_VERSION, XEMBED_MAPPED};
+ XChangeProperty(x11Info().display(), internalWinId(), ATOM(_XEMBED_INFO),
+ ATOM(_XEMBED_INFO), 32, PropModeReplace,
+ (unsigned char*) data, 2);
+
+ setFocusPolicy(Qt::StrongFocus);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QApplication::instance()->installEventFilter(this);
+
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::QX11EmbedWidget: constructed client"
+ << (void *)this << "with winId" << winId();
+#endif
+}
+
+/*!
+ Destructs the QX11EmbedWidget object. If the widget is embedded
+ when deleted, it is hidden and then detached from its container,
+ so that the container is free to embed a new widget.
+*/
+QX11EmbedWidget::~QX11EmbedWidget()
+{
+ Q_D(QX11EmbedWidget);
+ if (d->container) {
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::~QX11EmbedWidget: unmapping"
+ << (void *)this << "with winId" << winId()
+ << "from container with winId" << d->container;
+#endif
+ XUnmapWindow(x11Info().display(), internalWinId());
+ XReparentWindow(x11Info().display(), internalWinId(), x11Info().appRootWindow(), 0, 0);
+ }
+
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::~QX11EmbedWidget: destructed client"
+ << (void *)this << "with winId" << winId();
+#endif
+}
+
+/*!
+ Returns the type of error that occurred last. This is the same error code
+ that is emitted by the error() signal.
+
+ \sa Error
+*/
+QX11EmbedWidget::Error QX11EmbedWidget::error() const
+{
+ return d_func()->lastError;
+}
+
+/*!
+ When this function is called, the widget embeds itself into the
+ container whose window ID is \a id.
+
+ If \a id is \e not the window ID of a container this function will
+ behave unpredictably.
+*/
+void QX11EmbedWidget::embedInto(WId id)
+{
+ Q_D(QX11EmbedWidget);
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::embedInto: embedding client"
+ << (void *)this << "with winId" << winId() << "into container"
+ << id;
+#endif
+
+ d->container = id;
+ switch (XReparentWindow(x11Info().display(), internalWinId(), d->container, 0, 0)) {
+ case BadWindow:
+ d->emitError(InvalidWindowID);
+ break;
+ case BadMatch:
+ d->emitError(Internal);
+ break;
+ case Success:
+ default:
+ break;
+ }
+ QTLWExtra* x = d->extra ? d->extra->topextra : 0;
+ if (x)
+ x->frameStrut.setCoords(0, 0, 0, 0);
+ d->data.fstrut_dirty = false;
+}
+
+/*! \internal
+
+ Gets the first or last child widget that can get focus.
+*/
+QWidget *QX11EmbedWidgetPrivate::getFocusWidget(FocusWidgets fw)
+{
+ Q_Q(QX11EmbedWidget);
+ QWidget *tlw = q;
+ QWidget *w = tlw->nextInFocusChain();
+
+ QWidget *last = tlw;
+
+ extern bool qt_tab_all_widgets;
+ uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
+
+ while (w != tlw)
+ {
+ if (((w->focusPolicy() & focus_flag) == focus_flag)
+ && w->isVisibleTo(q) && w->isEnabled())
+ {
+ last = w;
+ if (fw == FirstFocusWidget)
+ break;
+ }
+ w = w->nextInFocusChain();
+ }
+
+ return last;
+}
+
+/*! \internal
+
+ Returns the xembed widget that the widget is a child of
+*/
+QX11EmbedWidget *QX11EmbedWidgetPrivate::xEmbedWidget(QObject *o) const
+{
+ QX11EmbedWidget *xec = 0;
+
+ // Check the widget itself, then its parents, and find the first
+ // QX11EmbedWidget.
+ do {
+ if ((xec = qobject_cast<QX11EmbedWidget *>(o)))
+ return xec;
+ } while ((o = o->parent()));
+ return 0;
+}
+
+/*! \internal
+
+ Checks the active window.
+*/
+void QX11EmbedWidgetPrivate::checkActivateWindow(QObject *o)
+{
+ Q_Q(QX11EmbedWidget);
+ QX11EmbedWidget *xec = xEmbedWidget(o);
+
+ // check if we are in the right xembed client
+ if (q != xec)
+ return;
+
+ QWidget *w = qobject_cast<QWidget *>(o);
+
+ // if it is no active window, then don't do the change
+ if (!(w && qApp->activeWindow()))
+ return;
+
+ // if it already is the active window, don't do anything
+ if (w->window() != qApp->activeWindow())
+ {
+ qApp->setActiveWindow(w->window());
+ currentFocus = w;
+
+ sendXEmbedMessage(xec->containerWinId(), q->x11Info().display(), XEMBED_REQUEST_FOCUS);
+ }
+}
+
+/*! \internal
+
+ Clears the focus
+*/
+void QX11EmbedWidgetPrivate::clearFocus()
+{
+ Q_Q(QX11EmbedWidget);
+ // Setting focus on the client itself removes Qt's
+ // logical focus rectangle. We can't just do a
+ // clearFocus here, because when we send the synthetic
+ // FocusIn to ourselves on activation, Qt will set
+ // focus on focusWidget() again. This way, we "hide"
+ // focus rather than clearing it.
+
+ if (!q->window()->hasFocus())
+ q->window()->setFocus(Qt::OtherFocusReason);
+
+ currentFocus = 0;
+}
+
+/*! \internal
+
+ Sets the embedded flag on the client.
+*/
+void QX11EmbedWidgetPrivate::setEmbedded()
+{
+ Q_Q(QX11EmbedWidget);
+ ((QHackWidget *)q->window())->topData()->embedded = 1;
+}
+
+/*! \internal
+
+ Handles WindowActivate and FocusIn events for the client.
+*/
+bool QX11EmbedWidget::eventFilter(QObject *o, QEvent *event)
+{
+ Q_D(QX11EmbedWidget);
+ switch (event->type()) {
+ case QEvent::FocusIn:
+ switch (((QFocusEvent *)event)->reason()) {
+ case Qt::MouseFocusReason:
+ // If the user clicks into one of the client widget's
+ // children and we didn't have focus already, we request
+ // focus from our container.
+ if (d->xEmbedWidget(o) == this) {
+ if (d->currentFocus.isNull())
+ sendXEmbedMessage(d->container, x11Info().display(), XEMBED_REQUEST_FOCUS);
+
+ d->currentFocus = qobject_cast<QWidget *>(o);
+ }
+ break;
+ case Qt::TabFocusReason:
+ // If the xembed client receives a focus event because of
+ // a Tab, then we are at the end of our focus chain and we
+ // ask the container to move to its next focus widget.
+ if (o == this) {
+ d->clearFocus();
+ sendXEmbedMessage(d->container, x11Info().display(), XEMBED_FOCUS_NEXT);
+ return true;
+ } else {
+ // We're listening on events from qApp, so in order
+ // for us to know who to set focus on if we receive an
+ // activation event, we note the widget that got the
+ // focusin last.
+ if (d->xEmbedWidget(o) == this)
+ d->currentFocus = qobject_cast<QWidget *>(o);
+ }
+ break;
+ case Qt::BacktabFocusReason:
+ // If the window receives a focus event because of
+ // a Backtab, then we are at the start of our focus chain
+ // and we ask the container to move to its previous focus
+ // widget.
+ if (o == this) {
+ // See comment for Tab.
+ // If we receive a XEMBED_FOCUS_IN
+ // XEMBED_FOCUS_CURRENT, we will set focus in
+ // currentFocus. To avoid that in this case, we reset
+ // currentFocus.
+ d->clearFocus();
+ sendXEmbedMessage(d->container, x11Info().display(), XEMBED_FOCUS_PREV);
+ return true;
+ } else {
+ if (d->xEmbedWidget(o) == this)
+ d->currentFocus = qobject_cast<QWidget *>(o);
+ }
+ break;
+ case Qt::ActiveWindowFocusReason:
+ if (isActiveWindow()) {
+ if (!d->currentFocus.isNull()) {
+ if (!d->currentFocus->hasFocus())
+ d->currentFocus->setFocus(Qt::OtherFocusReason);
+ } else {
+ d->clearFocus();
+ return true;
+ }
+ }
+
+ break;
+ case Qt::PopupFocusReason:
+ case Qt::ShortcutFocusReason:
+ case Qt::OtherFocusReason:
+ // If focus is received to any child widget because of any
+ // other reason, remember the widget so that we can give
+ // it focus again if we're activated.
+ if (d->xEmbedWidget(o) == this) {
+ d->currentFocus = qobject_cast<QWidget *>(o);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ // If we get a mouse button press event inside a embedded widget
+ // make sure this is the active window in qapp.
+ d->checkActivateWindow(o);
+ break;
+ default:
+ break;
+ }
+
+ return QWidget::eventFilter(o, event);
+}
+
+/*! \internal
+
+ Handles some notification events and client messages. Client side
+ XEmbed message receiving is also handled here.
+*/
+bool QX11EmbedWidget::x11Event(XEvent *event)
+{
+ Q_D(QX11EmbedWidget);
+ switch (event->type) {
+ case DestroyNotify:
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::x11Event: client"
+ << (void *)this << "with winId" << winId()
+ << "received a DestroyNotify";
+#endif
+ // If the container window is destroyed, we signal this to the user.
+ d->container = 0;
+ emit containerClosed();
+ break;
+ case ReparentNotify:
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::x11Event: client"
+ << (void *)this << "with winId" << winId()
+ << "received a ReparentNotify to"
+ << ((event->xreparent.parent == x11Info().appRootWindow())
+ ? QString::fromLatin1("root") : QString::number(event->xreparent.parent));
+#endif
+ // If the container shuts down, we will be reparented to the
+ // root window. We must also consider the case that we may be
+ // reparented from one container to another.
+ if (event->xreparent.parent == x11Info().appRootWindow()) {
+ if (((QHackWidget *)this)->topData()->embedded) {
+ d->container = 0;
+ emit containerClosed();
+ }
+ return true;
+ } else {
+ d->container = event->xreparent.parent;
+ }
+ break;
+ case UnmapNotify:
+ // Mapping and unmapping are handled by changes to the
+ // _XEMBED_INFO property. Any default map/unmap requests are
+ // ignored.
+ return true;
+ case PropertyNotify:
+ // The container sends us map/unmap messages through the
+ // _XEMBED_INFO property. We adhere to the XEMBED_MAPPED bit in
+ // data2.
+ if (event->xproperty.atom == ATOM(_XEMBED_INFO)) {
+ Atom actual_type_return;
+ int actual_format_return;
+ unsigned long nitems_return;
+ unsigned long bytes_after_return;
+ unsigned char *prop_return = 0;
+ if (XGetWindowProperty(x11Info().display(), internalWinId(), ATOM(_XEMBED_INFO), 0, 2,
+ false, ATOM(_XEMBED_INFO), &actual_type_return,
+ &actual_format_return, &nitems_return,
+ &bytes_after_return, &prop_return) == Success) {
+ if (nitems_return > 1) {
+ if (((int * )prop_return)[1] & XEMBED_MAPPED) {
+ XMapWindow(x11Info().display(), internalWinId());
+ } else {
+ XUnmapWindow(x11Info().display(), internalWinId());
+ }
+ }
+ }
+ }
+
+ break;
+ case ClientMessage:
+ // XEMBED messages have message_type _XEMBED
+ if (event->xclient.message_type == ATOM(_XEMBED)) {
+ // Discard XEMBED messages not to ourselves. (### dead code?)
+ if (event->xclient.window != internalWinId())
+ break;
+
+ // Update qt_x_time if necessary
+ Time msgtime = (Time) event->xclient.data.l[0];
+ if (msgtime > X11->time)
+ X11->time = msgtime;
+
+ switch (event->xclient.data.l[1]) {
+ case XEMBED_WINDOW_ACTIVATE: {
+ // When we receive an XEMBED_WINDOW_ACTIVATE, we simply send
+ // ourselves a WindowActivate event. Real activation happens
+ // when receive XEMBED_FOCUS_IN.
+ if (!isActiveWindow()) {
+ QEvent ev(QEvent::WindowActivate);
+ QApplication::sendEvent(this, &ev);
+ }
+ }
+ break;
+ case XEMBED_WINDOW_DEACTIVATE: {
+ // When we receive an XEMBED_WINDOW_DEACTIVATE, we simply send
+ // ourselves a WindowDeactivate event. Real activation happens
+ // when receive XEMBED_FOCUS_IN.
+ if (isActiveWindow()) {
+ if (!qApp->activePopupWidget())
+ QApplication::setActiveWindow(0);
+ } else {
+ QEvent ev(QEvent::WindowDeactivate);
+ QApplication::sendEvent(this, &ev);
+ }
+ }
+ break;
+ case XEMBED_EMBEDDED_NOTIFY: {
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedWidget::x11Event: client"
+ << (void *)this << "with winId" << winId()
+ << "received an XEMBED EMBEDDED NOTIFY message";
+#endif
+ // In this message's l[2] we have the max version
+ // supported by both the client and the
+ // container. QX11EmbedWidget does not use this field.
+
+ // We have been embedded, so we set our
+ // client's embedded flag.
+ d->setEmbedded();
+ emit embedded();
+ }
+ break;
+ case XEMBED_FOCUS_IN:
+ // don't set the focus if a modal dialog is open
+ if (qApp->activeModalWidget())
+ break;
+
+ // in case we embed more than one topLevel window inside the same
+ // host window.
+ if (window() != qApp->activeWindow())
+ qApp->setActiveWindow(this);
+
+ switch (event->xclient.data.l[2]) {
+ case XEMBED_FOCUS_CURRENT:
+ // The container sends us this message if it wants
+ // us to focus on the widget that last had focus.
+ // This is the reply when XEMBED_REQUEST_FOCUS is
+ // sent to the container.
+ if (!d->currentFocus.isNull()) {
+ if (!d->currentFocus->hasFocus())
+ d->currentFocus->setFocus(Qt::OtherFocusReason);
+ } else {
+ // No widget currently has focus. We set focus
+ // on the first widget next to the
+ // client widget. Since the setFocus will not work
+ // if the window is disabled, set the currentFocus
+ // directly so that it's set on window activate.
+ d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::FirstFocusWidget);
+ d->currentFocus->setFocus(Qt::OtherFocusReason);
+ }
+ break;
+ case XEMBED_FOCUS_FIRST:
+ // The container sends this message when it wants
+ // us to focus on the first widget in our focus
+ // chain (typically because of a tab).
+ d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::FirstFocusWidget);
+ d->currentFocus->setFocus(Qt::TabFocusReason);
+ break;
+ case XEMBED_FOCUS_LAST:
+ // The container sends this message when it wants
+ // us to focus on the last widget in our focus
+ // chain (typically because of a backtab).
+ d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::LastFocusWidget);
+ d->currentFocus->setFocus(Qt::BacktabFocusReason);
+ break;
+ default:
+ // Ignore any other XEMBED_FOCUS_IN details.
+ break;
+ }
+ break;
+ case XEMBED_FOCUS_OUT:
+ // The container sends us this message when it wants us
+ // to lose focus and forget about the widget that last
+ // had focus. Typically sent by the container when it
+ // loses focus because of mouse or tab activity. We do
+ // then not want to set focus on anything if we're
+ // activated.
+ if (isActiveWindow())
+ d->clearFocus();
+
+ break;
+ default:
+ // Ignore any other XEMBED messages.
+ break;
+ };
+ } else {
+ // Non-XEMBED client messages are not interesting.
+ }
+
+ break;
+ default:
+ // Ignore all other x11 events.
+ break;
+ }
+
+ // Allow default handling.
+ return QWidget::x11Event(event);
+}
+
+/*!
+ \reimp
+*/
+bool QX11EmbedWidget::event(QEvent *event)
+{
+ if (event->type() == QEvent::ParentChange) {
+ XSelectInput(x11Info().display(), internalWinId(),
+ KeyPressMask | KeyReleaseMask | ButtonPressMask
+ | ButtonReleaseMask
+ | KeymapStateMask | ButtonMotionMask | PointerMotionMask
+ | FocusChangeMask
+ | ExposureMask | StructureNotifyMask
+ | SubstructureNotifyMask | PropertyChangeMask);
+ }
+ return QWidget::event(event);
+}
+
+/*!
+ \reimp
+*/
+void QX11EmbedWidget::resizeEvent(QResizeEvent *event)
+{
+ if (layout())
+ layout()->update();
+ QWidget::resizeEvent(event);
+}
+
+/*!
+ If the widget is embedded, returns the window ID of the
+ container; otherwize returns 0.
+*/
+WId QX11EmbedWidget::containerWinId() const
+{
+ Q_D(const QX11EmbedWidget);
+ return d->container;
+}
+
+class QX11EmbedContainerPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QX11EmbedContainer)
+public:
+ inline QX11EmbedContainerPrivate()
+ {
+ lastError = QX11EmbedContainer::Unknown;
+ client = 0;
+ focusProxy = 0;
+ clientIsXEmbed = false;
+ xgrab = false;
+ }
+
+ bool isEmbedded() const;
+ void moveInputToProxy();
+
+ void acceptClient(WId window);
+ void rejectClient(WId window);
+
+ void checkGrab();
+
+ WId topLevelParentWinId() const;
+
+ void emitError(QX11EmbedContainer::Error error) {
+ Q_Q(QX11EmbedContainer);
+ lastError = error;
+ emit q->error(error);
+ }
+
+ WId client;
+ QWidget *focusProxy;
+ bool clientIsXEmbed;
+ bool xgrab;
+ QRect clientOriginalRect;
+ QSize wmMinimumSizeHint;
+
+ QX11EmbedContainer::Error lastError;
+
+ static QX11EmbedContainer *activeContainer;
+};
+
+QX11EmbedContainer *QX11EmbedContainerPrivate::activeContainer = 0;
+
+/*!
+ Creates a QX11EmbedContainer object with the given \a parent.
+*/
+QX11EmbedContainer::QX11EmbedContainer(QWidget *parent)
+ : QWidget(*new QX11EmbedContainerPrivate, parent, 0)
+{
+ Q_D(QX11EmbedContainer);
+ XSetErrorHandler(x11ErrorHandler);
+
+ setAttribute(Qt::WA_NativeWindow);
+ setAttribute(Qt::WA_DontCreateNativeAncestors);
+ createWinId();
+
+ setFocusPolicy(Qt::StrongFocus);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ // ### PORT setKeyCompression(false);
+ setAcceptDrops(true);
+ setEnabled(false);
+
+ // Everybody gets a focus proxy, but only one toplevel container's
+ // focus proxy is actually in use.
+ d->focusProxy = new QWidget(this);
+ d->focusProxy->setAttribute(Qt::WA_NativeWindow);
+ d->focusProxy->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ d->focusProxy->setGeometry(-1, -1, 1, 1);
+
+ // We need events from the window (activation status) and
+ // from qApp (keypress/release).
+ qApp->installEventFilter(this);
+
+ // Install X11 event filter.
+ if (!oldX11EventFilter)
+ oldX11EventFilter = QCoreApplication::instance()->setEventFilter(x11EventFilter);
+
+ XSelectInput(x11Info().display(), internalWinId(),
+ KeyPressMask | KeyReleaseMask
+ | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+ | KeymapStateMask
+ | PointerMotionMask
+ | EnterWindowMask | LeaveWindowMask
+ | FocusChangeMask
+ | ExposureMask
+ | StructureNotifyMask
+ | SubstructureNotifyMask);
+
+ // Make sure our new event mask takes effect as soon as possible.
+ XFlush(x11Info().display());
+
+ // Move input to our focusProxy if this widget is active, and not
+ // shaded by a modal dialog (in which case isActiveWindow() would
+ // still return true, but where we must not move input focus).
+ if (qApp->activeWindow() == window() && !d->isEmbedded())
+ d->moveInputToProxy();
+
+#ifdef QX11EMBED_DEBUG
+ qDebug() << "QX11EmbedContainer::QX11EmbedContainer: constructed container"
+ << (void *)this << "with winId" << winId();
+#endif
+}
+
+/*!
+ Destructs a QX11EmbedContainer.
+*/
+QX11EmbedContainer::~QX11EmbedContainer()
+{
+ Q_D(QX11EmbedContainer);
+ if (d->client) {
+ XUnmapWindow(x11Info().display(), d->client);
+ XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(), 0, 0);
+ }
+
+ if (d->xgrab)
+ XUngrabButton(x11Info().display(), AnyButton, AnyModifier, internalWinId());
+}
+
+
+QX11EmbedContainer::Error QX11EmbedContainer::error() const {
+ return d_func()->lastError;
+}
+
+
+/*! \reimp
+*/
+void QX11EmbedContainer::paintEvent(QPaintEvent *)
+{
+}
+
+/*! \internal
+
+ Returns wether or not the windows' embedded flag is set.
+*/
+bool QX11EmbedContainerPrivate::isEmbedded() const
+{
+ Q_Q(const QX11EmbedContainer);
+ return ((QHackWidget *)q->window())->topData()->embedded == 1;
+}
+
+/*! \internal
+
+ Returns the parentWinId of the window.
+*/
+WId QX11EmbedContainerPrivate::topLevelParentWinId() const
+{
+ Q_Q(const QX11EmbedContainer);
+ return ((QHackWidget *)q->window())->topData()->parentWinId;
+}
+
+/*!
+ If the container has an embedded widget, this function returns
+ the X11 window ID of the client; otherwise it returns 0.
+*/
+WId QX11EmbedContainer::clientWinId() const
+{
+ Q_D(const QX11EmbedContainer);
+ return d->client;
+}
+
+/*!
+ Instructs the container to embed the X11 window with window ID \a
+ id. The client widget will then move on top of the container
+ window and be resized to fit into the container.
+
+ The \a id should be the ID of a window controlled by an XEmbed
+ enabled application, but this is not mandatory. If \a id does not
+ belong to an XEmbed client widget, then focus handling,
+ activation, accelerators and other features will not work
+ properly.
+*/
+void QX11EmbedContainer::embedClient(WId id)
+{
+ Q_D(QX11EmbedContainer);
+
+ if (id == 0) {
+ d->emitError(InvalidWindowID);
+ return;
+ }
+
+ // Walk up the tree of parent windows to prevent embedding of ancestors.
+ WId thisId = internalWinId();
+ Window rootReturn;
+ Window parentReturn;
+ Window *childrenReturn = 0;
+ unsigned int nchildrenReturn;
+ do {
+ if (XQueryTree(x11Info().display(), thisId, &rootReturn,
+ &parentReturn, &childrenReturn, &nchildrenReturn) == 0) {
+ d->emitError(InvalidWindowID);
+ return;
+ }
+ if (childrenReturn) {
+ XFree(childrenReturn);
+ childrenReturn = 0;
+ }
+
+ thisId = parentReturn;
+ if (id == thisId) {
+ d->emitError(InvalidWindowID);
+ return;
+ }
+ } while (thisId != rootReturn);
+
+ // watch for property notify events (see below)
+ XGrabServer(x11Info().display());
+ XWindowAttributes attrib;
+ if (!XGetWindowAttributes(x11Info().display(), id, &attrib)) {
+ XUngrabServer(x11Info().display());
+ d->emitError(InvalidWindowID);
+ return;
+ }
+ XSelectInput(x11Info().display(), id, attrib.your_event_mask | PropertyChangeMask | StructureNotifyMask);
+ XUngrabServer(x11Info().display());
+
+ // Put the window into WithdrawnState
+ XUnmapWindow(x11Info().display(), id);
+ XSync(x11Info().display(), False); // make sure the window is hidden
+
+ /*
+ Wait for notification from the window manager that the window is
+ in withdrawn state. According to the ICCCM section 4.1.3.1,
+ we should wait for the WM_STATE property to either be deleted or
+ set to WithdrawnState.
+
+ For safety, we will not wait more than 500 ms, so that we can
+ preemptively workaround buggy window managers.
+ */
+ QTime t;
+ t.start();
+
+ functorData data;
+ data.id = id;
+ data.rootWindow = attrib.root;
+ data.clearedWmState = false;
+ data.reparentedToRoot = false;
+
+ do {
+ if (t.elapsed() > 500) // time-out after 500 ms
+ break;
+
+ XEvent event;
+ if (!XCheckIfEvent(x11Info().display(), &event, functor, (XPointer) &data)) {
+ XSync(x11Info().display(), False);
+ usleep(50000);
+ continue;
+ }
+
+ qApp->x11ProcessEvent(&event);
+ } while (!data.clearedWmState || !data.reparentedToRoot);
+
+ // restore the event mask
+ XSelectInput(x11Info().display(), id, attrib.your_event_mask);
+
+ switch (XReparentWindow(x11Info().display(), id, internalWinId(), 0, 0)) {
+ case BadWindow:
+ case BadMatch:
+ d->emitError(InvalidWindowID);
+ break;
+ default:
+ break;
+ }
+}
+
+/*! \internal
+
+ Handles key, activation and focus events for the container.
+*/
+bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
+{
+ Q_D(QX11EmbedContainer);
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ // Forward any keypresses to our client.
+ if (o == this && d->client) {
+ lastKeyEvent.window = d->client;
+ XSendEvent(x11Info().display(), d->client, false, KeyPressMask, (XEvent *) &lastKeyEvent);
+ return true;
+ }
+ break;
+ case QEvent::KeyRelease:
+ // Forward any keyreleases to our client.
+ if (o == this && d->client) {
+ lastKeyEvent.window = d->client;
+ XSendEvent(x11Info().display(), d->client, false, KeyReleaseMask, (XEvent *) &lastKeyEvent);
+ return true;
+ }
+ break;
+
+ case QEvent::WindowActivate:
+ // When our container window is activated, we pass the
+ // activation message on to our client. Note that X input
+ // focus is set to our focus proxy. We want to intercept all
+ // keypresses.
+ if (o == window() && d->client) {
+ if (!d->isEmbedded() && d->activeContainer == this)
+ d->moveInputToProxy();
+
+ if (d->clientIsXEmbed) {
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_ACTIVATE);
+ } else {
+ d->checkGrab();
+ if (hasFocus())
+ XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time());
+ }
+ }
+ break;
+ case QEvent::WindowDeactivate:
+ // When our container window is deactivated, we pass the
+ // deactivation message to our client.
+ if (o == window() && d->client) {
+ if (d->clientIsXEmbed)
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_DEACTIVATE);
+ else
+ d->checkGrab();
+ }
+ break;
+ case QEvent::FocusIn:
+ // When receiving FocusIn events generated by Tab or Backtab,
+ // we pass focus on to our client. Any mouse activity is sent
+ // directly to the client, and it will ask us for focus with
+ // XEMBED_REQUEST_FOCUS.
+ if (o == this && d->client) {
+ if (!d->isEmbedded())
+ d->activeContainer = this;
+
+ if (d->clientIsXEmbed) {
+ if (!d->isEmbedded())
+ d->moveInputToProxy();
+
+ QFocusEvent *fe = (QFocusEvent *)event;
+ switch (fe->reason()) {
+ case Qt::TabFocusReason:
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_FIRST);
+ break;
+ case Qt::BacktabFocusReason:
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_LAST);
+ break;
+ default:
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
+ break;
+ }
+ } else {
+ d->checkGrab();
+ XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time());
+ }
+ }
+
+ break;
+ case QEvent::FocusOut: {
+ // When receiving a FocusOut, we ask our client to remove its
+ // focus.
+ if (o == this && d->client) {
+ if (!d->isEmbedded()) {
+ d->activeContainer = 0;
+ if (isActiveWindow())
+ d->moveInputToProxy();
+ }
+
+ if (d->clientIsXEmbed) {
+ QFocusEvent *fe = (QFocusEvent *)event;
+ if (o == this && d->client && fe->reason() != Qt::ActiveWindowFocusReason)
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_OUT);
+ } else {
+ d->checkGrab();
+ }
+ }
+ }
+ break;
+
+ case QEvent::Close: {
+ if (o == this && d->client) {
+ // Unmap the client and reparent it to the root window.
+ // Wait until the messages have been processed. Then ask
+ // the window manager to delete the window.
+ XUnmapWindow(x11Info().display(), d->client);
+ XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(), 0, 0);
+ XSync(x11Info().display(), false);
+
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = d->client;
+ ev.xclient.message_type = ATOM(WM_PROTOCOLS);
+ ev.xclient.format = 32;
+ ev.xclient.data.s[0] = ATOM(WM_DELETE_WINDOW);
+ XSendEvent(x11Info().display(), d->client, false, NoEventMask, &ev);
+
+ XFlush(x11Info().display());
+ d->client = 0;
+ d->clientIsXEmbed = false;
+ d->wmMinimumSizeHint = QSize();
+ updateGeometry();
+ setEnabled(false);
+ update();
+
+ emit clientClosed();
+ }
+ }
+ default:
+ break;
+ }
+
+ return QWidget::eventFilter(o, event);
+}
+
+/*! \internal
+
+ Handles X11 events for the container.
+*/
+bool QX11EmbedContainer::x11Event(XEvent *event)
+{
+ Q_D(QX11EmbedContainer);
+
+ switch (event->type) {
+ case CreateNotify:
+ // The client created an embedded window.
+ if (d->client)
+ d->rejectClient(event->xcreatewindow.window);
+ else
+ d->acceptClient(event->xcreatewindow.window);
+ break;
+ case DestroyNotify:
+ if (event->xdestroywindow.window == d->client) {
+ // The client died.
+ d->client = 0;
+ d->clientIsXEmbed = false;
+ d->wmMinimumSizeHint = QSize();
+ updateGeometry();
+ update();
+ setEnabled(false);
+ emit clientClosed();
+ }
+ break;
+ case ReparentNotify:
+ // The client sends us this if it reparents itself out of our
+ // widget.
+ if (event->xreparent.window == d->client && event->xreparent.parent != internalWinId()) {
+ d->client = 0;
+ d->clientIsXEmbed = false;
+ d->wmMinimumSizeHint = QSize();
+ updateGeometry();
+ update();
+ setEnabled(false);
+ emit clientClosed();
+ } else if (event->xreparent.parent == internalWinId()) {
+ // The client reparented itself into this window.
+ if (d->client)
+ d->rejectClient(event->xreparent.window);
+ else
+ d->acceptClient(event->xreparent.window);
+ }
+ break;
+ case ClientMessage: {
+ if (event->xclient.message_type == ATOM(_XEMBED)) {
+ // Ignore XEMBED messages not to ourselves
+ if (event->xclient.window != internalWinId())
+ break;
+
+ // Receiving an XEmbed message means the client
+ // is an XEmbed client.
+ d->clientIsXEmbed = true;
+
+ Time msgtime = (Time) event->xclient.data.l[0];
+ if (msgtime > X11->time)
+ X11->time = msgtime;
+
+ switch (event->xclient.data.l[1]) {
+ case XEMBED_REQUEST_FOCUS: {
+ // This typically happens when the client gets focus
+ // because of a mouse click.
+ if (!hasFocus())
+ setFocus(Qt::OtherFocusReason);
+
+ // The message is passed along to the topmost container
+ // that eventually responds with a XEMBED_FOCUS_IN
+ // message. The focus in message is passed all the way
+ // back until it reaches the original focus
+ // requestor. In the end, not only the original client
+ // has focus, but also all its ancestor containers.
+ if (d->isEmbedded()) {
+ // If our window's embedded flag is set, then
+ // that suggests that we are part of a client. The
+ // parentWinId will then point to an container to whom
+ // we must pass this message.
+ sendXEmbedMessage(d->topLevelParentWinId(), x11Info().display(), XEMBED_REQUEST_FOCUS);
+ } else {
+ // Our window's embedded flag is not set,
+ // so we are the topmost container. We respond to
+ // the focus request message with a focus in
+ // message. This message will pass on from client
+ // to container to client until it reaches the
+ // originator of the XEMBED_REQUEST_FOCUS message.
+ sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
+ }
+
+ break;
+ }
+ case XEMBED_FOCUS_NEXT:
+ // Client sends this event when it received a tab
+ // forward and was at the end of its focus chain. If
+ // we are the only widget in the focus chain, we send
+ // ourselves a FocusIn event.
+ if (d->focus_next != this) {
+ focusNextPrevChild(true);
+ } else {
+ QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
+ qApp->sendEvent(this, &event);
+ }
+
+ break;
+ case XEMBED_FOCUS_PREV:
+ // Client sends this event when it received a backtab
+ // and was at the start of its focus chain. If we are
+ // the only widget in the focus chain, we send
+ // ourselves a FocusIn event.
+ if (d->focus_next != this) {
+ focusNextPrevChild(false);
+ } else {
+ QFocusEvent event(QEvent::FocusIn, Qt::BacktabFocusReason);
+ qApp->sendEvent(this, &event);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ case XButtonPress:
+ if (!d->clientIsXEmbed) {
+ setFocus(Qt::MouseFocusReason);
+ XAllowEvents(x11Info().display(), ReplayPointer, CurrentTime);
+ return true;
+ }
+ break;
+ case XButtonRelease:
+ if (!d->clientIsXEmbed)
+ XAllowEvents(x11Info().display(), SyncPointer, CurrentTime);
+ break;
+ default:
+ break;
+ }
+
+ return QWidget::x11Event(event);
+}
+
+/*! \internal
+
+ Whenever the container is resized, we need to resize our client.
+*/
+void QX11EmbedContainer::resizeEvent(QResizeEvent *)
+{
+ Q_D(QX11EmbedContainer);
+ if (d->client)
+ XResizeWindow(x11Info().display(), d->client, width(), height());
+}
+
+/*! \internal
+
+ We use the QShowEvent to signal to our client that we want it to
+ map itself. We do this by changing its window property
+ XEMBED_INFO. The client will get an X11 PropertyNotify.
+*/
+void QX11EmbedContainer::showEvent(QShowEvent *)
+{
+ Q_D(QX11EmbedContainer);
+ if (d->client) {
+ unsigned int data[] = {XEMBED_VERSION, XEMBED_MAPPED};
+ XChangeProperty(x11Info().display(), d->client, ATOM(_XEMBED_INFO), ATOM(_XEMBED_INFO), 32,
+ PropModeReplace, (unsigned char *) data, 2);
+ }
+}
+
+/*! \internal
+
+ We use the QHideEvent to signal to our client that we want it to
+ unmap itself. We do this by changing its window property
+ XEMBED_INFO. The client will get an X11 PropertyNotify.
+*/
+void QX11EmbedContainer::hideEvent(QHideEvent *)
+{
+ Q_D(QX11EmbedContainer);
+ if (d->client) {
+ unsigned int data[] = {XEMBED_VERSION, XEMBED_MAPPED};
+
+ XChangeProperty(x11Info().display(), d->client, ATOM(_XEMBED_INFO), ATOM(_XEMBED_INFO), 32,
+ PropModeReplace, (unsigned char *) data, 2);
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QX11EmbedContainer::event(QEvent *event)
+{
+ if (event->type() == QEvent::ParentChange) {
+ XSelectInput(x11Info().display(), internalWinId(),
+ KeyPressMask | KeyReleaseMask
+ | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+ | KeymapStateMask
+ | PointerMotionMask
+ | EnterWindowMask | LeaveWindowMask
+ | FocusChangeMask
+ | ExposureMask
+ | StructureNotifyMask
+ | SubstructureNotifyMask);
+ }
+ return QWidget::event(event);
+}
+
+/*! \internal
+
+ Rejects a client window by reparenting it to the root window. The
+ client will receive a reparentnotify, and will most likely assume
+ that the container has shut down. The XEmbed protocol does not
+ define any way to reject a client window, but this is a clean way
+ to do it.
+*/
+void QX11EmbedContainerPrivate::rejectClient(WId window)
+{
+ Q_Q(QX11EmbedContainer);
+ q->setEnabled(false);
+ XRemoveFromSaveSet(q->x11Info().display(), client);
+ XReparentWindow(q->x11Info().display(), window, q->x11Info().appRootWindow(), 0, 0);
+}
+
+/*! \internal
+
+ Accepts a client by mapping it, resizing it and optionally
+ activating and giving it logical focusing through XEMBED messages.
+*/
+void QX11EmbedContainerPrivate::acceptClient(WId window)
+{
+ Q_Q(QX11EmbedContainer);
+ client = window;
+ q->setEnabled(true);
+
+ // This tells Qt that we wish to forward DnD messages to
+ // our client.
+ if (!extra)
+ createExtra();
+ extraData()->xDndProxy = client;
+
+ unsigned int version = XEmbedVersion();
+
+ Atom actual_type_return;
+ int actual_format_return;
+ unsigned long nitems_return = 0;
+ unsigned long bytes_after_return;
+ unsigned char *prop_return = 0;
+ unsigned int clientversion = 0;
+
+ // Add this client to our saveset, so if we crash, the client window
+ // doesn't get destroyed. This is useful for containers that restart
+ // automatically after a crash, because it can simply reembed its clients
+ // without having to restart them (KDE panel).
+ XAddToSaveSet(q->x11Info().display(), client);
+
+ // XEmbed clients have an _XEMBED_INFO property in which we can
+ // fetch the version
+ if (XGetWindowProperty(q->x11Info().display(), client, ATOM(_XEMBED_INFO), 0, 2, false,
+ ATOM(_XEMBED_INFO), &actual_type_return, &actual_format_return,
+ &nitems_return, &bytes_after_return, &prop_return) == Success) {
+
+ if (actual_type_return != None && actual_format_return != 0) {
+ // Clients with the _XEMBED_INFO property are XEMBED clients.
+ clientIsXEmbed = true;
+
+ unsigned int *p = (unsigned int *)prop_return;
+ if (nitems_return >= 2)
+ clientversion = p[0];
+ }
+
+ XFree(prop_return);
+ }
+
+ // Store client window's original size and placement.
+ Window root;
+ int x_return, y_return;
+ unsigned int width_return, height_return, border_width_return, depth_return;
+ XGetGeometry(q->x11Info().display(), client, &root, &x_return, &y_return,
+ &width_return, &height_return, &border_width_return, &depth_return);
+ clientOriginalRect.setCoords(x_return, y_return,
+ x_return + width_return - 1,
+ y_return + height_return - 1);
+
+ // Ask the client for its minimum size.
+ XSizeHints size;
+ long msize;
+ if (XGetWMNormalHints(q->x11Info().display(), client, &size, &msize) && (size.flags & PMinSize)) {
+ wmMinimumSizeHint = QSize(size.min_width, size.min_height);
+ q->updateGeometry();
+ }
+
+ // The container should set the data2 field to the lowest of its
+ // supported version number and that of the client (from
+ // _XEMBED_INFO property).
+ unsigned int minversion = version > clientversion ? clientversion : version;
+ sendXEmbedMessage(client, q->x11Info().display(), XEMBED_EMBEDDED_NOTIFY, q->internalWinId(), minversion);
+ XMapWindow(q->x11Info().display(), client);
+
+ // Resize it, but no smaller than its minimum size hint.
+ XResizeWindow(q->x11Info().display(),
+ client,
+ qMax(q->width(), wmMinimumSizeHint.width()),
+ qMax(q->height(), wmMinimumSizeHint.height()));
+ q->update();
+
+ // Not mentioned in the protocol is that if the container
+ // is already active, the client must be activated to work
+ // properly.
+ if (q->window()->isActiveWindow())
+ sendXEmbedMessage(client, q->x11Info().display(), XEMBED_WINDOW_ACTIVATE);
+
+ // Also, if the container already has focus, then it must
+ // send a focus in message to its new client; otherwise we ask
+ // it to remove focus.
+ if (q->focusWidget() == q && q->hasFocus())
+ sendXEmbedMessage(client, q->x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_FIRST);
+ else
+ sendXEmbedMessage(client, q->x11Info().display(), XEMBED_FOCUS_OUT);
+
+ if (!clientIsXEmbed) {
+ checkGrab();
+ if (q->hasFocus()) {
+ XSetInputFocus(q->x11Info().display(), client, XRevertToParent, x11Time());
+ } else {
+ if (!isEmbedded())
+ moveInputToProxy();
+ }
+ }
+
+ emit q->clientIsEmbedded();
+}
+
+/*! \internal
+
+ Moves X11 keyboard input focus to the focusProxy, unless the focus
+ is there already. When X11 keyboard input focus is on the
+ focusProxy, which is a child of the container and a sibling of the
+ client, X11 keypresses and keyreleases will always go to the proxy
+ and not to the client.
+*/
+void QX11EmbedContainerPrivate::moveInputToProxy()
+{
+ Q_Q(QX11EmbedContainer);
+ WId focus;
+ int revert_to;
+ XGetInputFocus(q->x11Info().display(), &focus, &revert_to);
+ if (focus != focusProxy->internalWinId())
+ XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, x11Time());
+}
+
+/*! \internal
+
+ Ask the window manager to give us a default minimum size.
+*/
+QSize QX11EmbedContainer::minimumSizeHint() const
+{
+ Q_D(const QX11EmbedContainer);
+ if (!d->client || !d->wmMinimumSizeHint.isValid())
+ return QWidget::minimumSizeHint();
+ return d->wmMinimumSizeHint;
+}
+
+/*! \internal
+
+*/
+void QX11EmbedContainerPrivate::checkGrab()
+{
+ Q_Q(QX11EmbedContainer);
+ if (!clientIsXEmbed && q->isActiveWindow() && !q->hasFocus()) {
+ if (!xgrab) {
+ XGrabButton(q->x11Info().display(), AnyButton, AnyModifier, q->internalWinId(),
+ true, ButtonPressMask, GrabModeSync, GrabModeAsync,
+ None, None);
+ }
+ xgrab = true;
+ } else {
+ if (xgrab)
+ XUngrabButton(q->x11Info().display(), AnyButton, AnyModifier, q->internalWinId());
+ xgrab = false;
+ }
+}
+
+/*!
+ Detaches the client from the embedder. The client will appear as a
+ standalone window on the desktop.
+*/
+void QX11EmbedContainer::discardClient()
+{
+ Q_D(QX11EmbedContainer);
+ if (d->client) {
+ XResizeWindow(x11Info().display(), d->client, d->clientOriginalRect.width(),
+ d->clientOriginalRect.height());
+
+ d->rejectClient(d->client);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qx11embed_x11.h b/src/gui/kernel/qx11embed_x11.h
new file mode 100644
index 0000000000..7c8ab9cc73
--- /dev/null
+++ b/src/gui/kernel/qx11embed_x11.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QX11EMBED_X11_H
+#define QX11EMBED_X11_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QX11EmbedWidgetPrivate;
+class Q_GUI_EXPORT QX11EmbedWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ QX11EmbedWidget(QWidget *parent = 0);
+ ~QX11EmbedWidget();
+
+ void embedInto(WId id);
+ WId containerWinId() const;
+
+ enum Error {
+ Unknown,
+ Internal,
+ InvalidWindowID
+ };
+ Error error() const;
+
+Q_SIGNALS:
+ void embedded();
+ void containerClosed();
+ void error(QX11EmbedWidget::Error error);
+
+protected:
+ bool x11Event(XEvent *);
+ bool eventFilter(QObject *, QEvent *);
+ bool event(QEvent *);
+ void resizeEvent(QResizeEvent *);
+
+private:
+ Q_DECLARE_PRIVATE(QX11EmbedWidget)
+ Q_DISABLE_COPY(QX11EmbedWidget)
+};
+
+class QX11EmbedContainerPrivate;
+class Q_GUI_EXPORT QX11EmbedContainer : public QWidget
+{
+ Q_OBJECT
+public:
+ QX11EmbedContainer(QWidget *parent = 0);
+ ~QX11EmbedContainer();
+
+ void embedClient(WId id);
+ void discardClient();
+
+ WId clientWinId() const;
+
+ QSize minimumSizeHint() const;
+
+ enum Error {
+ Unknown,
+ Internal,
+ InvalidWindowID
+ };
+ Error error() const;
+
+Q_SIGNALS:
+ void clientIsEmbedded();
+ void clientClosed();
+ void error(QX11EmbedContainer::Error);
+
+protected:
+ bool x11Event(XEvent *);
+ bool eventFilter(QObject *, QEvent *);
+ void paintEvent(QPaintEvent *e);
+ void resizeEvent(QResizeEvent *);
+ void showEvent(QShowEvent *);
+ void hideEvent(QHideEvent *);
+ bool event(QEvent *);
+
+private:
+ Q_DECLARE_PRIVATE(QX11EmbedContainer)
+ Q_DISABLE_COPY(QX11EmbedContainer)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QX11EMBED_X11_H
diff --git a/src/gui/kernel/qx11info_x11.cpp b/src/gui/kernel/qx11info_x11.cpp
new file mode 100644
index 0000000000..d8a5c5e310
--- /dev/null
+++ b/src/gui/kernel/qx11info_x11.cpp
@@ -0,0 +1,542 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidget.h"
+#include "qpixmap.h"
+#include "qx11info_x11.h"
+#include "qt_x11_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QX11Info
+ \brief The QX11Info class provides information about the X display
+ configuration.
+
+ \ingroup shared
+
+ The class provides two APIs: a set of non-static functions that
+ provide information about a specific widget or pixmap, and a set
+ of static functions that provide the default information for the
+ application.
+
+ \warning This class is only available on X11. For querying
+ per-screen information in a portable way, use QDesktopWidget.
+
+ \sa QWidget::x11Info(), QPixmap::x11Info(), QDesktopWidget
+*/
+
+/*!
+ Constructs an empty QX11Info object.
+*/
+QX11Info::QX11Info()
+ : x11data(0)
+{
+}
+
+/*!
+ Constructs a copy of \a other.
+*/
+QX11Info::QX11Info(const QX11Info &other)
+{
+ x11data = other.x11data;
+ if (x11data)
+ ++x11data->ref;
+}
+
+/*!
+ Assigns \a other to this object and returns a reference to this
+ object.
+*/
+QX11Info &QX11Info::operator=(const QX11Info &other)
+{
+ if (other.x11data)
+ ++other.x11data->ref;
+ if (x11data && !--x11data->ref)
+ delete x11data;
+ x11data = other.x11data;
+ return *this;
+}
+
+/*!
+ Destroys the QX11Info object.
+*/
+QX11Info::~QX11Info()
+{
+ if (x11data && !--x11data->ref)
+ delete x11data;
+}
+
+/*!
+ \internal
+ Makes a shallow copy of the X11-specific data of \a fromDevice, if it is not
+ null. Otherwise this function sets it to null.
+*/
+
+void QX11Info::copyX11Data(const QPaintDevice *fromDevice)
+{
+ QX11InfoData *xd = 0;
+ if (fromDevice) {
+ if (fromDevice->devType() == QInternal::Widget)
+ xd = static_cast<const QWidget *>(fromDevice)->x11Info().x11data;
+ else if (fromDevice->devType() == QInternal::Pixmap)
+ xd = static_cast<const QPixmap *>(fromDevice)->x11Info().x11data;
+ }
+ setX11Data(xd);
+}
+
+/*!
+ \internal
+ Makes a deep copy of the X11-specific data of \a fromDevice, if it is not
+ null. Otherwise this function sets it to null.
+*/
+
+void QX11Info::cloneX11Data(const QPaintDevice *fromDevice)
+{
+ QX11InfoData *d = 0;
+ if (fromDevice) {
+ QX11InfoData *xd;
+ if (fromDevice->devType() == QInternal::Widget) {
+ xd = static_cast<const QWidget *>(fromDevice)->x11Info().x11data;
+ } else {
+ Q_ASSERT(fromDevice->devType() == QInternal::Pixmap);
+ xd = static_cast<const QPixmap *>(fromDevice)->x11Info().x11data;
+ }
+ d = new QX11InfoData(*xd);
+ d->ref = 0;
+ }
+ setX11Data(d);
+}
+
+/*!
+ \internal
+ Makes a shallow copy of the X11-specific data \a d and assigns it to this
+ class. This function increments the reference code of \a d.
+*/
+
+void QX11Info::setX11Data(const QX11InfoData* d)
+{
+ if (x11data && !--x11data->ref)
+ delete x11data;
+ x11data = (QX11InfoData *)d;
+ if (x11data)
+ ++x11data->ref;
+}
+
+
+/*!
+ \internal
+ If \a def is false, returns a deep copy of the x11Data, or 0 if x11Data is 0.
+ If \a def is true, makes a QX11Data struct filled with the default
+ values.
+
+ In either case the caller is responsible for deleting the returned
+ struct. But notice that the struct is a shared class, so other
+ classes might also have a reference to it. The reference count of
+ the returned QX11Data* is 0.
+*/
+
+QX11InfoData* QX11Info::getX11Data(bool def) const
+{
+ QX11InfoData* res = 0;
+ if (def) {
+ res = new QX11InfoData;
+ res->screen = appScreen();
+ res->depth = appDepth();
+ res->cells = appCells();
+ res->colormap = colormap();
+ res->defaultColormap = appDefaultColormap();
+ res->visual = (Visual*) appVisual();
+ res->defaultVisual = appDefaultVisual();
+ } else if (x11data) {
+ res = new QX11InfoData;
+ *res = *x11data;
+ }
+ res->ref = 0;
+ return res;
+}
+
+/*!
+ Returns the horizontal resolution of the given \a screen in terms of the
+ number of dots per inch.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa setAppDpiX(), appDpiY()
+*/
+int QX11Info::appDpiX(int screen)
+{
+ if (!X11)
+ return 75;
+ if (screen < 0)
+ screen = X11->defaultScreen;
+ if (screen > X11->screenCount)
+ return 0;
+ return X11->screens[screen].dpiX;
+}
+
+/*!
+ Sets the horizontal resolution of the given \a screen to the number of
+ dots per inch specified by \a xdpi.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa appDpiX(), setAppDpiY()
+*/
+
+void QX11Info::setAppDpiX(int screen, int xdpi)
+{
+ if (!X11)
+ return;
+ if (screen < 0)
+ screen = X11->defaultScreen;
+ if (screen > X11->screenCount)
+ return;
+ X11->screens[screen].dpiX = xdpi;
+}
+
+/*!
+ Returns the vertical resolution of the given \a screen in terms of the
+ number of dots per inch.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa setAppDpiY(), appDpiX()
+*/
+
+int QX11Info::appDpiY(int screen)
+{
+ if (!X11)
+ return 75;
+ if (screen < 0)
+ screen = X11->defaultScreen;
+ if (screen > X11->screenCount)
+ return 0;
+ return X11->screens[screen].dpiY;
+}
+
+/*!
+ Sets the vertical resolution of the given \a screen to the number of
+ dots per inch specified by \a ydpi.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa appDpiY(), setAppDpiX()
+*/
+void QX11Info::setAppDpiY(int screen, int ydpi)
+{
+ if (!X11)
+ return;
+ if (screen < 0)
+ screen = X11->defaultScreen;
+ if (screen > X11->screenCount)
+ return;
+ X11->screens[screen].dpiY = ydpi;
+}
+
+/*!
+ Returns the X11 time.
+
+ \sa setAppTime(), appUserTime()
+*/
+unsigned long QX11Info::appTime()
+{
+ return X11 ? X11->time : 0;
+}
+
+/*!
+ Sets the X11 time to the value specified by \a time.
+
+ \sa appTime(), setAppUserTime()
+*/
+void QX11Info::setAppTime(unsigned long time)
+{
+ if (X11) {
+ X11->time = time;
+ }
+}
+
+/*!
+ Returns the X11 user time.
+
+ \sa setAppUserTime(), appTime()
+*/
+unsigned long QX11Info::appUserTime()
+{
+ return X11 ? X11->userTime : 0;
+}
+
+/*!
+ Sets the X11 user time as specified by \a time.
+
+ \sa appUserTime(), setAppTime()
+*/
+void QX11Info::setAppUserTime(unsigned long time)
+{
+ if (X11) {
+ X11->userTime = time;
+ }
+}
+
+
+/*!
+ \fn const char *QX11Info::appClass()
+
+ Returns the X11 application class.
+
+ \sa display()
+*/
+
+/*!
+ Returns the default display for the application.
+
+ \sa appScreen()
+*/
+
+Display *QX11Info::display()
+{
+ return X11 ? X11->display : 0;
+}
+
+/*!
+ Returns the number of the screen where the application is being
+ displayed.
+
+ \sa display(), screen()
+*/
+int QX11Info::appScreen()
+{
+ return X11 ? X11->defaultScreen : 0;
+}
+
+/*!
+ Returns a handle for the application's color map on the given \a screen.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa colormap(), defaultColormap()
+*/
+Qt::HANDLE QX11Info::appColormap(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].colormap : 0;
+}
+
+/*!
+ Returns the current visual used by the application on the given
+ \a screen.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa visual(), defaultVisual()
+*/
+
+void *QX11Info::appVisual(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].visual : 0;
+}
+
+/*!
+ Returns a handle for the applications root window on the given \a screen.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa QApplication::desktop()
+*/
+Qt::HANDLE QX11Info::appRootWindow(int screen)
+{
+ return X11 ? RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen) : 0;
+}
+
+/*!
+ Returns the color depth (bits per pixel) used by the application on the
+ given \a screen.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa depth()
+*/
+
+int QX11Info::appDepth(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].depth : 32;
+}
+
+/*!
+ Returns the number of cells used by the application on the given \a screen.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa cells()
+*/
+
+int QX11Info::appCells(int screen)
+{ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].cells : 0; }
+
+/*!
+ Returns true if the application has a default color map on the given
+ \a screen; otherwise returns false.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+*/
+bool QX11Info::appDefaultColormap(int screen)
+{ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultColormap : true; }
+
+/*!
+ Returns true if the application has a default visual on the given \a screen;
+ otherwise returns false.
+
+ The \a screen argument is an X screen number. Be aware that if
+ the user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+*/
+bool QX11Info::appDefaultVisual(int screen)
+{ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultVisual : true; }
+
+/*!
+ Returns the number of the screen currently in use.
+
+ The return value is an X screen number. Be aware that if the
+ user's system uses Xinerama (as opposed to traditional X11
+ multiscreen), there is only one X screen. Use QDesktopWidget to
+ query for information about Xinerama screens.
+
+ \sa appScreen()
+*/
+int QX11Info::screen() const
+{ return x11data ? x11data->screen : QX11Info::appScreen(); }
+
+/*!
+ Returns the color depth (bits per pixel) of the X display.
+
+ \sa appDepth()
+*/
+
+int QX11Info::depth() const
+{ return x11data ? x11data->depth : QX11Info::appDepth(); }
+
+/*!
+ Returns the number of cells.
+
+ \sa appCells()
+*/
+
+int QX11Info::cells() const
+{ return x11data ? x11data->cells : QX11Info::appCells(); }
+
+/*!
+ Returns a handle for the color map.
+
+ \sa defaultColormap()
+*/
+
+Qt::HANDLE QX11Info::colormap() const
+{ return x11data ? x11data->colormap : QX11Info::appColormap(); }
+
+/*!
+ Returns true if there is a default color map; otherwise returns false.
+
+ \sa colormap()
+*/
+
+bool QX11Info::defaultColormap() const
+{ return x11data ? x11data->defaultColormap : QX11Info::appDefaultColormap(); }
+
+/*!
+ Returns the current visual.
+
+ \sa appVisual(), defaultVisual()
+*/
+
+void *QX11Info::visual() const
+{ return x11data ? x11data->visual : QX11Info::appVisual(); }
+
+/*!
+ Returns true if there is a default visual; otherwise returns false.
+
+ \sa visual(), appVisual()
+*/
+
+bool QX11Info::defaultVisual() const
+{ return x11data ? x11data->defaultVisual : QX11Info::appDefaultVisual(); }
+
+
+/*!
+ \since 4.4
+
+ Returns true if there is a compositing manager running.
+*/
+bool QX11Info::isCompositingManagerRunning()
+{
+ return X11 ? X11->compositingManagerRunning : false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qx11info_x11.h b/src/gui/kernel/qx11info_x11.h
new file mode 100644
index 0000000000..cd1d9966ff
--- /dev/null
+++ b/src/gui/kernel/qx11info_x11.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QX11INFO_X11_H
+#define QX11INFO_X11_H
+
+#include <QtCore/qnamespace.h>
+
+typedef struct _XDisplay Display;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+struct QX11InfoData;
+class QX11Info;
+class QPaintDevice;
+class QApplicationPrivate;
+class QX11InfoPrivate;
+struct QX11WindowAttributes;
+
+void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &a);
+class Q_GUI_EXPORT QX11Info
+{
+public:
+ QX11Info();
+ ~QX11Info();
+ QX11Info(const QX11Info &other);
+ QX11Info &operator=(const QX11Info &other);
+
+ static Display *display();
+ static const char *appClass();
+ int screen() const;
+ int depth() const;
+ int cells() const;
+ Qt::HANDLE colormap() const;
+ bool defaultColormap() const;
+ void *visual() const;
+ bool defaultVisual() const;
+
+ static int appScreen();
+ static int appDepth(int screen = -1);
+ static int appCells(int screen = -1);
+ static Qt::HANDLE appColormap(int screen = -1);
+ static void *appVisual(int screen = -1);
+ static Qt::HANDLE appRootWindow(int screen = -1);
+ static bool appDefaultColormap(int screen = -1);
+ static bool appDefaultVisual(int screen = -1);
+ static int appDpiX(int screen = -1);
+ static int appDpiY(int screen = -1);
+ static void setAppDpiX(int screen, int dpi);
+ static void setAppDpiY(int screen, int dpi);
+ static unsigned long appTime();
+ static unsigned long appUserTime();
+ static void setAppTime(unsigned long time);
+ static void setAppUserTime(unsigned long time);
+ static bool isCompositingManagerRunning();
+
+protected:
+ void copyX11Data(const QPaintDevice *);
+ void cloneX11Data(const QPaintDevice *);
+ void setX11Data(const QX11InfoData *);
+ QX11InfoData* getX11Data(bool def = false) const;
+
+ QX11InfoData *x11data;
+
+ friend class QX11PaintEngine;
+ friend class QPixmap;
+ friend class QX11PixmapData;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+ friend class QGLWidget;
+ friend void qt_init(QApplicationPrivate *priv, int, Display *display, Qt::HANDLE visual,
+ Qt::HANDLE colormap);
+ friend void qt_cleanup();
+ friend void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &a);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QX11INFO_X11_H
diff --git a/src/gui/kernel/win.pri b/src/gui/kernel/win.pri
new file mode 100644
index 0000000000..5ecf4dd94a
--- /dev/null
+++ b/src/gui/kernel/win.pri
@@ -0,0 +1,4 @@
+# Qt/Windows only configuration file
+# --------------------------------------------------------------------
+
+ INCLUDEPATH += ../3rdparty/wintab
diff --git a/src/gui/kernel/x11.pri b/src/gui/kernel/x11.pri
new file mode 100644
index 0000000000..ac40f69c63
--- /dev/null
+++ b/src/gui/kernel/x11.pri
@@ -0,0 +1,4 @@
+x11 {
+ contains(QT_CONFIG, nas): LIBS += -laudio -lXt
+}
+