昔 FVWM を使っていたころ、実画面のサイズの縦横が定数倍になった仮想ディスクトップとして使える機能があった。
当時から 1つの emacs プロセスで複数のフレームを、別々の画面に割り当てて使っていた。Ctrl+十字カーソルで画面を切替えることが出来るので、プログラムを開発するときに結構便利であった。
複数のフレームを配置するとき、何度かキーを叩きマウスぐりぐりするのが、相当面倒だった。
なので、emacs の 1つのキーシーケンスで、複数のフレーム生成して上下左右に飛ばすカスタマイズをしていた。
このカスタマイズが出来たので、 最終的には emacs の8フレーム、ターミナル、ブラウザを配置する形になった(右のイメージ)。
上のカスタマイズの肝は、仮想ディスクトップ上の geometry を指定すれば、任意の位置に配置することが出来ることだった。
FVWM は勿論 afterstep や sawfish の古いバージョンとかに共通した機能だったが、Gnome が標準で使っている metacity では仮想ディスクトップの実現方法がワークスペース?に変わってしまった。
幸いワークスペースは二次元的に配置が出来るので、以前と同様な使いかたが出来る。 唯一出来ないのは、emacs から別のワークスペースにフレームを飛ばすやりかたが分からなかった。
確か、特定のHints の値を変更すれば良かった気がするが、当時追っかけたら、 emacs から変更できる Hintsの型は 文字列だけだったような、そうでないような理由から面倒くさくて、ほったらかしにしていた。
完全に移行出来なかったが、最近 wmctl という外部プログラムを知って、取り組んでみたら上手くいった。
だいぶ幸せだ。
(global-unset-key "\C-z")
(define-key global-map "\C-z51" 'moi::make-frame-3)
(define-key global-map "\C-z52" 'moi::make-frame-6)
(define-key global-map "\C-z50" 'moi::delete-frame-6)
(setq moi::desktop-max-x 4)
(defun moi::move-frame (frame x y)
(let ((wid (frame-parameter (or frame (selected-frame)) 'outer-window-id))
(desk (int-to-string (+ (* moi::desktop-max-x y) x))))
(call-process
"wmctrl" nil nil nil "-i"
"-r" wid "-t" desk)))
(defun moi::make-frame (x y)
(let* ((fpar (frame-parameters))
(bw
(if (string-match "^20" emacs-version)
(cdr (assoc 'border-width fpar))
0))
(left (+ x bw (eval (cdr (assoc 'left fpar)))))
(top (+ y bw (eval (cdr (assoc 'top fpar)))))
(frame (make-frame)))
(sleep-for 0.09)
(modify-frame-parameters frame `((top + ,top) (left + ,left) ,(cons 'font "fontset-standard")))
(sleep-for 0.09)
frame))
(defun moi::make-frame2 (x y)
(let ((frame (moi::make-frame 0 0)))
(moi::move-frame frame (+ x 1) (+ y 2))
frame))
(defvar moi::make-frame-6-alist nil)
(defun moi::make-frame-3 ()
(interactive)
(if (not moi::make-frame-6-alist)
(setq moi::make-frame-6-alist
(list
(moi::make-frame2 1 0)
(moi::make-frame2 0 1)
(moi::make-frame2 1 1)
))))
(defun moi::make-frame-6 ()
(interactive)
(if (not moi::make-frame-6-alist)
(setq moi::make-frame-6-alist
(list
(moi::make-frame2 1 0)
(moi::make-frame2 -1 0)
(moi::make-frame2 0 1)
(moi::make-frame2 0 -1)
;;(moi::make-frame2 1 1)
(moi::make-frame2 -1 1)
(moi::make-frame2 1 -1)
(moi::make-frame2 -1 -1)
))))
(defun moi::delete-frame-6 ()
(interactive)
(while moi::make-frame-6-alist
(delete-frame (car moi::make-frame-6-alist))
(setq moi::make-frame-6-alist (cdr moi::make-frame-6-alist))))