guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: First steps towards a window manager


From: David Thompson
Subject: Re: First steps towards a window manager
Date: Thu, 31 Jan 2013 18:21:26 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130109 Thunderbird/17.0.2

On 01/31/2013 03:35 PM, Mark Witmer wrote:
Hi all,

I thought I'd follow up on my previous post regarding xlib and a guile
window manager.

First of all, I have guile-xlib working with guile-2.0; I'm calling my
branch "guile2-xlib." You can use git and pull it from
http://github.com/mwitmer/guile2-xlib or download an archive at
http://markwitmer.com/dist/guile2-xlib-0.1.tar.gz. I'm still toying with
the idea of writing some xcb bindings, time permitting!

As far as the window manager goes, you need very little code to get
started with something extremely basic. Here are a few lines that let
you open some X applications, though it lacks resizing/positioning
(guile-xlib doesn't support that... yet).

--8<---------------cut here---------------start------------->8---
(define-module (guile-wm wm)
   #:use-module (xlib xlib))

(define-once wm-display #f)
(define-once wm-display-string (or (getenv "DISPLAY") ":0"))
(define-once wm-event-hook (make-hook 1))

(define rc-file-location
   (string-append (passwd:dir (getpw (getuid))) "/.guilewmrc"))

(define-public (wm-init!)
   "Connect to a running X server and begin listening for events"
   (set! wm-display (x-open-display! wm-display-string))
   (let ((wm-root (x-root-window wm-display)))
     (x-select-input! wm-root (logior ButtonPressMask ExposureMask 
KeyPressMask))
     (wm-event-hook-refresh)
     (if (file-exists? rc-file-location) (load rc-file-location))
     (dynamic-wind
       (lambda () (x-flush! wm-display))
       (lambda () (x-event-loop! wm-display wm-event-hook))
       (lambda () (x-close-display! wm-display)))))

(define-public (wm-event-hook-refresh)
   "Refresh the event hook with the hooks listed in wm-event-hooks"
   (reset-hook! wm-event-hook)
   (for-each (lambda (hook) (add-hook! wm-event-hook hook)) wm-event-hooks))

(define-public (wm-shell-command command)
   "Execute COMMAND in a shell"
   (if (= (primitive-fork) 0)
       (let ((env (cons
                  (format #f "DISPLAY=~a.~a" wm-display-string
                          (x-screen-number-of-screen (x-screen-of-display 
wm-display)))
                  (environ))))
        (execle "/bin/sh" env "/bin/sh" "-c" command))))

;; guile-xlib doesn't have support for keysyms yet, so I just use raw
;; keycodes here
(define default-key-map
   `((24 . ,(lambda (event) (x-event-loop-quit! (x-event:button event))))
     (26 ,wm-shell-command "emacs")
     (28 ,wm-shell-command "xterm")))

(define (mapped-key-handler map)
   "Return a key handler that maps keycodes to commands"
   (lambda (event)
     (if (= (x-event:type event) KeyPress)
        (let ((command (assq-ref map (x-event:keycode event))))
           (if command
            (if (list? command)
                (apply (car command) (cdr command))
                (command event)))))))

(define-public wm-event-hooks (list (mapped-key-handler default-key-map)))
--8<---------------cut here---------------end--------------->8---

You also need a startup script like this:

--8<---------------cut here---------------start------------->8---
(use-modules (guile-wm wm))
(wm-init!)
--8<---------------cut here---------------end--------------->8---

The fun part is that you can put a line like

guile --listen=37147 -L /path/to/module/.../ \
   /path/to/startup/script/wm.scm

in your .xinitrc or xsession file, and then you can connect to that
listening process from Geiser or something like that and hack the wm
while it's running.

A lot of this is inspired by Stumpwm, a pretty nifty tiling wm written
in common lisp that's similarly configurable.

I'll put the wm code on github as well as I get more features
added. Feedback and suggestions are welcome!

Mark Witmer

Very cool. Writing a window manager in Guile has been something I've wanted to do. Good luck to you!



reply via email to

[Prev in Thread] Current Thread [Next in Thread]