From 3f7110b120e8b57048a363e1b933ef4db6a14cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Wed, 19 Aug 2009 00:50:49 +0200 Subject: [PATCH] Fix focus issues with the switch panel and auto-focus 1. Setup two windows in a workspace, one at the center and the other at a corner. Move the mouse to the center of the screen, so that the focus goes to the center window. Now, with the help of the keyboard (with Alt-tab, typically), try and switch the focus to the other window. In doing so, the switch panel shows up, gives the focus to the other window and then disappears. However, its disappearance make it seem to wmaker that the mouse has just entered the center window, so wmaker gives the focus to that window again. 2. It is a lit bit more involved. "Raise window when switching focus with keyboard" needs to be set. In a given workspace, maximize a first window A, then setup "above" window A two windows B and C (one in the upper left corner and the other one in the lower right corner, for example). Move the mouse so as to give the focus to window B. Press the Alt key, hit the key tab once (window A moves up to the "top"), then another time (window C is then selected). Eventually relase the Alt key: window B is given the focus again. Correction: it is a matter of ignoring some (EnterNotify) events when the switch panel is active or has just been used. --- src/cycling.c | 6 +++++- src/event.c | 6 ++++++ src/main.c | 2 ++ src/startup.c | 8 +++++++- src/switchpanel.c | 17 ++++++++++++++++- 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/cycling.c b/src/cycling.c index 8e9473ed..cabb4f80 100644 --- a/src/cycling.c +++ b/src/cycling.c @@ -134,7 +134,7 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool next) int i; WMMaskEvent(dpy, KeyPressMask | KeyReleaseMask | ExposureMask - | PointerMotionMask | ButtonReleaseMask, &ev); + | PointerMotionMask | ButtonReleaseMask | EnterWindowMask, &ev); /* ignore CapsLock */ modifiers = ev.xkey.state & ValidModMask; @@ -191,6 +191,10 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool next) } break; + case EnterNotify: + /* ignore unwanted EnterNotify's */ + break; + case LeaveNotify: case MotionNotify: case ButtonRelease: diff --git a/src/event.c b/src/event.c index cc42506a..c7657f88 100644 --- a/src/event.c +++ b/src/event.c @@ -85,6 +85,7 @@ extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW; extern Atom _XA_GNUSTEP_TITLEBAR_STATE; extern Atom _XA_WINDOWMAKER_WM_FUNCTION; extern Atom _XA_WINDOWMAKER_COMMAND; +extern Atom _XA_WM_IGNORE_FOCUS_EVENTS; #ifdef SHAPE extern Bool wShapeSupported; @@ -1008,6 +1009,11 @@ static void handleClientMessage(XEvent * event) wFrameWindowChangeState(wwin->frame, WS_FOCUSED); break; } + } else if (event->xclient.message_type == _XA_WM_IGNORE_FOCUS_EVENTS) { + WScreen *scr = wScreenSearchForRootWindow(event->xclient.window); + if (!scr) + return; + scr->flags.ignore_focus_events = event->xclient.data.l[0] ? 1 : 0; #ifdef NETWM_HINTS } else if (wNETWMProcessClientMessage(&event->xclient)) { /* do nothing */ diff --git a/src/main.c b/src/main.c index 3f8e36c6..fb7228b3 100644 --- a/src/main.c +++ b/src/main.c @@ -116,6 +116,8 @@ Atom _XA_WINDOWMAKER_COMMAND; Atom _XA_WINDOWMAKER_ICON_SIZE; Atom _XA_WINDOWMAKER_ICON_TILE; +Atom _XA_WM_IGNORE_FOCUS_EVENTS; + /* cursors */ Cursor wCursor[WCUR_LAST]; diff --git a/src/startup.c b/src/startup.c index 81666958..3550afe6 100644 --- a/src/startup.c +++ b/src/startup.c @@ -135,6 +135,8 @@ extern Atom _XA_WINDOWMAKER_ICON_TILE; extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW; extern Atom _XA_GNUSTEP_TITLEBAR_STATE; +extern Atom _XA_WM_IGNORE_FOCUS_EVENTS; + /* cursors */ extern Cursor wCursor[WCUR_LAST]; @@ -535,7 +537,9 @@ static char *atomNames[] = { GNUSTEP_WM_ATTR_NAME, GNUSTEP_WM_MINIATURIZE_WINDOW, - GNUSTEP_TITLEBAR_STATE + GNUSTEP_TITLEBAR_STATE, + + "WM_IGNORE_FOCUS_EVENTS" }; /* @@ -609,6 +613,8 @@ void StartUp(Bool defaultScreenOnly) _XA_GNUSTEP_WM_MINIATURIZE_WINDOW = atom[18]; _XA_GNUSTEP_TITLEBAR_STATE = atom[19]; + _XA_WM_IGNORE_FOCUS_EVENTS = atom[20]; + #ifdef XDND wXDNDInitializeAtoms(); #endif diff --git a/src/switchpanel.c b/src/switchpanel.c index 0cdb529d..3e1ae158 100644 --- a/src/switchpanel.c +++ b/src/switchpanel.c @@ -34,6 +34,9 @@ #include "switchpanel.h" #include "funcs.h" #include "xinerama.h" +#include "window.h" + +extern Atom _XA_WM_IGNORE_FOCUS_EVENTS; #ifdef SHAPE #include @@ -546,9 +549,21 @@ void wSwitchPanelDestroy(WSwitchPanel * panel) int i; RImage *image; - if (panel->win) + if (panel->win) { + Window info_win = panel->scr->info_window; + XEvent ev; + ev.xclient.type = ClientMessage; + ev.xclient.message_type = _XA_WM_IGNORE_FOCUS_EVENTS; + ev.xclient.format = 32; + ev.xclient.data.l[0] = True; + + XSendEvent(dpy, info_win, True, EnterWindowMask, &ev); WMUnmapWidget(panel->win); + ev.xclient.data.l[0] = False; + XSendEvent(dpy, info_win, True, EnterWindowMask, &ev); + } + if (panel->images) { WM_ITERATE_ARRAY(panel->images, image, i) { if (image)