mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2025-09-09 12:45:00 +00:00
add dbus patch
This commit is contained in:
parent
e7752b138a
commit
1124835f97
23
patches/dbus/README.md
Normal file
23
patches/dbus/README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
### Description
|
||||||
|
Implements a dbus service provider for Gnome-based enviroment.
|
||||||
|
|
||||||
|
### Download
|
||||||
|
- [main 2024-12-30](/icedman/dwl/raw/branch/dbus-patch/patches/dbus/dbus.patch)
|
||||||
|
|
||||||
|
### Author
|
||||||
|
- [icedman](https://codeberg.org/icedman)
|
||||||
|
|
||||||
|
### DBus Methods
|
||||||
|
- GetWindows() -> windows
|
||||||
|
- FocusWindow(window)
|
||||||
|
- CloseWindow(window)
|
||||||
|
- QuitApp(appid)
|
||||||
|
|
||||||
|
### Signals
|
||||||
|
- WindowOpen -> window
|
||||||
|
- WindowFocused -> window
|
||||||
|
- WindowClosed -> window
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
- Count (number of active windows)
|
||||||
|
|
903
patches/dbus/dbus.patch
Normal file
903
patches/dbus/dbus.patch
Normal file
@ -0,0 +1,903 @@
|
|||||||
|
From 62f3e56dee9471403addc6e8741aaf19e561dce3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: icedman <m4rvin2005@gmail.com>
|
||||||
|
Date: Mon, 30 Dec 2024 00:03:36 +0800
|
||||||
|
Subject: [PATCH 1/4] add dbus service
|
||||||
|
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
dwl.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 282 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 578194f..5df8984 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \
|
||||||
|
-Wfloat-conversion
|
||||||
|
|
||||||
|
# CFLAGS / LDFLAGS
|
||||||
|
-PKGS = wayland-server xkbcommon libinput $(XLIBS)
|
||||||
|
+PKGS = wayland-server xkbcommon libinput gio-2.0 glib-2.0 $(XLIBS)
|
||||||
|
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
|
||||||
|
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 0eba3e9..46d25cb 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -68,6 +68,9 @@
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#include <gio/gio.h>
|
||||||
|
+#include <glib.h>
|
||||||
|
+
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* macros */
|
||||||
|
@@ -243,6 +246,50 @@ typedef struct {
|
||||||
|
struct wl_listener destroy;
|
||||||
|
} SessionLock;
|
||||||
|
|
||||||
|
+typedef struct {
|
||||||
|
+ GMainContext *context;
|
||||||
|
+ GMainLoop *loop;
|
||||||
|
+ guint owner_id;
|
||||||
|
+ void* timer;
|
||||||
|
+ int interval;
|
||||||
|
+
|
||||||
|
+ GDBusConnection *connection;
|
||||||
|
+ gchar *property_message;
|
||||||
|
+ gint property_count;
|
||||||
|
+} DBusService;
|
||||||
|
+
|
||||||
|
+static DBusService *dbus;
|
||||||
|
+
|
||||||
|
+static GDBusNodeInfo *introspection_data = NULL;
|
||||||
|
+
|
||||||
|
+const gchar *introspection_xml =
|
||||||
|
+ "<node>"
|
||||||
|
+ " <interface name='com.dwl.DBus.Interface'>"
|
||||||
|
+ " <method name='FocusWindow'>"
|
||||||
|
+ " <arg type='s' name='window' direction='in'/>"
|
||||||
|
+ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
+ " </method>"
|
||||||
|
+ " <method name='GetWindows'>"
|
||||||
|
+ " <arg type='s' name='windows' direction='out'/>"
|
||||||
|
+ " </method>"
|
||||||
|
+ " <property name='Message' type='s' access='readwrite'/>"
|
||||||
|
+ " <property name='Count' type='i' access='read'/>"
|
||||||
|
+ " <signal name='WindowFocused'>"
|
||||||
|
+ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
+ " </signal>"
|
||||||
|
+ " <signal name='WindowOpened'>"
|
||||||
|
+ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
+ " </signal>"
|
||||||
|
+ " <signal name='WindowClosed'>"
|
||||||
|
+ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
+ " </signal>"
|
||||||
|
+ " </interface>"
|
||||||
|
+ "</node>";
|
||||||
|
+
|
||||||
|
+#define SERVICE_NAME "com.dwl.DBus"
|
||||||
|
+#define OBJECT_PATH "/com/dwl/DBus"
|
||||||
|
+#define INTERFACE_NAME "com.dwl.DBus.Interface"
|
||||||
|
+
|
||||||
|
/* function declarations */
|
||||||
|
static void applybounds(Client *c, struct wlr_box *bbox);
|
||||||
|
static void applyrules(Client *c);
|
||||||
|
@@ -356,6 +403,39 @@ static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
static void zoom(const Arg *arg);
|
||||||
|
|
||||||
|
+
|
||||||
|
+static void dbus_on_name_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+static void dbus_on_name_lost(GDBusConnection *connection, const gchar *name,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+static void dbus_on_bus_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+static int dbus_service_update(void *data);
|
||||||
|
+static int dbus_service_init(void);
|
||||||
|
+static void dbus_service_cleanup(void);
|
||||||
|
+
|
||||||
|
+// Method handler
|
||||||
|
+static void dbus_handle_method_call(GDBusConnection *connection, const gchar *sender,
|
||||||
|
+ const gchar *object_path,
|
||||||
|
+ const gchar *interface_name,
|
||||||
|
+ const gchar *method_name, GVariant *parameters,
|
||||||
|
+ GDBusMethodInvocation *invocation,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+// Property handlers
|
||||||
|
+static GVariant *dbus_get_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
+ const gchar *object_path,
|
||||||
|
+ const gchar *interface_name,
|
||||||
|
+ const gchar *property_name, GError **error,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+static gboolean dbus_set_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
+ const gchar *object_path,
|
||||||
|
+ const gchar *interface_name,
|
||||||
|
+ const gchar *property_name, GVariant *value,
|
||||||
|
+ GError **error, gpointer user_data);
|
||||||
|
+
|
||||||
|
+// Emit the MessageChanged signal
|
||||||
|
+static void dbus_emit_client_signal(GDBusConnection *connection, const char* signal, Client *c);
|
||||||
|
+
|
||||||
|
/* variables */
|
||||||
|
static pid_t child_pid = -1;
|
||||||
|
static int locked;
|
||||||
|
@@ -424,6 +504,13 @@ static struct wlr_xwayland *xwayland;
|
||||||
|
static xcb_atom_t netatom[NetLast];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+// VTable
|
||||||
|
+static const GDBusInterfaceVTable interface_vtable = {
|
||||||
|
+ .method_call = dbus_handle_method_call,
|
||||||
|
+ .get_property = dbus_get_property,
|
||||||
|
+ .set_property = dbus_set_property,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* configuration, allows nested code to access above variables */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
@@ -670,6 +757,8 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||||
|
void
|
||||||
|
cleanup(void)
|
||||||
|
{
|
||||||
|
+ dbus_service_cleanup();
|
||||||
|
+
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
wlr_xwayland_destroy(xwayland);
|
||||||
|
xwayland = NULL;
|
||||||
|
@@ -1404,6 +1493,8 @@ focusclient(Client *c, int lift)
|
||||||
|
|
||||||
|
/* Activate the new client */
|
||||||
|
client_activate_surface(client_surface(c), 1);
|
||||||
|
+
|
||||||
|
+ dbus_emit_client_signal(dbus->connection, "WindowFocused", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -1737,6 +1828,8 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
}
|
||||||
|
printstatus();
|
||||||
|
|
||||||
|
+ dbus_emit_client_signal(dbus->connection, "WindowOpened", c);
|
||||||
|
+
|
||||||
|
unset_fullscreen:
|
||||||
|
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
||||||
|
wl_list_for_each(w, &clients, link) {
|
||||||
|
@@ -2604,6 +2697,8 @@ setup(void)
|
||||||
|
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
+
|
||||||
|
+ dbus_service_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -2755,6 +2850,7 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
/* Called when the surface is unmapped, and should no longer be shown. */
|
||||||
|
Client *c = wl_container_of(listener, c, unmap);
|
||||||
|
+ dbus_emit_client_signal(dbus->connection, "WindowClosed", c);
|
||||||
|
if (c == grabc) {
|
||||||
|
cursor_mode = CurNormal;
|
||||||
|
grabc = NULL;
|
||||||
|
@@ -3151,6 +3247,191 @@ xwaylandready(struct wl_listener *listener, void *data)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+GString* gstring_append_client_json(GString *gstring, Client *c) {
|
||||||
|
+ const char *appid, *title;
|
||||||
|
+ const char *fmt = "{ \"id\": \"0x%x\", \"title\": \"%s\", \"app_id\": \"%s\" }";
|
||||||
|
+
|
||||||
|
+ GString *gstringTemp = g_string_new("");
|
||||||
|
+ appid = client_get_appid(c);
|
||||||
|
+ title = client_get_title(c);
|
||||||
|
+ g_string_assign(gstringTemp, title);
|
||||||
|
+ g_string_replace(gstringTemp, "\"", "'", 0);
|
||||||
|
+ g_string_append_printf(gstring, fmt, c, gstringTemp->str, appid);
|
||||||
|
+
|
||||||
|
+ g_string_free(gstringTemp, TRUE);
|
||||||
|
+ return gstring;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void dbus_handle_method_call(GDBusConnection *connection, const gchar *sender,
|
||||||
|
+ const gchar *object_path,
|
||||||
|
+ const gchar *interface_name,
|
||||||
|
+ const gchar *method_name, GVariant *parameters,
|
||||||
|
+ GDBusMethodInvocation *invocation,
|
||||||
|
+ gpointer user_data) {
|
||||||
|
+ if (g_strcmp0(method_name, "GetWindows") == 0) {
|
||||||
|
+ const char *response = "Hello from D-Bus!";
|
||||||
|
+ g_print("HelloWorld method called by %s\n", sender);
|
||||||
|
+
|
||||||
|
+ Client *c = NULL;
|
||||||
|
+ GString *gstring = g_string_new("[");
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ gstring_append_client_json(gstring, c);
|
||||||
|
+ if (c->link.next != &clients) {
|
||||||
|
+ g_string_append_printf(gstring, ",");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ g_string_append_printf(gstring, "]");
|
||||||
|
+ g_dbus_method_invocation_return_value(invocation,
|
||||||
|
+ g_variant_new("(s)", gstring->str));
|
||||||
|
+ g_string_free(gstring, TRUE);
|
||||||
|
+ } else if (g_strcmp0(method_name, "FocusWindow") == 0) {
|
||||||
|
+ const gchar *window;
|
||||||
|
+ g_variant_get(parameters, "(s)", &window);
|
||||||
|
+
|
||||||
|
+ uintptr_t address = strtol(window, NULL, 16); // Base 16 for hexadecimal
|
||||||
|
+ Client *c = NULL;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ if ((uintptr_t)c == address) {
|
||||||
|
+ focusclient(c, true);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // g_print("focus %s\n", window);
|
||||||
|
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", window));
|
||||||
|
+ g_free(window);
|
||||||
|
+
|
||||||
|
+ } else {
|
||||||
|
+ g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
|
||||||
|
+ G_DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
+ "Unknown method: %s", method_name);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static GVariant *dbus_get_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
+ const gchar *object_path,
|
||||||
|
+ const gchar *interface_name,
|
||||||
|
+ const gchar *property_name, GError **error,
|
||||||
|
+ gpointer user_data) {
|
||||||
|
+ if (g_strcmp0(property_name, "Message") == 0) {
|
||||||
|
+ return g_variant_new_string(dbus->property_message ? dbus->property_message
|
||||||
|
+ : "Default Message");
|
||||||
|
+ } else if (g_strcmp0(property_name, "Count") == 0) {
|
||||||
|
+ dbus->property_count = 0;
|
||||||
|
+ // Monitor *m = NULL;
|
||||||
|
+ // wl_list_for_each(m, &mons, link) {
|
||||||
|
+ // dbus->property_count++;
|
||||||
|
+ // }
|
||||||
|
+
|
||||||
|
+ Client *c = NULL;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ dbus->property_count++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return g_variant_new_int32(dbus->property_count);
|
||||||
|
+ }
|
||||||
|
+ return NULL; // Property not found
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static gboolean dbus_set_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
+ const gchar *object_path,
|
||||||
|
+ const gchar *interface_name,
|
||||||
|
+ const gchar *property_name, GVariant *value,
|
||||||
|
+ GError **error, gpointer user_data) {
|
||||||
|
+ if (g_strcmp0(property_name, "Message") == 0) {
|
||||||
|
+ g_free(dbus->property_message);
|
||||||
|
+ dbus->property_message = g_strdup(g_variant_get_string(value, NULL));
|
||||||
|
+ return TRUE;
|
||||||
|
+ }
|
||||||
|
+ g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_PROPERTY_READ_ONLY,
|
||||||
|
+ "The 'Count' property is read-only.");
|
||||||
|
+ return FALSE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void dbus_emit_client_signal(GDBusConnection *connection, const char* signal, Client *c) {
|
||||||
|
+ g_print("emit %s\n", signal);
|
||||||
|
+ GString *gstring = g_string_new("");
|
||||||
|
+ gstring_append_client_json(gstring, c);
|
||||||
|
+
|
||||||
|
+ g_dbus_connection_emit_signal(connection,
|
||||||
|
+ NULL, // No sender (broadcast to all clients)
|
||||||
|
+ OBJECT_PATH, // Object path
|
||||||
|
+ INTERFACE_NAME, // Interface name
|
||||||
|
+ signal, // Signal name
|
||||||
|
+ g_variant_new("(s)", gstring->str), // Arguments
|
||||||
|
+ NULL); // No error
|
||||||
|
+ g_string_free(gstring, TRUE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void dbus_on_name_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
+ gpointer user_data) {
|
||||||
|
+ g_print("Service name '%s' acquired.\n", SERVICE_NAME);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void dbus_on_name_lost(GDBusConnection *connection, const gchar *name,
|
||||||
|
+ gpointer user_data) {
|
||||||
|
+ g_print("Service name '%s' lost.\n", SERVICE_NAME);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void dbus_on_bus_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
+ gpointer user_data) {
|
||||||
|
+ GError *error = NULL;
|
||||||
|
+
|
||||||
|
+ // Register the object
|
||||||
|
+ guint registration_id = g_dbus_connection_register_object(
|
||||||
|
+ connection, OBJECT_PATH, introspection_data->interfaces[0],
|
||||||
|
+ &interface_vtable,
|
||||||
|
+ NULL, // user data
|
||||||
|
+ NULL, // user data free function
|
||||||
|
+ &error);
|
||||||
|
+
|
||||||
|
+ if (registration_id == 0) {
|
||||||
|
+ g_printerr("Failed to register object: %s\n", error->message);
|
||||||
|
+ g_error_free(error);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dbus->connection = connection;
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int dbus_service_update(void *data)
|
||||||
|
+{
|
||||||
|
+ g_main_context_iteration(dbus->context, FALSE);
|
||||||
|
+ wl_event_source_timer_update(dbus->timer, dbus->interval);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int dbus_service_init(void) {
|
||||||
|
+ dbus = ecalloc(1, sizeof(DBusService));
|
||||||
|
+ DBusService *d = dbus;
|
||||||
|
+ d->interval = 150;
|
||||||
|
+ d->property_message = NULL;
|
||||||
|
+ d->property_count = 0;
|
||||||
|
+
|
||||||
|
+ d->loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
+ d->context = g_main_loop_get_context(d->loop);
|
||||||
|
+
|
||||||
|
+ dbus->timer = wl_event_loop_add_timer(event_loop, dbus_service_update, dbus);
|
||||||
|
+
|
||||||
|
+ // Create introspection data
|
||||||
|
+ introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
||||||
|
+
|
||||||
|
+ // Acquire the bus name
|
||||||
|
+ d->owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, SERVICE_NAME,
|
||||||
|
+ G_BUS_NAME_OWNER_FLAGS_NONE, dbus_on_bus_acquired,
|
||||||
|
+ dbus_on_name_acquired, dbus_on_name_lost, NULL, NULL);
|
||||||
|
+
|
||||||
|
+ wl_event_source_timer_update(dbus->timer, dbus->interval);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void dbus_service_cleanup(void) {
|
||||||
|
+ g_bus_unown_name(dbus->owner_id);
|
||||||
|
+ g_main_loop_unref(dbus->loop);
|
||||||
|
+ g_dbus_node_info_unref(introspection_data);
|
||||||
|
+ free(dbus);
|
||||||
|
+ dbus = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.47.1
|
||||||
|
|
||||||
|
|
||||||
|
From 735481c04d7caed712990e7b005badbeb8a622b0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: icedman <m4rvin2005@gmail.com>
|
||||||
|
Date: Mon, 30 Dec 2024 00:33:15 +0800
|
||||||
|
Subject: [PATCH 2/4] add patch
|
||||||
|
|
||||||
|
---
|
||||||
|
patches/dbus/README.md | 8 +
|
||||||
|
patches/dbus/dbus.patch | 381 ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 389 insertions(+)
|
||||||
|
create mode 100644 patches/dbus/README.md
|
||||||
|
create mode 100644 patches/dbus/dbus.patch
|
||||||
|
|
||||||
|
diff --git a/patches/dbus/README.md b/patches/dbus/README.md
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..234223b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/patches/dbus/README.md
|
||||||
|
@@ -0,0 +1,8 @@
|
||||||
|
+### Description
|
||||||
|
+Implements a dbus service provider for Gnome-based enviroment.
|
||||||
|
+
|
||||||
|
+### Download
|
||||||
|
+- [main 2024-12-30](/icedman/dwl/raw/branch/dbus-patch/patches/dbus/dbus.patch)
|
||||||
|
+
|
||||||
|
+### Author
|
||||||
|
+- [icedman](https://codeberg.org/icedman)
|
||||||
|
diff --git a/patches/dbus/dbus.patch b/patches/dbus/dbus.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..3f8e984
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/patches/dbus/dbus.patch
|
||||||
|
@@ -0,0 +1,381 @@
|
||||||
|
+From 62f3e56dee9471403addc6e8741aaf19e561dce3 Mon Sep 17 00:00:00 2001
|
||||||
|
+From: icedman <m4rvin2005@gmail.com>
|
||||||
|
+Date: Mon, 30 Dec 2024 00:03:36 +0800
|
||||||
|
+Subject: [PATCH] add dbus service
|
||||||
|
+
|
||||||
|
+---
|
||||||
|
+ Makefile | 2 +-
|
||||||
|
+ dwl.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
+ 2 files changed, 282 insertions(+), 1 deletion(-)
|
||||||
|
+
|
||||||
|
+diff --git a/Makefile b/Makefile
|
||||||
|
+index 578194f..5df8984 100644
|
||||||
|
+--- a/Makefile
|
||||||
|
++++ b/Makefile
|
||||||
|
+@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \
|
||||||
|
+ -Wfloat-conversion
|
||||||
|
+
|
||||||
|
+ # CFLAGS / LDFLAGS
|
||||||
|
+-PKGS = wayland-server xkbcommon libinput $(XLIBS)
|
||||||
|
++PKGS = wayland-server xkbcommon libinput gio-2.0 glib-2.0 $(XLIBS)
|
||||||
|
+ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
|
||||||
|
+ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
|
||||||
|
+
|
||||||
|
+diff --git a/dwl.c b/dwl.c
|
||||||
|
+index 0eba3e9..46d25cb 100644
|
||||||
|
+--- a/dwl.c
|
||||||
|
++++ b/dwl.c
|
||||||
|
+@@ -68,6 +68,9 @@
|
||||||
|
+ #include <xcb/xcb_icccm.h>
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
++#include <gio/gio.h>
|
||||||
|
++#include <glib.h>
|
||||||
|
++
|
||||||
|
+ #include "util.h"
|
||||||
|
+
|
||||||
|
+ /* macros */
|
||||||
|
+@@ -243,6 +246,50 @@ typedef struct {
|
||||||
|
+ struct wl_listener destroy;
|
||||||
|
+ } SessionLock;
|
||||||
|
+
|
||||||
|
++typedef struct {
|
||||||
|
++ GMainContext *context;
|
||||||
|
++ GMainLoop *loop;
|
||||||
|
++ guint owner_id;
|
||||||
|
++ void* timer;
|
||||||
|
++ int interval;
|
||||||
|
++
|
||||||
|
++ GDBusConnection *connection;
|
||||||
|
++ gchar *property_message;
|
||||||
|
++ gint property_count;
|
||||||
|
++} DBusService;
|
||||||
|
++
|
||||||
|
++static DBusService *dbus;
|
||||||
|
++
|
||||||
|
++static GDBusNodeInfo *introspection_data = NULL;
|
||||||
|
++
|
||||||
|
++const gchar *introspection_xml =
|
||||||
|
++ "<node>"
|
||||||
|
++ " <interface name='com.dwl.DBus.Interface'>"
|
||||||
|
++ " <method name='FocusWindow'>"
|
||||||
|
++ " <arg type='s' name='window' direction='in'/>"
|
||||||
|
++ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
++ " </method>"
|
||||||
|
++ " <method name='GetWindows'>"
|
||||||
|
++ " <arg type='s' name='windows' direction='out'/>"
|
||||||
|
++ " </method>"
|
||||||
|
++ " <property name='Message' type='s' access='readwrite'/>"
|
||||||
|
++ " <property name='Count' type='i' access='read'/>"
|
||||||
|
++ " <signal name='WindowFocused'>"
|
||||||
|
++ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
++ " </signal>"
|
||||||
|
++ " <signal name='WindowOpened'>"
|
||||||
|
++ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
++ " </signal>"
|
||||||
|
++ " <signal name='WindowClosed'>"
|
||||||
|
++ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
++ " </signal>"
|
||||||
|
++ " </interface>"
|
||||||
|
++ "</node>";
|
||||||
|
++
|
||||||
|
++#define SERVICE_NAME "com.dwl.DBus"
|
||||||
|
++#define OBJECT_PATH "/com/dwl/DBus"
|
||||||
|
++#define INTERFACE_NAME "com.dwl.DBus.Interface"
|
||||||
|
++
|
||||||
|
+ /* function declarations */
|
||||||
|
+ static void applybounds(Client *c, struct wlr_box *bbox);
|
||||||
|
+ static void applyrules(Client *c);
|
||||||
|
+@@ -356,6 +403,39 @@ static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
|
+ Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
+ static void zoom(const Arg *arg);
|
||||||
|
+
|
||||||
|
++
|
||||||
|
++static void dbus_on_name_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
++ gpointer user_data);
|
||||||
|
++static void dbus_on_name_lost(GDBusConnection *connection, const gchar *name,
|
||||||
|
++ gpointer user_data);
|
||||||
|
++static void dbus_on_bus_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
++ gpointer user_data);
|
||||||
|
++static int dbus_service_update(void *data);
|
||||||
|
++static int dbus_service_init(void);
|
||||||
|
++static void dbus_service_cleanup(void);
|
||||||
|
++
|
||||||
|
++// Method handler
|
||||||
|
++static void dbus_handle_method_call(GDBusConnection *connection, const gchar *sender,
|
||||||
|
++ const gchar *object_path,
|
||||||
|
++ const gchar *interface_name,
|
||||||
|
++ const gchar *method_name, GVariant *parameters,
|
||||||
|
++ GDBusMethodInvocation *invocation,
|
||||||
|
++ gpointer user_data);
|
||||||
|
++// Property handlers
|
||||||
|
++static GVariant *dbus_get_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
++ const gchar *object_path,
|
||||||
|
++ const gchar *interface_name,
|
||||||
|
++ const gchar *property_name, GError **error,
|
||||||
|
++ gpointer user_data);
|
||||||
|
++static gboolean dbus_set_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
++ const gchar *object_path,
|
||||||
|
++ const gchar *interface_name,
|
||||||
|
++ const gchar *property_name, GVariant *value,
|
||||||
|
++ GError **error, gpointer user_data);
|
||||||
|
++
|
||||||
|
++// Emit the MessageChanged signal
|
||||||
|
++static void dbus_emit_client_signal(GDBusConnection *connection, const char* signal, Client *c);
|
||||||
|
++
|
||||||
|
+ /* variables */
|
||||||
|
+ static pid_t child_pid = -1;
|
||||||
|
+ static int locked;
|
||||||
|
+@@ -424,6 +504,13 @@ static struct wlr_xwayland *xwayland;
|
||||||
|
+ static xcb_atom_t netatom[NetLast];
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
++// VTable
|
||||||
|
++static const GDBusInterfaceVTable interface_vtable = {
|
||||||
|
++ .method_call = dbus_handle_method_call,
|
||||||
|
++ .get_property = dbus_get_property,
|
||||||
|
++ .set_property = dbus_set_property,
|
||||||
|
++};
|
||||||
|
++
|
||||||
|
+ /* configuration, allows nested code to access above variables */
|
||||||
|
+ #include "config.h"
|
||||||
|
+
|
||||||
|
+@@ -670,6 +757,8 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||||
|
+ void
|
||||||
|
+ cleanup(void)
|
||||||
|
+ {
|
||||||
|
++ dbus_service_cleanup();
|
||||||
|
++
|
||||||
|
+ #ifdef XWAYLAND
|
||||||
|
+ wlr_xwayland_destroy(xwayland);
|
||||||
|
+ xwayland = NULL;
|
||||||
|
+@@ -1404,6 +1493,8 @@ focusclient(Client *c, int lift)
|
||||||
|
+
|
||||||
|
+ /* Activate the new client */
|
||||||
|
+ client_activate_surface(client_surface(c), 1);
|
||||||
|
++
|
||||||
|
++ dbus_emit_client_signal(dbus->connection, "WindowFocused", c);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ void
|
||||||
|
+@@ -1737,6 +1828,8 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
+ }
|
||||||
|
+ printstatus();
|
||||||
|
+
|
||||||
|
++ dbus_emit_client_signal(dbus->connection, "WindowOpened", c);
|
||||||
|
++
|
||||||
|
+ unset_fullscreen:
|
||||||
|
+ m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
||||||
|
+ wl_list_for_each(w, &clients, link) {
|
||||||
|
+@@ -2604,6 +2697,8 @@ setup(void)
|
||||||
|
+ fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
|
||||||
|
+ }
|
||||||
|
+ #endif
|
||||||
|
++
|
||||||
|
++ dbus_service_init();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ void
|
||||||
|
+@@ -2755,6 +2850,7 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||||
|
+ {
|
||||||
|
+ /* Called when the surface is unmapped, and should no longer be shown. */
|
||||||
|
+ Client *c = wl_container_of(listener, c, unmap);
|
||||||
|
++ dbus_emit_client_signal(dbus->connection, "WindowClosed", c);
|
||||||
|
+ if (c == grabc) {
|
||||||
|
+ cursor_mode = CurNormal;
|
||||||
|
+ grabc = NULL;
|
||||||
|
+@@ -3151,6 +3247,191 @@ xwaylandready(struct wl_listener *listener, void *data)
|
||||||
|
+ }
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
++GString* gstring_append_client_json(GString *gstring, Client *c) {
|
||||||
|
++ const char *appid, *title;
|
||||||
|
++ const char *fmt = "{ \"id\": \"0x%x\", \"title\": \"%s\", \"app_id\": \"%s\" }";
|
||||||
|
++
|
||||||
|
++ GString *gstringTemp = g_string_new("");
|
||||||
|
++ appid = client_get_appid(c);
|
||||||
|
++ title = client_get_title(c);
|
||||||
|
++ g_string_assign(gstringTemp, title);
|
||||||
|
++ g_string_replace(gstringTemp, "\"", "'", 0);
|
||||||
|
++ g_string_append_printf(gstring, fmt, c, gstringTemp->str, appid);
|
||||||
|
++
|
||||||
|
++ g_string_free(gstringTemp, TRUE);
|
||||||
|
++ return gstring;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static void dbus_handle_method_call(GDBusConnection *connection, const gchar *sender,
|
||||||
|
++ const gchar *object_path,
|
||||||
|
++ const gchar *interface_name,
|
||||||
|
++ const gchar *method_name, GVariant *parameters,
|
||||||
|
++ GDBusMethodInvocation *invocation,
|
||||||
|
++ gpointer user_data) {
|
||||||
|
++ if (g_strcmp0(method_name, "GetWindows") == 0) {
|
||||||
|
++ const char *response = "Hello from D-Bus!";
|
||||||
|
++ g_print("HelloWorld method called by %s\n", sender);
|
||||||
|
++
|
||||||
|
++ Client *c = NULL;
|
||||||
|
++ GString *gstring = g_string_new("[");
|
||||||
|
++ wl_list_for_each(c, &clients, link) {
|
||||||
|
++ gstring_append_client_json(gstring, c);
|
||||||
|
++ if (c->link.next != &clients) {
|
||||||
|
++ g_string_append_printf(gstring, ",");
|
||||||
|
++ }
|
||||||
|
++ }
|
||||||
|
++ g_string_append_printf(gstring, "]");
|
||||||
|
++ g_dbus_method_invocation_return_value(invocation,
|
||||||
|
++ g_variant_new("(s)", gstring->str));
|
||||||
|
++ g_string_free(gstring, TRUE);
|
||||||
|
++ } else if (g_strcmp0(method_name, "FocusWindow") == 0) {
|
||||||
|
++ const gchar *window;
|
||||||
|
++ g_variant_get(parameters, "(s)", &window);
|
||||||
|
++
|
||||||
|
++ uintptr_t address = strtol(window, NULL, 16); // Base 16 for hexadecimal
|
||||||
|
++ Client *c = NULL;
|
||||||
|
++ wl_list_for_each(c, &clients, link) {
|
||||||
|
++ if ((uintptr_t)c == address) {
|
||||||
|
++ focusclient(c, true);
|
||||||
|
++ }
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ // g_print("focus %s\n", window);
|
||||||
|
++ g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", window));
|
||||||
|
++ g_free(window);
|
||||||
|
++
|
||||||
|
++ } else {
|
||||||
|
++ g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
|
||||||
|
++ G_DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
++ "Unknown method: %s", method_name);
|
||||||
|
++ }
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static GVariant *dbus_get_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
++ const gchar *object_path,
|
||||||
|
++ const gchar *interface_name,
|
||||||
|
++ const gchar *property_name, GError **error,
|
||||||
|
++ gpointer user_data) {
|
||||||
|
++ if (g_strcmp0(property_name, "Message") == 0) {
|
||||||
|
++ return g_variant_new_string(dbus->property_message ? dbus->property_message
|
||||||
|
++ : "Default Message");
|
||||||
|
++ } else if (g_strcmp0(property_name, "Count") == 0) {
|
||||||
|
++ dbus->property_count = 0;
|
||||||
|
++ // Monitor *m = NULL;
|
||||||
|
++ // wl_list_for_each(m, &mons, link) {
|
||||||
|
++ // dbus->property_count++;
|
||||||
|
++ // }
|
||||||
|
++
|
||||||
|
++ Client *c = NULL;
|
||||||
|
++ wl_list_for_each(c, &clients, link) {
|
||||||
|
++ dbus->property_count++;
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ return g_variant_new_int32(dbus->property_count);
|
||||||
|
++ }
|
||||||
|
++ return NULL; // Property not found
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static gboolean dbus_set_property(GDBusConnection *connection, const gchar *sender,
|
||||||
|
++ const gchar *object_path,
|
||||||
|
++ const gchar *interface_name,
|
||||||
|
++ const gchar *property_name, GVariant *value,
|
||||||
|
++ GError **error, gpointer user_data) {
|
||||||
|
++ if (g_strcmp0(property_name, "Message") == 0) {
|
||||||
|
++ g_free(dbus->property_message);
|
||||||
|
++ dbus->property_message = g_strdup(g_variant_get_string(value, NULL));
|
||||||
|
++ return TRUE;
|
||||||
|
++ }
|
||||||
|
++ g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_PROPERTY_READ_ONLY,
|
||||||
|
++ "The 'Count' property is read-only.");
|
||||||
|
++ return FALSE;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static void dbus_emit_client_signal(GDBusConnection *connection, const char* signal, Client *c) {
|
||||||
|
++ g_print("emit %s\n", signal);
|
||||||
|
++ GString *gstring = g_string_new("");
|
||||||
|
++ gstring_append_client_json(gstring, c);
|
||||||
|
++
|
||||||
|
++ g_dbus_connection_emit_signal(connection,
|
||||||
|
++ NULL, // No sender (broadcast to all clients)
|
||||||
|
++ OBJECT_PATH, // Object path
|
||||||
|
++ INTERFACE_NAME, // Interface name
|
||||||
|
++ signal, // Signal name
|
||||||
|
++ g_variant_new("(s)", gstring->str), // Arguments
|
||||||
|
++ NULL); // No error
|
||||||
|
++ g_string_free(gstring, TRUE);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static void dbus_on_name_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
++ gpointer user_data) {
|
||||||
|
++ g_print("Service name '%s' acquired.\n", SERVICE_NAME);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static void dbus_on_name_lost(GDBusConnection *connection, const gchar *name,
|
||||||
|
++ gpointer user_data) {
|
||||||
|
++ g_print("Service name '%s' lost.\n", SERVICE_NAME);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static void dbus_on_bus_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
|
++ gpointer user_data) {
|
||||||
|
++ GError *error = NULL;
|
||||||
|
++
|
||||||
|
++ // Register the object
|
||||||
|
++ guint registration_id = g_dbus_connection_register_object(
|
||||||
|
++ connection, OBJECT_PATH, introspection_data->interfaces[0],
|
||||||
|
++ &interface_vtable,
|
||||||
|
++ NULL, // user data
|
||||||
|
++ NULL, // user data free function
|
||||||
|
++ &error);
|
||||||
|
++
|
||||||
|
++ if (registration_id == 0) {
|
||||||
|
++ g_printerr("Failed to register object: %s\n", error->message);
|
||||||
|
++ g_error_free(error);
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ dbus->connection = connection;
|
||||||
|
++
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static int dbus_service_update(void *data)
|
||||||
|
++{
|
||||||
|
++ g_main_context_iteration(dbus->context, FALSE);
|
||||||
|
++ wl_event_source_timer_update(dbus->timer, dbus->interval);
|
||||||
|
++ return 0;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static int dbus_service_init(void) {
|
||||||
|
++ dbus = ecalloc(1, sizeof(DBusService));
|
||||||
|
++ DBusService *d = dbus;
|
||||||
|
++ d->interval = 150;
|
||||||
|
++ d->property_message = NULL;
|
||||||
|
++ d->property_count = 0;
|
||||||
|
++
|
||||||
|
++ d->loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
++ d->context = g_main_loop_get_context(d->loop);
|
||||||
|
++
|
||||||
|
++ dbus->timer = wl_event_loop_add_timer(event_loop, dbus_service_update, dbus);
|
||||||
|
++
|
||||||
|
++ // Create introspection data
|
||||||
|
++ introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
||||||
|
++
|
||||||
|
++ // Acquire the bus name
|
||||||
|
++ d->owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, SERVICE_NAME,
|
||||||
|
++ G_BUS_NAME_OWNER_FLAGS_NONE, dbus_on_bus_acquired,
|
||||||
|
++ dbus_on_name_acquired, dbus_on_name_lost, NULL, NULL);
|
||||||
|
++
|
||||||
|
++ wl_event_source_timer_update(dbus->timer, dbus->interval);
|
||||||
|
++ return 0;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static void dbus_service_cleanup(void) {
|
||||||
|
++ g_bus_unown_name(dbus->owner_id);
|
||||||
|
++ g_main_loop_unref(dbus->loop);
|
||||||
|
++ g_dbus_node_info_unref(introspection_data);
|
||||||
|
++ free(dbus);
|
||||||
|
++ dbus = NULL;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
+ int
|
||||||
|
+ main(int argc, char *argv[])
|
||||||
|
+ {
|
||||||
|
+--
|
||||||
|
+2.47.1
|
||||||
|
+
|
||||||
|
--
|
||||||
|
2.47.1
|
||||||
|
|
||||||
|
|
||||||
|
From 958933eeb575fb59c5555cb2c37a296c42bdcd52 Mon Sep 17 00:00:00 2001
|
||||||
|
From: icedman <m4rvin2005@gmail.com>
|
||||||
|
Date: Mon, 30 Dec 2024 00:38:13 +0800
|
||||||
|
Subject: [PATCH 3/4] update README with some dbus info
|
||||||
|
|
||||||
|
---
|
||||||
|
patches/dbus/README.md | 13 +++++++++++++
|
||||||
|
1 file changed, 13 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/patches/dbus/README.md b/patches/dbus/README.md
|
||||||
|
index 234223b..2cbab54 100644
|
||||||
|
--- a/patches/dbus/README.md
|
||||||
|
+++ b/patches/dbus/README.md
|
||||||
|
@@ -6,3 +6,16 @@ Implements a dbus service provider for Gnome-based enviroment.
|
||||||
|
|
||||||
|
### Author
|
||||||
|
- [icedman](https://codeberg.org/icedman)
|
||||||
|
+
|
||||||
|
+### DBus Methods
|
||||||
|
+- GetWindows() -> windows
|
||||||
|
+- FocusWindow(window)
|
||||||
|
+
|
||||||
|
+### Signals
|
||||||
|
+- WindowOpen -> window
|
||||||
|
+- WindowFocused -> window
|
||||||
|
+- WindowClosed -> window
|
||||||
|
+
|
||||||
|
+### Properties
|
||||||
|
+- Count (number of active windows)
|
||||||
|
+
|
||||||
|
--
|
||||||
|
2.47.1
|
||||||
|
|
||||||
|
|
||||||
|
From 421fef1f0d1c583e92bb73b41b75397d9ae89e93 Mon Sep 17 00:00:00 2001
|
||||||
|
From: icedman <m4rvin2005@gmail.com>
|
||||||
|
Date: Tue, 31 Dec 2024 10:35:30 +0800
|
||||||
|
Subject: [PATCH 4/4] add closeWindow and quitApp
|
||||||
|
|
||||||
|
---
|
||||||
|
dwl.c | 40 ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 40 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 46d25cb..c4a07d0 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -269,6 +269,14 @@ const gchar *introspection_xml =
|
||||||
|
" <arg type='s' name='window' direction='in'/>"
|
||||||
|
" <arg type='s' name='window' direction='out'/>"
|
||||||
|
" </method>"
|
||||||
|
+ " <method name='CloseWindow'>"
|
||||||
|
+ " <arg type='s' name='window' direction='in'/>"
|
||||||
|
+ " <arg type='s' name='window' direction='out'/>"
|
||||||
|
+ " </method>"
|
||||||
|
+ " <method name='QuitApp'>"
|
||||||
|
+ " <arg type='s' name='appid' direction='in'/>"
|
||||||
|
+ " <arg type='s' name='appid' direction='out'/>"
|
||||||
|
+ " </method>"
|
||||||
|
" <method name='GetWindows'>"
|
||||||
|
" <arg type='s' name='windows' direction='out'/>"
|
||||||
|
" </method>"
|
||||||
|
@@ -3300,6 +3308,38 @@ static void dbus_handle_method_call(GDBusConnection *connection, const gchar *se
|
||||||
|
g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", window));
|
||||||
|
g_free(window);
|
||||||
|
|
||||||
|
+ } else if (g_strcmp0(method_name, "CloseWindow") == 0) {
|
||||||
|
+ const gchar *window;
|
||||||
|
+ g_variant_get(parameters, "(s)", &window);
|
||||||
|
+
|
||||||
|
+ uintptr_t address = strtol(window, NULL, 16); // Base 16 for hexadecimal
|
||||||
|
+ Client *c = NULL;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ if ((uintptr_t)c == address) {
|
||||||
|
+ client_send_close(c);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // g_print("focus %s\n", window);
|
||||||
|
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", window));
|
||||||
|
+ g_free(window);
|
||||||
|
+
|
||||||
|
+ } else if (g_strcmp0(method_name, "QuitApp") == 0) {
|
||||||
|
+ const gchar *appid;
|
||||||
|
+ g_variant_get(parameters, "(s)", &appid);
|
||||||
|
+
|
||||||
|
+ Client *c = NULL;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ const char *c_appid = client_get_appid(c);
|
||||||
|
+ g_print("[%s] [%s]", appid, c_appid);
|
||||||
|
+ if (g_strcmp0(appid, c_appid) == 0) {
|
||||||
|
+ client_send_close(c);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", appid));
|
||||||
|
+ g_free(appid);
|
||||||
|
+
|
||||||
|
} else {
|
||||||
|
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
--
|
||||||
|
2.47.1
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user