FIle test
[clfswm.git] / src / clfswm-expose-mode.lisp
blob6211778ae465dc05ce0658a7bb0ef86c201f5b25
1 ;;; --------------------------------------------------------------------------
2 ;;; CLFSWM - FullScreen Window Manager
3 ;;;
4 ;;; --------------------------------------------------------------------------
5 ;;; Documentation: Expose functions - An expose like.
6 ;;; --------------------------------------------------------------------------
7 ;;;
8 ;;; (C) 2010 Philippe Brochard <hocwp@free.fr>
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-windows-list* nil)
31 (defun leave-expose-mode ()
32 "Leave the expose mode"
33 (throw 'exit-expose-loop nil))
35 (defun valid-expose-mode ()
36 "Valid the expose mode"
37 (throw 'exit-expose-loop t))
39 (defun mouse-leave-expose-mode (window root-x root-y)
40 "Leave the expose mode"
41 (declare (ignore window root-x root-y))
42 (throw 'exit-expose-loop nil))
44 (defun mouse-valid-expose-mode (window root-x root-y)
45 "Valid the expose mode"
46 (declare (ignore window root-x root-y))
47 (throw 'exit-expose-loop t))
50 (define-handler expose-mode :key-press (code state)
51 (funcall-key-from-code *expose-keys* code state))
53 (define-handler expose-mode :button-press (code state window root-x root-y)
54 (funcall-button-from-code *expose-mouse* code state window root-x root-y *fun-press*))
56 (define-handler expose-mode :exposure ()
57 (expose-draw-letter))
60 (add-hook *binding-hook* 'set-default-expose-keys)
62 (defun set-default-expose-keys ()
63 (define-expose-key ("Escape") 'leave-expose-mode)
64 (define-expose-key ("g" :control) 'leave-expose-mode)
65 (define-expose-key ("Escape" :alt) 'leave-expose-mode)
66 (define-expose-key ("g" :control :alt) 'leave-expose-mode)
67 (define-expose-key ("Return") 'valid-expose-mode)
68 (define-expose-key ("space") 'valid-expose-mode)
69 (define-expose-key ("Tab") 'valid-expose-mode)
70 (define-expose-key ("Right") 'speed-mouse-right)
71 (define-expose-key ("Left") 'speed-mouse-left)
72 (define-expose-key ("Down") 'speed-mouse-down)
73 (define-expose-key ("Up") 'speed-mouse-up)
74 (define-expose-key ("Left" :control) 'speed-mouse-undo)
75 (define-expose-key ("Up" :control) 'speed-mouse-first-history)
76 (define-expose-key ("Down" :control) 'speed-mouse-reset)
77 (define-expose-mouse (1) 'mouse-valid-expose-mode)
78 (define-expose-mouse (2) 'mouse-leave-expose-mode)
79 (define-expose-mouse (3) 'mouse-leave-expose-mode))
81 (defmacro define-expose-letter-keys ()
82 (labels ((produce-name (n)
83 (symb "%" "expose-fun-key-" n "%")))
84 `(progn
85 ,@(loop for n from 0 to 25
86 collect `(progn
87 (defun ,(produce-name n) ()
88 ,(format nil "Select child '~A' (~A)" (number->char n) n)
89 (let ((child (nth ,n *expose-windows-list*)))
90 (when child
91 (xlib:warp-pointer *root* (xlib:drawable-x (first child)) (xlib:drawable-y (first child)))
92 (when *expose-valid-on-key*
93 (valid-expose-mode)))))
94 (define-expose-key (,(number->char n)) ',(produce-name n)))))))
96 (define-expose-letter-keys)
99 (defun expose-draw-letter ()
100 (loop for lwin in *expose-windows-list* do
101 (xlib:draw-glyphs (first lwin) (second lwin)
102 (xlib:max-char-width *expose-font*)
103 (+ (xlib:font-ascent *expose-font*) (xlib:font-descent *expose-font*))
104 (third lwin))))
106 (defun expose-create-window (child n)
107 (let* ((*current-child* child)
108 (string (format nil "~A~A" (number->char n)
109 (if *expose-show-window-title*
110 (format nil " - ~A" (ensure-printable (child-fullname child)))
111 "")))
112 (width (if *expose-show-window-title*
113 (min (* (xlib:max-char-width *expose-font*) (+ (length string) 2))
114 (- (child-width child) 4))
115 (* (xlib:max-char-width *expose-font*) 3)))
116 (height (* (xlib:font-ascent *expose-font*) 2)))
117 (with-placement (*expose-mode-placement* x y width height)
118 (let* ((window (xlib:create-window :parent *root*
119 :x x :y y
120 :width width :height height
121 :background (get-color *expose-background*)
122 :border-width 1
123 :border (get-color *expose-border*)
124 :colormap (xlib:screen-default-colormap *screen*)
125 :event-mask '(:exposure :key-press)))
126 (gc (xlib:create-gcontext :drawable window
127 :foreground (get-color *expose-foreground*)
128 :background (get-color *expose-background*)
129 :font *expose-font*
130 :line-style :solid)))
131 (map-window window)
132 (push (list window gc string) *expose-windows-list*)))))
136 (defun expose-mode-display-accel-windows ()
137 (let ((n -1))
138 (with-all-children-reversed (*current-root* child)
139 (when (< n 25)
140 (expose-create-window child (incf n)))))
141 (setf *expose-windows-list* (nreverse *expose-windows-list*))
142 (expose-draw-letter))
145 (defun expose-windows-generic (first-restore-frame &optional body body-escape)
146 (setf *expose-font* (xlib:open-font *display* *expose-font-string*)
147 *expose-windows-list* nil)
148 (xlib:warp-pointer *root* (truncate (/ (xlib:screen-width *screen*) 2))
149 (truncate (/ (xlib:screen-height *screen*) 2)))
150 (with-all-frames (first-restore-frame frame)
151 (setf (frame-data-slot frame :old-layout) (frame-layout frame)
152 (frame-layout frame) #'tile-space-layout))
153 (show-all-children *current-root*)
154 (expose-mode-display-accel-windows)
155 (let ((grab-keyboard-p (xgrab-keyboard-p))
156 (grab-pointer-p (xgrab-pointer-p)))
157 (xgrab-pointer *root* 92 93)
158 (unless grab-keyboard-p
159 (ungrab-main-keys)
160 (xgrab-keyboard *root*))
161 (if (generic-mode 'expose-mode 'exit-expose-loop
162 :original-mode '(main-mode))
163 (multiple-value-bind (x y) (xlib:query-pointer *root*)
164 (let* ((child (find-child-under-mouse x y))
165 (parent (find-parent-frame child *root-frame*)))
166 (when (and child parent)
167 (pfuncall body parent)
168 (focus-all-children child parent))))
169 (pfuncall body-escape))
170 (dolist (lwin *expose-windows-list*)
171 (awhen (first lwin)
172 (xlib:destroy-window it))
173 (awhen (second lwin)
174 (xlib:free-gcontext it)))
175 (when *expose-font*
176 (xlib:close-font *expose-font*))
177 (setf *expose-windows-list* nil)
178 (with-all-frames (first-restore-frame frame)
179 (setf (frame-layout frame) (frame-data-slot frame :old-layout)
180 (frame-data-slot frame :old-layout) nil))
181 (show-all-children *current-root*)
182 (unless grab-keyboard-p
183 (xungrab-keyboard)
184 (grab-main-keys))
185 (if grab-pointer-p
186 (xgrab-pointer *root* 66 67)
187 (xungrab-pointer)))
191 (defun expose-windows-mode ()
192 "Present all windows in the current frame (An expose like)"
193 (stop-button-event)
194 (expose-windows-generic *current-root*))
196 (defun expose-all-windows-mode ()
197 "Present all windows in all frames (An expose like)"
198 (stop-button-event)
199 (let ((orig-root *current-root*))
200 (switch-to-root-frame :show-later t)
201 (expose-windows-generic *root-frame*
202 (lambda (parent)
203 (hide-all-children *root-frame*)
204 (setf *current-root* parent))
205 (lambda ()
206 (hide-all-children *current-root*)
207 (setf *current-root* orig-root)))))