forked from quickshell/quickshell
		
	hyprland/global_shortcuts: add GlobalShortcut
This commit is contained in:
		
							parent
							
								
									87a884ca36
								
							
						
					
					
						commit
						bba8cb8a7d
					
				
					 14 changed files with 569 additions and 6 deletions
				
			
		| 
						 | 
					@ -15,6 +15,8 @@ option(WAYLAND "Enable wayland support" ON)
 | 
				
			||||||
option(WAYLAND_WLR_LAYERSHELL "Support the zwlr_layer_shell_v1 wayland protocol" ON)
 | 
					option(WAYLAND_WLR_LAYERSHELL "Support the zwlr_layer_shell_v1 wayland protocol" ON)
 | 
				
			||||||
option(WAYLAND_SESSION_LOCK "Support the ext_session_lock_v1 wayland protocol" ON)
 | 
					option(WAYLAND_SESSION_LOCK "Support the ext_session_lock_v1 wayland protocol" ON)
 | 
				
			||||||
option(HYPRLAND "Support hyprland specific features" ON)
 | 
					option(HYPRLAND "Support hyprland specific features" ON)
 | 
				
			||||||
 | 
					option(HYPRLAND_GLOBAL_SHORTCUTS "Hyprland Global Shortcuts" ON)
 | 
				
			||||||
 | 
					option(HYPRLAND_FOCUS_GRAB "Hyprland Focus Grabbing" ON)
 | 
				
			||||||
