diff --git a/Makefile b/Makefile index 6ef5dd3..b995c43 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/core/cubes/wm.el b/core/cubes/wm.el new file mode 100644 index 0000000..a2d2fbe --- /dev/null +++ b/core/cubes/wm.el @@ -0,0 +1,54 @@ +;;; WMCube --- The elisp cube for FG42 -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2021 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; 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 . +;; +;;; 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 diff --git a/core/cubes/wm/core.el b/core/cubes/wm/core.el new file mode 100644 index 0000000..c83404e --- /dev/null +++ b/core/cubes/wm/core.el @@ -0,0 +1,159 @@ +;;; WMCube --- The elisp cube for FG42 -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2021 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; 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 . +;; +;;; 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-" 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-")) + (,(kbd "C-f") . right) + (,(kbd "M-f") . ,(kbd "C-")) + (,(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-")) + (,(kbd "C-c f") . ,(kbd "M-")) + (,(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 diff --git a/core/fg42.el b/core/fg42.el index 1ea333d..d4a886d 100644 --- a/core/fg42.el +++ b/core/fg42.el @@ -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) diff --git a/core/fg42/flags.el b/core/fg42/flags.el index d348f80..03c5f05 100644 --- a/core/fg42/flags.el +++ b/core/fg42/flags.el @@ -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) diff --git a/core/fg42/utils.el b/core/fg42/utils.el index ea8e0b6..b1ed1a4 100644 --- a/core/fg42/utils.el +++ b/core/fg42/utils.el @@ -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 diff --git a/core/fpkg.el b/core/fpkg.el index fa43f3d..9dff9a9 100644 --- a/core/fpkg.el +++ b/core/fpkg.el @@ -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)))