[news] TWM -- Revised Edition

Eeri Kask <[email protected]> Tue, 30 Sep 2008 19:20:25 +0200
Newsgroups gmane.comp.freedesktop.xorg,gmane.comp.xfree86.devel
Message-ID <[email protected]>
Hello TWM users,

Having tweaked the TWM since last year to turn it into something 
contemporary in look and handy in function, today as a landmark of 
approaching zero items in my own kept TWM bugs-, todo- and wish-list may 
I use the moment to present this humble effort which has kept me pretty 
busy in the leisure time since then.


(*) Initially significant emphasis went into introducing and finetuning 
Xft truetype font support which is now a per-screen startup configurable 
feature.  If e.g. the Xft subsystem is not available TWM automatically 
falls back to X11 core font renderer.  (If started with '-truetype' one 
can turn Xft off intentionally.)

X11 core font names and Xft font names can be used arbitrarily 
intermixed in .twmrc as each font name is first attempted to resolve as 
XLFD name and only if this fails, then as Xft name.


(*) Further, sloppy focus is now seamlessly integrated into TWM at its 
most core.  In the same sweep the icon manager highlighting now follows 
focus and not mouse, making a lot sense for keyboard users caring less 
about mouse.


(*) Keyboard-aided mouse navigation has been enhanced as well. It is a 
high priority to control TWM comfortably by keyboard (with the exception 
of 'f.move', 'f.resize'), so the functions

     f.warpnext, f.warpprev
     f.warpring
     f.forwiconmgr, f.backiconmgr, ...
     f.nexticonmgr, f.previconmgr
     f.warpto "", f.warptoiconmgr ""

all having to do with mouse warping along client windows have been 
overworked to expose kind of a unified, consistent behaviour (e.g. all 
tied to 'WarpUnmapped', and all respect originally only by 'window-ring' 
saved mouse location coordinates).


(*) Invented is 'f.swapiconmgrentry' as a simple mechanism for run-time 
icon manager manual sorting which now leads to arbitrary 
client-to-client mouse travelling by at most two "keystrokes", using the 
icon manager as a switchboard.


(*) There is Xinerama support which can be turned off by '-xinerama' 
command line parameter leading to TWM treating the logical screen at 
full size (but possibly loosing icon managers, icon regions and client 
windows into dead areas).

Into this improvement category belongs 'RandomPlacement' algorithm which 
got a preliminary step first looking for an empty area on screen large 
enough to fit the window prior to placing it blindly at some 'random' 
location.


(*) The '-v' command line option gives some more info on startup and on 
'f.identify'.


(*) Last but not least several old bugs have been corrected: most 
notably related to multiscreen configurations and to 'f.focus'; and icon 
manager navigation functions no longer should occasionally unexpectedly 
refuse service, except if rendered dysfunctional by 'NoIconManagers'.


(*) A script of all enhancements (at varying level of detail) is 
attached as "NEWS.RevisedEdition" and the man page is uptodate.  (If one 
agrees to read one entry in the man page, the 'IconManagerGeometry' is 
the item worth a look.)


Keeping up the tradition of X development not to impose policy and even 
less taste all visual/functional enhancements are not only tunable but 
the .twmrc file if kept as is, leads to no change in TWM traditional 
look and function with the exception of (1) coloured icons if provided 
by clients; and (2) the semantics of 'WarpCursor' is slightly broadened: 
in addition now automatic warping into transient windows of focused 
clients occurs if they get mapped.


Though, the whole effort has lead to increase in TWM executable file by 
a factor of circa 1.2 which is very unfortunate, the foremost 
contributors being (referencing the x86_64 platform)

     Xft  (by ~ 8 Kbytes)
     Xinerama  (~ 8 Kbytes)
     Xrandr  (~ 4 Kbytes)
     sloppy focus  (~ 4 Kbytes)
     visual appearance improvements altogether  ~ 12 Kbytes



Concluding, here are presented various TWM enhancement proposals; anyone 
caring I am happy to invite to comment/discuss/review these, and 
anything related how to further finetune/improve TWM ... as an X11 
window- (not necessarily an office desktop-) manager.  :-)

