Introduce QPA API for size grip handling.
- Introduce API to do size grip handling (mouse press and move). - Move Windows code to Windows plugin. - Move X11 code to XCB plugin and activate it. Change-Id: I2f61d6ddc1fa07447e668554d41ecc820efca23f Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
This commit is contained in:
parent
1539e8e310
commit
0137f092af
@ -117,6 +117,8 @@ public:
|
|||||||
|
|
||||||
virtual void windowEvent(QEvent *event);
|
virtual void windowEvent(QEvent *event);
|
||||||
|
|
||||||
|
virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QScopedPointer<QPlatformWindowPrivate> d_ptr;
|
QScopedPointer<QPlatformWindowPrivate> d_ptr;
|
||||||
private:
|
private:
|
||||||
|
@ -335,6 +335,23 @@ void QPlatformWindow::windowEvent(QEvent *event)
|
|||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Reimplement this method to start a system size grip drag
|
||||||
|
operation if the system supports it and return true to indicate
|
||||||
|
success.
|
||||||
|
It is called from the mouse press event handler of the size grip.
|
||||||
|
|
||||||
|
The default implementation is empty and does nothing with \a pos
|
||||||
|
and \a corner.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
||||||
|
{
|
||||||
|
Q_UNUSED(pos)
|
||||||
|
Q_UNUSED(corner)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QPlatformWindow
|
\class QPlatformWindow
|
||||||
\since 4.8
|
\since 4.8
|
||||||
|
@ -151,6 +151,16 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
compressMouseMove(&msg);
|
compressMouseMove(&msg);
|
||||||
|
// Eat mouse move after size grip drag.
|
||||||
|
if (msg.message == WM_MOUSEMOVE) {
|
||||||
|
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
|
||||||
|
if (platformWindow->testFlag(QWindowsWindow::SizeGripOperation)) {
|
||||||
|
MSG mouseMsg;
|
||||||
|
while (PeekMessage(&mouseMsg, platformWindow->handle(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) ;
|
||||||
|
platformWindow->clearFlag(QWindowsWindow::SizeGripOperation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
const QPoint client(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
|
const QPoint client(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
|
||||||
// Enter new window: track to generate leave event.
|
// Enter new window: track to generate leave event.
|
||||||
if (m_windowUnderMouse != window) {
|
if (m_windowUnderMouse != window) {
|
||||||
|
@ -1402,6 +1402,32 @@ void QWindowsWindow::setMouseGrabEnabled_sys(bool grab)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline DWORD cornerToWinOrientation(Qt::Corner corner)
|
||||||
|
{
|
||||||
|
switch (corner) {
|
||||||
|
case Qt::TopLeftCorner:
|
||||||
|
return 0xf004; // SZ_SIZETOPLEFT;
|
||||||
|
case Qt::TopRightCorner:
|
||||||
|
return 0xf005; // SZ_SIZETOPRIGHT
|
||||||
|
case Qt::BottomLeftCorner:
|
||||||
|
return 0xf007; // SZ_SIZEBOTTOMLEFT
|
||||||
|
case Qt::BottomRightCorner:
|
||||||
|
return 0xf008; // SZ_SIZEBOTTOMRIGHT
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
|
||||||
|
{
|
||||||
|
if (!GetSystemMenu(m_data.hwnd, FALSE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReleaseCapture();
|
||||||
|
PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
|
||||||
|
setFlag(SizeGripOperation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
|
#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
|
||||||
void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
|
void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
|
||||||
{
|
{
|
||||||
|
@ -122,7 +122,8 @@ public:
|
|||||||
OpenGLSurface = 0x10,
|
OpenGLSurface = 0x10,
|
||||||
OpenGLDoubleBuffered = 0x20,
|
OpenGLDoubleBuffered = 0x20,
|
||||||
OpenGlPixelFormatInitialized = 0x40,
|
OpenGlPixelFormatInitialized = 0x40,
|
||||||
BlockedByModal = 0x80
|
BlockedByModal = 0x80,
|
||||||
|
SizeGripOperation = 0x100
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WindowData
|
struct WindowData
|
||||||
@ -173,6 +174,8 @@ public:
|
|||||||
virtual bool setKeyboardGrabEnabled(bool grab);
|
virtual bool setKeyboardGrabEnabled(bool grab);
|
||||||
virtual bool setMouseGrabEnabled(bool grab);
|
virtual bool setMouseGrabEnabled(bool grab);
|
||||||
|
|
||||||
|
virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
|
||||||
|
|
||||||
Qt::WindowState windowState_sys() const;
|
Qt::WindowState windowState_sys() const;
|
||||||
Qt::WindowStates windowStates_sys() const;
|
Qt::WindowStates windowStates_sys() const;
|
||||||
|
|
||||||
|
@ -1670,4 +1670,37 @@ void QXcbWindow::setCursor(xcb_cursor_t cursor)
|
|||||||
xcb_flush(xcb_connection());
|
xcb_flush(xcb_connection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XCB_USE_XLIB
|
||||||
|
|
||||||
|
bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
|
||||||
|
{
|
||||||
|
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
|
||||||
|
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
|
||||||
|
return false;
|
||||||
|
XEvent xev;
|
||||||
|
xev.xclient.type = ClientMessage;
|
||||||
|
xev.xclient.message_type = moveResize;
|
||||||
|
Display *display = (Display *)connection()->xlib_display();
|
||||||
|
xev.xclient.display = display;
|
||||||
|
xev.xclient.window = xcb_window();
|
||||||
|
xev.xclient.format = 32;
|
||||||
|
const QPoint globalPos = window()->mapToGlobal(pos);
|
||||||
|
xev.xclient.data.l[0] = globalPos.x();
|
||||||
|
xev.xclient.data.l[1] = globalPos.y();
|
||||||
|
const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
|
||||||
|
const bool left = corner == Qt::BottomLeftCorner || corner == Qt::TopLeftCorner;
|
||||||
|
if (bottom)
|
||||||
|
xev.xclient.data.l[2] = left ? 6 : 4; // bottomleft/bottomright
|
||||||
|
else
|
||||||
|
xev.xclient.data.l[2] = left ? 0 : 2; // topleft/topright
|
||||||
|
xev.xclient.data.l[3] = Button1;
|
||||||
|
xev.xclient.data.l[4] = 0;
|
||||||
|
XUngrabPointer(display, CurrentTime);
|
||||||
|
XSendEvent(display, m_screen->root(), False,
|
||||||
|
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XCB_USE_XLIB
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -107,6 +107,10 @@ public:
|
|||||||
|
|
||||||
QSurfaceFormat format() const;
|
QSurfaceFormat format() const;
|
||||||
|
|
||||||
|
#ifdef XCB_USE_XLIB
|
||||||
|
bool startSystemResize(const QPoint &pos, Qt::Corner corner);
|
||||||
|
#endif // XCB_USE_XLIB
|
||||||
|
|
||||||
xcb_window_t xcb_window() const { return m_window; }
|
xcb_window_t xcb_window() const { return m_window; }
|
||||||
uint depth() const { return m_depth; }
|
uint depth() const { return m_depth; }
|
||||||
QImage::Format imageFormat() const { return m_imageFormat; }
|
QImage::Format imageFormat() const { return m_imageFormat; }
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
#include "qapplication.h"
|
#include "qapplication.h"
|
||||||
#include "qevent.h"
|
#include "qevent.h"
|
||||||
#include "qpainter.h"
|
#include "qpainter.h"
|
||||||
|
#include "qwindow.h"
|
||||||
|
#include <qpa/qplatformwindow.h>
|
||||||
#include "qstyle.h"
|
#include "qstyle.h"
|
||||||
#include "qstyleoption.h"
|
#include "qstyleoption.h"
|
||||||
#include "qlayout.h"
|
#include "qlayout.h"
|
||||||
@ -59,23 +61,8 @@
|
|||||||
#include <private/qwidget_p.h>
|
#include <private/qwidget_p.h>
|
||||||
#include <QtWidgets/qabstractscrollarea.h>
|
#include <QtWidgets/qabstractscrollarea.h>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
# include <QtCore/qt_windows.h>
|
|
||||||
# include "private/qapplication_p.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#if defined (Q_OS_WIN)
|
|
||||||
# define SZ_SIZEBOTTOMRIGHT 0xf008
|
|
||||||
# define SZ_SIZEBOTTOMLEFT 0xf007
|
|
||||||
# define SZ_SIZETOPLEFT 0xf004
|
|
||||||
# define SZ_SIZETOPRIGHT 0xf005
|
|
||||||
|
|
||||||
HMENU qt_getWindowsSystemMenu(const QWidget *w);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static QWidget *qt_sizegrip_topLevelWidget(QWidget* w)
|
static QWidget *qt_sizegrip_topLevelWidget(QWidget* w)
|
||||||
{
|
{
|
||||||
while (w && !w->isWindow() && w->windowType() != Qt::SubWindow)
|
while (w && !w->isWindow() && w->windowType() != Qt::SubWindow)
|
||||||
@ -87,6 +74,7 @@ class QSizeGripPrivate : public QWidgetPrivate
|
|||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QSizeGrip)
|
Q_DECLARE_PUBLIC(QSizeGrip)
|
||||||
public:
|
public:
|
||||||
|
QSizeGripPrivate();
|
||||||
void init();
|
void init();
|
||||||
QPoint p;
|
QPoint p;
|
||||||
QRect r;
|
QRect r;
|
||||||
@ -143,8 +131,19 @@ public:
|
|||||||
if (showSizeGrip)
|
if (showSizeGrip)
|
||||||
q->setVisible(true);
|
q->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool m_platformSizeGrip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QSizeGripPrivate::QSizeGripPrivate()
|
||||||
|
: dxMax(0)
|
||||||
|
, dyMax(0)
|
||||||
|
, gotMousePress(false)
|
||||||
|
, tlw(0)
|
||||||
|
, m_platformSizeGrip(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
void QSizeGripPrivate::updateMacSizer(bool hide) const
|
void QSizeGripPrivate::updateMacSizer(bool hide) const
|
||||||
{
|
{
|
||||||
@ -226,11 +225,7 @@ QSizeGrip::QSizeGrip(QWidget * parent)
|
|||||||
void QSizeGripPrivate::init()
|
void QSizeGripPrivate::init()
|
||||||
{
|
{
|
||||||
Q_Q(QSizeGrip);
|
Q_Q(QSizeGrip);
|
||||||
dxMax = 0;
|
|
||||||
dyMax = 0;
|
|
||||||
tlw = 0;
|
|
||||||
m_corner = q->isLeftToRight() ? Qt::BottomRightCorner : Qt::BottomLeftCorner;
|
m_corner = q->isLeftToRight() ? Qt::BottomRightCorner : Qt::BottomLeftCorner;
|
||||||
gotMousePress = false;
|
|
||||||
|
|
||||||
#if !defined(QT_NO_CURSOR) && !defined(Q_WS_MAC)
|
#if !defined(QT_NO_CURSOR) && !defined(Q_WS_MAC)
|
||||||
q->setCursor(m_corner == Qt::TopLeftCorner || m_corner == Qt::BottomRightCorner
|
q->setCursor(m_corner == Qt::TopLeftCorner || m_corner == Qt::BottomRightCorner
|
||||||
@ -284,6 +279,7 @@ void QSizeGrip::paintEvent(QPaintEvent *event)
|
|||||||
resize operation. The mouse press event is passed in the \a event
|
resize operation. The mouse press event is passed in the \a event
|
||||||
parameter.
|
parameter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void QSizeGrip::mousePressEvent(QMouseEvent * e)
|
void QSizeGrip::mousePressEvent(QMouseEvent * e)
|
||||||
{
|
{
|
||||||
if (e->button() != Qt::LeftButton) {
|
if (e->button() != Qt::LeftButton) {
|
||||||
@ -297,44 +293,20 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
|
|||||||
d->gotMousePress = true;
|
d->gotMousePress = true;
|
||||||
d->r = tlw->geometry();
|
d->r = tlw->geometry();
|
||||||
|
|
||||||
#ifdef Q_WS_X11
|
// Does the platform provide size grip support?
|
||||||
// Use a native X11 sizegrip for "real" top-level windows if supported.
|
d->m_platformSizeGrip = false;
|
||||||
if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE))
|
if (tlw->isWindow()
|
||||||
|
&& tlw->windowHandle()
|
||||||
&& !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)
|
&& !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)
|
||||||
&& !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !tlw->hasHeightForWidth()) {
|
&& !tlw->testAttribute(Qt::WA_DontShowOnScreen)
|
||||||
XEvent xev;
|
&& !tlw->hasHeightForWidth()) {
|
||||||
xev.xclient.type = ClientMessage;
|
QPlatformWindow *platformWindow = tlw->windowHandle()->handle();
|
||||||
xev.xclient.message_type = ATOM(_NET_WM_MOVERESIZE);
|
const QPoint topLevelPos = mapTo(tlw, e->pos());
|
||||||
xev.xclient.display = X11->display;
|
d->m_platformSizeGrip = platformWindow && platformWindow->startSystemResize(topLevelPos, d->m_corner);
|
||||||
xev.xclient.window = tlw->winId();
|
|
||||||
xev.xclient.format = 32;
|
|
||||||
xev.xclient.data.l[0] = e->globalPos().x();
|
|
||||||
xev.xclient.data.l[1] = e->globalPos().y();
|
|
||||||
if (d->atBottom())
|
|
||||||
xev.xclient.data.l[2] = d->atLeft() ? 6 : 4; // bottomleft/bottomright
|
|
||||||
else
|
|
||||||
xev.xclient.data.l[2] = d->atLeft() ? 0 : 2; // topleft/topright
|
|
||||||
xev.xclient.data.l[3] = Button1;
|
|
||||||
xev.xclient.data.l[4] = 0;
|
|
||||||
XUngrabPointer(X11->display, X11->time);
|
|
||||||
XSendEvent(X11->display, QX11Info::appRootWindow(x11Info().screen()), False,
|
|
||||||
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif // Q_WS_X11
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !tlw->hasHeightForWidth()) {
|
|
||||||
uint orientation = 0;
|
|
||||||
if (d->atBottom())
|
|
||||||
orientation = d->atLeft() ? SZ_SIZEBOTTOMLEFT : SZ_SIZEBOTTOMRIGHT;
|
|
||||||
else
|
|
||||||
orientation = d->atLeft() ? SZ_SIZETOPLEFT : SZ_SIZETOPRIGHT;
|
|
||||||
|
|
||||||
ReleaseCapture();
|
if (d->m_platformSizeGrip)
|
||||||
PostMessage(QApplicationPrivate::getHWNDForWidget(tlw), WM_SYSCOMMAND, orientation, 0);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
|
|
||||||
// Find available desktop/workspace geometry.
|
// Find available desktop/workspace geometry.
|
||||||
QRect availableGeometry;
|
QRect availableGeometry;
|
||||||
@ -400,32 +372,16 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
|
|||||||
*/
|
*/
|
||||||
void QSizeGrip::mouseMoveEvent(QMouseEvent * e)
|
void QSizeGrip::mouseMoveEvent(QMouseEvent * e)
|
||||||
{
|
{
|
||||||
if (e->buttons() != Qt::LeftButton) {
|
Q_D(QSizeGrip);
|
||||||
|
if (e->buttons() != Qt::LeftButton || d->m_platformSizeGrip) {
|
||||||
QWidget::mouseMoveEvent(e);
|
QWidget::mouseMoveEvent(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_D(QSizeGrip);
|
|
||||||
QWidget* tlw = qt_sizegrip_topLevelWidget(this);
|
QWidget* tlw = qt_sizegrip_topLevelWidget(this);
|
||||||
if (!d->gotMousePress || tlw->testAttribute(Qt::WA_WState_ConfigPending))
|
if (!d->gotMousePress || tlw->testAttribute(Qt::WA_WState_ConfigPending))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef Q_WS_X11
|
|
||||||
if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE))
|
|
||||||
&& tlw->isTopLevel() && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)
|
|
||||||
&& !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !tlw->hasHeightForWidth())
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
if (tlw->isWindow() && qt_getWindowsSystemMenu(tlw) && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !tlw->hasHeightForWidth()) {
|
|
||||||
if (const HWND hwnd = QApplicationPrivate::getHWNDForWidget(tlw)) {
|
|
||||||
MSG msg;
|
|
||||||
while (PeekMessage(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) ;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QPoint np(e->globalPos());
|
QPoint np(e->globalPos());
|
||||||
|
|
||||||
// Don't extend beyond the available geometry; bound to dyMax and dxMax.
|
// Don't extend beyond the available geometry; bound to dyMax and dxMax.
|
||||||
|
Loading…
Reference in New Issue
Block a user