From 41cc23e1cfc248eb10878fd172ca969ed27a5f44 Mon Sep 17 00:00:00 2001
From: Guido Cella <guidocella91@gmail.com>
Date: Fri, 28 Aug 2020 20:18:42 +0200
Subject: Implement the idle protocol

It allows clients such as swayidle and chat applications to monitor user
idle time.
---
 Makefile           | 14 ++++++++++++--
 dwl.c              | 12 ++++++++++++
 protocols/idle.xml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+), 2 deletions(-)
 create mode 100644 protocols/idle.xml

diff --git a/Makefile b/Makefile
index 3dc2336..abbbe39 100644
--- a/Makefile
+++ b/Makefile
@@ -33,12 +33,22 @@ wlr-layer-shell-unstable-v1-protocol.c:
 
 wlr-layer-shell-unstable-v1-protocol.o: wlr-layer-shell-unstable-v1-protocol.h
 
+idle-protocol.h:
+	$(WAYLAND_SCANNER) server-header \
+		protocols/idle.xml $@
+
+idle-protocol.c:
+	$(WAYLAND_SCANNER) private-code \
+		protocols/idle.xml $@
+
+idle-protocol.o: idle-protocol.h
+
 config.h: | config.def.h
 	cp config.def.h $@
 
-dwl.o: config.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h
+dwl.o: config.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h
 
-dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o
+dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o
 
 clean:
 	rm -f dwl *.o *-protocol.h *-protocol.c
diff --git a/dwl.c b/dwl.c
index cb5341a..1df7288 100644
--- a/dwl.c
+++ b/dwl.c
@@ -20,6 +20,7 @@
 #include <wlr/types/wlr_export_dmabuf_v1.h>
 #include <wlr/types/wlr_gamma_control_v1.h>
 #include <wlr/types/wlr_input_device.h>
+#include <wlr/types/wlr_idle.h>
 #include <wlr/types/wlr_layer_shell_v1.h>
 #include <wlr/types/wlr_keyboard.h>
 #include <wlr/types/wlr_matrix.h>
@@ -292,6 +293,7 @@ static struct wl_list clients; /* tiling order */
 static struct wl_list fstack;  /* focus order */
 static struct wl_list stack;   /* stacking z-order */
 static struct wl_list independents;
+static struct wlr_idle *idle;
 static struct wlr_layer_shell_v1 *layer_shell;
 static struct wlr_xdg_decoration_manager_v1 *xdeco_mgr;
 static struct wlr_output_manager_v1 *output_mgr;
@@ -611,6 +613,7 @@ axisnotify(struct wl_listener *listener, void *data)
 	/* This event is forwarded by the cursor when a pointer emits an axis event,
 	 * for example when you move the scroll wheel. */
 	struct wlr_event_pointer_axis *event = data;
+	wlr_idle_notify_activity(idle, seat);
 	/* Notify the client with pointer focus of the axis event. */
 	wlr_seat_pointer_notify_axis(seat,
 			event->time_msec, event->orientation, event->delta,
@@ -626,6 +629,8 @@ buttonpress(struct wl_listener *listener, void *data)
 	Client *c;
 	const Button *b;
 
+	wlr_idle_notify_activity(idle, seat);
+
 	switch (event->state) {
 	case WLR_BUTTON_PRESSED:;
 		/* Change focus if the button was _pressed_ over a client */
@@ -1217,6 +1222,9 @@ keypress(struct wl_listener *listener, void *data)
 
 	int handled = 0;
 	uint32_t mods = wlr_keyboard_get_modifiers(kb->device->keyboard);
+
+	wlr_idle_notify_activity(idle, seat);
+
 	/* On _press_, attempt to process a compositor keybinding. */
 	if (event->state == WLR_KEY_PRESSED)
 		for (i = 0; i < nsyms; i++)
@@ -1346,6 +1354,8 @@ motionnotify(uint32_t time)
 		time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
 	}
 
+	wlr_idle_notify_activity(idle, seat);
+
 	/* Update selmon (even while dragging a window) */
 	if (sloppyfocus)
 		selmon = xytomon(cursor->x, cursor->y);
@@ -1999,6 +2009,8 @@ setup(void)
 	wl_list_init(&stack);
 	wl_list_init(&independents);
 
+	idle = wlr_idle_create(dpy);
+
 	layer_shell = wlr_layer_shell_v1_create(dpy);
 	wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface);
 
diff --git a/protocols/idle.xml b/protocols/idle.xml
new file mode 100644
index 0000000..92d9989
--- /dev/null
+++ b/protocols/idle.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="idle">
+  <copyright><![CDATA[
+    Copyright (C) 2015 Martin Gräßlin
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  ]]></copyright>
+  <interface  name="org_kde_kwin_idle" version="1">
+      <description summary="User idle time manager">
+        This interface allows to monitor user idle time on a given seat. The interface
+        allows to register timers which trigger after no user activity was registered
+        on the seat for a given interval. It notifies when user activity resumes.
+
+        This is useful for applications wanting to perform actions when the user is not
+        interacting with the system, e.g. chat applications setting the user as away, power
+        management features to dim screen, etc..
+      </description>
+      <request name="get_idle_timeout">
+        <arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
+        <arg name="seat" type="object" interface="wl_seat"/>
+        <arg name="timeout" type="uint" summary="The idle timeout in msec"/>
+      </request>
+  </interface>
+  <interface name="org_kde_kwin_idle_timeout" version="1">
+      <request name="release" type="destructor">
+        <description summary="release the timeout object"/>
+      </request>
+      <request name="simulate_user_activity">
+          <description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
+      </request>
+      <event name="idle">
+          <description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
+      </event>
+      <event name="resumed">
+          <description summary="Triggered on the first user activity after an idle event"/>
+      </event>
+  </interface>
+</protocol>
-- 
cgit v1.2.3