Dispatch key messages from Emacs

Hi!

The Haiku port of Emacs is really cool, and with abstract submission deadlines coming up, I thought I should try using Haiku for research!

One problem I stumbled upon, is that ctrl+tab does not work for switching windows when Emacs is focused.

I would like to try to fix this (instead of writing conference abstracts, taking a first look at both the Haiku and Emacs code bases seems like much more fun!)

There is already an escape in haiku_support.cc (in Emacs) for calling BWindow::DispatchMessage from the EmacsWindow::DispatchMessage function when the menubar is active.

How should I figure out if a key press should be handled by emacs or forwarded to Haiku? Can a Haiku user change the default key bindings, or can I assume that ctrl+tab will always be bound to the window switcher?

Would it then be reasonable to just hardcode a special case for ctrl+tab, or is there a library function in Haiku for checking if a B_KEY_DOWN or B_KEY_UP-message is a desktop keyboard shortcut?

Cheers!
Tor-björn Claesson

1 Like

It seems like I’ve seen someone else ask this but I can’t find the conversation here on the forums. It might have been on IRC or something. In any case, we should ping @hgsfghs since he will be most likely to answer questions about Emacs internals.

This is actually the only problem I have with Emacs on Haiku. It’s a small thing, but quite annoying for “keyboard-centric” users. I don’t use C/C++ unless I have to, so I can’t provide any useful information, but I can confirm the problem is there and fixing it will make every Emacs user happy. I’m also glad someone decided to do something about it.

It is actually surprising nobody mentioned this problem before. I can only guess either most Haiku users don’t really use Emacs, or they just try to do everything from within Emacs so there is no need to switch windows often. The latter is certainly doable to a great extent (and it’s what I do at the moment) but it’s not a solution.

As a hacky solution, until a proper one is found, you can use the patch inlined below. It just passes C-tab to the parent BWindow::DispatchMessage, which makes window switching work for me.

I also noted, that window switching does not work with the Epiphany browser, is this a wider problem?

(I’m not comfortable with C++ either: I find in it a lot of fun, a bit like fireworks. Also like fireworks, I do not know how to safely use it in an operating theater, but very much respect people who have put in the time to learn how to do so :slight_smile:)

From 172cd4df289abbbc7eb3e754c09fa1560782da31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tor-bj=C3=B6rn=20Claesson?= <tclaesson@gmail.com>
Date: Tue, 19 Mar 2024 10:08:42 +0200
Subject: [PATCH] Haiku: Do not handle C-<tab>, pass msg to BWindow

---
 src/haiku_support.cc | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 1b9c5acdf14..b750d42a49f 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -1063,6 +1063,11 @@ my_team_id (void)
 
 	uint32_t mods = modifiers ();
 
+	if (mods & B_CONTROL_KEY && key == 38) {
+		BWindow::DispatchMessage (msg, handler);
+	    return;
+	}
+
 	if (mods & B_SHIFT_KEY)
 	  rq.modifiers |= HAIKU_MODIFIER_SHIFT;
 
-- 
2.43.2

1 Like

Thanks.

How should I figure out if a key press should be handled by emacs or forwarded to Haiku? Can a Haiku user change the default key bindings, or can I assume that ctrl+tab will always be bound to the window switcher?

It’s sadly impossible to reference the active keymap during event delivery, as each window’s event loop runs in a separate thread from Emacs’s recursive editing loop. A better option is to introduce a user option that controls the delivery of system shortcuts of this kind; it would be a welcome break if you took this initiative, but if not, I’m more than willing to implement it, provided you give me until the weekends to lay hands on a Haiku system : -)

Ok, thanks for the reply=)

I don’t have access to my Haiku computer until next week, but would be happy to implement this, if you would be willing to guide me a bit, as I have never looked under the hood of Emacs.

Is this a good way?

Add a lisp/haiku.el, with
(defgroup haiku… and
(defcustom haiku-reserved-keystrokes '(“C-TAB”) …
2.
check in EmacsWindow::DispatchMessage whether the current keystroke is a member of haiku-reserved-keystrokes.

Here, I am uncertain how to get the value of haiku-reserved-keystrokes from c. Can I lookup a c string and get a symbol?
Once we have that, Fmemq and NILP seem like the right way ahead=)

Cheers!
Tor-björn

1 Like

Right. A degree of separation between C++ windowing code and C interface code is enforced quite strictly in Emacs, so that C definitions need not be continually adjusted for compatibility with C++ compilers, and as such C and C++ must communicate through either “extern C” functions or data written to/from the ports set aside for this purpose.

If there are no other keyboard shortcuts besides C-TAB for which this treatment might also be in order, it should suffice to define a single boolean variable in the function “syms_of_haikufns”, a C function that returns its value in haikufns.c, with a prototype in haiku_support.h, to be called whenever a C-TAB key press is received by EmacsWindow::DispatchMessage, which then delivers the event to the system or to Emacs accordingly. Please grep for DEFVAR_BOOL for examples of boolean definitions.

2 Likes

Nice! Thanks, this sound fairly straight forward even for an amateur like me, I will get on it next week and report back with a patch:)

