Skip to content

Commit 6c11fd2

Browse files
committed
wayland/shortcuts-inhibitor: fix rest
1 parent 146152b commit 6c11fd2

File tree

4 files changed

+96
-32
lines changed

4 files changed

+96
-32
lines changed

changelog/next.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set shell id.
1414
- Added support for creating Polkit agents.
1515
- Added support for creating wayland idle inhibitors.
1616
- Added support for wayland idle timeouts.
17+
- Added support for inhibiting wayland compositor shortcuts for focused windows.
1718
- Added the ability to override Quickshell.cacheDir with a custom path.
1819

1920
## Other Changes

src/wayland/shortcuts_inhibit/inhibitor.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "inhibitor.hpp"
22

33
#include <private/qwaylandwindow_p.h>
4+
#include <qguiapplication.h>
45
#include <qlogging.h>
56
#include <qloggingcategory.h>
67
#include <qobject.h>
8+
#include <qtmetamacros.h>
9+
#include <qwindow.h>
710

811
#include "../../window/proxywindow.hpp"
912
#include "../../window/windowinterface.hpp"
@@ -19,8 +22,19 @@ ShortcutInhibitor::ShortcutInhibitor() {
1922

2023
this->bActive.setBinding([this]() {
2124
auto* inhibitor = this->bInhibitor.value();
22-
return inhibitor ? inhibitor->bindableActive().value() : false;
25+
if (!inhibitor) return false;
26+
if (!inhibitor->bindableActive().value()) return false;
27+
return this->bWindow.value() == this->bFocusedWindow;
2328
});
29+
30+
QObject::connect(
31+
dynamic_cast<QGuiApplication*>(QGuiApplication::instance()),
32+
&QGuiApplication::focusWindowChanged,
33+
this,
34+
&ShortcutInhibitor::onFocusedWindowChanged
35+
);
36+
37+
this->onFocusedWindowChanged(QGuiApplication::focusWindow());
2438
}
2539