Let me here in retrospect express my sincere thank you to all guys 
having helped to chase bugs and figure out better ways in making TWM better,

     Eeri Kask


P.S. To automatically compile, run
      http://www1.inf.tu-dresden.de/~ek1/TWM-Tweaked.sh

_______________________________________________
xorg mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/xorg
NEWS.RevisedEdition (text/plain, 29.9 KB)
    TWM -- Revised Edition
    ======================


Each of the  twm.man.diff??  patches belongs to the corresponding
patchset  diff??.twm-1.0.4.*.



(0) twm.man.diff00

    This patch documents previously undocumented twm functionality
    (most items were commented out).  Most notable are f.warpnext,
    f.warpprev.



Patchsets

    diff01.twm-1.0.4.MyFont_ChangeGC
    diff02.twm-1.0.4.MyWindow
    diff03.twm-1.0.4.TWM_USE_XFT

implement per-screen configurable Xft-truetype font support.



(1) diff01.twm-1.0.4.MyFont_ChangeGC

    First, few loose colour pairs denoting fore/back (twm.h, menus.h,
    iconmgr.h) are coupled into ColorPair-datastructure, necessary for
    later font rendering calling interface.

    Second, the functionality of MyFont_ChangeGC() in downshifted into
    MyFont_DrawString() and MyFont_DrawImageString() respectively and
    this function itself is removed. The calling interface of the
    MyFont_Draw...() functions is adapted accordingly.



(2) diff02.twm-1.0.4.MyWindow

    Twm own windows (menus, icons, iconmanagers, title bars,
    info-/sizewindow) which later will feature Xft-font rendering are
    enclosed into the 'MyWindow' datastructure to encapsulate the
    font-drawing target drawable: for core fonts or for Xft-fonts.
    The calling interface of MyFont_DrawString() and
    MyFont_DrawImageString() is adapted accordingly.



(3) diff03.twm-1.0.4.TWM_USE_XFT

    This patchset introduces the EnableXftFontRenderer per-screen
    keyword. The '-truetype' command line option disables Xft usage,
    falling back to core fonts.  Further, if Xft is not available,
    fallback to core fonts occurs as well. If during runtime core-font
    or Xft-font renderer is to be used is determined solely by the
    Scr->use_xft variable.

    As XftDrawCreate() in libXft may return a NULL-pointer, the sole
    purpose of the wrapper function MyXftDrawCreate() is to check this
    and output a warning.  MyXftDrawDestroy() does the cleanup. As the
    Xft-documentation apparently doesn't treat this NULL-pointer
    issue, the pointer is passed unaltered to XftDrawString8()
    delegating the responsibility not to crash twm to that function.

    The function MyFont_DrawShapeString() draws text (core font or
    Xft-font) onto a depth-1 pixmap to be used later as
    underground/shapemask in Shape-extension-based transparent text
    rendering in icons and icon managers.

    The MyFont_Draw...Ellipses() functions are prepared for
    abbreviated text drawing, which ends with "...".

    An aspect to be noted is, Xft-based rendering occurs with
    alpha-blending against the existing drawable background. This has
    the consequence that the background has to be cleared prior to any
    drawing in order to avoid text smearing which occurs on repeated
    Expose events. Therefore, in some cases the original
    MyFont_DrawString() is replaced by MyFont_DrawImageString() and in
    other cases preceded by XClearArea(). Affected is events.c
    HandleExpose() mostly.

    The core-font vs. Xft-font name in .twmrc is resolved as follows.
    The font name is first assumed to be a core font and its eventual
    alias is resolved by XGetFontProperty() using XA_FONT.  If this
    resolving succeeds, the 'core' font is opened using
    XftFontOpenXlfd().  Otherwise the font name is assumed Xft-name,
    and XftFontOpenName() is called.

    Xft-support is included by -DTWM_USE_XFT gcc option.



(4) diff04.twm-1.0.4.TWM_USE_SPACING

    Pixel-based text spacing is replaced by font-size-based text
    spacing. This ensures smaller baseline skips and left/right
    margins for small text sizes and vice versa. This spacing is
    independent of core- or Xft-font usage.  This feature can be
    enabled by -DTWM_USE_SPACING.