Thanks again for explaining, and have a nice weekend:)

2 Likes

Hi again,

The following patch works for me - setting haiku-pass-control-tab-to-system to nil breaks window switching and setting it back to t fixes it again :slight_smile:
Is the naming/descriptions ok? If so, should I send this to the emacs bug list?

Thanks again for your help :slight_smile:

From 0967cfac35eabad12bf9e820b1ed5f764a088e9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tor-bj=C3=B6rn=20Claesson?= <tclaesson@gmail.com>
Date: Mon, 25 Mar 2024 13:15:14 +0200
Subject: [PATCH] Add haiku-pass-control-tab-to-system

Emacs would previously intercept C-TAB on Haiku OS, breaking
window switching. This patch fixes this, with an option to
preserve the old behaviour by setting
haiku-pass-control-tab-to-system to nil.
Copyright-paperwork-exempt: yes
---
 src/haiku_support.cc |  6 ++++++
 src/haiku_support.h  |  2 ++
 src/haikufns.c       | 11 +++++++++++
 3 files changed, 19 insertions(+)

diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 1b9c5acdf14..e6871c57092 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -1063,6 +1063,12 @@ my_team_id (void)
 
 	uint32_t mods = modifiers ();
 
+	if (haiku_should_pass_control_tab_to_system() &&
+	    mods & B_CONTROL_KEY && key == 38) {
+	  BWindow::DispatchMessage (msg, handler);
+	  return;
+	}
+
 	if (mods & B_SHIFT_KEY)
 	  rq.modifiers |= HAIKU_MODIFIER_SHIFT;
 
diff --git a/src/haiku_support.h b/src/haiku_support.h
index e9ac7005d75..6c0e5fa7acd 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -691,6 +691,8 @@ #define BE_RECT_WIDTH(rect)	(ceil (((rect).right - (rect).left) + 1))
 extern bool be_is_display_grayscale (void);
 extern void be_warp_pointer (int, int);
 
+extern bool haiku_should_pass_control_tab_to_system (void);
+
 extern void EmacsView_set_up_double_buffering (void *);
 extern void EmacsView_disable_double_buffering (void *);
 extern void EmacsView_flip_and_blit (void *);
diff --git a/src/haikufns.c b/src/haikufns.c
index 173c1e369df..15eca07d8d4 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -2194,6 +2194,11 @@ haiku_set_use_frame_synchronization (struct frame *f, Lisp_Object arg,
   be_set_use_frame_synchronization (FRAME_HAIKU_VIEW (f), !NILP (arg));
 }
 
+bool
+haiku_should_pass_control_tab_to_system (void) {
+  return haiku_pass_control_tab_to_system;
+}
+
 
 
 DEFUN ("haiku-set-mouse-absolute-pixel-position",
@@ -3297,6 +3302,12 @@ syms_of_haikufns (void)
 	       doc: /* SKIP: real doc in xfns.c.  */);
   Vx_hourglass_pointer_shape = Qnil;
 
+  DEFVAR_BOOL ("haiku-pass-control-tab-to-system",
+	       haiku_pass_control_tab_to_system,
+	       doc: /* Whether or not to pass C-TAB to the system.
+		       Settings this variable will cause Emacs to pass C-TAB to the system (allowing window switching on Haiku), rather than intercepting it for use in Emacs."  */);
+  haiku_pass_control_tab_to_system = true;
+
   DEFVAR_LISP ("x-sensitive-text-pointer-shape",
 	       Vx_sensitive_text_pointer_shape,
 	       doc: /* SKIP: real doc in xfns.c.  */);
-- 
2.43.2
1 Like

Thanks. Yes, please post this to bug-gnu-emacs@gnu.org, and let’s take it from there. It’s probably large enough that copyright assignment will be required before we can accept it, and there are also several stylistic issues to be addressed.

1 Like