Skip to content

Commit

Permalink
Finally made Focus handling stable
Browse files Browse the repository at this point in the history
  • Loading branch information
iacore committed Mar 6, 2022
1 parent 28b5f24 commit f357b3c
Showing 1 changed file with 47 additions and 59 deletions.
106 changes: 47 additions & 59 deletions gui-agent/vmside.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/XInput2.h>
#include <X11/XKBlib.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
Expand Down Expand Up @@ -1611,9 +1612,13 @@ static void handle_keypress(Ghandles * g, XID UNUSED(winid))
fprintf(stderr, "failed to get modifier state\n");
state.mods = key.state;
}
// ignore all but CapsLock
state.mods &= LockMask;
key.state &= LockMask;
if (!g->sync_all_modifiers) {
// ignore all but CapsLock
state.mods &= LockMask;
key.state &= LockMask;
}
bool is_press = key.type == KeyPress;
bool duplicate = false;
if (state.mods != key.state) {
XModifierKeymap *modmap;
int mod_index;
Expand All @@ -1634,7 +1639,8 @@ static void handle_keypress(Ghandles * g, XID UNUSED(winid))
// #define Mod4MapIndex 6
// #define Mod5MapIndex 7
for (mod_index = 0; mod_index < 8; mod_index++) {
if (modmap->modifiermap[mod_index*modmap->max_keypermod] == 0x00) {
uint32_t keycode = modmap->modifiermap[mod_index*modmap->max_keypermod];
if (keycode == 0x00) {
if (g->log_level > 1)
fprintf(stderr, "ignoring disabled modifier %d\n", mod_index);
// no key set for this modifier, ignore
Expand All @@ -1644,22 +1650,24 @@ static void handle_keypress(Ghandles * g, XID UNUSED(winid))
// special case for caps lock switch by press+release
if (mod_index == LockMapIndex) {
if ((state.mods & mod_mask) ^ (key.state & mod_mask)) {
feed_xdriver(g, 'K', modmap->modifiermap[mod_index*modmap->max_keypermod], 1);
feed_xdriver(g, 'K', modmap->modifiermap[mod_index*modmap->max_keypermod], 0);
feed_xdriver(g, 'K', keycode, 1);
feed_xdriver(g, 'K', keycode, 0);
}
} else {
if ((state.mods & mod_mask) && !(key.state & mod_mask))
feed_xdriver(g, 'K', modmap->modifiermap[mod_index*modmap->max_keypermod], 0);
else if (!(state.mods & mod_mask) && (key.state & mod_mask))
feed_xdriver(g, 'K', modmap->modifiermap[mod_index*modmap->max_keypermod], 1);
if ((state.mods & mod_mask) && !(key.state & mod_mask)) {
feed_xdriver(g, 'K', keycode, 0);
if (keycode == key.keycode && is_press == 0) duplicate = true;
}
else if (!(state.mods & mod_mask) && (key.state & mod_mask)) {
feed_xdriver(g, 'K', keycode, 1);
if (keycode == key.keycode && is_press == 1) duplicate = true;
}
}
}
XFreeModifiermap(modmap);
}
}

if (key.keycode == 66) return; // caplocks
feed_xdriver(g, 'K', key.keycode, key.type == KeyPress ? 1 : 0);
if (!duplicate) feed_xdriver(g, 'K', key.keycode, is_press);
}

static void handle_button(Ghandles * g, XID winid)
Expand Down Expand Up @@ -1767,72 +1775,52 @@ static void handle_crossing(Ghandles * g, XID winid)

}

static void take_focus(Ghandles * g, XID winid)
{
// Send
XClientMessageEvent ev;
memset(&ev, 0, sizeof(ev));
ev.type = ClientMessage;
ev.display = g->display;
ev.window = winid;
ev.format = 32;
ev.message_type = g->wmProtocols;
ev.data.l[0] = g->wm_take_focus;
ev.data.l[1] = g->time;
XSendEvent(ev.display, ev.window, 1, 0, (XEvent *) & ev);
if (g->log_level > 0)
fprintf(stderr, "WM_TAKE_FOCUS sent for 0x%x\n",
(int) winid);

}
// static void take_focus(Ghandles * g, XID winid)
// {
// // Send
// XClientMessageEvent ev;
// memset(&ev, 0, sizeof(ev));
// ev.type = ClientMessage;
// ev.display = g->display;
// ev.window = winid;
// ev.format = 32;
// ev.message_type = g->wmProtocols;
// ev.data.l[0] = g->wm_take_focus;
// ev.data.l[1] = g->time;
// XSendEvent(ev.display, ev.window, 1, 0, (XEvent *) & ev);
// if (g->log_level > 0)
// fprintf(stderr, "WM_TAKE_FOCUS sent for 0x%x\n",
// (int) winid);

// }

static void handle_focus(Ghandles * g, XID winid)
{
struct msg_focus key;
struct genlist *l;
int input_hint;
int use_take_focus;

read_data(g->vchan, (char *) &key, sizeof(key));
if (key.type == FocusIn) {

XRaiseWindow(g->display, winid);

if (key.detail != NotifyUngrab) {
XSetInputFocus(g->display, winid, RevertToParent, g->time);
XRaiseWindow(g->display, winid);
} else return;

if ( (l=list_lookup(windows_list, winid)) && (l->data) ) {
input_hint = ((struct window_data*)l->data)->input_hint;
use_take_focus = ((struct window_data*)l->data)->support_take_focus;
if (((struct window_data*)l->data)->is_docked)
XRaiseWindow(g->display, ((struct window_data*)l->data)->embeder);
if (key.detail == NotifyNormal)
XRaiseWindow(g->display, ((struct window_data*)l->data)->embeder);
} else {
fprintf(stderr, "WARNING handle_focus: Window 0x%x data not initialized", (int)winid);
input_hint = True;
use_take_focus = False;
}

// Give input focus only to window that set the input hint
if (input_hint)
XSetInputFocus(g->display, winid, RevertToParent, g->time);

// Do not send take focus if the window doesn't support it
if (use_take_focus)
take_focus(g, winid);

if (g->log_level > 1)
fprintf(stderr, "0x%x raised\n", (int) winid);
} else if (key.type == FocusOut) {
if ( (l=list_lookup(windows_list, winid)) && (l->data) )
input_hint = ((struct window_data*)l->data)->input_hint;
else {
fprintf(stderr, "WARNING handle_focus: Window 0x%x data not initialized", (int)winid);
input_hint = True;
}
if (input_hint)
XSetInputFocus(g->display, None, RevertToParent, g->time);

XSetInputFocus(g->display, None, RevertToNone, g->time);
if (g->log_level > 1)
fprintf(stderr, "0x%x lost focus\n", (int) winid);
}

}

static int bitset(unsigned char *keys, int num)
Expand Down

0 comments on commit f357b3c

Please sign in to comment.