summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp235
1 files changed, 183 insertions, 52 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 586068d8d9..cb647e946d 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -101,7 +101,7 @@
#include <X11/Xutil.h>
#endif
-#if defined(XCB_USE_XINPUT2_MAEMO) || defined(XCB_USE_XINPUT2)
+#if defined(XCB_USE_XINPUT2)
#include <X11/extensions/XInput2.h>
#endif
@@ -166,16 +166,36 @@ static inline bool isTransient(const QWindow *w)
|| w->type() == Qt::Popup;
}
-static inline QImage::Format imageFormatForDepth(int depth)
+static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask)
{
switch (depth) {
- case 32: return QImage::Format_ARGB32_Premultiplied;
- case 24: return QImage::Format_RGB32;
- case 16: return QImage::Format_RGB16;
- default:
- qWarning("Unsupported screen depth: %d", depth);
- return QImage::Format_Invalid;
+ 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;
+ 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;
+ break;
+ case 16:
+ if (blue_mask == 0x1f)
+ return QImage::Format_RGB16;
+ break;
+ default:
+ break;
}
+ qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask);
+ return QImage::Format_Invalid;
}
static inline bool positionIncludesFrame(QWindow *w)
@@ -183,6 +203,8 @@ static inline bool positionIncludesFrame(QWindow *w)
return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive;
}
+static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
+
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
@@ -201,6 +223,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
#endif
, m_lastWindowStateEvent(-1)
, m_syncState(NoSyncNeeded)
+ , m_pendingSyncRequest(0)
{
m_screen = static_cast<QXcbScreen *>(window->screen()->handle());
@@ -225,7 +248,9 @@ void QXcbWindow::create()
if (type == Qt::Desktop) {
m_window = m_screen->root();
m_depth = m_screen->screen()->root_depth;
- m_imageFormat = imageFormatForDepth(m_depth);
+ m_visualId = m_screen->screen()->root_visual;
+ const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
connection()->addWindowEventListener(m_window, this);
return;
}
@@ -315,7 +340,7 @@ void QXcbWindow::create()
}
if (visualInfo) {
m_depth = visualInfo->depth;
- m_imageFormat = imageFormatForDepth(m_depth);
+ m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask);
Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
@@ -365,7 +390,8 @@ void QXcbWindow::create()
}
}
- m_imageFormat = imageFormatForDepth(m_depth);
+ const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth,
@@ -466,22 +492,7 @@ void QXcbWindow::create()
32, 2, (void *)data));
-#ifdef XCB_USE_XINPUT2_MAEMO
- if (connection()->isUsingXInput2Maemo()) {
- XIEventMask xieventmask;
- uchar bitmask[2] = { 0, 0 };
-
- xieventmask.deviceid = XIAllMasterDevices;
- xieventmask.mask = bitmask;
- xieventmask.mask_len = sizeof(bitmask);
-
- XISetMask(bitmask, XI_ButtonPress);
- XISetMask(bitmask, XI_ButtonRelease);
- XISetMask(bitmask, XI_Motion);
-
- XISelectEvents(DISPLAY_FROM_XCB(this), m_window, &xieventmask, 1);
- }
-#elif defined(XCB_USE_XINPUT2)
+#if defined(XCB_USE_XINPUT2)
connection()->xi2Select(m_window);
#endif
@@ -540,6 +551,9 @@ void QXcbWindow::destroy()
delete m_eglSurface;
m_eglSurface = 0;
#endif
+
+ if (m_pendingSyncRequest)
+ m_pendingSyncRequest->invalidate();
}
void QXcbWindow::setGeometry(const QRect &rect)
@@ -698,6 +712,11 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
+ if (window()->metaObject()->indexOfProperty(wm_window_type_property_id) >= 0) {
+ QXcbWindowFunctions::WmWindowTypes wmWindowTypes(window()->property(wm_window_type_property_id).value<int>());
+ setWmWindowType(wmWindowTypes);
+ }
+
if (connection()->time() != XCB_TIME_CURRENT_TIME)
updateNetWmUserTime(connection()->time());
@@ -1497,23 +1516,6 @@ void QXcbWindow::requestActivateWindow()
connection()->sync();
}
-#if XCB_USE_MAEMO_WINDOW_PROPERTIES
-void QXcbWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
-{
- int angle = 0;
- switch (orientation) {
- case Qt::PortraitOrientation: angle = 270; break;
- case Qt::LandscapeOrientation: angle = 0; break;
- case Qt::InvertedPortraitOrientation: angle = 90; break;
- case Qt::InvertedLandscapeOrientation: angle = 180; break;
- case Qt::PrimaryOrientation: break;
- }
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::MeegoTouchOrientationAngle), XCB_ATOM_CARDINAL, 32,
- 1, &angle));
-}
-#endif
-
QSurfaceFormat QXcbWindow::format() const
{
// ### return actual format
@@ -1535,6 +1537,130 @@ QXcbEGLSurface *QXcbWindow::eglSurface() const
}
#endif
+void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes)
+{
+ if (window->handle())
+ static_cast<QXcbWindow *>(window->handle())->setWmWindowType(windowTypes);
+ else
+ window->setProperty(wm_window_type_property_id, QVariant::fromValue(static_cast<int>(windowTypes)));
+}
+
+QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const
+{
+ QXcbWindowFunctions::WmWindowTypes result(0);
+
+ xcb_get_property_cookie_t get_cookie =
+ xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE),
+ XCB_ATOM_ATOM, 0, 1024);
+
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
+
+ if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
+ const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply));
+ const xcb_atom_t *types_end = types + reply->length;
+ for (; types != types_end; types++) {
+ QXcbAtom::Atom type = connection()->qatom(*types);
+ switch (type) {
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL:
+ result |= QXcbWindowFunctions::Normal;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP:
+ result |= QXcbWindowFunctions::Desktop;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK:
+ result |= QXcbWindowFunctions::Dock;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR:
+ result |= QXcbWindowFunctions::Toolbar;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_MENU:
+ result |= QXcbWindowFunctions::Menu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY:
+ result |= QXcbWindowFunctions::Utility;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH:
+ result |= QXcbWindowFunctions::Splash;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG:
+ result |= QXcbWindowFunctions::Dialog;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU:
+ result |= QXcbWindowFunctions::DropDownMenu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU:
+ result |= QXcbWindowFunctions::PopupMenu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP:
+ result |= QXcbWindowFunctions::Tooltip;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION:
+ result |= QXcbWindowFunctions::Notification;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO:
+ result |= QXcbWindowFunctions::Combo;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DND:
+ result |= QXcbWindowFunctions::Dnd;
+ break;
+ case QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE:
+ result |= QXcbWindowFunctions::KdeOverride;
+ break;
+ default:
+ break;
+ }
+ }
+ free(reply);
+ }
+ return result;
+}
+
+void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types)
+{
+ QVector<xcb_atom_t> atoms;
+
+ if (types & QXcbWindowFunctions::Normal)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
+ if (types & QXcbWindowFunctions::Desktop)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP));
+ if (types & QXcbWindowFunctions::Dock)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK));
+ if (types & QXcbWindowFunctions::Toolbar)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR));
+ if (types & QXcbWindowFunctions::Menu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_MENU));
+ if (types & QXcbWindowFunctions::Utility)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
+ if (types & QXcbWindowFunctions::Splash)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
+ if (types & QXcbWindowFunctions::Dialog)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
+ if (types & QXcbWindowFunctions::DropDownMenu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
+ if (types & QXcbWindowFunctions::PopupMenu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU));
+ if (types & QXcbWindowFunctions::Tooltip)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
+ if (types & QXcbWindowFunctions::Notification)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION));
+ if (types & QXcbWindowFunctions::Combo)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO));
+ if (types & QXcbWindowFunctions::Dnd)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DND));
+ if (types & QXcbWindowFunctions::KdeOverride)
+ atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+
+ if (atoms.isEmpty()) {
+ Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE)));
+ } else {
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
+ atoms.count(), atoms.constData()));
+ }
+ xcb_flush(xcb_connection());
+}
+
class ExposeCompressor
{
public:
@@ -1687,14 +1813,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
- if (!m_screen->availableGeometry().intersects(rect)) {
- Q_FOREACH (QPlatformScreen* screen, m_screen->virtualSiblings()) {
- if (screen->availableGeometry().intersects(rect)) {
- m_screen = static_cast<QXcbScreen*>(screen);
- QWindowSystemInterface::handleWindowScreenChanged(window(), m_screen->QPlatformScreen::screen());
- break;
- }
- }
+ QPlatformScreen *newScreen = screenForGeometry(rect);
+ if (newScreen != m_screen) {
+ m_screen = static_cast<QXcbScreen*>(newScreen);
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
m_configureNotifyPending = false;
@@ -2221,4 +2343,13 @@ bool QXcbWindow::needsSync() const
return m_syncState == SyncAndConfigureReceived;
}
+void QXcbWindow::postSyncWindowRequest()
+{
+ if (!m_pendingSyncRequest) {
+ QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
+ m_pendingSyncRequest = e;
+ QCoreApplication::postEvent(m_screen->connection(), e);
+ }
+}
+
QT_END_NAMESPACE