From f34b6911d2aff50d6d4b7499cb26d567653c97bb Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 9 Jul 2024 12:45:35 +0200 Subject: [PATCH 1/9] Initial backend plugin infrastructure --- panel/CMakeLists.txt | 17 +- panel/backends/CMakeLists.txt | 17 ++ ...ctbackend.cpp => ilxqtabstractwmiface.cpp} | 6 +- ...stractbackend.h => ilxqtabstractwmiface.h} | 35 +++- panel/backends/lxqtdummywmbackend.cpp | 170 +++++++++++++++++ ...bardummybackend.h => lxqtdummywmbackend.h} | 12 +- panel/backends/lxqttaskbardummybackend.cpp | 171 ------------------ panel/backends/xcb/CMakeLists.txt | 20 ++ ...rbackend_x11.cpp => lxqtwmbackend_x11.cpp} | 103 ++++++----- ...skbarbackend_x11.h => lxqtwmbackend_x11.h} | 24 ++- panel/lxqtpanel.cpp | 10 +- panel/lxqtpanelapplication.cpp | 113 ++++++++++-- panel/lxqtpanelapplication.h | 4 +- panel/lxqtpanelapplication_p.h | 6 +- plugin-desktopswitch/desktopswitch.cpp | 10 +- plugin-desktopswitch/desktopswitch.h | 4 +- .../desktopswitchconfiguration.cpp | 2 +- plugin-showdesktop/showdesktop.cpp | 2 +- plugin-taskbar/lxqttaskbar.cpp | 8 +- plugin-taskbar/lxqttaskbar.h | 6 +- plugin-taskbar/lxqttaskbarconfiguration.cpp | 2 +- plugin-taskbar/lxqttaskbarproxymodel.cpp | 18 +- plugin-taskbar/lxqttaskbarproxymodel.h | 8 +- plugin-taskbar/lxqttaskbutton.cpp | 2 +- plugin-taskbar/lxqttaskbutton.h | 4 +- plugin-taskbar/lxqttaskgroup.cpp | 6 +- 26 files changed, 470 insertions(+), 310 deletions(-) rename panel/backends/{ilxqttaskbarabstractbackend.cpp => ilxqtabstractwmiface.cpp} (64%) rename panel/backends/{ilxqttaskbarabstractbackend.h => ilxqtabstractwmiface.h} (76%) create mode 100644 panel/backends/lxqtdummywmbackend.cpp rename panel/backends/{lxqttaskbardummybackend.h => lxqtdummywmbackend.h} (89%) delete mode 100644 panel/backends/lxqttaskbardummybackend.cpp rename panel/backends/xcb/{lxqttaskbarbackend_x11.cpp => lxqtwmbackend_x11.cpp} (84%) rename panel/backends/xcb/{lxqttaskbarbackend_x11.h => lxqtwmbackend_x11.h} (83%) diff --git a/panel/CMakeLists.txt b/panel/CMakeLists.txt index 074c62af3..b9ba8f10f 100644 --- a/panel/CMakeLists.txt +++ b/panel/CMakeLists.txt @@ -1,6 +1,6 @@ set(PROJECT lxqt-panel) -# TODO +# Window Manager backends add_subdirectory(backends) set(PRIV_HEADERS @@ -21,12 +21,6 @@ set(PRIV_HEADERS config/configstyling.h config/configpluginswidget.h config/addplugindialog.h - - backends/ilxqttaskbarabstractbackend.h - backends/lxqttaskbartypes.h - - backends/lxqttaskbardummybackend.h - backends/xcb/lxqttaskbarbackend_x11.h ) # using LXQt namespace in the public headers. @@ -35,9 +29,6 @@ set(PUB_HEADERS pluginsettings.h ilxqtpanelplugin.h ilxqtpanel.h - - backends/ilxqttaskbarabstractbackend.h - backends/lxqttaskbartypes.h ) set(SOURCES @@ -57,11 +48,6 @@ set(SOURCES config/configstyling.cpp config/configpluginswidget.cpp config/addplugindialog.cpp - - backends/ilxqttaskbarabstractbackend.cpp - - backends/lxqttaskbardummybackend.cpp - backends/xcb/lxqttaskbarbackend_x11.cpp ) set(UI @@ -122,6 +108,7 @@ target_link_libraries(${PROJECT} KF6::WindowSystem LayerShellQt::Interface ${STATIC_PLUGINS} + lxqt-panel-backend-common ) set_property(TARGET ${PROJECT} PROPERTY ENABLE_EXPORTS TRUE) diff --git a/panel/backends/CMakeLists.txt b/panel/backends/CMakeLists.txt index 8f34a3c67..cf117c7e3 100644 --- a/panel/backends/CMakeLists.txt +++ b/panel/backends/CMakeLists.txt @@ -1 +1,18 @@ +# Common interface for Window Manager abstraction backend +# This also contains dummy backend + +add_library(lxqt-panel-backend-common STATIC + + lxqttaskbartypes.h + ilxqtabstractwmiface.h + ilxqtabstractwmiface.cpp + + lxqtdummywmbackend.h + lxqtdummywmbackend.cpp +) + +target_link_libraries(lxqt-panel-backend-common + Qt6::Gui +) + add_subdirectory(xcb) diff --git a/panel/backends/ilxqttaskbarabstractbackend.cpp b/panel/backends/ilxqtabstractwmiface.cpp similarity index 64% rename from panel/backends/ilxqttaskbarabstractbackend.cpp rename to panel/backends/ilxqtabstractwmiface.cpp index 137728263..080b07324 100644 --- a/panel/backends/ilxqttaskbarabstractbackend.cpp +++ b/panel/backends/ilxqtabstractwmiface.cpp @@ -1,13 +1,13 @@ -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "ilxqtabstractwmiface.h" -ILXQtTaskbarAbstractBackend::ILXQtTaskbarAbstractBackend(QObject *parent) +ILXQtAbstractWMInterface::ILXQtAbstractWMInterface(QObject *parent) : QObject(parent) { } -void ILXQtTaskbarAbstractBackend::moveApplicationToPrevNextDesktop(WId windowId, bool next) +void ILXQtAbstractWMInterface::moveApplicationToPrevNextDesktop(WId windowId, bool next) { int count = getWorkspacesCount(); if (count <= 1) diff --git a/panel/backends/ilxqttaskbarabstractbackend.h b/panel/backends/ilxqtabstractwmiface.h similarity index 76% rename from panel/backends/ilxqttaskbarabstractbackend.h rename to panel/backends/ilxqtabstractwmiface.h index 44840671a..4bd4c6561 100644 --- a/panel/backends/ilxqttaskbarabstractbackend.h +++ b/panel/backends/ilxqtabstractwmiface.h @@ -1,19 +1,20 @@ -#ifndef ILXQTTASKBARABSTRACTBACKEND_H -#define ILXQTTASKBARABSTRACTBACKEND_H +#ifndef ILXQT_ABSTRACT_WM_INTERFACE_H +#define ILXQT_ABSTRACT_WM_INTERFACE_H #include +#include "../lxqtpanelglobals.h" #include "lxqttaskbartypes.h" class QIcon; class QScreen; -class ILXQtTaskbarAbstractBackend : public QObject +class LXQT_PANEL_API ILXQtAbstractWMInterface : public QObject { Q_OBJECT public: - explicit ILXQtTaskbarAbstractBackend(QObject *parent = nullptr); + explicit ILXQtAbstractWMInterface(QObject *parent = nullptr); // Backend virtual bool supportsAction(WId windowId, LXQtTaskBarBackendAction action) const = 0; @@ -96,4 +97,28 @@ class ILXQtTaskbarAbstractBackend : public QObject void activeWindowChanged(WId windowId); }; -#endif // ILXQTTASKBARABSTRACTBACKEND_H +class LXQT_PANEL_API ILXQtWMBackendLibrary +{ +public: + /** + Destroys the ILXQtWMBackendLibrary object. + **/ + virtual ~ILXQtWMBackendLibrary() {} + + /** + Returns the score of this backend for current detected environment. + This is used to select correct backend at runtime + **/ + virtual int getBackendScore() const = 0; + + /** + Returns the root component object of the backend. When the library is finally unloaded, the root component will automatically be deleted. + **/ + virtual ILXQtAbstractWMInterface* instance() const = 0; +}; + + +Q_DECLARE_INTERFACE(ILXQtWMBackendLibrary, + "lxqt.org/Panel/WMInterface/1.0") + +#endif // ILXQT_ABSTRACT_WM_INTERFACE_H diff --git a/panel/backends/lxqtdummywmbackend.cpp b/panel/backends/lxqtdummywmbackend.cpp new file mode 100644 index 000000000..9d8e2f5e1 --- /dev/null +++ b/panel/backends/lxqtdummywmbackend.cpp @@ -0,0 +1,170 @@ +#include "lxqtdummywmbackend.h" + +#include + +LXQtDummyWMBackend::LXQtDummyWMBackend(QObject *parent) + : ILXQtAbstractWMInterface(parent) +{ + +} + +/************************************************ + * Windows function + ************************************************/ +bool LXQtDummyWMBackend::supportsAction(WId, LXQtTaskBarBackendAction) const +{ + return false; +} + +bool LXQtDummyWMBackend::reloadWindows() +{ + return false; +} + +QVector LXQtDummyWMBackend::getCurrentWindows() const +{ + return {}; +} + +QString LXQtDummyWMBackend::getWindowTitle(WId) const +{ + return QString(); +} + +bool LXQtDummyWMBackend::applicationDemandsAttention(WId) const +{ + return false; +} + +QIcon LXQtDummyWMBackend::getApplicationIcon(WId, int) const +{ + return QIcon(); +} + +QString LXQtDummyWMBackend::getWindowClass(WId) const +{ + return QString(); +} + +LXQtTaskBarWindowLayer LXQtDummyWMBackend::getWindowLayer(WId) const +{ + return LXQtTaskBarWindowLayer::Normal; +} + +bool LXQtDummyWMBackend::setWindowLayer(WId, LXQtTaskBarWindowLayer) +{ + return false; +} + +LXQtTaskBarWindowState LXQtDummyWMBackend::getWindowState(WId) const +{ + return LXQtTaskBarWindowState::Normal; +} + +bool LXQtDummyWMBackend::setWindowState(WId, LXQtTaskBarWindowState, bool) +{ + return false; +} + +bool LXQtDummyWMBackend::isWindowActive(WId) const +{ + return false; +} + +bool LXQtDummyWMBackend::raiseWindow(WId, bool) +{ + return false; +} + +bool LXQtDummyWMBackend::closeWindow(WId) +{ + return false; +} + +WId LXQtDummyWMBackend::getActiveWindow() const +{ + return 0; +} + + +/************************************************ + * Workspaces + ************************************************/ +int LXQtDummyWMBackend::getWorkspacesCount() const +{ + return 1; // Fake 1 workspace +} + +QString LXQtDummyWMBackend::getWorkspaceName(int) const +{ + return QString(); +} + +int LXQtDummyWMBackend::getCurrentWorkspace() const +{ + return 0; +} + +bool LXQtDummyWMBackend::setCurrentWorkspace(int) +{ + return false; +} + +int LXQtDummyWMBackend::getWindowWorkspace(WId) const +{ + return 0; +} + +bool LXQtDummyWMBackend::setWindowOnWorkspace(WId, int) +{ + return false; +} + +void LXQtDummyWMBackend::moveApplicationToPrevNextMonitor(WId, bool, bool) +{ + //No-op +} + +bool LXQtDummyWMBackend::isWindowOnScreen(QScreen *, WId) const +{ + return false; +} + +bool LXQtDummyWMBackend::setDesktopLayout(Qt::Orientation, int, int, bool) +{ + return false; +} + +/************************************************ + * X11 Specific + ************************************************/ +void LXQtDummyWMBackend::moveApplication(WId) +{ + //No-op +} + +void LXQtDummyWMBackend::resizeApplication(WId) +{ + //No-op +} + +void LXQtDummyWMBackend::refreshIconGeometry(WId, QRect const &) +{ + //No-op +} + +bool LXQtDummyWMBackend::isAreaOverlapped(const QRect &) const +{ + return false; +} + +bool LXQtDummyWMBackend::isShowingDesktop() const +{ + return false; +} + +bool LXQtDummyWMBackend::showDesktop(bool) +{ + return false; +} + diff --git a/panel/backends/lxqttaskbardummybackend.h b/panel/backends/lxqtdummywmbackend.h similarity index 89% rename from panel/backends/lxqttaskbardummybackend.h rename to panel/backends/lxqtdummywmbackend.h index 15506838f..75a9b04b7 100644 --- a/panel/backends/lxqttaskbardummybackend.h +++ b/panel/backends/lxqtdummywmbackend.h @@ -1,14 +1,14 @@ -#ifndef LXQTTASKBARDUMMYBACKEND_H -#define LXQTTASKBARDUMMYBACKEND_H +#ifndef LXQT_DUMMY_WM_BACKEND_H +#define LXQT_DUMMY_WM_BACKEND_H -#include "ilxqttaskbarabstractbackend.h" +#include "ilxqtabstractwmiface.h" -class LXQtTaskBarDummyBackend : public ILXQtTaskbarAbstractBackend +class LXQtDummyWMBackend : public ILXQtAbstractWMInterface { Q_OBJECT public: - explicit LXQtTaskBarDummyBackend(QObject *parent = nullptr); + explicit LXQtDummyWMBackend(QObject *parent = nullptr); // Backend bool supportsAction(WId windowId, LXQtTaskBarBackendAction action) const override; @@ -85,4 +85,4 @@ class LXQtTaskBarDummyBackend : public ILXQtTaskbarAbstractBackend void activeWindowChanged(WId windowId); }; -#endif // LXQTTASKBARDUMMYBACKEND_H +#endif // LXQT_DUMMY_WM_BACKEND_H diff --git a/panel/backends/lxqttaskbardummybackend.cpp b/panel/backends/lxqttaskbardummybackend.cpp deleted file mode 100644 index 15e7e1149..000000000 --- a/panel/backends/lxqttaskbardummybackend.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include "lxqttaskbardummybackend.h" - -#include - -LXQtTaskBarDummyBackend::LXQtTaskBarDummyBackend(QObject *parent) - : ILXQtTaskbarAbstractBackend(parent) -{ - -} - - -/************************************************ - * Windows function - ************************************************/ -bool LXQtTaskBarDummyBackend::supportsAction(WId, LXQtTaskBarBackendAction) const -{ - return false; -} - -bool LXQtTaskBarDummyBackend::reloadWindows() -{ - return false; -} - -QVector LXQtTaskBarDummyBackend::getCurrentWindows() const -{ - return {}; -} - -QString LXQtTaskBarDummyBackend::getWindowTitle(WId) const -{ - return QString(); -} - -bool LXQtTaskBarDummyBackend::applicationDemandsAttention(WId) const -{ - return false; -} - -QIcon LXQtTaskBarDummyBackend::getApplicationIcon(WId, int) const -{ - return QIcon(); -} - -QString LXQtTaskBarDummyBackend::getWindowClass(WId) const -{ - return QString(); -} - -LXQtTaskBarWindowLayer LXQtTaskBarDummyBackend::getWindowLayer(WId) const -{ - return LXQtTaskBarWindowLayer::Normal; -} - -bool LXQtTaskBarDummyBackend::setWindowLayer(WId, LXQtTaskBarWindowLayer) -{ - return false; -} - -LXQtTaskBarWindowState LXQtTaskBarDummyBackend::getWindowState(WId) const -{ - return LXQtTaskBarWindowState::Normal; -} - -bool LXQtTaskBarDummyBackend::setWindowState(WId, LXQtTaskBarWindowState, bool) -{ - return false; -} - -bool LXQtTaskBarDummyBackend::isWindowActive(WId) const -{ - return false; -} - -bool LXQtTaskBarDummyBackend::raiseWindow(WId, bool) -{ - return false; -} - -bool LXQtTaskBarDummyBackend::closeWindow(WId) -{ - return false; -} - -WId LXQtTaskBarDummyBackend::getActiveWindow() const -{ - return 0; -} - - -/************************************************ - * Workspaces - ************************************************/ -int LXQtTaskBarDummyBackend::getWorkspacesCount() const -{ - return 1; // Fake 1 workspace -} - -QString LXQtTaskBarDummyBackend::getWorkspaceName(int) const -{ - return QString(); -} - -int LXQtTaskBarDummyBackend::getCurrentWorkspace() const -{ - return 0; -} - -bool LXQtTaskBarDummyBackend::setCurrentWorkspace(int) -{ - return false; -} - -int LXQtTaskBarDummyBackend::getWindowWorkspace(WId) const -{ - return 0; -} - -bool LXQtTaskBarDummyBackend::setWindowOnWorkspace(WId, int) -{ - return false; -} - -void LXQtTaskBarDummyBackend::moveApplicationToPrevNextMonitor(WId, bool, bool) -{ - //No-op -} - -bool LXQtTaskBarDummyBackend::isWindowOnScreen(QScreen *, WId) const -{ - return false; -} - -bool LXQtTaskBarDummyBackend::setDesktopLayout(Qt::Orientation, int, int, bool) -{ - return false; -} - -/************************************************ - * X11 Specific - ************************************************/ -void LXQtTaskBarDummyBackend::moveApplication(WId) -{ - //No-op -} - -void LXQtTaskBarDummyBackend::resizeApplication(WId) -{ - //No-op -} - -void LXQtTaskBarDummyBackend::refreshIconGeometry(WId, QRect const &) -{ - //No-op -} - -bool LXQtTaskBarDummyBackend::isAreaOverlapped(const QRect &) const -{ - return false; -} - -bool LXQtTaskBarDummyBackend::isShowingDesktop() const -{ - return false; -} - -bool LXQtTaskBarDummyBackend::showDesktop(bool) -{ - return false; -} - diff --git a/panel/backends/xcb/CMakeLists.txt b/panel/backends/xcb/CMakeLists.txt index 8b1378917..08f2fe4b1 100644 --- a/panel/backends/xcb/CMakeLists.txt +++ b/panel/backends/xcb/CMakeLists.txt @@ -1 +1,21 @@ +set(NAME xcb_backend) +set(PROGRAM "lxqt-panel") +set(BACKEND "backend") +project(${PROGRAM}_${BACKEND}_${NAME}) +set(PROG_SHARE_DIR ${CMAKE_INSTALL_FULL_DATAROOTDIR}/lxqt/${PROGRAM}/${BACKEND}) +set(PLUGIN_SHARE_DIR ${PROG_SHARE_DIR}/${BACKEND}/${NAME}) +#************************************************ + +if (NOT DEFINED PLUGIN_DIR) + set (PLUGIN_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/${PROGRAM}) +endif (NOT DEFINED PLUGIN_DIR) + +set(QTX_LIBRARIES Qt6::Gui) + +set(SRC lxqtwmbackend_x11.h lxqtwmbackend_x11.cpp) + +add_library(${NAME} MODULE ${SRC}) # build dynamically loadable modules +install(TARGETS ${NAME} DESTINATION ${PLUGIN_DIR}/${BACKEND}) # install the *.so file + +target_link_libraries(${NAME} ${QTX_LIBRARIES} KF6::WindowSystem) diff --git a/panel/backends/xcb/lxqttaskbarbackend_x11.cpp b/panel/backends/xcb/lxqtwmbackend_x11.cpp similarity index 84% rename from panel/backends/xcb/lxqttaskbarbackend_x11.cpp rename to panel/backends/xcb/lxqtwmbackend_x11.cpp index fe0452776..40fd06a81 100644 --- a/panel/backends/xcb/lxqttaskbarbackend_x11.cpp +++ b/panel/backends/xcb/lxqtwmbackend_x11.cpp @@ -1,4 +1,4 @@ -#include "lxqttaskbarbackend_x11.h" +#include "lxqtwmbackend_x11.h" #include #include @@ -16,28 +16,28 @@ #include #undef Bool -LXQtTaskbarX11Backend::LXQtTaskbarX11Backend(QObject *parent) - : ILXQtTaskbarAbstractBackend(parent) +LXQtWMBackendX11::LXQtWMBackendX11(QObject *parent) + : ILXQtAbstractWMInterface(parent) { auto *x11Application = qGuiApp->nativeInterface(); - Q_ASSERT_X(x11Application, "LXQtTaskbarX11Backend", "Constructed without X11 connection"); + Q_ASSERT_X(x11Application, "LXQtWMBackendX11", "Constructed without X11 connection"); m_X11Display = x11Application->display(); m_xcbConnection = x11Application->connection(); - connect(KX11Extras::self(), &KX11Extras::windowChanged, this, &LXQtTaskbarX11Backend::onWindowChanged); - connect(KX11Extras::self(), &KX11Extras::windowAdded, this, &LXQtTaskbarX11Backend::onWindowAdded); - connect(KX11Extras::self(), &KX11Extras::windowRemoved, this, &LXQtTaskbarX11Backend::onWindowRemoved); + connect(KX11Extras::self(), &KX11Extras::windowChanged, this, &LXQtWMBackendX11::onWindowChanged); + connect(KX11Extras::self(), &KX11Extras::windowAdded, this, &LXQtWMBackendX11::onWindowAdded); + connect(KX11Extras::self(), &KX11Extras::windowRemoved, this, &LXQtWMBackendX11::onWindowRemoved); - connect(KX11Extras::self(), &KX11Extras::numberOfDesktopsChanged, this, &ILXQtTaskbarAbstractBackend::workspacesCountChanged); - connect(KX11Extras::self(), &KX11Extras::currentDesktopChanged, this, &ILXQtTaskbarAbstractBackend::currentWorkspaceChanged); + connect(KX11Extras::self(), &KX11Extras::numberOfDesktopsChanged, this, &ILXQtAbstractWMInterface::workspacesCountChanged); + connect(KX11Extras::self(), &KX11Extras::currentDesktopChanged, this, &ILXQtAbstractWMInterface::currentWorkspaceChanged); - connect(KX11Extras::self(), &KX11Extras::activeWindowChanged, this, &ILXQtTaskbarAbstractBackend::activeWindowChanged); + connect(KX11Extras::self(), &KX11Extras::activeWindowChanged, this, &ILXQtAbstractWMInterface::activeWindowChanged); } /************************************************ * Model slots ************************************************/ -void LXQtTaskbarX11Backend::onWindowChanged(WId windowId, NET::Properties prop, NET::Properties2 prop2) +void LXQtWMBackendX11::onWindowChanged(WId windowId, NET::Properties prop, NET::Properties2 prop2) { if(!m_windows.contains(windowId)) { @@ -97,7 +97,7 @@ void LXQtTaskbarX11Backend::onWindowChanged(WId windowId, NET::Properties prop, emit windowPropertyChanged(windowId, int(LXQtTaskBarWindowProperty::Urgency)); } -void LXQtTaskbarX11Backend::onWindowAdded(WId windowId) +void LXQtWMBackendX11::onWindowAdded(WId windowId) { if(m_windows.contains(windowId)) return; @@ -108,7 +108,7 @@ void LXQtTaskbarX11Backend::onWindowAdded(WId windowId) addWindow_internal(windowId); } -void LXQtTaskbarX11Backend::onWindowRemoved(WId windowId) +void LXQtWMBackendX11::onWindowRemoved(WId windowId) { const int row = m_windows.indexOf(windowId); if(row == -1) @@ -122,7 +122,7 @@ void LXQtTaskbarX11Backend::onWindowRemoved(WId windowId) /************************************************ * Model private functions ************************************************/ -bool LXQtTaskbarX11Backend::acceptWindow(WId windowId) const +bool LXQtWMBackendX11::acceptWindow(WId windowId) const { QFlags ignoreList; ignoreList |= NET::DesktopMask; @@ -161,7 +161,7 @@ bool LXQtTaskbarX11Backend::acceptWindow(WId windowId) const return !NET::typeMatchesMask(info.windowType(NET::AllTypesMask), normalFlag); } -void LXQtTaskbarX11Backend::addWindow_internal(WId windowId, bool emitAdded) +void LXQtWMBackendX11::addWindow_internal(WId windowId, bool emitAdded) { m_windows.append(windowId); if(emitAdded) @@ -172,7 +172,7 @@ void LXQtTaskbarX11Backend::addWindow_internal(WId windowId, bool emitAdded) /************************************************ * Windows function ************************************************/ -bool LXQtTaskbarX11Backend::supportsAction(WId windowId, LXQtTaskBarBackendAction action) const +bool LXQtWMBackendX11::supportsAction(WId windowId, LXQtTaskBarBackendAction action) const { NET::Action x11Action; @@ -221,7 +221,7 @@ bool LXQtTaskbarX11Backend::supportsAction(WId windowId, LXQtTaskBarBackendActio return info.actionSupported(x11Action); } -bool LXQtTaskbarX11Backend::reloadWindows() +bool LXQtWMBackendX11::reloadWindows() { QVector oldWindows; qSwap(oldWindows, m_windows); @@ -254,37 +254,37 @@ bool LXQtTaskbarX11Backend::reloadWindows() return true; } -QVector LXQtTaskbarX11Backend::getCurrentWindows() const +QVector LXQtWMBackendX11::getCurrentWindows() const { return m_windows; } -QString LXQtTaskbarX11Backend::getWindowTitle(WId windowId) const +QString LXQtWMBackendX11::getWindowTitle(WId windowId) const { KWindowInfo info(windowId, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); return title; } -bool LXQtTaskbarX11Backend::applicationDemandsAttention(WId windowId) const +bool LXQtWMBackendX11::applicationDemandsAttention(WId windowId) const { WId appRootWindow = XDefaultRootWindow(m_X11Display); return NETWinInfo(m_xcbConnection, windowId, appRootWindow, NET::Properties{}, NET::WM2Urgency).urgency() || KWindowInfo{windowId, NET::WMState}.hasState(NET::DemandsAttention); } -QIcon LXQtTaskbarX11Backend::getApplicationIcon(WId windowId, int devicePixels) const +QIcon LXQtWMBackendX11::getApplicationIcon(WId windowId, int devicePixels) const { return KX11Extras::icon(windowId, devicePixels, devicePixels); } -QString LXQtTaskbarX11Backend::getWindowClass(WId windowId) const +QString LXQtWMBackendX11::getWindowClass(WId windowId) const { KWindowInfo info(windowId, NET::Properties(), NET::WM2WindowClass); return QString::fromUtf8(info.windowClassClass()); } -LXQtTaskBarWindowLayer LXQtTaskbarX11Backend::getWindowLayer(WId windowId) const +LXQtTaskBarWindowLayer LXQtWMBackendX11::getWindowLayer(WId windowId) const { NET::States state = KWindowInfo(windowId, NET::WMState).state(); if(state.testFlag(NET::KeepAbove)) @@ -294,7 +294,7 @@ LXQtTaskBarWindowLayer LXQtTaskbarX11Backend::getWindowLayer(WId windowId) const return LXQtTaskBarWindowLayer::Normal; } -bool LXQtTaskbarX11Backend::setWindowLayer(WId windowId, LXQtTaskBarWindowLayer layer) +bool LXQtWMBackendX11::setWindowLayer(WId windowId, LXQtTaskBarWindowLayer layer) { switch(layer) { @@ -317,7 +317,7 @@ bool LXQtTaskbarX11Backend::setWindowLayer(WId windowId, LXQtTaskBarWindowLayer return true; } -LXQtTaskBarWindowState LXQtTaskbarX11Backend::getWindowState(WId windowId) const +LXQtTaskBarWindowState LXQtWMBackendX11::getWindowState(WId windowId) const { KWindowInfo info(windowId,NET::WMState | NET::XAWMState); if(info.isMinimized()) @@ -340,7 +340,7 @@ LXQtTaskBarWindowState LXQtTaskbarX11Backend::getWindowState(WId windowId) const return LXQtTaskBarWindowState::Normal; } -bool LXQtTaskbarX11Backend::setWindowState(WId windowId, LXQtTaskBarWindowState state, bool set) +bool LXQtWMBackendX11::setWindowState(WId windowId, LXQtTaskBarWindowState state, bool set) { // NOTE: window activation is left to the caller @@ -393,12 +393,12 @@ bool LXQtTaskbarX11Backend::setWindowState(WId windowId, LXQtTaskBarWindowState return true; } -bool LXQtTaskbarX11Backend::isWindowActive(WId windowId) const +bool LXQtWMBackendX11::isWindowActive(WId windowId) const { return KX11Extras::activeWindow() == windowId; } -bool LXQtTaskbarX11Backend::raiseWindow(WId windowId, bool onCurrentWorkSpace) +bool LXQtWMBackendX11::raiseWindow(WId windowId, bool onCurrentWorkSpace) { if (onCurrentWorkSpace && getWindowState(windowId) == LXQtTaskBarWindowState::Minimized) { @@ -418,14 +418,14 @@ bool LXQtTaskbarX11Backend::raiseWindow(WId windowId, bool onCurrentWorkSpace) return true; } -bool LXQtTaskbarX11Backend::closeWindow(WId windowId) +bool LXQtWMBackendX11::closeWindow(WId windowId) { // FIXME: Why there is no such thing in KWindowSystem?? NETRootInfo(m_xcbConnection, NET::CloseWindow).closeWindowRequest(windowId); return true; } -WId LXQtTaskbarX11Backend::getActiveWindow() const +WId LXQtWMBackendX11::getActiveWindow() const { return KX11Extras::activeWindow(); } @@ -434,22 +434,22 @@ WId LXQtTaskbarX11Backend::getActiveWindow() const /************************************************ * Workspaces ************************************************/ -int LXQtTaskbarX11Backend::getWorkspacesCount() const +int LXQtWMBackendX11::getWorkspacesCount() const { return KX11Extras::numberOfDesktops(); } -QString LXQtTaskbarX11Backend::getWorkspaceName(int idx) const +QString LXQtWMBackendX11::getWorkspaceName(int idx) const { return KX11Extras::desktopName(idx); } -int LXQtTaskbarX11Backend::getCurrentWorkspace() const +int LXQtWMBackendX11::getCurrentWorkspace() const { return KX11Extras::currentDesktop(); } -bool LXQtTaskbarX11Backend::setCurrentWorkspace(int idx) +bool LXQtWMBackendX11::setCurrentWorkspace(int idx) { if(KX11Extras::currentDesktop() == idx) return true; @@ -458,19 +458,19 @@ bool LXQtTaskbarX11Backend::setCurrentWorkspace(int idx) return true; } -int LXQtTaskbarX11Backend::getWindowWorkspace(WId windowId) const +int LXQtWMBackendX11::getWindowWorkspace(WId windowId) const { KWindowInfo info(windowId, NET::WMDesktop); return info.desktop(); } -bool LXQtTaskbarX11Backend::setWindowOnWorkspace(WId windowId, int idx) +bool LXQtWMBackendX11::setWindowOnWorkspace(WId windowId, int idx) { KX11Extras::setOnDesktop(windowId, idx); return true; } -void LXQtTaskbarX11Backend::moveApplicationToPrevNextMonitor(WId windowId, bool next, bool raiseOnCurrentDesktop) +void LXQtWMBackendX11::moveApplicationToPrevNextMonitor(WId windowId, bool next, bool raiseOnCurrentDesktop) { KWindowInfo info(windowId, NET::WMDesktop); if (!info.isOnCurrentDesktop()) @@ -516,7 +516,7 @@ void LXQtTaskbarX11Backend::moveApplicationToPrevNextMonitor(WId windowId, bool } } -bool LXQtTaskbarX11Backend::isWindowOnScreen(QScreen *screen, WId windowId) const +bool LXQtWMBackendX11::isWindowOnScreen(QScreen *screen, WId windowId) const { //TODO: old code was: //return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); @@ -528,7 +528,7 @@ bool LXQtTaskbarX11Backend::isWindowOnScreen(QScreen *screen, WId windowId) cons return screen->geometry().intersects(r); } -bool LXQtTaskbarX11Backend::setDesktopLayout(Qt::Orientation orientation, int rows, int columns, bool rightToLeft) +bool LXQtWMBackendX11::setDesktopLayout(Qt::Orientation orientation, int rows, int columns, bool rightToLeft) { NETRootInfo mDesktops(m_xcbConnection, NET::NumberOfDesktops | NET::CurrentDesktop | NET::DesktopNames, NET::WM2DesktopLayout); @@ -550,7 +550,7 @@ bool LXQtTaskbarX11Backend::setDesktopLayout(Qt::Orientation orientation, int ro /************************************************ * X11 Specific ************************************************/ -void LXQtTaskbarX11Backend::moveApplication(WId windowId) +void LXQtWMBackendX11::moveApplication(WId windowId) { KWindowInfo info(windowId, NET::WMDesktop); if (!info.isOnCurrentDesktop()) @@ -568,7 +568,7 @@ void LXQtTaskbarX11Backend::moveApplication(WId windowId) NETRootInfo(m_xcbConnection, NET::WMMoveResize).moveResizeRequest(windowId, X, Y, NET::Move); } -void LXQtTaskbarX11Backend::resizeApplication(WId windowId) +void LXQtWMBackendX11::resizeApplication(WId windowId) { KWindowInfo info(windowId, NET::WMDesktop); if (!info.isOnCurrentDesktop()) @@ -586,7 +586,7 @@ void LXQtTaskbarX11Backend::resizeApplication(WId windowId) NETRootInfo(m_xcbConnection, NET::WMMoveResize).moveResizeRequest(windowId, X, Y, NET::BottomRight); } -void LXQtTaskbarX11Backend::refreshIconGeometry(WId windowId, QRect const & geom) +void LXQtWMBackendX11::refreshIconGeometry(WId windowId, QRect const & geom) { // NOTE: This function announces where the task icon is, // such that X11 WMs can perform their related animations correctly. @@ -616,7 +616,7 @@ void LXQtTaskbarX11Backend::refreshIconGeometry(WId windowId, QRect const & geom info.setIconGeometry(nrect); } -bool LXQtTaskbarX11Backend::isAreaOverlapped(const QRect &area) const +bool LXQtWMBackendX11::isAreaOverlapped(const QRect &area) const { //TODO: reuse our m_windows cache? QFlags ignoreList; @@ -648,13 +648,26 @@ bool LXQtTaskbarX11Backend::isAreaOverlapped(const QRect &area) const return false; } -bool LXQtTaskbarX11Backend::isShowingDesktop() const +bool LXQtWMBackendX11::isShowingDesktop() const { return KWindowSystem::showingDesktop(); } -bool LXQtTaskbarX11Backend::showDesktop(bool value) +bool LXQtWMBackendX11::showDesktop(bool value) { KWindowSystem::setShowingDesktop(value); return true; } + +int LXQtWMBackendX11Library::getBackendScore() const +{ + auto *x11Application = qGuiApp->nativeInterface(); + if(x11Application) + return 80; + return 30; +} + +ILXQtAbstractWMInterface *LXQtWMBackendX11Library::instance() const +{ + return new LXQtWMBackendX11; +} diff --git a/panel/backends/xcb/lxqttaskbarbackend_x11.h b/panel/backends/xcb/lxqtwmbackend_x11.h similarity index 83% rename from panel/backends/xcb/lxqttaskbarbackend_x11.h rename to panel/backends/xcb/lxqtwmbackend_x11.h index 2478b3fff..1457c2b2d 100644 --- a/panel/backends/xcb/lxqttaskbarbackend_x11.h +++ b/panel/backends/xcb/lxqtwmbackend_x11.h @@ -1,20 +1,19 @@ -#ifndef LXQTTASKBARBACKEND_X11_H -#define LXQTTASKBARBACKEND_X11_H +#ifndef LXQT_WM_BACKEND_X11_H +#define LXQT_WM_BACKEND_X11_H -#include "../ilxqttaskbarabstractbackend.h" +#include "../ilxqtabstractwmiface.h" -//TODO: make PIMPL to forward declare NET::Properties, Display, xcb_connection_t #include typedef struct _XDisplay Display; struct xcb_connection_t; -class LXQtTaskbarX11Backend : public ILXQtTaskbarAbstractBackend +class LXQtWMBackendX11 : public ILXQtAbstractWMInterface { Q_OBJECT public: - explicit LXQtTaskbarX11Backend(QObject *parent = nullptr); + explicit LXQtWMBackendX11(QObject *parent = nullptr); // Backend virtual bool supportsAction(WId windowId, LXQtTaskBarBackendAction action) const override; @@ -86,4 +85,15 @@ private slots: QVector m_windows; }; -#endif // LXQTTASKBARBACKEND_X11_H +class LXQtWMBackendX11Library: public QObject, public ILXQtWMBackendLibrary +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "lxqt.org/Panel/WMInterface/1.0") + Q_INTERFACES(ILXQtWMBackendLibrary) +public: + int getBackendScore() const override; + + ILXQtAbstractWMInterface* instance() const override; +}; + +#endif // LXQT_WM_BACKEND_X11_H diff --git a/panel/lxqtpanel.cpp b/panel/lxqtpanel.cpp index f4144ff41..17e0c3520 100644 --- a/panel/lxqtpanel.cpp +++ b/panel/lxqtpanel.cpp @@ -52,7 +52,7 @@ #include #include -#include "backends/ilxqttaskbarabstractbackend.h" +#include "backends/ilxqtabstractwmiface.h" #include @@ -281,18 +281,18 @@ LXQtPanel::LXQtPanel(const QString &configGroup, LXQt::Settings *settings, QWidg LXQtPanelApplication *a = reinterpret_cast(qApp); auto wmBackend = a->getWMBackend(); - connect(wmBackend, &ILXQtTaskbarAbstractBackend::windowAdded, this, [this] { + connect(wmBackend, &ILXQtAbstractWMInterface::windowAdded, this, [this] { if (mHidable && mHideOnOverlap && !mHidden) { mShowDelayTimer.stop(); hidePanel(); } }); - connect(wmBackend, &ILXQtTaskbarAbstractBackend::windowRemoved, this, [this] { + connect(wmBackend, &ILXQtAbstractWMInterface::windowRemoved, this, [this] { if (mHidable && mHideOnOverlap && mHidden && !isPanelOverlapped()) mShowDelayTimer.start(); }); - connect(wmBackend, &ILXQtTaskbarAbstractBackend::currentWorkspaceChanged, this, [this] { + connect(wmBackend, &ILXQtAbstractWMInterface::currentWorkspaceChanged, this, [this] { if (mHidable && mHideOnOverlap) { if (!mHidden) @@ -304,7 +304,7 @@ LXQtPanel::LXQtPanel(const QString &configGroup, LXQt::Settings *settings, QWidg mShowDelayTimer.start(); } }); - connect(wmBackend, &ILXQtTaskbarAbstractBackend::windowPropertyChanged, + connect(wmBackend, &ILXQtAbstractWMInterface::windowPropertyChanged, this, [this] (WId /* id */, int prop) { if (mHidable && mHideOnOverlap diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp index c3b666620..887284df7 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -38,28 +38,64 @@ #include #include -#include "backends/lxqttaskbardummybackend.h" -#include "backends/xcb/lxqttaskbarbackend_x11.h" +#include +#include +#include -ILXQtTaskbarAbstractBackend *createWMBackend() +#include "backends/lxqtdummywmbackend.h" + +QString findBestBackend() { - if(qGuiApp->nativeInterface()) - return new LXQtTaskbarX11Backend; + QStringList dirs; + dirs << QProcessEnvironment::systemEnvironment().value(QStringLiteral("LXQTPANEL_PLUGIN_PATH")).split(QStringLiteral(":")); + dirs << QStringLiteral(PLUGIN_DIR); + + QString lastBackendFile; + int lastBackendScore = 0; - qWarning() << "\n" - << "ERROR: Could not create a backend for window managment operations.\n" - << "Only X11 supported!\n" - << "Falling back to dummy backend. Some functions will not be available.\n" - << "\n"; + for(const QString& dir : std::as_const(dirs)) + { + QDir backendsDir(dir); + backendsDir.cd(QLatin1String("backend")); - return new LXQtTaskBarDummyBackend; + const auto entryList = backendsDir.entryList(QDir::Files); + for(const QString& fileName : entryList) + { + const QString absPath = backendsDir.absoluteFilePath(fileName); + QPluginLoader loader(absPath); + loader.load(); + if(!loader.isLoaded()) + { + QString err = loader.errorString(); + qWarning() << "Backend error:" << err; + } + + QObject *plugin = loader.instance(); + if(!plugin) + continue; + + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) + { + int score = backend->getBackendScore(); + if(score > lastBackendScore) + { + lastBackendFile = absPath; + lastBackendScore = lastBackendScore; + } + } + loader.unload(); + } + } + + return lastBackendFile; } LXQtPanelApplicationPrivate::LXQtPanelApplicationPrivate(LXQtPanelApplication *q) : mSettings(nullptr), q_ptr(q) { - mWMBackend = createWMBackend(); + } @@ -90,6 +126,55 @@ ILXQtPanel::Position LXQtPanelApplicationPrivate::computeNewPanelPosition(const return static_cast (availablePosition); } +void LXQtPanelApplicationPrivate::loadBackend() +{ + QPluginLoader loader; + + // First try to load user preferred backend + QString preferredBackend = mSettings->value(QStringLiteral("preferred_backend")).toString(); + if(!preferredBackend.isEmpty()) + { + loader.setFileName(preferredBackend); + loader.load(); + if(!loader.isLoaded() || !loader.instance() || !qobject_cast(loader.instance())) + { + // Plugin not valid + loader.unload(); + preferredBackend.clear(); + } + } + + if(preferredBackend.isEmpty()) + { + // If user prefferred is not valid, find best available backend + QString fileName = findBestBackend(); + mSettings->setValue(QStringLiteral("preferred_backend"), fileName); + loader.setFileName(fileName); + loader.load(); + } + + QObject *plugin = loader.instance(); + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) + { + mWMBackend = backend->instance(); + } + else + { + // If no backend can be found fall back to dummy backend + loader.unload(); + mWMBackend = new LXQtDummyWMBackend; + + qWarning() << "\n" + << "ERROR: Could not create a backend for window managment operations.\n" + << "Only X11 supported!\n" + << "Falling back to dummy backend. Some functions will not be available.\n" + << "\n"; + } + + mWMBackend->setParent(q_ptr); +} + LXQtPanelApplication::LXQtPanelApplication(int& argc, char** argv) : LXQt::Application(argc, argv, true), d_ptr(new LXQtPanelApplicationPrivate(this)) @@ -124,6 +209,8 @@ LXQtPanelApplication::LXQtPanelApplication(int& argc, char** argv) else d->mSettings = new LXQt::Settings(configFile, QSettings::IniFormat, this); + d->loadBackend(); + // This is a workaround for Qt 5 bug #40681. const auto allScreens = screens(); for(QScreen* screen : allScreens) @@ -309,7 +396,7 @@ bool LXQtPanelApplication::isPluginSingletonAndRunning(QString const & pluginId) return false; } -ILXQtTaskbarAbstractBackend *LXQtPanelApplication::getWMBackend() const +ILXQtAbstractWMInterface *LXQtPanelApplication::getWMBackend() const { Q_D(const LXQtPanelApplication); return d->mWMBackend; diff --git a/panel/lxqtpanelapplication.h b/panel/lxqtpanelapplication.h index 15c912884..9ad8e3141 100644 --- a/panel/lxqtpanelapplication.h +++ b/panel/lxqtpanelapplication.h @@ -37,7 +37,7 @@ class QScreen; class LXQtPanel; class LXQtPanelApplicationPrivate; -class ILXQtTaskbarAbstractBackend; +class ILXQtAbstractWMInterface; /*! * \brief The LXQtPanelApplication class inherits from LXQt::Application and @@ -91,7 +91,7 @@ class LXQtPanelApplication : public LXQt::Application */ bool isPluginSingletonAndRunning(QString const & pluginId) const; - ILXQtTaskbarAbstractBackend* getWMBackend() const; + ILXQtAbstractWMInterface* getWMBackend() const; public slots: /*! diff --git a/panel/lxqtpanelapplication_p.h b/panel/lxqtpanelapplication_p.h index db924bf62..609546d26 100644 --- a/panel/lxqtpanelapplication_p.h +++ b/panel/lxqtpanelapplication_p.h @@ -27,7 +27,7 @@ namespace LXQt { class Settings; } -class ILXQtTaskbarAbstractBackend; +class ILXQtAbstractWMInterface; class LXQtPanelApplicationPrivate { Q_DECLARE_PUBLIC(LXQtPanelApplication) @@ -37,10 +37,12 @@ class LXQtPanelApplicationPrivate { ~LXQtPanelApplicationPrivate() {}; LXQt::Settings *mSettings; - ILXQtTaskbarAbstractBackend *mWMBackend; + ILXQtAbstractWMInterface *mWMBackend; ILXQtPanel::Position computeNewPanelPosition(const LXQtPanel *p, const int screenNum); + void loadBackend(); + private: LXQtPanelApplication *const q_ptr; }; diff --git a/plugin-desktopswitch/desktopswitch.cpp b/plugin-desktopswitch/desktopswitch.cpp index ea2a0fce3..453594f3d 100644 --- a/plugin-desktopswitch/desktopswitch.cpp +++ b/plugin-desktopswitch/desktopswitch.cpp @@ -35,7 +35,7 @@ #include #include "../panel/lxqtpanelapplication.h" -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" #include @@ -75,11 +75,11 @@ DesktopSwitch::DesktopSwitch(const ILXQtPanelPluginStartupInfo &startupInfo) : connect(m_buttons, &QButtonGroup::idClicked, this, &DesktopSwitch::setDesktop); - connect(mBackend, &ILXQtTaskbarAbstractBackend::workspacesCountChanged, this, &DesktopSwitch::onNumberOfDesktopsChanged); - connect(mBackend, &ILXQtTaskbarAbstractBackend::currentWorkspaceChanged, this, &DesktopSwitch::onCurrentDesktopChanged); - connect(mBackend, &ILXQtTaskbarAbstractBackend::workspaceNameChanged, this, &DesktopSwitch::onDesktopNamesChanged); + connect(mBackend, &ILXQtAbstractWMInterface::workspacesCountChanged, this, &DesktopSwitch::onNumberOfDesktopsChanged); + connect(mBackend, &ILXQtAbstractWMInterface::currentWorkspaceChanged, this, &DesktopSwitch::onCurrentDesktopChanged); + connect(mBackend, &ILXQtAbstractWMInterface::workspaceNameChanged, this, &DesktopSwitch::onDesktopNamesChanged); - connect(mBackend, &ILXQtTaskbarAbstractBackend::windowPropertyChanged, this, &DesktopSwitch::onWindowChanged); + connect(mBackend, &ILXQtAbstractWMInterface::windowPropertyChanged, this, &DesktopSwitch::onWindowChanged); } void DesktopSwitch::registerShortcuts() diff --git a/plugin-desktopswitch/desktopswitch.h b/plugin-desktopswitch/desktopswitch.h index 182eb0ced..07f14ce8d 100644 --- a/plugin-desktopswitch/desktopswitch.h +++ b/plugin-desktopswitch/desktopswitch.h @@ -41,7 +41,7 @@ namespace LXQt { class GridLayout; } -class ILXQtTaskbarAbstractBackend; +class ILXQtAbstractWMInterface; class DesktopSwitchWidget: public QFrame { @@ -83,7 +83,7 @@ class DesktopSwitch : public QObject, public ILXQtPanelPlugin LXQt::GridLayout *mLayout; int mRows; bool mShowOnlyActive; - ILXQtTaskbarAbstractBackend *mBackend; + ILXQtAbstractWMInterface *mBackend; DesktopSwitchButton::LabelType mLabelType; void refresh(); diff --git a/plugin-desktopswitch/desktopswitchconfiguration.cpp b/plugin-desktopswitch/desktopswitchconfiguration.cpp index 33781f7d8..39fac7f47 100644 --- a/plugin-desktopswitch/desktopswitchconfiguration.cpp +++ b/plugin-desktopswitch/desktopswitchconfiguration.cpp @@ -28,7 +28,7 @@ #include "ui_desktopswitchconfiguration.h" #include "../panel/lxqtpanelapplication.h" -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" #include #include diff --git a/plugin-showdesktop/showdesktop.cpp b/plugin-showdesktop/showdesktop.cpp index fb69f6067..4fa14658d 100644 --- a/plugin-showdesktop/showdesktop.cpp +++ b/plugin-showdesktop/showdesktop.cpp @@ -33,7 +33,7 @@ #include "../panel/pluginsettings.h" #include "../panel/lxqtpanelapplication.h" -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" #define DEFAULT_SHORTCUT "Control+Alt+D" diff --git a/plugin-taskbar/lxqttaskbar.cpp b/plugin-taskbar/lxqttaskbar.cpp index fb41ae7e0..9f3d40484 100644 --- a/plugin-taskbar/lxqttaskbar.cpp +++ b/plugin-taskbar/lxqttaskbar.cpp @@ -50,7 +50,7 @@ #include "lxqttaskgroup.h" #include "../panel/pluginsettings.h" -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" #include "../panel/lxqtpanelapplication.h" using namespace LXQt; @@ -104,9 +104,9 @@ LXQtTaskBar::LXQtTaskBar(ILXQtPanelPlugin *plugin, QWidget *parent) : connect(mSignalMapper, &QSignalMapper::mappedInt, this, &LXQtTaskBar::activateTask); QTimer::singleShot(0, this, &LXQtTaskBar::registerShortcuts); - connect(mBackend, &ILXQtTaskbarAbstractBackend::windowPropertyChanged, this, &LXQtTaskBar::onWindowChanged); - connect(mBackend, &ILXQtTaskbarAbstractBackend::windowAdded, this, &LXQtTaskBar::onWindowAdded); - connect(mBackend, &ILXQtTaskbarAbstractBackend::windowRemoved, this, &LXQtTaskBar::onWindowRemoved); + connect(mBackend, &ILXQtAbstractWMInterface::windowPropertyChanged, this, &LXQtTaskBar::onWindowChanged); + connect(mBackend, &ILXQtAbstractWMInterface::windowAdded, this, &LXQtTaskBar::onWindowAdded); + connect(mBackend, &ILXQtAbstractWMInterface::windowRemoved, this, &LXQtTaskBar::onWindowRemoved); // Consider already fetched windows const auto initialWindows = mBackend->getCurrentWindows(); diff --git a/plugin-taskbar/lxqttaskbar.h b/plugin-taskbar/lxqttaskbar.h index 9f94a2958..c6d6a6d29 100644 --- a/plugin-taskbar/lxqttaskbar.h +++ b/plugin-taskbar/lxqttaskbar.h @@ -47,7 +47,7 @@ class LXQtTaskGroup; class LeftAlignedTextStyle; -class ILXQtTaskbarAbstractBackend; +class ILXQtAbstractWMInterface; namespace LXQt { class GridLayout; @@ -86,7 +86,7 @@ class LXQtTaskBar : public QFrame ILXQtPanel * panel() const; inline ILXQtPanelPlugin * plugin() const { return mPlugin; } - inline ILXQtTaskbarAbstractBackend *getBackend() const { return mBackend; } + inline ILXQtAbstractWMInterface *getBackend() const { return mBackend; } public slots: void settingsChanged(); @@ -158,7 +158,7 @@ private slots: QWidget *mPlaceHolder; LeftAlignedTextStyle *mStyle; - ILXQtTaskbarAbstractBackend *mBackend; + ILXQtAbstractWMInterface *mBackend; }; #endif // LXQTTASKBAR_H diff --git a/plugin-taskbar/lxqttaskbarconfiguration.cpp b/plugin-taskbar/lxqttaskbarconfiguration.cpp index 0dd528e51..0e441f51b 100644 --- a/plugin-taskbar/lxqttaskbarconfiguration.cpp +++ b/plugin-taskbar/lxqttaskbarconfiguration.cpp @@ -31,7 +31,7 @@ #include "ui_lxqttaskbarconfiguration.h" #include "../panel/lxqtpanelapplication.h" -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" LXQtTaskbarConfiguration::LXQtTaskbarConfiguration(PluginSettings *settings, QWidget *parent): LXQtPanelPluginConfigDialog(settings, parent), diff --git a/plugin-taskbar/lxqttaskbarproxymodel.cpp b/plugin-taskbar/lxqttaskbarproxymodel.cpp index fdcdfa4d4..e02317ff7 100644 --- a/plugin-taskbar/lxqttaskbarproxymodel.cpp +++ b/plugin-taskbar/lxqttaskbarproxymodel.cpp @@ -1,6 +1,6 @@ #include "lxqttaskbarproxymodel.h" -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" #include @@ -209,12 +209,12 @@ void LXQtTaskBarProxyModel::setGroupByWindowClass(bool newGroupByWindowClass) } -ILXQtTaskbarAbstractBackend *LXQtTaskBarProxyModel::backend() const +ILXQtAbstractWMInterface *LXQtTaskBarProxyModel::backend() const { return m_backend; } -void LXQtTaskBarProxyModel::setBackend(ILXQtTaskbarAbstractBackend *newBackend) +void LXQtTaskBarProxyModel::setBackend(ILXQtAbstractWMInterface *newBackend) { beginResetModel(); @@ -222,11 +222,11 @@ void LXQtTaskBarProxyModel::setBackend(ILXQtTaskbarAbstractBackend *newBackend) if(m_backend) { - disconnect(m_backend, &ILXQtTaskbarAbstractBackend::windowAdded, + disconnect(m_backend, &ILXQtAbstractWMInterface::windowAdded, this, &LXQtTaskBarProxyModel::onWindowAdded); - disconnect(m_backend, &ILXQtTaskbarAbstractBackend::windowRemoved, + disconnect(m_backend, &ILXQtAbstractWMInterface::windowRemoved, this, &LXQtTaskBarProxyModel::onWindowRemoved); - disconnect(m_backend, &ILXQtTaskbarAbstractBackend::windowPropertyChanged, + disconnect(m_backend, &ILXQtAbstractWMInterface::windowPropertyChanged, this, &LXQtTaskBarProxyModel::onWindowPropertyChanged); } @@ -234,11 +234,11 @@ void LXQtTaskBarProxyModel::setBackend(ILXQtTaskbarAbstractBackend *newBackend) if(m_backend) { - connect(m_backend, &ILXQtTaskbarAbstractBackend::windowAdded, + connect(m_backend, &ILXQtAbstractWMInterface::windowAdded, this, &LXQtTaskBarProxyModel::onWindowAdded); - connect(m_backend, &ILXQtTaskbarAbstractBackend::windowRemoved, + connect(m_backend, &ILXQtAbstractWMInterface::windowRemoved, this, &LXQtTaskBarProxyModel::onWindowRemoved); - connect(m_backend, &ILXQtTaskbarAbstractBackend::windowPropertyChanged, + connect(m_backend, &ILXQtAbstractWMInterface::windowPropertyChanged, this, &LXQtTaskBarProxyModel::onWindowPropertyChanged); // Reload current windows diff --git a/plugin-taskbar/lxqttaskbarproxymodel.h b/plugin-taskbar/lxqttaskbarproxymodel.h index 8bbb5ec49..c78c28f5b 100644 --- a/plugin-taskbar/lxqttaskbarproxymodel.h +++ b/plugin-taskbar/lxqttaskbarproxymodel.h @@ -6,7 +6,7 @@ #include "../panel/backends/lxqttaskbartypes.h" -class ILXQtTaskbarAbstractBackend; +class ILXQtAbstractWMInterface; class LXQtTaskBarProxyModelWindow { @@ -64,8 +64,8 @@ class LXQtTaskBarProxyModel : public QAbstractListModel QIcon getWindowIcon(int itemRow, int windowIdxInGroup, int devicePixels) const; - ILXQtTaskbarAbstractBackend *backend() const; - void setBackend(ILXQtTaskbarAbstractBackend *newBackend); + ILXQtAbstractWMInterface *backend() const; + void setBackend(ILXQtAbstractWMInterface *newBackend); bool groupByWindowClass() const; void setGroupByWindowClass(bool newGroupByWindowClass); @@ -90,7 +90,7 @@ private slots: } private: - ILXQtTaskbarAbstractBackend *m_backend; + ILXQtAbstractWMInterface *m_backend; QVector m_items; diff --git a/plugin-taskbar/lxqttaskbutton.cpp b/plugin-taskbar/lxqttaskbutton.cpp index c86e6af5f..5a581929c 100644 --- a/plugin-taskbar/lxqttaskbutton.cpp +++ b/plugin-taskbar/lxqttaskbutton.cpp @@ -50,7 +50,7 @@ #include #include -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" diff --git a/plugin-taskbar/lxqttaskbutton.h b/plugin-taskbar/lxqttaskbutton.h index 9ccca36fa..12e83a613 100644 --- a/plugin-taskbar/lxqttaskbutton.h +++ b/plugin-taskbar/lxqttaskbutton.h @@ -41,7 +41,7 @@ class QPalette; class QMimeData; class LXQtTaskBar; -class ILXQtTaskbarAbstractBackend; +class ILXQtAbstractWMInterface; class LeftAlignedTextStyle : public QProxyStyle { @@ -124,7 +124,7 @@ public slots: protected: //TODO: public getter instead? - ILXQtTaskbarAbstractBackend *mBackend; + ILXQtAbstractWMInterface *mBackend; private: void moveApplicationToPrevNextDesktop(bool next); diff --git a/plugin-taskbar/lxqttaskgroup.cpp b/plugin-taskbar/lxqttaskgroup.cpp index 8317c034f..7f44bdc28 100644 --- a/plugin-taskbar/lxqttaskgroup.cpp +++ b/plugin-taskbar/lxqttaskgroup.cpp @@ -42,7 +42,7 @@ #include #include -#include "../panel/backends/ilxqttaskbarabstractbackend.h" +#include "../panel/backends/ilxqtabstractwmiface.h" /************************************************ @@ -65,8 +65,8 @@ LXQtTaskGroup::LXQtTaskGroup(const QString &groupName, WId window, LXQtTaskBar * connect(parent, &LXQtTaskBar::buttonStyleRefreshed, this, &LXQtTaskGroup::setToolButtonsStyle); connect(parent, &LXQtTaskBar::showOnlySettingChanged, this, &LXQtTaskGroup::refreshVisibility); connect(parent, &LXQtTaskBar::popupShown, this, &LXQtTaskGroup::groupPopupShown); - connect(mBackend, &ILXQtTaskbarAbstractBackend::currentWorkspaceChanged, this, &LXQtTaskGroup::onDesktopChanged); - connect(mBackend, &ILXQtTaskbarAbstractBackend::activeWindowChanged, this, &LXQtTaskGroup::onActiveWindowChanged); + connect(mBackend, &ILXQtAbstractWMInterface::currentWorkspaceChanged, this, &LXQtTaskGroup::onDesktopChanged); + connect(mBackend, &ILXQtAbstractWMInterface::activeWindowChanged, this, &LXQtTaskGroup::onActiveWindowChanged); } /************************************************ From 632c551799407b3682a00c56a740c544283e1fff Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 9 Jul 2024 16:35:19 +0200 Subject: [PATCH 2/9] Update licenses --- panel/backends/ilxqtabstractwmiface.cpp | 29 +++++++++++++++++++++++- panel/backends/ilxqtabstractwmiface.h | 28 +++++++++++++++++++++++ panel/backends/lxqtdummywmbackend.cpp | 27 ++++++++++++++++++++++ panel/backends/lxqtdummywmbackend.h | 28 +++++++++++++++++++++++ panel/backends/lxqttaskbartypes.h | 28 +++++++++++++++++++++++ panel/backends/xcb/lxqtwmbackend_x11.cpp | 28 +++++++++++++++++++++++ panel/backends/xcb/lxqtwmbackend_x11.h | 28 +++++++++++++++++++++++ 7 files changed, 195 insertions(+), 1 deletion(-) diff --git a/panel/backends/ilxqtabstractwmiface.cpp b/panel/backends/ilxqtabstractwmiface.cpp index 080b07324..cb8678647 100644 --- a/panel/backends/ilxqtabstractwmiface.cpp +++ b/panel/backends/ilxqtabstractwmiface.cpp @@ -1,5 +1,32 @@ -#include "ilxqtabstractwmiface.h" +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + +#include "ilxqtabstractwmiface.h" ILXQtAbstractWMInterface::ILXQtAbstractWMInterface(QObject *parent) : QObject(parent) diff --git a/panel/backends/ilxqtabstractwmiface.h b/panel/backends/ilxqtabstractwmiface.h index 4bd4c6561..cce9639d9 100644 --- a/panel/backends/ilxqtabstractwmiface.h +++ b/panel/backends/ilxqtabstractwmiface.h @@ -1,3 +1,31 @@ +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + + #ifndef ILXQT_ABSTRACT_WM_INTERFACE_H #define ILXQT_ABSTRACT_WM_INTERFACE_H diff --git a/panel/backends/lxqtdummywmbackend.cpp b/panel/backends/lxqtdummywmbackend.cpp index 9d8e2f5e1..071cbbfbd 100644 --- a/panel/backends/lxqtdummywmbackend.cpp +++ b/panel/backends/lxqtdummywmbackend.cpp @@ -1,3 +1,30 @@ +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + #include "lxqtdummywmbackend.h" #include diff --git a/panel/backends/lxqtdummywmbackend.h b/panel/backends/lxqtdummywmbackend.h index 75a9b04b7..de6217903 100644 --- a/panel/backends/lxqtdummywmbackend.h +++ b/panel/backends/lxqtdummywmbackend.h @@ -1,3 +1,31 @@ +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + + #ifndef LXQT_DUMMY_WM_BACKEND_H #define LXQT_DUMMY_WM_BACKEND_H diff --git a/panel/backends/lxqttaskbartypes.h b/panel/backends/lxqttaskbartypes.h index 656591fbc..dc82f980c 100644 --- a/panel/backends/lxqttaskbartypes.h +++ b/panel/backends/lxqttaskbartypes.h @@ -1,3 +1,31 @@ +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + + #ifndef LXQTTASKBARTYPES_H #define LXQTTASKBARTYPES_H diff --git a/panel/backends/xcb/lxqtwmbackend_x11.cpp b/panel/backends/xcb/lxqtwmbackend_x11.cpp index 40fd06a81..8279f641b 100644 --- a/panel/backends/xcb/lxqtwmbackend_x11.cpp +++ b/panel/backends/xcb/lxqtwmbackend_x11.cpp @@ -1,3 +1,31 @@ +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + + #include "lxqtwmbackend_x11.h" #include diff --git a/panel/backends/xcb/lxqtwmbackend_x11.h b/panel/backends/xcb/lxqtwmbackend_x11.h index 1457c2b2d..804221e8e 100644 --- a/panel/backends/xcb/lxqtwmbackend_x11.h +++ b/panel/backends/xcb/lxqtwmbackend_x11.h @@ -1,3 +1,31 @@ +/* BEGIN_COMMON_COPYRIGHT_HEADER + * (c)LGPL2+ + * + * LXQt - a lightweight, Qt based, desktop toolset + * https://lxqt.org + * + * Copyright: 2023 LXQt team + * Authors: + * Filippo Gentile + * + * This program or library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * END_COMMON_COPYRIGHT_HEADER */ + + #ifndef LXQT_WM_BACKEND_X11_H #define LXQT_WM_BACKEND_X11_H From 2986803efaafaa46901e4abd2ea8c2ea7a29b9cf Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 9 Jul 2024 16:40:24 +0200 Subject: [PATCH 3/9] lxqttaskbartypes.h: fix ShowOnAll desktops flag value --- panel/backends/lxqttaskbartypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panel/backends/lxqttaskbartypes.h b/panel/backends/lxqttaskbartypes.h index dc82f980c..e821b410d 100644 --- a/panel/backends/lxqttaskbartypes.h +++ b/panel/backends/lxqttaskbartypes.h @@ -78,7 +78,7 @@ enum class LXQtTaskBarWindowLayer enum class LXQtTaskBarWorkspace { - ShowOnAll = -1 + ShowOnAll = 0 // Virtual destops have 1-based indexes }; #endif // LXQTTASKBARTYPES_H From 438be7053b8181c5e073f4d8635d721542478c90 Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Fri, 12 Jul 2024 11:27:04 +0200 Subject: [PATCH 4/9] Fix backend load logic: do not load zero score backends - Fix X11 backend to return zero score on non-X11 platforms --- panel/backends/xcb/lxqtwmbackend_x11.cpp | 8 ++-- panel/lxqtpanelapplication.cpp | 50 ++++++++++++++++++------ 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/panel/backends/xcb/lxqtwmbackend_x11.cpp b/panel/backends/xcb/lxqtwmbackend_x11.cpp index 8279f641b..6e0be4889 100644 --- a/panel/backends/xcb/lxqtwmbackend_x11.cpp +++ b/panel/backends/xcb/lxqtwmbackend_x11.cpp @@ -690,9 +690,11 @@ bool LXQtWMBackendX11::showDesktop(bool value) int LXQtWMBackendX11Library::getBackendScore() const { auto *x11Application = qGuiApp->nativeInterface(); - if(x11Application) - return 80; - return 30; + if(!x11Application) + return 0; + + // Generic X11 backend + return 80; } ILXQtAbstractWMInterface *LXQtWMBackendX11Library::instance() const diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp index 887284df7..548eb3b9b 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -81,19 +81,23 @@ QString findBestBackend() if(score > lastBackendScore) { lastBackendFile = absPath; - lastBackendScore = lastBackendScore; + lastBackendScore = score; } } loader.unload(); } } + if(lastBackendScore == 0) + return QString(); // No available backend is good for this environment + return lastBackendFile; } LXQtPanelApplicationPrivate::LXQtPanelApplicationPrivate(LXQtPanelApplication *q) - : mSettings(nullptr), - q_ptr(q) + : mSettings(nullptr) + , mWMBackend(nullptr) + , q_ptr(q) { } @@ -136,7 +140,14 @@ void LXQtPanelApplicationPrivate::loadBackend() { loader.setFileName(preferredBackend); loader.load(); - if(!loader.isLoaded() || !loader.instance() || !qobject_cast(loader.instance())) + + QObject *plugin = loader.instance(); + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) + { + mWMBackend = backend->instance(); + } + else { // Plugin not valid loader.unload(); @@ -148,16 +159,33 @@ void LXQtPanelApplicationPrivate::loadBackend() { // If user prefferred is not valid, find best available backend QString fileName = findBestBackend(); - mSettings->setValue(QStringLiteral("preferred_backend"), fileName); - loader.setFileName(fileName); - loader.load(); + + if(!fileName.isEmpty()) + { + loader.setFileName(fileName); + loader.load(); + + QObject *plugin = loader.instance(); + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) + { + // Save this backend for next startup + preferredBackend = fileName; + mSettings->setValue(QStringLiteral("preferred_backend"), preferredBackend); + + mWMBackend = backend->instance(); + } + else + { + // Plugin not valid + loader.unload(); + } + } } - QObject *plugin = loader.instance(); - ILXQtWMBackendLibrary *backend = qobject_cast(plugin); - if(backend) + if(mWMBackend) { - mWMBackend = backend->instance(); + qDebug() << "Panel backend:" << preferredBackend; } else { From 0b5ec82a7d7a7097250e778d12574609f87c701b Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Sat, 17 Aug 2024 13:26:06 +0200 Subject: [PATCH 5/9] LXQtPanelApplication: always find best backend at startup If preferred backend is set try it first. Do not set preferred backend automatically. It must be user choice. --- panel/lxqtpanelapplication.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp index 548eb3b9b..1c6e3cd91 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -151,11 +151,10 @@ void LXQtPanelApplicationPrivate::loadBackend() { // Plugin not valid loader.unload(); - preferredBackend.clear(); } } - if(preferredBackend.isEmpty()) + if(!mWMBackend) { // If user prefferred is not valid, find best available backend QString fileName = findBestBackend(); @@ -169,10 +168,6 @@ void LXQtPanelApplicationPrivate::loadBackend() ILXQtWMBackendLibrary *backend = qobject_cast(plugin); if(backend) { - // Save this backend for next startup - preferredBackend = fileName; - mSettings->setValue(QStringLiteral("preferred_backend"), preferredBackend); - mWMBackend = backend->instance(); } else @@ -185,7 +180,7 @@ void LXQtPanelApplicationPrivate::loadBackend() if(mWMBackend) { - qDebug() << "Panel backend:" << preferredBackend; + qDebug() << "\nPanel backend:" << preferredBackend << "\n"; } else { @@ -195,7 +190,6 @@ void LXQtPanelApplicationPrivate::loadBackend() qWarning() << "\n" << "ERROR: Could not create a backend for window managment operations.\n" - << "Only X11 supported!\n" << "Falling back to dummy backend. Some functions will not be available.\n" << "\n"; } From 1f2bcdc34870c5cb93b6e846b7b9fbf86e1b2126 Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 20 Aug 2024 13:15:14 +0200 Subject: [PATCH 6/9] Panel backends: pass string argument for score calculation - Split XDG_CURRENT_DESKTOP - Skip LXQTPANEL_PLUGIN_PATH if empty --- panel/backends/ilxqtabstractwmiface.h | 2 +- panel/backends/xcb/lxqtwmbackend_x11.cpp | 4 +- panel/backends/xcb/lxqtwmbackend_x11.h | 2 +- panel/lxqtpanelapplication.cpp | 100 +++++++++++++++++------ 4 files changed, 81 insertions(+), 27 deletions(-) diff --git a/panel/backends/ilxqtabstractwmiface.h b/panel/backends/ilxqtabstractwmiface.h index cce9639d9..3f234f542 100644 --- a/panel/backends/ilxqtabstractwmiface.h +++ b/panel/backends/ilxqtabstractwmiface.h @@ -137,7 +137,7 @@ class LXQT_PANEL_API ILXQtWMBackendLibrary Returns the score of this backend for current detected environment. This is used to select correct backend at runtime **/ - virtual int getBackendScore() const = 0; + virtual int getBackendScore(const QString& key) const = 0; /** Returns the root component object of the backend. When the library is finally unloaded, the root component will automatically be deleted. diff --git a/panel/backends/xcb/lxqtwmbackend_x11.cpp b/panel/backends/xcb/lxqtwmbackend_x11.cpp index 6e0be4889..3196197bc 100644 --- a/panel/backends/xcb/lxqtwmbackend_x11.cpp +++ b/panel/backends/xcb/lxqtwmbackend_x11.cpp @@ -687,8 +687,10 @@ bool LXQtWMBackendX11::showDesktop(bool value) return true; } -int LXQtWMBackendX11Library::getBackendScore() const +int LXQtWMBackendX11Library::getBackendScore(const QString &key) const { + Q_UNUSED(key) + auto *x11Application = qGuiApp->nativeInterface(); if(!x11Application) return 0; diff --git a/panel/backends/xcb/lxqtwmbackend_x11.h b/panel/backends/xcb/lxqtwmbackend_x11.h index 804221e8e..e53b232f2 100644 --- a/panel/backends/xcb/lxqtwmbackend_x11.h +++ b/panel/backends/xcb/lxqtwmbackend_x11.h @@ -119,7 +119,7 @@ class LXQtWMBackendX11Library: public QObject, public ILXQtWMBackendLibrary Q_PLUGIN_METADATA(IID "lxqt.org/Panel/WMInterface/1.0") Q_INTERFACES(ILXQtWMBackendLibrary) public: - int getBackendScore() const override; + int getBackendScore(const QString& key) const override; ILXQtAbstractWMInterface* instance() const override; }; diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp index 1c6e3cd91..c88e8c9c2 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -44,48 +44,100 @@ #include "backends/lxqtdummywmbackend.h" + +static inline QList detectDesktopEnvironment() +{ + const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); + if (!xdgCurrentDesktop.isEmpty()) + { + // KDE, GNOME, UNITY, LXDE, MATE, XFCE... + // But also LXQt:$COMPOSITOR:wlroots + QList list = xdgCurrentDesktop.toUpper().split(':'); + if(!list.isEmpty()) + { + if(list.first() == QByteArrayLiteral("LXQT")) + list.removeFirst(); + if(!list.isEmpty()) + return list; + } + } + + // Classic fallbacks + if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) + return {QByteArrayLiteral("KDE")}; + + // Fallback to checking $DESKTOP_SESSION (unreliable) + QByteArray desktopSession = qgetenv("DESKTOP_SESSION"); + + // This can be a path in /usr/share/xsessions + int slash = desktopSession.lastIndexOf('/'); + // try decoding just the basename + desktopSession = desktopSession.mid(slash + 1); + + if (desktopSession == "kde" || desktopSession == "plasma") + return {QByteArrayLiteral("KDE")}; + + return {}; +} + QString findBestBackend() { QStringList dirs; - dirs << QProcessEnvironment::systemEnvironment().value(QStringLiteral("LXQTPANEL_PLUGIN_PATH")).split(QStringLiteral(":")); + + // LXQTPANEL_PLUGIN_PATH is not always defined, skip if empty + QStringList pluginPaths = QProcessEnvironment::systemEnvironment() + .value(QStringLiteral("LXQTPANEL_PLUGIN_PATH")) + .split(QStringLiteral(":"), Qt::SkipEmptyParts); + if(!pluginPaths.isEmpty()) + dirs << pluginPaths; + dirs << QStringLiteral(PLUGIN_DIR); QString lastBackendFile; int lastBackendScore = 0; - for(const QString& dir : std::as_const(dirs)) + QList desktops = detectDesktopEnvironment(); + for(const QByteArray& desktop : desktops) { - QDir backendsDir(dir); - backendsDir.cd(QLatin1String("backend")); + QString key = QString::fromUtf8(desktop); - const auto entryList = backendsDir.entryList(QDir::Files); - for(const QString& fileName : entryList) + for(const QString& dir : std::as_const(dirs)) { - const QString absPath = backendsDir.absoluteFilePath(fileName); - QPluginLoader loader(absPath); - loader.load(); - if(!loader.isLoaded()) + QDir backendsDir(dir); + backendsDir.cd(QLatin1String("backend")); + + const auto entryList = backendsDir.entryList(QDir::Files); + for(const QString& fileName : entryList) { - QString err = loader.errorString(); - qWarning() << "Backend error:" << err; - } + const QString absPath = backendsDir.absoluteFilePath(fileName); + QPluginLoader loader(absPath); + loader.load(); + if(!loader.isLoaded()) + { + QString err = loader.errorString(); + qWarning() << "Backend error:" << err; + } - QObject *plugin = loader.instance(); - if(!plugin) - continue; + QObject *plugin = loader.instance(); + if(!plugin) + continue; - ILXQtWMBackendLibrary *backend = qobject_cast(plugin); - if(backend) - { - int score = backend->getBackendScore(); - if(score > lastBackendScore) + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) { - lastBackendFile = absPath; - lastBackendScore = score; + int score = backend->getBackendScore(key); + if(score > lastBackendScore) + { + lastBackendFile = absPath; + lastBackendScore = score; + } } + loader.unload(); } - loader.unload(); } + + // Double the score before going to next key + lastBackendScore *= 2; } if(lastBackendScore == 0) From dc336dfd54488be5181c0dd12b1b74775d2762dd Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 20 Aug 2024 13:22:20 +0200 Subject: [PATCH 7/9] Backends: change name scheme libwmbackend_.so --- panel/backends/xcb/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/panel/backends/xcb/CMakeLists.txt b/panel/backends/xcb/CMakeLists.txt index 08f2fe4b1..76e5c98a4 100644 --- a/panel/backends/xcb/CMakeLists.txt +++ b/panel/backends/xcb/CMakeLists.txt @@ -1,6 +1,9 @@ -set(NAME xcb_backend) +set(PLATFORM_NAME xcb) + +set(PREFIX_NAME wmbackend) set(PROGRAM "lxqt-panel") set(BACKEND "backend") +set(NAME ${PREFIX_NAME}_${PLATFORM_NAME}) project(${PROGRAM}_${BACKEND}_${NAME}) set(PROG_SHARE_DIR ${CMAKE_INSTALL_FULL_DATAROOTDIR}/lxqt/${PROGRAM}/${BACKEND}) From 30cf17aa5f692ebb8754c8076628f382eeeff4fc Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 20 Aug 2024 13:38:38 +0200 Subject: [PATCH 8/9] LXQtPanelApplication: only consider plugins with valid names --- panel/lxqtpanelapplication.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp index c88e8c9c2..5b4a0d6c1 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -104,8 +104,13 @@ QString findBestBackend() for(const QString& dir : std::as_const(dirs)) { QDir backendsDir(dir); - backendsDir.cd(QLatin1String("backend")); + if ( QFile::exists( dir + QStringLiteral("/backend") ) ) + { + backendsDir.cd(QLatin1String("backend")); + } + + backendsDir.setNameFilters({QLatin1String("libwmbackend_*.so")}); const auto entryList = backendsDir.entryList(QDir::Files); for(const QString& fileName : entryList) { From 1ae3ff2eca4fd1b5962467167c33712bfe1f946d Mon Sep 17 00:00:00 2001 From: Filippo Gentile Date: Tue, 20 Aug 2024 13:58:17 +0200 Subject: [PATCH 9/9] LXQtPanelApplication: fix empty backend message --- panel/lxqtpanelapplication.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp index 5b4a0d6c1..59dd09eb0 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -226,6 +226,7 @@ void LXQtPanelApplicationPrivate::loadBackend() if(backend) { mWMBackend = backend->instance(); + preferredBackend = fileName; } else {