summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>2012-04-10 13:52:12 +0200
committerQt by Nokia <qt-info@nokia.com>2012-04-11 19:14:43 +0200
commit54f718e55287d0cfa7e7e53473b07ca68678e7f2 (patch)
tree3bfc35a0d7d5af0824c1a574914e43053c3fee01 /src/plugins/platforms/xcb
parent9839474e19dbef4b5b79abeaecebbf6e7bd6aed2 (diff)
XCB: Compress window state change events.
- Avoid sending Window State change events from WM_STATE/NET_WM_STATE changes irrelevant to Qt::WindowState. - Introduce QFlags for the NetWmState getter and setter to avoid passing QVector<> around. Change-Id: I74730928c7fffca0fa1cab3b90ded90b06304c06 Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp156
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h19
2 files changed, 97 insertions, 78 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 5a8f90b7ad..06cc5ad123 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -149,6 +149,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
#if defined(XCB_USE_EGL)
, m_eglSurface(0)
#endif
+ , m_lastWindowStateEvent(-1)
{
m_screen = static_cast<QXcbScreen *>(window->screen()->handle());
@@ -636,29 +637,9 @@ static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMoti
}
}
-void QXcbWindow::printNetWmState(const QVector<xcb_atom_t> &state)
+QXcbWindow::NetWmStates QXcbWindow::netWmStates()
{
- printf("_NET_WM_STATE (%d): ", state.size());
- for (int i = 0; i < state.size(); ++i) {
-#define CHECK_WM_STATE(state_atom) \
- if (state.at(i) == atom(QXcbAtom::state_atom))\
- printf(#state_atom " ");
- CHECK_WM_STATE(_NET_WM_STATE_ABOVE)
- CHECK_WM_STATE(_NET_WM_STATE_BELOW)
- CHECK_WM_STATE(_NET_WM_STATE_FULLSCREEN)
- CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_HORZ)
- CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_VERT)
- CHECK_WM_STATE(_NET_WM_STATE_MODAL)
- CHECK_WM_STATE(_NET_WM_STATE_STAYS_ON_TOP)
- CHECK_WM_STATE(_NET_WM_STATE_DEMANDS_ATTENTION)
-#undef CHECK_WM_STATE
- }
- printf("\n");
-}
-
-QVector<xcb_atom_t> QXcbWindow::getNetWmState()
-{
- QVector<xcb_atom_t> result;
+ NetWmStates result(0);
xcb_get_property_cookie_t get_cookie =
xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
@@ -668,15 +649,24 @@ QVector<xcb_atom_t> QXcbWindow::getNetWmState()
xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
- result.resize(reply->length);
-
- memcpy(result.data(), xcb_get_property_value(reply), reply->length * sizeof(xcb_atom_t));
-
-#ifdef NET_WM_STATE_DEBUG
- printf("getting net wm state (%x)\n", m_window);
- printNetWmState(result);
-#endif
-
+ const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply));
+ const xcb_atom_t *statesEnd = states + reply->length;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
+ result |= NetWmStateAbove;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_BELOW)))
+ result |= NetWmStateBelow;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
+ result |= NetWmStateFullScreen;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
+ result |= NetWmStateMaximizedHorz;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)))
+ result |= NetWmStateMaximizedVert;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MODAL)))
+ result |= NetWmStateModal;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)))
+ result |= NetWmStateStaysOnTop;
+ if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
+ result |= NetWmStateDemandsAttention;
free(reply);
} else {
#ifdef NET_WM_STATE_DEBUG
@@ -687,8 +677,26 @@ QVector<xcb_atom_t> QXcbWindow::getNetWmState()
return result;
}
-void QXcbWindow::setNetWmState(const QVector<xcb_atom_t> &atoms)
+void QXcbWindow::setNetWmStates(NetWmStates states)
{
+ QVector<xcb_atom_t> atoms;
+ if (states & NetWmStateAbove)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
+ if (states & NetWmStateBelow)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
+ if (states & NetWmStateFullScreen)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ if (states & NetWmStateMaximizedHorz)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
+ if (states & NetWmStateMaximizedVert)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
+ if (states & NetWmStateModal)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL));
+ if (states & NetWmStateStaysOnTop)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
+ if (states & NetWmStateDemandsAttention)
+ atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
+
if (atoms.isEmpty()) {
Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE)));
} else {
@@ -699,7 +707,6 @@ void QXcbWindow::setNetWmState(const QVector<xcb_atom_t> &atoms)
xcb_flush(xcb_connection());
}
-
Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
@@ -966,30 +973,28 @@ void QXcbWindow::updateMotifWmHintsBeforeMap()
void QXcbWindow::updateNetWmStateBeforeMap()
{
- QVector<xcb_atom_t> netWmState;
+ NetWmStates states(0);
- Qt::WindowFlags flags = window()->windowFlags();
+ const Qt::WindowFlags flags = window()->windowFlags();
if (flags & Qt::WindowStaysOnTopHint) {
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
+ states |= NetWmStateAbove;
+ states |= NetWmStateStaysOnTop;
} else if (flags & Qt::WindowStaysOnBottomHint) {
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_BELOW));
+ states |= NetWmStateBelow;
}
- if (window()->windowState() & Qt::WindowFullScreen) {
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
- }
+ if (window()->windowState() & Qt::WindowFullScreen)
+ states |= NetWmStateFullScreen;
if (window()->windowState() & Qt::WindowMaximized) {
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
+ states |= NetWmStateMaximizedHorz;
+ states |= NetWmStateMaximizedVert;
}
- if (window()->windowModality() != Qt::NonModal) {
- netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MODAL));
- }
+ if (window()->windowModality() != Qt::NonModal)
+ states |= NetWmStateModal;
- setNetWmState(netWmState);
+ setNetWmStates(states);
}
void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
@@ -1452,41 +1457,42 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
{
connection()->setTime(event->time);
- bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
+ const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
+ const xcb_atom_t netWmStateAtom = atom(QXcbAtom::_NET_WM_STATE);
+ const xcb_atom_t wmStateAtom = atom(QXcbAtom::WM_STATE);
- if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
+ if (event->atom == netWmStateAtom || event->atom == wmStateAtom) {
if (propertyDeleted)
return;
- xcb_get_property_cookie_t get_cookie =
- xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE),
- XCB_ATOM_ANY, 0, 1024);
+ Qt::WindowState newState = Qt::WindowNoState;
+ if (event->atom == wmStateAtom) { // WM_STATE: Quick check for 'Minimize'.
+ const xcb_get_property_cookie_t get_cookie =
+ xcb_get_property(xcb_connection(), 0, m_window, wmStateAtom,
+ XCB_ATOM_ANY, 0, 1024);
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
- xcb_atom_t wm_state = XCB_WM_STATE_WITHDRAWN;
- if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
- if (reply->length != 0)
- wm_state = ((long *)xcb_get_property_value(reply))[0];
- free(reply);
+ if (reply && reply->format == 32 && reply->type == wmStateAtom) {
+ const long *data = (const long *)xcb_get_property_value(reply);
+ if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0])
+ newState = Qt::WindowMinimized;
+ free(reply);
+ }
+ } // WM_STATE: Quick check for 'Minimize'.
+ if (newState != Qt::WindowMinimized) { // Something else changed, get _NET_WM_STATE.
+ const NetWmStates states = netWmStates();
+ if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
+ newState = Qt::WindowMaximized;
+ else if (states & NetWmStateFullScreen)
+ newState = Qt::WindowFullScreen;
+ }
+ // Send Window state, compress events in case other flags (modality, etc) are changed.
+ if (m_lastWindowStateEvent != newState) {
+ QWindowSystemInterface::handleWindowStateChanged(window(), newState);
+ m_lastWindowStateEvent = newState;
}
-
- QVector<xcb_atom_t> netWmState = getNetWmState();
-
- bool maximized = netWmState.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ))
- && netWmState.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- bool fullscreen = netWmState.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
-
- Qt::WindowState state = Qt::WindowNoState;
- if (wm_state == XCB_WM_STATE_ICONIC)
- state = Qt::WindowMinimized;
- else if (maximized)
- state = Qt::WindowMaximized;
- else if (fullscreen)
- state = Qt::WindowFullScreen;
-
- QWindowSystemInterface::handleWindowStateChanged(window(), state);
}
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index c212095e98..d4c8804486 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -59,6 +59,19 @@ class QXcbEGLSurface;
class QXcbWindow : public QXcbObject, public QPlatformWindow
{
public:
+ enum NetWmState {
+ NetWmStateAbove = 0x1,
+ NetWmStateBelow = 0x2,
+ NetWmStateFullScreen = 0x4,
+ NetWmStateMaximizedHorz = 0x8,
+ NetWmStateMaximizedVert = 0x10,
+ NetWmStateModal = 0x20,
+ NetWmStateStaysOnTop = 0x40,
+ NetWmStateDemandsAttention = 0x80
+ };
+
+ Q_DECLARE_FLAGS(NetWmStates, NetWmState)
+
QXcbWindow(QWindow *window);
~QXcbWindow();
@@ -121,9 +134,8 @@ public:
private:
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
- QVector<xcb_atom_t> getNetWmState();
- void setNetWmState(const QVector<xcb_atom_t> &atoms);
- void printNetWmState(const QVector<xcb_atom_t> &state);
+ NetWmStates netWmStates();
+ void setNetWmStates(NetWmStates);
void setNetWmWindowFlags(Qt::WindowFlags flags);
void setMotifWindowFlags(Qt::WindowFlags flags);
@@ -169,6 +181,7 @@ private:
QRegion m_exposeRegion;
xcb_visualid_t m_visualId;
+ int m_lastWindowStateEvent;
};
QT_END_NAMESPACE