(5) diff05.twm-1.0.4.TWM_USE_SLOPPYFOCUS

    First, the screen-based focus state variables "Scr->Focus" and
    "Scr->FocusRoot" are made global as nothing seems justifying them
    to be screen based and so simplifies understanding of twm focus
    management and cleans code.

    Second, few 'f.focus'-related bugs are corrected, e.g.
    WarpToScreen() and Execute(): the first not working at all, the
    latter executes the Execute() on the screen with f.focus'ed
    client and not where the mouse is. This is extremely
    counterintuitive. FindPointerScreenInfo() now finds the screen
    where the mouse is.

    The F_FOCUS handling in ExecuteFunction() in menus.c is shifted
    into a dedicated function FocusOnClient() to be used elsewhere as
    well.

    This patchset introduces the 'SloppyFocus' keyword and the
    'f.sloppyfocus' function, and implements the sloppy focusing of
    client windows: the client is not unfocused while leaving. It is
    unfocused only if entering some client which is going to accept
    focus (according to ICCCM).

    A client 'Tmp_win' accepting focus means the boolean expression

	(Tmp_win->wmhints == NULL) || (Tmp_win->wmhints->input == True)
		|| (Tmp_win->protocols & DoesWmTakeFocus)

    is evaluated to 'true'.

    If the client is not going to accept focus, the focus remains in
    the previous window (or, if in the icon manager, the focus is set
    to 'PointerRoot'). If in the icon manager and the highlighted
    client is iconified, the focus is set to 'PointerRoot' as well (in
    both cases not leaving the 'SloppyFocus' state, so the next
    focusable client grabs focus again).

    Most affected functions are HandleEnterNotify() and
    HandleLeaveNotify(). The 'Focus' global pointer always points to
    the client having focus or is NULL if no client is expicitly
    assigned focus by XSetInputFocus(). The 'FocusRoot' is never
    'true' if some client is f.focus'ed and blocks executing some code
    segments accordingly. Here SloppyFocus, which largely operates
    like f.focus, while 'true' unblocks most of these code segments
    (mostly the one in HandleEnterNotify()), so enabling focus
    assignment on entry into some client. So 'FocusRoot' can be 'true'
    while SloppyFocus is 'true', as long as no focusable client is
    entered.  It is intension that 'f.sloppyfocus' always first sets
    'FocusRoot' to 'true' (and sets X server focusing to 'PointerRoot'
    mode) so withdrawing focus out of some client if executed on a
    root window (though, if executed not on a root window e.g. by a
    twm keybinding, then while releasing the bound keypress an Enter
    event is generated for that client under mouse, so setting 'Focus'
    to that client and 'FocusRoot' to 'false').

    Finally, the window border, title bar highlight and icon manager
    highlighting reflect the following.  (1) The window border
    reflects Enter/Leave events (into/out of client windows, or
    respective icon manager entries label-windows), irrespective of
    SloppyFocus, f.focus, or client focusability.  (2) The title bar
    is highlighted by FocusIn/FocusOut events twm catches (or twm sets
    them in cases these events are not expected, like focusing by
    SendTakeFocus, or in PointerRoot mode).  (3) The icon manager
    highlighting reflects the twm's believing where the focus should,
    be irrespective where the mouse is (esp. in SloppyFocus mode);
    e.g.  unfocusable windows are not highlighted in the icon manager.
    As a rule the icon manager and the corresponding title bar
    highlighting should coincide (attn: 'NoTitleFocus' disables icon
    manager focus redirecting, so no entries in iconmanager are ever
    highlighted then).

    Last but not least, 'SloppyFocus' obsolates 'NoTitleFocus' for the
    time while 'true'.

    To enable sloppy focus, use -DTWM_USE_SLOPPYFOCUS compiler flag.



(6) diff06.twm-1.0.4.IconMgrCollapseFix

    If configuring some icon manager in .twmrc to have multiple
    columns, then moving or resizing that icon manager window and
    finally a new client is created or some destroyed (so that
    PackIconManager() is executed) one observes a kind of iconmanager
    window horizontal collapsing.  Seemingly this bug is known as in
    EndResize() in resize.c and the 'savewidth' variable in
    PackIconManager() function probably are attempts to deal with this
    issue. Further investigation disclosed the 'cur_rows' and
    'cur_columns' iconmanager member variables are never explicitly
    initialised having arbitrary initial values on first referencing
    in PackIconManager(). It looks like this leads to that said
    iconmanager window gradual collapse. This patchset cleans up this
    mess (i.e. provides a better solution).



