10bbfda8aSnia= CTWM PRINCIPLES OF OPERATION
20bbfda8aSniaOlaf 'Rhialto' Seibert <rhialto@falu.nl>
30bbfda8aSnia
40bbfda8aSniaThis document briefly explains some of the internal workings of ctwm.
50bbfda8aSnia
60bbfda8aSnia== Screens ==
70bbfda8aSnia
80bbfda8aSniaEvery X server may serve multiple screens, and ctwm can manage them all
90bbfda8aSniaat once from a single instance. In practice, this does not happen often.
100bbfda8aSniaFurthermore, in ctwm's code you see this only in a few places; it is
110bbfda8aSniahidden in quite a few more. Each screen can have its own configuration
120bbfda8aSniafile: `$HOME/.ctwmrc.<screen number>`.
130bbfda8aSnia
140bbfda8aSniaAt the start of the event handler, the screen for the current event is
150bbfda8aSniadetermined. That is stored in the global variable `Scr`. Everything that
160bbfda8aSniauses `Scr` is properly separated for the different screens.
170bbfda8aSnia
180bbfda8aSnia== Workspaces ==
190bbfda8aSnia
200bbfda8aSniaThe idea of workspaces is that every window has a bitfield called
210bbfda8aSnia`occupation` which indicates in which workspaces it should be visible.
220bbfda8aSnia
230bbfda8aSniaIf a window's occupation changes, or if the user switches the current
240bbfda8aSniaworkspace, the visibility of windows needs to be adjusted.
250bbfda8aSniaAll windows actually "`exist`" at all times (they are not destroyed), but
260bbfda8aSniathe ones that are not to be visible are unmapped. When switching
270bbfda8aSniaworkspaces or occupation, some windows will be unmapped and others will
280bbfda8aSniabe remapped.
290bbfda8aSnia
300bbfda8aSniaBecause windows are merely unmapped when invisible (and not destroyed),
310bbfda8aSniathey remain in the _window stack_. In other words they retain their
320bbfda8aSnia_stacking order_ which is the order in which they are front-to-back.
330bbfda8aSniaThere is only a single stacking order for all workspaces, even though it
340bbfda8aSniaseems that every workspace has its own. Each workspace really just shows
350bbfda8aSniaa subset of the global stacking order.
360bbfda8aSnia
370bbfda8aSniaBecause of the unmapping, all windows can keep the same root window as
380bbfda8aSniatheir parent.
390bbfda8aSnia
400bbfda8aSnia=== The Occupation Window ===
410bbfda8aSnia
420bbfda8aSniaThere is a single _Occupation Window_ for each Screen, which is used
430bbfda8aSniaevery time the `f.occupy` function is invoked.
440bbfda8aSniaThe Occupation Window is reparented and moved every time it is needed.
450bbfda8aSniaIf it is already mapped, and `f.occupy` is invoked again, the invocation
460bbfda8aSniafails. This makes it impossible for the user to manipulate the
470bbfda8aSniaoccupation of the occupation window in this way.
480bbfda8aSnia
490bbfda8aSnia=== The Workspace Manager Window ===
500bbfda8aSnia
510bbfda8aSniaEach _Virtual Screen_ has a separate _Workspace Manager Window_.
520bbfda8aSniaBy default it has _full occupation_, i.e. it is visible in all
530bbfda8aSniaworkspaces.
540bbfda8aSniaYou can change its occupation if you wish.
550bbfda8aSnia
560bbfda8aSniaThis window is filled by asking the X server for the stacking order
570bbfda8aSniawith `XQueryTree()`. Now that we have _OTP_ (see later), this should be
580bbfda8aSniaused instead.
590bbfda8aSnia
600bbfda8aSnia== On Top Priority ==
610bbfda8aSnia
620bbfda8aSniaAfter version 3.8.2, _OTP_ (OnTopPriority) was added. This allows the
630bbfda8aSniauser to select a priority for each window. Windows of lower priority can
640bbfda8aSnianever get on top of a window of higher priority.
650bbfda8aSnia
660bbfda8aSniaTo administrate this, the _OTP_  module aims to keep a private
670bbfda8aSniarepresentation of a somewhat idealized single window stack.  This
680bbfda8aSniaclashes with reality somewhat, as will become clear in other sections.
690bbfda8aSnia
700bbfda8aSniaTo check if the internalized single window stack matches the X server's
710bbfda8aSniaidea of the stack, there are regular consistency checks. If the _OTP_
720bbfda8aSniastack doesn't match, ctwm aborts.
730bbfda8aSniaThis should possibly be relaxed before a full release.
740bbfda8aSnia
750bbfda8aSnia== Window boxes ==
760bbfda8aSnia
770bbfda8aSniaWindows that are inside a box are not children of the root window.
780bbfda8aSniaTherefore they are not in its stacking order either.  But they must fit
790bbfda8aSniasomewhere in OTP's illusion of the global stacking order.
800bbfda8aSniaThe solution for that is that windows in a box are thought to be
810bbfda8aSniadirectly on top of their box.
820bbfda8aSnia
830bbfda8aSniaIn the _OTP_ consistency checking, the windows in a box are special-cased.
840bbfda8aSniaThey are not checked to be in proper order in the stacking order because
850bbfda8aSniathey are not in the stacking order at all.
860bbfda8aSnia
870bbfda8aSniaIf they were not ignored in this way, they would cause false alarms
880bbfda8aSniaabout the OWL list being incorrect.
890bbfda8aSnia
900bbfda8aSnia== Virtual Screens ==
910bbfda8aSnia
920bbfda8aSniaAt some point, X servers started to be able to present multiple monitors
930bbfda8aSniaas a single screen. This is the so-called Xinerama extension (or
940bbfda8aSnianowadays XRandR).  However, people often still want to have some
950bbfda8aSniaseparation between their monitors. Thus, Virtual Screens were invented
960bbfda8aSniain ctwm.
970bbfda8aSnia
980bbfda8aSniaCtwm's Virtual Screens (_vscreen_, or _vs_) work best if your monitors are
990bbfda8aSniathe same size.  What they do is allow you to show one workspace on one
1000bbfda8aSniascreen, and another workspace on the other. You can switch workspaces
1010bbfda8aSniaindependently (with some small limitations).
1020bbfda8aSnia
1030bbfda8aSniaTo make each virtual screen independent of the others (for example, each
1040bbfda8aSniaone needs their own coordinate system starting at (0,0)), a separate
1050bbfda8aSniavirtual root window is created for each virtual screen. Each monitor
1060bbfda8aSniathen is associated with one of the virtual screens (and their root
1070bbfda8aSniawindow). In your configuration you must give the geometry such that the
1080bbfda8aSnia_vscreens_ match the monitors.
1090bbfda8aSnia
1100bbfda8aSniaX has the important property that the windows form a strict tree: a
1110bbfda8aSniawindow can have only a single parent, and it can't be added twice to the
1120bbfda8aSniasame parent either.
1130bbfda8aSnia
1140bbfda8aSniaBecause of that, you can't view the same workspace on two virtual
1150bbfda8aSniascreens, for that would show its windows twice. Moreover, windows that
1160bbfda8aSniaoccupy multiple workspaces can also be visible once only, in a single
1170bbfda8aSnia_vscreen_.  If multiple visibility is about to happen, a single
1180bbfda8aSnia_vscreen_ is chosen to show the window. If a window is hidden from one
1190bbfda8aSnia_vscreen_, it might be possible to then show it on another.
1200bbfda8aSnia
1210bbfda8aSniaIf a window was first shown on one _vscreen_, and later on another, it
1220bbfda8aSnianeeds to be reparented from one root window to another. This is done
1230bbfda8aSnialazily.
1240bbfda8aSnia
1250bbfda8aSniaCtwm administrates this with the `TwmWin.vs` and `TwmWin.parent_vs`.
1260bbfda8aSnia`parent_vs` indicates the current parent virtual root window. Because a
1270bbfda8aSniawindow always has a parent, this can never be `NULL`.
1280bbfda8aSnia`TwmWin.vs` indicates the virtual screen where it is visible. This may be
1290bbfda8aSnia`NULL`, if the window has no occupation in (the workspace currently shown
1300bbfda8aSniain) the virtual screen. If it is not `NULL`, it must equal `.parent_vs`.
1310bbfda8aSnia(So `.vs` could be replaced with a boolean in most places)
1320bbfda8aSnia
1330bbfda8aSniaNote that most of ctwm's code still assumes there is a single window
1340bbfda8aSniastack for all windows, but with the virtual screens this is not true
1350bbfda8aSniaany more! Each virtual root window has its own window stack.
1360bbfda8aSnia
1370bbfda8aSniaWhat is true, for each separate _vscreen_, is that if you select from
1380bbfda8aSniactwm's global stack those windows that are actually parented in that
1390bbfda8aSniavscreen, that selection corresponds to the _vscreen_'s window stack.
1400bbfda8aSnia
1410bbfda8aSniaIn effect, the various _vscreen_'s window stacks are potentially
1420bbfda8aSniainterlaced like several packs of cards. Depending on "where you are",
1430bbfda8aSniayou must ignore the "wrong" windows in it.
1440bbfda8aSnia
1450bbfda8aSnia== Icon Managers ==
1460bbfda8aSnia
1470bbfda8aSnia=== Let's start with the one-workspace case. ===
1480bbfda8aSnia
1490bbfda8aSniaIn the `.ctwmrc` you can specify multiple icon managers, and which
1500bbfda8aSniawindows will be placed in them. Let's call them the primary `IconMgr`
1510bbfda8aSniaand secondary ``IconMgr``s.  There is nothing stopping you from
1520bbfda8aSniaspecifying them so, that one window might appear in multiple icon
1530bbfda8aSniamanagers, but it will only go into the first one that matches.
1540bbfda8aSnia
1550bbfda8aSnia`ScreenInfo.iconmgr` (`Scr->iconmgr`) points to the primary icon manager.
1560bbfda8aSniaThe secondary ones are linked to it via `IconMgr.next` and `.prev`.
1570bbfda8aSnia
1580bbfda8aSniaSo each window occurs in a single icon manager: it has a little
1590bbfda8aSniasub-window in it.
1600bbfda8aSniaThe sub-window is represented by a `WList`.
1610bbfda8aSnia`twm_win->iconmanagerlist` points to the `WList` for the window.
1620bbfda8aSnia
1630bbfda8aSniaThe various `WLists` that are in the same iconmanager are linked via
1640bbfda8aSnia`WList.next` and `.prev`.
1650bbfda8aSnia
1660bbfda8aSnia.Undiscovered:
1670bbfda8aSnia- `IconMgr.lasti`
1680bbfda8aSnia- how `IconMgr.first` `.last` `.active` (``WList``s) are related to the
1690bbfda8aSnia  pointers from the windows
1700bbfda8aSnia
1710bbfda8aSnia=== Expand to multiple workspaces. ===
1720bbfda8aSnia
1730bbfda8aSniaThe Icon Managers are different windows in each workspace: it is not
1740bbfda8aSniajust a single window with multiple occupation. This is so that you
1750bbfda8aSniacan move it where you want in each of them.
1760bbfda8aSnia(Personally I would probably have used a single window and moved it
1770bbfda8aSniaaround to remembered locations in each workspace)
1780bbfda8aSnia
1790bbfda8aSniaSo both the `IconMgr` and the ``WList``s are replicated for each
1800bbfda8aSniaworkspace.  These instances are linked via `IconMgr.nextv` and
1810bbfda8aSnia`WList.nextv`.
1820bbfda8aSnia
1830bbfda8aSniaThe replicated instances are created after the first `IconMgr`, in
1840bbfda8aSnia`AllocateOtherIconManagers()`.
1850bbfda8aSnia
1860bbfda8aSniaIf we believe `CreateIconManagers()`, then from the primary `IconMgr`
1870bbfda8aSniafor workspace #0 (`Scr->iconmgr`), you can follow `->nextv` to get to the
1880bbfda8aSniareplicas for workspace #1, #2, ..., and from each of those, follow
1890bbfda8aSnia`->next` to get to the secondary ``IconMgr``s for the same workspace.
1900bbfda8aSniaBut the replication function is confusing.
1910bbfda8aSnia
1920bbfda8aSniaOn the other hand, in `AddIconManager()`, a primary or secondary
1930bbfda8aSnia`IconMgr` is selected from workspace #0, and then `->nextv` is
1940bbfda8aSniafollowed to find each of the replicas. 
1950bbfda8aSnia
1960bbfda8aSnia`WorkSpace.iconmgr` points to the primary _Icon Manager_ that belongs to
1970bbfda8aSniathat workspace.
1980bbfda8aSnia
1990bbfda8aSniaIn `GotoWorkspace()`, there is a "`reorganisation`" of ``WList``s.
2000bbfda8aSniaI am not 100% sure what that means.
2010bbfda8aSniaProbably it is doing the job that more logically should be done in
2020bbfda8aSnia`ChangeOccupation()`, but lazily: put windows (``WList``s) in icon
2030bbfda8aSniamanagers and take them out, depending on their occupation.
2040bbfda8aSnia
2050bbfda8aSnia== Icons ==
2060bbfda8aSnia
2070bbfda8aSniaIcons consist of several parts. Some of them can come from different sources
2080bbfda8aSniaor be shared among windows.
2090bbfda8aSnia
2100bbfda8aSnia* `struct Icon`, which refers to
2110bbfda8aSnia** `struct Image`, which contains
2120bbfda8aSnia*** X `Pixmap`(s) for image and optionally shape
2130bbfda8aSnia** X `Window` to place the `Pixmap`(s) in
2140bbfda8aSnia
2150bbfda8aSniaEach `TwmWindow` may have a `struct Icon` which describes the currently
2160bbfda8aSniaassociated icon. Icons may change, if the title matches different images
2170bbfda8aSniafrom the Icon list over time:
2180bbfda8aSnia
2190bbfda8aSnia--------------------
2200bbfda8aSniaIcons
2210bbfda8aSnia{
2220bbfda8aSnia     "XTerm"   "xpm:xterm"
2230bbfda8aSnia     "* - VIM" "xpm:vim"
2240bbfda8aSnia}
2250bbfda8aSnia--------------------
2260bbfda8aSnia
2270bbfda8aSnia``Image``s that are loaded from an xpm or other file are stored as
2280bbfda8aSnia`struct Image` and cached in a global cache named `Scr->ImageCache`.
2290bbfda8aSniaTherefore they can be shared. The source of an `Image` is recorded in 
2300bbfda8aSnia`Icon->match` and can have the values `match_none`, `match_list`,
2310bbfda8aSnia`match_icon_pixmap_hint`, `match_net_wm_icon`, `match_unknown_default`.
2320bbfda8aSnia
2330bbfda8aSniamatch_list::
2340bbfda8aSniaIf a window changes icons like this (Vim changes the terminal window's
2350bbfda8aSniatitle when it starts up), it stores old icons on `TwmWin->iconslist` for
2360bbfda8aSnialater re-use. It must be certain that all these ``Image``s are indeed
2370bbfda8aSniafrom the cache and not from other sources, otherwise there may be a
2380bbfda8aSniamemory leak or use-after-free.  The `iconslist` is freed when a window
2390bbfda8aSniais freed, but the ``Image``s it points to are left alone.
2400bbfda8aSniafootnote:[A different implementation would allow ``Image``s from any
2410bbfda8aSniasource on the `iconslist` and check their source when freeing the list.]
2420bbfda8aSnia
2430bbfda8aSniamatch_icon_pixmap_hint::
2440bbfda8aSniaAnother source of `struct Image` is the Pixmap(s) that are given in the
2450bbfda8aSnia`WM_HINTS` property. These are not shared.
2460bbfda8aSnia
2470bbfda8aSniamatch_net_wm_icon::
2480bbfda8aSniaThe image is specified in the `_NET_WM_ICON` property. These `struct
2490bbfda8aSniaImages` are also not shared. Usually there are icons of different sizes.
2500bbfda8aSniaThe user can specify the desired size (width * height). If an exact
2510bbfda8aSniamatch is not found, the closest match is taken. This is based on
2520bbfda8aSniathe area (total number of pixels) of the icon. The differences are
2530bbfda8aSniacompared proportionally: the specified size times 2 is closer than 
2540bbfda8aSniathe size divided by 3.
2550bbfda8aSnia
2560bbfda8aSniamatch_unknown_default::
2570bbfda8aSniaFinally there is a default `Image`, which is shared among all windows
2580bbfda8aSniawhere needed.
2590bbfda8aSnia
2600bbfda8aSniaUsually ctwm creates the window to display the icon itself, but again
2610bbfda8aSniathere may be one given in the `WM_HINTS`. If so, this window must not be
2620bbfda8aSniadestroyed.
2630bbfda8aSnia
2640bbfda8aSnia
2650bbfda8aSnia// vim:ft=asciidoc:expandtab:
2660bbfda8aSnia// Gen:
2670bbfda8aSnia//  asciidoc -atoc -anumbered -o PRINCIPLES-OF-OPERATION.html PRINCIPLES-OF-OPERATION.txt 
2680bbfda8aSnia
269