1 ;;; xwem-frame.el -- Frames ops for XWEM.
3 ;; Copyright (C) 2003-2005 by XWEM Org.
5 ;; Author: Zajcev Evgeny <zevlg@yandex.ru>
6 ;; Steve Youngs <steve@youngs.au.com>
7 ;; Created: 21 Mar 2003
8 ;; Keywords: xlib, xwem
9 ;; X-CVS: $Id: xwem-frame.el,v 1.15 2005-04-04 19:54:11 lg Exp $
11 ;; This file is part of XWEM.
13 ;; XWEM is free software; you can redistribute it and/or modify it
14 ;; under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
21 ;; License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING. If not, write to the Free
25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 ;;; Synched up with: Not in FSF
32 ;; This file contain operations on XWEM frames.
38 (require 'xlib-xinerama)
44 (defgroup xwem-frame nil
45 "Group to customize xwem frames."
50 (defcustom xwem-frame-background "gray60"
51 "*Frame background color."
55 (defcustom xwem-frame-cursor-shape '(X-XC-top_left_arrow)
56 "*Cursors shape which will be used when pointer is over xwem frame."
57 :type (xwem-cursor-shape-choice)
58 :set (xwem-cus-set-cursor-shape xwem-frame-cursor
59 (mapcar 'xwem-frame-xwin (xwem-frames-list)))
60 :initialize 'custom-initialize-default
63 (defcustom xwem-frame-cursor-foreground-color "#111111"
64 "*Cursor's foreground color used when pointer is on xwem's frame."
66 :set (xwem-cus-set-cursor-foreground xwem-frame-cursor)
67 :initialize 'custom-initialize-default
70 (defcustom xwem-frame-cursor-background-color "#EEEEEE"
71 "*Cursor's background color used when pointer is on xwem's frame."
73 :set (xwem-cus-set-cursor-background xwem-frame-cursor)
74 :initialize 'custom-initialize-default
77 (defconst xwem-frame-builtin-properties
78 '(inner-border-width outer-border-width title-height title-thickness)
79 "List of valid builtin frame properties.")
82 (defcustom xwem-frame-default-properties
83 (list 'inner-border-width 3 ; Internal border of xwem's frame
84 'inner-border-thickness 1 ; Internal border thickness
85 'outer-border-width 0 ; X border
86 'background "gray60" ; background color
88 "*Default properties list for xwem frames."
89 :type '(restricted-sexp :match-alternatives (valid-plist-p))
93 (defcustom xwem-embedded-frame-default-properties
94 (list 'inner-border-width 0
95 'inner-border-thickness 0
96 'outer-border-width 0)
97 "*Default properties for embedded xwem frames.
98 Values in `xwem-embedded-frame-default-properties' overrides values in
99 `xwem-frame-default-properties'."
100 :type '(restricted-sexp :match-alternatives (valid-plist-p))
104 (defcustom xwem-dedicated-frame-defalut-properties
105 (list 'inner-border-width 2
106 'inner-border-thickness 1
107 'outer-border-width 0)
108 "*Default properties for dedicated xwem frames.
109 Values in `xwem-dedicated-frame-defalut-properties' overrides values in
110 `xwem-frame-default-properties'."
111 :type '(restricted-sexp :match-alternatives (valid-plist-p))
114 (defcustom xwem-frame-on-delim-resize-mode 'normal
115 "*Mode to outline current window when doing `xwem-frame-on-delim-resize'."
116 :type '(choice (const :tag "Normal border" normal)
117 (const :tag "Opaque" opaque)
121 (defcustom xwem-frame-iresize-mode 'normal
122 "*Default type of drawing outlines when resizing frame interactively.
123 Opaque mode can do unexpected things, such as eat your food from
124 refrigerator, so set it to Opaque on your own risk."
125 :type '(choice (const :tag "Normal border" normal)
126 (const :tag "Contiguous borders" contiguous)
127 (const :tag "Outline Corners" corners)
128 (const :tag "Grid" grid)
129 (const :tag "Opaque" opaque)
133 (defcustom xwem-frame-imove-mode 'normal
134 "*Default type of drawing outlines when moving frame interactively."
135 :type '(choice (const :tag "Normal border" normal)
136 (const :tag "Contiguous border" contiguous)
137 (const :tag "Outline Corners" corners)
138 (const :tag "Grid" grid)
139 (const :tag "Opaque" opaque)
143 (defcustom xwem-frame-imoveresize-mode-function
144 'xwem-frame-imoveresize-mode-function-default
145 "Function to call in way to select move or resize mode.
146 It is passed with two arguments - FRAME and WHAT.
147 Where FRAME is frame which is about to move/resize and WHAT is one of
149 It should return one of:
150 'normal - Normal resize/move mode, just outline frame rectangle.
151 'contiguous - Butified 'normal mode.
152 'corners - Outline frame corners.
153 'grid - Outline frame and draw grid inside.
154 'opaque - Opaque move/resize mode."
158 (defcustom xwem-frame-imoveresize-use-minibuffer t
159 "*If non-nil, frame's geometry will be show while imove/iresize."
163 (defun xwem-frame-imoveresize-mode-function-default (frame what)
164 "Default value of `xwem-frame-imoveresize-mode-function'.
165 Return `xwem-frame-iresize-mode' if WHAT is 'resize.
166 Return `xwem-frame-imove-mode' if WHAT is 'move."
167 (if (eq what 'resize)
168 xwem-frame-iresize-mode
169 xwem-frame-imove-mode))
171 (defcustom xwem-frame-rolling-switch t
172 "*Non-nil mean that \\<xwem-global-map>\\[xwem-frame-next] and
173 \\<xwem-global-map>\\[xwem-frame-previous] will always switch, even if
174 there no next or previous frame."
178 (defcustom xwem-frame-autoiconify-mode nil
179 "Non-nil mean frame possible automatically iconifies when switching.
180 If switching from OFR to NFR frame values mean next:
181 nil - No frame will be iconified.
182 intersect - OFR will be iconified if it intersects with NFR.
183 always - OFR always iconfied."
184 :type '(choice (const :tag "Disabled" nil)
185 (conts :tag "Intersect" intersect)
186 (const :tag "Always" always))
189 (defcustom xwem-frame-autoselect-embedded t
190 "*Non-nil mean if embedded frame selected as client, also select frame."
194 (defcustom xwem-frame-keep-number nil
195 "*Non-nil mean frames keeps their numbers when intermediate frame destroyed."
200 (defcustom xwem-frame-select-hook nil
201 "*Hooks to call when new frame just selected."
205 (defcustom xwem-frame-deselect-hook nil
206 "*Hooks to call when selected frame is about to be deselected."
210 (defcustom xwem-frame-creation-hook nil
211 "Hooks called with one argument - frame, when frame just created."
215 (defcustom xwem-frame-change-hook nil
216 "Hooks called with one argument - frame, when frame changed."
220 (defcustom xwem-frame-destroy-hook nil
221 "Hooks called with one argument - frame, when frame destroyed."
225 (defcustom xwem-frame-resize-hook nil
226 "Hooks called with one argument - frame, when frame resized."
230 (defcustom xwem-frame-move-hook nil
231 "Hooks called with one argument - frame, when frame moved."
235 (defcustom xwem-frame-redraw-hook nil
236 "Hooks called with one argument - frame, when frame redrawed."
240 (defcustom xwem-frame-configuration-exporting t
241 "*Non-nil mean, frame configuration exports after each frame command.
242 Non-nil value is useful when using xwem-agent. It allows you restore
243 frames on (S)XEmacs restart."
247 ;;; Internal variables
249 (defconst xwem-frame-ev-mask
250 (Xmask-or XM-Exposure
252 XM-SubstructureRedirect
253 XM-SubstructureNotify
254 XM-KeyPress XM-ButtonPress XM-ButtonRelease
256 "Events mask for xwem's frame.")
258 (defvar xwem-frame-cursor nil
259 "Cursor used for xwem frame.")
261 (defvar xwem-frame-types
262 '(desktop embedded embedded-desktop dedicated)
263 "List of xwem frame types.")
266 (defvar xwem-frames-list nil
267 "List of all xwem frames.")
269 (defvar xwem-frame-noredisplay nil
270 "If this non-nil than frame it reffers should not be redisplayed.
271 Internal variable, do not use.")
273 (defvar xwem-frame-dumped-config nil)
277 (defun xwem-frames-list (&optional type)
278 "Return list of xwem frames of TYPE.
279 If TYPE is ommited - list of frames of any type is returned."
280 (remove* nil xwem-frames-list
281 :test #'(lambda (f1 f2)
282 (not (and (xwem-frame-p f2)
283 (not (eq (xwem-frame-state f2) 'destroyed))
285 (eq (xwem-frame-type f2) type)))))))
288 (defmacro xwem-frame-link-insert-after (frame1 frame2)
289 "Make FRAME2 to be after FRAME1."
290 `(let ((nf (xwem-frame-link-next ,frame1)))
291 (when (xwem-frame-p nf)
292 (setf (xwem-frame-link-prev nf) ,frame2))
293 (setf (xwem-frame-link-next ,frame1) ,frame2)
294 (setf (xwem-frame-link-prev ,frame2) ,frame1)
295 (setf (xwem-frame-link-next ,frame2) nf)))
297 (defmacro xwem-frame-link-insert-before (frame1 frame2)
298 "Make FRAME2 to be before FRAME1."
299 `(let ((pf (xwem-frame-link-prev ,frame1)))
300 (when (xwem-frame-p pf)
301 (setf (xwem-frame-link-next pf) ,frame2))
302 (setf (xwem-frame-link-prev ,frame1) ,frame2)
303 (setf (xwem-frame-link-next ,frame2) ,frame1)
304 (setf (xwem-frame-link-prev ,frame2) pf)))
306 (defmacro xwem-frame-link-remove (frame)
307 "Remove FRAME from linkage."
308 `(let ((nfr (xwem-frame-link-next ,frame))
309 (pfr (xwem-frame-link-prev ,frame)))
310 (when (xwem-frame-p pfr)
311 (setf (xwem-frame-link-next pfr) nfr))
312 (when (xwem-frame-p nfr)
313 (setf (xwem-frame-link-prev nfr) pfr))))
315 (defmacro xwem-frame-link-head (frame)
316 "Returns head frame of FRAME's linkage."
318 (while (xwem-frame-p (xwem-frame-link-prev fr))
319 (setq fr (xwem-frame-link-prev fr)))
322 (defmacro xwem-frame-linkage-map (frame fn)
323 "Call FN for each frame in FRAME's linkage.
324 FN called with one argument - frame."
325 ;; TODO: avoid infinit recursion
326 `(let ((fr (xwem-frame-link-head ,frame)))
328 (while (xwem-frame-p fr)
330 (setq fr (xwem-frame-link-next fr)))))
333 (defmacro xwem-frame-XProperty-get (frame prop-atom-string)
334 `(xwem-XProperty-get (xwem-frame-xwin ,frame) ,prop-atom-string))
335 (defmacro xwem-frame-XProperty-set (frame prop-atom-string prop-val)
336 `(xwem-XProperty-set (xwem-frame-xwin ,frame) ,prop-atom-string ,prop-val))
338 (define-xwem-deffered xwem-frame-export-frame-configuration ()
339 "Export frame configuration to root window.
341 Profiling results on 9 frames with 32 windows:
342 Function Name Call Count Elapsed Time Average Time
343 ===================================== ========== ============ ============
344 xwem-frame-export-frame-configuration 50 0.016508 0.00033016
346 (xwem-XProperty-set (xwem-rootwin) "XWEM_FRAME_CONFIGURATION"
348 (xwem-frame-config-dump1 (xwem-frame-configuration)
350 (read (buffer-substring (point-min) (point-max))))))
352 (defun xwem-frame-frame-command-post-hook ()
353 "Function to use in `xwem-post-command-hook'.
354 It exports frame configuration after each xwem command."
355 (when xwem-frame-configuration-exporting
356 (xwem-frame-export-frame-configuration)))
358 (defun xwem-frame-import-frame-configuration ()
359 "Import frame configuration fram root window."
360 (eval (xwem-XProperty-get (xwem-rootwin) "XWEM_FRAME_CONFIGURATION")))
363 (define-xwem-deffered xwem-frame-apply-state (frame)
364 "Apply FRAME's state to life."
365 (cond ((eq (xwem-frame-state frame) 'mapped)
366 (XMapWindow (xwem-dpy) (xwem-frame-xwin frame)))
367 ((eq (xwem-frame-state frame) 'unmapped)
368 (XUnmapWindow (xwem-dpy) (xwem-frame-xwin frame)))))
370 (defun xwem-frame-unmap (frame)
372 (setf (xwem-frame-state frame) 'unmapped)
373 (xwem-frame-apply-state frame))
376 (defun xwem-frame-map (frame)
378 (setf (xwem-frame-state frame) 'mapped)
379 (xwem-frame-apply-state frame))
381 (define-xwem-deffered xwem-frame-apply-raise-lower (frame)
382 "Apply FRAME's raise/lower state to life."
383 (let ((rl (xwem-frame-get-prop frame 'raise-lower-state)))
384 (cond ((eq rl 'raise)
385 (xwem-misc-raise-xwin (xwem-frame-xwin frame)))
387 (xwem-misc-lower-xwin (xwem-frame-xwin frame))))))
389 ;;;###autoload(autoload 'xwem-frame-lower "xwem-frame" "" t)
390 (define-xwem-command xwem-frame-lower (frame)
391 "Lower FRAME's window."
392 (xwem-interactive (list (xwem-frame-selected)))
394 (xwem-frame-put-prop frame 'raise-lower-state 'lower)
395 (xwem-frame-apply-raise-lower frame))
396 (put 'xwem-frame-lower 'xwem-frame-command t)
398 ;;;###autoload(autoload 'xwem-frame-raise "xwem-frame" "" t)
399 (define-xwem-command xwem-frame-raise (frame)
400 "Raise FRAME's window."
401 (xwem-interactive (list (xwem-frame-selected)))
403 (xwem-frame-map frame) ; make sure frame is mapped
404 (xwem-frame-put-prop frame 'raise-lower-state 'raise)
405 (xwem-frame-apply-raise-lower frame))
406 (put 'xwem-frame-raise 'xwem-frame-command t)
408 (defun xwem-frame-embedded-for-frame (frame)
409 "Return XWEM frame for which FRAME is embedded."
410 (let* ((cl (and (xwem-frame-p frame)
411 (xwem-frame-get-prop frame 'xwem-embedded-cl)))
412 (rv (and (xwem-cl-p cl)
413 (xwem-cl-frame cl))))
416 (defun xwem-frame-unembedd (frame &optional new-type)
418 (when (xwem-frame-embedded-p frame)
419 (let* ((cl (xwem-frame-get-prop frame 'xwem-embedded-cl))
420 (tpnt (car (XTranslateCoordinates
421 (xwem-dpy) (xwem-frame-xwin frame)
422 (xwem-rootwin) (xwem-frame-x frame)
423 (xwem-frame-y frame)))))
424 ;; Remove clients stuff
427 ;; Unmark FRAME as embedded
428 (xwem-cl-rem-prop cl 'xwem-embedded-frame)
429 (xwem-frame-rem-prop frame 'xwem-embedded-cl)
431 ;; Set new frame TYPE
432 (setf (xwem-frame-type frame) (or new-type 'desktop))
434 (XReparentWindow (xwem-dpy) (xwem-frame-xwin frame) (xwem-rootwin)
435 (X-Point-x tpnt) (X-Point-y tpnt))
436 (xwem-frame-set-pos frame (X-Point-x tpnt) (X-Point-y tpnt))
437 (xwem-frame-apply-state frame))))
440 (defun xwem-select-frame (frame)
441 "Set FRAME to be selected frame.
442 Actually all the work done in `xwem-select-window'."
443 (or (xwem-frame-alive-p frame)
444 (error 'xwem-error "Selecting dead frame"))
445 (xwem-select-window (xwem-frame-selwin frame)))
447 (defun xwem-frame-autoiconify-on-deselect ()
448 "Maybe iconify FRAME, when deselecting FRAME."
449 (when (eq xwem-frame-autoiconify-mode 'always)
450 ;; NOTE: double deffering
451 (xwem-deffered-funcall
453 (when (xwem-frame-p frame)
454 (xwem-frame-unmap frame)))
455 (xwem-frame-selected))))
457 (defun xwem-frame-autoiconify-on-select ()
458 "Maybe iconify some frames when selecting FRAME."
459 (when (and (eq xwem-frame-autoiconify-mode 'intersect)
460 (xwem-frame-desktop-p (xwem-frame-selected)))
461 (let ((nfr-rect (X-Geom-to-X-Rect
462 (xwem-frame-xgeom (xwem-frame-selected))))
463 (frames (xwem-frames-list 'desktop)))
465 (when (and (not (eq (xwem-frame-selected) (car frames)))
466 (xwem-frame-mapped-p (car frames))
468 nfr-rect (X-Geom-to-X-Rect
469 (xwem-frame-xgeom (car frames)))))
470 ;; NOTE: double deffering
471 (xwem-deffered-funcall
473 (when (xwem-frame-p frame)
474 (xwem-frame-unmap frame)))
476 (setq frames (cdr frames))))))
478 ;;;###xwem-autoload(autoload 'xwem-make-frame-1 "xwem-frame")
479 (defun* xwem-make-frame-1 (type &key params props noselect)
480 "Create new frame with optional frame properties PROPS.
481 If EMBEDDED-p is non-nil than create embedded frame.
482 If NOSELECT is non-nil then do not select newly created frame to be
484 (let* ((fplist (copy-list xwem-frame-default-properties))
485 (frame (apply 'make-xwem-frame params))
488 (setf (xwem-frame-type frame) type)
489 (setf (xwem-frame-state frame) 'unmapped)
491 ;;; Initialise FRAME's geometry
492 (unless (xwem-frame-xgeom frame)
493 (setf (xwem-frame-xgeom frame) (make-X-Geom)))
495 (unless (xwem-frame-x frame)
496 (setf (xwem-frame-x frame) 0))
497 (unless (xwem-frame-y frame)
498 (setf (xwem-frame-y frame) 0))
499 (unless (xwem-frame-width frame)
500 (setf (xwem-frame-width frame) (X-Geom-width (xwem-rootgeom))))
501 (unless (xwem-frame-height frame)
502 (setf (xwem-frame-height frame)
503 (- (X-Geom-height (xwem-rootgeom))
504 (if (X-Geom-p (xwem-minib-xgeom xwem-minibuffer))
505 (X-Geom-height (xwem-minib-xgeom xwem-minibuffer))
508 ;;; Initialize FRAME's X window
509 (setq fwin (XCreateWindow
513 (xwem-frame-width frame)
514 (xwem-frame-height frame)
519 (make-X-Attr :override-redirect
520 (not (xwem-frame-embedded-p frame))
523 (unless (xwem-frame-embedded-p frame)
525 :cursor xwem-frame-cursor
526 :event-mask xwem-frame-ev-mask)))
527 (X-Win-put-prop fwin 'xwem-frame frame)
528 (setf (xwem-frame-xwin frame) fwin)
530 ;; Install events handlers
531 (X-Win-EventHandler-add-new
532 fwin 'xwem-frame-events-handler 150)
533 (X-Win-EventHandler-add-new
534 fwin 'xwem-ev-reconfig 40 (list X-ConfigureRequest))
536 ;; XXX Setup WM_XXX stuff
537 (XSetWMProtocols (xwem-dpy) fwin
538 (list (X-Atom-find-by-name (xwem-dpy) "WM_DELETE_WINDOW")
539 (X-Atom-find-by-name (xwem-dpy) "WM_TAKE_FOCUS")))
540 (XSetWMClass (xwem-dpy) fwin
541 (list (symbol-name (xwem-frame-type frame))
543 (XSetWMName (xwem-dpy) fwin "xwem-frame")
546 (xwem-kbd-install-grab 'xwem-frame-prefix fwin)
548 ;;; Initialise FRAME properties
549 ;; Adjust frame properties in case FRAME is embedded or dedicated
551 (setq fplist (xwem-misc-merge-plists
553 (cond ((xwem-frame-embedded-p frame)
554 xwem-embedded-frame-default-properties)
555 ((xwem-frame-dedicated-p frame)
556 xwem-dedicated-frame-defalut-properties))))
558 ;;; Initialize FRAME's root window
559 (setq parwin (xwem-win-new (list :frame frame) nil))
560 (setf (xwem-frame-selwin frame) parwin)
561 (setf (xwem-frame-rootwin frame) parwin)
563 ;; Set FRAME properties
564 (xwem-frame-set-properties frame (xwem-misc-merge-plists fplist props))
566 ;; Setup rootwin's geometry
567 (xwem-frame-setup-root-win frame)
569 ;; Find an empty place in xwem-frames-list or add to the end of
571 (let ((allframes xwem-frames-list))
572 (while (and allframes (xwem-frame-p (car allframes)))
573 (setq allframes (cdr allframes)))
575 (setcar allframes frame)
576 (setq xwem-frames-list
577 (append xwem-frames-list (list frame)))))
579 ;; Handle as client, i.e. make frame to be embedded
580 (when (xwem-frame-embedded-p frame)
581 (let ((ecl (xwem-xwin-try-to-manage (xwem-frame-xwin frame))))
582 (when (xwem-cl-p ecl)
583 (xwem-frame-put-prop frame 'xwem-embedded-cl ecl)
584 (xwem-cl-put-sys-prop ecl 'xwem-embedded-frame frame))))
586 ;; Finally map and maybe select newly created frame
587 (unless (xwem-frame-property frame 'initially-unmapped)
588 (xwem-frame-map frame))
591 (xwem-select-frame frame))
593 ;; Now run on-create hooks
594 (run-hook-with-args 'xwem-frame-creation-hook frame)
597 (defun xwem-init-frame-at-rect (xrect)
598 "Create frame to fit in XRECT rectangle."
599 (let ((xmrect (make-X-Rect
600 :x 0 :y 0 :width (X-Geom-width (xwem-rootgeom))
601 :height (if (xwem-minib-xgeom xwem-minibuffer)
602 (X-Geom-height (xwem-minib-xgeom xwem-minibuffer))
603 (+ (* 2 xwem-minibuffer-border-width)
605 (xwem-minib-frame xwem-minibuffer))
606 xwem-minibuffer-outer-border-width
607 xwem-minibuffer-outer-border-width)))))
609 (when (X-Rect-intersect-p xmrect xrect)
610 ;; Take into account this intersection
611 (setf (X-Rect-height xrect)
612 (- (X-Rect-height xrect)
613 (X-Rect-height xmrect))))
615 (xwem-make-frame-1 'desktop
616 :params (list :xgeom (X-Rect-to-X-Geom xrect))
619 (defun xwem-frame-adjust-geom (frame new-rect)
620 "Adjust FRAME geom according to NEW-RECT and xwem-minibuffer geom."
621 (let ((mrect (X-Geom-to-X-Rect (xwem-minib-xgeom xwem-minibuffer)))
622 (brd (X-Geom-border-width (xwem-minib-xgeom xwem-minibuffer)))
624 (when (eq (xwem-cl-state (xwem-minib-cl xwem-minibuffer)) 'active)
626 (incf (X-Rect-width mrect) (+ brd brd))
627 (incf (X-Rect-height mrect) (+ brd brd)))
629 (when (X-Rect-intersect-p new-rect mrect)
630 (setf (X-Rect-height new-rect)
631 (- (X-Rect-height new-rect)
632 (X-Rect-height mrect)))))
634 (setq ngeom (X-Rect-to-X-Geom new-rect))
635 (setf (X-Geom-border-width ngeom)
636 (X-Geom-border-width (xwem-frame-xgeom frame)))
637 (decf (X-Geom-width ngeom) (* 2 (X-Geom-border-width ngeom)))
638 (decf (X-Geom-height ngeom) (* 2 (X-Geom-border-width ngeom)))
640 (setf (xwem-frame-xgeom frame) ngeom)))
642 (defun xwem-frame-default-select-hook ()
643 "Do various default things when frame selected.
644 To be used in `xwem-frame-select-hook'."
645 (xwem-frame-autoiconify-on-select)
646 (xwem-frame-deffered-redraw-inner-border (xwem-frame-selected)))
648 (defun xwem-frame-default-deselect-hook ()
649 "Do various default things when frame deselected.
650 To be used in `xwem-frame-deselect-hook'."
651 (xwem-frame-autoiconify-on-deselect)
652 (xwem-frame-deffered-redraw-inner-border (xwem-frame-selected)))
654 (defun xwem-frame-create-initial ()
655 "Create initial frames."
656 ;; Try to import frame configuration from root window
657 (xwem-frame-import-frame-configuration)
659 (if xwem-frame-dumped-config
660 ;; Create frames from saved configuration
661 (xwem-frame-config-restore1)
664 (let ((xin (X-XIneramaQueryScreens (xwem-dpy)))
667 ;; XInerama enabled, so construct frames linkage
668 (while (setq xin (cdr xin))
669 (setq frame (xwem-init-frame-at-rect (car xin)))
671 (xwem-frame-link-insert-after frame-old frame))
672 (setq frame-old frame))
674 ;; No XInerama, crate just one frame
675 (xwem-init-frame-at-rect (X-Geom-to-X-Rect (xwem-rootgeom)))))
677 ;; Select very first frame
678 (xwem-select-frame (car (xwem-frames-list)))))
681 (defun xwem-frames-init ()
682 "xwem frames initializer."
683 (xwem-message 'init "Initializing frames ...")
685 (setq xwem-frames-list nil)
686 (setq xwem-current-frame nil)
688 ;; Create frame cursors
689 (setq xwem-frame-cursor
690 (xwem-make-cursor xwem-frame-cursor-shape
691 xwem-frame-cursor-foreground-color
692 xwem-frame-cursor-background-color))
694 ;; Add autoiconifier hooks
695 (add-hook 'xwem-frame-select-hook 'xwem-frame-default-select-hook)
696 (add-hook 'xwem-frame-deselect-hook 'xwem-frame-default-deselect-hook)
698 ;; Add post command hook to export frames configuration
699 (add-hook 'xwem-post-command-hook 'xwem-frame-frame-command-post-hook)
701 ;; Create initial frames
702 (xwem-frame-create-initial)
704 (xwem-message 'init "Initializing frames ... done"))
707 (defun xwem-frames-fini ()
709 (mapc 'xwem-frame-destroy (xwem-frames-list)))
711 ;;;###autoload(autoload 'xwem-make-frame "xwem-frame" "" t)
712 (define-xwem-command xwem-make-frame (type &optional arg)
713 "Interactively create new XWEM frame.
714 With prefix ARG create frame of 'desktop type."
715 (xwem-interactive (list (or (and xwem-prefix-arg 'desktop)
716 (xwem-completing-read
717 "XWEM Frame type [desktop]: "
718 (mapcar (lambda (cc) (list (symbol-name cc)))
722 (if (string= type "")
724 (setq type (intern-soft type))))
726 (xwem-make-frame-1 type))
728 (defun xwem-frame-find (how arg)
729 "Find frame by ARG. HOW is search type, one of 'xwin 'win 'cl or 'name."
730 (let ((flist (xwem-frames-list))
734 (if (cond ((and (eq how 'xwin)
737 (X-Win-id (xwem-frame-xwin (car flist)))))
741 (eq (xwem-win-frame arg) (car flist)))
745 (eq (xwem-cl-frame arg) (car flist)))
749 (string= arg (xwem-frame-name (car flist))))
754 (setq rf (car flist))
757 (setq flist (cdr flist))))
760 (defun xwem-frame-other-frame (frame)
761 "Return other frame for FRAME.
762 NOTE: not yet implemented"
764 ;; Try linkage, and then try closest frame
765 (let ((oframe (xwem-frame-link-next frame)))
766 (unless (xwem-frame-p oframe)
767 (setq oframe (xwem-frame-link-prev frame))
768 (unless (xwem-frame-p oframe)
769 (setq oframe (cadr (memq frame (xwem-frames-list
770 (xwem-frame-type frame)))))
771 (unless (xwem-frame-p oframe)
772 (setq oframe (cadr (memq frame (nreverse
774 (xwem-frame-type frame))))))
775 (unless (xwem-frame-p oframe)
776 (setq oframe (car (xwem-frames-list)))))))
780 (defun xwem-frame-other (frame &optional type)
781 "Same as `xwem-frame-other-frame', but return nil, if no good other frame found.
782 TYPE is ane of 'any, 'linkage"
786 ;; First try linkaged frames
787 (let ((allframes (xwem-frames-list))
788 (oframe (xwem-frame-link-next frame)))
789 (unless (xwem-frame-mapped-p oframe)
790 (setq oframe (xwem-frame-link-prev frame)))
792 ;; Now try parent in case when FRAME is embedded frame.
793 (unless (xwem-frame-mapped-p oframe)
794 (when (xwem-frame-embedded-p frame)
795 (let ((cl (xwem-frame-get-prop frame 'xwem-embedded-cl)))
797 (setq oframe (xwem-cl-frame cl))))))
799 (when (and (not (xwem-frame-mapped-p oframe))
801 ;; Scan frames list only for 'any TYPE
802 (while (and allframes (not (xwem-frame-mapped-p oframe)))
803 (when (and (xwem-frame-mapped-p (car allframes))
804 (not (eq frame (car allframes))))
805 (setq oframe (car allframes))
806 (setq allframes nil))
807 (setq allframes (cdr allframes))))
811 (defun xwem-frame-num (frame)
812 "Return FRAME index in `xwem-frames-list'."
813 (- (length xwem-frames-list)
814 (length (memq frame xwem-frames-list))))
816 (defun xwem-frame-xy-in-p (x y frame)
817 "Return non-nil if point at X Y is in FRAME."
818 (and (>= x (xwem-frame-x frame))
819 (<= x (+ (xwem-frame-x frame) (xwem-frame-width frame)))
820 (>= y (xwem-frame-y frame))
821 (<= y (+ (xwem-frame-y frame) (xwem-frame-height frame)))))
823 (defun xwem-frame-at (x y &optional maped-p)
824 "Return frame which contain point at X Y.
825 If MAPED-P is non-nil - search only mapped frame."
826 (loop for frame in (xwem-frames-list)
827 if (and (or (null maped-p)
828 (eq (xwem-frame-state frame) 'mapped))
829 (xwem-frame-xy-in-p x y frame))
832 ;;;###xwem-autoload(autoload 'xwem-frame-apply-xgeom-1 "xwem-frame" nil nil)
833 ;;;###xwem-autoload(autoload 'xwem-frame-apply-xgeom "xwem-frame" nil nil)
834 (define-xwem-deffered xwem-frame-apply-xgeom (frame)
835 "Apply FRAME's geometry to life."
836 (XConfigureWindow (xwem-dpy) (xwem-frame-xwin frame)
838 :x (xwem-frame-x frame)
839 :y (xwem-frame-y frame)
840 :width (xwem-frame-width frame)
841 :height (xwem-frame-height frame)
842 :border-width (xwem-frame-border-width frame)))
844 (xwem-frame-setup-root-win frame)
845 (run-hook-with-args 'xwem-frame-resize-hook frame))
847 (define-xwem-deffered xwem-frame-apply-position (frame)
848 "Apply FRAME's position to life."
849 (when (xwem-frame-p frame)
850 (XMoveWindow (xwem-dpy) (xwem-frame-xwin frame)
851 (xwem-frame-x frame) (xwem-frame-y frame))
852 (run-hook-with-args 'xwem-frame-move-hook frame)))
855 (defun xwem-frame-set-pos (frame new-x new-y)
856 "Set FRAME position at NEW-X and NEW-Y."
857 (setf (xwem-frame-x frame) new-x)
858 (setf (xwem-frame-y frame) new-y)
860 (xwem-frame-apply-position frame))
862 (define-xwem-deffered xwem-frame-apply-size (frame)
863 "Apply FRAME's size to life."
864 (when (xwem-frame-p frame)
865 (xwem-debug 'xwem-frame "Applying size: %dx%d"
866 '(xwem-frame-width frame) '(xwem-frame-height frame))
867 (XResizeWindow (xwem-dpy) (xwem-frame-xwin frame)
868 (xwem-frame-width frame) (xwem-frame-height frame))
870 (run-hook-with-args 'xwem-frame-resize-hook frame)))
873 (defun xwem-frame-set-size (frame new-width new-height)
874 "Resize FRAME to NEW-WIDTH and NEW-HEIGHT."
876 (setf (xwem-frame-width frame) new-width))
878 (setf (xwem-frame-height frame) new-height))
880 (xwem-frame-setup-root-win frame)
881 (xwem-frame-apply-size frame))
883 ;;; Frame Events handling
884 (defun xwem-frame-hexpose (frame xev)
885 "Expose event handler."
886 (xwem-debug 'xwem-frame "Exposure event count: %S"
887 '(X-Event-xexpose-count xev))
889 (when (zerop (X-Event-xexpose-count xev))
890 ;; Redraw only when no other exposure events follow
891 (and (xwem-frame-p frame)
892 (xwem-frame-draw frame nil))))
894 (defun xwem-frame-remove (frame &optional select-other)
895 "Remove FRAME from frames list, switch to other frame if SELECT-OTHER is non-nil."
896 (let ((oframe (xwem-frame-other frame 'any))) ; other frame
898 ;; Remove FRAME from linkage if any
899 (xwem-frame-link-remove frame)
901 ;; Now Remove FRAME from frame list
902 (unless xwem-frame-keep-number
903 (setq xwem-frames-list (delq frame xwem-frames-list)))
905 ;; If frame is not selected it mean that it was embedded
906 (if (and select-other (xwem-frame-p oframe) (not (eq oframe frame)))
907 (xwem-select-frame oframe)
908 (setq xwem-current-frame nil))))
910 (defun xwem-frame-total-remove (frame)
911 "Totally remove FRAME."
912 ;; Firstly we need to remove FRAME from frames list.
913 (let ((embed-cl (xwem-frame-get-prop frame 'xwem-embedded-cl))
914 (oframe (xwem-frame-other frame)))
916 ;; If FRAME is selected, select some other frame
917 (setq xwem-current-frame nil)
918 (when (xwem-frame-p oframe)
919 (xwem-select-frame oframe))
921 ;; Block events handling
922 (XSelectInput (xwem-dpy) (xwem-frame-xwin frame) 0)
923 (setf (X-Win-event-handlers (xwem-frame-xwin frame)) nil)
924 (X-Win-rem-prop (xwem-frame-xwin frame) 'xwem-frame)
926 ;; Remove clients from FRAME
927 (mapc #'(lambda (fcl)
928 (XReparentWindow (xwem-dpy) (xwem-cl-xwin fcl) (xwem-rootwin)
929 (X-Geom-width (xwem-rootgeom))
930 (X-Geom-height (xwem-rootgeom)))
932 (xwem-frame-clients frame))
934 ;; Destroy any X wins
935 (unless (eq (xwem-frame-state frame) 'destroyed)
936 (XDestroySubwindows (xwem-dpy) (xwem-frame-xwin frame))
937 (XDestroyWindow (xwem-dpy) (xwem-frame-xwin frame))
938 (setf (xwem-frame-state frame) 'destroyed))
940 ;; If we are embedded frame than emulate our destroing
941 (when (xwem-cl-p embed-cl)
942 (xwem-cl-destroy embed-cl))
944 ;; Remove frame from frames list and select another frame
945 (xwem-frame-remove frame t)
948 ;; Now run on-destroy hooks
949 (run-hook-with-args 'xwem-frame-destroy-hook frame)
950 ;; Mark FRAME as non valid for referencing.
951 (X-invalidate-cl-struct frame))))
953 (defun xwem-frame-hconfigure (frame xev)
954 "FRAME just received ConfigureNotify event XEV."
955 (let ((owid (xwem-frame-width frame))
956 (ohei (xwem-frame-height frame))
957 (nwid (X-Event-xconfigure-width xev)) ;new width
958 (nhei (X-Event-xconfigure-height xev))) ;new height
960 (unless (and (= owid nwid) (= ohei nhei))
961 (xwem-frame-set-size frame nwid nhei)
962 (run-hook-with-args 'xwem-frame-resize-hook frame))))
964 (defun xwem-frame-hclient (frame xev)
965 "FRAME just received XClientMessage event XEV."
966 (xwem-debug 'xwem-frame
967 "FRAME[%d] got ClientMessage, Atom=%S(%s).."
968 '(xwem-frame-num frame) '(X-Atom-id (X-Event-xclient-atom xev))
969 '(X-Atom-name (X-Event-xclient-atom xev)))
971 (cond ((string= (X-Atom-name (X-Event-xclient-atom xev)) "WM_PROTOCOLS")
972 (let ((wmda (X-Atom-find (xwem-dpy) (caar (X-Event-xclient-msg xev)))))
973 (when (X-Atom-p wmda)
974 (cond ((string= (X-Atom-name wmda) "WM_DELETE_WINDOW")
975 (xwem-debug 'xwem-frame "Killing frame, because of WM_DELETE_WINDOW client message")
976 (xwem-frame-total-remove frame))
977 ((string= (X-Atom-name wmda) "WM_TAKE_FOCUS")
978 (xwem-debug 'xwem-frame "Frame(%s): Taking focus .."
979 '(xwem-frame-name frame))
980 (xwem-focus-set (xwem-frame-cl frame)))))
983 (defun xwem-frame-hkeybutton (frame xev)
984 "On FRAME handle KeyPress, ButtonPress or ButtonRelease event XEV."
985 (xwem-overriding-local-map 'xwem-frame-prefix
986 (when (eq (xwem-dispatch-command-xevent xev) 'done)
987 (signal 'X-Events-stop nil))))
989 (defun xwem-frame-events-handler (xdpy win xev)
990 "Event handler for frame."
991 (let ((frame (X-Win-get-prop win 'xwem-frame)))
992 (when (xwem-frame-p frame)
993 (xwem-debug 'xwem-frame "Got event ev=%S, win=%S, frame: %d"
994 '(X-Event-name xev) '(X-Win-id win) '(xwem-frame-num frame))
997 (xwem-frame-hexpose frame xev))
999 ((:X-KeyPress :X-ButtonPress :X-ButtonRelease)
1000 (xwem-frame-hkeybutton frame xev))
1003 (setf (xwem-frame-state frame) 'destroyed)
1004 (xwem-frame-total-remove frame))
1006 (:X-ClientMessage (xwem-frame-hclient frame xev))
1008 ;; For emebedded frames
1010 (when (xwem-frame-embedded-p frame)
1011 (xwem-frame-hconfigure frame xev)))
1013 (when (xwem-frame-embedded-p frame)
1014 (xwem-frame-map frame)))
1016 (when (xwem-frame-embedded-p frame)
1017 (xwem-frame-unmap frame)))
1020 ;;;; Frame Events handling ends here
1022 (defun xwem-frame-draw (frame full)
1023 "Draw FRAME. If FULL is t then fully redraw it, i.e. ClearWindow first."
1024 (unless (eq frame xwem-frame-noredisplay)
1026 (XClearArea (xwem-dpy) (xwem-frame-xwin frame) 0 0
1027 (xwem-frame-width frame)
1028 (xwem-frame-height frame) nil))
1030 (xwem-frame-draw-inner-border frame)
1031 (run-hook-with-args 'xwem-frame-redraw-hook frame)))
1033 ;;; Frame configuration section
1035 (defun xwem-frame-configuration-p (frame-config)
1036 "Return non-nil if FRAME-CONFIG is looks like frame configuration."
1037 (and (listp frame-config)
1038 (eq 'xwem-frame-configuration
1039 (car frame-config))))
1041 (defun xwem-frame-config-find-sframe (frame sframe-list)
1042 "Find saved frame by FRAME."
1043 (while (and sframe-list
1044 (not (eq (xwem-frame-saved-frame (car sframe-list)) frame)))
1045 (setq sframe-list (cdr sframe-list)))
1049 (defun xwem-frame-configuration ()
1050 "Return current xwem frame configuration."
1051 ;; TODO: save domain faces
1052 (cons 'xwem-frame-configuration
1053 (mapcar #'(lambda (frame)
1054 (make-xwem-frame-saved
1056 :selected-p (xwem-frame-selected-p frame)
1057 :type (xwem-frame-type frame)
1058 :name (xwem-frame-name frame)
1059 :xgeom (copy-X-Geom (xwem-frame-xgeom frame))
1060 :state (xwem-frame-state frame)
1061 :plist (append (xwem-frame-properties frame)
1062 (unless (xwem-frame-mapped-p frame)
1063 '(initially-unmapped t)))
1064 :winconfig (xwem-window-configuration frame)))
1065 (xwem-frames-list))))
1068 (defun xwem-set-frame-configuration (frame-config &optional no-delete)
1069 "Restore the frames to the state described by FRAME-CONFIG."
1070 (unless (xwem-frame-configuration-p frame-config)
1071 (signal 'wrong-type-argument
1072 (list 'xwem-frame-configuration-p frame-config)))
1075 ;; - Maybe recreate frames that in config, but already destroyed?
1076 (let ((conf (cdr frame-config))
1078 (mapc #'(lambda (frame)
1079 (let ((sframe (xwem-frame-config-find-sframe frame conf)))
1080 (if (xwem-frame-saved-p sframe)
1082 (setf (xwem-frame-name frame)
1083 (xwem-frame-saved-name sframe)
1084 (xwem-frame-state frame)
1085 (xwem-frame-saved-state sframe))
1086 (xwem-frame-adjust-geom
1087 frame (xwem-frame-saved-xgeom sframe))
1088 (xwem-set-window-configuration
1089 (xwem-frame-saved-winconfig sframe)))
1091 (setq frames-to-delete (cons frame frames-to-delete)))))
1095 (mapc 'xwem-frame-hide frames-to-delete)
1096 (mapc 'xwem-frame-destroy frames-to-delete))
1099 (defun xwem-frame-config-dump1 (config buffer &optional append)
1100 "Dump frames CONFIG to BUFFER.
1101 If APPEND is non-nil, do not erase FILE, just append to the end."
1102 ;; TODO: dump also domain faces
1103 (let ((ccf (copy-sequence config))
1105 (with-current-buffer (or buffer (current-buffer))
1108 (goto-char (point-max))
1112 (insert "(setq xwem-frame-dumped-config (list 'xwem-frame-configuration\n")
1113 (mapc #'(lambda (sfr)
1114 (setf (xwem-frame-saved-frame sfr) nil)
1116 ;; Adjust win config
1117 (setq wcf (xwem-frame-saved-winconfig sfr))
1118 (setf (xwem-win-config-frame wcf) nil)
1119 (setf (xwem-win-config-current-cl wcf) nil)
1120 (flet ((clrwin (swin)
1121 (setf (xwem-win-saved-clients swin) nil)
1122 (setf (xwem-win-saved-cl swin) nil)
1123 (when (xwem-win-saved-first-vchild swin)
1124 (clrwin (xwem-win-saved-first-vchild swin)))
1125 (when (xwem-win-saved-first-hchild swin)
1126 (clrwin (xwem-win-saved-first-hchild swin)))
1127 (when (xwem-win-saved-next swin)
1128 (clrwin (xwem-win-saved-next swin)))
1129 (when (xwem-win-saved-prev swin)
1130 (clrwin (xwem-win-saved-prev swin)))))
1131 (clrwin (xwem-win-config-saved-root-window wcf)))
1133 (insert (format "%S\n" sfr)))
1137 (defun xwem-frame-config-dump (config &optional file)
1138 "Dump frame configuration CONFIG to FILE.
1139 If FILE ommited, than ~/.xwem/xwem-configs.el will be used."
1140 (unless (xwem-frame-configuration-p config)
1141 (error 'xwem-error "Not an xwem frame configuration" config))
1144 (setq file (expand-file-name "xwem-configs.el" xwem-dir)))
1146 (let* ((find-file-hooks nil) ; omit autoinsert and others
1147 (buf (find-file-noselect file)))
1148 (xwem-frame-config-dump1 config buf)
1151 (defun xwem-frame-config-restore1 ()
1152 "Internal frame config restorer."
1153 (let (frame-to-select)
1154 (mapc #'(lambda (sfr)
1155 (let ((swin (xwem-frame-saved-winconfig sfr))
1157 (setq nframe (xwem-make-frame-1
1158 (xwem-frame-saved-type sfr)
1159 :params (list :name (xwem-frame-saved-name sfr)
1160 :xgeom (xwem-frame-saved-xgeom sfr))
1161 :props (xwem-frame-saved-plist sfr)
1163 (when (xwem-frame-p nframe)
1164 (setf (xwem-win-config-frame swin) nframe)
1165 (xwem-set-window-configuration swin)
1167 (when (and (xwem-frame-saved-selected-p sfr)
1168 (not frame-to-select))
1169 (setq frame-to-select nframe)))
1171 (cdr xwem-frame-dumped-config))
1172 (when frame-to-select
1173 (xwem-select-frame frame-to-select)))
1175 ;; dumped config has been restored
1176 (setq xwem-frame-dumped-config nil))
1178 (defun xwem-frame-config-restore (&optional file)
1179 "Restore saved frames configuration from FILE.
1180 Default FILE is ~/.xwem/xwem-configs.el"
1182 (setq file (expand-file-name "xwem-configs.el" xwem-dir)))
1185 (unless (xwem-frame-configuration-p xwem-frame-dumped-config)
1186 (error 'xwem-error "no frames configuration to restore"))
1188 (xwem-frame-config-restore1))
1190 ;;; Frame configuration section ends here
1191 ;;;###autoload(autoload 'xwem-frame-next "xwem-frame" "" t)
1192 (define-xwem-command xwem-frame-next (arg)
1193 "Switch to ARG next frame."
1194 (xwem-interactive "p")
1196 (let ((frame (nth arg (memq (xwem-frame-selected) (xwem-frames-list)))))
1197 (when (and xwem-frame-rolling-switch
1198 (not (xwem-frame-p frame)))
1199 ;; Assume first frame if there no next
1200 (setq frame (car (xwem-frames-list))))
1202 (unless (xwem-frame-p frame)
1203 (error 'xwem-error "Invalid frame"))
1205 (xwem-select-frame frame)))
1206 (put 'xwem-frame-next 'xwem-frame-command t)
1208 ;;;###autoload(autoload 'xwem-frame-previous "xwem-frame" "" t)
1209 (define-xwem-command xwem-frame-previous (arg)
1210 "Switch to ARG previous frame."
1211 (xwem-interactive "p")
1213 (let ((frame (nth arg (memq (xwem-frame-selected)
1214 (reverse (xwem-frames-list))))))
1215 (when (and xwem-frame-rolling-switch
1216 (not (xwem-frame-p frame)))
1217 ;; Assume last frame if there no previous
1218 (setq frame (car (last (xwem-frames-list)))))
1220 (unless (xwem-frame-p frame)
1221 (error 'xwem-error "Invalid frame"))
1223 (xwem-select-frame frame)))
1224 (put 'xwem-frame-previous 'xwem-frame-command t)
1226 ;;;###autoload(autoload 'xwem-frame-switch "xwem-frame" "Switch to frame by name." t)
1227 (define-xwem-command xwem-frame-switch (name)
1228 "Switch to frame by NAME."
1230 (list (xwem-completing-read
1232 (mapcar #'(lambda (fr)
1233 (list (xwem-frame-name fr)))
1234 (xwem-frames-list)))))
1236 ;; Find frame by name
1237 (let ((frms (xwem-frames-list))
1239 (while (and frms (not (string= (xwem-frame-name (car frms)) name)))
1240 (setq frms (cdr frms)))
1241 (setq frame (car frms))
1243 (unless (xwem-frame-alive-p frame)
1244 (error 'xwem-error "No such frame"))
1246 (xwem-select-frame frame)))
1248 ;;;###autoload(autoload 'xwem-frame-switch-nth "xwem-frame" "" t)
1249 (define-xwem-command xwem-frame-switch-nth (arg)
1251 If ARG is numeric prefix, then switch to ARG frame.
1252 If ARG ommited, 0 as ARG value will be used.
1253 If ARG is list and selected frame is embedded, than unembedd it."
1254 (xwem-interactive "P")
1259 (let ((frame (nth (abs arg) xwem-frames-list)))
1260 (if (xwem-frame-p frame)
1261 (xwem-select-frame frame)
1262 (xwem-message 'warning "No such %S frame." (abs arg))))
1264 ;; UNEMBED selected frame
1265 (let ((frame (xwem-frame-selected)))
1266 (when (xwem-frame-embedded-p frame)
1267 (xwem-frame-unembedd frame)
1268 (xwem-select-frame frame)))
1271 ;;;###autoload(autoload 'xwem-frame-switch-nth-linkage "xwem-frame" "" t)
1272 (define-xwem-command xwem-frame-switch-nth-linkage (arg)
1273 "Raise all frames that in linkage of frame with number NUM."
1274 (xwem-interactive "P")
1276 (when (null arg) (setq arg 0))
1278 (let ((frame (nth (abs arg) xwem-frames-list)))
1279 (if (not (xwem-frame-p frame))
1280 (xwem-message 'warning "No such %S frame." (abs arg))
1283 (xwem-frame-linkage-map frame 'xwem-frame-raise)
1284 (xwem-select-frame frame)))
1285 (xwem-message 'warning "Strange arg value: %S" arg)))
1287 ;;;###autoload(autoload 'xwem-frame-destroy "xwem-frame" "" t)
1288 (define-xwem-command xwem-frame-destroy (frame &optional arg)
1289 "Destroy FRAME. If FRAME is not given selected frame assumed.
1290 If prefix ARG is given - close all clients managed in FRAME."
1291 (xwem-interactive (list (xwem-frame-selected) xwem-prefix-arg))
1293 ;; In case of prefix ARG - close all clients
1295 (mapc 'xwem-client-kill
1296 (xwem-clients-list #'(lambda (cl)
1297 (eq (xwem-cl-frame cl) frame)))))
1299 (when (xwem-frame-p frame)
1300 (xwem-frame-total-remove frame)))
1301 (put 'xwem-frame-destroy 'xwem-frame-command t)
1303 (defun xwem-frame-goto (n direction &optional frame)
1304 "Goto window at DIRECTION on FRAME N times.
1305 DIRECTION is one of 'next, 'prev, 'next-vert, ..."
1306 (let* ((gframe (or frame (xwem-frame-selected)))
1307 (cwin (xwem-frame-selwin gframe)))
1309 ;; Adjust N and DIRECTION if needed
1310 (when (and (eq direction 'next)
1316 (cond ((eq direction 'next)
1317 (setq cwin (xwem-window-next cwin)))
1318 ((eq direction 'prev)
1319 (setq cwin (xwem-window-prev cwin)))
1320 ((eq direction 'next-vert)
1321 (setq cwin (xwem-window-next-vertical cwin)))
1323 'xwem-error "Bad DIRECTION in `xwem-frame-goto'" direction)))
1326 (xwem-select-window cwin)))
1328 ;;;###autoload(autoload 'xwem-frame-goto-next "xwem-frame" "" t)
1329 (define-xwem-command xwem-frame-goto-next (arg)
1330 "Goto ARG next window in selected frame."
1331 (xwem-interactive "p")
1332 (xwem-frame-goto arg 'next))
1334 ;;;###autoload(autoload 'xwem-frame-goto-prev "xwem-frame" "" t)
1335 (define-xwem-command xwem-frame-goto-prev (arg)
1336 "Goto ARG previous window in selected frame."
1337 (xwem-interactive "p")
1338 (xwem-frame-goto arg 'prev))
1340 ;;;###autoload(autoload 'xwem-frame-goto-next-vert "xwem-frame" "" t)
1341 (define-xwem-command xwem-frame-goto-next-vert (arg)
1342 "Goto ARG next window in vertical direction in selected frame."
1343 (xwem-interactive "p")
1344 (xwem-frame-goto arg 'next-vert))
1346 ;;;###autoload(autoload 'xwem-frame-goto-next-hor "xwem-frame" "" t)
1347 (define-xwem-command xwem-frame-goto-next-hor (arg)
1348 "Goto ARG next window in horizontal direction in selected frame."
1349 (xwem-interactive "p")
1350 (xwem-frame-goto arg 'next-hor))
1352 ;;;###autoload(autoload 'xwem-frame-goto-prev-vert "xwem-frame" "" t)
1353 (define-xwem-command xwem-frame-goto-prev-vert (arg)
1354 "Goto ARG previous window in vertical direction in selected frame."
1355 (xwem-interactive "p")
1356 (xwem-frame-goto arg 'priv-vert))
1358 ;;;###autoload(autoload 'xwem-frame-goto-prev-hor "xwem-frame" "" t)
1359 (define-xwem-command xwem-frame-goto-prev-hor (arg)
1360 "Goto ARG previous window in horizontal direction in selected frame."
1361 (xwem-interactive "p")
1362 (xwem-frame-goto arg 'prev-hor))
1364 ;;;###autoload(autoload 'xwem-frame-split-sbs "xwem-frame" "" t)
1365 (define-xwem-command xwem-frame-split-sbs (n &optional frame side)
1366 "Makes N frames side by size of FRAME.
1367 SIDE is one of 'vertical or 'horizontal, if ommited or not one of
1368 above - 'horizontal will be used.
1372 +--------+ +----+----+--...--+----+
1373 +--------+ +----+----+--...--+----+
1374 | 1 | `xwem-frame-split-sbs' |--> | 1 | 2 | | N |
1376 +--------+ +----+----+--...--+----+
1378 Widths sum of all N frames after sbs split is equal to width of frame
1380 (xwem-interactive "p")
1382 (let* ((vertp (eq side 'vertical))
1383 (frm (or frame (xwem-frame-selected)))
1384 (wi (xwem-frame-width frm))
1385 (he (xwem-frame-height frm))
1392 (when (xwem-frame-embedded-p frm)
1393 (error 'xwem-error "Can't split embedded frame"))
1397 (setq nhe (/ he (1+ n)))
1398 (setq host (% he (1+ n))))
1399 (setq nwi (/ wi (1+ n)))
1400 (setq wost (% wi (1+ n))))
1402 (setq xoff (+ nwi wost))
1403 (setq yoff (+ nhe host))
1406 (xwem-frame-set-size frm xoff yoff)
1408 ;; TODO: - inherit same parent in case FRM is embedded
1409 ;; - install frames linkage
1412 (samex (xwem-frame-x frm))
1413 (samey (xwem-frame-y frm)))
1416 (xwem-make-frame-1 (xwem-frame-type frm)
1419 (make-X-Geom :x (if vertp
1428 ;; Now setup linkage
1429 (xwem-frame-link-insert-after oframe nframe)
1430 (setq oframe nframe)
1433 (setq yoff (+ yoff nhe))
1434 (setq xoff (+ xoff nwi)))
1437 (put 'xwem-frame-iresize 'xwem-frame-command t)
1439 ;;;###autoload(autoload 'xwem-frame-sbs-hor-split "xwem-frame" "" t)
1440 (define-xwem-command xwem-frame-sbs-hor-split (n)
1441 "Make horizontal sbs split N times for selected frame."
1442 (xwem-interactive "p")
1443 (xwem-frame-split-sbs n))
1444 (put 'xwem-frame-sbs-hor-split 'xwem-frame-command t)
1446 ;;;###autoload(autoload 'xwem-frame-sbs-vert-split "xwem-frame" "" t)
1447 (define-xwem-command xwem-frame-sbs-vert-split (n)
1448 "Make vertical sbs split N times for selected frame."
1449 (xwem-interactive "p")
1450 (xwem-frame-split-sbs n nil 'vertical))
1451 (put 'xwem-frame-sbs-vert-split 'xwem-frame-command t)
1453 ;;;###autoload(autoload 'xwem-frame-fit-screen "xwem-frame" "" t)
1454 (define-xwem-command xwem-frame-fit-screen (frame)
1455 "Fit FRAME to screen sizes."
1456 (xwem-interactive (list (xwem-frame-selected)))
1458 ;; Take into acount XInerama layout
1459 (let ((frect (X-Geom-to-X-Rect (xwem-frame-xgeom frame)))
1460 (xin (X-XIneramaQueryScreens (xwem-dpy))))
1464 (while (and (setq xin (cdr xin))
1465 (not (X-Rect-intersect-p (car xin) frect))))
1466 (setq xin (car xin)))
1468 ;; No XInerama, so use root geometry
1469 (setq xin (X-Geom-to-X-Rect (xwem-rootgeom))))
1471 (xwem-frame-adjust-geom frame xin)
1473 (xwem-frame-set-size
1474 frame (xwem-frame-width frame) (xwem-frame-height frame))
1476 frame (xwem-frame-x frame) (xwem-frame-y frame))
1478 ;; XXX uninstall linkage if any
1479 (xwem-frame-link-remove frame)))
1480 (put 'xwem-frame-fit-screen 'xwem-frame-command t)
1482 ;;;###autoload(autoload 'xwem-frame-transpose "xwem-frame" "" t)
1483 (define-xwem-command xwem-frame-transpose (arg)
1484 "Transpose frames ARG times."
1485 (xwem-interactive "p")
1486 (error 'xwem-error "`xwem-frame-transpose' not implemented yet."))
1488 ;;;###autoload(autoload 'xwem-frame-showroot "xwem-frame" "" t)
1489 (define-xwem-command xwem-frame-showroot ()
1490 "Show root window, i.e. unmap all xwem frames."
1492 (mapc 'xwem-frame-unmap (xwem-frames-list))
1493 (xwem-select-client nil))
1495 ;;;###autoload(autoload 'xwem-frame-hide "xwem-frame" "" t)
1496 (define-xwem-command xwem-frame-hide (frame &optional no-select)
1498 When called interactively, FRAME is selected frame.
1499 With prefix ARG, do not select new frame."
1500 (xwem-interactive (list (xwem-frame-selected)
1503 (let ((oframe (xwem-frame-other frame))
1505 (when (xwem-frame-mapped-p frame)
1506 ;; We are about to hide FRAME, so select other frame
1507 (when (and (not no-select)
1508 (xwem-frame-p oframe))
1509 (xwem-select-frame oframe))
1511 ;; In case FRAME is embedded frame - iconify coressponding
1513 (if (xwem-cl-p (setq em-cl (xwem-frame-get-prop
1514 frame 'xwem-embedded-cl)))
1515 (xwem-iconify em-cl)
1516 (xwem-frame-unmap frame)))))
1517 (put 'xwem-frame-hide 'xwem-frame-command t)
1519 ;;;###autoload(autoload 'xwem-transpose-frames "xwem-frame" "" t)
1520 (define-xwem-command xwem-transpose-frames (arg)
1521 "Transpose selected frame with ARG other frame."
1522 (xwem-interactive "p")
1524 (let* ((sfr (xwem-frame-selected))
1525 (ofr (xwem-frame-other sfr))
1528 (when (xwem-frame-p ofr)
1529 (setq sg (copy-sequence (xwem-frame-xgeom sfr))
1530 og (copy-sequence (xwem-frame-xgeom ofr)))
1532 (xwem-frame-set-pos sfr (X-Geom-x og) (X-Geom-y og))
1533 (xwem-frame-set-pos ofr (X-Geom-x sg) (X-Geom-y sg))
1535 (xwem-frame-set-size sfr (X-Geom-width og) (X-Geom-height og))
1536 (xwem-frame-set-size ofr (X-Geom-width sg) (X-Geom-height sg))
1538 ;; Finally exchange positions (aka frame number) in
1539 ;; `xwem-frames' list
1540 (xwem-list-exchange-els xwem-frames-list sfr ofr))))
1541 (put 'xwem-transpose-frames 'xwem-frame-command t)
1543 ;;;###autoload(autoload 'xwem-frame-set-name "xwem-frame" "" t)
1544 (define-xwem-command xwem-frame-set-name (name &optional frame)
1545 "Set FRAME's name to NAME."
1546 (xwem-interactive (list (xwem-read-from-minibuffer
1547 (format "New frame name (old: %s): "
1548 (xwem-frame-name (xwem-frame-selected))))
1549 (xwem-frame-selected)))
1551 (setf (xwem-frame-name frame) name)
1553 ;; Finally run hooks
1554 (run-hook-with-args 'xwem-frame-change-hook frame))
1555 (put 'xwem-frame-set-name 'xwem-frame-command t)
1558 (defun xwem-frame-in-delim-p (win x y)
1559 "Return non-nil if X Y is inside some delimeter."
1561 (let ((hc (xwem-win-hchild win))
1562 (vc (xwem-win-vchild win))
1565 (while (xwem-win-p hc)
1566 ;; For horizontal split
1567 (when (and (> x (+ (xwem-win-x hc) (xwem-win-width hc)))
1568 (< x (+ (xwem-win-x hc) (xwem-win-width hc)
1569 (xwem-win-delim-width hc)))
1570 (> y (xwem-win-y hc))
1571 (< y (+ (xwem-win-y hc) (xwem-win-height hc))))
1573 (when (setq rwin (xwem-frame-in-delim-p hc x y))
1574 (throw 'found rwin))
1575 (setq hc (xwem-win-next hc)))
1577 (while (xwem-win-p vc)
1578 (when (and (> x (xwem-win-x vc))
1579 (< x (+ (xwem-win-x vc) (xwem-win-width vc)))
1580 (> y (+ (xwem-win-y vc) (xwem-win-height vc)))
1581 (< y (+ (xwem-win-y vc) (xwem-win-height vc)
1582 (xwem-win-delim-width vc))))
1584 (when (setq rwin (xwem-frame-in-delim-p vc x y))
1585 (throw 'found rwin))
1586 (setq vc (xwem-win-next vc)))
1589 ;;;###autoload(autoload 'xwem-frame-on-delim-resize "xwem-frame" "" t)
1590 (define-xwem-command xwem-frame-on-delim-resize ()
1591 "Resize window dragging delimiter."
1594 (let* ((x (X-Event-xbutton-event-x xwem-last-xevent))
1595 (y (X-Event-xbutton-event-y xwem-last-xevent))
1596 (frame (or (X-Win-get-prop
1597 (X-Event-xbutton-event xwem-last-xevent) 'xwem-frame)
1598 (xwem-frame-at x y)))
1599 (in-xy (and (xwem-frame-p frame)
1600 (xwem-frame-in-delim-p
1601 (xwem-frame-rootwin frame) x y)))
1603 xrect type cursor done xev)
1605 (when (xwem-win-p win)
1606 ;; Findout resize tipe (vertical or horisontal)
1607 (if (> y (+ (xwem-win-y win)
1608 (xwem-win-height win)))
1613 (setq xrect (make-X-Rect :x (xwem-win-x win)
1615 :width (xwem-win-width win)
1616 :height (xwem-win-height win)))
1619 (setq cursor (xwem-make-cursor
1621 X-XC-sb_v_double_arrow
1622 X-XC-sb_h_double_arrow)))
1624 (xwem-mouse-grab cursor (xwem-frame-xwin frame)
1625 (Xmask-or XM-ButtonRelease XM-ButtonMotion))
1626 (unless (eq xwem-frame-on-delim-resize-mode 'opaque)
1627 (xwem-misc-outline xrect 'normal (xwem-frame-xwin frame)))
1628 (xwem-unwind-protect
1629 (while (and (not done) ; still not done?
1630 (setq xev (xwem-next-event)) ; deliver event before win check
1631 (xwem-win-next win)) ; still has delimiter?
1633 (:X-ButtonRelease (setq done t))
1636 (cond ((and (eq type 'vert)
1637 (> (X-Event-xmotion-event-y xev) 0)
1638 (> (X-Event-xmotion-event-y xev)
1639 (+ (X-Rect-y xrect) xwem-win-min-height))
1640 (not (= (X-Event-xmotion-event-y xev)
1642 (X-Rect-height xrect)))))
1643 (unless (eq xwem-frame-on-delim-resize-mode 'opaque)
1645 xrect 'normal (xwem-frame-xwin frame)))
1646 (setf (X-Rect-height xrect)
1647 (- (X-Event-xmotion-event-y xev) (X-Rect-y xrect)))
1648 (if (eq xwem-frame-on-delim-resize-mode 'opaque)
1649 (xwem-window-enlarge-vertically
1650 (- (X-Rect-height xrect) (xwem-win-height win)) win)
1652 xrect 'normal (xwem-frame-xwin frame))))
1654 ((and (eq type 'horz)
1655 (> (X-Event-xmotion-event-x xev) 0)
1656 (> (X-Event-xmotion-event-x xev)
1657 (+ (X-Rect-x xrect) xwem-win-min-width))
1658 (not (= (X-Event-xmotion-event-x xev)
1659 (+ (X-Rect-x xrect) (X-Rect-width xrect)))))
1660 (unless (eq xwem-frame-on-delim-resize-mode 'opaque)
1662 xrect 'normal (xwem-frame-xwin frame)))
1663 (setf (X-Rect-width xrect)
1664 (- (X-Event-xmotion-event-x xev) (X-Rect-x xrect)))
1665 (if (eq xwem-frame-on-delim-resize-mode 'opaque)
1666 (xwem-window-enlarge-horizontally
1667 (- (X-Rect-width xrect) (xwem-win-width win)) win)
1669 xrect 'normal (xwem-frame-xwin frame))))))))
1672 (XFreeCursor (xwem-dpy) cursor)
1674 (unless (eq xwem-frame-on-delim-resize-mode 'opaque)
1675 (xwem-misc-outline xrect 'normal (xwem-frame-xwin frame))
1678 (xwem-window-enlarge-vertically (- (X-Rect-height xrect)
1679 (xwem-win-height win)) win)
1680 (xwem-window-enlarge-horizontally (- (X-Rect-width xrect)
1681 (xwem-win-width win)) win)))
1683 (put 'xwem-frame-on-delim-resize 'xwem-frame-command t)
1685 ;;;###autoload(autoload 'xwem-frame-on-delim-menu "xwem-frame" "" t)
1686 (define-xwem-command xwem-frame-on-delim-menu ()
1687 "Popup menu when delimiter clicked."
1690 (let* ((x (X-Event-xbutton-event-x xwem-last-xevent))
1691 (y (X-Event-xbutton-event-y xwem-last-xevent))
1692 (frame (xwem-frame-at x y))
1693 (win (and (xwem-frame-p frame)
1694 (xwem-frame-in-delim-p
1695 (xwem-frame-rootwin frame) x y))))
1697 (when (xwem-win-p win)
1698 (xwem-popup-menu (xwem-generate-window-menu "Window" win)))))
1701 (defun xwem-frame-imove-internal (frame sx sy &optional imove-mode)
1702 "Interactively move FRAME."
1703 (when (xwem-frame-embedded-p frame)
1704 (error 'xwem-error "Can't interactively move embedded frame"))
1708 (funcall xwem-frame-imoveresize-mode-function frame 'move)))
1712 last-xrect curr-xrect xev
1715 (setq last-xrect (X-Geom-to-X-Rect (xwem-frame-xgeom frame))
1716 curr-xrect (copy-X-Rect last-xrect))
1718 (xwem-mouse-grab xwem-cursor-move nil ;(xwem-frame-xwin frame)
1719 (Xmask-or XM-ButtonPress XM-ButtonRelease
1720 XM-ButtonMotion XM-PointerMotion))
1721 (if (eq imove-mode 'opaque)
1722 (xwem-frame-map frame)
1723 (xwem-misc-outline last-xrect imove-mode))
1724 ;; Normally we should do this event loop under GrabServer, but
1725 ;; grabbing server causes XEmacs to freeze in some
1726 ;; circumstances. --lg
1727 (xwem-unwind-protect
1729 (setq xev (xwem-next-event nil (list X-ButtonPress X-ButtonRelease
1730 X-MotionNotify X-MapRequest)))
1733 (setq pevs (append pevs (list xev))))
1734 ((:X-ButtonPress :X-ButtonRelease) (setq done t))
1737 ;; Update curr-xrect
1738 (setf (X-Rect-x curr-xrect)
1739 (+ (X-Rect-x curr-xrect)
1740 (- (X-Event-xmotion-root-x xev) sx)))
1741 (setq sx (X-Event-xmotion-root-x xev))
1742 (setf (X-Rect-y curr-xrect)
1743 (+ (X-Rect-y curr-xrect)
1744 (- (X-Event-xmotion-root-y xev) sy)))
1745 (setq sy (X-Event-xmotion-root-y xev))
1747 (when (or (> (abs (- (X-Rect-x curr-xrect)
1748 (X-Rect-x last-xrect))) step)
1749 (> (abs (- (X-Rect-y curr-xrect)
1750 (X-Rect-y last-xrect))) step))
1751 (unless (eq imove-mode 'opaque)
1752 (xwem-misc-outline last-xrect imove-mode))
1754 (setf (X-Rect-x last-xrect) (X-Rect-x curr-xrect))
1755 (setf (X-Rect-y last-xrect) (X-Rect-y curr-xrect))
1756 (if (eq imove-mode 'opaque)
1758 frame (X-Rect-x last-xrect) (X-Rect-y last-xrect))
1759 (xwem-misc-outline last-xrect imove-mode))))))
1762 (unless (eq imove-mode 'opaque)
1763 (xwem-misc-outline last-xrect imove-mode))
1766 (xwem-frame-set-pos frame (X-Rect-x last-xrect) (X-Rect-y last-xrect)))
1768 ;; Dispatch map requests
1769 (mapc 'X-Dpy-event-dispatch pevs)))
1771 ;;;###autoload(autoload 'xwem-frame-imove "xwem-frame" "" t)
1772 (define-xwem-command xwem-frame-imove ()
1773 "Interactively move FRAME."
1776 (unless (or (interactive-p)
1777 (= (X-Event-type xwem-last-xevent) X-ButtonPress))
1778 (error 'xwem-error "`xwem-frame-imove'' must be binded to mouse event"))
1780 (let* ((srx (X-Event-xbutton-root-x xwem-last-xevent))
1781 (sry (X-Event-xbutton-root-y xwem-last-xevent))
1782 (frame (or (xwem-xwin-frame (X-Event-xbutton-event xwem-last-xevent))
1783 (xwem-frame-at srx sry))))
1785 (unless (xwem-frame-p frame)
1786 (error 'xwem-error "`xwem-frame-imove' on non-frame"))
1788 (xwem-frame-imove-internal frame srx sry)))
1789 (put 'xwem-frame-imove 'xwem-frame-command t)
1791 ;;;###autoload(autoload 'xwem-frame-iresize "xwem-frame" "" t)
1792 (define-xwem-command xwem-frame-iresize ()
1793 "Interactively resize frame"
1796 (unless (or (interactive-p)
1797 (= (X-Event-type xwem-last-xevent) X-ButtonPress))
1798 (error 'xwem-error "`xwem-frame-iresize' must be binded to mouse event"))
1800 (let* ((srx (X-Event-xbutton-root-x xwem-last-xevent))
1801 (sry (X-Event-xbutton-root-y xwem-last-xevent))
1802 (frame (or (xwem-xwin-frame (X-Event-xbutton-event xwem-last-xevent))
1803 (xwem-frame-at srx sry)))
1805 (funcall xwem-frame-imoveresize-mode-function frame 'resize))
1806 (last-xrect (and (xwem-frame-p frame)
1807 (make-X-Rect :x (xwem-frame-x frame)
1808 :y (xwem-frame-y frame)
1809 :width (- srx (xwem-frame-x frame))
1810 :height (- sry (xwem-frame-y frame)))))
1811 (curr-xrect (copy-X-Rect last-xrect))
1812 step-x step-y min-height min-width
1815 (unless (xwem-frame-p frame)
1816 (error 'xwem-error "`xwem-frame-iresize' on non-frame"))
1819 (when (xwem-frame-dedicated-p frame)
1820 (let ((sg (xwem-cl-step-geom (xwem-frame-cl frame)))
1821 (mg (xwem-cl-min-geom (xwem-frame-cl frame))))
1822 (setq step-x (car sg)
1825 min-height (cdr mg))))
1826 (unless step-x (setq step-x 1))
1827 (unless step-y (setq step-y 1))
1829 ;; Calculate minimal width/height of frame.
1830 ;; Simple sum win's min width/height so many times how many
1834 (+ xwem-win-min-width
1835 (- (xwem-frame-width frame)
1836 (xwem-win-width (xwem-frame-rootwin frame)))))
1837 (xwem-win-map #'(lambda (w)
1838 (let ((pwin (xwem-win-parent w)))
1839 (when (and (and pwin (xwem-win-hchild pwin)))
1841 (+ xwem-win-min-width
1842 (car xwem-win-horizontal-delim-width))))))
1843 (xwem-frame-selwin frame)))
1846 (+ xwem-win-min-height
1847 (- (xwem-frame-height frame)
1848 (xwem-win-height (xwem-frame-rootwin frame)))))
1849 (xwem-win-map #'(lambda (w)
1850 (let ((pwin (xwem-win-parent w)))
1851 (when (and (and pwin (xwem-win-vchild pwin)))
1853 (+ xwem-win-min-height
1854 (car xwem-win-vertical-delim-width))))))
1855 (xwem-frame-selwin frame)))
1857 ;; Adjust last-xrect according to calculated min-width/height
1858 (when (< (X-Rect-width last-xrect) min-width)
1859 (setf (X-Rect-width last-xrect) min-width))
1860 (when (< (X-Rect-height last-xrect) min-height)
1861 (setf (X-Rect-height last-xrect) min-height))
1863 (xwem-mouse-grab xwem-cursor-resize (xwem-frame-xwin frame)
1864 (Xmask-or XM-ButtonRelease XM-ButtonMotion))
1865 (unless (eq iresize-mode 'opaque)
1866 (xwem-misc-outline last-xrect iresize-mode))
1867 (xwem-unwind-protect
1869 (X-Event-CASE (setq xev (xwem-next-event))
1870 (:X-ButtonRelease (setq done t))
1873 ;; Update curr-xrect
1874 (setf (X-Rect-width curr-xrect)
1875 (- (X-Event-xmotion-root-x xev) (X-Rect-x curr-xrect)))
1876 (setf (X-Rect-height curr-xrect)
1877 (- (X-Event-xmotion-root-y xev) (X-Rect-y curr-xrect)))
1879 (when (and (or (>= (X-Rect-width curr-xrect) min-width)
1880 (>= (X-Rect-height curr-xrect) min-height))
1881 (or (> (abs (- (X-Rect-width curr-xrect)
1882 (X-Rect-width last-xrect))) step-x)
1883 (> (abs (- (X-Rect-height curr-xrect)
1884 (X-Rect-height last-xrect))) step-y)))
1885 (unless (eq iresize-mode 'opaque)
1886 (xwem-misc-outline last-xrect iresize-mode))
1887 (when (>= (X-Rect-width curr-xrect) min-width)
1888 (setf (X-Rect-width last-xrect) (X-Rect-width curr-xrect)))
1889 (when (>= (X-Rect-height curr-xrect) min-height)
1890 (setf (X-Rect-height last-xrect) (X-Rect-height curr-xrect)))
1891 (if (eq iresize-mode 'opaque)
1892 (xwem-frame-set-size
1893 frame (X-Rect-width last-xrect) (X-Rect-height last-xrect))
1894 (xwem-misc-outline last-xrect iresize-mode))
1897 (unless (eq iresize-mode 'opaque)
1898 (xwem-misc-outline last-xrect iresize-mode))
1901 (xwem-frame-set-pos frame (X-Rect-x last-xrect) (X-Rect-y last-xrect))
1902 (xwem-frame-set-size
1903 frame (X-Rect-width last-xrect) (X-Rect-height last-xrect)))
1905 (put 'xwem-frame-iresize 'xwem-frame-command t)
1908 (defun xwem-frame-clients (frame)
1909 "Make list of all clients FRAME holds."
1910 (xwem-clients-list `(lambda (cl)
1911 (eq (xwem-cl-frame cl) ,frame))))
1913 (define-xwem-face xwem-frame-inner-border-face
1914 `(((light nonselected) (:foreground "gray80" :background "gray80"))
1915 ((medium nonselected) (:foreground "gray50" :background "gray50"))
1916 ((dark nonselected) (:foreground "gray20" :background "gray20"))
1917 ((light selected) (:foreground "cyan2" :background "cyan2"))
1918 ((medium selected) (:foreground "royalblue" :background "royalblue"))
1919 ((dark selected) (:foreground "blue4" :background "blue4")))
1920 "Face to draw frame's inner border."
1924 ;;; Outline inner border
1925 (defun xwem-frame-draw-inner-border (frame)
1926 "Draw inner border for FRAME."
1927 (let* ((bw (xwem-frame-property frame 'inner-border-width))
1928 (th (or (xwem-frame-property frame 'inner-border-thickness) 1))
1929 (tag1 (if (xwem-frame-selected-p frame) 'selected 'nonselected))
1930 (wgc (xwem-face-get-gc 'xwem-frame-inner-border-face
1931 (list 'light tag1) frame))
1932 (bgc (xwem-face-get-gc 'xwem-frame-inner-border-face
1933 (list 'dark tag1) frame))
1934 (gc (xwem-face-get-gc 'xwem-frame-inner-border-face
1935 (list 'medium tag1) frame))
1940 (xwem-dpy) (xwem-frame-xwin frame)
1941 gc (mapcar #'(lambda (notused)
1943 (make-X-Rect :x off :y off
1944 :width (- (xwem-frame-width frame)
1946 :height (- (xwem-frame-height frame)
1949 (make-list (- bw (* 2 th)) nil)))
1951 (xwem-misc-draw-shadow (xwem-dpy) (xwem-frame-xwin frame)
1952 wgc bgc 0 0 (xwem-frame-width frame)
1953 (xwem-frame-height frame) th)
1954 (xwem-misc-draw-shadow (xwem-dpy) (xwem-frame-xwin frame)
1955 bgc wgc (- bw th) (- bw th)
1956 (- (xwem-frame-width frame) (* 2 (- bw th)))
1957 (- (xwem-frame-height frame) (* 2 (- bw th)))
1961 (define-xwem-deffered xwem-frame-deffered-redraw-inner-border (frame)
1962 "Redraw inner border for selected frame."
1963 (and (xwem-frame-p frame)
1964 (xwem-frame-draw-inner-border frame)))
1967 (defvar xwem-frame-showing-mode-hook nil
1968 "Hooks to call when entering/leaving showing mode.
1969 Each hook called with two arguments: FRAME and MODE,
1970 where mode is one of:
1972 `enter' - FRAME enters showing mode.
1973 `leave' - FRAME leaving showing mode.")
1975 (defun xwem-frame-enter-showing-mode (frame)
1976 "Enable showing mode for FRAME."
1977 (unless (eq (xwem-frame-property frame 'showing-mode) 'on)
1978 (let ((fcls (xwem-frame-clients frame)))
1979 (mapc 'xwem-iconify fcls)
1981 (xwem-frame-put-prop frame 'showing-mode 'on)
1982 (run-hook-with-args 'xwem-frame-showing-mode-hook frame 'enter))))
1984 (defun xwem-frame-leave-showing-mode (frame)
1985 "Disable showing mode."
1986 (unless (eq (xwem-frame-property frame 'showing-mode) 'off)
1987 (let ((fcls (xwem-frame-clients frame)))
1988 (mapcar 'xwem-manage fcls)
1990 (xwem-frame-put-prop frame 'showing-mode 'off)
1991 (run-hook-with-args 'xwem-frame-showing-mode-hook frame 'leave))))
1993 ;;; Frame properties
1994 (defvar xwem-frame-supported-properties nil
1995 "*List of supported frame properties.")
1997 (defmacro define-xwem-frame-property (prop doc &rest keys-val)
1998 "Define new frame property PROP.
1999 DOC is doc-string for property and KEYS-VAL is a list of keyword-value
2000 pairs. Supported keywords are:
2002 :type - Type of property (same as in `defcustom')
2003 :set - Function to set property.
2004 :get - Function to get property value.
2005 :notifiers - Functions to call when new value for property is set.
2008 (add-to-list 'xwem-frame-supported-properties (quote ,prop))
2009 (put (quote ,prop) 'xwem-property-definition (list :doc ,doc ,@keys-val))))
2011 (defun xwem-frame-get-prop-keyword (prop keyword &optional default)
2012 "Return PROP's KEYWORD value.
2013 Return DEFAULT is KEYWORD not found."
2014 (plist-get (get prop 'xwem-property-definition) keyword default))
2017 (defun xwem-frame-add-property-notifier (prop notifier)
2018 (let ((notifiers (xwem-frame-get-prop-keyword prop :notifiers)))
2020 (setcdr (last notifiers) (cons notifier nil))
2021 (put prop 'xwem-property-definition
2022 (plist-put (get prop 'xwem-property-definition)
2023 :notifiers (list notifier))))))
2026 (defun xwem-frame-set-property (frame prop val)
2027 "Set FRAME's propertie PROP to VAL.
2028 If FRAME is nil - selected frame is used."
2030 (setq frame (xwem-frame-selected)))
2031 (unless (equal (xwem-frame-property frame prop) val)
2032 (funcall (xwem-frame-get-prop-keyword prop :set 'xwem-frame-put-prop)
2035 (mapc #'(lambda (notifier) (funcall notifier frame prop val))
2036 (xwem-frame-get-prop-keyword prop :notifiers))))
2039 (defun xwem-frame-set-properties (frame props-plist)
2040 "Set FRAME properties PROPS."
2042 (xwem-frame-set-property frame (car props-plist) (cadr props-plist))
2043 (setq props-plist (cddr props-plist))))
2046 (defun xwem-frame-property (frame prop)
2047 "Return value for FRAME's property PROP.
2048 If FRAME is nil - selected frame is used."
2049 (funcall (xwem-frame-get-prop-keyword prop :get 'xwem-frame-get-prop)
2050 (or frame (xwem-frame-selected)) prop))
2053 (defun xwem-frame-properties (&optional frame)
2054 "Return a list of FRAME's properties.
2055 List is copied, you are free to modify it for your needs.
2056 Note that only supported properties are returned.
2057 If FRAME is omitted - selected frame is used."
2058 (let ((fplist (xwem-frame-plist (or frame (xwem-frame-selected))))
2061 (when (memq (car fplist) xwem-frame-supported-properties)
2062 (setq rplist (plist-put rplist (car fplist) (cadr fplist))))
2063 (setq fplist (cddr fplist)))
2066 ;; Define some basic properties
2067 (defun xwem-frame-setup-root-win (frame)
2068 (let ((tl (xwem-frame-property frame 'title-layout))
2069 (th (xwem-frame-property frame 'title-height))
2070 (ibw (xwem-frame-property frame 'inner-border-width))
2071 (fw (xwem-frame-width frame))
2072 (fh (xwem-frame-height frame))
2073 (root-win (xwem-frame-rootwin frame))
2079 h (- fh th ibw ibw)))
2084 h (- fh th ibw ibw)))
2101 (setf (xwem-win-x root-win) x
2102 (xwem-win-y root-win) y)
2103 (xwem-win-set-width root-win w)
2104 (xwem-win-set-height root-win h)))
2106 (defun xwem-frame-set-title-height (frame prop new-height)
2107 "Set FRAME's title height property PROP to NEW-HEIGHT."
2108 (let ((old-height (xwem-frame-property frame prop)))
2109 (xwem-frame-put-prop frame prop new-height)
2111 ;; Adjust root window position/size
2112 (when (and new-height old-height (xwem-frame-rootwin frame))
2113 (incf (xwem-win-y (xwem-frame-rootwin frame))
2114 (- new-height old-height))
2115 (xwem-frame-setup-root-win frame))))
2117 (defun xwem-frame-get-title-height (frame prop)
2118 "Return FRAME's title height."
2119 (or (xwem-frame-get-prop frame prop)
2122 (define-xwem-frame-property title-height
2123 "Frame's title height in pixels."
2125 :set 'xwem-frame-set-title-height
2126 :get 'xwem-frame-get-title-height)
2128 (defcustom xwem-frame-default-title-layout 'top
2129 "*Default FRAME's title layout."
2130 :type '(choice (const :tag "No title" none)
2131 (const :tag "Top" top)
2132 (const :tag "Bottom" bottom)
2133 (const :tag "Left" left)
2134 (const :tag "Right" right))
2137 (defun xwem-frame-get-title-layout (frame prop)
2138 "Return FRAME's title layout."
2139 (or (xwem-frame-get-prop frame prop)
2140 xwem-frame-default-title-layout))
2142 (defun xwem-frame-set-title-layout (frame prop new-layout)
2143 "Set FRAME's title layout property PROP to NEW-LAYOUT."
2144 (unless (memq new-layout '(left right top bottom none))
2145 (error 'xwem-error "Invalid title layout %S" new-layout))
2147 (xwem-frame-put-prop frame prop new-layout)
2148 (xwem-frame-setup-root-win frame))
2150 (define-xwem-frame-property title-layout
2151 "Frame's title layout property."
2152 :type '(choice (const :tag "Top" top)
2153 (const :tag "Bottom" bottom)
2154 (const :tag "Left" left)
2155 (const :tag "Right" right))
2156 :get 'xwem-frame-get-title-layout
2157 :set 'xwem-frame-set-title-layout)
2159 (defun xwem-frame-get-outer-border-width (frame prop)
2160 "Return FRAME's outer border width."
2161 (X-Geom-border-width (xwem-frame-xgeom frame)))
2163 (defun xwem-frame-set-outer-border-width (frame prop val)
2164 "Return FRAME's outer border width."
2166 (setf (X-Geom-border-width (xwem-frame-xgeom frame)) val)
2167 (XSetWindowBorderWidth (xwem-dpy) (xwem-frame-xwin frame)
2168 (X-Geom-border-width (xwem-frame-xgeom frame)))))
2170 (define-xwem-frame-property outer-border-width
2171 "Frame's outer border width in pixels."
2173 :get 'xwem-frame-get-outer-border-width
2174 :set 'xwem-frame-set-outer-border-width)
2176 (defun xwem-frame-set-outer-border-color (frame prop val)
2177 "Set FRAME's outer border color to VAL."
2178 (xwem-frame-put-prop frame prop val)
2181 (XSetWindowBorder (xwem-dpy) (xwem-frame-xwin frame)
2182 (XAllocColor (xwem-dpy) (XDefaultColormap (xwem-dpy))
2183 (xwem-make-color val)))))
2185 (define-xwem-frame-property outer-border-color
2186 "Frame's outer border color."
2188 :set 'xwem-frame-set-outer-border-color)
2190 (defun xwem-frame-set-inner-border-width (frame prop val)
2191 "Set FRAME's inner border property PROP to VAL."
2192 (xwem-frame-put-prop frame prop val)
2195 (when (xwem-frame-rootwin frame)
2196 (xwem-frame-setup-root-win frame)
2197 (xwem-deffered-funcall 'xwem-frame-draw frame t)))
2199 (defun xwem-frame-get-inner-border-width (frame prop)
2200 (or (xwem-frame-get-prop frame 'inner-border-width)
2203 (define-xwem-frame-property inner-border-width
2204 "Frame's inner border width in pixels."
2206 :get 'xwem-frame-get-inner-border-width
2207 :set 'xwem-frame-set-inner-border-width)
2209 (defun xwem-frame-set-inner-border-thickness (frame prop val)
2210 "Set FRAME's inner border width PROP to VAL."
2211 (when (and val (> (* val 2) (xwem-frame-property frame 'inner-border-width)))
2212 (error 'xwem-error "To large thickness to fill in title-height"))
2214 (xwem-frame-put-prop frame prop val)
2216 (xwem-deffered-funcall 'xwem-frame-draw frame nil)))
2218 (define-xwem-frame-property inner-border-thickness
2219 "Frame's inner border thickness."
2221 :set 'xwem-frame-set-inner-border-thickness)
2223 (defun xwem-frame-set-background (frame prop val)
2224 "Set FRAME's background color to VAL."
2225 (xwem-frame-put-prop frame prop val)
2228 (XSetWindowBackground (xwem-dpy) (xwem-frame-xwin frame)
2229 (XAllocColor (xwem-dpy) (XDefaultColormap (xwem-dpy))
2230 (xwem-make-color val)))
2231 (xwem-deffered-funcall 'xwem-frame-draw frame t)))
2233 (define-xwem-frame-property background
2234 "Frame's background color."
2236 :set 'xwem-frame-set-background)
2238 (defun xwem-frame-set-showing-mode (frame prop val)
2239 "Set FRAME's showing mode PROP to VAL."
2240 (xwem-frame-put-prop frame prop val)
2242 (xwem-frame-enter-showing-mode frame)
2243 (xwem-frame-leave-showing-mode frame)))
2245 (define-xwem-frame-property showing-mode
2246 "Frame's showing mode."
2248 :set 'xwem-frame-set-showing-mode)
2251 (provide 'xwem-frame)
2253 ;;; xwem-frame.el ends here