c3a981412e818aa734bddf65db36a6aea8d6cee8
[clfswm.git] / src / clfswm-expose-mode.lisp
blobc3a981412e818aa734bddf65db36a6aea8d6cee8
1 ;;; --------------------------------------------------------------------------
2 ;;; CLFSWM - FullScreen Window Manager
3 ;;;
4 ;;; --------------------------------------------------------------------------
5 ;;; Documentation: Expose functions - An expose like.
6 ;;; --------------------------------------------------------------------------
7 ;;;
8 ;;; (C) 2012 Philippe Brochard <pbrochard@common-lisp.net>
9 ;;;
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.
14 ;;;
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.
19 ;;;
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.
23 ;;;
24 ;;; --------------------------------------------------------------------------
26 (in-package :clfswm)
28 (defparameter *expose-font* nil)
29 (defparameter *expose-child-list* nil)
30 (defparameter *expose-selected-child* nil)
32 (defstruct expose-child child key window gc string)
34 (defun leave-expose-mode ()
35 "Leave the expose mode"
36 (throw 'exit-expose-loop nil))
38 (defun valid-expose-mode ()
39 "Valid the expose mode"
40 (throw 'exit-expose-loop t))
42 (defun mouse-leave-expose-mode (window root-x root-y)
43 "Leave the expose mode"
44 (declare (ignore window root-x root-y))
45 (throw 'exit-expose-loop nil))
47 (defun mouse-valid-expose-mode (window root-x root-y)
48 "Valid the expose mode"
49 (declare (ignore window root-x root-y))
50 (throw 'exit-expose-loop t))
55 (defun expose-sort (predicate type)
56 (lambda (x y)
57 (funcall predicate (funcall type x) (funcall type y))))
59 (defun expose-associate-keys ()
60 (let* ((acc nil)
61 (n 0)
62 (win-list (sort (get-all-windows) (expose-sort #'< #'xlib:window-id)))
63 (frame-list (sort (get-all-frames) (expose-sort #'< #'frame-number))))
64 (loop for c in win-list
65 do (push (make-expose-child :child c :key (number->letter n)) acc)
66 (incf n))
67 (loop for c in frame-list
68 do (unless (child-equal-p c *root-frame*)
69 (push (make-expose-child :child c :key (number->letter n)) acc)
70 (incf n)))
71 (nreverse acc)))
77 (defun expose-draw-letter ()
78 (dolist (ex-child *expose-child-list*)
79 (let ((window (expose-child-window ex-child))
80 (gc (expose-child-gc ex-child)))
81 (when (and window gc)
82 (clear-pixmap-buffer window gc)
83 (xlib:with-gcontext (gc :foreground (get-color (if (substring-equal *query-string* (expose-child-key ex-child))
84 *expose-foreground-letter*
85 *expose-foreground-letter-nok*))
86 :background (get-color (if (string-equal *query-string* (expose-child-key ex-child))
87 *expose-background-letter-match*
88 *expose-background*)))
89 (xlib:draw-image-glyphs *pixmap-buffer* gc
90 (xlib:max-char-width *expose-font*)
91 (+ (xlib:font-ascent *expose-font*) (xlib:font-descent *expose-font*))
92 (expose-child-key ex-child)))
93 (xlib:draw-glyphs *pixmap-buffer* gc
94 (xlib:max-char-width *expose-font*)
95 (+ (* 2 (xlib:font-ascent *expose-font*)) (xlib:font-descent *expose-font*) 1)
96 (expose-child-string ex-child))
97 (copy-pixmap-buffer window gc)))))
99 (defun expose-create-window (ex-child)
100 (let ((child (expose-child-child ex-child)))
101 (with-current-child (child)
102 (let* ((string (format nil "~A"
103 (if *expose-show-window-title*
104 (ensure-printable (child-fullname child))
105 "")))
106 (width (if *expose-show-window-title*
107 (min (* (xlib:max-char-width *expose-font*) (+ (length string) 2))
108 (- (child-width child) 4))
109 (* (xlib:max-char-width *expose-font*) 3)))
110 (height (* (xlib:font-ascent *expose-font*) 3)))
111 (with-placement (*expose-mode-placement* x y width height)
112 (let* ((window (xlib:create-window :parent *root*
113 :x x :y y
114 :width width :height height
115 :background (get-color *expose-background*)
116 :border-width *border-size*
117 :border (get-color *expose-border*)
118 :colormap (xlib:screen-default-colormap *screen*)
119 :event-mask '(:exposure :key-press)))
120 (gc (xlib:create-gcontext :drawable window
121 :foreground (get-color *expose-foreground*)
122 :background (get-color *expose-background*)
123 :font *expose-font*
124 :line-style :solid)))
125 (setf (window-transparency window) *expose-transparency*)
126 (map-window window)
127 (setf (expose-child-window ex-child) window
128 (expose-child-gc ex-child) gc
129 (expose-child-string ex-child) string)))))))
134 (defun expose-query-key-press-hook (code state)
135 (declare (ignore code state))
136 (expose-draw-letter)
137 (when (and *expose-direct-select* (<= (length *expose-child-list*) 26))
138 (leave-query-mode :return)))
140 (defun expose-query-button-press-hook (code state x y)
141 (declare (ignore state))
142 (when (= code 1)
143 (setf *expose-selected-child* (find-child-under-mouse x y)))
144 (leave-query-mode :click))
147 (defun expose-init ()
148 (setf *expose-font* (xlib:open-font *display* *expose-font-string*)
149 *expose-child-list* (expose-associate-keys)
150 *expose-selected-child* nil
151 *query-string* "")
152 (xlib:warp-pointer *root* (truncate (/ (xlib:screen-width *screen*) 2))
153 (truncate (/ (xlib:screen-height *screen*) 2)))
154 (add-hook *query-key-press-hook* 'expose-query-key-press-hook)
155 (add-hook *query-button-press-hook* 'expose-query-button-press-hook))
157 (defun expose-present-windows ()
158 (dolist (ex-child *expose-child-list*)
159 (let ((child (expose-child-child ex-child)))
160 (when (frame-p child)
161 (setf (frame-data-slot child :old-layout) (frame-layout child)
162 (frame-layout child) #'tile-space-layout))))
163 (show-all-children t))
165 (defun expose-unpresent-windows ()
166 (dolist (ex-child *expose-child-list*)
167 (let ((child (expose-child-child ex-child)))
168 (when (frame-p child)
169 (setf (frame-layout child) (frame-data-slot child :old-layout)
170 (frame-data-slot child :old-layout) nil)))))
172 (defun expose-mode-display-accel-windows ()
173 (with-all-root-child (root)
174 (with-all-children-reversed (root child)
175 (let ((ex-child (find child *expose-child-list* :test #'child-equal-p :key #'expose-child-child)))
176 (when ex-child
177 (if (or (frame-p (expose-child-child ex-child))
178 (managed-window-p (expose-child-child ex-child)
179 (find-parent-frame (expose-child-child ex-child) *root-frame*)))
180 (expose-create-window ex-child)
181 (hide-child (expose-child-child ex-child)))))))
182 (expose-draw-letter))
185 (defun expose-find-child-from-letters (letters)
186 (find letters *expose-child-list* :test #'string-equal :key #'expose-child-key))
188 (defun expose-select-child ()
189 (let ((*query-mode-placement* *expose-query-placement*))
190 (multiple-value-bind (letters return)
191 (query-string "Which child ?")
192 (let ((ex-child (case return
193 (:return (expose-find-child-from-letters letters))
194 (:click *expose-selected-child*))))
195 (when ex-child
196 (expose-child-child ex-child))))))
199 (defun expose-restore-windows ()
200 (remove-hook *query-key-press-hook* 'expose-query-key-press-hook)
201 (remove-hook *query-button-press-hook* 'expose-query-button-press-hook)
202 (dolist (ex-child *expose-child-list*)
203 (awhen (expose-child-gc ex-child)
204 (xlib:free-gcontext it))
205 (awhen (expose-child-window ex-child)
206 (xlib:destroy-window it)))
207 (when *expose-font*
208 (xlib:close-font *expose-font*))
209 (expose-unpresent-windows)
210 (setf *expose-child-list* nil))
212 (defun expose-focus-child (child)
213 (let ((parent (typecase child
214 (xlib:window (find-parent-frame child))
215 (frame child))))
216 (when (and child parent)
217 (change-root (find-root parent) parent)
218 (setf (current-child) child)
219 (focus-all-children child parent t))))
221 (defun expose-do-main ()
222 (stop-button-event)
223 (expose-init)
224 (expose-present-windows)
225 (expose-mode-display-accel-windows)
226 (let ((child (expose-select-child)))
227 (expose-restore-windows)
228 child))
230 (defun expose-windows-mode ()
231 "Present all windows in currents roots (An expose like)"
232 (awhen (expose-do-main)
233 (expose-focus-child it))
234 (show-all-children)
238 (defun expose-all-windows-mode ()
239 "Present all windows in all frames (An expose like)"
240 (let ((child nil))
241 (with-saved-root-list ()
242 (dolist (root (get-root-list))
243 (change-root root (root-original root)))
244 (setf child (expose-do-main)))
245 (when child
246 (expose-focus-child child)))
247 (show-all-children)