Tekwm The Tektronix Window Manager Proposed Tekwm Enhancements Public Domain Release Glenn Widener Tektronix, Inc. November 22, 1989 The following is a list of possible Tekwm enhancements, in rough order of my decreasing interest. Some were logged with Tek "XWS" bug tracking numbers where they have been encountered by someone other than the author. Hackers, here is your big chance! Optimization Optimize focus handling under frameFocus by resetting focus to PointerRoot when cursor enters the client window. Then the wm does not have to wake up when moving into another window to get focus moved. Seems that the fix to FocusChng.c was not enough? Add an f.killsession, that ignores WM_CLOSEDOWN and WM_PREPARE_TO_DIE. Add f.killsession and f.kill to the System/Window menus. Total level 3: 2 level 4 ICCCM: per proposed new section on grabs, grab on parent window instead of client window. Also eliminates existing grab collision bug with xterm. ICCCM: per proposed new section on grabs, replay all keys not actually used by the wm when doing passive grabs on the client window. ICCCM: implement WM_TAKE_FOCUS Necessary for override-redirect if we follow ICCCM restriction on installing override-redirect colormaps, since the client must use the Globally active focus model to insure that focus moves to the top-level window before the client maps the popup. The ICCCM is not clear on the border_width to be returned - should it be the actual client window border width, the apparent width seen by the user (including BorderContext), or the client-requested border width? Apparent seems most informative, however, Tekwm should send the client-requested border width, on the argument that the position of the inside of the window computed from the Notify should be correct. Currently, it does not appear to be sending what the code sqys it should! The ICCCM also does not specify the "above" field; Tekwm sets it to None. Tekwm should send the client window below the restacked window (if ICCCM adopts this, else this has lower priority) The ICCCM also does not specify that synthetic ConfigureNotify or CirculateNotify requests will be sent by the window manager when it restacks the client window. Tekwm currently does not send such synthetic events. It should. Total level 4: 9 level 5 --------------------------------------------------------------------- All enhancements below here are not planned to be completed before the first release. --------------------------------------------------------------------- Add an f.null to make (silently) disabling system-wide operations easier. Required if we add ability to bind multiple functions to one action. Be sure to update explanatory man page text on resetxxx. Disable "move" gadgets if fixedPosition is set, and disable "resize" gadgets if fixedSize is set or if the client sets min_width/height and max_width/height size hints the same. Particularly handy for Peer interface and request for immovable windows. Add ability to map multiple operations to the same event. Perhaps a general syntax (add) ? Handy for forming operations that are a sequence. Revise initial window sizing to support USPosition without USSize to interact with the user for size given an initial placement. At map time, initialize rubber box from anchored corner to cursor, with correct quadrant angle cursor, ignore button press, accept size on button release. Cursor is constrained to quadrant determined by PositionGravity hint. If PositionGravity is Center or an edge ("NorthGravity"), different feedback is required, e.g. a fixed center or the current feedback, with the anchored border fixed, one angle cursor to set one opposite corner at button press, and a bar cursor to set remaining side at release. Only anchored corners are required for Anchored VT. Add resources icon.pixmap and icon.mask that specifies a pixmap (bitmap) and pixmap mask to use as the icon if the client has not specified a pixmap. If both are specified, they must be the same size. The icon is the size of the pixmap. The existing icon.pixmap resource is renamed icon.text.pixmap. See also "text icon colors" below. (This is not really interesting enough to warrant doing). Currently, if the client requests initial_state = IconicState, the UL corner of the icon is placed at the upper left corner of the screen, unless the IconPositionHint is specified, in which case the specified position will be the center of the icon (but keeping the icon fully on screen). We should add some automatic icon placement as follows: add resources awm.initialIconX and awm.initialIconY, which give the starting UL corner position for new icons (default 0, 0), whether initially iconic or iconified by f.iconify (f.newiconify always iconifies at the cursor position.) The first icon is placed at this location, and subsequent icons are tiled from this position towards the direction specified by IconStackingDirection = {up, down, left, right}, default down. Should the icon stack hit the edge of the screen, (or the edge of a window?) the initialIcon position is reset to place the next icon adjacent to the first one, building a two-dimensional array of icons. (Do we need the ability to disable this feature? If so, add IconStackingDirection=none.) (Do we need the ability to disable this feature for f.iconify, but leave it operable for initial_state=Iconic? If so, add defaultIconifyPosition, class Auto, type Bool. If off, f.iconify switches to f.newiconify, per above.) Now, lets add the following: If f.newiconify is executed on an unplaced icon and the resource defaultNewIconifyPosition (class Auto) is on, place the new icon according to the default icon position rules above, warp the cursor to the icon, and continue with interactive placement. When the button is released (if still at initial icon position?), warp the cursor back to the button press point. If defaultNewIconifyPosition is off, f.newiconify works as it does now. warpOnDeiconify should warp to titlebar, so that the pointer is positioned for further actions (like iconify). Then a series of clicks toggles iconification. (FIxed by Rick Faltersack) Best - make deiconify position user-configurable via a geometry-style syntax: NorthWest, Center, etc, plus title/window Boolean. XWS00411 Suppress warpOnDeiconify and warpOnRaise when automatically deiconifying/raising - new resources WarpOnAutoDeiconify/WarpOnAutoRaise. < With X11 people accomplish this by applying f.move on button press and < f.raise on button release (or vice versa). Similarly, f.iconify should < be done in the same way, perhaps even on the same button motion. < < f.iconify = : icon: right down < f.raise = : icon: right down Unfortunately, awm (and I presume, uwm) does not allow multiple operations to be bound to the same action. Only the first function declared is used. Awm could be easily enhanced to allow this, anybody want it badly? Actually, the semantics of the two bindings above is a bit ambiguous - should it raise the icon that was selected, or the window mappped by the f.iconify? With the easiest implementation, it would be order independent. If we recomputed the context after each function, it would be order dependent, so that a f.raise declared before f.iconify would raise the icon, and declaring f.raise after f.iconify would raise the window (if warpOnDeIconify is on!) My vote is to leave it order independent, and explicitly adjust the context on f.iconify per enhancement above. (KISS) Once this is done, add an f.raise after all bound f.iconifys, and remove code that raises the deiconified window. Note that only immediately executed functions can be bound before another function on the same action - f.newiconify, f.move, f.moveopaque, f.menu, and f.resize cannot be bound except as the last function bound for an action. TRANSIENT_FOR windows should iconify and raise/lower with the FOR window. This probably should be backed up by a per-client option to independently disable either mode. Window groups should iconify, move, and raise/lower together. This probably should be backed up by a per-client option to independently disable any effect of window groups. (Many clients may not want move, so it should be off by default.) Standard colormap support WM_COLORMAP_WINDOWS setting (wait for resolution of ICCCM issues) Apparently, this is now required even on single-colormap hardware because WM_COLORMAP_WINDOWS can be dynamically changed by the client. Need to initialize WM_CLIENT_MACHINE and WM_COMMAND on tekwm's WM_PROTOCOLS window. Make a fancy example tekwmrc file for power users! () If WM_ICON_NAME or WM_NAME resolves to be the same as one already created, use N, or N, where N is an integer incremented from 2 for each icon/window with the same name. - and/or - If the client has not set WM_ICON_NAME or WM_NAME, use N, where N is an integer incremented from 1 for each window with the same WM_CLASS.res_name. If WM_CLASS.res_name does not exist, use WM_COMMAND[0]. If nothing, we are back to " Untitled Window " again, but number them 1 -> N. While we are at it, recode GetIconName to use XGetIconName() and XFetchName(). And of course this gets rid of the bug that no icon or window name property cases an empty icon. Redesign resize so it can dynamically change which corner or side is being resized like twm - when the size goes to zero in x or y, reset to original size and switch to the border or corner based on the current cursor position. Unlike twm, continue to select initial corner/edge immediatel on press; don't wait for the user to cross a boundary. total 19 level 5 to here... We should fix the protocol converter to put the client name in WM_CLASS, and then read Wm_options for override-redirect windows, so we can title X10 windows. Add support for buttons 4 and 5 - allow '1'-'5' for buttons. If color allocation fails, allocate closest of black/white in default colormap. (GetPixel) There should be a different shell command action that invokes the command on another node, say '@'. @ "command" invokes on machine given by $DISPLAY, @machine "command" invokes the sommand on the specified machine. Of course, requires rsh access. The client window needs to be protected from the borderContext cursor when its cursor is set to None (inheriting the root cursor). Proposal 1: BorderContext cursor should be reset to None (use root window's) if frameFocus and nothing is bound to context. Proposal 2: add an intermediate window, and set its cursor to XC_X_cursor. This works until the root cursor is changed. We can't fix this easily because there is no event on cursor change. Perhaps a periodic check, or else get xsetroot to also set a property onthe root window? Should we obey PPosition? No, if we get USSize without USPosition, we need to collapse all three buttons into the left button semantics, and place the pre-sized window at the button release. The initial rubber box, and the box for left or right button sizing should be a move grid instead of a resize grid. The initial rubber box before a button press should be at default size, not minimum size. A middle button press-release without a move of more than delta pixels or size_inc pixels, whichever is smaller, should give the default size, just like left button. Need to figure out a way to eliminate the race between the client mapping its window and the user trying to resize it. Proposal - add a syntax to the .awmrc file of ? ["geom"] that tells awm to go ahead and get a bounding box from the user, and stash it away for the next mapped window. The user puts the same geometry in this field that he gives to the client. This fixes the problem for clients that are brought up from the menu, the main area of annoyance. Problems - certain important hints like Pmin/max size and size increments are not available yet, so the user-provided size may get forced larger/smaller, and the resize popup will always be in pixel units, not size increments. How's this - start up the client immediately, and hold its window creation until the user selects it! Add per-window border width. This could be added as a per-window resource (wm_option) in Tekwm, regardless of the ICCCM. And the resource could even specify that the visible window border is to be taken from the border requested by the client at map time. We need to set the client window border to zero and use a parent window border, so that we do not have to modify the client border pixmap, which requires that we be able to allocate in the client window colormap in order to ever get correct colors on a per-window-colormap hardware, and so we don't care if clients modify it after mapping. (Not an issue unless we get clients that dynamically modify the border or we get per-window-colormap hardware.) Current decoration arrangement can be preserved by adding the intermediate window above. Add a client message action. It sends a WM_PROTOCOLS-style client message to the (pre-)selected window, with the atom named in the action rc file line: f.message=[context]:events:message" atom name" (suggested by Suresh) Similar to WM_PROTOCOLS-based messages in menus idea, but defined in rc file. More generally, incorporate toolkit translations in reverse - use the tm syntax to define a sequence of events or a string to be sent to the selected window. Allow a client specific gadget. Add the rc file syntax gadget[] that declares an unused gadget, and the resource syntax wm_option.gadget[n]: to set the gadget number n to gadget name. Can then invoke the login xterm with -name login to change its close gadget to a "shutdown X11" gadget. Allow individual gadgets to be disabled via the resource wm_option.gadget[n]: off. This is needed to disable the close gadget on the login (and possibly all xterm?) windows. Simultaneously remove "no gaps" restriction, i.e. gadget[0 2 3]... Allow gadgets to be disabled in the rc file by "gadget[n] = ()". Useful in user customization. May depend on "no gaps" restriction removal. Allow a client specific menu, as above. Add the resource syntax wm_option.menu: to attach menu to the client window (replacing any globally defined menu). Add tekwmrc menu color specification for default menu entry color (after highlight and title colors) (Wayne/Purdue's request) Add per-window icon colors (Wayne/Purdue's request) For both text and pixmap icons. add a resource to redirect stderr to console (use in xstart only). Total level 5 to here: 40 Optimization Try to resurrect old alternateGC/GXinvert menu optimization for the case where no menu colors are specified in the .tekwmrc file and menu.title.fore/background and menu.highlight.fore/background are the same as menu.fore/background. A further optimization could generate an invert plane mask on the fly, separate initial drawing from inversion, and work for any color combination. Optimize highlighting by globally caching Pixel values for text colors for windows using DefaultColormap. (eliminates a round trip for most windows) Title seems to be painted twice on window creation, at least for xterm -aro -ado. We could be caching window sizes, for example to save getting size from server in PutGadgets. (Done, but not used or kept up-to-date, as part of awi->xwa.) We should cache the XWindowAttributes for the client, to avoid at least two extra round trips during startup. (Done) When we do, we should fold awi->client_cmap into the attributes (Done, but not used everywhere yet (FocusChng, Gadget, Titlebar.c). (Note that ColormapNotify is already caught.) cache XWMHints (Done, but not used everywhere yet (Iconify, Icons, Restart, Titlebar). cache the SizeHints for resize, to avoid an extra round trip and sanity check at resize. Make AwmInfos into a linked list so Cleanup can traverse list instead of querying window tree. Look at post-sizing window creation. Compare with twm. Look at resize bbox tracking speed, general mouse tracking, window ops speed. Refresh.c should position the covering window just above the target in stacking order so it can only cover the target window. (unless of course the target is root). change autoRaise to not raise if not obscured by another window (i.e. off-screen). (Use f.raiseandlower algorithm, see also uwm menu bug autoRaise.) XWS00402 Icon names get repainted multiple times on button release from a move. Need to compress exposures across multiple damage events. Run tekwm remotely, and look for performance problems (and timing problems!). Stop tekwm from resetting the highlighting when pointer moves from client window into title bar. Total Deferred optimizations: 14 Add a context of "all gadgets" as "gadgets" or "g". So we can really get meta keys over the entire screen, without specifying each gadget individually. On menu functions that take a gin point, erase the menu except for the selected menu item after the item is selected, to reduce the chance of the menu covering the object you want to select. (XWS00107) XWS00295 Change f.iconify to re-adjust the computed event window/x/y to the new icon/window for subsequent operations bound to same button event or to delta. This makes an f.raise binding to icon after an f.iconify binding to icon raise the window. Changing it for the up button is probably also OK, but not as easy to do. How about other functions that change the apparent context (e.g. f.lower, raiseandlower, circleup, circledown, though adjusting does not seem useful on these)? Once this is done, add f.raise to icon : middle down. Default tekwmrc had an entry of f.iconify on icon : middle down and f.moveopaque on icon : middle delta. Should we restore it if this is fixed? Add a f.colormap function which, analogous to f.focus, permanently installs the selected window's colormap, so that neither future f.focus operations nor pointer motion changes the colormap. Selecting the root window restores colormap following focus (i.e. wherever f.focus goes). I can envision cases where the user is more interested in keeping the colors correct for some image that getting accurate colors for a menu. Add binding to a string of keystrokes in addition to mouse buttons, including "*". This latter permits implementing "beep on keys on root window". Title pixmap or background color should not be visible above or below the window name. Title background color should be filled in around to the extent of vPad. It would be nice if clients could specify a dynamic display gadget (boolean, plus perhaps string, bitmap, window?) which would display the value of a client-specified window property. Perhaps a top-level client window property that lists property atoms to be displayed? Plus perhaps a .awmrc specification as to gadget positions for dynamic gadgets (default, continue default placement). Add 3d shading to the bottom and right of icons (and windows?). Via a black window at the bottom of the window hierarchy. Possibly a user option... When window is moved back on screen, leave one pixel at edge of screen to get window manager (for Wall, normalw, normali). Map the popup so that the final cursor position is at the button press. Avoids warping. Always look in /usr/lib/X11/awm (SYSFILE define) last for pixmaps. Needed so tekwm can come up without any resources (e.g. xterminal bootstrap problem). Allow the title.text.background color to be "transparent", permitting the background pixmap to show through. Just special case color lookup, by checking for "transparent" before looking it up. Add an f.retitle function, which renames the selected window's title. Ugh, must prompt user for a string! Or else, implement ala Icon_typin. Turn on and document Icon_typin. If either window name or icon name is defaulted from another property, Icon_typin/Window_typin affects window/icon. Add a title.text.boldBackground, default title.text.background that is used on focus in. A gadget.background and gadget.foreground are needed, default title.background and title.foreground. Either they apply to both pixmaps and text, or else a gadget.text.fore/background are also needed. The resize box should stay within the bounds of the window being resized, if possible, if its normal position is off-screen, rather than just putting it in the corner of the screen. < Why not have another action in addition to {left,right,middle} {up,down,motion} < such as "deiconify-request"? < < f.iconify = : icon: deiconify-request < f.raise = : icon: deiconify-request < < You could also allow the action "iconify-request" and any number of others. < Alternatively, you could say that the deiconify-request implies (absolutely) < that the f.iconify operation be performed, but it would allow you to < specify additional actions to performed on receipt of the request (in < this case f.raise). < < Todd I kinda like this, so I will put it into the heap of possible enhancements. I would go for providing default bindings of the various requests (which are not reset by resetbindings) to their direct counterparts, and allowing them to be overridden in the awmrc file. Make sliding menus work (see uwm article). However, the last menu bound is the first one displayed, unlike uwm! Allow f.menu to be multiply bound to a single action, to produce sliding menus. The last menu bound is the first one invoked; sliding right off the menu (or only title?) gets the next menu, sliding left gets the previously bound menu. Need to handle win_gravity on Configuring non-reparented windows with final border different than requested, and undo it when undecorated. For now, simply don't change border width unless reparenting! make the menu return to the prior selection (but only at the first level, don't propogate to sub menus? - try it both ways). Enable off "autoSelect" resource. If there is no prior selection or prior cancel, select first item, per current autoSelect semantics. Total level 3: 1 Total level 4: 7 Total required: 8 level 5 above optimization: 36 level 5 below optimization: 21 Total level 5 enhancements: 57 level 5 optimizations: 14 Total level 5 (deferrable): 71 Total Optimizations: 15 Grand Total: 79 Enhancements Under Consideration Enhancements Rejected Should meta buttons on gadgets execute the gadget function? Or should we keep the meta bindings consistent across the whole screen, even though the intuitive expectation is that any set of modifiers over the gadget should work? How about icons? Currently, meta gets the root bindings everywhere. Answer: (in conferring with documentation) keep meta the same everywhere. The effective context for a delta binding is the context when the button was pressed. Therefore, for example, a binding of f.iconify to "icon : right down" and f.move to "icon : right delta" will not produce an intelligible result. This should be changed to re-establish the context for delta operations after any initial function is finished, so that the effective context is wherever the mouse is before the first motion event. Possible traps here - if you do a f.lower, and an icon appears under the mouse, and you move a bit before releasing the mouse... And suppose you drag fast after the button press, and end up getting an unintended motion operation... Is there a general solution? I don't think so! We may want to leave this alone. Instead, fix f.iconify to explicitly reset context. resize button should initialize rubber box at current size, pointer at current position, so down/up is a noop (same as move). < This would require warping the pointer around since the box is tracked < by querying the mouse (the resize grid is indeed created at the size < of the window, it's just that the first mouse position query sets < it to wherever you were when you depressed the button.) Are you sure < you want your mouse warping around like this? I believe that Todd clarified this one correctly - I don't see a need to warp the mouse. (Fixed - see resizeRelative resource) However, warping might be preferable, as it gives immediate feedback as to what resize operation is being performed (edge or corner), and makes the transition to opposite edges (see enhancement) work when the opposite edge is at edge of screen. However if nearest corner/edge is off-screen, it must re-size immediately on-screen (not warp cursor to screen edge and be relative from there). This gives a "feature" of adjusting to edge of screen automatically! 5 split resize window h/v padding and title h/v padding into separate resources (adding title hpad which causes title to be retained instead of gadgets in small titles.) (FIXED except for adding title hpad) < Good idea. I assume that the presence of title.hpad would result in < no centering of the title being done? Some might balk at this. The original < point was to move your gadgets out of the way, not vice-versa. I'm flexible < on this one. No, all I would make it do is control the padding around the text on both sides, for the purposes of 1. where background pixmap stops 2. where text background color stops 3. gadgets start disappearing. Note - windowName.offset needs to be rethought at the same time - it should be relative to the innermost gadget edge, and in addition to hPad. It does not cause title text to be retained over gadgets on oppposite end. If title text is too large We are controlling four things with two variables - should we reconfigure this? Gadgets supercede text; if windowName.offset = left or center, preserve left of text, else preserve right of text?? 5 Also, when title is too small for gadgets, outside gadgets should be retained, inside ones suppressed. 5 Gadget.pad should not allow the background pixmap to show through the gap. 5 need to suppress title.boldPixmap around gadgets and title. 5