2640
ShortcutInhibitor::~ShortcutInhibitor() {
@@ -32,7 +46,7 @@ ShortcutInhibitor::~ShortcutInhibitor() {
3246
manager->unrefShortcutsInhibitor(this->bInhibitor);
3347
}
3448

35-
void ShortcutInhibitor::boundWindowChanged() {
49+
void ShortcutInhibitor::onBoundWindowChanged() {
3650
auto* window = this->bBoundWindow.value();
3751
auto* proxyWindow = qobject_cast<ProxyWindowBase*>(window);
3852

@@ -44,17 +58,17 @@ void ShortcutInhibitor::boundWindowChanged() {
4458

4559
if (proxyWindow == this->proxyWindow) return;
4660

61+
if (this->proxyWindow) {
62+
QObject::disconnect(this->proxyWindow, nullptr, this, nullptr);
63+
this->proxyWindow = nullptr;
64+
}
65+
4766
if (this->mWaylandWindow) {
4867
QObject::disconnect(this->mWaylandWindow, nullptr, this, nullptr);
4968
this->mWaylandWindow = nullptr;
5069
this->onWaylandSurfaceDestroyed();
5170
}
5271

53-
if (this->proxyWindow) {
54-
QObject::disconnect(this->proxyWindow, nullptr, this, nullptr);
55-
this->proxyWindow = nullptr;
56-
}
57-
5872
if (proxyWindow) {
5973
this->proxyWindow = proxyWindow;
6074

@@ -74,7 +88,6 @@ void ShortcutInhibitor::boundWindowChanged() {
7488
void ShortcutInhibitor::onWindowDestroyed() {
7589
this->proxyWindow = nullptr;
7690
this->onWaylandSurfaceDestroyed();
77-
this->bWindowObject = nullptr;
7891
}
7992

8093
void ShortcutInhibitor::onWindowVisibilityChanged() {
@@ -90,6 +103,7 @@ void ShortcutInhibitor::onWindowVisibilityChanged() {
90103
}
91104
if (waylandWindow == this->mWaylandWindow) return;
92105
this->mWaylandWindow = waylandWindow;
106+
this->bWindow = window;
93107

94108
QObject::connect(
95109
waylandWindow,
@@ -144,7 +158,7 @@ void ShortcutInhibitor::onWaylandSurfaceDestroyed() {
144158
this->bInhibitor = nullptr;
145159
}
146160

147-
void ShortcutInhibitor::inhibitorChanged() {
161+
void ShortcutInhibitor::onInhibitorChanged() {
148162
auto* inhibitor = this->bInhibitor.value();
149163
if (inhibitor) {
150164
QObject::connect(
@@ -162,7 +176,12 @@ void ShortcutInhibitor::onInhibitorActiveChanged() {
162176
// Compositor has deactivated the inhibitor, making it invalid.
163177
// Set enabled to false so the user can enable it again to create a new inhibitor.
164178
this->bEnabled = false;
179+
emit this->cancelled();
165180
}
166181
}
167182

183+
void ShortcutInhibitor::onFocusedWindowChanged(QWindow* focusedWindow) {
184+
this->bFocusedWindow = focusedWindow;
185+
}
186+
168187
} // namespace qs::wayland::shortcuts_inhibit

src/wayland/shortcuts_inhibit/inhibitor.hpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <qqmlintegration.h>
66
#include <qtclasshelpermacros.h>
77
#include <qtmetamacros.h>
8+
#include <qwindow.h>
89

910
#include "../../window/proxywindow.hpp"
1011
#include "proto.hpp"
@@ -29,11 +30,12 @@ class ShortcutInhibitor: public QObject {
2930
/// If the shortcuts inhibitor should be enabled. Defaults to false.
3031
Q_PROPERTY(bool enabled READ default WRITE default NOTIFY enabledChanged BINDABLE bindableEnabled);
3132
/// The window to associate the shortcuts inhibitor with.
33+
/// The inhibitor will only inhibit shortcuts pressed while this window has keyboard focus.
3234
///
3335
/// Must be set to a non null value to enable the inhibitor.
3436
Q_PROPERTY(QObject* window READ default WRITE default NOTIFY windowChanged BINDABLE bindableWindow);
35-
/// Whether the inhibitor is currently active. The inhibitor is only active when the
36-
/// compositor has granted the request.
37+
/// Whether the inhibitor is currently active. The inhibitor is only active if @@enabled is true,
38+
/// @@window has keyboard focus, and the compositor grants the inhibit request.
3739
///
3840
/// The compositor may deactivate the inhibitor at any time (for example, if the user requests
3941
/// normal shortcuts to be restored). When deactivated by the compositor, the inhibitor cannot be
@@ -54,6 +56,8 @@ class ShortcutInhibitor: public QObject {
5456
void enabledChanged();
5557
void windowChanged();
5658
void activeChanged();
59+
/// Sent if the compositor cancels the inhibitor while it is active.
60+
void cancelled();
5761

5862
private slots:
5963
void onWindowDestroyed();
@@ -64,16 +68,20 @@ private slots:
6468
void onInhibitorActiveChanged();
6569

6670
private:
67-
void boundWindowChanged();
68-
void inhibitorChanged();
71+
void onBoundWindowChanged();
72+
void onInhibitorChanged();
73+
void onFocusedWindowChanged(QWindow* focusedWindow);
74+
6975
ProxyWindowBase* proxyWindow = nullptr;
7076
QtWaylandClient::QWaylandWindow* mWaylandWindow = nullptr;
7177

7278
// clang-format off
7379
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, bool, bEnabled, &ShortcutInhibitor::enabledChanged);
7480
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, QObject*, bWindowObject, &ShortcutInhibitor::windowChanged);
75-
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, QObject*, bBoundWindow, &ShortcutInhibitor::boundWindowChanged);
76-
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, impl::ShortcutsInhibitor*, bInhibitor, &ShortcutInhibitor::inhibitorChanged);
81+
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, QObject*, bBoundWindow, &ShortcutInhibitor::onBoundWindowChanged);
82+
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, impl::ShortcutsInhibitor*, bInhibitor, &ShortcutInhibitor::onInhibitorChanged);
83+
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, QWindow*, bWindow);
84+
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, QWindow*, bFocusedWindow);
7785
Q_OBJECT_BINDABLE_PROPERTY(ShortcutInhibitor, bool, bActive, &ShortcutInhibitor::activeChanged);
7886
// clang-format on
7987
};

src/wayland/shortcuts_inhibit/test/manual/test.qml

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,62 @@ import QtQuick.Controls
44
import Quickshell
55
import Quickshell.Wayland
66

7-
FloatingWindow {
8-
id: w
9-
color: contentItem.palette.window
7+
Scope {
8+
Timer {
9+
id: toggleTimer
10+
interval: 100
11+
onTriggered: windowLoader.active = true
12+
}
1013

11-
ColumnLayout {
12-
anchors.centerIn: parent
14+
LazyLoader {
15+
id: windowLoader
16+
active: true
1317

14-
CheckBox {
15-
id: enabledCb
16-
text: "Enabled"
17-
}
18+
property bool enabled: false
1819

19-
Label {
20-
text: `Active: ${inhibitor.active}`
21-
}
22-
}
20+
FloatingWindow {
21+
id: w
22+
color: contentItem.palette.window
23+
24+
ColumnLayout {
25+
anchors.centerIn: parent
26+
27+
CheckBox {
28+
id: loadedCb
29+
text: "Loaded"
30+
checked: true
31+
}
2332

24-
ShortcutInhibitor {
25-
id: inhibitor
26-
window: w
27-
enabled: enabledCb.checked
33+
CheckBox {
34+
id: enabledCb
35+
text: "Enabled"
36+
checked: windowLoader.enabled
37+
onCheckedChanged: windowLoader.enabled = checked
38+
}
39+
40+
Label {
41+
text: `Active: ${inhibitorLoader.item?.active ?? false}`
42+
}
43+
44+
Button {
45+
text: "Toggle Window"
46+
onClicked: {
47+
windowLoader.active = false;
48+
toggleTimer.start();
49+
}
50+
}
51+
}
52+
53+
LazyLoader {
54+
id: inhibitorLoader
55+
active: loadedCb.checked
56+
57+
ShortcutInhibitor {
58+
window: w
59+
enabled: enabledCb.checked
60+
onCancelled: enabledCb.checked = false
61+
}
62+
}
63+
}
2864
}
2965
}

0 commit comments

Comments
 (0)