Author: Neil McKay <mckay@eecs.umich.edu>
Author: Andreas Kupries <andreas_kupries@users.sourceforge.net>
Author: Donal K. Fellows <fellowsd@cs.man.ac.uk>
State: Final
Type: Project
Vote: Done
Created: 19-Jul-2001
Post-History:
Tcl-Version: 8.4
Abstract
With a few modifications to the Tk core, extensions could be written that would allow X window managers to be implemented as Tcl/Tk scripts.
Requirements
Writing X window managers in Tk requires some facilities that the current Tk core doesn't provide. A window manager must be able to:
draw to, and handle events on, the display's root window (including
, , , , and events, which are currently ignored) embed arbitrary windows inside Tk windows
receive
events from embedded windows perform a variety of other X-specific operations
Window embedding can be handled by an extension, if it is not
incorporated into the Tk frame widget at some later time.
Likewise, the X-specific operations can be handled by
an extension. However, Tk as it currently stands cannot
access the display's root window, nor can
Root Window Access
The root window is special in many ways:
It does not need to be created
It cannot be destroyed, moved, or resized
Only one process can receive
and events from it, and only one process can have the SubstructureRedirect and ResizeRedirect masks set It has no physical parent window
Because of these properties, access to the root window via a Tk
widget presents some difficulties. First, the widget's window cannot
be created in the standard way; however, this problem may be solved by
providing a non-standard creation routine via the
Tk_SetClassProcs procedure described in [5].
Likewise, the event handling required by the root window
can be enabled in an extension, although some care is required
when enabling
This window is a toplevel widget
This widget has a wrapper window
This widget's window is controlled by the window manager
This window is at the top of a physical window hierarchy within the current application
In the current version of Tk, toplevel widgets have all of these properties, and no other widgets have any of these properties; hence a single flag suffices. If we create a widget whose window is the display's root, then this is no longer the case; a root window has the last property, but not the first three. For this reason, it is necessary to replace the TK_TOP_LEVEL flag with at least two distinct flags. A better idea is to replace the TK_TOP_LEVEL flag with four flags, one for each of the properties listed above. (Even in a standard Tk distribution, this replacement is desirable for documentation reasons, since it will indicate what property of a toplevel widget is important in the current circumstances.) We must also replace the Tk_IsTopLevel macro with several macros, or just eliminate it entirely.
One possible set of flag names is:
TK_TOP_LEVEL: this is a toplevel widget
TK_HAS_WRAPPER: this window has a wrapper window
TK_WIN_MANAGED: this window is controlled by the window manager
TK_TOP_HIERARCHY: this window is at the top of a physical window hierarchy
New Event Bindings and Substitutions
A window manager must be able to intercept certain events on the root
window that the standard Tk distribution doesn't recognize, and
it must be able to obtain information about those events. In particular,
it needs to respond to
Obtaining information about these events is also necessary.
This is usually done via %-substitutions in the [bind] command;
however, there are two pieces of information that are necessary
for implementing a window manager that cannot be obtained via
the current %-substitution mechanism: the numerical X window ID,
required to handle
%i: substitute the numerical window ID for the event
%P: substitute the atom name for the property being changed
Propagating Events
In order to receive
winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
if (winPtr == NULL) {
if (eventPtr->type == PropertyNotify) {
TkSelPropProc(eventPtr);
}
return;
}
If the flag for propagating
winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
if (winPtr == NULL) {
if (eventPtr->type != PropertyNotify) {
return;
}
TkSelPropProc(eventPtr);
parentXId = (parent of handlerWindow);
winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId);
if (winPtr == NULL) {
return;
}
if (!(winPtr->flags & TK_PROP_PROPCHANGE)) {
return;
}
handlerWindow = parentXId;
return;
}
Patches
A patch (against tk8.4a2) that implements the changes described above is available http://www.eecs.umich.edu/~mckay/computer/wmenablers.84a3.patch.gz .
Notes
Andreas Kupries. There was a tkwm' patch once. http://www.neosoft.com/tcl/ftparchive/sorted/x11/tkwm/ <http://www.ensta.fr/internet/unix/windowmanagers/tkwm.html>
Copyright
This document is in the public domain.