summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp27
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h20
-rw-r--r--src/plugins/platforms/windows/qtwindows_additional.h4
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp54
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp124
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h8
7 files changed, 150 insertions, 90 deletions
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index 7eb1bd30c0..ce61a8b092 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -721,22 +721,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildI
if (varChildID.vt != VT_I4)
return E_INVALIDARG;
-
- int childIndex = varChildID.lVal;
-
- QAccessibleInterface *acc = 0;
-
-
- if (childIndex == 0) {
- // Yes, some AT clients (Active Accessibility Object Inspector)
- // actually ask for the same object. As a consequence, we need to clone ourselves:
- acc = accessible;
- } else if (childIndex < 0) {
- acc = QAccessible::accessibleInterface((QAccessible::Id)childIndex);
- } else {
- acc = accessible->child(childIndex - 1);
- }
-
+ QAccessibleInterface *acc = childPointer(accessible, varChildID);
if (acc) {
*ppdispChild = QWindowsAccessibility::wrap(acc);
return S_OK;
@@ -825,7 +810,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT var
QString descr;
if (varID.lVal) {
- QAccessibleInterface *child = childPointer(varID);
+ QAccessibleInterface *child = childPointer(accessible, varID);
if (!child)
return E_FAIL;
descr = child->text(QAccessible::Description);
@@ -850,7 +835,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BST
QString help;
if (varID.lVal) {
- QAccessibleInterface *child = childPointer(varID);
+ QAccessibleInterface *child = childPointer(accessible, varID);
if (!child)
return E_FAIL;
help = child->text(QAccessible::Help);
@@ -909,7 +894,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BST
QString name;
if (varID.lVal) {
- QAccessibleInterface *child = childPointer(varID);
+ QAccessibleInterface *child = childPointer(accessible, varID);
if (!child)
return E_FAIL;
name = child->text(QAccessible::Name);
@@ -952,7 +937,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VAR
QAccessible::Role role;
if (varID.lVal) {
- QAccessibleInterface *child = childPointer(varID);
+ QAccessibleInterface *child = childPointer(accessible, varID);
if (!child)
return E_FAIL;
role = child->role();
@@ -987,7 +972,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VA
QAccessible::State state;
if (varID.lVal) {
- QAccessibleInterface *child = childPointer(varID);
+ QAccessibleInterface *child = childPointer(accessible, varID);
if (!child)
return E_FAIL;
state = child->state();
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
index ef17acf3e9..d4f141c5d8 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
@@ -153,13 +153,23 @@ protected:
return 0;
}
- QAccessibleInterface *childPointer(VARIANT varID)
+ static QAccessibleInterface *childPointer(QAccessibleInterface *parent, VARIANT varID)
{
// -1 since windows API always uses 1 for the first child
- QAccessibleInterface *iface = accessibleInterface();
- if (iface)
- return accessibleInterface()->child(varID.lVal - 1);
- return 0;
+ Q_ASSERT(parent);
+
+ QAccessibleInterface *acc = 0;
+ int childIndex = varID.lVal;
+ if (childIndex == 0) {
+ // Yes, some AT clients (Active Accessibility Object Inspector)
+ // actually ask for the same object. As a consequence, we need to clone ourselves:
+ acc = parent;
+ } else if (childIndex < 0) {
+ acc = QAccessible::accessibleInterface((QAccessible::Id)childIndex);
+ } else {
+ acc = parent->child(childIndex - 1);
+ }
+ return acc;
}
private:
diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h
index 3b2e9787a2..49ddf3106b 100644
--- a/src/plugins/platforms/windows/qtwindows_additional.h
+++ b/src/plugins/platforms/windows/qtwindows_additional.h
@@ -49,6 +49,10 @@
# define WM_THEMECHANGED 0x031A
#endif
+#ifndef GWL_HWNDPARENT
+# define GWL_HWNDPARENT (-8)
+#endif
+
/* Complement the definitions and declarations missing
* when using MinGW or older Windows SDKs. */
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 3f4555a31f..872fd07729 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -842,9 +842,6 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::FocusOutEvent:
handleFocusEvent(et, platformWindow);
return true;
- case QtWindows::ShowEvent:
- platformWindow->handleShown();
- return false; // Indicate transient children should be shown by windows (SW_PARENTOPENING)
case QtWindows::HideEvent:
platformWindow->handleHidden();
return false;// Indicate transient children should be hidden by windows (SW_PARENTCLOSING)
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 5b84725edf..33b4eb4771 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -833,6 +833,7 @@ public:
bool hideFiltersDetails() const { return m_hideFiltersDetails; }
void setHideFiltersDetails(bool h) { m_hideFiltersDetails = h; }
void setDefaultSuffix(const QString &s);
+ inline bool hasDefaultSuffix() const { return m_hasDefaultSuffix; }
inline void setLabelText(QFileDialogOptions::DialogLabel l, const QString &text);
// Return the selected files for tracking in OnSelectionChanged().
@@ -857,6 +858,7 @@ public slots:
protected:
explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data);
bool init(const CLSID &clsId, const IID &iid);
+ void setDefaultSuffixSys(const QString &s);
inline IFileDialog * fileDialog() const { return m_fileDialog; }
static QString itemPath(IShellItem *item);
static QStringList libraryItemFolders(IShellItem *item);
@@ -873,12 +875,13 @@ private:
DWORD m_cookie;
QStringList m_nameFilters;
bool m_hideFiltersDetails;
+ bool m_hasDefaultSuffix;
QWindowsFileDialogSharedData m_data;
};
QWindowsNativeFileDialogBase::QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data) :
m_fileDialog(0), m_dialogEvents(0), m_cookie(0), m_hideFiltersDetails(false),
- m_data(data)
+ m_hasDefaultSuffix(false), m_data(data)
{
}
@@ -1188,6 +1191,15 @@ void QWindowsNativeFileDialogBase::setNameFilters(const QStringList &filters)
void QWindowsNativeFileDialogBase::setDefaultSuffix(const QString &s)
{
+ setDefaultSuffixSys(s);
+ m_hasDefaultSuffix = !s.isEmpty();
+}
+
+void QWindowsNativeFileDialogBase::setDefaultSuffixSys(const QString &s)
+{
+ // If this parameter is non-empty, it will be appended by the dialog for the 'Any files'
+ // filter ('*'). If this parameter is non-empty and the current filter has a suffix,
+ // the dialog will append the filter's suffix.
wchar_t *wSuffix = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(s.utf16()));
m_fileDialog->SetDefaultExtension(wSuffix);
}
@@ -1321,33 +1333,45 @@ HRESULT QWindowsNativeFileDialogEventHandler::OnFileOk(IFileDialog *)
class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase
{
+ Q_OBJECT
public:
- explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data) :
- QWindowsNativeFileDialogBase(data) {}
+ explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data);
virtual QStringList selectedFiles() const;
virtual QStringList dialogResult() const;
+
+private slots:
+ void slotFilterSelected(const QString &);
};
-// Append a suffix from the name filter "Foo files (*.foo;*.bar)"
-// unless the file name already has one.
-static inline QString appendSuffix(const QString &fileName, const QString &filter)
+// Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo".
+static inline QString suffixFromFilter(const QString &filter)
{
- const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
- const int lastSlash = fileName.lastIndexOf(QLatin1Char('/'));
- if (lastDot >= 0 && (lastSlash == -1 || lastDot > lastSlash))
- return fileName;
int suffixPos = filter.indexOf(QLatin1String("(*."));
if (suffixPos < 0)
- return fileName;
+ return QString();
suffixPos += 3;
int endPos = filter.indexOf(QLatin1Char(' '), suffixPos + 1);
if (endPos < 0)
endPos = filter.indexOf(QLatin1Char(';'), suffixPos + 1);
if (endPos < 0)
endPos = filter.indexOf(QLatin1Char(')'), suffixPos + 1);
- if (endPos < 0)
- return fileName;
- return fileName + QLatin1Char('.') + filter.mid(suffixPos, endPos - suffixPos);
+ return endPos >= 0 ? filter.mid(suffixPos, endPos - suffixPos) : QString();
+}
+
+QWindowsNativeSaveFileDialog::QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data)
+ : QWindowsNativeFileDialogBase(data)
+{
+ connect(this, &QWindowsNativeFileDialogBase::filterSelected,
+ this, &QWindowsNativeSaveFileDialog::slotFilterSelected);
+}
+
+void QWindowsNativeSaveFileDialog::slotFilterSelected(const QString &filter)
+{
+ // Cause the dialog to append the suffix of the current filter unless a default
+ // suffix is set (Note: Qt 4.8 sets the selected filter's suffix before
+ // calling GetSaveFileName()).
+ if (!hasDefaultSuffix())
+ setDefaultSuffixSys(suffixFromFilter(filter));
}
QStringList QWindowsNativeSaveFileDialog::dialogResult() const
@@ -1355,7 +1379,7 @@ QStringList QWindowsNativeSaveFileDialog::dialogResult() const
QStringList result;
IShellItem *item = 0;
if (SUCCEEDED(fileDialog()->GetResult(&item)) && item)
- result.push_back(appendSuffix(QWindowsNativeFileDialogBase::itemPath(item), selectedNameFilter()));
+ result.push_back(QWindowsNativeFileDialogBase::itemPath(item));
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 2a5e08cf41..010197d6d8 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -839,6 +839,15 @@ QWindowsWindow::~QWindowsWindow()
destroyIcon();
}
+void QWindowsWindow::fireExpose(const QRegion &region, bool force)
+{
+ if (region.isEmpty() && !force)
+ clearFlag(Exposed);
+ else
+ setFlag(Exposed);
+ QWindowSystemInterface::handleExposeEvent(window(), region);
+}
+
void QWindowsWindow::destroyWindow()
{
if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
@@ -942,13 +951,19 @@ void QWindowsWindow::setVisible(bool visible)
if (m_data.hwnd) {
if (visible) {
show_sys();
- QWindowSystemInterface::handleExposeEvent(window(),
- QRect(QPoint(), geometry().size()));
+
+ // When the window is layered, we won't get WM_PAINT, and "we" are in control
+ // over the rendering of the window
+ // There is nobody waiting for this, so we don't need to flush afterwards.
+ QWindow *w = window();
+ if (w->format().hasAlpha() || qFuzzyCompare(w->opacity(), qreal(1)))
+ fireExpose(QRect(0, 0, w->width(), w->height()));
+
} else {
if (hasMouseCapture())
setMouseGrabEnabled(false);
hide_sys();
- QWindowSystemInterface::handleExposeEvent(window(), QRegion());
+ fireExpose(QRegion());
}
}
}
@@ -998,6 +1013,24 @@ QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const
return pos;
}
+// Update the transient parent for a toplevel window. The concept does not
+// really exist on Windows, the relationship is set by passing a parent along with !WS_CHILD
+// to window creation or by setting the parent using GWL_HWNDPARENT (as opposed to
+// SetParent, which would make it a real child).
+void QWindowsWindow::updateTransientParent() const
+{
+#ifndef Q_OS_WINCE
+ // Update transient parent.
+ const HWND oldTransientParent =
+ GetAncestor(m_data.hwnd, GA_PARENT) == GetDesktopWindow() ? GetAncestor(m_data.hwnd, GA_ROOTOWNER) : HWND(0);
+ HWND newTransientParent = 0;
+ if (const QWindow *tp = window()->transientParent())
+ newTransientParent = QWindowsWindow::handleOf(tp);
+ if (newTransientParent && newTransientParent != oldTransientParent)
+ SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, (LONG_PTR)newTransientParent);
+#endif // !Q_OS_WINCE
+}
+
// partially from QWidgetPrivate::show_sys()
void QWindowsWindow::show_sys() const
{
@@ -1012,19 +1045,22 @@ void QWindowsWindow::show_sys() const
sm = SW_SHOWMINIMIZED;
if (!isVisible())
sm = SW_SHOWMINNOACTIVE;
- } else if (state & Qt::WindowMaximized) {
- sm = SW_SHOWMAXIMIZED;
- // Windows will not behave correctly when we try to maximize a window which does not
- // have minimize nor maximize buttons in the window frame. Windows would then ignore
- // non-available geometry, and rather maximize the widget to the full screen, minus the
- // window frame (caption). So, we do a trick here, by adding a maximize button before
- // maximizing the widget, and then remove the maximize button afterwards.
- if (flags & Qt::WindowTitleHint &&
- !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
- fakedMaximize = TRUE;
- setStyle(style() | WS_MAXIMIZEBOX);
- }
- }
+ } else {
+ updateTransientParent();
+ if (state & Qt::WindowMaximized) {
+ sm = SW_SHOWMAXIMIZED;
+ // Windows will not behave correctly when we try to maximize a window which does not
+ // have minimize nor maximize buttons in the window frame. Windows would then ignore
+ // non-available geometry, and rather maximize the widget to the full screen, minus the
+ // window frame (caption). So, we do a trick here, by adding a maximize button before
+ // maximizing the widget, and then remove the maximize button afterwards.
+ if (flags & Qt::WindowTitleHint &&
+ !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
+ fakedMaximize = TRUE;
+ setStyle(style() | WS_MAXIMIZEBOX);
+ }
+ } // Qt::WindowMaximized
+ } // !Qt::WindowMinimized
}
if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool)
sm = SW_SHOWNOACTIVATE;
@@ -1094,14 +1130,9 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
}
}
-void QWindowsWindow::handleShown()
-{
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
-}
-
void QWindowsWindow::handleHidden()
{
- QWindowSystemInterface::handleExposeEvent(window(), QRegion());
+ fireExpose(QRegion());
}
void QWindowsWindow::setGeometry(const QRect &rectIn)
@@ -1267,28 +1298,21 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
if (message == WM_ERASEBKGND) // Backing store - ignored.
return true;
PAINTSTRUCT ps;
- if (testFlag(OpenGLSurface)) {
- // Observed painting problems with Aero style disabled (QTBUG-7865).
- if (testFlag(OpenGLDoubleBuffered))
- InvalidateRect(hwnd, 0, false);
- BeginPaint(hwnd, &ps);
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(qrectFromRECT(ps.rcPaint)));
- if (!QWindowsContext::instance()->asyncExpose())
- QWindowSystemInterface::flushWindowSystemEvents();
- EndPaint(hwnd, &ps);
- } else {
- BeginPaint(hwnd, &ps);
- const QRect updateRect = qrectFromRECT(ps.rcPaint);
+ // Observed painting problems with Aero style disabled (QTBUG-7865).
+ if (testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered))
+ InvalidateRect(hwnd, 0, false);
- if (QWindowsContext::verboseIntegration)
- qDebug() << __FUNCTION__ << this << window() << updateRect;
+ BeginPaint(hwnd, &ps);
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(updateRect));
- if (!QWindowsContext::instance()->asyncExpose())
- QWindowSystemInterface::flushWindowSystemEvents();
- EndPaint(hwnd, &ps);
- }
+ // If the a window is obscured by another window (such as a child window)
+ // we still need to send isExposed=true, for compatibility.
+ // Our tests depend on it.
+ fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true);
+ if (!QWindowsContext::instance()->asyncExpose())
+ QWindowSystemInterface::flushWindowSystemEvents();
+
+ EndPaint(hwnd, &ps);
return true;
}
@@ -1366,9 +1390,23 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
}
}
+// Return the effective screen for full screen mode in a virtual desktop.
+static const QScreen *effectiveScreen(const QWindow *w)
+{
+ QPoint center = w->geometry().center();
+ if (!w->isTopLevel())
+ center = w->mapToGlobal(center);
+ const QScreen *screen = w->screen();
+ if (!screen->geometry().contains(center))
+ foreach (const QScreen *sibling, screen->virtualSiblings())
+ if (sibling->geometry().contains(center))
+ return sibling;
+ return screen;
+}
+
bool QWindowsWindow::isFullScreen_sys() const
{
- return geometry_sys() == window()->screen()->geometry();
+ return geometry_sys() == effectiveScreen(window())->geometry();
}
/*!
@@ -1444,7 +1482,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
newStyle |= WS_VISIBLE;
setStyle(newStyle);
- const QRect r = window()->screen()->geometry();
+ const QRect r = effectiveScreen(window())->geometry();
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 2117ca50b8..6c735ede7d 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -133,7 +133,8 @@ public:
WithinSetStyle = 0x800,
WithinDestroy = 0x1000,
TouchRegistered = 0x2000,
- AlertState = 0x4000
+ AlertState = 0x4000,
+ Exposed = 0x08000
};
struct WindowData
@@ -161,7 +162,7 @@ public:
virtual void setVisible(bool visible);
bool isVisible() const;
- virtual bool isExposed() const { return m_windowState != Qt::WindowMinimized && isVisible(); }
+ virtual bool isExposed() const { return testFlag(Exposed); }
virtual bool isActive() const;
virtual bool isEmbedded(const QPlatformWindow *parentWindow) const;
virtual QPoint mapToGlobal(const QPoint &pos) const;
@@ -217,7 +218,6 @@ public:
void handleMoved();
void handleResized(int wParam);
- void handleShown();
void handleHidden();
static inline HWND handleOf(const QWindow *w);
@@ -272,12 +272,14 @@ private:
inline bool isFullScreen_sys() const;
inline void setWindowState_sys(Qt::WindowState newState);
inline void setParent_sys(const QPlatformWindow *parent) const;
+ inline void updateTransientParent() const;
void destroyWindow();
void registerDropSite();
void unregisterDropSite();
void handleGeometryChange();
void handleWindowStateChange(Qt::WindowState state);
inline void destroyIcon();
+ void fireExpose(const QRegion &region, bool force=false);
mutable WindowData m_data;
mutable unsigned m_flags;