[Xcb] Finding which screen has focus in multi-head mode
Baron
baron at bologrew.net
Thu Nov 5 00:32:22 PST 2015
Greetings all.
I have been trying to fix a focus-stealing bug in the KDE KWin window manager
which occurs when you have two (or more) independent screens or heads (also
known as Zaphod mode).
The function that is required is to find which head has focus so I am using
"xcb_get_input_focus". The man page is incomplete with the "focus" reply
value just listed as "TODO: NOT YET DOCUMENTED". However, I think it has the
same replies as "XGetInputFocus" in which case it could be the window ID,
PointerRoot or None.
I am frequently getting "PointerRoot" as the returned value and there is
disagreement between the KWin maintainer and me as to exactly what that means
when you have two separate screens.
He says that "the value is simply unspecific" and tells you nothing about
which screen has the focus.
I, on the other hand, read the man page for "XGetInputFocus" which says "if
focus is PointerRoot, the focus window is dynamically taken to be the root
window of whatever screen the pointer is on at each keyboard event".
If that is the case then I can call "xcb_query_pointer" and ask it which
screen it is on.
Now I don't mind which, if either, of us is right but I really would like to
know what a focus of "PointerRoot" should or does mean in this context.
Alternatively, if anyone has a different way to find which screen has focus
then I'd love to hear about it.
My test program is reproduced below.
Thank-you for your time.
Nicholas Redgrave
#include <stdio.h>
#include <xcb/xcb.h>
#include <inttypes.h>
#include <stdlib.h>
int main ()
{
int i, screenNum;
xcb_screen_t *screen;
xcb_get_input_focus_reply_t *focus_reply;
xcb_get_geometry_reply_t *geometry_reply;
xcb_query_pointer_reply_t *pointer_reply;
xcb_generic_error_t *error;
xcb_connection_t *connection = xcb_connect (NULL, &screenNum);
printf("screenNum: %d\n",screenNum);
/* Get the screen whose number is screenNum */
const xcb_setup_t *setup = xcb_get_setup (connection);
xcb_screen_iterator_t iter = xcb_setup_roots_iterator (setup);
// we want the screen at index screenNum of the iterator
for (i = 0; i < screenNum; ++i) {
xcb_screen_next (&iter);
}
screen = iter.data;
/* find which screen has focus */
focus_reply = xcb_get_input_focus_reply (connection, xcb_get_input_focus(connection), &error);
if( error != NULL ) {
printf("Could not get focussed window (X error %d)\n",error->error_code);
free(error);
}
else {
printf("Focussed window is %d\n",focus_reply->focus);
if( focus_reply->focus == 0 ) {
printf("I presume this is None so no window anywhere has focus\n");
}
else if( focus_reply->focus == 1 ) {
printf("I presume this is PointerRoot - what does PointerRoot really mean?\n");
pointer_reply = xcb_query_pointer_reply (connection, xcb_query_pointer(connection, screen->root), &error);
if( error != NULL ) {
printf("Could not get pointer query (X error %d)\n",error->error_code);
free(error);
}
else {
printf ("Pointer on this screen?: %d\n", pointer_reply->same_screen);
free(pointer_reply);
}
}
else {
geometry_reply = xcb_get_geometry_reply (connection, xcb_get_geometry(connection, focus_reply->focus), NULL);
printf ("Focussed Window root id: %d\n", geometry_reply->root);
if( screen->root == geometry_reply->root ) {
printf("Window with focus on this screen\n");
}
else {
printf("Window with focus NOT on this screen\n");
}
free(geometry_reply);
}
free(focus_reply);
}
xcb_disconnect (connection);
return 0;
}
--
Fingerprint for GnuPG ID 0x0189562F
ADCF CC73 0DFB 9613 FA78 553B C98C 086F 0189 562F
More information about the Xcb
mailing list