mirror of
https://github.com/yann64/haikuports.git
synced 2026-04-22 11:40:06 +02:00
libfm_qt, bump version (#8915)
This commit is contained in:
@@ -4,16 +4,16 @@ to build desktop file managers which belongs to LXDE."
|
||||
HOMEPAGE="https://github.com/lxqt/libfm-qt"
|
||||
COPYRIGHT="2013-2019 LXQt team"
|
||||
LICENSE="GNU LGPL v2.1"
|
||||
REVISION="3"
|
||||
REVISION="1"
|
||||
SOURCE_URI="https://github.com/lxqt/libfm-qt/archive/$portVersion.tar.gz"
|
||||
CHECKSUM_SHA256="61c05da2afb22a5b869c6df3b62a2f7682ded33d3494bc73efb045a870295871"
|
||||
CHECKSUM_SHA256="4a747e2b578fa49df5f090d79970c9bd92816c67977e849befa527ee83ecac4e"
|
||||
SOURCE_DIR="libfm-qt-$portVersion"
|
||||
PATCHES="libfm_qt-$portVersion.patchset"
|
||||
|
||||
ARCHITECTURES="all !x86_gcc2 ?x86"
|
||||
SECONDARY_ARCHITECTURES="x86"
|
||||
|
||||
libVersion="6.0.0"
|
||||
libVersion="13.0.0"
|
||||
libVersionCompat="$libVersion compat >= ${libVersion%%.*}"
|
||||
|
||||
PROVIDES="
|
||||
@@ -72,17 +72,14 @@ defineDebugInfoPackage libfm_qt$secondaryArchSuffix \
|
||||
|
||||
BUILD()
|
||||
{
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. $cmakeDirArgs \
|
||||
-DCMAKE_BUILD_TYPE=Release -DPULL_TRANSLATIONS=no
|
||||
make $jobArgs
|
||||
cmake -Bbuild -S. -DCMAKE_BUILD_TYPE=Release \
|
||||
$cmakeDirArgs
|
||||
make -C build $jobArgs
|
||||
}
|
||||
|
||||
INSTALL()
|
||||
{
|
||||
cd build
|
||||
make install
|
||||
make -C build install
|
||||
|
||||
prepareInstalledDevelLib libfm-qt
|
||||
fixPkgconfig
|
||||
@@ -1,255 +0,0 @@
|
||||
From 66a5d896959b7d3f52f7b1d4e0929f6480950e85 Mon Sep 17 00:00:00 2001
|
||||
From: Sergei Reznikov <diver@gelios.net>
|
||||
Date: Wed, 30 Jan 2019 22:39:57 +0300
|
||||
Subject: WIP: fix build on Haiku
|
||||
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 553f1e6..5f79177 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -33,8 +33,9 @@ set(QT_MINIMUM_VERSION "5.7.1")
|
||||
|
||||
find_package(Qt5Widgets "${QT_MINIMUM_VERSION}" REQUIRED)
|
||||
find_package(Qt5LinguistTools "${QT_MINIMUM_VERSION}" REQUIRED)
|
||||
-find_package(Qt5X11Extras "${QT_MINIMUM_VERSION}" REQUIRED)
|
||||
-
|
||||
+if (UNIX AND NOT HAIKU)
|
||||
+ find_package(Qt5X11Extras "${REQUIRED_QT_VERSION}" REQUIRED)
|
||||
+endif()
|
||||
find_package(lxqt-build-tools "${LXQTBT_MINIMUM_VERSION}" REQUIRED)
|
||||
find_package(GLIB "${GLIB_MINIMUM_VERSION}" REQUIRED COMPONENTS gio gio-unix gobject gthread)
|
||||
find_package(MenuCache "${LIBMENUCACHE_MINIMUM_VERSION}" REQUIRED)
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index ec9d9c2..19ee0e9 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -131,9 +131,14 @@ install(EXPORT
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
+IF(UNIX AND NOT HAIKU)
|
||||
+target_link_libraries(${LIBFM_QT_LIBRARY_NAME}
|
||||
+ Qt5::X11Extras
|
||||
+)
|
||||
+endif()
|
||||
+
|
||||
target_link_libraries(${LIBFM_QT_LIBRARY_NAME}
|
||||
Qt5::Widgets
|
||||
- Qt5::X11Extras
|
||||
${GLIB_LIBRARIES}
|
||||
${GLIB_GIO_LIBRARIES}
|
||||
${GLIB_GOBJECT_LIBRARIES}
|
||||
diff --git a/src/applaunchcontext.cpp b/src/applaunchcontext.cpp
|
||||
index e599485..ea07648 100644
|
||||
--- a/src/applaunchcontext.cpp
|
||||
+++ b/src/applaunchcontext.cpp
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
|
||||
#include "applaunchcontext.h"
|
||||
-#include <QX11Info>
|
||||
-#include <X11/Xlib.h>
|
||||
+
|
||||
+#ifndef Q_OS_HAIKU
|
||||
+ #include <QX11Info>
|
||||
+ #include <X11/Xlib.h>
|
||||
+#endif
|
||||
|
||||
typedef struct _FmAppLaunchContext {
|
||||
GAppLaunchContext parent;
|
||||
@@ -29,11 +32,13 @@ typedef struct _FmAppLaunchContext {
|
||||
G_DEFINE_TYPE(FmAppLaunchContext, fm_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
|
||||
|
||||
static char* fm_app_launch_context_get_display(GAppLaunchContext * /*context*/, GAppInfo * /*info*/, GList * /*files*/) {
|
||||
+#ifndef Q_OS_HAIKU
|
||||
Display* dpy = QX11Info::display();
|
||||
if(dpy) {
|
||||
char* xstr = DisplayString(dpy);
|
||||
return g_strdup(xstr);
|
||||
}
|
||||
+#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
diff --git a/src/core/thumbnailjob.cpp b/src/core/thumbnailjob.cpp
|
||||
index bddd7de..ec2940d 100644
|
||||
--- a/src/core/thumbnailjob.cpp
|
||||
+++ b/src/core/thumbnailjob.cpp
|
||||
@@ -9,6 +9,15 @@
|
||||
|
||||
#include "core/legacy/fm-config.h"
|
||||
|
||||
+#ifdef Q_OS_HAIKU
|
||||
+static inline void *
|
||||
+mempcpy(void *to, const void *from, size_t size)
|
||||
+{
|
||||
+ memcpy(to, from, size);
|
||||
+ return (unsigned char *)to + size;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
namespace Fm {
|
||||
|
||||
QThreadPool* ThumbnailJob::threadPool_ = nullptr;
|
||||
diff --git a/src/folderview.cpp b/src/folderview.cpp
|
||||
index d1930e8..0bae5fe 100644
|
||||
--- a/src/folderview.cpp
|
||||
+++ b/src/folderview.cpp
|
||||
@@ -42,7 +42,9 @@
|
||||
#include <QMessageBox>
|
||||
#include <QLineEdit>
|
||||
#include <QTextEdit>
|
||||
-#include <QX11Info> // for XDS support
|
||||
+#ifndef Q_OS_HAIKU
|
||||
+ #include <QX11Info> // for XDS support
|
||||
+#endif
|
||||
#include <xcb/xcb.h> // for XDS support
|
||||
#include "xdndworkaround.h" // for XDS support
|
||||
#include "folderview_p.h"
|
||||
@@ -1092,6 +1094,7 @@ void FolderView::childDropEvent(QDropEvent* e) {
|
||||
// NOTE: in theory, it's not possible to implement XDS with pure Qt.
|
||||
// We achieved this with some dirty XCB/XDND workarounds.
|
||||
// Please refer to XdndWorkaround::clientMessage() in xdndworkaround.cpp for details.
|
||||
+#ifndef Q_OS_HAIKU
|
||||
if(QX11Info::isPlatformX11() && e->mimeData()->hasFormat("XdndDirectSave0")) {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
const QWidget* targetWidget = childView()->viewport();
|
||||
@@ -1130,7 +1133,7 @@ void FolderView::childDropEvent(QDropEvent* e) {
|
||||
e->accept(); // yeah! we've done with XDS so stop Qt from further event propagation.
|
||||
return;
|
||||
}
|
||||
-
|
||||
+#endif
|
||||
if(e->keyboardModifiers() == Qt::NoModifier) {
|
||||
// if no key modifiers are used, popup a menu
|
||||
// to ask the user for the action he/she wants to perform.
|
||||
diff --git a/src/libfmqt.cpp b/src/libfmqt.cpp
|
||||
index 83905ee..c7c060b 100644
|
||||
--- a/src/libfmqt.cpp
|
||||
+++ b/src/libfmqt.cpp
|
||||
@@ -32,7 +32,9 @@ struct LibFmQtData {
|
||||
~LibFmQtData();
|
||||
|
||||
QTranslator translator;
|
||||
+#ifndef Q_OS_HAIKU
|
||||
XdndWorkaround workaround;
|
||||
+#endif
|
||||
int refCount;
|
||||
Q_DISABLE_COPY(LibFmQtData)
|
||||
};
|
||||
diff --git a/src/xdndworkaround.cpp b/src/xdndworkaround.cpp
|
||||
index f0a35d2..65de54a 100644
|
||||
--- a/src/xdndworkaround.cpp
|
||||
+++ b/src/xdndworkaround.cpp
|
||||
@@ -21,7 +21,9 @@
|
||||
#include "xdndworkaround.h"
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
-#include <QX11Info>
|
||||
+#ifndef Q_OS_HAIKU
|
||||
+ #include <QX11Info>
|
||||
+#endif
|
||||
#include <QMimeData>
|
||||
#include <QCursor>
|
||||
#include <QWidget>
|
||||
@@ -44,72 +46,24 @@
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
|
||||
|
||||
XdndWorkaround::XdndWorkaround() {
|
||||
- if(!QX11Info::isPlatformX11()) {
|
||||
+// if(!QX11Info::isPlatformX11()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we need to filter all X11 events
|
||||
- qApp->installNativeEventFilter(this);
|
||||
+// qApp->installNativeEventFilter(this);
|
||||
|
||||
-// This part is for Qt >= 5.4 only
|
||||
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
|
||||
- lastDrag_ = nullptr;
|
||||
|
||||
- // initialize xinput2 since newer versions of Qt5 uses it.
|
||||
- static char xi_name[] = "XInputExtension";
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- xcb_query_extension_cookie_t cookie = xcb_query_extension(conn, strlen(xi_name), xi_name);
|
||||
- xcb_generic_error_t* err = nullptr;
|
||||
- xcb_query_extension_reply_t* reply = xcb_query_extension_reply(conn, cookie, &err);
|
||||
- if(err == nullptr) {
|
||||
- xinput2Enabled_ = true;
|
||||
- xinputOpCode_ = reply->major_opcode;
|
||||
- xinputEventBase_ = reply->first_event;
|
||||
- xinputErrorBase_ = reply->first_error;
|
||||
- // qDebug() << "xinput: " << m_xi2Enabled << m_xiOpCode << m_xiEventBase;
|
||||
- }
|
||||
- else {
|
||||
- xinput2Enabled_ = false;
|
||||
- free(err);
|
||||
- }
|
||||
- free(reply);
|
||||
-#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
|
||||
-}
|
||||
|
||||
XdndWorkaround::~XdndWorkaround() {
|
||||
- if(!QX11Info::isPlatformX11()) {
|
||||
+// if(!QX11Info::isPlatformX11()) {
|
||||
return;
|
||||
- }
|
||||
- qApp->removeNativeEventFilter(this);
|
||||
+// }
|
||||
+// qApp->removeNativeEventFilter(this);
|
||||
}
|
||||
|
||||
-bool XdndWorkaround::nativeEventFilter(const QByteArray& eventType, void* message, long* /*result*/) {
|
||||
- if(Q_LIKELY(eventType == "xcb_generic_event_t")) {
|
||||
- xcb_generic_event_t* event = static_cast<xcb_generic_event_t*>(message);
|
||||
- switch(event->response_type & ~0x80) {
|
||||
- case XCB_CLIENT_MESSAGE:
|
||||
- return clientMessage(reinterpret_cast<xcb_client_message_event_t*>(event));
|
||||
- case XCB_SELECTION_NOTIFY:
|
||||
- return selectionNotify(reinterpret_cast<xcb_selection_notify_event_t*>(event));
|
||||
-// This part is for Qt >= 5.4 only
|
||||
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
|
||||
- case XCB_SELECTION_REQUEST:
|
||||
- return selectionRequest(reinterpret_cast<xcb_selection_request_event_t*>(event));
|
||||
- case XCB_GE_GENERIC:
|
||||
- // newer versions of Qt5 supports xinput2, which sends its mouse events via XGE.
|
||||
- return genericEvent(reinterpret_cast<xcb_ge_generic_event_t*>(event));
|
||||
- case XCB_BUTTON_RELEASE:
|
||||
- // older versions of Qt5 receive mouse events via old XCB events.
|
||||
- buttonRelease();
|
||||
- break;
|
||||
-#endif // Qt >= 5.4
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
|
||||
+/*
|
||||
// static
|
||||
QByteArray XdndWorkaround::atomName(xcb_atom_t atom) {
|
||||
QByteArray name;
|
||||
@@ -290,3 +244,4 @@ void XdndWorkaround::buttonRelease() {
|
||||
}
|
||||
|
||||
#endif // QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
|
||||
+*/
|
||||
diff --git a/src/xdndworkaround.h b/src/xdndworkaround.h
|
||||
index 9d40c11..bab0368 100644
|
||||
--- a/src/xdndworkaround.h
|
||||
+++ b/src/xdndworkaround.h
|
||||
@@ -60,7 +60,7 @@ class XdndWorkaround : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
explicit XdndWorkaround();
|
||||
~XdndWorkaround();
|
||||
- bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
+// bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
static QByteArray atomName(xcb_atom_t atom);
|
||||
static xcb_atom_t internAtom(const char* name, int len = -1);
|
||||
static QByteArray windowProperty(xcb_window_t window, xcb_atom_t propAtom, xcb_atom_t typeAtom, int len);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
415
x11-libs/libfm-qt/patches/libfm_qt-1.3.0.patchset
Normal file
415
x11-libs/libfm-qt/patches/libfm_qt-1.3.0.patchset
Normal file
@@ -0,0 +1,415 @@
|
||||
From 1360dda746ca031ad0e0fcc8033536119c8a28ea Mon Sep 17 00:00:00 2001
|
||||
From: Sergei Reznikov <diver@gelios.net>
|
||||
Date: Wed, 30 Jan 2019 22:39:57 +0300
|
||||
Subject: WIP: fix build on Haiku
|
||||
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 4b6e0c3..406f5f6 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -33,7 +33,9 @@ set(QT_MINIMUM_VERSION "5.15.0")
|
||||
|
||||
find_package(Qt5Widgets "${QT_MINIMUM_VERSION}" REQUIRED)
|
||||
find_package(Qt5LinguistTools "${QT_MINIMUM_VERSION}" REQUIRED)
|
||||
-find_package(Qt5X11Extras "${QT_MINIMUM_VERSION}" REQUIRED)
|
||||
+if (UNIX AND NOT HAIKU)
|
||||
+ find_package(Qt5X11Extras "${REQUIRED_QT_VERSION}" REQUIRED)
|
||||
+endif()
|
||||
|
||||
find_package(lxqt-build-tools "${LXQTBT_MINIMUM_VERSION}" REQUIRED)
|
||||
find_package(GLIB "${GLIB_MINIMUM_VERSION}" REQUIRED COMPONENTS gio gio-unix gobject gthread)
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index 2058156..a3202fe 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -131,9 +131,14 @@ install(EXPORT
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
+IF(UNIX AND NOT HAIKU)
|
||||
+target_link_libraries(${LIBFM_QT_LIBRARY_NAME}
|
||||
+ Qt5::X11Extras
|
||||
+)
|
||||
+endif()
|
||||
+
|
||||
target_link_libraries(${LIBFM_QT_LIBRARY_NAME}
|
||||
Qt5::Widgets
|
||||
- Qt5::X11Extras
|
||||
${GLIB_LIBRARIES}
|
||||
${GLIB_GIO_LIBRARIES}
|
||||
${GLIB_GOBJECT_LIBRARIES}
|
||||
diff --git a/src/applaunchcontext.cpp b/src/applaunchcontext.cpp
|
||||
index 55f80f7..7306571 100644
|
||||
--- a/src/applaunchcontext.cpp
|
||||
+++ b/src/applaunchcontext.cpp
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
|
||||
#include "applaunchcontext.h"
|
||||
-#include <QX11Info>
|
||||
-#include <X11/Xlib.h>
|
||||
+
|
||||
+#ifndef Q_OS_HAIKU
|
||||
+ #include <QX11Info>
|
||||
+ #include <X11/Xlib.h>
|
||||
+#endif
|
||||
|
||||
typedef struct _FmAppLaunchContext {
|
||||
GAppLaunchContext parent;
|
||||
@@ -29,6 +32,7 @@ typedef struct _FmAppLaunchContext {
|
||||
G_DEFINE_TYPE(FmAppLaunchContext, fm_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
|
||||
|
||||
static char* fm_app_launch_context_get_display(GAppLaunchContext * /*context*/, GAppInfo * /*info*/, GList * /*files*/) {
|
||||
+#ifndef Q_OS_HAIKU
|
||||
if(QX11Info::isPlatformX11()) {
|
||||
Display* dpy = QX11Info::display();
|
||||
if(dpy) {
|
||||
@@ -36,6 +40,7 @@ static char* fm_app_launch_context_get_display(GAppLaunchContext * /*context*/,
|
||||
return g_strdup(xstr);
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
diff --git a/src/core/thumbnailjob.cpp b/src/core/thumbnailjob.cpp
|
||||
index 097bbc5..7a46036 100644
|
||||
--- a/src/core/thumbnailjob.cpp
|
||||
+++ b/src/core/thumbnailjob.cpp
|
||||
@@ -9,6 +9,15 @@
|
||||
|
||||
#include "core/legacy/fm-config.h"
|
||||
|
||||
+#ifdef Q_OS_HAIKU
|
||||
+static inline void *
|
||||
+mempcpy(void *to, const void *from, size_t size)
|
||||
+{
|
||||
+ memcpy(to, from, size);
|
||||
+ return (unsigned char *)to + size;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
namespace Fm {
|
||||
|
||||
QThreadPool* ThumbnailJob::threadPool_ = nullptr;
|
||||
diff --git a/src/folderview.cpp b/src/folderview.cpp
|
||||
index 58110c8..654c40f 100644
|
||||
--- a/src/folderview.cpp
|
||||
+++ b/src/folderview.cpp
|
||||
@@ -46,7 +46,9 @@
|
||||
#include <QTextEdit>
|
||||
#include <QWidgetAction> // for detailed list header context menu
|
||||
#include <QLabel> // for detailed list header context menu
|
||||
-#include <QX11Info> // for XDS support
|
||||
+#ifndef Q_OS_HAIKU
|
||||
+ #include <QX11Info> // for XDS support
|
||||
+#endif
|
||||
#include <xcb/xcb.h> // for XDS support
|
||||
#include "xdndworkaround.h" // for XDS support
|
||||
#include "folderview_p.h"
|
||||
@@ -1558,6 +1560,7 @@ void FolderView::childDropEvent(QDropEvent* e) {
|
||||
// NOTE: in theory, it's not possible to implement XDS with pure Qt.
|
||||
// We achieved this with some dirty XCB/XDND workarounds.
|
||||
// Please refer to XdndWorkaround::clientMessage() in xdndworkaround.cpp for details.
|
||||
+#ifndef Q_OS_HAIKU
|
||||
if(QX11Info::isPlatformX11() && e->mimeData()->hasFormat(QStringLiteral("XdndDirectSave0"))) {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
const QWidget* targetWidget = childView()->viewport();
|
||||
@@ -1596,6 +1599,7 @@ void FolderView::childDropEvent(QDropEvent* e) {
|
||||
e->accept(); // yeah! we've done with XDS so stop Qt from further event propagation.
|
||||
return;
|
||||
}
|
||||
+#endif
|
||||
|
||||
if(e->keyboardModifiers() == Qt::NoModifier) {
|
||||
// If no key modifiers are used, pop up a menu
|
||||
diff --git a/src/libfmqt.cpp b/src/libfmqt.cpp
|
||||
index 6f82dc9..a405bbb 100644
|
||||
--- a/src/libfmqt.cpp
|
||||
+++ b/src/libfmqt.cpp
|
||||
@@ -32,7 +32,9 @@ struct LibFmQtData {
|
||||
~LibFmQtData();
|
||||
|
||||
QTranslator translator;
|
||||
+#ifndef Q_OS_HAIKU
|
||||
XdndWorkaround workaround;
|
||||
+#endif
|
||||
int refCount;
|
||||
Q_DISABLE_COPY(LibFmQtData)
|
||||
};
|
||||
diff --git a/src/xdndworkaround.cpp b/src/xdndworkaround.cpp
|
||||
index e66f681..95945fc 100644
|
||||
--- a/src/xdndworkaround.cpp
|
||||
+++ b/src/xdndworkaround.cpp
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "xdndworkaround.h"
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
-#include <QX11Info>
|
||||
#include <QMimeData>
|
||||
#include <QCursor>
|
||||
#include <QWidget>
|
||||
@@ -41,246 +40,9 @@
|
||||
|
||||
|
||||
XdndWorkaround::XdndWorkaround() {
|
||||
- if(!QX11Info::isPlatformX11()) {
|
||||
return;
|
||||
}
|
||||
|
||||
- // we need to filter all X11 events
|
||||
- qApp->installNativeEventFilter(this);
|
||||
-
|
||||
- lastDrag_ = nullptr;
|
||||
- xinput2Enabled_ = false;
|
||||
- xinputOpCode_ = 0;
|
||||
- xinputEventBase_ = 0;
|
||||
- xinputErrorBase_ = 0;
|
||||
-
|
||||
- // initialize xinput2 since newer versions of Qt5 uses it.
|
||||
- static char xi_name[] = "XInputExtension";
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- xcb_query_extension_cookie_t cookie = xcb_query_extension(conn, strlen(xi_name), xi_name);
|
||||
- xcb_generic_error_t* err = nullptr;
|
||||
- xcb_query_extension_reply_t* reply = xcb_query_extension_reply(conn, cookie, &err);
|
||||
- if(err == nullptr) {
|
||||
- xinput2Enabled_ = true;
|
||||
- if(reply != nullptr) {
|
||||
- xinputOpCode_ = reply->major_opcode;
|
||||
- xinputEventBase_ = reply->first_event;
|
||||
- xinputErrorBase_ = reply->first_error;
|
||||
- }
|
||||
- // qDebug() << "xinput: " << m_xi2Enabled << m_xiOpCode << m_xiEventBase;
|
||||
- }
|
||||
- else {
|
||||
- free(err);
|
||||
- }
|
||||
- if(reply != nullptr) {
|
||||
- free(reply);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
XdndWorkaround::~XdndWorkaround() {
|
||||
- if(!QX11Info::isPlatformX11()) {
|
||||
return;
|
||||
}
|
||||
- qApp->removeNativeEventFilter(this);
|
||||
-}
|
||||
-
|
||||
-bool XdndWorkaround::nativeEventFilter(const QByteArray& eventType, void* message, long* /*result*/) {
|
||||
- if(Q_LIKELY(eventType == "xcb_generic_event_t")) {
|
||||
- xcb_generic_event_t* event = static_cast<xcb_generic_event_t*>(message);
|
||||
- switch(event->response_type & ~0x80) {
|
||||
- case XCB_CLIENT_MESSAGE:
|
||||
- return clientMessage(reinterpret_cast<xcb_client_message_event_t*>(event));
|
||||
- case XCB_SELECTION_NOTIFY:
|
||||
- return selectionNotify(reinterpret_cast<xcb_selection_notify_event_t*>(event));
|
||||
- case XCB_SELECTION_REQUEST:
|
||||
- return selectionRequest(reinterpret_cast<xcb_selection_request_event_t*>(event));
|
||||
- case XCB_GE_GENERIC:
|
||||
- // newer versions of Qt5 supports xinput2, which sends its mouse events via XGE.
|
||||
- return genericEvent(reinterpret_cast<xcb_ge_generic_event_t*>(event));
|
||||
- case XCB_BUTTON_RELEASE:
|
||||
- // older versions of Qt5 receive mouse events via old XCB events.
|
||||
- buttonRelease();
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
-// static
|
||||
-QByteArray XdndWorkaround::atomName(xcb_atom_t atom) {
|
||||
- QByteArray name;
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(conn, atom);
|
||||
- xcb_get_atom_name_reply_t* reply = xcb_get_atom_name_reply(conn, cookie, nullptr);
|
||||
- if(reply != nullptr) {
|
||||
- int len = xcb_get_atom_name_name_length(reply);
|
||||
- if(len > 0) {
|
||||
- name.append(xcb_get_atom_name_name(reply), len);
|
||||
- }
|
||||
- free(reply);
|
||||
- }
|
||||
- return name;
|
||||
-}
|
||||
-
|
||||
-// static
|
||||
-xcb_atom_t XdndWorkaround::internAtom(const char* name, int len) {
|
||||
- xcb_atom_t atom = 0;
|
||||
- if(len == -1) {
|
||||
- len = strlen(name);
|
||||
- }
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- xcb_intern_atom_cookie_t cookie = xcb_intern_atom(conn, false, len, name);
|
||||
- xcb_generic_error_t* err = nullptr;
|
||||
- xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(conn, cookie, &err);
|
||||
- if(reply != nullptr) {
|
||||
- atom = reply->atom;
|
||||
- free(reply);
|
||||
- }
|
||||
- if(err != nullptr) {
|
||||
- free(err);
|
||||
- }
|
||||
- return atom;
|
||||
-}
|
||||
-
|
||||
-// static
|
||||
-QByteArray XdndWorkaround::windowProperty(xcb_window_t window, xcb_atom_t propAtom, xcb_atom_t typeAtom, int len) {
|
||||
- QByteArray data;
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- xcb_get_property_cookie_t cookie = xcb_get_property(conn, false, window, propAtom, typeAtom, 0, len);
|
||||
- xcb_generic_error_t* err = nullptr;
|
||||
- xcb_get_property_reply_t* reply = xcb_get_property_reply(conn, cookie, &err);
|
||||
- if(reply != nullptr) {
|
||||
- len = xcb_get_property_value_length(reply);
|
||||
- const char* buf = (const char*)xcb_get_property_value(reply);
|
||||
- data.append(buf, len);
|
||||
- free(reply);
|
||||
- }
|
||||
- if(err != nullptr) {
|
||||
- free(err);
|
||||
- }
|
||||
- return data;
|
||||
-}
|
||||
-
|
||||
-// static
|
||||
-void XdndWorkaround::setWindowProperty(xcb_window_t window, xcb_atom_t propAtom, xcb_atom_t typeAtom, void* data, int len, int format) {
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, propAtom, typeAtom, format, len, data);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-bool XdndWorkaround::clientMessage(xcb_client_message_event_t* event) {
|
||||
- QByteArray event_type = atomName(event->type);
|
||||
- // qDebug() << "client message:" << event_type;
|
||||
-
|
||||
- // NOTE: Because of the limitation of Qt, this hack is required to provide
|
||||
- // Xdnd direct save (XDS) protocol support.
|
||||
- // https://www.freedesktop.org/wiki/Specifications/XDS/#index4h2
|
||||
- //
|
||||
- // XDS requires that the drop target should get and set the window property of the
|
||||
- // drag source to pass the file path, but in Qt there is NO way to know the
|
||||
- // window ID of the drag source so it's not possible to implement XDS with Qt alone.
|
||||
- // Here is a simple hack. We get the drag source window ID with raw XCB code.
|
||||
- // Then, save it on the drop target widget using QObject dynamic property.
|
||||
- // So in the drop event handler of the target widget, it can obtain the
|
||||
- // window ID of the drag source with QObject::property().
|
||||
- // This hack works 99.99% of the time, but it's not bullet-proof.
|
||||
- // In theory, there is one corner case for which this will not work.
|
||||
- // That is, when you drag multiple XDS sources at the same time and drop
|
||||
- // all of them on the same widget. (Does XDND support doing this?)
|
||||
- // I do not think that any app at the moment support this.
|
||||
- // Even if somebody is using it, X11 will die and we should solve this in Wayland instead.
|
||||
- //
|
||||
- if(event_type == "XdndDrop") {
|
||||
- // data.l[0] contains the XID of the source window.
|
||||
- // data.l[1] is reserved for future use (flags).
|
||||
- // data.l[2] contains the time stamp for retrieving the data. (new in version 1)
|
||||
- QWidget* target = QWidget::find(event->window);
|
||||
- if(target != nullptr) { // drop on our widget
|
||||
- target = qApp->widgetAt(QCursor::pos()); // get the exact child widget that receives the drop
|
||||
- if(target != nullptr) {
|
||||
- target->setProperty("xdnd::lastDragSource", event->data.data32[0]);
|
||||
- target->setProperty("xdnd::lastDropTime", event->data.data32[2]);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- else if(event_type == "XdndFinished") {
|
||||
- lastDrag_ = nullptr;
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
-bool XdndWorkaround::selectionNotify(xcb_selection_notify_event_t* event) {
|
||||
- qDebug() << "selection notify" << atomName(event->selection);
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-bool XdndWorkaround::selectionRequest(xcb_selection_request_event_t* event) {
|
||||
- xcb_connection_t* conn = QX11Info::connection();
|
||||
- if(event->property == XCB_ATOM_PRIMARY || event->property == XCB_ATOM_SECONDARY) {
|
||||
- return false; // we only touch selection requests related to XDnd
|
||||
- }
|
||||
- QByteArray prop_name = atomName(event->property);
|
||||
- if(prop_name == "CLIPBOARD") {
|
||||
- return false; // we do not touch clipboard, either
|
||||
- }
|
||||
-
|
||||
- xcb_atom_t atomFormat = event->target;
|
||||
- QByteArray type_name = atomName(atomFormat);
|
||||
- // qDebug() << "selection request" << prop_name << type_name;
|
||||
- // We only want to handle text/x-moz-url and text/uri-list
|
||||
- if(type_name == "text/x-moz-url" || type_name.startsWith("text/uri-list")) {
|
||||
- QDragManager* mgr = QDragManager::self();
|
||||
- QDrag* drag = mgr->object();
|
||||
- if(drag == nullptr) {
|
||||
- drag = lastDrag_;
|
||||
- }
|
||||
- QMimeData* mime = drag ? drag->mimeData() : nullptr;
|
||||
- if(mime != nullptr && mime->hasUrls()) {
|
||||
- QByteArray data;
|
||||
- const QList<QUrl> uris = mime->urls();
|
||||
- if(type_name == "text/x-moz-url") {
|
||||
- QString mozurl = uris.at(0).toString(QUrl::FullyEncoded);
|
||||
- data.append((const char*)mozurl.utf16(), mozurl.length() * 2);
|
||||
- }
|
||||
- else { // text/uri-list
|
||||
- for(const QUrl& uri : uris) {
|
||||
- data.append(uri.toString(QUrl::FullyEncoded).toUtf8());
|
||||
- data.append("\r\n");
|
||||
- }
|
||||
- }
|
||||
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, event->requestor, event->property,
|
||||
- atomFormat, 8, data.size(), (const void*)data.constData());
|
||||
- xcb_selection_notify_event_t notify;
|
||||
- notify.response_type = XCB_SELECTION_NOTIFY;
|
||||
- notify.requestor = event->requestor;
|
||||
- notify.selection = event->selection;
|
||||
- notify.time = event->time;
|
||||
- notify.property = event->property;
|
||||
- notify.target = atomFormat;
|
||||
- xcb_window_t proxy_target = event->requestor;
|
||||
- xcb_send_event(conn, false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char*)¬ify);
|
||||
- return true; // stop Qt 5 from touching the event
|
||||
- }
|
||||
- }
|
||||
- return false; // let Qt handle this
|
||||
-}
|
||||
-
|
||||
-bool XdndWorkaround::genericEvent(xcb_ge_generic_event_t* event) {
|
||||
- // check this is an xinput event
|
||||
- if(xinput2Enabled_ && event->extension == xinputOpCode_) {
|
||||
- if(event->event_type == XI_ButtonRelease) {
|
||||
- buttonRelease();
|
||||
- }
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
-void XdndWorkaround::buttonRelease() {
|
||||
- QDragManager* mgr = QDragManager::self();
|
||||
- lastDrag_ = mgr->object();
|
||||
- // qDebug() << "BUTTON RELEASE!!!!" << xcbDrag()->canDrop() << lastDrag_;
|
||||
-}
|
||||
-
|
||||
diff --git a/src/xdndworkaround.h b/src/xdndworkaround.h
|
||||
index 62f86c7..db194e1 100644
|
||||
--- a/src/xdndworkaround.h
|
||||
+++ b/src/xdndworkaround.h
|
||||
@@ -60,7 +60,7 @@ class XdndWorkaround : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
explicit XdndWorkaround();
|
||||
~XdndWorkaround() override;
|
||||
- bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
+// bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
static QByteArray atomName(xcb_atom_t atom);
|
||||
static xcb_atom_t internAtom(const char* name, int len = -1);
|
||||
static QByteArray windowProperty(xcb_window_t window, xcb_atom_t propAtom, xcb_atom_t typeAtom, int len);
|
||||
--
|
||||
2.37.3
|
||||
|
||||
Reference in New Issue
Block a user