forked from jpe90/guile-wm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
guile-wm.texi
1713 lines (1339 loc) · 59.8 KB
/
guile-wm.texi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename guile-wm.info
@settitle The Guile-WM Manual 1.0
@c %**end of header
@copying
This manual is for Guile-WM, version 1.0.
Copyright @copyright{} 2013 Mark Witmer.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License."
@end quotation
@end copying
@dircategory X11
@direntry
* Guile-WM: (guile-wm). A Scheme Window Manager Toolkit
@end direntry
@titlepage
@title Guile-WM
@subtitle A Scheme Window Manager Toolkit
@author Mark Witmer
@c The following two commands
@c start the copyright page.
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@c So the toc is printed at the start.
@contents
@ifnottex
@node Top
@top Guile-WM
This manual is for Guile-WM, version 1.0.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License."
Guile-WM is an extensible window manager and support toolkit for the
X11 windowing system, written in Guile Scheme.
@end ifnottex
@menu
* Introduction::
* Getting Started::
* X11 Abstraction Layer::
* User-Facing Modules::
* Function Index::
@end menu
@findex
@node Introduction
@chapter Introduction
Guile-WM is an extensible window manager and support toolkit for the
X11 windowing system, written in Guile Scheme. It includes a library
of modules for handling X11-related tasks such as detecting
keystrokes, reparenting windows, and controlling input focus. It also
provides modules with end-user facing window management features that
can be mixed together according to the user's preferences.
Guile-WM's architecture is inspired by the microkernel concept in
operating system design. In mircokernels, a small core process is
fronted by a set of user-specified modules that provide much of the
desired behavior. In the case of Guile-WM, the core process is simply
an X event loop that begins when the window manager starts. The
behavior of the window manager is determined by the set of modules
loaded in the user's configuration file.
Guile-WM is built on top of Guile XCB, a Scheme X client
library. @inforef{Top, Guile XCB, guile-xcb}.
@node Getting Started
@chapter Getting Started
@menu
* Running the WM::
* Configuring the WM::
* Creating a WM Module::
* WM Hooks::
@end menu
@node Running the WM
@section Running the WM
By default, Guile-WM simply starts the event loop and loads and
evaluates a Scheme file containing the user's configuration. The
configuration file is mandatory; if it isn't found, Guile-WM won't
start.
Guile-WM takes a few command line arguments (preceded by @samp{--} in their
long format) that can affect its behavior.
@deffn{Command Line} version -v
Display the version number of Guile-WM and exit
@end deffn
@deffn{Command Line} help -h
Display a message documenting the command line options and exit
@end deffn
@deffn{Command Line} init-file -i
Select an alternate configuration file location (default is @code{$HOME/.guile-wm})
@end deffn
@deffn{Command Line} log-file -l
Select an alternate log file location (default is @code{/tmp/guile-wm.log})
@end deffn
@node Configuring the WM
@section Configuring the WM
For the most part, the configuration file is evaluated just like any
other Scheme source file. An additional facility is provided for
loading and initializing window-manager specific modules by listing
them in special lines of comments prefixed with @code{wm-modules:}.
If an item in the list is a symbol, it will be expanded to
@code{(guile-wm module @var{symbol})}. Lists are imported as-is.
@lisp
;; -*- scheme -*-
;; File: $HOME/.guile-wm
;; wm-modules: cursor root-keymap
;; wm-modules: repl randr fullscreen
;; wm-modules: menu message window-menu time simple-reparent
;; wm-modules: simple-focus window-cycle (path-to another module)
@end lisp
Modules listed in the comments are imported by @code{(guile-wm user)},
the module in which the configuration file runs. Some of these modules
include a procedure that is to be run after the X server connection is
established. Those procedures are called before the body of the
configuration file is evaluated. @xref{Creating a WM Module}.
In addition to importing modules, this file can configure their
behavior according to the user's preferences. Of course, since this is
just Scheme code, this file can also import modules from other sources
and provide more elaborate extensions to the core WM behavior.
@node Creating a WM Module
@section Creating a WM Module
Some user-facing modules in the window manager perform setup actions
requiring an open connection to the X server. These modules can
register themselves as observers to evaluate code once the X
connection has been opened.
@deffn{Scheme Procedure} wm-init proc
Add @var{proc} to a list of procedures that will be called immediately
after the window manager connects to the X server. Inside of proc, the
parameter @code{current-xcb-connection} exported by @code{(xcb xml)} will
have its value bound to the opened X connection.
If this procedure is called multiple times by a module, only the last
registered procedure will be used.
@end deffn
@node WM Hooks
@section WM Hooks
Because of how the Guile XCB event loop is designed, normal Guile
hooks do not work in Guile-WM. Consequently, it comes with a
substitute Scheme-only interface found in @code{(guile-wm shared)}.
@sc{Guile hooks DO NOT work in Guile-WM. You have been
warned!}
These procedures have the same behavior as their corresponding Guile
hook procedures. @inforef{Hooks, Hooks, guile}.
@deffn{Scheme Procedure} wm-hook-empty? hook
See hook-empty?
@end deffn
@deffn{Scheme Procedure} make-wm-hook [arity]
See make-hook
@end deffn
@deffn{Scheme Procedure} add-wm-hook! hook proc
See add-hook!
@end deffn
@deffn{Scheme Procedure} remove-wm-hook! hook proc
See remove-hook!
@end deffn
@deffn{Scheme Procedure} reset-wm-hook! hook
See reset-hook!
@end deffn
@deffn{Scheme Procedure} run-wm-hook hook . args
See run-hook
@end deffn
@node X11 Abstraction Layer
@chapter X11 Abstraction Layer
These features don't affect the behavior of the window manager
directly, but they provide a framework on top of the core X11 protocol
for the user-facing part of the package to use.
@menu
* Keyboard Input:: Reading keystrokes from the WM
* Drawing:: Graphical Contexts, Pixmaps, and Windows
* Commands:: Telling the WM what to do
* Reparenting and Redirection:: Taking control of windows
* Text:: Displaying and editing text
* Color:: Using the colormap
* Focus:: Setting the focus
* ICCCM:: A little bit of support for the standard
* Logging:: Keeping a record
@end menu
@node Keyboard Input
@section Keyboard Input
Guile-WM provides two complementary interfaces for keyboard input:
keystroke listeners and keymaps. Keystroke listeners receive keyboard
input and convert it into symbols. Keymaps map keys to actions or
other keymaps. They can be driven by keyboard input for various
purposes: selecting user commands, editing a text buffer, and so on.
@menu
* Keystroke Listeners:: Listening to the keyboard
* Keymaps:: Binding keys to actions
@end menu
@node Keystroke Listeners
@subsection Keystroke Listeners
Keyboard input in X11 is somewhat complicated. First, X11 assigns a
numeric code to each key on the keyboard. Keycodes are dynamically
mapped into a set of fixed numerical keysyms which correspond to all
the different possible keys the X11 designers could think of.
The benefit of this system is that users can use a program like
xmodmap to change what keysyms the keycodes are mapped to. This lets
users do fun things like remap the caps lock key to make it an extra
control key and so forth.
Guile-WM simplifies this process by providing an interface to X11
keyboard events with one procedure, found in @code{(guile-wm keystroke)}.
@deffn{Scheme Procedure} keystroke-listen! win
Create a keystroke listener on window @var{win}. Returns a procedure
that can be called with zero arguments in order to yield control to
the event loop until a key is pressed on @var{win}. That key will then
be returned. If the procedure is called with @code{#f} as its
argument, the listener will be canceled. If the procedure is called
with another, single-argument procedure as its argument, control will
not immediately be yielded to the event loop. Instead, the provided
procedure will be called when the key is pressed.
The procedure can be called any number of times while the listener is
active and will wait for a new keystroke each time. If the keyboard
mapping changes while a keystroke listener is active, the listener will
automatically update itself.
Keys returned by the procedure are symbols; alphabetic characters are
in the format @code{a}, @code{b}, @code{c}, etc. Numbers and symbols
use words: @code{one}, @code{two}, @code{three}, @code{asterisk},
@code{percent}, and so on. When a modifier is pressed down, it is
prepended to the key: for control, the prefix is ``C-'' (@code{C-a},
@code{C-one}, @code{C-up}, etc.), for meta, the prefix is ``M-''. If
both are pressed down, they are both prepended, with ``C-''
first. (@code{C-M-a}, @code{C-M-one}, etc.).
See keystroke.scm for the full list of mappings.
@end deffn
In other applications, the term ``keystroke'' often refers to the full
key-down/key-up cycle. In Guile-WM, listeners created by
@code{keystroke-listen!} respond specifically to key-down events.
@node Keymaps
@subsection Keymaps
Keymaps are a flexible tool for binding input to behavior. At their
core is a mapping from input values to procedures, referred to here as
key handlers. The procedures @code{keymap-lookup} and @code{do-keymap}
are used to run keymaps.
Keymap support is located in @code{(guile-wm keymap)}
@deffn{Scheme Syntax} create-keymap mapping ...
Create a new keymap. Each @var{mapping} is a mapping from a key to a
key handler. There are four forms available for mappings.
The first two forms map a key to a procedure that takes the rest
arguments provided to @code{keymap-lookup}:
@code{((k args ...) exp ...)}
Maps key @var{k} to a handler consisting of expressions @var{exp}
..., called with arguments @var{args}.
@code{(k => proc)}
Maps key @var{k} to handler @var{proc}.
The other two forms map a key to a procedure that takes the
@code{key-provider} procedure as well as the rest arguments provided
to @code{keymap-lookup}. This allows the handler to start a subsidiary
keymap that receives keys from the same source as the primary keymap.
@code{(k ==> proc)}
Maps key @var{k} to procedure @var{proc}.
@code{((k ==> args) stmt ...)}
Maps key @var{k} to a procedure with args @var{args} ... and body
@var{stmt} ... .
In all four forms, @var{k} is evaluated inside of @code{quasiquote}, so
an expression that evaluates to some literal can be provided if it is
unquoted.
@end deffn
@deffn{Scheme Procedure} keymap-lookup keymap key-provider . args
Reads a key by calling thunk @var{key-provider} and returns another
thunk to call the procedure the key is bound to, if one exists.
This procedure returns a thunk so that the caller can perform any
desired actions (hide a menu, signal something to the user, etc.)
prior to actually invoking the keymap's behavior.
@var{args} will be passed to the matched key handler.
Ordinarily, @var{key-provider} returns key symbols, but that is not a
requirement. Keymaps can run on anything that can be differentiated by
@code{eq?}.
@end deffn
@deffn{Scheme Procedure} do-keymap keymap key-provider . args
Call @code{keymap-lookup} with the provided arguments and then
immediately evaluate the result.
@end deffn
@deffn{Scheme Syntax} define-keymap name mapping ...
Create a keymap with @var{mappings} and bind it to @var{name}.
@end deffn
@deffn{Scheme Syntax} define-keymap-once name mapping ...
Define a keymap that will not be redefined if the module it is in gets
recompiled.
@end deffn
@deffn{Scheme Procedure} bind-key! keymap key proc
Bind @var{key} to handler @var{proc} in @var{keymap}. @var{proc} will
be called with the rest arguments provided to @code{keymap-lookup} as
its arguments.
@end deffn
@deffn{Scheme Procedure} bind-intermediate-key! keymap key proc
Bind @var{key} to handler @var{proc} in @var{keymap}. @var{proc} will
be called with the @var{key-provider} and rest arguments provided to
@code{keymap-lookup} as its arguments.
@end deffn
@deffn{Scheme Procedure} unbind-key! keymap key
Delete the binding for @var{key} in @var{keymap}.
@end deffn
By default, keymaps produce an error when they receive an unbound
key. The following procedures modify that behavior:
@deffn{Scheme Procedure} keymap-with-default keymap default
Return a new keymap with the same bindings as @var{keymap}, but with
an additional default key handler, @var{default}, to call when a key is
provided for which there is no binding.
@var{default} should take arguments (@var{key} @var{arg} ...), where
@var{key} is the unbound key and @var{arg} ... are the rest arguments
that were passed to @code{keymap-lookup}.
@end deffn
@deffn{Scheme Procedure} keymap-ignore key . args
Ignore the key and return the additional arguments as values,
unchanged. This procedure can be used with @code{keymap-with-default}
to create a keymap that ignores unknown keys.
@end deffn
@subsubsection Prompt Keymaps
A common use case for a keymap is to run some kind of stateful
operation, such as a text editing buffer or menu. These operations can
often be modeled with a ``continue-cancel-confirm'' sequence. For
example, in a menu, pressing @code{up} or @code{down} moves the
selection and continues the keymap. Pressing @code{escape} will cancel
the keymap, and pressing @code{enter} confirms it.
Since this model occurs frequently, Guile-WM includes special
procedures and syntax for creating and running ``prompt'' keymaps.
These keymaps run in a tail-recursive loop, taking the output from one
iteration and passing it in as the input to the next iteration. A
state variable (@code{continue}, @code{confirm}, or @code{cancel}) is
passed along transparently.
@deffn{Scheme Syntax} create-prompt-keymap mapping ...
Create a prompt keymap with mappings @var{mapping} ... . In addition
to the mappings specified, @code{escape} and @code{C-g} will
automatically be bound to @code{cancel-keymap}, and @code{return} will
be bound to @code{confirm-keymap}.
Syntax for mappings remains the same as in
@code{create-keymap}. However, handlers bound using @code{==>} now
must accept one additional argument that provides the state of the
keymap after @code{key-provider} and before the other arguments.
Because these keymaps are stateful, handlers must return the values
that will be passed back into the keymap on its next iteration. For
example, in a text buffer editor, a handler will receive arguments
describing the state of the text editor, and should return a set of
values of the same length describing the state of the text editor
after the operation corresponding to the key pressed has been
performed.
Handlers bound with @code{==>} must return the state variable before
the other values, but do not need to return @code{key-provider}. The
state returned should be one of the symbols @code{cancel},
@code{confirm}, or @code{continue}.
In summary, a handler bound with @code{==>} is called and returns
values in this manner:
@samp{(handler keymap-lookup state arg ...) -> (values new-state new-arg ...)}
Other handlers are called like this:
@samp{(handler arg ...) -> (values new-arg ...)}
These handlers automatically have @code{continue} appended to their
return values.
@end deffn
Note that @code{bind-key!} and @code{bind-intermediate-key!} can be
used with prompt keymaps, but they must explicitly include the state
argument in their list of arguments.
@deffn{Scheme Syntax} define-prompt-keymap name mapping ...
Create a prompt keymap with name @var{name} and mappings @var{mapping} ... .
@end deffn
@deffn{Scheme Procedure} do-prompt-keymap keymap get-key on-continue on-cancel . args
Run prompt keymap @var{keymap} with initial arguments @var{args} by
getting keys using @var{get-key}. When a handler returns
@code{(values 'continue ...)}, @var{on-continue} will be called with the other
values returned by the handler as its arguments. The keymap will then
run again, with those values as its new arguments.
When a handler returns @code{(values 'cancel ...)}, @var{on-cancel}
will be called with the other values returned by the handler as its
arguments. Likewise, when @code{(values 'confirm ...)} is returned,
@var{on-confirm} is called before the keymap ends. In both cases, the
keymap will then terminate.
@end deffn
@deffn{Scheme Procedure} prompt-keymap-with-default keymap default
Returns a new keymap copied from @var{keymap} with @var{default} as
the handler for unknown keys. @var{default} should take the unknown
key as an argument and then the other arguments, and will
automatically continue the keymap.
@end deffn
@deffn{Scheme Procedure} cancel-keymap state . args
Cancel the prompt keymap by returning @code{(values 'cancel args ...)}
@end deffn
@deffn{Scheme Procedure} confirm-keymap state . args
Confirm the prompt keymap by returning @code{(values 'confirm args ...)}
@end deffn
@deffn{Scheme Procedure} continue-keymap state . args
Continue the prompt keymap by returning @code{(values 'continue args ...)}
@end deffn
These keymaps are complicated to explain, but simple to use. Here is a
simple keymap and binding in the root keymap to prompt the user to
select a number from zero to one hundred:
@lisp
(use-modules (guile-wm keymap))
(use-wm-modules root-keymap message)
(define-prompt-keymap number-adjust-keymap
((less-than quantity) (max 0 (- quantity 5))) ;; state hidden syntax
((greater-than ==> get-key state quantity) ;; ==> syntax
(values 'continue (min 100 (+ quantity 5)))))
(bind-intermediate-key!
root-keymap 'N
(lambda (get-key)
(do-prompt-keymap
number-adjust-keymap get-key
(lambda (n) (message (format #f "Number: ~a" n)))
(lambda (n) (message (format #f "Confirmed: ~a" n)))
(lambda (n) (message "Canceled"))
50)))
@end lisp
@node Drawing
@section Drawing
Often, when performing basic graphical tasks with an X server, it is
necessary to ask the X server to create a server-side data structure
and then to delete it when the structure is no longer needed.
Guile-WM provides some syntax in @code{(guile-wm draw)} to handle the
create/destroy action transparently.
@deffn{Scheme Syntax} with-gc (gc drawable prop ...) stmt stmt* ...
Have the X server create a graphical context by passing drawable
@var{drawable} and a keyword list of properties @var{prop} ... in a
@code{make-gc} request. Evaluate @var{stmt} @var{stmt*} ... with @var{gc}
bound to the XID of the newly created graphical context. Request that
the X server destroy the graphical context when it goes out of scope.
@end deffn
@deffn{Scheme Syntax} with-font (name font) stmt stmt* ...
Have the X server create a font by passing font string @var{font} in
an @code{open-font} request. Evaluate @var{stmt} @var{stmt*} ... with
@var{font} bound to the XID of the newly created font. Request that
the X server destroy the font when it goes out of scope.
@end deffn
@deffn{Scheme Syntax} with-pixmap (pixmap win color width height) stmt stmt* ...
Have the X server create a pixmap by passing window @var{win}, pixel
integer @var{color}, integer @var{width}, and integer @var{height}
in a @code{create-pixmap} request. Evaluate @var{stmt} @var{stmt*} ... with
@var{pixmap} bound to the XID of the newly created pixmap. Request
that the X server destroy the pixmap when it goes out of scope.
@end deffn
This module also includes some simple methods for creating windows:
@deffn{Scheme Procedure} basic-window-create x y width height border [events]
Create an unmapped window with dimensions (@var{x}, @var{y}), size
(@var{width}, @var{height}) and border width
@var{border}. @var{events} is an optional list of symbols from the
xenum @code{event-mask} in @code{(xcb xml xproto)} to use as the
window's event mask. By default it consists of @code{key-press},
@code{structure-notify}, and @code{exposure}.
@end deffn
@deffn{Scheme Procedure} fixed-window-create x y width height border [events] [#:focused?=#t]
Create an unmapped window with dimensions (@var{x}, @var{y}), size
(@var{width}, @var{height}) and border width
@var{border}. @var{events} is an optional list of symbols from the
xenum @code{event-mask} in @code{(xml xcb xproto)} to use as the
window's event mask. By default it consists of @code{key-press},
@code{structure-notify}, and @code{exposure}.
Event listeners will be created so that this window will automatically
recirculate to always be on top, and if @var{focused?} is true, it
will always grab the keyboard input when visible.
Use this procedure to create window manager overlays such as the
message display, minibuffer, or menu.
@end deffn
@deffn{Scheme Procedure} fixed-window? win
Returns @code{#t} if XID @var{win} refers to a fixed window.
@end deffn
@node Commands
@section Commands
Guile-WM provides users with a simple command execution
facility. Internally, these commands are evaluated using a small
customized language that executes a Scheme procedures with the same
name. As a result, commands can be used both interactively and in
code. For example, the command @code{shell-command xterm} will be
evaluated as @code{(shell-command "xterm")}.
Commands save the user the trouble of writing out a full Scheme
expression for every simple task he or she wants to perform. Guile-WM
provides a minibuffer and a root keymap that can be used to enter and
select commands. @xref{Minibuffer}, or @ref{Root Keymap}.
The following definitions are found in @code{(guile-wm command)}:
@deffn{Scheme Syntax} define-command (name (arg type) ...) stmt ...
@deffnx{Scheme Syntax} define-command (name arg type) stmt ...
Define a new command named @var{name}. It creates and exports a
procedure with arguments @var{arg} ... and body @var{stmt} ...;
@var{type} for each @var{arg} should be one of the following:
@code{#:number}, @code{#:string}, or @code{#:symbol}. In the command
language, no quoting is needed. Instead, the language parses and
quotes arguments based on what type is specified for them.
The second version creates a command that accepts any number of
arguments of type @var{type}.
@end deffn
@deffn{Scheme Procedure} run-command cmd [arg-missing-proc]
Runs the given string @var{cmd} as a command. If the string doesn't
include enough arguments, @var{arg-missing-proc} is called to supply
additional arguments. It takes arguments @var{name} and @var{type},
the name and type of the required argument. Possible types are
@code{#:string}, @code{#:symbol}, and
@code{#:number}. @var{arg-missing-proc} may return a number, symbol,
or string which will be coerced to the correct type.
@end deffn
Some syntax is also provided to bind keys to commands. @xref{Keymaps}.
@deffn{Scheme Syntax} bind-key-commands keymap (key command) ...
@deffnx{Scheme Syntax} bind-key-commands keymap arg-missing (key command) ...
Bind @var{key} to command string @var{command} in @var{keymap}.
In the second form, @var{arg-missing} is a procedure to call to supply
arguments that are missing from the command string, as with
@code{run-command}.
@end deffn
The docstring for a commands procedure can be accessed using the
procedure @code{command-documentation}:
@deffn{Scheme Procedure} command-documentation command
Return the docstring for the procedure associated with symbol
@var{command}.
@end deffn
Some basic commands are provided by default:
@deffn{Command} quit
Quit the window manager and close the connection to the X
server. Replaces the core binding of the same name.
@end deffn
@deffn{Command} shell-command commands #:string
Concatenate @var{commands} into a single string and execute the result
in a detached process.
@end deffn
@deffn{Command} shell-command-output commands #:string
Concatenate @var{commands} into a single string and execute the result
in a process; wait for the command to terminate and return a string
containing its output.
@end deffn
@deffn{Command} wm-eval (exp #:string)
Evaluate S-expression @var{exp} in the window manager's current
environment.
@end deffn
@node Reparenting and Redirection
@section Reparenting and Redirection
Reparenting and redirection are two common X11 window manager
behaviors. When redirecting, window managers can rewrite or ignore
certain X requests that applications make to ensure that their windows
follow the window management rules that are in place. These requests
include mapping windows to the root window, changing their size and
position, and placing them above or below other windows.
When window managers redirect map requests, they often add the step of
reparenting the X window inside of another window which the window
manager owns and keeps track of. These parent windows can contain
window decoration, icons, titlebars, and so on.
Guile-WM provides support for redirecting requests and reparenting
windows in modules @code{(guile-wm redirect)} and @code{(guile-wm
reparent)}, respectively.
@deffn{Scheme Procedure} wm-reparent-window child parent x y
Reparent @var{child} inside of @var{parent} at coordinates (@var{x},
@var{y}), and set up event handlers to manage the life-cycle of the
parent window.
@end deffn
@deffn{Scheme Procedure} begin-redirect! on-map on-configure on-circulate
Begin redirecting @code{map-request}, @code{configure-request}, and
@code{circulate-request} events on the root window so that
@code{map-request} events are passed to @var{on-map},
@code{configure-request} events to @var{on-configure}, and
@code{circulate-request} to @var{on-circulate}.
@end deffn
@deffn{Scheme Procedure} end-redirect!
Stop redirecting requests on the root window.
@end deffn
Guile-WM can be configured to automatically reparent new windows with
the following method:
@deffn{Scheme Procedure} begin-reparent-redirect! create-parent
child-x child-y allow-configure? allow-circulate?
Begin redirecting client map, configure, and circulate requests. When
a map request for a new window arrives from another application, a
parent window is created by calling thunk @var{create-parent}. The
child window is reparented inside the parent at coordinates
(@var{child-x}, @var{child-y}).
@var{allow-configure?} and @var{allow-circulate?} specify whether
configure and circulate requests made by the child window's
application should sent to the X server or ignored. Ignored requests
can still be handled by procedures added to
@code{configure-request-hook} and @code{circulate-request-hook}.
@end deffn
The following hooks are run when requests come from client windows:
@deffn{WM Hook} after-reparent-hook
Called after a child window has been reparented inside a parent and
mapped. If this hooks is empty, the parent window will be mapped
automatically and the child window will be given the focus. Its two
arguments are the XID of the child window and the XID of the parent
window.
@end deffn
@deffn{WM Hook} unmap-notify-hook
Called when another application unmaps a reparented window. If this
hook is empty, the parent window will be unmapped. Its two arguments
are the unmap-notify event, and the XID of the parent window.
@end deffn
@deffn{WM Hook} configure-request-hook
Called when a configure request is received. The request is its
single argument.
@end deffn
@deffn{WM Hook} circulate-request-hook
Called when a circulate request is received. The request is its
single argument.
@end deffn
@node Text
@section Text
Guile-WM provides an interface for rendering text in an X window, as
well as an interface for editing the contents of a text buffer.
@menu
* Displaying Text::
* Editing Text::
@end menu
@node Displaying Text
@subsection Displaying Text
Guile-WM renders text using the core X11 protocol's support for simple
bitmapped fonts. Being able to use TTF and OTF fonts would be much
better, but the infrastructure for doing so is built on top of the
xlib and/or xcb X client libraries, and Guile-XCB (despite it's name)
doesn't inter-operate with either of those at the moment. Nor does it
have its own font rendering library. Hopefully this situation will be
rectified eventually.
Text display functions are in @code{(guile-wm text)}:
@deffn{Scheme Procedure} put-text text win fg bg font-string
Render escaped text string @var{text} in X window @var{win}, which is
resized to fit the text with two pixels of padding all
around. @var{fg} is the desired foreground color, and @var{bg} is the
background color. @var{font-string} should be a font string following
the core X11 font specification format.
@end deffn
Text strings passed to @code{put-text} can contain some simple escape
sequences to change color inline or insert newlines. These escapes are
s-expressions prefixed by the symbol @code{^}. For example, to invert
the foreground and background colors between the words ``this'' and
``house'' in the phrase ``this house'', the string should read
@code{"this ^(invert)house"}. To insert a single @code{^}, include two
carats in a row like this: @code{^^}. This method is a bit verbose,
but it is a lot more readable than the inscrutable escape sequences
used in terminal emulators.
@deffn{Text Escape} invert
Output the remainder of the text with the foreground and background
colors reversed.
@end deffn
@deffn{Text Escape} color fg [bg]
Output the remainder of the text with the foreground color set to
@var{fg} and the background color set to @var{bg}, if it is provided.
@end deffn
@deffn{Text Escape} start-new-line
Begin a new line in the displayed text. This escape can also be
accomplished by simply placing an actual newline in the string.
@end deffn
@node Editing Text
@subsection Editing Text
The module @code{(guile-wm text-edit)} exports a number of procedures
that can be used to edit a text buffer. These procedures all use a
record type called @code{text-edit-data}, which has two fields---the
text stored in the buffer, the location of the cursor or point in the
buffer.
The text is stored in a vlist of strings, with each string
representing one line. @inforef{Vlists,
Vlists, guile}.
Point is a pair of integers, @code{(x . y)}, where x is the column of
point and y is the row.
Text editor state is an @emph{immutable} data structure---procedures
that set its properties actually return a new copy of the data
structure with the old property value replaced by the new
one. @inforef{SRFI-9 Records, Functional ``Setters'', guile}.
@deffn{Scheme Procedure} make-text-edit-data point text
Create a new text edit data structure with point @var{point} and text
buffer @var{text}.
@end deffn
@deffn{Scheme Procedure} empty-text-edit-data
Create a new text edit data structure with an empty buffer and point
at (0, 0).
@end deffn
@deffn{Scheme Procedure} data-text
@deffnx{Scheme Procedure} set-data-text
Getter and functional setter for the text edit data's text buffer
@end deffn
@deffn{Scheme Procedure} data-point
@deffnx{Scheme Procedure} set-data-point
Getter and functional setter for the text edit data's point
@end deffn
The following procedures perform transformations on instances of text
edit data. As with the record type itself, the text buffer is
considered immutable and all operations return new values.
@deffn{Scheme Procedure} point-start data
Move point to the start of the current line
@end deffn
@deffn{Scheme Procedure} point-end data
Move point to the end of the current line
@end deffn
@deffn{Scheme Procedure} point-left data
Move point one column to the left, or to the end of the preceding row
if it is already all the way to the left. Point will not move if it is
already at the start of the first row
@end deffn
@deffn{Scheme Procedure} point-right data
Move point one column to the right, or to the start of the following row
if it is already all the way to the right. Point will not move if it is
already at the end of the last row
@end deffn
@deffn{Scheme Procedure} point-insert data str
Insert string @var{str} at the current point and move point to the end
of the newly inserted string.
@end deffn
@deffn{Scheme Procedure} delete-backwards data
Delete the character preceding point and move point back one
character. If point is at the beginning of a line, delete the
preceding newline and combine the current line with the preceding
line. Do nothing if point is at the beginning of the text.
@end deffn
@deffn{Scheme Procedure} delete-forwards data
Delete the character at point. If point is at the end of a line,
delete the newline and merge the current line with the next line. Do
nothing if point is at the end of the text.
@end deffn
@deffn{Scheme Procedure} kill-to-end-of-line data
Delete text from point's location to the end of the current line
@end deffn
@deffn{Scheme Procedure} insert-newline data
Insert a newline at point
@end deffn
@deffn{Scheme Procedure} point-forwards-word data
Move point forward past one word to the next word separator character,
or to the end of the text if no such character is found.
@end deffn
@deffn{Scheme Procedure} point-backwards-word data
Move point backwards past one word to the preceding word separator
character, or to the beginning of the text if no such character is found.
@end deffn
@deffn{Scheme Procedure} delete-forwards-word data
Delete text and move point forward past one word to the next word
separator character, or to the end of the text if no such character is
found.
@end deffn
@deffn{Scheme Procedure} delete-backwards-word data
Delete text and move point backward past one word to the preceding
word separator character, or to the beginning of the text if no such
character is found.
@end deffn
@deffn{Scheme Procedure} point-up data
Move point up one row if it is not already in the first row. Preserve
its column if the new row is wide enough, otherwise move it to the end
of the new row.
@end deffn
@deffn{Scheme Procedure} point-down data
Move point down one row if it is not already in the last row. Preserve
its column if the new row is wide enough, otherwise move it to the end
of the new row.
@end deffn
Additional text modifier procedures can be defined using helper syntax
that destructures the text edit data, passes its properties as
arguments to a procedure, and then constructs and returns new text
edit data from the values returned by that procedure.
@deffn{Scheme Syntax} define-text-modifier (name text point-x point-y other ...) stmt ...
Define procedure @var{name}, which takes a record of type
@code{text-edit-data} as an argument along with arguments @var{other}
... . The text, point column, and point row of that record are passed
along with @var{args} ... as arguments @var{text}, @var{point-x}, and
@var{point-y} and @var{args} ... to a procedure with body @var{stmt
...} . This procedure must return three values: the new text, the new
point column, and the new point row. Those values are combined into
a new record of type @code{text-edit-data}, which is then returned.
@end deffn
This syntax is simply a means of eliminating getter/setter
boilerplate, and is quite simple to use in practice. See text-edit.scm
for examples.
@node Color
@section Color
X11 was designed when the number of colors available at any one time
on a system was often very limited. As a result, it associates a
``colormap'' with each screen; the colormap maps integer values
(``pixels,'' in X11 terms) to colors, and it is possible to swap
colormaps so that multiple set of colors can be made
available. However, colormaps now can have a large depth, normally 24
bits at the very least, and swapping colormaps is more or less
obsolete.
That is all a long way of saying that when creating its own windows,
Guile-WM makes the bold assumption that the system it's running on
supports 24 bit color depth and lets the user worry about colormaps if
necessary. @xref{Drawing}. @code{(guile-wm color)} provides a
procedure to convert a color name into the appropriate pixel for the
given colormap.
@deffn{Scheme Procedure} pixel-for-color cmap color
Look up and return a pixel value for the given color name @var{color}
in colormap @var{cmap}. @var{color} should be a symbol corresponding
to one of X11s built-in colors, following the usual Scheme naming
conventions (all lowercase, words dash-separated).
@end deffn
@node Focus
@section Focus
In X11, the window with the focus is the one that normally gets
keyboard events. Rather than sending a @code{set-input-focus} request
directly to the server, modules in Guile-WM should call the procedure
@code{set-focus} in module @code{(guile-wm focus)}, which handles some
internal housekeeping and runs a hook so that other parts of the
window manager can update as necessary.
@deffn{Scheme Procedure} set-focus new-focus