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/ilxqtabstractwmiface.cpp b/panel/backends/ilxqtabstractwmiface.cpp new file mode 100644 index 000000000..cb8678647 --- /dev/null +++ b/panel/backends/ilxqtabstractwmiface.cpp @@ -0,0 +1,52 @@ +/* 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) +{ + +} + +void ILXQtAbstractWMInterface::moveApplicationToPrevNextDesktop(WId windowId, bool next) +{ + int count = getWorkspacesCount(); + if (count <= 1) + return; + + int targetWorkspace = getWindowWorkspace(windowId) + (next ? 1 : -1); + + // Wrap around + if (targetWorkspace > count) + targetWorkspace = 1; //Ids are 1-based + else if (targetWorkspace < 1) + targetWorkspace = count; + + setWindowOnWorkspace(windowId, targetWorkspace); +} diff --git a/panel/backends/ilxqttaskbarabstractbackend.h b/panel/backends/ilxqtabstractwmiface.h similarity index 61% rename from panel/backends/ilxqttaskbarabstractbackend.h rename to panel/backends/ilxqtabstractwmiface.h index 44840671a..3f234f542 100644 --- a/panel/backends/ilxqttaskbarabstractbackend.h +++ b/panel/backends/ilxqtabstractwmiface.h @@ -1,19 +1,48 @@ -#ifndef ILXQTTASKBARABSTRACTBACKEND_H -#define ILXQTTASKBARABSTRACTBACKEND_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 */ + + +#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 +125,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 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. + **/ + 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/ilxqttaskbarabstractbackend.cpp b/panel/backends/ilxqttaskbarabstractbackend.cpp deleted file mode 100644 index 137728263..000000000 --- a/panel/backends/ilxqttaskbarabstractbackend.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "../panel/backends/ilxqttaskbarabstractbackend.h" - - -ILXQtTaskbarAbstractBackend::ILXQtTaskbarAbstractBackend(QObject *parent) - : QObject(parent) -{ - -} - -void ILXQtTaskbarAbstractBackend::moveApplicationToPrevNextDesktop(WId windowId, bool next) -{ - int count = getWorkspacesCount(); - if (count <= 1) - return; - - int targetWorkspace = getWindowWorkspace(windowId) + (next ? 1 : -1); - - // Wrap around - if (targetWorkspace > count) - targetWorkspace = 1; //Ids are 1-based - else if (targetWorkspace < 1) - targetWorkspace = count; - - setWindowOnWorkspace(windowId, targetWorkspace); -} diff --git a/panel/backends/lxqtdummywmbackend.cpp b/panel/backends/lxqtdummywmbackend.cpp new file mode 100644 index 000000000..071cbbfbd --- /dev/null +++ b/panel/backends/lxqtdummywmbackend.cpp @@ -0,0 +1,197 @@ +/* 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 + +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 65% rename from panel/backends/lxqttaskbardummybackend.h rename to panel/backends/lxqtdummywmbackend.h index 15506838f..de6217903 100644 --- a/panel/backends/lxqttaskbardummybackend.h +++ b/panel/backends/lxqtdummywmbackend.h @@ -1,14 +1,42 @@ -#ifndef LXQTTASKBARDUMMYBACKEND_H -#define LXQTTASKBARDUMMYBACKEND_H - -#include "ilxqttaskbarabstractbackend.h" - -class LXQtTaskBarDummyBackend : public ILXQtTaskbarAbstractBackend +/* 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 + +#include "ilxqtabstractwmiface.h" + +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 +113,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/lxqttaskbartypes.h b/panel/backends/lxqttaskbartypes.h index 656591fbc..e821b410d 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 @@ -50,7 +78,7 @@ enum class LXQtTaskBarWindowLayer enum class LXQtTaskBarWorkspace { - ShowOnAll = -1 + ShowOnAll = 0 // Virtual destops have 1-based indexes }; #endif // LXQTTASKBARTYPES_H diff --git a/panel/backends/xcb/CMakeLists.txt b/panel/backends/xcb/CMakeLists.txt index 8b1378917..76e5c98a4 100644 --- a/panel/backends/xcb/CMakeLists.txt +++ b/panel/backends/xcb/CMakeLists.txt @@ -1 +1,24 @@ +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}) +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 80% rename from panel/backends/xcb/lxqttaskbarbackend_x11.cpp rename to panel/backends/xcb/lxqtwmbackend_x11.cpp index fe0452776..3196197bc 100644 --- a/panel/backends/xcb/lxqttaskbarbackend_x11.cpp +++ b/panel/backends/xcb/lxqtwmbackend_x11.cpp @@ -1,4 +1,32 @@ -#include "lxqttaskbarbackend_x11.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 "lxqtwmbackend_x11.h" #include #include @@ -16,28 +44,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 +125,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 +136,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 +150,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 +189,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 +200,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 +249,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 +282,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 +322,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 +345,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 +368,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 +421,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 +446,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 +462,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 +486,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 +544,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 +556,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 +578,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 +596,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 +614,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 +644,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 +676,30 @@ 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 QString &key) const +{ + Q_UNUSED(key) + + auto *x11Application = qGuiApp->nativeInterface(); + if(!x11Application) + return 0; + + // Generic X11 backend + return 80; +} + +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 63% rename from panel/backends/xcb/lxqttaskbarbackend_x11.h rename to panel/backends/xcb/lxqtwmbackend_x11.h index 2478b3fff..e53b232f2 100644 --- a/panel/backends/xcb/lxqttaskbarbackend_x11.h +++ b/panel/backends/xcb/lxqtwmbackend_x11.h @@ -1,20 +1,47 @@ -#ifndef LXQTTASKBARBACKEND_X11_H -#define LXQTTASKBARBACKEND_X11_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 */ + + +#ifndef LXQT_WM_BACKEND_X11_H +#define LXQT_WM_BACKEND_X11_H + +#include "../ilxqtabstractwmiface.h" -#include "../ilxqttaskbarabstractbackend.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 +113,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 QString& key) 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..59dd09eb0 100644 --- a/panel/lxqtpanelapplication.cpp +++ b/panel/lxqtpanelapplication.cpp @@ -38,28 +38,125 @@ #include #include -#include "backends/lxqttaskbardummybackend.h" -#include "backends/xcb/lxqttaskbarbackend_x11.h" +#include +#include +#include -ILXQtTaskbarAbstractBackend *createWMBackend() +#include "backends/lxqtdummywmbackend.h" + + +static inline QList detectDesktopEnvironment() { - if(qGuiApp->nativeInterface()) - return new LXQtTaskbarX11Backend; + 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"); - 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"; + // This can be a path in /usr/share/xsessions + int slash = desktopSession.lastIndexOf('/'); + // try decoding just the basename + desktopSession = desktopSession.mid(slash + 1); - return new LXQtTaskBarDummyBackend; + if (desktopSession == "kde" || desktopSession == "plasma") + return {QByteArrayLiteral("KDE")}; + + return {}; +} + +QString findBestBackend() +{ + QStringList dirs; + + // 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; + + QList desktops = detectDesktopEnvironment(); + for(const QByteArray& desktop : desktops) + { + QString key = QString::fromUtf8(desktop); + + for(const QString& dir : std::as_const(dirs)) + { + QDir backendsDir(dir); + + 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) + { + 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(key); + if(score > lastBackendScore) + { + lastBackendFile = absPath; + lastBackendScore = score; + } + } + loader.unload(); + } + } + + // Double the score before going to next key + lastBackendScore *= 2; + } + + 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) { - mWMBackend = createWMBackend(); + } @@ -90,6 +187,74 @@ 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(); + + QObject *plugin = loader.instance(); + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) + { + mWMBackend = backend->instance(); + } + else + { + // Plugin not valid + loader.unload(); + } + } + + if(!mWMBackend) + { + // If user prefferred is not valid, find best available backend + QString fileName = findBestBackend(); + + if(!fileName.isEmpty()) + { + loader.setFileName(fileName); + loader.load(); + + QObject *plugin = loader.instance(); + ILXQtWMBackendLibrary *backend = qobject_cast(plugin); + if(backend) + { + mWMBackend = backend->instance(); + preferredBackend = fileName; + } + else + { + // Plugin not valid + loader.unload(); + } + } + } + + if(mWMBackend) + { + qDebug() << "\nPanel backend:" << preferredBackend << "\n"; + } + 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" + << "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 +289,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 +476,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); } /************************************************