diff options
-rw-r--r-- | core/meson.build | 1 | ||||
-rw-r--r-- | core/src/idle-inhibit.c | 114 | ||||
-rw-r--r-- | core/src/idle-inhibit.h | 22 | ||||
-rw-r--r-- | core/src/meson.build | 40 | ||||
-rw-r--r-- | core/src/vapi/AstalInhibitManager.vapi | 13 | ||||
-rw-r--r-- | core/src/widget/window.vala | 28 |
6 files changed, 216 insertions, 2 deletions
diff --git a/core/meson.build b/core/meson.build index 12b4f1d..a2606db 100644 --- a/core/meson.build +++ b/core/meson.build @@ -15,7 +15,6 @@ prefix = get_option('prefix') libdir = get_option('prefix') / get_option('libdir') pkgdatadir = prefix / get_option('datadir') / 'astal' - assert( get_option('lib') or get_option('cli'), 'Either lib or cli option must be set to true.', diff --git a/core/src/idle-inhibit.c b/core/src/idle-inhibit.c new file mode 100644 index 0000000..48f2471 --- /dev/null +++ b/core/src/idle-inhibit.c @@ -0,0 +1,114 @@ +#include "idle-inhibit.h" + +#include <gdk/gdk.h> +#include <gdk/gdkwayland.h> +#include <gio/gio.h> +#include <glib-object.h> +#include <glib.h> +#include <gtk/gtk.h> +#include <wayland-client-protocol.h> +#include <wayland-client.h> + +#include "idle-inhibit-unstable-v1-client.h" + +struct _AstalInhibitManager { + GObject parent_instance; +}; + +typedef struct { + gboolean init; + struct wl_registry* wl_registry; + struct wl_display* display; + struct zwp_idle_inhibit_manager_v1* idle_inhibit_manager; +} AstalInhibitManagerPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(AstalInhibitManager, astal_inhibit_manager, G_TYPE_OBJECT) + +AstalInhibitor* astal_inhibit_manager_inhibit(AstalInhibitManager* self, GtkWindow* window) { + AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self); + g_assert_true(priv->init); + GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window)); + struct wl_surface* surface = gdk_wayland_window_get_wl_surface(gdk_window); + return zwp_idle_inhibit_manager_v1_create_inhibitor(priv->idle_inhibit_manager, surface); +} + +static void global_registry_handler(void* data, struct wl_registry* registry, uint32_t id, + const char* interface, uint32_t version) { + AstalInhibitManager* self = ASTAL_INHIBIT_MANAGER(data); + AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self); + + if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) { + priv->idle_inhibit_manager = + wl_registry_bind(registry, id, &zwp_idle_inhibit_manager_v1_interface, 1); + } +} + +static void global_registry_remover(void* data, struct wl_registry* registry, uint32_t id) { + // neither inhibit_manager nor inhibitor is going to be removed by the compositor, so we don't + // need do anything here. +} + +static const struct wl_registry_listener registry_listener = {global_registry_handler, + global_registry_remover}; + +static gboolean astal_inhibit_manager_wayland_init(AstalInhibitManager* self) { + AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self); + + if (priv->init) return TRUE; + + GdkDisplay* gdk_display = gdk_display_get_default(); + priv->display = gdk_wayland_display_get_wl_display(gdk_display); + + priv->wl_registry = wl_display_get_registry(priv->display); + wl_registry_add_listener(priv->wl_registry, ®istry_listener, self); + + wl_display_roundtrip(priv->display); + + if (priv->idle_inhibit_manager == NULL) { + g_critical("Can not connect idle inhibitor protocol"); + return FALSE; + } + + priv->init = TRUE; + return TRUE; +} + +AstalInhibitManager* astal_inhibit_manager_get_default() { + static AstalInhibitManager* self = NULL; + + if (self == NULL) { + self = g_object_new(ASTAL_TYPE_INHIBIT_MANAGER, NULL); + if (!astal_inhibit_manager_wayland_init(self)) { + g_object_unref(self); + self = NULL; + } + } + + return self; +} + +static void astal_inhibit_manager_init(AstalInhibitManager* self) { + AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self); + priv->init = FALSE; + priv->display = NULL; + priv->wl_registry = NULL; + priv->idle_inhibit_manager = NULL; +} + +static void astal_inhibit_manager_finalize(GObject* object) { + AstalInhibitManager* self = ASTAL_INHIBIT_MANAGER(object); + AstalInhibitManagerPrivate* priv = astal_inhibit_manager_get_instance_private(self); + + if (priv->display != NULL) wl_display_roundtrip(priv->display); + + if (priv->wl_registry != NULL) wl_registry_destroy(priv->wl_registry); + if (priv->idle_inhibit_manager != NULL) + zwp_idle_inhibit_manager_v1_destroy(priv->idle_inhibit_manager); + + G_OBJECT_CLASS(astal_inhibit_manager_parent_class)->finalize(object); +} + +static void astal_inhibit_manager_class_init(AstalInhibitManagerClass* class) { + GObjectClass* object_class = G_OBJECT_CLASS(class); + object_class->finalize = astal_inhibit_manager_finalize; +} diff --git a/core/src/idle-inhibit.h b/core/src/idle-inhibit.h new file mode 100644 index 0000000..5e9a3ab --- /dev/null +++ b/core/src/idle-inhibit.h @@ -0,0 +1,22 @@ +#ifndef ASTAL_IDLE_INHIBITOR_H +#define ASTAL_IDLE_INHIBITOR_H + +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "idle-inhibit-unstable-v1-client.h" + +G_BEGIN_DECLS + +#define ASTAL_TYPE_INHIBIT_MANAGER (astal_inhibit_manager_get_type()) + +G_DECLARE_FINAL_TYPE(AstalInhibitManager, astal_inhibit_manager, ASTAL, INHIBIT_MANAGER, GObject) + +typedef struct zwp_idle_inhibitor_v1 AstalInhibitor; + +AstalInhibitManager* astal_inhibit_manager_get_default(); +AstalInhibitor* astal_inhibit_manager_inhibit(AstalInhibitManager* self, GtkWindow* window); + +G_END_DECLS + +#endif // !ASTAL_IDLE_INHIBITOR_H diff --git a/core/src/meson.build b/core/src/meson.build index d7d3871..b5adda2 100644 --- a/core/src/meson.build +++ b/core/src/meson.build @@ -3,6 +3,9 @@ api_version = version_split[0] + '.' + version_split[1] gir = 'Astal-' + api_version + '.gir' typelib = 'Astal-' + api_version + '.typelib' +vapi_dir = meson.current_source_dir() / 'vapi' +add_project_arguments(['--vapidir', vapi_dir], language: 'vala') + config = configure_file( input: 'config.vala.in', output: 'config.vala', @@ -22,10 +25,41 @@ pkgconfig_deps = [ dependency('gtk+-3.0'), dependency('gdk-pixbuf-2.0'), dependency('gtk-layer-shell-0'), + dependency('wayland-client'), ] deps = pkgconfig_deps + meson.get_compiler('c').find_library('m') + +wayland_protos = dependency('wayland-protocols') +wayland_scanner = find_program('wayland-scanner') + +wl_protocol_dir = wayland_protos.get_variable(pkgconfig: 'pkgdatadir') + +gen_client_header = generator( + wayland_scanner, + output: ['@[email protected]'], + arguments: ['-c', 'client-header', '@INPUT@', '@BUILD_DIR@/@[email protected]'], +) + +gen_private_code = generator( + wayland_scanner, + output: ['@[email protected]'], + arguments: ['-c', 'private-code', '@INPUT@', '@BUILD_DIR@/@[email protected]'], +) + +protocols = [ + join_paths(wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml') +] + +client_protocol_srcs = [] + +foreach protocol : protocols + client_header = gen_client_header.process(protocol) + code = gen_private_code.process(protocol) + client_protocol_srcs += [client_header, code] +endforeach + sources = [ config, 'widget/box.vala', @@ -47,13 +81,16 @@ sources = [ 'process.vala', 'time.vala', 'variable.vala', -] + 'idle-inhibit.h', + 'idle-inhibit.c', +] + client_protocol_srcs if get_option('lib') lib = library( meson.project_name(), sources, dependencies: deps, + vala_args: ['--pkg', 'AstalInhibitManager'], vala_header: meson.project_name() + '.h', vala_vapi: meson.project_name() + '-' + api_version + '.vapi', vala_gir: gir, @@ -92,6 +129,7 @@ if get_option('cli') executable( meson.project_name(), ['cli.vala', sources], + vala_args: ['--pkg', 'AstalInhibitManager'], dependencies: deps, install: true, ) diff --git a/core/src/vapi/AstalInhibitManager.vapi b/core/src/vapi/AstalInhibitManager.vapi new file mode 100644 index 0000000..6232a3c --- /dev/null +++ b/core/src/vapi/AstalInhibitManager.vapi @@ -0,0 +1,13 @@ +[CCode (cprefix = "Astal", gir_namespace = "Astal", lower_case_cprefix = "astal_")] +namespace Astal { + [CCode (cheader_filename = "idle-inhibit.h", type_id = "astal_idle_inhibit_manager_get_type()")] + public class InhibitManager : GLib.Object { + public static unowned InhibitManager? get_default(); + public Inhibitor inhibit (Gtk.Window window); + } + + [CCode (cheader_filename = "idle-inhibit.h", free_function = "zwp_idle_inhibitor_v1_destroy")] + [Compact] + public class Inhibitor { + } +} diff --git a/core/src/widget/window.vala b/core/src/widget/window.vala index 17dc76d..f1a377f 100644 --- a/core/src/widget/window.vala +++ b/core/src/widget/window.vala @@ -38,6 +38,9 @@ public class Window : Gtk.Window { return false; } + private InhibitManager? inhibit_manager; + private Inhibitor? inhibitor; + construct { if (check("initialize layer shell")) return; @@ -45,6 +48,31 @@ public class Window : Gtk.Window { height_request = 1; width_request = 1; init_for_window(this); + inhibit_manager = InhibitManager.get_default(); + } + + public bool inhibit { + set { + if (inhibit_manager == null) { + return; + } + if (value && inhibitor == null) { + inhibitor = inhibit_manager.inhibit(this); + } + else if (!value && inhibitor != null) { + inhibitor = null; + } + } + get { + return inhibitor != null; + } + } + + public override void show() { + base.show(); + if(inhibit) { + inhibitor = inhibit_manager.inhibit(this); + } } public string namespace { |