From 5a866ddf1c29104591f7ae6a2e0e81d36c0afe57 Mon Sep 17 00:00:00 2001 From: Almarhoon Ibraheem Date: Sat, 15 Jun 2024 10:57:11 +0300 Subject: [PATCH] init commit --- README.org | 127 ++ behavior.scm | 9 + commander | 39 + config | 2 + init.scm | 51 + keybindings.scm | 122 ++ modules/auto-reload.scm | 4 + modules/general.scm | 124 ++ modules/kbd.scm | 2113 ++++++++++++++++++++++++++++++++++ modules/which-key.scm | 4 + modules/workspace-grid.scm | 167 +++ modules/workspace-groups.scm | 110 ++ sjson/builder.scm | 280 +++++ sjson/parser.scm | 490 ++++++++ sjson/record.scm | 230 ++++ swayipc/connection.scm | 201 ++++ swayipc/dispatcher.scm | 1495 ++++++++++++++++++++++++ swayipc/events.scm | 173 +++ swayipc/info.scm | 113 ++ swayipc/records.scm | 491 ++++++++ 20 files changed, 6345 insertions(+) create mode 100644 README.org create mode 100755 behavior.scm create mode 100755 commander create mode 100644 config create mode 100755 init.scm create mode 100755 keybindings.scm create mode 100755 modules/auto-reload.scm create mode 100755 modules/general.scm create mode 100755 modules/kbd.scm create mode 100755 modules/which-key.scm create mode 100755 modules/workspace-grid.scm create mode 100755 modules/workspace-groups.scm create mode 100644 sjson/builder.scm create mode 100644 sjson/parser.scm create mode 100644 sjson/record.scm create mode 100755 swayipc/connection.scm create mode 100644 swayipc/dispatcher.scm create mode 100755 swayipc/events.scm create mode 100755 swayipc/info.scm create mode 100755 swayipc/records.scm diff --git a/README.org b/README.org new file mode 100644 index 0000000..938404a --- /dev/null +++ b/README.org @@ -0,0 +1,127 @@ +#+title: Readme +#+STARTUP: inlineimages +#+OPTIONS: toc:3 ^:nil + +** SWAYIPC + +I am an =Emacs= user and previously used =StumpWM=, an =X11= window manager written in =Common Lisp=. I believe window managers should be scriptable because the level of workflow customization required by users often exceeds what can be achieved with simple configuration parameters (see my workflow below for a clearer understanding of why this is the case). Unfortunately, =Sway/i3= lacks a straightforward programmable interface for customization. This project provides complete control over =Sway/i3= using =Guile=! + +** Why Sway? + +I had to migrate to =Wayland= at some point. Being a big fan of =StumpWM=, I tried to replicate a similar environment in one of the =Wayland= window managers. I made some progress with =hyprland= using a set of =Guile= bindings I developed called =hypripc=, but I found that =Hyprland= isn't as stable as =Sway=. + +** Quick Overview + +*** Query Sway + +You can retrieve information about =Sway=, such as list of available =workspaces= or =outputs=. The response will be in Guile records, which you can easily manipulate! (refer to =swayipc/records.scm=) + +#+begin_src scheme +;; get focused workspace from a list of workspaces +(define (focused-workspace-name workspaces) + (cond + ((null? workspaces) #f) + ((equal? #t (sway-workspace-focused (car workspaces))) + (sway-workspace-name (car workspaces))) + (else (focused-workspace-name (cdr workspaces))))) + +(focused-workspace-name (sway-get-workspaces)) +#+end_src + +*** Assign Keybindings + +You can assign keybindings that execute Guile code! Obviously, running shell commands is straightforward since you're operating within Guile. Additionally, you have full access to Sway/i3 specific commands (refer to =swayipc/dispatcher.scm=). + +#+begin_src scheme + ;; define leader keymap + (sway-define-keys + #:prefix "s-Space" #:wk "Leader" + `("o" (exec "rofi -show drun")) + `("C-g" (sway-mode "default") #:wk "abort") + + ;; rofi keymap + `(sway-define-keys + #:prefix "r" #:wk "Rofi" + ("p" (exec "~/.config/rofi/bin/password-manager")) + ("m" (exec "rofi-mount")) + ("u" (exec "rofi-unmount")) + ("w" (exec ".config/rofi/bin/wifi")) + ("b" (exec "~/.config/rofi/bin/bluetooth")) + ("f" (exec "~/.config/rofi/bin/finder")) + ("k" (exec "~/.config/rofi/bin/keyboard-layout")) + ("P" (exec "~/.config/rofi/bin/powermenu")) + ("s" (exec "~/.config/rofi/bin/sound-input")) + ("S" (exec "~/.config/rofi/bin/sound-output"))) + + ;; window management + `(sway-define-keys + #:prefix "w" #:wk "Window" + ("v" (sway-split-container SWAY-SPLIT-VERTICAL)) + ("h" (sway-split-container SWAY-SPLIT-HORIZONTAL)) + ("f" (sway-fullscreen SWAY-FULLSCREEN-TOGGLE)) + ("d" (sway-fullscreen SWAY-FULLSCREEN-TOGGLE)))) +#+end_src + +*** Subscribe for Events + +Certain scenarios necessitate subscribing to events. One example from my =workflow= described below requires this capability. With =swayipc=, you have the ability to listen for events and execute actions in response. + +#+begin_src scheme + (define (workspace-changed workspace-event) + (let* ((current-tree (sway-workspace-event-current workspace-event)) + (workspace (sway-tree-name current-tree)) + (focused-workspace (focused-workspace (sway-get-workspaces)))) + + (display workspace))) + + (add-hook! sway-workspace-hook workspace-changed) +#+end_src + +** Documentation (WIP) + +Most of the source code is documented. You can refer to =init.scm= for a configuration sample. Here are some important points to consider before hacking your Sway setup: + +*** Quick Start +Clone this repository to your =~/.config/sway= + +*** Project Structure + +| File | Description | +|------------------------------+-----------------------------------------------------------------------------------------------------------| +| init.scm | Main entry point for configuring Sway using Guile. | +| behavior.scm | Loaded by =init.scm=; modifies parameters and behavior of Sway. | +| keybindings.scm | Loaded by =init.scm=; adds custom keybindings to Sway. | +| commander | Guile script to send commands to =swayipc= (facilitates keybinding functionality). | +| config | Sway configuration file; typically used to invoke =init.scm=. | +| sjson | A patched version of =guile-json=; planned to be a separate dependency in the future (not embedded). | +|------------------------------+-----------------------------------------------------------------------------------------------------------| +| modules/ | Directory containing modules for extending Sway using =swayipc=. | +| modules/auto-reload.scm | TODO: Watcher to automatically reload Sway when Guile files change. | +| modules/general.scm | Inspired by Emacs =general= package; provides an easy interface for assigning keybindings. | +| modules/kbd.scm | WIP: Translates Emacs-like keybindings to be compatible with =Sway=. | +| modules/which-key.scm | TODO: Inspired by Emacs =which-key= package; enhances keybinding discovery and management. | +| modules/workspace-grid.scm | Configures workspaces in a grid and enables movement between them in specified directions (see workflow). | +| modules/workspace-groups.scm | WIP: Spans/synchronizes workspaces across monitors (see workflow). | +|------------------------------+-----------------------------------------------------------------------------------------------------------| +| swayipc/ | Directory containing the core code for =swayipc=, facilitating communication with Sway. | +| swayipc/connection | Establishes =IPC= connection for handling events and commands with Sway. | +| swayipc/dispatcher | Provides =Guile functions= for all available =Sway= commands. | +| swayipc/events | Provides =Gulie Hooks= for all available =Sway= events. | +| swayipc/info | Provides =Guile functions= for querying Sway's current state and information. | +| swayipc/records | Provides =Guile records= representing Sway's data structures. | + +1- You can start your =swayipc= configurations from the =REPL=, =terminal=, or a configuration file. +Remember: for debugging or displaying output, it's best to run Guile from the REPL or terminal. You can also pipe the output to a file if you desire. + +#+begin_src conf +# from sway config file +exec_always "~/.config/sway/init.scm" +#+end_src + +2- I plan to publish a module for =swayipc=, it's currently not hosted anywhere. You'll need to add the module to your =load path=. Additionally, =swayipc= includes another patched Guile library called =guile-json=, which is embedded for now. In the future, this will be included as a separate dependency rather than embedded. + +#+begin_src scheme +(add-to-load-path + (dirname (or (current-filename) + (string-append (getenv "HOME") "/.config/sway/init.scm")))) +#+end_src diff --git a/behavior.scm b/behavior.scm new file mode 100755 index 0000000..71d8eb8 --- /dev/null +++ b/behavior.scm @@ -0,0 +1,9 @@ +(use-modules (swayipc dispatcher)) + +(sway-output "HDMI-A-2" "resolution 1920x1080 position 0,0") +(sway-output "DP-1" "resolution 1920x1080 position 0,0") +(sway-output "DP-2" "resolution 1920x1080 position 0,0") + +(sway-output "*" "bg /home/ebeem/dotfiles/.wallpapers/fixed/flat-20.png fill") + +(sway-focus-follow-mouse SWAY-FOCUS-FOLLOW-MOUSE-FLAG-NO) diff --git a/commander b/commander new file mode 100755 index 0000000..25d15dd --- /dev/null +++ b/commander @@ -0,0 +1,39 @@ +#!/usr/bin/guile \ +-e main -s +!# +;; #!/usr/bin/guile --fresh-auto-compile +;; ensure that the swayipc module is available under the same directory as the init file +;; otherwise, the module should be referenced from packaging system or via custom load path + +(add-to-load-path + (dirname (or (current-filename) + (string-append (getenv "HOME") "/.config/sway/init.scm")))) + +(use-modules (swayipc connection) + (ice-9 popen) + (sjson builder) + (ice-9 binary-ports) + (rnrs bytevectors) + (rnrs io ports) + (oop goops) + (srfi srfi-18) + (srfi srfi-9) + (srfi srfi-1)) + +(define COMMANDS-CLIENT-SOCKET (socket AF_UNIX SOCK_STREAM 0)) +(display (string-append "connecting to " SOCKET-COMMANDS-LISTENER-PATH "\n")) +(connect COMMANDS-CLIENT-SOCKET + (make-socket-address AF_UNIX SOCKET-COMMANDS-LISTENER-PATH)) +(display "connected\n") + +(define (send-command command) + (display (string-append "sending command: " command "\n")) + (display (write-msg COMMANDS-CLIENT-SOCKET + RUN-COMMMAND-MSG-ID + (scm->json-string command))) + (display "sent\n")) + +(define (main args) + (display (string-join (cdr args) " ")) + (newline) + (send-command (string-join (cdr args) " "))) diff --git a/config b/config new file mode 100644 index 0000000..76a5015 --- /dev/null +++ b/config @@ -0,0 +1,2 @@ +include /etc/sway/config.d/* +exec_always "~/.config/sway/init.scm" diff --git a/init.scm b/init.scm new file mode 100755 index 0000000..b1a7f82 --- /dev/null +++ b/init.scm @@ -0,0 +1,51 @@ +#!/usr/bin/guile +!# + +(add-to-load-path + (dirname (or (current-filename) + (string-append (getenv "HOME") "/.config/sway/init.scm")))) + +(use-modules (oop goops) + (srfi srfi-18) + (modules workspace-groups) + (modules workspace-grid) + (swayipc connection) + (swayipc records) + (swayipc info) + (swayipc events) + (swayipc dispatcher)) + +(load "behavior.scm") +;; init keybindings +(load "keybindings.scm") +(keybindings-init) + +;; subscribe to all events +(sway-subscribe-all) + +(set! OUTPUTS '("HDMI-A-2" "DP-1" "DP-2")) +(set! GROUPS + '(("11-browser" "21-browser" "31-browser") + ("12-development" "22-development" "32-development") + ("13-databases" "23-databases" "33-databases") + ("14-communication" "24-communication" "34-communication") + ("15-development" "25-development" "35-development") + ("16-gaming" "26-gaming" "36-gaming") + ("17-mail" "27-mail" "37-mail") + ("18-development" "28-development" "38-development") + ("19-media" "29-media" "39-media"))) + +(workspace-groups-init) + +(set! ROWS 3) +(set! COLUMNS 3) +(set! WORKSPACES (apply map list GROUPS)) + +(workspace-grid-init) + +;; TODO: load which key module + +(start-commands-listener-thread) +(start-event-listener-thread) +(thread-join! LISTENER-THREAD) +(thread-join! COMMANDS-LISTENER-THREAD) diff --git a/keybindings.scm b/keybindings.scm new file mode 100755 index 0000000..5539fa4 --- /dev/null +++ b/keybindings.scm @@ -0,0 +1,122 @@ +(use-modules (modules kbd) + (modules general) + (ice-9 popen) + (srfi srfi-18) + (ice-9 textual-ports)) + +(define (exec command) + "execute given shell command" + (display (string-append "running " command "\n")) + (thread-start! (make-thread (lambda () (system command))))) + +(define (custom-sway-keybinding-translator key) + "Translates keybindings, passing kbd function will enable emacs + like key chords. The default implementation doesn't modify passed keybindings" + (kbd key)) + +(define (keybindings-init) + (kbd-init) + + ;; (configure-sway-keybinding-translator custom-sway-keybinding-translator) + (define general-module (resolve-module '(modules general))) + (configure-sway-keybinding-translator custom-sway-keybinding-translator) + + ;; define root keybindings + (sway-define-keys + ;; media-keys + `("XF86AudioLowerVolume" (exec "pactl set-sink-volume @DEFAULT_SINK@ -5%")) + `("XF86AudioRaiseVolume" (exec "pactl set-sink-volume @DEFAULT_SINK@ +5%")) + `("s-[" (exec "pactl set-sink-volume @DEFAULT_SINK@ -5%")) + `("s-]" (exec "pactl set-sink-volume @DEFAULT_SINK@ +5%")) + `("XF86AudioMute" (exec "pactl set-sink-mute @DEFAULT_SINK@ toggle")) + `("XF86AudioNext" (exec "mpc next")) + `("XF86AudioPrev" (exec "mpc prev")) + `("XF86AudioPlay" (exec "mpc toggle")) + + ;; brightness-keys + `("XF86MonBrightnessUp" (exec "brightnessctl set +10%")) + `("XF86MonBrightnessDown" (exec "brightnessctl set 10%-")) + + ;; window and group management + `("s-f" (sway-fullscreen SWAY-FULLSCREEN-TOGGLE)) + + ;; move focus + `("s-h" (sway-focus-container SWAY-DIRECTION-LEFT)) + `("s-j" (sway-focus-container SWAY-DIRECTION-DOWN)) + `("s-k" (sway-focus-container SWAY-DIRECTION-UP)) + `("s-l" (sway-focus-container SWAY-DIRECTION-RIGHT)) + + ;; move containers + `("s-S-h" (sway-move-container SWAY-DIRECTION-LEFT)) + `("s-S-j" (sway-move-container SWAY-DIRECTION-DOWN)) + `("s-S-k" (sway-move-container SWAY-DIRECTION-UP)) + `("s-S-l" (sway-move-container SWAY-DIRECTION-RIGHT)) + + ;; switch workspace + `("s-C-h" (switch-workspace-left)) + `("s-C-j" (switch-workspace-down)) + `("s-C-k" (switch-workspace-up)) + `("s-C-l" (switch-workspace-right)) + + ;; move container to workspace + `("s-M-C-h" (move-container-to-workspace-left)) + `("s-M-C-j" (move-container-to-workspace-down)) + `("s-M-C-k" (move-container-to-workspace-up)) + `("s-M-C-l" (move-container-to-workspace-right)) + + ;; ;; Tab like cycling + ;; (define-key *top-map* (kbd "s-.") "next-in-frame") + ;; (define-key *top-map* (kbd "s-,") "prev-in-frame") + + `("s-w" (sway-kill)) + `("s-Return" (exec "alacritty")) + `("M-s-Space" (exec "~/.bin/switch-keyboard-layout")) + `("C-s-Space" (exec "rofi -show drun"))) + + ;; define leader keymap + (sway-define-keys + #:prefix "s-Space" #:wk "Leader" + `("o" (exec "rofi -show drun")) + `("C-g" (sway-mode "default") #:wk "abort") + + ;; rofi keymap + `(sway-define-keys + #:prefix "r" #:wk "Rofi" + ("p" (exec "~/.config/rofi/bin/password-manager")) + ("m" (exec "rofi-mount")) + ("u" (exec "rofi-unmount")) + ("w" (exec ".config/rofi/bin/wifi")) + ("b" (exec "~/.config/rofi/bin/bluetooth")) + ("f" (exec "~/.config/rofi/bin/finder")) + ("k" (exec "~/.config/rofi/bin/keyboard-layout")) + ("P" (exec "~/.config/rofi/bin/powermenu")) + ("s" (exec "~/.config/rofi/bin/sound-input")) + ("S" (exec "~/.config/rofi/bin/sound-output"))) + + ;; screenshot keymap + `(sway-define-keys + #:prefix "s" #:wk "Screenshot" + ("d" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot gui")) + ("s" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot screen")) + ("f" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot full")) + ("m" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot gui --last-region")) + + (sway-define-keys + #:prefix "d" #:wk "DelayScreenshot" + ("d" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot gui -d 2500")) + ("s" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot screen -d 2500")) + ("f" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot full -d 2500")) + ("l" (exec "export XDG_CURRENT_DESKTOP=sway && flameshot gui -d 2500 --last-region")))) + + ;; session keymap + `(sway-define-keys + #:prefix "q" #:wk "Session" + ("q" (sway-exit)) + ("r" (sway-reload))) + + `(sway-define-keys + #:prefix "w" #:wk "Window" + ("v" (sway-split-container SWAY-SPLIT-VERTICAL)) + ("h" (sway-split-container SWAY-SPLIT-HORIZONTAL)) + ("f" (sway-fullscreen SWAY-FULLSCREEN-TOGGLE)) + ("d" (sway-fullscreen SWAY-FULLSCREEN-TOGGLE))))) diff --git a/modules/auto-reload.scm b/modules/auto-reload.scm new file mode 100755 index 0000000..22637ca --- /dev/null +++ b/modules/auto-reload.scm @@ -0,0 +1,4 @@ +(define-module (modules which-key) + #:use-module (swayipc dispatcher) + #:export ()) + diff --git a/modules/general.scm b/modules/general.scm new file mode 100755 index 0000000..350c3d5 --- /dev/null +++ b/modules/general.scm @@ -0,0 +1,124 @@ +(define-module (modules general) + #:use-module (sjson parser) + #:use-module (swayipc dispatcher) + #:use-module (swayipc connection) + #:use-module (srfi srfi-18) + #:use-module (ice-9 hash-table) + #:export (sway-keybinding-translator + configure-sway-keybinding-translator + sway-define-keys + sway-define-key + sway-keybindings + sway-submaps)) + +;; Local copy of keybindings configured by general, it's recommended to +;; only use general to assign keybindings, otherwise this hashtable won't +;; by synced with actual keybindings available in sway +(define sway-keybindings (make-hash-table)) + +;; Local copy of submaps configured by general, it's recommended to +;; only use general to assign submaps, otherwise this hashtable won't +;; by synced with actual submaps available in sway" +(define sway-submaps (make-hash-table)) +(hash-set! sway-submaps "" "default") + +(define (sway-keybinding-translator key) + "Translates keybindings, passing kbd function will enable emacs + like key chords. The default implementation doesn't modify passed keybindings" + key) + +(define (configure-sway-keybinding-translator proc) + (set! sway-keybinding-translator proc)) + +(define (exp->string exp) + (call-with-output-string (lambda (p) + (write exp p)))) + +(define* (define-submap chord key wk submap parent-submap) + (display (string-append "define submap " chord "\n")) + (hash-set! sway-submaps chord submap) + (define-keybindings chord key + `(sway-mode ,submap) + wk parent-submap) + (define-keybindings (string-append chord " Esc") + "Escape" `(sway-mode "default") + "Escape" submap)) + +(define (last-key key) + (car (reverse (string-split key #\+)))) + +(define (sway-command exp-str) + (string-append "exec '" (dirname (dirname (current-filename))) "/commander " + (exp->string exp-str) "'")) + +(define* (define-keybindings chord key exp wk submap) + (hash-set! sway-keybindings chord '(key exp wk submap)) + (let* ((type (if (string->number (last-key key)) "bindcode" "bindsym")) + (command (string-append type " " key " " (sway-command (exp->string exp)))) + (esc (string-append type " " key " " (sway-command (exp->string `(and ,exp (sway-mode "default"))))))) + (if (equal? submap "default") + (dispatch-command command) + (begin + (sway-mode-subcommand submap command) + (unless (equal? "sway-mode" (symbol->string (car exp))) + (display "escape after executing\n") + (display esc) + (sway-mode-subcommand submap esc)))))) + +(define (find-submap chord) + (or + (hash-get-handle sway-submaps + (string-join + (list-head chord (- (length chord) 1)) " ")) + (error 'find-submap "chord was not found in submaps, a submap has to be defined for it" chord))) + +(define* (sway-define-key chord #:optional exp #:key wk submap) + "assign a key to a given expression" + (let* ((chord-ls + (map sway-keybinding-translator + (string-split chord #\Space))) + (chord (string-join chord-ls " ")) + (key (car (last-pair chord-ls))) + (key-code (string->number key)) + (description (or wk (or submap (symbol->string (car exp)))))) + (if submap + (define-submap chord key wk submap + (cdr (find-submap chord-ls))) + (define-keybindings chord key exp wk + (cdr (find-submap chord-ls)))))) + +(define* (sway-define-keys #:key parent-prefix prefix wk . args ) + (when parent-prefix + (set! prefix (string-append parent-prefix " " prefix))) + + (when prefix + (display (string-append "define prefix submap: " prefix ", wk " wk "\n")) + (sway-define-key prefix #:submap wk)) + + (map (lambda (arg) + (when (list? arg) + + (display "ARG: ") + (display arg) + (newline) + (display (car arg)) + (newline) + (if (and + (symbol? (car arg)) + (equal? "sway-define-keys" (symbol->string (car arg)))) + (apply sway-define-keys (append `(#:parent-prefix ,prefix) (cdr arg))) + (apply sway-define-key + (cons (string-append + (if prefix (string-append prefix " ") "") + (car arg)) (cdr arg)))))) + args)) + +(define (custom-exception-handler exc command-id payload) + (display "An error occurred: ") + (display (exp->string exc)) + (newline) + (display (string-append "command: " (number->string command-id) ", payload: " payload))) + +(add-hook! command-received-hook + (lambda (command-id payload) + (eval-string (json-string->scm payload)))) diff --git a/modules/kbd.scm b/modules/kbd.scm new file mode 100755 index 0000000..472e70e --- /dev/null +++ b/modules/kbd.scm @@ -0,0 +1,2113 @@ +(define-module (modules kbd) + #:use-module (ice-9 hash-table) + #:export (kbd-init + define-keysym + define-modsym + keysym-translations + modsym-translations + keysym-clean + kbd)) + +(define keysym-translations (make-hash-table)) +(define modsym-translations (make-hash-table)) + +(define (replace-char str old-char new-char) + (string-map + (lambda (ch) + (if (char=? ch old-char) + new-char + ch)) + str)) + +(define (keysym-clean key) + (if (<= (string-length (string-trim-both key)) 1) + key + (string-trim-both + (string-downcase + (replace-char key #\_ #\-))))) + +(define (define-keysym key translation) + "Define a mapping from a modifier to a code." + (hash-set! keysym-translations (keysym-clean key) translation)) + +(define (define-modsym key translation) + "Define a mapping from a key to a code." + (hash-set! modsym-translations key translation)) + +(define (string-starts-with? str prefix) + (let ((prefix-length (string-length prefix))) + (and (>= (string-length str) prefix-length) + (string=? (substring str 0 prefix-length) prefix)))) + +(define* (replace-modifiers key #:optional (translation "")) + (cond + ((< (string-length key) 2) (list translation key)) + ((hash-get-handle modsym-translations (substring key 0 2)) + (replace-modifiers + (substring key 2) + (string-append + translation + (cdr (hash-get-handle modsym-translations (substring key 0 2)))))) + (else (list translation key)))) + +(define* (replace-key-symbols key) + (if + (and (equal? #\< (string-ref key 0)) + (equal? #\> (string-ref key (- (string-length key) 1)))) + (let* ((lkey (keysym-clean (substring key 1 (- (string-length key) 1)))) + (translation (hash-get-handle keysym-translations lkey))) + (if (pair? translation) + (cdr translation) + key)) + key)) + +(define (sway-key key) + (let* ((modifier (replace-modifiers key)) + (rkey (replace-key-symbols (list-ref modifier 1)))) + (string-append (list-ref modifier 0) + (if (number? rkey) + (number->string rkey) + rkey)))) + +(define (kbd seq) + "return sway compatible keybinding symbols from emacs like key sequence" + (string-join + (map sway-key + (string-split seq #\Space)) " ")) + +(define (kbd-init) + ;; key modifiers + (define-modsym "C-" "Control+") + (define-modsym "S-" "Shift+") + (define-modsym "s-" "mod4+") + (define-modsym "M-" "Alt+") + (define-modsym "C-" "Control+") + + ;; key symbols + (define-keysym "VoidSymbol" #xffffff) + (define-keysym "BackSpace" #xff08) + (define-keysym "Tab" #xff09) + (define-keysym "Linefeed" #xff0a) + (define-keysym "Clear" #xff0b) + (define-keysym "Return" #xff0d) + (define-keysym "Ret" #xff0d) + (define-keysym "Pause" #xff13) + (define-keysym "Scroll_Lock" #xff14) + (define-keysym "Sys_Req" #xff15) + (define-keysym "Escape" #xff1b) + (define-keysym "Esc" #xff1b) + (define-keysym "Delete" #xffff) + (define-keysym "Del" #xffff) + (define-keysym "Multi_key" #xff20) + (define-keysym "Codeinput" #xff37) + (define-keysym "SingleCandidate" #xff3c) + (define-keysym "MultipleCandidate" #xff3d) + (define-keysym "PreviousCandidate" #xff3e) + (define-keysym "Kanji" #xff21) + (define-keysym "Muhenkan" #xff22) + (define-keysym "Henkan_Mode" #xff23) + (define-keysym "Henkan" #xff23) + (define-keysym "Romaji" #xff24) + (define-keysym "Hiragana" #xff25) + (define-keysym "Katakana" #xff26) + (define-keysym "Hiragana_Katakana" #xff27) + (define-keysym "Zenkaku" #xff28) + (define-keysym "Hankaku" #xff29) + (define-keysym "Zenkaku_Hankaku" #xff2a) + (define-keysym "Touroku" #xff2b) + (define-keysym "Massyo" #xff2c) + (define-keysym "Kana_Lock" #xff2d) + (define-keysym "Kana_Shift" #xff2e) + (define-keysym "Eisu_Shift" #xff2f) + (define-keysym "Eisu_toggle" #xff30) + (define-keysym "Kanji_Bangou" #xff37) + (define-keysym "Zen_Koho" #xff3d) + (define-keysym "Mae_Koho" #xff3e) + (define-keysym "Home" #xff50) + (define-keysym "Left" #xff51) + (define-keysym "Up" #xff52) + (define-keysym "Right" #xff53) + (define-keysym "Down" #xff54) + (define-keysym "Prior" #xff55) + (define-keysym "Page_Up" #xff55) + (define-keysym "Next" #xff56) + (define-keysym "Page_Down" #xff56) + (define-keysym "End" #xff57) + (define-keysym "Begin" #xff58) + (define-keysym "Select" #xff60) + (define-keysym "Print" #xff61) + (define-keysym "Execute" #xff62) + (define-keysym "Insert" #xff63) + (define-keysym "Undo" #xff65) + (define-keysym "Redo" #xff66) + (define-keysym "Menu" #xff67) + (define-keysym "Find" #xff68) + (define-keysym "Cancel" #xff69) + (define-keysym "Help" #xff6a) + (define-keysym "Break" #xff6b) + (define-keysym "Mode_switch" #xff7e) + (define-keysym "script_switch" #xff7e) + (define-keysym "Num_Lock" #xff7f) + (define-keysym "KP_Space" #xff80) + (define-keysym "KP_Tab" #xff89) + (define-keysym "KP_Enter" #xff8d) + (define-keysym "KP_F1" #xff91) + (define-keysym "KP_F2" #xff92) + (define-keysym "KP_F3" #xff93) + (define-keysym "KP_F4" #xff94) + (define-keysym "KP_Home" #xff95) + (define-keysym "KP_Left" #xff96) + (define-keysym "KP_Up" #xff97) + (define-keysym "KP_Right" #xff98) + (define-keysym "KP_Down" #xff99) + (define-keysym "KP_Prior" #xff9a) + (define-keysym "KP_Page_Up" #xff9a) + (define-keysym "KP_Next" #xff9b) + (define-keysym "KP_Page_Down" #xff9b) + (define-keysym "KP_End" #xff9c) + (define-keysym "KP_Begin" #xff9d) + (define-keysym "KP_Insert" #xff9e) + (define-keysym "KP_Delete" #xff9f) + (define-keysym "KP_Equal" #xffbd) + (define-keysym "KP_Multiply" #xffaa) + (define-keysym "KP_Add" #xffab) + (define-keysym "KP_Separator" #xffac) + (define-keysym "KP_Subtract" #xffad) + (define-keysym "KP_Decimal" #xffae) + (define-keysym "KP_Divide" #xffaf) + (define-keysym "KP_0" #xffb0) + (define-keysym "KP_1" #xffb1) + (define-keysym "KP_2" #xffb2) + (define-keysym "KP_3" #xffb3) + (define-keysym "KP_4" #xffb4) + (define-keysym "KP_5" #xffb5) + (define-keysym "KP_6" #xffb6) + (define-keysym "KP_7" #xffb7) + (define-keysym "KP_8" #xffb8) + (define-keysym "KP_9" #xffb9) + (define-keysym "F1" #xffbe) + (define-keysym "F2" #xffbf) + (define-keysym "F3" #xffc0) + (define-keysym "F4" #xffc1) + (define-keysym "F5" #xffc2) + (define-keysym "F6" #xffc3) + (define-keysym "F7" #xffc4) + (define-keysym "F8" #xffc5) + (define-keysym "F9" #xffc6) + (define-keysym "F10" #xffc7) + (define-keysym "F11" #xffc8) + (define-keysym "F12" #xffc9) + (define-keysym "F13" #xffca) + (define-keysym "F14" #xffcb) + (define-keysym "F15" #xffcc) + (define-keysym "F16" #xffcd) + (define-keysym "F17" #xffce) + (define-keysym "F18" #xffcf) + (define-keysym "F19" #xffd0) + (define-keysym "F20" #xffd1) + (define-keysym "F21" #xffd2) + (define-keysym "F22" #xffd3) + (define-keysym "F23" #xffd4) + (define-keysym "F24" #xffd5) + (define-keysym "F25" #xffd6) + (define-keysym "F26" #xffd7) + (define-keysym "F27" #xffd8) + (define-keysym "F28" #xffd9) + (define-keysym "F29" #xffda) + (define-keysym "F30" #xffdb) + (define-keysym "F31" #xffdc) + (define-keysym "F32" #xffdd) + (define-keysym "F33" #xffde) + (define-keysym "F34" #xffdf) + (define-keysym "F35" #xffe0) + (define-keysym "Shift_L" #xffe1) + (define-keysym "Shift_R" #xffe2) + (define-keysym "Control_L" #xffe3) + (define-keysym "Control_R" #xffe4) + (define-keysym "Caps_Lock" #xffe5) + (define-keysym "Shift_Lock" #xffe6) + (define-keysym "Meta_L" #xffe7) + (define-keysym "Meta_R" #xffe8) + (define-keysym "Alt_L" #xffe9) + (define-keysym "Alt_R" #xffea) + (define-keysym "Super_L" #xffeb) + (define-keysym "Super_R" #xffec) + (define-keysym "Hyper_L" #xffed) + (define-keysym "Hyper_R" #xffee) + (define-keysym "ISO_Lock" #xfe01) + (define-keysym "ISO_Level2_Latch" #xfe02) + (define-keysym "ISO_Level3_Shift" #xfe03) + (define-keysym "ISO_Level3_Latch" #xfe04) + (define-keysym "ISO_Level3_Lock" #xfe05) + (define-keysym "ISO_Group_Shift" #xff7e) + (define-keysym "ISO_Group_Latch" #xfe06) + (define-keysym "ISO_Group_Lock" #xfe07) + (define-keysym "ISO_Next_Group" #xfe08) + (define-keysym "ISO_Next_Group_Lock" #xfe09) + (define-keysym "ISO_Prev_Group" #xfe0a) + (define-keysym "ISO_Prev_Group_Lock" #xfe0b) + (define-keysym "ISO_First_Group" #xfe0c) + (define-keysym "ISO_First_Group_Lock" #xfe0d) + (define-keysym "ISO_Last_Group" #xfe0e) + (define-keysym "ISO_Last_Group_Lock" #xfe0f) + (define-keysym "ISO_Left_Tab" #xfe20) + (define-keysym "ISO_Move_Line_Up" #xfe21) + (define-keysym "ISO_Move_Line_Down" #xfe22) + (define-keysym "ISO_Partial_Line_Up" #xfe23) + (define-keysym "ISO_Partial_Line_Down" #xfe24) + (define-keysym "ISO_Partial_Space_Left" #xfe25) + (define-keysym "ISO_Partial_Space_Right" #xfe26) + (define-keysym "ISO_Set_Margin_Left" #xfe27) + (define-keysym "ISO_Set_Margin_Right" #xfe28) + (define-keysym "ISO_Release_Margin_Left" #xfe29) + (define-keysym "ISO_Release_Margin_Right" #xfe2a) + (define-keysym "ISO_Release_Both_Margins" #xfe2b) + (define-keysym "ISO_Fast_Cursor_Left" #xfe2c) + (define-keysym "ISO_Fast_Cursor_Right" #xfe2d) + (define-keysym "ISO_Fast_Cursor_Up" #xfe2e) + (define-keysym "ISO_Fast_Cursor_Down" #xfe2f) + (define-keysym "ISO_Continuous_Underline" #xfe30) + (define-keysym "ISO_Discontinuous_Underline" #xfe31) + (define-keysym "ISO_Emphasize" #xfe32) + (define-keysym "ISO_Center_Object" #xfe33) + (define-keysym "ISO_Enter" #xfe34) + + (define-keysym "First_Virtual_Screen" #xfed0) + (define-keysym "Prev_Virtual_Screen" #xfed1) + (define-keysym "Next_Virtual_Screen" #xfed2) + (define-keysym "Last_Virtual_Screen" #xfed4) + (define-keysym "Terminate_Server" #xfed5) + (define-keysym "AccessX_Enable" #xfe70) + (define-keysym "AccessX_Feedback_Enable" #xfe71) + (define-keysym "RepeatKeys_Enable" #xfe72) + (define-keysym "SlowKeys_Enable" #xfe73) + (define-keysym "BounceKeys_Enable" #xfe74) + (define-keysym "StickyKeys_Enable" #xfe75) + (define-keysym "MouseKeys_Enable" #xfe76) + (define-keysym "MouseKeys_Accel_Enable" #xfe77) + (define-keysym "Overlay1_Enable" #xfe78) + (define-keysym "Overlay2_Enable" #xfe79) + (define-keysym "AudibleBell_Enable" #xfe7a) + (define-keysym "Pointer_Left" #xfee0) + (define-keysym "Pointer_Right" #xfee1) + (define-keysym "Pointer_Up" #xfee2) + (define-keysym "Pointer_Down" #xfee3) + (define-keysym "Pointer_UpLeft" #xfee4) + (define-keysym "Pointer_UpRight" #xfee5) + (define-keysym "Pointer_DownLeft" #xfee6) + (define-keysym "Pointer_DownRight" #xfee7) + (define-keysym "Pointer_Button_Dflt" #xfee8) + (define-keysym "Pointer_Button1" #xfee9) + (define-keysym "Pointer_Button2" #xfeea) + (define-keysym "Pointer_Button3" #xfeeb) + (define-keysym "Pointer_Button4" #xfeec) + (define-keysym "Pointer_Button5" #xfeed) + (define-keysym "Pointer_DblClick_Dflt" #xfeee) + (define-keysym "Pointer_DblClick1" #xfeef) + (define-keysym "Pointer_DblClick2" #xfef0) + (define-keysym "Pointer_DblClick3" #xfef1) + (define-keysym "Pointer_DblClick4" #xfef2) + (define-keysym "Pointer_DblClick5" #xfef3) + (define-keysym "Pointer_Drag_Dflt" #xfef4) + (define-keysym "Pointer_Drag1" #xfef5) + (define-keysym "Pointer_Drag2" #xfef6) + (define-keysym "Pointer_Drag3" #xfef7) + (define-keysym "Pointer_Drag4" #xfef8) + (define-keysym "Pointer_Drag5" #xfefd) + (define-keysym "Pointer_EnableKeys" #xfef9) + (define-keysym "Pointer_Accelerate" #xfefa) + (define-keysym "Pointer_DfltBtnNext" #xfefb) + (define-keysym "Pointer_DfltBtnPrev" #xfefc) + (define-keysym "3270_Duplicate" #xfd01) + (define-keysym "3270_FieldMark" #xfd02) + (define-keysym "3270_Right2" #xfd03) + (define-keysym "3270_Left2" #xfd04) + (define-keysym "3270_BackTab" #xfd05) + (define-keysym "3270_EraseEOF" #xfd06) + (define-keysym "3270_EraseInput" #xfd07) + (define-keysym "3270_Reset" #xfd08) + (define-keysym "3270_Quit" #xfd09) + (define-keysym "3270_PA1" #xfd0a) + (define-keysym "3270_PA2" #xfd0b) + (define-keysym "3270_PA3" #xfd0c) + (define-keysym "3270_Test" #xfd0d) + (define-keysym "3270_Attn" #xfd0e) + (define-keysym "3270_CursorBlink" #xfd0f) + (define-keysym "3270_AltCursor" #xfd10) + (define-keysym "3270_KeyClick" #xfd11) + (define-keysym "3270_Jump" #xfd12) + (define-keysym "3270_Ident" #xfd13) + (define-keysym "3270_Rule" #xfd14) + (define-keysym "3270_Copy" #xfd15) + (define-keysym "3270_Play" #xfd16) + (define-keysym "3270_Setup" #xfd17) + (define-keysym "3270_Record" #xfd18) + (define-keysym "3270_ChangeScreen" #xfd19) + (define-keysym "3270_DeleteWord" #xfd1a) + (define-keysym "3270_ExSelect" #xfd1b) + (define-keysym "3270_CursorSelect" #xfd1c) + (define-keysym "3270_PrintScreen" #xfd1d) + (define-keysym "3270_Enter" #xfd1e) + (define-keysym "space" #x0020) + (define-keysym "Spc" #x0020) + (define-keysym "exclam" #x0021) + (define-keysym "quotedbl" #x0022) + (define-keysym "numbersign" #x0023) + (define-keysym "dollar" #x0024) + (define-keysym "percent" #x0025) + (define-keysym "ampersand" #x0026) + (define-keysym "apostrophe" #x0027) + (define-keysym "quoteright" #x0027) + (define-keysym "parenleft" #x0028) + (define-keysym "parenright" #x0029) + (define-keysym "asterisk" #x002a) + (define-keysym "plus" #x002b) + (define-keysym "comma" #x002c) + (define-keysym "minus" #x002d) + (define-keysym "period" #x002e) + (define-keysym "slash" #x002f) + (define-keysym "0" #x0030) + (define-keysym "1" #x0031) + (define-keysym "2" #x0032) + (define-keysym "3" #x0033) + (define-keysym "4" #x0034) + (define-keysym "5" #x0035) + (define-keysym "6" #x0036) + (define-keysym "7" #x0037) + (define-keysym "8" #x0038) + (define-keysym "9" #x0039) + (define-keysym "colon" #x003a) + (define-keysym "semicolon" #x003b) + (define-keysym "less" #x003c) + (define-keysym "equal" #x003d) + (define-keysym "greater" #x003e) + (define-keysym "question" #x003f) + (define-keysym "at" #x0040) + (define-keysym "A" #x0041) + (define-keysym "B" #x0042) + (define-keysym "C" #x0043) + (define-keysym "D" #x0044) + (define-keysym "E" #x0045) + (define-keysym "F" #x0046) + (define-keysym "G" #x0047) + (define-keysym "H" #x0048) + (define-keysym "I" #x0049) + (define-keysym "J" #x004a) + (define-keysym "K" #x004b) + (define-keysym "L" #x004c) + (define-keysym "M" #x004d) + (define-keysym "N" #x004e) + (define-keysym "O" #x004f) + (define-keysym "P" #x0050) + (define-keysym "Q" #x0051) + (define-keysym "R" #x0052) + (define-keysym "S" #x0053) + (define-keysym "T" #x0054) + (define-keysym "U" #x0055) + (define-keysym "V" #x0056) + (define-keysym "W" #x0057) + (define-keysym "X" #x0058) + (define-keysym "Y" #x0059) + (define-keysym "Z" #x005a) + (define-keysym "bracketleft" #x005b) + (define-keysym "backslash" #x005c) + (define-keysym "bracketright" #x005d) + (define-keysym "asciicircum" #x005e) + (define-keysym "underscore" #x005f) + (define-keysym "grave" #x0060) + (define-keysym "quoteleft" #x0060) + (define-keysym "a" #x0061) + (define-keysym "b" #x0062) + (define-keysym "c" #x0063) + (define-keysym "d" #x0064) + (define-keysym "e" #x0065) + (define-keysym "f" #x0066) + (define-keysym "g" #x0067) + (define-keysym "h" #x0068) + (define-keysym "i" #x0069) + (define-keysym "j" #x006a) + (define-keysym "k" #x006b) + (define-keysym "l" #x006c) + (define-keysym "m" #x006d) + (define-keysym "n" #x006e) + (define-keysym "o" #x006f) + (define-keysym "p" #x0070) + (define-keysym "q" #x0071) + (define-keysym "r" #x0072) + (define-keysym "s" #x0073) + (define-keysym "t" #x0074) + (define-keysym "u" #x0075) + (define-keysym "v" #x0076) + (define-keysym "w" #x0077) + (define-keysym "x" #x0078) + (define-keysym "y" #x0079) + (define-keysym "z" #x007a) + (define-keysym "braceleft" #x007b) + (define-keysym "bar" #x007c) + (define-keysym "braceright" #x007d) + (define-keysym "asciitilde" #x007e) + (define-keysym "nobreakspace" #x00a0) + (define-keysym "exclamdown" #x00a1) + (define-keysym "cent" #x00a2) + (define-keysym "sterling" #x00a3) + (define-keysym "currency" #x00a4) + (define-keysym "yen" #x00a5) + (define-keysym "brokenbar" #x00a6) + (define-keysym "section" #x00a7) + (define-keysym "diaeresis" #x00a8) + (define-keysym "copyright" #x00a9) + (define-keysym "ordfeminine" #x00aa) + (define-keysym "guillemotleft" #x00ab) + (define-keysym "notsign" #x00ac) + (define-keysym "hyphen" #x00ad) + (define-keysym "registered" #x00ae) + (define-keysym "macron" #x00af) + (define-keysym "degree" #x00b0) + (define-keysym "plusminus" #x00b1) + (define-keysym "twosuperior" #x00b2) + (define-keysym "threesuperior" #x00b3) + (define-keysym "acute" #x00b4) + (define-keysym "mu" #x00b5) + (define-keysym "paragraph" #x00b6) + (define-keysym "periodcentered" #x00b7) + (define-keysym "cedilla" #x00b8) + (define-keysym "onesuperior" #x00b9) + (define-keysym "masculine" #x00ba) + (define-keysym "guillemotright" #x00bb) + (define-keysym "onequarter" #x00bc) + (define-keysym "onehalf" #x00bd) + (define-keysym "threequarters" #x00be) + (define-keysym "questiondown" #x00bf) + (define-keysym "Agrave" #x00c0) + (define-keysym "Aacute" #x00c1) + (define-keysym "Acircumflex" #x00c2) + (define-keysym "Atilde" #x00c3) + (define-keysym "Adiaeresis" #x00c4) + (define-keysym "Aring" #x00c5) + (define-keysym "AE" #x00c6) + (define-keysym "Ccedilla" #x00c7) + (define-keysym "Egrave" #x00c8) + (define-keysym "Eacute" #x00c9) + (define-keysym "Ecircumflex" #x00ca) + (define-keysym "Ediaeresis" #x00cb) + (define-keysym "Igrave" #x00cc) + (define-keysym "Iacute" #x00cd) + (define-keysym "Icircumflex" #x00ce) + (define-keysym "Idiaeresis" #x00cf) + (define-keysym "ETH" #x00d0) + (define-keysym "Eth" #x00d0) + (define-keysym "Ntilde" #x00d1) + (define-keysym "Ograve" #x00d2) + (define-keysym "Oacute" #x00d3) + (define-keysym "Ocircumflex" #x00d4) + (define-keysym "Otilde" #x00d5) + (define-keysym "Odiaeresis" #x00d6) + (define-keysym "multiply" #x00d7) + (define-keysym "Oslash" #x00d8) + (define-keysym "Ooblique" #x00d8) + (define-keysym "Ugrave" #x00d9) + (define-keysym "Uacute" #x00da) + (define-keysym "Ucircumflex" #x00db) + (define-keysym "Udiaeresis" #x00dc) + (define-keysym "Yacute" #x00dd) + (define-keysym "THORN" #x00de) + (define-keysym "Thorn" #x00de) + (define-keysym "ssharp" #x00df) + (define-keysym "agrave" #x00e0) + (define-keysym "aacute" #x00e1) + (define-keysym "acircumflex" #x00e2) + (define-keysym "atilde" #x00e3) + (define-keysym "adiaeresis" #x00e4) + (define-keysym "aring" #x00e5) + (define-keysym "ae" #x00e6) + (define-keysym "ccedilla" #x00e7) + (define-keysym "egrave" #x00e8) + (define-keysym "eacute" #x00e9) + (define-keysym "ecircumflex" #x00ea) + (define-keysym "ediaeresis" #x00eb) + (define-keysym "igrave" #x00ec) + (define-keysym "iacute" #x00ed) + (define-keysym "icircumflex" #x00ee) + (define-keysym "idiaeresis" #x00ef) + (define-keysym "eth" #x00f0) + (define-keysym "ntilde" #x00f1) + (define-keysym "ograve" #x00f2) + (define-keysym "oacute" #x00f3) + (define-keysym "ocircumflex" #x00f4) + (define-keysym "otilde" #x00f5) + (define-keysym "odiaeresis" #x00f6) + (define-keysym "division" #x00f7) + (define-keysym "oslash" #x00f8) + (define-keysym "ooblique" #x00f8) + (define-keysym "ugrave" #x00f9) + (define-keysym "uacute" #x00fa) + (define-keysym "ucircumflex" #x00fb) + (define-keysym "udiaeresis" #x00fc) + (define-keysym "yacute" #x00fd) + (define-keysym "thorn" #x00fe) + (define-keysym "ydiaeresis" #x00ff) + (define-keysym "Aogonek" #x01a1) + (define-keysym "breve" #x01a2) + (define-keysym "Lstroke" #x01a3) + (define-keysym "Lcaron" #x01a5) + (define-keysym "Sacute" #x01a6) + (define-keysym "Scaron" #x01a9) + (define-keysym "Scedilla" #x01aa) + (define-keysym "Tcaron" #x01ab) + (define-keysym "Zacute" #x01ac) + (define-keysym "Zcaron" #x01ae) + (define-keysym "Zabovedot" #x01af) + (define-keysym "aogonek" #x01b1) + (define-keysym "ogonek" #x01b2) + (define-keysym "lstroke" #x01b3) + (define-keysym "lcaron" #x01b5) + (define-keysym "sacute" #x01b6) + (define-keysym "caron" #x01b7) + (define-keysym "scaron" #x01b9) + (define-keysym "scedilla" #x01ba) + (define-keysym "tcaron" #x01bb) + (define-keysym "zacute" #x01bc) + (define-keysym "doubleacute" #x01bd) + (define-keysym "zcaron" #x01be) + (define-keysym "zabovedot" #x01bf) + (define-keysym "Racute" #x01c0) + (define-keysym "Abreve" #x01c3) + (define-keysym "Lacute" #x01c5) + (define-keysym "Cacute" #x01c6) + (define-keysym "Ccaron" #x01c8) + (define-keysym "Eogonek" #x01ca) + (define-keysym "Ecaron" #x01cc) + (define-keysym "Dcaron" #x01cf) + (define-keysym "Dstroke" #x01d0) + (define-keysym "Nacute" #x01d1) + (define-keysym "Ncaron" #x01d2) + (define-keysym "Odoubleacute" #x01d5) + (define-keysym "Rcaron" #x01d8) + (define-keysym "Uring" #x01d9) + (define-keysym "Udoubleacute" #x01db) + (define-keysym "Tcedilla" #x01de) + (define-keysym "racute" #x01e0) + (define-keysym "abreve" #x01e3) + (define-keysym "lacute" #x01e5) + (define-keysym "cacute" #x01e6) + (define-keysym "ccaron" #x01e8) + (define-keysym "eogonek" #x01ea) + (define-keysym "ecaron" #x01ec) + (define-keysym "dcaron" #x01ef) + (define-keysym "dstroke" #x01f0) + (define-keysym "nacute" #x01f1) + (define-keysym "ncaron" #x01f2) + (define-keysym "odoubleacute" #x01f5) + (define-keysym "udoubleacute" #x01fb) + (define-keysym "rcaron" #x01f8) + (define-keysym "uring" #x01f9) + (define-keysym "tcedilla" #x01fe) + (define-keysym "abovedot" #x01ff) + (define-keysym "Hstroke" #x02a1) + (define-keysym "Hcircumflex" #x02a6) + (define-keysym "Iabovedot" #x02a9) + (define-keysym "Gbreve" #x02ab) + (define-keysym "Jcircumflex" #x02ac) + (define-keysym "hstroke" #x02b1) + (define-keysym "hcircumflex" #x02b6) + (define-keysym "idotless" #x02b9) + (define-keysym "gbreve" #x02bb) + (define-keysym "jcircumflex" #x02bc) + (define-keysym "Cabovedot" #x02c5) + (define-keysym "Ccircumflex" #x02c6) + (define-keysym "Gabovedot" #x02d5) + (define-keysym "Gcircumflex" #x02d8) + (define-keysym "Ubreve" #x02dd) + (define-keysym "Scircumflex" #x02de) + (define-keysym "cabovedot" #x02e5) + (define-keysym "ccircumflex" #x02e6) + (define-keysym "gabovedot" #x02f5) + (define-keysym "gcircumflex" #x02f8) + (define-keysym "ubreve" #x02fd) + (define-keysym "scircumflex" #x02fe) + (define-keysym "kra" #x03a2) + (define-keysym "kappa" #x03a2) + (define-keysym "Rcedilla" #x03a3) + (define-keysym "Itilde" #x03a5) + (define-keysym "Lcedilla" #x03a6) + (define-keysym "Emacron" #x03aa) + (define-keysym "Gcedilla" #x03ab) + (define-keysym "Tslash" #x03ac) + (define-keysym "rcedilla" #x03b3) + (define-keysym "itilde" #x03b5) + (define-keysym "lcedilla" #x03b6) + (define-keysym "emacron" #x03ba) + (define-keysym "gcedilla" #x03bb) + (define-keysym "tslash" #x03bc) + (define-keysym "ENG" #x03bd) + (define-keysym "eng" #x03bf) + (define-keysym "Amacron" #x03c0) + (define-keysym "Iogonek" #x03c7) + (define-keysym "Eabovedot" #x03cc) + (define-keysym "Imacron" #x03cf) + (define-keysym "Ncedilla" #x03d1) + (define-keysym "Omacron" #x03d2) + (define-keysym "Kcedilla" #x03d3) + (define-keysym "Uogonek" #x03d9) + (define-keysym "Utilde" #x03dd) + (define-keysym "Umacron" #x03de) + (define-keysym "amacron" #x03e0) + (define-keysym "iogonek" #x03e7) + (define-keysym "eabovedot" #x03ec) + (define-keysym "imacron" #x03ef) + (define-keysym "ncedilla" #x03f1) + (define-keysym "omacron" #x03f2) + (define-keysym "kcedilla" #x03f3) + (define-keysym "uogonek" #x03f9) + (define-keysym "utilde" #x03fd) + (define-keysym "umacron" #x03fe) + (define-keysym "Babovedot" #x1001e02) + (define-keysym "babovedot" #x1001e03) + (define-keysym "Dabovedot" #x1001e0a) + (define-keysym "Wgrave" #x1001e80) + (define-keysym "Wacute" #x1001e82) + (define-keysym "dabovedot" #x1001e0b) + (define-keysym "Ygrave" #x1001ef2) + (define-keysym "Fabovedot" #x1001e1e) + (define-keysym "fabovedot" #x1001e1f) + (define-keysym "Mabovedot" #x1001e40) + (define-keysym "mabovedot" #x1001e41) + (define-keysym "Pabovedot" #x1001e56) + (define-keysym "wgrave" #x1001e81) + (define-keysym "pabovedot" #x1001e57) + (define-keysym "wacute" #x1001e83) + (define-keysym "Sabovedot" #x1001e60) + (define-keysym "ygrave" #x1001ef3) + (define-keysym "Wdiaeresis" #x1001e84) + (define-keysym "wdiaeresis" #x1001e85) + (define-keysym "sabovedot" #x1001e61) + (define-keysym "Wcircumflex" #x1000174) + (define-keysym "Tabovedot" #x1001e6a) + (define-keysym "Ycircumflex" #x1000176) + (define-keysym "wcircumflex" #x1000175) + (define-keysym "tabovedot" #x1001e6b) + (define-keysym "ycircumflex" #x1000177) + (define-keysym "OE" #x13bc) + (define-keysym "oe" #x13bd) + (define-keysym "Ydiaeresis" #x13be) + (define-keysym "overline" #x047e) + (define-keysym "kana_fullstop" #x04a1) + (define-keysym "kana_openingbracket" #x04a2) + (define-keysym "kana_closingbracket" #x04a3) + (define-keysym "kana_comma" #x04a4) + (define-keysym "kana_conjunctive" #x04a5) + (define-keysym "kana_middledot" #x04a5) + (define-keysym "kana_WO" #x04a6) + (define-keysym "kana_a" #x04a7) + (define-keysym "kana_i" #x04a8) + (define-keysym "kana_u" #x04a9) + (define-keysym "kana_e" #x04aa) + (define-keysym "kana_o" #x04ab) + (define-keysym "kana_ya" #x04ac) + (define-keysym "kana_yu" #x04ad) + (define-keysym "kana_yo" #x04ae) + (define-keysym "kana_tsu" #x04af) + (define-keysym "kana_tu" #x04af) + (define-keysym "prolongedsound" #x04b0) + (define-keysym "kana_A" #x04b1) + (define-keysym "kana_I" #x04b2) + (define-keysym "kana_U" #x04b3) + (define-keysym "kana_E" #x04b4) + (define-keysym "kana_O" #x04b5) + (define-keysym "kana_KA" #x04b6) + (define-keysym "kana_KI" #x04b7) + (define-keysym "kana_KU" #x04b8) + (define-keysym "kana_KE" #x04b9) + (define-keysym "kana_KO" #x04ba) + (define-keysym "kana_SA" #x04bb) + (define-keysym "kana_SHI" #x04bc) + (define-keysym "kana_SU" #x04bd) + (define-keysym "kana_SE" #x04be) + (define-keysym "kana_SO" #x04bf) + (define-keysym "kana_TA" #x04c0) + (define-keysym "kana_CHI" #x04c1) + (define-keysym "kana_TI" #x04c1) + (define-keysym "kana_TSU" #x04c2) + (define-keysym "kana_TU" #x04c2) + (define-keysym "kana_TE" #x04c3) + (define-keysym "kana_TO" #x04c4) + (define-keysym "kana_NA" #x04c5) + (define-keysym "kana_NI" #x04c6) + (define-keysym "kana_NU" #x04c7) + (define-keysym "kana_NE" #x04c8) + (define-keysym "kana_NO" #x04c9) + (define-keysym "kana_HA" #x04ca) + (define-keysym "kana_HI" #x04cb) + (define-keysym "kana_FU" #x04cc) + (define-keysym "kana_HU" #x04cc) + (define-keysym "kana_HE" #x04cd) + (define-keysym "kana_HO" #x04ce) + (define-keysym "kana_MA" #x04cf) + (define-keysym "kana_MI" #x04d0) + (define-keysym "kana_MU" #x04d1) + (define-keysym "kana_ME" #x04d2) + (define-keysym "kana_MO" #x04d3) + (define-keysym "kana_YA" #x04d4) + (define-keysym "kana_YU" #x04d5) + (define-keysym "kana_YO" #x04d6) + (define-keysym "kana_RA" #x04d7) + (define-keysym "kana_RI" #x04d8) + (define-keysym "kana_RU" #x04d9) + (define-keysym "kana_RE" #x04da) + (define-keysym "kana_RO" #x04db) + (define-keysym "kana_WA" #x04dc) + (define-keysym "kana_N" #x04dd) + (define-keysym "voicedsound" #x04de) + (define-keysym "semivoicedsound" #x04df) + (define-keysym "kana_switch" #xff7e) + (define-keysym "Farsi_0" #x10006f0) + (define-keysym "Farsi_1" #x10006f1) + (define-keysym "Farsi_2" #x10006f2) + (define-keysym "Farsi_3" #x10006f3) + (define-keysym "Farsi_4" #x10006f4) + (define-keysym "Farsi_5" #x10006f5) + (define-keysym "Farsi_6" #x10006f6) + (define-keysym "Farsi_7" #x10006f7) + (define-keysym "Farsi_8" #x10006f8) + (define-keysym "Farsi_9" #x10006f9) + (define-keysym "Arabic_percent" #x100066a) + (define-keysym "Arabic_superscript_alef" #x1000670) + (define-keysym "Arabic_tteh" #x1000679) + (define-keysym "Arabic_peh" #x100067e) + (define-keysym "Arabic_tcheh" #x1000686) + (define-keysym "Arabic_ddal" #x1000688) + (define-keysym "Arabic_rreh" #x1000691) + (define-keysym "Arabic_comma" #x05ac) + (define-keysym "Arabic_fullstop" #x10006d4) + (define-keysym "Arabic_0" #x1000660) + (define-keysym "Arabic_1" #x1000661) + (define-keysym "Arabic_2" #x1000662) + (define-keysym "Arabic_3" #x1000663) + (define-keysym "Arabic_4" #x1000664) + (define-keysym "Arabic_5" #x1000665) + (define-keysym "Arabic_6" #x1000666) + (define-keysym "Arabic_7" #x1000667) + (define-keysym "Arabic_8" #x1000668) + (define-keysym "Arabic_9" #x1000669) + (define-keysym "Arabic_semicolon" #x05bb) + (define-keysym "Arabic_question_mark" #x05bf) + (define-keysym "Arabic_hamza" #x05c1) + (define-keysym "Arabic_maddaonalef" #x05c2) + (define-keysym "Arabic_hamzaonalef" #x05c3) + (define-keysym "Arabic_hamzaonwaw" #x05c4) + (define-keysym "Arabic_hamzaunderalef" #x05c5) + (define-keysym "Arabic_hamzaonyeh" #x05c6) + (define-keysym "Arabic_alef" #x05c7) + (define-keysym "Arabic_beh" #x05c8) + (define-keysym "Arabic_tehmarbuta" #x05c9) + (define-keysym "Arabic_teh" #x05ca) + (define-keysym "Arabic_theh" #x05cb) + (define-keysym "Arabic_jeem" #x05cc) + (define-keysym "Arabic_hah" #x05cd) + (define-keysym "Arabic_khah" #x05ce) + (define-keysym "Arabic_dal" #x05cf) + (define-keysym "Arabic_thal" #x05d0) + (define-keysym "Arabic_ra" #x05d1) + (define-keysym "Arabic_zain" #x05d2) + (define-keysym "Arabic_seen" #x05d3) + (define-keysym "Arabic_sheen" #x05d4) + (define-keysym "Arabic_sad" #x05d5) + (define-keysym "Arabic_dad" #x05d6) + (define-keysym "Arabic_tah" #x05d7) + (define-keysym "Arabic_zah" #x05d8) + (define-keysym "Arabic_ain" #x05d9) + (define-keysym "Arabic_ghain" #x05da) + (define-keysym "Arabic_tatweel" #x05e0) + (define-keysym "Arabic_feh" #x05e1) + (define-keysym "Arabic_qaf" #x05e2) + (define-keysym "Arabic_kaf" #x05e3) + (define-keysym "Arabic_lam" #x05e4) + (define-keysym "Arabic_meem" #x05e5) + (define-keysym "Arabic_noon" #x05e6) + (define-keysym "Arabic_ha" #x05e7) + (define-keysym "Arabic_heh" #x05e7) + (define-keysym "Arabic_waw" #x05e8) + (define-keysym "Arabic_alefmaksura" #x05e9) + (define-keysym "Arabic_yeh" #x05ea) + (define-keysym "Arabic_fathatan" #x05eb) + (define-keysym "Arabic_dammatan" #x05ec) + (define-keysym "Arabic_kasratan" #x05ed) + (define-keysym "Arabic_fatha" #x05ee) + (define-keysym "Arabic_damma" #x05ef) + (define-keysym "Arabic_kasra" #x05f0) + (define-keysym "Arabic_shadda" #x05f1) + (define-keysym "Arabic_sukun" #x05f2) + (define-keysym "Arabic_madda_above" #x1000653) + (define-keysym "Arabic_hamza_above" #x1000654) + (define-keysym "Arabic_hamza_below" #x1000655) + (define-keysym "Arabic_jeh" #x1000698) + (define-keysym "Arabic_veh" #x10006a4) + (define-keysym "Arabic_keheh" #x10006a9) + (define-keysym "Arabic_gaf" #x10006af) + (define-keysym "Arabic_noon_ghunna" #x10006ba) + (define-keysym "Arabic_heh_doachashmee" #x10006be) + (define-keysym "Farsi_yeh" #x10006cc) + (define-keysym "Arabic_farsi_yeh" #x10006cc) + (define-keysym "Arabic_yeh_baree" #x10006d2) + (define-keysym "Arabic_heh_goal" #x10006c1) + (define-keysym "Arabic_switch" #xff7e) + (define-keysym "Cyrillic_GHE_bar" #x1000492) + (define-keysym "Cyrillic_ghe_bar" #x1000493) + (define-keysym "Cyrillic_ZHE_descender" #x1000496) + (define-keysym "Cyrillic_zhe_descender" #x1000497) + (define-keysym "Cyrillic_KA_descender" #x100049a) + (define-keysym "Cyrillic_ka_descender" #x100049b) + (define-keysym "Cyrillic_KA_vertstroke" #x100049c) + (define-keysym "Cyrillic_ka_vertstroke" #x100049d) + (define-keysym "Cyrillic_EN_descender" #x10004a2) + (define-keysym "Cyrillic_en_descender" #x10004a3) + (define-keysym "Cyrillic_U_straight" #x10004ae) + (define-keysym "Cyrillic_u_straight" #x10004af) + (define-keysym "Cyrillic_U_straight_bar" #x10004b0) + (define-keysym "Cyrillic_u_straight_bar" #x10004b1) + (define-keysym "Cyrillic_HA_descender" #x10004b2) + (define-keysym "Cyrillic_ha_descender" #x10004b3) + (define-keysym "Cyrillic_CHE_descender" #x10004b6) + (define-keysym "Cyrillic_che_descender" #x10004b7) + (define-keysym "Cyrillic_CHE_vertstroke" #x10004b8) + (define-keysym "Cyrillic_che_vertstroke" #x10004b9) + (define-keysym "Cyrillic_SHHA" #x10004ba) + (define-keysym "Cyrillic_shha" #x10004bb) + (define-keysym "Cyrillic_SCHWA" #x10004d8) + (define-keysym "Cyrillic_schwa" #x10004d9) + (define-keysym "Cyrillic_I_macron" #x10004e2) + (define-keysym "Cyrillic_i_macron" #x10004e3) + (define-keysym "Cyrillic_O_bar" #x10004e8) + (define-keysym "Cyrillic_o_bar" #x10004e9) + (define-keysym "Cyrillic_U_macron" #x10004ee) + (define-keysym "Cyrillic_u_macron" #x10004ef) + (define-keysym "Serbian_dje" #x06a1) + (define-keysym "Macedonia_gje" #x06a2) + (define-keysym "Cyrillic_io" #x06a3) + (define-keysym "Ukrainian_ie" #x06a4) + (define-keysym "Ukranian_je" #x06a4) + (define-keysym "Macedonia_dse" #x06a5) + (define-keysym "Ukrainian_i" #x06a6) + (define-keysym "Ukranian_i" #x06a6) + (define-keysym "Ukrainian_yi" #x06a7) + (define-keysym "Ukranian_yi" #x06a7) + (define-keysym "Cyrillic_je" #x06a8) + (define-keysym "Serbian_je" #x06a8) + (define-keysym "Cyrillic_lje" #x06a9) + (define-keysym "Serbian_lje" #x06a9) + (define-keysym "Cyrillic_nje" #x06aa) + (define-keysym "Serbian_nje" #x06aa) + (define-keysym "Serbian_tshe" #x06ab) + (define-keysym "Macedonia_kje" #x06ac) + (define-keysym "Ukrainian_ghe_with_upturn" #x06ad) + (define-keysym "Byelorussian_shortu" #x06ae) + (define-keysym "Cyrillic_dzhe" #x06af) + (define-keysym "Serbian_dze" #x06af) + (define-keysym "numerosign" #x06b0) + (define-keysym "Serbian_DJE" #x06b1) + (define-keysym "Macedonia_GJE" #x06b2) + (define-keysym "Cyrillic_IO" #x06b3) + (define-keysym "Ukrainian_IE" #x06b4) + (define-keysym "Ukranian_JE" #x06b4) + (define-keysym "Macedonia_DSE" #x06b5) + (define-keysym "Ukrainian_I" #x06b6) + (define-keysym "Ukranian_I" #x06b6) + (define-keysym "Ukrainian_YI" #x06b7) + (define-keysym "Ukranian_YI" #x06b7) + (define-keysym "Cyrillic_JE" #x06b8) + (define-keysym "Serbian_JE" #x06b8) + (define-keysym "Cyrillic_LJE" #x06b9) + (define-keysym "Serbian_LJE" #x06b9) + (define-keysym "Cyrillic_NJE" #x06ba) + (define-keysym "Serbian_NJE" #x06ba) + (define-keysym "Serbian_TSHE" #x06bb) + (define-keysym "Macedonia_KJE" #x06bc) + (define-keysym "Ukrainian_GHE_WITH_UPTURN" #x06bd) + (define-keysym "Byelorussian_SHORTU" #x06be) + (define-keysym "Cyrillic_DZHE" #x06bf) + (define-keysym "Serbian_DZE" #x06bf) + (define-keysym "Cyrillic_yu" #x06c0) + (define-keysym "Cyrillic_a" #x06c1) + (define-keysym "Cyrillic_be" #x06c2) + (define-keysym "Cyrillic_tse" #x06c3) + (define-keysym "Cyrillic_de" #x06c4) + (define-keysym "Cyrillic_ie" #x06c5) + (define-keysym "Cyrillic_ef" #x06c6) + (define-keysym "Cyrillic_ghe" #x06c7) + (define-keysym "Cyrillic_ha" #x06c8) + (define-keysym "Cyrillic_i" #x06c9) + (define-keysym "Cyrillic_shorti" #x06ca) + (define-keysym "Cyrillic_ka" #x06cb) + (define-keysym "Cyrillic_el" #x06cc) + (define-keysym "Cyrillic_em" #x06cd) + (define-keysym "Cyrillic_en" #x06ce) + (define-keysym "Cyrillic_o" #x06cf) + (define-keysym "Cyrillic_pe" #x06d0) + (define-keysym "Cyrillic_ya" #x06d1) + (define-keysym "Cyrillic_er" #x06d2) + (define-keysym "Cyrillic_es" #x06d3) + (define-keysym "Cyrillic_te" #x06d4) + (define-keysym "Cyrillic_u" #x06d5) + (define-keysym "Cyrillic_zhe" #x06d6) + (define-keysym "Cyrillic_ve" #x06d7) + (define-keysym "Cyrillic_softsign" #x06d8) + (define-keysym "Cyrillic_yeru" #x06d9) + (define-keysym "Cyrillic_ze" #x06da) + (define-keysym "Cyrillic_sha" #x06db) + (define-keysym "Cyrillic_e" #x06dc) + (define-keysym "Cyrillic_shcha" #x06dd) + (define-keysym "Cyrillic_che" #x06de) + (define-keysym "Cyrillic_hardsign" #x06df) + (define-keysym "Cyrillic_YU" #x06e0) + (define-keysym "Cyrillic_A" #x06e1) + (define-keysym "Cyrillic_BE" #x06e2) + (define-keysym "Cyrillic_TSE" #x06e3) + (define-keysym "Cyrillic_DE" #x06e4) + (define-keysym "Cyrillic_IE" #x06e5) + (define-keysym "Cyrillic_EF" #x06e6) + (define-keysym "Cyrillic_GHE" #x06e7) + (define-keysym "Cyrillic_HA" #x06e8) + (define-keysym "Cyrillic_I" #x06e9) + (define-keysym "Cyrillic_SHORTI" #x06ea) + (define-keysym "Cyrillic_KA" #x06eb) + (define-keysym "Cyrillic_EL" #x06ec) + (define-keysym "Cyrillic_EM" #x06ed) + (define-keysym "Cyrillic_EN" #x06ee) + (define-keysym "Cyrillic_O" #x06ef) + (define-keysym "Cyrillic_PE" #x06f0) + (define-keysym "Cyrillic_YA" #x06f1) + (define-keysym "Cyrillic_ER" #x06f2) + (define-keysym "Cyrillic_ES" #x06f3) + (define-keysym "Cyrillic_TE" #x06f4) + (define-keysym "Cyrillic_U" #x06f5) + (define-keysym "Cyrillic_ZHE" #x06f6) + (define-keysym "Cyrillic_VE" #x06f7) + (define-keysym "Cyrillic_SOFTSIGN" #x06f8) + (define-keysym "Cyrillic_YERU" #x06f9) + (define-keysym "Cyrillic_ZE" #x06fa) + (define-keysym "Cyrillic_SHA" #x06fb) + (define-keysym "Cyrillic_E" #x06fc) + (define-keysym "Cyrillic_SHCHA" #x06fd) + (define-keysym "Cyrillic_CHE" #x06fe) + (define-keysym "Cyrillic_HARDSIGN" #x06ff) + (define-keysym "Greek_ALPHAaccent" #x07a1) + (define-keysym "Greek_EPSILONaccent" #x07a2) + (define-keysym "Greek_ETAaccent" #x07a3) + (define-keysym "Greek_IOTAaccent" #x07a4) + (define-keysym "Greek_IOTAdieresis" #x07a5) + (define-keysym "Greek_IOTAdiaeresis" #x07a5) + (define-keysym "Greek_OMICRONaccent" #x07a7) + (define-keysym "Greek_UPSILONaccent" #x07a8) + (define-keysym "Greek_UPSILONdieresis" #x07a9) + (define-keysym "Greek_OMEGAaccent" #x07ab) + (define-keysym "Greek_accentdieresis" #x07ae) + (define-keysym "Greek_horizbar" #x07af) + (define-keysym "Greek_alphaaccent" #x07b1) + (define-keysym "Greek_epsilonaccent" #x07b2) + (define-keysym "Greek_etaaccent" #x07b3) + (define-keysym "Greek_iotaaccent" #x07b4) + (define-keysym "Greek_iotadieresis" #x07b5) + (define-keysym "Greek_iotaaccentdieresis" #x07b6) + (define-keysym "Greek_omicronaccent" #x07b7) + (define-keysym "Greek_upsilonaccent" #x07b8) + (define-keysym "Greek_upsilondieresis" #x07b9) + (define-keysym "Greek_upsilonaccentdieresis" #x07ba) + (define-keysym "Greek_omegaaccent" #x07bb) + (define-keysym "Greek_ALPHA" #x07c1) + (define-keysym "Greek_BETA" #x07c2) + (define-keysym "Greek_GAMMA" #x07c3) + (define-keysym "Greek_DELTA" #x07c4) + (define-keysym "Greek_EPSILON" #x07c5) + (define-keysym "Greek_ZETA" #x07c6) + (define-keysym "Greek_ETA" #x07c7) + (define-keysym "Greek_THETA" #x07c8) + (define-keysym "Greek_IOTA" #x07c9) + (define-keysym "Greek_KAPPA" #x07ca) + (define-keysym "Greek_LAMDA" #x07cb) + (define-keysym "Greek_LAMBDA" #x07cb) + (define-keysym "Greek_MU" #x07cc) + (define-keysym "Greek_NU" #x07cd) + (define-keysym "Greek_XI" #x07ce) + (define-keysym "Greek_OMICRON" #x07cf) + (define-keysym "Greek_PI" #x07d0) + (define-keysym "Greek_RHO" #x07d1) + (define-keysym "Greek_SIGMA" #x07d2) + (define-keysym "Greek_TAU" #x07d4) + (define-keysym "Greek_UPSILON" #x07d5) + (define-keysym "Greek_PHI" #x07d6) + (define-keysym "Greek_CHI" #x07d7) + (define-keysym "Greek_PSI" #x07d8) + (define-keysym "Greek_OMEGA" #x07d9) + (define-keysym "Greek_alpha" #x07e1) + (define-keysym "Greek_beta" #x07e2) + (define-keysym "Greek_gamma" #x07e3) + (define-keysym "Greek_delta" #x07e4) + (define-keysym "Greek_epsilon" #x07e5) + (define-keysym "Greek_zeta" #x07e6) + (define-keysym "Greek_eta" #x07e7) + (define-keysym "Greek_theta" #x07e8) + (define-keysym "Greek_iota" #x07e9) + (define-keysym "Greek_kappa" #x07ea) + (define-keysym "Greek_lamda" #x07eb) + (define-keysym "Greek_lambda" #x07eb) + (define-keysym "Greek_mu" #x07ec) + (define-keysym "Greek_nu" #x07ed) + (define-keysym "Greek_xi" #x07ee) + (define-keysym "Greek_omicron" #x07ef) + (define-keysym "Greek_pi" #x07f0) + (define-keysym "Greek_rho" #x07f1) + (define-keysym "Greek_sigma" #x07f2) + (define-keysym "Greek_finalsmallsigma" #x07f3) + (define-keysym "Greek_tau" #x07f4) + (define-keysym "Greek_upsilon" #x07f5) + (define-keysym "Greek_phi" #x07f6) + (define-keysym "Greek_chi" #x07f7) + (define-keysym "Greek_psi" #x07f8) + (define-keysym "Greek_omega" #x07f9) + (define-keysym "Greek_switch" #xff7e) + (define-keysym "leftradical" #x08a1) + (define-keysym "topleftradical" #x08a2) + (define-keysym "horizconnector" #x08a3) + (define-keysym "topintegral" #x08a4) + (define-keysym "botintegral" #x08a5) + (define-keysym "vertconnector" #x08a6) + (define-keysym "topleftsqbracket" #x08a7) + (define-keysym "botleftsqbracket" #x08a8) + (define-keysym "toprightsqbracket" #x08a9) + (define-keysym "botrightsqbracket" #x08aa) + (define-keysym "topleftparens" #x08ab) + (define-keysym "botleftparens" #x08ac) + (define-keysym "toprightparens" #x08ad) + (define-keysym "botrightparens" #x08ae) + (define-keysym "leftmiddlecurlybrace" #x08af) + (define-keysym "rightmiddlecurlybrace" #x08b0) + (define-keysym "topleftsummation" #x08b1) + (define-keysym "botleftsummation" #x08b2) + (define-keysym "topvertsummationconnector" #x08b3) + (define-keysym "botvertsummationconnector" #x08b4) + (define-keysym "toprightsummation" #x08b5) + (define-keysym "botrightsummation" #x08b6) + (define-keysym "rightmiddlesummation" #x08b7) + (define-keysym "lessthanequal" #x08bc) + (define-keysym "notequal" #x08bd) + (define-keysym "greaterthanequal" #x08be) + (define-keysym "integral" #x08bf) + (define-keysym "therefore" #x08c0) + (define-keysym "variation" #x08c1) + (define-keysym "infinity" #x08c2) + (define-keysym "nabla" #x08c5) + (define-keysym "approximate" #x08c8) + (define-keysym "similarequal" #x08c9) + (define-keysym "ifonlyif" #x08cd) + (define-keysym "implies" #x08ce) + (define-keysym "identical" #x08cf) + (define-keysym "radical" #x08d6) + (define-keysym "includedin" #x08da) + (define-keysym "includes" #x08db) + (define-keysym "intersection" #x08dc) + (define-keysym "union" #x08dd) + (define-keysym "logicaland" #x08de) + (define-keysym "logicalor" #x08df) + (define-keysym "partialderivative" #x08ef) + (define-keysym "function" #x08f6) + (define-keysym "leftarrow" #x08fb) + (define-keysym "uparrow" #x08fc) + (define-keysym "rightarrow" #x08fd) + (define-keysym "downarrow" #x08fe) + (define-keysym "blank" #x09df) + (define-keysym "soliddiamond" #x09e0) + (define-keysym "checkerboard" #x09e1) + (define-keysym "ht" #x09e2) + (define-keysym "ff" #x09e3) + (define-keysym "cr" #x09e4) + (define-keysym "lf" #x09e5) + (define-keysym "nl" #x09e8) + (define-keysym "vt" #x09e9) + (define-keysym "lowrightcorner" #x09ea) + (define-keysym "uprightcorner" #x09eb) + (define-keysym "upleftcorner" #x09ec) + (define-keysym "lowleftcorner" #x09ed) + (define-keysym "crossinglines" #x09ee) + (define-keysym "horizlinescan1" #x09ef) + (define-keysym "horizlinescan3" #x09f0) + (define-keysym "horizlinescan5" #x09f1) + (define-keysym "horizlinescan7" #x09f2) + (define-keysym "horizlinescan9" #x09f3) + (define-keysym "leftt" #x09f4) + (define-keysym "rightt" #x09f5) + (define-keysym "bott" #x09f6) + (define-keysym "topt" #x09f7) + (define-keysym "vertbar" #x09f8) + (define-keysym "emspace" #x0aa1) + (define-keysym "enspace" #x0aa2) + (define-keysym "em3space" #x0aa3) + (define-keysym "em4space" #x0aa4) + (define-keysym "digitspace" #x0aa5) + (define-keysym "punctspace" #x0aa6) + (define-keysym "thinspace" #x0aa7) + (define-keysym "hairspace" #x0aa8) + (define-keysym "emdash" #x0aa9) + (define-keysym "endash" #x0aaa) + (define-keysym "signifblank" #x0aac) + (define-keysym "ellipsis" #x0aae) + (define-keysym "doubbaselinedot" #x0aaf) + (define-keysym "onethird" #x0ab0) + (define-keysym "twothirds" #x0ab1) + (define-keysym "onefifth" #x0ab2) + (define-keysym "twofifths" #x0ab3) + (define-keysym "threefifths" #x0ab4) + (define-keysym "fourfifths" #x0ab5) + (define-keysym "onesixth" #x0ab6) + (define-keysym "fivesixths" #x0ab7) + (define-keysym "careof" #x0ab8) + (define-keysym "figdash" #x0abb) + (define-keysym "leftanglebracket" #x0abc) + (define-keysym "decimalpoint" #x0abd) + (define-keysym "rightanglebracket" #x0abe) + (define-keysym "marker" #x0abf) + (define-keysym "oneeighth" #x0ac3) + (define-keysym "threeeighths" #x0ac4) + (define-keysym "fiveeighths" #x0ac5) + (define-keysym "seveneighths" #x0ac6) + (define-keysym "trademark" #x0ac9) + (define-keysym "signaturemark" #x0aca) + (define-keysym "trademarkincircle" #x0acb) + (define-keysym "leftopentriangle" #x0acc) + (define-keysym "rightopentriangle" #x0acd) + (define-keysym "emopencircle" #x0ace) + (define-keysym "emopenrectangle" #x0acf) + (define-keysym "leftsinglequotemark" #x0ad0) + (define-keysym "rightsinglequotemark" #x0ad1) + (define-keysym "leftdoublequotemark" #x0ad2) + (define-keysym "rightdoublequotemark" #x0ad3) + (define-keysym "prescription" #x0ad4) + (define-keysym "minutes" #x0ad6) + (define-keysym "seconds" #x0ad7) + (define-keysym "latincross" #x0ad9) + (define-keysym "hexagram" #x0ada) + (define-keysym "filledrectbullet" #x0adb) + (define-keysym "filledlefttribullet" #x0adc) + (define-keysym "filledrighttribullet" #x0add) + (define-keysym "emfilledcircle" #x0ade) + (define-keysym "emfilledrect" #x0adf) + (define-keysym "enopencircbullet" #x0ae0) + (define-keysym "enopensquarebullet" #x0ae1) + (define-keysym "openrectbullet" #x0ae2) + (define-keysym "opentribulletup" #x0ae3) + (define-keysym "opentribulletdown" #x0ae4) + (define-keysym "openstar" #x0ae5) + (define-keysym "enfilledcircbullet" #x0ae6) + (define-keysym "enfilledsqbullet" #x0ae7) + (define-keysym "filledtribulletup" #x0ae8) + (define-keysym "filledtribulletdown" #x0ae9) + (define-keysym "leftpointer" #x0aea) + (define-keysym "rightpointer" #x0aeb) + (define-keysym "club" #x0aec) + (define-keysym "diamond" #x0aed) + (define-keysym "heart" #x0aee) + (define-keysym "maltesecross" #x0af0) + (define-keysym "dagger" #x0af1) + (define-keysym "doubledagger" #x0af2) + (define-keysym "checkmark" #x0af3) + (define-keysym "ballotcross" #x0af4) + (define-keysym "musicalsharp" #x0af5) + (define-keysym "musicalflat" #x0af6) + (define-keysym "malesymbol" #x0af7) + (define-keysym "femalesymbol" #x0af8) + (define-keysym "telephone" #x0af9) + (define-keysym "telephonerecorder" #x0afa) + (define-keysym "phonographcopyright" #x0afb) + (define-keysym "caret" #x0afc) + (define-keysym "singlelowquotemark" #x0afd) + (define-keysym "doublelowquotemark" #x0afe) + (define-keysym "cursor" #x0aff) + (define-keysym "leftcaret" #x0ba3) + (define-keysym "rightcaret" #x0ba6) + (define-keysym "downcaret" #x0ba8) + (define-keysym "upcaret" #x0ba9) + (define-keysym "overbar" #x0bc0) + (define-keysym "downtack" #x0bc2) + (define-keysym "upshoe" #x0bc3) + (define-keysym "downstile" #x0bc4) + (define-keysym "underbar" #x0bc6) + (define-keysym "jot" #x0bca) + (define-keysym "quad" #x0bcc) + (define-keysym "uptack" #x0bce) + (define-keysym "circle" #x0bcf) + (define-keysym "upstile" #x0bd3) + (define-keysym "downshoe" #x0bd6) + (define-keysym "rightshoe" #x0bd8) + (define-keysym "leftshoe" #x0bda) + (define-keysym "lefttack" #x0bdc) + (define-keysym "righttack" #x0bfc) + (define-keysym "hebrew_doublelowline" #x0cdf) + (define-keysym "hebrew_aleph" #x0ce0) + (define-keysym "hebrew_bet" #x0ce1) + (define-keysym "hebrew_beth" #x0ce1) + (define-keysym "hebrew_gimel" #x0ce2) + (define-keysym "hebrew_gimmel" #x0ce2) + (define-keysym "hebrew_dalet" #x0ce3) + (define-keysym "hebrew_daleth" #x0ce3) + (define-keysym "hebrew_he" #x0ce4) + (define-keysym "hebrew_waw" #x0ce5) + (define-keysym "hebrew_zain" #x0ce6) + (define-keysym "hebrew_zayin" #x0ce6) + (define-keysym "hebrew_chet" #x0ce7) + (define-keysym "hebrew_het" #x0ce7) + (define-keysym "hebrew_tet" #x0ce8) + (define-keysym "hebrew_teth" #x0ce8) + (define-keysym "hebrew_yod" #x0ce9) + (define-keysym "hebrew_finalkaph" #x0cea) + (define-keysym "hebrew_kaph" #x0ceb) + (define-keysym "hebrew_lamed" #x0cec) + (define-keysym "hebrew_finalmem" #x0ced) + (define-keysym "hebrew_mem" #x0cee) + (define-keysym "hebrew_finalnun" #x0cef) + (define-keysym "hebrew_nun" #x0cf0) + (define-keysym "hebrew_samech" #x0cf1) + (define-keysym "hebrew_samekh" #x0cf1) + (define-keysym "hebrew_ayin" #x0cf2) + (define-keysym "hebrew_finalpe" #x0cf3) + (define-keysym "hebrew_pe" #x0cf4) + (define-keysym "hebrew_finalzade" #x0cf5) + (define-keysym "hebrew_finalzadi" #x0cf5) + (define-keysym "hebrew_zade" #x0cf6) + (define-keysym "hebrew_zadi" #x0cf6) + (define-keysym "hebrew_qoph" #x0cf7) + (define-keysym "hebrew_kuf" #x0cf7) + (define-keysym "hebrew_resh" #x0cf8) + (define-keysym "hebrew_shin" #x0cf9) + (define-keysym "hebrew_taw" #x0cfa) + (define-keysym "hebrew_taf" #x0cfa) + (define-keysym "Hebrew_switch" #xff7e) + (define-keysym "Thai_kokai" #x0da1) + (define-keysym "Thai_khokhai" #x0da2) + (define-keysym "Thai_khokhuat" #x0da3) + (define-keysym "Thai_khokhwai" #x0da4) + (define-keysym "Thai_khokhon" #x0da5) + (define-keysym "Thai_khorakhang" #x0da6) + (define-keysym "Thai_ngongu" #x0da7) + (define-keysym "Thai_chochan" #x0da8) + (define-keysym "Thai_choching" #x0da9) + (define-keysym "Thai_chochang" #x0daa) + (define-keysym "Thai_soso" #x0dab) + (define-keysym "Thai_chochoe" #x0dac) + (define-keysym "Thai_yoying" #x0dad) + (define-keysym "Thai_dochada" #x0dae) + (define-keysym "Thai_topatak" #x0daf) + (define-keysym "Thai_thothan" #x0db0) + (define-keysym "Thai_thonangmontho" #x0db1) + (define-keysym "Thai_thophuthao" #x0db2) + (define-keysym "Thai_nonen" #x0db3) + (define-keysym "Thai_dodek" #x0db4) + (define-keysym "Thai_totao" #x0db5) + (define-keysym "Thai_thothung" #x0db6) + (define-keysym "Thai_thothahan" #x0db7) + (define-keysym "Thai_thothong" #x0db8) + (define-keysym "Thai_nonu" #x0db9) + (define-keysym "Thai_bobaimai" #x0dba) + (define-keysym "Thai_popla" #x0dbb) + (define-keysym "Thai_phophung" #x0dbc) + (define-keysym "Thai_fofa" #x0dbd) + (define-keysym "Thai_phophan" #x0dbe) + (define-keysym "Thai_fofan" #x0dbf) + (define-keysym "Thai_phosamphao" #x0dc0) + (define-keysym "Thai_moma" #x0dc1) + (define-keysym "Thai_yoyak" #x0dc2) + (define-keysym "Thai_rorua" #x0dc3) + (define-keysym "Thai_ru" #x0dc4) + (define-keysym "Thai_loling" #x0dc5) + (define-keysym "Thai_lu" #x0dc6) + (define-keysym "Thai_wowaen" #x0dc7) + (define-keysym "Thai_sosala" #x0dc8) + (define-keysym "Thai_sorusi" #x0dc9) + (define-keysym "Thai_sosua" #x0dca) + (define-keysym "Thai_hohip" #x0dcb) + (define-keysym "Thai_lochula" #x0dcc) + (define-keysym "Thai_oang" #x0dcd) + (define-keysym "Thai_honokhuk" #x0dce) + (define-keysym "Thai_paiyannoi" #x0dcf) + (define-keysym "Thai_saraa" #x0dd0) + (define-keysym "Thai_maihanakat" #x0dd1) + (define-keysym "Thai_saraaa" #x0dd2) + (define-keysym "Thai_saraam" #x0dd3) + (define-keysym "Thai_sarai" #x0dd4) + (define-keysym "Thai_saraii" #x0dd5) + (define-keysym "Thai_saraue" #x0dd6) + (define-keysym "Thai_sarauee" #x0dd7) + (define-keysym "Thai_sarau" #x0dd8) + (define-keysym "Thai_sarauu" #x0dd9) + (define-keysym "Thai_phinthu" #x0dda) + (define-keysym "Thai_maihanakat_maitho" #x0dde) + (define-keysym "Thai_baht" #x0ddf) + (define-keysym "Thai_sarae" #x0de0) + (define-keysym "Thai_saraae" #x0de1) + (define-keysym "Thai_sarao" #x0de2) + (define-keysym "Thai_saraaimaimuan" #x0de3) + (define-keysym "Thai_saraaimaimalai" #x0de4) + (define-keysym "Thai_lakkhangyao" #x0de5) + (define-keysym "Thai_maiyamok" #x0de6) + (define-keysym "Thai_maitaikhu" #x0de7) + (define-keysym "Thai_maiek" #x0de8) + (define-keysym "Thai_maitho" #x0de9) + (define-keysym "Thai_maitri" #x0dea) + (define-keysym "Thai_maichattawa" #x0deb) + (define-keysym "Thai_thanthakhat" #x0dec) + (define-keysym "Thai_nikhahit" #x0ded) + (define-keysym "Thai_leksun" #x0df0) + (define-keysym "Thai_leknung" #x0df1) + (define-keysym "Thai_leksong" #x0df2) + (define-keysym "Thai_leksam" #x0df3) + (define-keysym "Thai_leksi" #x0df4) + (define-keysym "Thai_lekha" #x0df5) + (define-keysym "Thai_lekhok" #x0df6) + (define-keysym "Thai_lekchet" #x0df7) + (define-keysym "Thai_lekpaet" #x0df8) + (define-keysym "Thai_lekkao" #x0df9) + (define-keysym "Hangul" #xff31) + (define-keysym "Hangul_Start" #xff32) + (define-keysym "Hangul_End" #xff33) + (define-keysym "Hangul_Hanja" #xff34) + (define-keysym "Hangul_Jamo" #xff35) + (define-keysym "Hangul_Romaja" #xff36) + (define-keysym "Hangul_Codeinput" #xff37) + (define-keysym "Hangul_Jeonja" #xff38) + (define-keysym "Hangul_Banja" #xff39) + (define-keysym "Hangul_PreHanja" #xff3a) + (define-keysym "Hangul_PostHanja" #xff3b) + (define-keysym "Hangul_SingleCandidate" #xff3c) + (define-keysym "Hangul_MultipleCandidate" #xff3d) + (define-keysym "Hangul_PreviousCandidate" #xff3e) + (define-keysym "Hangul_Special" #xff3f) + (define-keysym "Hangul_switch" #xff7e) + (define-keysym "Hangul_Kiyeog" #x0ea1) + (define-keysym "Hangul_SsangKiyeog" #x0ea2) + (define-keysym "Hangul_KiyeogSios" #x0ea3) + (define-keysym "Hangul_Nieun" #x0ea4) + (define-keysym "Hangul_NieunJieuj" #x0ea5) + (define-keysym "Hangul_NieunHieuh" #x0ea6) + (define-keysym "Hangul_Dikeud" #x0ea7) + (define-keysym "Hangul_SsangDikeud" #x0ea8) + (define-keysym "Hangul_Rieul" #x0ea9) + (define-keysym "Hangul_RieulKiyeog" #x0eaa) + (define-keysym "Hangul_RieulMieum" #x0eab) + (define-keysym "Hangul_RieulPieub" #x0eac) + (define-keysym "Hangul_RieulSios" #x0ead) + (define-keysym "Hangul_RieulTieut" #x0eae) + (define-keysym "Hangul_RieulPhieuf" #x0eaf) + (define-keysym "Hangul_RieulHieuh" #x0eb0) + (define-keysym "Hangul_Mieum" #x0eb1) + (define-keysym "Hangul_Pieub" #x0eb2) + (define-keysym "Hangul_SsangPieub" #x0eb3) + (define-keysym "Hangul_PieubSios" #x0eb4) + (define-keysym "Hangul_Sios" #x0eb5) + (define-keysym "Hangul_SsangSios" #x0eb6) + (define-keysym "Hangul_Ieung" #x0eb7) + (define-keysym "Hangul_Jieuj" #x0eb8) + (define-keysym "Hangul_SsangJieuj" #x0eb9) + (define-keysym "Hangul_Cieuc" #x0eba) + (define-keysym "Hangul_Khieuq" #x0ebb) + (define-keysym "Hangul_Tieut" #x0ebc) + (define-keysym "Hangul_Phieuf" #x0ebd) + (define-keysym "Hangul_Hieuh" #x0ebe) + (define-keysym "Hangul_A" #x0ebf) + (define-keysym "Hangul_AE" #x0ec0) + (define-keysym "Hangul_YA" #x0ec1) + (define-keysym "Hangul_YAE" #x0ec2) + (define-keysym "Hangul_EO" #x0ec3) + (define-keysym "Hangul_E" #x0ec4) + (define-keysym "Hangul_YEO" #x0ec5) + (define-keysym "Hangul_YE" #x0ec6) + (define-keysym "Hangul_O" #x0ec7) + (define-keysym "Hangul_WA" #x0ec8) + (define-keysym "Hangul_WAE" #x0ec9) + (define-keysym "Hangul_OE" #x0eca) + (define-keysym "Hangul_YO" #x0ecb) + (define-keysym "Hangul_U" #x0ecc) + (define-keysym "Hangul_WEO" #x0ecd) + (define-keysym "Hangul_WE" #x0ece) + (define-keysym "Hangul_WI" #x0ecf) + (define-keysym "Hangul_YU" #x0ed0) + (define-keysym "Hangul_EU" #x0ed1) + (define-keysym "Hangul_YI" #x0ed2) + (define-keysym "Hangul_I" #x0ed3) + (define-keysym "Hangul_J_Kiyeog" #x0ed4) + (define-keysym "Hangul_J_SsangKiyeog" #x0ed5) + (define-keysym "Hangul_J_KiyeogSios" #x0ed6) + (define-keysym "Hangul_J_Nieun" #x0ed7) + (define-keysym "Hangul_J_NieunJieuj" #x0ed8) + (define-keysym "Hangul_J_NieunHieuh" #x0ed9) + (define-keysym "Hangul_J_Dikeud" #x0eda) + (define-keysym "Hangul_J_Rieul" #x0edb) + (define-keysym "Hangul_J_RieulKiyeog" #x0edc) + (define-keysym "Hangul_J_RieulMieum" #x0edd) + (define-keysym "Hangul_J_RieulPieub" #x0ede) + (define-keysym "Hangul_J_RieulSios" #x0edf) + (define-keysym "Hangul_J_RieulTieut" #x0ee0) + (define-keysym "Hangul_J_RieulPhieuf" #x0ee1) + (define-keysym "Hangul_J_RieulHieuh" #x0ee2) + (define-keysym "Hangul_J_Mieum" #x0ee3) + (define-keysym "Hangul_J_Pieub" #x0ee4) + (define-keysym "Hangul_J_PieubSios" #x0ee5) + (define-keysym "Hangul_J_Sios" #x0ee6) + (define-keysym "Hangul_J_SsangSios" #x0ee7) + (define-keysym "Hangul_J_Ieung" #x0ee8) + (define-keysym "Hangul_J_Jieuj" #x0ee9) + (define-keysym "Hangul_J_Cieuc" #x0eea) + (define-keysym "Hangul_J_Khieuq" #x0eeb) + (define-keysym "Hangul_J_Tieut" #x0eec) + (define-keysym "Hangul_J_Phieuf" #x0eed) + (define-keysym "Hangul_J_Hieuh" #x0eee) + (define-keysym "Hangul_RieulYeorinHieuh" #x0eef) + (define-keysym "Hangul_SunkyeongeumMieum" #x0ef0) + (define-keysym "Hangul_SunkyeongeumPieub" #x0ef1) + (define-keysym "Hangul_PanSios" #x0ef2) + (define-keysym "Hangul_KkogjiDalrinIeung" #x0ef3) + (define-keysym "Hangul_SunkyeongeumPhieuf" #x0ef4) + (define-keysym "Hangul_YeorinHieuh" #x0ef5) + (define-keysym "Hangul_AraeA" #x0ef6) + (define-keysym "Hangul_AraeAE" #x0ef7) + (define-keysym "Hangul_J_PanSios" #x0ef8) + (define-keysym "Hangul_J_KkogjiDalrinIeung" #x0ef9) + (define-keysym "Hangul_J_YeorinHieuh" #x0efa) + (define-keysym "Korean_Won" #x0eff) + (define-keysym "Armenian_ligature_ew" #x1000587) + (define-keysym "Armenian_full_stop" #x1000589) + (define-keysym "Armenian_verjaket" #x1000589) + (define-keysym "Armenian_separation_mark" #x100055d) + (define-keysym "Armenian_but" #x100055d) + (define-keysym "Armenian_hyphen" #x100058a) + (define-keysym "Armenian_yentamna" #x100058a) + (define-keysym "Armenian_exclam" #x100055c) + (define-keysym "Armenian_amanak" #x100055c) + (define-keysym "Armenian_accent" #x100055b) + (define-keysym "Armenian_shesht" #x100055b) + (define-keysym "Armenian_question" #x100055e) + (define-keysym "Armenian_paruyk" #x100055e) + (define-keysym "Armenian_AYB" #x1000531) + (define-keysym "Armenian_ayb" #x1000561) + (define-keysym "Armenian_BEN" #x1000532) + (define-keysym "Armenian_ben" #x1000562) + (define-keysym "Armenian_GIM" #x1000533) + (define-keysym "Armenian_gim" #x1000563) + (define-keysym "Armenian_DA" #x1000534) + (define-keysym "Armenian_da" #x1000564) + (define-keysym "Armenian_YECH" #x1000535) + (define-keysym "Armenian_yech" #x1000565) + (define-keysym "Armenian_ZA" #x1000536) + (define-keysym "Armenian_za" #x1000566) + (define-keysym "Armenian_E" #x1000537) + (define-keysym "Armenian_e" #x1000567) + (define-keysym "Armenian_AT" #x1000538) + (define-keysym "Armenian_at" #x1000568) + (define-keysym "Armenian_TO" #x1000539) + (define-keysym "Armenian_to" #x1000569) + (define-keysym "Armenian_ZHE" #x100053a) + (define-keysym "Armenian_zhe" #x100056a) + (define-keysym "Armenian_INI" #x100053b) + (define-keysym "Armenian_ini" #x100056b) + (define-keysym "Armenian_LYUN" #x100053c) + (define-keysym "Armenian_lyun" #x100056c) + (define-keysym "Armenian_KHE" #x100053d) + (define-keysym "Armenian_khe" #x100056d) + (define-keysym "Armenian_TSA" #x100053e) + (define-keysym "Armenian_tsa" #x100056e) + (define-keysym "Armenian_KEN" #x100053f) + (define-keysym "Armenian_ken" #x100056f) + (define-keysym "Armenian_HO" #x1000540) + (define-keysym "Armenian_ho" #x1000570) + (define-keysym "Armenian_DZA" #x1000541) + (define-keysym "Armenian_dza" #x1000571) + (define-keysym "Armenian_GHAT" #x1000542) + (define-keysym "Armenian_ghat" #x1000572) + (define-keysym "Armenian_TCHE" #x1000543) + (define-keysym "Armenian_tche" #x1000573) + (define-keysym "Armenian_MEN" #x1000544) + (define-keysym "Armenian_men" #x1000574) + (define-keysym "Armenian_HI" #x1000545) + (define-keysym "Armenian_hi" #x1000575) + (define-keysym "Armenian_NU" #x1000546) + (define-keysym "Armenian_nu" #x1000576) + (define-keysym "Armenian_SHA" #x1000547) + (define-keysym "Armenian_sha" #x1000577) + (define-keysym "Armenian_VO" #x1000548) + (define-keysym "Armenian_vo" #x1000578) + (define-keysym "Armenian_CHA" #x1000549) + (define-keysym "Armenian_cha" #x1000579) + (define-keysym "Armenian_PE" #x100054a) + (define-keysym "Armenian_pe" #x100057a) + (define-keysym "Armenian_JE" #x100054b) + (define-keysym "Armenian_je" #x100057b) + (define-keysym "Armenian_RA" #x100054c) + (define-keysym "Armenian_ra" #x100057c) + (define-keysym "Armenian_SE" #x100054d) + (define-keysym "Armenian_se" #x100057d) + (define-keysym "Armenian_VEV" #x100054e) + (define-keysym "Armenian_vev" #x100057e) + (define-keysym "Armenian_TYUN" #x100054f) + (define-keysym "Armenian_tyun" #x100057f) + (define-keysym "Armenian_RE" #x1000550) + (define-keysym "Armenian_re" #x1000580) + (define-keysym "Armenian_TSO" #x1000551) + (define-keysym "Armenian_tso" #x1000581) + (define-keysym "Armenian_VYUN" #x1000552) + (define-keysym "Armenian_vyun" #x1000582) + (define-keysym "Armenian_PYUR" #x1000553) + (define-keysym "Armenian_pyur" #x1000583) + (define-keysym "Armenian_KE" #x1000554) + (define-keysym "Armenian_ke" #x1000584) + (define-keysym "Armenian_O" #x1000555) + (define-keysym "Armenian_o" #x1000585) + (define-keysym "Armenian_FE" #x1000556) + (define-keysym "Armenian_fe" #x1000586) + (define-keysym "Armenian_apostrophe" #x100055a) + (define-keysym "Georgian_an" #x10010d0) + (define-keysym "Georgian_ban" #x10010d1) + (define-keysym "Georgian_gan" #x10010d2) + (define-keysym "Georgian_don" #x10010d3) + (define-keysym "Georgian_en" #x10010d4) + (define-keysym "Georgian_vin" #x10010d5) + (define-keysym "Georgian_zen" #x10010d6) + (define-keysym "Georgian_tan" #x10010d7) + (define-keysym "Georgian_in" #x10010d8) + (define-keysym "Georgian_kan" #x10010d9) + (define-keysym "Georgian_las" #x10010da) + (define-keysym "Georgian_man" #x10010db) + (define-keysym "Georgian_nar" #x10010dc) + (define-keysym "Georgian_on" #x10010dd) + (define-keysym "Georgian_par" #x10010de) + (define-keysym "Georgian_zhar" #x10010df) + (define-keysym "Georgian_rae" #x10010e0) + (define-keysym "Georgian_san" #x10010e1) + (define-keysym "Georgian_tar" #x10010e2) + (define-keysym "Georgian_un" #x10010e3) + (define-keysym "Georgian_phar" #x10010e4) + (define-keysym "Georgian_khar" #x10010e5) + (define-keysym "Georgian_ghan" #x10010e6) + (define-keysym "Georgian_qar" #x10010e7) + (define-keysym "Georgian_shin" #x10010e8) + (define-keysym "Georgian_chin" #x10010e9) + (define-keysym "Georgian_can" #x10010ea) + (define-keysym "Georgian_jil" #x10010eb) + (define-keysym "Georgian_cil" #x10010ec) + (define-keysym "Georgian_char" #x10010ed) + (define-keysym "Georgian_xan" #x10010ee) + (define-keysym "Georgian_jhan" #x10010ef) + (define-keysym "Georgian_hae" #x10010f0) + (define-keysym "Georgian_he" #x10010f1) + (define-keysym "Georgian_hie" #x10010f2) + (define-keysym "Georgian_we" #x10010f3) + (define-keysym "Georgian_har" #x10010f4) + (define-keysym "Georgian_hoe" #x10010f5) + (define-keysym "Georgian_fi" #x10010f6) + (define-keysym "Xabovedot" #x1001e8a) + (define-keysym "Ibreve" #x100012c) + (define-keysym "Zstroke" #x10001b5) + (define-keysym "Gcaron" #x10001e6) + (define-keysym "Ocaron" #x10001d1) + (define-keysym "Obarred" #x100019f) + (define-keysym "xabovedot" #x1001e8b) + (define-keysym "ibreve" #x100012d) + (define-keysym "zstroke" #x10001b6) + (define-keysym "gcaron" #x10001e7) + (define-keysym "ocaron" #x10001d2) + (define-keysym "obarred" #x1000275) + (define-keysym "SCHWA" #x100018f) + (define-keysym "schwa" #x1000259) + (define-keysym "Lbelowdot" #x1001e36) + (define-keysym "lbelowdot" #x1001e37) + (define-keysym "Abelowdot" #x1001ea0) + (define-keysym "abelowdot" #x1001ea1) + (define-keysym "Ahook" #x1001ea2) + (define-keysym "ahook" #x1001ea3) + (define-keysym "Acircumflexacute" #x1001ea4) + (define-keysym "acircumflexacute" #x1001ea5) + (define-keysym "Acircumflexgrave" #x1001ea6) + (define-keysym "acircumflexgrave" #x1001ea7) + (define-keysym "Acircumflexhook" #x1001ea8) + (define-keysym "acircumflexhook" #x1001ea9) + (define-keysym "Acircumflextilde" #x1001eaa) + (define-keysym "acircumflextilde" #x1001eab) + (define-keysym "Acircumflexbelowdot" #x1001eac) + (define-keysym "acircumflexbelowdot" #x1001ead) + (define-keysym "Abreveacute" #x1001eae) + (define-keysym "abreveacute" #x1001eaf) + (define-keysym "Abrevegrave" #x1001eb0) + (define-keysym "abrevegrave" #x1001eb1) + (define-keysym "Abrevehook" #x1001eb2) + (define-keysym "abrevehook" #x1001eb3) + (define-keysym "Abrevetilde" #x1001eb4) + (define-keysym "abrevetilde" #x1001eb5) + (define-keysym "Abrevebelowdot" #x1001eb6) + (define-keysym "abrevebelowdot" #x1001eb7) + (define-keysym "Ebelowdot" #x1001eb8) + (define-keysym "ebelowdot" #x1001eb9) + (define-keysym "Ehook" #x1001eba) + (define-keysym "ehook" #x1001ebb) + (define-keysym "Etilde" #x1001ebc) + (define-keysym "etilde" #x1001ebd) + (define-keysym "Ecircumflexacute" #x1001ebe) + (define-keysym "ecircumflexacute" #x1001ebf) + (define-keysym "Ecircumflexgrave" #x1001ec0) + (define-keysym "ecircumflexgrave" #x1001ec1) + (define-keysym "Ecircumflexhook" #x1001ec2) + (define-keysym "ecircumflexhook" #x1001ec3) + (define-keysym "Ecircumflextilde" #x1001ec4) + (define-keysym "ecircumflextilde" #x1001ec5) + (define-keysym "Ecircumflexbelowdot" #x1001ec6) + (define-keysym "ecircumflexbelowdot" #x1001ec7) + (define-keysym "Ihook" #x1001ec8) + (define-keysym "ihook" #x1001ec9) + (define-keysym "Ibelowdot" #x1001eca) + (define-keysym "ibelowdot" #x1001ecb) + (define-keysym "Obelowdot" #x1001ecc) + (define-keysym "obelowdot" #x1001ecd) + (define-keysym "Ohook" #x1001ece) + (define-keysym "ohook" #x1001ecf) + (define-keysym "Ocircumflexacute" #x1001ed0) + (define-keysym "ocircumflexacute" #x1001ed1) + (define-keysym "Ocircumflexgrave" #x1001ed2) + (define-keysym "ocircumflexgrave" #x1001ed3) + (define-keysym "Ocircumflexhook" #x1001ed4) + (define-keysym "ocircumflexhook" #x1001ed5) + (define-keysym "Ocircumflextilde" #x1001ed6) + (define-keysym "ocircumflextilde" #x1001ed7) + (define-keysym "Ocircumflexbelowdot" #x1001ed8) + (define-keysym "ocircumflexbelowdot" #x1001ed9) + (define-keysym "Ohornacute" #x1001eda) + (define-keysym "ohornacute" #x1001edb) + (define-keysym "Ohorngrave" #x1001edc) + (define-keysym "ohorngrave" #x1001edd) + (define-keysym "Ohornhook" #x1001ede) + (define-keysym "ohornhook" #x1001edf) + (define-keysym "Ohorntilde" #x1001ee0) + (define-keysym "ohorntilde" #x1001ee1) + (define-keysym "Ohornbelowdot" #x1001ee2) + (define-keysym "ohornbelowdot" #x1001ee3) + (define-keysym "Ubelowdot" #x1001ee4) + (define-keysym "ubelowdot" #x1001ee5) + (define-keysym "Uhook" #x1001ee6) + (define-keysym "uhook" #x1001ee7) + (define-keysym "Uhornacute" #x1001ee8) + (define-keysym "uhornacute" #x1001ee9) + (define-keysym "Uhorngrave" #x1001eea) + (define-keysym "uhorngrave" #x1001eeb) + (define-keysym "Uhornhook" #x1001eec) + (define-keysym "uhornhook" #x1001eed) + (define-keysym "Uhorntilde" #x1001eee) + (define-keysym "uhorntilde" #x1001eef) + (define-keysym "Uhornbelowdot" #x1001ef0) + (define-keysym "uhornbelowdot" #x1001ef1) + (define-keysym "Ybelowdot" #x1001ef4) + (define-keysym "ybelowdot" #x1001ef5) + (define-keysym "Yhook" #x1001ef6) + (define-keysym "yhook" #x1001ef7) + (define-keysym "Ytilde" #x1001ef8) + (define-keysym "ytilde" #x1001ef9) + (define-keysym "Ohorn" #x10001a0) + (define-keysym "ohorn" #x10001a1) + (define-keysym "Uhorn" #x10001af) + (define-keysym "uhorn" #x10001b0) + (define-keysym "EcuSign" #x10020a0) + (define-keysym "ColonSign" #x10020a1) + (define-keysym "CruzeiroSign" #x10020a2) + (define-keysym "FFrancSign" #x10020a3) + (define-keysym "LiraSign" #x10020a4) + (define-keysym "MillSign" #x10020a5) + (define-keysym "NairaSign" #x10020a6) + (define-keysym "PesetaSign" #x10020a7) + (define-keysym "RupeeSign" #x10020a8) + (define-keysym "WonSign" #x10020a9) + (define-keysym "NewSheqelSign" #x10020aa) + (define-keysym "DongSign" #x10020ab) + (define-keysym "EuroSign" #x20ac) + (define-keysym "zerosuperior" #x1002070) + (define-keysym "foursuperior" #x1002074) + (define-keysym "fivesuperior" #x1002075) + (define-keysym "sixsuperior" #x1002076) + (define-keysym "sevensuperior" #x1002077) + (define-keysym "eightsuperior" #x1002078) + (define-keysym "ninesuperior" #x1002079) + (define-keysym "zerosubscript" #x1002080) + (define-keysym "onesubscript" #x1002081) + (define-keysym "twosubscript" #x1002082) + (define-keysym "threesubscript" #x1002083) + (define-keysym "foursubscript" #x1002084) + (define-keysym "fivesubscript" #x1002085) + (define-keysym "sixsubscript" #x1002086) + (define-keysym "sevensubscript" #x1002087) + (define-keysym "eightsubscript" #x1002088) + (define-keysym "ninesubscript" #x1002089) + (define-keysym "partdifferential" #x1002202) + (define-keysym "emptyset" #x1002205) + (define-keysym "elementof" #x1002208) + (define-keysym "notelementof" #x1002209) + (define-keysym "containsas" #x100220B) + (define-keysym "squareroot" #x100221A) + (define-keysym "cuberoot" #x100221B) + (define-keysym "fourthroot" #x100221C) + (define-keysym "dintegral" #x100222C) + (define-keysym "tintegral" #x100222D) + (define-keysym "because" #x1002235) + (define-keysym "approxeq" #x1002248) + (define-keysym "notapproxeq" #x1002247) + (define-keysym "notidentical" #x1002262) + (define-keysym "stricteq" #x1002263) + (define-keysym "hpmute_acute" #x100000A8) + (define-keysym "hpmute_grave" #x100000A9) + (define-keysym "hpmute_asciicircum" #x100000AA) + (define-keysym "hpmute_diaeresis" #x100000AB) + (define-keysym "hpmute_asciitilde" #x100000AC) + (define-keysym "hplira" #x100000AF) + (define-keysym "hpguilder" #x100000BE) + (define-keysym "hpYdiaeresis" #x100000EE) + (define-keysym "hpIO" #x100000EE) + (define-keysym "hplongminus" #x100000F6) + (define-keysym "hpblock" #x100000FC) + (define-keysym "apLineDel" #x1000FF00) + (define-keysym "apCharDel" #x1000FF01) + (define-keysym "apCopy" #x1000FF02) + (define-keysym "apCut" #x1000FF03) + (define-keysym "apPaste" #x1000FF04) + (define-keysym "apMove" #x1000FF05) + (define-keysym "apGrow" #x1000FF06) + (define-keysym "apCmd" #x1000FF07) + (define-keysym "apShell" #x1000FF08) + (define-keysym "apLeftBar" #x1000FF09) + (define-keysym "apRightBar" #x1000FF0A) + (define-keysym "apLeftBox" #x1000FF0B) + (define-keysym "apRightBox" #x1000FF0C) + (define-keysym "apUpBox" #x1000FF0D) + (define-keysym "apDownBox" #x1000FF0E) + (define-keysym "apPop" #x1000FF0F) + (define-keysym "apRead" #x1000FF10) + (define-keysym "apEdit" #x1000FF11) + (define-keysym "apSave" #x1000FF12) + (define-keysym "apExit" #x1000FF13) + (define-keysym "apRepeat" #x1000FF14) + (define-keysym "hpModelock1" #x1000FF48) + (define-keysym "hpModelock2" #x1000FF49) + (define-keysym "hpReset" #x1000FF6C) + (define-keysym "hpSystem" #x1000FF6D) + (define-keysym "hpUser" #x1000FF6E) + (define-keysym "hpClearLine" #x1000FF6F) + (define-keysym "hpInsertLine" #x1000FF70) + (define-keysym "hpDeleteLine" #x1000FF71) + (define-keysym "hpInsertChar" #x1000FF72) + (define-keysym "hpDeleteChar" #x1000FF73) + (define-keysym "hpBackTab" #x1000FF74) + (define-keysym "hpKP_BackTab" #x1000FF75) + (define-keysym "apKP_parenleft" #x1000FFA8) + (define-keysym "apKP_parenright" #x1000FFA9) + (define-keysym "I2ND_FUNC_L" #x10004001) + (define-keysym "I2ND_FUNC_R" #x10004002) + (define-keysym "IREMOVE" #x10004003) + (define-keysym "IREPEAT" #x10004004) + (define-keysym "IA1" #x10004101) + (define-keysym "IA2" #x10004102) + (define-keysym "IA3" #x10004103) + (define-keysym "IA4" #x10004104) + (define-keysym "IA5" #x10004105) + (define-keysym "IA6" #x10004106) + (define-keysym "IA7" #x10004107) + (define-keysym "IA8" #x10004108) + (define-keysym "IA9" #x10004109) + (define-keysym "IA10" #x1000410A) + (define-keysym "IA11" #x1000410B) + (define-keysym "IA12" #x1000410C) + (define-keysym "IA13" #x1000410D) + (define-keysym "IA14" #x1000410E) + (define-keysym "IA15" #x1000410F) + (define-keysym "IB1" #x10004201) + (define-keysym "IB2" #x10004202) + (define-keysym "IB3" #x10004203) + (define-keysym "IB4" #x10004204) + (define-keysym "IB5" #x10004205) + (define-keysym "IB6" #x10004206) + (define-keysym "IB7" #x10004207) + (define-keysym "IB8" #x10004208) + (define-keysym "IB9" #x10004209) + (define-keysym "IB10" #x1000420A) + (define-keysym "IB11" #x1000420B) + (define-keysym "IB12" #x1000420C) + (define-keysym "IB13" #x1000420D) + (define-keysym "IB14" #x1000420E) + (define-keysym "IB15" #x1000420F) + (define-keysym "IB16" #x10004210) + (define-keysym "DRemove" #x1000FF00) + (define-keysym "Dring_accent" #x1000FEB0) + (define-keysym "Dcircumflex_accent" #x1000FE5E) + (define-keysym "Dcedilla_accent" #x1000FE2C) + (define-keysym "Dacute_accent" #x1000FE27) + (define-keysym "Dgrave_accent" #x1000FE60) + (define-keysym "Dtilde" #x1000FE7E) + (define-keysym "Ddiaeresis" #x1000FE22) + (define-keysym "osfCopy" #x1004FF02) + (define-keysym "osfCut" #x1004FF03) + (define-keysym "osfPaste" #x1004FF04) + (define-keysym "osfBackTab" #x1004FF07) + (define-keysym "osfBackSpace" #x1004FF08) + (define-keysym "osfClear" #x1004FF0B) + (define-keysym "osfEscape" #x1004FF1B) + (define-keysym "osfAddMode" #x1004FF31) + (define-keysym "osfPrimaryPaste" #x1004FF32) + (define-keysym "osfQuickPaste" #x1004FF33) + (define-keysym "osfPageLeft" #x1004FF40) + (define-keysym "osfPageUp" #x1004FF41) + (define-keysym "osfPageDown" #x1004FF42) + (define-keysym "osfPageRight" #x1004FF43) + (define-keysym "osfActivate" #x1004FF44) + (define-keysym "osfMenuBar" #x1004FF45) + (define-keysym "osfLeft" #x1004FF51) + (define-keysym "osfUp" #x1004FF52) + (define-keysym "osfRight" #x1004FF53) + (define-keysym "osfDown" #x1004FF54) + (define-keysym "osfPrior" #x1004FF55) + (define-keysym "osfNext" #x1004FF56) + (define-keysym "osfEndLine" #x1004FF57) + (define-keysym "osfBeginLine" #x1004FF58) + (define-keysym "osfEndData" #x1004FF59) + (define-keysym "osfBeginData" #x1004FF5A) + (define-keysym "osfPrevMenu" #x1004FF5B) + (define-keysym "osfNextMenu" #x1004FF5C) + (define-keysym "osfPrevField" #x1004FF5D) + (define-keysym "osfNextField" #x1004FF5E) + (define-keysym "osfSelect" #x1004FF60) + (define-keysym "osfInsert" #x1004FF63) + (define-keysym "osfUndo" #x1004FF65) + (define-keysym "osfMenu" #x1004FF67) + (define-keysym "osfCancel" #x1004FF69) + (define-keysym "osfHelp" #x1004FF6A) + (define-keysym "osfSelectAll" #x1004FF71) + (define-keysym "osfDeselectAll" #x1004FF72) + (define-keysym "osfReselect" #x1004FF73) + (define-keysym "osfExtend" #x1004FF74) + (define-keysym "osfRestore" #x1004FF78) + (define-keysym "osfSwitchDirection" #x1004FF7E) + (define-keysym "osfPriorMinor" #x1004FFF5) + (define-keysym "osfNextMinor" #x1004FFF6) + (define-keysym "osfRightLine" #x1004FFF7) + (define-keysym "osfLeftLine" #x1004FFF8) + (define-keysym "osfDelete" #x1004FFFF) + (define-keysym "SunFA_Grave" #x1005FF00) + (define-keysym "SunFA_Circum" #x1005FF01) + (define-keysym "SunFA_Tilde" #x1005FF02) + (define-keysym "SunFA_Acute" #x1005FF03) + (define-keysym "SunFA_Diaeresis" #x1005FF04) + (define-keysym "SunFA_Cedilla" #x1005FF05) + (define-keysym "SunF36" #x1005FF10) + (define-keysym "SunF37" #x1005FF11) + (define-keysym "SunSys_Req" #x1005FF60) + (define-keysym "SunProps" #x1005FF70) + (define-keysym "SunFront" #x1005FF71) + (define-keysym "SunCopy" #x1005FF72) + (define-keysym "SunOpen" #x1005FF73) + (define-keysym "SunPaste" #x1005FF74) + (define-keysym "SunCut" #x1005FF75) + (define-keysym "SunPowerSwitch" #x1005FF76) + (define-keysym "SunAudioLowerVolume" #x1005FF77) + (define-keysym "SunAudioMute" #x1005FF78) + (define-keysym "SunAudioRaiseVolume" #x1005FF79) + (define-keysym "SunVideoDegauss" #x1005FF7A) + (define-keysym "SunVideoLowerBrightness" #x1005FF7B) + (define-keysym "SunVideoRaiseBrightness" #x1005FF7C) + (define-keysym "SunPowerSwitchShift" #x1005FF7D) + (define-keysym "SunCompose" #xFF20) + (define-keysym "SunPageUp" #xFF55) + (define-keysym "SunPageDown" #xFF56) + (define-keysym "SunPrint_Screen" #xFF61) + (define-keysym "SunUndo" #xFF65) + (define-keysym "SunAgain" #xFF66) + (define-keysym "SunFind" #xFF68) + (define-keysym "SunStop" #xFF69) + (define-keysym "SunAltGraph" #xFF7E) + (define-keysym "WYSetup" #x1006FF00) + (define-keysym "ncdSetup" #x1006FF00) + (define-keysym "XeroxPointerButton1" #x10070001) + (define-keysym "XeroxPointerButton2" #x10070002) + (define-keysym "XeroxPointerButton3" #x10070003) + (define-keysym "XeroxPointerButton4" #x10070004) + (define-keysym "XeroxPointerButton5" #x10070005) + (define-keysym "XF86ModeLock" #x1008FF01) + (define-keysym "XF86MonBrightnessUp" #x1008FF02) + (define-keysym "XF86MonBrightnessDown" #x1008FF03) + (define-keysym "XF86KbdLightOnOff" #x1008FF04) + (define-keysym "XF86KbdBrightnessUp" #x1008FF05) + (define-keysym "XF86KbdBrightnessDown" #x1008FF06) + (define-keysym "XF86Standby" #x1008FF10) + (define-keysym "XF86AudioLowerVolume" #x1008FF11) + (define-keysym "XF86AudioMute" #x1008FF12) + (define-keysym "XF86AudioRaiseVolume" #x1008FF13) + (define-keysym "XF86AudioPlay" #x1008FF14) + (define-keysym "XF86AudioStop" #x1008FF15) + (define-keysym "XF86AudioPrev" #x1008FF16) + (define-keysym "XF86AudioNext" #x1008FF17) + (define-keysym "XF86HomePage" #x1008FF18) + (define-keysym "XF86Mail" #x1008FF19) + (define-keysym "XF86Start" #x1008FF1A) + (define-keysym "XF86Search" #x1008FF1B) + (define-keysym "XF86AudioRecord" #x1008FF1C) + (define-keysym "XF86Calculator" #x1008FF1D) + (define-keysym "XF86Memo" #x1008FF1E) + (define-keysym "XF86ToDoList" #x1008FF1F) + (define-keysym "XF86Calendar" #x1008FF20) + (define-keysym "XF86PowerDown" #x1008FF21) + (define-keysym "XF86ContrastAdjust" #x1008FF22) + (define-keysym "XF86RockerUp" #x1008FF23) + (define-keysym "XF86RockerDown" #x1008FF24) + (define-keysym "XF86RockerEnter" #x1008FF25) + (define-keysym "XF86Back" #x1008FF26) + (define-keysym "XF86Forward" #x1008FF27) + (define-keysym "XF86Stop" #x1008FF28) + (define-keysym "XF86Refresh" #x1008FF29) + (define-keysym "XF86PowerOff" #x1008FF2A) + (define-keysym "XF86WakeUp" #x1008FF2B) + (define-keysym "XF86Eject" #x1008FF2C) + (define-keysym "XF86ScreenSaver" #x1008FF2D) + (define-keysym "XF86WWW" #x1008FF2E) + (define-keysym "XF86Sleep" #x1008FF2F) + (define-keysym "XF86Favorites" #x1008FF30) + (define-keysym "XF86AudioPause" #x1008FF31) + (define-keysym "XF86AudioMedia" #x1008FF32) + (define-keysym "XF86MyComputer" #x1008FF33) + (define-keysym "XF86VendorHome" #x1008FF34) + (define-keysym "XF86LightBulb" #x1008FF35) + (define-keysym "XF86Shop" #x1008FF36) + (define-keysym "XF86History" #x1008FF37) + (define-keysym "XF86OpenURL" #x1008FF38) + (define-keysym "XF86AddFavorite" #x1008FF39) + (define-keysym "XF86HotLinks" #x1008FF3A) + (define-keysym "XF86BrightnessAdjust" #x1008FF3B) + (define-keysym "XF86Finance" #x1008FF3C) + (define-keysym "XF86Community" #x1008FF3D) + (define-keysym "XF86AudioRewind" #x1008FF3E) + (define-keysym "XF86BackForward" #x1008FF3F) + (define-keysym "XF86Launch0" #x1008FF40) + (define-keysym "XF86Launch1" #x1008FF41) + (define-keysym "XF86Launch2" #x1008FF42) + (define-keysym "XF86Launch3" #x1008FF43) + (define-keysym "XF86Launch4" #x1008FF44) + (define-keysym "XF86Launch5" #x1008FF45) + (define-keysym "XF86Launch6" #x1008FF46) + (define-keysym "XF86Launch7" #x1008FF47) + (define-keysym "XF86Launch8" #x1008FF48) + (define-keysym "XF86Launch9" #x1008FF49) + (define-keysym "XF86LaunchA" #x1008FF4A) + (define-keysym "XF86LaunchB" #x1008FF4B) + (define-keysym "XF86LaunchC" #x1008FF4C) + (define-keysym "XF86LaunchD" #x1008FF4D) + (define-keysym "XF86LaunchE" #x1008FF4E) + (define-keysym "XF86LaunchF" #x1008FF4F) + (define-keysym "XF86ApplicationLeft" #x1008FF50) + (define-keysym "XF86ApplicationRight" #x1008FF51) + (define-keysym "XF86Book" #x1008FF52) + (define-keysym "XF86CD" #x1008FF53) + (define-keysym "XF86Calculater" #x1008FF54) + (define-keysym "XF86Clear" #x1008FF55) + (define-keysym "XF86Close" #x1008FF56) + (define-keysym "XF86Copy" #x1008FF57) + (define-keysym "XF86Cut" #x1008FF58) + (define-keysym "XF86Display" #x1008FF59) + (define-keysym "XF86DOS" #x1008FF5A) + (define-keysym "XF86Documents" #x1008FF5B) + (define-keysym "XF86Excel" #x1008FF5C) + (define-keysym "XF86Explorer" #x1008FF5D) + (define-keysym "XF86Game" #x1008FF5E) + (define-keysym "XF86Go" #x1008FF5F) + (define-keysym "XF86iTouch" #x1008FF60) + (define-keysym "XF86LogOff" #x1008FF61) + (define-keysym "XF86Market" #x1008FF62) + (define-keysym "XF86Meeting" #x1008FF63) + (define-keysym "XF86MenuKB" #x1008FF65) + (define-keysym "XF86MenuPB" #x1008FF66) + (define-keysym "XF86MySites" #x1008FF67) + (define-keysym "XF86New" #x1008FF68) + (define-keysym "XF86News" #x1008FF69) + (define-keysym "XF86OfficeHome" #x1008FF6A) + (define-keysym "XF86Open" #x1008FF6B) + (define-keysym "XF86Option" #x1008FF6C) + (define-keysym "XF86Paste" #x1008FF6D) + (define-keysym "XF86Phone" #x1008FF6E) + (define-keysym "XF86Q" #x1008FF70) + (define-keysym "XF86Reply" #x1008FF72) + (define-keysym "XF86Reload" #x1008FF73) + (define-keysym "XF86RotateWindows" #x1008FF74) + (define-keysym "XF86RotationPB" #x1008FF75) + (define-keysym "XF86RotationKB" #x1008FF76) + (define-keysym "XF86Save" #x1008FF77) + (define-keysym "XF86ScrollUp" #x1008FF78) + (define-keysym "XF86ScrollDown" #x1008FF79) + (define-keysym "XF86ScrollClick" #x1008FF7A) + (define-keysym "XF86Send" #x1008FF7B) + (define-keysym "XF86Spell" #x1008FF7C) + (define-keysym "XF86SplitScreen" #x1008FF7D) + (define-keysym "XF86Support" #x1008FF7E) + (define-keysym "XF86TaskPane" #x1008FF7F) + (define-keysym "XF86Terminal" #x1008FF80) + (define-keysym "XF86Tools" #x1008FF81) + (define-keysym "XF86Travel" #x1008FF82) + (define-keysym "XF86UserPB" #x1008FF84) + (define-keysym "XF86User1KB" #x1008FF85) + (define-keysym "XF86User2KB" #x1008FF86) + (define-keysym "XF86Video" #x1008FF87) + (define-keysym "XF86WheelButton" #x1008FF88) + (define-keysym "XF86Word" #x1008FF89) + (define-keysym "XF86Xfer" #x1008FF8A) + (define-keysym "XF86ZoomIn" #x1008FF8B) + (define-keysym "XF86ZoomOut" #x1008FF8C) + (define-keysym "XF86Away" #x1008FF8D) + (define-keysym "XF86Messenger" #x1008FF8E) + (define-keysym "XF86WebCam" #x1008FF8F) + (define-keysym "XF86MailForward" #x1008FF90) + (define-keysym "XF86Pictures" #x1008FF91) + (define-keysym "XF86Music" #x1008FF92) + (define-keysym "XF86Battery" #x1008FF93) + (define-keysym "XF86Bluetooth" #x1008FF94) + (define-keysym "XF86WLAN" #x1008FF95) + (define-keysym "XF86UWB" #x1008FF96) + (define-keysym "XF86AudioForward" #x1008FF97) + (define-keysym "XF86AudioRepeat" #x1008FF98) + (define-keysym "XF86AudioRandomPlay" #x1008FF99) + (define-keysym "XF86Subtitle" #x1008FF9A) + (define-keysym "XF86AudioCycleTrack" #x1008FF9B) + (define-keysym "XF86CycleAngle" #x1008FF9C) + (define-keysym "XF86FrameBack" #x1008FF9D) + (define-keysym "XF86FrameForward" #x1008FF9E) + (define-keysym "XF86Time" #x1008FF9F) + (define-keysym "XF86Select" #x1008FFA0) + (define-keysym "XF86View" #x1008FFA1) + (define-keysym "XF86TopMenu" #x1008FFA2) + (define-keysym "XF86Red" #x1008FFA3) + (define-keysym "XF86Green" #x1008FFA4) + (define-keysym "XF86Yellow" #x1008FFA5) + (define-keysym "XF86Blue" #x1008FFA6) + (define-keysym "XF86Suspend" #x1008FFA7) + (define-keysym "XF86Hibernate" #x1008FFA8) + (define-keysym "XF86TouchpadToggle" #x1008FFA9) + (define-keysym "XF86TouchpadOn" #x1008FFB0) + (define-keysym "XF86TouchpadOff" #x1008FFB1) + (define-keysym "XF86AudioMicMute" #x1008FFB2) + (define-keysym "XF86RFKill" #x1008FFB5) + (define-keysym "XF86_Switch_VT_1" #x1008FE01) + (define-keysym "XF86_Switch_VT_2" #x1008FE02) + (define-keysym "XF86_Switch_VT_3" #x1008FE03) + (define-keysym "XF86_Switch_VT_4" #x1008FE04) + (define-keysym "XF86_Switch_VT_5" #x1008FE05) + (define-keysym "XF86_Switch_VT_6" #x1008FE06) + (define-keysym "XF86_Switch_VT_7" #x1008FE07) + (define-keysym "XF86_Switch_VT_8" #x1008FE08) + (define-keysym "XF86_Switch_VT_9" #x1008FE09) + (define-keysym "XF86_Switch_VT_10" #x1008FE0A) + (define-keysym "XF86_Switch_VT_11" #x1008FE0B) + (define-keysym "XF86_Switch_VT_12" #x1008FE0C) + (define-keysym "XF86_Ungrab" #x1008FE20) + (define-keysym "XF86_ClearGrab" #x1008FE21) + (define-keysym "XF86_Next_VMode" #x1008FE22) + (define-keysym "XF86_Prev_VMode" #x1008FE23) + (define-keysym "usldead_acute" #x100000A8) + (define-keysym "usldead_grave" #x100000A9) + (define-keysym "usldead_diaeresis" #x100000AB) + (define-keysym "usldead_asciicircum" #x100000AA) + (define-keysym "usldead_asciitilde" #x100000AC) + (define-keysym "usldead_cedilla" #x1000FE2C) + (define-keysym "usldead_ring" #x1000FEB0)) diff --git a/modules/which-key.scm b/modules/which-key.scm new file mode 100755 index 0000000..22637ca --- /dev/null +++ b/modules/which-key.scm @@ -0,0 +1,4 @@ +(define-module (modules which-key) + #:use-module (swayipc dispatcher) + #:export ()) + diff --git a/modules/workspace-grid.scm b/modules/workspace-grid.scm new file mode 100755 index 0000000..c807c4b --- /dev/null +++ b/modules/workspace-grid.scm @@ -0,0 +1,167 @@ +;; use example: + +;; (set! WORKSPACES +;; (("10" "11" "12" "13" "14" "15" "16" "17" "18" "19") +;; ("20" "21" "22" "23" "24" "25" "26" "27" "28" "29") +;; ("30" "31" "32" "33" "34" "35" "36" "37" "38" "39")) + +;; (set! ROWS 3) +;; (set! COLUMNS 3) + +;; (workspace-grid-init) + +(define-module (modules workspace-grid) + #:use-module (swayipc records) + #:use-module (swayipc info) + #:use-module (swayipc dispatcher) + #:use-module (swayipc events) + + #:export ( + WORKSPACES + COLUMNS + ROWS + configure-workspaces + configure-rows + configure-columns + get-active-workspace-index + switch-workspace-up + switch-workspace-right + switch-workspace-down + switch-workspace-left + move-container-to-workspace-up + move-container-to-workspace-right + move-container-to-workspace-down + move-container-to-workspace-left + valid-grid? + workspace-grid-init)) + +;; The order in which the outputs are organized, it's important that +;; the order of outputs match the order of workspaces in `WORKSPACE` +;; example: +;; (set! WORKSPACES '(("ws-o1-1" "ws-o1-2" "ws-o1-3") ("ws-o2-1" "ws-o2-2" "ws-o2-3")) +(define WORKSPACES '()) + +;; number of rows in the grid +(define ROWS 1) +;; number of columns in the grid +(define COLUMNS 1) + +(define (configure-workspaces workspaces) + (set! WORKSPACES workspaces)) + +(define (configure-rows rows) + (set! ROWS rows)) + +(define (configure-columns columns) + (set! COLUMNS columns)) + +(define* (get-active-workspace-name #:optional (workspaces (sway-get-workspaces))) + "get name of active workspace" + (cond + ((null? workspaces) #f) + ((equal? (sway-workspace-focused (car workspaces)) #t) + (sway-workspace-name (car workspaces))) + (else (get-active-workspace-name (cdr workspaces))))) + +(define* (get-output-index workspace #:optional (workspaces WORKSPACES) (index 0)) + "get output index of target workspace" + (cond + ((null? workspaces) #f) + ((member workspace (car workspaces)) index) + (else (get-output-index workspace (cdr workspaces) (+ index 1))))) + +(define* (get-workspace-index workspace #:optional + (workspaces + (list-ref WORKSPACES (get-output-index workspace)))) + "get index of target workspace" + (let* ((memberls (member workspace workspaces))) + (if memberls (- (length workspaces) (length memberls))))) + +(define (get-active-workspace-index) + "get index of active/focused workspace" + (let* ((workspace (get-active-workspace-name))) + (get-workspace-index workspace))) + +;; available directions, up, right, down, left +(define* (get-workspace-direction direction #:optional (index -1)) + "get the index the next workspace after applying the direction" + (let* ((index (if (< index 0) (get-active-workspace-index) index)) + (current-row (floor (/ index COLUMNS))) + (current-column (modulo index COLUMNS)) + (target-row + (cond ((equal? direction "up") (- current-row 1)) + ((equal? direction "down") (+ current-row 1)) + (else current-row))) + (target-column + (cond ((equal? direction "left") (- current-column 1)) + ((equal? direction "right") (+ current-column 1)) + (else current-column)))) + (+ (* COLUMNS (modulo target-row ROWS)) + (modulo target-column COLUMNS)))) + +(define* (get-workspace-name #:optional + (workspace (get-active-workspace-index)) + (output (get-output-index (get-active-workspace-name)))) + (list-ref (list-ref WORKSPACES output) workspace)) + +;; exposed command for easier access +(define (switch-workspace-up) + (sway-switch-workspace + (get-workspace-name + (get-workspace-direction "up")))) + +(define (switch-workspace-right) + (sway-switch-workspace + (get-workspace-name + (get-workspace-direction "right")))) + +(define (switch-workspace-down) + (sway-switch-workspace + (get-workspace-name + (get-workspace-direction "down")))) + +(define (switch-workspace-left) + (sway-switch-workspace + (get-workspace-name + (get-workspace-direction "left")))) + +(define (move-container-to-workspace-up) + (sway-move-container-to-workspace + (get-workspace-name + (get-workspace-direction "up"))) + (switch-workspace-up)) + +(define (move-container-to-workspace-right) + (sway-move-container-to-workspace + (get-workspace-name + (get-workspace-direction "right"))) + (switch-workspace-right)) + +(define (move-container-to-workspace-down) + (sway-move-container-to-workspace + (get-workspace-name + (get-workspace-direction "down"))) + (switch-workspace-down)) + +(define (move-container-to-workspace-left) + (sway-move-container-to-workspace + (get-workspace-name + (get-workspace-direction "left"))) + (switch-workspace-left)) + +(define (valid-grid? rows columns workspaces) + "validate the grid structure" + (and (> (length workspaces) 0) + (equal? (* rows columns) (length (car workspaces))))) + +(define (workspace-grid-init) + (display "starting workspace-grid\n") + (display WORKSPACES) + (newline) + (if (valid-grid? ROWS COLUMNS WORKSPACES) + (display (string-append "successfully started workspace " + (number->string ROWS) "x" + (number->string COLUMNS) "\n")) + (display (string-append "workspace grid failed to start the grid configs " + (number->string ROWS) "x" + (number->string COLUMNS) "\n")))) diff --git a/modules/workspace-groups.scm b/modules/workspace-groups.scm new file mode 100755 index 0000000..c57a731 --- /dev/null +++ b/modules/workspace-groups.scm @@ -0,0 +1,110 @@ +;; use example: + +;; (set! OUTPUTS '("HDMI-A-2" "DP-1" "DP-2")) +;; (set! GROUPS +;; '(("10" "20" "30") +;; ("11" "21" "31") +;; ("12" "22" "32") +;; ("13" "23" "33") +;; ("14" "24" "34") +;; ("15" "25" "35") +;; ("16" "26" "36") +;; ("17" "27" "37") +;; ("18" "28" "38") +;; ("19" "29" "39"))) + +;; (workspace-groups-init) + +(define-module (modules workspace-groups) + #:use-module (swayipc records) + #:use-module (swayipc info) + #:use-module (swayipc dispatcher) + #:use-module (swayipc events) + + #:export (workspace-groups-init + OUTPUTS + GROUPS)) + +;; The order in which the outputs are organized, it's important that +;; the order of outputs match the order of workspaces in `WORKSPACE-GROUPS` +;; example: +;; (set! OUTPUTS '("HDMI-A-2" "DP-1" "DP-2")) +(define OUTPUTS '()) + +;; The workspace groups, each is a list of workspace names +;; if a workspace of this list is activated, the rest of the workspaces +;; will be activated as well. +;; example: +;; (set! GROUPS +;; '(("10" "20" "30") +;; ("19" "29" "39"))) +(define GROUPS '()) + +(define (configure-outputs outputs) + (set! OUTPUTS outputs)) + +(define (configure-groups groups) + (set! GROUPS groups)) + +(define last-switched-group '()) + +(define (is-workspace-focused workspace output outputs) + (cond + ((null? outputs) #f) + ((equal? output (sway-output-name (car outputs))) + (equal? workspace (sway-output-current-workspace (car outputs)))) + (else (is-workspace-focused workspace output (cdr outputs))))) + +(define (switch-to-workspace-group group initiator) + (unless (equal? last-switched-group group) + (let* ((initiator-output "") + (outputs (sway-get-outputs))) + (set! last-switched-group group) + (newline) + (for-each + (lambda (workspace output) + (if (equal? workspace initiator) + (set! initiator-output output) + (unless (is-workspace-focused workspace output outputs) + (sway-switch-workspace workspace)))) + group OUTPUTS) + + ;; switch to initiator at last so the focus behaves as expected + (sway-switch-workspace initiator)))) + +(define (focused-workspace workspaces) + (cond + ((null? workspaces) #f) + ((equal? #t (sway-workspace-focused (car workspaces))) + (sway-workspace-name (car workspaces))) + (else (focused-workspace (cdr workspaces))))) + +(define (workspace-changed workspace-event) + (let* ((current-tree (sway-workspace-event-current workspace-event)) + (workspace (sway-tree-name current-tree)) + (focused-workspace (focused-workspace (sway-get-workspaces)))) + + ;; sometimes there is a delay in events, it's neccessary to ensure + ;; that event workspace is same as the currently focused workspace + (when (equal? workspace focused-workspace) + (unless (member workspace last-switched-group) + (set! last-switched-group '())) + (for-each + (lambda (group) + (when (member workspace group) + (switch-to-workspace-group group workspace))) + GROUPS)))) + +(define (pin-workspaces-to-output groups outputs) + (for-each + (lambda (group) + (for-each + (lambda (workspace output) + (sway-switch-workspace-on-output workspace output)) + group outputs)) + groups)) + +(define (workspace-groups-init) + ;; pin workspaces to output + (pin-workspaces-to-output GROUPS OUTPUTS) + (add-hook! sway-workspace-hook workspace-changed)) diff --git a/sjson/builder.scm b/sjson/builder.scm new file mode 100644 index 0000000..905061a --- /dev/null +++ b/sjson/builder.scm @@ -0,0 +1,280 @@ +;;; (json builder) --- Guile JSON implementation. + +;; Copyright (C) 2013-2020 Aleix Conchillo Flaque +;; Copyright (C) 2015,2016 Jan Nieuwenhuizen +;; +;; This file is part of guile-json. +;; +;; guile-json 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. +;; +;; guile-json 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 guile-json. If not, see https://www.gnu.org/licenses/. + +;;; Commentary: + +;; JSON module for Guile + +;;; Code: + +(define-module (sjson builder) + #:use-module (ice-9 format) + #:use-module (ice-9 textual-ports) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-43) + #:export (scm->json + scm->json-string + scm->json-seq + scm->json-seq-string)) + + +;; +;; Miscellaneuos helpers +;; + +(define (indent-string pretty level) + (if pretty (format #f "~v_" (* 2 level)) "")) + +;; +;; String builder helpers +;; + +(define (unicode->json-string unicode) + (format #f "\\u~4,'0x" unicode)) + +(define (unicode->json-surrogate-pair unicode) + (let* ((u (- unicode #x10000)) + (w1 (+ #xD800 (ash u -10))) + (w2 (+ #xDC00 (logand u #x3ff)))) + (string-append (unicode->json-string w1) + (unicode->json-string w2)))) + +(define (build-json-unicode c) + (let* ((value (char->integer c))) + (cond + ((< value 32) + (unicode->json-string value)) + ((<= value 255) + (string c)) + ((<= value #xFFFF) + (unicode->json-string value)) + ((<= value #x10FFFF) + (unicode->json-surrogate-pair value)) + (else (throw 'json-invalid (string c)))))) + +(define (->string x) + (cond ((char? x) (make-string 1 x)) + ((number? x) (number->string x)) + ((symbol? x) (symbol->string x)) + (else x))) + +(define (build-string c port solidus unicode) + (case c + ((#\" #\\) (format port "\\~c" c)) + ((#\bs) (put-string port "\\b")) + ((#\ff) (put-string port "\\f")) + ((#\lf) (put-string port "\\n")) + ((#\cr) (put-string port "\\r")) + ((#\ht) (put-string port "\\t")) + ((#\/) (if solidus + (put-string port "\\/") + (put-char port c))) + (else (if unicode + (put-string port (build-json-unicode c)) + (put-char port c))))) + +(define (json-build-string scm port solidus unicode) + (put-string port "\"") + (for-each (lambda (c) (build-string c port solidus unicode)) + (string->list (->string scm))) + (put-string port "\"")) + +;; +;; Object builder functions +;; + +(define (build-object-pair p port solidus unicode null pretty level) + (put-string port (indent-string pretty level)) + (json-build-string (car p) port solidus unicode) + (put-string port ":") + (build-space port pretty) + (json-build (cdr p) port solidus unicode null pretty level)) + +(define (build-newline port pretty) + (cond (pretty (newline port)))) + +(define (build-space port pretty) + (cond (pretty (put-string port " ")))) + +(define (json-build-object scm port solidus unicode null pretty level) + (put-string port "{") + (let ((pairs scm)) + (unless (null? pairs) + (build-newline port pretty) + (build-object-pair (car pairs) port solidus unicode null pretty (+ level 1)) + (for-each (lambda (p) + (put-string port ",") + (build-newline port pretty) + (build-object-pair p port solidus unicode null pretty (+ level 1))) + (cdr pairs)) + (build-newline port pretty) + (put-string port (indent-string pretty level)))) + (put-string port "}")) + +;; +;; Array builder functions +;; + +(define (json-build-array scm port solidus unicode null pretty level) + (put-string port "[") + (unless (or (null? scm) (zero? (vector-length scm))) + (build-newline port pretty) + (vector-for-each (lambda (i v) + (cond + ((> i 0) + (put-string port ",") + (build-newline port pretty))) + (put-string port (indent-string pretty (+ level 1))) + (json-build v port solidus unicode null pretty (+ level 1))) + scm) + (build-newline port pretty) + (put-string port (indent-string pretty level))) + (put-string port "]")) + +;; +;; Booleans, null and number builder functions +;; + +(define (json-build-boolean scm port) + (put-string port (if scm "true" "false"))) + +(define (json-build-null port) + (put-string port "null")) + +(define (json-build-number scm port) + (if (and (rational? scm) (not (integer? scm))) + (put-string port (number->string (exact->inexact scm))) + (put-string port (number->string scm)))) + +;; +;; Main builder functions +;; + +(define (json-number? number) + (and (number? number) (eqv? (imag-part number) 0) (finite? number))) + +(define (json-key? scm) + (or (symbol? scm) (string? scm))) + +(define (json-valid? scm null) + (cond + ((eq? scm null) #t) + ((boolean? scm) #t) + ((json-number? scm) #t) + ((symbol? scm) #t) + ((string? scm) #t) + ((vector? scm) (vector-every (lambda (elem) (json-valid? elem null)) scm)) + ((pair? scm) + (every (lambda (entry) + (and (pair? entry) + (json-key? (car entry)) + (json-valid? (cdr entry) null))) + scm)) + ((null? scm) #t) + (else (throw 'json-invalid scm)))) + +(define (json-build scm port solidus unicode null pretty level) + (cond + ((eq? scm null) (json-build-null port)) + ((boolean? scm) (json-build-boolean scm port)) + ((json-number? scm) (json-build-number scm port)) + ((symbol? scm) (json-build-string (symbol->string scm) port solidus unicode)) + ((string? scm) (json-build-string scm port solidus unicode)) + ((vector? scm) (json-build-array scm port solidus unicode null pretty level)) + ((or (pair? scm) (null? scm)) + (json-build-object scm port solidus unicode null pretty level)) + (else (throw 'json-invalid scm)))) + +;; +;; Public procedures +;; + +(define* (scm->json scm + #:optional (port (current-output-port)) + #:key + (solidus #f) (unicode #f) (null 'null) + (validate #t) (pretty #f)) + "Creates a JSON document from native. The argument @var{scm} contains the +native value of the JSON document. Takes one optional argument, @var{port}, +which defaults to the current output port where the JSON document will be +written. It also takes a few keyword arguments: @{solidus}: if true, the +slash (/ solidus) character will be escaped (defaults to false), @{unicode}: +if true, unicode characters will be escaped when needed (defaults to false), +@{null}: value for JSON's null (defaults to the 'null symbol), @{validate} : +if true, the native value will be validated before starting to print the JSON +document (defaults to true) and @{pretty}: if true, the JSON document will be +pretty printed (defaults to false). + +Note that when using alists to build JSON objects, symbols or numbers might be +used as keys and they both will be converted to strings. +" + (cond + ((and validate (json-valid? scm null)) + (json-build scm port solidus unicode null pretty 0)) + (else + (json-build scm port solidus unicode null pretty 0)))) + +(define* (scm->json-string scm #:key + (solidus #f) (unicode #f) (null 'null) + (validate #t) (pretty #f)) + "Creates a JSON document from native into a string. The argument @var{scm} +contains the native value of the JSON document. It also takes a few keyword +arguments: @{solidus}: if true, the slash (/ solidus) character will be +escaped (defaults to false), @{unicode}: if true, unicode characters will be +escaped when needed (defaults to false), @{null}: value for JSON's +null (defaults to the 'null symbol), @{validate} : if true, the native value +will be validated before starting to print the JSON document (defaults to +true) and @{pretty}: if true, the JSON document will be pretty +printed (defaults to false). + +Note that when using alists to build JSON objects, symbols or numbers might be +used as keys and they both will be converted to strings. +" + (call-with-output-string + (lambda (p) + (scm->json scm p + #:solidus solidus #:unicode unicode #:null null + #:pretty pretty #:validate validate)))) + +(define* (scm->json-seq objects #:optional (port (current-output-port)) + #:key (null 'null) (solidus #f) (validate #t)) + "Create a JSON text sequence from native @var{objects} and write it. +The optional argument @var{port} specifies the output port, which defaults to +the current output port. This procedure also takes a subset of +@code{json->scm} keyword arguments - @{null}, @{solidus} and @{validate}. +@{unicode} and @{pretty} are unsupported because RFC 7464 requires JSON text +sequences to be written in UTF-8, one per line." + (define (put-entry object) + (put-char port #\rs) + (scm->json object port + #:unicode #t #:null null #:solidus solidus #:validate validate) + (put-char port #\lf)) + (for-each put-entry objects)) + +(define* (scm->json-seq-string objects + #:key (null 'null) (solidus #f) (validate #t)) + "Create a JSON text sequence from native @var{objects} and return it. +This procedure takes the same keyword arguments as @code{scm->json-seq}." + (call-with-output-string + (lambda (port) + (scm->json-seq objects port + #:null null #:solidus solidus #:validate validate)))) + +;;; (json builder) ends here diff --git a/sjson/parser.scm b/sjson/parser.scm new file mode 100644 index 0000000..72e8464 --- /dev/null +++ b/sjson/parser.scm @@ -0,0 +1,490 @@ +;;; (json parser) --- Guile JSON implementation. + +;; Copyright (C) 2013-2020 Aleix Conchillo Flaque +;; +;; This file is part of guile-json. +;; +;; guile-json 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. +;; +;; guile-json 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 guile-json. If not, see https://www.gnu.org/licenses/. + +;;; Commentary: + +;; JSON module for Guile + +;;; Code: + +(define-module (sjson parser) + #:use-module (ice-9 rdelim) + #:use-module (ice-9 streams) + #:use-module (rnrs io ports) + #:export (json->scm + json-string->scm + json-seq->scm + json-seq-string->scm)) + +;; +;; Miscellaneuos helpers +;; + +(define (json-exception port) + (throw 'json-invalid port)) + +(define (digit? c) + (case c + ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #t) + (else #f))) + +(define (whitespace? c) + (case c + ((#\sp #\ht #\lf #\cr) #t) + (else #f))) + +(define (control-char? ch) + (<= (char->integer ch) #x1F)) + +(define (skip-whitespaces port) + (let ((ch (peek-char port))) + (cond + ((whitespace? ch) + (read-char port) + (skip-whitespaces port)) + (else *unspecified*)))) + +(define (expect-string port expected return) + (let loop ((n 0)) + (cond + ;; All characters match. + ((= n (string-length expected)) return) + ;; Go to next characters. + ((eqv? (read-char port) (string-ref expected n)) + (loop (+ n 1))) + ;; Anything else is an error. + (else (json-exception port))))) + +(define (expect-delimiter port delimiter) + (let ((ch (read-char port))) + (cond + ((not (eqv? ch delimiter)) (json-exception port)) + ;; Unexpected EOF. + ((eof-object? ch) (json-exception port))))) + +(define (skip-record-separators port) + (when (eqv? #\rs (peek-char port)) + (read-char port) + (skip-record-separators port))) + +;; +;; Number parsing helpers +;; + +(define (expect-digit port) + (let ((ch (peek-char port))) + (cond + ((not (digit? ch)) (json-exception port)) + ;; Unexpected EOF. + ((eof-object? ch) (json-exception port))))) + +;; Read + or -, and return 1 or -1 respectively. If something different is +;; found, return 1. +(define (read-sign port) + (let ((ch (peek-char port))) + (cond + ((eqv? ch #\+) + (read-char port) + 1) + ((eqv? ch #\-) + (read-char port) + -1) + (else 1)))) + +(define (read-digit-value port) + (let ((ch (read-char port))) + (cond + ((eqv? ch #\0) 0) + ((eqv? ch #\1) 1) + ((eqv? ch #\2) 2) + ((eqv? ch #\3) 3) + ((eqv? ch #\4) 4) + ((eqv? ch #\5) 5) + ((eqv? ch #\6) 6) + ((eqv? ch #\7) 7) + ((eqv? ch #\8) 8) + ((eqv? ch #\9) 9) + (else (json-exception port))))) + +;; Read digits [0..9]. +(define (read-digits port) + (expect-digit port) + (let loop ((ch (peek-char port)) (number 0)) + (cond + ((digit? ch) + (let ((value (read-digit-value port))) + (loop (peek-char port) (+ (* number 10) value)))) + (else number)))) + +(define (read-digits-fraction port) + (expect-digit port) + (let loop ((ch (peek-char port)) (number 0) (length 0)) + (cond + ((digit? ch) + (let ((value (read-digit-value port))) + (loop (peek-char port) (+ (* number 10) value) (+ length 1)))) + (else + (/ number (expt 10 length)))))) + +(define (read-exponent port) + (let ((ch (peek-char port))) + (cond + ((or (eqv? ch #\e) (eqv? ch #\E)) + (read-char port) + (let ((sign (read-sign port)) + (digits (read-digits port))) + (if (<= digits 1000) ;; Some maximum exponent. + (expt 10 (* sign digits)) + (json-exception port)))) + (else 1)))) + +(define (read-fraction port) + (let ((ch (peek-char port))) + (cond + ((eqv? ch #\.) + (read-char port) + (read-digits-fraction port)) + (else 0)))) + +(define (read-positive-number port) + (let* ((number + (let ((ch (peek-char port))) + (cond + ;; Numbers that start with 0 must be a fraction. + ((eqv? ch #\0) + (read-char port) + 0) + ;; Otherwise read more digits. + (else (read-digits port))))) + (fraction (read-fraction port)) + (exponent (read-exponent port)) + (result (* (+ number fraction) exponent))) + (if (and (zero? fraction) (>= exponent 1)) + result + (exact->inexact result)))) + +(define (json-read-number port) + (let ((ch (peek-char port))) + (cond + ;; Negative numbers. + ((eqv? ch #\-) + (read-char port) + (expect-digit port) + (* -1 (read-positive-number port))) + ;; Positive numbers. + ((digit? ch) + (read-positive-number port)) + ;; Anything else is an error. + (else (json-exception port))))) + +;; +;; Object parsing helpers +;; + +(define (read-pair port null ordered) + ;; Read key. + (let ((key (json-read-string port))) + (skip-whitespaces port) + (let ((ch (peek-char port))) + (cond + ;; Skip colon and read value. + ((eqv? ch #\:) + (read-char port) + (cons key (json-read port null ordered))) + ;; Anything other than colon is an error. + (else (json-exception port)))))) + +(define (uniquify-keys pairs res) + (cond ((null? pairs) res) + ((assoc (caar pairs) res) + (uniquify-keys (cdr pairs) res)) + (else (uniquify-keys (cdr pairs) (cons (car pairs) res))))) + +(define (json-read-object port null ordered) + (expect-delimiter port #\{) + (let loop ((pairs '()) (added #t)) + (skip-whitespaces port) + (let ((ch (peek-char port))) + (cond + ;; End of object. + ((eqv? ch #\}) + (read-char port) + (cond + (added (if ordered + (uniquify-keys pairs '()) + (reverse! (uniquify-keys pairs '())))) + (else (json-exception port)))) + ;; Read one pair and continue. + ((eqv? ch #\") + (let ((pair (read-pair port null ordered))) + (loop (cons pair pairs) #t))) + ;; Skip comma and read more pairs. + ((eqv? ch #\,) + (read-char port) + (cond + (added (loop pairs #f)) + (else (json-exception port)))) + ;; Invalid object. + (else (json-exception port)))))) + +;; +;; Array parsing helpers +;; + +(define (json-read-array port null ordered) + (expect-delimiter port #\[) + (skip-whitespaces port) + (cond + ;; Special case when array is empty. + ((eqv? (peek-char port) #\]) + (read-char port) + #()) + (else + ;; Read first element in array. + (let loop ((values (list (json-read port null ordered)))) + (skip-whitespaces port) + (let ((ch (peek-char port))) + (cond + ;; Unexpected EOF. + ((eof-object? ch) (json-exception port)) + ;; Handle comma (if there's a comma there should be another element). + ((eqv? ch #\,) + (read-char port) + (loop (cons (json-read port null ordered) values))) + ;; End of array. + ((eqv? ch #\]) + (read-char port) + (list->vector (reverse! values))) + ;; Anything else other than comma and end of array is wrong. + (else (json-exception port)))))))) + +;; +;; String parsing helpers +;; + +(define (read-hex-digit->integer port) + (let ((ch (read-char port))) + (cond + ((eqv? ch #\0) 0) + ((eqv? ch #\1) 1) + ((eqv? ch #\2) 2) + ((eqv? ch #\3) 3) + ((eqv? ch #\4) 4) + ((eqv? ch #\5) 5) + ((eqv? ch #\6) 6) + ((eqv? ch #\7) 7) + ((eqv? ch #\8) 8) + ((eqv? ch #\9) 9) + ((or (eqv? ch #\A) (eqv? ch #\a)) 10) + ((or (eqv? ch #\B) (eqv? ch #\b)) 11) + ((or (eqv? ch #\C) (eqv? ch #\c)) 12) + ((or (eqv? ch #\D) (eqv? ch #\d)) 13) + ((or (eqv? ch #\E) (eqv? ch #\e)) 14) + ((or (eqv? ch #\F) (eqv? ch #\f)) 15) + (else (json-exception port))))) + +(define (read-unicode-value port) + (+ (* 4096 (read-hex-digit->integer port)) + (* 256 (read-hex-digit->integer port)) + (* 16 (read-hex-digit->integer port)) + (read-hex-digit->integer port))) + +;; Unicode codepoint with surrogates is: +;; 10000 + (high - D800) + (low - DC00) +;; which is equivalent to: +;; (high << 10) + low - 35FDC00 +;; see +;; https://github.com/aconchillo/guile-json/issues/58#issuecomment-662744070 +(define (json-surrogate-pair->unicode high low) + (+ (* high #x400) low #x-35FDC00)) + +(define (read-unicode-char port) + (let ((codepoint (read-unicode-value port))) + (cond + ;; Surrogate pairs. `codepoint` already contains the higher surrogate + ;; (between D800 and DC00) . At this point we are expecting another + ;; \uXXXX that holds the lower surrogate (between DC00 and DFFF). + ((and (>= codepoint #xD800) (< codepoint #xDC00)) + (expect-string port "\\u" #f) + (let ((low-surrogate (read-unicode-value port))) + (if (and (>= low-surrogate #xDC00) (< low-surrogate #xE000)) + (integer->char (json-surrogate-pair->unicode codepoint low-surrogate)) + (json-exception port)))) + ;; Reserved for surrogates (we just need to check starting from the low + ;; surrogates). + ((and (>= codepoint #xDC00) (< codepoint #xE000)) + (json-exception port)) + (else (integer->char codepoint))))) + +(define (read-control-char port) + (let ((ch (read-char port))) + (cond + ((eqv? ch #\") #\") + ((eqv? ch #\\) #\\) + ((eqv? ch #\/) #\/) + ((eqv? ch #\b) #\bs) + ((eqv? ch #\f) #\ff) + ((eqv? ch #\n) #\lf) + ((eqv? ch #\r) #\cr) + ((eqv? ch #\t) #\ht) + ((eqv? ch #\u) (read-unicode-char port)) + (else (json-exception port))))) + +(define (json-read-string port) + (expect-delimiter port #\") + (let loop ((chars '()) (ch (read-char port))) + (cond + ;; Unexpected EOF. + ((eof-object? ch) (json-exception port)) + ;; Unescaped control characters are not allowed. + ((control-char? ch) (json-exception port)) + ;; End of string. + ((eqv? ch #\") (reverse-list->string chars)) + ;; Escaped characters. + ((eqv? ch #\\) + (loop (cons (read-control-char port) chars) (read-char port))) + ;; All other characters. + (else + (loop (cons ch chars) (read-char port)))))) + +;; +;; Booleans and null parsing helpers +;; + +(define (json-read-true port) + (expect-string port "true" #t)) + +(define (json-read-false port) + (expect-string port "false" #f)) + +(define (json-read-null port null) + (expect-string port "null" null)) + +;; +;; Main parser functions +;; + +(define (json-read port null ordered) + (skip-whitespaces port) + (let ((ch (peek-char port))) + (cond + ;; Unexpected EOF. + ((eof-object? ch) (json-exception port)) + ;; Read JSON values. + ((eqv? ch #\t) (json-read-true port)) + ((eqv? ch #\f) (json-read-false port)) + ((eqv? ch #\n) (json-read-null port null)) + ((eqv? ch #\{) (json-read-object port null ordered)) + ((eqv? ch #\[) (json-read-array port null ordered)) + ((eqv? ch #\") (json-read-string port)) + ;; Anything else should be a number. + (else (json-read-number port))))) + +;; +;; Public procedures +;; + +(define* (json->scm #:optional (port (current-input-port)) + #:key (null 'null) (ordered #f) (concatenated #f)) + "Parse a JSON document into native. Takes one optional argument, +@var{port}, which defaults to the current input port from where the JSON +document is read. It also takes a few of keyword arguments: @{null}: value for +JSON's null, it defaults to the 'null symbol, @{ordered} to indicate whether +JSON objects order should be preserved or not (the default) and @{concatenated} +which can be used to tell the parser that more JSON documents might come after a +properly parsed document." + (let loop ((value (json-read port null ordered))) + ;; Skip any trailing whitespaces. + (skip-whitespaces port) + (cond + ;; If we reach the end the parsing succeeded. + ((eof-object? (peek-char port)) value) + ;; If there's anything else other than the end, check if user wants to keep + ;; parsing concatenated valid JSON documents, otherwise parser fails. + (else + (cond (concatenated value) + (else (json-exception port))))))) + +(define* (json-string->scm str #:key (null 'null) (ordered #f)) + "Parse a JSON document into native. Takes a string argument, +@var{str}, that contains the JSON document. It also takes a couple of keyword +argument: @{null}: value for JSON's null, it defaults to the 'null symbol and +@{ordered} to indicate whether JSON objects order should be preserved or +not (the default)." + (call-with-input-string str (lambda (p) (json->scm p #:null null #:ordered ordered)))) + +(define* (json-seq->scm #:optional (port (current-input-port)) + #:key (null 'null) (ordered #f) + (handle-truncate 'skip) (truncated-object 'truncated)) + "Lazy parse a JSON text sequence from the port @var{port}. +This procedure returns a stream of parsed documents. The optional argument +@var{port} defines the port to read from and defaults to the current input +port. It also takes a few keyword arguments: @{null}: value for JSON's null +(defaults to the 'null symbol), @{ordered} to indicate whether JSON objects +order should be preserved or not (the default), @{handle-truncate}: defines how +to handle data loss, @{truncated-object}: used to replace unparsable +objects. Allowed values for @{handle-truncate} argument are 'throw (throw an +exception), 'stop (stop parsing and end the stream), 'skip (default, skip +corrupted fragment and return the next entry), 'replace (skip corrupted fragment +and return @{truncated-object} instead)." + (letrec ((handle-truncation + (case handle-truncate + ((throw) json-exception) + ((stop) (const (eof-object))) + ((skip) + (lambda (port) + (read-delimited "\x1e" port 'peek) + (read-entry port))) + ((replace) + (lambda (port) + (read-delimited "\x1e" port 'peek) + truncated-object)))) + (read-entry + (lambda (port) + (let ((ch (read-char port))) + (cond + ((eof-object? ch) ch) + ((not (eqv? ch #\rs)) + (handle-truncation port)) + (else + (skip-record-separators port) + (catch 'json-invalid + (lambda () + (let ((next (json-read port null ordered))) + (if (eqv? #\lf (peek-char port)) + (begin + (read-char port) + next) + (handle-truncation port)))) + (lambda (_ port) + (handle-truncation port))))))))) + (port->stream port read-entry))) + +(define* (json-seq-string->scm str #:key (null 'null) (ordered #f) + (handle-truncate 'skip) (truncated-object 'truncated)) + "Lazy parse a JSON text sequence from the string @var{str}. +This procedure returns a stream of parsed documents and also takes the same +keyword arguments as @code{json-seq->scm}." + (call-with-input-string str + (lambda (p) + (json-seq->scm p #:null null #:ordered ordered + #:handle-truncate handle-truncate + #:truncated-object truncated-object)))) + +;;; (json parser) ends here diff --git a/sjson/record.scm b/sjson/record.scm new file mode 100644 index 0000000..2751c17 --- /dev/null +++ b/sjson/record.scm @@ -0,0 +1,230 @@ +;;; (json record) --- Guile JSON implementation. + +;; Copyright (C) 2020-2021 Aleix Conchillo Flaque +;; Copyright (C) 2018, 2019 Ludovic Courtès +;; +;; This file is part of guile-json. +;; +;; guile-json 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. +;; +;; guile-json 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 guile-json. If not, see https://www.gnu.org/licenses/. + +;;; Commentary: + +;; JSON module for Guile + +;; The initial code of this file was copied from GNU Guix: +;; http://git.savannah.gnu.org/cgit/guix.git/tree/guix/json.scm + +;;; Code: + +(define-module (sjson record) + #:use-module (sjson builder) + #:use-module (sjson parser) + #:use-module (srfi srfi-9) + #:export (<=> define-json-mapping define-json-type)) + +(define <=> '<=>) + +(define-syntax-rule (define-json-reader json->record ctor spec ...) + "Define JSON->RECORD as a procedure that converts a JSON representation, +read from a port, string, or alist, into a record created by CTOR and following +SPEC, a series of field specifications." + (define (json->record input) + (let ((table (cond ((port? input) + (json->scm input)) + ((string? input) + (json-string->scm input)) + ;; This allows to pass native values. + ((or (null? input) (pair? input)) + input)))) + (let-syntax ((extract-field (syntax-rules () + ((_ table (field key scm->value value->scm)) + (scm->value (if (and (pair? (assoc key table)) (not (equal? 'null (cdr (assoc key table))))) + (cdr (assoc key table)) *unspecified*))) + ((_ table (field key scm->value)) + (scm->value (if (and (pair? (assoc key table)) (not (equal? 'null (cdr (assoc key table))))) + (cdr (assoc key table)) *unspecified*))) + ((_ table (field key)) + (if (and (pair? (assoc key table)) (not (equal? 'null (cdr (assoc key table))))) + (cdr (assoc key table)) *unspecified*)) + ((_ table (field)) + (if (pair? (assoc (symbol->string 'field) table)) (cdr (assoc (symbol->string 'field) table)) *unspecified*))))) + (ctor (extract-field table spec) ...))))) + +(define-syntax-rule (define-json-writer record->json spec ...) + "Define RECORD->JSON as a procedure that converts a RECORD into its JSON +representation following SPEC, a series of field specifications." + (define (record->json record) + (let-syntax ((extract-field (syntax-rules () + ((_ (field getter key scm->value value->scm)) + (cons key (if (unspecified? (getter record)) *unspecified* (value->scm (getter record))))) + ((_ (field getter key scm->value)) + (cons key (getter record))) + ((_ (field getter key)) + (cons key (getter record))) + ((_ (field getter)) + (cons (symbol->string 'field) (getter record)))))) + (let* ((full-object `(,(extract-field spec) ...)) + (object (filter (lambda (p) (not (unspecified? (cdr p)))) + full-object))) + (scm->json-string object))))) + +(define-syntax-rule (define-native-reader scm->record ctor spec ...) + "Define SCM->RECORD as a procedure that converts an alist into a record +created by CTOR and following SPEC, a series of field specifications." + (define (scm->record table) + (let-syntax ((extract-field (syntax-rules () + ((_ table (field key scm->value value->scm)) + (scm->value (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*))) + ((_ table (field key scm->value)) + (scm->value (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*))) + ((_ table (field key)) + (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*)) + ((_ table (field)) + (if (pair? (assoc (symbol->string 'field) table)) (cdr (assoc (symbol->string 'field) table)) *unspecified*))))) + (ctor (extract-field table spec) ...)))) + +(define-syntax-rule (define-native-writer record->scm spec ...) + "Define RECORD->SCM as a procedure that converts a RECORD into it an alist +representation following SPEC, a series of field specifications." + (define (record->scm record) + (let-syntax ((extract-field (syntax-rules () + ((_ (field getter key scm->value value->scm)) + (cons key (if (unspecified? (getter record)) *unspecified* (value->scm (getter record))))) + ((_ (field getter key scm->value)) + (cons key (getter record))) + ((_ (field getter key)) + (cons key (getter record))) + ((_ (field getter)) + (cons (symbol->string 'field) (getter record)))))) + (let ((full-object `(,(extract-field spec) ...))) + (filter (lambda (p) (not (unspecified? (cdr p)))) full-object))))) + +(define-syntax define-json-mapping + (syntax-rules (<=>) + "Define RTD as a record type with the given FIELDs and GETTERs, à la SRFI-9, +and define JSON->RECORD as a conversion from JSON (from a port, string or alist) +to a record of this type. Optionally, define RECORD->JSON as a conversion from a +record of this type to a JSON string. Additionally, define SCM->RECORD as a +conversion from an alist to a record of this type (equivalent to JSON->RECORD +when passing an alist) and RECORD->SCM as a conversion from a record of this +type to an alist." + ((_ rtd ctor pred json->record (field getter spec ...) ...) + (begin + (define-record-type rtd + (ctor field ...) + pred + (field getter) ...) + + (define-json-reader json->record ctor + (field spec ...) ...))) + ((_ rtd ctor pred json->record <=> record->json (field getter spec ...) ...) + (begin + (define-record-type rtd + (ctor field ...) + pred + (field getter) ...) + + (define-json-reader json->record ctor + (field spec ...) ...) + + (define-json-writer record->json + (field getter spec ...) ...))) + ((_ rtd ctor pred json->record <=> record->json <=> scm->record <=> record->scm (field getter spec ...) ...) + (begin + (define-record-type rtd + (ctor field ...) + pred + (field getter) ...) + + (define-json-reader json->record ctor + (field spec ...) ...) + + (define-json-writer record->json + (field getter spec ...) ...) + + (define-native-reader scm->record ctor + (field spec ...) ...) + + (define-native-writer record->scm + (field getter spec ...) ...))))) + +(define-syntax define-json-type + (lambda (x) + "Define RTD as a record type with the given FIELDs. This will automatically +define a record and its constructor, predicate and fields with their getters as +they would be defined by define-json-mapping." + (define (gen-id template-id . args) + (datum->syntax + template-id + (string->symbol + (apply string-append + (map (lambda (x) + (if (string? x) x (symbol->string (syntax->datum x)))) + args))))) + (define (cleanup-single-rtd template-id) + (datum->syntax + template-id + (string->symbol + (string-delete + (lambda (c) (or (eq? c #\<) (eq? c #\>))) + (symbol->string (syntax->datum template-id)))))) + (define (cleanup-vector-rtd template-id) + (cleanup-single-rtd (datum->syntax template-id (vector-ref (syntax->datum template-id) 0)))) + + (define (cleanup-rtd template-id) + (if (vector? (syntax->datum template-id)) + (cleanup-vector-rtd template-id) + (cleanup-single-rtd template-id))) + (syntax-case x (<=>) + ((_ rtd field ...) + (with-syntax ((mapping-rtd #'rtd) + (constructor (gen-id #'rtd "make-" (cleanup-rtd #'rtd))) + (predicate (gen-id #'rtd (cleanup-rtd #'rtd) "?")) + (json->record (gen-id #'rtd "json->" (cleanup-rtd #'rtd))) + (record->json (gen-id #'rtd (cleanup-rtd #'rtd) "->json")) + (scm->record (gen-id #'rtd "scm->" (cleanup-rtd #'rtd))) + (record->scm (gen-id #'rtd (cleanup-rtd #'rtd) "->scm")) + ((fields ...) + (map + (lambda (f) + (syntax-case f () + ((name) + #`(name #,(gen-id #'rtd (cleanup-rtd #'rtd) "-" #'name))) + ((name key) + #`(name #,(gen-id #'rtd (cleanup-rtd #'rtd) "-" #'name) key)) + ((name key field-rtd) + #`(name + #,(gen-id #'rtd (cleanup-rtd #'rtd) "-" #'name) + key + #,(if (vector? (syntax->datum #'field-rtd)) + #`(lambda (v) (if (unspecified? v) + *unspecified* + (map #,(gen-id #'field-rtd "scm->" (cleanup-rtd #'field-rtd)) + (vector->list v)))) + #`(lambda (v) (if (unspecified? v) + *unspecified* + (#,(gen-id #'field-rtd "scm->" (cleanup-rtd #'field-rtd)) v)))) + #,(if (vector? (syntax->datum #'field-rtd)) + #`(lambda (v) + (list->vector + (map #,(gen-id #'field-rtd (cleanup-rtd #'field-rtd) "->scm") v))) + (gen-id #'field-rtd (cleanup-rtd #'field-rtd) "->scm" )))))) + #'(field ...)))) + #'(define-json-mapping mapping-rtd + constructor + predicate + json->record <=> record->json <=> scm->record <=> record->scm + fields ...)))))) + +;;; (json record) ends here diff --git a/swayipc/connection.scm b/swayipc/connection.scm new file mode 100755 index 0000000..ae837db --- /dev/null +++ b/swayipc/connection.scm @@ -0,0 +1,201 @@ +(define-module (swayipc connection) + #:use-module (ice-9 popen) + #:use-module (ice-9 binary-ports) + #:use-module (ice-9 hash-table) + #:use-module (rnrs bytevectors) + #:use-module (rnrs io ports) + #:use-module (oop goops) + #:use-module (srfi srfi-18) + #:use-module (srfi srfi-9) + #:use-module (srfi srfi-1) + + #:export (RUN-COMMMAND-MSG-ID + GET-WORKSPACES-MSG-ID + SUBSCRIBE-MSG-ID + GET-OUTPUTS-MSG-ID + GET-TREE-MSG-ID + GET-MARKS-MSG-ID + GET-BAR-CONFIG-MSG-ID + GET-VERSION-MSG-ID + GET-BINDING-MODES-MSG-ID + GET-CONFIG-MSG-ID + SEND-TICK-MSG-ID + SYNC-MSG-ID + GET-BINDING-STATE-MSG-ID + GET-INPUTS-MSG-ID + GET-SEATS-MSG-ID + + WORKSPACE-EVENT-REPLY + OUTPUT-EVENT-REPLY + MODE-EVENT-REPLY + WINDOW-EVENT-REPLY + BAR-CONFIG-UPDATE-EVENT-REPLY + BINDING-EVENT-REPLY + SHUTDOWN-EVENT-REPLY + TICK-EVENT-REPLY + BAR-STATE-UPDATE-EVENT-REPLY + INPUT-EVENT-REPLY + + SOCKET-PATH + COMMAND-SOCKET + LISTENER-SOCKET + LISTENER-THREAD + MSG-MAGIC + MSG-MAGIC-BV + start-event-listener-thread + start-event-listener + data-received-hook + command-received-hook + + SOCKET-COMMANDS-LISTENER-PATH + COMMANDS-LISTENER-SOCKET + COMMANDS-LISTENER-THREAD + start-commands-listener-thread + start-commands-listener + + write-msg + read-msg + encode-msg)) + +;; sway messages and replies types +;; man: sway-ipc(7): MESSAGES AND REPLIES +(define RUN-COMMMAND-MSG-ID 0) +(define GET-WORKSPACES-MSG-ID 1) +(define SUBSCRIBE-MSG-ID 2) +(define GET-OUTPUTS-MSG-ID 3) +(define GET-TREE-MSG-ID 4) +(define GET-MARKS-MSG-ID 5) +(define GET-BAR-CONFIG-MSG-ID 6) +(define GET-VERSION-MSG-ID 7) +(define GET-BINDING-MODES-MSG-ID 8) +(define GET-CONFIG-MSG-ID 9) +(define SEND-TICK-MSG-ID 10) +(define SYNC-MSG-ID 11) +(define GET-BINDING-STATE-MSG-ID 12) +(define GET-INPUTS-MSG-ID 100) +(define GET-SEATS-MSG-ID 101) + +(define WORKSPACE-EVENT-REPLY 2147483648) +(define OUTPUT-EVENT-REPLY 2147483649) +(define MODE-EVENT-REPLY 2147483650) +(define WINDOW-EVENT-REPLY 2147483651) +(define BAR-CONFIG-UPDATE-EVENT-REPLY 2147483652) +(define BINDING-EVENT-REPLY 2147483653) +(define SHUTDOWN-EVENT-REPLY 2147483654) +(define TICK-EVENT-REPLY 2147483655) +(define BAR-STATE-UPDATE-EVENT-REPLY 2147483656) +(define INPUT-EVENT-REPLY 2147483657) + +(define LISTENER-THREAD #:f) +(define COMMANDS-LISTENER-THREAD #:f) +(define MSG-MAGIC "i3-ipc") +(define MSG-MAGIC-BV (string->utf8 MSG-MAGIC)) + +;; TODO: maybe also get from sway and i3 binaries +(define SOCKET-PATH + (and (getenv "SWAYSOCK") + (getenv "I3SOCK"))) + +(define SOCKET-COMMANDS-LISTENER-PATH + (string-append (dirname SOCKET-PATH) "/sway-commands-ipc.sock")) + +(define COMMAND-SOCKET (socket AF_UNIX SOCK_STREAM 0)) +(connect COMMAND-SOCKET (make-socket-address AF_UNIX SOCKET-PATH)) +(define LISTENER-SOCKET (socket AF_UNIX SOCK_STREAM 0)) +(connect LISTENER-SOCKET (make-socket-address AF_UNIX SOCKET-PATH)) +(define COMMANDS-LISTENER-SOCKET (socket AF_UNIX SOCK_STREAM 0)) + +;; is i3-ipc, for compatibility with i3 +;; is a 32-bit integer in native byte order +;; is a 32-bit integer in native byte order +(define (encode-msg command-id payload) + (let* ((bv (make-bytevector (+ 14 (string-length payload))))) + ;; + (bytevector-copy! (string->utf8 "i3-ipc") 0 bv 0 6) + (bytevector-u32-set! bv 6 (string-length payload) (native-endianness)) + (bytevector-u32-set! bv 10 command-id (native-endianness)) + + ;; payload is optional + (when (> (string-length payload) 0) + (bytevector-copy! (string->utf8 payload) 0 bv 14 (string-length payload))) + bv)) + +(define (write-msg sock command-id payload) + (put-bytevector sock (encode-msg command-id payload))) + +;; Mutex for synchronization +(define mutex-table (make-hash-table)) + +(define (read-msg sock) + (let* ((mutex (if (hash-get-handle mutex-table (fileno sock)) + (cdr (hash-get-handle mutex-table (fileno sock))) + (hash-set! mutex-table (fileno sock) (make-mutex))))) + (mutex-lock! mutex) + (let* ((bv-header (get-bytevector-n sock 14)) + (payload-length (bytevector-u32-ref bv-header 6 (native-endianness))) + (command-id (bytevector-u32-ref bv-header 10 (native-endianness))) + (payload (utf8->string (get-bytevector-n sock payload-length)))) + (mutex-unlock! mutex) + (list command-id (or payload ""))))) + +(define (read-from-socket sock) + (let loop () + (let ((data (read-msg sock))) + (run-hook data-received-hook + (list-ref data 0) + (list-ref data 1)) + (loop)))) + +(define data-received-hook + ;; data received: emitted on new data received via ipc. + + ;; Parameters: + ;; - arg1: command-id. + ;; - arg2: payload. + (make-hook 2)) + +(define command-received-hook + ;; data received: emitted on new command received via ipc. + + ;; Parameters: + ;; - arg1: command-id. + ;; - arg2: payload. + (make-hook 2)) + +(define (handle-client client) + (let ((port (car client))) + (let ((data (read-msg port))) + (run-hook command-received-hook + (list-ref data 0) + (list-ref data 1))) + + ;; Close the connection + (close-port port))) + +(define (custom-exception-handler exc) + (display "An error occurred while handling client connection\n")) + +(define (start-server-socket sock) + (listen sock 15) + (let loop () + (let ((client (accept sock))) + (handle-client client) + (loop)))) + +(define (start-event-listener) + (read-from-socket LISTENER-SOCKET)) + +(define (start-event-listener-thread) + (set! LISTENER-THREAD (make-thread start-event-listener)) + (thread-start! LISTENER-THREAD)) + +(define (start-commands-listener) + (when (file-exists? SOCKET-COMMANDS-LISTENER-PATH) + (delete-file SOCKET-COMMANDS-LISTENER-PATH)) + + (bind COMMANDS-LISTENER-SOCKET (make-socket-address AF_UNIX SOCKET-COMMANDS-LISTENER-PATH)) + (start-server-socket COMMANDS-LISTENER-SOCKET)) + +(define (start-commands-listener-thread) + (set! COMMANDS-LISTENER-THREAD (make-thread start-commands-listener)) + (thread-start! COMMANDS-LISTENER-THREAD)) diff --git a/swayipc/dispatcher.scm b/swayipc/dispatcher.scm new file mode 100644 index 0000000..7e6e7dd --- /dev/null +++ b/swayipc/dispatcher.scm @@ -0,0 +1,1495 @@ +(define-module (swayipc dispatcher) + #:use-module (swayipc connection) + #:use-module (swayipc records) + #:use-module (srfi srfi-9) + #:use-module (srfi srfi-1) + #:use-module (sjson parser) + + #:export (SWAY-ORIENTATION-HORIZONTAL + SWAY-ORIENTATION-VERTICAL + SWAY-ORIENTATION-AUTO + sway-default-orientation + sway-include + sway-swaybg-command + sway-swaynag-command + SWAY-LAYOUT-DEFAULT + SWAY-LAYOUT-STAKCING + SWAY-LAYOUT-TABBED + sway-workspace-layout + SWAY-XWAYLAND-ENABLE + SWAY-XWAYLAND-DISABLE + SWAY-XWAYLAND-FORCE + sway-xwayland + SWAY-BORDER-NONE + SWAY-BORDER-NORMAL + SWAY-BORDER-CSD + SWAY-BORDER-PIXEL + sway-border + sway-border-toggle + sway-exit + SWAY-FLOATING-ENABLED + SWAY-FLOATING-DISABLED + SWAY-FLOATING-TOGGLE + sway-floating + sway-focus-container-criteria + SWAY-DIRECTION-UP + SWAY-DIRECTION-RIGHT + SWAY-DIRECTION-DOWN + SWAY-DIRECTION-LEFT + SWAY-SIBLING-NEXT + SWAY-SIBLING-PREV + SWAY-HIERARCHY-CHILD + SWAY-HIERARCHY-PARENT + sway-focus-container + sway-focus-container-sibling + sway-focus-container-child + sway-focus-container-parent + sway-focus-output-direction + sway-focus-output-name + sway-focus-container-tiling + sway-focus-container-floating + SWAY-FULLSCREEN-ENABLED + SWAY-FULLSCREEN-DISABLED + SWAY-FULLSCREEN-TOGGLE + sway-fullscreen + SWAY-GAPS-OPTION-INNER + SWAY-GAPS-OPTION-OUTER + SWAY-GAPS-OPTION-HORIZONTAL + SWAY-GAPS-OPTION-VERTICAL + SWAY-GAPS-OPTION-TOP + SWAY-GAPS-OPTION-RIGHT + SWAY-GAPS-OPTION-BOTTOM + SWAY-GAPS-OPTION-LEFT + SWAY-GAPS-WORKSPACE-ALL + SWAY-GAPS-WORKSPACE-CURRENT + SWAY-GAPS-WORKSPACE-SET + SWAY-GAPS-WORKSPACE-PLUS + SWAY-GAPS-WORKSPACE-MINUS + SWAY-GAPS-WORKSPACE-TOGGLE + sway-gaps + SWAY-INHIBIT-IDLE-FOCUS + SWAY-INHIBIT-IDLE-FULLSCREEN + SWAY-INHIBIT-IDLE-OPEN + SWAY-INHIBIT-IDLE-NONE + SWAY-INHIBIT-IDLE-VISIBLE + sway-inhibit-idle + SWAY-LAYOUT-SPLITH + SWAY-LAYOUT-SPLITV + SWAY-LAYOUT-STACKING + sway-layout + SWAY-LAYOUT-TOGGLE-ALL + SWAY-LAYOUT-TOGGLE-SPLIT + sway-move-container + sway-move-container-absolute-position + sway-move-container-absolute-center + sway-move-container-cursor + sway-move-container-to-mark + SWAY-WORKSPACE-PREVIOUS + SWAY-WORKSPACE-NEXT + SWAY-WORKSPACE-CURRENT + SWAY-WORKSPACE-PREVIOUS-ON-OUTPUT + SWAY-WORKSPACE-NEXT-ON-OUTPUT + SWAY-WORKSPACE-BACK-AND-FORTH + sway-move-container-to-workspace + SWAY-OUTPUT-CURRENT + SWAY-OUTPUT-UP + SWAY-OUTPUT-RIGHT + SWAY-OUTPUT-DOWN + SWAY-OUTPUT-LEFT + sway-move-container-to-output + sway-move-container-to-scratchpad + sway-move-workspace-to-output + sway-reload + sway-rename-workspace + sway-rename-current-workspace + SWAY-RESIZE-TYPE-SHRINK + SWAY-RESIZE-TYPE-GROW-WIDTH + SWAY-RESIZE-TYPE-GROW-HEIGHT + SWAY-SIZE-UNIT-PX + SWAY-SIZE-UNIT-PPT + sway-show-scratchpad + sway-shortcuts-inhibitor + SWAY-SPLIT-VERTICAL + SWAY-SPLIT-HORIZONTAL + SWAY-SPLIT-NONE + SWAY-SPLIT-TOGGLE + sway-split-container + SWAY-STICKY-ENABLE + SWAY-STICKY-DISABLE + SWAY-STICKY-TOGGLE + sway-sticky + sway-title-format + sway-assign-to-workspace + sway-assign-to-output + bindings + sway-client-background + sway-client-focused-tab-title-color + SWAY-BORDER-STYLE-NONE + SWAY-BORDER-STYLE-NORMAL + SWAY-BORDER-STYLE-PIXEL + sway-exec + sway-exec-always + sway-floating-maximum-size + sway-floating-minimum-size + SWAY-FLOATING-MODIFIER-TYPE-NORMAL + SWAY-FLOATING-MODIFIER-TYPE-INVERSE + sway-floating-modifier + SWAY-FOCUS-FOLLOW-MOUSE-FLAG-YES + SWAY-FOCUS-FOLLOW-MOUSE-FLAG-NO + SWAY-FOCUS-FOLLOW-MOUSE-FLAG-ALWAYS + sway-focus-follow-mouse + SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-SMART + SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-URGENT + SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-FOCUS + SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-NONE + sway-focus-on-window-activation + SWAY-FOCUS-WRAPPING-FLAG-YES + SWAY-FOCUS-WRAPPING-FLAG-NO + SWAY-FOCUS-WRAPPING-FLAG-FORCE + SWAY-FOCUS-WRAPPING-FLAG-WORKSPACE + sway-focus-wrapping + sway-force-display-urgency-hint + sway-titlebar-border-thickness + sway-titlebar-padding + sway-for-window + sway-default-gaps + SWAY-EDGE-BORDER-TYPE-NONE + SWAY-EDGE-BORDER-TYPE-VERTICAL + SWAY-EDGE-BORDER-TYPE-HORIZONTAL + SWAY-EDGE-BORDER-TYPE-BOTH + SWAY-EDGE-BORDER-TYPE-SMART + SWAY-EDGE-BORDER-TYPE-SMART-NO-GAPS + sway-input + sway-seat + sway-kill + SWAY-SMART-BORDERS-ON + SWAY-SMART-BORDERS-OFF + SWAY-SMART-BORDERS-NO-GAPS + sway-smart-borders + SWAY-SMART-GAPS-ON + SWAY-SMART-GAPS-OFF + SWAY-SMART-GAPS-TOGGLE + SWAY-SMART-GAPS-INVERSE-OUTER + sway-smart-gaps + sway-mode + sway-mode-subcommand + SWAY-MOUSE-WARPING-OUTPUT + SWAY-MOUSE-WARPING-CONTAINER + SWAY-MOUSE-WARPING-NONE + sway-mouse-warping + sway-no-focus + sway-output + SWAY-POPUP-TYPE-OUTPUTSMART + SWAY-POPUP-TYPE-IGNORE + SWAY-POPUP-TYPE-LEAVE-FULLSCREEN + sway-popup-during-fullscreen + SWAY-PRIMARY-SELECTION-ENABLED + SWAY-PRIMARY-SELECTION-DISABLED + sway-primary-selection + SWAY-SHOW-MARKS-YES + SWAY-SHOW-MARKS-NO + sway-show-marks + SWAY-OPACITY-SET + SWAY-OPACITY-PLUS + SWAY-OPACITY-MINUS + sway-opacity + SWAY-TILING-DRAG-ENABLE + SWAY-TILING-DRAG-DISABLE + SWAY-TILING-DRAG-TOGGLE + sway-tiling-drag + sway-tiling-drag-threshold + SWAY-TILING-ALIGN-LEFT + SWAY-TILING-ALIGN-CENTER + SWAY-TILING-ALIGN-RIGHT + sway-tiling-align + sway-switch-workspace-on-output + sway-switch-workspace + SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-YES + SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-NO + sway-workspace-auto-back-and-forth + sway-workspace-gaps + sway-criteria + dispatch-commands + dispatch-command)) + +(define (custom-exception-handler exc) + (display "An error occurred while dispatching the command\n")) + +(define (catch-all thunk) + (with-exception-handler + (lambda (exn) + (format (current-error-port) + "Uncaught exception: ~s\n" exn) + #f) + thunk + #:unwind? #t)) + +(define (dispatch-command command) + "Parses and runs the payload as sway command. +Parameters: + - a sway command +Response: + An array of objects corresponding to each command that was parsed. Each + object has the property success." + (dispatch-commands command)) + +(define (dispatch-commands . commands) + "Parses and runs the payload as sway commands +Parameters: + - list of sway commands +Response: + An array of objects corresponding to each command that was parsed. Each + object has the property success." + (display "dispatching: ") + (display (string-join commands "\n")) + (newline) + + (catch-all + (lambda () + (begin + ;; write the commands message + (write-msg COMMAND-SOCKET RUN-COMMMAND-MSG-ID (string-join commands " ")) + ;; read response from socket + (map + (lambda (res) + (scm->sway-tick res)) + (vector->list + (json-string->scm + (list-ref (read-msg COMMAND-SOCKET) 1)))))))) + +;; bar [] +;; For details on bar subcommands, see sway-bar(5). + +(define SWAY-ORIENTATION-HORIZONTAL "horizontal") +(define SWAY-ORIENTATION-VERTICAL "vertical") +(define SWAY-ORIENTATION-AUTO "auto") + +(define (sway-default-orientation orientation) + "Sets the default container layout for tiled containers. + parameters: + - orientation: `SWAY-ORIENTATION-HORIZONTAL`, `SWAY-ORIENTATION-VERTICAL`, `SWAY-ORIENTATION-AUTO`" + (dispatch-command + (string-append "default_orientation " orientation))) + +(define (sway-include file-path) + "Includes another configuration file from path (not scheme file). + parameters: + - file-path: string" + (dispatch-command + (string-append "include " file-path))) + +(define (sway-swaybg-command command) + "Executes custom background command. Default is swaybg. + parameters: + - command: string" + (dispatch-command + (string-append "swaybg_command " command))) + +(define (sway-swaynag-command command) + "Executes custom command for swaynag. Default is swaynag. + parameters: + - command: string" + (dispatch-command + (string-append "swaynag_command " command))) + +(define SWAY-LAYOUT-DEFAULT "default") +(define SWAY-LAYOUT-STAKCING "vertical") +(define SWAY-LAYOUT-TABBED "tabbed") + +(define (sway-workspace-layout layout) + "Specifies the initial layout for new containers in an empty workspace. + parameters: + - layout: `SWAY-LAYOUT-DEFAULT`, `SWAY-LAYOUT-STAKCING`, `SWAY-LAYOUT-TABBED`" + (dispatch-command + (string-append "workspace_layout " layout))) + +(define SWAY-XWAYLAND-ENABLE "enable") +(define SWAY-XWAYLAND-DISABLE "disable") +(define SWAY-XWAYLAND-FORCE "force") + +(define (sway-xwayland option) + "Enables or disables Xwayland support, which allows X11 applications to be used. + parameters: + - option: `SWAY-XWAYLAND-ENABLE`, `SWAY-XWAYLAND-DISABLE`, `SWAY-XWAYLAND-FORCE`" + (dispatch-command + (string-append "xwayland " (cond + ((equal? #t option) SWAY-XWAYLAND-ENABLE) + ((equal? #f option) SWAY-XWAYLAND-DISABLE) + (else option))))) + +(define SWAY-BORDER-NONE "none") +(define SWAY-BORDER-NORMAL "normal") +(define SWAY-BORDER-CSD "csd") +(define SWAY-BORDER-PIXEL "pixel") + +(define (sway-border option thickness) + "Enables or disables Xwayland support, which allows X11 applications to be used. + parameters: + - option: `SWAY-BORDER-NONE`, `SWAY-BORDER-NORMAL`, `SWAY-BORDER-CSD`, `SWAY-BORDER-PIXEL` + - thickness: int" + (dispatch-command + (string-append "border " option (number->string thickness)))) + +(define (sway-border-toggle) + "Cycles through the available border styles." + (dispatch-command + (string-append "border toggle"))) + +(define (sway-exit) + "Exit sway and end your Wayland session." + (dispatch-command + (string-append "exit"))) + +(define SWAY-FLOATING-ENABLED "enabled") +(define SWAY-FLOATING-DISABLED "disabled") +(define SWAY-FLOATING-TOGGLE "toggle") + +(define (sway-floating option) + "Make focused view floating, non-floating, or the opposite of what it is now. + parameters: + - layout: `SWAY-FLOATING-ENABLED`, `SWAY-FLOATING-DISABLED`, `SWAY-FLOATING-TOGGLE`" + (dispatch-command + (string-append "floating " (cond + ((equal? #t option) SWAY-FLOATING-ENABLED) + ((equal? #f option) SWAY-FLOATING-DISABLED) + (else option))))) + +(define (sway-focus-container-criteria criteria) + "Moves focus to the container that matches the specified criteria. + parameters: + - criteria: sway criteria" + (dispatch-command + (string-append criteria " focus"))) + +(define SWAY-DIRECTION-UP "up") +(define SWAY-DIRECTION-RIGHT "right") +(define SWAY-DIRECTION-DOWN "down") +(define SWAY-DIRECTION-LEFT "left") +(define SWAY-SIBLING-NEXT "next") +(define SWAY-SIBLING-PREV "prev") +(define SWAY-HIERARCHY-CHILD "child") +(define SWAY-HIERARCHY-PARENT "parent") + +(define (sway-focus-container direction) + "Moves focus to the next container in the specified direction. + parameters: + - direction: `SWAY-DIRECTION-UP`, `SWAY-DIRECTION-RIGHT`, `SWAY-DIRECTION-DOWN`, `SWAY-DIRECTION-LEFT`" + (dispatch-command + (string-append "focus " direction))) + +(define (sway-focus-container-sibling sibling) + "Moves focus to the previous or next container in the current layout. + parameters: + - sibling: `SWAY-SIBLING-NEXT`, `SWAY-SIBLING-PREV`" + (dispatch-command + (string-append "focus " sibling))) + +(define (sway-focus-container-child) + "Moves focus to the last-focused child of the focused container." + (dispatch-command + (string-append "focus child"))) + +(define (sway-focus-container-parent) + "Moves focus to the last-focused child of the focused container." + (dispatch-command + (string-append "focus parent"))) + +(define (sway-focus-output-direction direction) + "Moves focus to the next output in the specified direction. + parameters: + - direction: `SWAY-DIRECTION-UP`, `SWAY-DIRECTION-RIGHT`, `SWAY-DIRECTION-DOWN`, `SWAY-DIRECTION-LEFT`" + (dispatch-command + (string-append "focus output " direction))) + +(define (sway-focus-output-name name) + "Moves focus to the named output. + parameters: + - name: string, output name" + (dispatch-command + (string-append "focus output " name))) + +(define (sway-focus-container-tiling) + "Sets focus to the last focused tiling container." + (dispatch-command + (string-append "focus tiling"))) + +(define (sway-focus-container-floating) + "Sets focus to the last focused floating container." + (dispatch-command + (string-append "focus floating"))) + +(define SWAY-FULLSCREEN-ENABLED "enabled") +(define SWAY-FULLSCREEN-DISABLED "disabled") +(define SWAY-FULLSCREEN-TOGGLE "toggle") + +(define* (sway-fullscreen option #:key global) + "Makes focused view fullscreen, non-fullscreen, or the opposite of current. + parameters: + - option: `SWAY-FULLSCREEN-ENABLED`, `SWAY-FULLSCREEN-DISABLED`, `SWAY-FULLSCREEN-TOGGLE` + - global: #t, #f" + (dispatch-command + (string-append "fullscreen " (cond + ((equal? #t option) SWAY-FULLSCREEN-ENABLED) + ((equal? #f option) SWAY-FULLSCREEN-DISABLED) + (else option)) + (if global " global" "")))) + +(define SWAY-GAPS-OPTION-INNER "inner") +(define SWAY-GAPS-OPTION-OUTER "outer") +(define SWAY-GAPS-OPTION-HORIZONTAL "horizontal") +(define SWAY-GAPS-OPTION-VERTICAL "vertical") +(define SWAY-GAPS-OPTION-TOP "top") +(define SWAY-GAPS-OPTION-RIGHT "right") +(define SWAY-GAPS-OPTION-BOTTOM "bottom") +(define SWAY-GAPS-OPTION-LEFT "left") + +(define SWAY-GAPS-WORKSPACE-ALL "all") +(define SWAY-GAPS-WORKSPACE-CURRENT "current") +(define SWAY-GAPS-WORKSPACE-SET "set") +(define SWAY-GAPS-WORKSPACE-PLUS "plus") +(define SWAY-GAPS-WORKSPACE-MINUS "minus") +(define SWAY-GAPS-WORKSPACE-TOGGLE "toggle") + +(define (sway-gaps option workspace amount) + "Changes the inner or outer gaps for either all workspaces or the current workspace. + parameters: + - option: `SWAY-GAPS-OPTION-INNER`, `SWAY-GAPS-OPTION-OUTER`, `SWAY-GAPS-OPTION-HORIZONTAL`, + `SWAY-GAPS-OPTION-VERTICAL`, `SWAY-GAPS-OPTION-TOP`, `SWAY-GAPS-OPTION-RIGHT`, + `SWAY-GAPS-OPTION-BOTTOM`, `SWAY-GAPS-OPTION-LEFT` + - workspace: `SWAY-GAPS-WORKSPACE-ALL`, `SWAY-GAPS-WORKSPACE-CURRENT`, `SWAY-GAPS-WORKSPACE-SET`, + `SWAY-GAPS-WORKSPACE-PLUS`, `SWAY-GAPS-WORKSPACE-MINUS`, `SWAY-GAPS-WORKSPACE-TOGGLE` + - amount: amount of gap (number)" + (dispatch-command + (string-append "gaps " option " " workspace " " (number->string amount)))) + +(define SWAY-INHIBIT-IDLE-FOCUS "focus") +(define SWAY-INHIBIT-IDLE-FULLSCREEN "fullscreen") +(define SWAY-INHIBIT-IDLE-OPEN "open") +(define SWAY-INHIBIT-IDLE-NONE "none") +(define SWAY-INHIBIT-IDLE-VISIBLE "visible") + +(define (sway-inhibit-idle option) + "Set/unset an idle inhibitor for the view. + parameters: + - option: `SWAY-INHIBIT-IDLE-FOCUS`, `SWAY-INHIBIT-IDLE-FULLSCREEN`, `SWAY-INHIBIT-IDLE-OPEN`, + `SWAY-INHIBIT-IDLE-NONE`, `SWAY-INHIBIT-IDLE-VISIBLE`" + (dispatch-command + (string-append "inhibit_idle " option))) + +(define SWAY-LAYOUT-SPLITH "splith") +(define SWAY-LAYOUT-SPLITV "splitv") +(define SWAY-LAYOUT-STACKING "stacking") + +(define (sway-layout option) + "Set/unset an idle inhibitor for the view. + parameters: + - option: `SWAY-LAYOUT-DEFAULT`, `SWAY-LAYOUT-SPLITH`, `SWAY-LAYOUT-SPLITV`, + `SWAY-LAYOUT-STACKING`, `SWAY-LAYOUT-TABBED`" + (dispatch-command + (string-append "layout " option))) + +(define SWAY-LAYOUT-TOGGLE-ALL "all") +(define SWAY-LAYOUT-TOGGLE-SPLIT "split") + +(define* (sway-layout-toggle #:key option) + "Cycles the layout mode of the focused container though a preset list of layouts. + parameters: + - option: `SWAY-LAYOUT-TOGGLE-ALL`, `SWAY-LAYOUT-TOGGLE-SPLIT`" + (dispatch-command + (string-append "layout toggle" (if option (string-append " " option) "")))) + +(define* (sway-move-container direction #:key amount) + "Moves the focused container in the direction specified. + parameters: + - direction: `SWAY-DIRECTION-UP`, `SWAY-DIRECTION-RIGHT`, `SWAY-DIRECTION-DOWN`, `SWAY-DIRECTION-LEFT` + - amount: int" + (dispatch-command + (string-append "move " direction + (if amount (string-append " " (number->string amount)) "")))) + +(define (sway-move-container-absolute-position x y) + "Moves the focused container to the specified position in the workspace. + parameters: + - x: int + - y: int" + (dispatch-command + (string-append "move absolute position " (number->string x) " " (number->string y)))) + +(define (sway-move-container-absolute-center) + "Moves the focused container to be centered on the workspace." + (dispatch-command + (string-append "move absolute position center"))) + +(define (sway-move-container-cursor) + "Moves the focused container to be centered on the cursor." + (dispatch-command + (string-append "move position cursor"))) + +(define (sway-move-container-to-mark mark) + "Moves the focused container to the specified mark." + (dispatch-command + (string-append "move container to mark " mark))) + +(define SWAY-WORKSPACE-PREVIOUS "prev") +(define SWAY-WORKSPACE-NEXT "next") +(define SWAY-WORKSPACE-CURRENT "current") +(define SWAY-WORKSPACE-PREVIOUS-ON-OUTPUT "prev_on_output") +(define SWAY-WORKSPACE-NEXT-ON-OUTPUT "next_on_output") +(define SWAY-WORKSPACE-BACK-AND-FORTH "back_and_forth") + +(define (sway-move-container-to-workspace workspace) + "Moves the focused container to the workspace name + parameters: + - workspace: workspace name, `SWAY-WORKSPACE-PREVIOUS`, `SWAY-WORKSPACE-NEXT`, `SWAY-WORKSPACE-CURRENT`, + `SWAY-WORKSPACE-PREVIOUS-ON-OUTPUT`, `SWAY-WORKSPACE-NEXT-ON-OUTPUT`, `SWAY-WORKSPACE-BACK-AND-FORTH`" + (dispatch-command + (string-append "move container to workspace \"" workspace "\""))) + +(define SWAY-OUTPUT-CURRENT "current") +(define SWAY-OUTPUT-UP "up") +(define SWAY-OUTPUT-RIGHT "right") +(define SWAY-OUTPUT-DOWN "down") +(define SWAY-OUTPUT-LEFT "left") + +(define (sway-move-container-to-output output) + "Moves the focused container to the specified output id|name|direction. + parameters: + - workspace: output name, output id, `SWAY-OUTPUT-CURRENT`, `SWAY-OUTPUT-UP`, + `SWAY-OUTPUT-RIGHT`, `SWAY-OUTPUT-DOWN`, `SWAY-OUTPUT-LEFT`" + (dispatch-command + (string-append "move container to output " (or (and (number? output) + (number->string output)) + output)))) + +(define (sway-move-container-to-scratchpad) + "Moves the focused container to the scratchpad." + (dispatch-command + (string-append "move container to scratchpad"))) + +(define (sway-move-workspace-to-output output) + "Moves the focused workspace to the specified output id|name|direction. + parameters: + - workspace: output name, output id, `SWAY-OUTPUT-CURRENT`, `SWAY-OUTPUT-UP`, + `SWAY-OUTPUT-RIGHT`, `SWAY-OUTPUT-DOWN`, `SWAY-OUTPUT-LEFT`" + (dispatch-command + (string-append "move workspace to output " (or (and (number? output) + (number->string output)) + output)))) + +(define* (sway-nop #:key (comment "")) + "A no operation command that can be used to override default behaviour. + parameters: + - comment: optional comment argument is ignored, but logged for debugging purposes." + (dispatch-command + (string-append "nop " comment))) + +(define (sway-reload) + "Reloads the sway config file and applies any changes." + (dispatch-command + (string-append "reload"))) + +(define (sway-rename-workspace old-name new-name) + "Rename workspace to the + parameters: + - old-name: old workspace name (str). + - new-name: new workspace name (str)." + (dispatch-command + (string-append "rename workspace " old-name " to " new-name))) + +(define (sway-rename-current-workspace new-name) + "Rename current workspace to the + parameters: + - new-name: new workspace name (str)." + (dispatch-command + (string-append "rename workspace to " new-name))) + +(define SWAY-RESIZE-TYPE-SHRINK "shrink") +(define SWAY-RESIZE-TYPE-GROW-WIDTH "grow height") +(define SWAY-RESIZE-TYPE-GROW-HEIGHT "grow width") + +(define SWAY-SIZE-UNIT-PX "px") +(define SWAY-SIZE-UNIT-PPT "ppt") + +(define* (sway-resize type amount #:key unit) + "Resizes the currently focused container by amount, specified in pixels or percentage points. +If the units are omitted, floating containers are resized in px and tiled containers by ppt. + parameters: + - type: `SWAY-RESIZE-TYPE-SHRINK`, `SWAY-RESIZE-TYPE-GROW-WIDTH`, `SWAY-RESIZE-TYPE-GROW-HEIGHT` + - amount: number + - unit: `SWAY-SIZE-UNIT-PX`, `SWAY-SIZE-UNIT-PPT`" + (dispatch-command + (string-append "resize " type " " + (number->string amount) + (if unit (string-append " " unit) "")))) + +(define* (sway-resize-height amount #:key unit) + "Sets the height of the container to height, specified in pixels or percentage points." + (dispatch-command + (string-append "resize height " (number->string amount) + (if unit (string-append " " unit) "")))) + +(define* (sway-resize-width amount #:key unit) + "Sets the width of the container to width, specified in pixels or percentage points." + (dispatch-command + (string-append "resize width " (number->string amount) + (if unit (string-append " " unit) "")))) + +(define (sway-show-scratchpad) + "Shows a window from the scratchpad." + (dispatch-command + (string-append "scratchpad show"))) + +(define (sway-shortcuts-inhibitor flag) + "Enables or disables the ability of clients to inhibit keyboard shortcuts for a view." + (dispatch-command + (string-append "scratchpad " (if flag "enabled" "disabled")))) + +(define SWAY-SPLIT-VERTICAL "vertical") +(define SWAY-SPLIT-HORIZONTAL "horizontal") +(define SWAY-SPLIT-NONE "none") +(define SWAY-SPLIT-TOGGLE "toggle") + +(define (sway-split-container option) + "Splits the current container, vertically or horizontally. When none is specified, + the effect of a previous split is undone. + parameters: + - option: `SWAY-SPLIT-VERTICAL`, `SWAY-SPLIT-HORIZONTAL`, `SWAY-SPLIT-NONE`, `SWAY-SPLIT-TOGGLE`" + (dispatch-command + (string-append "split " option))) + +(define SWAY-STICKY-ENABLE "enable") +(define SWAY-STICKY-DISABLE "disable") +(define SWAY-STICKY-TOGGLE "toggle") + +(define (sway-sticky flag) + "Sticks a floating window to the current output so that it shows up on all workspaces. + parameters: + - flag: `SWAY-STICKY-ENABLE`, `SWAY-STICKY-DISABLE`, `SWAY-STICKY-TOGGLE`" + (dispatch-command + (string-append "sticky " (cond + ((equal? #t flag) SWAY-STICKY-ENABLE) + ((equal? #f flag) SWAY-STICKY-DISABLE) + (else flag))))) + +(define SWAY-SWAY-CONTAINER-TYPE-ID "id") +(define SWAY-SWAY-CONTAINER-TYPE-CONTAINER-ID "con_id") +(define SWAY-SWAY-CONTAINER-TYPE-MARK "mark") + +(define (sway-swap-container type arg) + "Swaps the position, geometry, and fullscreen status of focused container with another + target container. + parameters: + - type: `SWAY-SWAY-CONTAINER-TYPE-ID`, `SWAY-SWAY-CONTAINER-TYPE-CONTAINER-ID`, + `SWAY-SWAY-CONTAINER-TYPE-MARK` + - arg: argument passed (based on selected type)" + (dispatch-command + (string-append "swap container with " type " " + (if (number? arg) + (number->string arg) + arg)))) + +(define (sway-title-format format) + "Sets the format of window titles. + parameters: + - format: a string that can use some placehodlers to display windows title format + %title - The title supplied by the window + %app_id - The wayland app ID (applicable to wayland windows only) + %class - The X11 classname (applicable to xwayland windows only) + %instance - The X11 instance (applicable to xwayland windows only) + %shell - The protocol the window is using (typically xwayland or xdg_shell)" + + (dispatch-command + (string-append "title_format " format))) + +(define (sway-assign-to-workspace criteria workspace) + "Assigns views matching criteria to workspace. + parameters: + - criteria: a criteria string, use (sway-criteria) to build a one + - workspace: workspace name" + (dispatch-command + (string-append "assign " criteria " workspace " (or (and (number? workspace) + (number->string workspace)) + workspace)))) + +(define (sway-assign-to-output criteria output) + "Assigns views matching criteria to output. + parameters: + - criteria: a criteria string, use (sway-criteria) to build a one + - output: output name" + (dispatch-command + (string-append "assign " criteria " output " output))) + +(define* (sway-bindsym key command #:key whole-window border exclude-titlebar + release locked to-code input-device no-warn + no-repeat inhibited group) + "Binds key combo to execute the sway command command when pressed. + parameters: + - key: a string that represents the key to bind + - command: a string sway command to execute option receiving the key + - whole-window: affect the region in which the mouse bindings can be triggered. + - border: affect the region in which the mouse bindings can be triggered. + - exclude-titlebar: affect the region in which the mouse bindings can be triggered. + - release: command is executed when the key combo is released. + - locked: run command also when screen locking program is active + - to-code: the keysyms will be translated into the corresponding keycodes + this will make them layout independant + - input-device: the binding will only be executed for specified input device + - no-warn: silence sway warning when overriding a keybinding + - no-repeat: the command will not be run repeatedly when the key is held + - inhibited: keyboard shortcuts run also when inhibitor is active for the currently focused window. + - group: binding will only be available for specified group." + (dispatch-command + (string-append "bindsym " + (string-join + (filter (lambda (x) (> (string-length x) 0)) + (list + (if whole-window "--whole-window" "") + (if border "--border" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if release "--release" "") + (if locked "--locked" "") + (if to-code "--to-code" "") + (if input-device (string-append "--input-device=" input-device) "") + (if no-warn "--no-warn" "") + (if no-repeat "--no-repeat" "") + (if inhibited "--inhibited" "") + (if group "--group" ""))) + " ") + key " " command))) + +(define* (sway-bindcode code command #:key whole-window border exclude-titlebar + release locked input-device no-warn + no-repeat inhibited group) + "for binding with key/button codes instead of key/button names. + parameters: + - key: a string that represents the key to bind + - command: a string sway command to execute option receiving the key + - whole-window: affect the region in which the mouse bindings can be triggered. + - border: affect the region in which the mouse bindings can be triggered. + - exclude-titlebar: affect the region in which the mouse bindings can be triggered. + - release: command is executed when the key combo is released. + - locked: run command also when screen locking program is active + - input-device: the binding will only be executed for specified input device + - no-warn: silence sway warning when overriding a keybinding + - no-repeat: the command will not be run repeatedly when the key is held + - inhibited: keyboard shortcuts run also when inhibitor is active for the currently focused window. + - group: binding will only be available for specified group." + (dispatch-command + (string-append "bindcode " + (string-join + (filter (lambda (x) (> (string-length x) 0)) + (list + (if whole-window "--whole-window" "") + (if border "--border" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if release "--release" "") + (if locked "--locked" "") + (if input-device (string-append "--input-device=" input-device) "") + (if no-warn "--no-warn" "") + (if no-repeat "--no-repeat" "") + (if inhibited "--inhibited" "") + (if group "--group" ""))) + " ") + code " " command))) + +(define* (sway-bindswitch switch state command #:key locked no-warn reload) + "Binds to execute the sway command command on state changes. + parameters: + - switch: Supported switches are lid (laptop lid) and tablet (tablet mode) switches. + - state: valid values are on, off and toggle. + - command: a string sway command to execute option receiving the key + - locked: run command also when screen locking program is active + - no-warn: silence sway warning when overriding a keybinding + - reload: the binding should also be executed when the config is reloaded." + (dispatch-command + (string-append "bindswitch " + (string-join + (filter (lambda (x) (> (string-length x) 0)) + (list + (if locked "--locked" "") + (if no-warn "--no-warn" "") + (if reload "--reload" ""))) + " ") + switch ":" state " " command))) + +;; TODO +;; bindgesture [--exact] [--input-device=] [--no-warn] [:][:directions] +;; Binds gesture to execute the sway command command when detected. +;; Currently supports the hold, pinch or swipe gesture. Optionally can +;; be limited to bind to a certain number of fingers or, for a pinch or +;; swipe gesture, to certain directions. + +;; ┌───────┬─────────┬────────────────────────────────────────────────────┐ +;; │ type │ fingers │ direction │ +;; ├───────┼─────────┼────────────────────────────────────────────────────┤ +;; │ hold │ 1 - 5 │ none │ +;; ├───────┼─────────┼────────────────────────────────────────────────────┤ +;; │ swipe │ 3 - 5 │ up, down, left, right │ +;; ├───────┼─────────┼────────────────────────────────────────────────────┤ +;; │ pinch │ 2 - 5 │ all above + inward, outward, clockwise, counter‐ │ +;; │ │ │ clockwise │ +;; └───────┴─────────┴────────────────────────────────────────────────────┘ + +;; The fingers can be limited to any sensible number or left empty to +;; accept any finger counts. Valid directions are up, down, left and +;; right, as well as inward, outward, clockwise, counterclockwise for +;; the pinch gesture. Multiple directions can be combined by a plus. + +;; If a input-device is given, the binding will only be executed for +;; that input device and will be executed instead of any binding that +;; is generic to all devices. By default, if you overwrite a binding, +;; swaynag will give you a warning. To silence this, use the --no-warn +;; flag. + +;; The --exact flag can be used to ensure a binding only matches when +;; exactly all specified directions are matched and nothing more. If +;; there is matching binding with --exact, it will be preferred. + +;; The priority for matching bindings is as follows: input device, then +;; exact matches followed by matches with the highest number of match‐ +;; ing directions. + +;; Gestures executed while the pointer is above a bar are not handled +;; by sway. See the respective documentation, e.g. bindgesture in sway- +;; bar(5). + +;; Example: +;; # Allow switching between workspaces with left and right swipes +;; bindgesture swipe:right workspace prev +;; bindgesture swipe:left workspace next + +;; # Allow container movements by pinching them +;; bindgesture pinch:inward+up move up +;; bindgesture pinch:inward+down move down +;; bindgesture pinch:inward+left move left +;; bindgesture pinch:inward+right move right + +(define* (sway-unbindswitch switch state) + "Removes a binding for when changes to . + parameters: + - switch: Supported switches are lid (laptop lid) and tablet (tablet mode) switches. + - state: valid values are on, off and toggle." + (dispatch-command + (string-append "unbindswitch " switch ":" state))) + +;; TODO +;; unbindgesture [--exact] [--input-device=] [:][:directions] +;; Removes a binding for the specified gesture, fingers and directions +;; combination. + +(define* (sway-unbindsym key #:key whole-window border exclude-titlebar + release locked to-code input-device) + "Removes the binding for key combo that was previously bound with the given flags. + parameters: + - key: a string that represents the key to bind + - whole-window: affect the region in which the mouse bindings can be triggered. + - border: affect the region in which the mouse bindings can be triggered. + - exclude-titlebar: affect the region in which the mouse bindings can be triggered. + - release: command is executed when the key combo is released. + - locked: run command also when screen locking program is active + - to-code: the keysyms will be translated into the corresponding keycodes + this will make them layout independant + - input-device: the binding will only be executed for specified input device" + (dispatch-command + (string-append "unbindsym " + (string-join + (filter (lambda (x) (> (string-length x) 0)) + (list + (if whole-window "--whole-window" "") + (if border "--border" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if release "--release" "") + (if locked "--locked" "") + (if to-code "--to-code" "") + (if input-device (string-append "--input-device=" input-device) ""))) + " ") + key))) + +(define* (sway-unbindcode code #:key whole-window border exclude-titlebar + release locked input-device) + "Removes the binding for code that was previously bound with the given flags. + parameters: + - key: a string that represents the key to bind + - whole-window: affect the region in which the mouse bindings can be triggered. + - border: affect the region in which the mouse bindings can be triggered. + - exclude-titlebar: affect the region in which the mouse bindings can be triggered. + - release: command is executed when the key combo is released. + - locked: run command also when screen locking program is active + - input-device: the binding will only be executed for specified input device" + (dispatch-command + (string-append "unbindcode " + (string-join + (filter (lambda (x) (> (string-length x) 0)) + (list + (if whole-window "--whole-window" "") + (if border "--border" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if exclude-titlebar "--exclude-titlebar" "") + (if release "--release" "") + (if locked "--locked" "") + (if input-device (string-append "--input-device=" input-device) ""))) + " ") + code))) + +(define* (sway-unmark identifier) + "remove identifier from the list of current marks on a window. + Parameters: + - mark: string mark." + (dispatch-command + (string-append "unmark " identifier))) + +(define SWAY-URGENT-ENABLE "enable") +(define SWAY-URGENT-DISABLE "disable") +(define SWAY-URGENT-ALLOW "allow") +(define SWAY-URGENT-DENY "deny") + +(define* (sway-urgent flag) + "Using enable or disable manually sets or unsets the window's urgent state. + Parameters: + - flag: `SWAY-URGENT-ENABLE`, `SWAY-URGENT-DISABLE`, + `SWAY-URGENT-ALLOW`, `SWAY-URGENT-DENY`" + (dispatch-command + (string-append "urgent " flag))) + +;; The meaning of each color is: +;; border: The border around the title bar. +;; background: The background of the title bar. +;; text: The text color of the title bar. +;; indicator: The color used to indicate where a new view will open. +;; child_border: The border around the view itself. +(define (sway-client-background color) + "This command is ignored and is only present for i3 compatibility. + parameters: + - color: color code to be used (str)" + (dispatch-command + (string-append "client.background " color))) + +(define* (sway-client-focused-color border-color background-color text-color + #:key indictor-color child-border-color) + "Configures the color of window borders and title bars of the window that has focus. + parameters: + - border-color: color code to be used for border (str) + - background-color: color code to be used for background (str) + - text-color: color code to be used for text (str) + - indictor-color: color code to be used for indicator (str) + - child-border-color: color code to be used for child border (str)" + (dispatch-command + (string-append "client.focused " border-color background-color text-color + (if indictor-color (string-append " " indictor-color) "") + (if child-border-color (string-append " " child-border-color) "")))) + +(define* (sway-client-focused-inactive-color border-color background-color text-color + #:key indictor-color child-border-color) + "Configures the color of window borders and title bars of the most + recently focused view within a container which is not focused. + parameters: + - border-color: color code to be used for border (str) + - background-color: color code to be used for background (str) + - text-color: color code to be used for text (str) + - indictor-color: color code to be used for indicator (str) + - child-border-color: color code to be used for child border (str)" + (dispatch-command + (string-append "client.focused_inactive " border-color background-color text-color + (if indictor-color (string-append " " indictor-color) "") + (if child-border-color (string-append " " child-border-color) "")))) + +(define (sway-client-focused-tab-title-color border-color background-color text-color) + "Configures the color of window borders and title bars of a + view that has focused descendant container. + parameters: + - border-color: color code to be used for border (str) + - background-color: color code to be used for background (str) + - text-color: color code to be used for text (str) + - indictor-color: color code to be used for indicator (str) + - child-border-color: color code to be used for child border (str)" + (dispatch-command + (string-append "client.focused_tab_title " border-color background-color text-color))) + +(define* (sway-client-placeholder-color border-color background-color text-color + #:key indictor-color child-border-color) + "Ignored (present for i3 compatibility). + parameters: + - border-color: color code to be used for border (str) + - background-color: color code to be used for background (str) + - text-color: color code to be used for text (str) + - indictor-color: color code to be used for indicator (str) + - child-border-color: color code to be used for child border (str)" + (dispatch-command + (string-append "client.placeholder " border-color background-color text-color + (if indictor-color (string-append " " indictor-color) "") + (if child-border-color (string-append " " child-border-color) "")))) + +(define* (sway-client-unfocused-color border-color background-color text-color + #:key indictor-color child-border-color) + "Configures the color of window borders and title bars of a + view that does not have focus. + parameters: + - border-color: color code to be used for border (str) + - background-color: color code to be used for background (str) + - text-color: color code to be used for text (str) + - indictor-color: color code to be used for indicator (str) + - child-border-color: color code to be used for child border (str)" + (dispatch-command + (string-append "client.unfocused " border-color background-color text-color + (if indictor-color (string-append " " indictor-color) "") + (if child-border-color (string-append " " child-border-color) "")))) + +(define* (sway-client-urgent-color border-color background-color text-color + #:key indictor-color child-border-color) + "Configures the color of window borders and title bars of a + view with an urgency hint.. + parameters: + - border-color: color code to be used for border (str) + - background-color: color code to be used for background (str) + - text-color: color code to be used for text (str) + - indictor-color: color code to be used for indicator (str) + - child-border-color: color code to be used for child border (str)" + (dispatch-command + (string-append "client.urgent " border-color background-color text-color + (if indictor-color (string-append " " indictor-color) "") + (if child-border-color (string-append " " child-border-color) "")))) + +(define SWAY-BORDER-STYLE-NONE "none") +(define SWAY-BORDER-STYLE-NORMAL "normal") +(define SWAY-BORDER-STYLE-PIXEL "pixel") + +(define* (sway-default-border-style type #:key n) + "Set default border style for new tiled windows. + parameters: + - type: color code to be used for border (str) + - n: units in case pixel is chosen (number)" + (dispatch-command + (string-append "default_border " type " " (if n (number->string n) "")))) + +(define* (sway-default-floating-border-style type #:key n) + "Set default border style for new tiled windows. + parameters: + - type: color code to be used for border (str) + - n: units in case pixel is chosen (number)" + (dispatch-command + (string-append "default_floating_border " type " " (if n (number->string n) "")))) + +(define (sway-exec command) + "Executes shell command with sh. + parameters: + - command: command to be executed (str)" + (dispatch-command + (string-append "exec " command))) + +(define (sway-exec-always command) + "Like exec, but the shell command will be executed again after reload. + parameters: + - command: command to be executed (str)" + (dispatch-command + (string-append "exec_always " command))) + +(define (sway-floating-maximum-size width height) + "Specifies the maximum size of floating windows. + parameters: + - width: target size width (number) + - height: target size height (number)" + (dispatch-command + (string-append "floating_maximum_size " + (number->string width) " x " + (number->string height)))) + +(define (sway-floating-minimum-size width height) + "Specifies the minimum size of floating windows. + parameters: + - width: target size width (number) + - height: target size height (number)" + (dispatch-command + (string-append "floating_minimum_size " + (number->string width) " x " + (number->string height)))) + +(define SWAY-FLOATING-MODIFIER-TYPE-NORMAL "normal") +(define SWAY-FLOATING-MODIFIER-TYPE-INVERSE "inverse") + +(define (sway-floating-modifier modifier type) + "When the modifier key is held down, you may hold left click to move windows, + and right click to resize them. + parameters: + - modifier: the modifier key (str) + - type: `SWAY-FLOATING-MODIFIER-TYPE-NORMAL`, `SWAY-FLOATING-MODIFIER-TYPE-INVERSE`" + (dispatch-command + (string-append "floating_modifier" modifier " x " type))) + +(define SWAY-FOCUS-FOLLOW-MOUSE-FLAG-YES "yes") +(define SWAY-FOCUS-FOLLOW-MOUSE-FLAG-NO "no") +(define SWAY-FOCUS-FOLLOW-MOUSE-FLAG-ALWAYS "always") + +(define (sway-focus-follow-mouse flag) + "If set to yes, moving your mouse over a window will focus that window. + If set to always, the window under the cursor will always be + focused, even after switching between workspaces. + parameters: + - flag: `SWAY-FOCUS-FOLLOW-MOUSE-FLAG-YES`, `SWAY-FOCUS-FOLLOW-MOUSE-FLAG-NO`, + `SWAY-FOCUS-FOLLOW-MOUSE-FLAG-ALWAYS`" + (dispatch-command + (string-append "focus_follows_mouse " flag))) + +(define SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-SMART "smart") +(define SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-URGENT "urgent") +(define SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-FOCUS "focus") +(define SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-NONE "none") + +(define (sway-focus-on-window-activation flag) + "This option determines what to do when a client requests window activation. + parameters: + - flag: `SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-SMART`, `SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-URGENT`, + `SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-FOCUS`, `SWAY-FOCUS-ON-WINDOW-ACTIVATION-FLAG-NONE`" + (dispatch-command + (string-append "focus_on_window_activation " flag))) + +(define SWAY-FOCUS-WRAPPING-FLAG-YES "yes") +(define SWAY-FOCUS-WRAPPING-FLAG-NO "no") +(define SWAY-FOCUS-WRAPPING-FLAG-FORCE "force") +(define SWAY-FOCUS-WRAPPING-FLAG-WORKSPACE "workspace") + +(define (sway-focus-wrapping flag) + "This option determines what to do when a client requests window activation. + parameters: + - flag: `SWAY-FOCUS-WRAPPING-FLAG-YES`, `SWAY-FOCUS-WRAPPING-FLAG-NO`, + `SWAY-FOCUS-WRAPPING-FLAG-FORCE`, `SWAY-FOCUS-WRAPPING-FLAG-WORKSPACE`" + (dispatch-command + (string-append "focus_wrapping " flag))) + +(define* (sway-font font #:key pango) + "Sets font to use for the title bars. To enable support for pango markup, + preface the font name with pango: + parameters: + - font: font name (str) + - pango: whether to use pango or not (boolean)" + (dispatch-command + (string-append "font " (if pango "pango:" "") font))) + +(define (sway-force-display-urgency-hint timeout) + "If an application on another workspace sets an urgency hint. + parameters: + - timeout: urgency timeout (number)" + (dispatch-command + (string-append "force_display_urgency_hint " (number->string timeout)))) + +(define (sway-titlebar-border-thickness thickness) + "Thickness of the titlebar border in pixels. + parameters: + - thickness: thickness of border (number)" + (dispatch-command + (string-append "titlebar_border_thickness " (number->string thickness)))) + +(define (sway-titlebar-padding horizontal vertical) + "Padding of the text in the titlebar. + parameters: + - horizontal: horizontal padding (number) + - vertical: vertical padding (number)" + (dispatch-command + (string-append "titlebar_padding " (number->string horizontal) + " " (number->string vertical)))) + +;; TODO: it should be possible to get commands as strings instead of dispatching them immediately +(define (sway-for-window criteria commands) + "Whenever a window that matches criteria appears, run list of commands. + parameters: + - criteria: a criteria string, use (sway-criteria) to build a one + - command: list of commands to execute (string)" + (dispatch-command + (string-append "for_window " criteria " " commands))) + +(define (sway-default-gaps option amount) + "Sets default amount pixels of inner or outer gap. + parameters: + - option: `SWAY-GAPS-OPTION-INNER`, `SWAY-GAPS-OPTION-OUTER`, `SWAY-GAPS-OPTION-HORIZONTAL`, + `SWAY-GAPS-OPTION-VERTICAL`, `SWAY-GAPS-OPTION-TOP`, `SWAY-GAPS-OPTION-RIGHT`, + `SWAY-GAPS-OPTION-BOTTOM`, `SWAY-GAPS-OPTION-LEFT` + - amount: amount of gap (number)" + (dispatch-command + (string-append "gaps " option " " (number->string amount)))) + +(define SWAY-EDGE-BORDER-TYPE-NONE "none") +(define SWAY-EDGE-BORDER-TYPE-VERTICAL "vertical") +(define SWAY-EDGE-BORDER-TYPE-HORIZONTAL "horizontal") +(define SWAY-EDGE-BORDER-TYPE-BOTH "both") +(define SWAY-EDGE-BORDER-TYPE-SMART "smart") +(define SWAY-EDGE-BORDER-TYPE-SMART-NO-GAPS "smart_no_gaps") + +(define* (sway-hide-edge-borders type #:key i3) + "Hides window borders adjacent to the screen edges. + parameters: + - type: `SWAY-EDGE-BORDER-TYPE-NONE`, `SWAY-EDGE-BORDER-TYPE-VERTICAL`, `SWAY-EDGE-BORDER-TYPE-HORIZONTAL`, + `SWAY-EDGE-BORDER-TYPE-BOTH`, `SWAY-EDGE-BORDER-TYPE-SMART`, `SWAY-EDGE-BORDER-TYPE-SMART-NO-GAPS` + - i3: enables i3-compatible behavior to hide the title bar on tabbed and stacked containers with one child" + (dispatch-command + (string-append "hide_edge_borders " (if i3 "--i3 " "") type))) + +(define (sway-input device subcommands) + "For details on input subcommands, see sway-input(5). + parameters: + - device: the name of the target device + - subcommands: list of commands to execute (string)" + (dispatch-command + (string-append "input " device " " subcommands))) + +(define (sway-seat seat subcommands) + "For details on input subcommands, see sway-input(5). + parameters: + - seat: the name of the seat device + - subcommands: list of commands to execute (string)" + (dispatch-command + (string-append "seat " seat " " subcommands))) + +(define (sway-kill) + "Kills (closes) the currently focused container and all of its children." + (dispatch-command + (string-append "kill"))) + +(define SWAY-SMART-BORDERS-ON "on") +(define SWAY-SMART-BORDERS-OFF "off") +(define SWAY-SMART-BORDERS-NO-GAPS "no_gaps") + +(define (sway-smart-borders flag) + "If smart_borders are on, borders will only be enabled if the + workspace has more than one visible child. + parameters: + - flag: `SWAY-SMART-BORDERS-ON`, `SWAY-SMART-BORDERS-OFF`, `SWAY-SMART-BORDERS-NO-GAPS`" + (dispatch-command + (string-append "smart_borders " (cond + ((equal? flag #t) SWAY-SMART-BORDERS-ON) + ((equal? flag #f) SWAY-SMART-BORDERS-OFF) + (else flag))))) + +(define SWAY-SMART-GAPS-ON "on") +(define SWAY-SMART-GAPS-OFF "off") +(define SWAY-SMART-GAPS-TOGGLE "toggle") +(define SWAY-SMART-GAPS-INVERSE-OUTER "inverse_outer") + +(define (sway-smart-gaps flag) + "If smart_gaps are on gaps will only be enabled if a + workspace has more than one child. + parameters: + - flag: `SWAY-SMART-GAPS-ON`, `SWAY-SMART-GAPS-OFF`, + `SWAY-SMART-GAPS-TOGGLE`, `SWAY-SMART-GAPS-INVERSE-OUTER`" + (dispatch-command + (string-append "smart_gaps " (cond + ((equal? flag #t) SWAY-SMART-GAPS-ON) + ((equal? flag #f) SWAY-SMART-GAPS-OFF) + (else flag))))) + +;; mark --add|--replace [--toggle] +;; Marks are arbitrary labels that can be used to identify certain win‐ +;; dows and then jump to them at a later time. Each identifier can only +;; be set on a single window at a time since they act as a unique iden‐ +;; tifier. By default, mark sets identifier as the only mark on a win‐ +;; dow. --add will instead add identifier to the list of current marks +;; for that window. If --toggle is specified mark will remove identi‐ +;; fier if it is already marked. + +(define (sway-mode mode) + "Switches to the specified mode. The default mode is default. + parameters: + - mode: name of the mode (str)" + (dispatch-command + (string-append "mode \"" mode "\""))) + +(define (sway-mode-subcommand mode subcommand) + "The only valid mode-subcommands are bindsym, bindcode, bindswitch, and set. + parameters: + - mode: name of the mode (str) + - subcommand: list of subcommands (str)" + (dispatch-command + (string-append "mode \"" mode "\" " subcommand))) + +(define SWAY-MOUSE-WARPING-OUTPUT "output") +(define SWAY-MOUSE-WARPING-CONTAINER "container") +(define SWAY-MOUSE-WARPING-NONE "none") + +(define (sway-mouse-warping mode) + "If output is specified, the mouse will be moved to new outputs as you move focus between them. + If container is specified, the mouse will be moved to the middle of the container on switch. + parameters: + - mode: `SWAY-MOUSE-WARPING-OUTPUT`, `SWAY-MOUSE-WARPING-CONTAINER`, `SWAY-MOUSE-WARPING-NONE`" + (dispatch-command + (string-append "mouse_warping " mode))) + +(define (sway-no-focus criteria) + "Prevents windows matching from being focused automatically when they're created. + parameters: + - criteria: a criteria string, use (sway-criteria) to build a one" + (dispatch-command + (string-append "no_focus " criteria))) + +(define (sway-output output subcommands) + "For details on output subcommands, see sway-output(5). + parameters: + - output: name of the output (str) + - subcommand: list of subcommands (str)" + (dispatch-command + (string-append "output " output " " subcommands))) + +(define SWAY-POPUP-TYPE-OUTPUTSMART "outputsmart") +(define SWAY-POPUP-TYPE-IGNORE "ignore") +(define SWAY-POPUP-TYPE-LEAVE-FULLSCREEN "leave_fullscreen") + +(define (sway-popup-during-fullscreen type) + "Determines what to do when a fullscreen view opens a dialog. + parameters: + - type: `SWAY-POPUP-TYPE-OUTPUTSMART`, `SWAY-POPUP-TYPE-IGNORE`, `SWAY-POPUP-TYPE-LEAVE-FULLSCREEN`" + (dispatch-command + (string-append "popup_during_fullscreen " type))) + +(define SWAY-PRIMARY-SELECTION-ENABLED "enabled") +(define SWAY-PRIMARY-SELECTION-DISABLED "disabled") + +(define (sway-primary-selection type) + "Enable or disable the primary selection clipboard. May only be configured at launch. Default is enabled. + parameters: + - type: `SWAY-PRIMARY-SELECTION-ENABLED`, `SWAY-PRIMARY-SELECTION-DISABLED`" + (dispatch-command + (string-append "primary_selection " (cond + ((equal? type #t) SWAY-PRIMARY-SELECTION-ENABLED) + ((equal? type #f) SWAY-PRIMARY-SELECTION-DISABLED) + (else type))))) + +(define SWAY-SHOW-MARKS-YES "yes") +(define SWAY-SHOW-MARKS-NO "no") + +(define (sway-show-marks flag) + "If show_marks is yes, marks will be displayed in the window borders. + parameters: + - flag: `SWAY-SHOW-MARKS-YES`, `SWAY-SHOW-MARKS-NO`" + (dispatch-command + (string-append "show_marks " (cond + ((equal? flag #t) SWAY-SHOW-MARKS-YES) + ((equal? flag #f) SWAY-SHOW-MARKS-NO) + (else flag))))) + +(define SWAY-OPACITY-SET "set") +(define SWAY-OPACITY-PLUS "plus") +(define SWAY-OPACITY-MINUS "minus") + +(define (sway-opacity type value) + "Adjusts the opacity of the window between 0 (completely transparent) and 1 (completely opaque) + parameters: + - type: `SWAY-OPACITY-SET`, `SWAY-OPACITY-PLUS`, `SWAY-OPACITY-MINUS` + - value: opacity value (number) should be between 0 and 1" + (dispatch-command + (string-append "opacity " type " " (number->string value)))) + +(define SWAY-TILING-DRAG-ENABLE "enable") +(define SWAY-TILING-DRAG-DISABLE "disable") +(define SWAY-TILING-DRAG-TOGGLE "toggle") + +(define (sway-tiling-drag flag) + "Sets whether or not tiling containers can be dragged with the mouse. + parameters: + - flag: `SWAY-TILING-DRAG-ENABLE`, `SWAY-TILING-DRAG-DISABLE`, `SWAY-TILING-DRAG-TOGGLE`" + (dispatch-command + (string-append "tiling_drag " (cond + ((equal? flag #t) SWAY-TILING-DRAG-ENABLE) + ((equal? flag #f) SWAY-TILING-DRAG-DISABLE) + (else flag))))) + +(define (sway-tiling-drag-threshold threshold) + "Sets whether or not tiling containers can be dragged with the mouse. + parameters: + - threshold: threshold value (number)" + (dispatch-command + (string-append "tiling_drag_threshold " (number->string threshold)))) + +(define SWAY-TILING-ALIGN-LEFT "left") +(define SWAY-TILING-ALIGN-CENTER "center") +(define SWAY-TILING-ALIGN-RIGHT "right") + +(define (sway-tiling-align type) + "Sets the title alignment. + parameters: + - type: `SWAY-TILING-ALIGN-LEFT`, `SWAY-TILING-ALIGN-CENTER`, `SWAY-TILING-ALIGN-RIGHT`" + (dispatch-command + (string-append "title_align " type))) + +(define* (sway-switch-workspace-id id #:key auto-back-and-forth) + "switch to the workspace with the provided id. + parameters: + - id: workspace id (number) + - auto-back-and-forth: enable/disable auto back and forth" + (dispatch-command + (string-append "workspace number " + (unless auto-back-and-forth "--no-auto-back-and-forth ") + (number->string id)))) + +(define* (sway-switch-workspace workspace #:key auto-back-and-forth) + "switch to the workspace with the provided name. + parameters: + - workspace: workspace name (str) + - auto-back-and-forth: enable/disable auto back and forth" + (dispatch-command + (string-append "workspace " + (unless auto-back-and-forth "--no-auto-back-and-forth ") + workspace))) + +(define (sway-switch-workspace-on-output workspace output) + "assigns workspace to output. + parameters: + - workspace: workspace name (str) + - output: output name" + (dispatch-command + (string-append "workspace " workspace " output " output))) + +(define SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-YES "yes") +(define SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-NO "no") + +(define (sway-workspace-auto-back-and-forth option) + "When yes, repeating a workspace switch command will switch back to the prior workspace. + parameters: + - option: `SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-YES`, `SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-NO`" + (dispatch-command + (string-append "workspace_auto_back_and_forth " + (cond + ((equal? option #t) SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-YES) + ((equal? option #f) SWAY-WORKSPACE-AUTO-BACK-AND-FORTH-OPTION-NO) + (else option))))) + +(define (sway-workspace-gaps workspace option amount) + "Specifies that workspace name should have the given gaps settings when it is created. + This command does not affect existing workspaces. To alter the gaps of an existing workspace, + use the `sway-gaps` command. + parameters: + - workspace: workspace name (str) + - option: `SWAY-GAPS-OPTION-INNER`, `SWAY-GAPS-OPTION-OUTER`, `SWAY-GAPS-OPTION-HORIZONTAL`, + `SWAY-GAPS-OPTION-VERTICAL`, `SWAY-GAPS-OPTION-TOP`, `SWAY-GAPS-OPTION-RIGHT`, + `SWAY-GAPS-OPTION-BOTTOM`, `SWAY-GAPS-OPTION-LEFT` + - amount: the amount of gap (number)" + (dispatch-command + (string-append "workspace " workspace option (number->string amount)))) + +(define* (sway-criteria #:key app-id class con-id con-mark + floating id instance pid shell tiling title urgent + window-role window-type workspace) + "Generate a string that contains one or more (space separated) attribute/value pairs." + (string-append + "[" + (string-join + (filter (lambda (x) (> (string-length x) 0)) + (list + (if app-id (string-append "app_id=" app-id) "") + (if class (string-append "class=" class) "") + (if con-id (string-append "con_id=" con-id) "") + (if con-mark (string-append "con_mark=" con-mark) "") + (if floating (string-append "floating=" floating) "") + (if id (string-append "id=" id) "") + (if instance (string-append "instance=" instance) "") + (if pid (string-append "pid=" pid) "") + (if shell (string-append "shell=" shell) "") + (if tiling (string-append "tiling=" tiling) "") + (if title (string-append "title=" title) "") + (if urgent (string-append "urgent=" urgent) "") + (if window-role (string-append "window_role=" window-role) "") + (if window-type (string-append "window_type=" window-type) "") + (if workspace (string-append "workspace=" workspace)) "")) + " ") + "]")) diff --git a/swayipc/events.scm b/swayipc/events.scm new file mode 100755 index 0000000..b9a7e09 --- /dev/null +++ b/swayipc/events.scm @@ -0,0 +1,173 @@ +(define-module (swayipc events) + #:use-module (swayipc connection) + #:use-module (swayipc records) + + #:export (sway-subscribe-event + sway-subscribe-workspace-change + sway-subscribe-workspace-event + sway-subscribe-output-event + sway-subscribe-binding-mode-event + sway-subscribe-window-event + sway-subscribe-barconfig-update-event + sway-subscribe-binding-event + sway-subscribe-shutdown-event + sway-subscribe-tick-event + sway-subscribe-bar-state-event + sway-subscribe-input-event + sway-subscribe-all + + sway-workspace-hook + sway-output-hook + sway-mode-hook + sway-window-hook + sway-bar-config-hook + sway-shutdown-hook + sway-tick-hook + sway-bar-state-update-hook + sway-input-hook)) + +(define (sway-subscribe-event event) + "A client can subscribe to any events it wants to be notified of changes for." + (write-msg LISTENER-SOCKET SUBSCRIBE-MSG-ID event) + (json->sway-tick (list-ref (read-msg LISTENER-SOCKET) 1))) + +(define (sway-subscribe-workspace-event) + "Sent whenever an event involving a workspace occurs such as initialization + of a new workspace or a different workspace gains focus." + (sway-subscribe-event "['workspace']")) + +(define (sway-subscribe-output-event) + "Sent when outputs are updated." + (sway-subscribe-event "['output']")) + +(define (sway-subscribe-binding-mode-event) + "Sent whenever the binding mode changes." + (sway-subscribe-event "['mode']")) + +(define (sway-subscribe-window-event) + "Sent whenever an event involving a view occurs such as being reparented, focused, or closed." + (sway-subscribe-event "['window']")) + +(define (sway-subscribe-barconfig-update-event) + "Sent whenever a bar config changes." + (sway-subscribe-event "['barconfig_update']")) + +(define (sway-subscribe-binding-event) + "Sent when a configured binding is executed." + (sway-subscribe-event "['binding']")) + +(define (sway-subscribe-shutdown-event) + "Sent when the ipc shuts down because sway is exiting." + (sway-subscribe-event "['shutdown']")) + +(define (sway-subscribe-tick-event) + "Sent when an ipc client sends a SEND_TICK message." + (sway-subscribe-event "['tick']")) + +(define (sway-subscribe-bar-state-event) + "Send when the visibility of a bar should change due to a modifier." + (sway-subscribe-event "['bar_state_update']")) + +(define (sway-subscribe-input-event) + "Sent when something related to input devices changes." + (sway-subscribe-event "['input']")) + +(define (sway-subscribe-all) + "subscribe to all available events." + (sway-subscribe-event "['workspace', 'output', 'mode', 'window', 'barconfig_update', + 'binding', 'shutdown', 'tick', 'bar_state_update', 'input']")) + +(define (custom-exception-handler exc command-id payload) + (display "An error occurred while receiving event data\n") + (display (string-append "command: " (number->string command-id) ", payload: " payload))) + +(add-hook! data-received-hook + (lambda (command-id payload) + (with-exception-handler + (lambda (exc) + (custom-exception-handler exc command-id payload)) + (lambda () (handle-event command-id payload)) + #:unwind? #t))) + +(define (handle-event command-id payload) + (cond + ((= command-id WORKSPACE-EVENT-REPLY) + (run-hook sway-workspace-hook (json->sway-workspace-event payload))) + ((= command-id OUTPUT-EVENT-REPLY) + (run-hook sway-output-hook (json->sway-output-event payload))) + ((= command-id MODE-EVENT-REPLY) + (run-hook sway-mode-hook (json->sway-mode-event payload))) + ((= command-id WINDOW-EVENT-REPLY) + (run-hook sway-window-hook (json->sway-window-event payload))) + ((= command-id BAR-CONFIG-UPDATE-EVENT-REPLY) + (run-hook sway-bar-config-hook (json->sway-bar-config payload))) + ((= command-id BINDING-EVENT-REPLY) + (run-hook sway-binding-hook (json->sway-binding-event payload))) + ((= command-id SHUTDOWN-EVENT-REPLY) + (run-hook sway-shutdown-hook (json->sway-shutdown-event payload))) + ((= command-id TICK-EVENT-REPLY) + (run-hook sway-tick-hook (json->sway-tick-event payload))) + ((= command-id BAR-STATE-UPDATE-EVENT-REPLY) + (run-hook sway-bar-state-update-hook (json->sway-bar-state-update-event payload))) + ((= command-id INPUT-EVENT-REPLY) + (run-hook sway-input-hook (json->sway-input-event payload))))) + +(define sway-workspace-hook + ;; workspace changed: emitted on workspace change. + ;; Parameters: + ;; - arg1: sway-workspace-event. + (make-hook 1)) + +(define sway-output-hook + ;; output changed: emitted on output change. + ;; Parameters: + ;; - arg1: sway-output-event. + (make-hook 1)) + +(define sway-mode-hook + ;; mode changed: emitted on mode change. + ;; Parameters: + ;; - arg1: sway-mode-event. + (make-hook 1)) + +(define sway-window-hook + ;; window changed: emitted on window change. + ;; Parameters: + ;; - arg1: sway-window-event. + (make-hook 1)) + +(define sway-binding-hook + ;; binding changed: emitted on binding change. + ;; Parameters: + ;; - arg1: sway-binding-event. + (make-hook 1)) + +(define sway-bar-config-hook + ;; bar-config changed: emitted on bar-config change. + ;; Parameters: + ;; - arg1: sway-bar-config-event. + (make-hook 1)) + +(define sway-shutdown-hook + ;; shutdown changed: emitted on shutdown change. + ;; Parameters: + ;; - arg1: sway-shutdown-event. + (make-hook 1)) + +(define sway-tick-hook + ;; tick changed: emitted on tick change. + ;; Parameters: + ;; - arg1: sway-tick-event. + (make-hook 1)) + +(define sway-bar-state-update-hook + ;; bar-state-update changed: emitted on bar-state-update change. + ;; Parameters: + ;; - arg1: sway-bar-state-update-event. + (make-hook 1)) + +(define sway-input-hook + ;; input changed: emitted on input change. + ;; Parameters: + ;; - arg1: sway-input-event. + (make-hook 1)) diff --git a/swayipc/info.scm b/swayipc/info.scm new file mode 100755 index 0000000..bc862d5 --- /dev/null +++ b/swayipc/info.scm @@ -0,0 +1,113 @@ +(define-module (swayipc info) + #:use-module (swayipc connection) + #:use-module (swayipc records) + #:use-module (oop goops) + #:use-module (sjson parser) + #:use-module (srfi srfi-9) + #:use-module (srfi srfi-1) + + #:export (sway-get-workspaces + sway-get-outputs + sway-get-tree + sway-get-marks + sway-get-bars + sway-get-bar-config + sway-get-version + sway-get-binding-modes + sway-get-config + sway-get-binding-state + sway-get-inputs + sway-get-seats)) + +(define (custom-exception-handler exc command-id payload) + (display "An error occurred: ") + (display (exp->string exc)) + (newline) + (display (string-append "command: " (number->string command-id) ", payload: " payload))) + +(define (sway-send-query message-id payload) + "returns the ipc response from sway after sending the message-id and payload" + (with-exception-handler + (lambda (exc) + (custom-exception-handler exc command-id payload)) + (lambda () (begin + (write-msg COMMAND-SOCKET + message-id + payload) + (let* ((out (read-msg COMMAND-SOCKET))) + (list-ref out 1)))) + #:unwind? #t)) + +(define (sway-get-workspaces) + "Retrieves the list of workspaces." + (map + (lambda (workspace) + (scm->sway-workspace workspace)) + (vector->list + (json-string->scm + (sway-send-query GET-WORKSPACES-MSG-ID ""))))) + +(define (sway-get-outputs) + "Retrieve the list of outputs." + (map + (lambda (output) + (scm->sway-output output)) + (vector->list + (json-string->scm + (sway-send-query GET-OUTPUTS-MSG-ID ""))))) + +(define (sway-get-tree) + "Retrieve a representation of the tree." + (json->sway-tree (sway-send-query GET-TREE-MSG-ID ""))) + +(define (sway-get-marks) + "Retrieve the currently set marks." + (vector->list + (json-string->scm + (sway-send-query GET-MARKS-MSG-ID "")))) + +(define (sway-get-bars) + "retrieves the list of configured bar IDs." + (vector->list + (json-string->scm + (sway-send-query GET-BAR-CONFIG-MSG-ID "")))) + +(define (sway-get-bar-config bar-id) + "retrieves the config associated with the specified by the bar ID." + (json->sway-bar-config (sway-send-query GET-BAR-CONFIG-MSG-ID bar-id))) + +(define (sway-get-version) + "Retrieve version information about the sway process." + (json->sway-version (sway-send-query GET-VERSION-MSG-ID ""))) + +(define (sway-get-binding-modes) + "Retrieve the list of binding modes that currently configured." + (vector->list + (json-string->scm + (sway-send-query GET-BINDING-MODES-MSG-ID "")))) + +(define (sway-get-config) + "Retrieve the list of binding modes that currently configured." + (json->sway-config (sway-send-query GET-CONFIG-MSG-ID ""))) + +(define (sway-get-binding-state) + "Returns the currently active binding mode." + (json->sway-binding-state (sway-send-query GET-BINDING-STATE-MSG-ID ""))) + +(define (sway-get-inputs) + "Retrieve a list of the input devices currently available." + (map + (lambda (input) + (scm->sway-input input)) + (vector->list + (json-string->scm + (sway-send-query GET-INPUTS-MSG-ID ""))))) + +(define (sway-get-seats) + "Retrieve a list of the seats currently configured." + (map + (lambda (seat) + (scm->sway-seat seat)) + (vector->list + (json-string->scm + (sway-send-query GET-SEATS-MSG-ID ""))))) diff --git a/swayipc/records.scm b/swayipc/records.scm new file mode 100755 index 0000000..cd816f3 --- /dev/null +++ b/swayipc/records.scm @@ -0,0 +1,491 @@ +(define-module (swayipc records) + #:use-module (oop goops) + #:use-module (sjson record) + #:use-module (sjson parser) + #:use-module (sjson builder) + + #:export ( + scm->sway-rect + json->sway-rect + sway-rect-x + sway-rect-y + sway-rect-width + sway-rect-height + + + scm->sway-workspace + json->sway-workspace + sway-workspace-num + sway-workspace-name + sway-workspace-visible + sway-workspace-focused + sway-workspace-urgent + sway-workspace-rect + sway-workspace-output + + + scm->sway-mode + json->sway-mode + sway-mode-width + sway-mode-height + sway-mode-refresh + sway-mode-picture-aspect-ratio + + + scm->sway-output + json->sway-output + sway-output-name + sway-output-make + sway-output-model + sway-output-serial + sway-output-active + sway-output-primary + sway-output-scale + sway-output-subpixel-hinting + sway-output-transform + sway-output-current-workspace + sway-output-modes + sway-output-current-mode + + + scm->sway-window-property + json->sway-window-property + class + instance + title + transient-for + + + scm->sway-tree + json->sway-tree + sway-tree-id + sway-tree-name + sway-tree-type + sway-tree-border + sway-tree-current-border-width + sway-tree-layout + sway-tree-orientation + sway-tree-percent + sway-tree-rect + sway-tree-window-rect + sway-tree-deco-rect + sway-tree-geometry + sway-tree-urgent + sway-tree-sticky + sway-tree-marks + sway-tree-focused + sway-tree-focus + sway-tree-nodes + sway-tree-floating-nodes + sway-tree-representation + sway-tree-fullscreen-mode + sway-tree-app-id + sway-tree-pid + sway-tree-visible + sway-tree-shell + sway-tree-inhibit-idle + sway-tree-idle-inhibitors + sway-tree-window + sway-tree-window-properties + + + scm->sway-bar-color + json->sway-bar-color + sway-bar-color-background + sway-bar-color-status-line + sway-bar-color-separator + sway-bar-color-focused-background + sway-bar-color-focused-statusline + sway-bar-color-focused-separator + sway-bar-color-focused-workspace-text + sway-bar-color-focused-workspace-background + sway-bar-color-focused-workspace-border + sway-bar-color-active-workspace-text + sway-bar-color-active-workspace-background + sway-bar-color-active-workspace-border + sway-bar-color-inactive-workspace-text + sway-bar-color-inactive-workspace-background + sway-bar-color-inactive-workspace-border + sway-bar-color-urgent-workspace-text + sway-bar-color-urgent-workspace-background + sway-bar-color-urgent-workspace-border + sway-bar-color-binding-mode-text + sway-bar-color-binding-mode-background + sway-bar-color-binding-mode-border + + + scm->sway-bar-gap + json->sway-bar-gap + sway-bar-gap-top + sway-bar-gap-right + sway-bar-gap-bottom + sway-bar-gap-left + + + scm->sway-bar-config + json->sway-bar-config + sway-bar-config-id + sway-bar-config-mode + sway-bar-config-position + sway-bar-config-status-command + sway-bar-config-font + sway-bar-config-workspace-buttons + sway-bar-config-workspace-min-width + sway-bar-config-binding-mode-indicator + sway-bar-config-verbose + sway-bar-config-colors + sway-bar-config-gaps + sway-bar-config-bar-height + sway-bar-config-status-padding + sway-bar-config-status-edge-padding + + + scm->sway-version + json->sway-version + sway-version-major + sway-version-minor + sway-version-patch + sway-version-human-readable + sway-version-loaded-config-file-name + + + scm->sway-config + json->sway-config + sway-config-config + + + scm->sway-tick + json->sway-tick + sway-tick-success + sway-tick-parse-error + sway-tick-error + + + scm->sway-sync + json->sway-sync + sway-sync-success + + + scm->sway-binding-state + json->sway-binding-state + sway-binding-state-name + + + scm->sway-lib-input + json->sway-lib-input + sway-lib-input-send-events + sway-lib-input-tap + sway-lib-input-tap-button-map + sway-lib-input-tap-drag + sway-lib-input-tap-drag-lock + sway-lib-input-accel-speed + sway-lib-input-accel-profile + sway-lib-input-natural-scroll + sway-lib-input-left-handed + sway-lib-input-click-method + sway-lib-input-middle-emulation + sway-lib-input-scroll-method + sway-lib-input-scroll-button + sway-lib-input-scroll-button-lock + sway-lib-input-dwt + sway-lib-input-dwtp + sway-lib-input-calibration-matrix + + + scm->sway-input + json->sway-input + sway-input-identifier + sway-input-name + sway-input-vendor + sway-input-product + sway-input-type + sway-input-xkb-active-layout-name + sway-input-xkb-layout-names + sway-input-scroll-factor + sway-input-libinput + + + scm->sway-seat + json->sway-seat + sway-seat-name + sway-seat-capabilities + sway-seat-focus + sway-seat-devices + + + scm->sway-workspace-event + json->sway-workspace-event + sway-workspace-event-change + sway-workspace-event-old + sway-workspace-event-current + + + scm->sway-output-event + json->sway-output-event + sway-output-event-change + + + scm->sway-mode-event + json->sway-mode-event + sway-mode-event-change + sway-mode-event-pango-markup + + + scm->sway-window-event + json->sway-window-event + sway-window-event-change + sway-window-event-container + + + scm->sway-binding-event + json->sway-binding-event + sway-binding-event-change + sway-binding-event-binding + + + scm->sway-binding-event-binding + json->sway-binding-event-binding + sway-binding-event-binding-command + sway-binding-event-binding-event-state-mask + sway-binding-event-binding-input-code + sway-binding-event-binding-sybmol + sway-binding-event-binding-input-type + + + scm->sway-shutdown-event + json->sway-shutdown-event + sway-shutdown-event-change + + + scm->sway-tick-event + json->sway-tick-event + sway-tick-event-first + sway-tick-event-paylaod + + + scm->sway-bar-state-update-event + json->sway-bar-state-update-event + sway-bar-state-update-event-id + sway-bar-state-update-event-visible-by-modifier + + + scm->sway-input-event + json->sway-input-event + sway-input-event-change + sway-input-event-input)) + +(define-json-type + (x) + (y) + (width) + (height)) + +(define-json-type + (num) + (name) + (visible) + (focused) + (urgent) + (rect "rect" ) + (output)) + +(define-json-type + (picture-aspect-ratio "picture_aspect_ratio") + (refresh) + (height) + (width)) + +(define-json-type + (name) + (make) + (model) + (serial) + (active) + (primary) + (scale) + (subpixel-hinting "subpixel_hinting") + (transform) + (current-workspace "current_workspace") + (modes "modes" #()) + (current-mode "current_mode" )) + +(define-json-type + (class) + (instance) + (title) + (transient-for "transient_for")) + +(define-json-type + (id) + (name) + (type) + (border) + (current-border-width "current_border_width") + (layout) + (orientation) + (percent) + (rect "rect" ) + (window-rect "window_rect" ) + (deco-rect "deco_rect" ) + (geometry "geometry" ) + (urgent) + (sticky) + (marks) + (focused) + (focus) + (nodes "nodes" #()) + (floating-nodes "floating_nodes" #()) + (representation) + (fullscreen-mode "fullscreen_mode") + (app-id "app_id") + (pid) + (visible) + (shell) + (inhibit-idle "inhibit_idle") + (idle-inhibitors "idle_inhibitors") + (window) + (window-properties "window_properties" )) + +(define-json-type + (background) + (status-line "statusline") + (separator) + (focused-background "focused_background") + (focused-statusline "focused_statusline") + (focused-separator "focused_separator") + (focused-workspace-text "focused_workspace_text") + (focused-workspace-background "focused_workspace_bg") + (focused-workspace-border "focused_workspace_border") + (active-workspace-text "active_workspace_text") + (active-workspace-background "active_workspace_bg") + (active-workspace-border "active_workspace_border") + (inactive-workspace-text "inactive_workspace_text") + (inactive-workspace-background "inactive_workspace_bg") + (inactive-workspace-border "inactive_workspace_border") + (urgent-workspace-text "urgent_workspace_text") + (urgent-workspace-background "urgent_workspace_bg") + (urgent-workspace-border "urgent_workspace_border") + (binding-mode-text "binding_mode_text") + (binding-mode-background "binding_mode_bg") + (binding-mode-border "binding_mode_border")) + +(define-json-type + (top) + (right) + (bottom) + (left)) + +(define-json-type + (id) + (mode) + (position) + (status-command "status_command") + (font) + (workspace-buttons "workspace_buttons") + (workspace-min-width "workspace_min_width") + (binding-mode-indicator) + (verbose) + (colors "colors" ) + (gaps "gaps" ) + (bar-height "bar_height") + (status-padding "status_padding") + (status-edge-padding "status_edge_padding")) + +(define-json-type + (major) + (minor) + (patch) + (human-readable "human_readable") + (loaded-config-file-name "loaded_config_file_name")) + +(define-json-type + (config)) + +(define-json-type + (success) + (parse-error "parse_error") + (error)) + +(define-json-type + (success)) + +(define-json-type + (name)) + +(define-json-type + (send-events "send_events") + (tap) + (tap-button-map "tap_button_map") + (tap-drag "tap_drag") + (tap-drag-lock "tap_drag_lock") + (accel-speed "accel_speed") + (accel-profile "accel_profile") + (natural-scroll "natural_scroll") + (left-handed "left_handed") + (click-method "click_method") + (middle-emulation "middle_emulation") + (scroll-method "scroll_method") + (scroll-button "scroll_button") + (scroll-button-lock "scroll_button_lock") + (dwt) + (dwtp) + (calibration-matrix "calibration_matrix")) + +(define-json-type + (identifier) + (name) + (vendor) + (product) + (type) + (xkb-active-layout-name "xkb_active_layout_name") + (xkb-layout-names "xkb_layout_names") + (scroll-factor "scroll_factor") + (libinput )) + +(define-json-type + (name) + (capabilities) + (focus) + (devices "devices" #())) + +(define-json-type + (change) + (old "old" ) + (current "current" )) + +(define-json-type + (change)) + +(define-json-type + (change) + (pango-markup "pango_markup")) + +(define-json-type + (change) + (container "container" + (change) + (binding "binding" + (command) + (event-state-mask "event_state_mask") + (input-code "input_code") + (sybmol) + (input-type "input_type")) + +(define-json-type + (change)) + +(define-json-type + (first) + (paylaod)) + +(define-json-type + (id) + (visible-by-modifier "visible_by_modifier")) + +(define-json-type + (change) + (input "input" ))