forked from quickshell/quickshell
		
	hyprland/focus_grab: add HyprlandFocusGrab
This commit is contained in:
		
							parent
							
								
									e7cfb5cf37
								
							
						
					
					
						commit
						6e9bb4183c
					
				
					 15 changed files with 608 additions and 0 deletions
				
			
		| 
						 | 
					@ -14,6 +14,7 @@ option(SOCKETS "Enable unix socket support" ON)
 | 
				
			||||||
option(WAYLAND "Enable wayland support" ON)
 | 
					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(SERVICE_STATUS_NOTIFIER "StatusNotifierItem service" ON)
 | 
					option(SERVICE_STATUS_NOTIFIER "StatusNotifierItem service" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message(STATUS "Quickshell configuration")
 | 
					message(STATUS "Quickshell configuration")
 | 
				
			||||||
| 
						 | 
					@ -27,6 +28,7 @@ if (WAYLAND)
 | 
				
			||||||
endif ()
 | 
					endif ()
 | 
				
			||||||
message(STATUS "  Services")
 | 
					message(STATUS "  Services")
 | 
				
			||||||
message(STATUS "    StatusNotifier: ${SERVICE_STATUS_NOTIFIER}")
 | 
					message(STATUS "    StatusNotifier: ${SERVICE_STATUS_NOTIFIER}")
 | 
				
			||||||
 | 
					message(STATUS "  Hyprland: ${HYPRLAND}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (NOT DEFINED GIT_REVISION)
 | 
					if (NOT DEFINED GIT_REVISION)
 | 
				
			||||||
	execute_process(
 | 
						execute_process(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,6 +88,7 @@ void ProxyWindowBase::createWindow() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ProxyWindowBase::deleteWindow() {
 | 
					void ProxyWindowBase::deleteWindow() {
 | 
				
			||||||
 | 
						if (this->window != nullptr) emit this->windowDestroyed();
 | 
				
			||||||
	if (auto* window = this->disownWindow()) {
 | 
						if (auto* window = this->disownWindow()) {
 | 
				
			||||||
		if (auto* generation = EngineGeneration::findObjectGeneration(this)) {
 | 
							if (auto* generation = EngineGeneration::findObjectGeneration(this)) {
 | 
				
			||||||
			generation->deregisterIncubationController(window->incubationController());
 | 
								generation->deregisterIncubationController(window->incubationController());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,6 +102,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
	void windowConnected();
 | 
						void windowConnected();
 | 
				
			||||||
 | 
						void windowDestroyed();
 | 
				
			||||||
	void visibleChanged();
 | 
						void visibleChanged();
 | 
				
			||||||
	void backerVisibilityChanged();
 | 
						void backerVisibilityChanged();
 | 
				
			||||||
	void xChanged();
 | 
						void xChanged();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,10 @@ if (WAYLAND_SESSION_LOCK)
 | 
				
			||||||
	add_subdirectory(session_lock)
 | 
						add_subdirectory(session_lock)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (HYPRLAND)
 | 
				
			||||||
 | 
						add_subdirectory(hyprland)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-wayland PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-wayland PRIVATE ${QT_DEPS})
 | 
				
			||||||
target_link_libraries(quickshell-wayland-init PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-wayland-init PRIVATE ${QT_DEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/wayland/hyprland/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/wayland/hyprland/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					qt_add_library(quickshell-hyprland STATIC)
 | 
				
			||||||
 | 
					qt_add_qml_module(quickshell-hyprland URI Quickshell.Hyprland VERSION 0.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_subdirectory(focus_grab)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-hyprland PRIVATE ${QT_DEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland)
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprlandplugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell PRIVATE quickshell-hyprlandplugin)
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/wayland/hyprland/focus_grab/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/wayland/hyprland/focus_grab/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					qt_add_library(quickshell-hyprland-focus-grab STATIC
 | 
				
			||||||
 | 
						manager.cpp
 | 
				
			||||||
 | 
						grab.cpp
 | 
				
			||||||
 | 
						qml.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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-init PRIVATE ${QT_DEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland-focus-grab)
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland-focus-grabplugin)
 | 
				
			||||||
 | 
					qs_pch(quickshell-hyprland-focus-grab-init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell PRIVATE quickshell-hyprland-focus-grabplugin quickshell-hyprland-focus-grab-init)
 | 
				
			||||||
							
								
								
									
										78
									
								
								src/wayland/hyprland/focus_grab/grab.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/wayland/hyprland/focus_grab/grab.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,78 @@
 | 
				
			||||||
 | 
					#include "grab.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <private/qwaylandwindow_p.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					#include <wayland-hyprland-focus-grab-v1-client-protocol.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::focus_grab {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FocusGrab::FocusGrab(::hyprland_focus_grab_v1* grab) { this->init(grab); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FocusGrab::~FocusGrab() {
 | 
				
			||||||
 | 
						if (this->isInitialized()) {
 | 
				
			||||||
 | 
							this->destroy();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FocusGrab::isActive() const { return this->active; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FocusGrab::addWindow(QWindow* window) {
 | 
				
			||||||
 | 
						if (auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle())) {
 | 
				
			||||||
 | 
							this->addWaylandWindow(waylandWindow);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							QObject::connect(window, &QWindow::visibleChanged, this, [this, window]() {
 | 
				
			||||||
 | 
								if (window->isVisible()) {
 | 
				
			||||||
 | 
									if (window->handle() == nullptr) {
 | 
				
			||||||
 | 
										window->create();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle());
 | 
				
			||||||
 | 
									this->addWaylandWindow(waylandWindow);
 | 
				
			||||||
 | 
									this->sync();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FocusGrab::removeWindow(QWindow* window) {
 | 
				
			||||||
 | 
						QObject::disconnect(window, nullptr, this, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle())) {
 | 
				
			||||||
 | 
							this->pendingAdditions.removeAll(waylandWindow);
 | 
				
			||||||
 | 
							this->remove_surface(waylandWindow->surface());
 | 
				
			||||||
 | 
							this->commitRequired = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FocusGrab::addWaylandWindow(QWaylandWindow* window) {
 | 
				
			||||||
 | 
						this->add_surface(window->surface());
 | 
				
			||||||
 | 
						this->pendingAdditions.append(window);
 | 
				
			||||||
 | 
						this->commitRequired = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FocusGrab::sync() {
 | 
				
			||||||
 | 
						if (this->commitRequired) {
 | 
				
			||||||
 | 
							this->commit();
 | 
				
			||||||
 | 
							this->commitRequired = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// the protocol will always send cleared() when the grab is deactivated,
 | 
				
			||||||
 | 
							// even if it was due to window destruction, so we don't need to track it.
 | 
				
			||||||
 | 
							if (!this->pendingAdditions.isEmpty()) {
 | 
				
			||||||
 | 
								this->pendingAdditions.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!this->active) {
 | 
				
			||||||
 | 
									this->active = true;
 | 
				
			||||||
 | 
									emit this->activated();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void FocusGrab::hyprland_focus_grab_v1_cleared() {
 | 
				
			||||||
 | 
						this->active = false;
 | 
				
			||||||
 | 
						emit this->cleared();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::focus_grab
 | 
				
			||||||
							
								
								
									
										46
									
								
								src/wayland/hyprland/focus_grab/grab.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/wayland/hyprland/focus_grab/grab.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <private/qwaylandwindow_p.h>
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qwayland-hyprland-focus-grab-v1.h>
 | 
				
			||||||
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					#include <wayland-hyprland-focus-grab-v1-client-protocol.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::focus_grab {
 | 
				
			||||||
 | 
					using HyprlandFocusGrab = QtWayland::hyprland_focus_grab_v1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FocusGrab
 | 
				
			||||||
 | 
					    : public QObject
 | 
				
			||||||
 | 
					    , public HyprlandFocusGrab {
 | 
				
			||||||
 | 
						using QWaylandWindow = QtWaylandClient::QWaylandWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit FocusGrab(::hyprland_focus_grab_v1* grab);
 | 
				
			||||||
 | 
						~FocusGrab() override;
 | 
				
			||||||
 | 
						Q_DISABLE_COPY_MOVE(FocusGrab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] bool isActive() const;
 | 
				
			||||||
 | 
						void addWindow(QWindow* window);
 | 
				
			||||||
 | 
						void removeWindow(QWindow* window);
 | 
				
			||||||
 | 
						void sync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						void activated();
 | 
				
			||||||
 | 
						void cleared();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						void hyprland_focus_grab_v1_cleared() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void addWaylandWindow(QWaylandWindow* window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QList<QWaylandWindow*> pendingAdditions;
 | 
				
			||||||
 | 
						bool commitRequired = false;
 | 
				
			||||||
 | 
						bool active = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::focus_grab
 | 
				
			||||||
							
								
								
									
										128
									
								
								src/wayland/hyprland/focus_grab/hyprland-focus-grab-v1.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/wayland/hyprland/focus_grab/hyprland-focus-grab-v1.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,128 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<protocol name="hyprland_focus_grab_v1">
 | 
				
			||||||
 | 
					  <copyright>
 | 
				
			||||||
 | 
					    Copyright © 2024 outfoxxed
 | 
				
			||||||
 | 
					    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="limit input focus to a set of surfaces">
 | 
				
			||||||
 | 
					    This protocol allows clients to limit input focus to a specific set
 | 
				
			||||||
 | 
					    of surfaces and receive a notification when the limiter is removed as
 | 
				
			||||||
 | 
					    detailed below.
 | 
				
			||||||
 | 
					  </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="hyprland_focus_grab_manager_v1" version="1">
 | 
				
			||||||
 | 
					    <description summary="manager for focus grab objects">
 | 
				
			||||||
 | 
					      This interface allows a client to create surface grab objects.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="create_grab">
 | 
				
			||||||
 | 
					      <description summary="create a focus grab object">
 | 
				
			||||||
 | 
					        Create a surface grab object.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <arg name="grab" type="new_id" interface="hyprland_focus_grab_v1"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="destroy the focus grab manager">
 | 
				
			||||||
 | 
					        Destroy the focus grab manager.
 | 
				
			||||||
 | 
					        This doesn't destroy existing focus grab objects.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="hyprland_focus_grab_v1" version="1">
 | 
				
			||||||
 | 
					    <description summary="input focus limiter">
 | 
				
			||||||
 | 
					      This interface restricts input focus to a specified whitelist of
 | 
				
			||||||
 | 
					      surfaces as long as the focus grab object exists and has at least
 | 
				
			||||||
 | 
					      one comitted surface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Mouse and touch events inside a whitelisted surface will be passed
 | 
				
			||||||
 | 
					      to the surface normally, while events outside of a whitelisted surface
 | 
				
			||||||
 | 
					      will clear the grab object. Keyboard events will be passed to the client
 | 
				
			||||||
 | 
					      and a compositor-picked surface in the whitelist will receive a
 | 
				
			||||||
 | 
					      wl_keyboard::enter event if a whitelisted surface is not already entered.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Upon meeting implementation-defined criteria usually meaning a mouse or
 | 
				
			||||||
 | 
					      touch input outside of any whitelisted surfaces, the compositor will
 | 
				
			||||||
 | 
					      clear the whitelist, rendering the grab inert and sending the cleared
 | 
				
			||||||
 | 
					      event. The same will happen if another focus grab or similar action
 | 
				
			||||||
 | 
					      is started at the compositor's discretion.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="add_surface">
 | 
				
			||||||
 | 
					      <description summary="add a surface to the focus whitelist">
 | 
				
			||||||
 | 
					        Add a surface to the whitelist. Destroying the surface is treated the
 | 
				
			||||||
 | 
					        same as an explicit call to remove_surface and duplicate additions are
 | 
				
			||||||
 | 
					        ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Does not take effect until commit is called.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <arg name="surface" type="object" interface="wl_surface"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="remove_surface">
 | 
				
			||||||
 | 
					      <description summary="remove a surface from the focus whitelist">
 | 
				
			||||||
 | 
					        Remove a surface from the whitelist. Destroying the surface is treated
 | 
				
			||||||
 | 
					        the same as an explicit call to this function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If the grab was active and the removed surface was entered by the
 | 
				
			||||||
 | 
					        keyboard, another surface will be entered on commit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Does not take effect until commit is called.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <arg name="surface" type="object" interface="wl_surface"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="commit">
 | 
				
			||||||
 | 
					      <description summary="commit the focus whitelist">
 | 
				
			||||||
 | 
					        Commit pending changes to the surface whitelist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If the list previously had no entries and now has at least one, the grab
 | 
				
			||||||
 | 
					        will start. If it previously had entries and now has none, the grab will
 | 
				
			||||||
 | 
					        become inert.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="destroy the focus grab">
 | 
				
			||||||
 | 
					        Destroy the grab object and remove the grab if active.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="cleared">
 | 
				
			||||||
 | 
					      <description summary="the focus grab was cleared">
 | 
				
			||||||
 | 
					        Sent when an active grab is cancelled by the compositor,
 | 
				
			||||||
 | 
					        regardless of cause.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					</protocol>
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/wayland/hyprland/focus_grab/init.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/wayland/hyprland/focus_grab/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._FocusGrab",
 | 
				
			||||||
 | 
							    QQmlModuleImportLatest
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QS_REGISTER_PLUGIN(HyprlandFocusGrabPlugin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/wayland/hyprland/focus_grab/manager.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/wayland/hyprland/focus_grab/manager.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					#include "manager.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qwaylandclientextension.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "grab.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::focus_grab {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FocusGrabManager::FocusGrabManager(): QWaylandClientExtensionTemplate<FocusGrabManager>(1) {
 | 
				
			||||||
 | 
						this->initialize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool FocusGrabManager::available() const { return this->isActive(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FocusGrab* FocusGrabManager::createGrab() { return new FocusGrab(this->create_grab()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FocusGrabManager* FocusGrabManager::instance() {
 | 
				
			||||||
 | 
						static FocusGrabManager* instance = nullptr; // NOLINT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (instance == nullptr) {
 | 
				
			||||||
 | 
							instance = new FocusGrabManager();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return instance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::focus_grab
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/wayland/hyprland/focus_grab/manager.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/wayland/hyprland/focus_grab/manager.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qwayland-hyprland-focus-grab-v1.h>
 | 
				
			||||||
 | 
					#include <qwaylandclientextension.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland::focus_grab {
 | 
				
			||||||
 | 
					using HyprlandFocusGrabManager = QtWayland::hyprland_focus_grab_manager_v1;
 | 
				
			||||||
 | 
					class FocusGrab;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FocusGrabManager
 | 
				
			||||||
 | 
					    : public QWaylandClientExtensionTemplate<FocusGrabManager>
 | 
				
			||||||
 | 
					    , public HyprlandFocusGrabManager {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit FocusGrabManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] bool available() const;
 | 
				
			||||||
 | 
						[[nodiscard]] FocusGrab* createGrab();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static FocusGrabManager* instance();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland::focus_grab
 | 
				
			||||||
							
								
								
									
										132
									
								
								src/wayland/hyprland/focus_grab/qml.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/wayland/hyprland/focus_grab/qml.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,132 @@
 | 
				
			||||||
 | 
					#include "qml.hpp"
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qqmllist.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../../../core/proxywindow.hpp"
 | 
				
			||||||
 | 
					#include "../../../core/windowinterface.hpp"
 | 
				
			||||||
 | 
					#include "grab.hpp"
 | 
				
			||||||
 | 
					#include "manager.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland {
 | 
				
			||||||
 | 
					using focus_grab::FocusGrab;
 | 
				
			||||||
 | 
					using focus_grab::FocusGrabManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::componentComplete() { this->tryActivate(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool HyprlandFocusGrab::isActive() const { return this->grab != nullptr && this->grab->isActive(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::setActive(bool active) {
 | 
				
			||||||
 | 
						if (active == this->targetActive) return;
 | 
				
			||||||
 | 
						this->targetActive = active;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!active) {
 | 
				
			||||||
 | 
							delete this->grab;
 | 
				
			||||||
 | 
							this->grab = nullptr;
 | 
				
			||||||
 | 
							emit this->activeChanged();
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							this->tryActivate();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QObjectList HyprlandFocusGrab::windows() const { return this->windowObjects; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::setWindows(QObjectList windows) {
 | 
				
			||||||
 | 
						if (windows == this->windowObjects) return;
 | 
				
			||||||
 | 
						this->windowObjects = std::move(windows);
 | 
				
			||||||
 | 
						this->syncWindows();
 | 
				
			||||||
 | 
						emit this->windowsChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::onGrabActivated() { emit this->activeChanged(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::onGrabCleared() {
 | 
				
			||||||
 | 
						emit this->cleared();
 | 
				
			||||||
 | 
						this->setActive(false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::onProxyConnected() {
 | 
				
			||||||
 | 
						if (this->grab != nullptr) {
 | 
				
			||||||
 | 
							this->grab->addWindow(qobject_cast<ProxyWindowBase*>(this->sender())->backingWindow());
 | 
				
			||||||
 | 
							this->grab->sync();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::tryActivate() {
 | 
				
			||||||
 | 
						qDebug() << "tryactivate";
 | 
				
			||||||
 | 
						if (!this->targetActive || this->isActive()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto* manager = FocusGrabManager::instance();
 | 
				
			||||||
 | 
						if (!manager->isActive()) {
 | 
				
			||||||
 | 
							qWarning() << "The active compositor does not support the hyprland_focus_grab_v1 protocol. "
 | 
				
			||||||
 | 
							              "HyprlandFocusGrab will not work.";
 | 
				
			||||||
 | 
							qWarning() << "** Learn why $XDG_CURRENT_DESKTOP sucks and download a better compositor "
 | 
				
			||||||
 | 
							              "today at https://hyprland.org";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->grab = manager->createGrab();
 | 
				
			||||||
 | 
						this->grab->setParent(this);
 | 
				
			||||||
 | 
						QObject::connect(this->grab, &FocusGrab::activated, this, &HyprlandFocusGrab::onGrabActivated);
 | 
				
			||||||
 | 
						QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto* proxy: this->trackedProxies) {
 | 
				
			||||||
 | 
							if (proxy->backingWindow() != nullptr) {
 | 
				
			||||||
 | 
								this->grab->addWindow(proxy->backingWindow());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->grab->sync();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HyprlandFocusGrab::syncWindows() {
 | 
				
			||||||
 | 
						auto newProxy = QList<ProxyWindowBase*>();
 | 
				
			||||||
 | 
						for (auto* windowObject: this->windowObjects) {
 | 
				
			||||||
 | 
							auto* proxyWindow = qobject_cast<ProxyWindowBase*>(windowObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (proxyWindow == nullptr) {
 | 
				
			||||||
 | 
								if (auto* iface = qobject_cast<WindowInterface*>(windowObject)) {
 | 
				
			||||||
 | 
									proxyWindow = iface->proxyWindow();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (proxyWindow != nullptr) {
 | 
				
			||||||
 | 
								newProxy.push_back(proxyWindow);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto* oldWindow: this->trackedProxies) {
 | 
				
			||||||
 | 
							if (!newProxy.contains(oldWindow)) {
 | 
				
			||||||
 | 
								QObject::disconnect(oldWindow, nullptr, this, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (this->grab != nullptr && oldWindow->backingWindow() != nullptr) {
 | 
				
			||||||
 | 
									this->grab->removeWindow(oldWindow->backingWindow());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto* newProxy: newProxy) {
 | 
				
			||||||
 | 
							if (!this->trackedProxies.contains(newProxy)) {
 | 
				
			||||||
 | 
								QObject::connect(
 | 
				
			||||||
 | 
								    newProxy,
 | 
				
			||||||
 | 
								    &ProxyWindowBase::windowConnected,
 | 
				
			||||||
 | 
								    this,
 | 
				
			||||||
 | 
								    &HyprlandFocusGrab::onProxyConnected
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (this->grab != nullptr && newProxy->backingWindow() != nullptr) {
 | 
				
			||||||
 | 
									this->grab->addWindow(newProxy->backingWindow());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->trackedProxies = newProxy;
 | 
				
			||||||
 | 
						if (this->grab != nullptr) this->grab->sync();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::hyprland
 | 
				
			||||||
							
								
								
									
										111
									
								
								src/wayland/hyprland/focus_grab/qml.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/wayland/hyprland/focus_grab/qml.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,111 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qqmlintegration.h>
 | 
				
			||||||
 | 
					#include <qqmllist.h>
 | 
				
			||||||
 | 
					#include <qqmlparserstatus.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProxyWindowBase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::hyprland {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace focus_grab {
 | 
				
			||||||
 | 
					class FocusGrab;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///! Input focus grabber
 | 
				
			||||||
 | 
					/// Object for managing input focus grabs via the [hyprland_focus_grab_v1]
 | 
				
			||||||
 | 
					/// wayland protocol.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// When enabled, all of the windows listed in the `windows` property will
 | 
				
			||||||
 | 
					/// receive input normally, and will retain keyboard focus even if the mouse
 | 
				
			||||||
 | 
					/// is moved off of them. When areas of the screen that are not part of a listed
 | 
				
			||||||
 | 
					/// window are clicked or touched, the grab will become inactive and emit the
 | 
				
			||||||
 | 
					/// cleared signal.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// This is useful for implementing dismissal of popup type windows.
 | 
				
			||||||
 | 
					/// ```qml
 | 
				
			||||||
 | 
					/// import Quickshell
 | 
				
			||||||
 | 
					/// import Quickshell.Hyprland
 | 
				
			||||||
 | 
					/// import QtQuick.Controls
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ShellRoot {
 | 
				
			||||||
 | 
					///   FloatingWindow {
 | 
				
			||||||
 | 
					///     id: window
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					///     Button {
 | 
				
			||||||
 | 
					///       anchors.centerIn: parent
 | 
				
			||||||
 | 
					///       text: grab.active ? "Remove exclusive focus" : "Take exclusive focus"
 | 
				
			||||||
 | 
					///       onClicked: grab.active = !grab.active
 | 
				
			||||||
 | 
					///     }
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					///     HyprlandFocusGrab {
 | 
				
			||||||
 | 
					///       id: grab
 | 
				
			||||||
 | 
					///       windows: [ window ]
 | 
				
			||||||
 | 
					///     }
 | 
				
			||||||
 | 
					///   }
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// [hyprland_focus_grab_v1]: https://github.com/hyprwm/hyprland-protocols/blob/main/protocols/hyprland-global-shortcuts-v1.xml
 | 
				
			||||||
 | 
					class HyprlandFocusGrab
 | 
				
			||||||
 | 
					    : public QObject
 | 
				
			||||||
 | 
					    , public QQmlParserStatus {
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
						/// If the focus grab is active. Defaults to false.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// When set to true, an input grab will be created for the listed windows.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// This property will change to false once the grab is dismissed.
 | 
				
			||||||
 | 
						/// It will not change to true until the grab begins, which requires
 | 
				
			||||||
 | 
						/// at least one visible window.
 | 
				
			||||||
 | 
						Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged);
 | 
				
			||||||
 | 
						/// The list of windows to whitelist for input.
 | 
				
			||||||
 | 
						Q_PROPERTY(QList<QObject*> windows READ windows WRITE setWindows NOTIFY windowsChanged);
 | 
				
			||||||
 | 
						QML_ELEMENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit HyprlandFocusGrab(QObject* parent = nullptr): QObject(parent) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void classBegin() override {}
 | 
				
			||||||
 | 
						void componentComplete() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] bool isActive() const;
 | 
				
			||||||
 | 
						void setActive(bool active);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QObjectList windows() const;
 | 
				
			||||||
 | 
						void setWindows(QObjectList windows);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						/// Sent whenever the compositor clears the focus grab.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// This may be in response to all windows being removed
 | 
				
			||||||
 | 
						/// from the list or simultaneously hidden, in addition to
 | 
				
			||||||
 | 
						/// a normal clear.
 | 
				
			||||||
 | 
						void cleared();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void activeChanged();
 | 
				
			||||||
 | 
						void windowsChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
						void onGrabActivated();
 | 
				
			||||||
 | 
						void onGrabCleared();
 | 
				
			||||||
 | 
						void onProxyConnected();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						void tryActivate();
 | 
				
			||||||
 | 
						void syncWindows();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool targetActive = false;
 | 
				
			||||||
 | 
						QObjectList windowObjects;
 | 
				
			||||||
 | 
						QList<ProxyWindowBase*> trackedProxies;
 | 
				
			||||||
 | 
						QList<QWindow*> trackedWindows;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						focus_grab::FocusGrab* grab = nullptr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}; // namespace qs::hyprland
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/wayland/hyprland/module.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/wayland/hyprland/module.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					name = "Quickshell.Hyprland"
 | 
				
			||||||
 | 
					description = "Hyprland specific Quickshell types"
 | 
				
			||||||
 | 
					headers = [
 | 
				
			||||||
 | 
						"focus_grab/qml.hpp"
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					-----
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue