diff -u -r WindowMaker-0.80.2/src/actions.c WindowMaker-mine/src/actions.c --- WindowMaker-0.80.2/src/actions.c 2002-07-01 20:30:25.000000000 -0400 +++ WindowMaker-mine/src/actions.c 2004-06-04 16:17:30.000000000 -0400 @@ -86,16 +86,33 @@ static int ignoreTimestamp=0; +int ignoreFocus; +/* + *---------------------------------------------------------------------- + * wProcessEvents -- + * Processes up to event_count events from the display's queue. + * + * Side effects: + * Many -- whatever handling events may involve. + * + *---------------------------------------------------------------------- + */ +void +wProcessEvents(int event_count) +{ + XEvent event; + while (XPending(dpy) && event_count--) { + WMNextEvent(dpy, &event); + WMHandleEvent(&event); + } +} -#ifdef ANIMATIONS static void -processEvents(int event_count) +hackProcessEvents(int event_count) { - XEvent event; - /* - * This is a hack. When animations are enabled, processing of + * This is a hack. When animations are enabled, processing of * events ocurred during a animation are delayed until it's end. * Calls that consider the TimeStamp, like XSetInputFocus(), will * fail because the TimeStamp is too old. Then, for example, if @@ -103,21 +120,16 @@ * in course, the window will not get focus properly after the end * of the animation. This tries to workaround it by passing CurrentTime * as the TimeStamp for XSetInputFocus() for all events ocurred during + * the animation. */ ignoreTimestamp=1; - while (XPending(dpy) && event_count--) { - WMNextEvent(dpy, &event); - WMHandleEvent(&event); - } + wProcessEvents(event_count); ignoreTimestamp=0; } -#endif /* ANIMATIONS */ - - /* - *---------------------------------------------------------------------- + *---------------------------------------------------------------------- * wSetFocusTo-- * Changes the window focus to the one passed as argument. * If the window to focus is not already focused, it will be brought @@ -139,23 +151,33 @@ int timestamp=LastTimestamp; WApplication *oapp=NULL, *napp=NULL; int wasfocused; - + + if (ignoreFocus || LastFocusChange > timestamp) + return; + if (!old_scr) - old_scr=scr; + old_scr=scr; old_focused=old_scr->focused_window; LastFocusChange = timestamp; - -/* - * This is a hack, because XSetInputFocus() should have a proper - * timestamp instead of CurrentTime but it seems that some times - * clients will not receive focus properly that way. + + /* + * This is a hack, because XSetInputFocus() should have a proper + * timestamp instead of CurrentTime but it seems that some times + * clients will not receive focus properly that way. + * XXX lesha -- what clients are those? Explain, or this + * comment will go away, as will support for those clients. + */ + /* + * Passing CurrentTime with focus messages is a bad idea -- that is + * the root cause of the GTK2 flicker bug. Don't do it, except when + * animations require it. XXX lesha -- Animations untested + */ if (ignoreTimestamp) -*/ - timestamp = CurrentTime; + timestamp = CurrentTime; if (old_focused) - oapp = wApplicationOf(old_focused->main_window); + oapp = wApplicationOf(old_focused->main_window); if (wwin == NULL) { XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp); @@ -326,9 +348,9 @@ #ifdef ANIMATIONS if (!wwin->screen_ptr->flags.startup) { - /* Look at processEvents() for reason of this code. */ - XSync(dpy, 0); - processEvents(XPending(dpy)); + /* Look at hackProcessEvents() for reason of this code. */ + XSync(dpy, 0); + hackProcessEvents(XPending(dpy)); } #endif } @@ -1031,9 +1053,9 @@ Window clientwin = wwin->client_win; XSync(dpy, 0); - processEvents(XPending(dpy)); - - /* the window can disappear while doing the processEvents() */ + hackProcessEvents(XPending(dpy)); + + /* the window can disappear while doing the hackProcessEvents() */ if (!wWindowFor(clientwin)) return; } @@ -1146,7 +1168,7 @@ Window clientwin = wwin->client_win; XSync(dpy, 0); - processEvents(XPending(dpy)); + hackProcessEvents(XPending(dpy)); if (!wWindowFor(clientwin)) return; diff -u -r WindowMaker-0.80.2/src/actions.h WindowMaker-mine/src/actions.h --- WindowMaker-0.80.2/src/actions.h 2002-01-08 08:45:07.000000000 -0500 +++ WindowMaker-mine/src/actions.h 2004-06-04 16:18:40.000000000 -0400 @@ -30,6 +30,8 @@ void wSetFocusTo(WScreen *scr, WWindow *wwin); +void wProcessEvents(int event_count); + int wMouseMoveWindow(WWindow *wwin, XEvent *ev); int wKeyboardMoveResizeWindow(WWindow *wwin); diff -u -r WindowMaker-0.80.2/src/event.c WindowMaker-mine/src/event.c --- WindowMaker-0.80.2/src/event.c 2002-01-08 08:45:13.000000000 -0500 +++ WindowMaker-mine/src/event.c 2004-06-04 15:47:16.000000000 -0400 @@ -402,8 +402,6 @@ static void saveTimestamp(XEvent *event) { - LastTimestamp = CurrentTime; - switch (event->type) { case ButtonRelease: case ButtonPress: diff -u -r WindowMaker-0.80.2/src/main.c WindowMaker-mine/src/main.c --- WindowMaker-0.80.2/src/main.c 2002-03-26 05:47:12.000000000 -0500 +++ WindowMaker-mine/src/main.c 2004-06-04 15:47:16.000000000 -0400 @@ -123,9 +123,9 @@ Cursor wCursor[WCUR_LAST]; /* last event timestamp for XSetInputFocus */ -Time LastTimestamp; +Time LastTimestamp = CurrentTime; /* timestamp on the last time we did XSetInputFocus() */ -Time LastFocusChange; +Time LastFocusChange = CurrentTime; #ifdef SHAPE Bool wShapeSupported; diff -u -r WindowMaker-0.80.2/src/workspace.c WindowMaker-mine/src/workspace.c --- WindowMaker-0.80.2/src/workspace.c 2002-01-08 08:45:33.000000000 -0500 +++ WindowMaker-mine/src/workspace.c 2004-06-04 16:27:18.000000000 -0400 @@ -55,7 +55,7 @@ extern WPreferences wPreferences; extern XContext wWinContext; - +extern int ignoreFocus; static WMPropList *dWorkspaces=NULL; static WMPropList *dClip, *dName; @@ -555,6 +555,17 @@ tmp = tmp->prev; } + /* Gobble up events unleashed by our mapping & unmapping. + * These may trigger various grab-initiated focus & + * crossing events. However, we don't care about them, + * and ignore their focus implications altogether to avoid + * flicker. + */ + XSync(dpy, False); + ignoreFocus = 1; + wProcessEvents(XPending(dpy)); + ignoreFocus = 0; + if (!foc) foc = foc2; @@ -571,14 +582,23 @@ tmp = NULL; if (XQueryPointer(dpy, scr->root_win, &bar, &win, - &foo, &foo, &foo, &foo, &mask)) { + &foo, &foo, &foo, &foo, &mask)) tmp = wWindowFor(win); - } - if (!tmp && wPreferences.focus_mode == WKF_SLOPPY) { - wSetFocusTo(scr, foc); + + /* If there's a window under the pointer, focus it. + * (we ate all other focus events above, so it's + * certainly not focused). Otherwise focus last + * focused, or the root (depending on sloppiness) + */ + if (tmp) { + wSetFocusTo(scr, tmp); } else { - wSetFocusTo(scr, tmp); - } + if (wPreferences.focus_mode == WKF_SLOPPY) { + wSetFocusTo(scr, foc); + } else { + wSetFocusTo(scr, tmp); + } + } } }