1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-23 14:42:29 +01:00

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.
This commit is contained in:
Daniel Déchelotte
2009-08-19 00:50:49 +02:00
committed by Carlos R. Mafra
parent f9bb2a428a
commit 3f7110b120
5 changed files with 36 additions and 3 deletions

View File

@@ -134,7 +134,7 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool next)
int i; int i;
WMMaskEvent(dpy, KeyPressMask | KeyReleaseMask | ExposureMask WMMaskEvent(dpy, KeyPressMask | KeyReleaseMask | ExposureMask
| PointerMotionMask | ButtonReleaseMask, &ev); | PointerMotionMask | ButtonReleaseMask | EnterWindowMask, &ev);
/* ignore CapsLock */ /* ignore CapsLock */
modifiers = ev.xkey.state & ValidModMask; modifiers = ev.xkey.state & ValidModMask;
@@ -191,6 +191,10 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool next)
} }
break; break;
case EnterNotify:
/* ignore unwanted EnterNotify's */
break;
case LeaveNotify: case LeaveNotify:
case MotionNotify: case MotionNotify:
case ButtonRelease: case ButtonRelease:

View File

@@ -85,6 +85,7 @@ extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;
extern Atom _XA_GNUSTEP_TITLEBAR_STATE; extern Atom _XA_GNUSTEP_TITLEBAR_STATE;
extern Atom _XA_WINDOWMAKER_WM_FUNCTION; extern Atom _XA_WINDOWMAKER_WM_FUNCTION;
extern Atom _XA_WINDOWMAKER_COMMAND; extern Atom _XA_WINDOWMAKER_COMMAND;
extern Atom _XA_WM_IGNORE_FOCUS_EVENTS;
#ifdef SHAPE #ifdef SHAPE
extern Bool wShapeSupported; extern Bool wShapeSupported;
@@ -1008,6 +1009,11 @@ static void handleClientMessage(XEvent * event)
wFrameWindowChangeState(wwin->frame, WS_FOCUSED); wFrameWindowChangeState(wwin->frame, WS_FOCUSED);
break; 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 #ifdef NETWM_HINTS
} else if (wNETWMProcessClientMessage(&event->xclient)) { } else if (wNETWMProcessClientMessage(&event->xclient)) {
/* do nothing */ /* do nothing */

View File

@@ -116,6 +116,8 @@ Atom _XA_WINDOWMAKER_COMMAND;
Atom _XA_WINDOWMAKER_ICON_SIZE; Atom _XA_WINDOWMAKER_ICON_SIZE;
Atom _XA_WINDOWMAKER_ICON_TILE; Atom _XA_WINDOWMAKER_ICON_TILE;
Atom _XA_WM_IGNORE_FOCUS_EVENTS;
/* cursors */ /* cursors */
Cursor wCursor[WCUR_LAST]; Cursor wCursor[WCUR_LAST];

View File

@@ -135,6 +135,8 @@ extern Atom _XA_WINDOWMAKER_ICON_TILE;
extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW; extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;
extern Atom _XA_GNUSTEP_TITLEBAR_STATE; extern Atom _XA_GNUSTEP_TITLEBAR_STATE;
extern Atom _XA_WM_IGNORE_FOCUS_EVENTS;
/* cursors */ /* cursors */
extern Cursor wCursor[WCUR_LAST]; extern Cursor wCursor[WCUR_LAST];
@@ -535,7 +537,9 @@ static char *atomNames[] = {
GNUSTEP_WM_ATTR_NAME, GNUSTEP_WM_ATTR_NAME,
GNUSTEP_WM_MINIATURIZE_WINDOW, 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_WM_MINIATURIZE_WINDOW = atom[18];
_XA_GNUSTEP_TITLEBAR_STATE = atom[19]; _XA_GNUSTEP_TITLEBAR_STATE = atom[19];
_XA_WM_IGNORE_FOCUS_EVENTS = atom[20];
#ifdef XDND #ifdef XDND
wXDNDInitializeAtoms(); wXDNDInitializeAtoms();
#endif #endif

View File

@@ -34,6 +34,9 @@
#include "switchpanel.h" #include "switchpanel.h"
#include "funcs.h" #include "funcs.h"
#include "xinerama.h" #include "xinerama.h"
#include "window.h"
extern Atom _XA_WM_IGNORE_FOCUS_EVENTS;
#ifdef SHAPE #ifdef SHAPE
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
@@ -546,9 +549,21 @@ void wSwitchPanelDestroy(WSwitchPanel * panel)
int i; int i;
RImage *image; 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); WMUnmapWidget(panel->win);
ev.xclient.data.l[0] = False;
XSendEvent(dpy, info_win, True, EnterWindowMask, &ev);
}
if (panel->images) { if (panel->images) {
WM_ITERATE_ARRAY(panel->images, image, i) { WM_ITERATE_ARRAY(panel->images, image, i) {
if (image) if (image)