Sam Varshavchik
Sam Varshavchik

Reputation: 118435

X11: input focus for popups

For some fun and self-education, I'm tinkering with writing my own X11 toolkit. Here's something that's stumping me.

I have a traditional combo box display element, a typical combo box with a dropdown popup list, like all popular toolkits have.

For the dropdown popup list, I'm creating a new window, a child of the root window, appropriately positioned below the main combo-box display element.

The dropdown popup list is a window in its own full right, that implements keyboard-based navigation, to select the individual entries in the dropdown list.

So, I'm using SetInputFocus to set the input focus to the popup after it opens.

What I find is that when I do that, the window manager then redraws the frame of the main window to indicate that it no longer has input focus. Which is technically true, but I don't see the same results with the more mainstream toolkits, where, in the comparable situation, the main window's frame shows that it still has input focus.

For the pop-up window, in addition to setting override-redirect, I'm also doing everything I can think of, to tell the window manager what's going on: setting the window group leader ID in the popup window's WM_HINTS, setting WM_TRANSIENT_FOR, and setting _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_COMBO; none of that seems to work (I verified that the properties are approriately set, via xprop).

It seems like I have to keep the input focus in the combo box window, and forward keypress and keyrelease events to the display elements in the dropdown popup, which feels clunky. Am I overlooking some property that would tell the window manager that the popup's input focus is linked to the main window's (besides the ones that I've mentioned), that would keep the main window's frame drawn to show that it has input focus, when the input focus is actually in the popup?

Upvotes: -3

Views: 2510

Answers (2)

Andrzej Szombierski
Andrzej Szombierski

Reputation: 359

This is a surprisingly obscure topic so I don't have any sources to quote on this, but one can run simple experiments to see how other toolkits approach this.

The simplest use-case is the common menu bar. In general, I've encountered two approaches:

  1. Keep the toplevel window focused, but internally interpret keyboard events in the context of the popup.
  2. Keep the toplevel window focused, but configure a keyboard grab for the popup window, ensuring that X11 will direct keyboard events to it.

In both cases, the toplevel window maintains focus during the whole process. This also means that the toolkit needs to maintain the concept of a "focused popup window" internally, as the X server will not be aware of it. One can verify this by running xdotool getwindowfocus; sleep 5s; xdotool getwindowfocus and navigating to the menu. The focused window ID will stay the same.

The first approach differs from the second in the way special keyboard events are handled. With a keyboard grab, global hotkeys (such as volume keys) will also be captured, so they won't be handled properly as long as the popup is active.

Upvotes: 0

n. m. could be an AI
n. m. could be an AI

Reputation: 120059

Most X11 override-redirect exclusive popup windows (menus, combo boxes, ...) grab the keyboard and/or pointer with either passive or active grab.

See XGrabKey, XGrabKeyboard, XGrabButton, XGrabPointer in the X11 programming manual.

Or maybe don't, because the manual is totally unclear about what the heck these functions are and how they can be used. Search the interwebs for usage examples, probably in other widget libraries. Unfortunately I don't know of a simple informative example offhand.

It is not necessary to call XSetInputFocus at all because all keyboard and/or pointer events are reported to the grabbing clients.

Upvotes: 8

Related Questions