From 5bca4a0a26f89c70357fbbbe13ad1fe9d3b07b24 Mon Sep 17 00:00:00 2001
From: John Ankarstrom <john@ankarstrom.se>
Date: Wed, 30 Jun 2021 19:30:09 +0200
Subject: Use enter and escape keys to navigate confirmation dialog

---
 src/confirm.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/src/confirm.c b/src/confirm.c
index 77aa48e..e71735a 100644
--- a/src/confirm.c
+++ b/src/confirm.c
@@ -15,6 +15,7 @@
 #include "button.h"
 #include "screen.h"
 #include "color.h"
+#include "key.h"
 #include "misc.h"
 
 #ifndef DISABLE_CONFIRM
@@ -58,6 +59,7 @@ static void DrawButtons(DialogType *d);
 static DialogType *FindDialogByWindow(Window w);
 static int HandleDialogExpose(const XExposeEvent *event); 
 static int HandleDialogButtonRelease(const XButtonEvent *event);
+static int HandleDialogKey(const XKeyEvent *event);
 
 /** Initialize the dialog processing data. */
 void InitializeDialogs() {
@@ -92,6 +94,9 @@ int ProcessDialogEvent(const XEvent *event) {
 		return HandleDialogExpose(&event->xexpose);
 	case ButtonRelease:
 		return HandleDialogButtonRelease(&event->xbutton);
+	case KeyPress:
+	case KeyRelease:
+		return HandleDialogKey(&event->xkey);
 	default:
 		break;
 	}
@@ -154,6 +159,35 @@ int HandleDialogButtonRelease(const XButtonEvent *event) {
 
 }
 
+/** Handle a key release event. */
+int HandleDialogKey(const XKeyEvent *event) {
+	static int enter = 0;
+
+	ClientNode *np;
+	DialogType *dp;
+
+	Assert(event);
+
+	if(!(np = GetActiveClient()))
+		return 0;
+	if(!(dp = FindDialogByWindow(np->window)))
+		return 0;
+
+	switch(GetKey(event) & 0xFF) {
+	case KEY_ENTER:
+		/* Ignore release without preceding press. */
+		if(event->type == KeyPress && ++enter || !enter || --enter)
+			break;
+		(dp->action)(dp->client);
+		/* FALLTHROUGH */
+	case KEY_ESC:
+		DestroyConfirmDialog(dp);
+		break;
+	}
+
+	return 1;
+}
+
 /** Find a dialog by window or frame. */
 DialogType *FindDialogByWindow(Window w) {
 
@@ -235,6 +269,8 @@ void ShowConfirmDialog(ClientNode *np, void (*action)(ClientNode*), ...) {
 
 	JXGrabButton(display, AnyButton, AnyModifier, window,
 		True, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
+        JXGrabKeyboard(display, window, False,
+		GrabModeAsync, GrabModeAsync, CurrentTime);
 
 }
 
@@ -274,6 +310,8 @@ void DestroyConfirmDialog(DialogType *dp) {
 	}
 	Release(dp);
 
+        JXUngrabKeyboard(display, CurrentTime);
+
 }
 
 /** Compute the size of a dialog window. */
-- 
cgit v1.2.3