I find I have some diffs in my local sources, that I might as well check in. It has been a while since I made them, so looking at them they seem to be about cleaning up RaiseOnWarp and SaveWorkspaceFocus.
I remember that there are ways to get SaveWorkspaceFocus in a somewhat confused state (my note suggest that this would be if it tries to raise a window in another workspace) so I have it turned off anyway. Shall I clean up the commented-out code from below and commit, or should I not bother? # # old_revision [a4554d63ca7723d1314942c56f5e65224147e10c] # # patch "ctwm.c" # from [92a7863c957acb35f0e3133941561a89ace04bdf] # to [7861df4001dbaa4831380d6bdbac7f61628792fe] # # patch "ctwm.man" # from [c385bd243f2a15648c06e6cb5d9296dbc72d1179] # to [a5f55e11b6b9aa147fcec5a2ccae5cb34443d311] # # patch "events.c" # from [be0f52531ec7c2299e41b6e5f8eea9ffcd56b396] # to [eb953d9c3d511b86492d3b0feaf0f79ffc17c63f] # # patch "menus.c" # from [099ca5c6fd77c789ff8974e3c48fd0ada4020987] # to [e2155ac7176b8e5e13ae125b64a1604da931b0f8] # # patch "menus.h" # from [f00c50306ff90f9498ffb11d47fcc3e210e9b01f] # to [cf30375fe93100a6b01ca77fd4ef0903a6f2254f] # # patch "parse.c" # from [f64e39e6f42dbcbcb4deb0775ce09344f9fee04f] # to [0cc3cbf9680a8f7cd99d778908847b1537700e5a] # # patch "resize.c" # from [158533f362262ddadb3e5b937f3c1d726872abcc] # to [67786881a1dccfd7eaeea0924ce7c61ce16cc69a] # # patch "screen.h" # from [e3be8919dc8c0b63029d7a0772974bc1e433d9ff] # to [563a224723b4f0c82c9eecb749d00f242682d445] # # patch "workmgr.c" # from [ea9dbcb2897548e5721e6a6cd2da57223c2dfaad] # to [e15ade89451967b36f052fba572ac2552f4ba90b] # ============================================================ --- ctwm.c 92a7863c957acb35f0e3133941561a89ace04bdf +++ ctwm.c 7861df4001dbaa4831380d6bdbac7f61628792fe @@ -151,7 +151,7 @@ Bool PrintErrorMessages = False; /* cont int PreviousScreen; /* last screen that we were on */ int FirstScreen; /* TRUE ==> first screen of display */ Bool PrintErrorMessages = False; /* controls error messages */ -Bool ShowWelcomeWindow = True; +Bool ShowWelcomeWindow = False; static int RedirectError; /* TRUE ==> another window manager running */ /* for settting RedirectError */ static int CatchRedirectError(Display *display, XErrorEvent *event); @@ -1020,7 +1020,7 @@ void InitVariables(void) Scr->NoRaiseMove = FALSE; Scr->NoRaiseResize = FALSE; Scr->NoRaiseDeicon = FALSE; - Scr->NoRaiseWarp = FALSE; + Scr->RaiseOnWarp = TRUE; Scr->DontMoveOff = FALSE; Scr->DoZoom = FALSE; Scr->TitleFocus = TRUE; ============================================================ --- ctwm.man c385bd243f2a15648c06e6cb5d9296dbc72d1179 +++ ctwm.man a5f55e11b6b9aa147fcec5a2ccae5cb34443d311 @@ -1223,6 +1223,8 @@ WorkSpaceMap can be used only to modify This keyword tells \fIctwm\fP to move the actual window when the user is moving the small windows in the WorkSpaceMap window. If not present the WorkSpaceMap can be used only to modify the occupation of a window. +Pressing the \fIshift\fP key while dragging a window in the workspace manager +temporarily toggles this option. .IP "\fBResizeFont\fP \fIstring\fP" 8 This variable specifies the font to be used for in the dimensions window when @@ -1513,6 +1515,9 @@ WindowGeometries { } .EE +.IP "\fBWindowRegion\fP \fIgeomstring\fP \fIvgrav\fP fIhgrav\fP [{ \fIwin\-list\fP }]" 8 +Similar to IconRegion, but for windows. + .IP "\fBWindowRing\fP [{ \fIwin\-list\fP }]" 8 This variable specifies a list of windows along which the \fBf.warpring\fP function cycles. If no argument is given, all the windows are in the ring. @@ -2201,6 +2206,7 @@ press another button before releasing th press another button before releasing the first button. .IP "\fBf.restart\fP" 8 +.IP "\fBf.twmrc\fP" 8 This function kills and restarts \fIctwm\fP. .IP "\fBf.restoregeometry\fP" 8 @@ -2507,8 +2513,6 @@ lists. The resource manager should have been used instead of all of the window lists. .PP -The \fBIconRegion\fP variable should take a list. -.PP Double clicking very fast to get the constrained move function will sometimes cause the window to move, even though the pointer is not moved. .PP ============================================================ --- events.c be0f52531ec7c2299e41b6e5f8eea9ffcd56b396 +++ events.c eb953d9c3d511b86492d3b0feaf0f79ffc17c63f @@ -2186,6 +2186,13 @@ void HandleDestroyNotify(void) Scr->Focus = (TwmWindow*) NULL; FocusOnRoot(); } + if (Scr->SaveWorkspaceFocus) { + struct WorkSpace *ws; + for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { + if (ws->save_focus == Tmp_win) + ws->save_focus = NULL; + } + } XDeleteContext(dpy, Tmp_win->w, TwmContext); XDeleteContext(dpy, Tmp_win->w, ScreenContext); XDeleteContext(dpy, Tmp_win->frame, TwmContext); @@ -3757,15 +3764,18 @@ void HandleLeaveNotify(void) if (Scr->RingLeader && Scr->RingLeader == Tmp_win && (Event.xcrossing.detail != NotifyInferior && Event.xcrossing.window != Tmp_win->w)) { + //fprintf(stderr, "HandleLeaveNotify: Event.xcrossing.window %x != Tmp_win->w %x\n", Event.xcrossing.window, Tmp_win->w); if (!inicon) { - if (Tmp_win->mapped) { + if (Event.xcrossing.window != Tmp_win->frame /*Tmp_win->mapped*/) { // XXX Tmp_win->ring.cursor_valid = False; - } else { + //fprintf(stderr, "HandleLeaveNotify: cursor_valid = False\n"); + } else { // Event.xcrossing.window == Tmp_win->frame Tmp_win->ring.cursor_valid = True; Tmp_win->ring.curs_x = (Event.xcrossing.x_root - Tmp_win->frame_x); Tmp_win->ring.curs_y = (Event.xcrossing.y_root - Tmp_win->frame_y); + //fprintf(stderr, "HandleLeaveNotify: cursor_valid = True; x = %d (%d-%d), y = %d (%d-%d)\n", Tmp_win->ring.curs_x, Event.xcrossing.x_root, Tmp_win->frame_x, Tmp_win->ring.curs_y, Event.xcrossing.y_root, Tmp_win->frame_y); } } Scr->RingLeader = (TwmWindow *) NULL; ============================================================ --- menus.c 099ca5c6fd77c789ff8974e3c48fd0ada4020987 +++ menus.c e2155ac7176b8e5e13ae125b64a1604da931b0f8 @@ -2281,6 +2281,7 @@ int ExecuteFunction(int func, char *acti case F_POPUP: tmp_win = (TwmWindow *)action; + if (! tmp_win) break; if (Scr->WindowFunction.func != 0) { ExecuteFunction(Scr->WindowFunction.func, @@ -2300,8 +2301,8 @@ int ExecuteFunction(int func, char *acti if (! tmp_win) break; if (Scr->WarpUnmapped || tmp_win->mapped) { if (!tmp_win->mapped) DeIconify (tmp_win); - if (!Scr->NoRaiseWarp) RaiseWindow (tmp_win); - WarpToWindow (tmp_win); + // if (Scr->RaiseOnWarp) RaiseWindow (tmp_win); + WarpToWindow (tmp_win, Scr->RaiseOnWarp); } break; @@ -3438,8 +3439,8 @@ int ExecuteFunction(int func, char *acti if (tw) { if (Scr->WarpUnmapped || tw->mapped) { if (!tw->mapped) DeIconify (tw); - if (!Scr->NoRaiseWarp) RaiseWindow (tw); - WarpToWindow (tw); + //if (Scr->RaiseOnWarp) RaiseWindow (tw); + WarpToWindow (tw, Scr->RaiseOnWarp); } } else { XBell (dpy, 0); @@ -3514,7 +3515,7 @@ int ExecuteFunction(int func, char *acti tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win; } } - tmp_win->ring.cursor_valid = False; + //tmp_win->ring.cursor_valid = False; break; case F_WARPRING: @@ -4111,7 +4112,7 @@ void DeIconify(TwmWindow *tmp_win) if (isicon && (Scr->WarpCursor || LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class))) - WarpToWindow (tmp_win); + WarpToWindow (tmp_win, 0); /* now de-iconify and window group transients */ ReMapTransients(tmp_win); @@ -4721,7 +4722,7 @@ void WarpAlongRing (XButtonEvent *ev, Bo TwmWindow *p = Scr->RingLeader, *t; Scr->RingLeader = r; - WarpToWindow (r); + WarpToWindow (r, 1); if (p && p->mapped && (t = GetTwmWindow(ev->window)) && @@ -4729,6 +4730,8 @@ void WarpAlongRing (XButtonEvent *ev, Bo p->ring.cursor_valid = True; p->ring.curs_x = ev->x_root - t->frame_x; p->ring.curs_y = ev->y_root - t->frame_y; + //fprintf(stderr, "WarpAlongRing: cursor_valid := True; x := %d (%d-%d), y := %d (%d-%d)\n", Tmp_win->ring.curs_x, ev->x_root, t->frame_x, Tmp_win->ring.curs_y, ev->y_root, t->frame_y); +#if 0 if (p->ring.curs_x < -p->frame_bw || p->ring.curs_x >= p->frame_width + p->frame_bw || p->ring.curs_y < -p->frame_bw || @@ -4736,25 +4739,61 @@ void WarpAlongRing (XButtonEvent *ev, Bo /* somehow out of window */ p->ring.curs_x = p->frame_width / 2; p->ring.curs_y = p->frame_height / 2; + //fprintf(stderr, "WarpAlongRing: outside window; x := %d, y := %d\n", Tmp_win->ring.curs_x, Tmp_win->ring.curs_y); } +#endif } } } -void WarpToWindow (TwmWindow *t) +void WarpToWindow (TwmWindow *t, int must_raise) { int x, y; - if (t->auto_raise || !Scr->NoRaiseWarp) AutoRaiseWindow (t); if (t->ring.cursor_valid) { x = t->ring.curs_x; y = t->ring.curs_y; + //fprintf(stderr, "WarpToWindow: cursor_valid; x == %d, y == %d\n", x, y); + + // XXX is this correct with 3D borders? Easier check possible? + // frame_bw is for the left border. + if (x < t->frame_bw) + x = t->frame_bw; + if (x >= t->frame_width + t->frame_bw) + x = t->frame_width + t->frame_bw - 1; + if (y < t->title_height + t->frame_bw) + y = t->title_height + t->frame_bw; + if (y >= t->frame_height + t->frame_bw) + y = t->frame_height + t->frame_bw - 1; + //fprintf(stderr, "WarpToWindow: adjusted ; x := %d, y := %d\n", x, y); } else { x = t->frame_width / 2; y = t->frame_height / 2; + //fprintf(stderr, "WarpToWindow: middle; x := %d, y := %d\n", x, y); } +#if 0 + int dest_x, dest_y; + Window child; + + /* + * Check if the proposed position actually is visible. If not, raise the window. + * "If the coordinates are contained in a mapped + * child of dest_w, that child is returned to child_return." + * We'll need to check for the right child window; the frame probably. + * (What about XXX window boxes?) + * + * Alternatively, use XQueryPointer() which returns the root window + * the pointer is in, but XXX that won't work for VirtualScreens. + */ + if (XTranslateCoordinates(dpy, t->frame, Scr->Root, x, y, &dest_x, &dest_y, &child)) { + if (child != t->frame) + must_raise = 1; + } +#endif + //if (t->auto_raise || Scr->RaiseOnWarp) AutoRaiseWindow (t); + if (t->auto_raise || must_raise) AutoRaiseWindow (t); if (! visible (t)) { WorkSpace *wlist; @@ -4763,7 +4802,23 @@ void WarpToWindow (TwmWindow *t) } if (wlist != NULL) GotoWorkSpace (Scr->currentvs, wlist); } - XWarpPointer (dpy, None, t->frame, 0, 0, 0, 0, x, y); + //XWarpPointer (dpy, None, t->frame, 0, 0, 0, 0, x, y); + XWarpPointer (dpy, None, Scr->Root, 0, 0, 0, 0, x + t->frame_x, y + t->frame_y); +#if 1 + { + Window root_return; + Window child_return; + int root_x_return; + int root_y_return; + int win_x_return; + int win_y_return; + unsigned int mask_return; + + if (XQueryPointer(dpy, t->frame, &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &mask_return)) { + //fprintf(stderr, "XQueryPointer: root_return=%x, child_return=%x, root_x_return=%d, root_y_return=%d, win_x_return=%d, win_y_return=%d\n", root_return, child_return, root_x_return, root_y_return, win_x_return, win_y_return); + } + } +#endif } ============================================================ --- menus.h f00c50306ff90f9498ffb11d47fcc3e210e9b01f +++ menus.h cf30375fe93100a6b01ca77fd4ef0903a6f2254f @@ -257,7 +257,7 @@ extern void WarpAlongRing (XButtonEvent extern void TryToGrid (TwmWindow *tmp_win, int *x, int *y); extern void resizeFromCenter(Window w, TwmWindow *tmp_win); extern void WarpAlongRing (XButtonEvent *ev, Bool forward); -extern void WarpToWindow (TwmWindow *t); +extern void WarpToWindow (TwmWindow *t, int must_raise); extern void DisplayPosition (TwmWindow *tmp_win, int x, int y); extern void packwindow (TwmWindow *tmp_win, char *direction); extern void fillwindow (TwmWindow *tmp_win, char *direction); ============================================================ --- parse.c f64e39e6f42dbcbcb4deb0775ce09344f9fee04f +++ parse.c 0cc3cbf9680a8f7cd99d778908847b1537700e5a @@ -1276,9 +1276,15 @@ int do_single_keyword (int keyword) return 1; case kw0_NoRaiseOnWarp: - Scr->NoRaiseWarp = TRUE; + Scr->RaiseOnWarp = FALSE; return 1; +#if 0 + case kw0_RaiseOnWarp: + Scr->RaiseOnWarp = TRUE; + return 1; +#endif + case kw0_WarpUnmapped: Scr->WarpUnmapped = TRUE; return 1; ============================================================ --- resize.c 158533f362262ddadb3e5b937f3c1d726872abcc +++ resize.c 67786881a1dccfd7eaeea0924ce7c61ce16cc69a @@ -627,6 +627,7 @@ void EndResize(void) XUnmapWindow(dpy, Scr->SizeWindow); tmp_win = GetTwmWindow(ResizeWindow); + if (!tmp_win) return; ConstrainSize (tmp_win, &dragWidth, &dragHeight); @@ -873,6 +874,8 @@ void SetupFrame (TwmWindow *tmp_win, int fprintf (stderr, "SetupWindow: x=%d, y=%d, w=%d, h=%d, bw=%d\n", x, y, w, h, bw); #endif + if (!tmp_win) /* should not happen */ + return; if (x >= Scr->rootw) x = Scr->rootw - 16; /* one "average" cursor width */ ============================================================ --- screen.h e3be8919dc8c0b63029d7a0772974bc1e433d9ff +++ screen.h 563a224723b4f0c82c9eecb749d00f242682d445 @@ -388,7 +388,7 @@ struct ScreenInfo short NoRaiseMove; /* don't raise window following move */ short NoRaiseResize; /* don't raise window following resize */ short NoRaiseDeicon; /* don't raise window on deiconify */ - short NoRaiseWarp; /* don't raise window on warp */ + short RaiseOnWarp; /* do raise window on warp */ short DontMoveOff; /* don't allow windows to be moved off */ int MoveOffResistance; /* nb of pixel before moveOff gives up */ int MovePackResistance; /* nb of pixel before f.movepack gives up */ ============================================================ --- workmgr.c ea9dbcb2897548e5721e6a6cd2da57223c2dfaad +++ workmgr.c e15ade89451967b36f052fba572ac2552f4ba90b @@ -626,12 +626,13 @@ void GotoWorkSpace (virtualScreen *vs, W /* If SaveWorkspaceFocus is on, try to restore the focus to the last window which was focused when we left this workspace. */ - if ( Scr->SaveWorkspaceFocus && newws->save_focus) { - for (twmWin = &(Scr->TwmRoot); twmWin != NULL; twmWin = twmWin->next) { - if (twmWin == newws->save_focus) { - WarpToWindow(twmWin); - } - } + if (Scr->SaveWorkspaceFocus && newws->save_focus) { + twmWin = newws->save_focus; + if (OCCUPY(twmWin, newws)) { /* check should not even be needed anymore */ + WarpToWindow(twmWin, 0); + } else { + newws->save_focus = NULL; + } } /* keep track of the order of the workspaces across restarts */ @@ -1502,10 +1503,14 @@ void ChangeOccupation (TwmWindow *tmp_wi for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { int mask = 1 << ws->number; if (changedoccupation & mask) { - if (newoccupation & mask) + if (newoccupation & mask) { WMapAddToList (tmp_win, ws); - else + } else { WMapRemoveFromList (tmp_win, ws); + if (Scr->SaveWorkspaceFocus && ws->save_focus == tmp_win) { + ws->save_focus = NULL; + } + } } } @@ -1585,8 +1590,8 @@ void WMgrAddToCurrentWorkSpaceAndWarp (v } if (! tw->mapped) DeIconify (tw); - if (! Scr->NoRaiseWarp) RaiseWindow (tw); - WarpToWindow (tw); + //if (! Scr->RaiseOnWarp) RaiseWindow (tw); + WarpToWindow (tw, Scr->RaiseOnWarp); } static void CreateWorkSpaceManagerWindow (virtualScreen *vs) @@ -2900,7 +2905,7 @@ move: XMoveWindow (dpy, w, newX - XW, n XMapWindow (dpy, sw); XDestroyWindow (dpy, w); GotoWorkSpace (vs, ws); - if (!Scr->DontWarpCursorInWMap) WarpToWindow (win); + if (!Scr->DontWarpCursorInWMap) WarpToWindow (win, Scr->RaiseOnWarp); control_L_sym = XStringToKeysym ("Control_L"); control_R_sym = XStringToKeysym ("Control_R"); control_L_code = XKeysymToKeycode (dpy, control_L_sym); -Olaf. -- ___ Olaf 'Rhialto' Seibert -- The Doctor: No, 'eureka' is Greek for \X/ rhialto/at/xs4all.nl -- 'this bath is too hot.'