Date copyright and version update
[clfswm.git] / src / clfswm-layout.lisp
blobe4d72a56beb271e0e7bde390dfc9b9737cb5f532
1 ;;; --------------------------------------------------------------------------
2 ;;; CLFSWM - FullScreen Window Manager
3 ;;;
4 ;;; --------------------------------------------------------------------------
5 ;;; Documentation: Layout functions
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)
29 ;;; CONFIG - Layout menu
30 ;;;
31 ;;; To add a new layout:
32 ;;; 1- define your own layout: a method returning the real size of the
33 ;;; child in screen size (integer) as 5 values (rx, ry, rw, rh).
34 ;;; This method can use the float size of the child (x, y ,w , h).
35 ;;; It can be specialised for xlib:window or frame
36 ;;; 2- Define a setter function for your layout
37 ;;; 3- Register your new layout with register-layout or create
38 ;;; a sub menu for it with register-layout-sub-menu.
42 (defparameter *layout-current-key* (1- (char-code #\a)))
45 ;;; Generic functions
46 (defun set-layout (layout)
47 "Set the layout of the current child"
48 (when (frame-p *current-child*)
49 (setf (frame-layout *current-child*) layout)
50 (leave-second-mode)))
52 (defun set-layout-dont-leave (layout)
53 "Set the layout of the current child"
54 (when (frame-p *current-child*)
55 (setf (frame-layout *current-child*) layout)))
57 (defun set-layout-once (layout-name)
58 (set-layout-dont-leave layout-name)
59 (show-all-children *current-root*)
60 (fixe-real-size-current-child)
61 (set-layout-dont-leave #'no-layout))
64 (defun get-managed-child (parent)
65 "Return only the windows that are managed for tiling"
66 (when (frame-p parent)
67 (remove-if #'(lambda (x)
68 (and (xlib:window-p x) (not (managed-window-p x parent))))
69 (frame-child parent))))
72 (defun next-layout-key ()
73 (code-char (incf *layout-current-key*)))
76 (defun register-layout (layout)
77 (add-menu-key 'frame-layout-menu (next-layout-key) layout))
80 (defun register-layout-sub-menu (name doc layout-list)
81 (add-sub-menu 'frame-layout-menu (next-layout-key) name doc)
82 (loop :for item :in layout-list
83 :for i :from 0
84 :do (typecase item
85 (cons (add-menu-key name (first item) (second item)))
86 (string (add-menu-comment name item))
87 (t (add-menu-key name (number->char i) item)))))
92 (defun layout-ask-size (msg slot &optional (min 80))
93 (when (frame-p *current-child*)
94 (let ((new-size (/ (or (query-number msg (* (frame-data-slot *current-child* slot) 100)) min) 100)))
95 (when (<= 0 new-size 1)
96 (setf (frame-data-slot *current-child* slot) new-size)))))
102 (defun fast-layout-switch ()
103 "Switch between two layouts"
104 (when (frame-p *current-child*)
105 (with-slots (layout) *current-child*
106 (let* ((layout-list (frame-data-slot *current-child* :fast-layout))
107 (first-layout (ensure-function (first layout-list)))
108 (second-layout (ensure-function (second layout-list))))
109 (setf layout (if (eql layout first-layout)
110 second-layout
111 first-layout))
112 (leave-second-mode)))))
115 (defun push-in-fast-layout-list ()
116 "Push the current layout in the fast layout list"
117 (when (frame-p *current-child*)
118 (setf (frame-data-slot *current-child* :fast-layout)
119 (list (frame-layout *current-child*)
120 (first (frame-data-slot *current-child* :fast-layout))))
121 (leave-second-mode)))
125 (register-layout-sub-menu 'frame-fast-layout-menu "Frame fast layout menu"
126 '(("s" fast-layout-switch)
127 ("p" push-in-fast-layout-list)))
131 ;;; No layout
132 (defgeneric no-layout (child parent)
133 (:documentation "No layout: Maximize windows in there frame - Leave frames to there original size"))
135 (defmethod no-layout ((child xlib:window) parent)
136 (with-slots (rx ry rw rh) parent
137 (values (1+ rx)
138 (1+ ry)
139 (- rw 2)
140 (- rh 2))))
142 (defmethod no-layout ((child frame) parent)
143 (values (x-fl->px (frame-x child) parent)
144 (y-fl->px (frame-y child) parent)
145 (w-fl->px (frame-w child) parent)
146 (h-fl->px (frame-h child) parent)))
150 (defun set-no-layout ()
151 "No layout: Maximize windows in there frame - Leave frames to there original size"
152 (set-layout #'no-layout))
154 (register-layout 'set-no-layout)
156 ;;; No layout remember size
157 (defun set-no-layout-remember-size ()
158 "No layout: Maximize windows in there frame - Leave frames to there actual size"
159 (fixe-real-size-current-child)
160 (set-no-layout))
162 (register-layout 'set-no-layout-remember-size)
166 ;;; Maximize layout
167 (defgeneric maximize-layout (child parent)
168 (:documentation "Maximize layout: Maximize windows and frames in there parent frame"))
170 (defmethod maximize-layout (child parent)
171 (declare (ignore child))
172 (with-slots (rx ry rw rh) parent
173 (values (1+ rx)
174 (1+ ry)
175 (- rw 2)
176 (- rh 2))))
179 (defun set-maximize-layout ()
180 "Maximize layout: Maximize windows and frames in there parent frame"
181 (set-layout #'maximize-layout))
183 (register-layout 'set-maximize-layout)
188 ;;; Tile layout
189 (defun set-layout-managed-children ()
190 (when (frame-p *current-child*)
191 (setf (frame-data-slot *current-child* :layout-managed-children)
192 (copy-list (get-managed-child *current-child*)))))
194 (defun update-layout-managed-children (child parent)
195 (let ((managed-children (frame-data-slot parent :layout-managed-children))
196 (managed-in-parent (get-managed-child parent)))
197 (dolist (ch managed-in-parent)
198 (unless (member ch managed-children)
199 (setf managed-children (append managed-children (list child)))))
200 (setf managed-children (remove-if-not (lambda (x)
201 (member x managed-in-parent :test #'equal))
202 managed-children))
203 (setf (frame-data-slot parent :layout-managed-children) managed-children)
204 managed-children))
206 (defgeneric tile-layout (child parent)
207 (:documentation "Tile child in its frame (vertical)"))
209 (defmethod tile-layout (child parent)
210 (let* ((managed-children (update-layout-managed-children child parent))
211 (pos (position child managed-children))
212 (len (length managed-children))
213 (n (ceiling (sqrt len)))
214 (dx (/ (frame-rw parent) n))
215 (dy (/ (frame-rh parent) (ceiling (/ len n)))))
216 (values (round (+ (frame-rx parent) (truncate (* (mod pos n) dx)) 1))
217 (round (+ (frame-ry parent) (truncate (* (truncate (/ pos n)) dy)) 1))
218 (round (- dx 2))
219 (round (- dy 2)))))
221 (defun set-tile-layout ()
222 "Tile child in its frame (vertical)"
223 (set-layout-managed-children)
224 (set-layout #'tile-layout))
228 ;; Horizontal tiling layout
229 (defgeneric tile-horizontal-layout (child parent)
230 (:documentation "Tile child in its frame (horizontal)"))
232 (defmethod tile-horizontal-layout (child parent)
233 (let* ((managed-children (update-layout-managed-children child parent))
234 (pos (position child managed-children))
235 (len (length managed-children))
236 (n (ceiling (sqrt len)))
237 (dx (/ (frame-rw parent) (ceiling (/ len n))))
238 (dy (/ (frame-rh parent) n)))
239 (values (round (+ (frame-rx parent) (truncate (* (truncate (/ pos n)) dx)) 1))
240 (round (+ (frame-ry parent) (truncate (* (mod pos n) dy)) 1))
241 (round (- dx 2))
242 (round (- dy 2)))))
244 (defun set-tile-horizontal-layout ()
245 "Tile child in its frame (horizontal)"
246 (set-layout-managed-children)
247 (set-layout #'tile-horizontal-layout))
251 ;; One column layout
252 (defgeneric one-column-layout (child parent)
253 (:documentation "One column layout"))
255 (defmethod one-column-layout (child parent)
256 (let* ((managed-children (update-layout-managed-children child parent))
257 (pos (position child managed-children))
258 (len (length managed-children))
259 (dy (/ (frame-rh parent) len)))
260 (values (round (+ (frame-rx parent) 1))
261 (round (+ (frame-ry parent) (* pos dy) 1))
262 (round (- (frame-rw parent) 2))
263 (round (- dy 2)))))
265 (defun set-one-column-layout ()
266 "One column layout"
267 (set-layout-managed-children)
268 (set-layout #'one-column-layout))
271 ;; One line layout
272 (defgeneric one-line-layout (child parent)
273 (:documentation "One line layout"))
275 (defmethod one-line-layout (child parent)
276 (let* ((managed-children (update-layout-managed-children child parent))
277 (pos (position child managed-children))
278 (len (length managed-children))
279 (dx (/ (frame-rw parent) len)))
280 (values (round (+ (frame-rx parent) (* pos dx) 1))
281 (round (+ (frame-ry parent) 1))
282 (round (- dx 2))
283 (round (- (frame-rh parent) 2)))))
285 (defun set-one-line-layout ()
286 "One line layout"
287 (set-layout-managed-children)
288 (set-layout #'one-line-layout))
294 ;;; Space layout
295 (defun tile-space-layout (child parent)
296 "Tile Space: tile child in its frame leaving spaces between them"
297 (with-slots (rx ry rw rh) parent
298 (let* ((managed-children (get-managed-child parent))
299 (pos (position child managed-children))
300 (len (length managed-children))
301 (n (ceiling (sqrt len)))
302 (dx (/ rw n))
303 (dy (/ rh (ceiling (/ len n))))
304 (size (or (frame-data-slot parent :tile-space-size) 0.1)))
305 (when (> size 0.5) (setf size 0.45))
306 (values (round (+ rx (truncate (* (mod pos n) dx)) (* dx size) 1))
307 (round (+ ry (truncate (* (truncate (/ pos n)) dy)) (* dy size) 1))
308 (round (- dx (* dx size 2) 2))
309 (round (- dy (* dy size 2) 2))))))
314 (defun set-tile-space-layout ()
315 "Tile Space: tile child in its frame leaving spaces between them"
316 (layout-ask-size "Space size in percent (%)" :tile-space-size 0.01)
317 (set-layout #'tile-space-layout))
321 (register-layout-sub-menu 'frame-tile-layout-menu "Frame tile layout menu"
322 '(("v" set-tile-layout)
323 ("h" set-tile-horizontal-layout)
324 ("c" set-one-column-layout)
325 ("l" set-one-line-layout)
326 ("s" set-tile-space-layout)))
330 ;;; Tile Left
331 (defun tile-left-layout (child parent)
332 "Tile Left: main child on left and others on right"
333 (with-slots (rx ry rw rh) parent
334 (let* ((managed-children (get-managed-child parent))
335 (pos (position child managed-children))
336 (len (max (1- (length managed-children)) 1))
337 (dy (/ rh len))
338 (size (or (frame-data-slot parent :tile-size) 0.8)))
339 (if (> (length managed-children) 1)
340 (if (= pos 0)
341 (values (1+ rx)
342 (1+ ry)
343 (- (round (* rw size)) 2)
344 (- rh 2))
345 (values (1+ (round (+ rx (* rw size))))
346 (1+ (round (+ ry (* dy (1- pos)))))
347 (- (round (* rw (- 1 size))) 2)
348 (- (round dy) 2)))
349 (no-layout child parent)))))
352 (defun set-tile-left-layout ()
353 "Tile Left: main child on left and others on right"
354 (layout-ask-size "Tile size in percent (%)" :tile-size)
355 (set-layout #'tile-left-layout))
359 ;;; Tile right
360 (defun tile-right-layout (child parent)
361 "Tile Right: main child on right and others on left"
362 (with-slots (rx ry rw rh) parent
363 (let* ((managed-children (get-managed-child parent))
364 (pos (position child managed-children))
365 (len (max (1- (length managed-children)) 1))
366 (dy (/ rh len))
367 (size (or (frame-data-slot parent :tile-size) 0.8)))
368 (if (> (length managed-children) 1)
369 (if (= pos 0)
370 (values (1+ (round (+ rx (* rw (- 1 size)))))
371 (1+ ry)
372 (- (round (* rw size)) 2)
373 (- rh 2))
374 (values (1+ rx)
375 (1+ (round (+ ry (* dy (1- pos)))))
376 (- (round (* rw (- 1 size))) 2)
377 (- (round dy) 2)))
378 (no-layout child parent)))))
381 (defun set-tile-right-layout ()
382 "Tile Right: main child on right and others on left"
383 (layout-ask-size "Tile size in percent (%)" :tile-size)
384 (set-layout #'tile-right-layout))
391 ;;; Tile Top
392 (defun tile-top-layout (child parent)
393 "Tile Top: main child on top and others on bottom"
394 (with-slots (rx ry rw rh) parent
395 (let* ((managed-children (get-managed-child parent))
396 (pos (position child managed-children))
397 (len (max (1- (length managed-children)) 1))
398 (dx (/ rw len))
399 (size (or (frame-data-slot parent :tile-size) 0.8)))
400 (if (> (length managed-children) 1)
401 (if (= pos 0)
402 (values (1+ rx)
403 (1+ ry)
404 (- rw 2)
405 (- (round (* rh size)) 2))
406 (values (1+ (round (+ rx (* dx (1- pos)))))
407 (1+ (round (+ ry (* rh size))))
408 (- (round dx) 2)
409 (- (round (* rh (- 1 size))) 2)))
410 (no-layout child parent)))))
413 (defun set-tile-top-layout ()
414 "Tile Top: main child on top and others on bottom"
415 (layout-ask-size "Tile size in percent (%)" :tile-size)
416 (set-layout #'tile-top-layout))
421 ;;; Tile Bottom
422 (defun tile-bottom-layout (child parent)
423 "Tile Bottom: main child on bottom and others on top"
424 (with-slots (rx ry rw rh) parent
425 (let* ((managed-children (get-managed-child parent))
426 (pos (position child managed-children))
427 (len (max (1- (length managed-children)) 1))
428 (dx (/ rw len))
429 (size (or (frame-data-slot parent :tile-size) 0.8)))
430 (if (> (length managed-children) 1)
431 (if (= pos 0)
432 (values (1+ rx)
433 (1+ (round (+ ry (* rh (- 1 size)))))
434 (- rw 2)
435 (- (round (* rh size)) 2))
436 (values (1+ (round (+ rx (* dx (1- pos)))))
437 (1+ ry)
438 (- (round dx) 2)
439 (- (round (* rh (- 1 size))) 2)))
440 (no-layout child parent)))))
444 (defun set-tile-bottom-layout ()
445 "Tile Bottom: main child on bottom and others on top"
446 (layout-ask-size "Tile size in percent (%)" :tile-size)
447 (set-layout #'tile-bottom-layout))
450 (register-layout-sub-menu 'frame-tile-dir-layout-menu "Tile in one direction layout menu"
451 '(("l" set-tile-left-layout)
452 ("r" set-tile-right-layout)
453 ("t" set-tile-top-layout)
454 ("b" set-tile-bottom-layout)))
461 ;;; Left and space layout: like left layout but leave a space on the left
462 (defun layout-ask-space (msg slot &optional (default 100))
463 (when (frame-p *current-child*)
464 (let ((new-space (or (query-number msg (or (frame-data-slot *current-child* slot) default)) default)))
465 (setf (frame-data-slot *current-child* slot) new-space))))
468 (defun tile-left-space-layout (child parent)
469 "Tile Left Space: main child on left and others on right. Leave some space on the left."
470 (with-slots (rx ry rw rh) parent
471 (let* ((managed-children (get-managed-child parent))
472 (pos (position child managed-children))
473 (len (max (1- (length managed-children)) 1))
474 (dy (/ rh len))
475 (size (or (frame-data-slot parent :tile-size) 0.8))
476 (space (or (frame-data-slot parent :tile-left-space) 100)))
477 (if (> (length managed-children) 1)
478 (if (= pos 0)
479 (values (+ rx space 1)
480 (1+ ry)
481 (- (round (* rw size)) 2 space)
482 (- rh 2))
483 (values (1+ (round (+ rx (* rw size))))
484 (1+ (round (+ ry (* dy (1- pos)))))
485 (- (round (* rw (- 1 size))) 2)
486 (- (round dy) 2)))
487 (multiple-value-bind (rnx rny rnw rnh)
488 (no-layout child parent)
489 (values (+ rnx space)
491 (- rnw space)
492 rnh))))))
495 (defun set-tile-left-space-layout ()
496 "Tile Left Space: main child on left and others on right. Leave some space on the left."
497 (layout-ask-size "Tile size in percent (%)" :tile-size)
498 (layout-ask-space "Tile space" :tile-left-space)
499 (set-layout #'tile-left-space-layout))
501 (register-layout-sub-menu 'frame-tile-space-layout-menu "Tile with some space on one side menu"
502 '(set-tile-left-space-layout))
507 ;;; Main windows layout - A possible GIMP layout
508 ;;; The windows in the main list are tiled on the frame
509 ;;; others windows are on one side of the frame.
510 (defun main-window-right-layout (child parent)
511 "Main window right: Main windows on the right. Others on the left."
512 (with-slots (rx ry rw rh) parent
513 (let* ((main-windows (frame-data-slot parent :main-window-list))
514 (len (length main-windows))
515 (size (or (frame-data-slot parent :tile-size) 0.8)))
516 (if (zerop len)
517 (no-layout child parent)
518 (if (member child main-windows)
519 (let* ((dy (/ rh len))
520 (pos (position child main-windows)))
521 (values (1+ (round (+ rx (* rw (- 1 size)))))
522 (1+ (round (+ ry (* dy pos))))
523 (- (round (* rw size)) 2)
524 (- (round dy) 2)))
525 (values (1+ rx)
526 (1+ ry)
527 (- (round (* rw (- 1 size))) 2)
528 (- rh 2)))))))
530 (defun set-main-window-right-layout ()
531 "Main window right: Main windows on the right. Others on the left."
532 (layout-ask-size "Split size in percent (%)" :tile-size)
533 (set-layout #'main-window-right-layout))
538 (defun main-window-left-layout (child parent)
539 "Main window left: Main windows on the left. Others on the right."
540 (with-slots (rx ry rw rh) parent
541 (let* ((main-windows (frame-data-slot parent :main-window-list))
542 (len (length main-windows))
543 (size (or (frame-data-slot parent :tile-size) 0.8)))
544 (if (zerop len)
545 (no-layout child parent)
546 (if (member child main-windows)
547 (let* ((dy (/ rh len))
548 (pos (position child main-windows)))
549 (values (1+ rx)
550 (1+ (round (+ ry (* dy pos))))
551 (- (round (* rw size)) 2)
552 (- (round dy) 2)))
553 (values (1+ (round (+ rx (* rw size))))
554 (1+ ry)
555 (- (round (* rw (- 1 size))) 2)
556 (- rh 2)))))))
558 (defun set-main-window-left-layout ()
559 "Main window left: Main windows on the left. Others on the right."
560 (layout-ask-size "Split size in percent (%)" :tile-size)
561 (set-layout #'main-window-left-layout))
565 (defun main-window-top-layout (child parent)
566 "Main window top: Main windows on the top. Others on the bottom."
567 (with-slots (rx ry rw rh) parent
568 (let* ((main-windows (frame-data-slot parent :main-window-list))
569 (len (length main-windows))
570 (size (or (frame-data-slot parent :tile-size) 0.8)))
571 (if (zerop len)
572 (no-layout child parent)
573 (if (member child main-windows)
574 (let* ((dx (/ rw len))
575 (pos (position child main-windows)))
576 (values (1+ (round (+ rx (* dx pos))))
577 (1+ ry)
578 (- (round dx) 2)
579 (- (round (* rh size)) 2)))
580 (values (1+ rx)
581 (1+ (round (+ ry (* rh size))))
582 (- rw 2)
583 (- (round (* rh (- 1 size))) 2)))))))
585 (defun set-main-window-top-layout ()
586 "Main window top: Main windows on the top. Others on the bottom."
587 (layout-ask-size "Split size in percent (%)" :tile-size)
588 (set-layout #'main-window-top-layout))
592 (defun main-window-bottom-layout (child parent)
593 "Main window bottom: Main windows on the bottom. Others on the top."
594 (with-slots (rx ry rw rh) parent
595 (let* ((main-windows (frame-data-slot parent :main-window-list))
596 (len (length main-windows))
597 (size (or (frame-data-slot parent :tile-size) 0.8)))
598 (if (zerop len)
599 (no-layout child parent)
600 (if (member child main-windows)
601 (let* ((dx (/ rw len))
602 (pos (position child main-windows)))
603 (values (1+ (round (+ rx (* dx pos))))
604 (1+ (round (+ ry (* rh (- 1 size)))))
605 (- (round dx) 2)
606 (- (round (* rh size)) 2)))
607 (values (1+ rx)
608 (1+ ry)
609 (- rw 2)
610 (- (round (* rh (- 1 size))) 2)))))))
612 (defun set-main-window-bottom-layout ()
613 "Main window bottom: Main windows on the bottom. Others on the top."
614 (layout-ask-size "Split size in percent (%)" :tile-size)
615 (set-layout #'main-window-bottom-layout))
621 (defun add-in-main-window-list ()
622 "Add the current window in the main window list"
623 (when (frame-p *current-child*)
624 (with-current-window
625 (when (member window (get-managed-child *current-child*))
626 (pushnew window (frame-data-slot *current-child* :main-window-list)))))
627 (leave-second-mode))
630 (defun remove-in-main-window-list ()
631 "Remove the current window from the main window list"
632 (when (frame-p *current-child*)
633 (with-current-window
634 (when (member window (get-managed-child *current-child*))
635 (setf (frame-data-slot *current-child* :main-window-list)
636 (remove window (frame-data-slot *current-child* :main-window-list))))))
637 (leave-second-mode))
639 (defun clear-main-window-list ()
640 "Clear the main window list"
641 (when (frame-p *current-child*)
642 (setf (frame-data-slot *current-child* :main-window-list) nil))
643 (leave-second-mode))
648 (register-layout-sub-menu 'frame-main-window-layout-menu "Main window layout menu"
649 '(("r" set-main-window-right-layout)
650 ("l" set-main-window-left-layout)
651 ("t" set-main-window-top-layout)
652 ("b" set-main-window-bottom-layout)
653 "-=- Actions on main windows list -=-"
654 ("a" add-in-main-window-list)
655 ("v" remove-in-main-window-list)
656 ("c" clear-main-window-list)))
660 (defun select-next/previous-child-no-main-window (fun-rotate)
661 "Select the next/previous child - Skip windows in main window list"
662 (when (frame-p *current-child*)
663 (with-slots (child) *current-child*
664 (let* ((main-windows (frame-data-slot *current-child* :main-window-list))
665 (to-skip? (not (= (length main-windows)
666 (length child)))))
667 (labels ((rec ()
668 (setf child (funcall fun-rotate child))
669 (when (and to-skip?
670 (member (frame-selected-child *current-child*) main-windows))
671 (rec))))
672 (unselect-all-frames)
673 (rec)
674 (show-all-children))))))
677 (defun select-next-child-no-main-window ()
678 "Select the next child - Skip windows in main window list"
679 (select-next/previous-child-no-main-window #'rotate-list))
681 (defun select-previous-child-no-main-window ()
682 "Select the previous child - Skip windows in main window list"
683 (select-next/previous-child-no-main-window #'anti-rotate-list))
686 (defun mouse-click-to-focus-and-move-no-main-window (window root-x root-y)
687 "Move and focus the current frame or focus the current window parent.
688 Or do actions on corners - Skip windows in main window list"
689 (unless (do-corner-action root-x root-y *corner-main-mode-left-button*)
690 (if (and (frame-p *current-child*)
691 (member window (frame-data-slot *current-child* :main-window-list)))
692 (replay-button-event)
693 (mouse-click-to-focus-generic window root-x root-y #'move-frame))))
697 (defun set-gimp-layout ()
698 "The GIMP Layout"
699 (when (frame-p *current-child*)
700 ;; Note: There is no need to ungrab/grab keys because this
701 ;; is done when leaving the second mode.
702 (define-main-key ("F8" :mod-1) 'add-in-main-window-list)
703 (define-main-key ("F9" :mod-1) 'remove-in-main-window-list)
704 (define-main-key ("F10" :mod-1) 'clear-main-window-list)
705 (define-main-key ("Tab" :mod-1) 'select-next-child-no-main-window)
706 (define-main-key ("Tab" :mod-1 :shift) 'select-previous-child-no-main-window)
707 (define-main-mouse (1) 'mouse-click-to-focus-and-move-no-main-window)
708 (setf (frame-data-slot *current-child* :focus-policy-save)
709 (frame-focus-policy *current-child*))
710 (setf (frame-focus-policy *current-child*) :sloppy)
711 (setf (frame-data-slot *current-child* :layout-save)
712 (frame-layout *current-child*))
713 ;; Set the default layout and leave the second mode.
714 (set-main-window-right-layout)))
717 (defun set-previous-layout ()
718 "Restore the previous layout"
719 (undefine-main-key ("F8" :mod-1))
720 (undefine-main-key ("F9" :mod-1))
721 (undefine-main-key ("F10" :mod-1))
722 (define-main-key ("Tab" :mod-1) 'select-next-child)
723 (define-main-key ("Tab" :mod-1 :shift) 'select-previous-child)
724 (define-main-mouse (1) 'mouse-click-to-focus-and-move)
725 (setf (frame-focus-policy *current-child*)
726 (frame-data-slot *current-child* :focus-policy-save))
727 (setf (frame-layout *current-child*)
728 (frame-data-slot *current-child* :layout-save))
729 (leave-second-mode))
732 (defun help-on-gimp-layout ()
733 "Help on the GIMP layout"
734 (info-mode `(("-=- Help on The GIMP layout -=-" ,*info-color-title*)
736 "The GIMP layout is a main-window-layout with a sloppy focus policy."
737 "You can change the main windows direction with the layout menu."
739 "Press Alt+F8 to add a window to the main windows list."
740 "Press Alt+F9 to remove a window from the main windows list."
741 "Press Alt+F10 to clear the main windows list."
743 "You can select a main window with the right mouse button."
745 "Use the layout menu to restore the previous layout and keybinding."))
746 (leave-second-mode))
749 (register-layout-sub-menu 'frame-gimp-layout-menu "The GIMP layout menu"
750 '(("g" set-gimp-layout)
751 ("p" set-previous-layout)
752 ("h" help-on-gimp-layout)
753 "-=- Main window layout -=-"
754 ("r" set-main-window-right-layout)
755 ("l" set-main-window-left-layout)
756 ("t" set-main-window-top-layout)
757 ("b" set-main-window-bottom-layout)
758 "-=- Actions on main windows list -=-"
759 ("a" add-in-main-window-list)
760 ("v" remove-in-main-window-list)
761 ("c" clear-main-window-list)))