(7) diff07.twm-1.0.4.Fixes

    This patchset only contains some of the obvious bugs in twm,
    various others are silently dealt with in appropriate other
    patchsets.

    (a) There is a missing 'break' leading to unintended 'switch'
    fallthrough in gram.y.

    (b) The 'dpy' call parameter is removed from I18N_FetchName() and
    I18N_GetIconName() calling interface as this is a global variable
    anyway and passing this into these only functions is pointless.

    (c) XShapeSelectInput() is called consequently twice in
    AddWindow() with no apparent reason.

    (d) The Zoom() function includes 'unsigned' integers in an
    arithmetical operation assuming signed-integer arguments. (Leading
    to nonsense in icon zooming drawing; how this bug could survive 20
    years?)
    Iconify() and DeIconify() are slightly reordered.

    (e) I18N_FetchName(), I18N_GetIconName() very probably leak
    memory, especially the latter (not setting 'iconname' to NULL if
    it fails, missing XFree(text_prop.value); etc). Both are
    cleaned up.

    (f) The ":menu" pixmap (which is created only once in twm
    lifetime) can easily have different uses, like be used on the
    title bar with a huge font, and in a menu having a small font.
    Now using the same pixmap tuned for the large font size is wrong
    in the case of a menu. So CreateMenuPixmap() had to be rewritten
    with this in mind.

    (g) SetFocus() in util.c didn't check Scr->Focus being NULL and
    crashed twm in '#ifdef TRACE' branch while performing f.restart.

    (h) F_CUT and F_CUTFILE included obvious buffer overflow holes.
    (The purpose of these functions is yet to be figured out; at first
    sight it looks like alien garbage ... in the sense that, why
    wasn't that code snippet prepended with XOpenDisplay() and moved
    out into a stand-alone application, and then run by 'f.exec'?)

    (i) CreateIconManagers() had potential buffer overflow holes
    caused by sprintf().

    (j) Identify() shows the borderwidth 'bw' which is always '0' for
    all clients all times, as this borderwidth is always kept zero,
    as can be seen in AddWindow().

    (k) DrawIconManagerBorder() may sometimes draw to some other
    screen as pointed to by 'Scr' (look at 'UnHighLight_win' in
    events.c in HandleEnterNotify()!). It is essential to use the
    saved 'scr' iconmanager member variable as reference for that
    drawing.

    (l) ExecuteFunction() should only in few selected cases (F_MOVE,
    F_RESIZE) execute XGrabPointer() with 'confined_to' set to
    Scr->Root on entry.  In a multiscreen environment this leads to
    mouse warpings to some other screen where some random X-event
    happens without an apparent reason for the twm user (e.g.
    client-initiated 'iconify').

    (m) Twm suppressed printing out of most X-protocol errors in
    TwmErrorHandler().  Often these are generated by having events of
    a dead client in the twm X-event pipeline. Now introduced
    DiscardWindowEvents() should throw these out in
    RemoveIconManager(), HandleDestroyNotify() and
    HandleUnmapNotify().
    This X-error printout is enabled again without restrictions and
    all occurrences of these errors should be considered twm bugs
    which are to be investigated.



