2003-03-27 20:40:16 -05:00
|
|
|
(define-record-type root-wm :root-wm
|
2003-03-29 20:46:01 -05:00
|
|
|
(make-root-wm dpy managers current-manager in-channel)
|
2003-03-27 20:40:16 -05:00
|
|
|
root-wm?
|
|
|
|
(dpy root-wm:dpy)
|
|
|
|
(managers root-wm:managers set-root-wm:managers!)
|
2003-03-29 20:46:01 -05:00
|
|
|
(current-manager root-wm:current-manager set-root-wm:current-manager!)
|
|
|
|
(in-channel root-wm:in-channel))
|
2003-03-27 20:40:16 -05:00
|
|
|
|
|
|
|
(define (create-root-wm dpy)
|
|
|
|
(let* ((window (default-root-window dpy))
|
|
|
|
(children (window-children dpy window))
|
|
|
|
(in-channel (make-channel))
|
2003-03-29 20:46:01 -05:00
|
|
|
(root-wm (make-root-wm dpy '() #f in-channel))
|
2003-03-27 20:40:16 -05:00
|
|
|
(initial-manager (create-move-wm in-channel dpy window '())))
|
|
|
|
(mdisplay "creating root-wm\n")
|
|
|
|
(set-root-wm:current-manager! root-wm initial-manager)
|
2003-03-29 20:46:01 -05:00
|
|
|
(add-manager! root-wm initial-manager)
|
2003-03-27 20:40:16 -05:00
|
|
|
|
|
|
|
(map-window dpy (wm:window initial-manager))
|
|
|
|
|
|
|
|
(for-each (lambda (window)
|
|
|
|
(wm-manage-window initial-manager window))
|
|
|
|
children)
|
2003-03-29 20:46:01 -05:00
|
|
|
|
|
|
|
(grab-shortcut dpy window (string->keys dpy "M-k h") ;; -> options!
|
|
|
|
'split-horizontal in-channel #t)
|
|
|
|
(grab-shortcut dpy window (string->keys dpy "M-k v")
|
|
|
|
'split-vertical in-channel #t)
|
2003-03-27 20:40:16 -05:00
|
|
|
|
|
|
|
(call-with-event-channel
|
|
|
|
dpy window (event-mask substructure-redirect)
|
|
|
|
(lambda (event-channel)
|
|
|
|
(call-with-current-continuation
|
|
|
|
(lambda (exit)
|
|
|
|
(let loop ()
|
|
|
|
(select*
|
|
|
|
(wrap (receive-rv event-channel)
|
|
|
|
(lambda (xevent)
|
|
|
|
(handle-xevent root-wm exit xevent)))
|
|
|
|
(wrap (receive-rv in-channel)
|
|
|
|
(lambda (msg)
|
|
|
|
(handle-message root-wm exit msg))))
|
|
|
|
(loop))))))))
|
|
|
|
|
|
|
|
(define (handle-xevent root-wm exit xevent)
|
|
|
|
(let ((type (any-event-type xevent))
|
|
|
|
(dpy (root-wm:dpy root-wm)))
|
|
|
|
(cond
|
|
|
|
((configure-request-event? xevent)
|
|
|
|
;; TODO: maybe let it configure by the future manager...
|
|
|
|
(configure-window dpy (configure-request-event-window xevent)
|
|
|
|
(configure-request-event-window-change-alist xevent)))
|
|
|
|
((map-request-event? xevent)
|
|
|
|
(wm-manage-window (root-wm:current-manager root-wm)
|
|
|
|
(map-request-event-window xevent)
|
|
|
|
#f))
|
|
|
|
)))
|
|
|
|
|
|
|
|
(define (handle-message root-wm exit msg)
|
2003-03-29 20:46:01 -05:00
|
|
|
(case (car msg)
|
|
|
|
((split-vertical split-horizontal)
|
|
|
|
(let* ((current (root-wm:current-manager root-wm))
|
|
|
|
(parent (manager-parent root-wm current)) ;; #f if root
|
|
|
|
(dpy (wm:dpy current))
|
|
|
|
(in-channel (root-wm:in-channel root-wm))
|
|
|
|
(orientation (if (eq? 'split-vertical (car msg))
|
|
|
|
'vertical 'horizontal))
|
2003-04-01 08:18:38 -05:00
|
|
|
(splitter (create-split-wm in-channel dpy
|
|
|
|
(window-parent dpy (wm:window current))
|
2003-03-29 20:46:01 -05:00
|
|
|
;; TODO other options
|
|
|
|
(list (cons 'orientation orientation))))
|
|
|
|
(first current)
|
2003-04-01 08:18:38 -05:00
|
|
|
;; TODO: ask for second manager
|
2003-03-29 20:46:01 -05:00
|
|
|
(second (create-switch-wm in-channel dpy (wm:window splitter)
|
2003-04-01 08:18:38 -05:00
|
|
|
;; TODO options
|
2003-03-29 20:46:01 -05:00
|
|
|
'())))
|
2003-04-01 08:18:38 -05:00
|
|
|
;; we just replace the client:window
|
|
|
|
(if parent
|
|
|
|
(client-replace-window parent (wm:window current)
|
|
|
|
(wm:window splitter))
|
|
|
|
(map-window dpy (wm:window splitter))) ;; maybe resize ??
|
2003-03-29 20:46:01 -05:00
|
|
|
(wm-manage-window splitter (wm:window first))
|
|
|
|
(wm-manage-window splitter (wm:window second))
|
2003-04-01 08:18:38 -05:00
|
|
|
|
2003-03-29 20:46:01 -05:00
|
|
|
(add-manager! root-wm splitter)
|
|
|
|
(add-manager! root-wm second)))
|
2003-04-01 08:18:38 -05:00
|
|
|
|
2003-03-29 20:46:01 -05:00
|
|
|
((manager-focused)
|
|
|
|
(let ((manager (second msg)))
|
2003-04-01 08:18:38 -05:00
|
|
|
;; a split-wm should never be the current manager
|
|
|
|
(if (not (eq? (manager-type split) (wm:type manager)))
|
|
|
|
(set-root-wm:current-manager! root-wm manager))))
|
|
|
|
((root-drop)
|
|
|
|
(let ((window (second msg))
|
|
|
|
(pointer-x (third msg))
|
|
|
|
(pointer-y (fourth msg)))
|
|
|
|
(let ((manager (find-manager-at root-wm pointer-x pointer-y)))
|
|
|
|
(if manager
|
|
|
|
(wm-manage-window manager window)
|
|
|
|
(mdisplay "did not find a manager at " pointer-x ":"
|
|
|
|
pointer-y "\n")))))
|
2003-03-29 20:46:01 -05:00
|
|
|
(else (mdisplay "unknown root message: " msg "\n"))))
|
2003-03-27 20:40:16 -05:00
|
|
|
|
|
|
|
;; *** observing managers ********************************************
|
|
|
|
|
2003-03-29 20:46:01 -05:00
|
|
|
(define (add-manager! root-wm manager)
|
|
|
|
(set-root-wm:managers! root-wm (cons manager
|
|
|
|
(root-wm:managers root-wm)))
|
|
|
|
(spawn*
|
|
|
|
(lambda (release)
|
|
|
|
(call-with-event-channel
|
|
|
|
(root-wm:dpy root-wm) (wm:window manager)
|
|
|
|
(event-mask structure-notify
|
|
|
|
focus-change)
|
|
|
|
(lambda (event-channel)
|
|
|
|
(release)
|
|
|
|
(let loop ()
|
|
|
|
(let ((e (receive event-channel)))
|
|
|
|
(cond
|
|
|
|
((destroy-window-event? e) #t)
|
|
|
|
((focus-change-event? e)
|
|
|
|
;; look at mode/detail ??
|
|
|
|
(if (window-contains-focus? (root-wm:dpy root-wm)
|
|
|
|
(wm:window manager))
|
|
|
|
(send (root-wm:in-channel root-wm)
|
|
|
|
(list 'manager-focused manager)))
|
|
|
|
(loop))
|
|
|
|
(else (loop))))
|
|
|
|
(loop)))))))
|
|
|
|
|
|
|
|
(define (manager-parent root-wm manager)
|
|
|
|
(let loop ((parent-window (window-parent (root-wm:dpy root-wm)
|
|
|
|
(wm:window manager))))
|
|
|
|
(if (zero? parent-window)
|
|
|
|
#f
|
|
|
|
(let ((l (filter (lambda (m)
|
|
|
|
(equal? (wm:window m) parent-window))
|
|
|
|
(root-wm:managers root-wm))))
|
|
|
|
(if (null? l)
|
|
|
|
(loop (window-parent (root-wm:dpy root-wm)
|
|
|
|
parent-window))
|
|
|
|
(car l))))))
|
2003-04-01 08:18:38 -05:00
|
|
|
|
|
|
|
(define (find-manager-at root-wm x y)
|
|
|
|
;; returns the upper-most manager at root-window's coords x y
|
|
|
|
(let* ((dpy (root-wm:dpy root-wm))
|
|
|
|
(candidates
|
|
|
|
(filter (lambda (wm)
|
|
|
|
(point-in-rectangle? (root-rectangle dpy (wm:window wm))
|
|
|
|
x y))
|
|
|
|
(root-wm:managers root-wm))))
|
|
|
|
(letrec ((loop (lambda (wm level rest)
|
|
|
|
(if (null? rest)
|
|
|
|
wm
|
|
|
|
(let* ((next (car rest))
|
|
|
|
(next-level (window-level dpy
|
|
|
|
(wm:window next))))
|
|
|
|
(if (> next-level level)
|
|
|
|
(loop next next-level (cdr rest))
|
|
|
|
(loop wm level (cdr rest))))))))
|
|
|
|
(loop #f -1 candidates))))
|