parent
0598918d0c
commit
985b20dcb2
|
@ -0,0 +1,86 @@
|
|||
(define-record-type icon :icon
|
||||
(make-icon wm client window)
|
||||
icon?
|
||||
(wm icon:wm)
|
||||
(client icon:client)
|
||||
(window icon:window))
|
||||
|
||||
(define (create-icon wm client rect)
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
(window (create-simple-window dpy (wm:window wm)
|
||||
(rectangle:x rect) (rectangle:y rect)
|
||||
(rectangle:width rect)
|
||||
(rectangle:height rect)
|
||||
0
|
||||
(black-pixel dpy) (white-pixel dpy)))
|
||||
(gc (create-gc dpy window
|
||||
(make-gc-value-alist
|
||||
(foreground (black-pixel dpy))
|
||||
(background (white-pixel dpy))))))
|
||||
(spawn*
|
||||
(list 'move-wm-icon wm client window)
|
||||
(lambda (release)
|
||||
(call-with-current-continuation
|
||||
(lambda (exit)
|
||||
(call-with-event-channel
|
||||
dpy window (event-mask exposure
|
||||
structure-notify
|
||||
button-press)
|
||||
(lambda (event-channel)
|
||||
(release)
|
||||
(let loop ()
|
||||
(let ((xevent (receive event-channel)))
|
||||
(cond
|
||||
((destroy-window-event? xevent) (exit 'destroyed))
|
||||
|
||||
((expose-event? xevent)
|
||||
(if (= 0 (expose-event-count xevent))
|
||||
(draw-icon dpy window gc client)))
|
||||
|
||||
((and (button-event? xevent)
|
||||
(eq? (event-type button-press)
|
||||
(button-event-type xevent)))
|
||||
(send (wm:internal-out-channel wm)
|
||||
(list 'normalize-client client))
|
||||
(exit 'normalized)))
|
||||
(loop)))))))
|
||||
(free-gc dpy gc)))
|
||||
(make-icon wm client window)))
|
||||
|
||||
(define (map-icon icon)
|
||||
(map-window (wm:dpy (icon:wm icon)) (icon:window icon)))
|
||||
|
||||
(define (destroy-icon icon)
|
||||
(destroy-window (wm:dpy (icon:wm icon)) (icon:window icon)))
|
||||
|
||||
(define (draw-icon dpy window gc client)
|
||||
(let ((title (client-name dpy client)) ;; or WM_ICON_NAME ??
|
||||
(r (clip-rectangle dpy window)))
|
||||
(draw-image-string dpy window gc 2 14 title)))
|
||||
|
||||
(define (find-icon-rect wm-rect icons)
|
||||
(let* ((icon-w 200)
|
||||
(icon-h 18)
|
||||
(xs (iota (quotient (rectangle:width wm-rect) icon-w)))
|
||||
(ys (reverse (iota (quotient (rectangle:height wm-rect) icon-h))))
|
||||
(all (flatten (map (lambda (yi)
|
||||
(map (lambda (xi)
|
||||
(make-rectangle (* xi icon-w)
|
||||
(* yi icon-h)
|
||||
icon-w icon-h))
|
||||
xs))
|
||||
ys)))
|
||||
(icon-rects (map (lambda (i)
|
||||
(window-rectangle (wm:dpy (icon:wm i))
|
||||
(icon:window i)))
|
||||
icons))
|
||||
(free (filter (lambda (r)
|
||||
(not (any (lambda (ir)
|
||||
(rectangles-overlap? r ir))
|
||||
icon-rects)))
|
||||
all)))
|
||||
(if (null? free)
|
||||
(if (null? all)
|
||||
(make-rectangle 0 0 icon-w icon-h)
|
||||
(car all))
|
||||
(car free))))
|
|
@ -12,7 +12,9 @@
|
|||
|
||||
(define (create-move-wm out-channel dpy parent options default-options
|
||||
. children)
|
||||
(create-wm dpy parent options default-options children
|
||||
(create-wm dpy parent options (append default-options
|
||||
'((focus-policy . (click))))
|
||||
children
|
||||
(manager-type move) move-wm-options-spec
|
||||
out-channel
|
||||
(lambda (wm in-channel)
|
||||
|
@ -77,6 +79,33 @@
|
|||
(append (make-window-change-alist
|
||||
(border-width 0))
|
||||
changes))))
|
||||
|
||||
((iconify-client)
|
||||
(let ((client (second msg)))
|
||||
(if (not (client-data:icon client))
|
||||
(begin
|
||||
(unmap-window dpy (client:client-window client))
|
||||
(unmap-window dpy (client:window client))
|
||||
(set-wm-state! dpy (client:window client) (wm-state iconic)
|
||||
none)
|
||||
(let ((icon (create-client-icon wm client)))
|
||||
(set-client-data:icon! client icon)
|
||||
(map-icon icon))))))
|
||||
|
||||
((maximize-client)
|
||||
(let ((client (second msg)))
|
||||
(maximize-window dpy (client:client-window client))))
|
||||
|
||||
((normalize-client)
|
||||
(let ((client (second msg)))
|
||||
(if (client-data:icon client)
|
||||
(begin
|
||||
(destroy-icon (client-data:icon client))
|
||||
(map-window dpy (client:window client))
|
||||
(map-window dpy (client:client-window client))
|
||||
(set-wm-state! dpy (client:window client) (wm-state normal)
|
||||
none)
|
||||
(set-client-data:icon! client #f)))))
|
||||
|
||||
((draw-client-window)
|
||||
(draw-client-window wm (second msg) gc))
|
||||
|
@ -97,17 +126,41 @@
|
|||
(state (if focused?
|
||||
'focused
|
||||
'normal))
|
||||
(titlebar (car (client:data client))))
|
||||
(titlebar (client-data:titlebar client)))
|
||||
(set-titlebar-state! titlebar state)))
|
||||
|
||||
((update-client-name)
|
||||
(let ((client (second msg))
|
||||
(name (third msg)))
|
||||
(let ((titlebar (car (client:data client))))
|
||||
(let ((titlebar (client-data:titlebar client)))
|
||||
(set-titlebar-title! titlebar name))))
|
||||
|
||||
((show-clients)
|
||||
(let ((clients (second msg)))
|
||||
(for-each (lambda (c)
|
||||
(if (client-data:icon c)
|
||||
(handle-message wm gc exit
|
||||
(list 'normalize-client c)))
|
||||
(raise-window dpy (client:client-window c)))
|
||||
clients)))
|
||||
|
||||
(else (warn "unhandled move-wm message" wm msg)))))
|
||||
|
||||
(define (make-client-data titlebar resizer icon)
|
||||
(list titlebar resizer icon))
|
||||
|
||||
(define (client-data:titlebar client)
|
||||
(first (client:data client)))
|
||||
|
||||
(define (client-data:resizer client)
|
||||
(second (client:data client)))
|
||||
|
||||
(define (client-data:icon client)
|
||||
(third (client:data client)))
|
||||
|
||||
(define (set-client-data:icon! client icon)
|
||||
(set-car! (cddr (client:data client)) icon))
|
||||
|
||||
(define (init-client wm client maybe-rect)
|
||||
(let ((dpy (wm:dpy wm)))
|
||||
(let* ((r (initial-client-rect wm (client:window client) maybe-rect))
|
||||
|
@ -115,7 +168,7 @@
|
|||
(titlebar (create-client-titlebar channel wm client))
|
||||
(resizer (create-resizer wm client))
|
||||
(options (wm:options wm)))
|
||||
(set-client:data! client (list titlebar resizer))
|
||||
(set-client:data! client (make-client-data titlebar resizer #f))
|
||||
(set-titlebar-title! titlebar (client-name dpy client))
|
||||
(let ((bw (get-option-value options 'border-width))
|
||||
(th (get-option-value options 'titlebar-height)))
|
||||
|
@ -155,6 +208,10 @@
|
|||
;; from titlebar-buttons
|
||||
((kill)
|
||||
(delete-window dpy (client:window client) (second msg)))
|
||||
((iconify)
|
||||
(wm-iconify-window wm (client:window client)))
|
||||
((maximize)
|
||||
(wm-maximize-window wm (client:window client)))
|
||||
))))
|
||||
;; TODO: internal channel
|
||||
(loop))
|
||||
|
@ -169,7 +226,7 @@
|
|||
(let ((options (wm:options wm)))
|
||||
(create-titlebar channel (wm:dpy wm) (client:client-window client)
|
||||
(wm:colormap wm)
|
||||
(list (cons 'buttons '(kill maximize))
|
||||
(list (cons 'buttons '(kill maximize iconify))
|
||||
(cons 'normal-colors
|
||||
(get-option options 'titlebar-colors))
|
||||
(cons 'active-colors
|
||||
|
@ -181,7 +238,14 @@
|
|||
|
||||
(define (deinit-client wm client)
|
||||
(let ((dpy (wm:dpy wm)))
|
||||
#t))
|
||||
(set-input-focus dpy (wm:window wm) (revert-to parent) current-time)))
|
||||
|
||||
(define (create-client-icon wm client)
|
||||
(let* ((other-icons (filter (lambda (x) x)
|
||||
(map client-data:icon (wm-clients wm))))
|
||||
(r (find-icon-rect (clip-rectangle (wm:dpy wm) (wm:window wm))
|
||||
other-icons)))
|
||||
(create-icon wm client r)))
|
||||
|
||||
;; ***
|
||||
|
||||
|
@ -201,7 +265,7 @@
|
|||
(- (window-attribute:height wa)
|
||||
(+ (* 2 border-width) titlebar-height))))
|
||||
(move-resize-titlebar
|
||||
(car (client:data client))
|
||||
(client-data:titlebar client)
|
||||
(make-rectangle border-width border-width
|
||||
(- (window-attribute:width wa) (* 2 border-width))
|
||||
titlebar-height))))
|
||||
|
@ -223,8 +287,14 @@
|
|||
(let* ((dpy (wm:dpy wm))
|
||||
(win (client:client-window client))
|
||||
(x (window-x dpy win))
|
||||
(y (window-y dpy win)))
|
||||
#t)) ;; ... TODO
|
||||
(y (window-y dpy win))
|
||||
(w (window-width (wm:window wm)))
|
||||
(h (window-height (wm:window wm))))
|
||||
;; TODO: assert-icon-visible ...
|
||||
(if (>= x w)
|
||||
(set-window-x! win (- w 10)))
|
||||
(if (>= y h)
|
||||
(set-window-y! win (- h 10)))))
|
||||
|
||||
(define (draw-client-window wm client gc)
|
||||
(let* ((options (wm:options wm))
|
||||
|
@ -267,7 +337,15 @@
|
|||
(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))))
|
||||
(maybe-x.y (find-free-position wm w.h (cons 0 0)))
|
||||
(x.y (desired-position/hints dpy win maybe-x.y)))
|
||||
(make-rectangle (car x.y) (cdr x.y)
|
||||
(car w.h) (cdr w.h)))))
|
||||
|
||||
(define (find-free-position wm size default-pos)
|
||||
(let* ((dpy (wm:dpy wm))
|
||||
(max-w (window-width dpy (wm:window wm)))
|
||||
(max-h (window-height dpy (wm:window wm)))
|
||||
(w (car size))
|
||||
(h (cdr size)))
|
||||
default-pos)) ;; TODO
|
||||
|
|
|
@ -109,6 +109,8 @@
|
|||
(or first-client second-client))
|
||||
(let ((r (client:window (or first-client second-client))))
|
||||
(send (wm:out-channel wm) (list 'destroy-wm wm r)))))))
|
||||
|
||||
((iconfiy-client maximize-client) #t)
|
||||
|
||||
((draw-client-window) #t)
|
||||
|
||||
|
@ -138,6 +140,8 @@
|
|||
(if (data:second-client data)
|
||||
(wm-select-client wm (data:second-client data) time))))
|
||||
|
||||
((show-clients) #t)
|
||||
|
||||
(else (warn "unhandled split-wm message" wm msg)))))
|
||||
|
||||
(define (calc-rectangles wm)
|
||||
|
|
|
@ -89,6 +89,8 @@
|
|||
((deinit-client)
|
||||
(deinit-client wm data (second msg)))
|
||||
|
||||
((iconify-client maximize-client) #t)
|
||||
|
||||
((configure-window)
|
||||
(let ((window (second msg))
|
||||
(changes (third msg)))
|
||||
|
@ -144,6 +146,15 @@
|
|||
((select-next) (select-next-client wm (second msg)))
|
||||
((select-previous) (select-previous-client wm (second msg)))
|
||||
|
||||
((show-clients)
|
||||
(let ((clients (second msg)))
|
||||
;; it's a list of a client and it's transients.
|
||||
(let ((cc (wm-current-client wm))
|
||||
(top (last clients)))
|
||||
(if (and cc (window-mapped? dpy (client:client-window cc)))
|
||||
(unmap-window dpy (client:client-window cc)))
|
||||
(map-window dpy (client:client-window top)))))
|
||||
|
||||
(else (warn "unhandled switch-wm message" wm msg)))))
|
||||
|
||||
(define (fit-titlebars wm data)
|
||||
|
@ -222,7 +233,7 @@
|
|||
(map-titlebar titlebar)
|
||||
(if (window-exists? dpy (client:window client))
|
||||
(map-window dpy (client:window client)))
|
||||
(map-window dpy (client:client-window client)))))
|
||||
(wm-select-client wm client current-time))))
|
||||
|
||||
(define (create-client-titlebar channel wm client)
|
||||
(let ((options (wm:options wm)))
|
||||
|
@ -263,7 +274,12 @@
|
|||
(data:titlebars data)))
|
||||
(if tb (destroy-titlebar tb))
|
||||
(fit-titlebars wm data)
|
||||
(update-titlebars wm data)))
|
||||
(update-titlebars wm data)
|
||||
(if (eq? client (wm-current-client wm))
|
||||
(if (null? (wm-clients wm))
|
||||
(set-input-focus dpy (wm:window wm) (revert-to parent)
|
||||
current-time)
|
||||
(wm-select-client wm (car (wm-clients wm)) current-time)))))
|
||||
|
||||
;; ***
|
||||
|
||||
|
|
Loading…
Reference in New Issue