(8) diff08.twm-1.0.4.Appearance

    (a) If the iconmanager layout specification contains 'North' or
    'East' then the iconmanager while growing extends to the left or
    top (iconmanager "gravity" against to the root window is at some
    other as the default top-left corner).  This functionality is
    essential for 'horizontal' icon managers, e.g. at the screen
    bottom to not extend off screen if rows are appended (and then
    automatically shrink down if rows are removed). Principal code
    is in InsertInIconManager() (list reversing) and SortIconManager()
    (sorting order predicate inversion).

    (b) If the 'columns' parameter in icon manager layout
    specification is negative, extra entries are prepended (not
    appended) to the linked list.  This also affects the
    ascending/descending icon manager alphabetical sorting.
    Principal code is in PackIconManager().

    (c) Iconmanagers now have ClassHints and can be configured by
    .twmrc as usual clients.

    (d) Iconmanager "iconify knob" has now sizes 11x11 (original
    size), 13x13, 15x15, 17x17, 19x19, 21x21; and the size to be used
    is chosen proportional to iconmanager font height during icon
    manager creation. Global variables 'iconifybox_width',
    'iconifybox_height', 'iconmgr_textx' must be now local to 'Scr'.

    (e) Icon manager entry iconify-knobs and title bar buttons pixmaps
    are respective window background pixmaps now, therefore no Expose
    events are needed for drawing them, so HandleExpose() could be
    simplified.

    (f) The twm-client list and the ring-list are backwards sorted in
    respect to the (unsorted) icon manager list order. This leads to
    confusion if f.warpnext and f.warpring "next" highlight icon
    manager entries which run in reversed order (bottom up or right to
    left). Elements in both first lists are prepended, icon manager
    elements are appended to the list. Now all elements in both lists
    are sorted accoring to 'Scr->iconmgr.reversed' being 'true'
    (prepended) or 'false' (appended).

    (g) If the value given to 'FramePadding' is greater than TitleFont
    height (which only becomes apparent after font loading), this
    value is treated as title bar height and the actual value for
    'FramePadding' is calculated as the half difference of the title
    bar height and TitleFont height. This allows to specify title bar
    height in pixels exactly.  (If 'FramePadding' specified in .twmrc
    is not greater than TitleFont height, this recalculation is not
    performed.)

    (h) The 'DefaultFont' keyword is introduced (used by Infowindow).

    (i) Info-/Sizewindows now have border width of Scr->BorderWidth
    and border color of Scr->BorderColor.

    (j) Menu titles are rendered using the Scr->TitleBarFont.

    (k) Infowindow of f.identify displays some client window property
    values if twm is started with '-v'. (f.version shows the focus
    window and 'revert-to' ... to chase clients which set focus to
    None.)



(9) diff09.twm-1.0.4.TitleHighlight

    This patchset introduces

	TitleHighlightForeground
	TitleHighlightBackground
	TitleButtonForeground
	TitleButtonBackground
	RoundedTitle
	BorderTile

    .twmrc keywords. The first two are the BorderTileForeground,
    BorderTileBackground counterparts and specify the title bar focus
    highlight pixmap foreground, background colors. Button colours do
    the same to titlebar buttons (the button border is painted in
    button foreground color; alternatively one can set the border
    width to zero and enlarge the button bitmap accordingly).

    'RoundedTitle' can be seen as "SqueezeTitle-Light" setting 3x3
    shape (bounding, and if borderwidth > 0 then for clipping) bitmaps
    to the upper left/right corners of the frame window.
    InitTitlebarCorners() initialises the shape pixmaps and
    SetFrameShape() sets the shape on frame-window resize etc. The
    upper corners of menus are shaped only if the first entry is of
    type 'F_TITLE'. (And, of course, client windows not having the
    title bar are not shaped as well.)

    'BorderTile' is the 'TitleHighlight' pixmap counterpart: the
    xbm-pixmap for client window frame borders.

    All above parameters default to their usual values.



(10) diff10.twm-1.0.4.Ellipses

    Text on window titlebars, iconmanager entries and icon labels is
    cut off not to exceed some maximum length apparent from the
    particular context and become the string "..." appended depicting
    this cutoff.  E.g., if icon regions are specified in .twmrc, then
    the maximum area width of a grid cell over all given icon regions
    is determined and no icon label will be wider than this value.
    This ensures the icon placing algorithm always succeeds in finding
    a grid location for the icon and doesn't place the icon randomly
    at the mouse location arbitrarily on the root window stretching
    from the left screen edge to the right. In HandleExpose() in
    events.c all occurrences of MyFont_Draw..String() are replaced by
    MyFont_Draw..StringEllipses() accordingly.



