Skip to content

Commit ac5f7d2

Browse files
authored
Merge pull request #18 from Aylur/feat/idle-inhibitor
add idle inhibitor
2 parents c68d116 + d035a53 commit ac5f7d2

File tree

6 files changed

+216
-2
lines changed

6 files changed

+216
-2
lines changed

core/meson.build

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ prefix = get_option('prefix')
1515
libdir = get_option('prefix') / get_option('libdir')
1616
pkgdatadir = prefix / get_option('datadir') / 'astal'
1717

18-
1918
assert(
2019
get_option('lib') or get_option('cli'),
2120
'Either lib or cli option must be set to true.',

core/src/idle-inhibit.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#include "idle-inhibit.h"
2+
3+
#include <gdk/gdk.h>
4+
#include <gdk/gdkwayland.h>
5+
#include <gio/gio.h>
6+
#include <glib-object.h>
7+
#include <glib.h>
8+
#include <gtk/gtk.h>
9+
#include <wayland-client-protocol.h>
10+
#include <wayland-client.h>
11+
12+
#include "idle-inhibit-unstable-v1-client.h"
13+
14+
struct _AstalInhibitManager {
15+
GObject parent_instance;
16+
};
17+
18+
typedef struct {
19+
gboolean init;
20+
struct wl_registry* wl_registry;
21+
struct wl_display* display;
22+
struct zwp_idle_inhibit_manager_v1* idle_inhibit_manager;
23+
} AstalInhibitManagerPrivate;
24+
25+
G_DEFINE_TYPE_WITH_PRIVATE(AstalInhibitManager, astal_inhibit_manager, G_TYPE_OBJECT)
26+
27+
AstalInhibitor* astal_inhibit_manager_inhibit(AstalInhibitManager* self, GtkWindow* window) {
28+
AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self);
29+
g_assert_true(priv->init);
30+
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
31+
struct wl_surface* surface = gdk_wayland_window_get_wl_surface(gdk_window);
32+
return zwp_idle_inhibit_manager_v1_create_inhibitor(priv->idle_inhibit_manager, surface);
33+
}
34+
35+
static void global_registry_handler(void* data, struct wl_registry* registry, uint32_t id,
36+
const char* interface, uint32_t version) {
37+
AstalInhibitManager* self = ASTAL_INHIBIT_MANAGER(data);
38+
AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self);
39+
40+
if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
41+
priv->idle_inhibit_manager =
42+
wl_registry_bind(registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
43+
}
44+
}
45+
46+
static void global_registry_remover(void* data, struct wl_registry* registry, uint32_t id) {
47+
// neither inhibit_manager nor inhibitor is going to be removed by the compositor, so we don't
48+
// need do anything here.
49+
}
50+
51+
static const struct wl_registry_listener registry_listener = {global_registry_handler,
52+
global_registry_remover};
53+
54+
static gboolean astal_inhibit_manager_wayland_init(AstalInhibitManager* self) {
55+
AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self);
56+
57+
if (priv->init) return TRUE;
58+
59+
GdkDisplay* gdk_display = gdk_display_get_default();
60+
priv->display = gdk_wayland_display_get_wl_display(gdk_display);
61+
62+
priv->wl_registry = wl_display_get_registry(priv->display);
63+
wl_registry_add_listener(priv->wl_registry, &registry_listener, self);
64+
65+
wl_display_roundtrip(priv->display);
66+
67+
if (priv->idle_inhibit_manager == NULL) {
68+
g_critical("Can not connect idle inhibitor protocol");
69+
return FALSE;
70+
}
71+
72+
priv->init = TRUE;
73+
return TRUE;
74+
}
75+
76+
AstalInhibitManager* astal_inhibit_manager_get_default() {
77+
static AstalInhibitManager* self = NULL;
78+
79+
if (self == NULL) {
80+
self = g_object_new(ASTAL_TYPE_INHIBIT_MANAGER, NULL);
81+
if (!astal_inhibit_manager_wayland_init(self)) {
82+
g_object_unref(self);
83+
self = NULL;
84+
}
85+
}
86+
87+
return self;
88+
}
89+
90+
static void astal_inhibit_manager_init(AstalInhibitManager* self) {
91+
AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self);
92+
priv->init = FALSE;
93+
priv->display = NULL;
94+
priv->wl_registry = NULL;
95+
priv->idle_inhibit_manager = NULL;
96+
}
97+
98+
static void astal_inhibit_manager_finalize(GObject* object) {
99+
AstalInhibitManager* self = ASTAL_INHIBIT_MANAGER(object);
100+
AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self);
101+
102+
if (priv->display != NULL) wl_display_roundtrip(priv->display);
103+
104+
if (priv->wl_registry != NULL) wl_registry_destroy(priv->wl_registry);
105+
if (priv->idle_inhibit_manager != NULL)
106+
zwp_idle_inhibit_manager_v1_destroy(priv->idle_inhibit_manager);
107+
108+
G_OBJECT_CLASS(astal_inhibit_manager_parent_class)->finalize(object);
109+
}
110+
111+
static void astal_inhibit_manager_class_init(AstalInhibitManagerClass* class) {
112+
GObjectClass* object_class = G_OBJECT_CLASS(class);
113+
object_class->finalize = astal_inhibit_manager_finalize;
114+
}

