Next: Displaying the Menu, Previous: A Quick Tour of CLX, Up: A Quick Tour of CLX [Contents][Index]
The example client program creates and displays a simple pop-up menu consisting of a column of strings–a title string followed by selectable menu item strings. The implementation uses one window to represent the entire menu, plus a set of subwindows, one for each menu item. Here is the definition of a structure which represents such a menu.
(defstruct (menu) "A simple menu of text strings." (title "Choose an item:") item-alist ;((item-window item-string)) window gcontext width title-width item-width item-height (geometry-changed-p t)) ;nil if unchanged since displayed
The window
slot will contain the
window (see window)
object that represents the menu. The item-
alist
represents the relationship between the menu items
and their associated subwindows. Each entry in item-alist
is a list whose first element is a (sub)window object and whose second
element is the corresponding item string. A
window (see window)
object is an instance of a CLX-defined data type which represents X
windows. A
window (see window)
object actually carries two pieces of information: an X window ID
integer and a
display (see display)
object. A
display (see display)
is another CLX-defined data type that represents a connection to a
specific X display server. The gcontext
slot contains an
instance of a CLX data type known as a graphics context. A
graphics context is a set of display attribute values, such as
foreground color, fill style, line style, text font, and so forth. Each
X graphics request (and hence each CLX graphics function call) must
supply a graphics context to use in displaying the request. The menu’s
gcontext
will thus hold all of the attribute values used
during menu display.
The first thing to do is make an instance of a menu
object:
(defun create-menu (parent-window text-color background-color text-font) (make-menu ;; Create menu graphics context :gcontext (CREATE-GCONTEXT :drawable parent-window :foreground text-color :background background-color :font text-font) ;; Create menu window :window (CREATE-WINDOW :parent parent-window :class :input-output :x 0 ;temporary value :y 0 ;temporary value :width 16 ;temporary value :height 16 ;temporary value :border-width 2 :border text-color :background background-color :save-under :on :override-redirect :on ;override window mgr when positioning :event-mask (MAKE-EVENT-MASK :leave-window :exposure))))
create-window (see create-window) is one of the most important CLX functions, since it creates and returns a window (see window) object. Several of its options are shown here. The default window class is :input-output, but X provides for :input-only windows, too. Every window must have a parent window, except for a system-defined root window, which represents an entire display screen. The :event-mask keyword value, a CLX event-mask (see event-mask) data type, says that an input event will be received for the menu window when the window is exposed and also when the pointer cursor leaves the window. The window border is a pattern-filled or (as in this case) a solid-colored boundary which is maintained automatically by the X server; a client cannot draw in a window’s border, since all graphics requests are relative to the origin (upper-left corner) of the window’s interior and are clipped by the server to this inside region. Turning on the :save-under option is a hint to the X server that, when this window is made visible, it may be more efficient to save the pixels it obscures, rather than require several client programs to refresh their windows when the pop-up menu disappears. This is a way to work around X’s client-managed refresh policy when only a small amount of screen space is needed temporarily.
Why is :override-redirect turned on for the menu window? This is actually a little unusual, because it prevents any window manager client from redirecting the position of the menu when it is popped up. Remember that the window manager represents the user’s policy for controlling the positions of his windows, so this kind of redirection is ordinarily correct. However, in this case, as a favor to the user, the menu avoids redirection in order to pop up the menu at a very specific location; that is, under the pointer cursor.
What about the item subwindows? The menu-set-item-list
function in the following example creates them whenever the menu’s item
list is changed. The upper-left x and y coordinates and the width and
height are not important yet, because they are computed just before the
menu is displayed. This function also calls
create-window (see create-window),
demonstrating the equal treatment of parent and children windows in the
X window hierarchy.
(defun menu-set-item-list (menu &rest item-strings) ;; Assume the new items will change the menu's width and height (setf (menu-geometry-changed-p menu) t) ;; Destroy any existing item windows (dolist (item (menu-item-alist menu)) (DESTROY-WINDOW (first item))) ;; Add (item-window item-string) elements to item-alist (setf (menu-item-alist menu) (let (alist) (dolist (item item-strings (nreverse alist)) (push (list (CREATE-WINDOW :parent (menu-window menu) :x 0 ;temporary value :y 0 ;temporary value :width 16 ;temporary value :height 16 ;temporary value :background (GCONTEXT-BACKGROUND (menu-gcontext menu)) :event-mask (MAKE-EVENT-MASK :enter-window :leave-window :button-press :button-release)) item) alist)))))
Next: Displaying the Menu, Previous: A Quick Tour of CLX, Up: A Quick Tour of CLX [Contents][Index]