(11) diff11.twm-1.0.4.ShapedIcons

    Introduces 'IconBitmapColor' keyword to determine the foreground
    color for depth-1 pixmaps for icons instead of using the
    'IconForeground'. Further, if some client provides a color icon in
    WM_HINTS, this is used by XCopyArea() instead of historical
    XCopyPlane() which used to work for depth-1 pixmaps.

    Further, 'ShapedIconPixmaps' boolean variable determines if the
    icon area in the icon window gets a bounding shape (assuming the
    client provides a shape pixmap in WM_HINTS). For clients providing
    depth-1 icon pixmap this same pixmap is used for bounding shape.

    'ShapedIconLabels' (translation) geometry variable activates the
    icon label text shaping. First, the text is drawn onto a shape
    bitmap (depth-1). Then if the translation argument is not "+0+0"
    then the shape bitmap is copied onto itself appropriately for
    the specified amount of x-shift and y-shift. This bitmap is used
    as bounding-shape for the text area of the icon. The shifted area
    is painted in 'IconBackground', influencing the text (which is
    drawn by 'IconForeground') contrast and readability against the
    root window.  SetIconShapeMask() sets both bounding shapes: for
    the icon pictogram and for the icon label text.



(12) diff12.twm-1.0.4.ShapedIconManager

    'ShapedIconManagerLabels' is the icon manager counterpart of
    'ShapedIconLabels'.

    In DrawIconManagerBorder() the 'FilledIconManagerHighlight' draws
    a filled background as iconmanager highlighting and not a
    rectangular outline.

    The shape masks are drawn directly onto the iconmanager
    twm-window-frame denoted 'ip->twm_win->frame'. Alternatively one
    could draw them onto iconmanager client window 'ip->twm_win->w'
    and rely on twm's HandleShapeNotify() to copy them to the 'frame'
    but this gives nothing except a huge copy overhead. The only
    cosmetic drawback is, SetFrameShape() erases this shape mask and
    after F_MOVE'ing the iconmanager these shapes need to be painted
    anew in ExecuteFunction().

    Finally, to speedup iconmanager Enter/Leave events handling, these
    events are ignored (not selected at all) in AddWindow() for the
    'tmp_win->frame' and 'tmp_win->w' windows of the corresponding
    iconmanager clients.  Processed are Enter/Leave events only
    into/out-of iconmanager client-label windows; which is enough.
    Therefore unnecessarily repeated iconmanager painting by
    ActiveIconManager() and NotActiveIconManager() can be avoided
    which is otherwise caused by entering the above 'frame' and 'w'.
    Though, as a downside the 'AutoRaise' of iconmanagers needs
    special treatment in HandleEnterNotify() now; which is far less
    costly as the unnecessary (shape, etc) painting otherwise.



(13) diff13.twm-1.0.4.XUrgency

    The RaiseInfoWindow() contains now code which is extracted from
    Identify() in order to generally use Infowindow regardless of
    purpose (f.version, f.identify).  Now Infowindow shows the client
    window name if this client sets the XUrgency flag in WM_HINTS.
    This Infowindow is positioned across the title bar of the client
    (or at the top-left corner of the screen if the client is
    iconified).

    Apart from the purpose above this mechanism can be successfully
    (mis-)used by the client to communicate a message to the twm user
    by XUrgency: first set the window title to some message text, then
    raise XUrgency, and then restore the original title text again.
    The message appears above the client window title bar in the
    infowindow.



(14) diff14.twm-1.0.4.NoWindowRing

    Simple usage extension of WindowRing: include into window ring
    anything but clients in 'NoWindowRing'.  Though, if 'WindowRing'
    is specified in .twmrc, then this variable here is void.