option(SERVICE_STATUS_NOTIFIER "StatusNotifierItem service" ON)
 | 
					option(SERVICE_STATUS_NOTIFIER "StatusNotifierItem service" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message(STATUS "Quickshell configuration")
 | 
					message(STATUS "Quickshell configuration")
 | 
				
			||||||
| 
						 | 
					@ -29,6 +31,10 @@ endif ()
 | 
				
			||||||
message(STATUS "  Services")
 | 
					message(STATUS "  Services")
 | 
				
			||||||
message(STATUS "    StatusNotifier: ${SERVICE_STATUS_NOTIFIER}")
 | 
					message(STATUS "    StatusNotifier: ${SERVICE_STATUS_NOTIFIER}")
 | 
				
			||||||
message(STATUS "  Hyprland: ${HYPRLAND}")
 | 
					message(STATUS "  Hyprland: ${HYPRLAND}")
 | 
				
			||||||
 | 
					if (HYPRLAND)
 | 
				
			||||||
 | 
						message(STATUS "    Focus Grabbing: ${HYPRLAND_FOCUS_GRAB}")
 | 
				
			||||||
 | 
						message(STATUS "    Global Shortcuts: ${HYPRLAND_GLOBAL_SHORTCUTS}")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (NOT DEFINED GIT_REVISION)
 | 
					if (NOT DEFINED GIT_REVISION)
 | 
				
			||||||
	execute_process(
 | 
						execute_process(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1,3 @@
 | 
				
			||||||
add_subdirectory(status_notifier)
 | 
					if (SERVICE_STATUS_NOTIFIER)
 | 
				
			||||||
 | 
						add_subdirectory(status_notifier)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,13 @@
 | 
				
			||||||
qt_add_library(quickshell-hyprland STATIC)
 | 
					qt_add_library(quickshell-hyprland STATIC)
 | 
				
			||||||
qt_add_qml_module(quickshell-hyprland URI Quickshell.Hyprland VERSION 0.1)
 | 
					qt_add_qml_module(quickshell-hyprland URI Quickshell.Hyprland VERSION 0.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(focus_grab)
 | 
					if (HYPRLAND_FOCUS_GRAB)
 | 
				
			||||||
 | 
						add_subdirectory(focus_grab)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (HYPRLAND_GLOBAL_SHORTCUTS)
 | 
				
			||||||
 | 
						add_subdirectory(global_shortcuts)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-hyprland PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-hyprland PRIVATE ${QT_DEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,11 +4,18 @@ qt_add_library(quickshell-hyprland-focus-grab STATIC
 | 
				
			||||||
	qml.cpp
 | 
						qml.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qt_add_qml_module(quickshell-hyprland-focus-grab URI Quickshell.Hyprland._FocusGrab VERSION 0.1)
 | 
					qt_add_qml_module(quickshell-hyprland-focus-grab
 | 
				
			||||||
 | 
						URI Quickshell.Hyprland._FocusGrab
 | 
				
			||||||
 | 
						VERSION 0.1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_library(quickshell-hyprland-focus-grab-init OBJECT init.cpp)
 | 
					add_library(quickshell-hyprland-focus-grab-init OBJECT init.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wl_proto(quickshell-hyprland-focus-grab hyprland-focus-grab-v1 "${CMAKE_CURRENT_SOURCE_DIR}/hyprland-focus-grab-v1.xml")
 | 
					wl_proto(quickshell-hyprland-focus-grab
 | 
				
			||||||
 | 
						hyprland-focus-grab-v1
 | 
				
			||||||
 | 
						"${CMAKE_CURRENT_SOURCE_DIR}/hyprland-focus-grab-v1.xml"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-hyprland-focus-grab PRIVATE ${QT_DEPS} wayland-client)
 | 
					target_link_libraries(quickshell-hyprland-focus-grab PRIVATE ${QT_DEPS} wayland-client)
 | 
				
			||||||
target_link_libraries(quickshell-hyprland-focus-grab-init PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-hyprland-focus-grab-init PRIVATE ${QT_DEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,4 +23,7 @@ qs_pch(quickshell-hyprland-focus-grab)
 | 
				
			||||||
qs_pch(quickshell-hyprland-focus-grabplugin)
 | 
					qs_pch(quickshell-hyprland-focus-grabplugin)
 | 
				
			||||||
qs_pch(quickshell-hyprland-focus-grab-init)
 | 
					qs_pch(quickshell-hyprland-focus-grab-init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-hyprland-focus-grabplugin quickshell-hyprland-focus-grab-init)
 | 
					target_link_libraries(quickshell PRIVATE
 | 
				
			||||||
 | 
						quickshell-hyprland-focus-grabplugin
 | 
				
			||||||
 | 
						quickshell-hyprland-focus-grab-init
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/wayland/hyprland/global_shortcuts/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/wayland/hyprland/global_shortcuts/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					qt_add_library(quickshell-hyprland-global-shortcuts STATIC
 | 
				
			||||||
 | 
						qml.cpp
 | 
				
			||||||
 | 
						manager.cpp
 | 
				
			||||||
 | 
						shortcut.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qt_add_qml_module(quickshell-hyprland-global-shortcuts
 | 
				
			||||||
 | 
						URI Quickshell.Hyprland._GlobalShortcuts
 | 
				
			||||||
 | 
						VERSION 0.1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(quickshell-hyprland-global-shortcuts-init OBJECT init.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wl_proto(quickshell-hyprland-global-shortcuts
 | 
				
			||||||
 | 
						hyprland-global-shortcuts-v1
 | 
				
			||||||
 | 
						"${CMAKE_CURRENT_SOURCE_DIR}/hyprland-global-shortcuts-v1.xml"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-hyprland-global-shortcuts PRIVATE ${QT_DEPS} wayland-client)
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-hyprland-global-shortcuts-init PRIVATE ${QT_DEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland-global-shortcuts)
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland-global-shortcutsplugin)
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland-global-shortcuts-init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell PRIVATE
 | 
				
			||||||
 | 
						quickshell-hyprland-global-shortcutsplugin
 | 
				
			||||||
 | 
						quickshell-hyprland-global-shortcuts-init
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<protocol name="hyprland_global_shortcuts_v1">
 | 
				
			||||||
 | 
					  <copyright>
 | 
				
			||||||
 | 
					    Copyright © 2022 Vaxry
 | 
				
			||||||
 | 
					    All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					    modification, are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    1. Redistributions of source code must retain the above copyright notice, this
 | 
				
			||||||
 | 
					       list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    2. Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					       this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					       and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    3. Neither the name of the copyright holder nor the names of its
 | 
				
			||||||
 | 
					       contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					       this software without specific prior written permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 | 
				
			||||||
 | 
					    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
				
			||||||
 | 
					    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
				
			||||||
 | 
					    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					  </copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <description summary="registering global shortcuts">
 | 
				
			||||||
 | 
					    This protocol allows a client to register triggerable actions,
 | 
				
			||||||
 | 
					    meant to be global shortcuts.
 | 
				
			||||||
 | 
					  </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="hyprland_global_shortcuts_manager_v1" version="1">
 | 
				
			||||||
 | 
					    <description summary="manager to register global shortcuts">
 | 
				
			||||||
 | 
					      This object is a manager which offers requests to create global shortcuts.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="register_shortcut">
 | 
				
			||||||
 | 
					      <description summary="register a shortcut">
 | 
				
			||||||
 | 
					        Register a new global shortcut.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        A global shortcut is anonymous, meaning the app does not know what key(s) trigger it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The shortcut's keybinding shall be dealt with by the compositor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        In the case of a duplicate app_id + id combination, the already_taken protocol error is raised.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="shortcut" type="new_id" interface="hyprland_global_shortcut_v1"/>
 | 
				
			||||||
 | 
					      <arg name="id" type="string" summary="a unique id for the shortcut"/>
 | 
				
			||||||
 | 
					      <arg name="app_id" type="string" summary="the app_id of the application requesting the shortcut"/>
 | 
				
			||||||
 | 
					      <arg name="description" type="string" summary="user-readable text describing what the shortcut does."/>
 | 
				
			||||||
 | 
					      <arg name="trigger_description" type="string" summary="user-readable text describing how to trigger the shortcut for the client to render."/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="destroy the manager">
 | 
				
			||||||
 | 
					        All objects created by the manager will still remain valid, until their
 | 
				
			||||||
 | 
					        appropriate destroy request has been called.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="error">
 | 
				
			||||||
 | 
					      <entry name="already_taken" value="0"
 | 
				
			||||||
 | 
					        summary="the app_id + id combination has already been registered."/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="hyprland_global_shortcut_v1" version="1">
 | 
				
			||||||
 | 
					    <description summary="a shortcut">
 | 
				
			||||||
 | 
					      This object represents a single shortcut.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="pressed">
 | 
				
			||||||
 | 
					      <description summary="keystroke pressed">
 | 
				
			||||||
 | 
					        The keystroke was pressed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tv_ values hold the timestamp of the occurrence.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="tv_sec_hi" type="uint"
 | 
				
			||||||
 | 
					           summary="high 32 bits of the seconds part of the timestamp"/>
 | 
				
			||||||
 | 
					      <arg name="tv_sec_lo" type="uint"
 | 
				
			||||||
 | 
					           summary="low 32 bits of the seconds part of the timestamp"/>
 | 
				
			||||||
 | 
					      <arg name="tv_nsec" type="uint"
 | 
				
			||||||
 | 
					           summary="nanoseconds part of the timestamp"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="released">
 | 
				
			||||||
 | 
					      <description summary="keystroke released">
 | 
				
			||||||
 | 
					        The keystroke was released.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tv_ values hold the timestamp of the occurrence.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="tv_sec_hi" type="uint"
 | 
				
			||||||
 | 
					           summary="high 32 bits of the seconds part of the timestamp"/>
 | 
				
			||||||
 | 
					      <arg name="tv_sec_lo" type="uint"
 | 
				
			||||||
 | 
					           summary="low 32 bits of the seconds part of the timestamp"/>
 | 
				
			||||||
 | 
					      <arg name="tv_nsec" type="uint"
 | 
				
			||||||
 | 
					           summary="nanoseconds part of the timestamp"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="delete this object, used or not">
 | 
				
			||||||
 | 
					        Destroys the shortcut. Can be sent at any time by the client.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					</protocol>
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/wayland/hyprland/global_shortcuts/init.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/wayland/hyprland/global_shortcuts/init.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#include <qqml.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../../../core/plugin.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HyprlandFocusGrabPlugin: public QuickshellPlugin {
 | 
				
			||||||
 | 
						void registerTypes() override {
 | 
				
			||||||
 | 
							qmlRegisterModuleImport(
 | 
				
			||||||
 | 
							    "Quickshell.Hyprland",
 | 
				
			||||||
 | 
							    QQmlModuleImportModuleAny,
 | 
				
			||||||
 | 
							    "Quickshell.Hyprland._GlobalShortcuts",
 | 
				
			||||||
 | 
							    QQmlModuleImportLatest
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QS_REGISTER_PLUGIN(HyprlandFocusGrabPlugin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace
 | 
				
			||||||
							
								
								
									
										55
									
								
								src/wayland/hyprland/global_shortcuts/manager.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/wayland/hyprland/global_shortcuts/manager.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,55 @@
 | 
				
			||||||
 | 
					#include "manager.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					#include <qwaylandclientextension.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "shortcut.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::global_shortcuts::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalShortcutManager::GlobalShortcutManager()
 | 
				
			||||||
 | 
					    : QWaylandClientExtensionTemplate<GlobalShortcutManager>(1) {
 | 
				
			||||||
 | 
						this->initialize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalShortcut* GlobalShortcutManager::registerShortcut(
 | 
				
			||||||
 | 
					    const QString& appid,
 | 
				
			||||||
 | 
					    const QString& name,
 | 
				
			||||||
 | 
					    const QString& description,
 | 
				
			||||||
 | 
					    const QString& triggerDescription
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
						auto shortcut = this->shortcuts.value({appid, name});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (shortcut.second != nullptr) {
 | 
				
			||||||
 | 
							this->shortcuts.insert({appid, name}, {shortcut.first + 1, shortcut.second});
 | 
				
			||||||
 | 
							return shortcut.second;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							auto* shortcutObj = this->register_shortcut(name, appid, description, triggerDescription);
 | 
				
			||||||
 | 
							auto* managedObj = new GlobalShortcut(shortcutObj);
 | 
				
			||||||
 | 
							this->shortcuts.insert({appid, name}, {1, managedObj});
 | 
				
			||||||
 | 
							return managedObj;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcutManager::unregisterShortcut(const QString& appid, const QString& name) {
 | 
				
			||||||
 | 
						auto shortcut = this->shortcuts.value({appid, name});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (shortcut.first > 1) {
 | 
				
			||||||
 | 
							this->shortcuts.insert({appid, name}, {shortcut.first - 1, shortcut.second});
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							delete shortcut.second;
 | 
				
			||||||
 | 
							this->shortcuts.remove({appid, name});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalShortcutManager* GlobalShortcutManager::instance() {
 | 
				
			||||||
 | 
						static GlobalShortcutManager* instance = nullptr; // NOLINT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (instance == nullptr) {
 | 
				
			||||||
 | 
							instance = new GlobalShortcutManager();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return instance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::global_shortcuts::impl
 | 
				
			||||||
							
								
								
									
										34
									
								
								src/wayland/hyprland/global_shortcuts/manager.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/wayland/hyprland/global_shortcuts/manager.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qcontainerfwd.h>
 | 
				
			||||||
 | 
					#include <qhash.h>
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					#include <qwayland-hyprland-global-shortcuts-v1.h>
 | 
				
			||||||
 | 
					#include <qwaylandclientextension.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "shortcut.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::global_shortcuts::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GlobalShortcutManager
 | 
				
			||||||
 | 
					    : public QWaylandClientExtensionTemplate<GlobalShortcutManager>
 | 
				
			||||||
 | 
					    , public QtWayland::hyprland_global_shortcuts_manager_v1 {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit GlobalShortcutManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GlobalShortcut* registerShortcut(
 | 
				
			||||||
 | 
						    const QString& appid,
 | 
				
			||||||
 | 
						    const QString& name,
 | 
				
			||||||
 | 
						    const QString& description,
 | 
				
			||||||
 | 
						    const QString& triggerDescription
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void unregisterShortcut(const QString& appid, const QString& name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static GlobalShortcutManager* instance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						QHash<QPair<QString, QString>, QPair<qint32, GlobalShortcut*>> shortcuts;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::global_shortcuts::impl
 | 
				
			||||||
							
								
								
									
										115
									
								
								src/wayland/hyprland/global_shortcuts/qml.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/wayland/hyprland/global_shortcuts/qml.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,115 @@
 | 
				
			||||||
 | 
					#include "qml.hpp"
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "manager.hpp"
 | 
				
			||||||
 | 
					#include "shortcut.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::global_shortcuts {
 | 
				
			||||||
 | 
					using impl::GlobalShortcutManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalShortcut::~GlobalShortcut() {
 | 
				
			||||||
 | 
						auto* manager = GlobalShortcutManager::instance();
 | 
				
			||||||
 | 
						if (manager != nullptr) {
 | 
				
			||||||
 | 
							manager->unregisterShortcut(this->mAppid, this->mName);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::onPostReload() {
 | 
				
			||||||
 | 
						if (this->mName.isEmpty()) {
 | 
				
			||||||
 | 
							qWarning() << "Unable to create GlobalShortcut with empty name.";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto* manager = GlobalShortcutManager::instance();
 | 
				
			||||||
 | 
						if (manager == nullptr) {
 | 
				
			||||||
 | 
							qWarning() << "The active compositor does not support hyprland_global_shortcuts_v1.";
 | 
				
			||||||
 | 
							qWarning() << "GlobalShortcut will not work.";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->shortcut = manager->registerShortcut(
 | 
				
			||||||
 | 
						    this->mAppid,
 | 
				
			||||||
 | 
						    this->mName,
 | 
				
			||||||
 | 
						    this->mDescription,
 | 
				
			||||||
 | 
						    this->mTriggerDescription
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::connect(this->shortcut, &ShortcutImpl::pressed, this, &GlobalShortcut::onPressed);
 | 
				
			||||||
 | 
						QObject::connect(this->shortcut, &ShortcutImpl::released, this, &GlobalShortcut::onReleased);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool GlobalShortcut::isPressed() const { return this->mPressed; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString GlobalShortcut::appid() const { return this->mAppid; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::setAppid(QString appid) {
 | 
				
			||||||
 | 
						if (this->shortcut != nullptr) {
 | 
				
			||||||
 | 
							qWarning() << "GlobalShortcut cannot be modified after creation.";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (appid == this->mAppid) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mAppid = std::move(appid);
 | 
				
			||||||
 | 
						emit this->appidChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString GlobalShortcut::name() const { return this->mName; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::setName(QString name) {
 | 
				
			||||||
 | 
						if (this->shortcut != nullptr) {
 | 
				
			||||||
 | 
							qWarning() << "GlobalShortcut cannot be modified after creation.";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (name == this->mName) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mName = std::move(name);
 | 
				
			||||||
 | 
						emit this->nameChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString GlobalShortcut::description() const { return this->mDescription; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::setDescription(QString description) {
 | 
				
			||||||
 | 
						if (this->shortcut != nullptr) {
 | 
				
			||||||
 | 
							qWarning() << "GlobalShortcut cannot be modified after creation.";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (description == this->mDescription) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mDescription = std::move(description);
 | 
				
			||||||
 | 
						emit this->descriptionChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString GlobalShortcut::triggerDescription() const { return this->mTriggerDescription; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::setTriggerDescription(QString triggerDescription) {
 | 
				
			||||||
 | 
						if (this->shortcut != nullptr) {
 | 
				
			||||||
 | 
							qWarning() << "GlobalShortcut cannot be modified after creation.";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (triggerDescription == this->mTriggerDescription) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->mTriggerDescription = std::move(triggerDescription);
 | 
				
			||||||
 | 
						emit this->triggerDescriptionChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::onPressed() {
 | 
				
			||||||
 | 
						this->mPressed = true;
 | 
				
			||||||
 | 
						emit this->pressed();
 | 
				
			||||||
 | 
						emit this->pressedChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::onReleased() {
 | 
				
			||||||
 | 
						this->mPressed = false;
 | 
				
			||||||
 | 
						emit this->released();
 | 
				
			||||||
 | 
						emit this->pressedChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::global_shortcuts
 | 
				
			||||||
							
								
								
									
										108
									
								
								src/wayland/hyprland/global_shortcuts/qml.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/wayland/hyprland/global_shortcuts/qml.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,108 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qqmlintegration.h>
 | 
				
			||||||
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../../../core/reload.hpp"
 | 
				
			||||||
 | 
					#include "shortcut.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::global_shortcuts {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///! Hyprland global shortcut.
 | 
				
			||||||
 | 
					/// Global shortcut implemented with [hyprland_global_shortcuts_v1].
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// You can use this within hyprland as a global shortcut:
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					/// bind = <modifiers>, <key>, global, <appid>:<name>
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					/// See [the wiki] for details.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// > [!WARNING] The shortcuts protocol does not allow duplicate appid + name pairs.
 | 
				
			||||||
 | 
					/// > Within a single instance of quickshell this is handled internally, and both
 | 
				
			||||||
 | 
					/// > users will be notified, but multiple instances of quickshell or XDPH may collide.
 | 
				
			||||||
 | 
					/// >
 | 
				
			||||||
 | 
					/// > If that happens, whichever client that tries to register the shortcuts last will crash.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// > [!INFO] This type does *not* use the xdg-desktop-portal global shortcuts protocol,
 | 
				
			||||||
 | 
					/// > as it is not fully functional without flatpak and would cause a considerably worse
 | 
				
			||||||
 | 
					/// > user experience from other limitations. It will only work with Hyprland.
 | 
				
			||||||
 | 
					/// > Note that, as this type bypasses xdg-desktop-portal, XDPH is not required.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// [hyprland_global_shortcuts_v1]: https://github.com/hyprwm/hyprland-protocols/blob/main/protocols/hyprland-global-shortcuts-v1.xml
 | 
				
			||||||
 | 
					/// [the wiki]: https://wiki.hyprland.org/Configuring/Binds/#dbus-global-shortcuts
 | 
				
			||||||
 | 
					class GlobalShortcut
 | 
				
			||||||
 | 
					    : public QObject
 | 
				
			||||||
 | 
					    , public PostReloadHook {
 | 
				
			||||||
 | 
						using ShortcutImpl = impl::GlobalShortcut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
						// clang-format off
 | 
				
			||||||
 | 
						/// If the keybind is currently pressed.
 | 
				
			||||||
 | 
						Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged);
 | 
				
			||||||
 | 
						/// The appid of the shortcut. Defaults to `quickshell`.
 | 
				
			||||||
 | 
						/// You cannot change this at runtime.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// If you have more than one shortcut we recommend subclassing
 | 
				
			||||||
 | 
						/// GlobalShortcut to set this.
 | 
				
			||||||
 | 
						Q_PROPERTY(QString appid READ appid WRITE setAppid NOTIFY appidChanged);
 | 
				
			||||||
 | 
						/// The name of the shortcut.
 | 
				
			||||||
 | 
						/// You cannot change this at runtime.
 | 
				
			||||||
 | 
						Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged);
 | 
				
			||||||
 | 
						/// The description of the shortcut that appears in `hyprctl globalshortcuts`.
 | 
				
			||||||
 | 
						/// You cannot change this at runtime.
 | 
				
			||||||
 | 
						Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged);
 | 
				
			||||||
 | 
						/// Have not seen this used ever, but included for completeness. Safe to ignore.
 | 
				
			||||||
 | 
						Q_PROPERTY(QString triggerDescription READ triggerDescription WRITE setTriggerDescription NOTIFY triggerDescriptionChanged);
 | 
				
			||||||
 | 
						// clang-format on
 | 
				
			||||||
 | 
						QML_ELEMENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit GlobalShortcut(QObject* parent = nullptr): QObject(parent) {}
 | 
				
			||||||
 | 
						~GlobalShortcut() override;
 | 
				
			||||||
 | 
						Q_DISABLE_COPY_MOVE(GlobalShortcut);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void onPostReload() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] bool isPressed() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QString appid() const;
 | 
				
			||||||
 | 
						void setAppid(QString appid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QString name() const;
 | 
				
			||||||
 | 
						void setName(QString name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QString description() const;
 | 
				
			||||||
 | 
						void setDescription(QString description);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QString triggerDescription() const;
 | 
				
			||||||
 | 
						void setTriggerDescription(QString triggerDescription);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						/// Fired when the keybind is pressed.
 | 
				
			||||||
 | 
						void pressed();
 | 
				
			||||||
 | 
						/// Fired when the keybind is released.
 | 
				
			||||||
 | 
						void released();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void pressedChanged();
 | 
				
			||||||
 | 
						void appidChanged();
 | 
				
			||||||
 | 
						void nameChanged();
 | 
				
			||||||
 | 
						void descriptionChanged();
 | 
				
			||||||
 | 
						void triggerDescriptionChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
						void onPressed();
 | 
				
			||||||
 | 
						void onReleased();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						impl::GlobalShortcut* shortcut = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool mPressed = false;
 | 
				
			||||||
 | 
						QString mAppid = "quickshell";
 | 
				
			||||||
 | 
						QString mName;
 | 
				
			||||||
 | 
						QString mDescription;
 | 
				
			||||||
 | 
						QString mTriggerDescription;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::global_shortcuts
 | 
				
			||||||
							
								
								
									
										33
									
								
								src/wayland/hyprland/global_shortcuts/shortcut.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/wayland/hyprland/global_shortcuts/shortcut.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,33 @@
 | 
				
			||||||
 | 
					#include "shortcut.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					#include <wayland-hyprland-global-shortcuts-v1-client-protocol.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::global_shortcuts::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalShortcut::GlobalShortcut(::hyprland_global_shortcut_v1* shortcut) { this->init(shortcut); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalShortcut::~GlobalShortcut() {
 | 
				
			||||||
 | 
						if (this->isInitialized()) {
 | 
				
			||||||
 | 
							this->destroy();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::hyprland_global_shortcut_v1_pressed(
 | 
				
			||||||
 | 
					    quint32 /*unused*/,
 | 
				
			||||||
 | 
					    quint32 /*unused*/,
 | 
				
			||||||
 | 
					    quint32 /*unused*/
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
						emit this->pressed();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GlobalShortcut::hyprland_global_shortcut_v1_released(
 | 
				
			||||||
 | 
					    quint32 /*unused*/,
 | 
				
			||||||
 | 
					    quint32 /*unused*/,
 | 
				
			||||||
 | 
					    quint32 /*unused*/
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
						emit this->released();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::global_shortcuts::impl
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/wayland/hyprland/global_shortcuts/shortcut.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/wayland/hyprland/global_shortcuts/shortcut.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					#include <qwayland-hyprland-global-shortcuts-v1.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::global_shortcuts::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GlobalShortcut
 | 
				
			||||||
 | 
					    : public QObject
 | 
				
			||||||
 | 
					    , public QtWayland::hyprland_global_shortcut_v1 {
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit GlobalShortcut(::hyprland_global_shortcut_v1* shortcut);
 | 
				
			||||||
 | 
						~GlobalShortcut() override;
 | 
				
			||||||
 | 
						Q_DISABLE_COPY_MOVE(GlobalShortcut);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						void pressed();
 | 
				
			||||||
 | 
						void released();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						// clang-format off
 | 
				
			||||||
 | 
						void hyprland_global_shortcut_v1_pressed(quint32 tvSecHi, quint32 tvSecLo, quint32 tvNsec) override;
 | 
				
			||||||
 | 
						void hyprland_global_shortcut_v1_released(quint32 tvSecHi, quint32 tvSecLo, quint32 tvNsec) override;
 | 
				
			||||||
 | 
						// clang-format on
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::global_shortcuts::impl
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
name = "Quickshell.Hyprland"
 | 
					name = "Quickshell.Hyprland"
 | 
				
			||||||
description = "Hyprland specific Quickshell types"
 | 
					description = "Hyprland specific Quickshell types"
 | 
				
			||||||
headers = [
 | 
					headers = [
 | 
				
			||||||
	"focus_grab/qml.hpp"
 | 
						"focus_grab/qml.hpp",
 | 
				
			||||||
 | 
						"global_shortcuts/qml.hpp",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue