Mode line formatters can register sections of text to be clickable by
use of the color formatters :on-click and
:on-click-end. Any text enclosed by these formatters has its
bounds saved, and when the mode line recieves a button press event these
bounds are checked against to find a clickable area, whose registered
function is then called. These formatters can be thought of as similar
to XML tags.
To disable the on-click behavior, remove the function
check-for-ml-press from the hook *mode-line-click-hook*.
To call a function by click the function must first be registered. The function must take at least one argument, the button code. Here is an example of a click-to-focus function and its registration:
(defun ml-on-click-focus-window (code id &rest rest)
(declare (ignore code rest))
(when-let ((window (window-by-id id)))
(focus-all window)))
(register-ml-on-click-id :ml-on-click-focus-window #'ml-on-click-focus-window)
This defines a function that focuses a window based upon its X11 window
ID, and registers it under the ID :ml-on-click-focus-window. Here
is an example of a mode line formatter that makes use of this function:
(add-screen-mode-line-formatter #\i 'fmt-head-window-list-clickable)
(defun fmt-head-window-list-clickable (ml)
"Using *window-format*, return a 1 line list of the windows,
space seperated and clickable."
(flet ((fmt-w (w)
(let ((str (format-expand *window-formatters*
*window-format*
w)))
(format-with-on-click-id (if (eq w (current-window))
(fmt-highlight str)
str)
:ml-on-click-focus-window
(window-id w)))))
(format nil "~{~a~^ ~}"
(mapcar #'fmt-w
(sort1 (head-windows (mode-line-current-group ml)
(mode-line-head ml))
#'< :key #'window-number)))))
In the above formatter, every windows expansion is wrapped in a
:on-click/end pair, which takes the ID we registered as the function to
call and the window ID as an argument to be passed to its function. The
arguments provided to :on-click will be read but not
evaluated. The string generated will look like so:
"^(:on-click :ml-on-click-focus-window 308242)window text^(:on-click-end)"
Clickable text can be nested, in which case the innermost clickable text
will take precendent. In the following example :id2 will be
dispatched when clicking 2, but :id1 will be dispatched
when clicking 1 and 3:
"^(:on-click :id1)1^(:on-click :id2)2^(:on-click-end)3^(:on-click-end)"
If one wished for right click to delete windows, then the following example could be placed in the .stumpwmrc:
(labels ((ml-on-click-focus-or-delete-window (code id &rest rest)
(declare (ignore rest))
(when-let ((window (window-by-id id)))
(let ((button (decode-button-code code)))
(case button
((:left-button)
(focus-all window))
((:right-button)
(delete-window window)))))))
(register-ml-on-click-id :ml-on-click-focus-window
#'ml-on-click-focus-or-delete-window))
This will replace the :ml-on-click-focus-window function, and all
uses of :on-click formatters referring to
:ml-on-click-focus-window will use the new function.
Register FN with ID, to be used by the :on-click mode line color formatter.
Wrap STRING in :on-click and :on-click-end color formatters, using ID as the id to call when clicked and ARGUMENTS as the arguments to pass to the ID’s function. STRING may not contain the :> color formatter, but may contain any other color formatters.