(15) diff15.twm-1.0.4.NoWarpCursor

    'WarpCursor' semantics is moderately extended: not only is the
    mouse warped into the client on deiconifying but on client mapping
    as well.  Though, this warping is disabled if some client has
    'f.focus' activated. Not only is it a security issue but it is not
    apparent what to do with f.focus in such a case generally, e.g.
    (1) release f.focus, (2) transfer f.focus to the client to be
    warped into, (3) restore f.focus or not after disappearing of this
    client (needs implementing of focus history mechanism); or any
    combination of these.  Being a complex issue the most reasonable
    seems to do nothing automatically in this case, justifying this
    with the fact that the user having intentionally activated f.focus
    now it is up to him to manually unfocus that client first in order
    to restore the 'WarpCursor' auto-warping functionality.

    Finally and most importantly, 'WarpCursor' or 'NoWarpCursor', each
    of these activate automatic warping into 'local' transient
    windows which means, that happens if and only if that transient
    window's WM_TRANSIENT_FOR points to the client having iconmanager
    highlight or having focus; or if the transient window is in the
    same 'window group' as the client being highlighted or having
    focus.

    'NoWarpCursor' activates warping into all clients but these listed
    here. If 'WarpCursor' is also specified, this list here is ignored.



(16) diff16.twm-1.0.4.Fmaximize

    A simple extension of f.fullzoom: enlarges the client to
    preferrably (up to ConstrainSize()) cover 100% of the root window;
    leaving twm-generated titlebar and frame window borders out of the
    visible screen area. The top-left pixel of the client is always
    at (0,0).


(17) diff17.twm-1.0.4.RandomPlacement

    Btw. not being 'random' placing at all this patchset doesn't
    change that fact either but first tries to find an empty screen
    area to be large enough to fit the client without covering some
    other client, and only if this fails then falls back to the
    original placing algorithm. The area search looks for a 'best fit'
    and 'next to best fit' area: the first is slightly larger than the
    client so leaving some empty room on each side, the latter may
    result in edge-to-edge placement in respect to some other client.
    The client windows are filled in left-to-right and  top-bottom
    order across the screen. The FindEmptyArea() runs recursively and
    takes rectangle-info (4x4 integers plus pointer) from the stack as
    'auto' variable on each iteration.

    Some toolkits put transient windows at arbitraty locations not
    checking if they are fully visible on the screen, so twm now
    checks that (and tries to make them 100% visible).



(18) diff18.twm-1.0.4.TWM_USE_XINERAMA

    Xinerama support includes:

    (a) The xinerama-specific X11 code is only in twm.c in setting up
    the tile list.

    (b) Previously existing geometry-checking inlined code is shifted
    into EnsureRectangleOnScreen() or EnsureRectangleOnTile()
    functions.

    (c) Twm menus, icon regions, icon managers, info-/sizewindows are
    ensured to not fall in dead areas by a minimum possible effort.
    Menus are not split across tiles. Client windows are first
    attempted to put on tiles having already group members or
    WM_TRANSIENT_FOR 'relatives', only then they are put on the tile
    containing the mouse. If a 'reference' client spans several tiles,
    the one is chosen containing the most pixel area of that client.

    (d) Xinerama zoom: clients are usually zoomed across these
    physical screen tiles which they already intersect and not extend
    to others, with few obvious exceptions to that rule.

    The algorithm is window edge based and first determines the
    rectangular convex hull in terms of existing tiles including the
    client window pixel area. This area is usually (but not always)
    larger than the client pixel area.  Then this rectangular area is
    shrunk as much as possible to reduce (and not introducing) dead
    areas enclosed. If the client is initially (partially) outside of
    all physical tiles, it is brought to the nearest (in euclidean
    sense) tile.
    This approach should hopefully survive a variety of different
    geometrical and topological physical screen tile arrangements, at
    least most reasonable cases.

    There are few (currently pixel-based) parameters with hard-coded
    values determining how large slits between tiles are not
    considered dead areas. (It is hoped usually there are no slits in
    practice so this is more of a "theoretical" concern.)



(19) diff19.twm-1.0.4.TWM_USE_XRANDR

    The 'RestartOnScreenChangeNotify' handler first unzooms all
    windows on all screens as their location and size data is lost
    during f.restart.  All tile housekeeping is done by code
    introduced by Xinerama support.



(20) diff20.twm-1.0.4.SwapIconMgrEntry

    In order to better utilise twm for keyboard-driven
    focus/mouse-navigation across client windows some manual sorting
    of icon manager entries is essential. The 'f.swapiconmgrentry'
    function swaps two consecutive elements in the WList* chain of the
    corresponding icon manager. If 'SortIconManager' is true, this
    manual sorting makes no sense (is disabled).



