I showed you my source code, pls respond
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
5.2 KiB

4 years ago
4 years ago
  1. #+TITLE: Desktop
  2. #+AUTHOR: Christopher James Hayward
  3. #+EMAIL: chris@chrishayward.xyz
  4. #+PROPERTY: header-args:emacs-lisp :tangle desktop.el :comments org
  5. #+PROPERTY: header-args :results silent :eval no-export :comments org
  6. #+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil
  7. #+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
  8. I use Emacs as a Desktop Environment with the *EXWM*[fn:1] package. It allows Emacs to function as a complete tiling window manager for *X11*[fn:2].
  9. * Profile
  10. :PROPERTIES:
  11. :header-args: :tangle ../config/profile :comments org
  12. :END:
  13. Setup the default shell profile to run Emacs as a desktop environment.
  14. ** Append to the $PATH
  15. Ensure that ~~/.local/bin~ added to the =$PATH= variable.
  16. #+begin_src shell
  17. PATH=$PATH:~/.local/bin
  18. export PATH
  19. #+end_src
  20. ** Launch on TTY1
  21. When launching into a new session on ~TTY1~, if the display server is not running, run *StartX*[fn:3]. This will launch the window manager.
  22. #+begin_src shell
  23. if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then
  24. exec startx
  25. fi
  26. #+end_src
  27. ** Create symbolic link
  28. The system will look for the default shell profile at ~~/.profile~. Create a symbolic link from this location to the configuration file defined.
  29. #+begin_src emacs-lisp
  30. (dotfiles/symlink "~/.emacs.d/config/profile"
  31. "~/.profile")
  32. #+end_src
  33. * Window manager
  34. :PROPERTIES:
  35. :header-args: :tangle ../config/xinitrc :comments org
  36. :END:
  37. My workflow includes launching the window manager with *Xinit*[fn:3], without the use of a display manager, controlling *everything* within Emacs.
  38. #+begin_src conf
  39. exec dbus-launch --exit-with-session emacs -mm --debug-init
  40. #+end_src
  41. ** Create a symbolic link
  42. *Xinit*[fn:3] reads its configuration from ~~/.xinitrc~. Override this location with a link to the custom configuration.
  43. #+begin_src emacs-lisp
  44. (dotfiles/symlink "~/.emacs.d/config/xinitrc"
  45. "~/.xinitrc")
  46. #+end_src
  47. * Browser integration
  48. Write out the ~$BROWSER~ variable so other applications can pick up the custom browser.
  49. #+begin_src emacs-lisp
  50. (setenv "BROWSER" dotfiles/browser)
  51. #+end_src
  52. * Displays detection
  53. When the window manager first launches the ~init-hook~ executes, allowing us to define some custom logic.
  54. + Display time and date
  55. + Display battery info (if available)
  56. In my personal configuration, I do not want the battery or time displayed within Emacs when it's not running as desktop environment because that information is typically already available.
  57. #+begin_src emacs-lisp
  58. (defun dotfiles/init-hook ()
  59. (exwm-workspace-switch-create 1)
  60. (setq display-time-and-date t)
  61. (display-battery-mode 1)
  62. (display-time-mode 1))
  63. #+end_src
  64. Using =autorandr= with pre configured profiles, switching screens (AKA hot plugging) is also handled through a hook.
  65. #+begin_src emacs-lisp
  66. (defun dotfiles/update-display ()
  67. "Update the displays by forcing a change through autorandr."
  68. (dotfiles/run-in-background "autorandr --change --force"))
  69. #+end_src
  70. * Shell interaction
  71. Define a method to run an external process, allowing us to launch any application on a new process without interferring with Emacs.
  72. #+begin_src emacs-lisp
  73. (defun dotfiles/run (cmd)
  74. "Run an external process."
  75. (interactive (list (read-shell-command "λ ")))
  76. (start-process-shell-command cmd nil cmd))
  77. #+end_src
  78. Apply methods to the current call process to avoid issues with hooks.
  79. #+begin_src emacs-lisp
  80. (defun dotfiles/run-in-background (cmd)
  81. (let ((command-parts (split-string cmd "[ ]+")))
  82. (apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts)))))
  83. #+end_src
  84. Place keybindings for executing shell commands behind =SPC x=.
  85. + Run shell commands with =x=
  86. + Run async shell commands with =z=
  87. #+begin_src emacs-lisp
  88. (dotfiles/leader
  89. "x" '(:ignore t :which-key "Run")
  90. "xx" '(dotfiles/run :which-key "Run")
  91. "xz" '(async-shell-command :which-key "Async"))
  92. #+end_src
  93. * Configuration
  94. Connect our custom hooks and configure the input keys, a custom layer for key capture layers.
  95. + Enable =randr= support
  96. + Pass through to Emacs
  97. + =M-x= to Emacs
  98. + =C-g= to Emacs
  99. + =C-SPC= to Emacs
  100. + Bindings with =S= (Super / Win)
  101. + Reset =S-r=
  102. + Launch =S-&=
  103. + Workspace =S-[1..9]=
  104. #+begin_src emacs-lisp
  105. (use-package exwm
  106. :when (window-system)
  107. :custom (exwm-workspace-show-all-buffers t)
  108. (exwm-input-prefix-keys
  109. '(?\M-x
  110. ?\C-g
  111. ?\C-\ ))
  112. (exwm-input-global-keys
  113. `(([?\s-r] . exwm-reset)
  114. ,@(mapcar (lambda (i)
  115. `(,(kbd (format "s-%d" i)) .
  116. (lambda ()
  117. (interactive)
  118. (exwm-workspace-switch-create ,i))))
  119. (number-sequence 1 9))))
  120. :config (require 'exwm-randr)
  121. (exwm-randr-enable)
  122. (add-hook 'exwm-init-hook #'dotfiles/init-hook)
  123. (add-hook 'exwm-randr-screen-change-hook #'dotfiles/update-display)
  124. (add-hook 'exwm-update-class-hook (lambda () (exwm-workspace-rename-buffer exwm-class-name)))
  125. (dotfiles/update-display)
  126. (exwm-enable))
  127. #+end_src
  128. * Resources
  129. [fn:1] https://github.com/ch11ng/exwm
  130. [fn:2] https://en.wikipedia.org/wiki/X_Window_System
  131. [fn:3] https://en.wikipedia.org/wiki/Xinit