core/src/idle-inhibit.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef ASTAL_IDLE_INHIBITOR_H
2+
#define ASTAL_IDLE_INHIBITOR_H
3+
4+
#include <glib-object.h>
5+
#include <gtk/gtk.h>
6+
7+
#include "idle-inhibit-unstable-v1-client.h"
8+
9+
G_BEGIN_DECLS
10+
11+
#define ASTAL_TYPE_INHIBIT_MANAGER (astal_inhibit_manager_get_type())
12+
13+
G_DECLARE_FINAL_TYPE(AstalInhibitManager, astal_inhibit_manager, ASTAL, INHIBIT_MANAGER, GObject)
14+
15+
typedef struct zwp_idle_inhibitor_v1 AstalInhibitor;
16+
17+
AstalInhibitManager* astal_inhibit_manager_get_default();
18+
AstalInhibitor* astal_inhibit_manager_inhibit(AstalInhibitManager* self, GtkWindow* window);
19+
20+
G_END_DECLS
21+
22+
#endif // !ASTAL_IDLE_INHIBITOR_H

core/src/meson.build

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ api_version = version_split[0] + '.' + version_split[1]
33
gir = 'Astal-' + api_version + '.gir'
44
typelib = 'Astal-' + api_version + '.typelib'
55

6+
vapi_dir = meson.current_source_dir() / 'vapi'
7+
add_project_arguments(['--vapidir', vapi_dir], language: 'vala')
8+
69
config = configure_file(
710
input: 'config.vala.in',
811
output: 'config.vala',
@@ -22,10 +25,41 @@ pkgconfig_deps = [
2225
dependency('gtk+-3.0'),
2326
dependency('gdk-pixbuf-2.0'),
2427
dependency('gtk-layer-shell-0'),
28+
dependency('wayland-client'),
2529
]
2630

2731
deps = pkgconfig_deps + meson.get_compiler('c').find_library('m')
2832

33+
34+
wayland_protos = dependency('wayland-protocols')
35+
wayland_scanner = find_program('wayland-scanner')
36+
37+
wl_protocol_dir = wayland_protos.get_variable(pkgconfig: 'pkgdatadir')
38+
39+
gen_client_header = generator(
40+
wayland_scanner,
41+
output: ['@BASENAME@-client.h'],
42+
arguments: ['-c', 'client-header', '@INPUT@', '@BUILD_DIR@/@BASENAME@-client.h'],
43+
)
44+
45+
gen_private_code = generator(
46+
wayland_scanner,
47+
output: ['@BASENAME@.c'],
48+
arguments: ['-c', 'private-code', '@INPUT@', '@BUILD_DIR@/@BASENAME@.c'],
49+
)
50+
51+
protocols = [
52+
join_paths(wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml')
53+
]
54+
55+
client_protocol_srcs = []
56+
57+
foreach protocol : protocols
58+
client_header = gen_client_header.process(protocol)
59+
code = gen_private_code.process(protocol)
60+
client_protocol_srcs += [client_header, code]
61+
endforeach
62+
2963
sources = [
3064
config,
3165
'widget/box.vala',
@@ -47,13 +81,16 @@ sources = [
4781
'process.vala',
4882
'time.vala',
4983
'variable.vala',
50-
]
84+
'idle-inhibit.h',
85+
'idle-inhibit.c',
86+
] + client_protocol_srcs
5187

5288
if get_option('lib')
5389
lib = library(
5490
meson.project_name(),
5591
sources,
5692
dependencies: deps,
93+
vala_args: ['--pkg', 'AstalInhibitManager'],
5794
vala_header: meson.project_name() + '.h',
5895
vala_vapi: meson.project_name() + '-' + api_version + '.vapi',
5996
vala_gir: gir,
@@ -92,6 +129,7 @@ if get_option('cli')
92129
executable(
93130
meson.project_name(),
94131
['cli.vala', sources],
132+
vala_args: ['--pkg', 'AstalInhibitManager'],
95133
dependencies: deps,
96134
install: true,
97135
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[CCode (cprefix = "Astal", gir_namespace = "Astal", lower_case_cprefix = "astal_")]
2+
namespace Astal {
3+
[CCode (cheader_filename = "idle-inhibit.h", type_id = "astal_idle_inhibit_manager_get_type()")]
4+
public class InhibitManager : GLib.Object {
5+
public static unowned InhibitManager? get_default();
6+
public Inhibitor inhibit (Gtk.Window window);
7+
}
8+
9+
[CCode (cheader_filename = "idle-inhibit.h", free_function = "zwp_idle_inhibitor_v1_destroy")]
10+
[Compact]
11+
public class Inhibitor {
12+
}
13+
}

core/src/widget/window.vala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,41 @@ public class Window : Gtk.Window {
3838
return false;
3939
}
4040

41+
private InhibitManager? inhibit_manager;
42+
private Inhibitor? inhibitor;
43+
4144
construct {
4245
if (check("initialize layer shell"))
4346
return;
4447

4548
height_request = 1;
4649
width_request = 1;
4750
init_for_window(this);
51+
inhibit_manager = InhibitManager.get_default();
52+
}
53+
54+
public bool inhibit {
55+
set {
56+
if (inhibit_manager == null) {
57+
return;
58+
}
59+
if (value && inhibitor == null) {
60+
inhibitor = inhibit_manager.inhibit(this);
61+
}
62+
else if (!value && inhibitor != null) {
63+
inhibitor = null;
64+
}
65+
}
66+
get {
67+
return inhibitor != null;
68+
}
69+
}
70+
71+
public override void show() {
72+
base.show();
73+
if(inhibit) {
74+
inhibitor = inhibit_manager.inhibit(this);
75+
}
4876
}
4977

5078
public string namespace {

0 commit comments

Comments
 (0)