Add the WM cube to support emacs as a window manager

This commit is contained in:
Sameer Rahmani 2021-04-21 11:45:33 +01:00
parent 862724290b
commit 801fcb06e7
7 changed files with 254 additions and 15 deletions

View File

@ -61,3 +61,11 @@ compile:
clean:
@rm -rf $(shell find `pwd` -iname "*~")
@rm -rf $(shell find `pwd`/core -iname "*.elc")
.PHYNY: dummy-x
dummy-x:
Xephyr -br -ac -noreset -screen 800x600 :1
.PHONY: test-wm
test-wm:
DISPLAY=:1 FG42_WM=true FG42_V3=true fg42-wm

54
core/cubes/wm.el Normal file
View File

@ -0,0 +1,54 @@
;;; WMCube --- The elisp cube for FG42 -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2010-2021 Sameer Rahmani & Contributors
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;;; Code:
(require 'fpkg)
(require 'fg42/flags)
(require 'fg42/cube)
(require 'fg42/utils)
(autoload-cube 'fg42/initialize-wm "wm/core.el" "Initalize the WM mode.")
(defflag wm
"The flag to enable WM mode in FG42.")
(defmacro when-wm (&rest body)
"Run the BODY only if in wm mode."
(if (string= (getenv "FG42_WM") "true")
`(progn ,@body)
nil))
(defcube fg42/wm-cube
(:docs "cubes/fg42/wm-cube.org")
(if-flag wm
(when-wm
(message "[WM] Initilizing...")
(fpkg/use exwm)
(fg42/initialize-wm))
(error "[SKIP] WM flag is not active.")))
(provide 'cubes/wm)
;;; wm.el ends here

159
core/cubes/wm/core.el Normal file
View File

@ -0,0 +1,159 @@
;;; WMCube --- The elisp cube for FG42 -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2010-2021 Sameer Rahmani & Contributors
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;;; Code:
(defun wm-randr ()
"RandR support for WM"
(when-wm
(require 'exwm-randr)
(setq exwm-randr-workspace-output-plist '(0 "HDMI-1"
1 "HDMI-1"
2 "HDMI-1"
3 "HDMI-1"
4 "HDMI-1"
5 "HDMI-1"
6 "eDP-1"
7 "HDMI-1"
8 "HDMI-1"
9 "HDMI-1"))
(add-hook 'exwm-randr-screen-change-hook
(lambda ()
(start-process-shell-command
"xrandr" nil "xrandr --output HDMI-1 --above eDP-1 --mode 1920x1080")))
(exwm-randr-enable)))
(defun fg42/initialize-wm ()
"Initilize EXWM window manager with the given PARAMS."
(interactive)
(require 'exwm)
(require 'exwm-config)
(require 'exwm-systemtray)
(exwm-config-ido)
;; Set the initial number of workspaces (they can also be created later).
(setq exwm-workspace-number 10)
;; All buffers created in EXWM mode are named "*EXWM*". You may want to
;; change it in `exwm-update-class-hook' and `exwm-update-title-hook', which
;; are run when a new X window class name or title is available. Here's
;; some advice on this topic:
;; + Always use `exwm-workspace-rename-buffer` to avoid naming conflict.
;; + For applications with multiple windows (e.g. GIMP), the class names of
;; all windows are probably the same. Using window titles for them makes
;; more sense.
;; In the following example, we use class names for all windows except for
;; Java applications and GIMP.
(add-hook 'exwm-update-class-hook
(lambda ()
(unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
(string= "gimp" exwm-instance-name))
(exwm-workspace-rename-buffer exwm-class-name))))
(add-hook 'exwm-update-title-hook
(lambda ()
(when (or (not exwm-instance-name)
(string-prefix-p "sun-awt-X11-" exwm-instance-name)
(string= "gimp" exwm-instance-name))
(exwm-workspace-rename-buffer exwm-title))))
;; Global keybindings can be defined with `exwm-input-global-keys'.
;; Here are a few examples:
(setq exwm-input-global-keys
`(
;; Bind "s-r" to exit char-mode and fullscreen mode.
([?\s-r] . exwm-reset)
([?\s-g] . keyboard-quit)
([8388640] . other-window)
;; Bind "s-w" to switch workspace interactively.
([?\s-w] . exwm-workspace-switch)
;; Bind "s-0" to "s-9" to switch to a workspace by its index.
,@(mapcar (lambda (i)
`(,(kbd (format "s-%d" i)) .
(lambda ()
(interactive)
(exwm-workspace-switch-create ,i))))
(number-sequence 0 9))
;; Bind "s-&" to launch applications ('M-&' also works if the output
;; buffer does not bother you).
([?\s-d] . (lambda (command)
(interactive (list (read-shell-command "$ ")))
(start-process-shell-command command nil command)))
;; Bind "s-<f2>" to "slock", a simple X display locker.
([s-f2] . (lambda ()
(interactive)
(start-process "" nil "/usr/bin/slock")))))
;; To add a key binding only available in line-mode, simply define it in
;; `exwm-mode-map'. The following example shortens 'C-c q' to 'C-q'.
(define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
(push ?\C-c exwm-input-prefix-keys)
;; The following example demonstrates how to use simulation keys to mimic
;; the behavior of Emacs. The value of `exwm-input-simulation-keys` is a
;; list of cons cells (SRC . DEST), where SRC is the key sequence you press
;; and DEST is what EXWM actually sends to application. Note that both SRC
;; and DEST should be key sequences (vector or string).
(setq exwm-input-simulation-keys
`(
;; movement
(,(kbd "C-b") . left)
(,(kbd "M-b") . ,(kbd "C-<left>"))
(,(kbd "C-f") . right)
(,(kbd "M-f") . ,(kbd "C-<right>"))
(,(kbd "C-p") . up)
(,(kbd "C-n") . down)
(,(kbd "C-a") . home)
(,(kbd "C-e") . end)
(,(kbd "M-v") . prior)
(,(kbd "C-v") . next)
(,(kbd "C-d") . delete)
;;(,(kbs "C-k") . [S-end delete])
;; navigation
(,(kbd "C-c b") . ,(kbd "M-<left>"))
(,(kbd "C-c f") . ,(kbd "M-<right>"))
(,(kbd "C-c w") . ,(kbd "C-w"))
(,(kbd "C-w") . ,(kbd "C-x"))
(,(kbd "M-w") . ,(kbd "C-c"))
(,(kbd "C-y") . ,(kbd "C-v"))
;; search
(,(kbd "C-s") . ,(kbd "C-f"))))
;; You can hide the minibuffer and echo area when they're not used, by
;; uncommenting the following line.
;;(setq exwm-workspace-minibuffer-position 'bottom)
;; Do not forget to enable EXWM. It will start by itself when things are
;; ready. You can put it _anywhere_ in your configuration.
(exwm-enable)
(exwm-systemtray-enable)
(wm-randr)
;; (with-flag nlinum
;; (add-hook 'exwm-mode-hook 'disable-nlinum))
)
(provide 'cubes/wm/core)
;;; core.el ends here

View File

@ -33,10 +33,8 @@
(defun fg42/initialize ()
"Initialize FG42 after the Emacs window is rendered by loading the user init file."
(add-hook 'window-setup-hook
(lambda ()
(when (file-exists-p user-init-file)
(load user-init-file)))))
(when (file-exists-p user-init-file)
(load user-init-file)))
(provide 'fg42)

View File

@ -38,7 +38,7 @@ Flags are defined using the \\[defflag] through out the source code.
To see a list of available flags use \\[fg42/show-all-flags] and to see
the documentation of each flag simply use \\[describe-flag]."
:group fg42
:group 'fg42
:package-version '(FG42 . "3.x")
:type '(symbol)
:tag "FG42 Flags")
@ -46,7 +46,8 @@ the documentation of each flag simply use \\[describe-flag]."
(defmacro use-flags (&rest flags)
"Set the given FLAGS to activate their functionalities in FG42."
(setq fg42/flags flags))
(setq fg42/flags flags)
t)
(defun fg42/-merge-flags (flags-set &rest new-flags)
@ -81,25 +82,38 @@ For example, `(fg42/merge-flags (list f1 f2 f3) f4 -f2)' will return `(f1 f3 f4)
(defmacro defflag (flag-name docstring)
"Define a new flag FLAG-NAME with the given DOCSTRING."
(let ((var-name (format "fg42/-flag-%s" flag-name)))
`(if (boundp ,var-name)
(let ((var-name (intern (format "fg42/-flag-%s" flag-name))))
`(if (boundp ',var-name)
(warn (foramt "Flag name `%s' already defined" ,flag-name))
(progn
(defvar ,var-name t)
(add-to-list 'fg42/available-flags ,flag-name)))))
(add-to-list 'fg42/available-flags ',flag-name)))))
(defmacro when-flag (flag &rest body)
"Evaluate the BODY only if the given FLAG is active."
(declare (indent defun))
;; The `cube-local-flags' variable here is going to be
;; defined in cubes to hold the local flags for each cube
(if (and (boundp 'cube-local-flags)
(member flag cube-local-flags))
`,@body
(if (member flag fg42/flags)
`,@body
nil)))
`(if (member ',flag fg42/flags)
,body
nil)))
(defmacro if-flag (flag then else)
"Evaluate the THEN expr only if the given FLAG is active otherwise ELSE."
(declare (indent defun))
;; The `cube-local-flags' variable here is going to be
;; defined in cubes to hold the local flags for each cube
(if (and (boundp 'cube-local-flags)
(member flag cube-local-flags))
`,@then
`(if (member ',flag fg42/flags)
,then
,else)))
(provide 'fg42/flags)

View File

@ -163,5 +163,11 @@ last item in second form, etc."
(load-file file)))
(defmacro autoload-cube (fn file docstring)
"A wrapper for autloading FN at FILE with the given DOCSTRING.
This macro looks inside of the cubes directories."
`(autoload ,fn (expand-file-name (format "core/cubes/%s" ,file) fg42-home) ,docstring))
(provide 'fg42/utils)
;;; utils.el ends here

View File

@ -32,8 +32,8 @@
(defmacro fpkg/use (pkg &rest details)
"Install the given package details PKG via use-package and straight."
(declare (indent defun))
(message "heeeeeeeeeeeeeeeeeeeeer %s" pkg)
(if (listp details)
(if (and (listp details) (< 0 (length details)))
`(use-package ,pkg :straight ,@details :defer t)
`(use-package ,pkg :straight t :defer t)))