summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/accessible/widgets/itemviews.cpp217
-rw-r--r--src/plugins/accessible/widgets/itemviews.h10
-rw-r--r--src/plugins/accessible/widgets/main.cpp3
-rw-r--r--src/plugins/accessible/widgets/widgets.json4
-rw-r--r--src/plugins/bearer/corewlan/corewlan.pro4
-rw-r--r--src/plugins/generic/meego/qmeegointegration.h4
-rw-r--r--src/plugins/generic/tslib/qtslib.h4
-rw-r--r--src/plugins/imageformats/gif/gif.json3
-rw-r--r--src/plugins/imageformats/ico/ico.json3
-rw-r--r--src/plugins/imageformats/jpeg/jpeg.json3
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp20
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h13
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm34
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintrospection.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm35
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.mm31
-rwxr-xr-xsrc/plugins/platforms/cocoa/qcocoasystemtrayicon.mm47
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm7
-rw-r--r--src/plugins/platforms/cocoa/qmacdefines_mac.h4
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac.mm5
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac_p.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm22
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.h20
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm25
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac_p.h2
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm18
-rw-r--r--src/plugins/platforms/directfb/qdirectfbcursor.cpp5
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp21
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.cpp7
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks.h6
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_stub.cpp112
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp36
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h6
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp5
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.h2
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp3
-rw-r--r--src/plugins/platforms/kms/kms.pro5
-rw-r--r--src/plugins/platforms/kms/qkmscursor.cpp68
-rw-r--r--src/plugins/platforms/kms/qkmscursor.h10
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp12
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp1
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.h3
-rw-r--r--src/plugins/platforms/offscreen/main.cpp67
-rw-r--r--src/plugins/platforms/offscreen/offscreen.json3
-rw-r--r--src/plugins/platforms/offscreen/offscreen.pro25
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.cpp229
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.h109
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp162
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.h80
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp47
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp252
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.h108
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.cpp199
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.h86
-rw-r--r--src/plugins/platforms/platforms.pro2
-rw-r--r--src/plugins/platforms/qnx/qnx.pro7
-rw-r--r--src/plugins/platforms/qnx/qqnxcursor.cpp78
-rw-r--r--src/plugins/platforms/qnx/qqnxcursor.h67
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp11
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.h4
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp15
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.h2
-rw-r--r--src/plugins/platforms/windows/qtwindows_additional.h4
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp35
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h5
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp451
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp42
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp133
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h20
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp60
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h20
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp32
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp9
-rw-r--r--src/plugins/platformthemes/gtk2/gtk2.json3
-rw-r--r--src/plugins/platformthemes/gtk2/gtk2.pro20
-rw-r--r--src/plugins/platformthemes/gtk2/main.cpp67
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp609
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h143
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2theme.cpp77
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2theme.h62
-rw-r--r--src/plugins/platformthemes/platformthemes.pro3
-rw-r--r--src/plugins/plugins.pro5
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp5
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport_p.h3
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.cpp5
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.h3
113 files changed, 3838 insertions, 568 deletions
diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp
index a3fcc22fc4..17764a3c2e 100644
--- a/src/plugins/accessible/widgets/itemviews.cpp
+++ b/src/plugins/accessible/widgets/itemviews.cpp
@@ -299,9 +299,28 @@ bool QAccessibleTable::selectRow(int row)
if (!view()->model() || !view()->selectionModel())
return false;
QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
- if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
return false;
- view()->selectionModel()->select(index, QItemSelectionModel::Select);
+ case QAbstractItemView::SingleSelection:
+ if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 )
+ return false;
+ view()->clearSelection();
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
return true;
}
@@ -310,9 +329,26 @@ bool QAccessibleTable::selectColumn(int column)
if (!view()->model() || !view()->selectionModel())
return false;
QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
- if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectRows)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
return false;
- view()->selectionModel()->select(index, QItemSelectionModel::Select);
+ case QAbstractItemView::SingleSelection:
+ if (view()->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1)
+ return false;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Columns);
return true;
}
@@ -320,10 +356,35 @@ bool QAccessibleTable::unselectRow(int row)
{
if (!view()->model() || !view()->selectionModel())
return false;
+
QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
- if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
+ if (!index.isValid())
return false;
- view()->selectionModel()->select(index, QItemSelectionModel::Deselect);
+
+ QItemSelection selection(index, index);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::SingleSelection:
+ //In SingleSelection and ContiguousSelection once an item
+ //is selected, there's no way for the user to unselect all items
+ if (selectedRowCount() == 1)
+ return false;
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if (selectedRowCount() == 1)
+ return false;
+
+ if ((!row || view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) {
+ //If there are rows selected both up the current row and down the current rown,
+ //the ones which are down the current row will be deselected
+ selection = QItemSelection(index, view()->model()->index(rowCount() - 1, 0, view()->rootIndex()));
+ }
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
return true;
}
@@ -331,10 +392,35 @@ bool QAccessibleTable::unselectColumn(int column)
{
if (!view()->model() || !view()->selectionModel())
return false;
+
QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
- if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
+ if (!index.isValid())
return false;
- view()->selectionModel()->select(index, QItemSelectionModel::Columns & QItemSelectionModel::Deselect);
+
+ QItemSelection selection(index, index);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::SingleSelection:
+ //In SingleSelection and ContiguousSelection once an item
+ //is selected, there's no way for the user to unselect all items
+ if (selectedColumnCount() == 1)
+ return false;
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if (selectedColumnCount() == 1)
+ return false;
+
+ if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
+ && view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
+ //If there are columns selected both at the left of the current row and at the right
+ //of the current rown, the ones which are at the right will be deselected
+ selection = QItemSelection(index, view()->model()->index(0, columnCount() - 1, view()->rootIndex()));
+ }
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Columns);
return true;
}
@@ -576,9 +662,28 @@ bool QAccessibleTree::selectRow(int row)
if (!view()->selectionModel())
return false;
QModelIndex index = indexFromLogical(row);
- if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection)
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
return false;
- view()->selectionModel()->select(index, QItemSelectionModel::Select);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1))
+ return false;
+ view()->clearSelection();
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
return true;
}
@@ -595,6 +700,8 @@ void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t)
{
if (t == QAccessible::TableCellInterface)
return static_cast<QAccessibleTableCellInterface*>(this);
+ if (t == QAccessible::ActionInterface)
+ return static_cast<QAccessibleActionInterface*>(this);
return 0;
}
@@ -668,6 +775,89 @@ bool QAccessibleTableCell::isSelected() const
return view->selectionModel()->isSelected(m_index);
}
+QStringList QAccessibleTableCell::actionNames() const
+{
+ QStringList names;
+ names << toggleAction();
+ return names;
+}
+
+void QAccessibleTableCell::doAction(const QString& actionName)
+{
+ if (actionName == toggleAction()) {
+ if (isSelected())
+ unselectCell();
+ else
+ selectCell();
+ }
+}
+
+QStringList QAccessibleTableCell::keyBindingsForAction(const QString& actionName) const
+{
+ return QStringList();
+}
+
+
+void QAccessibleTableCell::selectCell()
+{
+ QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection))
+ return;
+
+ QSharedPointer<QAccessibleTableInterface> cellTable(table()->tableInterface());
+
+ switch (view->selectionBehavior()) {
+ case QAbstractItemView::SelectItems:
+ break;
+ case QAbstractItemView::SelectColumns:
+ if (cellTable.data())
+ cellTable->selectColumn(m_index.column());
+ return;
+ case QAbstractItemView::SelectRows:
+ if (cellTable.data())
+ cellTable->selectRow(m_index.row());
+ return;
+ }
+
+ if (selectionMode == QAbstractItemView::SingleSelection) {
+ view->clearSelection();
+ }
+
+ view->selectionModel()->select(m_index, QItemSelectionModel::Select);
+}
+
+void QAccessibleTableCell::unselectCell()
+{
+
+ QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (!m_index.isValid() || (selectionMode & QAbstractItemView::NoSelection))
+ return;
+
+ QSharedPointer<QAccessibleTableInterface> cellTable(table()->tableInterface());
+
+ switch (view->selectionBehavior()) {
+ case QAbstractItemView::SelectItems:
+ break;
+ case QAbstractItemView::SelectColumns:
+ if (cellTable.data())
+ cellTable->unselectColumn(m_index.column());
+ return;
+ case QAbstractItemView::SelectRows:
+ if (cellTable.data())
+ cellTable->unselectRow(m_index.row());
+ return;
+ }
+
+ //If the mode is not MultiSelection or ExtendedSelection and only
+ //one cell is selected it cannot be unselected by the user
+ if ((selectionMode != QAbstractItemView::MultiSelection)
+ && (selectionMode != QAbstractItemView::ExtendedSelection)
+ && (view->selectionModel()->selectedIndexes().count() <= 1))
+ return;
+
+ view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
+}
+
void QAccessibleTableCell::rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const
{
*row = m_index.row();
@@ -856,14 +1046,11 @@ bool QAccessibleTableHeaderCell::isValid() const
QAccessibleInterface *QAccessibleTableHeaderCell::parent() const
{
- if (false) {
#ifndef QT_NO_TREEVIEW
- } else if (qobject_cast<const QTreeView*>(view)) {
+ if (qobject_cast<const QTreeView*>(view))
return new QAccessibleTree(view);
#endif
- } else {
- return new QAccessibleTable(view);
- }
+ return new QAccessibleTable(view);
}
QAccessibleInterface *QAccessibleTableHeaderCell::child(int) const
diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/plugins/accessible/widgets/itemviews.h
index d58d504690..baf7fd8587 100644
--- a/src/plugins/accessible/widgets/itemviews.h
+++ b/src/plugins/accessible/widgets/itemviews.h
@@ -159,7 +159,7 @@ private:
QModelIndex indexFromLogical(int row, int column = 0) const;
};
-class QAccessibleTableCell: public QAccessibleInterface, public QAccessibleTableCellInterface
+class QAccessibleTableCell: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface
{
public:
QAccessibleTableCell(QAbstractItemView *view, const QModelIndex &m_index, QAccessible::Role role);
@@ -192,6 +192,11 @@ public:
virtual void rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const;
virtual QAccessibleInterface* table() const;
+ //action interface
+ virtual QStringList actionNames() const;
+ virtual void doAction(const QString &actionName);
+ virtual QStringList keyBindingsForAction(const QString &actionName) const;
+
private:
QHeaderView *verticalHeader() const;
QHeaderView *horizontalHeader() const;
@@ -199,6 +204,9 @@ private:
QModelIndex m_index;
QAccessible::Role m_role;
+ void selectCell();
+ void unselectCell();
+
friend class QAccessibleTable;
friend class QAccessibleTree;
};
diff --git a/src/plugins/accessible/widgets/main.cpp b/src/plugins/accessible/widgets/main.cpp
index 9a42474910..92cda9f3ca 100644
--- a/src/plugins/accessible/widgets/main.cpp
+++ b/src/plugins/accessible/widgets/main.cpp
@@ -251,6 +251,9 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
} else if (classname == QLatin1String("QDockWidget")) {
iface = new QAccessibleDockWidget(widget);
#endif
+
+ } else if (classname == QLatin1String("QDesktopScreenWidget")) {
+ iface = 0;
} else {
iface = new QAccessibleWidget(widget);
}
diff --git a/src/plugins/accessible/widgets/widgets.json b/src/plugins/accessible/widgets/widgets.json
index 69584b9bc8..094987daf5 100644
--- a/src/plugins/accessible/widgets/widgets.json
+++ b/src/plugins/accessible/widgets/widgets.json
@@ -47,5 +47,7 @@
"QScrollArea",
"QCalendarWidget",
"QDockWidget",
- "QAccessibleWidget" ]
+ "QAccessibleWidget",
+ "QDesktopScreenWidget"
+ ]
}
diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro
index db8651de6e..674af0cbbe 100644
--- a/src/plugins/bearer/corewlan/corewlan.pro
+++ b/src/plugins/bearer/corewlan/corewlan.pro
@@ -8,9 +8,7 @@ QT = core-private network-private
LIBS += -framework Foundation -framework SystemConfiguration
contains(QT_CONFIG, corewlan) {
- !contains(QMAKE_MAC_SDK, ".*MacOSX10\\.[345]\\.sdk") {
- LIBS += -framework CoreWLAN -framework Security
- }
+ LIBS += -framework CoreWLAN -framework Security
}
HEADERS += qcorewlanengine.h \
diff --git a/src/plugins/generic/meego/qmeegointegration.h b/src/plugins/generic/meego/qmeegointegration.h
index 88e2aae721..998bbbf8d3 100644
--- a/src/plugins/generic/meego/qmeegointegration.h
+++ b/src/plugins/generic/meego/qmeegointegration.h
@@ -47,8 +47,6 @@
#include "contextkitproperty.h"
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QMeeGoIntegration : public QObject
@@ -67,6 +65,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QMEEGOINTEGRATION_H
diff --git a/src/plugins/generic/tslib/qtslib.h b/src/plugins/generic/tslib/qtslib.h
index 0c5c74f672..9342fdfea5 100644
--- a/src/plugins/generic/tslib/qtslib.h
+++ b/src/plugins/generic/tslib/qtslib.h
@@ -45,8 +45,6 @@
#include <qobject.h>
//#include <Qt>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QSocketNotifier;
@@ -72,6 +70,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QTSLIB_H
diff --git a/src/plugins/imageformats/gif/gif.json b/src/plugins/imageformats/gif/gif.json
index b599b40ffe..1d6cb126c4 100644
--- a/src/plugins/imageformats/gif/gif.json
+++ b/src/plugins/imageformats/gif/gif.json
@@ -1,3 +1,4 @@
{
- "Keys": [ "gif" ]
+ "Keys": [ "gif" ],
+ "MimeTypes": [ "image/gif" ]
}
diff --git a/src/plugins/imageformats/ico/ico.json b/src/plugins/imageformats/ico/ico.json
index d22cb739a1..bd46e07e54 100644
--- a/src/plugins/imageformats/ico/ico.json
+++ b/src/plugins/imageformats/ico/ico.json
@@ -1,3 +1,4 @@
{
- "Keys": [ "ico" ]
+ "Keys": [ "ico" ],
+ "MimeTypes": [ "image/vnd.microsoft.icon" ]
}
diff --git a/src/plugins/imageformats/jpeg/jpeg.json b/src/plugins/imageformats/jpeg/jpeg.json
index 132c642c05..5e26a97206 100644
--- a/src/plugins/imageformats/jpeg/jpeg.json
+++ b/src/plugins/imageformats/jpeg/jpeg.json
@@ -1,3 +1,4 @@
{
- "Keys": [ "jpg", "jpeg" ]
+ "Keys": [ "jpg", "jpeg" ],
+ "MimeTypes": [ "image/jpeg", "image/jpeg" ]
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index f4e7666a85..53e9b171d5 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -226,26 +226,6 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint
}
-/* Kernel keycode -> X keycode table */
-static const unsigned int keycode_table[256] = {
- 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 76, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 111, 221, 94, 95, 96, 211, 128, 127, 129, 208, 131, 126,
- 108, 109, 112, 111, 113, 181, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107,
- 239, 160, 174, 176, 222, 157, 123, 110, 139, 134, 209, 210, 133, 115, 116, 117,
- 232, 133, 134, 135, 140, 248, 191, 192, 122, 188, 245, 158, 161, 193, 223, 227,
- 198, 199, 200, 147, 159, 151, 178, 201, 146, 203, 166, 236, 230, 235, 234, 233,
- 163, 204, 253, 153, 162, 144, 164, 177, 152, 190, 208, 129, 130, 231, 209, 210,
- 136, 220, 143, 246, 251, 137, 138, 182, 183, 184, 93, 184, 247, 132, 170, 219,
- 249, 205, 207, 149, 150, 154, 155, 167, 168, 169, 171, 172, 173, 165, 175, 179,
- 180, 0, 185, 186, 187, 118, 119, 120, 121, 229, 194, 195, 196, 197, 148, 202,
- 101, 212, 237, 214, 215, 216, 217, 218, 228, 142, 213, 240, 241, 242, 243, 244,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
bool
QIBusPlatformInputContext::x11FilterEvent(uint keyval, uint keycode, uint state, bool press)
{
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
index 6dd7ea2fb3..e44b2d1b6d 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
@@ -93,19 +93,6 @@
@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader);
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
-
-@protocol NSApplicationDelegate <NSObject>
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
-- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
-- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames;
-- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
-- (void)applicationDidBecomeActive:(NSNotification *)notification;
-- (void)applicationDidResignActive:(NSNotification *)notification;
-@end
-
-#endif
-
@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> {
bool startedQuit;
NSMenu *dockMenu;
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index a36a855bcd..12808b7041 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -65,8 +65,9 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window)
{
Q_UNUSED(window);
+ const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
// Check for a suitable built-in NSCursor first:
- switch (cursor->shape()) {
+ switch (newShape) {
case Qt::ArrowCursor:
[[NSCursor arrowCursor] set];
break;
@@ -104,7 +105,7 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window)
default : {
// No suitable OS cursor exist, use cursors provided
// by Qt for the rest. Check for a cached cursor:
- NSCursor *cocoaCursor = m_cursors.value(cursor->shape());
+ NSCursor *cocoaCursor = m_cursors.value(newShape);
if (cocoaCursor && cursor->shape() == Qt::BitmapCursor) {
[cocoaCursor release];
cocoaCursor = 0;
@@ -115,7 +116,7 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window)
[[NSCursor arrowCursor] set];
return;
}
- m_cursors.insert(cursor->shape(), cocoaCursor);
+ m_cursors.insert(newShape, cocoaCursor);
}
[cocoaCursor set];
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index a0734530c5..987600c6b4 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -149,10 +149,10 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer()
CFTimeInterval oneyear = CFTimeInterval(3600. * 24. * 365.);
// Q: when should the CFRunLoopTimer fire for the first time?
- struct timeval tv;
+ struct timespec tv;
if (timerInfoList.timerWait(tv)) {
// A: when we have timers to fire, of course
- interval = qMax(tv.tv_sec + tv.tv_usec / 1000000., 0.0000001);
+ interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001);
} else {
// this shouldn't really happen, but in case it does, set the timer to fire a some point in the distant future
interval = oneyear;
@@ -172,10 +172,10 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer()
CFTimeInterval interval;
// Q: when should the timer first next?
- struct timeval tv;
+ struct timespec tv;
if (timerInfoList.timerWait(tv)) {
// A: when we have timers to fire, of course
- interval = qMax(tv.tv_sec + tv.tv_usec / 1000000., 0.0000001);
+ interval = qMax(tv.tv_sec + tv.tv_nsec / 1000000000., 0.0000001);
} else {
// no timers can fire, but we cannot stop the CFRunLoopTimer, set the timer to fire at some
// point in the distant future (the timer interval is one year)
@@ -490,14 +490,12 @@ static bool IsMouseOrKeyEvent( NSEvent* event )
case NSOtherMouseUp:
case NSOtherMouseDragged:
#ifndef QT_NO_GESTURES
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
case NSEventTypeGesture: // touch events
case NSEventTypeMagnify:
case NSEventTypeSwipe:
case NSEventTypeRotate:
case NSEventTypeBeginGesture:
case NSEventTypeEndGesture:
-#endif
#endif // QT_NO_GESTURES
result = true;
break;
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 61646041fb..9cc0353dc6 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -77,11 +77,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
@class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
: NSObject<NSOpenSavePanelDelegate>
-#else
- : NSObject
-#endif
{
@public
NSOpenPanel *mOpenPanel;
@@ -216,7 +212,7 @@ static QString strippedText(QString s)
- (void)closePanel
{
*mCurrentSelection = QT_PREPEND_NAMESPACE(QCFString::toQString)([[mSavePanel URL] path]);
- if ([mSavePanel respondsToSelector:@selector(closePanel:)])
+ if ([mSavePanel respondsToSelector:@selector(close)])
[mSavePanel close];
if ([mSavePanel isSheet])
[NSApp endSheet: mSavePanel];
@@ -230,6 +226,7 @@ static QString strippedText(QString s)
bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:nil shouldShowFilename:filepath];
+ [self updateProperties];
[mOpenPanel setAllowedFileTypes:nil];
[mOpenPanel setDirectoryURL:selectable ? [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath())]
: [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.path())]];
@@ -274,6 +271,7 @@ static QString strippedText(QString s)
bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:nil shouldShowFilename:filepath];
+ [self updateProperties];
[mSavePanel setDirectoryURL:selectable ? [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath())]
: [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.path())]];
[mSavePanel setNameFieldStringValue:selectable ? QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()) : nil];
@@ -405,6 +403,9 @@ static QString strippedText(QString s)
[mSavePanel setCanCreateDirectories:!(mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::ReadOnly)))];
[mOpenPanel setAllowsMultipleSelection:(fileMode == QT_PREPEND_NAMESPACE(QFileDialogOptions::ExistingFiles))];
[mOpenPanel setResolvesAliases:!(mOptions->testOption(QT_PREPEND_NAMESPACE(QFileDialogOptions::DontResolveSymlinks)))];
+ [mOpenPanel setTitle:QCFString::toNSString(mOptions->windowTitle())];
+ [mSavePanel setTitle:QCFString::toNSString(mOptions->windowTitle())];
+ [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead?
QStringList ext = [self acceptableExtensionsForSave];
const QString defaultSuffix = mOptions->defaultSuffix();
@@ -577,13 +578,16 @@ extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding
void QCocoaFileDialogHelper::setDirectory(const QString &directory)
{
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
- [delegate->mSavePanel setDirectoryURL:[NSURL fileURLWithPath:QCFString::toNSString(directory)]];
+ if (delegate)
+ [delegate->mSavePanel setDirectoryURL:[NSURL fileURLWithPath:QCFString::toNSString(directory)]];
}
QString QCocoaFileDialogHelper::directory() const
{
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
- return QCFString::toQString([delegate->mSavePanel directory]);
+ if (delegate)
+ return QCFString::toQString([delegate->mSavePanel directory]);
+ return QString();
}
void QCocoaFileDialogHelper::selectFile(const QString &filename)
@@ -600,12 +604,16 @@ void QCocoaFileDialogHelper::selectFile(const QString &filename)
QStringList QCocoaFileDialogHelper::selectedFiles() const
{
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
- return [delegate selectedFiles];
+ if (delegate)
+ return [delegate selectedFiles];
+ return QStringList();
}
void QCocoaFileDialogHelper::setFilter()
{
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ if (!delegate)
+ return;
const SharedPointerFileDialogOptions &opts = options();
[delegate->mSavePanel setTitle:QCFString::toNSString(opts->windowTitle())];
if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
@@ -618,9 +626,13 @@ void QCocoaFileDialogHelper::setFilter()
void QCocoaFileDialogHelper::selectNameFilter(const QString &filter)
{
+ if (!options())
+ return;
const int index = options()->nameFilters().indexOf(filter);
if (index != -1) {
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ if (!delegate)
+ return;
[delegate->mPopUpButton selectItemAtIndex:index];
[delegate filterChanged:nil];
}
@@ -629,7 +641,11 @@ void QCocoaFileDialogHelper::selectNameFilter(const QString &filter)
QString QCocoaFileDialogHelper::selectedNameFilter() const
{
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ if (!delegate)
+ return QString();
int index = [delegate->mPopUpButton indexOfSelectedItem];
+ if (index >= options()->nameFilters().count())
+ return QString();
return index != -1 ? options()->nameFilters().at(index) : QString();
}
@@ -675,6 +691,8 @@ bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModalit
{
createNSOpenSavePanelDelegate();
QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ if (!delegate)
+ return false;
if (windowModality == Qt::NonModal)
[delegate showModelessPanel];
else if (windowModality == Qt::WindowModal && parent)
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 831ab579f5..c801d9d926 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -84,8 +84,6 @@ HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion &region);
OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage);
-CGFloat qt_mac_get_scalefactor();
-
QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 91a6f5a4c7..29a8c49511 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -475,11 +475,9 @@ CGColorSpaceRef qt_mac_genericColorSpace()
{
#if 0
if (!m_genericColorSpace) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
} else
-#endif
{
m_genericColorSpace = CGColorSpaceCreateDeviceRGB();
}
@@ -616,11 +614,6 @@ InvalidContext:
return err;
}
-CGFloat qt_mac_get_scalefactor()
-{
- return [[NSScreen mainScreen] userSpaceScaleFactor];
-}
-
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
{
if (buttonNum == 0)
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 7fcdab4d97..f33d4cb68b 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -105,7 +105,9 @@ void QCocoaScreen::updateGeometry()
m_physicalSize = QSizeF(size.width, size.height);
m_logicalDpi.first = 72;
m_logicalDpi.second = 72;
- m_refreshRate = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(dpy));
+ float refresh = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(dpy));
+ if (refresh > 0)
+ m_refreshRate = refresh;
// Get m_name (brand/model of the monitor)
NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName);
diff --git a/src/plugins/platforms/cocoa/qcocoaintrospection.mm b/src/plugins/platforms/cocoa/qcocoaintrospection.mm
index ffb6ae4294..806effc929 100644
--- a/src/plugins/platforms/cocoa/qcocoaintrospection.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintrospection.mm
@@ -83,7 +83,6 @@ void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class prox
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
#endif
{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
// The following code replaces the _implementation_ for the selector we want to hack
// (originalSel) with the implementation found in proxyClass. Then it creates
// a new 'backup' method inside baseClass containing the old, original,
@@ -104,7 +103,6 @@ void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class prox
Method backupMethod = class_getInstanceMethod(proxyClass, backupSel);
class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod));
}
-#endif
}
}
@@ -114,11 +112,9 @@ void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL b
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
#endif
{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel);
method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass));
-#endif
}
}
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index 09b62a9bcd..439b7f1a75 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -51,8 +51,6 @@
@class NSMenu;
@class NSObject;
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QCocoaMenu : public QPlatformMenu
@@ -71,11 +69,17 @@ public:
void syncMenuItem(QPlatformMenuItem *menuItem);
void setEnabled(bool enabled);
void setVisible(bool visible);
+ void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item);
+
void syncSeparatorsCollapsible(bool enable);
void syncModalState(bool modal);
- virtual void setText(const QString &text);
+ virtual void setIcon(const QIcon &icon) { Q_UNUSED(icon) }
+
+ void setText(const QString &text);
+ void setMinimumWidth(int width);
+ void setFont(const QFont &font);
void setParentItem(QCocoaMenuItem* item);
@@ -102,6 +106,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 676f0683fa..0fe4c48510 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -47,6 +47,8 @@
#include <QtCore/QtDebug>
#include "qcocoaapplication.h"
#include "qcocoamenuloader.h"
+#include "qcocoawindow.h"
+#import "qnsview.h"
static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
{
@@ -133,6 +135,20 @@ void QCocoaMenu::setText(const QString &text)
[m_nativeItem setTitle:QCFString::toNSString(stripped)];
}
+void QCocoaMenu::setMinimumWidth(int width)
+{
+ m_nativeMenu.minimumWidth = width;
+}
+
+void QCocoaMenu::setFont(const QFont &font)
+{
+ if (font.resolve()) {
+ NSFont *customMenuFont = [NSFont fontWithName:QCFString::toNSString(font.family())
+ size:font.pointSize()];
+ m_nativeMenu.font = customMenuFont;
+ }
+}
+
void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
{
QCocoaAutoReleasePool pool;
@@ -290,9 +306,26 @@ void QCocoaMenu::setVisible(bool visible)
[m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)];
}
+void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item)
+{
+ QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : 0;
+ NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil;
+ NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil;
+ NSPoint nsPos = NSMakePoint(pos.x(), pos.y());
+ [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:view];
+
+ // The call above blocks, and also swallows any mouse release event,
+ // so we need to clear any mouse button that triggered the menu popup.
+ if ([view isKindOfClass:[QNSView class]])
+ [(QNSView *)view resetMouseButtons];
+}
+
QPlatformMenuItem *QCocoaMenu::menuItemAt(int position) const
{
- return m_menuItems.at(position);
+ if (0 <= position && position < m_menuItems.count())
+ return m_menuItems.at(position);
+
+ return 0;
}
QPlatformMenuItem *QCocoaMenu::menuItemForTag(quintptr tag) const
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h
index fe5193a50c..0e6d17343d 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h
@@ -51,8 +51,6 @@
@class NSMenuItem;
@class NSMenu;
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QCocoaMenu;
@@ -76,6 +74,7 @@ public:
void setFont(const QFont &font);
void setRole(MenuRole role);
void setShortcut(const QKeySequence& shortcut);
+ void setCheckable(bool checkable) { Q_UNUSED(checkable) }
void setChecked(bool isChecked);
void setEnabled(bool isEnabled);
@@ -110,8 +109,6 @@ private:
quintptr m_tag;
};
-QT_END_HEADER
-
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h
index 040b687c4e..83cf1ffada 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h
+++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h
@@ -55,6 +55,7 @@ public:
QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE;
QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE;
QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const Q_DECL_OVERRIDE;
+ QList<QPair<QString, QSizeF> > supportedSizesWithNames(const QPrinterInfo &) const Q_DECL_OVERRIDE;
QList<QPrinterInfo> availablePrinters() Q_DECL_OVERRIDE;
QPrinterInfo printerInfo(const QString &printerName) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm
index a48db02949..cfa23b7a30 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm
@@ -138,3 +138,34 @@ QPrinterInfo QCocoaPrinterSupport::printerInfoFromPMPrinter(const PMPrinter &pri
return createPrinterInfo(name, description, location, makeAndModel, isDefault, 0);
}
+
+QList<QPair<QString, QSizeF> > QCocoaPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const
+{
+ QList<QPair<QString, QSizeF> > returnValue;
+ if (printerInfo.isNull())
+ return returnValue;
+
+ PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName()));
+ if (!printer)
+ return returnValue;
+
+ CFArrayRef array;
+ if (PMPrinterGetPaperList(printer, &array) != noErr) {
+ PMRelease(printer);
+ return returnValue;
+ }
+
+ int count = CFArrayGetCount(array);
+ for (int i = 0; i < count; ++i) {
+ PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i)));
+ double width, height;
+ if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) {
+ static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4;
+ QCFString paperName;
+ if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr)
+ returnValue.append(qMakePair(QString(paperName), QSizeF(width * OnePointInMillimeters, height * OnePointInMillimeters)));
+ }
+ }
+ PMRelease(printer);
+ return returnValue;
+}
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index e092db8172..99f533b33a 100755
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -93,7 +93,11 @@ QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QNSMenu);
@class QT_MANGLE_NAMESPACE(QNSImageView);
-@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject {
+@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+ <NSUserNotificationCenterDelegate>
+#endif
+ {
@public
QCocoaSystemTrayIcon *systray;
NSStatusItem *item;
@@ -108,6 +112,11 @@ QT_USE_NAMESPACE
-(QRectF)geometry;
- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton;
- (void)doubleClickSelector:(id)sender;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification;
+- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification;
+#endif
@end
@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView {
@@ -132,9 +141,19 @@ class QSystemTrayIconSys
public:
QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) {
item = [[QT_MANGLE_NAMESPACE(QNSStatusItem) alloc] initWithSysTray:sys];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
+ [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item];
+ }
+#endif
}
~QSystemTrayIconSys() {
[[[item item] view] setHidden: YES];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
+ [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
+ }
+#endif
[item release];
}
QT_MANGLE_NAMESPACE(QNSStatusItem) *item;
@@ -223,6 +242,18 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess
if (!m_sys)
return;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
+ NSUserNotification *notification = [[NSUserNotification alloc] init];
+ notification.title = [NSString stringWithUTF8String:title.toUtf8().data()];
+ notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()];
+
+ [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
+
+ return;
+ }
+#endif
+
#ifdef QT_MAC_SYSTEMTRAY_USE_GROWL
// Make sure that we have Growl installed on the machine we are running on.
QCFType<CFURLRef> cfurl;
@@ -439,6 +470,20 @@ QT_END_NAMESPACE
emit systray->activated(QPlatformSystemTrayIcon::DoubleClick);
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
+ Q_UNUSED(center);
+ Q_UNUSED(notification);
+ return YES;
+}
+
+- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
+ Q_UNUSED(center);
+ Q_UNUSED(notification);
+ emit systray->messageClicked();
+}
+#endif
+
@end
class QSystemTrayIconQMenu : public QPlatformMenu
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 324a43c8ae..291c688915 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -115,6 +115,8 @@ public:
bool setMouseGrabEnabled(bool grab);
QMargins frameMargins() const;
+ void requestActivateWindow();
+
WId winId() const;
void setParent(const QPlatformWindow *window);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 45100f9906..56ca2e0b14 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -658,6 +658,13 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
setOpacity(opacity);
}
+void QCocoaWindow::requestActivateWindow()
+{
+ NSWindow *window = [m_contentView window];
+ [ window makeFirstResponder : m_contentView ];
+ [ window makeKeyWindow ];
+}
+
NSWindow * QCocoaWindow::createNSWindow()
{
QCocoaAutoReleasePool pool;
diff --git a/src/plugins/platforms/cocoa/qmacdefines_mac.h b/src/plugins/platforms/cocoa/qmacdefines_mac.h
index 18c1ac84de..c03b398836 100644
--- a/src/plugins/platforms/cocoa/qmacdefines_mac.h
+++ b/src/plugins/platforms/cocoa/qmacdefines_mac.h
@@ -79,15 +79,11 @@
*/
/* This is just many defines. Therefore it doesn't need things like:
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-QT_END_HEADER
-
Yes, it is an informative comment ;-)
*/
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
index 337d962c7f..fc0048f998 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
@@ -42,8 +42,6 @@
#include "qmultitouch_mac_p.h"
#include "qcocoahelpers.h"
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-
QT_BEGIN_NAMESPACE
QHash<qint64, QCocoaTouch*> QCocoaTouch::_currentTouches;
@@ -214,6 +212,3 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
}
QT_END_NAMESPACE
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h
index 1244b8223f..736eb3f878 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h
@@ -61,8 +61,6 @@
#include <qhash.h>
#include <QtCore>
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-
QT_BEGIN_NAMESPACE
class QCocoaTouch
@@ -92,7 +90,5 @@ class QCocoaTouch
QT_END_NAMESPACE
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-
#endif // QMULTITOUCH_MAC_P_H
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index b4b3379a82..eec0cfe5f6 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -82,6 +82,9 @@ QT_END_NAMESPACE
- (BOOL)isFlipped;
- (BOOL)acceptsFirstResponder;
+- (BOOL)becomeFirstResponder;
+
+- (void)resetMouseButtons;
- (void)handleMouseEvent:(NSEvent *)theEvent;
- (void)mouseDown:(NSEvent *)theEvent;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 1d59592e7d..cdbaa235e4 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -331,8 +331,25 @@ static QTouchDevice *touchDevice = 0;
return YES;
}
+- (BOOL)becomeFirstResponder
+{
+ QWindow *focusWindow = m_window;
+
+ // For widgets we need to do a bit of trickery as the window
+ // to activate is the window of the top-level widget.
+ if (m_window->metaObject()->className() == QStringLiteral("QWidgetWindow")) {
+ while (focusWindow->parent()) {
+ focusWindow = focusWindow->parent();
+ }
+ }
+ QWindowSystemInterface::handleWindowActivated(focusWindow);
+ return YES;
+}
+
- (BOOL)acceptsFirstResponder
{
+ if ((m_window->flags() & Qt::ToolTip) == Qt::ToolTip)
+ return NO;
return YES;
}
@@ -381,6 +398,11 @@ static QTouchDevice *touchDevice = 0;
}
}
+- (void)resetMouseButtons
+{
+ m_buttons = Qt::NoButton;
+}
+
- (void)handleMouseEvent:(NSEvent *)theEvent
{
QPoint qtWindowPoint, qtScreenPoint;
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h
index 53bbeb1318..98ad7b8c9d 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.h
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h
@@ -46,26 +46,6 @@
#include "qcocoawindow.h"
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
-@protocol NSWindowDelegate <NSObject>
-//- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
-//- (void)windowDidMiniaturize:(NSNotification*)notification;
-- (void)windowDidResize:(NSNotification *)notification;
-- (void)windowWillClose:(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;
-//- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu;
-//- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard;
-//- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame;
-@end
-#endif
-
@interface QNSWindowDelegate : NSObject <NSWindowDelegate>
{
QCocoaWindow *m_cocoaWindow;
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index 0b6392fb65..56ab732a32 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -90,14 +90,11 @@ void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig
if (rgn.isEmpty()) {
CGContextAddRect(hd, CGRectMake(0, 0, 0, 0));
} else {
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
QCFType<HIMutableShapeRef> shape = qt_mac_QRegionToHIMutableShape(rgn);
Q_ASSERT(!HIShapeIsEmpty(shape));
HIShapeReplacePathInCGContext(shape, hd);
- } else
-#endif
- {
+ } else {
QVector<QRect> rects = rgn.rects();
const int count = rects.size();
for (int i = 0; i < count; i++) {
@@ -338,11 +335,9 @@ CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace()
{
#if 0
if (!m_genericColorSpace) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
} else
-#endif
{
m_genericColorSpace = CGColorSpaceCreateDeviceRGB();
}
@@ -1185,7 +1180,6 @@ extern "C" {
void
QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode)
{
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
int cg_mode = kCGBlendModeNormal;
switch (mode) {
@@ -1267,11 +1261,9 @@ QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode)
if (cg_mode > -1) {
CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode));
}
- } else
-#endif
- // The standard porter duff ops.
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3
+ } else if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3
&& mode <= QPainter::CompositionMode_Xor) {
+ // The standard porter duff ops.
int cg_mode = kCGCompositeModeCopy;
switch (mode) {
case QPainter::CompositionMode_SourceOver:
@@ -1317,7 +1309,6 @@ QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode)
if (cg_mode > -1)
CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode));
} else {
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
bool needPrivateAPI = false;
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
int cg_mode = kCGBlendModeNormal;
@@ -1367,7 +1358,6 @@ QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode)
else
CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode));
}
-#endif
}
}
@@ -1376,13 +1366,8 @@ QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints)
{
Q_D(QCoreGraphicsPaintEngine);
CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing);
- static const CGFloat ScaleFactor = qt_mac_get_scalefactor();
- if (ScaleFactor > 1.) {
- CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh);
- } else {
- CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ?
- kCGInterpolationHigh : kCGInterpolationNone);
- }
+ CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ?
+ kCGInterpolationHigh : kCGInterpolationNone);
bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing;
if (!textAntialiasing || d->disabledSmoothFonts) {
d->disabledSmoothFonts = !textAntialiasing;
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
index 2763a14690..fa000b9f92 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
@@ -122,8 +122,6 @@ public:
void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
{ QPaintEngine::drawPolygon(points, pointCount, mode); }
- bool supportsTransformations(qreal, const QTransform &) const { return true; };
-
protected:
friend class QMacPrintEngine;
friend class QMacPrintEnginePrivate;
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index 54019372bc..4570a663f6 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -190,23 +190,7 @@ QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const
if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) {
PMResolution res;
OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount);
- if (status == kPMNotImplemented) {
-#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
- // *Sigh* we have to use the non-indexed version.
- if (PMPrinterGetPrinterResolution(printer, kPMMinSquareResolution, &res) == noErr)
- resolutions.append(int(res.hRes));
- if (PMPrinterGetPrinterResolution(printer, kPMMaxSquareResolution, &res) == noErr) {
- QVariant var(int(res.hRes));
- if (!resolutions.contains(var))
- resolutions.append(var);
- }
- if (PMPrinterGetPrinterResolution(printer, kPMDefaultResolution, &res) == noErr) {
- QVariant var(int(res.hRes));
- if (!resolutions.contains(var))
- resolutions.append(var);
- }
-#endif
- } else if (status == noErr) {
+ if (status == noErr) {
// According to the docs, index start at 1.
for (UInt32 i = 1; i <= resCount; ++i) {
if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr)
diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.cpp b/src/plugins/platforms/directfb/qdirectfbcursor.cpp
index afddba3482..b03af51b1a 100644
--- a/src/plugins/platforms/directfb/qdirectfbcursor.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbcursor.cpp
@@ -59,8 +59,9 @@ void QDirectFBCursor::changeCursor(QCursor *cursor, QWindow *)
int ySpot;
QPixmap map;
- if (cursor->shape() != Qt::BitmapCursor) {
- m_image->set(cursor->shape());
+ const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
+ if (newShape != Qt::BitmapCursor) {
+ m_image->set(newShape);
xSpot = m_image->hotspot().x();
ySpot = m_image->hotspot().y();
QImage *i = m_image->image();
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp
index 66b42d64e7..06db4e02db 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp
@@ -43,14 +43,17 @@
#include "qeglfswindow.h"
#include "qeglfscursor.h"
#include "qeglfshooks.h"
+#include "qeglfsintegration.h"
+#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include <QtGui/QSurface>
#include <QtDebug>
QT_BEGIN_NAMESPACE
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
EGLDisplay display, EGLenum eglApi)
- : QEGLPlatformContext(hooks->surfaceFormatFor(format), share, display, eglApi)
+ : QEGLPlatformContext(format, share, display, QEglFSIntegration::chooseConfig(display, format), eglApi)
{
}
@@ -61,16 +64,20 @@ bool QEglFSContext::makeCurrent(QPlatformSurface *surface)
EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
{
- QEglFSWindow *window = static_cast<QEglFSWindow *>(surface);
- return window->surface();
+ if (surface->surface()->surfaceClass() == QSurface::Window)
+ return static_cast<QEglFSWindow *>(surface)->surface();
+ else
+ return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
void QEglFSContext::swapBuffers(QPlatformSurface *surface)
{
- QEglFSWindow *window = static_cast<QEglFSWindow *>(surface);
- // draw the cursor
- if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->cursor()))
- cursor->paintOnScreen();
+ if (surface->surface()->surfaceClass() == QSurface::Window) {
+ QEglFSWindow *window = static_cast<QEglFSWindow *>(surface);
+ // draw the cursor
+ if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->cursor()))
+ cursor->paintOnScreen();
+ }
QEGLPlatformContext::swapBuffers(surface);
}
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.cpp b/src/plugins/platforms/eglfs/qeglfscursor.cpp
index c245b1b5bb..9dc836b8b1 100644
--- a/src/plugins/platforms/eglfs/qeglfscursor.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscursor.cpp
@@ -196,15 +196,16 @@ void QEglFSCursor::changeCursor(QCursor *cursor, QWindow *window)
bool QEglFSCursor::setCurrentCursor(QCursor *cursor)
{
- if (m_cursor.shape == cursor->shape() && cursor->shape() != Qt::BitmapCursor)
+ const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
+ if (m_cursor.shape == newShape && newShape != Qt::BitmapCursor)
return false;
if (m_cursor.shape == Qt::BitmapCursor) {
m_cursor.customCursorImage = QImage(); // in case render() never uploaded it
}
- m_cursor.shape = cursor->shape();
- if (cursor->shape() != Qt::BitmapCursor) { // standard cursor
+ m_cursor.shape = newShape;
+ if (newShape != Qt::BitmapCursor) { // standard cursor
const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width,
hs = (float)m_cursorAtlas.cursorHeight / m_cursorAtlas.height;
m_cursor.textureRect = QRectF(ws * (m_cursor.shape % m_cursorAtlas.cursorsPerRow),
diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h
index 2d095ba934..f3b6a28e70 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks.h
+++ b/src/plugins/platforms/eglfs/qeglfshooks.h
@@ -55,10 +55,11 @@ class QEglFSScreen;
class QEglFSHooks
{
public:
- virtual ~QEglFSHooks() {};
+ virtual ~QEglFSHooks() {}
virtual void platformInit();
virtual void platformDestroy();
virtual EGLNativeDisplayType platformDisplay() const;
+ virtual QSizeF physicalScreenSize() const;
virtual QSize screenSize() const;
virtual int screenDepth() const;
virtual QImage::Format screenFormat() const;
@@ -67,6 +68,9 @@ public:
virtual void destroyNativeWindow(EGLNativeWindowType window);
virtual bool hasCapability(QPlatformIntegration::Capability cap) const;
virtual QEglFSCursor *createCursor(QEglFSScreen *screen) const;
+ virtual bool filterConfig(EGLDisplay display, EGLConfig config) const;
+
+ virtual const char *fbDeviceName() const;
};
#ifdef EGLFS_PLATFORM_HOOKS
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
index e9a22ea605..a8fa81a6ec 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
+++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
@@ -46,8 +46,15 @@
#include <linux/fb.h>
#include <sys/ioctl.h>
+#include <private/qmath_p.h>
+
QT_BEGIN_NAMESPACE
+const char *QEglFSHooks::fbDeviceName() const
+{
+ return "/dev/fb0";
+}
+
void QEglFSHooks::platformInit()
{
Q_UNUSED(hooks);
@@ -62,6 +69,61 @@ EGLNativeDisplayType QEglFSHooks::platformDisplay() const
return EGL_DEFAULT_DISPLAY;
}
+QSizeF QEglFSHooks::physicalScreenSize() const
+{
+ static QSizeF size;
+ if (size.isEmpty()) {
+
+ // Note: in millimeters
+ int width = qgetenv("QT_QPA_EGLFS_PHYSICAL_WIDTH").toInt();
+ int height = qgetenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT").toInt();
+
+ if (width && height) {
+ // no need to read fb0
+ size.setWidth(width);
+ size.setHeight(height);
+ return size;
+ }
+
+ struct fb_var_screeninfo vinfo;
+ int fd = open(fbDeviceName(), O_RDONLY);
+
+ int w = -1;
+ int h = -1;
+
+ if (fd != -1) {
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ qWarning("EGLFS: Could not query variable screen info.");
+ } else {
+ w = vinfo.width;
+ h = vinfo.height;
+ }
+
+ close(fd);
+ } else {
+ qWarning("EGLFS: Failed to open %s to detect physical screen size.", fbDeviceName());
+ }
+
+ const int defaultPhysicalDpi = 100;
+ size.setWidth(w <= 0 ? vinfo.xres * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(w));
+ size.setHeight(h <= 0 ? vinfo.yres * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(h));
+
+ if (w <= 0 || h <= 0) {
+ qWarning("EGLFS: Unable to query physical screen size, defaulting to %d dpi.\n"
+ "EGLFS: To override, set QT_QPA_EGLFS_PHYSICAL_WIDTH "
+ "and QT_QPA_EGLFS_PHYSICAL_HEIGHT (in millimeters).",
+ defaultPhysicalDpi);
+ }
+
+ // override fb0 from environment var setting
+ if (width)
+ size.setWidth(width);
+ if (height)
+ size.setWidth(height);
+ }
+ return size;
+}
+
QSize QEglFSHooks::screenSize() const
{
static QSize size;
@@ -78,17 +140,33 @@ QSize QEglFSHooks::screenSize() const
}
struct fb_var_screeninfo vinfo;
- int fd = open("/dev/fb0", O_RDONLY);
+ int fd = open(fbDeviceName(), O_RDONLY);
+
+ int xres = -1;
+ int yres = -1;
if (fd != -1) {
- if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
- qWarning("Could not query variable screen info.");
- else
- size = QSize(vinfo.xres, vinfo.yres);
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ qWarning("EGLFS: Could not query variable screen info.");
+ } else {
+ xres = vinfo.xres;
+ yres = vinfo.yres;
+ }
close(fd);
} else {
- qWarning("Failed to open /dev/fb0 to detect screen resolution.");
+ qWarning("EGLFS: Failed to open %s to detect screen resolution.", fbDeviceName());
+ }
+
+ const int defaultWidth = 800;
+ const int defaultHeight = 600;
+ size.setWidth(xres <= 0 ? defaultWidth : xres);
+ size.setHeight(yres <= 0 ? defaultHeight : yres);
+
+ if (xres <= 0 || yres <= 0) {
+ qWarning("EGLFS: Unable to query screen resolution, defaulting to %dx%d.\n"
+ "EGLFS: To override, set QT_QPA_EGLFS_WIDTH and QT_QPA_EGLFS_HEIGHT.",
+ defaultWidth, defaultHeight);
}
// override fb0 from environment var setting
@@ -107,21 +185,30 @@ int QEglFSHooks::screenDepth() const
if (depth == 0) {
struct fb_var_screeninfo vinfo;
- int fd = open("/dev/fb0", O_RDONLY);
+ int fd = open(fbDeviceName(), O_RDONLY);
if (fd != -1) {
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
- qWarning("Could not query variable screen info.");
+ qWarning("EGLFS: Could not query variable screen info.");
else
depth = vinfo.bits_per_pixel;
close(fd);
} else {
- qWarning("Failed to open /dev/fb0 to detect screen depth.");
+ qWarning("EGLFS: Failed to open %s to detect screen depth.", fbDeviceName());
+ }
+
+ const int defaultDepth = 32;
+
+ if (depth <= 0) {
+ depth = defaultDepth;
+
+ qWarning("EGLFS: Unable to query screen depth, defaulting to %d.\n"
+ "EGLFS: To override, set QT_QPA_EGLFS_DEPTH.", defaultDepth);
}
}
- return depth == 0 ? 32 : depth;
+ return depth;
}
QImage::Format QEglFSHooks::screenFormat() const
@@ -134,6 +221,11 @@ QSurfaceFormat QEglFSHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat)
return inputFormat;
}
+bool QEglFSHooks::filterConfig(EGLDisplay, EGLConfig) const
+{
+ return true;
+}
+
EGLNativeWindowType QEglFSHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format)
{
Q_UNUSED(size);
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 0dcde9ca36..dd212c80a0 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -49,7 +49,9 @@
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <QtPlatformSupport/private/qeglpbuffer_p.h>
#if !defined(QT_NO_EVDEV)
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
@@ -61,6 +63,7 @@
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
+#include <QtGui/QOffscreenSurface>
#include <qpa/qplatformcursor.h>
#include "qeglfscontext.h"
@@ -150,7 +153,13 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi
QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- return new QEglFSContext(context->format(), 0 /*share*/, mDisplay);
+ return new QEglFSContext(hooks->surfaceFormatFor(context->format()), context->shareHandle(), mDisplay);
+}
+
+QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+ QEglFSScreen *screen = static_cast<QEglFSScreen *>(surface->screen()->handle());
+ return new QEGLPbuffer(screen->display(), hooks->surfaceFormatFor(surface->requestedFormat()), surface);
}
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
@@ -201,4 +210,29 @@ void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QO
return 0;
}
+EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
+{
+ class Chooser : public QEglConfigChooser {
+ public:
+ Chooser(EGLDisplay display, QEglFSHooks *hooks)
+ : QEglConfigChooser(display)
+ , m_hooks(hooks)
+ {
+ }
+
+ protected:
+ bool filterConfig(EGLConfig config) const
+ {
+ return m_hooks->filterConfig(display(), config) && QEglConfigChooser::filterConfig(config);
+ }
+
+ private:
+ QEglFSHooks *m_hooks;
+ };
+
+ Chooser chooser(display, hooks);
+ chooser.setSurfaceFormat(format);
+ return chooser.chooseConfig();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h
index 42b132b73a..e048c5d310 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.h
@@ -48,8 +48,6 @@
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformscreen.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QEglFSIntegration : public QPlatformIntegration, public QPlatformNativeInterface
@@ -63,6 +61,7 @@ public:
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const;
QPlatformNativeInterface *nativeInterface() const;
QPlatformFontDatabase *fontDatabase() const;
@@ -75,6 +74,8 @@ public:
void *nativeResourceForIntegration(const QByteArray &resource);
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
+ static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);
+
private:
EGLDisplay mDisplay;
QAbstractEventDispatcher *mEventDispatcher;
@@ -83,6 +84,5 @@ private:
};
QT_END_NAMESPACE
-QT_END_HEADER
#endif // QEGLFSINTEGRATION_H
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
index 1bc1e944de..43d7cb3b1f 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
@@ -83,6 +83,11 @@ QImage::Format QEglFSScreen::format() const
return hooks->screenFormat();
}
+QSizeF QEglFSScreen::physicalSize() const
+{
+ return hooks->physicalScreenSize();
+}
+
QPlatformCursor *QEglFSScreen::cursor() const
{
return m_cursor;
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h
index 309791d6c2..8d3c5dbaec 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.h
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.h
@@ -63,6 +63,8 @@ public:
int depth() const;
QImage::Format format() const;
+ QSizeF physicalSize() const;
+
QPlatformCursor *cursor() const;
EGLDisplay display() const { return m_dpy; }
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index ceb04901c4..26f701d7ba 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -84,7 +84,8 @@ void QEglFSWindow::create()
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
QSurfaceFormat platformFormat = hooks->surfaceFormatFor(window()->requestedFormat());
- EGLConfig config = q_configFromGLFormat(display, platformFormat);
+ EGLConfig config = QEglFSIntegration::chooseConfig(display, platformFormat);
+
m_format = q_glFormatFromConfig(display, config);
m_window = hooks->createNativeWindow(hooks->screenSize(), m_format);
m_surface = eglCreateWindowSurface(display, config, m_window, NULL);
diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro
index c0300e0960..711cf9e5c7 100644
--- a/src/plugins/platforms/kms/kms.pro
+++ b/src/plugins/platforms/kms/kms.pro
@@ -4,9 +4,10 @@ PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QKmsIntegrationPlugin
load(qt_plugin)
-QT += core-private gui-private platformsupport-private opengl-private
+QT += core-private gui-private platformsupport-private
+qtHaveModule(opengl):QT += opengl-private
-DEFINES += MESA_EGL_NO_X11_HEADERS
+DEFINES += MESA_EGL_NO_X11_HEADERS __GBM__
CONFIG += link_pkgconfig egl qpa/genericunixfontdatabase
diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp
index d9345ce89b..da5dc9bb06 100644
--- a/src/plugins/platforms/kms/qkmscursor.cpp
+++ b/src/plugins/platforms/kms/qkmscursor.cpp
@@ -48,22 +48,17 @@ QT_BEGIN_NAMESPACE
QKmsCursor::QKmsCursor(QKmsScreen *screen)
: m_screen(screen),
m_graphicsBufferManager(screen->device()->gbmDevice()),
+ m_cursorBufferObject(gbm_bo_create(m_graphicsBufferManager, 64, 64, GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_CURSOR_64X64|GBM_BO_USE_WRITE)),
+ m_cursorImage(new QPlatformCursorImage(0, 0, 0, 0, 0, 0)),
m_moved(false)
{
- gbm_bo *bo = gbm_bo_create(m_graphicsBufferManager, 64, 64,
- GBM_BO_FORMAT_ARGB8888,
- GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_RENDERING);
-
- m_eglImage = eglCreateImageKHR(m_screen->device()->eglDisplay(), 0, EGL_NATIVE_PIXMAP_KHR,
- bo, 0);
- gbm_bo_destroy(bo);
- m_cursorImage = new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
}
QKmsCursor::~QKmsCursor()
{
- drmModeSetCursor(m_screen->device()->fd(), m_screen->crtcId(),
- 0, 0, 0);
+ drmModeSetCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0, 0);
+ gbm_bo_destroy(m_cursorBufferObject);
}
void QKmsCursor::pointerEvent(const QMouseEvent &event)
@@ -78,57 +73,30 @@ void QKmsCursor::pointerEvent(const QMouseEvent &event)
}
}
-void QKmsCursor::changeCursor(QCursor *widgetCursor, QWindow *window)
+void QKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
Q_UNUSED(window)
if (!m_moved)
drmModeMoveCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0);
- if (widgetCursor->shape() != Qt::BitmapCursor) {
- m_cursorImage->set(widgetCursor->shape());
- } else {
- m_cursorImage->set(widgetCursor->pixmap().toImage(),
- widgetCursor->hotSpot().x(),
- widgetCursor->hotSpot().y());
- }
-
- if ((m_cursorImage->image()->width() > 64) || (m_cursorImage->image()->width() > 64)) {
- qWarning("failed to set hardware cursor: larger than 64x64.");
- return;
- }
-
- QImage cursorImage = m_cursorImage->image()->convertToFormat(QImage::Format_RGB32);
-
- //Load cursor image into EGLImage
- GLuint cursorTexture;
- glGenTextures(1, &cursorTexture);
- glBindTexture(GL_TEXTURE_2D, cursorTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-
- //TODO: Format may be wrong here, need a color icon to test.
- if (m_eglImage != EGL_NO_IMAGE_KHR) {
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cursorImage.width(),
- cursorImage.height(), GL_RGBA,
- GL_UNSIGNED_BYTE, cursorImage.constBits());
+ const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor;
+ if (newShape != Qt::BitmapCursor) {
+ m_cursorImage->set(newShape);
} else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cursorImage.width(),
- cursorImage.height(), 0, GL_RGBA,
- GL_UNSIGNED_BYTE, cursorImage.constBits());
+ m_cursorImage->set(windowCursor->pixmap().toImage(),
+ windowCursor->hotSpot().x(),
+ windowCursor->hotSpot().y());
}
- //EGLImage needs to contain sprite before calling this:
- gbm_bo *bufferObject = gbm_bo_import(m_graphicsBufferManager, GBM_BO_IMPORT_EGL_IMAGE,
- m_eglImage, GBM_BO_USE_CURSOR_64X64);
- quint32 handle = gbm_bo_get_handle(bufferObject).u32;
+ if ((m_cursorImage->image()->width() > 64) || (m_cursorImage->image()->width() > 64))
+ qWarning("Warning: cursor larger than 64x64; only 64x64 pixels will be shown.");
- gbm_bo_destroy(bufferObject);
+ QImage cursorImage = m_cursorImage->image()->
+ convertToFormat(QImage::Format_ARGB32).copy(0, 0, 64, 64);
+ gbm_bo_write(m_cursorBufferObject, cursorImage.constBits(), cursorImage.byteCount());
+ quint32 handle = gbm_bo_get_handle(m_cursorBufferObject).u32;
int status = drmModeSetCursor(m_screen->device()->fd(),
m_screen->crtcId(), handle, 64, 64);
diff --git a/src/plugins/platforms/kms/qkmscursor.h b/src/plugins/platforms/kms/qkmscursor.h
index fda47ebedc..ee65b01e36 100644
--- a/src/plugins/platforms/kms/qkmscursor.h
+++ b/src/plugins/platforms/kms/qkmscursor.h
@@ -44,15 +44,11 @@
#include <qpa/qplatformcursor.h>
-#define EGL_EGLEXT_PROTOTYPES 1
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
QT_BEGIN_NAMESPACE
class QKmsScreen;
class gbm_device;
+class gbm_bo;
class QKmsCursor : public QPlatformCursor
{
@@ -61,12 +57,12 @@ public:
~QKmsCursor();
void pointerEvent(const QMouseEvent &event);
- void changeCursor(QCursor *widgetCursor, QWindow *window);
+ void changeCursor(QCursor *windowCursor, QWindow *window);
private:
QKmsScreen *m_screen;
gbm_device *m_graphicsBufferManager;
- EGLImageKHR m_eglImage;
+ gbm_bo *m_cursorBufferObject;
QPlatformCursorImage *m_cursorImage;
bool m_moved;
};
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
index 123dcc283f..892f7bb01f 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -124,10 +124,14 @@ void QKmsScreen::initializeScreenMode()
drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
drmModeModeInfo *mode = 0;
- if (connector->count_modes > 0)
- mode = &connector->modes[0];
- else
- mode = &builtin_1024x768;
+ for (int i = 0; i < connector->count_modes; ++i) {
+ if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
+ mode = &connector->modes[i];
+ break;
+ }
+ }
+ if (!mode)
+ mode = mode = &builtin_1024x768;
drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
if (encoder == 0)
diff --git a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp
index da89100359..cb245f2e5c 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
QMinimalEglBackingStore::QMinimalEglBackingStore(QWindow *window)
: QPlatformBackingStore(window)
, m_context(new QOpenGLContext)
+ , m_device(0)
{
m_context->setFormat(window->requestedFormat());
m_context->setScreen(window->screen());
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.h b/src/plugins/platforms/minimalegl/qminimaleglintegration.h
index fb86c967e1..dba7504033 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.h
@@ -47,8 +47,6 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformscreen.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
class QMinimalEglIntegration : public QPlatformIntegration
@@ -75,6 +73,5 @@ private:
};
QT_END_NAMESPACE
-QT_END_HEADER
#endif // QMINIMALEGLINTEGRATION_H
diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp
new file mode 100644
index 0000000000..ca7dc1d18b
--- /dev/null
+++ b/src/plugins/platforms/offscreen/main.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qpa/qplatformintegrationplugin.h>
+#include "qoffscreenintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE "offscreen.json")
+public:
+ QPlatformIntegration *create(const QString&, const QStringList&);
+};
+
+QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+ Q_UNUSED(paramList);
+ if (system.toLower() == "offscreen")
+ return QOffscreenIntegration::createOffscreenIntegration();
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/platforms/offscreen/offscreen.json b/src/plugins/platforms/offscreen/offscreen.json
new file mode 100644
index 0000000000..6e87744de0
--- /dev/null
+++ b/src/plugins/platforms/offscreen/offscreen.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "offscreen" ]
+}
diff --git a/src/plugins/platforms/offscreen/offscreen.pro b/src/plugins/platforms/offscreen/offscreen.pro
new file mode 100644
index 0000000000..270e3ce228
--- /dev/null
+++ b/src/plugins/platforms/offscreen/offscreen.pro
@@ -0,0 +1,25 @@
+TARGET = qoffscreen
+
+PLUGIN_TYPE = platforms
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private
+
+SOURCES = main.cpp \
+ qoffscreenintegration.cpp \
+ qoffscreenwindow.cpp \
+ qoffscreencommon.cpp
+
+HEADERS = qoffscreenintegration.h \
+ qoffscreenwindow.h \
+ qoffscreencommon.h
+
+OTHER_FILES += offscreen.json
+
+contains(QT_CONFIG, xcb):contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2) {
+ SOURCES += qoffscreenintegration_x11.cpp
+ HEADERS += qoffscreenintegration_x11.h
+ system(echo "Using X11 offscreen integration with GLX")
+} else {
+ SOURCES += qoffscreenintegration_dummy.cpp
+}
diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp
new file mode 100644
index 0000000000..069b20693d
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoffscreencommon.h"
+#include "qoffscreenwindow.h"
+
+#include <QtGui/private/qpixmap_raster_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+QPlatformWindow *QOffscreenScreen::windowContainingCursor = 0;
+
+class QOffscreenCursor : public QPlatformCursor
+{
+public:
+ QOffscreenCursor() : m_pos(10, 10) {}
+
+ QPoint pos() const { return m_pos; }
+ void setPos(const QPoint &pos)
+ {
+ m_pos = pos;
+ QWindowList wl = QGuiApplication::topLevelWindows();
+ QWindow *containing = 0;
+ foreach (QWindow *w, wl) {
+ if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(pos)) {
+ containing = w;
+ break;
+ }
+ }
+
+ QPoint local = pos;
+ if (containing)
+ local -= containing->position();
+
+ QWindow *previous = QOffscreenScreen::windowContainingCursor ? QOffscreenScreen::windowContainingCursor->window() : 0;
+
+ if (containing != previous)
+ QWindowSystemInterface::handleEnterLeaveEvent(containing, previous, local, pos);
+
+ QWindowSystemInterface::handleMouseEvent(containing, local, pos, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
+
+ QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : 0;
+ }
+
+ void changeCursor(QCursor *windowCursor, QWindow *window)
+ {
+ Q_UNUSED(windowCursor);
+ Q_UNUSED(window);
+ }
+
+private:
+ QPoint m_pos;
+};
+
+QOffscreenScreen::QOffscreenScreen()
+ : m_geometry(0, 0, 800, 600)
+ , m_cursor(new QOffscreenCursor)
+{
+}
+
+QPixmap QOffscreenScreen::grabWindow(WId id, int x, int y, int width, int height) const
+{
+ QRect rect(x, y, width, height);
+
+ QOffscreenWindow *window = QOffscreenWindow::windowForWinId(id);
+ if (!window || window->window()->type() == Qt::Desktop) {
+ QWindowList wl = QGuiApplication::topLevelWindows();
+ QWindow *containing = 0;
+ foreach (QWindow *w, wl) {
+ if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(rect)) {
+ containing = w;
+ break;
+ }
+ }
+
+ if (!containing)
+ return QPixmap();
+
+ id = containing->winId();
+ rect = rect.translated(-containing->geometry().topLeft());
+ }
+
+ QOffscreenBackingStore *store = QOffscreenBackingStore::backingStoreForWinId(id);
+ if (store)
+ return store->grabWindow(id, rect);
+ return QPixmap();
+}
+
+QOffscreenBackingStore::QOffscreenBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+{
+}
+
+QOffscreenBackingStore::~QOffscreenBackingStore()
+{
+ clearHash();
+}
+
+QPaintDevice *QOffscreenBackingStore::paintDevice()
+{
+ return &m_image;
+}
+
+void QOffscreenBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(region);
+
+ if (m_image.size().isEmpty())
+ return;
+
+ QSize imageSize = m_image.size();
+
+ QRegion clipped = QRect(0, 0, window->width(), window->height());
+ clipped &= QRect(0, 0, imageSize.width(), imageSize.height()).translated(-offset);
+
+ QRect bounds = clipped.boundingRect().translated(offset);
+
+ if (bounds.isNull())
+ return;
+
+ WId id = window->winId();
+
+ m_windowAreaHash[id] = bounds;
+ m_backingStoreForWinIdHash[id] = this;
+}
+
+void QOffscreenBackingStore::resize(const QSize &size, const QRegion &)
+{
+ QImage::Format format = QGuiApplication::primaryScreen()->handle()->format();
+ if (m_image.size() != size)
+ m_image = QImage(size, format);
+ clearHash();
+}
+
+extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
+
+bool QOffscreenBackingStore::scroll(const QRegion &area, int dx, int dy)
+{
+ if (m_image.isNull())
+ return false;
+
+ const QVector<QRect> rects = area.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ qt_scrollRectInImage(m_image, rects.at(i), QPoint(dx, dy));
+
+ return true;
+}
+
+QPixmap QOffscreenBackingStore::grabWindow(WId window, const QRect &rect) const
+{
+ QRect area = m_windowAreaHash.value(window, QRect());
+ if (area.isNull())
+ return QPixmap();
+
+ QRect adjusted = rect;
+ if (adjusted.width() <= 0)
+ adjusted.setWidth(area.width());
+ if (adjusted.height() <= 0)
+ adjusted.setHeight(area.height());
+
+ adjusted = adjusted.translated(area.topLeft()) & area;
+
+ if (adjusted.isEmpty())
+ return QPixmap();
+
+ return QPixmap::fromImage(m_image.copy(adjusted));
+}
+
+QOffscreenBackingStore *QOffscreenBackingStore::backingStoreForWinId(WId id)
+{
+ return m_backingStoreForWinIdHash.value(id, 0);
+}
+
+void QOffscreenBackingStore::clearHash()
+{
+ QList<WId> ids = m_windowAreaHash.keys();
+ foreach (WId id, ids) {
+ QHash<WId, QOffscreenBackingStore *>::iterator it = m_backingStoreForWinIdHash.find(id);
+ if (it.value() == this)
+ m_backingStoreForWinIdHash.remove(id);
+ }
+ m_windowAreaHash.clear();
+}
+
+QHash<WId, QOffscreenBackingStore *> QOffscreenBackingStore::m_backingStoreForWinIdHash;
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h
new file mode 100644
index 0000000000..a5df7d05d3
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreencommon.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOFFSCREENCOMMON_H
+#define QOFFSCREENCOMMON_H
+
+#include <qpa/qplatformbackingstore.h>
+#include <qpa/qplatformdrag.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformwindow.h>
+
+#include <qscopedpointer.h>
+#include <qimage.h>
+#include <qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenScreen : public QPlatformScreen
+{
+public:
+ QOffscreenScreen();
+
+ QRect geometry() const { return m_geometry; }
+ int depth() const { return 32; }
+ QImage::Format format() const { return QImage::Format_RGB32; }
+ QPlatformCursor *cursor() const { return m_cursor.data(); }
+
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+
+ static QPlatformWindow *windowContainingCursor;
+
+public:
+ QRect m_geometry;
+ QScopedPointer<QPlatformCursor> m_cursor;
+};
+
+class QOffscreenDrag : public QPlatformDrag
+{
+public:
+ QMimeData *platformDropData() { return 0; }
+ Qt::DropAction drag(QDrag *) { return Qt::IgnoreAction; }
+};
+
+class QOffscreenBackingStore : public QPlatformBackingStore
+{
+public:
+ QOffscreenBackingStore(QWindow *window);
+ ~QOffscreenBackingStore();
+
+ QPaintDevice *paintDevice();
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset);
+ void resize(const QSize &size, const QRegion &staticContents);
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ QPixmap grabWindow(WId window, const QRect &rect) const;
+
+ static QOffscreenBackingStore *backingStoreForWinId(WId id);
+
+private:
+ void clearHash();
+
+ QImage m_image;
+ QHash<WId, QRect> m_windowAreaHash;
+
+ static QHash<WId, QOffscreenBackingStore *> m_backingStoreForWinIdHash;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
new file mode 100644
index 0000000000..e3fcc7ebb0
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoffscreenintegration.h"
+#include "qoffscreenwindow.h"
+#include "qoffscreencommon.h"
+
+#if defined(Q_OS_UNIX)
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#if defined(Q_OS_MAC)
+#include <qpa/qplatformfontdatabase.h>
+#else
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#endif
+#elif defined(Q_OS_WIN)
+#include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
+#include <QtCore/private/qeventdispatcher_win_p.h>
+#endif
+
+#include <QtGui/private/qpixmap_raster_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatformservices.h>
+
+QT_BEGIN_NAMESPACE
+
+template <typename BaseEventDispatcher>
+class QOffscreenEventDispatcher : public BaseEventDispatcher
+{
+public:
+ explicit QOffscreenEventDispatcher(QObject *parent = 0)
+ : BaseEventDispatcher(parent)
+ {
+ }
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags)
+ {
+ bool didSendEvents = QWindowSystemInterface::sendWindowSystemEvents(flags);
+
+ return BaseEventDispatcher::processEvents(flags) || didSendEvents;
+ }
+
+ bool hasPendingEvents()
+ {
+ return BaseEventDispatcher::hasPendingEvents()
+ || QWindowSystemInterface::windowSystemEventsQueued();
+ }
+
+ void flush()
+ {
+ if (qApp)
+ qApp->sendPostedEvents();
+ BaseEventDispatcher::flush();
+ }
+};
+
+QOffscreenIntegration::QOffscreenIntegration()
+{
+#if defined(Q_OS_UNIX)
+ m_eventDispatcher = createUnixEventDispatcher();
+#if defined(Q_OS_MAC)
+ m_fontDatabase.reset(new QPlatformFontDatabase());
+#else
+ m_fontDatabase.reset(new QGenericUnixFontDatabase());
+#endif
+#elif defined(Q_OS_WIN)
+ m_eventDispatcher = new QOffscreenEventDispatcher<QEventDispatcherWin32>();
+ m_fontDatabase.reset(new QBasicFontDatabase());
+#endif
+
+ m_drag.reset(new QOffscreenDrag);
+ m_services.reset(new QPlatformServices);
+
+ QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher);
+ screenAdded(new QOffscreenScreen);
+}
+
+QOffscreenIntegration::~QOffscreenIntegration()
+{
+}
+
+bool QOffscreenIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case MultipleWindows: return true;
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformWindow *QOffscreenIntegration::createPlatformWindow(QWindow *window) const
+{
+ Q_UNUSED(window);
+ QPlatformWindow *w = new QOffscreenWindow(window);
+ w->requestActivateWindow();
+ return w;
+}
+
+QPlatformBackingStore *QOffscreenIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ return new QOffscreenBackingStore(window);
+}
+
+QAbstractEventDispatcher *QOffscreenIntegration::guiThreadEventDispatcher() const
+{
+ return m_eventDispatcher;
+}
+
+QPlatformFontDatabase *QOffscreenIntegration::fontDatabase() const
+{
+ return m_fontDatabase.data();
+}
+
+QPlatformDrag *QOffscreenIntegration::drag() const
+{
+ return m_drag.data();
+}
+
+QPlatformServices *QOffscreenIntegration::services() const
+{
+ return m_services.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h
new file mode 100644
index 0000000000..eb03100ec9
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOFFSCREENINTEGRATION_H
+#define QOFFSCREENINTEGRATION_H
+
+#include <qpa/qplatformintegration.h>
+
+#include <qscopedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenBackendData;
+
+class QOffscreenIntegration : public QPlatformIntegration
+{
+public:
+ QOffscreenIntegration();
+ ~QOffscreenIntegration();
+
+ bool hasCapability(QPlatformIntegration::Capability cap) const;
+
+ QPlatformWindow *createPlatformWindow(QWindow *window) const;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+ QPlatformDrag *drag() const;
+ QPlatformServices *services() const;
+
+ QPlatformFontDatabase *fontDatabase() const;
+ QAbstractEventDispatcher *guiThreadEventDispatcher() const;
+
+ static QOffscreenIntegration *createOffscreenIntegration();
+
+private:
+ QAbstractEventDispatcher *m_eventDispatcher;
+ QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
+ QScopedPointer<QPlatformDrag> m_drag;
+ QScopedPointer<QPlatformServices> m_services;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp
new file mode 100644
index 0000000000..8bc1b17a56
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoffscreenintegration.h"
+
+QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
+{
+ return new QOffscreenIntegration;
+}
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
new file mode 100644
index 0000000000..4b27afd80f
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoffscreenintegration_x11.h"
+
+#include <QByteArray>
+#include <QOpenGLContext>
+
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+#include <QtPlatformSupport/private/qglxconvenience_p.h>
+
+#include <qpa/qplatformsurface.h>
+#include <qsurface.h>
+
+QT_BEGIN_NAMESPACE
+
+QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
+{
+ return new QOffscreenX11Integration;
+}
+
+bool QOffscreenX11Integration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case OpenGL: return true;
+ case ThreadedOpenGL: return true;
+ default: return QOffscreenIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformOpenGLContext *QOffscreenX11Integration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ if (!m_connection)
+ m_connection.reset(new QOffscreenX11Connection);
+
+ return new QOffscreenX11GLXContext(m_connection->x11Info(), context);
+}
+
+QOffscreenX11Connection::QOffscreenX11Connection()
+{
+ XInitThreads();
+
+ QByteArray displayName = qgetenv("DISPLAY");
+ Display *display = XOpenDisplay(displayName.constData());
+ m_display = display;
+ m_screenNumber = DefaultScreen(display);
+}
+
+QOffscreenX11Connection::~QOffscreenX11Connection()
+{
+ XCloseDisplay((Display *)m_display);
+}
+
+class QOffscreenX11Info
+{
+public:
+ QOffscreenX11Info(QOffscreenX11Connection *connection)
+ : m_connection(connection)
+ {
+ }
+
+ Display *display() const {
+ return (Display *)m_connection->display();
+ }
+
+ Window root() const {
+ return DefaultRootWindow(display());
+ }
+
+ int screenNumber() const {
+ return m_connection->screenNumber();
+ }
+
+private:
+ QOffscreenX11Connection *m_connection;
+};
+
+QOffscreenX11Info *QOffscreenX11Connection::x11Info()
+{
+ if (!m_x11Info)
+ m_x11Info.reset(new QOffscreenX11Info(this));
+ return m_x11Info.data();
+}
+
+class QOffscreenX11GLXContextData
+{
+public:
+ QOffscreenX11Info *x11;
+ QSurfaceFormat format;
+ GLXContext context;
+ GLXContext shareContext;
+ Window window;
+};
+
+static Window createDummyWindow(QOffscreenX11Info *x11, XVisualInfo *visualInfo)
+{
+ Colormap cmap = XCreateColormap(x11->display(), x11->root(), visualInfo->visual, AllocNone);
+ XSetWindowAttributes a;
+ a.background_pixel = WhitePixel(x11->display(), x11->screenNumber());
+ a.border_pixel = BlackPixel(x11->display(), x11->screenNumber());
+ a.colormap = cmap;
+
+ Window window = XCreateWindow(x11->display(), x11->root(),
+ 0, 0, 100, 100,
+ 0, visualInfo->depth, InputOutput, visualInfo->visual,
+ CWBackPixel|CWBorderPixel|CWColormap, &a);
+ XFreeColormap(x11->display(), cmap);
+ return window;
+}
+
+static Window createDummyWindow(QOffscreenX11Info *x11, GLXFBConfig config)
+{
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(x11->display(), config);
+ if (!visualInfo)
+ qFatal("Could not initialize GLX");
+ Window window = createDummyWindow(x11, visualInfo);
+ XFree(visualInfo);
+ return window;
+}
+
+QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context)
+ : d(new QOffscreenX11GLXContextData)
+{
+ d->x11 = x11;
+ d->format = context->format();
+
+ d->shareContext = 0;
+ if (context->shareHandle())
+ d->shareContext = static_cast<QOffscreenX11GLXContext *>(context->shareHandle())->d->context;
+
+ GLXFBConfig config = qglx_findConfig(x11->display(), x11->screenNumber(), d->format);
+ if (config) {
+ d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, d->shareContext, true);
+ if (!d->context && d->shareContext) {
+ d->shareContext = 0;
+ // re-try without a shared glx context
+ d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, 0, true);
+ }
+
+ // Get the basic surface format details
+ if (d->context)
+ d->format = qglx_surfaceFormatFromGLXFBConfig(x11->display(), config, d->context);
+
+ // Create a temporary window so that we can make the new context current
+ d->window = createDummyWindow(x11, config);
+ } else {
+ XVisualInfo *visualInfo = qglx_findVisualInfo(x11->display(), 0, &d->format);
+ if (!visualInfo)
+ qFatal("Could not initialize GLX");
+ d->context = glXCreateContext(x11->display(), visualInfo, d->shareContext, true);
+ if (!d->context && d->shareContext) {
+ // re-try without a shared glx context
+ d->shareContext = 0;
+ d->context = glXCreateContext(x11->display(), visualInfo, 0, true);
+ }
+
+ d->window = createDummyWindow(x11, visualInfo);
+ XFree(visualInfo);
+ }
+}
+
+QOffscreenX11GLXContext::~QOffscreenX11GLXContext()
+{
+ glXDestroyContext(d->x11->display(), d->context);
+ XDestroyWindow(d->x11->display(), d->window);
+}
+
+bool QOffscreenX11GLXContext::makeCurrent(QPlatformSurface *surface)
+{
+ QSize size = surface->surface()->size();
+
+ XResizeWindow(d->x11->display(), d->window, size.width(), size.height());
+ XSync(d->x11->display(), true);
+
+ if (glXMakeCurrent(d->x11->display(), d->window, d->context)) {
+ glViewport(0, 0, size.width(), size.height());
+ return true;
+ }
+
+ return false;
+}
+
+void QOffscreenX11GLXContext::doneCurrent()
+{
+ glXMakeCurrent(d->x11->display(), 0, 0);
+}
+
+void QOffscreenX11GLXContext::swapBuffers(QPlatformSurface *)
+{
+}
+
+void (*QOffscreenX11GLXContext::getProcAddress(const QByteArray &procName)) ()
+{
+ return (void (*)())glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.constData()));
+}
+
+QSurfaceFormat QOffscreenX11GLXContext::format() const
+{
+ return d->format;
+}
+
+bool QOffscreenX11GLXContext::isSharing() const
+{
+ return d->shareContext;
+}
+
+bool QOffscreenX11GLXContext::isValid() const
+{
+ return d->context && d->window;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
new file mode 100644
index 0000000000..9afa302b04
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOFFSCREENINTEGRATION_X11_H
+#define QOFFSCREENINTEGRATION_X11_H
+
+#include "qoffscreenintegration.h"
+
+#include <qglobal.h>
+#include <qscopedpointer.h>
+
+#include <qpa/qplatformopenglcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenX11Connection;
+class QOffscreenX11Info;
+
+class QOffscreenX11Integration : public QOffscreenIntegration
+{
+public:
+ bool hasCapability(QPlatformIntegration::Capability cap) const;
+
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+
+private:
+ mutable QScopedPointer<QOffscreenX11Connection> m_connection;
+};
+
+class QOffscreenX11Connection {
+public:
+ QOffscreenX11Connection();
+ ~QOffscreenX11Connection();
+
+ QOffscreenX11Info *x11Info();
+
+ void *display() const { return m_display; }
+ int screenNumber() const { return m_screenNumber; }
+
+private:
+ void *m_display;
+ int m_screenNumber;
+
+ QScopedPointer<QOffscreenX11Info> m_x11Info;
+};
+
+class QOffscreenX11GLXContextData;
+
+class QOffscreenX11GLXContext : public QPlatformOpenGLContext
+{
+public:
+ QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context);
+ ~QOffscreenX11GLXContext();
+
+ bool makeCurrent(QPlatformSurface *surface);
+ void doneCurrent();
+ void swapBuffers(QPlatformSurface *surface);
+ void (*getProcAddress(const QByteArray &procName)) ();
+
+ QSurfaceFormat format() const;
+ bool isSharing() const;
+ bool isValid() const;
+
+private:
+ QScopedPointer<QOffscreenX11GLXContextData> d;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
new file mode 100644
index 0000000000..702ef2300c
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoffscreenwindow.h"
+#include "qoffscreencommon.h"
+
+#include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <private/qwindow_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QOffscreenWindow::QOffscreenWindow(QWindow *window)
+ : QPlatformWindow(window)
+ , m_positionIncludesFrame(false)
+ , m_visible(false)
+ , m_pendingGeometryChangeOnShow(true)
+{
+ if (window->windowState() == Qt::WindowNoState)
+ setGeometry(window->geometry());
+ else
+ setWindowState(window->windowState());
+
+ QWindowSystemInterface::flushWindowSystemEvents();
+
+ static WId counter = 0;
+ m_winId = ++counter;
+
+ m_windowForWinIdHash[m_winId] = this;
+}
+
+QOffscreenWindow::~QOffscreenWindow()
+{
+ if (QOffscreenScreen::windowContainingCursor == this)
+ QOffscreenScreen::windowContainingCursor = 0;
+ m_windowForWinIdHash.remove(m_winId);
+}
+
+void QOffscreenWindow::setGeometry(const QRect &rect)
+{
+ if (window()->windowState() != Qt::WindowNoState)
+ return;
+
+ m_positionIncludesFrame = qt_window_private(window())->positionPolicy == QWindowPrivate::WindowFrameInclusive;
+
+ setFrameMarginsEnabled(true);
+ setGeometryImpl(rect);
+
+ m_normalGeometry = geometry();
+}
+
+void QOffscreenWindow::setGeometryImpl(const QRect &rect)
+{
+ QRect adjusted = rect;
+ if (adjusted.width() <= 0)
+ adjusted.setWidth(1);
+ if (adjusted.height() <= 0)
+ adjusted.setHeight(1);
+
+ if (m_positionIncludesFrame) {
+ adjusted.translate(m_margins.left(), m_margins.top());
+ } else {
+ // make sure we're not placed off-screen
+ if (adjusted.left() < m_margins.left())
+ adjusted.translate(m_margins.left(), 0);
+ if (adjusted.top() < m_margins.top())
+ adjusted.translate(0, m_margins.top());
+ }
+
+ QPlatformWindow::setGeometry(adjusted);
+
+ if (m_visible) {
+ QWindowSystemInterface::handleGeometryChange(window(), adjusted);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), adjusted.size()));
+ } else {
+ m_pendingGeometryChangeOnShow = true;
+ }
+}
+
+void QOffscreenWindow::setVisible(bool visible)
+{
+ if (visible == m_visible)
+ return;
+
+ if (visible) {
+ if (window()->type() != Qt::ToolTip)
+ QWindowSystemInterface::handleWindowActivated(window());
+
+ if (m_pendingGeometryChangeOnShow) {
+ m_pendingGeometryChangeOnShow = false;
+ QWindowSystemInterface::handleGeometryChange(window(), geometry());
+ }
+ }
+
+ if (visible) {
+ QRect rect(QPoint(), geometry().size());
+ QWindowSystemInterface::handleExposeEvent(window(), rect);
+ } else {
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion());
+ }
+
+ m_visible = visible;
+}
+
+void QOffscreenWindow::requestActivateWindow()
+{
+ if (m_visible)
+ QWindowSystemInterface::handleWindowActivated(window());
+}
+
+WId QOffscreenWindow::winId() const
+{
+ return m_winId;
+}
+
+QMargins QOffscreenWindow::frameMargins() const
+{
+ return m_margins;
+}
+
+void QOffscreenWindow::setFrameMarginsEnabled(bool enabled)
+{
+ if (enabled && !(window()->flags() & Qt::FramelessWindowHint))
+ m_margins = QMargins(2, 2, 2, 2);
+ else
+ m_margins = QMargins(0, 0, 0, 0);
+}
+
+void QOffscreenWindow::setWindowState(Qt::WindowState state)
+{
+ setFrameMarginsEnabled(state != Qt::WindowFullScreen);
+ m_positionIncludesFrame = false;
+
+ switch (state) {
+ case Qt::WindowFullScreen:
+ setGeometryImpl(screen()->geometry());
+ break;
+ case Qt::WindowMaximized:
+ setGeometryImpl(screen()->availableGeometry().adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom()));
+ break;
+ case Qt::WindowMinimized:
+ break;
+ case Qt::WindowNoState:
+ setGeometryImpl(m_normalGeometry);
+ break;
+ default:
+ break;
+ }
+
+ QWindowSystemInterface::handleWindowStateChanged(window(), state);
+}
+
+QOffscreenWindow *QOffscreenWindow::windowForWinId(WId id)
+{
+ return m_windowForWinIdHash.value(id, 0);
+}
+
+QHash<WId, QOffscreenWindow *> QOffscreenWindow::m_windowForWinIdHash;
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h
new file mode 100644
index 0000000000..cd1cf8e0aa
--- /dev/null
+++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOFFSCREENWINDOW_H
+#define QOFFSCREENWINDOW_H
+
+#include <qpa/qplatformbackingstore.h>
+#include <qpa/qplatformwindow.h>
+
+#include <qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenWindow : public QPlatformWindow
+{
+public:
+ QOffscreenWindow(QWindow *window);
+ ~QOffscreenWindow();
+
+ void setGeometry(const QRect &rect);
+ void setWindowState(Qt::WindowState state);
+
+ QMargins frameMargins() const;
+
+ void setVisible(bool visible);
+ void requestActivateWindow();
+
+ WId winId() const;
+
+ static QOffscreenWindow *windowForWinId(WId id);
+
+private:
+ void setFrameMarginsEnabled(bool enabled);
+ void setGeometryImpl(const QRect &rect);
+
+ QRect m_normalGeometry;
+ QMargins m_margins;
+ bool m_positionIncludesFrame;
+ bool m_visible;
+ bool m_pendingGeometryChangeOnShow;
+ WId m_winId;
+
+ static QHash<WId, QOffscreenWindow *> m_windowForWinIdHash;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 828867c3a7..173757568f 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
-SUBDIRS += minimal
+SUBDIRS += minimal offscreen
contains(QT_CONFIG, xcb) {
SUBDIRS += xcb
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 8367513fc5..203cdebda9 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -39,6 +39,7 @@ CONFIG(blackberry) {
#DEFINES += QQNXSCREEN_DEBUG
#DEFINES += QQNXVIRTUALKEYBOARD_DEBUG
#DEFINES += QQNXWINDOW_DEBUG
+#DEFINES += QQNXCURSOR_DEBUG
SOURCES = main.cpp \
@@ -54,7 +55,8 @@ SOURCES = main.cpp \
qqnxnavigatoreventhandler.cpp \
qqnxabstractnavigator.cpp \
qqnxabstractvirtualkeyboard.cpp \
- qqnxservices.cpp
+ qqnxservices.cpp \
+ qqnxcursor.cpp
HEADERS = main.h \
qqnxbuffer.h \
@@ -70,7 +72,8 @@ HEADERS = main.h \
qqnxnavigatoreventhandler.h \
qqnxabstractnavigator.h \
qqnxabstractvirtualkeyboard.h \
- qqnxservices.h
+ qqnxservices.h \
+ qqnxcursor.h
LIBS += -lscreen
diff --git a/src/plugins/platforms/qnx/qqnxcursor.cpp b/src/plugins/platforms/qnx/qqnxcursor.cpp
new file mode 100644
index 0000000000..4fdff666d7
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxcursor.cpp
@@ -0,0 +1,78 @@
+/***************************************************************************
+**
+** Copyright (C) 2011 - 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqnxcursor.h"
+
+#include <QtCore/QDebug>
+
+#ifdef QQNXCURSOR_DEBUG
+#define qCursorDebug qDebug
+#else
+#define qCursorDebug QT_NO_QDEBUG_MACRO
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QQnxCursor::QQnxCursor()
+{
+}
+
+#ifndef QT_NO_CURSOR
+void QQnxCursor::changeCursor(QCursor *windowCursor, QWindow *window)
+{
+ Q_UNUSED(windowCursor);
+ Q_UNUSED(window);
+}
+#endif
+
+void QQnxCursor::setPos(const QPoint &pos)
+{
+ qCursorDebug() << "QQnxCursor::setPos -" << pos;
+ m_pos = pos;
+}
+
+QPoint QQnxCursor::pos() const
+{
+ qCursorDebug() << "QQnxCursor::pos -" << m_pos;
+ return m_pos;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxcursor.h b/src/plugins/platforms/qnx/qqnxcursor.h
new file mode 100644
index 0000000000..5d6a8b2c30
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxcursor.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+**
+** Copyright (C) 2011 - 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQNXCURSOR_H
+#define QQNXCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQnxCursor : public QPlatformCursor
+{
+public:
+ QQnxCursor();
+
+#ifndef QT_NO_CURSOR
+ void changeCursor(QCursor *windowCursor, QWindow *window);
+#endif
+ void setPos(const QPoint &pos);
+
+ QPoint pos() const;
+
+private:
+ QPoint m_pos;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQNXCURSOR_H
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index 1e58f047ab..fc8b3bb167 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -41,6 +41,7 @@
#include "qqnxscreen.h"
#include "qqnxwindow.h"
+#include "qqnxcursor.h"
#include <QtCore/QThread>
#include <QtCore/QDebug>
@@ -110,7 +111,8 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
m_posted(false),
m_keyboardHeight(0),
m_nativeOrientation(Qt::PrimaryOrientation),
- m_platformContext(0)
+ m_platformContext(0),
+ m_cursor(new QQnxCursor())
{
qScreenDebug() << Q_FUNC_INFO;
// Cache initial orientation of this display
@@ -149,6 +151,8 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
QQnxScreen::~QQnxScreen()
{
qScreenDebug() << Q_FUNC_INFO;
+
+ delete m_cursor;
}
static int defaultDepth()
@@ -492,6 +496,11 @@ void QQnxScreen::onWindowPost(QQnxWindow *window)
}
}
+QPlatformCursor * QQnxScreen::cursor() const
+{
+ return m_cursor;
+}
+
void QQnxScreen::keyboardHeightChanged(int height)
{
if (height == m_keyboardHeight)
diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h
index 2851c13c52..39cd4159d1 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.h
+++ b/src/plugins/platforms/qnx/qqnxscreen.h
@@ -95,6 +95,8 @@ public:
QSharedPointer<QQnxRootWindow> rootWindow() const;
+ QPlatformCursor *cursor() const;
+
public Q_SLOTS:
void setRotation(int rotation);
void newWindowCreated(void *window);
@@ -130,6 +132,8 @@ private:
QList<QQnxWindow *> m_childWindows;
QList<screen_window_t> m_overlays;
+
+ QPlatformCursor *m_cursor;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index 4412bb34bd..2d3c7608bf 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -347,6 +347,8 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
qFatal("QQNX: failed to query event position, errno=%d", errno);
}
+ QCursor::setPos(pos[0], pos[1]);
+
// get window coordinates of touch
errno = 0;
int windowPos[2];
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
index 3ccc6212a9..8830d3023a 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -162,21 +162,10 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
}
}
- typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
-
#if defined(Q_OS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
// There is no user32.lib nor NotifyWinEvent for CE
return;
#else
- static PtrNotifyWinEvent ptrNotifyWinEvent = 0;
- static bool resolvedNWE = false;
- if (!resolvedNWE) {
- resolvedNWE = true;
- ptrNotifyWinEvent = (PtrNotifyWinEvent)QSystemLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent");
- }
- if (!ptrNotifyWinEvent)
- return;
-
// An event has to be associated with a window,
// so find the first parent that is a widget and that has a WId
QAccessibleInterface *iface = event->accessibleInterface();
@@ -213,7 +202,7 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
eventNum %= 50; //[0..49]
int eventId = - (eventNum - 1);
qAccessibleRecentSentEvents()->insert(eventId, qMakePair(QPointer<QObject>(event->object()), event->child()));
- ptrNotifyWinEvent(event->type(), hWnd, OBJID_CLIENT, eventId);
+ ::NotifyWinEvent(event->type(), hWnd, OBJID_CLIENT, eventId);
++eventNum;
}
#endif // Q_OS_WINCE
@@ -283,7 +272,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W
{
if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) {
/* For UI Automation */
- } else if ((DWORD)lParam == OBJID_CLIENT) {
+ } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) {
#if 1
// Ignoring all requests while starting up
// ### Maybe QPA takes care of this???
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
index af0bd65c80..5a6dc0c2e5 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
@@ -48,7 +48,6 @@
#include <oleacc.h>
-QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QWindowsAccessibility : public QPlatformAccessibility
@@ -69,6 +68,5 @@ public:
};
QT_END_NAMESPACE
-QT_END_HEADER
#endif // QWINDOWSACCESSIBILITY_H
diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h
index 8d59fbd7c6..3b2e9787a2 100644
--- a/src/plugins/platforms/windows/qtwindows_additional.h
+++ b/src/plugins/platforms/windows/qtwindows_additional.h
@@ -126,6 +126,10 @@ typedef struct tagUPDATELAYEREDWINDOWINFO {
// IME.
#define IMR_CONFIRMRECONVERTSTRING 0x0005
+#ifndef MAPVK_VK_TO_CHAR
+# define MAPVK_VK_TO_CHAR 2
+#endif
+
#endif // if defined(Q_CC_MINGW)
/* Touch is supported from Windows 7 onwards and data structures
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 99ef3aacf3..a6709dffb3 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -783,7 +783,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::CalculateSize:
- return false;
+ return QWindowsGeometryHint::handleCalculateSize(d->m_creationContext->customMargins, msg, result);
default:
break;
}
@@ -818,12 +818,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
return true;// maybe available on some SDKs revisit WM_NCCALCSIZE
case QtWindows::CalculateSize:
- // NCCALCSIZE_PARAMS structure if wParam==TRUE
- if (wParam && QWindowsContext::verboseWindows) {
- const NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(lParam);
- qDebug() << platformWindow->window() << *ncp;
- }
- break;
+ return QWindowsGeometryHint::handleCalculateSize(platformWindow->customMargins(), msg, result);
#endif
case QtWindows::ExposeEvent:
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 4dc9af61d8..5b2a3acbae 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -395,6 +395,19 @@ QWindowsWindowCursor QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
}
/*!
+ \brief Return cached pixmap cursor or create new one.
+*/
+
+QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c)
+{
+ const qint64 cacheKey = c.pixmap().cacheKey();
+ PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey);
+ if (it == m_pixmapCursorCache.end())
+ it = m_pixmapCursorCache.insert(cacheKey, QWindowsWindowCursor(c));
+ return it.value();
+}
+
+/*!
\brief Set a cursor on a window.
This is called frequently as the mouse moves over widgets in the window
@@ -406,11 +419,15 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
if (QWindowsContext::verboseWindows > 1)
qDebug() << __FUNCTION__ << cursorIn << window;
- if (!cursorIn || !window)
+ if (!window)
+ return;
+ if (!cursorIn) {
+ QWindowsWindow::baseWindowOf(window)->setCursor(QWindowsWindowCursor());
return;
+ }
const QWindowsWindowCursor wcursor =
cursorIn->shape() == Qt::BitmapCursor ?
- QWindowsWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape());
+ pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape());
if (wcursor.handle()) {
QWindowsWindow::baseWindowOf(window)->setCursor(wcursor);
} else {
@@ -449,6 +466,7 @@ void QWindowsCursor::setPos(const QPoint &pos)
class QWindowsWindowCursorData : public QSharedData
{
public:
+ QWindowsWindowCursorData() : m_cursor(Qt::ArrowCursor), m_handle(0) {}
explicit QWindowsWindowCursorData(const QCursor &c);
~QWindowsWindowCursorData();
@@ -464,7 +482,13 @@ QWindowsWindowCursorData::QWindowsWindowCursorData(const QCursor &c) :
QWindowsWindowCursorData::~QWindowsWindowCursorData()
{
- DestroyCursor(m_handle);
+ if (m_handle)
+ DestroyCursor(m_handle);
+}
+
+QWindowsWindowCursor::QWindowsWindowCursor() :
+ m_data(new QWindowsWindowCursorData)
+{
}
QWindowsWindowCursor::QWindowsWindowCursor(const QCursor &c) :
@@ -488,6 +512,11 @@ QWindowsWindowCursor & QWindowsWindowCursor::operator =(const QWindowsWindowCurs
return *this;
}
+bool QWindowsWindowCursor::isNull() const
+{
+ return m_data->m_handle == 0;
+}
+
QCursor QWindowsWindowCursor::cursor() const
{
return m_data->m_cursor;
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index b0256d4203..1e818bc9b8 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -55,11 +55,13 @@ class QWindowsWindowCursorData;
class QWindowsWindowCursor
{
public:
+ QWindowsWindowCursor();
explicit QWindowsWindowCursor(const QCursor &c);
~QWindowsWindowCursor();
QWindowsWindowCursor(const QWindowsWindowCursor &c);
QWindowsWindowCursor &operator=(const QWindowsWindowCursor &c);
+ bool isNull() const;
QCursor cursor() const;
HCURSOR handle() const;
@@ -81,11 +83,14 @@ public:
static QPoint mousePosition();
QWindowsWindowCursor standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
+ QWindowsWindowCursor pixmapWindowCursor(const QCursor &c);
private:
typedef QHash<Qt::CursorShape, QWindowsWindowCursor> StandardCursorCache;
+ typedef QHash<qint64, QWindowsWindowCursor> PixmapCursorCache;
StandardCursorCache m_standardCursorCache;
+ PixmapCursorCache m_pixmapCursorCache;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 74193c47a3..e9c0cccc14 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -58,6 +58,10 @@
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QSysInfo>
+#include <QtCore/QSharedData>
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
#include <QtCore/private/qsystemlibrary_p.h>
#include "qtwindows_additional.h"
@@ -387,6 +391,9 @@ void eatMouseMove()
Vista on) that mimick the behaviour of their QDialog
counterparts as close as possible.
+ Instances of derived classes are controlled by
+ QWindowsDialogHelperBase-derived classes.
+
A major difference is that there is only an exec(), which
is a modal, blocking call; there is no non-blocking show().
There 2 types of native dialogs:
@@ -401,6 +408,7 @@ void eatMouseMove()
like close() can be called on them from event handlers.
\endlist
+ \sa QWindowsDialogHelperBase
\internal
\ingroup qt-lighthouse-win
*/
@@ -411,7 +419,6 @@ class QWindowsNativeDialogBase : public QObject
public:
virtual void setWindowTitle(const QString &title) = 0;
virtual void exec(HWND owner = 0) = 0;
- virtual QPlatformDialogHelper::DialogCode result() const = 0;
signals:
void accepted();
@@ -432,12 +439,10 @@ protected:
The native dialog is created in setVisible_sys() since
then modality and the state of DontUseNativeDialog is known.
- Modal dialogs are then started via the platformNativeDialogModalHelp(),
- platformNativeDialogModalHelp() slots.
- Non-modal dialogs are shown using a separate thread should
- they support it.
+ Modal dialogs are then run by exec(). Non-modal dialogs are shown using a
+ separate thread started in show() should they support it.
- \sa QWindowsDialogThread
+ \sa QWindowsDialogThread, QWindowsNativeDialogBase
\internal
\ingroup qt-lighthouse-win
*/
@@ -445,17 +450,12 @@ protected:
template <class BaseClass>
QWindowsDialogHelperBase<BaseClass>::QWindowsDialogHelperBase() :
m_nativeDialog(0),
- m_ownerWindow(0)
+ m_ownerWindow(0),
+ m_timerId(0)
{
}
template <class BaseClass>
-QWindowsDialogHelperBase<BaseClass>::~QWindowsDialogHelperBase()
-{
- delete m_nativeDialog;
-}
-
-template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::nativeDialog() const
{
if (!m_nativeDialog) {
@@ -466,6 +466,19 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::nativeDialog() co
}
template <class BaseClass>
+void QWindowsDialogHelperBase<BaseClass>::deleteNativeDialog()
+{
+ delete m_nativeDialog;
+ m_nativeDialog = 0;
+}
+
+template <class BaseClass>
+void QWindowsDialogHelperBase<BaseClass>::timerEvent(QTimerEvent *)
+{
+ startDialogThread();
+}
+
+template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialog()
{
// Create dialog and apply common settings.
@@ -486,22 +499,18 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo
class QWindowsDialogThread : public QThread
{
public:
- QWindowsDialogThread(QWindowsNativeDialogBase *dialog,
- HWND owner = 0) :
- m_dialog(dialog), m_owner(owner) {}
-
+ QWindowsDialogThread(QPlatformDialogHelper *h) : m_helper(h) {}
void run();
private:
- QWindowsNativeDialogBase *m_dialog;
- const HWND m_owner;
+ QPlatformDialogHelper *m_helper;
};
void QWindowsDialogThread::run()
{
if (QWindowsContext::verboseDialogs)
qDebug(">%s" , __FUNCTION__);
- m_dialog->exec(m_owner);
+ m_helper->exec();
deleteLater();
if (QWindowsContext::verboseDialogs)
qDebug("<%s" , __FUNCTION__);
@@ -512,7 +521,7 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
Qt::WindowModality windowModality,
QWindow *parent)
{
- const bool modal = (windowModality == Qt::ApplicationModal);
+ const bool modal = (windowModality != Qt::NonModal);
if (parent) {
m_ownerWindow = QWindowsWindow::handleOf(parent);
} else {
@@ -521,18 +530,40 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
if (QWindowsContext::verboseDialogs)
qDebug("%s modal=%d native=%p parent=%p" ,
__FUNCTION__, modal, m_nativeDialog, m_ownerWindow);
- if (!modal && !supportsNonModalDialog())
+ if (!modal && !supportsNonModalDialog(parent))
return false; // Was it changed in-between?
if (!ensureNativeDialog())
return false;
- if (!modal) { // Modal dialogs are shown in separate slot.
- QWindowsDialogThread *thread = new QWindowsDialogThread(m_nativeDialog, m_ownerWindow);
- thread->start();
+ // Start a background thread to show the dialog. For modal dialogs,
+ // a subsequent call to exec() may follow. So, start an idle timer
+ // which will start the dialog thread. If exec() is then called, the
+ // timer is stopped and dialog->exec() is called directly.
+ if (modal) {
+ m_timerId = this->startTimer(0);
+ } else {
+ startDialogThread();
}
return true;
}
template <class BaseClass>
+void QWindowsDialogHelperBase<BaseClass>::startDialogThread()
+{
+ QWindowsDialogThread *thread = new QWindowsDialogThread(this);
+ thread->start();
+ stopTimer();
+}
+
+template <class BaseClass>
+void QWindowsDialogHelperBase<BaseClass>::stopTimer()
+{
+ if (m_timerId) {
+ this->killTimer(m_timerId);
+ m_timerId = 0;
+ }
+}
+
+template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::hide()
{
if (m_nativeDialog)
@@ -545,8 +576,11 @@ void QWindowsDialogHelperBase<BaseClass>::exec()
{
if (QWindowsContext::verboseDialogs)
qDebug("%s" , __FUNCTION__);
- if (QWindowsNativeDialogBase *nd = nativeDialog())
+ stopTimer();
+ if (QWindowsNativeDialogBase *nd = nativeDialog()) {
nd->exec(m_ownerWindow);
+ deleteNativeDialog();
+ }
}
static inline bool snapToDefaultButtonHint()
@@ -568,6 +602,101 @@ QVariant QWindowsDialogHelperBase<BaseClass>::styleHint(QPlatformDialogHelper::S
}
/*!
+ \class QWindowsFileDialogSharedData
+ \brief Explicitly shared file dialog parameters that are not in QFileDialogOptions.
+
+ Contain Parameters that need to be cached while the native dialog does not
+ exist yet. In addition, the data are updated by the change notifications of the
+ IFileDialogEvent, as querying them after the dialog has closed
+ does not reliably work. Provides thread-safe setters (for the non-modal case).
+
+ \internal
+ \ingroup qt-lighthouse-win
+ \sa QFileDialogOptions
+*/
+
+class QWindowsFileDialogSharedData
+{
+public:
+ QWindowsFileDialogSharedData() : m_data(new Data) {}
+ void fromOptions(const QSharedPointer<QFileDialogOptions> &o);
+
+ QString directory() const;
+ void setDirectory(const QString &);
+ QString selectedNameFilter() const;
+ void setSelectedNameFilter(const QString &);
+ QStringList selectedFiles() const;
+ void setSelectedFiles(const QStringList &);
+ QString selectedFile() const;
+
+private:
+ class Data : public QSharedData {
+ public:
+ QString directory;
+ QString selectedNameFilter;
+ QStringList selectedFiles;
+ QMutex mutex;
+ };
+ QExplicitlySharedDataPointer<Data> m_data;
+};
+
+inline QString QWindowsFileDialogSharedData::directory() const
+{
+ m_data->mutex.lock();
+ const QString result = m_data->directory;
+ m_data->mutex.unlock();
+ return result;
+}
+
+inline void QWindowsFileDialogSharedData::setDirectory(const QString &d)
+{
+ QMutexLocker (&m_data->mutex);
+ m_data->directory = d;
+}
+
+inline QString QWindowsFileDialogSharedData::selectedNameFilter() const
+{
+ m_data->mutex.lock();
+ const QString result = m_data->selectedNameFilter;
+ m_data->mutex.unlock();
+ return result;
+}
+
+inline void QWindowsFileDialogSharedData::setSelectedNameFilter(const QString &f)
+{
+ QMutexLocker (&m_data->mutex);
+ m_data->selectedNameFilter = f;
+}
+
+inline QStringList QWindowsFileDialogSharedData::selectedFiles() const
+{
+ m_data->mutex.lock();
+ const QStringList result = m_data->selectedFiles;
+ m_data->mutex.unlock();
+ return result;
+}
+
+inline QString QWindowsFileDialogSharedData::selectedFile() const
+{
+ const QStringList files = selectedFiles();
+ return files.isEmpty() ? QString() : files.front();
+}
+
+inline void QWindowsFileDialogSharedData::setSelectedFiles(const QStringList &f)
+{
+ QMutexLocker (&m_data->mutex);
+ m_data->selectedFiles = f;
+}
+
+inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFileDialogOptions> &o)
+{
+ QMutexLocker (&m_data->mutex);
+ m_data->directory = o->initialDirectory();
+ m_data->selectedFiles = o->initiallySelectedFiles();
+ m_data->selectedNameFilter = o->initiallySelectedNameFilter();
+}
+
+/*!
\class QWindowsNativeFileDialogEventHandler
\brief Listens to IFileDialog events and forwards them to QWindowsNativeFileDialogBase
@@ -609,7 +738,7 @@ public:
}
// IFileDialogEvents methods
- IFACEMETHODIMP OnFileOk(IFileDialog *) { return S_OK; }
+ IFACEMETHODIMP OnFileOk(IFileDialog *);
IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; }
IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *);
IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; }
@@ -658,15 +787,17 @@ class QWindowsNativeFileDialogBase : public QWindowsNativeDialogBase
public:
~QWindowsNativeFileDialogBase();
- inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am);
+ inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data);
virtual void setWindowTitle(const QString &title);
inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::FileDialogOptions options);
inline void setDirectory(const QString &directory);
+ inline void updateDirectory() { setDirectory(m_data.directory()); }
inline QString directory() const;
virtual void exec(HWND owner = 0);
inline void setNameFilters(const QStringList &f);
inline void selectNameFilter(const QString &filter);
+ inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); }
inline QString selectedNameFilter() const;
void selectFile(const QString &fileName) const;
bool hideFiltersDetails() const { return m_hideFiltersDetails; }
@@ -674,14 +805,16 @@ public:
void setDefaultSuffix(const QString &s);
inline void setLabelText(QFileDialogOptions::DialogLabel l, const QString &text);
- virtual QPlatformDialogHelper::DialogCode result() const
- { return fileResult(); }
- virtual QPlatformDialogHelper::DialogCode fileResult(QStringList *fileResult = 0) const = 0;
+ // Return the selected files for tracking in OnSelectionChanged().
virtual QStringList selectedFiles() const = 0;
+ // Return the result for tracking in OnFileOk(). Differs from selection for
+ // example by appended default suffixes, etc.
+ virtual QStringList dialogResult() const = 0;
inline void onFolderChange(IShellItem *);
inline void onSelectionChange();
inline void onTypeChange();
+ inline bool onFileOk();
signals:
void directoryEntered(const QString& directory);
@@ -692,23 +825,28 @@ public slots:
virtual void close() { m_fileDialog->Close(S_OK); }
protected:
- QWindowsNativeFileDialogBase();
+ explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data);
bool init(const CLSID &clsId, const IID &iid);
inline IFileDialog * fileDialog() const { return m_fileDialog; }
static QString itemPath(IShellItem *item);
static int itemPaths(IShellItemArray *items, QStringList *fileResult = 0);
static IShellItem *shellItem(const QString &path);
+ const QWindowsFileDialogSharedData &data() const { return m_data; }
+ QWindowsFileDialogSharedData &data() { return m_data; }
+
private:
IFileDialog *m_fileDialog;
IFileDialogEvents *m_dialogEvents;
DWORD m_cookie;
QStringList m_nameFilters;
bool m_hideFiltersDetails;
+ QWindowsFileDialogSharedData m_data;
};
-QWindowsNativeFileDialogBase::QWindowsNativeFileDialogBase() :
- m_fileDialog(0), m_dialogEvents(0), m_cookie(0), m_hideFiltersDetails(false)
+QWindowsNativeFileDialogBase::QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data) :
+ m_fileDialog(0), m_dialogEvents(0), m_cookie(0), m_hideFiltersDetails(false),
+ m_data(data)
{
}
@@ -764,15 +902,17 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QString &path)
return result;
}
#endif
- qErrnoWarning("%s: SHCreateItemFromParsingName()) failed", __FUNCTION__);
+ qErrnoWarning("%s: SHCreateItemFromParsingName(%s)) failed", __FUNCTION__, qPrintable(path));
return 0;
}
void QWindowsNativeFileDialogBase::setDirectory(const QString &directory)
{
- if (IShellItem *psi = QWindowsNativeFileDialogBase::shellItem(directory)) {
- m_fileDialog->SetFolder(psi);
- psi->Release();
+ if (!directory.isEmpty()) {
+ if (IShellItem *psi = QWindowsNativeFileDialogBase::shellItem(directory)) {
+ m_fileDialog->SetFolder(psi);
+ psi->Release();
+ }
}
}
@@ -983,14 +1123,16 @@ static int indexOfNameFilter(const QStringList &filters, const QString &needle)
void QWindowsNativeFileDialogBase::selectNameFilter(const QString &filter)
{
+ if (filter.isEmpty())
+ return;
const int index = indexOfNameFilter(m_nameFilters, filter);
- if (index >= 0) {
- m_fileDialog->SetFileTypeIndex(index + 1); // one-based.
- } else {
+ if (index < 0) {
qWarning("%s: Invalid parameter '%s' not found in '%s'.",
__FUNCTION__, qPrintable(filter),
qPrintable(m_nameFilters.join(QStringLiteral(", "))));
+ return;
}
+ m_fileDialog->SetFileTypeIndex(index + 1); // one-based.
}
QString QWindowsNativeFileDialogBase::selectedNameFilter() const
@@ -1008,6 +1150,7 @@ void QWindowsNativeFileDialogBase::onFolderChange(IShellItem *item)
{
if (item) {
const QString directory = QWindowsNativeFileDialogBase::itemPath(item);
+ m_data.setDirectory(directory);
emit directoryEntered(directory);
}
}
@@ -1015,13 +1158,23 @@ void QWindowsNativeFileDialogBase::onFolderChange(IShellItem *item)
void QWindowsNativeFileDialogBase::onSelectionChange()
{
const QStringList current = selectedFiles();
+ m_data.setSelectedFiles(current);
if (current.size() == 1)
emit currentChanged(current.front());
}
void QWindowsNativeFileDialogBase::onTypeChange()
{
- emit filterSelected(selectedNameFilter());
+ const QString filter = selectedNameFilter();
+ m_data.setSelectedNameFilter(filter);
+ emit filterSelected(filter);
+}
+
+bool QWindowsNativeFileDialogBase::onFileOk()
+{
+ // Store selected files as GetResults() returns invalid data after the dialog closes.
+ m_data.setSelectedFiles(dialogResult());
+ return true;
}
HRESULT QWindowsNativeFileDialogEventHandler::OnFolderChanging(IFileDialog *, IShellItem *item)
@@ -1042,6 +1195,11 @@ HRESULT QWindowsNativeFileDialogEventHandler::OnTypeChange(IFileDialog *)
return S_OK;
}
+HRESULT QWindowsNativeFileDialogEventHandler::OnFileOk(IFileDialog *)
+{
+ return m_nativeFileDialog->onFileOk() ? S_OK : S_FALSE;
+}
+
/*!
\class QWindowsNativeSaveFileDialog
\brief Windows native file save dialog wrapper around IFileSaveDialog.
@@ -1055,8 +1213,10 @@ HRESULT QWindowsNativeFileDialogEventHandler::OnTypeChange(IFileDialog *)
class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase
{
public:
- virtual QPlatformDialogHelper::DialogCode fileResult(QStringList *fileResult = 0) const;
+ explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data) :
+ QWindowsNativeFileDialogBase(data) {}
virtual QStringList selectedFiles() const;
+ virtual QStringList dialogResult() const;
};
// Append a suffix from the name filter "Foo files (*.foo;*.bar)"
@@ -1079,17 +1239,13 @@ static inline QString appendSuffix(const QString &fileName, const QString &filte
return fileName + QLatin1Char('.') + filter.mid(suffixPos, endPos - suffixPos);
}
-QPlatformDialogHelper::DialogCode QWindowsNativeSaveFileDialog::fileResult(QStringList *result /* = 0 */) const
+QStringList QWindowsNativeSaveFileDialog::dialogResult() const
{
- if (result)
- result->clear();
+ QStringList result;
IShellItem *item = 0;
- const HRESULT hr = fileDialog()->GetResult(&item);
- if (FAILED(hr) || !item)
- return QPlatformDialogHelper::Rejected;
- if (result)
- result->push_back(appendSuffix(QWindowsNativeFileDialogBase::itemPath(item), selectedNameFilter()));
- return QPlatformDialogHelper::Accepted;
+ if (SUCCEEDED(fileDialog()->GetResult(&item)) && item)
+ result.push_back(appendSuffix(QWindowsNativeFileDialogBase::itemPath(item), selectedNameFilter()));
+ return result;
}
QStringList QWindowsNativeSaveFileDialog::selectedFiles() const
@@ -1115,23 +1271,23 @@ QStringList QWindowsNativeSaveFileDialog::selectedFiles() const
class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase
{
public:
- virtual QPlatformDialogHelper::DialogCode fileResult(QStringList *fileResult = 0) const;
+ explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) :
+ QWindowsNativeFileDialogBase(data) {}
virtual QStringList selectedFiles() const;
+ virtual QStringList dialogResult() const;
private:
inline IFileOpenDialog *openFileDialog() const
{ return static_cast<IFileOpenDialog *>(fileDialog()); }
};
-QPlatformDialogHelper::DialogCode QWindowsNativeOpenFileDialog::fileResult(QStringList *result /* = 0 */) const
+QStringList QWindowsNativeOpenFileDialog::dialogResult() const
{
- if (result)
- result->clear();
+ QStringList result;
IShellItemArray *items = 0;
- const HRESULT hr = openFileDialog()->GetResults(&items);
- if (SUCCEEDED(hr) && items && QWindowsNativeFileDialogBase::itemPaths(items, result) > 0)
- return QPlatformDialogHelper::Accepted;
- return QPlatformDialogHelper::Rejected;
+ if (SUCCEEDED(openFileDialog()->GetResults(&items)) && items)
+ QWindowsNativeFileDialogBase::itemPaths(items, &result);
+ return result;
}
QStringList QWindowsNativeOpenFileDialog::selectedFiles() const
@@ -1150,17 +1306,18 @@ QStringList QWindowsNativeOpenFileDialog::selectedFiles() const
QFileDialog::AcceptMode.
*/
-QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOptions::AcceptMode am)
+QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOptions::AcceptMode am,
+ const QWindowsFileDialogSharedData &data)
{
QWindowsNativeFileDialogBase *result = 0;
if (am == QFileDialogOptions::AcceptOpen) {
- result = new QWindowsNativeOpenFileDialog;
+ result = new QWindowsNativeOpenFileDialog(data);
if (!result->init(CLSID_FileOpenDialog, IID_IFileOpenDialog)) {
delete result;
return 0;
}
} else {
- result = new QWindowsNativeSaveFileDialog;
+ result = new QWindowsNativeSaveFileDialog(data);
if (!result->init(CLSID_FileSaveDialog, IID_IFileSaveDialog)) {
delete result;
return 0;
@@ -1169,16 +1326,17 @@ QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOp
return result;
}
+static inline bool isQQuickWindow(const QWindow *w = 0)
+{
+ return w && w->inherits("QQuickWindow");
+}
+
/*!
\class QWindowsFileDialogHelper
\brief Helper for native Windows file dialogs
- Non-modal dialogs are disabled for now. The functionality is
- implemented in principle, however there are failures
- when querying the results from a dialog run in another thread.
- This could probably be fixed be calling CoInitializeEx() with
- the right parameters from each thread. The problem is though
- that calls to CoInitialize() occur in several places in Qt.
+ For Qt 4 compatibility, do not create native non-modal dialogs on widgets,
+ but only on QQuickWindows, which do not have a fallback.
\internal
\ingroup qt-lighthouse-win
@@ -1188,8 +1346,9 @@ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDi
{
public:
QWindowsFileDialogHelper() {}
- virtual bool supportsNonModalDialog() const { return false; }
-
+ // For Qt 4 compatibility, do not create native non-modal dialogs on widgets,
+ // but only on QQuickWindows, which do not have a fallback.
+ virtual bool supportsNonModalDialog(const QWindow *parent = 0) const { return isQQuickWindow(parent); }
virtual bool defaultNameFilterDisables() const
{ return true; }
virtual void setDirectory(const QString &directory);
@@ -1205,11 +1364,14 @@ private:
virtual QWindowsNativeDialogBase *createNativeDialog();
inline QWindowsNativeFileDialogBase *nativeFileDialog() const
{ return static_cast<QWindowsNativeFileDialogBase *>(nativeDialog()); }
+
+ // Cache for the case no native dialog is created.
+ QWindowsFileDialogSharedData m_data;
};
QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
{
- QWindowsNativeFileDialogBase *result = QWindowsNativeFileDialogBase::create(options()->acceptMode());
+ QWindowsNativeFileDialogBase *result = QWindowsNativeFileDialogBase::create(options()->acceptMode(), m_data);
if (!result)
return 0;
QObject::connect(result, SIGNAL(accepted()), this, SIGNAL(accept()));
@@ -1223,6 +1385,7 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
// Apply settings.
const QSharedPointer<QFileDialogOptions> &opts = options();
+ m_data.fromOptions(opts);
result->setWindowTitle(opts->windowTitle());
result->setMode(opts->fileMode(), opts->options());
result->setHideFiltersDetails(opts->testOption(QFileDialogOptions::HideNameFilterDetails));
@@ -1233,18 +1396,14 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
result->setLabelText(QFileDialogOptions::FileName, opts->labelText(QFileDialogOptions::FileName));
if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
result->setLabelText(QFileDialogOptions::Accept, opts->labelText(QFileDialogOptions::Accept));
- const QString initialDirectory = opts->initialDirectory();
- if (!initialDirectory.isEmpty())
- result->setDirectory(initialDirectory);
+ result->updateDirectory();
+ result->updateSelectedNameFilter();
const QStringList initialSelection = opts->initiallySelectedFiles();
if (initialSelection.size() > 0) {
QFileInfo info(initialSelection.front());
if (!info.isDir())
result->selectFile(info.fileName());
}
- const QString initialNameFilter = opts->initiallySelectedNameFilter();
- if (!initialNameFilter.isEmpty())
- result->selectNameFilter(initialNameFilter);
const QString defaultSuffix = opts->defaultSuffix();
if (!defaultSuffix.isEmpty())
result->setDefaultSuffix(defaultSuffix);
@@ -1256,15 +1415,14 @@ void QWindowsFileDialogHelper::setDirectory(const QString &directory)
if (QWindowsContext::verboseDialogs)
qDebug("%s %s" , __FUNCTION__, qPrintable(directory));
- if (QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- nfd->setDirectory(directory);
+ m_data.setDirectory(directory);
+ if (hasNativeDialog())
+ nativeFileDialog()->updateDirectory();
}
QString QWindowsFileDialogHelper::directory() const
{
- if (const QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- return nfd->directory();
- return QString();
+ return m_data.directory();
}
void QWindowsFileDialogHelper::selectFile(const QString &fileName)
@@ -1278,13 +1436,7 @@ void QWindowsFileDialogHelper::selectFile(const QString &fileName)
QStringList QWindowsFileDialogHelper::selectedFiles() const
{
- QStringList files;
- if (const QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- nfd->fileResult(&files);
- if (QWindowsContext::verboseDialogs)
- qDebug("%s files='%s'" , __FUNCTION__,
- qPrintable(files.join(QStringLiteral(", "))));
- return files;
+ return m_data.selectedFiles();
}
void QWindowsFileDialogHelper::setFilter()
@@ -1303,15 +1455,14 @@ void QWindowsFileDialogHelper::setNameFilters(const QStringList &filters)
void QWindowsFileDialogHelper::selectNameFilter(const QString &filter)
{
- if (QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- nfd->selectNameFilter(filter);
+ m_data.setSelectedNameFilter(filter);
+ if (hasNativeDialog())
+ nativeFileDialog()->updateSelectedNameFilter();
}
QString QWindowsFileDialogHelper::selectedNameFilter() const
{
- if (const QWindowsNativeFileDialogBase *nfd = nativeFileDialog())
- return nfd->selectedNameFilter();
- return QString();
+ return m_data.selectedNameFilter();
}
#ifndef Q_OS_WINCE
@@ -1335,20 +1486,12 @@ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase
public:
typedef QSharedPointer<QFileDialogOptions> OptionsPtr;
- static QWindowsXpNativeFileDialog *create(const OptionsPtr &options);
+ static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
virtual void setWindowTitle(const QString &t) { m_title = t; }
virtual void exec(HWND owner = 0);
virtual QPlatformDialogHelper::DialogCode result() const { return m_result; }
- void setDirectory(const QString &d) { m_directory = d; }
- QString directory() const { return m_directory; }
- void selectFile(const QString &f) { m_initialFile = f; }
- QStringList selectedFiles() const { return m_selectedFiles; }
- void setNameFilters(const QStringList &n) { m_nameFilters = n; }
- void selectNameFilter(const QString &f);
- QString selectedNameFilter() const { return m_selectedNameFilter; }
-
int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam);
public slots:
@@ -1358,19 +1501,15 @@ private:
typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW);
typedef BOOL (APIENTRY *PtrGetSaveFileNameW)(LPOPENFILENAMEW);
- explicit QWindowsXpNativeFileDialog(const OptionsPtr &options);
+ explicit QWindowsXpNativeFileDialog(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
void populateOpenFileName(OPENFILENAME *ofn, HWND owner) const;
QStringList execExistingDir(HWND owner);
QStringList execFileNames(HWND owner, int *selectedFilterIndex) const;
const OptionsPtr m_options;
QString m_title;
- QString m_directory;
- QString m_initialFile;
- QStringList m_selectedFiles;
- QString m_selectedNameFilter;
- QStringList m_nameFilters;
QPlatformDialogHelper::DialogCode m_result;
+ QWindowsFileDialogSharedData m_data;
static PtrGetOpenFileNameW m_getOpenFileNameW;
static PtrGetSaveFileNameW m_getSaveFileNameW;
@@ -1379,7 +1518,7 @@ private:
QWindowsXpNativeFileDialog::PtrGetOpenFileNameW QWindowsXpNativeFileDialog::m_getOpenFileNameW = 0;
QWindowsXpNativeFileDialog::PtrGetSaveFileNameW QWindowsXpNativeFileDialog::m_getSaveFileNameW = 0;
-QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr &options)
+QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data)
{
// GetOpenFileNameW() GetSaveFileName() are resolved
// dynamically as not to create a dependency on Comdlg32, which
@@ -1390,51 +1529,33 @@ QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr
m_getSaveFileNameW = (PtrGetSaveFileNameW)(library.resolve("GetSaveFileNameW"));
}
if (m_getOpenFileNameW && m_getSaveFileNameW)
- return new QWindowsXpNativeFileDialog(options);
+ return new QWindowsXpNativeFileDialog(options, data);
return 0;
}
-QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options) :
- m_options(options), m_result(QPlatformDialogHelper::Rejected)
+QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options,
+ const QWindowsFileDialogSharedData &data) :
+ m_options(options), m_result(QPlatformDialogHelper::Rejected), m_data(data)
{
- const QStringList nameFilters = m_options->nameFilters();
- if (!nameFilters.isEmpty())
- setNameFilters(nameFilters);
- const QString initialDirectory = m_options->initialDirectory();
- if (!initialDirectory.isEmpty())
- setDirectory(initialDirectory);
- const QString initialNameFilter = m_options->initiallySelectedNameFilter();
- if (!initialNameFilter.isEmpty())
- selectNameFilter(initialNameFilter);
- const QStringList selectedFiles = m_options->initiallySelectedFiles();
- if (!selectedFiles.isEmpty())
- selectFile(selectedFiles.front());
setWindowTitle(m_options->windowTitle());
}
-void QWindowsXpNativeFileDialog::selectNameFilter(const QString &f)
-{
- const int index = indexOfNameFilter(m_nameFilters, f);
- if (index >= 0)
- m_selectedNameFilter = m_nameFilters.at(index);
-}
-
void QWindowsXpNativeFileDialog::exec(HWND owner)
{
int selectedFilterIndex = -1;
- m_selectedFiles = m_options->fileMode() == QFileDialogOptions::DirectoryOnly ?
+ const QStringList selectedFiles =
+ m_options->fileMode() == QFileDialogOptions::DirectoryOnly ?
execExistingDir(owner) : execFileNames(owner, &selectedFilterIndex);
+ m_data.setSelectedFiles(selectedFiles);
QWindowsDialogs::eatMouseMove();
- if (m_selectedFiles.isEmpty()) {
+ if (selectedFiles.isEmpty()) {
m_result = QPlatformDialogHelper::Rejected;
emit rejected();
} else {
- if (selectedFilterIndex >= 0 && selectedFilterIndex < m_nameFilters.size()) {
- m_selectedNameFilter = m_nameFilters.at(selectedFilterIndex);
- } else {
- m_selectedNameFilter.clear();
- }
- m_directory = QFileInfo(m_selectedFiles.front()).absolutePath();
+ const QStringList nameFilters = m_options->nameFilters();
+ if (selectedFilterIndex >= 0 && selectedFilterIndex < nameFilters.size())
+ m_data.setSelectedNameFilter(nameFilters.at(selectedFilterIndex));
+ m_data.setDirectory(QFileInfo(selectedFiles.front()).absolutePath());
m_result = QPlatformDialogHelper::Accepted;
emit accepted();
}
@@ -1458,9 +1579,11 @@ typedef PIDLIST_ABSOLUTE qt_LpItemIdList;
int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
{
switch (uMsg) {
- case BFFM_INITIALIZED:
- if (!m_initialFile.isEmpty())
- SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(m_initialFile.utf16()));
+ case BFFM_INITIALIZED: {
+ const QString initialFile = m_data.selectedFile();
+ if (!initialFile.isEmpty())
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initialFile.utf16()));
+ }
break;
case BFFM_SELCHANGED: {
wchar_t path[MAX_PATH];
@@ -1532,7 +1655,7 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
*ptr++ = 0;
}
*ptr = 0;
- const int nameFilterIndex = indexOfNameFilter(m_nameFilters, m_selectedNameFilter);
+ const int nameFilterIndex = indexOfNameFilter(m_options->nameFilters(), m_data.selectedNameFilter());
if (nameFilterIndex >= 0)
ofn->nFilterIndex = nameFilterIndex + 1; // 1..n based.
// lpstrFile receives the initial selection and is the buffer
@@ -1540,10 +1663,10 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
// will not show.
ofn->nMaxFile = 65535;
const QString initiallySelectedFile =
- QDir::toNativeSeparators(m_initialFile).remove(QLatin1Char('<')).
+ QDir::toNativeSeparators(m_data.selectedFile()).remove(QLatin1Char('<')).
remove(QLatin1Char('>')).remove(QLatin1Char('"')).remove(QLatin1Char('|'));
ofn->lpstrFile = qStringToWCharArray(initiallySelectedFile, ofn->nMaxFile);
- ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_directory));
+ ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_data.directory()));
ofn->lpstrTitle = (wchar_t*)m_title.utf16();
// Determine lpstrDefExt. Note that the current MSDN docs document this
// member wrong. It should rather be documented as "the default extension
@@ -1612,8 +1735,7 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFile
{
public:
QWindowsXpFileDialogHelper() {}
- virtual bool supportsNonModalDialog() const { return false; }
-
+ virtual bool supportsNonModalDialog(const QWindow *parent = 0) const { return isQQuickWindow(parent); }
virtual bool defaultNameFilterDisables() const
{ return true; }
virtual void setDirectory(const QString &directory);
@@ -1629,11 +1751,14 @@ private:
virtual QWindowsNativeDialogBase *createNativeDialog();
inline QWindowsXpNativeFileDialog *nativeFileDialog() const
{ return static_cast<QWindowsXpNativeFileDialog *>(nativeDialog()); }
+
+ QWindowsFileDialogSharedData m_data;
};
QWindowsNativeDialogBase *QWindowsXpFileDialogHelper::createNativeDialog()
{
- if (QWindowsNativeDialogBase *result = QWindowsXpNativeFileDialog::create(options())) {
+ m_data.fromOptions(options());
+ if (QWindowsXpNativeFileDialog *result = QWindowsXpNativeFileDialog::create(options(), m_data)) {
QObject::connect(result, SIGNAL(accepted()), this, SIGNAL(accept()));
QObject::connect(result, SIGNAL(rejected()), this, SIGNAL(reject()));
return result;
@@ -1643,47 +1768,37 @@ QWindowsNativeDialogBase *QWindowsXpFileDialogHelper::createNativeDialog()
void QWindowsXpFileDialogHelper::setDirectory(const QString &directory)
{
- if (QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- nfd->setDirectory(directory);
+ m_data.setDirectory(directory); // Dialog cannot be updated at run-time.
}
QString QWindowsXpFileDialogHelper::directory() const
{
- if (const QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- return nfd->directory();
- return QString();
+ return m_data.directory();
}
void QWindowsXpFileDialogHelper::selectFile(const QString &filename)
{
- if (QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- nfd->selectFile(filename);
+ m_data.setSelectedFiles(QStringList(filename)); // Dialog cannot be updated at run-time.
}
QStringList QWindowsXpFileDialogHelper::selectedFiles() const
{
- if (const QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- return nfd->selectedFiles();
- return QStringList();
+ return m_data.selectedFiles();
}
-void QWindowsXpFileDialogHelper::setNameFilters(const QStringList &n)
+void QWindowsXpFileDialogHelper::setNameFilters(const QStringList &)
{
- if (QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- nfd->setNameFilters(n);
+ // Dialog cannot be updated at run-time.
}
void QWindowsXpFileDialogHelper::selectNameFilter(const QString &f)
{
- if (QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- nfd->selectNameFilter(f);
+ m_data.setSelectedNameFilter(f); // Dialog cannot be updated at run-time.
}
QString QWindowsXpFileDialogHelper::selectedNameFilter() const
{
- if (const QWindowsXpNativeFileDialog *nfd = nativeFileDialog())
- return nfd->selectedNameFilter();
- return QString();
+ return m_data.selectedNameFilter();
}
#endif // Q_OS_WINCE
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 07f105cb35..7884f398f3 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -65,6 +65,7 @@ template <class BaseClass>
class QWindowsDialogHelperBase : public BaseClass
{
public:
+ ~QWindowsDialogHelperBase() { deleteNativeDialog(); }
virtual void exec();
virtual bool show(Qt::WindowFlags windowFlags,
@@ -73,19 +74,24 @@ public:
virtual void hide();
virtual QVariant styleHint(QPlatformDialogHelper::StyleHint) const;
- virtual bool supportsNonModalDialog() const { return true; }
+ virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
protected:
QWindowsDialogHelperBase();
- ~QWindowsDialogHelperBase();
QWindowsNativeDialogBase *nativeDialog() const;
+ inline bool hasNativeDialog() const { return m_nativeDialog; }
+ void deleteNativeDialog();
+ void timerEvent(QTimerEvent *);
private:
virtual QWindowsNativeDialogBase *createNativeDialog() = 0;
inline QWindowsNativeDialogBase *ensureNativeDialog();
+ inline void startDialogThread();
+ inline void stopTimer();
QWindowsNativeDialogBase *m_nativeDialog;
HWND m_ownerWindow;
+ int m_timerId;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 1286f5c106..fedda750d9 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -304,10 +304,10 @@ private:
class DragCursorHandle {
Q_DISABLE_COPY(DragCursorHandle)
public:
- DragCursorHandle(HCURSOR c, quint64 k) : cursor(c), cacheKey(k) {}
+ DragCursorHandle(HCURSOR c, qint64 k) : cursor(c), cacheKey(k) {}
~DragCursorHandle() { DestroyCursor(cursor); }
HCURSOR cursor;
- quint64 cacheKey;
+ qint64 cacheKey;
};
typedef QMap <Qt::DropAction, QSharedPointer<DragCursorHandle> > ActionCursorMap;
@@ -490,7 +490,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
qDebug("%s dwEffect=%lu, action=%d", __FUNCTION__, dwEffect, action);
QSharedPointer<DragCursorHandle> cursorHandler = m_cursors.value(action);
- quint64 currentCacheKey = m_drag->currentDrag()->dragCursor(action).cacheKey();
+ qint64 currentCacheKey = m_drag->currentDrag()->dragCursor(action).cacheKey();
if (cursorHandler.isNull() || currentCacheKey != cursorHandler->cacheKey)
createCursors();
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index b4fb19e8e8..c1c906523f 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -1160,9 +1160,7 @@ QWindowsFontDatabase::~QWindowsFontDatabase()
removeApplicationFonts();
}
-QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef,
- QUnicodeTables::Script script,
- void *handle)
+QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle)
{
QFontEngine *fe = QWindowsFontDatabase::createEngine(script, fontDef,
0, QWindowsContext::instance()->defaultDPI(), false,
@@ -1215,7 +1213,7 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal
request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch;
request.hintingPreference = hintingPreference;
- fontEngine = QWindowsFontDatabase::createEngine(QUnicodeTables::Common, request, 0,
+ fontEngine = QWindowsFontDatabase::createEngine(QChar::Script_Common, request, 0,
QWindowsContext::instance()->defaultDPI(), false, QStringList(),
sharedFontData());
@@ -1529,8 +1527,8 @@ HFONT QWindowsFontDatabase::systemFont()
static inline bool scriptRequiresOpenType(int script)
{
- return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
- || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko);
+ return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
+ || script == QChar::Script_Khmer || script == QChar::Script_Nko);
}
static const char *other_tryFonts[] = {
@@ -1715,7 +1713,7 @@ static QStringList extraTryFontsForFamily(const QString& family)
return result;
}
-QStringList QWindowsFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
+QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script);
if (!result.isEmpty())
@@ -1917,7 +1915,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ
directWriteFont->Release();
#endif
- if (script == QUnicodeTables::Common
+ if (script == QChar::Script_Common
&& !(request.styleStrategy & QFont::NoFontMerging)) {
QStringList extraFonts = extraTryFontsForFamily(request.family);
if (extraFonts.size()) {
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index c14d6027c2..b9e6c38eaa 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -78,9 +78,9 @@ public:
~QWindowsFontDatabase();
virtual void populateFontDatabase();
- virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle);
+ virtual QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
- virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const;
+ virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
virtual void releaseHandle(void *handle);
virtual QString fontDir() const;
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 406dc636b8..c2ddb912f1 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -362,7 +362,7 @@ void QWindowsFontDatabaseFT::populate(const QString &family)
ReleaseDC(0, dummy);
}
-QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle)
+QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle)
{
QFontEngine *fe = QBasicFontDatabase::fontEngine(fontDef, script, handle);
if (QWindowsContext::verboseFonts)
@@ -430,9 +430,9 @@ static const char *kr_tryFonts[] = {
static const char **tryFonts = 0;
-QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
+QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
- if(script == QUnicodeTables::Common) {
+ if (script == QChar::Script_Common) {
// && !(request.styleStrategy & QFont::NoFontMerging)) {
QFontDatabase db;
if (!db.writingSystems(family).contains(QFontDatabase::Symbol)) {
@@ -518,8 +518,8 @@ HFONT QWindowsFontDatabaseFT::systemFont()
static inline bool scriptRequiresOpenType(int script)
{
- return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
- || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko);
+ return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
+ || script == QChar::Script_Khmer || script == QChar::Script_Nko);
}
static inline int verticalDPI()
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 2ce429d012..d3cbc0210a 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -52,10 +52,10 @@ class QWindowsFontDatabaseFT : public QBasicFontDatabase
{
public:
void populateFontDatabase();
- QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
- QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
virtual QString fontDir() const;
virtual QFont defaultFont() const;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 7fcd9814bd..c402f00453 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -66,7 +66,6 @@
#include <QtCore/QThreadStorage>
#include <QtCore/private/qsystemlibrary_p.h>
-#include <QtCore/private/qunicodetables_p.h>
#include <QtCore/QDebug>
#include <limits.h>
@@ -155,9 +154,20 @@ static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc)
return otm;
}
+bool QWindowsFontEngine::hasCFFTable() const
+{
+ HDC hdc = m_fontEngineData->hdc;
+ SelectObject(hdc, hfont);
+ return GetFontData(hdc, MAKE_TAG('C', 'F', 'F', ' '), 0, 0, 0) != GDI_ERROR;
+}
+
void QWindowsFontEngine::getCMap()
{
ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE);
+
+ // TMPF_TRUETYPE is not set for fonts with CFF tables
+ cffTable = !ttf && hasCFFTable();
+
HDC hdc = m_fontEngineData->hdc;
SelectObject(hdc, hfont);
bool symb = false;
@@ -1041,7 +1051,7 @@ void QWindowsFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gly
bool QWindowsFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
{
- if (!ttf)
+ if (!ttf && !cffTable)
return false;
HDC hdc = m_fontEngineData->hdc;
SelectObject(hdc, hfont);
@@ -1216,13 +1226,13 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra
{
HFONT font = hfont;
- int contrast;
+ UINT contrast;
SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0);
SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) 1000, 0);
int margin = glyphMargin(QFontEngineGlyphCache::Raster_RGBMask);
QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32);
- SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) contrast, 0);
+ SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) quintptr(contrast), 0);
if (mask == 0)
return QImage();
@@ -1258,7 +1268,7 @@ QFontEngine *QWindowsFontEngine::cloneWithSize(qreal pixelSize) const
request.styleStrategy |= QFont::NoFontMerging;
QFontEngine *fontEngine =
- QWindowsFontDatabase::createEngine(QUnicodeTables::Common, request, 0,
+ QWindowsFontDatabase::createEngine(QChar::Script_Common, request, 0,
QWindowsContext::instance()->defaultDPI(),
false,
QStringList(), m_fontEngineData);
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index a23db2f235..2bf6ead503 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -145,6 +145,7 @@ public:
private:
QWindowsNativeImage *drawGDIGlyph(HFONT font, glyph_t, int margin, const QTransform &xform,
QImage::Format mask_format);
+ bool hasCFFTable() const;
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
@@ -155,6 +156,7 @@ private:
uint stockFont : 1;
uint ttf : 1;
uint hasOutline : 1;
+ uint cffTable : 1;
TEXTMETRIC tm;
int lw;
const unsigned char *cmap;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index 183acedfc8..5b6ce695d8 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -376,10 +376,12 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
if (SUCCEEDED(hr)) {
for (int i=0; i<glyphs->numGlyphs; ++i) {
glyphs->advances_x[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth);
- if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- glyphs->advances_x[i] = glyphs->advances_x[i].round();
glyphs->advances_y[i] = 0;
}
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ for (int i = 0; i < glyphs->numGlyphs; ++i)
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ }
} else {
qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
}
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index da4519199f..30e0478e64 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -77,6 +77,7 @@
#include <QtCore/private/qeventdispatcher_win_p.h>
#include <QtCore/QDebug>
+#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
@@ -114,6 +115,11 @@ public:
bool asyncExpose() const;
void setAsyncExpose(bool value);
+
+ QVariantMap windowProperties(QPlatformWindow *window) const;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name) const;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
+ void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
};
void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
@@ -150,6 +156,37 @@ void *QWindowsNativeInterface::nativeResourceForBackingStore(const QByteArray &r
return 0;
}
+static const char customMarginPropertyC[] = "WindowsCustomMargins";
+
+QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
+{
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window);
+ if (name == QLatin1String(customMarginPropertyC))
+ return qVariantFromValue(platformWindow->customMargins());
+ return QVariant();
+}
+
+QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const
+{
+ const QVariant result = windowProperty(window, name);
+ return result.isValid() ? result : defaultValue;
+}
+
+void QWindowsNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
+{
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window);
+ if (name == QLatin1String(customMarginPropertyC))
+ platformWindow->setCustomMargins(qvariant_cast<QMargins>(value));
+}
+
+QVariantMap QWindowsNativeInterface::windowProperties(QPlatformWindow *window) const
+{
+ QVariantMap result;
+ const QString customMarginProperty = QLatin1String(customMarginPropertyC);
+ result.insert(customMarginProperty, windowProperty(window, customMarginProperty));
+ return result;
+}
+
#ifndef QT_NO_OPENGL
void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
{
@@ -372,6 +409,11 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindow::WindowData requested;
requested.flags = window->flags();
requested.geometry = window->geometry();
+ // Apply custom margins (see QWindowsWindow::setCustomMargins())).
+ const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
+ if (customMarginsV.isValid())
+ requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
+
const QWindowsWindow::WindowData obtained
= QWindowsWindow::WindowData::create(window, requested, window->title());
if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 56deb27442..924d604641 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -856,9 +856,15 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
if (isNumpad && (nModifiers & AltAny)) {
code = winceKeyBend(msg.wParam);
} else if (!isDeadKey) {
- unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
- GetKeyboardState(kbdBuffer);
- code = toKeyOrUnicode(msg.wParam, scancode, kbdBuffer);
+ // QTBUG-8764, QTBUG-10032
+ // Can't call toKeyOrUnicode because that would call ToUnicode, and, if a dead key
+ // is pressed at the moment, Windows would NOT use it to compose a character for the next
+ // WM_CHAR event.
+
+ // Instead, use MapVirtualKey, which will provide adequate values.
+ code = MapVirtualKey(msg.wParam, MAPVK_VK_TO_CHAR);
+ if (code < 0x20 || code == 0x7f) // The same logic as in toKeyOrUnicode()
+ code = winceKeyBend(msg.wParam);
}
// Invert state logic:
@@ -1120,7 +1126,7 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
}
result << int(baseKey + keyMods); // The base key is _always_ valid, of course
- for (int i = 1; i < NumMods; ++i) {
+ for (size_t i = 1; i < NumMods; ++i) {
Qt::KeyboardModifiers neededMods = ModsTbl[i];
quint32 key = kbItem.qtKey[i];
if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 7fb32d3513..a8bacd631d 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -703,14 +703,14 @@ QWindowsMimeURI::QWindowsMimeURI()
bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
- if (getCf(formatetc) == CF_HDROP) {
+ if (mimeData->hasUrls() && 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(QStringLiteral("text/uri-list"));
+ return (getCf(formatetc) == CF_INETURL_W || getCf(formatetc) == CF_INETURL) && mimeData->hasUrls();
}
bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index e1f4f4b143..dd16ea1c6f 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -49,6 +49,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
+#include <QtGui/QWindow>
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
@@ -236,6 +237,9 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
if (QWindowsContext::verboseEvents)
qDebug() << "Automatic mouse capture " << window;
+ // Implement "Click to focus" for native child windows.
+ if (!window->isTopLevel() && QGuiApplication::focusWindow() != window)
+ window->requestActivate();
} else if (platformWindow->hasMouseCapture()
&& platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
&& (msg.message == WM_LBUTTONUP || msg.message == WM_MBUTTONUP
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index bcae2e0816..250fea56b1 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -44,6 +44,7 @@
#include <QtCore/QUrl>
#include <QtCore/QDebug>
+#include <QtCore/QDir>
#include <shlobj.h>
#ifndef Q_OS_WINCE
@@ -57,7 +58,8 @@ enum { debug = 0 };
static inline bool shellExecute(const QString &file)
{
#ifndef Q_OS_WINCE
- const quintptr result = (quintptr)ShellExecute(0, 0, (wchar_t*)file.utf16(), 0, 0, SW_SHOWNORMAL);
+ const QString nativeFilePath = QDir::toNativeSeparators(file);
+ const quintptr result = (quintptr)ShellExecute(0, 0, (wchar_t*)nativeFilePath.utf16(), 0, 0, SW_SHOWNORMAL);
// ShellExecute returns a value greater than 32 if successful
if (result <= 32) {
qWarning("ShellExecute '%s' failed (error %s).", qPrintable(file), qPrintable(QString::number(result)));
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 07dc668b3f..d565420f4f 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -296,7 +296,7 @@ struct WindowCreationData
tool(false), embedded(false), hasAlpha(false) {}
void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
- inline WindowData create(const QWindow *w, const QRect &geometry, QString title) const;
+ inline WindowData create(const QWindow *w, const WindowData &data, QString title) const;
inline void applyWindowFlags(HWND hwnd) const;
void initialize(HWND h, bool frameChange, qreal opacityLevel) const;
@@ -448,7 +448,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
QWindowsWindow::WindowData
- WindowCreationData::create(const QWindow *w, const QRect &geometry, QString title) const
+ WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const
{
typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr;
@@ -474,24 +474,25 @@ QWindowsWindow::WindowData
const wchar_t *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
const wchar_t *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
- // Capture events before CreateWindowEx() returns.
- const QWindowCreationContextPtr context(new QWindowCreationContext(w, geometry, style, exStyle));
+ // Capture events before CreateWindowEx() returns. The context is cleared in
+ // the QWindowsWindow constructor.
+ const QWindowCreationContextPtr context(new QWindowCreationContext(w, data.geometry, data.customMargins, style, exStyle));
QWindowsContext::instance()->setWindowCreationContext(context);
if (QWindowsContext::verboseWindows)
qDebug().nospace()
<< "CreateWindowEx: " << w << *this
<< " class=" <<windowClassName << " title=" << title
- << "\nrequested: " << geometry << ": "
+ << "\nrequested: " << data.geometry << ": "
<< context->frameWidth << 'x' << context->frameHeight
- << '+' << context->frameX << '+' << context->frameY;
+ << '+' << context->frameX << '+' << context->frameY
+ << " custom margins: " << context->customMargins;
result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
style,
context->frameX, context->frameY,
context->frameWidth, context->frameHeight,
parentHandle, NULL, appinst, NULL);
- QWindowsContext::instance()->setWindowCreationContext(QWindowCreationContextPtr());
if (QWindowsContext::verboseWindows)
qDebug().nospace()
<< "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
@@ -505,6 +506,7 @@ QWindowsWindow::WindowData
result.geometry = context->obtainedGeometry;
result.frame = context->margins;
result.embedded = embedded;
+ result.customMargins = context->customMargins;
return result;
}
@@ -543,6 +545,8 @@ void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLe
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(hwnd, HWND_BOTTOM, 0, 0, 0, 0, swpFlags);
+ } else if (frameChange) { // Force WM_NCCALCSIZE with wParam=1 in case of custom margins.
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0, swpFlags);
}
if (flags & (Qt::CustomizeWindowHint|Qt::WindowTitleHint)) {
HMENU systemMenu = GetSystemMenu(hwnd, FALSE);
@@ -603,6 +607,33 @@ QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle)
return result;
}
+bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
+{
+#ifndef Q_OS_WINCE
+ // NCCALCSIZE_PARAMS structure if wParam==TRUE
+ if (!msg.wParam || customMargins.isNull())
+ return false;
+ *result = DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+ NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
+ const RECT oldClientArea = ncp->rgrc[0];
+ ncp->rgrc[0].left += customMargins.left();
+ ncp->rgrc[0].top += customMargins.top();
+ ncp->rgrc[0].right -= customMargins.right();
+ ncp->rgrc[0].bottom -= customMargins.bottom();
+ result = 0;
+ if (QWindowsContext::verboseWindows)
+ qDebug() << __FUNCTION__ << oldClientArea << '+' << customMargins << "-->"
+ << ncp->rgrc[0] << ' ' << ncp->rgrc[1] << ' ' << ncp->rgrc[2]
+ << ' ' << ncp->lppos->cx << ',' << ncp->lppos->cy;
+ return true;
+#else
+ Q_UNUSED(customMargins)
+ Q_UNUSED(msg)
+ Q_UNUSED(result)
+ return false;
+#endif
+}
+
#ifndef Q_OS_WINCE
void QWindowsGeometryHint::applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const
{
@@ -669,10 +700,11 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
QWindowCreationContext::QWindowCreationContext(const QWindow *w,
const QRect &geometry,
+ const QMargins &cm,
DWORD style_, DWORD exStyle_) :
geometryHint(w), style(style_), exStyle(exStyle_),
requestedGeometry(geometry), obtainedGeometry(geometry),
- margins(QWindowsGeometryHint::frame(style, exStyle)),
+ margins(QWindowsGeometryHint::frame(style, exStyle)), customMargins(cm),
frameX(CW_USEDEFAULT), frameY(CW_USEDEFAULT),
frameWidth(CW_USEDEFAULT), frameHeight(CW_USEDEFAULT)
{
@@ -683,14 +715,16 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
if (geometry.isValid()) {
frameX = geometry.x();
frameY = geometry.y();
- frameWidth = margins.left() + geometry.width() + margins.right();
- frameHeight = margins.top() + geometry.height() + margins.bottom();
+ const QMargins effectiveMargins = margins + customMargins;
+ frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right();
+ frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom();
const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
- frameX -= margins.left();
- frameY -= margins.top();
+ frameX -= effectiveMargins.left();
+ frameY -= effectiveMargins.top();
}
}
+
if (QWindowsContext::verboseWindows)
qDebug().nospace()
<< __FUNCTION__ << ' ' << w << geometry
@@ -698,7 +732,8 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
<< " frame: " << frameWidth << 'x' << frameHeight << '+'
<< frameX << '+' << frameY
<< " min" << geometryHint.minimumSize
- << " max" << geometryHint.maximumSize;
+ << " max" << geometryHint.maximumSize
+ << " custom margins " << customMargins;
}
/*!
@@ -730,9 +765,6 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
m_hdc(0),
m_windowState(Qt::WindowNoState),
m_opacity(1.0),
-#ifndef QT_NO_CURSOR
- m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()),
-#endif
m_dropTarget(0),
m_savedStyle(0),
m_format(aWindow->format()),
@@ -747,6 +779,8 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
{
if (aWindow->surfaceType() == QWindow::OpenGLSurface)
setFlag(OpenGLSurface);
+ // Clear the creation context as the window can be found in QWindowsContext's map.
+ QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>());
QWindowsContext::instance()->addWindow(m_data.hwnd, this);
if (aWindow->isTopLevel()) {
switch (aWindow->type()) {
@@ -872,8 +906,9 @@ QWindowsWindow::WindowData
{
WindowCreationData creationData;
creationData.fromWindow(w, parameters.flags);
- WindowData result = creationData.create(w, parameters.geometry, title);
- creationData.initialize(result.hwnd, false, 1);
+ WindowData result = creationData.create(w, parameters, title);
+ // Force WM_NCCALCSIZE (with wParam=1) via SWP_FRAMECHANGED for custom margin.
+ creationData.initialize(result.hwnd, !parameters.customMargins.isNull(), 1);
return result;
}
@@ -1163,7 +1198,7 @@ QRect QWindowsWindow::frameGeometry_sys() const
QRect QWindowsWindow::geometry_sys() const
{
- return frameGeometry_sys() - frameMargins();
+ return frameGeometry_sys().marginsRemoved(frameMargins());
}
/*!
@@ -1490,7 +1525,7 @@ QMargins QWindowsWindow::frameMargins() const
m_data.frame = QWindowsGeometryHint::frame(style(), exStyle());
clearFlag(FrameDirty);
}
- return m_data.frame;
+ return m_data.frame + m_data.customMargins;
}
void QWindowsWindow::setOpacity(qreal level)
@@ -1664,20 +1699,42 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
void QWindowsWindow::applyCursor()
{
#ifndef QT_NO_CURSOR
- SetCursor(m_cursor.handle());
+ if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor.
+ if (const QWindow *p = window()->parent())
+ QWindowsWindow::baseWindowOf(p)->applyCursor();
+ } else {
+ SetCursor(m_cursor.handle());
+ }
#endif
}
+// Check whether to apply a new cursor. Either the window in question is
+// currently under mouse, or it is the parent of the window under mouse and
+// there is no other window with an explicitly set cursor in-between.
+static inline bool applyNewCursor(const QWindow *w)
+{
+ const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse();
+ if (underMouse == w)
+ return true;
+ for (const QWindow *p = underMouse; p ; p = p->parent()) {
+ if (p == w)
+ return true;
+ if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull())
+ return false;
+ }
+ return false;
+}
+
void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
{
#ifndef QT_NO_CURSOR
if (c.handle() != m_cursor.handle()) {
- const bool underMouse = QWindowsContext::instance()->windowUnderMouse() == window();
+ const bool apply = applyNewCursor(window());
if (QWindowsContext::verboseWindows)
qDebug() << window() << __FUNCTION__ << "Shape=" << c.cursor().shape()
- << " isWUM=" << underMouse;
+ << " doApply=" << apply;
m_cursor = c;
- if (underMouse)
+ if (apply)
applyCursor();
}
#endif
@@ -1850,4 +1907,32 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon)
}
}
+/*!
+ \brief Sets custom margins to be added to the default margins determined by
+ the windows style in the handling of the WM_NCCALCSIZE message.
+
+ This is currently used to give the Aero-style QWizard a smaller top margin.
+ The property can be set using QPlatformNativeInterface::setWindowProperty() or,
+ before platform window creation, by setting a dynamic property
+ on the QWindow (see QWindowsIntegration::createPlatformWindow()).
+*/
+
+void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
+{
+ if (newCustomMargins != m_data.customMargins) {
+ const QMargins oldCustomMargins = m_data.customMargins;
+ m_data.customMargins = newCustomMargins;
+ // Re-trigger WM_NCALCSIZE with wParam=1 by passing SWP_FRAMECHANGED
+ const QRect currentFrameGeometry = frameGeometry_sys();
+ const QPoint topLeft = currentFrameGeometry.topLeft();
+ QRect newFrame = currentFrameGeometry.marginsRemoved(oldCustomMargins) + m_data.customMargins;
+ newFrame.moveTo(topLeft);
+ setFlag(FrameDirty);
+ if (QWindowsContext::verboseWindows)
+ qDebug() << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins
+ << currentFrameGeometry << "->" << newFrame;
+ SetWindowPos(m_data.hwnd, 0, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index f3b480b0af..8fe5cbe17b 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -69,6 +69,7 @@ struct QWindowsGeometryHint
QWindowsGeometryHint() {}
explicit QWindowsGeometryHint(const QWindow *w);
static QMargins frame(DWORD style, DWORD exStyle);
+ static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result);
#ifndef Q_OS_WINCE //MinMax maybe define struct if not available
void applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const;
void applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const;
@@ -89,6 +90,7 @@ struct QWindowsGeometryHint
struct QWindowCreationContext
{
QWindowCreationContext(const QWindow *w, const QRect &r,
+ const QMargins &customMargins,
DWORD style, DWORD exStyle);
#ifndef Q_OS_WINCE //MinMax maybe define struct if not available
void applyToMinMaxInfo(MINMAXINFO *mmi) const
@@ -101,6 +103,7 @@ struct QWindowCreationContext
QRect requestedGeometry;
QRect obtainedGeometry;
QMargins margins;
+ QMargins customMargins; // User-defined, additional frame for WM_NCCALCSIZE
int frameX; // Passed on to CreateWindowEx(), including frame.
int frameY;
int frameWidth;
@@ -137,6 +140,7 @@ public:
Qt::WindowFlags flags;
QRect geometry;
QMargins frame; // Do not use directly for windows, see FrameDirty.
+ QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd;
bool embedded;
@@ -191,6 +195,9 @@ public:
void setFrameStrutEventsEnabled(bool enabled);
bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
+ QMargins customMargins() const { return m_data.customMargins; }
+ void setCustomMargins(const QMargins &m);
+
#ifdef QT_OPENGL_ES_2
EGLSurface eglSurfaceHandle() const { return m_eglSurface;}
EGLSurface ensureEglSurfaceHandle(const QWindowsEGLStaticContextPtr &staticContext, EGLConfig config);
@@ -290,17 +297,6 @@ private:
HICON m_iconBig;
};
-// Conveniences for window frames.
-inline QRect operator+(const QRect &r, const QMargins &m)
-{
- return r.adjusted(-m.left(), -m.top(), m.right(), m.bottom());
-}
-
-inline QRect operator-(const QRect &r, const QMargins &m)
-{
- return r.adjusted(m.left(), m.top(), -m.right(), -m.bottom());
-}
-
// Debug
QDebug operator<<(QDebug d, const RECT &r);
#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO/WM_NCCALCSIZE
@@ -371,4 +367,6 @@ inline void QWindowsWindow::destroyIcon()
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QMargins)
+
#endif // QWINDOWSWINDOW_H
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 11c74edc45..854f7bcd17 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -50,6 +50,7 @@
#include <GL/glx.h>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOffscreenSurface>
#include "qglxintegration.h"
#include <QtPlatformSupport/private/qglxconvenience_p.h>
@@ -270,6 +271,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_screen(screen)
, m_context(0)
, m_format(format)
+ , m_isPBufferCurrent(false)
{
m_shareContext = 0;
if (share)
@@ -391,19 +393,35 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface)
{
Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
- GLXDrawable glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
-
- return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), glxDrawable, m_context);
+ QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
+ if (surfaceClass == QSurface::Window) {
+ m_isPBufferCurrent = false;
+ QXcbWindow *window = static_cast<QXcbWindow *>(surface);
+ return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), window->xcb_window(), m_context);
+ } else if (surfaceClass == QSurface::Offscreen) {
+ m_isPBufferCurrent = true;
+ QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
+ return glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), pbuffer->pbuffer(), pbuffer->pbuffer(), m_context);
+ }
+ return false;
}
void QGLXContext::doneCurrent()
{
- glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0);
+ if (m_isPBufferCurrent)
+ glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0, 0);
+ else
+ glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0);
+ m_isPBufferCurrent = false;
}
void QGLXContext::swapBuffers(QPlatformSurface *surface)
{
- GLXDrawable glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
+ GLXDrawable glxDrawable = 0;
+ if (surface->surface()->surfaceClass() == QSurface::Offscreen)
+ glxDrawable = static_cast<QGLXPbuffer *>(surface)->pbuffer();
+ else
+ glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), glxDrawable);
}
@@ -455,4 +473,36 @@ bool QGLXContext::isValid() const
return m_context != 0;
}
+
+QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
+ : QPlatformOffscreenSurface(offscreenSurface)
+ , m_format(offscreenSurface->requestedFormat())
+ , m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
+ , m_pbuffer(0)
+{
+ GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
+
+ if (config) {
+ const int attributes[] = {
+ GLX_PBUFFER_WIDTH, offscreenSurface->size().width(),
+ GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(),
+ GLX_LARGEST_PBUFFER, False,
+ GLX_PRESERVED_CONTENTS, False,
+ GLX_NONE
+ };
+
+ m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes);
+
+ if (m_pbuffer)
+ m_format = qglx_surfaceFormatFromGLXFBConfig(DISPLAY_FROM_XCB(m_screen), config);
+ }
+}
+
+QGLXPbuffer::~QGLXPbuffer()
+{
+ if (m_pbuffer)
+ glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index 78e9985334..d10b1d441b 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -46,6 +46,7 @@
#include "qxcbscreen.h"
#include <qpa/qplatformopenglcontext.h>
+#include <qpa/qplatformoffscreensurface.h>
#include <QtGui/QSurfaceFormat>
#include <QtCore/QMutex>
@@ -89,6 +90,25 @@ private:
GLXContext m_context;
GLXContext m_shareContext;
QSurfaceFormat m_format;
+ bool m_isPBufferCurrent;
+};
+
+
+class QGLXPbuffer : public QPlatformOffscreenSurface
+{
+public:
+ explicit QGLXPbuffer(QOffscreenSurface *offscreenSurface);
+ ~QGLXPbuffer();
+
+ QSurfaceFormat format() const { return m_format; }
+ bool isValid() const { return m_pbuffer != 0; }
+
+ GLXPbuffer pbuffer() const { return m_pbuffer; }
+
+private:
+ QSurfaceFormat m_format;
+ QXcbScreen *m_screen;
+ GLXPbuffer m_pbuffer;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index e29b21c9c8..1b11ef7f95 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -287,8 +287,14 @@ QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
QXcbCursor::~QXcbCursor()
{
+ xcb_connection_t *conn = xcb_connection();
if (!--cursorCount)
- xcb_close_font(xcb_connection(), cursorFont);
+ xcb_close_font(conn, cursorFont);
+
+ foreach (xcb_cursor_t cursor, m_bitmapCursorMap)
+ xcb_free_cursor(conn, cursor);
+ foreach (xcb_cursor_t cursor, m_shapeCursorMap)
+ xcb_free_cursor(conn, cursor);
}
#ifndef QT_NO_CURSOR
@@ -301,17 +307,19 @@ void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget)
// No X11 cursor control when there is no widget under the cursor
return;
- xcb_cursor_t c;
- if (cursor->shape() == Qt::BitmapCursor) {
- qint64 id = cursor->pixmap().cacheKey();
- if (!m_bitmapCursorMap.contains(id))
- m_bitmapCursorMap.insert(id, createBitmapCursor(cursor));
- c = m_bitmapCursorMap.value(id);
- } else {
- int id = cursor->shape();
- if (!m_shapeCursorMap.contains(id))
- m_shapeCursorMap.insert(id, createFontCursor(cursor->shape()));
- c = m_shapeCursorMap.value(id);
+ xcb_cursor_t c = XCB_CURSOR_NONE;
+ if (cursor) {
+ if (cursor->shape() == Qt::BitmapCursor) {
+ qint64 id = cursor->pixmap().cacheKey();
+ if (!m_bitmapCursorMap.contains(id))
+ m_bitmapCursorMap.insert(id, createBitmapCursor(cursor));
+ c = m_bitmapCursorMap.value(id);
+ } else {
+ int id = cursor->shape();
+ if (!m_shapeCursorMap.contains(id))
+ m_shapeCursorMap.insert(id, createFontCursor(cursor->shape()));
+ c = m_shapeCursorMap.value(id);
+ }
}
w->setCursor(c);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 1840dd1ce5..d0b0ab8d02 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -78,10 +78,12 @@
#elif defined(XCB_USE_EGL)
#include "qxcbeglsurface.h"
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <QtPlatformSupport/private/qeglpbuffer_p.h>
#endif
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
+#include <QtGui/QOffscreenSurface>
#ifndef QT_NO_ACCESSIBILITY
#include <qpa/qplatformaccessibility.h>
#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
@@ -168,7 +170,10 @@ public:
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface)
{
- return static_cast<QXcbWindow *>(surface)->eglSurface()->surface();
+ if (surface->surface()->surfaceClass() == QSurface::Window)
+ return static_cast<QXcbWindow *>(surface)->eglSurface()->surface();
+ else
+ return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
private:
@@ -205,6 +210,20 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind
return new QXcbBackingStore(window);
}
+QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+#if defined(XCB_USE_GLX)
+ return new QGLXPbuffer(surface);
+#elif defined(XCB_USE_EGL)
+ QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle());
+ return new QEGLPbuffer(screen->connection()->egl_display(), surface->requestedFormat(), surface);
+#else
+ Q_UNUSED(surface);
+ qWarning("QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled");
+ return 0;
+#endif
+}
+
bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index cd6c2fd73c..13b3b115ca 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -68,6 +68,8 @@ public:
#endif
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const;
+
bool hasCapability(Capability cap) const;
QAbstractEventDispatcher *guiThreadEventDispatcher() const;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index bda54b4682..4ac60f6077 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -1081,6 +1081,7 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
int qtcode = 0;
int count = chars.count();
QString string = translateKeySym(sym, state, qtcode, modifiers, chars, count);
+ string.truncate(count);
bool isAutoRepeat = false;
@@ -1102,7 +1103,7 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
bool filtered = false;
if (inputContext) {
- QKeyEvent event(type, qtcode, modifiers, code, sym, state, string.left(count), isAutoRepeat, count);
+ QKeyEvent event(type, qtcode, modifiers, code, sym, state, string, isAutoRepeat, count);
event.setTimestamp(time);
filtered = inputContext->filterEvent(&event);
}
@@ -1114,7 +1115,7 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers);
}
QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
- code, sym, state, string.left(count), isAutoRepeat);
+ code, sym, state, string, isAutoRepeat);
}
if (isAutoRepeat && type == QEvent::KeyRelease) {
@@ -1130,13 +1131,13 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
}
if (!filtered && inputContext) {
- QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string.left(count), isAutoRepeat, count);
+ QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat, count);
event.setTimestamp(time);
filtered = inputContext->filterEvent(&event);
}
if (!filtered)
QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
- code, sym, state, string.left(count), isAutoRepeat);
+ code, sym, state, string, isAutoRepeat);
}
}
diff --git a/src/plugins/platformthemes/gtk2/gtk2.json b/src/plugins/platformthemes/gtk2/gtk2.json
new file mode 100644
index 0000000000..86dd8e58fa
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/gtk2.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "gtk2" ]
+}
diff --git a/src/plugins/platformthemes/gtk2/gtk2.pro b/src/plugins/platformthemes/gtk2/gtk2.pro
new file mode 100644
index 0000000000..bb02192f91
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/gtk2.pro
@@ -0,0 +1,20 @@
+TARGET = qgtk2
+
+PLUGIN_TYPE = platformthemes
+PLUGIN_CLASS_NAME = QGtk2ThemePlugin
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private
+
+CONFIG += X11
+QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTK2
+LIBS += $$QT_LIBS_QGTK2
+
+HEADERS += \
+ qgtk2dialoghelpers.h \
+ qgtk2theme.h
+
+SOURCES += \
+ main.cpp \
+ qgtk2dialoghelpers.cpp \
+ qgtk2theme.cpp \
diff --git a/src/plugins/platformthemes/gtk2/main.cpp b/src/plugins/platformthemes/gtk2/main.cpp
new file mode 100644
index 0000000000..0c3fe46e29
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/main.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformthemeplugin.h>
+#include "qgtk2theme.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGtk2ThemePlugin : public QPlatformThemePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformThemeFactoryInterface.5.1" FILE "gtk2.json")
+
+public:
+ QPlatformTheme *create(const QString &key, const QStringList &params);
+};
+
+QPlatformTheme *QGtk2ThemePlugin::create(const QString &key, const QStringList &params)
+{
+ Q_UNUSED(params);
+ if (!key.compare(QStringLiteral("gtk2"), Qt::CaseInsensitive))
+ return new QGtk2Theme;
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp
new file mode 100644
index 0000000000..2a8815654f
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp
@@ -0,0 +1,609 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgtk2dialoghelpers.h"
+
+#include <qeventloop.h>
+#include <qwindow.h>
+#include <qcolor.h>
+#include <qdebug.h>
+#include <qfont.h>
+
+#include <private/qguiapplication_p.h>
+
+#undef signals
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <pango/pango.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGtk2Dialog : public QWindow
+{
+ Q_OBJECT
+
+public:
+ QGtk2Dialog(GtkWidget *gtkWidget);
+ ~QGtk2Dialog();
+
+ GtkDialog* gtkDialog() const;
+
+ void exec();
+ bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
+ void hide();
+
+Q_SIGNALS:
+ void accept();
+ void reject();
+
+protected:
+ static void onResponse(QGtk2Dialog *dialog, int response);
+
+private:
+ GtkWidget *gtkWidget;
+};
+
+QGtk2Dialog::QGtk2Dialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget)
+{
+ g_signal_connect_swapped(G_OBJECT(gtkWidget), "response", G_CALLBACK(onResponse), this);
+ g_signal_connect(G_OBJECT(gtkWidget), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+}
+
+QGtk2Dialog::~QGtk2Dialog()
+{
+ gtk_widget_destroy(gtkWidget);
+}
+
+GtkDialog* QGtk2Dialog::gtkDialog() const
+{
+ return GTK_DIALOG(gtkWidget);
+}
+
+void QGtk2Dialog::exec()
+{
+ if (modality() == Qt::ApplicationModal) {
+ // block input to the whole app, including other GTK dialogs
+ gtk_dialog_run(gtkDialog());
+ } else {
+ // block input to the window, allow input to other GTK dialogs
+ QEventLoop loop;
+ connect(this, SIGNAL(accept()), &loop, SLOT(quit()));
+ connect(this, SIGNAL(reject()), &loop, SLOT(quit()));
+ loop.exec();
+ }
+}
+
+bool QGtk2Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
+{
+ setParent(parent);
+ setFlags(flags);
+ setModality(modality);
+
+ gtk_widget_realize(gtkWidget); // creates X window
+
+ if (parent) {
+ XSetTransientForHint(gdk_x11_drawable_get_xdisplay(gtkWidget->window),
+ gdk_x11_drawable_get_xid(gtkWidget->window),
+ parent->winId());
+ }
+
+ if (modality != Qt::NonModal) {
+ gdk_window_set_modal_hint(gtkWidget->window, true);
+ QGuiApplicationPrivate::showModalWindow(this);
+ }
+
+ gtk_widget_show(gtkWidget);
+ return true;
+}
+
+void QGtk2Dialog::hide()
+{
+ QGuiApplicationPrivate::hideModalWindow(this);
+ gtk_widget_hide(gtkWidget);
+}
+
+void QGtk2Dialog::onResponse(QGtk2Dialog *dialog, int response)
+{
+ if (response == GTK_RESPONSE_OK)
+ emit dialog->accept();
+ else
+ emit dialog->reject();
+}
+
+QGtk2ColorDialogHelper::QGtk2ColorDialogHelper()
+{
+ d.reset(new QGtk2Dialog(gtk_color_selection_dialog_new("")));
+ connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
+ connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject()));
+
+ GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(d->gtkDialog()));
+ g_signal_connect_swapped(gtkColorSelection, "color-changed", G_CALLBACK(onColorChanged), this);
+}
+
+QGtk2ColorDialogHelper::~QGtk2ColorDialogHelper()
+{
+}
+
+bool QGtk2ColorDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
+{
+ applyOptions();
+ return d->show(flags, modality, parent);
+}
+
+void QGtk2ColorDialogHelper::exec()
+{
+ d->exec();
+}
+
+void QGtk2ColorDialogHelper::hide()
+{
+ d->hide();
+}
+
+void QGtk2ColorDialogHelper::setCurrentColor(const QColor &color)
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(gtkDialog));
+ GdkColor gdkColor;
+ gdkColor.red = color.red() << 8;
+ gdkColor.green = color.green() << 8;
+ gdkColor.blue = color.blue() << 8;
+ gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(gtkColorSelection), &gdkColor);
+ if (color.alpha() < 255) {
+ gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(gtkColorSelection), true);
+ gtk_color_selection_set_current_alpha(GTK_COLOR_SELECTION(gtkColorSelection), color.alpha() << 8);
+ }
+}
+
+QColor QGtk2ColorDialogHelper::currentColor() const
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(gtkDialog));
+ GdkColor gdkColor;
+ gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(gtkColorSelection), &gdkColor);
+ guint16 alpha = gtk_color_selection_get_current_alpha(GTK_COLOR_SELECTION(gtkColorSelection));
+ return QColor(gdkColor.red >> 8, gdkColor.green >> 8, gdkColor.blue >> 8, alpha >> 8);
+}
+
+void QGtk2ColorDialogHelper::onAccepted()
+{
+ emit accept();
+ emit colorSelected(currentColor());
+}
+
+void QGtk2ColorDialogHelper::onColorChanged(QGtk2ColorDialogHelper *dialog)
+{
+ emit dialog->currentColorChanged(dialog->currentColor());
+}
+
+void QGtk2ColorDialogHelper::applyOptions()
+{
+ GtkDialog* gtkDialog = d->gtkDialog();
+ gtk_window_set_title(GTK_WINDOW(gtkDialog), options()->windowTitle().toUtf8());
+
+ GtkWidget *gtkColorSelection = gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(gtkDialog));
+ gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(gtkColorSelection), options()->testOption(QColorDialogOptions::ShowAlphaChannel));
+
+ GtkWidget *okButton = 0;
+ GtkWidget *cancelButton = 0;
+ GtkWidget *helpButton = 0;
+ g_object_get(G_OBJECT(gtkDialog), "ok-button", &okButton, "cancel-button", &cancelButton, "help-button", &helpButton, NULL);
+ if (okButton)
+ g_object_set(G_OBJECT(okButton), "visible", !options()->testOption(QColorDialogOptions::NoButtons), NULL);
+ if (cancelButton)
+ g_object_set(G_OBJECT(cancelButton), "visible", !options()->testOption(QColorDialogOptions::NoButtons), NULL);
+ if (helpButton)
+ gtk_widget_hide(helpButton);
+}
+
+QGtk2FileDialogHelper::QGtk2FileDialogHelper()
+{
+ d.reset(new QGtk2Dialog(gtk_file_chooser_dialog_new("", 0,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL)));
+ connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
+ connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject()));
+
+ g_signal_connect(GTK_FILE_CHOOSER(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
+ g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
+}
+
+QGtk2FileDialogHelper::~QGtk2FileDialogHelper()
+{
+}
+
+bool QGtk2FileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
+{
+ _dir.clear();
+ _selection.clear();
+
+ applyOptions();
+ return d->show(flags, modality, parent);
+}
+
+void QGtk2FileDialogHelper::exec()
+{
+ d->exec();
+}
+
+void QGtk2FileDialogHelper::hide()
+{
+ // After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder()
+ // & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual
+ // values before hiding the dialog
+ _dir = directory();
+ _selection = selectedFiles();
+
+ d->hide();
+}
+
+bool QGtk2FileDialogHelper::defaultNameFilterDisables() const
+{
+ return false;
+}
+
+void QGtk2FileDialogHelper::setDirectory(const QString &directory)
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), directory.toUtf8());
+}
+
+QString QGtk2FileDialogHelper::directory() const
+{
+ // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder()
+ // returns a bogus value -> return the cached value before hiding
+ if (!_dir.isEmpty())
+ return _dir;
+
+ QString ret;
+ GtkDialog *gtkDialog = d->gtkDialog();
+ gchar *folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(gtkDialog));
+ if (folder) {
+ ret = QString::fromUtf8(folder);
+ g_free(folder);
+ }
+ return ret;
+}
+
+void QGtk2FileDialogHelper::selectFile(const QString &filename)
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(gtkDialog), filename.toUtf8());
+}
+
+QStringList QGtk2FileDialogHelper::selectedFiles() const
+{
+ // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames()
+ // returns a bogus value -> return the cached value before hiding
+ if (!_selection.isEmpty())
+ return _selection;
+
+ QStringList selection;
+ GtkDialog *gtkDialog = d->gtkDialog();
+ GSList *filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(gtkDialog));
+ for (GSList *it = filenames; it; it = it->next)
+ selection += QString::fromUtf8((const char*)it->data);
+ g_slist_free(filenames);
+ return selection;
+}
+
+void QGtk2FileDialogHelper::setFilter()
+{
+ applyOptions();
+}
+
+void QGtk2FileDialogHelper::selectNameFilter(const QString &filter)
+{
+ GtkFileFilter *gtkFilter = _filters.value(filter);
+ if (gtkFilter) {
+ GtkDialog *gtkDialog = d->gtkDialog();
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(gtkDialog), gtkFilter);
+ }
+}
+
+QString QGtk2FileDialogHelper::selectedNameFilter() const
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(gtkDialog));
+ return _filterNames.value(gtkFilter);
+}
+
+void QGtk2FileDialogHelper::onAccepted()
+{
+ emit accept();
+
+ QString filter = selectedNameFilter();
+ if (filter.isEmpty())
+ emit filterSelected(filter);
+
+ QStringList files = selectedFiles();
+ emit filesSelected(files);
+ if (files.count() == 1)
+ emit fileSelected(files.first());
+}
+
+void QGtk2FileDialogHelper::onSelectionChanged(GtkDialog *gtkDialog, QGtk2FileDialogHelper *helper)
+{
+ QString selection;
+ gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog));
+ if (filename) {
+ selection = QString::fromUtf8(filename);
+ g_free(filename);
+ }
+ emit helper->currentChanged(selection);
+}
+
+void QGtk2FileDialogHelper::onCurrentFolderChanged(QGtk2FileDialogHelper *dialog)
+{
+ emit dialog->directoryEntered(dialog->directory());
+}
+
+static GtkFileChooserAction gtkFileChooserAction(const QSharedPointer<QFileDialogOptions> &options)
+{
+ switch (options->fileMode()) {
+ case QFileDialogOptions::AnyFile:
+ case QFileDialogOptions::ExistingFile:
+ case QFileDialogOptions::ExistingFiles:
+ if (options->acceptMode() == QFileDialogOptions::AcceptOpen)
+ return GTK_FILE_CHOOSER_ACTION_OPEN;
+ else
+ return GTK_FILE_CHOOSER_ACTION_SAVE;
+ case QFileDialogOptions::Directory:
+ case QFileDialogOptions::DirectoryOnly:
+ default:
+ if (options->acceptMode() == QFileDialogOptions::AcceptOpen)
+ return GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
+ else
+ return GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
+ }
+}
+
+void QGtk2FileDialogHelper::applyOptions()
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ const QSharedPointer<QFileDialogOptions> &opts = options();
+
+ gtk_window_set_title(GTK_WINDOW(gtkDialog), opts->windowTitle().toUtf8());
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(gtkDialog), true);
+
+ const GtkFileChooserAction action = gtkFileChooserAction(opts);
+ gtk_file_chooser_set_action(GTK_FILE_CHOOSER(gtkDialog), action);
+
+ const bool selectMultiple = opts->fileMode() == QFileDialogOptions::ExistingFiles;
+ gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(gtkDialog), selectMultiple);
+
+ const bool confirmOverwrite = !opts->testOption(QFileDialogOptions::DontConfirmOverwrite);
+ gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(gtkDialog), confirmOverwrite);
+
+ const QStringList nameFilters = opts->nameFilters();
+ if (!nameFilters.isEmpty())
+ setNameFilters(nameFilters);
+
+ const QString initialDirectory = opts->initialDirectory();
+ if (!initialDirectory.isEmpty())
+ setDirectory(initialDirectory);
+
+ foreach (const QString &filename, opts->initiallySelectedFiles())
+ selectFile(filename);
+
+ const QString initialNameFilter = opts->initiallySelectedNameFilter();
+ if (!initialNameFilter.isEmpty())
+ selectNameFilter(initialNameFilter);
+
+ GtkWidget *acceptButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK);
+ if (acceptButton) {
+ if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
+ gtk_button_set_label(GTK_BUTTON(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8());
+ else if (opts->acceptMode() == QFileDialogOptions::AcceptOpen)
+ gtk_button_set_label(GTK_BUTTON(acceptButton), GTK_STOCK_OPEN);
+ else
+ gtk_button_set_label(GTK_BUTTON(acceptButton), GTK_STOCK_SAVE);
+ }
+
+ GtkWidget *rejectButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL);
+ if (rejectButton) {
+ if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject))
+ gtk_button_set_label(GTK_BUTTON(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8());
+ else
+ gtk_button_set_label(GTK_BUTTON(rejectButton), GTK_STOCK_CANCEL);
+ }
+}
+
+void QGtk2FileDialogHelper::setNameFilters(const QStringList& filters)
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ foreach (GtkFileFilter *filter, _filters)
+ gtk_file_chooser_remove_filter(GTK_FILE_CHOOSER(gtkDialog), filter);
+
+ _filters.clear();
+ _filterNames.clear();
+
+ foreach (const QString &filter, filters) {
+ GtkFileFilter *gtkFilter = gtk_file_filter_new();
+ const QString name = filter.left(filter.indexOf(QLatin1Char('(')));
+ const QStringList extensions = cleanFilterList(filter);
+
+ gtk_file_filter_set_name(gtkFilter, name.isEmpty() ? extensions.join(QStringLiteral(", ")).toUtf8() : name.toUtf8());
+ foreach (const QString &ext, extensions)
+ gtk_file_filter_add_pattern(gtkFilter, ext.toUtf8());
+
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(gtkDialog), gtkFilter);
+
+ _filters.insert(filter, gtkFilter);
+ _filterNames.insert(gtkFilter, filter);
+ }
+}
+
+QGtk2FontDialogHelper::QGtk2FontDialogHelper()
+{
+ d.reset(new QGtk2Dialog(gtk_font_selection_dialog_new("")));
+ connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
+ connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject()));
+}
+
+QGtk2FontDialogHelper::~QGtk2FontDialogHelper()
+{
+}
+
+bool QGtk2FontDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
+{
+ applyOptions();
+ return d->show(flags, modality, parent);
+}
+
+void QGtk2FontDialogHelper::exec()
+{
+ d->exec();
+}
+
+void QGtk2FontDialogHelper::hide()
+{
+ d->hide();
+}
+
+static QString qt_fontToString(const QFont& font)
+{
+ PangoFontDescription *desc = pango_font_description_new();
+ pango_font_description_set_size(desc, font.pointSizeF() * PANGO_SCALE);
+ pango_font_description_set_family(desc, font.family().toUtf8());
+
+ int weight = font.weight();
+ if (weight >= QFont::Black)
+ pango_font_description_set_weight(desc, PANGO_WEIGHT_HEAVY);
+ else if (weight >= QFont::Bold)
+ pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
+ else if (weight >= QFont::DemiBold)
+ pango_font_description_set_weight(desc, PANGO_WEIGHT_SEMIBOLD);
+ else if (weight >= QFont::Normal)
+ pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
+ else
+ pango_font_description_set_weight(desc, PANGO_WEIGHT_LIGHT);
+
+ int style = font.style();
+ if (style == QFont::StyleItalic)
+ pango_font_description_set_style(desc, PANGO_STYLE_ITALIC);
+ else if (style == QFont::StyleOblique)
+ pango_font_description_set_style(desc, PANGO_STYLE_OBLIQUE);
+ else
+ pango_font_description_set_style(desc, PANGO_STYLE_NORMAL);
+
+ char *str = pango_font_description_to_string(desc);
+ QString name = QString::fromUtf8(str);
+ pango_font_description_free(desc);
+ g_free(str);
+ return name;
+}
+
+static QFont qt_fontFromString(const QString &name)
+{
+ QFont font;
+ PangoFontDescription* desc = pango_font_description_from_string(name.toUtf8());
+ font.setPointSizeF(static_cast<float>(pango_font_description_get_size(desc)) / PANGO_SCALE);
+
+ QString family = QString::fromUtf8(pango_font_description_get_family(desc));
+ if (!family.isEmpty())
+ font.setFamily(family);
+
+ int weight = pango_font_description_get_weight(desc);
+ if (weight >= PANGO_WEIGHT_HEAVY)
+ font.setWeight(QFont::Black);
+ else if (weight >= PANGO_WEIGHT_BOLD)
+ font.setWeight(QFont::Bold);
+ else if (weight >= PANGO_WEIGHT_SEMIBOLD)
+ font.setWeight(QFont::DemiBold);
+ else if (weight >= PANGO_WEIGHT_NORMAL)
+ font.setWeight(QFont::Normal);
+ else
+ font.setWeight(QFont::Light);
+
+ PangoStyle style = pango_font_description_get_style(desc);
+ if (style == PANGO_STYLE_ITALIC)
+ font.setStyle(QFont::StyleItalic);
+ else if (style == PANGO_STYLE_OBLIQUE)
+ font.setStyle(QFont::StyleOblique);
+ else
+ font.setStyle(QFont::StyleNormal);
+
+ pango_font_description_free(desc);
+ return font;
+}
+
+void QGtk2FontDialogHelper::setCurrentFont(const QFont &font)
+{
+ GtkFontSelectionDialog *gtkDialog = GTK_FONT_SELECTION_DIALOG(d->gtkDialog());
+ gtk_font_selection_dialog_set_font_name(gtkDialog, qt_fontToString(font).toUtf8());
+}
+
+QFont QGtk2FontDialogHelper::currentFont() const
+{
+ GtkFontSelectionDialog *gtkDialog = GTK_FONT_SELECTION_DIALOG(d->gtkDialog());
+ gchar *name = gtk_font_selection_dialog_get_font_name(gtkDialog);
+ QFont font = qt_fontFromString(QString::fromUtf8(name));
+ g_free(name);
+ return font;
+}
+
+void QGtk2FontDialogHelper::onAccepted()
+{
+ emit accept();
+ emit fontSelected(currentFont());
+}
+
+void QGtk2FontDialogHelper::applyOptions()
+{
+ GtkDialog *gtkDialog = d->gtkDialog();
+ const QSharedPointer<QFontDialogOptions> &opts = options();
+
+ gtk_window_set_title(GTK_WINDOW(gtkDialog), opts->windowTitle().toUtf8());
+
+ GtkWidget *okButton = gtk_font_selection_dialog_get_ok_button(GTK_FONT_SELECTION_DIALOG(gtkDialog));
+ GtkWidget *cancelButton = gtk_font_selection_dialog_get_cancel_button(GTK_FONT_SELECTION_DIALOG(gtkDialog));
+ if (okButton)
+ gtk_widget_set_visible(okButton, !options()->testOption(QFontDialogOptions::NoButtons));
+ if (cancelButton)
+ gtk_widget_set_visible(cancelButton, !options()->testOption(QFontDialogOptions::NoButtons));
+}
+
+QT_END_NAMESPACE
+
+#include "qgtk2dialoghelpers.moc"
diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
new file mode 100644
index 0000000000..2c5381aec8
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGTK2DIALOGHELPERS_P_H
+#define QGTK2DIALOGHELPERS_P_H
+
+#include <QtCore/qscopedpointer.h>
+#include <qpa/qplatformdialoghelper.h>
+
+typedef struct _GtkDialog GtkDialog;
+typedef struct _GtkFileFilter GtkFileFilter;
+
+QT_BEGIN_NAMESPACE
+
+class QGtk2Dialog;
+
+class QGtk2ColorDialogHelper : public QPlatformColorDialogHelper
+{
+ Q_OBJECT
+
+public:
+ QGtk2ColorDialogHelper();
+ ~QGtk2ColorDialogHelper();
+
+ virtual bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
+ virtual void exec();
+ virtual void hide();
+
+ virtual void setCurrentColor(const QColor &color);
+ virtual QColor currentColor() const;
+
+private Q_SLOTS:
+ void onAccepted();
+
+private:
+ static void onColorChanged(QGtk2ColorDialogHelper *helper);
+ void applyOptions();
+
+ mutable QScopedPointer<QGtk2Dialog> d;
+};
+
+class QGtk2FileDialogHelper : public QPlatformFileDialogHelper
+{
+ Q_OBJECT
+
+public:
+ QGtk2FileDialogHelper();
+ ~QGtk2FileDialogHelper();
+
+ virtual bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
+ virtual void exec();
+ virtual void hide();
+
+ virtual bool defaultNameFilterDisables() const;
+ virtual void setDirectory(const QString &directory);
+ virtual QString directory() const;
+ virtual void selectFile(const QString &filename);
+ virtual QStringList selectedFiles() const;
+ virtual void setFilter();
+ virtual void selectNameFilter(const QString &filter);
+ virtual QString selectedNameFilter() const;
+
+private Q_SLOTS:
+ void onAccepted();
+
+private:
+ static void onSelectionChanged(GtkDialog *dialog, QGtk2FileDialogHelper *helper);
+ static void onCurrentFolderChanged(QGtk2FileDialogHelper *helper);
+ void applyOptions();
+ void setNameFilters(const QStringList &filters);
+
+ QString _dir;
+ QStringList _selection;
+ QHash<QString, GtkFileFilter*> _filters;
+ QHash<GtkFileFilter*, QString> _filterNames;
+ mutable QScopedPointer<QGtk2Dialog> d;
+};
+
+class QGtk2FontDialogHelper : public QPlatformFontDialogHelper
+{
+ Q_OBJECT
+
+public:
+ QGtk2FontDialogHelper();
+ ~QGtk2FontDialogHelper();
+
+ virtual bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
+ virtual void exec();
+ virtual void hide();
+
+ virtual void setCurrentFont(const QFont &font);
+ virtual QFont currentFont() const;
+
+private Q_SLOTS:
+ void onAccepted();
+
+private:
+ void applyOptions();
+
+ mutable QScopedPointer<QGtk2Dialog> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGTK2DIALOGHELPERS_P_H
diff --git a/src/plugins/platformthemes/gtk2/qgtk2theme.cpp b/src/plugins/platformthemes/gtk2/qgtk2theme.cpp
new file mode 100644
index 0000000000..7bb538b888
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/qgtk2theme.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgtk2theme.h"
+#include "qgtk2dialoghelpers.h"
+
+#undef signals
+#include <gtk/gtk.h>
+
+QT_BEGIN_NAMESPACE
+
+const char *QGtk2Theme::name = "gtk2";
+
+QGtk2Theme::QGtk2Theme()
+{
+ gtk_init(0, 0);
+}
+
+bool QGtk2Theme::usePlatformNativeDialog(DialogType type) const
+{
+ Q_UNUSED(type);
+ return true;
+}
+
+QPlatformDialogHelper *QGtk2Theme::createPlatformDialogHelper(DialogType type) const
+{
+ switch (type) {
+ case ColorDialog:
+ return new QGtk2ColorDialogHelper;
+ case FileDialog:
+ return new QGtk2FileDialogHelper;
+ case FontDialog:
+ return new QGtk2FontDialogHelper;
+ default:
+ return 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/gtk2/qgtk2theme.h b/src/plugins/platformthemes/gtk2/qgtk2theme.h
new file mode 100644
index 0000000000..6d8768dd8e
--- /dev/null
+++ b/src/plugins/platformthemes/gtk2/qgtk2theme.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGTK2THEME_H
+#define QGTK2THEME_H
+
+#include <private/qgenericunixthemes_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGtk2Theme : public QGnomeTheme
+{
+public:
+ QGtk2Theme();
+
+ virtual bool usePlatformNativeDialog(DialogType type) const;
+ virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
+
+ static const char *name;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGTK2THEME_H
diff --git a/src/plugins/platformthemes/platformthemes.pro b/src/plugins/platformthemes/platformthemes.pro
new file mode 100644
index 0000000000..23dcda2c82
--- /dev/null
+++ b/src/plugins/platformthemes/platformthemes.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+contains(QT_CONFIG, gtk2): SUBDIRS += gtk2
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 3b0ff3f6c8..516105401e 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,7 +1,8 @@
TEMPLATE = subdirs
-SUBDIRS *= sqldrivers bearer
-qtHaveModule(gui): SUBDIRS *= imageformats platforms platforminputcontexts generic
+SUBDIRS *= sqldrivers
+qtHaveModule(network): SUBDIRS += bearer
+qtHaveModule(gui): SUBDIRS *= imageformats platforms platforminputcontexts platformthemes generic
qtHaveModule(widgets): SUBDIRS += accessible
!wince*:qtHaveModule(widgets): SUBDIRS += printsupport
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
index c2e9bd445f..f41d4f5047 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
@@ -86,6 +86,11 @@ QList<QPrinter::PaperSize> QCupsPrinterSupport::supportedPaperSizes(const QPrint
return QCUPSSupport::getCupsPrinterPaperSizes(printerIndex(printerInfo));
}
+QList<QPair<QString, QSizeF> > QCupsPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const
+{
+ return QCUPSSupport::getCupsPrinterPaperSizesWithNames(printerIndex(printerInfo));
+}
+
void QCupsPrinterSupport::loadCups()
{
cupsGetDests = (CupsGetDests) m_cups.resolve("cupsGetDests");
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
index 43fe871021..e9fe24203e 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
@@ -52,7 +52,6 @@
#include <cups/cups.h>
-QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
typedef int (*CupsGetDests)(cups_dest_t **dests);
@@ -68,6 +67,7 @@ public:
virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode);
virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode);
virtual QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const;
+ virtual QList<QPair<QString, QSizeF> > supportedSizesWithNames(const QPrinterInfo &) const;
virtual QString printerOption(const QPrinterInfo &printer, const QString &key) const;
virtual PrinterOptions printerOptions(const QPrinterInfo &printer) const;
@@ -86,7 +86,6 @@ private:
};
QT_END_NAMESPACE
-QT_END_HEADER
#endif // QT_NO_PRINTER
#endif // QCUPSPRINTERSUPPORT_H
diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp
index 469dbdb34e..36e7a3fb8e 100644
--- a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp
@@ -93,4 +93,9 @@ QList<QPrinter::PaperSize> QWindowsPrinterSupport::supportedPaperSizes(const QPr
return QWin32PrintEngine::supportedPaperSizes(printerInfo);
}
+QList<QPair<QString, QSizeF> >QWindowsPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const
+{
+ return QWin32PrintEngine::supportedSizesWithNames(printerInfo);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h
index afa341a82f..1d5a4f3da4 100644
--- a/src/plugins/printsupport/windows/qwindowsprintersupport.h
+++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h
@@ -44,7 +44,6 @@
#include <qpa/qplatformprintersupport.h>
-QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QWin32PrintEngine;
@@ -58,9 +57,9 @@ public:
virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode);
virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode);
virtual QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const;
+ virtual QList<QPair<QString, QSizeF> >supportedSizesWithNames(const QPrinterInfo &printerInfo) const;
};
QT_END_NAMESPACE
-QT_END_HEADER
#endif // WINDOWSPRINTERSUPPORT_H