1 ;;; --------------------------------------------------------------------------
2 ;;; CLFSWM - FullScreen Window Manager
4 ;;; --------------------------------------------------------------------------
5 ;;; Documentation: Main functions
6 ;;; --------------------------------------------------------------------------
8 ;;; (C) 2010 Philippe Brochard <hocwp@free.fr>
10 ;;; This program is free software; you can redistribute it and/or modify
11 ;;; it under the terms of the GNU General Public License as published by
12 ;;; the Free Software Foundation; either version 3 of the License, or
13 ;;; (at your option) any later version.
15 ;;; This program is distributed in the hope that it will be useful,
16 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;;; GNU General Public License for more details.
20 ;;; You should have received a copy of the GNU General Public License
21 ;;; along with this program; if not, write to the Free Software
22 ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 ;;; --------------------------------------------------------------------------
28 (defparameter *circulate-window
* nil
)
29 (defparameter *circulate-font
* nil
)
30 (defparameter *circulate-gc
* nil
)
32 (defparameter *circulate-hit
* 0)
33 (defparameter *circulate-orig
* nil
)
34 (defparameter *circulate-parent
* nil
)
36 (defun draw-circulate-mode-window ()
37 (raise-window *circulate-window
*)
38 (clear-pixmap-buffer *circulate-window
* *circulate-gc
*)
39 (let* ((text (format nil
"~A [~A]"
40 (limit-length (ensure-printable (child-name (xlib:input-focus
*display
*)))
41 *circulate-text-limite
*)
42 (limit-length (ensure-printable (child-name *current-child
*))
43 *circulate-text-limite
*)))
45 (xlib:draw-glyphs
*pixmap-buffer
* *circulate-gc
*
46 (truncate (/ (- *circulate-width
* (* (xlib:max-char-width
*circulate-font
*) len
)) 2))
47 (truncate (/ (+ *circulate-height
* (- (xlib:font-ascent
*circulate-font
*) (xlib:font-descent
*circulate-font
*))) 2))
49 (copy-pixmap-buffer *circulate-window
* *circulate-gc
*))
53 (defun leave-circulate-mode ()
54 "Leave the circulate mode"
55 (throw 'exit-circulate-loop nil
))
59 (defun reset-circulate-child ()
60 (setf *circulate-hit
* 0
61 *circulate-parent
* nil
62 *circulate-orig
* (frame-child *current-child
*)))
64 (defun reset-circulate-brother ()
65 (setf *circulate-parent
* (find-parent-frame *current-child
*))
66 (when (frame-p *circulate-parent
*)
67 (setf *circulate-orig
* (frame-child *circulate-parent
*))))
71 (defun reorder-child (direction)
73 (with-slots (child) *current-child
*
74 (unless *circulate-orig
*
75 (reset-circulate-child))
76 (let ((len (length *circulate-orig
*)))
78 (let ((elem (nth (mod (incf *circulate-hit
* direction
) len
) *circulate-orig
*)))
79 (setf child
(cons elem
(child-remove elem
*circulate-orig
*)))))
81 (draw-circulate-mode-window))))
84 (defun reorder-brother (direction)
86 (let ((frame-is-root?
(and (child-equal-p *current-root
* *current-child
*)
87 (not (child-equal-p *current-root
* *root-frame
*)))))
89 (hide-all *current-root
*)
90 (select-current-frame nil
))
91 (unless (and *circulate-orig
* *circulate-parent
*)
92 (reset-circulate-brother))
93 (let ((len (length *circulate-orig
*)))
95 (when (frame-p *circulate-parent
*)
96 (let ((elem (nth (mod (incf *circulate-hit
* direction
) len
) *circulate-orig
*)))
97 (setf (frame-child *circulate-parent
*) (cons elem
(child-remove elem
*circulate-orig
*))
98 *current-child
* (frame-selected-child *circulate-parent
*))))
100 (setf *current-root
* *current-child
*))))
101 (show-all-children (if frame-is-root?
103 (find-parent-frame *current-child
*)))
104 (draw-circulate-mode-window)))
106 (defun reorder-subchild (direction)
107 (declare (ignore direction
))
108 (when (frame-p *current-child
*)
109 (let ((selected-child (frame-selected-child *current-child
*)))
110 (when (frame-p selected-child
)
112 (with-slots (child) selected-child
113 (let ((elem (first (last child
))))
114 (setf child
(cons elem
(child-remove elem child
)))
115 (show-all-children selected-child
)
116 (draw-circulate-mode-window)))))))
122 (defun circulate-select-next-child ()
123 "Select the next child"
124 (when (frame-p *current-child
*)
125 (when *circulate-parent
*
126 (reset-circulate-child))
129 (defun circulate-select-previous-child ()
130 "Select the previous child"
131 (when (frame-p *current-child
*)
132 (when *circulate-parent
*
133 (reset-circulate-child))
137 (defun circulate-select-next-brother ()
138 "Select the next brother"
139 (unless *circulate-parent
*
140 (reset-circulate-brother))
141 (reorder-brother +1))
143 (defun circulate-select-previous-brother ()
144 "Select the previous borther"
145 (unless *circulate-parent
*
146 (reset-circulate-brother))
147 (reorder-brother -
1))
149 (defun circulate-select-next-subchild ()
150 "Select the next subchild"
151 (reorder-subchild +1))
155 (add-hook *binding-hook
* 'set-default-circulate-keys
)
157 (defun set-default-circulate-keys ()
158 (define-circulate-key ("Escape") 'leave-circulate-mode
)
159 (define-circulate-key ("g" :control
) 'leave-circulate-mode
)
160 (define-circulate-key ("Escape" :alt
) 'leave-circulate-mode
)
161 (define-circulate-key ("g" :control
:alt
) 'leave-circulate-mode
)
162 (define-circulate-key ("Tab" :mod-1
) 'circulate-select-next-child
)
163 (define-circulate-key ("Tab" :mod-1
:control
) 'circulate-select-next-subchild
)
164 (define-circulate-key ("Tab" :mod-1
:shift
) 'circulate-select-previous-child
)
165 (define-circulate-key ("Iso_Left_Tab" :mod-1
:shift
) 'circulate-select-previous-child
)
166 (define-circulate-key ("Right" :mod-1
) 'circulate-select-next-brother
)
167 (define-circulate-key ("Left" :mod-1
) 'circulate-select-previous-brother
)
168 (define-circulate-release-key ("Alt_L" :alt
) 'leave-circulate-mode
)
169 (define-circulate-release-key ("Alt_L") 'leave-circulate-mode
))
172 (defun circulate-leave-function ()
174 (xlib:free-gcontext
*circulate-gc
*))
175 (when *circulate-window
*
176 (xlib:destroy-window
*circulate-window
*))
177 (when *circulate-font
*
178 (xlib:close-font
*circulate-font
*))
179 (xlib:display-finish-output
*display
*)
180 (setf *circulate-window
* nil
182 *circulate-font
* nil
))
184 (defun circulate-loop-function ()
185 (unless (is-a-key-pressed-p)
186 (leave-circulate-mode)))
188 (define-handler circulate-mode
:key-press
(code state
)
189 (unless (funcall-key-from-code *circulate-keys
* code state
)
190 (setf *circulate-hit
* 0
192 *circulate-parent
* nil
)
193 (funcall-key-from-code *main-keys
* code state
)))
196 (define-handler circulate-mode
:key-release
(code state
)
197 (funcall-key-from-code *circulate-keys-release
* code state
))
201 (defun circulate-mode (&key child-direction brother-direction subchild-direction
)
202 (setf *circulate-hit
* 0)
203 (with-placement (*circulate-mode-placement
* x y
*circulate-width
* *circulate-height
*)
204 (setf *circulate-font
* (xlib:open-font
*display
* *circulate-font-string
*)
205 *circulate-window
* (xlib:create-window
:parent
*root
*
208 :width
*circulate-width
*
209 :height
*circulate-height
*
210 :background
(get-color *circulate-background
*)
212 :border
(get-color *circulate-border
*)
213 :colormap
(xlib:screen-default-colormap
*screen
*)
214 :event-mask
'(:exposure
:key-press
))
215 *circulate-gc
* (xlib:create-gcontext
:drawable
*circulate-window
*
216 :foreground
(get-color *circulate-foreground
*)
217 :background
(get-color *circulate-background
*)
218 :font
*circulate-font
*
220 (map-window *circulate-window
*)
221 (draw-circulate-mode-window)
222 (when child-direction
223 (reorder-child child-direction
))
224 (when brother-direction
225 (reorder-brother brother-direction
))
226 (when subchild-direction
227 (reorder-subchild subchild-direction
))
228 (let ((grab-keyboard-p (xgrab-keyboard-p))
229 (grab-pointer-p (xgrab-pointer-p)))
230 (xgrab-pointer *root
* 92 93)
231 (unless grab-keyboard-p
233 (xgrab-keyboard *root
*))
234 (generic-mode 'circulate-mode
'exit-circulate-loop
235 :loop-function
#'circulate-loop-function
236 :leave-function
#'circulate-leave-function
237 :original-mode
'(main-mode))
238 (circulate-leave-function)
239 (unless grab-keyboard-p
243 (xgrab-pointer *root
* 66 67)
244 (xungrab-pointer)))))
247 (defun select-next-child ()
248 "Select the next child"
249 (when (frame-p *current-child
*)
250 (setf *circulate-orig
* (frame-child *current-child
*)
251 *circulate-parent
* nil
)
252 (circulate-mode :child-direction
+1)))
254 (defun select-previous-child ()
255 "Select the previous child"
256 (when (frame-p *current-child
*)
257 (setf *circulate-orig
* (frame-child *current-child
*)
258 *circulate-parent
* nil
)
259 (circulate-mode :child-direction -
1)))
262 (defun select-next-brother ()
263 "Select the next brother"
264 (setf *circulate-parent
* (find-parent-frame *current-child
*))
265 (when (frame-p *circulate-parent
*)
266 (setf *circulate-orig
* (frame-child *circulate-parent
*)))
267 (circulate-mode :brother-direction
+1))
269 (defun select-previous-brother ()
270 "Select the previous brother"
271 (setf *circulate-parent
* (find-parent-frame *current-child
*))
272 (when (frame-p *circulate-parent
*)
273 (setf *circulate-orig
* (frame-child *circulate-parent
*)))
274 (circulate-mode :brother-direction -
1))
276 (defun select-next-subchild ()
277 "Select the next subchild"
278 (when (and (frame-p *current-child
*)
279 (frame-p (frame-selected-child *current-child
*)))
280 (setf *circulate-orig
* (frame-child *current-child
*)
281 *circulate-parent
* nil
)
282 (circulate-mode :subchild-direction
+1)))