├── src
├── io
│ ├── plugin.cpp
│ ├── module.md
│ ├── test
│ │ ├── process.hpp
│ │ ├── datastream.hpp
│ │ ├── CMakeLists.txt
│ │ └── process.cpp
│ ├── CMakeLists.txt
│ ├── processcore.cpp
│ └── ipccomm.hpp
├── core
│ ├── test
│ │ ├── popupwindow.hpp
│ │ ├── transformwatcher.hpp
│ │ ├── stacklist.hpp
│ │ ├── CMakeLists.txt
│ │ ├── ringbuf.hpp
│ │ └── scriptmodel.hpp
│ ├── shell.cpp
│ ├── common.cpp
│ ├── iconprovider.hpp
│ ├── common.hpp
│ ├── model.cpp
│ ├── enginecontext.hpp
│ ├── platformmenu_p.hpp
│ ├── incubator.cpp
│ ├── iconimageprovider.hpp
│ ├── shell.hpp
│ ├── toolsupport.hpp
│ ├── doc.hpp
│ ├── persistentprops.cpp
│ ├── elapsedtimer.cpp
│ ├── singleton.hpp
│ ├── incubator.hpp
│ ├── module.md
│ ├── rootwrapper.hpp
│ ├── scan.hpp
│ ├── desktopentrymonitor.hpp
│ ├── types.cpp
│ ├── plugin.cpp
│ ├── instanceinfo.hpp
│ ├── easingcurve.cpp
│ ├── instanceinfo.cpp
│ ├── logging_qtprivate.hpp
│ ├── CMakeLists.txt
│ ├── plugin.hpp
│ ├── elapsedtimer.hpp
│ ├── easingcurve.hpp
│ ├── imageprovider.hpp
│ ├── platformmenu.hpp
│ ├── singleton.cpp
│ ├── logcat.hpp
│ ├── persistentprops.hpp
│ └── desktopentrymonitor.cpp
├── widgets
│ ├── cliprect.cpp
│ ├── ClippingWrapperRectangleInternal.qml
│ ├── module.md
│ ├── cliprect.hpp
│ ├── CMakeLists.txt
│ └── shaders
│ │ └── cliprect.frag
├── window
│ ├── panelinterface.cpp
│ ├── test
│ │ ├── windowattached.hpp
│ │ ├── CMakeLists.txt
│ │ └── popupwindow.hpp
│ ├── init.cpp
│ └── CMakeLists.txt
├── crash
│ ├── main.hpp
│ ├── interface.hpp
│ ├── handler.hpp
│ └── CMakeLists.txt
├── wayland
│ ├── platformmenu.hpp
│ ├── util.hpp
│ ├── screencopy
│ │ ├── build.hpp.in
│ │ ├── wlr_screencopy
│ │ │ ├── CMakeLists.txt
│ │ │ └── wlr_screencopy.hpp
│ │ ├── hyprland_screencopy
│ │ │ ├── CMakeLists.txt
│ │ │ ├── hyprland_screencopy.hpp
│ │ │ └── hyprland_screencopy_p.hpp
│ │ ├── manager.hpp
│ │ ├── image_copy_capture
│ │ │ ├── CMakeLists.txt
│ │ │ ├── image_copy_capture.hpp
│ │ │ └── image_copy_capture_p.hpp
│ │ ├── CMakeLists.txt
│ │ └── manager.cpp
│ ├── util.cpp
│ ├── hyprland
│ │ ├── module.md
│ │ ├── focus_grab
│ │ │ ├── manager.hpp
│ │ │ ├── manager.cpp
│ │ │ ├── CMakeLists.txt
│ │ │ └── grab.hpp
│ │ ├── surface
│ │ │ ├── manager.hpp
│ │ │ ├── manager.cpp
│ │ │ ├── CMakeLists.txt
│ │ │ ├── surface.hpp
│ │ │ └── surface.cpp
│ │ ├── global_shortcuts
│ │ │ ├── CMakeLists.txt
│ │ │ ├── shortcut.cpp
│ │ │ ├── shortcut.hpp
│ │ │ ├── manager.hpp
│ │ │ └── manager.cpp
│ │ ├── test
│ │ │ └── manual
│ │ │ │ ├── workspaces.qml
│ │ │ │ ├── toplevel-association.qml
│ │ │ │ └── toplevels.qml
│ │ ├── ipc
│ │ │ └── CMakeLists.txt
│ │ └── CMakeLists.txt
│ ├── module.md
│ ├── xdgshell.cpp
│ ├── idle_inhibit
│ │ ├── test
│ │ │ └── manual
│ │ │ │ └── idle_inhibit.qml
│ │ ├── CMakeLists.txt
│ │ ├── proto.hpp
│ │ └── proto.cpp
│ ├── buffer
│ │ ├── manager_p.hpp
│ │ ├── CMakeLists.txt
│ │ ├── qsg.hpp
│ │ └── shm.hpp
│ ├── popupanchor.hpp
│ ├── xdgshell.hpp
│ ├── session_lock
│ │ ├── shell_integration.hpp
│ │ ├── CMakeLists.txt
│ │ ├── shell_integration.cpp
│ │ ├── manager.cpp
│ │ ├── manager.hpp
│ │ ├── lock.hpp
│ │ ├── lock.cpp
│ │ └── surface.hpp
│ ├── wlr_layershell
│ │ ├── shell_integration.hpp
│ │ ├── shell_integration.cpp
│ │ └── CMakeLists.txt
│ ├── output_tracking.hpp
│ ├── idle_notify
│ │ ├── CMakeLists.txt
│ │ ├── test
│ │ │ └── manual
│ │ │ │ └── idle_notify.qml
│ │ ├── proto.hpp
│ │ └── monitor.cpp
│ ├── shortcuts_inhibit
│ │ ├── CMakeLists.txt
│ │ └── test
│ │ │ └── manual
│ │ │ └── test.qml
│ └── toplevel_management
│ │ ├── CMakeLists.txt
│ │ └── manager.hpp
├── launch
│ ├── main.hpp
│ └── CMakeLists.txt
├── main.cpp
├── dbus
│ ├── dbusmenu
│ │ ├── module.md
│ │ ├── CMakeLists.txt
│ │ └── dbus_menu_types.hpp
│ ├── dbus_objectmanager_types.hpp
│ ├── bus.hpp
│ ├── org.freedesktop.DBus.ObjectManager.xml
│ ├── objectmanager.hpp
│ ├── org.freedesktop.DBus.Properties.xml
│ ├── CMakeLists.txt
│ └── bus.cpp
├── services
│ ├── mpris
│ │ ├── module.md
│ │ ├── org.mpris.MediaPlayer2.xml
│ │ ├── org.mpris.MediaPlayer2.Player.xml
│ │ ├── CMakeLists.txt
│ │ └── watcher.hpp
│ ├── greetd
│ │ ├── module.md
│ │ ├── CMakeLists.txt
│ │ └── qml.cpp
│ ├── pipewire
│ │ ├── module.md
│ │ ├── connection.cpp
│ │ ├── connection.hpp
│ │ ├── CMakeLists.txt
│ │ ├── metadata.hpp
│ │ ├── core.hpp
│ │ └── device.hpp
│ ├── status_notifier
│ │ ├── module.md
│ │ ├── org.kde.StatusNotifierWatcher.xml
│ │ ├── qml.hpp
│ │ ├── qml.cpp
│ │ ├── dbus_item_types.hpp
│ │ ├── host.hpp
│ │ ├── CMakeLists.txt
│ │ └── watcher.hpp
│ ├── upower
│ │ ├── module.md
│ │ ├── org.freedesktop.UPower.xml
│ │ ├── org.freedesktop.UPower.Device.xml
│ │ └── CMakeLists.txt
│ ├── notifications
│ │ ├── module.md
│ │ ├── CMakeLists.txt
│ │ ├── dbusimage.hpp
│ │ └── org.freedesktop.Notifications.xml
│ ├── pam
│ │ ├── CMakeLists.txt
│ │ ├── subprocess.hpp
│ │ ├── ipc.hpp
│ │ └── ipc.cpp
│ ├── CMakeLists.txt
│ └── polkit
│ │ ├── CMakeLists.txt
│ │ ├── qml.cpp
│ │ ├── gobjectref.hpp
│ │ └── session.hpp
├── bluetooth
│ ├── org.bluez.Device.xml
│ ├── org.bluez.Adapter.xml
│ ├── module.md
│ └── CMakeLists.txt
├── debug
│ ├── CMakeLists.txt
│ └── lint.hpp
├── ipc
│ ├── CMakeLists.txt
│ └── ipccommand.hpp
├── x11
│ ├── i3
│ │ ├── module.md
│ │ ├── CMakeLists.txt
│ │ └── ipc
│ │ │ ├── CMakeLists.txt
│ │ │ ├── listener.cpp
│ │ │ ├── workspace.cpp
│ │ │ └── listener.hpp
│ ├── util.hpp
│ ├── CMakeLists.txt
│ ├── init.cpp
│ └── util.cpp
├── ui
│ ├── CMakeLists.txt
│ ├── reload_popup.hpp
│ └── reload_popup.cpp
├── build
│ ├── build.hpp.in
│ └── CMakeLists.txt
└── CMakeLists.txt
├── changelog
├── v0.1.0.md
├── v0.2.1.md
└── next.md
├── .github
├── ISSUE_TEMPLATE
│ └── config.yml
└── workflows
│ └── lint.yml
├── overlay.nix
├── ci
├── variations.nix
└── matrix.nix
├── assets
├── org.quickshell.desktop
└── quickshell.svg
├── .gitignore
├── .editorconfig
├── README.md
├── flake.lock
├── flake.nix
├── cmake
├── util.cmake
└── pch.cmake
├── shell.nix
└── Justfile
/src/io/plugin.cpp:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/core/test/popupwindow.hpp:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/changelog/v0.1.0.md:
--------------------------------------------------------------------------------
1 | Initial release
2 |
--------------------------------------------------------------------------------
/src/widgets/cliprect.cpp:
--------------------------------------------------------------------------------
1 | #include "cliprect.hpp" // NOLINT
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 |
--------------------------------------------------------------------------------
/src/window/panelinterface.cpp:
--------------------------------------------------------------------------------
1 | #include "panelinterface.hpp" // NOLINT
2 |
--------------------------------------------------------------------------------
/src/crash/main.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void qsCheckCrash(int argc, char** argv);
4 |
--------------------------------------------------------------------------------
/src/wayland/platformmenu.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void installPlatformMenuHook();
4 |
--------------------------------------------------------------------------------
/src/launch/main.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace qs::launch {
4 |
5 | int main(int argc, char** argv);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "launch/main.hpp"
2 |
3 | int main(int argc, char** argv) { return qs::launch::main(argc, argv); }
4 |
--------------------------------------------------------------------------------
/overlay.nix:
--------------------------------------------------------------------------------
1 | { rev ? null }: (final: prev: {
2 | quickshell = final.callPackage ./default.nix {
3 | gitRev = rev;
4 | };
5 | })
6 |
--------------------------------------------------------------------------------
/ci/variations.nix:
--------------------------------------------------------------------------------
1 | {
2 | clangStdenv,
3 | gccStdenv,
4 | }: {
5 | clang = { stdenv = clangStdenv; };
6 | gcc = { stdenv = gccStdenv; };
7 | }
8 |
--------------------------------------------------------------------------------
/assets/org.quickshell.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Version=1.5
3 | Type=Application
4 | NoDisplay=true
5 |
6 | Name=Quickshell
7 | Icon=org.quickshell
8 |
--------------------------------------------------------------------------------
/src/dbus/dbusmenu/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.DBusMenu"
2 | description = "Types related to DBusMenu (used in system tray)"
3 | headers = [ "dbusmenu.hpp" ]
4 | -----
5 |
--------------------------------------------------------------------------------
/src/services/mpris/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Services.Mpris"
2 | description = "Mpris Service"
3 | headers = [
4 | "player.hpp",
5 | "watcher.hpp",
6 | ]
7 | -----
8 |
--------------------------------------------------------------------------------
/src/services/greetd/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Services.Greetd"
2 | description = "Greetd integration"
3 | headers = [
4 | "qml.hpp",
5 | "connection.hpp",
6 | ]
7 | -----
8 |
--------------------------------------------------------------------------------
/src/services/pipewire/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Services.Pipewire"
2 | description = "Pipewire API"
3 | headers = [
4 | "qml.hpp",
5 | "link.hpp",
6 | "node.hpp",
7 | ]
8 | -----
9 |
--------------------------------------------------------------------------------
/src/services/mpris/org.mpris.MediaPlayer2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/services/status_notifier/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Services.SystemTray"
2 | description = "Types for implementing a system tray"
3 | headers = [ "qml.hpp", "item.hpp" ]
4 | -----
5 |
--------------------------------------------------------------------------------
/src/core/shell.cpp:
--------------------------------------------------------------------------------
1 | #include "shell.hpp"
2 |
3 | #include "qmlglobal.hpp"
4 |
5 | QuickshellSettings* ShellRoot::settings() const { // NOLINT
6 | return QuickshellSettings::instance();
7 | }
8 |
--------------------------------------------------------------------------------
/src/services/upower/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Services.UPower"
2 | description = "UPower Service"
3 | headers = [
4 | "core.hpp",
5 | "device.hpp",
6 | "powerprofiles.hpp",
7 | ]
8 | -----
9 |
--------------------------------------------------------------------------------
/src/wayland/util.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../window/proxywindow.hpp"
4 |
5 | namespace qs::wayland::util {
6 |
7 | void scheduleCommit(ProxyWindowBase* window);
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/services/notifications/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Services.Notifications"
2 | description = "Types for implementing a notification daemon"
3 | headers = [ "qml.hpp", "notification.hpp" ]
4 | -----
5 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/build.hpp.in:
--------------------------------------------------------------------------------
1 | #pragma once
2 | // NOLINTBEGIN
3 | #cmakedefine01 SCREENCOPY_ICC
4 | #cmakedefine01 SCREENCOPY_WLR
5 | #cmakedefine01 SCREENCOPY_HYPRLAND_TOPLEVEL
6 | // NOLINTEND
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # related repos
2 | /docs
3 | /examples
4 |
5 | # build files
6 | /result
7 | /build/
8 | /compile_commands.json
9 |
10 | # clangd
11 | /.cache
12 |
13 | # direnv
14 | /.envrc
15 | /.direnv/
16 |
--------------------------------------------------------------------------------
/src/core/common.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | #include
4 |
5 | namespace qs {
6 |
7 | const QDateTime Common::LAUNCH_TIME = QDateTime::currentDateTime();
8 |
9 | } // namespace qs
10 |
--------------------------------------------------------------------------------
/src/bluetooth/org.bluez.Device.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/debug/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-debug STATIC
2 | lint.cpp
3 | )
4 |
5 | qs_pch(quickshell-debug)
6 | target_link_libraries(quickshell-debug PRIVATE Qt::Quick)
7 | target_link_libraries(quickshell PRIVATE quickshell-debug)
8 |
--------------------------------------------------------------------------------
/src/io/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Io"
2 | description = "Io types"
3 | headers = [
4 | "datastream.hpp",
5 | "socket.hpp",
6 | "process.hpp",
7 | "fileview.hpp",
8 | "jsonadapter.hpp",
9 | "ipchandler.hpp",
10 | ]
11 | -----
12 |
--------------------------------------------------------------------------------
/src/widgets/ClippingWrapperRectangleInternal.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 |
3 | ClippingRectangle {
4 | id: root
5 | property alias __implicitWidthInternal: root.implicitWidth
6 | property alias __implicitHeightInternal: root.implicitHeight
7 | }
8 |
--------------------------------------------------------------------------------
/src/core/iconprovider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | QIcon getEngineImageAsIcon(QQmlEngine* engine, const QUrl& url);
8 | QIcon getCurrentEngineImageAsIcon(const QUrl& url);
9 |
--------------------------------------------------------------------------------
/src/debug/lint.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace qs::debug {
7 |
8 | void lintObjectTree(QObject* object);
9 | void lintItemTree(QQuickItem* item);
10 |
11 | } // namespace qs::debug
12 |
--------------------------------------------------------------------------------
/src/ipc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-ipc STATIC
2 | ipc.cpp
3 | )
4 |
5 | qs_pch(quickshell-ipc)
6 |
7 | target_link_libraries(quickshell-ipc PRIVATE Qt::Quick Qt::Network)
8 |
9 | target_link_libraries(quickshell PRIVATE quickshell-ipc)
10 |
--------------------------------------------------------------------------------
/src/wayland/util.cpp:
--------------------------------------------------------------------------------
1 | #include "util.hpp"
2 |
3 | #include "../window/proxywindow.hpp"
4 |
5 | namespace qs::wayland::util {
6 |
7 | void scheduleCommit(ProxyWindowBase* window) { window->schedulePolish(); }
8 |
9 | } // namespace qs::wayland::util
10 |
--------------------------------------------------------------------------------
/src/io/test/process.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class TestProcess: public QObject {
7 | Q_OBJECT;
8 |
9 | private slots:
10 | static void startAfterReload();
11 | static void testExec();
12 | };
13 |
--------------------------------------------------------------------------------
/src/bluetooth/org.bluez.Adapter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/io/test/datastream.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class TestSplitParser: public QObject {
7 | Q_OBJECT;
8 |
9 | private slots:
10 | void splits_data(); // NOLINT
11 | void splits();
12 | void initBuffer();
13 | };
14 |
--------------------------------------------------------------------------------
/src/x11/i3/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.I3"
2 | description = "I3 specific Quickshell types"
3 | headers = [
4 | "ipc/connection.hpp",
5 | "ipc/controller.hpp",
6 | "ipc/qml.hpp",
7 | "ipc/workspace.hpp",
8 | "ipc/monitor.hpp",
9 | "ipc/listener.hpp",
10 | ]
11 | -----
12 |
--------------------------------------------------------------------------------
/src/core/common.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace qs {
7 |
8 | struct Common {
9 | static const QDateTime LAUNCH_TIME;
10 | static inline QProcessEnvironment INITIAL_ENVIRONMENT = {}; // NOLINT
11 | };
12 |
13 | } // namespace qs
14 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = tab
8 |
9 | [*.nix]
10 | indent_style = space
11 | indent_size = 2
12 |
13 | [*.{yml,yaml}]
14 | indent_style = space
15 | indent_size = 2
16 |
17 | [*.scm]
18 | indent_style = space
--------------------------------------------------------------------------------
/src/core/test/transformwatcher.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class TestTransformWatcher: public QObject {
7 | Q_OBJECT;
8 |
9 | private slots:
10 | void aParentOfB();
11 | void bParentOfA();
12 | void aParentChainB();
13 | void multiWindow();
14 | };
15 |
--------------------------------------------------------------------------------
/src/core/test/stacklist.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class TestStackList: public QObject {
7 | Q_OBJECT;
8 |
9 | private slots:
10 | static void push();
11 | static void pushAndGrow();
12 | static void copy();
13 | static void viewVla();
14 | static void viewVlaGrown();
15 | };
16 |
--------------------------------------------------------------------------------
/src/dbus/dbus_objectmanager_types.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using DBusObjectManagerInterfaces = QHash;
10 | using DBusObjectManagerObjects = QHash;
11 |
--------------------------------------------------------------------------------
/src/crash/interface.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class CrashReporterGui: public QWidget {
6 | public:
7 | CrashReporterGui(QString reportFolder, int pid);
8 |
9 | private slots:
10 | void openFolder();
11 |
12 | static void openReportUrl();
13 | static void cancel();
14 |
15 | private:
16 | QString reportFolder;
17 | };
18 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Hyprland"
2 | description = "Hyprland specific Quickshell types"
3 | headers = [
4 | "ipc/connection.hpp",
5 | "ipc/monitor.hpp",
6 | "ipc/workspace.hpp",
7 | "ipc/hyprland_toplevel.hpp",
8 | "ipc/qml.hpp",
9 | "focus_grab/qml.hpp",
10 | "global_shortcuts/qml.hpp",
11 | "surface/qml.hpp",
12 | ]
13 | -----
14 |
--------------------------------------------------------------------------------
/src/bluetooth/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Bluetooth"
2 | description = "Bluetooth API"
3 | headers = [
4 | "bluez.hpp",
5 | "adapter.hpp",
6 | "device.hpp",
7 | ]
8 | -----
9 | This module exposes Bluetooth management APIs provided by the BlueZ DBus interface.
10 | Both DBus and BlueZ must be running to use it.
11 |
12 | See the @@Quickshell.Bluetooth.Bluetooth singleton.
13 |
--------------------------------------------------------------------------------
/src/wayland/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Wayland"
2 | description = "Wayland specific Quickshell types"
3 | headers = [
4 | "wlr_layershell/wlr_layershell.hpp",
5 | "session_lock.hpp",
6 | "toplevel_management/qml.hpp",
7 | "screencopy/view.hpp",
8 | "idle_inhibit/inhibitor.hpp",
9 | "idle_notify/monitor.hpp",
10 | "shortcuts_inhibit/inhibitor.hpp",
11 | ]
12 | -----
13 |
--------------------------------------------------------------------------------
/src/widgets/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell.Widgets"
2 | description = "Bundled widgets"
3 |
4 | headers = [
5 | "wrapper.hpp",
6 | "marginwrapper.hpp",
7 | ]
8 |
9 | qml_files = [
10 | "IconImage.qml",
11 | "ClippingRectangle.qml",
12 | "WrapperItem.qml",
13 | "WrapperMouseArea.qml",
14 | "WrapperRectangle.qml",
15 | "ClippingWrapperRectangle.qml",
16 | ]
17 | -----
18 |
--------------------------------------------------------------------------------
/src/dbus/bus.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | namespace qs::dbus {
10 |
11 | void tryLaunchService(
12 | QObject* parent,
13 | QDBusConnection& connection,
14 | const QString& serviceName,
15 | const std::function& callback
16 | );
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/core/model.cpp:
--------------------------------------------------------------------------------
1 | #include "model.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | QHash UntypedObjectModel::roleNames() const {
8 | return {{Qt::UserRole, "modelData"}};
9 | }
10 |
11 | UntypedObjectModel* UntypedObjectModel::emptyInstance() {
12 | static auto* instance = new ObjectModel(nullptr);
13 | return instance;
14 | }
15 |
--------------------------------------------------------------------------------
/src/window/test/windowattached.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class TestWindowAttachment: public QObject {
7 | Q_OBJECT;
8 |
9 | private slots:
10 | static void attachedAfterReload();
11 | static void attachedBeforeReload();
12 | static void earlyAttachReloaded();
13 | static void owningWindowChanged();
14 | static void nonItemParents();
15 | };
16 |
--------------------------------------------------------------------------------
/src/wayland/xdgshell.cpp:
--------------------------------------------------------------------------------
1 | #include "xdgshell.hpp"
2 |
3 | #include
4 |
5 | namespace qs::wayland::xdg_shell {
6 |
7 | XdgWmBase::XdgWmBase(): QWaylandClientExtensionTemplate(6) { this->initialize(); }
8 |
9 | XdgWmBase* XdgWmBase::instance() {
10 | static auto* instance = new XdgWmBase(); // NOLINT
11 | return instance;
12 | }
13 |
14 | } // namespace qs::wayland::xdg_shell
15 |
--------------------------------------------------------------------------------
/src/core/enginecontext.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "qsintercept.hpp"
4 | #include "scan.hpp"
5 | #include "singleton.hpp"
6 |
7 | class EngineContext {
8 | public:
9 | explicit EngineContext(const QmlScanner& scanner);
10 |
11 | private:
12 | const QmlScanner& scanner;
13 | QQmlEngine engine;
14 | QsInterceptNetworkAccessManagerFactory interceptFactory;
15 | SingletonRegistry singletonRegistry;
16 | };
17 |
--------------------------------------------------------------------------------
/ci/matrix.nix:
--------------------------------------------------------------------------------
1 | {
2 | qtver,
3 | compiler,
4 | }: let
5 | checkouts = import ./nix-checkouts.nix;
6 | nixpkgs = checkouts.${builtins.replaceStrings ["."] ["_"] qtver};
7 | compilerOverride = (nixpkgs.callPackage ./variations.nix {}).${compiler};
8 | pkg = (nixpkgs.callPackage ../default.nix {}).override (compilerOverride // {
9 | wayland-protocols = checkouts.latest.wayland-protocols;
10 | });
11 | in pkg
12 |
--------------------------------------------------------------------------------
/src/window/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function (qs_test name)
2 | add_executable(${name} ${ARGN})
3 | target_link_libraries(${name} PRIVATE Qt::Quick Qt::Test quickshell-window quickshell-core quickshell-ui quickshell-io)
4 | add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $)
5 | endfunction()
6 |
7 | qs_test(popupwindow popupwindow.cpp)
8 | qs_test(windowattached windowattached.cpp)
9 |
--------------------------------------------------------------------------------
/src/wayland/idle_inhibit/test/manual/idle_inhibit.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import Quickshell
4 | import Quickshell.Wayland
5 |
6 | FloatingWindow {
7 | id: root
8 | color: contentItem.palette.window
9 |
10 | CheckBox {
11 | id: enableCb
12 | anchors.centerIn: parent
13 | text: "Enable Inhibitor"
14 | }
15 |
16 | IdleInhibitor {
17 | window: root
18 | enabled: enableCb.checked
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/window/test/popupwindow.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class TestPopupWindow: public QObject {
7 | Q_OBJECT;
8 |
9 | private slots:
10 | void initiallyVisible();
11 | void reloadReparent();
12 | void reloadUnparent();
13 | void invisibleWithoutParent();
14 | void moveWithParent();
15 | void attachParentLate();
16 | void reparentLate();
17 | void xMigrationFix();
18 | };
19 |
--------------------------------------------------------------------------------
/src/wayland/buffer/manager_p.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "dmabuf.hpp"
4 | #include "manager.hpp"
5 |
6 | namespace qs::wayland::buffer {
7 |
8 | class WlBufferManagerPrivate {
9 | public:
10 | explicit WlBufferManagerPrivate(WlBufferManager* manager);
11 |
12 | void dmabufReady();
13 |
14 | WlBufferManager* manager;
15 | dmabuf::LinuxDmabufManager dmabuf;
16 |
17 | bool mReady = false;
18 | };
19 |
20 | } // namespace qs::wayland::buffer
21 |
--------------------------------------------------------------------------------
/src/ui/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-ui STATIC
2 | reload_popup.cpp
3 | )
4 |
5 | # do not install this module
6 | qt_add_qml_module(quickshell-ui
7 | URI Quickshell._InternalUi
8 | VERSION 0.1
9 | DEPENDENCIES QtQuick
10 | QML_FILES
11 | Tooltip.qml
12 | ReloadPopup.qml
13 | )
14 |
15 | qs_module_pch(quickshell-ui SET large)
16 |
17 | target_link_libraries(quickshell-ui PRIVATE Qt::Quick)
18 | target_link_libraries(quickshell PRIVATE quickshell-uiplugin)
19 |
--------------------------------------------------------------------------------
/src/io/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function (qs_test name)
2 | add_executable(${name} ${ARGN})
3 | target_link_libraries(${name} PRIVATE Qt::Quick Qt::Network Qt::Test quickshell-io quickshell-core quickshell-window quickshell-ui)
4 | add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $)
5 | endfunction()
6 |
7 | qs_test(datastream datastream.cpp ../datastream.cpp)
8 | qs_test(process process.cpp ../process.cpp ../datastream.cpp ../processcore.cpp)
9 |
--------------------------------------------------------------------------------
/src/wayland/popupanchor.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "../core/popupanchor.hpp"
6 |
7 | class WaylandPopupPositioner: public PopupPositioner {
8 | public:
9 | void reposition(PopupAnchor* anchor, QWindow* window, bool onlyIfDirty = true) override;
10 | [[nodiscard]] bool shouldRepositionOnMove() const override;
11 |
12 | private:
13 | static void setFlags(PopupAnchor* anchor, QWindow* window);
14 | };
15 |
16 | void installPopupPositioner();
17 |
--------------------------------------------------------------------------------
/src/build/build.hpp.in:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // NOLINTBEGIN
4 | #define GIT_REVISION "@GIT_REVISION@"
5 | #define DISTRIBUTOR "@DISTRIBUTOR@"
6 | #define DISTRIBUTOR_DEBUGINFO_AVAILABLE @DEBUGINFO_AVAILABLE@
7 | #define CRASH_REPORTER @CRASH_REPORTER_DEF@
8 | #define BUILD_TYPE "@CMAKE_BUILD_TYPE@"
9 | #define COMPILER "@CMAKE_CXX_COMPILER_ID@ (@CMAKE_CXX_COMPILER_VERSION@)"
10 | #define COMPILE_FLAGS "@CMAKE_CXX_FLAGS@"
11 | #define BUILD_CONFIGURATION "@QS_BUILD_OPTIONS@"
12 | // NOLINTEND
13 |
--------------------------------------------------------------------------------
/src/crash/handler.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "../core/instanceinfo.hpp"
6 | namespace qs::crash {
7 |
8 | struct CrashHandlerPrivate;
9 |
10 | class CrashHandler {
11 | public:
12 | explicit CrashHandler();
13 | ~CrashHandler();
14 | Q_DISABLE_COPY_MOVE(CrashHandler);
15 |
16 | void init();
17 | void setRelaunchInfo(const RelaunchInfo& info);
18 |
19 | private:
20 | CrashHandlerPrivate* d;
21 | };
22 |
23 | } // namespace qs::crash
24 |
--------------------------------------------------------------------------------
/src/core/platformmenu_p.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | namespace qs::menu::platform {
6 |
7 | class PlatformMenuQMenu: public QMenu {
8 | public:
9 | explicit PlatformMenuQMenu() = default;
10 | ~PlatformMenuQMenu() override;
11 | Q_DISABLE_COPY_MOVE(PlatformMenuQMenu);
12 |
13 | void setVisible(bool visible) override;
14 |
15 | PlatformMenuQMenu* containingMenu = nullptr;
16 | QPoint targetPosition;
17 | };
18 |
19 | } // namespace qs::menu::platform
20 |
--------------------------------------------------------------------------------
/src/core/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function (qs_test name)
2 | add_executable(${name} ${ARGN})
3 | target_link_libraries(${name} PRIVATE Qt::Quick Qt::Test quickshell-core quickshell-window quickshell-ui quickshell-io)
4 | add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $)
5 | endfunction()
6 |
7 | qs_test(transformwatcher transformwatcher.cpp)
8 | qs_test(ringbuffer ringbuf.cpp)
9 | qs_test(scriptmodel scriptmodel.cpp)
10 | qs_test(stacklist stacklist.cpp)
11 |
--------------------------------------------------------------------------------
/src/core/incubator.cpp:
--------------------------------------------------------------------------------
1 | #include "incubator.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "logcat.hpp"
8 |
9 | QS_LOGGING_CATEGORY(logIncubator, "quickshell.incubator", QtWarningMsg);
10 |
11 | void QsQmlIncubator::statusChanged(QQmlIncubator::Status status) {
12 | switch (status) {
13 | case QQmlIncubator::Ready: emit this->completed(); break;
14 | case QQmlIncubator::Error: emit this->failed(); break;
15 | default: break;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ipc/ipccommand.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "../io/ipccomm.hpp"
6 | #include "ipc.hpp"
7 |
8 | namespace qs::ipc {
9 |
10 | struct IpcKillCommand: std::monostate {
11 | static void exec(IpcServerConnection* /*unused*/);
12 | };
13 |
14 | using IpcCommand = std::variant<
15 | std::monostate,
16 | IpcKillCommand,
17 | qs::io::ipc::comm::QueryMetadataCommand,
18 | qs::io::ipc::comm::StringCallCommand,
19 | qs::io::ipc::comm::StringPropReadCommand>;
20 |
21 | } // namespace qs::ipc
22 |
--------------------------------------------------------------------------------
/src/widgets/cliprect.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class ClippingRectangleBorder {
10 | Q_GADGET;
11 | Q_PROPERTY(QColor color MEMBER color);
12 | Q_PROPERTY(bool pixelAligned MEMBER pixelAligned);
13 | Q_PROPERTY(int width MEMBER width);
14 | QML_VALUE_TYPE(clippingRectangleBorder);
15 |
16 | public:
17 | QColor color = Qt::black;
18 | bool pixelAligned = true;
19 | int width = 0;
20 | };
21 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/wlr_screencopy/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-screencopy-wlr STATIC
2 | wlr_screencopy.cpp
3 | )
4 |
5 | wl_proto(wlp-wlr-screencopy wlr-screencopy-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
6 |
7 | target_link_libraries(quickshell-wayland-screencopy-wlr PRIVATE
8 | Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
9 | Qt::Quick # for pch
10 | )
11 |
12 | target_link_libraries(quickshell-wayland-screencopy-wlr PUBLIC wlp-wlr-screencopy)
13 |
14 | qs_pch(quickshell-wayland-screencopy-wlr SET large)
15 |
--------------------------------------------------------------------------------
/src/wayland/xdgshell.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace qs::wayland::xdg_shell {
7 |
8 | // Hack that binds xdg_wm_base twice as QtWaylandXdgShell headers are not exported anywhere.
9 |
10 | class XdgWmBase
11 | : public QWaylandClientExtensionTemplate
12 | , public QtWayland::xdg_wm_base {
13 | public:
14 | static XdgWmBase* instance();
15 |
16 | private:
17 | explicit XdgWmBase();
18 | };
19 |
20 | } // namespace qs::wayland::xdg_shell
21 |
--------------------------------------------------------------------------------
/src/x11/i3/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-i3 STATIC)
2 |
3 | target_link_libraries(quickshell-i3 PRIVATE ${QT_DEPS})
4 |
5 | set(I3_MODULES)
6 |
7 | if (I3_IPC)
8 | add_subdirectory(ipc)
9 | list(APPEND I3_MODULES Quickshell.I3._Ipc)
10 | endif()
11 |
12 | qt_add_qml_module(quickshell-i3
13 | URI Quickshell.I3
14 | VERSION 0.1
15 | IMPORTS ${I3_MODULES}
16 | )
17 |
18 | install_qml_module(quickshell-i3)
19 |
20 | qs_pch(quickshell-i3)
21 | qs_pch(quickshell-i3plugin)
22 |
23 | target_link_libraries(quickshell PRIVATE quickshell-i3plugin)
24 |
--------------------------------------------------------------------------------
/src/launch/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(CLI11 CONFIG REQUIRED)
2 |
3 | qt_add_library(quickshell-launch STATIC
4 | parsecommand.cpp
5 | command.cpp
6 | launch.cpp
7 | main.cpp
8 | )
9 |
10 | target_link_libraries(quickshell-launch PRIVATE
11 | Qt::Quick Qt::Widgets CLI11::CLI11 quickshell-build
12 | )
13 |
14 | qs_add_pchset(launch
15 | DEPENDENCIES Qt::Core CLI11::CLI11
16 | HEADERS
17 |
18 |
19 | )
20 |
21 | qs_pch(quickshell-launch SET launch)
22 |
23 | target_link_libraries(quickshell PRIVATE quickshell-launch)
24 |
--------------------------------------------------------------------------------
/src/services/pipewire/connection.cpp:
--------------------------------------------------------------------------------
1 | #include "connection.hpp"
2 |
3 | #include
4 |
5 | namespace qs::service::pipewire {
6 |
7 | PwConnection::PwConnection(QObject* parent): QObject(parent) {
8 | if (this->core.isValid()) {
9 | this->registry.init(this->core);
10 | }
11 | }
12 |
13 | PwConnection* PwConnection::instance() {
14 | static PwConnection* instance = nullptr; // NOLINT
15 |
16 | if (instance == nullptr) {
17 | instance = new PwConnection();
18 | }
19 |
20 | return instance;
21 | }
22 |
23 | } // namespace qs::service::pipewire
24 |
--------------------------------------------------------------------------------
/src/services/upower/org.freedesktop.UPower.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/core/test/ringbuf.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class TestObject {
9 | public:
10 | explicit TestObject(quint32* count);
11 | ~TestObject();
12 | Q_DISABLE_COPY_MOVE(TestObject);
13 |
14 | private:
15 | quint32* count;
16 | };
17 |
18 | class TestRingBuffer: public QObject {
19 | Q_OBJECT;
20 |
21 | private slots:
22 | static void fill();
23 | static void clearPartial();
24 | static void move();
25 |
26 | static void hashLookup();
27 | };
28 |
--------------------------------------------------------------------------------
/src/wayland/session_lock/shell_integration.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class QSWaylandSessionLockIntegration: public QtWaylandClient::QWaylandShellIntegration {
9 | public:
10 | bool initialize(QtWaylandClient::QWaylandDisplay* /* display */) override { return true; }
11 | QtWaylandClient::QWaylandShellSurface*
12 | createShellSurface(QtWaylandClient::QWaylandWindow* window) override;
13 | };
14 |
--------------------------------------------------------------------------------
/src/services/greetd/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-service-greetd STATIC
2 | qml.cpp
3 | connection.cpp
4 | )
5 |
6 | qt_add_qml_module(quickshell-service-greetd
7 | URI Quickshell.Services.Greetd
8 | VERSION 0.1
9 | DEPENDENCIES QtQml
10 | )
11 |
12 | install_qml_module(quickshell-service-greetd)
13 |
14 | # can't be Qt::Qml because generation.hpp pulls in gui types
15 | target_link_libraries(quickshell-service-greetd PRIVATE Qt::Quick)
16 |
17 | qs_module_pch(quickshell-service-greetd)
18 |
19 | target_link_libraries(quickshell PRIVATE quickshell-service-greetdplugin)
20 |
--------------------------------------------------------------------------------
/src/services/pam/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-service-pam STATIC
2 | qml.cpp
3 | conversation.cpp
4 | ipc.cpp
5 | subprocess.cpp
6 | )
7 |
8 | qt_add_qml_module(quickshell-service-pam
9 | URI Quickshell.Services.Pam
10 | VERSION 0.1
11 | DEPENDENCIES QtQml
12 | )
13 |
14 | install_qml_module(quickshell-service-pam)
15 |
16 | target_link_libraries(quickshell-service-pam PRIVATE
17 | Qt::Qml pam ${PAM_LIBRARIES}
18 | Qt::Quick # pch
19 | )
20 |
21 | qs_module_pch(quickshell-service-pam)
22 |
23 | target_link_libraries(quickshell PRIVATE quickshell-service-pamplugin)
24 |
--------------------------------------------------------------------------------
/src/services/pipewire/connection.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "core.hpp"
4 | #include "defaults.hpp"
5 | #include "registry.hpp"
6 |
7 | namespace qs::service::pipewire {
8 |
9 | class PwConnection: public QObject {
10 | Q_OBJECT;
11 |
12 | public:
13 | explicit PwConnection(QObject* parent = nullptr);
14 |
15 | PwRegistry registry;
16 | PwDefaultTracker defaults {&this->registry};
17 |
18 | static PwConnection* instance();
19 |
20 | private:
21 | // init/destroy order is important. do not rearrange.
22 | PwCore core;
23 | };
24 |
25 | } // namespace qs::service::pipewire
26 |
--------------------------------------------------------------------------------
/src/wayland/buffer/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(PkgConfig REQUIRED)
2 | pkg_check_modules(dmabuf-deps REQUIRED IMPORTED_TARGET libdrm gbm egl)
3 |
4 | qt_add_library(quickshell-wayland-buffer STATIC
5 | manager.cpp
6 | dmabuf.cpp
7 | shm.cpp
8 | )
9 |
10 | wl_proto(wlp-linux-dmabuf linux-dmabuf-v1 "${WAYLAND_PROTOCOLS}/stable/linux-dmabuf")
11 |
12 | target_link_libraries(quickshell-wayland-buffer PRIVATE
13 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
14 | PkgConfig::dmabuf-deps
15 | wlp-linux-dmabuf
16 | )
17 |
18 | qs_pch(quickshell-wayland-buffer SET large)
19 |
--------------------------------------------------------------------------------
/src/core/iconimageprovider.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | class IconImageProvider: public QQuickImageProvider {
7 | public:
8 | explicit IconImageProvider(): QQuickImageProvider(QQuickImageProvider::Pixmap) {}
9 |
10 | QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override;
11 |
12 | static QPixmap missingPixmap(const QSize& size);
13 |
14 | static QString requestString(
15 | const QString& icon,
16 | const QString& path = QString(),
17 | const QString& fallback = QString()
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/src/x11/i3/ipc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-i3-ipc STATIC
2 | connection.cpp
3 | qml.cpp
4 | workspace.cpp
5 | monitor.cpp
6 | controller.cpp
7 | listener.cpp
8 | )
9 |
10 | qt_add_qml_module(quickshell-i3-ipc
11 | URI Quickshell.I3._Ipc
12 | VERSION 0.1
13 | DEPENDENCIES QtQml
14 | )
15 |
16 | qs_add_module_deps_light(quickshell-i3-ipc Quickshell)
17 |
18 | install_qml_module(quickshell-i3-ipc)
19 |
20 | target_link_libraries(quickshell-i3-ipc PRIVATE Qt::Quick)
21 |
22 | qs_module_pch(quickshell-i3-ipc SET large)
23 |
24 | target_link_libraries(quickshell PRIVATE quickshell-i3-ipcplugin)
25 |
--------------------------------------------------------------------------------
/src/core/shell.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "qmlglobal.hpp"
9 | #include "reload.hpp"
10 |
11 | ///! Optional root config element, allowing some settings to be specified inline.
12 | class ShellRoot: public ReloadPropagator {
13 | Q_OBJECT;
14 | Q_PROPERTY(QuickshellSettings* settings READ settings CONSTANT);
15 | QML_ELEMENT;
16 |
17 | public:
18 | explicit ShellRoot(QObject* parent = nullptr): ReloadPropagator(parent) {}
19 |
20 | [[nodiscard]] QuickshellSettings* settings() const;
21 | };
22 |
--------------------------------------------------------------------------------
/src/wayland/session_lock/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-sessionlock STATIC
2 | manager.cpp
3 | surface.cpp
4 | lock.cpp
5 | shell_integration.cpp
6 | session_lock.cpp
7 | )
8 |
9 | wl_proto(wlp-session-lock ext-session-lock-v1 "${WAYLAND_PROTOCOLS}/staging/ext-session-lock")
10 |
11 | target_link_libraries(quickshell-wayland-sessionlock PRIVATE
12 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
13 | wlp-session-lock
14 | )
15 |
16 | qs_pch(quickshell-wayland-sessionlock SET large)
17 |
18 | target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-sessionlock)
19 |
--------------------------------------------------------------------------------
/src/crash/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-crash STATIC
2 | main.cpp
3 | interface.cpp
4 | handler.cpp
5 | )
6 |
7 | qs_pch(quickshell-crash SET large)
8 |
9 | find_package(PkgConfig REQUIRED)
10 | pkg_check_modules(breakpad REQUIRED IMPORTED_TARGET breakpad)
11 | # only need client?? take only includes from pkg config todo
12 | target_link_libraries(quickshell-crash PRIVATE PkgConfig::breakpad -lbreakpad_client)
13 |
14 | # quick linked for pch compat
15 | target_link_libraries(quickshell-crash PRIVATE quickshell-build Qt::Quick Qt::Widgets)
16 |
17 | target_link_libraries(quickshell PRIVATE quickshell-crash)
18 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/hyprland_screencopy/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-screencopy-hyprland STATIC
2 | hyprland_screencopy.cpp
3 | )
4 |
5 | wl_proto(wlp-hyprland-screencopy hyprland-toplevel-export-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
6 |
7 | target_link_libraries(quickshell-wayland-screencopy-hyprland PRIVATE
8 | Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
9 | Qt::Quick # for pch
10 | )
11 |
12 | target_link_libraries(quickshell-wayland-screencopy-hyprland PUBLIC
13 | wlp-hyprland-screencopy wlp-foreign-toplevel
14 | )
15 |
16 | qs_pch(quickshell-wayland-screencopy-hyprland SET large)
17 |
--------------------------------------------------------------------------------
/src/services/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | if (SERVICE_STATUS_NOTIFIER)
2 | add_subdirectory(status_notifier)
3 | endif()
4 |
5 | if (SERVICE_PIPEWIRE)
6 | add_subdirectory(pipewire)
7 | endif()
8 |
9 | if (SERVICE_MPRIS)
10 | add_subdirectory(mpris)
11 | endif()
12 |
13 | if (SERVICE_PAM)
14 | add_subdirectory(pam)
15 | endif()
16 |
17 | if (SERVICE_POLKIT)
18 | add_subdirectory(polkit)
19 | endif()
20 |
21 | if (SERVICE_GREETD)
22 | add_subdirectory(greetd)
23 | endif()
24 |
25 | if (SERVICE_UPOWER)
26 | add_subdirectory(upower)
27 | endif()
28 |
29 | if (SERVICE_NOTIFICATIONS)
30 | add_subdirectory(notifications)
31 | endif()
32 |
--------------------------------------------------------------------------------
/src/core/toolsupport.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "scan.hpp"
6 |
7 | namespace qs::core {
8 |
9 | class QmlToolingSupport {
10 | public:
11 | static bool updateTooling(const QDir& configRoot, QmlScanner& scanner);
12 |
13 | private:
14 | static QString getQmllsConfig();
15 | static bool lockTooling();
16 | static bool updateQmllsConfig(const QDir& configRoot, bool create);
17 | static void updateToolingFs(QmlScanner& scanner, const QDir& scanDir, const QDir& linkDir);
18 | static inline bool toolingEnabled = false;
19 | static inline QFile* toolingLock = nullptr;
20 | };
21 |
22 | } // namespace qs::core
23 |
--------------------------------------------------------------------------------
/src/window/init.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "../core/plugin.hpp"
5 |
6 | namespace {
7 |
8 | class WindowPlugin: public QsEnginePlugin {
9 | // _Window has to be registered before wayland or x11 modules, otherwise module overlays
10 | // will apply in the wrong order.
11 | QString name() override { return "window"; }
12 |
13 | void registerTypes() override {
14 | qmlRegisterModuleImport(
15 | "Quickshell",
16 | QQmlModuleImportModuleAny,
17 | "Quickshell._Window",
18 | QQmlModuleImportLatest
19 | );
20 | }
21 | };
22 |
23 | QS_REGISTER_PLUGIN(WindowPlugin);
24 |
25 | } // namespace
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Quickshell
2 | See the [website](https://quickshell.outfoxxed.me) for more information
3 | and installation instructions.
4 |
5 | This repo is hosted at:
6 | - https://git.outfoxxed.me/quickshell/quickshell
7 | - https://github.com/quickshell-mirror/quickshell
8 |
9 | # Contributing / Development
10 | See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
11 |
12 | #### License
13 |
14 |
15 | Licensed under the GNU LGPL 3.
16 |
17 |
18 |
19 |
20 |
21 | Unless you explicitly state otherwise, any contribution submitted
22 | for inclusion shall be licensed as above, without any additional
23 | terms or conditions.
24 |
25 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "nixpkgs": {
4 | "locked": {
5 | "lastModified": 1762977756,
6 | "narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=",
7 | "owner": "NixOS",
8 | "repo": "nixpkgs",
9 | "rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55",
10 | "type": "github"
11 | },
12 | "original": {
13 | "id": "nixpkgs",
14 | "ref": "nixos-unstable",
15 | "type": "indirect"
16 | }
17 | },
18 | "root": {
19 | "inputs": {
20 | "nixpkgs": "nixpkgs"
21 | }
22 | }
23 | },
24 | "root": "root",
25 | "version": 7
26 | }
27 |
--------------------------------------------------------------------------------
/src/core/doc.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // hide a property, function, or signal from typegen
4 | #define QSDOC_HIDE
5 |
6 | // override the base class as seen by typegen
7 | #define QSDOC_BASECLASS(baseclass)
8 |
9 | // make the type visible in the docs even if not a QML_ELEMENT
10 | #define QSDOC_ELEMENT
11 | #define QSDOC_NAMED_ELEMENT(name)
12 |
13 | // unmark uncreatable (will be overlayed by other types)
14 | #define QSDOC_CREATABLE
15 |
16 | // change the cname used for this type
17 | #define QSDOC_CNAME(name)
18 |
19 | // overridden properties
20 | #define QSDOC_PROPERTY_OVERRIDE(...)
21 |
22 | // override types of properties for docs
23 | #define QSDOC_TYPE_OVERRIDE(type)
24 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/focus_grab/manager.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace qs::hyprland::focus_grab {
7 | using HyprlandFocusGrabManager = QtWayland::hyprland_focus_grab_manager_v1;
8 | class FocusGrab;
9 |
10 | class FocusGrabManager
11 | : public QWaylandClientExtensionTemplate
12 | , public HyprlandFocusGrabManager {
13 | public:
14 | explicit FocusGrabManager();
15 |
16 | [[nodiscard]] bool available() const;
17 | [[nodiscard]] FocusGrab* createGrab();
18 |
19 | static FocusGrabManager* instance();
20 | };
21 |
22 | } // namespace qs::hyprland::focus_grab
23 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/surface/manager.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "surface.hpp"
8 |
9 | namespace qs::hyprland::surface::impl {
10 |
11 | class HyprlandSurfaceManager
12 | : public QWaylandClientExtensionTemplate
13 | , public QtWayland::hyprland_surface_manager_v1 {
14 | public:
15 | explicit HyprlandSurfaceManager();
16 |
17 | HyprlandSurface* createHyprlandExtension(QtWaylandClient::QWaylandWindow* surface);
18 |
19 | static HyprlandSurfaceManager* instance();
20 | };
21 |
22 | } // namespace qs::hyprland::surface::impl
23 |
--------------------------------------------------------------------------------
/src/build/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(quickshell-build INTERFACE)
2 |
3 | if (NOT DEFINED GIT_REVISION)
4 | execute_process(
5 | COMMAND git rev-parse HEAD
6 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
7 | OUTPUT_VARIABLE GIT_REVISION
8 | OUTPUT_STRIP_TRAILING_WHITESPACE
9 | )
10 | endif()
11 |
12 | if (CRASH_REPORTER)
13 | set(CRASH_REPORTER_DEF 1)
14 | else()
15 | set(CRASH_REPORTER_DEF 0)
16 | endif()
17 |
18 | if (DISTRIBUTOR_DEBUGINFO_AVAILABLE)
19 | set(DEBUGINFO_AVAILABLE 1)
20 | else()
21 | set(DEBUGINFO_AVAILABLE 0)
22 | endif()
23 |
24 | configure_file(build.hpp.in build.hpp @ONLY ESCAPE_QUOTES)
25 |
26 | target_include_directories(quickshell-build INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
27 |
--------------------------------------------------------------------------------
/src/x11/util.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | xcb_connection_t* x11Connection();
9 |
10 | class XAtom {
11 | public:
12 | [[nodiscard]] bool isValid();
13 | [[nodiscard]] const xcb_atom_t& atom();
14 |
15 | // NOLINTBEGIN
16 | static XAtom _NET_WM_STRUT;
17 | static XAtom _NET_WM_STRUT_PARTIAL;
18 | static XAtom _NET_WM_DESKTOP;
19 | // NOLINTEND
20 |
21 | static void initAtoms();
22 |
23 | private:
24 | void init(const QByteArray& name);
25 | void resolve();
26 |
27 | bool resolved = false;
28 | xcb_atom_t mAtom = XCB_ATOM_NONE;
29 | xcb_intern_atom_cookie_t cookie {};
30 | };
31 |
--------------------------------------------------------------------------------
/changelog/v0.2.1.md:
--------------------------------------------------------------------------------
1 | ## New Features
2 |
3 | - Changes to desktop entries are now tracked in real time.
4 |
5 | ## Other Changes
6 |
7 | - Added support for Qt 6.10
8 |
9 | ## Bug Fixes
10 |
11 | - Fixed volumes getting stuck on change for pipewire devices with few volume steps.
12 | - Fixed a crash when running out of disk space to write log files.
13 | - Fixed a rare crash when disconnecting a monitor.
14 | - Fixed build issues preventing cross compilation from working.
15 | - Fixed dekstop entries with lower priority than a hidden entry not being hidden.
16 | - Fixed desktop entry keys with mismatched modifier or country not being discarded.
17 | - Fixed greetd hanging when authenticating with a fingerprint.
18 |
--------------------------------------------------------------------------------
/src/core/persistentprops.cpp:
--------------------------------------------------------------------------------
1 | #include "persistentprops.hpp"
2 |
3 | #include
4 | #include
5 |
6 | void PersistentProperties::onReload(QObject* oldInstance) {
7 | if (qobject_cast(oldInstance) == nullptr) {
8 | emit this->loaded();
9 | return;
10 | }
11 |
12 | const auto* metaObject = this->metaObject();
13 | for (auto i = metaObject->propertyOffset(); i < metaObject->propertyCount(); i++) {
14 | const auto prop = metaObject->property(i);
15 | auto oldProp = oldInstance->property(prop.name());
16 |
17 | if (oldProp.isValid()) {
18 | this->setProperty(prop.name(), oldProp);
19 | }
20 | }
21 |
22 | emit this->loaded();
23 | emit this->reloaded();
24 | }
25 |
--------------------------------------------------------------------------------
/src/dbus/org.freedesktop.DBus.ObjectManager.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/x11/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(XCB REQUIRED COMPONENTS XCB)
2 |
3 | qt_add_library(quickshell-x11 STATIC
4 | util.cpp
5 | panel_window.cpp
6 | )
7 |
8 | qt_add_qml_module(quickshell-x11
9 | URI Quickshell.X11
10 | VERSION 0.1
11 | DEPENDENCIES QtQuick
12 | )
13 |
14 | if(I3)
15 | add_subdirectory(i3)
16 | endif()
17 |
18 | install_qml_module(quickshell-x11)
19 |
20 | add_library(quickshell-x11-init OBJECT init.cpp)
21 |
22 | target_link_libraries(quickshell-x11 PRIVATE Qt::Quick ${XCB_LIBRARIES})
23 | target_link_libraries(quickshell-x11-init PRIVATE Qt::Quick Qt::Qml ${XCB_LIBRARIES})
24 |
25 | qs_module_pch(quickshell-x11 SET large)
26 |
27 | target_link_libraries(quickshell PRIVATE quickshell-x11plugin quickshell-x11-init)
28 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_executable(quickshell main.cpp)
2 |
3 | install(TARGETS quickshell RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
4 |
5 | add_subdirectory(build)
6 | add_subdirectory(launch)
7 | add_subdirectory(core)
8 | add_subdirectory(debug)
9 | add_subdirectory(ipc)
10 | add_subdirectory(window)
11 | add_subdirectory(io)
12 | add_subdirectory(widgets)
13 | add_subdirectory(ui)
14 |
15 | if (CRASH_REPORTER)
16 | add_subdirectory(crash)
17 | endif()
18 |
19 | if (DBUS)
20 | add_subdirectory(dbus)
21 | endif()
22 |
23 | if (WAYLAND)
24 | add_subdirectory(wayland)
25 | endif()
26 |
27 | if (X11)
28 | add_subdirectory(x11)
29 | endif()
30 |
31 | add_subdirectory(services)
32 |
33 | if (BLUETOOTH)
34 | add_subdirectory(bluetooth)
35 | endif()
36 |
--------------------------------------------------------------------------------
/src/services/mpris/org.mpris.MediaPlayer2.Player.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/core/elapsedtimer.cpp:
--------------------------------------------------------------------------------
1 | #include "elapsedtimer.hpp"
2 |
3 | #include
4 |
5 | ElapsedTimer::ElapsedTimer() { this->timer.start(); }
6 |
7 | qreal ElapsedTimer::elapsed() { return static_cast(this->elapsedNs()) / 1000000000.0; }
8 |
9 | qreal ElapsedTimer::restart() { return static_cast(this->restartNs()) / 1000000000.0; }
10 |
11 | qint64 ElapsedTimer::elapsedMs() { return this->timer.elapsed(); }
12 |
13 | qint64 ElapsedTimer::restartMs() { return this->timer.restart(); }
14 |
15 | qint64 ElapsedTimer::elapsedNs() { return this->timer.nsecsElapsed(); }
16 |
17 | qint64 ElapsedTimer::restartNs() {
18 | // see qelapsedtimer.cpp
19 | auto old = this->timer;
20 | this->timer.start();
21 | return old.durationTo(this->timer).count();
22 | }
23 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/wlr_screencopy/wlr_screencopy.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../manager.hpp"
8 |
9 | namespace qs::wayland::screencopy::wlr {
10 |
11 | class WlrScreencopyManager
12 | : public QWaylandClientExtensionTemplate
13 | , public QtWayland::zwlr_screencopy_manager_v1 {
14 | public:
15 | ScreencopyContext* captureOutput(QScreen* screen, bool paintCursors, QRect region = QRect());
16 |
17 | static WlrScreencopyManager* instance();
18 |
19 | private:
20 | explicit WlrScreencopyManager();
21 |
22 | friend class WlrScreencopyContext;
23 | };
24 |
25 | } // namespace qs::wayland::screencopy::wlr
26 |
--------------------------------------------------------------------------------
/src/core/singleton.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "reload.hpp"
12 |
13 | ///! The root component for reloadable singletons.
14 | /// All singletons should inherit from this type.
15 | class Singleton: public ReloadPropagator {
16 | Q_OBJECT;
17 | QML_ELEMENT;
18 |
19 | public:
20 | void componentComplete() override;
21 | };
22 |
23 | class SingletonRegistry {
24 | public:
25 | SingletonRegistry() = default;
26 |
27 | void registerSingleton(const QUrl& url, Singleton* singleton);
28 | void onReload(SingletonRegistry* old);
29 |
30 | private:
31 | QHash registry;
32 | };
33 |
--------------------------------------------------------------------------------
/src/io/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-io STATIC
2 | datastream.cpp
3 | processcore.cpp
4 | process.cpp
5 | fileview.cpp
6 | jsonadapter.cpp
7 | ipccomm.cpp
8 | ipc.cpp
9 | ipchandler.cpp
10 | )
11 |
12 | if (SOCKETS)
13 | target_sources(quickshell-io PRIVATE socket.cpp)
14 | endif()
15 |
16 | qt_add_qml_module(quickshell-io
17 | URI Quickshell.Io
18 | VERSION 0.1
19 | DEPENDENCIES QtQml
20 | QML_FILES
21 | FileView.qml
22 | )
23 |
24 | qs_add_module_deps_light(quickshell-io Quickshell)
25 | install_qml_module(quickshell-io)
26 |
27 | target_link_libraries(quickshell-io PRIVATE Qt::Quick)
28 | target_link_libraries(quickshell PRIVATE quickshell-ioplugin)
29 |
30 | qs_module_pch(quickshell-io)
31 |
32 | if (BUILD_TESTING)
33 | add_subdirectory(test)
34 | endif()
35 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/focus_grab/manager.cpp:
--------------------------------------------------------------------------------
1 | #include "manager.hpp"
2 |
3 | #include
4 |
5 | #include "grab.hpp"
6 |
7 | namespace qs::hyprland::focus_grab {
8 |
9 | FocusGrabManager::FocusGrabManager(): QWaylandClientExtensionTemplate(1) {
10 | this->initialize();
11 | }
12 |
13 | bool FocusGrabManager::available() const { return this->isActive(); }
14 |
15 | FocusGrab* FocusGrabManager::createGrab() { return new FocusGrab(this->create_grab()); }
16 |
17 | FocusGrabManager* FocusGrabManager::instance() {
18 | static FocusGrabManager* instance = nullptr; // NOLINT
19 |
20 | if (instance == nullptr) {
21 | instance = new FocusGrabManager();
22 | }
23 |
24 | return instance;
25 | }
26 |
27 | } // namespace qs::hyprland::focus_grab
28 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/surface/manager.cpp:
--------------------------------------------------------------------------------
1 | #include "manager.hpp"
2 |
3 | #include
4 | #include
5 |
6 | #include "surface.hpp"
7 |
8 | namespace qs::hyprland::surface::impl {
9 |
10 | HyprlandSurfaceManager::HyprlandSurfaceManager(): QWaylandClientExtensionTemplate(2) {
11 | this->initialize();
12 | }
13 |
14 | HyprlandSurface*
15 | HyprlandSurfaceManager::createHyprlandExtension(QtWaylandClient::QWaylandWindow* surface) {
16 | return new HyprlandSurface(this->get_hyprland_surface(surface->surface()), surface);
17 | }
18 |
19 | HyprlandSurfaceManager* HyprlandSurfaceManager::instance() {
20 | static auto* instance = new HyprlandSurfaceManager();
21 | return instance;
22 | }
23 |
24 | } // namespace qs::hyprland::surface::impl
25 |
--------------------------------------------------------------------------------
/src/wayland/wlr_layershell/shell_integration.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace qs::wayland::layershell {
9 |
10 | class LayerShellIntegration
11 | : public QtWaylandClient::QWaylandShellIntegrationTemplate
12 | , public QtWayland::zwlr_layer_shell_v1 {
13 | public:
14 | LayerShellIntegration();
15 | ~LayerShellIntegration() override;
16 | Q_DISABLE_COPY_MOVE(LayerShellIntegration);
17 |
18 | QtWaylandClient::QWaylandShellSurface*
19 | createShellSurface(QtWaylandClient::QWaylandWindow* window) override;
20 | };
21 |
22 | } // namespace qs::wayland::layershell
23 |
--------------------------------------------------------------------------------
/src/wayland/output_tracking.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | struct wl_output;
9 |
10 | namespace qs::wayland {
11 |
12 | class WlOutputTracker: public QObject {
13 | Q_OBJECT;
14 |
15 | public:
16 | [[nodiscard]] const QList& screens() const { return this->mScreens; }
17 |
18 | signals:
19 | void screenAdded(QScreen* screen);
20 | void screenRemoved(QScreen* screen);
21 |
22 | public slots:
23 | void addOutput(::wl_output* output);
24 | void removeOutput(::wl_output* output);
25 |
26 | private slots:
27 | void onQScreenAdded(QScreen* screen);
28 |
29 | private:
30 | QList mScreens;
31 | QList<::wl_output*> mOutputs;
32 | };
33 |
34 | } // namespace qs::wayland
35 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/manager.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../buffer/manager.hpp"
8 |
9 | namespace qs::wayland::screencopy {
10 |
11 | class ScreencopyContext: public QObject {
12 | Q_OBJECT;
13 |
14 | public:
15 | [[nodiscard]] buffer::WlBufferSwapchain& swapchain() { return this->mSwapchain; }
16 | virtual void captureFrame() = 0;
17 |
18 | signals:
19 | void frameCaptured();
20 | void stopped();
21 |
22 | protected:
23 | ScreencopyContext() = default;
24 |
25 | buffer::WlBufferSwapchain mSwapchain;
26 | };
27 |
28 | class ScreencopyManager {
29 | public:
30 | static ScreencopyContext* createContext(QObject* object, bool paintCursors);
31 | };
32 |
33 | } // namespace qs::wayland::screencopy
34 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/surface/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-hyprland-surface-extensions STATIC
2 | qml.cpp
3 | manager.cpp
4 | surface.cpp
5 | )
6 |
7 | qt_add_qml_module(quickshell-hyprland-surface-extensions
8 | URI Quickshell.Hyprland._SurfaceExtensions
9 | VERSION 0.1
10 | DEPENDENCIES QtQml
11 | )
12 |
13 | install_qml_module(quickshell-hyprland-surface-extensions)
14 |
15 | wl_proto(wlp-hyprland-surface hyprland-surface-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
16 |
17 | target_link_libraries(quickshell-hyprland-surface-extensions PRIVATE
18 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
19 | wlp-hyprland-surface
20 | )
21 |
22 | qs_module_pch(quickshell-hyprland-surface-extensions)
23 |
24 | target_link_libraries(quickshell PRIVATE quickshell-hyprland-surface-extensionsplugin)
25 |
--------------------------------------------------------------------------------
/src/wayland/wlr_layershell/shell_integration.cpp:
--------------------------------------------------------------------------------
1 | #include "shell_integration.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "surface.hpp"
8 |
9 | namespace qs::wayland::layershell {
10 |
11 | LayerShellIntegration::LayerShellIntegration()
12 | : QtWaylandClient::QWaylandShellIntegrationTemplate(4) {}
13 |
14 | LayerShellIntegration::~LayerShellIntegration() {
15 | if (this->isInitialized()) {
16 | this->destroy();
17 | }
18 | }
19 |
20 | QtWaylandClient::QWaylandShellSurface*
21 | LayerShellIntegration::createShellSurface(QtWaylandClient::QWaylandWindow* window) {
22 | return new LayerSurface(this, window);
23 | }
24 |
25 | } // namespace qs::wayland::layershell
26 |
--------------------------------------------------------------------------------
/src/core/incubator.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "logcat.hpp"
8 |
9 | QS_DECLARE_LOGGING_CATEGORY(logIncubator);
10 |
11 | class QsQmlIncubator
12 | : public QObject
13 | , public QQmlIncubator {
14 | Q_OBJECT;
15 |
16 | public:
17 | explicit QsQmlIncubator(QsQmlIncubator::IncubationMode mode, QObject* parent = nullptr)
18 | : QObject(parent)
19 | , QQmlIncubator(mode) {}
20 |
21 | void statusChanged(QQmlIncubator::Status status) override;
22 |
23 | signals:
24 | void completed();
25 | void failed();
26 | };
27 |
28 | class DelayedQmlIncubationController: public QQmlIncubationController {
29 | // Do nothing.
30 | // This ensures lazy loaders don't start blocking before onReload creates windows.
31 | };
32 |
--------------------------------------------------------------------------------
/src/core/module.md:
--------------------------------------------------------------------------------
1 | name = "Quickshell"
2 | description = "Core Quickshell types"
3 | headers = [
4 | "qmlglobal.hpp",
5 | "qmlscreen.hpp",
6 | "reload.hpp",
7 | "shell.hpp",
8 | "variants.hpp",
9 | "region.hpp",
10 | "../window/proxywindow.hpp",
11 | "persistentprops.hpp",
12 | "../window/windowinterface.hpp",
13 | "../window/panelinterface.hpp",
14 | "../window/floatingwindow.hpp",
15 | "../window/popupwindow.hpp",
16 | "singleton.hpp",
17 | "lazyloader.hpp",
18 | "easingcurve.hpp",
19 | "transformwatcher.hpp",
20 | "boundcomponent.hpp",
21 | "model.hpp",
22 | "elapsedtimer.hpp",
23 | "desktopentry.hpp",
24 | "qsmenu.hpp",
25 | "retainable.hpp",
26 | "popupanchor.hpp",
27 | "types.hpp",
28 | "qsmenuanchor.hpp",
29 | "clock.hpp",
30 | "scriptmodel.hpp",
31 | "colorquantizer.hpp",
32 | ]
33 | -----
34 |
--------------------------------------------------------------------------------
/src/wayland/session_lock/shell_integration.cpp:
--------------------------------------------------------------------------------
1 | #include "shell_integration.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "session_lock.hpp"
8 | #include "surface.hpp"
9 |
10 | QtWaylandClient::QWaylandShellSurface*
11 | QSWaylandSessionLockIntegration::createShellSurface(QtWaylandClient::QWaylandWindow* window) {
12 | auto* lock = LockWindowExtension::get(window->window());
13 | if (lock == nullptr || lock->surface == nullptr) {
14 | qFatal() << "Visibility canary failed. A window with a LockWindowExtension MUST be set to "
15 | "visible via LockWindowExtension::setVisible";
16 | }
17 |
18 | QSWaylandSessionLockSurface* surface = lock->surface; // shut up the unused include linter
19 | return surface;
20 | }
21 |
--------------------------------------------------------------------------------
/src/services/upower/org.freedesktop.UPower.Device.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/wayland/idle_notify/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-idle-notify STATIC
2 | proto.cpp
3 | monitor.cpp
4 | )
5 |
6 | qt_add_qml_module(quickshell-wayland-idle-notify
7 | URI Quickshell.Wayland._IdleNotify
8 | VERSION 0.1
9 | DEPENDENCIES QtQuick
10 | )
11 |
12 | install_qml_module(quickshell-wayland-idle-notify)
13 |
14 | qs_add_module_deps_light(quickshell-wayland-idle-notify Quickshell)
15 |
16 | wl_proto(wlp-idle-notify ext-idle-notify-v1 "${WAYLAND_PROTOCOLS}/staging/ext-idle-notify")
17 |
18 | target_link_libraries(quickshell-wayland-idle-notify PRIVATE
19 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
20 | wlp-idle-notify
21 | )
22 |
23 | qs_module_pch(quickshell-wayland-idle-notify SET large)
24 |
25 | target_link_libraries(quickshell PRIVATE quickshell-wayland-idle-notifyplugin)
26 |
--------------------------------------------------------------------------------
/src/wayland/session_lock/manager.cpp:
--------------------------------------------------------------------------------
1 | #include "manager.hpp"
2 |
3 | #include
4 |
5 | #include "lock.hpp"
6 |
7 | QSWaylandSessionLockManager::QSWaylandSessionLockManager()
8 | : QWaylandClientExtensionTemplate(1) {
9 | this->initialize();
10 | }
11 |
12 | QSWaylandSessionLockManager::~QSWaylandSessionLockManager() { this->destroy(); }
13 |
14 | QSWaylandSessionLock* QSWaylandSessionLockManager::acquireLock() {
15 | if (this->isLocked()) return nullptr;
16 | this->active = new QSWaylandSessionLock(this, this->lock());
17 | return this->active;
18 | }
19 |
20 | bool QSWaylandSessionLockManager::isLocked() const { return this->active != nullptr; }
21 | bool QSWaylandSessionLockManager::isSecure() const {
22 | return this->isLocked() && this->active->hasCompositorLock();
23 | }
24 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/global_shortcuts/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-hyprland-global-shortcuts STATIC
2 | qml.cpp
3 | manager.cpp
4 | shortcut.cpp
5 | )
6 |
7 | qt_add_qml_module(quickshell-hyprland-global-shortcuts
8 | URI Quickshell.Hyprland._GlobalShortcuts
9 | VERSION 0.1
10 | DEPENDENCIES QtQml
11 | )
12 |
13 | install_qml_module(quickshell-hyprland-global-shortcuts)
14 |
15 | wl_proto(wlp-hyprland-shortcuts hyprland-global-shortcuts-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
16 |
17 | target_link_libraries(quickshell-hyprland-global-shortcuts PRIVATE
18 | Qt::Qml Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
19 | Qt::Quick # pch
20 | wlp-hyprland-shortcuts
21 | )
22 |
23 | qs_module_pch(quickshell-hyprland-global-shortcuts)
24 |
25 | target_link_libraries(quickshell PRIVATE quickshell-hyprland-global-shortcutsplugin)
26 |
--------------------------------------------------------------------------------
/src/wayland/idle_inhibit/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-idle-inhibit STATIC
2 | proto.cpp
3 | inhibitor.cpp
4 | )
5 |
6 | qt_add_qml_module(quickshell-wayland-idle-inhibit
7 | URI Quickshell.Wayland._IdleInhibitor
8 | VERSION 0.1
9 | DEPENDENCIES QtQuick
10 | )
11 |
12 | install_qml_module(quickshell-wayland-idle-inhibit)
13 |
14 | qs_add_module_deps_light(quickshell-wayland-idle-inhibit Quickshell)
15 |
16 | wl_proto(wlp-idle-inhibit idle-inhibit-unstable-v1 "${WAYLAND_PROTOCOLS}/unstable/idle-inhibit")
17 |
18 | target_link_libraries(quickshell-wayland-idle-inhibit PRIVATE
19 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
20 | wlp-idle-inhibit
21 | )
22 |
23 | qs_module_pch(quickshell-wayland-idle-inhibit SET large)
24 |
25 | target_link_libraries(quickshell PRIVATE quickshell-wayland-idle-inhibitplugin)
26 |
--------------------------------------------------------------------------------
/src/core/rootwrapper.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "generation.hpp"
11 |
12 | class RootWrapper: public QObject {
13 | Q_OBJECT;
14 |
15 | public:
16 | explicit RootWrapper(QString rootPath, QString shellId);
17 | ~RootWrapper() override;
18 | Q_DISABLE_COPY_MOVE(RootWrapper);
19 |
20 | void reloadGraph(bool hard);
21 |
22 | private slots:
23 | void generationDestroyed();
24 | void onWatchFilesChanged();
25 | void onWatchedFilesChanged();
26 | void updateTooling();
27 |
28 | private:
29 | QString rootPath;
30 | QString shellId;
31 | EngineGeneration* generation = nullptr;
32 | QString originalWorkingDirectory;
33 | QFileSystemWatcher configDirWatcher;
34 | };
35 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/focus_grab/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-hyprland-focus-grab STATIC
2 | manager.cpp
3 | grab.cpp
4 | qml.cpp
5 | )
6 |
7 | qt_add_qml_module(quickshell-hyprland-focus-grab
8 | URI Quickshell.Hyprland._FocusGrab
9 | VERSION 0.1
10 | DEPENDENCIES QtQml
11 | )
12 |
13 | qs_add_module_deps_light(quickshell-hyprland-focus-grab Quickshell)
14 |
15 | install_qml_module(quickshell-hyprland-focus-grab)
16 |
17 | wl_proto(wlp-hyprland-focus-grab hyprland-focus-grab-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
18 |
19 | target_link_libraries(quickshell-hyprland-focus-grab PRIVATE
20 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
21 | wlp-hyprland-focus-grab
22 | )
23 |
24 | qs_module_pch(quickshell-hyprland-focus-grab SET large)
25 |
26 | target_link_libraries(quickshell PRIVATE quickshell-hyprland-focus-grabplugin)
27 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "../../toplevel_management/handle.hpp"
7 | #include "../manager.hpp"
8 |
9 | namespace qs::wayland::screencopy::hyprland {
10 |
11 | class HyprlandScreencopyManager
12 | : public QWaylandClientExtensionTemplate
13 | , public QtWayland::hyprland_toplevel_export_manager_v1 {
14 | public:
15 | ScreencopyContext*
16 | captureToplevel(toplevel_management::impl::ToplevelHandle* handle, bool paintCursors);
17 |
18 | static HyprlandScreencopyManager* instance();
19 |
20 | private:
21 | explicit HyprlandScreencopyManager();
22 |
23 | friend class HyprlandScreencopyContext;
24 | };
25 |
26 | } // namespace qs::wayland::screencopy::hyprland
27 |
--------------------------------------------------------------------------------
/src/x11/init.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "../core/plugin.hpp"
7 | #include "panel_window.hpp"
8 | #include "util.hpp"
9 |
10 | namespace {
11 |
12 | class X11Plugin: public QsEnginePlugin {
13 | QList dependencies() override { return {"window"}; }
14 |
15 | bool applies() override { return QGuiApplication::platformName() == "xcb"; }
16 |
17 | void init() override { XAtom::initAtoms(); }
18 |
19 | void registerTypes() override {
20 | qmlRegisterType("Quickshell._X11Overlay", 1, 0, "PanelWindow");
21 |
22 | qmlRegisterModuleImport(
23 | "Quickshell",
24 | QQmlModuleImportModuleAny,
25 | "Quickshell._X11Overlay",
26 | QQmlModuleImportLatest
27 | );
28 | }
29 | };
30 |
31 | QS_REGISTER_PLUGIN(X11Plugin);
32 |
33 | } // namespace
34 |
--------------------------------------------------------------------------------
/src/core/scan.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "logcat.hpp"
10 |
11 | QS_DECLARE_LOGGING_CATEGORY(logQmlScanner);
12 |
13 | // expects canonical paths
14 | class QmlScanner {
15 | public:
16 | QmlScanner() = default;
17 | QmlScanner(const QDir& rootPath): rootPath(rootPath) {}
18 |
19 | void scanDir(const QDir& dir);
20 | void scanQmlRoot(const QString& path);
21 |
22 | QVector scannedDirs;
23 | QVector scannedFiles;
24 | QHash fileIntercepts;
25 |
26 | private:
27 | QDir rootPath;
28 |
29 | bool scanQmlFile(const QString& path, bool& singleton, bool& internal);
30 | bool scanQmlJson(const QString& path);
31 | [[nodiscard]] static QPair jsonToQml(const QJsonValue& value, int indent = 0);
32 | };
33 |
--------------------------------------------------------------------------------
/src/core/test/scriptmodel.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | struct ModelOperation {
9 | enum Enum : quint8 {
10 | Insert,
11 | Remove,
12 | Move,
13 | };
14 |
15 | ModelOperation(Enum operation, qint32 index, qint32 length, qint32 destIndex = -1)
16 | : operation(operation)
17 | , index(index)
18 | , length(length)
19 | , destIndex(destIndex) {}
20 |
21 | Enum operation;
22 | qint32 index = 0;
23 | qint32 length = 0;
24 | qint32 destIndex = -1;
25 |
26 | [[nodiscard]] bool operator==(const ModelOperation& other) const;
27 | };
28 |
29 | QDebug& operator<<(QDebug& debug, const ModelOperation& op);
30 |
31 | class TestScriptModel: public QObject {
32 | Q_OBJECT;
33 |
34 | private slots:
35 | static void unique_data(); // NOLINT
36 | static void unique();
37 | };
38 |
--------------------------------------------------------------------------------
/src/services/pipewire/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(PkgConfig REQUIRED)
2 | pkg_check_modules(pipewire REQUIRED IMPORTED_TARGET libpipewire-0.3)
3 |
4 | qt_add_library(quickshell-service-pipewire STATIC
5 | qml.cpp
6 | core.cpp
7 | connection.cpp
8 | registry.cpp
9 | node.cpp
10 | metadata.cpp
11 | link.cpp
12 | device.cpp
13 | defaults.cpp
14 | )
15 |
16 | qt_add_qml_module(quickshell-service-pipewire
17 | URI Quickshell.Services.Pipewire
18 | VERSION 0.1
19 | DEPENDENCIES QtQml
20 | )
21 |
22 | qs_add_module_deps_light(quickshell-service-pipewire Quickshell)
23 |
24 | install_qml_module(quickshell-service-pipewire)
25 |
26 | target_link_libraries(quickshell-service-pipewire PRIVATE
27 | Qt::Qml PkgConfig::pipewire
28 | Qt::Quick # pch
29 | )
30 |
31 | qs_module_pch(quickshell-service-pipewire)
32 |
33 | target_link_libraries(quickshell PRIVATE quickshell-service-pipewireplugin)
34 |
--------------------------------------------------------------------------------
/src/wayland/idle_notify/test/manual/idle_notify.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Controls
3 | import QtQuick.Layouts
4 | import Quickshell
5 | import Quickshell.Wayland
6 |
7 | FloatingWindow {
8 | color: contentItem.palette.window
9 |
10 | IdleMonitor {
11 | id: monitor
12 | enabled: enabledCb.checked
13 | timeout: timeoutSb.value
14 | respectInhibitors: respectInhibitorsCb.checked
15 | }
16 |
17 | ColumnLayout {
18 | Label { text: `Is idle? ${monitor.isIdle}` }
19 |
20 | CheckBox {
21 | id: enabledCb
22 | text: "Enabled"
23 | checked: true
24 | }
25 |
26 | CheckBox {
27 | id: respectInhibitorsCb
28 | text: "Respect Inhibitors"
29 | checked: true
30 | }
31 |
32 | RowLayout {
33 | Label { text: "Timeout" }
34 |
35 | SpinBox {
36 | id: timeoutSb
37 | editable: true
38 | from: 0
39 | to: 1000
40 | value: 5
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/wayland/session_lock/manager.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "lock.hpp"
8 |
9 | class QSWaylandSessionLockManager
10 | : public QWaylandClientExtensionTemplate
11 | , public QtWayland::ext_session_lock_manager_v1 {
12 | public:
13 | QSWaylandSessionLockManager();
14 | ~QSWaylandSessionLockManager() override;
15 | Q_DISABLE_COPY_MOVE(QSWaylandSessionLockManager);
16 |
17 | // Create a new session lock if there is no currently active lock, otherwise null.
18 | QSWaylandSessionLock* acquireLock();
19 | [[nodiscard]] bool isLocked() const;
20 | [[nodiscard]] bool isSecure() const;
21 |
22 | static bool sessionLocked();
23 |
24 | private:
25 | QSWaylandSessionLock* active = nullptr;
26 |
27 | friend class QSWaylandSessionLock;
28 | };
29 |
--------------------------------------------------------------------------------
/src/wayland/shortcuts_inhibit/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-shortcuts-inhibit STATIC
2 | proto.cpp
3 | inhibitor.cpp
4 | )
5 |
6 | qt_add_qml_module(quickshell-wayland-shortcuts-inhibit
7 | URI Quickshell.Wayland._ShortcutsInhibitor
8 | VERSION 0.1
9 | DEPENDENCIES QtQuick
10 | )
11 |
12 | install_qml_module(quickshell-wayland-shortcuts-inhibit)
13 |
14 | qs_add_module_deps_light(quickshell-wayland-shortcuts-inhibit Quickshell)
15 |
16 | wl_proto(wlp-shortcuts-inhibit keyboard-shortcuts-inhibit-unstable-v1 "${WAYLAND_PROTOCOLS}/unstable/keyboard-shortcuts-inhibit")
17 |
18 | target_link_libraries(quickshell-wayland-shortcuts-inhibit PRIVATE
19 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
20 | wlp-shortcuts-inhibit
21 | )
22 |
23 | qs_module_pch(quickshell-wayland-shortcuts-inhibit SET large)
24 |
25 | target_link_libraries(quickshell PRIVATE quickshell-wayland-shortcuts-inhibitplugin)
--------------------------------------------------------------------------------
/src/wayland/hyprland/global_shortcuts/shortcut.cpp:
--------------------------------------------------------------------------------
1 | #include "shortcut.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | namespace qs::hyprland::global_shortcuts::impl {
8 |
9 | GlobalShortcut::GlobalShortcut(::hyprland_global_shortcut_v1* shortcut) { this->init(shortcut); }
10 |
11 | GlobalShortcut::~GlobalShortcut() {
12 | if (this->isInitialized()) {
13 | this->destroy();
14 | }
15 | }
16 |
17 | void GlobalShortcut::hyprland_global_shortcut_v1_pressed(
18 | quint32 /*unused*/,
19 | quint32 /*unused*/,
20 | quint32 /*unused*/
21 | ) {
22 | emit this->pressed();
23 | }
24 |
25 | void GlobalShortcut::hyprland_global_shortcut_v1_released(
26 | quint32 /*unused*/,
27 | quint32 /*unused*/,
28 | quint32 /*unused*/
29 | ) {
30 | emit this->released();
31 | }
32 |
33 | } // namespace qs::hyprland::global_shortcuts::impl
34 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/test/manual/workspaces.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import Quickshell
4 | import Quickshell.Widgets
5 | import Quickshell.Hyprland
6 |
7 | FloatingWindow {
8 | ListView {
9 | anchors.fill: parent
10 | model: Hyprland.workspaces
11 | spacing: 5
12 |
13 | delegate: WrapperRectangle {
14 | id: wsDelegate
15 | required property HyprlandWorkspace modelData
16 | color: "lightgray"
17 |
18 | ColumnLayout {
19 | Text { text: `Workspace ${wsDelegate.modelData.id} on ${wsDelegate.modelData.monitor} | urgent: ${wsDelegate.modelData.urgent}`}
20 |
21 | ColumnLayout {
22 | Repeater {
23 | model: wsDelegate.modelData.toplevels
24 | Text {
25 | id: tDelegate
26 | required property HyprlandToplevel modelData;
27 | text: `${tDelegate.modelData}: ${tDelegate.modelData.title}`
28 | }
29 | }
30 | }
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/image_copy_capture/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-screencopy-icc STATIC
2 | image_copy_capture.cpp
3 | )
4 |
5 | wl_proto(wlp-ext-foreign-toplevel ext-foreign-toplevel-list-v1 "${WAYLAND_PROTOCOLS}/staging/ext-foreign-toplevel-list")
6 | wl_proto(wlp-image-copy-capture ext-image-copy-capture-v1 "${WAYLAND_PROTOCOLS}/staging/ext-image-copy-capture")
7 | wl_proto(wlp-image-capture-source ext-image-capture-source-v1 "${WAYLAND_PROTOCOLS}/staging/ext-image-capture-source")
8 |
9 | target_link_libraries(quickshell-wayland-screencopy-icc PRIVATE
10 | Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
11 | Qt::Quick # for pch
12 | )
13 |
14 | target_link_libraries(quickshell-wayland-screencopy-icc PUBLIC
15 | wlp-image-copy-capture wlp-image-capture-source
16 | wlp-ext-foreign-toplevel # required for capture source to build
17 | )
18 |
19 | qs_pch(quickshell-wayland-screencopy-icc SET large)
20 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = {
3 | nixpkgs.url = "nixpkgs/nixos-unstable";
4 | };
5 |
6 | outputs = { self, nixpkgs }: let
7 | overlayPkgs = p: p.appendOverlays [ self.overlays.default ];
8 |
9 | forEachSystem = fn:
10 | nixpkgs.lib.genAttrs
11 | nixpkgs.lib.platforms.linux
12 | (system: fn system (overlayPkgs nixpkgs.legacyPackages.${system}));
13 | in {
14 | overlays.default = import ./overlay.nix {
15 | rev = self.rev or self.dirtyRev;
16 | };
17 |
18 | packages = forEachSystem (system: pkgs: rec {
19 | quickshell = pkgs.quickshell;
20 | default = quickshell;
21 | });
22 |
23 | devShells = forEachSystem (system: pkgs: rec {
24 | default = import ./shell.nix {
25 | inherit pkgs;
26 | quickshell = self.packages.${system}.quickshell.override {
27 | stdenv = pkgs.clangStdenv;
28 | };
29 | };
30 | });
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/src/core/desktopentrymonitor.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class DesktopEntryMonitor: public QObject {
9 | Q_OBJECT
10 |
11 | public:
12 | explicit DesktopEntryMonitor(QObject* parent = nullptr);
13 | ~DesktopEntryMonitor() override = default;
14 | DesktopEntryMonitor(const DesktopEntryMonitor&) = delete;
15 | DesktopEntryMonitor& operator=(const DesktopEntryMonitor&) = delete;
16 | DesktopEntryMonitor(DesktopEntryMonitor&&) = delete;
17 | DesktopEntryMonitor& operator=(DesktopEntryMonitor&&) = delete;
18 |
19 | signals:
20 | void desktopEntriesChanged();
21 |
22 | private slots:
23 | void onDirectoryChanged(const QString& path);
24 | void processChanges();
25 |
26 | private:
27 | void startMonitoring();
28 | void scanAndWatch(const QString& dirPath);
29 |
30 | QFileSystemWatcher watcher;
31 | QTimer debounceTimer;
32 | };
33 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/test/manual/toplevel-association.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import Quickshell
4 | import Quickshell.Hyprland
5 | import Quickshell.Wayland
6 |
7 | FloatingWindow {
8 | ColumnLayout {
9 | anchors.fill: parent
10 |
11 | Text { text: "Hyprland -> Wayland" }
12 |
13 | ListView {
14 | Layout.fillWidth: true
15 | Layout.fillHeight: true
16 | clip: true
17 | model: Hyprland.toplevels
18 | delegate: Text {
19 | required property HyprlandToplevel modelData
20 | text: `${modelData} -> ${modelData.wayland}`
21 | }
22 | }
23 |
24 | Text { text: "Wayland -> Hyprland" }
25 |
26 | ListView {
27 | Layout.fillWidth: true
28 | Layout.fillHeight: true
29 | clip: true
30 | model: ToplevelManager.toplevels
31 | delegate: Text {
32 | required property Toplevel modelData
33 | text: `${modelData} -> ${modelData.HyprlandToplevel.handle}`
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/test/manual/toplevels.qml:
--------------------------------------------------------------------------------
1 | import QtQuick
2 | import QtQuick.Layouts
3 | import Quickshell
4 | import Quickshell.Hyprland
5 |
6 | FloatingWindow {
7 | ColumnLayout {
8 | anchors.fill: parent
9 |
10 | Text { text: "Current toplevel:" }
11 |
12 | ToplevelFromHyprland {
13 | modelData: Hyprland.activeToplevel
14 | }
15 |
16 | Text { text: "\nAll toplevels:" }
17 |
18 | ListView {
19 | Layout.fillHeight: true
20 | Layout.fillWidth: true
21 | clip: true
22 | model: Hyprland.toplevels
23 | delegate: ToplevelFromHyprland {}
24 | }
25 | }
26 |
27 | component ToplevelFromHyprland: ColumnLayout {
28 | required property HyprlandToplevel modelData
29 |
30 | Text {
31 | text: `Window 0x${modelData.address}, title: ${modelData.title}, activated: ${modelData.activated}, workspace id: ${modelData.workspace.id}, monitor name: ${modelData.monitor.name}, urgent: ${modelData.urgent}`
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/window/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-window STATIC
2 | proxywindow.cpp
3 | windowinterface.cpp
4 | panelinterface.cpp
5 | floatingwindow.cpp
6 | popupwindow.cpp
7 | )
8 |
9 | qt_add_qml_module(quickshell-window
10 | URI Quickshell._Window
11 | VERSION 0.1
12 | DEPENDENCIES QtQuick
13 | )
14 |
15 | qs_add_module_deps_light(quickshell-window Quickshell)
16 |
17 | install_qml_module(quickshell-window)
18 |
19 | add_library(quickshell-window-init OBJECT init.cpp)
20 |
21 | target_link_libraries(quickshell-window PRIVATE
22 | Qt::Core Qt::Gui Qt::Quick Qt6::QuickPrivate
23 | )
24 |
25 | qs_add_link_dependencies(quickshell-window quickshell-debug)
26 |
27 | target_link_libraries(quickshell-window-init PRIVATE Qt::Qml)
28 |
29 | qs_module_pch(quickshell-window SET large)
30 |
31 | target_link_libraries(quickshell PRIVATE quickshell-windowplugin quickshell-window-init)
32 |
33 | if (BUILD_TESTING)
34 | add_subdirectory(test)
35 | endif()
36 |
--------------------------------------------------------------------------------
/src/core/types.cpp:
--------------------------------------------------------------------------------
1 | #include "types.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | QRect Box::qrect() const { return {this->x, this->y, this->w, this->h}; }
9 |
10 | bool Box::operator==(const Box& other) const {
11 | return this->x == other.x && this->y == other.y && this->w == other.w && this->h == other.h;
12 | }
13 |
14 | QDebug operator<<(QDebug debug, const Box& box) {
15 | auto saver = QDebugStateSaver(debug);
16 | debug.nospace() << "Box(" << box.x << ',' << box.y << ' ' << box.w << 'x' << box.h << ')';
17 | return debug;
18 | }
19 |
20 | Qt::Edges Edges::toQt(Edges::Flags edges) { return Qt::Edges(edges.toInt()); }
21 |
22 | bool Edges::isOpposing(Edges::Flags edges) {
23 | return edges.testFlags(Edges::Top | Edges::Bottom) || edges.testFlags(Edges::Left | Edges::Right);
24 | }
25 |
26 | QMargins Margins::qmargins() const { return {this->left, this->top, this->right, this->bottom}; }
27 |
--------------------------------------------------------------------------------
/src/services/pam/subprocess.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include // NOLINT std::cout
4 |
5 | #include
6 |
7 | #include "ipc.hpp"
8 |
9 | // endls are intentional as it makes debugging much easier when the buffer actually flushes.
10 | // NOLINTBEGIN
11 | #define logIf(log) \
12 | if (log) std::cout << "quickshell.service.pam.subprocess: "
13 | // NOLINTEND
14 |
15 | class PamSubprocess {
16 | public:
17 | explicit PamSubprocess(bool log, int fdIn, int fdOut): log(log), pipes(fdIn, fdOut) {}
18 | PamIpcExitCode exec(const char* configDir, const char* config, const char* user);
19 | void sendCode(PamIpcExitCode code);
20 |
21 | private:
22 | static int conversation(
23 | int msgCount,
24 | const pam_message** msgArray,
25 | pam_response** responseArray,
26 | void* appdata
27 | );
28 |
29 | bool log;
30 | PamIpcPipes pipes;
31 | };
32 |
--------------------------------------------------------------------------------
/src/wayland/toplevel_management/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-toplevel-management STATIC
2 | manager.cpp
3 | handle.cpp
4 | qml.cpp
5 | )
6 |
7 | qt_add_qml_module(quickshell-wayland-toplevel-management
8 | URI Quickshell.Wayland._ToplevelManagement
9 | VERSION 0.1
10 | DEPENDENCIES QtQml
11 | )
12 |
13 | qs_add_module_deps_light(quickshell-wayland-toplevel-management
14 | Quickshell Quickshell.Wayland
15 | )
16 |
17 | install_qml_module(quickshell-wayland-toplevel-management)
18 |
19 | wl_proto(wlp-foreign-toplevel wlr-foreign-toplevel-management-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
20 |
21 | target_link_libraries(quickshell-wayland-toplevel-management PRIVATE
22 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
23 | wlp-foreign-toplevel
24 | )
25 |
26 | qs_module_pch(quickshell-wayland-toplevel-management SET large)
27 |
28 | target_link_libraries(quickshell PRIVATE quickshell-wayland-toplevel-managementplugin)
29 |
--------------------------------------------------------------------------------
/src/dbus/objectmanager.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "dbus_objectmanager_types.hpp"
9 |
10 | class DBusObjectManagerInterface;
11 |
12 | namespace qs::dbus {
13 |
14 | class DBusObjectManager: public QObject {
15 | Q_OBJECT;
16 |
17 | public:
18 | explicit DBusObjectManager(QObject* parent = nullptr);
19 |
20 | bool setInterface(
21 | const QString& service,
22 | const QString& path,
23 | const QDBusConnection& connection = QDBusConnection::sessionBus()
24 | );
25 |
26 | signals:
27 | void
28 | interfacesAdded(const QDBusObjectPath& objectPath, const DBusObjectManagerInterfaces& interfaces);
29 | void interfacesRemoved(const QDBusObjectPath& objectPath, const QStringList& interfaces);
30 |
31 | private:
32 | void fetchInitialObjects();
33 |
34 | DBusObjectManagerInterface* mInterface = nullptr;
35 | };
36 |
37 | } // namespace qs::dbus
--------------------------------------------------------------------------------
/src/wayland/hyprland/surface/surface.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | namespace qs::hyprland::surface::impl {
14 |
15 | class HyprlandSurface: public QtWayland::hyprland_surface_v1 {
16 | public:
17 | explicit HyprlandSurface(::hyprland_surface_v1* surface, QtWaylandClient::QWaylandWindow* backer);
18 | ~HyprlandSurface() override;
19 | Q_DISABLE_COPY_MOVE(HyprlandSurface);
20 |
21 | [[nodiscard]] bool surfaceEq(wl_surface* surface) const;
22 |
23 | void setOpacity(qreal opacity);
24 | void setVisibleRegion(const QRegion& region);
25 |
26 | private:
27 | wl_surface* backerSurface = nullptr;
28 | };
29 |
30 | } // namespace qs::hyprland::surface::impl
31 |
--------------------------------------------------------------------------------
/src/services/status_notifier/org.kde.StatusNotifierWatcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/global_shortcuts/shortcut.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace qs::hyprland::global_shortcuts::impl {
10 |
11 | class GlobalShortcut
12 | : public QObject
13 | , public QtWayland::hyprland_global_shortcut_v1 {
14 | Q_OBJECT;
15 |
16 | public:
17 | explicit GlobalShortcut(::hyprland_global_shortcut_v1* shortcut);
18 | ~GlobalShortcut() override;
19 | Q_DISABLE_COPY_MOVE(GlobalShortcut);
20 |
21 | signals:
22 | void pressed();
23 | void released();
24 |
25 | private:
26 | // clang-format off
27 | void hyprland_global_shortcut_v1_pressed(quint32 tvSecHi, quint32 tvSecLo, quint32 tvNsec) override;
28 | void hyprland_global_shortcut_v1_released(quint32 tvSecHi, quint32 tvSecLo, quint32 tvNsec) override;
29 | // clang-format on
30 | };
31 |
32 | } // namespace qs::hyprland::global_shortcuts::impl
33 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 | on: [push, pull_request, workflow_dispatch]
3 |
4 | jobs:
5 | lint:
6 | name: Lint
7 | runs-on: ubuntu-latest
8 | permissions:
9 | contents: read
10 | id-token: write
11 | steps:
12 | - uses: actions/checkout@v4
13 | # Use cachix action over detsys for testing with act.
14 | # - uses: cachix/install-nix-action@v27
15 | - uses: DeterminateSystems/nix-installer-action@main
16 | - uses: DeterminateSystems/magic-nix-cache-action@main
17 | with:
18 | use-flakehub: false
19 | - uses: nicknovitski/nix-develop@v1
20 |
21 | - name: Check formatting
22 | run: clang-format -Werror --dry-run src/**/*.{cpp,hpp}
23 |
24 | # required for lint
25 | - name: Build
26 | run: |
27 | just configure debug -DNO_PCH=ON -DBUILD_TESTING=ON
28 | just build
29 |
30 | - name: Run lints
31 | run: LC_ALL=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 just lint-ci
32 |
--------------------------------------------------------------------------------
/src/io/processcore.cpp:
--------------------------------------------------------------------------------
1 | #include "processcore.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "../core/common.hpp"
9 |
10 | namespace qs::io::process {
11 |
12 | void setupProcessEnvironment(
13 | QProcess* process,
14 | bool clear,
15 | const QHash& envChanges
16 | ) {
17 | const auto& sysenv = qs::Common::INITIAL_ENVIRONMENT;
18 | auto env = clear ? QProcessEnvironment() : sysenv;
19 |
20 | for (auto& name: envChanges.keys()) {
21 | auto value = envChanges.value(name);
22 | if (!value.isValid()) continue;
23 |
24 | if (clear) {
25 | if (value.isNull()) {
26 | if (sysenv.contains(name)) env.insert(name, sysenv.value(name));
27 | } else env.insert(name, value.toString());
28 | } else {
29 | if (value.isNull()) env.remove(name);
30 | else env.insert(name, value.toString());
31 | }
32 | }
33 |
34 | process->setProcessEnvironment(env);
35 | }
36 |
37 | } // namespace qs::io::process
38 |
--------------------------------------------------------------------------------
/src/services/notifications/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_dbus_adaptor(DBUS_INTERFACES
2 | org.freedesktop.Notifications.xml
3 | server.hpp
4 | qs::service::notifications::NotificationServer
5 | dbus_notifications
6 | DBusNotificationServer
7 | )
8 |
9 | qt_add_library(quickshell-service-notifications STATIC
10 | server.cpp
11 | notification.cpp
12 | dbusimage.cpp
13 | qml.cpp
14 | ${DBUS_INTERFACES}
15 | )
16 |
17 | # dbus headers
18 | target_include_directories(quickshell-service-notifications PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
19 |
20 | qt_add_qml_module(quickshell-service-notifications
21 | URI Quickshell.Services.Notifications
22 | VERSION 0.1
23 | )
24 |
25 | qs_add_module_deps_light(quickshell-service-notifications Quickshell)
26 | install_qml_module(quickshell-service-notifications)
27 |
28 | target_link_libraries(quickshell-service-notifications PRIVATE Qt::Quick Qt::DBus)
29 | target_link_libraries(quickshell PRIVATE quickshell-service-notificationsplugin)
30 |
31 | qs_module_pch(quickshell-service-notifications SET dbus)
32 |
--------------------------------------------------------------------------------
/src/services/polkit/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(PkgConfig REQUIRED)
2 | pkg_check_modules(glib REQUIRED IMPORTED_TARGET glib-2.0>=2.36)
3 | pkg_check_modules(gobject REQUIRED IMPORTED_TARGET gobject-2.0)
4 | pkg_check_modules(polkit_agent REQUIRED IMPORTED_TARGET polkit-agent-1)
5 | pkg_check_modules(polkit REQUIRED IMPORTED_TARGET polkit-gobject-1)
6 |
7 | qt_add_library(quickshell-service-polkit STATIC
8 | agentimpl.cpp
9 | flow.cpp
10 | identity.cpp
11 | listener.cpp
12 | session.cpp
13 | qml.cpp
14 | )
15 |
16 | qt_add_qml_module(quickshell-service-polkit
17 | URI Quickshell.Services.Polkit
18 | VERSION 0.1
19 | DEPENDENCIES QtQml
20 | )
21 |
22 | install_qml_module(quickshell-service-polkit)
23 |
24 | target_link_libraries(quickshell-service-polkit PRIVATE
25 | Qt::Qml
26 | Qt::Quick
27 | PkgConfig::glib
28 | PkgConfig::gobject
29 | PkgConfig::polkit_agent
30 | PkgConfig::polkit
31 | )
32 |
33 | qs_module_pch(quickshell-service-polkit)
34 |
35 | target_link_libraries(quickshell PRIVATE quickshell-service-polkitplugin)
36 |
--------------------------------------------------------------------------------
/src/wayland/wlr_layershell/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-wayland-layershell STATIC
2 | wlr_layershell.cpp
3 | shell_integration.cpp
4 | surface.cpp
5 | )
6 |
7 | qt_add_qml_module(quickshell-wayland-layershell
8 | URI Quickshell.Wayland._WlrLayerShell
9 | VERSION 0.1
10 | DEPENDENCIES QtQuick
11 | )
12 |
13 | qs_add_module_deps_light(quickshell-wayland-layershell Quickshell Quickshell.Wayland)
14 |
15 | install_qml_module(quickshell-wayland-layershell)
16 |
17 | wl_proto(wlp-layer-shell wlr-layer-shell-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
18 |
19 | # link dependency of wlr-layer-shell's codegen
20 | wl_proto(wlp-xdg-shell xdg-shell "${WAYLAND_PROTOCOLS}/stable/xdg-shell")
21 |
22 | target_link_libraries(quickshell-wayland-layershell PRIVATE
23 | Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
24 | wlp-layer-shell wlp-xdg-shell
25 | )
26 |
27 | qs_module_pch(quickshell-wayland-layershell SET large)
28 |
29 | target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-layershellplugin)
30 |
--------------------------------------------------------------------------------
/src/services/pam/ipc.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | enum class PamIpcEvent : uint8_t {
10 | Request,
11 | Exit,
12 | };
13 |
14 | enum class PamIpcExitCode : uint8_t {
15 | Success,
16 | StartFailed,
17 | AuthFailed,
18 | MaxTries,
19 | PamError,
20 | OtherError,
21 | };
22 |
23 | struct PamIpcRequestFlags {
24 | bool echo;
25 | bool error;
26 | bool responseRequired;
27 | };
28 |
29 | class PamIpcPipes {
30 | public:
31 | explicit PamIpcPipes() = default;
32 | explicit PamIpcPipes(int fdIn, int fdOut): fdIn(fdIn), fdOut(fdOut) {}
33 | ~PamIpcPipes();
34 | Q_DISABLE_COPY_MOVE(PamIpcPipes);
35 |
36 | [[nodiscard]] bool readBytes(char* buffer, size_t length) const;
37 | [[nodiscard]] bool writeBytes(const char* buffer, size_t length) const;
38 | [[nodiscard]] std::string readString(bool* ok) const;
39 | [[nodiscard]] bool writeString(const std::string& string) const;
40 |
41 | int fdIn = 0;
42 | int fdOut = 0;
43 | };
44 |
--------------------------------------------------------------------------------
/src/dbus/dbusmenu/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set_source_files_properties(com.canonical.dbusmenu.xml PROPERTIES
2 | CLASSNAME DBusMenuInterface
3 | INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/dbus_menu_types.hpp
4 | )
5 |
6 | qt_add_dbus_interface(DBUS_INTERFACES
7 | com.canonical.dbusmenu.xml
8 | dbus_menu
9 | )
10 |
11 | qt_add_library(quickshell-dbusmenu STATIC
12 | dbus_menu_types.cpp
13 | dbusmenu.cpp
14 | ${DBUS_INTERFACES}
15 | )
16 |
17 | qt_add_qml_module(quickshell-dbusmenu
18 | URI Quickshell.DBusMenu
19 | VERSION 0.1
20 | DEPENDENCIES QtQml
21 | )
22 |
23 | qs_add_module_deps_light(quickshell-dbusmenu Quickshell)
24 |
25 | install_qml_module(quickshell-dbusmenu)
26 |
27 | # dbus headers
28 | target_include_directories(quickshell-dbusmenu PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
29 |
30 | target_link_libraries(quickshell-dbusmenu PRIVATE Qt::Quick Qt::DBus)
31 | qs_add_link_dependencies(quickshell-dbusmenu quickshell-dbus)
32 |
33 | qs_module_pch(quickshell-dbusmenu SET dbus)
34 |
35 | target_link_libraries(quickshell PRIVATE quickshell-dbusmenuplugin)
36 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/global_shortcuts/manager.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "shortcut.hpp"
10 |
11 | namespace qs::hyprland::global_shortcuts::impl {
12 |
13 | class GlobalShortcutManager
14 | : public QWaylandClientExtensionTemplate
15 | , public QtWayland::hyprland_global_shortcuts_manager_v1 {
16 | public:
17 | explicit GlobalShortcutManager();
18 |
19 | GlobalShortcut* registerShortcut(
20 | const QString& appid,
21 | const QString& name,
22 | const QString& description,
23 | const QString& triggerDescription
24 | );
25 |
26 | void unregisterShortcut(const QString& appid, const QString& name);
27 |
28 | static GlobalShortcutManager* instance();
29 |
30 | private:
31 | QHash, QPair> shortcuts;
32 | };
33 |
34 | } // namespace qs::hyprland::global_shortcuts::impl
35 |
--------------------------------------------------------------------------------
/src/ui/reload_popup.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "../core/generation.hpp"
10 |
11 | namespace qs::ui {
12 |
13 | class ReloadPopup: public QObject {
14 | Q_OBJECT;
15 | QML_NAMED_ELEMENT(ReloadPopupInfo);
16 | QML_UNCREATABLE("")
17 | Q_PROPERTY(QString instanceId MEMBER instanceId CONSTANT);
18 | Q_PROPERTY(bool failed MEMBER failed CONSTANT);
19 | Q_PROPERTY(QString errorString MEMBER errorString CONSTANT);
20 |
21 | public:
22 | Q_INVOKABLE void closed();
23 |
24 | static void spawnPopup(QString instanceId, bool failed, QString errorString);
25 |
26 | private:
27 | ReloadPopup(QString instanceId, bool failed, QString errorString);
28 |
29 | EngineGeneration* generation;
30 | QObject* popup = nullptr;
31 | QString instanceId;
32 | bool failed = false;
33 | bool deleting = false;
34 | QString errorString;
35 |
36 | static ReloadPopup* activePopup;
37 | };
38 |
39 | } // namespace qs::ui
40 |
--------------------------------------------------------------------------------
/src/core/plugin.cpp:
--------------------------------------------------------------------------------
1 | #include "plugin.hpp"
2 | #include
3 |
4 | #include // NOLINT (what??)
5 |
6 | #include "generation.hpp"
7 |
8 | static QVector plugins; // NOLINT
9 |
10 | void QsEnginePlugin::registerPlugin(QsEnginePlugin& plugin) { plugins.push_back(&plugin); }
11 |
12 | void QsEnginePlugin::initPlugins() {
13 | plugins.removeIf([](QsEnginePlugin* plugin) { return !plugin->applies(); });
14 |
15 | std::ranges::sort(plugins, [](QsEnginePlugin* a, QsEnginePlugin* b) {
16 | return b->dependencies().contains(a->name());
17 | });
18 |
19 | for (QsEnginePlugin* plugin: plugins) {
20 | plugin->init();
21 | }
22 |
23 | for (QsEnginePlugin* plugin: plugins) {
24 | plugin->registerTypes();
25 | }
26 | }
27 |
28 | void QsEnginePlugin::runConstructGeneration(EngineGeneration& generation) {
29 | for (QsEnginePlugin* plugin: plugins) {
30 | plugin->constructGeneration(generation);
31 | }
32 | }
33 |
34 | void QsEnginePlugin::runOnReload() {
35 | for (QsEnginePlugin* plugin: plugins) {
36 | plugin->onReload();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/wayland/idle_inhibit/proto.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
9 |
10 | namespace qs::wayland::idle_inhibit::impl {
11 |
12 | class IdleInhibitor;
13 |
14 | class IdleInhibitManager
15 | : public QWaylandClientExtensionTemplate
16 | , public QtWayland::zwp_idle_inhibit_manager_v1 {
17 | public:
18 | explicit IdleInhibitManager();
19 |
20 | IdleInhibitor* createIdleInhibitor(QtWaylandClient::QWaylandWindow* surface);
21 |
22 | static IdleInhibitManager* instance();
23 | };
24 |
25 | class IdleInhibitor: public QtWayland::zwp_idle_inhibitor_v1 {
26 | public:
27 | explicit IdleInhibitor(::zwp_idle_inhibitor_v1* inhibitor)
28 | : QtWayland::zwp_idle_inhibitor_v1(inhibitor) {}
29 |
30 | ~IdleInhibitor() override;
31 | Q_DISABLE_COPY_MOVE(IdleInhibitor);
32 | };
33 |
34 | } // namespace qs::wayland::idle_inhibit::impl
35 |
--------------------------------------------------------------------------------
/src/core/instanceinfo.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | struct InstanceInfo {
9 | QString instanceId;
10 | QString configPath;
11 | QString shellId;
12 | QDateTime launchTime;
13 | pid_t pid = -1;
14 | QString display;
15 |
16 | static InstanceInfo CURRENT; // NOLINT
17 | };
18 |
19 | struct RelaunchInfo {
20 | InstanceInfo instance;
21 | bool noColor = false;
22 | bool timestamp = false;
23 | bool sparseLogsOnly = false;
24 | QtMsgType defaultLogLevel = QtWarningMsg;
25 | QString logRules;
26 | };
27 |
28 | QDataStream& operator<<(QDataStream& stream, const InstanceInfo& info);
29 | QDataStream& operator>>(QDataStream& stream, InstanceInfo& info);
30 |
31 | QDataStream& operator<<(QDataStream& stream, const RelaunchInfo& info);
32 | QDataStream& operator>>(QDataStream& stream, RelaunchInfo& info);
33 |
34 | namespace qs::crash {
35 |
36 | struct CrashInfo {
37 | int logFd = -1;
38 |
39 | static CrashInfo INSTANCE; // NOLINT
40 | };
41 |
42 | } // namespace qs::crash
43 |
--------------------------------------------------------------------------------
/cmake/util.cmake:
--------------------------------------------------------------------------------
1 | # Adds a dependency hint to the link order, but does not block build on the dependency.
2 | function (qs_add_link_dependencies target)
3 | set_property(
4 | TARGET ${target}
5 | APPEND PROPERTY INTERFACE_LINK_LIBRARIES
6 | ${ARGN}
7 | )
8 | endfunction()
9 |
10 | function (qs_append_qmldir target text)
11 | get_property(qmldir_content TARGET ${target} PROPERTY _qt_internal_qmldir_content)
12 |
13 | if ("${qmldir_content}" STREQUAL "")
14 | message(WARNING "qs_append_qmldir depends on private Qt cmake code, which has broken.")
15 | return()
16 | endif()
17 |
18 | set_property(TARGET ${target} APPEND_STRING PROPERTY _qt_internal_qmldir_content ${text})
19 | endfunction()
20 |
21 | # DEPENDENCIES introduces a cmake dependency which we don't need with static modules.
22 | # This greatly improves comp speed by not introducing those dependencies.
23 | function (qs_add_module_deps_light target)
24 | foreach (dep IN LISTS ARGN)
25 | string(APPEND qmldir_extra "depends ${dep}\n")
26 | endforeach()
27 |
28 | qs_append_qmldir(${target} "${qmldir_extra}")
29 | endfunction()
30 |
--------------------------------------------------------------------------------
/src/dbus/org.freedesktop.DBus.Properties.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/ipc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-hyprland-ipc STATIC
2 | connection.cpp
3 | monitor.cpp
4 | workspace.cpp
5 | qml.cpp
6 | )
7 |
8 | qt_add_qml_module(quickshell-hyprland-ipc
9 | URI Quickshell.Hyprland._Ipc
10 | VERSION 0.1
11 | DEPENDENCIES QtQuick
12 | )
13 |
14 | qs_add_module_deps_light(quickshell-hyprland-ipc Quickshell)
15 |
16 | install_qml_module(quickshell-hyprland-ipc)
17 |
18 | target_link_libraries(quickshell-hyprland-ipc PRIVATE Qt::Quick)
19 |
20 | if (WAYLAND_TOPLEVEL_MANAGEMENT)
21 | target_sources(quickshell-hyprland-ipc PRIVATE
22 | toplevel_mapping.cpp
23 | hyprland_toplevel.cpp
24 | )
25 |
26 | wl_proto(wlp-hyprland-toplevel-mapping hyprland-toplevel-mapping-v1 "${CMAKE_CURRENT_SOURCE_DIR}")
27 |
28 | target_link_libraries(quickshell-hyprland-ipc PRIVATE
29 | Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
30 | wlp-hyprland-toplevel-mapping
31 | wlp-foreign-toplevel
32 | )
33 | endif()
34 |
35 | qs_module_pch(quickshell-hyprland-ipc SET large)
36 |
37 | target_link_libraries(quickshell PRIVATE quickshell-hyprland-ipcplugin)
38 |
--------------------------------------------------------------------------------
/src/core/easingcurve.cpp:
--------------------------------------------------------------------------------
1 | #include "easingcurve.hpp"
2 | #include
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | qreal EasingCurve::valueAt(qreal x) const { return this->mCurve.valueForProgress(x); }
11 |
12 | qreal EasingCurve::interpolate(qreal x, qreal a, qreal b) const {
13 | return a + (b - a) * this->valueAt(x);
14 | }
15 |
16 | QPointF EasingCurve::interpolate(qreal x, const QPointF& a, const QPointF& b) const {
17 | return QPointF(this->interpolate(x, a.x(), b.x()), this->interpolate(x, a.y(), b.y()));
18 | }
19 |
20 | QRectF EasingCurve::interpolate(qreal x, const QRectF& a, const QRectF& b) const {
21 | return QRectF(
22 | this->interpolate(x, a.topLeft(), b.topLeft()),
23 | this->interpolate(x, a.bottomRight(), b.bottomRight())
24 | );
25 | }
26 |
27 | QEasingCurve EasingCurve::curve() const { return this->mCurve; }
28 |
29 | void EasingCurve::setCurve(QEasingCurve curve) {
30 | if (this->mCurve == curve) return;
31 | this->mCurve = std::move(curve);
32 | emit this->curveChanged();
33 | }
34 |
--------------------------------------------------------------------------------
/src/wayland/screencopy/image_copy_capture/image_copy_capture.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "../manager.hpp"
9 |
10 | namespace qs::wayland::screencopy::icc {
11 |
12 | class IccManager
13 | : public QWaylandClientExtensionTemplate
14 | , public QtWayland::ext_image_copy_capture_manager_v1 {
15 | public:
16 | ScreencopyContext* createSession(::ext_image_capture_source_v1* source, bool paintCursors);
17 |
18 | static IccManager* instance();
19 |
20 | private:
21 | explicit IccManager();
22 | };
23 |
24 | class IccOutputSourceManager
25 | : public QWaylandClientExtensionTemplate
26 | , public QtWayland::ext_output_image_capture_source_manager_v1 {
27 | public:
28 | ScreencopyContext* captureOutput(QScreen* screen, bool paintCursors);
29 |
30 | static IccOutputSourceManager* instance();
31 |
32 | private:
33 | explicit IccOutputSourceManager();
34 | };
35 |
36 | } // namespace qs::wayland::screencopy::icc
37 |
--------------------------------------------------------------------------------
/src/bluetooth/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set_source_files_properties(org.bluez.Adapter.xml PROPERTIES
2 | CLASSNAME DBusBluezAdapterInterface
3 | )
4 |
5 | set_source_files_properties(org.bluez.Device.xml PROPERTIES
6 | CLASSNAME DBusBluezDeviceInterface
7 | )
8 |
9 | qt_add_dbus_interface(DBUS_INTERFACES
10 | org.bluez.Adapter.xml
11 | dbus_adapter
12 | )
13 |
14 | qt_add_dbus_interface(DBUS_INTERFACES
15 | org.bluez.Device.xml
16 | dbus_device
17 | )
18 |
19 | qt_add_library(quickshell-bluetooth STATIC
20 | adapter.cpp
21 | bluez.cpp
22 | device.cpp
23 | ${DBUS_INTERFACES}
24 | )
25 |
26 | qt_add_qml_module(quickshell-bluetooth
27 | URI Quickshell.Bluetooth
28 | VERSION 0.1
29 | DEPENDENCIES QtQml
30 | )
31 |
32 | install_qml_module(quickshell-bluetooth)
33 |
34 | # dbus headers
35 | target_include_directories(quickshell-bluetooth PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
36 |
37 | target_link_libraries(quickshell-bluetooth PRIVATE Qt::Qml Qt::DBus)
38 | qs_add_link_dependencies(quickshell-bluetooth quickshell-dbus)
39 |
40 | qs_module_pch(quickshell-bluetooth SET dbus)
41 |
42 | target_link_libraries(quickshell PRIVATE quickshell-bluetoothplugin)
43 |
--------------------------------------------------------------------------------
/src/wayland/hyprland/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt_add_library(quickshell-hyprland STATIC)
2 |
3 | target_link_libraries(quickshell-hyprland PRIVATE ${QT_DEPS})
4 |
5 | set(HYPRLAND_MODULES)
6 |
7 | if (HYPRLAND_IPC)
8 | add_subdirectory(ipc)
9 | list(APPEND HYPRLAND_MODULES Quickshell.Hyprland._Ipc)
10 | endif()
11 |
12 | if (HYPRLAND_FOCUS_GRAB)
13 | add_subdirectory(focus_grab)
14 | list(APPEND HYPRLAND_MODULES Quickshell.Hyprland._FocusGrab)
15 | endif()
16 |
17 | if (HYPRLAND_GLOBAL_SHORTCUTS)
18 | add_subdirectory(global_shortcuts)
19 | list(APPEND HYPRLAND_MODULES Quickshell.Hyprland._GlobalShortcuts)
20 | endif()
21 |
22 | if (HYPRLAND_SURFACE_EXTENSIONS)
23 | add_subdirectory(surface)
24 | list(APPEND HYPRLAND_MODULES Quickshell.Hyprland._SurfaceExtensions)
25 | endif()
26 |
27 | qt_add_qml_module(quickshell-hyprland
28 | URI Quickshell.Hyprland
29 | VERSION 0.1
30 | IMPORTS ${HYPRLAND_MODULES}
31 | )
32 |
33 | qs_add_module_deps_light(quickshell-io Quickshell)
34 | install_qml_module(quickshell-hyprland)
35 |
36 | # intentionally no pch as the module is empty
37 |
38 | target_link_libraries(quickshell PRIVATE quickshell-hyprlandplugin)
39 |
--------------------------------------------------------------------------------
/src/services/pipewire/metadata.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "core.hpp"
10 | #include "registry.hpp"
11 |
12 | namespace qs::service::pipewire {
13 |
14 | class PwMetadata: public PwBindable {
15 | Q_OBJECT;
16 |
17 | public:
18 | void bindHooks() override;
19 | void unbindHooks() override;
20 | void initProps(const spa_dict* props) override;
21 |
22 | [[nodiscard]] const QString& name() const;
23 | [[nodiscard]] bool hasSetPermission() const;
24 |
25 | // null value clears
26 | void setProperty(const char* key, const char* type, const char* value);
27 |
28 | signals:
29 | void propertyChanged(const char* key, const char* type, const char* value);
30 |
31 | private:
32 | static const pw_metadata_events EVENTS;
33 | static int
34 | onProperty(void* data, quint32 subject, const char* key, const char* type, const char* value);
35 |
36 | QString mName;
37 |
38 | SpaHook listener;
39 | };
40 |
41 | } // namespace qs::service::pipewire
42 |
--------------------------------------------------------------------------------
/src/wayland/session_lock/lock.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include