summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbeventdispatcher.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp137
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h19
14 files changed, 60 insertions, 142 deletions
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index b9ae587958..2f37ee64b5 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -926,4 +926,5 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target,
QT_END_NAMESPACE
+#include "moc_qxcbclipboard.cpp"
#include "qxcbclipboard.moc"
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 9e2a37a6a1..0eafb9b368 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -750,7 +750,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
- m_keyboard->updateKeymap(ev);
+ m_keyboard->updateKeymap();
break;
}
default:
@@ -1199,3 +1199,5 @@ void QXcbConnectionGrabber::release()
}
QT_END_NAMESPACE
+
+#include "moc_qxcbconnection.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
index 9dd608cdc0..115a196769 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
@@ -430,3 +430,5 @@ void QXcbBasicConnection::initializeXKB()
}
QT_END_NAMESPACE
+
+#include "moc_qxcbconnection_basic.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp b/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp
index 3cb2a5b5ef..eb0280cfb7 100644
--- a/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp
@@ -160,3 +160,5 @@ QAbstractEventDispatcher *QXcbEventDispatcher::createEventDispatcher(QXcbConnect
}
QT_END_NAMESPACE
+
+#include "moc_qxcbeventdispatcher.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
index 9f3c381216..14f53106e9 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -400,3 +400,5 @@ bool QXcbEventQueue::isCloseConnectionEvent(const xcb_generic_event_t *event)
}
QT_END_NAMESPACE
+
+#include "moc_qxcbeventqueue.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index efecd7e2d1..e8286381a2 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -365,17 +365,6 @@ void QXcbKeyboard::updateKeymap(xcb_mapping_notify_event_t *event)
updateKeymap();
}
-void QXcbKeyboard::updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event)
-{
- if (!event)
- return;
-
- if (event->deviceID != event->oldDeviceID)
- m_config = false;
-
- updateKeymap();
-}
-
void QXcbKeyboard::updateKeymap()
{
KeysymModifierMap keysymMods;
@@ -383,6 +372,8 @@ void QXcbKeyboard::updateKeymap()
keysymMods = keysymsToModifiers();
updateModifiers(keysymMods);
+ m_config = true;
+
if (!m_xkbContext) {
m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES));
if (!m_xkbContext) {
@@ -398,13 +389,8 @@ void QXcbKeyboard::updateKeymap()
if (connection()->hasXKB()) {
m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(),
core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS));
- if (m_xkbKeymap) {
- if (m_config)
- m_xkbState.reset(xkb_state_new(m_xkbKeymap.get()));
- else
- m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
-
- }
+ if (m_xkbKeymap)
+ m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
} else {
m_xkbKeymap.reset(keymapFromCore(keysymMods));
if (m_xkbKeymap)
@@ -425,8 +411,6 @@ void QXcbKeyboard::updateKeymap()
updateXKBMods();
QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get());
-
- m_config = true;
}
QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index b652c85fe3..0ee08aeff2 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -69,7 +69,6 @@ public:
Qt::KeyboardModifiers translateModifiers(int s) const;
void updateKeymap(xcb_mapping_notify_event_t *event);
- void updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event);
void updateKeymap();
QList<int> possibleKeys(const QKeyEvent *event) const;
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index 0b3219f792..bbce69614b 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -319,3 +319,5 @@ xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString
}
QT_END_NAMESPACE
+
+#include "moc_qxcbmime.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 30fa6864ac..c96bcb1dab 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -675,3 +675,5 @@ QString QXcbNativeInterface::dumpNativeWindows(WId root) const
}
QT_END_NAMESPACE
+
+#include "moc_qxcbnativeinterface.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index 4656f46be5..f80f23f0cb 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -133,8 +133,6 @@ signals:
private:
const QByteArray m_nativeEventType = QByteArrayLiteral("xcb_generic_event_t");
- xcb_atom_t m_sysTraySelectionAtom = XCB_ATOM_NONE;
-
static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
QList<QXcbNativeInterfaceHandler *> m_handlers;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 464d038671..9edba7257e 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -271,7 +271,7 @@ void QXcbVirtualDesktop::handleScreenChange(xcb_randr_screen_change_notify_event
_NET_WORKAREA means with multiple attached monitors. This gets worse when monitors have
different dimensions and/or screens are not virtually aligned. In Qt we want the available
geometry per monitor (QScreen), not desktop (represented by _NET_WORKAREA). WM specification
- does not have an atom for this. Thus, QScreen is limted by the lack of support from the
+ does not have an atom for this. Thus, QScreen is limited by the lack of support from the
underlying system.
One option could be that Qt does WM's job of calculating this by subtracting geometries of
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index ff5ad98cd2..7f1fc7f5eb 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -176,3 +176,5 @@ xcb_visualid_t QXcbSystemTrayTracker::netSystemTrayVisual()
}
QT_END_NAMESPACE
+
+#include "moc_qxcbsystemtraytracker.cpp"
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index dfc9c7d7a3..bffad0fac5 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -93,6 +93,8 @@ enum {
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
+
Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE);
#undef FocusIn
@@ -555,6 +557,7 @@ void QXcbWindow::destroy()
}
m_mapped = false;
+ m_recreationReasons = RecreationNotNeeded;
if (m_pendingSyncRequest)
m_pendingSyncRequest->invalidate();
@@ -564,11 +567,6 @@ void QXcbWindow::setGeometry(const QRect &rect)
{
QPlatformWindow::setGeometry(rect);
- if (shouldDeferTask(Task::SetGeometry)) {
- m_deferredGeometry = rect;
- return;
- }
-
propagateSizeHints();
QXcbScreen *currentScreen = xcbScreen();
@@ -693,10 +691,12 @@ void QXcbWindow::setVisible(bool visible)
void QXcbWindow::show()
{
- if (shouldDeferTask(Task::Map))
- return;
-
if (window()->isTopLevel()) {
+ if (m_recreationReasons != RecreationNotNeeded) {
+ qCDebug(lcQpaWindow) << "QXcbWindow: need to recreate window" << window() << m_recreationReasons;
+ create();
+ m_recreationReasons = RecreationNotNeeded;
+ }
// update WM_NORMAL_HINTS
propagateSizeHints();
@@ -706,7 +706,7 @@ void QXcbWindow::show()
if (isTransient(window())) {
const QWindow *tp = window()->transientParent();
if (tp && tp->handle())
- transientXcbParent = static_cast<const QXcbWindow *>(tp->handle())->winId();
+ transientXcbParent = tp->handle()->winId();
// Default to client leader if there is no transient parent, else modal dialogs can
// be hidden by their parents.
if (!transientXcbParent)
@@ -746,10 +746,6 @@ void QXcbWindow::show()
void QXcbWindow::hide()
{
- if (shouldDeferTask(Task::Unmap))
- return;
-
- m_wmStateValid = false;
xcb_unmap_window(xcb_connection(), m_window);
// send synthetic UnmapNotify event according to icccm 4.1.4
@@ -909,9 +905,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
- if (shouldDeferTask(Task::SetWindowFlags))
- return;
-
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
if (type == Qt::ToolTip)
@@ -919,6 +912,12 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
if (type == Qt::Popup)
flags |= Qt::X11BypassWindowManagerHint;
+ Qt::WindowFlags oldflags = window()->flags();
+ if ((oldflags & Qt::WindowStaysOnTopHint) != (flags & Qt::WindowStaysOnTopHint))
+ m_recreationReasons |= WindowStaysOnTopHintChanged;
+ if ((oldflags & Qt::WindowStaysOnBottomHint) != (flags & Qt::WindowStaysOnBottomHint))
+ m_recreationReasons |= WindowStaysOnBottomHintChanged;
+
const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
const quint32 values[] = {
// XCB_CW_OVERRIDE_REDIRECT
@@ -941,8 +940,6 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus);
-
- m_isWmManagedWindow = !(flags & Qt::X11BypassWindowManagerHint);
}
void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags)
@@ -1142,9 +1139,6 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
if (state == m_windowState)
return;
- if (shouldDeferTask(Task::SetWindowState))
- return;
-
// unset old state
if (m_windowState & Qt::WindowMinimized)
xcb_map_window(xcb_connection(), m_window);
@@ -1350,6 +1344,12 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
}
if (!icon_data.isEmpty()) {
+ // Ignore icon exceeding maximum xcb request length
+ if (size_t(icon_data.size()) > xcb_get_maximum_request_length(xcb_connection())) {
+ qWarning("Ignoring window icon: Size %d exceeds maximum xcb request length %u.",
+ icon_data.size(), xcb_get_maximum_request_length(xcb_connection()));
+ return;
+ }
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
@@ -1894,10 +1894,6 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
if (event->window == m_window) {
m_mapped = false;
QWindowSystemInterface::handleExposeEvent(window(), QRegion());
- if (!m_isWmManagedWindow || parent()) {
- m_wmStateValid = true;
- handleDeferredTasks();
- }
}
}
@@ -2212,98 +2208,30 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, event->detail, event->time);
}
-bool QXcbWindow::shouldDeferTask(Task task)
-{
- if (m_wmStateValid)
- return false;
-
- m_deferredTasks.append(task);
- return true;
-}
-
-void QXcbWindow::handleDeferredTasks()
-{
- Q_ASSERT(m_wmStateValid == true);
- if (m_deferredTasks.isEmpty())
- return;
-
- bool map = false;
- bool unmap = false;
-
- QVector<Task> tasks;
- for (auto taskIt = m_deferredTasks.rbegin(); taskIt != m_deferredTasks.rend(); ++taskIt) {
- if (!tasks.contains(*taskIt))
- tasks.prepend(*taskIt);
- }
-
- for (Task task : tasks) {
- switch (task) {
- case Task::Map:
- map = true;
- unmap = false;
- break;
- case Task::Unmap:
- unmap = true;
- map = false;
- break;
- case Task::SetGeometry:
- setGeometry(m_deferredGeometry);
- break;
- case Task::SetWindowFlags:
- setWindowFlags(window()->flags());
- break;
- case Task::SetWindowState:
- setWindowState(window()->windowState());
- break;
- }
- }
- m_deferredTasks.clear();
-
- if (map) {
- Q_ASSERT(unmap == false);
- show();
- }
- if (unmap) {
- Q_ASSERT(map == false);
- hide();
- }
-}
-
void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
{
connection()->setTime(event->time);
- const bool wmStateChanged = event->atom == atom(QXcbAtom::WM_STATE);
- const bool netWmStateChanged = event->atom == atom(QXcbAtom::_NET_WM_STATE);
- if (netWmStateChanged || wmStateChanged) {
- if (wmStateChanged && !m_wmStateValid && m_isWmManagedWindow) {
- // ICCCM 4.1.4
- // Clients that want to re-use a client window (e.g. by mapping it again)
- // after withdrawing it must wait for the withdrawal to be complete before
- // proceeding. The preferred method for doing this is for clients to wait for
- // a window manager to update or remove the WM_STATE property.
- m_wmStateValid = true;
- handleDeferredTasks();
- }
- if (event->state == XCB_PROPERTY_DELETE)
+ const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
+
+ if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
+ if (propertyDeleted)
return;
- if (wmStateChanged) {
+ Qt::WindowStates newState = Qt::WindowNoState;
+
+ if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
0, m_window, atom(QXcbAtom::WM_STATE),
XCB_ATOM_ANY, 0, 1024);
if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
- auto data = static_cast<const quint32 *>(xcb_get_property_value(reply.get()));
- if (reply->length != 0) {
- const bool changedToWithdrawn = data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN;
- const bool changedToIconic = data[0] == XCB_ICCCM_WM_STATE_ICONIC;
- m_minimized = changedToIconic || (changedToWithdrawn && m_minimized);
- }
+ const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
+ if (reply->length != 0)
+ m_minimized = (data[0] == XCB_ICCCM_WM_STATE_ICONIC
+ || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
}
}
- // _NET_WM_STATE handling
- Qt::WindowStates newState = Qt::WindowNoState;
const NetWmStates states = netWmStates();
// _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would
// not be visible on the screen if its desktop/viewport were active and its coordinates were
@@ -2325,6 +2253,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this)
connection()->setMouseGrabber(nullptr);
}
+ return;
} else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
m_dirtyFrameMargins = true;
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 55af9279b1..8de486c6d2 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -74,13 +74,12 @@ public:
Q_DECLARE_FLAGS(NetWmStates, NetWmState)
- enum Task {
- Map,
- Unmap,
- SetGeometry,
- SetWindowFlags,
- SetWindowState
+ enum RecreationReason {
+ RecreationNotNeeded = 0,
+ WindowStaysOnTopHintChanged = 0x1,
+ WindowStaysOnBottomHintChanged = 0x2
};
+ Q_DECLARE_FLAGS(RecreationReasons, RecreationReason)
QXcbWindow(QWindow *window);
~QXcbWindow();
@@ -151,9 +150,6 @@ public:
QXcbWindow *toWindow() override;
- bool shouldDeferTask(Task task);
- void handleDeferredTasks();
-
void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source);
@@ -293,10 +289,7 @@ protected:
qreal m_sizeHintsScaleFactor = 1.0;
- bool m_wmStateValid = true;
- QVector<Task> m_deferredTasks;
- bool m_isWmManagedWindow = true;
- QRect m_deferredGeometry;
+ RecreationReasons m_recreationReasons = RecreationNotNeeded;
};
class QXcbForeignWindow : public QXcbWindow