diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 161 |
1 files changed, 58 insertions, 103 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index affc2a0dd6..475a4e37f3 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -51,6 +51,7 @@ #include "qxcbscreen.h" #include "qxcbdrag.h" #include "qxcbkeyboard.h" +#include "qxcbimage.h" #include "qxcbwmsupport.h" #include "qxcbimage.h" #include "qxcbnativeinterface.h" @@ -176,80 +177,23 @@ static inline bool isTransient(const QWindow *w) || w->type() == Qt::Popup; } -static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask, bool *rgbSwap) +void QXcbWindow::setImageFormatForVisual(const xcb_visualtype_t *visual) { - if (rgbSwap) - *rgbSwap = false; - switch (depth) { - case 32: - if (blue_mask == 0xff) - return QImage::Format_ARGB32_Premultiplied; - if (red_mask == 0x3ff) - return QImage::Format_A2BGR30_Premultiplied; - if (blue_mask == 0x3ff) - return QImage::Format_A2RGB30_Premultiplied; - if (red_mask == 0xff) { - if (rgbSwap) - *rgbSwap = true; - return QImage::Format_ARGB32_Premultiplied; - } - break; - case 30: - if (red_mask == 0x3ff) - return QImage::Format_BGR30; - if (blue_mask == 0x3ff) - return QImage::Format_RGB30; - break; - case 24: - if (blue_mask == 0xff) - return QImage::Format_RGB32; - if (red_mask == 0xff) { - if (rgbSwap) - *rgbSwap = true; - return QImage::Format_RGB32; - } - break; - case 16: - if (blue_mask == 0x1f) - return QImage::Format_RGB16; - if (red_mask == 0x1f) { - if (rgbSwap) - *rgbSwap = true; - return QImage::Format_RGB16; - } - break; - case 15: - if (blue_mask == 0x1f) - return QImage::Format_RGB555; - if (red_mask == 0x1f) { - if (rgbSwap) - *rgbSwap = true; - return QImage::Format_RGB555; - } - break; -#if QT_CONFIG(xcb_native_painting) - case 8: - if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled()) - return QImage::Format_Indexed8; - break; -#endif - default: - break; - } - qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask); + if (qt_xcb_imageFormatForVisual(connection(), m_depth, visual, &m_imageFormat, &m_imageRgbSwap)) + return; - switch (depth) { + switch (m_depth) { + case 32: case 24: qWarning("Using RGB32 fallback, if this works your X11 server is reporting a bad screen format."); - return QImage::Format_RGB32; + m_imageFormat = QImage::Format_RGB32; + break; case 16: qWarning("Using RGB16 fallback, if this works your X11 server is reporting a bad screen format."); - return QImage::Format_RGB16; + m_imageFormat = QImage::Format_RGB16; default: break; } - - return QImage::Format_Invalid; } static inline bool positionIncludesFrame(QWindow *w) @@ -287,7 +231,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) if (!mapper || errCode < 0) { mapper = QTextCodec::codecForName("latin1"); if (!mapper || !mapper->canEncode(s)) - return Q_NULLPTR; + return nullptr; #endif static QByteArray qcs; qcs = s.toLatin1(); @@ -322,7 +266,7 @@ static QWindow *childWindowAt(QWindow *win, const QPoint &p) && win->geometry().contains(win->parent()->mapFromGlobal(p))) { return win; } - return Q_NULLPTR; + return nullptr; } static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; @@ -381,7 +325,7 @@ void QXcbWindow::create() } if (!visual) visual = platformScreen->visualForId(m_visualId); - m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); + setImageFormatForVisual(visual); connection()->addWindowEventListener(m_window, this); return; } @@ -418,7 +362,7 @@ void QXcbWindow::create() resolveFormat(platformScreen->surfaceFormatFor(window()->requestedFormat())); - const xcb_visualtype_t *visual = Q_NULLPTR; + const xcb_visualtype_t *visual = nullptr; if (connection()->hasDefaultVisualId()) { visual = platformScreen->visualForId(connection()->defaultVisualId()); @@ -451,7 +395,7 @@ void QXcbWindow::create() m_visualId = visual->visual_id; m_depth = platformScreen->depthOfVisual(m_visualId); - m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); + setImageFormatForVisual(visual); quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL @@ -641,7 +585,7 @@ void QXcbWindow::destroy() if (connection()->focusWindow() == this) doFocusOut(); if (connection()->mouseGrabber() == this) - connection()->setMouseGrabber(Q_NULLPTR); + connection()->setMouseGrabber(nullptr); if (m_syncCounter && m_usingSyncProtocol) xcb_sync_destroy_counter(xcb_connection(), m_syncCounter); @@ -877,12 +821,12 @@ void QXcbWindow::hide() xcb_flush(xcb_connection()); if (connection()->mouseGrabber() == this) - connection()->setMouseGrabber(Q_NULLPTR); + connection()->setMouseGrabber(nullptr); if (QPlatformWindow *w = connection()->mousePressWindow()) { // Unset mousePressWindow when it (or one of its parents) is unmapped while (w) { if (w == this) { - connection()->setMousePressWindow(Q_NULLPTR); + connection()->setMousePressWindow(nullptr); break; } w = w->parent(); @@ -900,7 +844,7 @@ void QXcbWindow::hide() // Find the top level window at cursor position. // Don't use QGuiApplication::topLevelAt(): search only the virtual siblings of this window's screen - QWindow *enterWindow = Q_NULLPTR; + QWindow *enterWindow = nullptr; const auto screens = xcbScreen()->virtualSiblings(); for (QPlatformScreen *screen : screens) { if (screen->geometry().contains(cursorPos)) { @@ -1998,13 +1942,14 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even return; if (event->type == atom(QXcbAtom::WM_PROTOCOLS)) { - if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) { + xcb_atom_t protocolAtom = event->data.data32[0]; + if (protocolAtom == atom(QXcbAtom::WM_DELETE_WINDOW)) { QWindowSystemInterface::handleCloseEvent(window()); - } else if (event->data.data32[0] == atom(QXcbAtom::WM_TAKE_FOCUS)) { + } else if (protocolAtom == atom(QXcbAtom::WM_TAKE_FOCUS)) { connection()->setTime(event->data.data32[1]); relayFocusToModalWindow(); return; - } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) { + } else if (protocolAtom == atom(QXcbAtom::_NET_WM_PING)) { if (event->window == xcbScreen()->root()) return; @@ -2013,20 +1958,23 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even reply.response_type = XCB_CLIENT_MESSAGE; reply.window = xcbScreen()->root(); - xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&reply); xcb_flush(xcb_connection()); - } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) { + } else if (protocolAtom == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) { connection()->setTime(event->data.data32[1]); m_syncValue.lo = event->data.data32[2]; m_syncValue.hi = event->data.data32[3]; if (m_usingSyncProtocol) m_syncState = SyncReceived; #ifndef QT_NO_WHATSTHIS - } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) { + } else if (protocolAtom == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) { QWindowSystemInterface::handleEnterWhatsThisEvent(); #endif } else { - qWarning() << "QXcbWindow: Unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]); + qCWarning(lcQpaXcb, "Unhandled WM_PROTOCOLS (%s)", + connection()->atomName(protocolAtom).constData()); } #ifndef QT_NO_DRAGANDDROP } else if (event->type == atom(QXcbAtom::XdndEnter)) { @@ -2054,7 +2002,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even || event->type == atom(QXcbAtom::_GTK_LOAD_ICONTHEMES)) { //silence the _COMPIZ and _GTK messages for now } else { - qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type); + qCWarning(lcQpaXcb) << "Unhandled client message: " << connection()->atomName(event->type); } } @@ -2163,7 +2111,8 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) } void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, - int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source) + int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, + QEvent::Type type, Qt::MouseEventSource source) { const bool isWheel = detail >= 4 && detail <= 7; if (!isWheel && window() != QGuiApplication::focusWindow()) { @@ -2212,11 +2161,12 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in connection()->setMousePressWindow(this); - handleMouseEvent(timestamp, local, global, modifiers, source); + handleMouseEvent(timestamp, local, global, modifiers, type, source); } void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y, - int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source) + int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, + QEvent::Type type, Qt::MouseEventSource source) { QPoint local(event_x, event_y); QPoint global(root_x, root_y); @@ -2227,9 +2177,9 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, } if (connection()->buttonState() == Qt::NoButton) - connection()->setMousePressWindow(Q_NULLPTR); + connection()->setMousePressWindow(nullptr); - handleMouseEvent(timestamp, local, global, modifiers, source); + handleMouseEvent(timestamp, local, global, modifiers, type, source); } static inline bool doCheckUnGrabAncestor(QXcbConnection *conn) @@ -2252,7 +2202,7 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn) return true; } -static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR) +static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = nullptr) { return ((doCheckUnGrabAncestor(conn) && mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) @@ -2261,7 +2211,7 @@ static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); } -static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR) +static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = nullptr) { return ((doCheckUnGrabAncestor(conn) && mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) @@ -2330,7 +2280,8 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, } void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y, - Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source) + Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, + QEvent::Type type, Qt::MouseEventSource source) { QPoint local(event_x, event_y); QPoint global(root_x, root_y); @@ -2338,33 +2289,34 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, i // "mousePressWindow" can be NULL i.e. if a window will be grabbed or unmapped, so set it again here. // Unset "mousePressWindow" when mouse button isn't pressed - in some cases the release event won't arrive. const bool isMouseButtonPressed = (connection()->buttonState() != Qt::NoButton); - const bool hasMousePressWindow = (connection()->mousePressWindow() != Q_NULLPTR); + const bool hasMousePressWindow = (connection()->mousePressWindow() != nullptr); if (isMouseButtonPressed && !hasMousePressWindow) connection()->setMousePressWindow(this); else if (hasMousePressWindow && !isMouseButtonPressed) - connection()->setMousePressWindow(Q_NULLPTR); + connection()->setMousePressWindow(nullptr); - handleMouseEvent(timestamp, local, global, modifiers, source); + handleMouseEvent(timestamp, local, global, modifiers, type, source); } void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) { Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); handleButtonPressEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail, - modifiers, event->time); + modifiers, event->time, QEvent::MouseButtonPress); } void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event) { Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); handleButtonReleaseEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail, - modifiers, event->time); + modifiers, event->time, QEvent::MouseButtonRelease); } void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) { Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); - handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers, event->time); + handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers, + event->time, QEvent::MouseMove); } #if QT_CONFIG(xinput2) @@ -2415,18 +2367,18 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButtonState(button, true); - handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source); + handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonPress, source); break; case XI_ButtonRelease: if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButtonState(button, false); - handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source); + handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonRelease, source); break; case XI_Motion: if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName); - handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, source); + handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, QEvent::MouseMove, source); break; default: qWarning() << "Unrecognized XI2 mouse event" << ev->evtype; @@ -2471,10 +2423,13 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event) QXcbWindow *QXcbWindow::toWindow() { return this; } void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, - Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source) + Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source) { connection()->setTime(time); - QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttonState(), modifiers, source); + Qt::MouseButton button = type == QEvent::MouseMove ? Qt::NoButton : connection()->button(); + QWindowSystemInterface::handleMouseEvent(window(), time, local, global, + connection()->buttonState(), button, + type, modifiers, source); } void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) @@ -2524,7 +2479,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev m_lastWindowStateEvent = newState; m_windowState = newState; if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this) - connection()->setMouseGrabber(Q_NULLPTR); + connection()->setMouseGrabber(nullptr); } return; } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) { @@ -2592,7 +2547,7 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) bool QXcbWindow::setMouseGrabEnabled(bool grab) { if (!grab && connection()->mouseGrabber() == this) - connection()->setMouseGrabber(Q_NULLPTR); + connection()->setMouseGrabber(nullptr); #if QT_CONFIG(xinput2) if (connection()->hasXInput2() && !connection()->xi2MouseEventsDisabled()) { |