Windows QPA: Detect screen by mouse position when dragging a window

When dragging a window by its border, detect the screen by mouse position
to prevent it from oscillating between screens when it resizes.

Task-number: QTBUG-62971
Change-Id: I0a4a584ef8ff3bb7288d1abec4de51fb4091dccd
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
bb10
Friedemann Kleint 2017-09-19 13:18:49 +02:00
parent bd72ead4d1
commit f1ec81b543
4 changed files with 39 additions and 11 deletions

View File

@ -101,6 +101,8 @@ enum WindowsEventType // Simplify event types
FocusOutEvent = WindowEventFlag + 18,
WhatsThisEvent = WindowEventFlag + 19,
DpiChangedEvent = WindowEventFlag + 21,
EnterSizeMoveEvent = WindowEventFlag + 22,
ExitSizeMoveEvent = WindowEventFlag + 23,
MouseEvent = MouseEventFlag + 1,
MouseWheelEvent = MouseEventFlag + 2,
CursorEvent = MouseEventFlag + 3,
@ -274,6 +276,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::DeviceChangeEvent;
case WM_DPICHANGED:
return QtWindows::DpiChangedEvent;
case WM_ENTERSIZEMOVE:
return QtWindows::EnterSizeMoveEvent;
case WM_EXITSIZEMOVE:
return QtWindows::ExitSizeMoveEvent;
default:
break;
}

View File

@ -1055,6 +1055,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
#endif
break;
case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
return true;
case QtWindows::ExitSizeMoveEvent:
platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
platformWindow->checkForScreenChanged();
return true;
case QtWindows::ScrollEvent:
#if QT_CONFIG(sessionmanager)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);

View File

@ -1527,6 +1527,26 @@ void QWindowsWindow::handleResized(int wParam)
}
}
void QWindowsWindow::checkForScreenChanged()
{
if (parent())
return;
QPlatformScreen *currentScreen = screen();
const auto &screenManager = QWindowsContext::instance()->screenManager();
// QTBUG-62971: When dragging a window by its border, detect by mouse position
// to prevent it from oscillating between screens when it resizes
const QWindowsScreen *newScreen = testFlag(ResizeMoveActive)
? screenManager.screenAtDp(QWindowsCursor::mousePosition())
: screenManager.screenForHwnd(m_data.hwnd);
if (newScreen != nullptr && newScreen != currentScreen) {
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << currentScreen->name()
<< "\"->\"" << newScreen->name() << '"';
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
}
void QWindowsWindow::handleGeometryChange()
{
const QRect previousGeometry = m_data.geometry;
@ -1541,17 +1561,9 @@ void QWindowsWindow::handleGeometryChange()
&& !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true);
}
if (!parent() && previousGeometry.topLeft() != m_data.geometry.topLeft()) {
QPlatformScreen *currentScreen = screen();
const QWindowsScreen *newScreen =
QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd);
if (newScreen != nullptr && newScreen != currentScreen) {
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << currentScreen->name()
<< "\"->\"" << newScreen->name() << '"';
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
}
checkForScreenChanged();
if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);

View File

@ -208,6 +208,7 @@ public:
Compositing = 0x200000,
HasBorderInFullScreen = 0x400000,
WithinDpiChanged = 0x800000,
ResizeMoveActive = 0x2000000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@ -313,6 +314,8 @@ public:
void alertWindow(int durationMs = 0);
void stopAlertWindow();
void checkForScreenChanged();
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);