From 748e6ce020c721438e37596f119506990bf0032d Mon Sep 17 00:00:00 2001 From: David Rosca Date: Fri, 25 Sep 2015 22:04:05 +0200 Subject: [PATCH] Ported all X11 specific code to xcb It now also runtime checks for X11 platform, so it should work on Wayland without recompilation; --- BUILDING | 8 ++-- src/lib/app/browserwindow.cpp | 81 ++++++++++++++++++++++------------- src/lib/lib.pro | 2 +- src/lib/tools/qztools.cpp | 35 ++++++++------- src/lib/tools/qztools.h | 1 - 5 files changed, 74 insertions(+), 53 deletions(-) diff --git a/BUILDING b/BUILDING index 0f4defc8d..e0418e998 100644 --- a/BUILDING +++ b/BUILDING @@ -33,7 +33,7 @@ Linux / Unix You need to have Qt 4 (>= 4.7) or Qt 5 development libraries, pkg-config is highly recommended to correctly detect QtWebKit version. - Next compulsory requirement is OpenSSL (libcrypto). X11 libraries are also + Next compulsory requirement is OpenSSL (libcrypto). xcb libraries are also required unless you specify NO_X11 build option. To build spellcheck plugin, you need: @@ -151,8 +151,10 @@ Available Defines Linux / Unix specific defines: - NO_X11 Disable all direct X11 calls. - Enable this when building for Wayland. + NO_X11 Disable all X11 calls. + Enable this when building for Wayland-only. + All X11 calls are guarded by runtime X11 platform check + even without this option. example: $ export NO_X11="true" diff --git a/src/lib/app/browserwindow.cpp b/src/lib/app/browserwindow.cpp index 3deb44675..c5608dd9e 100644 --- a/src/lib/app/browserwindow.cpp +++ b/src/lib/app/browserwindow.cpp @@ -86,8 +86,9 @@ #include #ifdef QZ_WS_X11 -#include -#include +#include +#include +#include #endif #ifdef Q_OS_WIN @@ -1469,47 +1470,67 @@ bool BrowserWindow::restoreState(const QByteArray &state, int version) #ifdef QZ_WS_X11 int BrowserWindow::getCurrentVirtualDesktop() const { - Display* display = static_cast(QzTools::X11Display(this)); - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long bytes; - unsigned long* data; + if (!QX11Info::isPlatformX11()) + return 0; - Atom net_wm_desktop = XInternAtom(display, "_NET_WM_DESKTOP", False); - if (net_wm_desktop == None) { - return -1; - } + xcb_intern_atom_cookie_t intern_atom; + xcb_intern_atom_reply_t *atom_reply = 0; + xcb_atom_t atom; + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply = 0; + uint32_t value; - int status = XGetWindowProperty(display, winId(), net_wm_desktop, 0, 1, - False, XA_CARDINAL, &actual_type, &actual_format, - &nitems, &bytes, (unsigned char**) &data); + intern_atom = xcb_intern_atom(QX11Info::connection(), false, qstrlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP"); + atom_reply = xcb_intern_atom_reply(QX11Info::connection(), intern_atom, 0); - if (status != Success || data == NULL) { - return -1; - } + if (!atom_reply) + goto error; - int desktop = *data; - XFree(data); + atom = atom_reply->atom; - return desktop; + cookie = xcb_get_property(QX11Info::connection(), false, winId(), atom, XCB_ATOM_CARDINAL, 0, 1); + reply = xcb_get_property_reply(QX11Info::connection(), cookie, 0); + + if (!reply || reply->type != XCB_ATOM_CARDINAL || reply->value_len != 1 || reply->format != sizeof(uint32_t) * 8) + goto error; + + value = *reinterpret_cast(xcb_get_property_value(reply)); + + free(reply); + free(atom_reply); + return value; + +error: + free(reply); + free(atom_reply); + return 0; } void BrowserWindow::moveToVirtualDesktop(int desktopId) { + if (!QX11Info::isPlatformX11()) + return; + // Don't move when window is already visible or it is first app window - if (desktopId < 0 || isVisible() || m_windowType == Qz::BW_FirstAppWindow) { + if (desktopId < 0 || isVisible() || m_windowType == Qz::BW_FirstAppWindow) return; - } - Display* display = static_cast(QzTools::X11Display(this)); + xcb_intern_atom_cookie_t intern_atom; + xcb_intern_atom_reply_t *atom_reply = 0; + xcb_atom_t atom; - Atom net_wm_desktop = XInternAtom(display, "_NET_WM_DESKTOP", False); - if (net_wm_desktop == None) { - return; - } + intern_atom = xcb_intern_atom(QX11Info::connection(), false, qstrlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP"); + atom_reply = xcb_intern_atom_reply(QX11Info::connection(), intern_atom, 0); - XChangeProperty(display, winId(), net_wm_desktop, XA_CARDINAL, - 32, PropModeReplace, (unsigned char*) &desktopId, 1L); + if (!atom_reply) + goto error; + + atom = atom_reply->atom; + + xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, winId(), atom, + XCB_ATOM_CARDINAL, 32, 1, (const void*) &desktopId); + +error: + free(atom_reply); } #endif diff --git a/src/lib/lib.pro b/src/lib/lib.pro index b0bca707b..6e752e505 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -504,7 +504,7 @@ qtHaveModule(ftp) { INSTALLS += target !contains(DEFINES, NO_X11) { - LIBS += -lX11 + LIBS += -lxcb QT *= x11extras } diff --git a/src/lib/tools/qztools.cpp b/src/lib/tools/qztools.cpp index 5cb035191..81fbcf48b 100644 --- a/src/lib/tools/qztools.cpp +++ b/src/lib/tools/qztools.cpp @@ -45,8 +45,7 @@ #endif #ifdef QZ_WS_X11 #include -#include -#include +#include #endif #ifdef Q_OS_WIN @@ -818,26 +817,26 @@ QString QzTools::escape(const QString &string) #endif } -void* QzTools::X11Display(const QWidget* widget) -{ - Q_UNUSED(widget) - -#ifdef QZ_WS_X11 - return QX11Info::display(); -#else - return 0; -#endif -} - void QzTools::setWmClass(const QString &name, const QWidget* widget) { #ifdef QZ_WS_X11 - QByteArray nameData = name.toUtf8(); + if (!QX11Info::isPlatformX11()) + return; + + const QByteArray &nameData = name.toUtf8(); + const QByteArray &classData = QByteArrayLiteral("QupZilla"); + + uint32_t class_len = nameData.length() + 1 + classData.length() + 1; + char *class_hint = (char*) malloc(class_len); + + qstrcpy(class_hint, nameData.constData()); + qstrcpy(class_hint + nameData.length() + 1, classData.constData()); + + xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, widget->winId(), + XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, class_len, class_hint); + + free(class_hint); - XClassHint classHint; - classHint.res_name = const_cast(nameData.constData()); - classHint.res_class = const_cast("QupZilla"); - XSetClassHint((Display*)X11Display(widget), widget->winId(), &classHint); #else Q_UNUSED(name) Q_UNUSED(widget) diff --git a/src/lib/tools/qztools.h b/src/lib/tools/qztools.h index ed902d2a5..0342ec00e 100644 --- a/src/lib/tools/qztools.h +++ b/src/lib/tools/qztools.h @@ -86,7 +86,6 @@ public: static bool isCertificateValid(const QSslCertificate &cert); static QString escape(const QString &string); - static void* X11Display(const QWidget* widget); static void setWmClass(const QString &name, const QWidget* widget); template