Associate child under mouse to expose-child
[clfswm.git] / src / clfswm-expose-mode.lisp
blob50f36efa694ed44d6d62e60877a30e19780864ca
1 ;;; --------------------------------------------------------------------------
2 ;;; CLFSWM - FullScreen Window Manager
3 ;;;
4 ;;; --------------------------------------------------------------------------
5 ;;; Documentation: Expose functions - An expose like.
6 ;;; --------------------------------------------------------------------------
7 ;;;
8 ;;; (C) 2005-2013 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-selected-child* nil)
31 (defstruct expose-child child key window gc string)
33 (defun leave-expose-mode ()
34 "Leave the expose mode"
35 (throw 'exit-expose-loop nil))
37 (defun valid-expose-mode ()
38 "Valid the expose mode"
39 (throw 'exit-expose-loop t))
41 (defun mouse-leave-expose-mode (window root-x root-y)
42 "Leave the expose mode"
43 (declare (ignore window root-x root-y))
44 (throw 'exit-expose-loop nil))
46 (defun mouse-valid-expose-mode (window root-x root-y)
47 "Valid the expose mode"
48 (declare (ignore window root-x root-y))
49 (throw 'exit-expose-loop t))
52 (defun expose-associate-keys ()
53 (let* ((all nil)
54 (new nil))
55 (with-all-children-reversed (*root-frame* child)
56 (unless (child-equal-p child *root-frame*)
57 (push child all)
58 (unless (member child *expose-child-list* :test #'child-equal-p :key #'expose-child-child)
59 (push (make-expose-child :child child :key (number->letter *expose-current-number*)) new)
60 (incf *expose-current-number*))))
61 (append (remove-if-not (lambda (x) (member x all :test #'child-equal-p)) *expose-child-list*
62 :key #'expose-child-child)
63 (nreverse new))))
69 (defun expose-draw-letter ()
70 (dolist (ex-child *expose-child-list*)
71 (let ((window (expose-child-window ex-child))
72 (gc (expose-child-gc ex-child)))
73 (when (and window gc)
74 (clear-pixmap-buffer window gc)
75 (xlib:with-gcontext (gc :foreground (get-color (if (substring-equal *query-string* (expose-child-key ex-child))
76 *expose-foreground-letter*
77 *expose-foreground-letter-nok*))
78 :background (get-color (if (string-equal *query-string* (expose-child-key ex-child))
79 *expose-background-letter-match*
80 *expose-background*)))
81 (xlib:draw-image-glyphs *pixmap-buffer* gc
82 (xlib:max-char-width *expose-font*)
83 (+ (xlib:font-ascent *expose-font*) (xlib:font-descent *expose-font*))
84 (expose-child-key ex-child)))
85 (xlib:draw-glyphs *pixmap-buffer* gc
86 (xlib:max-char-width *expose-font*)
87 (+ (* 2 (xlib:font-ascent *expose-font*)) (xlib:font-descent *expose-font*) 1)
88 (expose-child-string ex-child))
89 (copy-pixmap-buffer window gc)))))
92 (defun expose-create-window (ex-child)
93 (let ((child (expose-child-child ex-child)))
94 (with-current-child (child)
95 (let* ((string (format nil "~A"
96 (if *expose-show-window-title*
97 (ensure-printable (child-fullname child))
98 "")))
99 (width (if *expose-show-window-title*
100 (min (* (xlib:max-char-width *expose-font*) (+ (length string) 2))
101 (- (child-width child) 4))
102 (* (xlib:max-char-width *expose-font*) 3)))
103 (height (* (xlib:font-ascent *expose-font*) 3)))
104 (with-placement (*expose-mode-placement* x y width height)
105 (let* ((window (xlib:create-window :parent *root*
106 :x x :y y
107 :width width :height height
108 :background (get-color *expose-background*)
109 :border-width *border-size*
110 :border (get-color *expose-border*)
111 :colormap (xlib:screen-default-colormap *screen*)
112 :event-mask '(:exposure :key-press)))
113 (gc (xlib:create-gcontext :drawable window
114 :foreground (get-color *expose-foreground*)
115 :background (get-color *expose-background*)
116 :font *expose-font*
117 :line-style :solid)))
118 (setf (window-transparency window) *expose-transparency*)
119 (map-window window)
120 (setf (expose-child-window ex-child) window
121 (expose-child-gc ex-child) gc
122 (expose-child-string ex-child) string)))))))
127 (defun expose-query-key-press-hook (code state)
128 (declare (ignore code state))
129 (expose-draw-letter)
130 (when (and *expose-direct-select* (<= (length *expose-child-list*) 26))
131 (leave-query-mode :return)))
133 (defun expose-query-button-press-hook (code state x y)
134 (declare (ignore state))
135 (when (= code 1)
136 (setf *expose-selected-child*
137 (find (find-child-under-mouse x y) *expose-child-list* :test #'child-equal-p :key #'expose-child-child)))
138 (leave-query-mode :click))
141 (defun expose-init ()
142 (setf *expose-font* (xlib:open-font *display* *expose-font-string*)
143 *expose-child-list* (expose-associate-keys)
144 *expose-selected-child* nil
145 *query-string* "")
146 (xlib:warp-pointer *root* (truncate (/ (screen-width) 2))
147 (truncate (/ (screen-height) 2)))
148 (add-hook *query-key-press-hook* 'expose-query-key-press-hook)
149 (add-hook *query-button-press-hook* 'expose-query-button-press-hook))
151 (defun expose-present-windows ()
152 (dolist (ex-child *expose-child-list*)
153 (let ((child (expose-child-child ex-child)))
154 (when (frame-p child)
155 (setf (frame-data-slot child :old-layout) (frame-layout child)
156 (frame-layout child) #'tile-space-layout))))
157 (show-all-children t))
159 (defun expose-unpresent-windows ()
160 (dolist (ex-child *expose-child-list*)
161 (let ((child (expose-child-child ex-child)))
162 (when (frame-p child)
163 (setf (frame-layout child) (frame-data-slot child :old-layout)
164 (frame-data-slot child :old-layout) nil)))))
166 (defun expose-mode-display-accel-windows ()
167 (with-all-root-child (root)
168 (with-all-children-reversed (root child)
169 (let ((ex-child (find child *expose-child-list* :test #'child-equal-p :key #'expose-child-child)))
170 (when ex-child
171 (if (or (frame-p (expose-child-child ex-child))
172 (managed-window-p (expose-child-child ex-child)
173 (find-parent-frame (expose-child-child ex-child) *root-frame*)))
174 (expose-create-window ex-child)
175 (hide-child (expose-child-child ex-child)))))))
176 (expose-draw-letter))
179 (defun expose-find-child-from-letters (letters)
180 (find letters *expose-child-list* :test #'string-equal :key #'expose-child-key))
182 (defun expose-select-child ()
183 (let ((*query-mode-placement* *expose-query-placement*))
184 (multiple-value-bind (letters return)
185 (query-string "Which child ?")
186 (let ((ex-child (case return
187 (:return (expose-find-child-from-letters letters))
188 (:click *expose-selected-child*))))
189 (when ex-child
190 (expose-child-child ex-child))))))
193 (defun expose-restore-windows ()
194 (remove-hook *query-key-press-hook* 'expose-query-key-press-hook)
195 (remove-hook *query-button-press-hook* 'expose-query-button-press-hook)
196 (dolist (ex-child *expose-child-list*)
197 (awhen (expose-child-gc ex-child)
198 (xlib:free-gcontext it))
199 (awhen (expose-child-window ex-child)
200 (xlib:destroy-window it))
201 (setf (expose-child-gc ex-child) nil
202 (expose-child-window ex-child) nil))
203 (when *expose-font*
204 (xlib:close-font *expose-font*))
205 (expose-unpresent-windows))
207 (defun expose-focus-child (child)
208 (let ((parent (typecase child
209 (xlib:window (find-parent-frame child))
210 (frame child))))
211 (when (and child parent)
212 (change-root (find-root parent) parent)
213 (setf (current-child) child)
214 (focus-all-children child parent t))))
216 (defun expose-do-main ()
217 (stop-button-event)
218 (expose-init)
219 (expose-present-windows)
220 (expose-mode-display-accel-windows)
221 (let ((child (expose-select-child)))
222 (expose-restore-windows)
223 child))
225 (defun expose-windows-mode ()
226 "Present all windows in currents roots (An expose like)"
227 (awhen (expose-do-main)
228 (expose-focus-child it))
229 (show-all-children)
233 (defun expose-all-windows-mode ()
234 "Present all windows in all frames (An expose like)"
235 (let ((child nil))
236 (with-saved-root-list ()
237 (dolist (root (get-root-list))
238 (change-root root (root-original root)))
239 (setf child (expose-do-main)))
240 (when child
241 (expose-focus-child child)))
242 (show-all-children)