(21) diff21.twm-1.0.4.Warp

    Twm features mouse/focus warping at least in the following
    ways:

    (a) f.warpnext, f.warpprev
    (b) f.warpring "next", f.warpring "prev"
    (c) f.forwiconmgr, f.backiconmgr
    (d) f.nexticonmgr, f.previconmgr
    (e) f.warpto, f.warptoiconmgr
    (f) WarpCursor

    (missing is f.warptoscreen not being client window/focus related)

    Until now of these only f.warpring tracks and utilises current
    mouse coordinates in the client; in all other cases the mouse is
    warped to some uncomfortable location on the top of the window.

    This patchset introduces SaveRingMouseLocation() and changes
    WarpToWindow() accordingly in order to create a unified mechanism
    of mouse warping with always saving/restoring mouse location on
    warp.

    The 'ring.cursor_valid' variable is removed: the saved mouse
    location is always valid, except if moving out of a client
    crossing its window border, which is detected in
    HandleLeaveNotify().

    Second, if the client is resized, the saved location is set to its
    initial default value (which is slightly to the right and up from
    the middle of the client window) should it fall outside the window
    during f.resize.

    Last but most important, the semantics of f.warpto is extended to
    allow an empty string as argument:  f.warpto "".
    This is a counterpart of f.warptoiconmgr "" as it warps mouse into
    the client highlighted by the icon manager, or if none is
    apparently highlighted, into the one having focus.  This is one of
    the insignificant changes to twm improving its
    usability-by-keyboard dramatically.

    A side note: f.warpring now honours the 'WarpUnmapped' .twmrc
    parameter, the same way f.warpnext, f.warpprev do.



(22) diff22.twm-1.0.4.ActiveIconMgr

    Many iconmanager related bugs are corrected not otherwise included
    in previous patchsets.

    Functions WarpToIconManager() and HideIconManager() are introduced
    to enclose otherwise repeated code. (Now all iconmanagers can be
    uniformly hidden/un-hidden.)

    In ExecuteFunction() all iconmanager related F-functions are
    enclused in "if (Scr->NoIconManagers == FALSE)" for clarity.

    Now each screen may contain an 'active' iconmanager; the global
    pointer 'Active' is gone. Each iconmanager can contain an
    'active' entry (such as most recently used client in that
    iconmanager).

    MoveIconManager() and JumpIconManager() now try to activate an
    iconmanager if none is active to perform the move/jump operation.
    That activated iconmanager is considered as a result of move/jump.
    This improves twm's usability-by-keyboard in that it should never
    happen that twm doesn't respond to iconmanager navigation
    functions (invoked by twm keybindings).  Twm should always respond
    in doing something meaningful, irrespective if iconmanagers are
    mapped or not, or if there is some entry highlighted or not; and
    the like (iconmanager navigation functions honour the
    'WarpUnmapped' parameter whenever possible).

    (Another story is if some client executes

	XSetInputFocus (dpy, None, RevertToNone, CurrentTime);

    and then exits. This may raise false impression of twm out of a
    sudden not responding to keybindings because of twm bugs, which is
    highly arguable in this situation.  Mouse-button-bindings are
    unaffected by this situation and moving mouse into some focusable
    window restores the keybinding mechanism.)



(23) diff23.twm-1.0.4.TWM_USE_OPACITY

    Twm supports the _XA_NET_WM_WINDOW_OPACITY property twofold. First
    by .twmrc configuration this property can be set to twm own
    graphical elements (menus, icons, iconmanagers, infowindow by
    SetWindowOpacity(); and second, twm passes the client property to
    its own-created frame window in HandleMapRequest() and
    HandlePropertyNotify() by PropagateWindowOpacity(). It is up to
    some background composite manager to do something with these
    properties, twm doesn't care or expect anything.



(99) twm.man.diff99

    Appends "REVISED EDITION; Eeri Kask, Dresden University of Technology"
    to the man page to denote the above updates (improvements and bugs).



Eeri Kask                            Dresden, Sept 2007 ... Sept 2008
twm-1.0.4-tweaked-diffs.tar (application/x-tar, 200 KB) - not displayed
TWM-RevisedEdition.png (image/png, 131.4 KB) - not displayed