separated default options (config) and saved options (layout)
added some synchronization optimized focus-control cleaned up a bit
This commit is contained in:
parent
315a71013a
commit
de00f837dc
256
src/manager.scm
256
src/manager.scm
|
@ -37,7 +37,7 @@
|
|||
((eq? type (manager-type switch)) "switch-wm")
|
||||
((eq? type (manager-type move)) "move-wm")))
|
||||
|
||||
(define (create-wm dpy parent options children
|
||||
(define (create-wm dpy parent options default-options children
|
||||
type options-spec out-channel fun)
|
||||
(let* ((wa (get-window-attributes dpy parent))
|
||||
(main-window
|
||||
|
@ -52,8 +52,10 @@
|
|||
(wm (make-wm type in-channel out-channel internal-out-channel
|
||||
dpy main-window colormap
|
||||
(create-options dpy colormap
|
||||
(options-spec-union options-spec
|
||||
manager-options-spec)
|
||||
(spec-defaults default-options
|
||||
(options-spec-union
|
||||
options-spec
|
||||
manager-options-spec))
|
||||
options)
|
||||
'() #f)))
|
||||
|
||||
|
@ -118,8 +120,18 @@
|
|||
(send internal-out-channel '(fit-windows)))
|
||||
|
||||
((focus-change-event? xevent)
|
||||
;; really send it always ??
|
||||
(send internal-out-channel '(update-manager-state)))
|
||||
(if (window-exists? dpy (wm:window wm))
|
||||
(let ((mode (focus-change-event-mode xevent))
|
||||
(detail (focus-change-event-detail xevent)))
|
||||
(if (and (eq? mode (notify-mode normal))
|
||||
(memq detail (list (notify-detail nonlinear)
|
||||
(notify-detail nonlinear-virtual)
|
||||
(notify-detail virtual)
|
||||
(notify-detail ancestor))))
|
||||
(let ((focused? (eq? (event-type focus-in)
|
||||
(focus-change-event-type xevent))))
|
||||
(send internal-out-channel
|
||||
(list 'update-manager-state focused?)))))))
|
||||
|
||||
;; the manager got the focus (as a client)
|
||||
((client-message-event? xevent)
|
||||
|
@ -147,90 +159,78 @@
|
|||
(let ((internal-out-channel (wm:internal-out-channel wm))
|
||||
(dpy (wm:dpy wm)))
|
||||
(case (car msg)
|
||||
((manage-window)
|
||||
(let ((window (second msg))
|
||||
(maybe-rect (third msg)))
|
||||
(let ((client (create-client wm window)))
|
||||
(set-wm:clients! wm (append (wm:clients wm) (list client)))
|
||||
(send internal-out-channel
|
||||
(list 'init-client client maybe-rect))
|
||||
;; sync??
|
||||
;;(if (window-exists? dpy window)
|
||||
;; (map-window dpy window))
|
||||
;;(send internal-out-channel (list 'fit-client client))
|
||||
;;(send internal-out-channel (list 'update-client-state client))
|
||||
)))
|
||||
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
(send internal-out-channel
|
||||
(list 'configure-window window changes))))
|
||||
|
||||
((unmanage-window)
|
||||
(let* ((window (second msg))
|
||||
(client (find (lambda (c)
|
||||
(eq? window (client:window c)))
|
||||
(wm:clients wm))))
|
||||
(if client
|
||||
(reparent-to-root dpy window))))
|
||||
|
||||
((destroy-manager)
|
||||
;; (send internal-out-channel '(deinit-manager))
|
||||
;; sync ??
|
||||
(if (window-exists? dpy (wm:window wm))
|
||||
(destroy-window dpy (wm:window wm))))
|
||||
|
||||
((deinit-client)
|
||||
(let ((client (second msg)))
|
||||
(set-wm:clients! wm (filter (lambda (c) (not (eq? c client)))
|
||||
(wm:clients wm)))
|
||||
(if (eq? (wm:current-client wm) client)
|
||||
(set-wm:current-client! wm (and (not (null? (wm:clients wm)))
|
||||
(car (wm:clients wm)))))
|
||||
(send (wm:internal-out-channel wm) (list 'deinit-client client))
|
||||
;; sync ??
|
||||
(destroy-window dpy (client:client-window client))))
|
||||
|
||||
((select-client)
|
||||
(let ((client (second msg))
|
||||
(time (third msg)))
|
||||
(for-each (lambda (client)
|
||||
(set-wm:current-client! wm client)
|
||||
(raise-window dpy (client:client-window client))
|
||||
(if (window-exists? dpy (client:window client))
|
||||
(take-focus dpy (client:window client) time)))
|
||||
(cons client (transients-for-client wm client)))
|
||||
; (for-each (lambda (c)
|
||||
; (if (not (eq? c client))
|
||||
; (grab-button dpy
|
||||
; (button button1) (state-set)
|
||||
; (client:client-window c) #f
|
||||
; (event-mask button-press)
|
||||
; (grab-mode async) (grab-mode async)
|
||||
; none none)))
|
||||
; (wm:clients wm))
|
||||
))
|
||||
|
||||
)))
|
||||
((wait)
|
||||
(let ((sp (second msg))
|
||||
(message (third msg)))
|
||||
(handle-external-message wm exit message)
|
||||
(sync-point-release sp)))
|
||||
|
||||
((manage-window)
|
||||
(let ((window (second msg))
|
||||
(maybe-rect (third msg)))
|
||||
(let ((client (create-client wm window)))
|
||||
(set-wm:clients! wm (append (wm:clients wm) (list client)))
|
||||
(send-message+wait internal-out-channel
|
||||
(list 'init-client client maybe-rect)))))
|
||||
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
(send-message+wait internal-out-channel
|
||||
(list 'configure-window window changes))))
|
||||
|
||||
((unmanage-window)
|
||||
(let* ((window (second msg))
|
||||
(client (find (lambda (c)
|
||||
(eq? window (client:window c)))
|
||||
(wm:clients wm))))
|
||||
(if client
|
||||
(reparent-to-root dpy window))))
|
||||
|
||||
((destroy-manager)
|
||||
(send-message+wait internal-out-channel '(deinit-manager))
|
||||
(if (window-exists? dpy (wm:window wm))
|
||||
(destroy-window dpy (wm:window wm))))
|
||||
|
||||
((deinit-client)
|
||||
(let ((client (second msg)))
|
||||
(set-wm:clients! wm (filter (lambda (c) (not (eq? c client)))
|
||||
(wm:clients wm)))
|
||||
(if (eq? (wm:current-client wm) client)
|
||||
;; select-client ??
|
||||
(set-wm:current-client! wm (and (not (null? (wm:clients wm)))
|
||||
(car (wm:clients wm)))))
|
||||
(send-message+wait (wm:internal-out-channel wm)
|
||||
(list 'deinit-client client))
|
||||
(destroy-window dpy (client:client-window client))))
|
||||
|
||||
((select-client)
|
||||
(let ((client (second msg))
|
||||
(time (third msg)))
|
||||
(for-each (lambda (client)
|
||||
(set-wm:current-client! wm client)
|
||||
(raise-window dpy (client:client-window client))
|
||||
(if (window-exists? dpy (client:window client))
|
||||
(take-focus dpy (client:window client) time)))
|
||||
(cons client (transients-for-client wm client)))))
|
||||
|
||||
(else (warn "unhandled manager message" wm msg)))))
|
||||
|
||||
(define (wm-deinit-client wm client)
|
||||
(mdisplay "manager deinit-client " wm " " client "\n")
|
||||
(send (wm:in-channel wm) (list 'deinit-client client)))
|
||||
|
||||
;; *** external messages *********************************************
|
||||
|
||||
(define (wm-manage-window wm window . rect)
|
||||
(send (wm:in-channel wm)
|
||||
(list 'manage-window window
|
||||
(if (null? rect)
|
||||
#f
|
||||
(car rect))))
|
||||
;; sync ??
|
||||
)
|
||||
(let ((maybe-rect (if (null? rect)
|
||||
#f
|
||||
(car rect))))
|
||||
(send-message+wait (wm:in-channel wm)
|
||||
(list 'manage-window window maybe-rect))))
|
||||
|
||||
(define (wm-configure-window wm window changes)
|
||||
(send (wm:in-channel wm) (list 'configure-window window changes)))
|
||||
(send-message+wait (wm:in-channel wm)
|
||||
(list 'configure-window window changes)))
|
||||
|
||||
(define (wm-unmanage-window wm window)
|
||||
(send (wm:in-channel wm) (list 'unmanage-window window)))
|
||||
|
@ -240,7 +240,7 @@
|
|||
(send (wm:in-channel wm) (list 'select-client client time)))))
|
||||
|
||||
(define (destroy-wm wm)
|
||||
(send (wm:in-channel wm) '(destroy-manager)))
|
||||
(send-message+wait (wm:in-channel wm) '(destroy-manager)))
|
||||
|
||||
(define (send-root-drop wm window x y)
|
||||
(send (wm:out-channel wm) (list 'root-drop window x y)))
|
||||
|
@ -248,19 +248,27 @@
|
|||
;; *** client ********************************************************
|
||||
|
||||
(define-record-type client :client
|
||||
(make-client window client-window in-channel data)
|
||||
(make-client window client-window in-channel data focused?)
|
||||
client?
|
||||
(window client:window set-client:window!)
|
||||
(client-window client:client-window)
|
||||
(in-channel client:in-channel)
|
||||
(data client:data set-client:data!))
|
||||
(data client:data set-client:data!)
|
||||
(focused? client:focused? set-client:focused?!))
|
||||
|
||||
(define (set-client-focused?! wm client focused?)
|
||||
(let ((prev (client:focused? client)))
|
||||
(if (not (eq? prev focused?))
|
||||
(begin
|
||||
(set-client:focused?! client focused?)
|
||||
(send (wm:internal-out-channel wm)
|
||||
(list 'update-client-state client focused?))))))
|
||||
|
||||
(define-record-discloser :client
|
||||
(lambda (c)
|
||||
`(Client ,(client:window c) in ,(client:client-window c))))
|
||||
|
||||
(define (create-client wm window)
|
||||
(mdisplay "creating client for " window "\n")
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
(client-window (create-simple-window dpy (wm:window wm)
|
||||
0 0
|
||||
|
@ -270,10 +278,9 @@
|
|||
(white-pixel dpy)
|
||||
(black-pixel dpy)))
|
||||
(in-channel (make-channel))
|
||||
(client (make-client window client-window in-channel #f)))
|
||||
(client (make-client window client-window in-channel #f #f)))
|
||||
(reparent-window dpy window client-window 0 0)
|
||||
(create-client-handler wm client)
|
||||
;;(map-window dpy window)
|
||||
client))
|
||||
|
||||
(define (create-client-handler wm client)
|
||||
|
@ -303,9 +310,11 @@
|
|||
(lambda (msg)
|
||||
(case (car msg)
|
||||
((restart-handler)
|
||||
(mdisplay "restart-handler " wm " " client "\n")
|
||||
(create-client-handler wm client)
|
||||
(exit 'restart)))))
|
||||
(sync-point-release (second msg))
|
||||
(exit 'restart))
|
||||
(else (warn "unhandled client message" wm
|
||||
client msg)))))
|
||||
(wrap (receive-rv client-window-channel)
|
||||
(lambda (xevent)
|
||||
(handle-client-window-xevent wm exit client xevent)))
|
||||
|
@ -315,13 +324,11 @@
|
|||
(loop)))))))))))
|
||||
|
||||
(define (client-of-window wm window)
|
||||
(let ((l (filter (lambda (client)
|
||||
(equal? window (client:window client)))
|
||||
(wm-clients wm))))
|
||||
(and (pair? l) (car l))))
|
||||
(find (lambda (client)
|
||||
(equal? window (client:window client)))
|
||||
(wm-clients wm)))
|
||||
|
||||
(define (client-replace-window wm old-window new-window)
|
||||
(mdisplay "client-replace-window: " wm " " old-window " " new-window "\n")
|
||||
(let ((client (client-of-window wm old-window))
|
||||
(internal-out-channel (wm:internal-out-channel wm))
|
||||
(dpy (wm:dpy wm)))
|
||||
|
@ -332,16 +339,14 @@
|
|||
(client:client-window client)))
|
||||
(reparent-window dpy new-window (client:client-window client)
|
||||
0 0))
|
||||
(send (client:in-channel client) '(restart-handler))
|
||||
;; wait ?!
|
||||
;; update everything... TODO
|
||||
;;(send internal-out-channel (list 'init-client client #f))
|
||||
(send internal-out-channel (list 'fit-client client))
|
||||
;;(send internal-out-channel (list 'fit-windows client))
|
||||
;; sync ??
|
||||
(map-window (wm:dpy wm) new-window)
|
||||
(send internal-out-channel (list 'update-client-state client))
|
||||
)
|
||||
(let ((sp (make-sync-point)))
|
||||
(send (client:in-channel client)
|
||||
(list 'restart-handler sp))
|
||||
(sync-point-wait sp))
|
||||
(send-message+wait internal-out-channel (list 'fit-client client))
|
||||
(send internal-out-channel
|
||||
(list 'update-client-name client (client-name dpy client)))
|
||||
(map-window (wm:dpy wm) new-window))
|
||||
#f)))
|
||||
|
||||
(define (handle-client-window-xevent wm exit client xevent)
|
||||
|
@ -370,18 +375,17 @@
|
|||
changes))
|
||||
(send internal-out-channel (list 'fit-client-window client)))
|
||||
(send-configuration dpy (client:window client)))))
|
||||
((circulate-event? xevent)
|
||||
(send internal-out-channel (list 'update-client-state client)))
|
||||
;; ((circulate-event? xevent)
|
||||
;; (send internal-out-channel (list 'update-client-state client)))
|
||||
((eq? (event-type enter-notify) type)
|
||||
(if (memq 'enter (get-option-value (wm:options wm) 'focus-policy))
|
||||
(wm-select-client wm client (crossing-event-time xevent))))
|
||||
|
||||
((eq? (event-type button-press) type)
|
||||
(if (memq 'click (get-option-value (wm:options wm) 'focus-policy))
|
||||
(wm-select-client wm client (button-event-time xevent))))
|
||||
;; ((eq? (event-type button-press) type)
|
||||
;; (if (memq 'click (get-option-value (wm:options wm) 'focus-policy))
|
||||
;; (wm-select-client wm client (button-event-time xevent))))
|
||||
|
||||
((destroy-window-event? xevent)
|
||||
(mdisplay "client-window destroyed" wm client "\n")
|
||||
(exit 'destroy)))))
|
||||
|
||||
(define (handle-client-xevent wm exit client xevent)
|
||||
|
@ -389,29 +393,23 @@
|
|||
(internal-out-channel (wm:internal-out-channel wm))
|
||||
(dpy (wm:dpy wm)))
|
||||
(cond
|
||||
((eq? (event-type focus-out) type)
|
||||
((focus-change-event? xevent)
|
||||
(if (window-exists? dpy (client:window client))
|
||||
(let ((mode (focus-change-event-mode xevent))
|
||||
(detail (focus-change-event-detail xevent)))
|
||||
(if (and (eq? mode (notify-mode normal))
|
||||
(memq detail (list (notify-detail nonlinear)
|
||||
(notify-detail nonlinear-virtual)
|
||||
(notify-detail virtual)
|
||||
(notify-detail ancestor))))
|
||||
(uninstall-colormaps dpy (client:window client)))))
|
||||
(send internal-out-channel
|
||||
(list 'update-client-state client)))
|
||||
|
||||
((eq? (event-type focus-in) type)
|
||||
(if (window-exists? dpy (client:window client))
|
||||
(let ((mode (focus-change-event-mode xevent))
|
||||
(detail (focus-change-event-detail xevent)))
|
||||
(if (and (eq? mode (notify-mode normal))
|
||||
(memq detail (list (notify-detail nonlinear)
|
||||
(notify-detail nonlinear-virtual)
|
||||
(notify-detail ancestor))))
|
||||
(install-colormaps dpy (client:window client)))))
|
||||
(send internal-out-channel
|
||||
(list 'update-client-state client)))
|
||||
(if (eq? (event-type focus-in)
|
||||
(focus-change-event-type xevent))
|
||||
(begin
|
||||
(install-colormaps dpy (client:window client))
|
||||
(set-client-focused?! wm client #t))
|
||||
(begin
|
||||
(uninstall-colormaps dpy (client:window client))
|
||||
(set-client-focused?! wm client #f)))))))
|
||||
|
||||
((property-event? xevent)
|
||||
(if (window-exists? dpy (client:window client))
|
||||
|
@ -420,20 +418,18 @@
|
|||
(cond
|
||||
((equal? "WM_NAME" name)
|
||||
(send internal-out-channel
|
||||
(list 'update-client-state client)))
|
||||
;; TODO: respect NORMAL_HINTS change
|
||||
))))
|
||||
(list 'update-client-name client
|
||||
(client-name dpy client))))))))
|
||||
|
||||
((reparent-event? xevent)
|
||||
(if (and (window-exists? dpy (client:window client))
|
||||
(not (eq? (client:client-window client)
|
||||
(window-parent dpy (client:window client)))))
|
||||
(begin
|
||||
;; window has been reparented away
|
||||
(mdisplay "manager " (wm:type wm) " reparented client\n")
|
||||
(wm-deinit-client wm client)
|
||||
(exit 'reparent))))
|
||||
((destroy-window-event? xevent)
|
||||
(mdisplay "destroy-window-event client " wm " " client "\n")
|
||||
(if (eq? (client:window client) (destroy-window-event-event xevent))
|
||||
(begin
|
||||
(wm-deinit-client wm client)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
xc-bottom-side xc-bottom-left-corner default-cursor))))
|
||||
|
||||
(spawn*
|
||||
(list 'move-wm-resizer wm client)
|
||||
(lambda (release)
|
||||
(call-with-event-channel
|
||||
dpy window
|
||||
|
@ -34,13 +35,14 @@
|
|||
(lambda ()
|
||||
(let ((xevent (receive event-channel)))
|
||||
(cond
|
||||
((motion-event? xevent)
|
||||
((and (motion-event? xevent) (window-exists? dpy window))
|
||||
(set-resize-cursor wm client cursors
|
||||
(motion-event-x xevent)
|
||||
(motion-event-y xevent))
|
||||
(idle))
|
||||
((eq? (event-type button-press)
|
||||
(any-event-type xevent))
|
||||
((and (eq? (event-type button-press)
|
||||
(any-event-type xevent))
|
||||
(window-exists? dpy window))
|
||||
(let* ((x (button-event-x xevent))
|
||||
(y (button-event-y xevent))
|
||||
(dir (resizer-direction wm client x y)))
|
||||
|
@ -80,7 +82,11 @@
|
|||
prev-rect dir)))))))
|
||||
(idle))))
|
||||
(free-gc dpy gc)
|
||||
(for-each (lambda (c) (free-cursor dpy (cdr c))) cursors)))))
|
||||
(for-each (lambda (c) (free-cursor dpy (cdr c))) cursors)))
|
||||
window))
|
||||
|
||||
(define (destroy-resizer dpy resizer)
|
||||
(destroy-window dpy resizer))
|
||||
|
||||
(define (rubber-draw dpy gc rect)
|
||||
(draw-rectangle dpy (default-root-window dpy) gc
|
||||
|
|
165
src/move-wm.scm
165
src/move-wm.scm
|
@ -10,73 +10,103 @@
|
|||
(border-colors colors '("#333333" "#dddddd"))
|
||||
)
|
||||
|
||||
(define (create-move-wm out-channel dpy parent options . children)
|
||||
(create-wm dpy parent options children
|
||||
(define (create-move-wm out-channel dpy parent options default-options
|
||||
. children)
|
||||
(create-wm dpy parent options default-options children
|
||||
(manager-type move) move-wm-options-spec
|
||||
out-channel
|
||||
(lambda (wm in-channel)
|
||||
(spawn* (list 'move-wm wm)
|
||||
(lambda (release)
|
||||
(release)
|
||||
(move-wm-handler wm in-channel)))
|
||||
(init-move-wm wm in-channel)
|
||||
wm)))
|
||||
|
||||
(define (move-wm-handler wm channel)
|
||||
(define (init-move-wm wm channel)
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
(window (wm:window wm))
|
||||
(gc (create-gc dpy window '())))
|
||||
(let loop ()
|
||||
(let ((msg (receive channel)))
|
||||
(case (car msg)
|
||||
((draw-main-window)
|
||||
(set-gc-foreground! dpy gc (black-pixel dpy))
|
||||
(fill-rectangle* dpy window gc
|
||||
(clip-rectangle dpy window)))
|
||||
(spawn* (list 'move-wm wm)
|
||||
(lambda (release)
|
||||
(release)
|
||||
(call-with-current-continuation
|
||||
(lambda (exit)
|
||||
(let loop ()
|
||||
(let ((msg (receive channel)))
|
||||
(handle-message wm gc exit msg)
|
||||
(loop)))))
|
||||
(free-gc dpy gc)))))
|
||||
|
||||
((fit-windows)
|
||||
(map (lambda (client)
|
||||
(assert-client-visible wm client))
|
||||
(wm-clients wm)))
|
||||
|
||||
((init-client)
|
||||
(init-client wm (second msg) (third msg)))
|
||||
((deinit-client)
|
||||
(deinit-client wm (second msg)))
|
||||
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
;; TODO: exact sizes ?!
|
||||
(configure-window dpy window
|
||||
(append (make-window-change-alist
|
||||
(border-width 0))
|
||||
changes))))
|
||||
(define (handle-message wm gc exit msg)
|
||||
(let ((dpy (wm:dpy wm))
|
||||
(window (wm:window wm)))
|
||||
(case (car msg)
|
||||
((wait)
|
||||
(let ((sp (second msg))
|
||||
(message (third msg)))
|
||||
(handle-message wm gc
|
||||
(lambda args
|
||||
(sync-point-release sp)
|
||||
(apply exit args))
|
||||
message)
|
||||
(sync-point-release sp)))
|
||||
|
||||
((deinit-manager)
|
||||
(exit 'deinit-manager))
|
||||
|
||||
((draw-client-window)
|
||||
(draw-client-window wm (second msg) gc))
|
||||
((fit-client)
|
||||
;; client-window changed it's size
|
||||
(fit-client-windows wm (second msg)))
|
||||
|
||||
((fit-client-window)
|
||||
;; client changed it's size ??
|
||||
(fit-client-window wm (second msg)))
|
||||
|
||||
((manager-focused) #t)
|
||||
((draw-main-window)
|
||||
(set-gc-foreground! dpy gc (black-pixel dpy))
|
||||
(fill-rectangle* dpy window gc
|
||||
(clip-rectangle dpy window)))
|
||||
|
||||
((update-client-state)
|
||||
(let* ((client (second msg))
|
||||
(dpy (wm:dpy wm))
|
||||
(window (client:window client))
|
||||
(state (if (window-contains-focus? dpy window)
|
||||
'focused
|
||||
'normal))
|
||||
(titlebar (car (client:data client)))
|
||||
(name (client-name (wm:dpy wm) client)))
|
||||
(set-titlebar-title+state! titlebar name state)))
|
||||
))
|
||||
(loop))
|
||||
(free-gc (wm:dpy wm) gc)))
|
||||
((update-manager-state) #t)
|
||||
|
||||
((fit-windows)
|
||||
(map (lambda (client)
|
||||
(assert-client-visible wm client))
|
||||
(wm-clients wm)))
|
||||
|
||||
((init-client)
|
||||
(init-client wm (second msg) (third msg)))
|
||||
|
||||
((deinit-client)
|
||||
(deinit-client wm (second msg)))
|
||||
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
;; TODO: exact sizes ?!
|
||||
(configure-window dpy window
|
||||
(append (make-window-change-alist
|
||||
(border-width 0))
|
||||
changes))))
|
||||
|
||||
((draw-client-window)
|
||||
(draw-client-window wm (second msg) gc))
|
||||
|
||||
((fit-client)
|
||||
;; client-window changed it's size
|
||||
(fit-client-windows wm (second msg)))
|
||||
|
||||
((fit-client-window)
|
||||
;; client changed it's size ??
|
||||
(fit-client-window wm (second msg)))
|
||||
|
||||
((manager-focused) #t)
|
||||
|
||||
((update-client-state)
|
||||
(let* ((client (second msg))
|
||||
(focused? (third msg))
|
||||
(state (if focused?
|
||||
'focused
|
||||
'normal))
|
||||
(titlebar (car (client:data client))))
|
||||
(set-titlebar-state! titlebar state)))
|
||||
|
||||
((update-client-name)
|
||||
(let ((client (second msg))
|
||||
(name (third msg)))
|
||||
(let ((titlebar (car (client:data client))))
|
||||
(set-titlebar-title! titlebar name))))
|
||||
|
||||
(else (warn "unhandled move-wm message" wm msg)))))
|
||||
|
||||
(define (init-client wm client maybe-rect)
|
||||
(let ((dpy (wm:dpy wm)))
|
||||
|
@ -127,7 +157,8 @@
|
|||
(delete-window dpy (client:window client) (second msg)))
|
||||
))))
|
||||
;; TODO: internal channel
|
||||
(loop))))
|
||||
(loop))
|
||||
(destroy-resizer dpy resizer)))
|
||||
|
||||
(map-titlebar titlebar)
|
||||
(if (window-exists? dpy (client:window client))
|
||||
|
@ -138,8 +169,8 @@
|
|||
(let ((options (wm:options wm)))
|
||||
(create-titlebar channel (wm:dpy wm) (client:client-window client)
|
||||
(wm:colormap wm)
|
||||
;; TODO: buttons
|
||||
(list (cons 'normal-colors
|
||||
(list (cons 'buttons '(kill maximize))
|
||||
(cons 'normal-colors
|
||||
(get-option options 'titlebar-colors))
|
||||
(cons 'active-colors
|
||||
(get-option options'titlebar-colors-focused))
|
||||
|
@ -222,8 +253,20 @@
|
|||
(if maybe-rect
|
||||
maybe-rect
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
(w.h (desired-size/hints dpy win
|
||||
(maximal-size/hints dpy win 400 200)))
|
||||
(default-width 400)
|
||||
(default-height 200)
|
||||
(w.h-1
|
||||
(let ((w.h (minimal-size/hints dpy win default-width
|
||||
default-height)))
|
||||
(cons (if (< default-width (car w.h))
|
||||
(car w.h)
|
||||
default-width)
|
||||
(if (< default-height (cdr w.h))
|
||||
(cdr w.h)
|
||||
default-height))))
|
||||
(w.h-2 (maximal-size/hints dpy win (car w.h-1) (cdr w.h-1)))
|
||||
(w.h (desired-size/hints dpy win w.h-2))
|
||||
;; TODO: look for a free position ?! Transients centered?
|
||||
(x.y (desired-position/hints dpy win (cons 0 0))))
|
||||
(make-rectangle (car x.y) (cdr x.y)
|
||||
(car w.h) (cdr w.h)))))
|
||||
|
|
223
src/split-wm.scm
223
src/split-wm.scm
|
@ -17,100 +17,128 @@
|
|||
;; | | | | |
|
||||
;; ---------- ----------
|
||||
|
||||
(define (create-split-wm external-in-channel dpy parent options . children)
|
||||
(create-wm dpy parent options children
|
||||
(define (create-split-wm external-in-channel dpy parent options
|
||||
default-options . children)
|
||||
(create-wm dpy parent options default-options children
|
||||
(manager-type split) split-wm-options-spec
|
||||
external-in-channel
|
||||
(lambda (wm in-channel)
|
||||
(spawn* (list 'split-wm wm)
|
||||
(lambda (release)
|
||||
(release)
|
||||
(split-wm-handler wm in-channel)))
|
||||
(init-split-wm wm in-channel)
|
||||
wm)))
|
||||
|
||||
(define (split-wm? wm)
|
||||
(and (wm? wm) (eq? (wm:type wm) (manager-type split))))
|
||||
(define-record-type split-data :split-data
|
||||
(make-split-data resizer first-client second-client)
|
||||
split-data?
|
||||
(resizer data:resizer)
|
||||
(first-client data:first-client set-data:first-client!)
|
||||
(second-client data:second-client set-data:second-client!))
|
||||
|
||||
(define (split-wm-handler wm channel)
|
||||
(let ((resizer-window (create-resizer wm))
|
||||
(dpy (wm:dpy wm))
|
||||
(first-client #f)
|
||||
(second-client #f))
|
||||
(map-window (wm:dpy wm) resizer-window)
|
||||
(let loop ()
|
||||
(let ((msg (receive channel)))
|
||||
(case (car msg)
|
||||
((draw-main-window) #t)
|
||||
|
||||
((fit-windows)
|
||||
(fit-windows wm resizer-window first-client second-client))
|
||||
|
||||
((init-client)
|
||||
(let ((client (second msg))
|
||||
(first? (not first-client)))
|
||||
(if first?
|
||||
(set! first-client client)
|
||||
(set! second-client client))
|
||||
|
||||
(set-window-border-width! dpy (client:window client) 0)
|
||||
(fit-windows wm resizer-window first-client second-client)
|
||||
|
||||
(map-window dpy (client:window client))
|
||||
(map-window dpy (client:client-window client))
|
||||
(define (init-split-wm wm channel)
|
||||
(let* ((resizer (create-resizer wm))
|
||||
(data (make-split-data resizer #f #f)))
|
||||
(spawn* (list 'split-wm wm)
|
||||
(lambda (release)
|
||||
(map-window (wm:dpy wm) resizer)
|
||||
(release)
|
||||
(call-with-current-continuation
|
||||
(lambda (exit)
|
||||
(let loop ()
|
||||
(let ((msg (receive channel)))
|
||||
(handle-message wm channel data exit msg)
|
||||
(loop)))))))))
|
||||
|
||||
(let ((opt (if (eq? (get-option-value (wm:options wm)
|
||||
'orientation)
|
||||
'horizontal)
|
||||
(if first? 'select-right 'select-left)
|
||||
(if first? 'select-down 'select-up))))
|
||||
(grab-shortcut dpy (client:client-window client)
|
||||
(get-option-value (wm:options wm) opt)
|
||||
(if first? 'select-second 'select-first)
|
||||
channel #f))
|
||||
))
|
||||
|
||||
((deinit-client)
|
||||
(let ((client (second msg)))
|
||||
(if (eq? client first-client)
|
||||
(set! first-client #f))
|
||||
(if (eq? client second-client)
|
||||
(set! second-client #f))
|
||||
;; destroy split if only one client left
|
||||
(if (and (not (and first-client second-client))
|
||||
(or first-client second-client))
|
||||
(let ((repl (client:window (or first-client second-client))))
|
||||
(mdisplay "destroying " wm ". with replacement " repl "\n")
|
||||
(send (wm:out-channel wm)
|
||||
(list 'destroy-wm wm repl))))))
|
||||
|
||||
((draw-client-window) #t)
|
||||
|
||||
((fit-client)
|
||||
;; client-window changed it's size
|
||||
(fit-client-windows wm (second msg)))
|
||||
|
||||
((fit-client-window)
|
||||
;; client changed it's size ??
|
||||
#t)
|
||||
(define (handle-message wm channel data exit msg)
|
||||
(let ((dpy (wm:dpy wm)))
|
||||
(case (car msg)
|
||||
((wait)
|
||||
(let ((sp (second msg))
|
||||
(message (third msg)))
|
||||
(handle-message wm channel data
|
||||
(lambda args
|
||||
(sync-point-release sp)
|
||||
(apply exit args))
|
||||
message)
|
||||
(sync-point-release sp)))
|
||||
|
||||
((deinit-manager)
|
||||
(destroy-window dpy (data:resizer data))
|
||||
(exit 'deinit-manager))
|
||||
|
||||
((manager-focused)
|
||||
(let ((time (second msg))
|
||||
(cc (wm-current-client wm)))
|
||||
(if cc (wm-select-client wm cc time))))
|
||||
((draw-main-window) #t)
|
||||
|
||||
((update-manager-state) #t)
|
||||
|
||||
((fit-windows)
|
||||
(fit-windows wm data))
|
||||
|
||||
((init-client)
|
||||
(let ((client (second msg))
|
||||
(first? (not (data:first-client data))))
|
||||
(if first?
|
||||
(set-data:first-client! data client)
|
||||
(set-data:second-client! data client))
|
||||
|
||||
(set-window-border-width! dpy (client:window client) 0)
|
||||
(fit-windows wm data)
|
||||
|
||||
(map-window dpy (client:window client))
|
||||
(map-window dpy (client:client-window client))
|
||||
|
||||
((update-client-state) #t)
|
||||
(let ((opt (if (eq? (get-option-value (wm:options wm)
|
||||
'orientation)
|
||||
'horizontal)
|
||||
(if first? 'select-right 'select-left)
|
||||
(if first? 'select-down 'select-up))))
|
||||
(grab-shortcut dpy (client:client-window client)
|
||||
(get-option-value (wm:options wm) opt)
|
||||
(if first? 'select-second 'select-first)
|
||||
channel #f))
|
||||
))
|
||||
|
||||
((deinit-client)
|
||||
(let ((client (second msg)))
|
||||
(if (eq? client (data:first-client data))
|
||||
(set-data:first-client! data #f))
|
||||
(if (eq? client (data:second-client data))
|
||||
(set-data:second-client! data #f))
|
||||
;; destroy split if only one client left. replace the
|
||||
;; wm by the remaining client.
|
||||
(let ((first-client (data:first-client data))
|
||||
(second-client (data:second-client data)))
|
||||
(if (and (not (and first-client second-client))
|
||||
(or first-client second-client))
|
||||
(let ((r (client:window (or first-client second-client))))
|
||||
(send (wm:out-channel wm) (list 'destroy-wm wm r)))))))
|
||||
|
||||
((draw-client-window) #t)
|
||||
|
||||
((fit-client)
|
||||
;; client-window changed it's size
|
||||
(fit-client-windows wm (second msg)))
|
||||
|
||||
((fit-client-window)
|
||||
;; client changed it's size ??
|
||||
#t)
|
||||
|
||||
;; Shortcuts
|
||||
((select-first)
|
||||
(let ((time (second msg)))
|
||||
(if first-client
|
||||
(wm-select-client wm first-client time))))
|
||||
((select-second)
|
||||
(let ((time (second msg)))
|
||||
(if second-client
|
||||
(wm-select-client wm second-client time))))
|
||||
))
|
||||
(loop))))
|
||||
((manager-focused)
|
||||
(let ((time (second msg))
|
||||
(cc (wm-current-client wm)))
|
||||
(if cc (wm-select-client wm cc time))))
|
||||
|
||||
((update-client-state) #t)
|
||||
((update-client-name) #t)
|
||||
|
||||
;; Shortcuts
|
||||
((select-first)
|
||||
(let ((time (second msg)))
|
||||
(if (data:first-client data)
|
||||
(wm-select-client wm (data:first-client data) time))))
|
||||
((select-second)
|
||||
(let ((time (second msg)))
|
||||
(if (data:second-client data)
|
||||
(wm-select-client wm (data:second-client data) time))))
|
||||
|
||||
(else (warn "unhandled split-wm message" wm msg)))))
|
||||
|
||||
(define (calc-rectangles wm)
|
||||
(let* ((options (wm:options wm))
|
||||
|
@ -141,18 +169,21 @@
|
|||
(+ (rectangle:height r1) bar-width)))))
|
||||
(list r1 r2 r3)))))
|
||||
|
||||
(define (fit-windows wm resizer-window first-client second-client)
|
||||
(let* ((rects (calc-rectangles wm))
|
||||
(dpy (wm:dpy wm)))
|
||||
(move-resize-window* dpy resizer-window (second rects))
|
||||
(if first-client
|
||||
(move-resize-window* dpy
|
||||
(client:client-window first-client)
|
||||
(first rects)))
|
||||
(if second-client
|
||||
(move-resize-window* dpy
|
||||
(client:client-window second-client)
|
||||
(third rects)))))
|
||||
(define (fit-windows wm data)
|
||||
(let ((resizer-window (data:resizer data))
|
||||
(first-client (data:first-client data))
|
||||
(second-client (data:second-client data)))
|
||||
(let* ((rects (calc-rectangles wm))
|
||||
(dpy (wm:dpy wm)))
|
||||
(move-resize-window* dpy resizer-window (second rects))
|
||||
(if first-client
|
||||
(move-resize-window* dpy
|
||||
(client:client-window first-client)
|
||||
(first rects)))
|
||||
(if second-client
|
||||
(move-resize-window* dpy
|
||||
(client:client-window second-client)
|
||||
(third rects))))))
|
||||
|
||||
(define (fit-client-windows wm client)
|
||||
(let ((dpy (wm:dpy wm)))
|
||||
|
|
|
@ -9,15 +9,13 @@
|
|||
(select-previous keys "M-k p")
|
||||
)
|
||||
|
||||
(define (create-switch-wm out-channel dpy parent options . children)
|
||||
(create-wm dpy parent options children
|
||||
(define (create-switch-wm out-channel dpy parent options default-options
|
||||
. children)
|
||||
(create-wm dpy parent options default-options children
|
||||
(manager-type switch) switch-wm-options-spec
|
||||
out-channel
|
||||
(lambda (wm in-channel)
|
||||
(spawn* (list 'switch-wm wm)
|
||||
(lambda (release)
|
||||
(release)
|
||||
(switch-wm-handler wm in-channel)))
|
||||
(init-switch-wm wm in-channel)
|
||||
wm)))
|
||||
|
||||
(define-record-type switch-wm-data :switch-wm-data
|
||||
|
@ -26,7 +24,7 @@
|
|||
(titlebars data:titlebars set-data:titlebars!)
|
||||
(empty-titlebar data:empty-titlebar))
|
||||
|
||||
(define (switch-wm-handler wm channel)
|
||||
(define (init-switch-wm wm channel)
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
(window (wm:window wm))
|
||||
(options (wm:options wm))
|
||||
|
@ -42,74 +40,111 @@
|
|||
(get-option-value options 'select-previous)
|
||||
'select-previous channel #f)
|
||||
|
||||
(let loop ()
|
||||
(let ((msg (receive channel)))
|
||||
(case (car msg)
|
||||
((draw-main-window)
|
||||
(set-gc-foreground! dpy gc (black-pixel dpy))
|
||||
(fill-rectangle* dpy window gc
|
||||
(clip-rectangle dpy window)))
|
||||
(spawn* (list 'switch-wm wm)
|
||||
(lambda (release)
|
||||
(release)
|
||||
(call-with-current-continuation
|
||||
(lambda (exit)
|
||||
(let loop ()
|
||||
(let ((msg (receive channel)))
|
||||
(handle-message wm data gc exit msg)
|
||||
(loop)))))
|
||||
(free-gc dpy gc)))))
|
||||
|
||||
((fit-windows)
|
||||
(fit-titlebars wm data)
|
||||
(for-each (lambda (c)
|
||||
(fit-client-window wm c))
|
||||
(wm-clients wm)))
|
||||
|
||||
((init-client)
|
||||
(init-client wm data (second msg) (third msg)))
|
||||
((deinit-client)
|
||||
(deinit-client wm data (second msg)))
|
||||
(define (handle-message wm data gc exit msg)
|
||||
(let ((dpy (wm:dpy wm))
|
||||
(window (wm:window wm)))
|
||||
(case (car msg)
|
||||
((wait)
|
||||
(let ((sp (second msg))
|
||||
(message (third msg)))
|
||||
(handle-message wm data gc
|
||||
(lambda args
|
||||
(sync-point-release sp)
|
||||
(apply exit args))
|
||||
message)
|
||||
(sync-point-release sp)))
|
||||
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
;; TODO: exact sizes ?!
|
||||
(configure-window dpy window
|
||||
(append (make-window-change-alist
|
||||
(border-width 0))
|
||||
changes))))
|
||||
|
||||
((draw-client-window) #f)
|
||||
((deinit-manager)
|
||||
(destroy-titlebar (data:empty-titlebar data))
|
||||
(for-each (lambda (client.tb)
|
||||
(destroy-titlebar (cdr client.tb)))
|
||||
(data:titlebars data))
|
||||
(exit 'deinit-manager))
|
||||
|
||||
((fit-client)
|
||||
;; client-window changed it's size
|
||||
(fit-client wm (second msg)))
|
||||
|
||||
((fit-client-window)
|
||||
;; client changed it's size ??
|
||||
(fit-client-window wm (second msg)))
|
||||
((draw-main-window)
|
||||
(set-gc-foreground! dpy gc (black-pixel dpy))
|
||||
(fill-rectangle* dpy window gc
|
||||
(clip-rectangle dpy window)))
|
||||
|
||||
((update-manager-state)
|
||||
(let ((state (if (window-contains-focus? dpy (wm:window wm))
|
||||
'focused
|
||||
'active)))
|
||||
(set-titlebar-state! empty-titlebar state)))
|
||||
((fit-windows)
|
||||
(fit-titlebars wm data)
|
||||
(for-each (lambda (c)
|
||||
(fit-client-window wm c))
|
||||
(wm-clients wm)))
|
||||
|
||||
((init-client)
|
||||
(init-client wm data (second msg) (third msg)))
|
||||
|
||||
((manager-focused)
|
||||
(let ((time (second msg))
|
||||
(cc (wm-current-client wm)))
|
||||
(if cc (wm-select-client wm cc time))))
|
||||
|
||||
((update-client-state)
|
||||
(let* ((client (second msg))
|
||||
(dpy (wm:dpy wm))
|
||||
(window (client:window client)))
|
||||
(if (window-exists? dpy window)
|
||||
(let ((state (if (window-contains-focus? dpy window)
|
||||
'focused
|
||||
(if (window-viewable? dpy window)
|
||||
'active
|
||||
'normal)))
|
||||
(titlebar (assq/false client (data:titlebars data)))
|
||||
(name (client-name dpy client)))
|
||||
(set-titlebar-title+state! titlebar name state)))))
|
||||
((deinit-client)
|
||||
(deinit-client wm data (second msg)))
|
||||
|
||||
((select-next) (select-next-client wm (second msg)))
|
||||
((select-previous) (select-previous-client wm (second msg)))
|
||||
))
|
||||
(loop))
|
||||
(free-gc (wm:dpy wm) gc)))
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
;; TODO: exact sizes ?!
|
||||
(configure-window dpy window
|
||||
(append (make-window-change-alist
|
||||
(border-width 0))
|
||||
changes))))
|
||||
|
||||
((draw-client-window) #f)
|
||||
|
||||
((fit-client)
|
||||
;; client-window changed it's size
|
||||
(fit-client wm (second msg)))
|
||||
|
||||
((fit-client-window)
|
||||
;; client changed it's size ??
|
||||
(fit-client-window wm (second msg)))
|
||||
|
||||
((update-manager-state)
|
||||
(let* ((focused? (second msg))
|
||||
(state (if focused?
|
||||
'focused
|
||||
'active)))
|
||||
(set-titlebar-state! (data:empty-titlebar data) state)))
|
||||
|
||||
((manager-focused)
|
||||
(let ((time (second msg))
|
||||
(cc (wm-current-client wm)))
|
||||
(if cc (wm-select-client wm cc time))))
|
||||
|
||||
((update-client-state)
|
||||
(let* ((client (second msg))
|
||||
(focused? (third msg))
|
||||
(dpy (wm:dpy wm))
|
||||
(window (client:window client))
|
||||
(titlebar (assq/false client (data:titlebars data))))
|
||||
(if (and titlebar (window-exists? dpy window))
|
||||
(let ((state (if focused?
|
||||
'focused
|
||||
(if (window-viewable? dpy window)
|
||||
'active
|
||||
'normal))))
|
||||
(set-titlebar-state! titlebar state)))))
|
||||
|
||||
((update-client-name)
|
||||
(let ((client (second msg))
|
||||
(name (third msg)))
|
||||
(let ((titlebar (assq/false client (data:titlebars data))))
|
||||
(if titlebar
|
||||
(set-titlebar-title! titlebar name)))))
|
||||
|
||||
((select-next) (select-next-client wm (second msg)))
|
||||
((select-previous) (select-previous-client wm (second msg)))
|
||||
|
||||
(else (warn "unhandled switch-wm message" wm msg)))))
|
||||
|
||||
(define (fit-titlebars wm data)
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
|
@ -144,15 +179,16 @@
|
|||
(data:titlebars data))))))
|
||||
|
||||
(define (init-client wm data client maybe-rect)
|
||||
;; TODO: transients!
|
||||
(let ((dpy (wm:dpy wm))
|
||||
(options (wm:options wm)))
|
||||
(let* ((channel (make-channel))
|
||||
(titlebar (create-client-titlebar channel wm client)))
|
||||
(set-data:titlebars! data (append (data:titlebars data)
|
||||
(list (cons client titlebar))))
|
||||
(set-titlebar-title! titlebar (client-name dpy client))
|
||||
(fit-titlebars wm data)
|
||||
(update-titlebars wm data)
|
||||
|
||||
(fit-client-window wm client)
|
||||
(fit-client wm client)
|
||||
|
||||
|
@ -180,8 +216,7 @@
|
|||
;; from titlebar-buttons
|
||||
((kill)
|
||||
(delete-window dpy (client:window client) (second msg)))
|
||||
(else (mdisplay "unhandled client message: " msg "\n"))))
|
||||
;; TODO: internal channel
|
||||
(else (warn "unhandled client message " wm client msg))))
|
||||
(loop))))
|
||||
|
||||
(map-titlebar titlebar)
|
||||
|
@ -193,8 +228,8 @@
|
|||
(let ((options (wm:options wm)))
|
||||
(create-titlebar channel (wm:dpy wm) (wm:window wm)
|
||||
(wm:colormap wm)
|
||||
;; TODO: buttons
|
||||
(list (cons 'normal-colors
|
||||
(list (cons 'buttons '(kill))
|
||||
(cons 'normal-colors
|
||||
(get-option options 'titlebar-colors))
|
||||
(cons 'active-colors
|
||||
(get-option options 'titlebar-colors-active))
|
||||
|
@ -207,7 +242,7 @@
|
|||
(let* ((options (wm:options wm))
|
||||
(tb
|
||||
(create-titlebar #f (wm:dpy wm) (wm:window wm) (wm:colormap wm)
|
||||
(list ;; TODO: (cons 'draggable #f)
|
||||
(list
|
||||
(cons 'normal-colors
|
||||
(get-option options 'titlebar-colors))
|
||||
(cons 'active-colors
|
||||
|
|
Loading…
Reference in New Issue