├── config.conf ├── preview.png ├── .gitattributes ├── src ├── css.hpp ├── config_parser.hpp ├── key.hpp ├── main.hpp ├── css.cpp ├── key.cpp ├── layout.hpp ├── window.hpp ├── config_parser.cpp ├── os-compatibility.h ├── layouts.hpp ├── window.cpp ├── main.cpp ├── protos.cpp ├── os-compatibility.c ├── layout.cpp └── keymap.tpp ├── .gitignore ├── README.md ├── style.css ├── Makefile ├── proto ├── virtual-keyboard-unstable-v1.xml └── input-method-unstable-v2.xml └── LICENSE /config.conf: -------------------------------------------------------------------------------- 1 | [main] 2 | margin=10 3 | height=500 4 | layout=full 5 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/System64fumo/sysboard/HEAD/preview.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /src/css.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class css_loader : public Glib::RefPtr { 4 | public: 5 | css_loader(const std::string &path, Gtk::Window *window); 6 | }; 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | build/ 3 | src/git_info.hpp 4 | src/input-method-unstable-v2.c 5 | src/input-method-unstable-v2.h 6 | src/virtual-keyboard-unstable-v1.c 7 | src/virtual-keyboard-unstable-v1.h 8 | -------------------------------------------------------------------------------- /src/config_parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | // INI parser 6 | class config_parser { 7 | public: 8 | config_parser(const std::string&); 9 | std::map> data; 10 | bool available; 11 | 12 | private: 13 | std::string trim(const std::string&); 14 | }; 15 | -------------------------------------------------------------------------------- /src/key.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class key : public Gtk::Box { 6 | public: 7 | key(const int &code, const std::string &label, const std::string &label_shift); 8 | void set_shift(const bool &state); 9 | 10 | int code; 11 | std::string label; 12 | std::string label_shift; 13 | 14 | private: 15 | Gtk::Label label_main; 16 | }; 17 | -------------------------------------------------------------------------------- /src/main.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class sysboard; 6 | sysboard* window; 7 | 8 | typedef sysboard* (*sysboard_create_func)(const std::map>&); 9 | sysboard_create_func sysboard_create_ptr; 10 | 11 | typedef void (*sysboard_handle_signal_func)(sysboard*, int); 12 | sysboard_handle_signal_func sysboard_handle_signal_ptr; 13 | -------------------------------------------------------------------------------- /src/css.cpp: -------------------------------------------------------------------------------- 1 | #include "css.hpp" 2 | #include 3 | #include 4 | 5 | css_loader::css_loader(const std::string &path, Gtk::Window *window) { 6 | if (!std::filesystem::exists(path)) 7 | return; 8 | 9 | auto css = Gtk::CssProvider::create(); 10 | css->load_from_path(path); 11 | auto style_context = window->get_style_context(); 12 | style_context->add_provider_for_display(window->property_display(), css, GTK_STYLE_PROVIDER_PRIORITY_USER); 13 | } 14 | -------------------------------------------------------------------------------- /src/key.cpp: -------------------------------------------------------------------------------- 1 | #include "key.hpp" 2 | 3 | key::key(const int &code, const std::string &label, const std::string &label_shift) : code(code), label(label), label_shift(label_shift) { 4 | append(label_main); 5 | label_main.set_hexpand(true); 6 | 7 | // TODO: Add different handling for special keys 8 | add_css_class("key-" + label); 9 | add_css_class("key"); 10 | set_shift(false); 11 | } 12 | 13 | void key::set_shift(const bool &state) { 14 | label_main.set_text(state ? label_shift : label); 15 | } 16 | -------------------------------------------------------------------------------- /src/layout.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | class sysboard; 7 | class key; 8 | 9 | class layout : public Gtk::Grid { 10 | public: 11 | layout(sysboard* win, const std::string&); 12 | void handle_keycode(key*, const bool&); 13 | 14 | private: 15 | sysboard *window; 16 | std::string keymap_name; 17 | 18 | std::map>>> layout_map; 19 | std::vector>> keymap; 20 | std::map mod_map; 21 | int mods; 22 | long last_shift_time; 23 | bool shift_held; 24 | bool shift_temp; 25 | 26 | void load(); 27 | long get_time_in_us(); 28 | }; 29 | -------------------------------------------------------------------------------- /src/window.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "virtual-keyboard-unstable-v1.h" 5 | #include "input-method-unstable-v2.h" 6 | 7 | class layout; 8 | 9 | class sysboard : public Gtk::Window { 10 | public: 11 | sysboard(const std::map>&); 12 | std::map> config_main; 13 | bool manual_mode = false; 14 | 15 | zwp_virtual_keyboard_manager_v1* keyboard_manager; 16 | zwp_input_method_manager_v2* input_method_manager; 17 | 18 | void create_virtual_keyboard(); 19 | void create_input_manager(); 20 | void press_key(const int&, const int&); 21 | void set_modifier(const int&); 22 | void load_layout(); 23 | void handle_signal(const int&, const bool& manual = false); 24 | 25 | private: 26 | sigc::connection timeout_connection; 27 | GdkDisplay *gdk_display; 28 | GdkSeat *gdk_seat; 29 | wl_seat *seat; 30 | 31 | zwp_virtual_keyboard_v1* virtual_keyboard; 32 | zwp_input_method_v2* input_method; 33 | layout *layout_board; 34 | 35 | void initialize_protos(); 36 | }; 37 | 38 | extern "C" { 39 | sysboard *sysboard_create(const std::map>&); 40 | void sysboard_signal(sysboard*, int); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/config_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "config_parser.hpp" 2 | #include 3 | #include 4 | 5 | config_parser::config_parser(const std::string& filename) { 6 | std::ifstream file(filename); 7 | std::string line; 8 | std::string current_section; 9 | 10 | available = file.is_open(); 11 | 12 | if (available) { 13 | while (std::getline(file, line)) { 14 | line = trim(line); 15 | 16 | if (line.empty() || line[0] == ';' || line[0] == '#') { 17 | continue; 18 | } 19 | else if (line[0] == '[' && line[line.size() - 1] == ']') { 20 | current_section = line.substr(1, line.size() - 2); 21 | } 22 | else { 23 | size_t delimiter_pos = line.find('='); 24 | if (delimiter_pos != std::string::npos) { 25 | std::string key = trim(line.substr(0, delimiter_pos)); 26 | std::string value = trim(line.substr(delimiter_pos + 1)); 27 | data[current_section][key] = value; 28 | } 29 | } 30 | } 31 | file.close(); 32 | } 33 | else { 34 | std::fprintf(stderr, "Unable to open file: %s\n", filename.c_str()); 35 | } 36 | } 37 | 38 | std::string config_parser::trim(const std::string& str) { 39 | const size_t first = str.find_first_not_of(' '); 40 | if (std::string::npos == first) { 41 | return str; 42 | } 43 | const size_t last = str.find_last_not_of(' '); 44 | return str.substr(first, (last - first + 1)); 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sysboard 2 | sysboard is a simple virtual keyboard (On screen keyboard) for wayland written in gtkmm 4
3 | ![preview](https://github.com/System64fumo/sysboard/blob/main/preview.png "preview") 4 | 5 | [![Packaging status](https://repology.org/badge/vertical-allrepos/sysboard.svg)](https://repology.org/project/sysboard/versions) 6 | 7 | # Configuration 8 | sysboard can be configured in 3 ways
9 | 1: By changing config.hpp and recompiling (Suckless style)
10 | 2: Using a config file (~/.config/sys64/board/config.conf)
11 | 3: Using launch arguments
12 | ``` 13 | arguments: 14 | -m Set margin 15 | -H Set height 16 | -l Set layout (full, mobile, mobile_numbers) 17 | -v Prints version info 18 | ``` 19 | 20 | # Signals 21 | While the keyboard can show up on it's own, Sometimes you might want to trigger it manually
22 | You can send signals to show/hide the window
23 | ``pkill -USR1 sysboard`` to show
24 | ``pkill -USR2 sysboard`` to hide
25 | ``pkill -RTMIN sysboard`` to toggle
26 | Note: When triggered manually it will not hide on it's own
27 | 28 | # Theming 29 | sysboard uses your gtk4 theme by default, However it can be also load custom css,
30 | Just copy the included style.css file to ~/.config/sys64/board/style.css
31 | 32 | # Also check out 33 | [wvkbd](https://github.com/jjsullivan5196/wvkbd)
34 | [wf-osk](https://github.com/WayfireWM/wf-osk)
35 | -------------------------------------------------------------------------------- /src/os-compatibility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Collabora, Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef OS_COMPATIBILITY_H 27 | #define OS_COMPATIBILITY_H 28 | 29 | #include 30 | #ifdef __cplusplus 31 | extern "C" 32 | { 33 | int os_fd_set_cloexec(int fd); 34 | int os_socketpair_cloexec(int domain, int type, int protocol, int *sv); 35 | int os_epoll_create_cloexec(void); 36 | int os_create_anonymous_file(off_t size); 37 | #ifdef MISSING_STRCHRNUL 38 | char * strchrnul(const char *s, int c); 39 | #endif 40 | } 41 | #endif 42 | 43 | #endif /* OS_COMPATIBILITY_H */ 44 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | #sysboard { 2 | background: @theme_base_color; 3 | border-top: 1px solid @borders; 4 | transition: all 3s linear; 5 | } 6 | 7 | #sysboard label { 8 | background: mix(mix(@theme_base_color, CurrentColor, 0.15), blue, 0.005); 9 | border-top: 1px solid rgba(255, 255, 255, 0.05); 10 | border-radius: 6px; 11 | margin: 7px 3px 7px 3px; 12 | box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.1); 13 | font-size: 18px; 14 | transition: background-color 0.1s ease-out; 15 | } 16 | 17 | /* Custom colors */ 18 | #sysboard .full .key-Esc label, 19 | #sysboard .full .key-Tab label, 20 | #sysboard .full .key-Caps label, 21 | #sysboard .key-Shift label, 22 | #sysboard .full .key-Ctrl label, 23 | #sysboard .full .key-Alt label, 24 | #sysboard .full .key-Meta label, 25 | #sysboard .full .key-Space label, 26 | #sysboard .full .key-← label, 27 | #sysboard .full .key-↑ label, 28 | #sysboard .full .key-↓ label, 29 | #sysboard .full .key-→ label, 30 | #sysboard .key-Enter label, 31 | #sysboard .full .key-\\ label, 32 | #sysboard .key-Backspace label, 33 | #sysboard .key-123 label, 34 | #sysboard .key-abc label { 35 | background: mix(@theme_base_color, CurrentColor, 0.075); 36 | } 37 | 38 | #sysboard .key-Shift label, 39 | #sysboard .key-Backspace label, 40 | #sysboard .key-Space label, 41 | #sysboard .key-Enter label { 42 | font-size: 0px; 43 | background-position: center; 44 | background-size: 32px; 45 | background-repeat: no-repeat; 46 | } 47 | 48 | #sysboard .key-Shift label { 49 | background-image: -gtk-icontheme("keyboard-shift-symbolic"); 50 | } 51 | 52 | #sysboard .key-Backspace label { 53 | background-image: -gtk-icontheme("edit-clear-symbolic"); 54 | } 55 | #sysboard .key-Space label { 56 | background-image: -gtk-icontheme("keyboard-spacebar"); 57 | } 58 | #sysboard .key-Enter label { 59 | background-image: -gtk-icontheme("keyboard-enter"); 60 | } 61 | 62 | #sysboard .key.toggled label, 63 | #sysboard .key.pressed label { 64 | background-color: mix(@theme_base_color, CurrentColor, 0.25); 65 | } 66 | -------------------------------------------------------------------------------- /src/layouts.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Use this to create a new layout: https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h 3 | // Order: Width Code Label Label_Shift 4 | 5 | std::vector>> keymap_desktop = { 6 | {1, {"4 1 Esc Esc", "4 2 1 !", "4 3 2 @", "4 4 3 #", "4 5 4 $", "4 6 5 %", "4 7 6 ^", "4 8 7 &", " 4 9 8 *", "4 10 9 (", "4 11 0 )", "4 12 - _", "4 13 = +", "8 14 Backspace Backspace"}}, 7 | {1, {"5 15 Tab Tab", "4 16 q Q", "4 17 w W", "4 18 e E", "4 19 r R", "4 20 t T", "4 21 y Y", "4 22 u U", "4 23 i I", "4 24 o O", "4 25 p P", "4 26 [ {", "4 27 ] }", "7 43 \\ |"}}, 8 | {1, {"6 58 Caps Caps", "4 30 a A", "4 31 s S", "4 32 d D", "4 33 f F", "4 34 g G", "4 35 h H", "4 36 j J", "4 37 k K ", "4 38 l L", "4 39 ; :", "4 40 ' \"", "10 28 Enter Enter"}}, 9 | {1, {"8 42 Shift Shift", "4 44 z Z", "4 45 x X", "4 46 c C", "4 47 v V", "4 48 b B", "4 49 n N", "4 50 m M", "4 51 , <", "4 52 . >", "4 53 / ?", "12 54 Shift Shift"}}, 10 | {1, {"5 29 Ctrl Ctrl", "5 56 Alt Alt", "5 125 Meta Meta", "29 57 Space Space", "4 105 ← ←", "4 103 ↑ ↑", "4 108 ↓ ↓", "4 106 → →"}} 11 | }; 12 | 13 | std::vector>> keymap_mobile = { 14 | {2, {"3 1 Esc Esc", "3 15 Tab Tab", "2 29 Ctrl Ctrl", "2 56 Alt Alt", "2 53 / ?", "2 105 ← ←", "2 103 ↑ ↑", "2 108 ↓ ↓", "2 106 → →"}}, 15 | {3, {"2 16 q Q", "2 17 w W", "2 18 e E", "2 19 r R", "2 20 t T", "2 21 y Y", "2 22 u U", "2 23 i I", "2 24 o O", "2 25 p P"}}, 16 | {3, {"1 0 Pad Pad", "2 30 a A", "2 31 s S", "2 32 d D", "2 33 f F", "2 34 g G", "2 35 h H", "2 36 j J", "2 37 k K ", "2 38 l L", "1 0 Pad Pad"}}, 17 | {3, {"3 42 Shift Shift", "2 44 z Z", "2 45 x X", "2 46 c C", "2 47 v V", "2 48 b B", "2 49 n N", "2 50 m M", "3 14 Backspace Backspace"}}, 18 | {3, {"5 0 123 123", "10 57 Space Space", "5 28 Enter Enter"}} 19 | }; 20 | 21 | std::vector>> keymap_mobile_numbers = { 22 | {2, {"3 1 Esc Esc", "3 15 Tab Tab", "2 29 Ctrl Ctrl", "2 56 Alt Alt", "2 53 / ?", "2 105 ← ←", "2 103 ↑ ↑", "2 108 ↓ ↓", "2 106 → →"}}, 23 | {3, {"2 2 1 !", "2 3 2 @", "2 4 3 #", "2 5 4 $", "2 6 5 %", "2 7 6 ^", "2 8 7 &", " 2 9 8 *", "2 10 9 (", "2 11 0 )"}}, 24 | {3, {"2 0 Pad Pad", "2 12 - _", "2 13 = +", "2 26 [ {", "2 27 ] }", "2 43 \\ |", "2 39 ; :", "2 40 ' \"", "2 41 ` ~", "2 0 Pad Pad"}}, 25 | {3, {"3 42 Shift Shift", "4 0 Pad Pad", "2 51 , <", "2 52 . >", "2 53 / ?", "4 0 Pad Pad", "3 14 Backspace Backspace"}}, 26 | {3, {"5 0 abc abc", "10 57 Space Space", "5 28 Enter Enter"}} 27 | }; 28 | -------------------------------------------------------------------------------- /src/window.cpp: -------------------------------------------------------------------------------- 1 | #include "window.hpp" 2 | #include "layout.hpp" 3 | #include "css.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | sysboard::sysboard(const std::map>& cfg) { 11 | config_main = cfg; 12 | 13 | // Layer shell stuff 14 | gtk_layer_init_for_window(gobj()); 15 | gtk_layer_set_namespace(gobj(), "sysboard"); 16 | gtk_layer_set_layer(gobj(), GTK_LAYER_SHELL_LAYER_OVERLAY); 17 | gtk_layer_auto_exclusive_zone_enable(gobj()); 18 | 19 | gtk_layer_set_anchor(gobj(), GTK_LAYER_SHELL_EDGE_BOTTOM, true); 20 | gtk_layer_set_anchor(gobj(), GTK_LAYER_SHELL_EDGE_LEFT, true); 21 | gtk_layer_set_anchor(gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, true); 22 | 23 | // Initialization 24 | set_name("sysboard"); 25 | set_default_size(-1, stoi(config_main["main"]["height"])); 26 | initialize_protos(); 27 | load_layout(); 28 | 29 | // Load custom css 30 | std::string style_path; 31 | if (std::filesystem::exists(std::string(getenv("HOME")) + "/.config/sys64/board/style.css")) 32 | style_path = std::string(getenv("HOME")) + "/.config/sys64/board/style.css"; 33 | else if (std::filesystem::exists("/usr/share/sys64/board/style.css")) 34 | style_path = "/usr/share/sys64/board/style.css"; 35 | else 36 | style_path = "/usr/local/share/sys64/board/style.css"; 37 | css_loader css(style_path, this); 38 | } 39 | 40 | void sysboard::load_layout() { 41 | layout_board = Gtk::make_managed(this, config_main["main"]["layout"]); 42 | set_child(*layout_board); 43 | layout_board->set_margin(stoi(config_main["main"]["margin"])); 44 | } 45 | 46 | void sysboard::handle_signal(const int &signum, const bool& manual) { 47 | // Timeout exists to prevent a ping pong effect 48 | // Currently it's set to 250ms altho 100ms also works well enough 49 | timeout_connection.disconnect(); 50 | timeout_connection = Glib::signal_timeout().connect([&, signum, manual]() { 51 | Glib::signal_idle().connect([&, signum, manual]() { 52 | 53 | // Reset all active modifiers to prevent weird behavior 54 | set_modifier(0); 55 | 56 | if (signum == SIGUSR1) { // Show 57 | show(); 58 | } 59 | 60 | else if (signum == SIGUSR2) { // Hide 61 | layout_board->handle_keycode(nullptr, false); 62 | hide(); 63 | } 64 | 65 | else if (signum == SIGRTMIN) { // Toggle 66 | set_visible(!manual_mode); 67 | } 68 | 69 | if (manual) { 70 | manual_mode = get_visible(); 71 | } 72 | 73 | return false; 74 | }); 75 | return false; 76 | }, 250); 77 | } 78 | 79 | extern "C" { 80 | sysboard* sysboard_create(const std::map>& cfg) { 81 | return new sysboard(cfg); 82 | } 83 | void sysboard_signal(sysboard* window, int signal) { 84 | window->handle_signal(signal, true); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BINS = sysboard 2 | LIBS = libsysboard.so 3 | PKGS = gtkmm-4.0 gtk4-layer-shell-0 4 | SRCS = $(wildcard src/*.cpp) 5 | 6 | PREFIX ?= /usr/local 7 | BINDIR ?= $(PREFIX)/bin 8 | LIBDIR ?= $(PREFIX)/lib 9 | DATADIR ?= $(PREFIX)/share 10 | BUILDDIR = build 11 | 12 | CXXFLAGS += -Os -s -Wall -flto=auto -fno-exceptions -fPIC 13 | LDFLAGS += -Wl,-O1,--no-as-needed,-z,now,-z,pack-relative-relocs 14 | 15 | CXXFLAGS += $(shell pkg-config --cflags $(PKGS)) 16 | LDFLAGS += $(shell pkg-config --libs $(PKGS)) 17 | 18 | OBJS = $(patsubst src/%.cpp, $(BUILDDIR)/%.o, $(SRCS)) 19 | 20 | PROTOS = $(wildcard proto/*.xml) 21 | PROTO_HDRS = $(patsubst proto/%.xml, src/%.h, $(PROTOS)) 22 | PROTO_SRCS = $(patsubst proto/%.xml, src/%.c, $(PROTOS)) 23 | PROTO_OBJS = $(patsubst src/%.c, $(BUILDDIR)/%.o, $(PROTO_SRCS)) 24 | 25 | JOB_COUNT := $(BINS) $(LIBS) $(OBJS) $(PROTO_HDRS) $(PROTO_SRCS) $(PROTO_OBJS) $(BUILDDIR)/os-compatibility.o src/git_info.hpp 26 | JOBS_DONE := $(shell ls -l $(JOB_COUNT) 2> /dev/null | wc -l) 27 | 28 | define progress 29 | $(eval JOBS_DONE := $(shell echo $$(($(JOBS_DONE) + 1)))) 30 | @printf "[$(JOBS_DONE)/$(shell echo $(JOB_COUNT) | wc -w)] %s %s\n" $(1) $(2) 31 | endef 32 | 33 | all: $(BINS) $(LIBS) 34 | 35 | install: all 36 | @echo "Installing..." 37 | @install -D -t $(DESTDIR)$(BINDIR) $(BUILDDIR)/$(BINS) 38 | @install -D -t $(DESTDIR)$(LIBDIR) $(BUILDDIR)/$(LIBS) 39 | @install -D -t $(DESTDIR)$(DATADIR)/sys64/board config.conf style.css 40 | 41 | clean: 42 | @echo "Cleaning up" 43 | @rm -rf $(BUILDDIR) $(BINS) $(LIBS) $(PROTO_HDRS) $(PROTO_SRCS) src/git_info.hpp 44 | 45 | $(BINS): src/git_info.hpp $(BUILDDIR)/main.o $(BUILDDIR)/config_parser.o 46 | $(call progress, Linking $@) 47 | @$(CXX) -o $(BUILDDIR)/$@ \ 48 | $(BUILDDIR)/main.o \ 49 | $(BUILDDIR)/config_parser.o \ 50 | $(CXXFLAGS) \ 51 | $(LDFLAGS) -lwayland-client 52 | 53 | $(LIBS): $(PROTO_HDRS) $(PROTO_OBJS) $(OBJS) $(BUILDDIR)/os-compatibility.o 54 | $(call progress, Linking $@) 55 | @$(CXX) -o $(BUILDDIR)/$@ \ 56 | $(filter-out $(BUILDDIR)/main.o $(BUILDDIR)/config_parser.o, $(OBJS)) \ 57 | $(PROTO_OBJS) \ 58 | $(BUILDDIR)/os-compatibility.o \ 59 | $(CXXFLAGS) \ 60 | $(LDFLAGS) \ 61 | -shared 62 | 63 | $(BUILDDIR)/%.o: src/%.cpp 64 | @mkdir -p $(dir $@) 65 | $(call progress, Compiling $@) 66 | @$(CXX) -c $< -o $@ \ 67 | $(CXXFLAGS) 68 | 69 | $(BUILDDIR)/%.o: src/%.c 70 | @mkdir -p $(dir $@) 71 | $(call progress, Compiling $@) 72 | @$(CC) -c $< -o $@ $(CFLAGS) 73 | 74 | $(BUILDDIR)/os-compatibility.o: src/os-compatibility.c 75 | @mkdir -p $(dir $@) 76 | $(call progress, Compiling $@) 77 | @$(CC) -c $< -o $@ $(CFLAGS) 78 | 79 | $(PROTO_HDRS): src/%.h : proto/%.xml 80 | $(call progress, Creating $@) 81 | @wayland-scanner client-header $< $@ 82 | 83 | $(PROTO_SRCS): src/%.c : proto/%.xml 84 | $(call progress, Creating $@) 85 | @wayland-scanner public-code $< $@ 86 | 87 | src/git_info.hpp: 88 | $(call progress, Creating $@) 89 | @commit_hash=$$(git rev-parse HEAD); \ 90 | commit_date=$$(git show -s --format=%cd --date=short $$commit_hash); \ 91 | commit_message=$$(git show -s --format="%s" $$commit_hash | sed 's/"/\\\"/g'); \ 92 | echo "#define GIT_COMMIT_MESSAGE \"$$commit_message\"" > src/git_info.hpp; \ 93 | echo "#define GIT_COMMIT_DATE \"$$commit_date\"" >> src/git_info.hpp 94 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.hpp" 2 | #include "config_parser.hpp" 3 | #include "git_info.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | void handle_signal(int signum) { 10 | sysboard_handle_signal_ptr(window, signum); 11 | } 12 | 13 | void load_libsysboard() { 14 | void* handle = dlopen("libsysboard.so", RTLD_LAZY); 15 | if (!handle) { 16 | std::fprintf(stderr, "Cannot open library: %s\n", dlerror()); 17 | exit(1); 18 | } 19 | 20 | sysboard_create_ptr = (sysboard_create_func)dlsym(handle, "sysboard_create"); 21 | sysboard_handle_signal_ptr = (sysboard_handle_signal_func)dlsym(handle, "sysboard_signal"); 22 | 23 | if (!sysboard_create_ptr || !sysboard_handle_signal_ptr) { 24 | std::fprintf(stderr, "Cannot load symbols: %s\n", dlerror()); 25 | dlclose(handle); 26 | exit(1); 27 | } 28 | } 29 | 30 | int main(int argc, char *argv[]) { 31 | // Load the config 32 | std::string config_path; 33 | std::map> config; 34 | std::map> config_usr; 35 | 36 | bool cfg_sys = std::filesystem::exists("/usr/share/sys64/board/config.conf"); 37 | bool cfg_sys_local = std::filesystem::exists("/usr/local/share/sys64/board/config.conf"); 38 | bool cfg_usr = std::filesystem::exists(std::string(getenv("HOME")) + "/.config/sys64/board/config.conf"); 39 | 40 | // Load default config 41 | if (cfg_sys) 42 | config_path = "/usr/share/sys64/board/config.conf"; 43 | else if (cfg_sys_local) 44 | config_path = "/usr/local/share/sys64/board/config.conf"; 45 | else 46 | std::fprintf(stderr, "No default config found, Things will get funky!\n"); 47 | 48 | config = config_parser(config_path).data; 49 | 50 | // Load user config 51 | if (cfg_usr) 52 | config_path = std::string(getenv("HOME")) + "/.config/sys64/board/config.conf"; 53 | else 54 | std::fprintf(stderr, "No user config found\n"); 55 | 56 | config_usr = config_parser(config_path).data; 57 | 58 | // Merge configs 59 | for (const auto& [key, nested_map] : config_usr) 60 | for (const auto& [inner_key, inner_value] : nested_map) 61 | config[key][inner_key] = inner_value; 62 | 63 | // Sanity check 64 | if (!(cfg_sys || cfg_sys_local || cfg_usr)) { 65 | std::fprintf(stderr, "No config available, Something ain't right here."); 66 | return 1; 67 | } 68 | 69 | while (true) { 70 | switch(getopt(argc, argv, "m:H:l:vh")) { 71 | case 'm': 72 | config["main"]["margin"] = optarg; 73 | continue; 74 | 75 | case 'H': 76 | config["main"]["height"] = optarg; 77 | continue; 78 | 79 | case 'l': 80 | config["main"]["layout"] = optarg; 81 | continue; 82 | 83 | case 'v': 84 | std::printf("Commit: %s", GIT_COMMIT_MESSAGE); 85 | std::printf("Date: %s", GIT_COMMIT_DATE); 86 | return 0; 87 | 88 | case 'h': 89 | default : 90 | std::printf("usage:\n");; 91 | std::printf(" sysboard [argument...]:\n\n");; 92 | std::printf("arguments:\n");; 93 | std::printf(" -m Set margin\n");; 94 | std::printf(" -H Set height\n");; 95 | std::printf(" -l Set layout\n");; 96 | std::printf(" -v Prints version info\n");; 97 | std::printf(" -h Show this help message\n");; 98 | return 0; 99 | 100 | case -1: 101 | break; 102 | } 103 | 104 | break; 105 | } 106 | 107 | Glib::RefPtr app = Gtk::Application::create("funky.sys64.sysboard"); 108 | app->hold(); 109 | 110 | load_libsysboard(); 111 | window = sysboard_create_ptr(config); 112 | (void)window; // This is to avoid the unused variable warning 113 | 114 | // Catch signals 115 | signal(SIGUSR1, handle_signal); 116 | signal(SIGUSR2, handle_signal); 117 | signal(SIGRTMIN, handle_signal); 118 | 119 | return app->run(); 120 | } 121 | -------------------------------------------------------------------------------- /src/protos.cpp: -------------------------------------------------------------------------------- 1 | #include "window.hpp" 2 | #include "keymap.tpp" 3 | #include "os-compatibility.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | static void registry_handler(void* data, struct wl_registry* registry, 10 | uint32_t id, const char* interface, uint32_t version) { 11 | 12 | auto self = static_cast(data); 13 | 14 | if (strcmp(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0) { 15 | self->keyboard_manager = (zwp_virtual_keyboard_manager_v1*) 16 | wl_registry_bind(registry, id, 17 | &zwp_virtual_keyboard_manager_v1_interface, 1u); 18 | self->create_virtual_keyboard(); 19 | } 20 | else if (strcmp(interface, zwp_input_method_manager_v2_interface.name) == 0) { 21 | self->input_method_manager = (zwp_input_method_manager_v2*) 22 | wl_registry_bind(registry, id, 23 | &zwp_input_method_manager_v2_interface, 1u); 24 | self->create_input_manager(); 25 | } 26 | } 27 | 28 | static wl_registry_listener registry_listener = { 29 | ®istry_handler 30 | }; 31 | 32 | static void input_method_activate(void* data, struct zwp_input_method_v2* zwp_input_method_v2) { 33 | auto self = static_cast(data); 34 | if (!self->manual_mode) 35 | self->handle_signal(10); 36 | } 37 | 38 | static void input_method_deactivate(void* data, struct zwp_input_method_v2* zwp_input_method_v2) { 39 | auto self = static_cast(data); 40 | if (!self->manual_mode) 41 | self->handle_signal(12); 42 | } 43 | 44 | static void input_method_surrounding_text(void* data, 45 | struct zwp_input_method_v2* zwp_input_method_v2, 46 | const char* text, uint32_t cursor, uint32_t anchor) { 47 | // I could probably use this for autocomplete/autocorrect 48 | } 49 | 50 | static void input_method_text_change_cause(void *data, 51 | struct zwp_input_method_v2 *zwp_input_method_v2, 52 | uint32_t cause) {} 53 | 54 | static void input_method_content_type(void *data, 55 | struct zwp_input_method_v2 *zwp_input_method_v2, 56 | uint32_t hint, 57 | uint32_t purpose) { 58 | auto self = static_cast(data); 59 | if (purpose == 9) // Pin 60 | self->handle_signal(12); 61 | } 62 | 63 | static void input_method_done(void *data, struct zwp_input_method_v2 *zwp_input_method_v2) { 64 | auto wl_display = wl_display_connect(NULL); 65 | wl_display_roundtrip(wl_display); 66 | } 67 | 68 | static void input_method_unavailable(void *data, struct zwp_input_method_v2 *zwp_input_method_v2) {} 69 | 70 | static zwp_input_method_v2_listener input_method_listener = { 71 | .activate = input_method_activate, 72 | .deactivate = input_method_deactivate, 73 | .surrounding_text = input_method_surrounding_text, 74 | .text_change_cause = input_method_text_change_cause, 75 | .content_type = input_method_content_type, 76 | .done = input_method_done, 77 | .unavailable = input_method_unavailable, 78 | }; 79 | 80 | void sysboard::initialize_protos() { 81 | gdk_display = gdk_display_get_default(); 82 | gdk_seat = gdk_display_get_default_seat(gdk_display); 83 | seat = gdk_wayland_seat_get_wl_seat(gdk_seat); 84 | auto display = gdk_wayland_display_get_wl_display(gdk_display); 85 | auto registry = wl_display_get_registry(display); 86 | wl_registry_add_listener(registry, ®istry_listener, this); 87 | } 88 | 89 | void sysboard::create_virtual_keyboard() { 90 | virtual_keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( 91 | keyboard_manager, seat); 92 | 93 | size_t keymap_size = strlen(keymap) + 1; 94 | int keymap_fd = os_create_anonymous_file(keymap_size); 95 | void *ptr = mmap(nullptr, keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymap_fd, 0); 96 | std::strcpy((char*)ptr, keymap); 97 | 98 | zwp_virtual_keyboard_v1_keymap( 99 | virtual_keyboard, 100 | WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, 101 | keymap_fd, 102 | keymap_size); 103 | } 104 | 105 | void sysboard::create_input_manager() { 106 | input_method = zwp_input_method_manager_v2_get_input_method(input_method_manager, seat); 107 | zwp_input_method_v2_add_listener(input_method, &input_method_listener, this); 108 | } 109 | 110 | void sysboard::press_key(const int &keycode, const int &state) { 111 | timespec ts; 112 | clock_gettime(CLOCK_MONOTONIC, &ts); 113 | guint32 time = ts.tv_sec * 1000ll + ts.tv_nsec / 1000000ll; 114 | zwp_virtual_keyboard_v1_key(virtual_keyboard, time, keycode, state); 115 | } 116 | 117 | void sysboard::set_modifier(const int &mod) { 118 | zwp_virtual_keyboard_v1_modifiers(virtual_keyboard, 119 | mod, 0, 0, 0); 120 | } 121 | -------------------------------------------------------------------------------- /proto/virtual-keyboard-unstable-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright © 2008-2011 Kristian Høgsberg 5 | Copyright © 2010-2013 Intel Corporation 6 | Copyright © 2012-2013 Collabora, Ltd. 7 | Copyright © 2018 Purism SPC 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a 10 | copy of this software and associated documentation files (the "Software"), 11 | to deal in the Software without restriction, including without limitation 12 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | and/or sell copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice (including the next 17 | paragraph) shall be included in all copies or substantial portions of the 18 | Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | 30 | 31 | The virtual keyboard provides an application with requests which emulate 32 | the behaviour of a physical keyboard. 33 | 34 | This interface can be used by clients on its own to provide raw input 35 | events, or it can accompany the input method protocol. 36 | 37 | 38 | 39 | 40 | Provide a file descriptor to the compositor which can be 41 | memory-mapped to provide a keyboard mapping description. 42 | 43 | Format carries a value from the keymap_format enumeration. 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | A key was pressed or released. 57 | The time argument is a timestamp with millisecond granularity, with an 58 | undefined base. All requests regarding a single object must share the 59 | same clock. 60 | 61 | Keymap must be set before issuing this request. 62 | 63 | State carries a value from the key_state enumeration. 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | Notifies the compositor that the modifier and/or group state has 73 | changed, and it should update state. 74 | 75 | The client should use wl_keyboard.modifiers event to synchronize its 76 | internal state with seat state. 77 | 78 | Keymap must be set before issuing this request. 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | A virtual keyboard manager allows an application to provide keyboard 94 | input events as if they came from a physical keyboard. 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Creates a new virtual keyboard associated to a seat. 104 | 105 | If the compositor enables a keyboard to perform arbitrary actions, it 106 | should present an error when an untrusted client requests a new 107 | keyboard. 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /src/os-compatibility.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Collabora, Ltd. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #define _POSIX_C_SOURCE 200809L 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "os-compatibility.h" 38 | 39 | int 40 | os_fd_set_cloexec(int fd) 41 | { 42 | long flags; 43 | 44 | if (fd == -1) 45 | return -1; 46 | 47 | flags = fcntl(fd, F_GETFD); 48 | if (flags == -1) 49 | return -1; 50 | 51 | if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) 52 | return -1; 53 | 54 | return 0; 55 | } 56 | 57 | static int 58 | set_cloexec_or_close(int fd) 59 | { 60 | if (os_fd_set_cloexec(fd) != 0) { 61 | close(fd); 62 | return -1; 63 | } 64 | return fd; 65 | } 66 | 67 | int 68 | os_socketpair_cloexec(int domain, int type, int protocol, int *sv) 69 | { 70 | int ret; 71 | 72 | #ifdef SOCK_CLOEXEC 73 | ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); 74 | if (ret == 0 || errno != EINVAL) 75 | return ret; 76 | #endif 77 | 78 | ret = socketpair(domain, type, protocol, sv); 79 | if (ret < 0) 80 | return ret; 81 | 82 | sv[0] = set_cloexec_or_close(sv[0]); 83 | sv[1] = set_cloexec_or_close(sv[1]); 84 | 85 | if (sv[0] != -1 && sv[1] != -1) 86 | return 0; 87 | 88 | close(sv[0]); 89 | close(sv[1]); 90 | return -1; 91 | } 92 | 93 | int 94 | os_epoll_create_cloexec(void) 95 | { 96 | int fd; 97 | 98 | #ifdef EPOLL_CLOEXEC 99 | fd = epoll_create1(EPOLL_CLOEXEC); 100 | if (fd >= 0) 101 | return fd; 102 | if (errno != EINVAL) 103 | return -1; 104 | #endif 105 | 106 | fd = epoll_create(1); 107 | return set_cloexec_or_close(fd); 108 | } 109 | 110 | static int 111 | create_tmpfile_cloexec(char *tmpname) 112 | { 113 | int fd; 114 | 115 | #ifdef HAVE_MKOSTEMP 116 | fd = mkostemp(tmpname, O_CLOEXEC); 117 | if (fd >= 0) 118 | unlink(tmpname); 119 | #else 120 | fd = mkstemp(tmpname); 121 | if (fd >= 0) { 122 | fd = set_cloexec_or_close(fd); 123 | unlink(tmpname); 124 | } 125 | #endif 126 | 127 | return fd; 128 | } 129 | 130 | /* 131 | * Create a new, unique, anonymous file of the given size, and 132 | * return the file descriptor for it. The file descriptor is set 133 | * CLOEXEC. The file is immediately suitable for mmap()'ing 134 | * the given size at offset zero. 135 | * 136 | * The file should not have a permanent backing store like a disk, 137 | * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. 138 | * 139 | * The file name is deleted from the file system. 140 | * 141 | * The file is suitable for buffer sharing between processes by 142 | * transmitting the file descriptor over Unix sockets using the 143 | * SCM_RIGHTS methods. 144 | * 145 | * If the C library implements posix_fallocate(), it is used to 146 | * guarantee that disk space is available for the file at the 147 | * given size. If disk space is insufficient, errno is set to ENOSPC. 148 | * If posix_fallocate() is not supported, program may receive 149 | * SIGBUS on accessing mmap()'ed file contents instead. 150 | */ 151 | int 152 | os_create_anonymous_file(off_t size) 153 | { 154 | static const char template[] = "/weston-shared-XXXXXX"; 155 | const char *path; 156 | char *name; 157 | int fd; 158 | int ret; 159 | 160 | path = getenv("XDG_RUNTIME_DIR"); 161 | if (!path) { 162 | errno = ENOENT; 163 | return -1; 164 | } 165 | 166 | name = malloc(strlen(path) + sizeof(template)); 167 | if (!name) 168 | return -1; 169 | 170 | strcpy(name, path); 171 | strcat(name, template); 172 | 173 | fd = create_tmpfile_cloexec(name); 174 | 175 | free(name); 176 | 177 | if (fd < 0) 178 | return -1; 179 | 180 | #ifdef HAVE_POSIX_FALLOCATE 181 | do { 182 | ret = posix_fallocate(fd, 0, size); 183 | } while (ret == EINTR); 184 | if (ret != 0) { 185 | close(fd); 186 | errno = ret; 187 | return -1; 188 | } 189 | #else 190 | do { 191 | ret = ftruncate(fd, size); 192 | } while (ret < 0 && errno == EINTR); 193 | if (ret < 0) { 194 | close(fd); 195 | return -1; 196 | } 197 | #endif 198 | 199 | return fd; 200 | } 201 | 202 | #ifndef MISSING_STRCHRNUL 203 | char * 204 | strchrnul(const char *s, int c) 205 | { 206 | while (*s && *s != c) 207 | s++; 208 | return (char *)s; 209 | } 210 | #endif 211 | -------------------------------------------------------------------------------- /src/layout.cpp: -------------------------------------------------------------------------------- 1 | #include "layout.hpp" 2 | #include "layouts.hpp" 3 | #include "window.hpp" 4 | #include "key.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | layout::layout(sysboard *win, const std::string &keymap_name) : Gtk::Grid() { 11 | window = win; 12 | mods = 0; 13 | last_shift_time = 0; 14 | shift_held = false; 15 | shift_temp = false; 16 | this->keymap_name = keymap_name; 17 | 18 | // Layouts 19 | layout_map["full"] = keymap_desktop; 20 | layout_map["mobile"] = keymap_mobile; 21 | layout_map["mobile_numbers"] = keymap_mobile_numbers; 22 | 23 | // Modifiers 24 | mod_map[42] = 1; // Left Shift 25 | mod_map[54] = 1; // Right Shift 26 | mod_map[29] = 4; // Ctrl 27 | mod_map[56] = 8; // Alt 28 | mod_map[125] = 4; // Meta 29 | 30 | load(); 31 | } 32 | 33 | void layout::load() { 34 | keymap = layout_map[keymap_name]; 35 | add_css_class(keymap_name); 36 | set_column_homogeneous(true); 37 | set_row_homogeneous(true); 38 | 39 | // Rows 40 | unsigned int row_counter = 0; 41 | for (ulong i = 0; i < keymap.size(); ++i) { 42 | int height = keymap[i].first; 43 | 44 | // Columns 45 | unsigned int col_counter = 0; 46 | for (ulong j = 0; j < keymap[i].second.size(); ++j) { 47 | std::istringstream iss(keymap[i].second[j]); 48 | unsigned int width; 49 | int code; 50 | std::string label; 51 | std::string label_shift; 52 | iss >> width >> code >> label >> label_shift; 53 | 54 | if (label == "Pad") { 55 | Gtk::Box* kbd_key = Gtk::make_managed(); 56 | attach(*kbd_key, col_counter, row_counter, width, height); 57 | } 58 | else { 59 | key* kbd_key = Gtk::make_managed(code, label, label_shift); 60 | 61 | Glib::RefPtr gesture_click = Gtk::GestureClick::create(); 62 | kbd_key->add_controller(gesture_click); 63 | 64 | // Handle events 65 | gesture_click->signal_pressed().connect([&, kbd_key](int, double, double) { 66 | handle_keycode(kbd_key, true); 67 | }); 68 | gesture_click->signal_released().connect([&, kbd_key](int, double, double) { 69 | handle_keycode(kbd_key, false); 70 | }); 71 | attach(*kbd_key, col_counter, row_counter, width, height); 72 | } 73 | col_counter += width; 74 | } 75 | row_counter += height; 76 | } 77 | } 78 | 79 | void layout::handle_keycode(key *kbd_key, const bool &pressed) { 80 | if (kbd_key == nullptr) { 81 | keymap_name = window->config_main["main"]["layout"]; 82 | mods = 0; 83 | window->set_modifier(mods); 84 | 85 | for (auto& child : get_children()) 86 | remove(*child); 87 | 88 | load(); 89 | return; 90 | } 91 | 92 | auto style = kbd_key->get_style_context(); 93 | bool is_shift = kbd_key->code == 42 || kbd_key->code == 54; 94 | 95 | if (is_shift) { 96 | if (pressed) { 97 | long current_time = get_time_in_us(); 98 | long time_diff = current_time - last_shift_time; 99 | last_shift_time = current_time; 100 | 101 | if (shift_held) { 102 | // Release held shift 103 | shift_held = false; 104 | shift_temp = false; 105 | mods &= ~mod_map[kbd_key->code]; 106 | style->remove_class("toggled"); 107 | } 108 | else if (shift_temp && time_diff < 500000) { 109 | // Double tap: promote temp shift to shift hold 110 | shift_temp = false; 111 | shift_held = true; 112 | // Keep toggled class 113 | } 114 | else if (shift_temp) { 115 | // Single press when already temp: untoggle 116 | shift_temp = false; 117 | mods &= ~mod_map[kbd_key->code]; 118 | style->remove_class("toggled"); 119 | } 120 | else { 121 | // First press: temporary shift 122 | shift_temp = true; 123 | mods |= mod_map[kbd_key->code]; 124 | style->add_class("toggled"); 125 | } 126 | } 127 | 128 | window->set_modifier(mods); 129 | 130 | bool shift_active = mods & 1; 131 | for (auto& row : get_children()) { 132 | if (!row->has_css_class("key")) continue; 133 | auto row_key = static_cast(row); 134 | row_key->set_shift(shift_active); 135 | } 136 | return; 137 | } 138 | 139 | // Handle other modifiers 140 | if (mod_map.find(kbd_key->code) != mod_map.end()) { 141 | if (!pressed) 142 | return; 143 | 144 | if (style->has_class("toggled")) { 145 | style->remove_class("toggled"); 146 | mods -= mod_map[kbd_key->code]; 147 | window->set_modifier(mods); 148 | window->press_key(kbd_key->code, 0); 149 | } 150 | else { 151 | style->add_class("toggled"); 152 | mods += mod_map[kbd_key->code]; 153 | window->set_modifier(mods); 154 | window->press_key(kbd_key->code, 1); 155 | } 156 | 157 | bool shift_active = mods & 1; 158 | for (auto& row : get_children()) { 159 | if (!row->has_css_class("key")) continue; 160 | auto row_key = static_cast(row); 161 | row_key->set_shift(shift_active); 162 | } 163 | return; 164 | } 165 | 166 | // Normal key press/release 167 | if (pressed) { 168 | style->add_class("pressed"); 169 | window->press_key(kbd_key->code, 1); 170 | } 171 | else { 172 | style->remove_class("pressed"); 173 | window->press_key(kbd_key->code, 0); 174 | } 175 | 176 | // Clear temporary shift after one use 177 | if (shift_temp && !shift_held) { 178 | shift_temp = false; 179 | mods &= ~1; // Only remove shift modifier, not all modifiers 180 | window->set_modifier(mods); 181 | 182 | for (auto& row : get_children()) { 183 | if (!row->has_css_class("key")) continue; 184 | key* kbd_button = static_cast(row); 185 | kbd_button->set_shift(false); 186 | // Only remove toggled class from shift keys 187 | if (kbd_button->code == 42 || kbd_button->code == 54) { 188 | kbd_button->get_style_context()->remove_class("toggled"); 189 | } 190 | } 191 | } 192 | 193 | // Handle layout switching (e.g. 123/abc key) 194 | if (!pressed && kbd_key->code == 0) { 195 | if (kbd_key->label == "123") 196 | keymap_name = "mobile_numbers"; 197 | else if (kbd_key->label == "abc") 198 | keymap_name = "mobile"; 199 | 200 | for (auto& child : get_children()) 201 | remove(*child); 202 | 203 | mods = 0; 204 | window->set_modifier(mods); 205 | load(); 206 | } 207 | } 208 | 209 | long layout::get_time_in_us() { 210 | struct timeval tv; 211 | gettimeofday(&tv, nullptr); 212 | return (tv.tv_sec * 1000000 + tv.tv_usec); 213 | } -------------------------------------------------------------------------------- /proto/input-method-unstable-v2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright © 2008-2011 Kristian Høgsberg 6 | Copyright © 2010-2011 Intel Corporation 7 | Copyright © 2012-2013 Collabora, Ltd. 8 | Copyright © 2012, 2013 Intel Corporation 9 | Copyright © 2015, 2016 Jan Arne Petersen 10 | Copyright © 2017, 2018 Red Hat, Inc. 11 | Copyright © 2018 Purism SPC 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a 14 | copy of this software and associated documentation files (the "Software"), 15 | to deal in the Software without restriction, including without limitation 16 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | and/or sell copies of the Software, and to permit persons to whom the 18 | Software is furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice (including the next 21 | paragraph) shall be included in all copies or substantial portions of the 22 | Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 | DEALINGS IN THE SOFTWARE. 31 | 32 | 33 | 34 | This protocol allows applications to act as input methods for compositors. 35 | 36 | An input method context is used to manage the state of the input method. 37 | 38 | Text strings are UTF-8 encoded, their indices and lengths are in bytes. 39 | 40 | This document adheres to the RFC 2119 when using words like "must", 41 | "should", "may", etc. 42 | 43 | Warning! The protocol described in this file is experimental and 44 | backward incompatible changes may be made. Backward compatible changes 45 | may be added together with the corresponding interface version bump. 46 | Backward incompatible changes are done by bumping the version number in 47 | the protocol and interface names and resetting the interface version. 48 | Once the protocol is to be declared stable, the 'z' prefix and the 49 | version number in the protocol and interface names are removed and the 50 | interface version number is reset. 51 | 52 | 53 | 54 | 55 | An input method object allows for clients to compose text. 56 | 57 | The objects connects the client to a text input in an application, and 58 | lets the client to serve as an input method for a seat. 59 | 60 | The zwp_input_method_v2 object can occupy two distinct states: active and 61 | inactive. In the active state, the object is associated to and 62 | communicates with a text input. In the inactive state, there is no 63 | associated text input, and the only communication is with the compositor. 64 | Initially, the input method is in the inactive state. 65 | 66 | Requests issued in the inactive state must be accepted by the compositor. 67 | Because of the serial mechanism, and the state reset on activate event, 68 | they will not have any effect on the state of the next text input. 69 | 70 | There must be no more than one input method object per seat. 71 | 72 | 73 | 74 | 75 | Notification that a text input focused on this seat requested the input 76 | method to be activated. 77 | 78 | This event serves the purpose of providing the compositor with an 79 | active input method. 80 | 81 | This event resets all state associated with previous enable, disable, 82 | surrounding_text, text_change_cause, and content_type events, as well 83 | as the state associated with set_preedit_string, commit_string, and 84 | delete_surrounding_text requests. In addition, it marks the 85 | zwp_input_method_v2 object as active, and makes any existing 86 | zwp_input_popup_surface_v2 objects visible. 87 | 88 | The surrounding_text, and content_type events must follow before the 89 | next done event if the text input supports the respective 90 | functionality. 91 | 92 | State set with this event is double-buffered. It will get applied on 93 | the next zwp_input_method_v2.done event, and stay valid until changed. 94 | 95 | 96 | 97 | 98 | 99 | Notification that no focused text input currently needs an active 100 | input method on this seat. 101 | 102 | This event marks the zwp_input_method_v2 object as inactive. The 103 | compositor must make all existing zwp_input_popup_surface_v2 objects 104 | invisible until the next activate event. 105 | 106 | State set with this event is double-buffered. It will get applied on 107 | the next zwp_input_method_v2.done event, and stay valid until changed. 108 | 109 | 110 | 111 | 112 | 113 | Updates the surrounding plain text around the cursor, excluding the 114 | preedit text. 115 | 116 | If any preedit text is present, it is replaced with the cursor for the 117 | purpose of this event. 118 | 119 | The argument text is a buffer containing the preedit string, and must 120 | include the cursor position, and the complete selection. It should 121 | contain additional characters before and after these. There is a 122 | maximum length of wayland messages, so text can not be longer than 4000 123 | bytes. 124 | 125 | cursor is the byte offset of the cursor within the text buffer. 126 | 127 | anchor is the byte offset of the selection anchor within the text 128 | buffer. If there is no selected text, anchor must be the same as 129 | cursor. 130 | 131 | If this event does not arrive before the first done event, the input 132 | method may assume that the text input does not support this 133 | functionality and ignore following surrounding_text events. 134 | 135 | Values set with this event are double-buffered. They will get applied 136 | and set to initial values on the next zwp_input_method_v2.done 137 | event. 138 | 139 | The initial state for affected fields is empty, meaning that the text 140 | input does not support sending surrounding text. If the empty values 141 | get applied, subsequent attempts to change them may have no effect. 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | Tells the input method why the text surrounding the cursor changed. 151 | 152 | Whenever the client detects an external change in text, cursor, or 153 | anchor position, it must issue this request to the compositor. This 154 | request is intended to give the input method a chance to update the 155 | preedit text in an appropriate way, e.g. by removing it when the user 156 | starts typing with a keyboard. 157 | 158 | cause describes the source of the change. 159 | 160 | The value set with this event is double-buffered. It will get applied 161 | and set to its initial value on the next zwp_input_method_v2.done 162 | event. 163 | 164 | The initial value of cause is input_method. 165 | 166 | 167 | 168 | 169 | 170 | 171 | Indicates the content type and hint for the current 172 | zwp_input_method_v2 instance. 173 | 174 | Values set with this event are double-buffered. They will get applied 175 | on the next zwp_input_method_v2.done event. 176 | 177 | The initial value for hint is none, and the initial value for purpose 178 | is normal. 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | Atomically applies state changes recently sent to the client. 187 | 188 | The done event establishes and updates the state of the client, and 189 | must be issued after any changes to apply them. 190 | 191 | Text input state (content purpose, content hint, surrounding text, and 192 | change cause) is conceptually double-buffered within an input method 193 | context. 194 | 195 | Events modify the pending state, as opposed to the current state in use 196 | by the input method. A done event atomically applies all pending state, 197 | replacing the current state. After done, the new pending state is as 198 | documented for each related request. 199 | 200 | Events must be applied in the order of arrival. 201 | 202 | Neither current nor pending state are modified unless noted otherwise. 203 | 204 | 205 | 206 | 207 | 208 | Send the commit string text for insertion to the application. 209 | 210 | Inserts a string at current cursor position (see commit event 211 | sequence). The string to commit could be either just a single character 212 | after a key press or the result of some composing. 213 | 214 | The argument text is a buffer containing the string to insert. There is 215 | a maximum length of wayland messages, so text can not be longer than 216 | 4000 bytes. 217 | 218 | Values set with this event are double-buffered. They must be applied 219 | and reset to initial on the next zwp_text_input_v3.commit request. 220 | 221 | The initial value of text is an empty string. 222 | 223 | 224 | 225 | 226 | 227 | 228 | Send the pre-edit string text to the application text input. 229 | 230 | Place a new composing text (pre-edit) at the current cursor position. 231 | Any previously set composing text must be removed. Any previously 232 | existing selected text must be removed. The cursor is moved to a new 233 | position within the preedit string. 234 | 235 | The argument text is a buffer containing the preedit string. There is 236 | a maximum length of wayland messages, so text can not be longer than 237 | 4000 bytes. 238 | 239 | The arguments cursor_begin and cursor_end are counted in bytes relative 240 | to the beginning of the submitted string buffer. Cursor should be 241 | hidden by the text input when both are equal to -1. 242 | 243 | cursor_begin indicates the beginning of the cursor. cursor_end 244 | indicates the end of the cursor. It may be equal or different than 245 | cursor_begin. 246 | 247 | Values set with this event are double-buffered. They must be applied on 248 | the next zwp_input_method_v2.commit event. 249 | 250 | The initial value of text is an empty string. The initial value of 251 | cursor_begin, and cursor_end are both 0. 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | Remove the surrounding text. 261 | 262 | before_length and after_length are the number of bytes before and after 263 | the current cursor index (excluding the preedit text) to delete. 264 | 265 | If any preedit text is present, it is replaced with the cursor for the 266 | purpose of this event. In effect before_length is counted from the 267 | beginning of preedit text, and after_length from its end (see commit 268 | event sequence). 269 | 270 | Values set with this event are double-buffered. They must be applied 271 | and reset to initial on the next zwp_input_method_v2.commit request. 272 | 273 | The initial values of both before_length and after_length are 0. 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | Apply state changes from commit_string, set_preedit_string and 282 | delete_surrounding_text requests. 283 | 284 | The state relating to these events is double-buffered, and each one 285 | modifies the pending state. This request replaces the current state 286 | with the pending state. 287 | 288 | The connected text input is expected to proceed by evaluating the 289 | changes in the following order: 290 | 291 | 1. Replace existing preedit string with the cursor. 292 | 2. Delete requested surrounding text. 293 | 3. Insert commit string with the cursor at its end. 294 | 4. Calculate surrounding text to send. 295 | 5. Insert new preedit text in cursor position. 296 | 6. Place cursor inside preedit text. 297 | 298 | The serial number reflects the last state of the zwp_input_method_v2 299 | object known to the client. The value of the serial argument must be 300 | equal to the number of done events already issued by that object. When 301 | the compositor receives a commit request with a serial different than 302 | the number of past done events, it must proceed as normal, except it 303 | should not change the current state of the zwp_input_method_v2 object. 304 | 305 | 306 | 307 | 308 | 309 | 310 | Creates a new zwp_input_popup_surface_v2 object wrapping a given 311 | surface. 312 | 313 | The surface gets assigned the "input_popup" role. If the surface 314 | already has an assigned role, the compositor must issue a protocol 315 | error. 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | Allow an input method to receive hardware keyboard input and process 324 | key events to generate text events (with pre-edit) over the wire. This 325 | allows input methods which compose multiple key events for inputting 326 | text like it is done for CJK languages. 327 | 328 | The compositor should send all keyboard events on the seat to the grab 329 | holder via the returned wl_keyboard object. Nevertheless, the 330 | compositor may decide not to forward any particular event. The 331 | compositor must not further process any event after it has been 332 | forwarded to the grab holder. 333 | 334 | Releasing the resulting wl_keyboard object releases the grab. 335 | 336 | 338 | 339 | 340 | 341 | 342 | The input method ceased to be available. 343 | 344 | The compositor must issue this event as the only event on the object if 345 | there was another input_method object associated with the same seat at 346 | the time of its creation. 347 | 348 | The compositor must issue this request when the object is no longer 349 | useable, e.g. due to seat removal. 350 | 351 | The input method context becomes inert and should be destroyed after 352 | deactivation is handled. Any further requests and events except for the 353 | destroy request must be ignored. 354 | 355 | 356 | 357 | 358 | 359 | Destroys the zwp_text_input_v2 object and any associated child 360 | objects, i.e. zwp_input_popup_surface_v2 and 361 | zwp_input_method_keyboard_grab_v2. 362 | 363 | 364 | 365 | 366 | 367 | 368 | This interface marks a surface as a popup for interacting with an input 369 | method. 370 | 371 | The compositor should place it near the active text input area. It must 372 | be visible if and only if the input method is in the active state. 373 | 374 | The client must not destroy the underlying wl_surface while the 375 | zwp_input_popup_surface_v2 object exists. 376 | 377 | 378 | 379 | 380 | Notify about the position of the area of the text input expressed as a 381 | rectangle in surface local coordinates. 382 | 383 | This is a hint to the input method telling it the relative position of 384 | the text being entered. 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | The zwp_input_method_keyboard_grab_v2 interface represents an exclusive 399 | grab of the wl_keyboard interface associated with the seat. 400 | 401 | 402 | 403 | 404 | This event provides a file descriptor to the client which can be 405 | memory-mapped to provide a keyboard mapping description. 406 | 407 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | A key was pressed or released. 416 | The time argument is a timestamp with millisecond granularity, with an 417 | undefined base. 418 | 419 | 420 | 421 | 422 | 424 | 425 | 426 | 427 | 428 | Notifies clients that the modifier and/or group state has changed, and 429 | it should update its local state. 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | Informs the client about the keyboard's repeat rate and delay. 445 | 446 | This event is sent as soon as the zwp_input_method_keyboard_grab_v2 447 | object has been created, and is guaranteed to be received by the 448 | client before any key press event. 449 | 450 | Negative values for either rate or delay are illegal. A rate of zero 451 | will disable any repeating (regardless of the value of delay). 452 | 453 | This event can be sent later on as well with a new value if necessary, 454 | so clients should continue listening for the event past the creation 455 | of zwp_input_method_keyboard_grab_v2. 456 | 457 | 459 | 461 | 462 | 463 | 464 | 465 | 466 | The input method manager allows the client to become the input method on 467 | a chosen seat. 468 | 469 | No more than one input method must be associated with any seat at any 470 | given time. 471 | 472 | 473 | 474 | 475 | Request a new input zwp_input_method_v2 object associated with a given 476 | seat. 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | Destroys the zwp_input_method_manager_v2 object. 485 | 486 | The zwp_input_method_v2 objects originating from it remain valid. 487 | 488 | 489 | 490 | 491 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 2025 system64fumo 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | sysboard Copyright (C) 2025 system64fumo 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /src/keymap.tpp: -------------------------------------------------------------------------------- 1 | static const char keymap[] = "xkb_keymap {\ 2 | xkb_keycodes \"(unnamed)\" {\ 3 | minimum = 8;\ 4 | maximum = 255;\ 5 | = 9;\ 6 | = 10;\ 7 | = 11;\ 8 | = 12;\ 9 | = 13;\ 10 | = 14;\ 11 | = 15;\ 12 | = 16;\ 13 | = 17;\ 14 | = 18;\ 15 | = 19;\ 16 | = 20;\ 17 | = 21;\ 18 | = 22;\ 19 | = 23;\ 20 | = 24;\ 21 | = 25;\ 22 | = 26;\ 23 | = 27;\ 24 | = 28;\ 25 | = 29;\ 26 | = 30;\ 27 | = 31;\ 28 | = 32;\ 29 | = 33;\ 30 | = 34;\ 31 | = 35;\ 32 | = 36;\ 33 | = 37;\ 34 | = 38;\ 35 | = 39;\ 36 | = 40;\ 37 | = 41;\ 38 | = 42;\ 39 | = 43;\ 40 | = 44;\ 41 | = 45;\ 42 | = 46;\ 43 | = 47;\ 44 | = 48;\ 45 | = 49;\ 46 | = 50;\ 47 | = 51;\ 48 | = 52;\ 49 | = 53;\ 50 | = 54;\ 51 | = 55;\ 52 | = 56;\ 53 | = 57;\ 54 | = 58;\ 55 | = 59;\ 56 | = 60;\ 57 | = 61;\ 58 | = 62;\ 59 | = 63;\ 60 | = 64;\ 61 | = 65;\ 62 | = 66;\ 63 | = 67;\ 64 | = 68;\ 65 | = 69;\ 66 | = 70;\ 67 | = 71;\ 68 | = 72;\ 69 | = 73;\ 70 | = 74;\ 71 | = 75;\ 72 | = 76;\ 73 | = 77;\ 74 | = 78;\ 75 | = 79;\ 76 | = 80;\ 77 | = 81;\ 78 | = 82;\ 79 | = 83;\ 80 | = 84;\ 81 | = 85;\ 82 | = 86;\ 83 | = 87;\ 84 | = 88;\ 85 | = 89;\ 86 | = 90;\ 87 | = 91;\ 88 | = 92;\ 89 | = 94;\ 90 | = 95;\ 91 | = 96;\ 92 | = 97;\ 93 | = 98;\ 94 | = 99;\ 95 | = 100;\ 96 | = 101;\ 97 | = 102;\ 98 | = 103;\ 99 | = 104;\ 100 | = 105;\ 101 | = 106;\ 102 | = 107;\ 103 | = 108;\ 104 | = 109;\ 105 | = 110;\ 106 | = 111;\ 107 | = 112;\ 108 | = 113;\ 109 | = 114;\ 110 | = 115;\ 111 | = 116;\ 112 | = 117;\ 113 | = 118;\ 114 | = 119;\ 115 | = 120;\ 116 | = 121;\ 117 | = 122;\ 118 | = 123;\ 119 | = 124;\ 120 | = 125;\ 121 | = 126;\ 122 | = 127;\ 123 | = 128;\ 124 | = 129;\ 125 | = 130;\ 126 | = 131;\ 127 | = 132;\ 128 | = 133;\ 129 | = 134;\ 130 | = 135;\ 131 | = 136;\ 132 | = 137;\ 133 | = 138;\ 134 | = 139;\ 135 | = 140;\ 136 | = 141;\ 137 | = 142;\ 138 | = 143;\ 139 | = 144;\ 140 | = 145;\ 141 | = 146;\ 142 | = 147;\ 143 | = 148;\ 144 | = 149;\ 145 | = 150;\ 146 | = 151;\ 147 | = 152;\ 148 | = 153;\ 149 | = 154;\ 150 | = 155;\ 151 | = 156;\ 152 | = 157;\ 153 | = 158;\ 154 | = 159;\ 155 | = 160;\ 156 | = 161;\ 157 | = 162;\ 158 | = 163;\ 159 | = 164;\ 160 | = 165;\ 161 | = 166;\ 162 | = 167;\ 163 | = 168;\ 164 | = 169;\ 165 | = 170;\ 166 | = 171;\ 167 | = 172;\ 168 | = 173;\ 169 | = 174;\ 170 | = 175;\ 171 | = 176;\ 172 | = 177;\ 173 | = 178;\ 174 | = 179;\ 175 | = 180;\ 176 | = 181;\ 177 | = 182;\ 178 | = 183;\ 179 | = 184;\ 180 | = 185;\ 181 | = 186;\ 182 | = 187;\ 183 | = 188;\ 184 | = 189;\ 185 | = 190;\ 186 | = 191;\ 187 | = 192;\ 188 | = 193;\ 189 | = 194;\ 190 | = 195;\ 191 | = 196;\ 192 | = 197;\ 193 | = 198;\ 194 | = 199;\ 195 | = 200;\ 196 | = 201;\ 197 | = 202;\ 198 | = 203;\ 199 | = 204;\ 200 | = 205;\ 201 | = 206;\ 202 | = 207;\ 203 | = 208;\ 204 | = 209;\ 205 | = 210;\ 206 | = 211;\ 207 | = 212;\ 208 | = 213;\ 209 | = 214;\ 210 | = 215;\ 211 | = 216;\ 212 | = 217;\ 213 | = 218;\ 214 | = 219;\ 215 | = 220;\ 216 | = 221;\ 217 | = 222;\ 218 | = 223;\ 219 | = 224;\ 220 | = 225;\ 221 | = 226;\ 222 | = 227;\ 223 | = 228;\ 224 | = 229;\ 225 | = 230;\ 226 | = 231;\ 227 | = 232;\ 228 | = 233;\ 229 | = 234;\ 230 | = 235;\ 231 | = 236;\ 232 | = 237;\ 233 | = 238;\ 234 | = 239;\ 235 | = 240;\ 236 | = 241;\ 237 | = 242;\ 238 | = 243;\ 239 | = 244;\ 240 | = 245;\ 241 | = 246;\ 242 | = 247;\ 243 | = 248;\ 244 | = 249;\ 245 | = 250;\ 246 | = 251;\ 247 | = 252;\ 248 | = 253;\ 249 | = 254;\ 250 | = 255;\ 251 | indicator 1 = \"Caps Lock\";\ 252 | indicator 2 = \"Num Lock\";\ 253 | indicator 3 = \"Scroll Lock\";\ 254 | indicator 4 = \"Compose\";\ 255 | indicator 5 = \"Kana\";\ 256 | indicator 6 = \"Sleep\";\ 257 | indicator 7 = \"Suspend\";\ 258 | indicator 8 = \"Mute\";\ 259 | indicator 9 = \"Misc\";\ 260 | indicator 10 = \"Mail\";\ 261 | indicator 11 = \"Charging\";\ 262 | indicator 12 = \"Shift Lock\";\ 263 | indicator 13 = \"Group 2\";\ 264 | indicator 14 = \"Mouse Keys\";\ 265 | alias = ;\ 266 | alias = ;\ 267 | alias = ;\ 268 | alias = ;\ 269 | alias = ;\ 270 | alias = ;\ 271 | alias = ;\ 272 | alias = ;\ 273 | alias = ;\ 274 | alias = ;\ 275 | alias = ;\ 276 | alias = ;\ 277 | alias = ;\ 278 | alias = ;\ 279 | alias = ;\ 280 | alias = ;\ 281 | alias = ;\ 282 | alias = ;\ 283 | alias = ;\ 284 | alias = ;\ 285 | alias = ;\ 286 | alias = ;\ 287 | alias = ;\ 288 | alias = ;\ 289 | alias = ;\ 290 | alias = ;\ 291 | alias = ;\ 292 | alias = ;\ 293 | alias = ;\ 294 | alias = ;\ 295 | alias = ;\ 296 | alias = ;\ 297 | alias = ;\ 298 | };\ 299 | \ 300 | xkb_types \"(unnamed)\" {\ 301 | virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;\ 302 | \ 303 | type \"ONE_LEVEL\" {\ 304 | modifiers= none;\ 305 | level_name[Level1]= \"Any\";\ 306 | };\ 307 | type \"TWO_LEVEL\" {\ 308 | modifiers= Shift;\ 309 | map[Shift]= Level2;\ 310 | level_name[Level1]= \"Base\";\ 311 | level_name[Level2]= \"Shift\";\ 312 | };\ 313 | type \"ALPHABETIC\" {\ 314 | modifiers= Shift+Lock;\ 315 | map[Shift]= Level2;\ 316 | map[Lock]= Level2;\ 317 | level_name[Level1]= \"Base\";\ 318 | level_name[Level2]= \"Caps\";\ 319 | };\ 320 | type \"SHIFT+ALT\" {\ 321 | modifiers= Shift+Alt;\ 322 | map[Shift+Alt]= Level2;\ 323 | level_name[Level1]= \"Base\";\ 324 | level_name[Level2]= \"Shift+Alt\";\ 325 | };\ 326 | type \"PC_SUPER_LEVEL2\" {\ 327 | modifiers= Mod4;\ 328 | map[Mod4]= Level2;\ 329 | level_name[Level1]= \"Base\";\ 330 | level_name[Level2]= \"Super\";\ 331 | };\ 332 | type \"PC_CONTROL_LEVEL2\" {\ 333 | modifiers= Control;\ 334 | map[Control]= Level2;\ 335 | level_name[Level1]= \"Base\";\ 336 | level_name[Level2]= \"Control\";\ 337 | };\ 338 | type \"PC_LCONTROL_LEVEL2\" {\ 339 | modifiers= LControl;\ 340 | map[LControl]= Level2;\ 341 | level_name[Level1]= \"Base\";\ 342 | level_name[Level2]= \"LControl\";\ 343 | };\ 344 | type \"PC_RCONTROL_LEVEL2\" {\ 345 | modifiers= RControl;\ 346 | map[RControl]= Level2;\ 347 | level_name[Level1]= \"Base\";\ 348 | level_name[Level2]= \"RControl\";\ 349 | };\ 350 | type \"PC_ALT_LEVEL2\" {\ 351 | modifiers= Alt;\ 352 | map[Alt]= Level2;\ 353 | level_name[Level1]= \"Base\";\ 354 | level_name[Level2]= \"Alt\";\ 355 | };\ 356 | type \"PC_LALT_LEVEL2\" {\ 357 | modifiers= LAlt;\ 358 | map[LAlt]= Level2;\ 359 | level_name[Level1]= \"Base\";\ 360 | level_name[Level2]= \"LAlt\";\ 361 | };\ 362 | type \"PC_RALT_LEVEL2\" {\ 363 | modifiers= RAlt;\ 364 | map[RAlt]= Level2;\ 365 | level_name[Level1]= \"Base\";\ 366 | level_name[Level2]= \"RAlt\";\ 367 | };\ 368 | type \"CTRL+ALT\" {\ 369 | modifiers= Shift+Control+Alt+LevelThree;\ 370 | map[Shift]= Level2;\ 371 | preserve[Shift]= Shift;\ 372 | map[LevelThree]= Level3;\ 373 | map[Shift+LevelThree]= Level4;\ 374 | preserve[Shift+LevelThree]= Shift;\ 375 | map[Control+Alt]= Level5;\ 376 | level_name[Level1]= \"Base\";\ 377 | level_name[Level2]= \"Shift\";\ 378 | level_name[Level3]= \"Alt Base\";\ 379 | level_name[Level4]= \"Shift Alt\";\ 380 | level_name[Level5]= \"Ctrl+Alt\";\ 381 | };\ 382 | type \"LOCAL_EIGHT_LEVEL\" {\ 383 | modifiers= Shift+Lock+Control+LevelThree;\ 384 | map[Shift]= Level2;\ 385 | map[Lock]= Level2;\ 386 | map[LevelThree]= Level3;\ 387 | map[Shift+Lock+LevelThree]= Level3;\ 388 | map[Shift+LevelThree]= Level4;\ 389 | map[Lock+LevelThree]= Level4;\ 390 | map[Control]= Level5;\ 391 | map[Shift+Lock+Control]= Level5;\ 392 | map[Shift+Control]= Level6;\ 393 | map[Lock+Control]= Level6;\ 394 | map[Control+LevelThree]= Level7;\ 395 | map[Shift+Lock+Control+LevelThree]= Level7;\ 396 | map[Shift+Control+LevelThree]= Level8;\ 397 | map[Lock+Control+LevelThree]= Level8;\ 398 | level_name[Level1]= \"Base\";\ 399 | level_name[Level2]= \"Shift\";\ 400 | level_name[Level3]= \"Level3\";\ 401 | level_name[Level4]= \"Shift Level3\";\ 402 | level_name[Level5]= \"Ctrl\";\ 403 | level_name[Level6]= \"Shift Ctrl\";\ 404 | level_name[Level7]= \"Level3 Ctrl\";\ 405 | level_name[Level8]= \"Shift Level3 Ctrl\";\ 406 | };\ 407 | type \"THREE_LEVEL\" {\ 408 | modifiers= Shift+LevelThree;\ 409 | map[Shift]= Level2;\ 410 | map[LevelThree]= Level3;\ 411 | map[Shift+LevelThree]= Level3;\ 412 | level_name[Level1]= \"Base\";\ 413 | level_name[Level2]= \"Shift\";\ 414 | level_name[Level3]= \"Level3\";\ 415 | };\ 416 | type \"EIGHT_LEVEL\" {\ 417 | modifiers= Shift+LevelThree+LevelFive;\ 418 | map[Shift]= Level2;\ 419 | map[LevelThree]= Level3;\ 420 | map[Shift+LevelThree]= Level4;\ 421 | map[LevelFive]= Level5;\ 422 | map[Shift+LevelFive]= Level6;\ 423 | map[LevelThree+LevelFive]= Level7;\ 424 | map[Shift+LevelThree+LevelFive]= Level8;\ 425 | level_name[Level1]= \"Base\";\ 426 | level_name[Level2]= \"Shift\";\ 427 | level_name[Level3]= \"Alt Base\";\ 428 | level_name[Level4]= \"Shift Alt\";\ 429 | level_name[Level5]= \"X\";\ 430 | level_name[Level6]= \"X Shift\";\ 431 | level_name[Level7]= \"X Alt Base\";\ 432 | level_name[Level8]= \"X Shift Alt\";\ 433 | };\ 434 | type \"EIGHT_LEVEL_ALPHABETIC\" {\ 435 | modifiers= Shift+Lock+LevelThree+LevelFive;\ 436 | map[Shift]= Level2;\ 437 | map[Lock]= Level2;\ 438 | map[LevelThree]= Level3;\ 439 | map[Shift+LevelThree]= Level4;\ 440 | map[Lock+LevelThree]= Level4;\ 441 | map[Shift+Lock+LevelThree]= Level3;\ 442 | map[LevelFive]= Level5;\ 443 | map[Shift+LevelFive]= Level6;\ 444 | map[Lock+LevelFive]= Level6;\ 445 | map[LevelThree+LevelFive]= Level7;\ 446 | map[Shift+LevelThree+LevelFive]= Level8;\ 447 | map[Lock+LevelThree+LevelFive]= Level8;\ 448 | map[Shift+Lock+LevelThree+LevelFive]= Level7;\ 449 | level_name[Level1]= \"Base\";\ 450 | level_name[Level2]= \"Shift\";\ 451 | level_name[Level3]= \"Alt Base\";\ 452 | level_name[Level4]= \"Shift Alt\";\ 453 | level_name[Level5]= \"X\";\ 454 | level_name[Level6]= \"X Shift\";\ 455 | level_name[Level7]= \"X Alt Base\";\ 456 | level_name[Level8]= \"X Shift Alt\";\ 457 | };\ 458 | type \"EIGHT_LEVEL_LEVEL_FIVE_LOCK\" {\ 459 | modifiers= Shift+Lock+NumLock+LevelThree+LevelFive;\ 460 | map[Shift]= Level2;\ 461 | map[LevelThree]= Level3;\ 462 | map[Shift+LevelThree]= Level4;\ 463 | map[LevelFive]= Level5;\ 464 | map[Shift+LevelFive]= Level6;\ 465 | preserve[Shift+LevelFive]= Shift;\ 466 | map[LevelThree+LevelFive]= Level7;\ 467 | map[Shift+LevelThree+LevelFive]= Level8;\ 468 | map[NumLock]= Level5;\ 469 | map[Shift+NumLock]= Level6;\ 470 | preserve[Shift+NumLock]= Shift;\ 471 | map[NumLock+LevelThree]= Level7;\ 472 | map[Shift+NumLock+LevelThree]= Level8;\ 473 | map[Shift+NumLock+LevelFive]= Level2;\ 474 | map[NumLock+LevelThree+LevelFive]= Level3;\ 475 | map[Shift+NumLock+LevelThree+LevelFive]= Level4;\ 476 | map[Shift+Lock]= Level2;\ 477 | map[Lock+LevelThree]= Level3;\ 478 | map[Shift+Lock+LevelThree]= Level4;\ 479 | map[Lock+LevelFive]= Level5;\ 480 | map[Shift+Lock+LevelFive]= Level6;\ 481 | preserve[Shift+Lock+LevelFive]= Shift;\ 482 | map[Lock+LevelThree+LevelFive]= Level7;\ 483 | map[Shift+Lock+LevelThree+LevelFive]= Level8;\ 484 | map[Lock+NumLock]= Level5;\ 485 | map[Shift+Lock+NumLock]= Level6;\ 486 | preserve[Shift+Lock+NumLock]= Shift;\ 487 | map[Lock+NumLock+LevelThree]= Level7;\ 488 | map[Shift+Lock+NumLock+LevelThree]= Level8;\ 489 | map[Shift+Lock+NumLock+LevelFive]= Level2;\ 490 | map[Lock+NumLock+LevelThree+LevelFive]= Level3;\ 491 | map[Shift+Lock+NumLock+LevelThree+LevelFive]= Level4;\ 492 | level_name[Level1]= \"Base\";\ 493 | level_name[Level2]= \"Shift\";\ 494 | level_name[Level3]= \"Alt Base\";\ 495 | level_name[Level4]= \"Shift Alt\";\ 496 | level_name[Level5]= \"X\";\ 497 | level_name[Level6]= \"X Shift\";\ 498 | level_name[Level7]= \"X Alt Base\";\ 499 | level_name[Level8]= \"X Shift Alt\";\ 500 | };\ 501 | type \"EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK\" {\ 502 | modifiers= Shift+Lock+NumLock+LevelThree+LevelFive;\ 503 | map[Shift]= Level2;\ 504 | map[LevelThree]= Level3;\ 505 | map[Shift+LevelThree]= Level4;\ 506 | map[LevelFive]= Level5;\ 507 | map[Shift+LevelFive]= Level6;\ 508 | preserve[Shift+LevelFive]= Shift;\ 509 | map[LevelThree+LevelFive]= Level7;\ 510 | map[Shift+LevelThree+LevelFive]= Level8;\ 511 | map[NumLock]= Level5;\ 512 | map[Shift+NumLock]= Level6;\ 513 | preserve[Shift+NumLock]= Shift;\ 514 | map[NumLock+LevelThree]= Level7;\ 515 | map[Shift+NumLock+LevelThree]= Level8;\ 516 | map[Shift+NumLock+LevelFive]= Level2;\ 517 | map[NumLock+LevelThree+LevelFive]= Level3;\ 518 | map[Shift+NumLock+LevelThree+LevelFive]= Level4;\ 519 | map[Lock]= Level2;\ 520 | map[Lock+LevelThree]= Level3;\ 521 | map[Shift+Lock+LevelThree]= Level4;\ 522 | map[Lock+LevelFive]= Level5;\ 523 | map[Shift+Lock+LevelFive]= Level6;\ 524 | map[Lock+LevelThree+LevelFive]= Level7;\ 525 | map[Shift+Lock+LevelThree+LevelFive]= Level8;\ 526 | map[Lock+NumLock]= Level5;\ 527 | map[Shift+Lock+NumLock]= Level6;\ 528 | map[Lock+NumLock+LevelThree]= Level7;\ 529 | map[Shift+Lock+NumLock+LevelThree]= Level8;\ 530 | map[Lock+NumLock+LevelFive]= Level2;\ 531 | map[Lock+NumLock+LevelThree+LevelFive]= Level4;\ 532 | map[Shift+Lock+NumLock+LevelThree+LevelFive]= Level3;\ 533 | level_name[Level1]= \"Base\";\ 534 | level_name[Level2]= \"Shift\";\ 535 | level_name[Level3]= \"Alt Base\";\ 536 | level_name[Level4]= \"Shift Alt\";\ 537 | level_name[Level5]= \"X\";\ 538 | level_name[Level6]= \"X Shift\";\ 539 | level_name[Level7]= \"X Alt Base\";\ 540 | level_name[Level8]= \"X Shift Alt\";\ 541 | };\ 542 | type \"EIGHT_LEVEL_SEMIALPHABETIC\" {\ 543 | modifiers= Shift+Lock+LevelThree+LevelFive;\ 544 | map[Shift]= Level2;\ 545 | map[Lock]= Level2;\ 546 | map[LevelThree]= Level3;\ 547 | map[Shift+LevelThree]= Level4;\ 548 | map[Lock+LevelThree]= Level3;\ 549 | preserve[Lock+LevelThree]= Lock;\ 550 | map[Shift+Lock+LevelThree]= Level4;\ 551 | preserve[Shift+Lock+LevelThree]= Lock;\ 552 | map[LevelFive]= Level5;\ 553 | map[Shift+LevelFive]= Level6;\ 554 | map[Lock+LevelFive]= Level6;\ 555 | preserve[Lock+LevelFive]= Lock;\ 556 | map[Shift+Lock+LevelFive]= Level6;\ 557 | preserve[Shift+Lock+LevelFive]= Lock;\ 558 | map[LevelThree+LevelFive]= Level7;\ 559 | map[Shift+LevelThree+LevelFive]= Level8;\ 560 | map[Lock+LevelThree+LevelFive]= Level7;\ 561 | preserve[Lock+LevelThree+LevelFive]= Lock;\ 562 | map[Shift+Lock+LevelThree+LevelFive]= Level8;\ 563 | preserve[Shift+Lock+LevelThree+LevelFive]= Lock;\ 564 | level_name[Level1]= \"Base\";\ 565 | level_name[Level2]= \"Shift\";\ 566 | level_name[Level3]= \"Alt Base\";\ 567 | level_name[Level4]= \"Shift Alt\";\ 568 | level_name[Level5]= \"X\";\ 569 | level_name[Level6]= \"X Shift\";\ 570 | level_name[Level7]= \"X Alt Base\";\ 571 | level_name[Level8]= \"X Shift Alt\";\ 572 | };\ 573 | type \"FOUR_LEVEL\" {\ 574 | modifiers= Shift+LevelThree;\ 575 | map[Shift]= Level2;\ 576 | map[LevelThree]= Level3;\ 577 | map[Shift+LevelThree]= Level4;\ 578 | level_name[Level1]= \"Base\";\ 579 | level_name[Level2]= \"Shift\";\ 580 | level_name[Level3]= \"Alt Base\";\ 581 | level_name[Level4]= \"Shift Alt\";\ 582 | };\ 583 | type \"FOUR_LEVEL_ALPHABETIC\" {\ 584 | modifiers= Shift+Lock+LevelThree;\ 585 | map[Shift]= Level2;\ 586 | map[Lock]= Level2;\ 587 | map[LevelThree]= Level3;\ 588 | map[Shift+LevelThree]= Level4;\ 589 | map[Lock+LevelThree]= Level4;\ 590 | map[Shift+Lock+LevelThree]= Level3;\ 591 | level_name[Level1]= \"Base\";\ 592 | level_name[Level2]= \"Shift\";\ 593 | level_name[Level3]= \"Alt Base\";\ 594 | level_name[Level4]= \"Shift Alt\";\ 595 | };\ 596 | type \"FOUR_LEVEL_SEMIALPHABETIC\" {\ 597 | modifiers= Shift+Lock+LevelThree;\ 598 | map[Shift]= Level2;\ 599 | map[Lock]= Level2;\ 600 | map[LevelThree]= Level3;\ 601 | map[Shift+LevelThree]= Level4;\ 602 | map[Lock+LevelThree]= Level3;\ 603 | preserve[Lock+LevelThree]= Lock;\ 604 | map[Shift+Lock+LevelThree]= Level4;\ 605 | preserve[Shift+Lock+LevelThree]= Lock;\ 606 | level_name[Level1]= \"Base\";\ 607 | level_name[Level2]= \"Shift\";\ 608 | level_name[Level3]= \"Alt Base\";\ 609 | level_name[Level4]= \"Shift Alt\";\ 610 | };\ 611 | type \"FOUR_LEVEL_MIXED_KEYPAD\" {\ 612 | modifiers= Shift+NumLock+LevelThree;\ 613 | map[NumLock]= Level2;\ 614 | map[Shift]= Level2;\ 615 | map[LevelThree]= Level3;\ 616 | map[NumLock+LevelThree]= Level3;\ 617 | map[Shift+LevelThree]= Level4;\ 618 | map[Shift+NumLock+LevelThree]= Level4;\ 619 | level_name[Level1]= \"Base\";\ 620 | level_name[Level2]= \"Number\";\ 621 | level_name[Level3]= \"Alt Base\";\ 622 | level_name[Level4]= \"Shift Alt\";\ 623 | };\ 624 | type \"FOUR_LEVEL_X\" {\ 625 | modifiers= Shift+Control+Alt+LevelThree;\ 626 | map[LevelThree]= Level2;\ 627 | map[Shift+LevelThree]= Level3;\ 628 | map[Control+Alt]= Level4;\ 629 | level_name[Level1]= \"Base\";\ 630 | level_name[Level2]= \"Alt Base\";\ 631 | level_name[Level3]= \"Shift Alt\";\ 632 | level_name[Level4]= \"Ctrl+Alt\";\ 633 | };\ 634 | type \"SEPARATE_CAPS_AND_SHIFT_ALPHABETIC\" {\ 635 | modifiers= Shift+Lock+LevelThree;\ 636 | map[Shift]= Level2;\ 637 | map[Lock]= Level4;\ 638 | preserve[Lock]= Lock;\ 639 | map[LevelThree]= Level3;\ 640 | map[Shift+LevelThree]= Level4;\ 641 | map[Lock+LevelThree]= Level3;\ 642 | preserve[Lock+LevelThree]= Lock;\ 643 | map[Shift+Lock+LevelThree]= Level3;\ 644 | level_name[Level1]= \"Base\";\ 645 | level_name[Level2]= \"Shift\";\ 646 | level_name[Level3]= \"AltGr Base\";\ 647 | level_name[Level4]= \"Shift AltGr\";\ 648 | };\ 649 | type \"FOUR_LEVEL_PLUS_LOCK\" {\ 650 | modifiers= Shift+Lock+LevelThree;\ 651 | map[Shift]= Level2;\ 652 | map[LevelThree]= Level3;\ 653 | map[Shift+LevelThree]= Level4;\ 654 | map[Lock]= Level5;\ 655 | map[Shift+Lock]= Level2;\ 656 | map[Lock+LevelThree]= Level3;\ 657 | map[Shift+Lock+LevelThree]= Level4;\ 658 | level_name[Level1]= \"Base\";\ 659 | level_name[Level2]= \"Shift\";\ 660 | level_name[Level3]= \"Alt Base\";\ 661 | level_name[Level4]= \"Shift Alt\";\ 662 | level_name[Level5]= \"Lock\";\ 663 | };\ 664 | type \"KEYPAD\" {\ 665 | modifiers= Shift+NumLock;\ 666 | map[Shift]= Level2;\ 667 | map[NumLock]= Level2;\ 668 | level_name[Level1]= \"Base\";\ 669 | level_name[Level2]= \"Number\";\ 670 | };\ 671 | type \"FOUR_LEVEL_KEYPAD\" {\ 672 | modifiers= Shift+NumLock+LevelThree;\ 673 | map[Shift]= Level2;\ 674 | map[NumLock]= Level2;\ 675 | map[LevelThree]= Level3;\ 676 | map[Shift+LevelThree]= Level4;\ 677 | map[NumLock+LevelThree]= Level4;\ 678 | map[Shift+NumLock+LevelThree]= Level3;\ 679 | level_name[Level1]= \"Base\";\ 680 | level_name[Level2]= \"Number\";\ 681 | level_name[Level3]= \"Alt Base\";\ 682 | level_name[Level4]= \"Alt Number\";\ 683 | };\ 684 | };\ 685 | \ 686 | xkb_compatibility \"(unnamed)\" {\ 687 | virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;\ 688 | \ 689 | interpret.useModMapMods= AnyLevel;\ 690 | interpret.repeat= False;\ 691 | interpret ISO_Level2_Latch+Exactly(Shift) {\ 692 | useModMapMods=level1;\ 693 | action= LatchMods(modifiers=Shift,clearLocks,latchToLock);\ 694 | };\ 695 | interpret Shift_Lock+AnyOf(Shift+Lock) {\ 696 | action= LockMods(modifiers=Shift);\ 697 | };\ 698 | interpret Num_Lock+AnyOf(all) {\ 699 | virtualModifier= NumLock;\ 700 | action= LockMods(modifiers=NumLock);\ 701 | };\ 702 | interpret ISO_Level3_Shift+AnyOf(all) {\ 703 | virtualModifier= LevelThree;\ 704 | useModMapMods=level1;\ 705 | action= SetMods(modifiers=LevelThree,clearLocks);\ 706 | };\ 707 | interpret ISO_Level3_Latch+AnyOf(all) {\ 708 | virtualModifier= LevelThree;\ 709 | useModMapMods=level1;\ 710 | action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);\ 711 | };\ 712 | interpret ISO_Level3_Lock+AnyOf(all) {\ 713 | virtualModifier= LevelThree;\ 714 | useModMapMods=level1;\ 715 | action= LockMods(modifiers=LevelThree);\ 716 | };\ 717 | interpret Alt_L+AnyOf(all) {\ 718 | virtualModifier= Alt;\ 719 | action= SetMods(modifiers=modMapMods,clearLocks);\ 720 | };\ 721 | interpret Alt_R+AnyOf(all) {\ 722 | virtualModifier= Alt;\ 723 | action= SetMods(modifiers=modMapMods,clearLocks);\ 724 | };\ 725 | interpret Meta_L+AnyOf(all) {\ 726 | virtualModifier= Meta;\ 727 | action= SetMods(modifiers=modMapMods,clearLocks);\ 728 | };\ 729 | interpret Meta_R+AnyOf(all) {\ 730 | virtualModifier= Meta;\ 731 | action= SetMods(modifiers=modMapMods,clearLocks);\ 732 | };\ 733 | interpret Super_L+AnyOf(all) {\ 734 | virtualModifier= Super;\ 735 | action= SetMods(modifiers=modMapMods,clearLocks);\ 736 | };\ 737 | interpret Super_R+AnyOf(all) {\ 738 | virtualModifier= Super;\ 739 | action= SetMods(modifiers=modMapMods,clearLocks);\ 740 | };\ 741 | interpret Hyper_L+AnyOf(all) {\ 742 | virtualModifier= Hyper;\ 743 | action= SetMods(modifiers=modMapMods,clearLocks);\ 744 | };\ 745 | interpret Hyper_R+AnyOf(all) {\ 746 | virtualModifier= Hyper;\ 747 | action= SetMods(modifiers=modMapMods,clearLocks);\ 748 | };\ 749 | interpret Scroll_Lock+AnyOf(all) {\ 750 | virtualModifier= ScrollLock;\ 751 | action= LockMods(modifiers=modMapMods);\ 752 | };\ 753 | interpret ISO_Level5_Shift+AnyOf(all) {\ 754 | virtualModifier= LevelFive;\ 755 | useModMapMods=level1;\ 756 | action= SetMods(modifiers=LevelFive,clearLocks);\ 757 | };\ 758 | interpret ISO_Level5_Latch+AnyOf(all) {\ 759 | virtualModifier= LevelFive;\ 760 | useModMapMods=level1;\ 761 | action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock);\ 762 | };\ 763 | interpret ISO_Level5_Lock+AnyOf(all) {\ 764 | virtualModifier= LevelFive;\ 765 | useModMapMods=level1;\ 766 | action= LockMods(modifiers=LevelFive);\ 767 | };\ 768 | interpret Mode_switch+AnyOfOrNone(all) {\ 769 | virtualModifier= AltGr;\ 770 | useModMapMods=level1;\ 771 | action= SetGroup(group=+1);\ 772 | };\ 773 | interpret ISO_Level3_Shift+AnyOfOrNone(all) {\ 774 | action= SetMods(modifiers=LevelThree,clearLocks);\ 775 | };\ 776 | interpret ISO_Level3_Latch+AnyOfOrNone(all) {\ 777 | action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);\ 778 | };\ 779 | interpret ISO_Level3_Lock+AnyOfOrNone(all) {\ 780 | action= LockMods(modifiers=LevelThree);\ 781 | };\ 782 | interpret ISO_Group_Latch+AnyOfOrNone(all) {\ 783 | virtualModifier= AltGr;\ 784 | useModMapMods=level1;\ 785 | action= LatchGroup(group=2);\ 786 | };\ 787 | interpret ISO_Next_Group+AnyOfOrNone(all) {\ 788 | virtualModifier= AltGr;\ 789 | useModMapMods=level1;\ 790 | action= LockGroup(group=+1);\ 791 | };\ 792 | interpret ISO_Prev_Group+AnyOfOrNone(all) {\ 793 | virtualModifier= AltGr;\ 794 | useModMapMods=level1;\ 795 | action= LockGroup(group=-1);\ 796 | };\ 797 | interpret ISO_First_Group+AnyOfOrNone(all) {\ 798 | action= LockGroup(group=1);\ 799 | };\ 800 | interpret ISO_Last_Group+AnyOfOrNone(all) {\ 801 | action= LockGroup(group=2);\ 802 | };\ 803 | interpret KP_1+AnyOfOrNone(all) {\ 804 | repeat= True;\ 805 | action= MovePtr(x=-1,y=+1);\ 806 | };\ 807 | interpret KP_End+AnyOfOrNone(all) {\ 808 | repeat= True;\ 809 | action= MovePtr(x=-1,y=+1);\ 810 | };\ 811 | interpret KP_2+AnyOfOrNone(all) {\ 812 | repeat= True;\ 813 | action= MovePtr(x=+0,y=+1);\ 814 | };\ 815 | interpret KP_Down+AnyOfOrNone(all) {\ 816 | repeat= True;\ 817 | action= MovePtr(x=+0,y=+1);\ 818 | };\ 819 | interpret KP_3+AnyOfOrNone(all) {\ 820 | repeat= True;\ 821 | action= MovePtr(x=+1,y=+1);\ 822 | };\ 823 | interpret KP_Next+AnyOfOrNone(all) {\ 824 | repeat= True;\ 825 | action= MovePtr(x=+1,y=+1);\ 826 | };\ 827 | interpret KP_4+AnyOfOrNone(all) {\ 828 | repeat= True;\ 829 | action= MovePtr(x=-1,y=+0);\ 830 | };\ 831 | interpret KP_Left+AnyOfOrNone(all) {\ 832 | repeat= True;\ 833 | action= MovePtr(x=-1,y=+0);\ 834 | };\ 835 | interpret KP_6+AnyOfOrNone(all) {\ 836 | repeat= True;\ 837 | action= MovePtr(x=+1,y=+0);\ 838 | };\ 839 | interpret KP_Right+AnyOfOrNone(all) {\ 840 | repeat= True;\ 841 | action= MovePtr(x=+1,y=+0);\ 842 | };\ 843 | interpret KP_7+AnyOfOrNone(all) {\ 844 | repeat= True;\ 845 | action= MovePtr(x=-1,y=-1);\ 846 | };\ 847 | interpret KP_Home+AnyOfOrNone(all) {\ 848 | repeat= True;\ 849 | action= MovePtr(x=-1,y=-1);\ 850 | };\ 851 | interpret KP_8+AnyOfOrNone(all) {\ 852 | repeat= True;\ 853 | action= MovePtr(x=+0,y=-1);\ 854 | };\ 855 | interpret KP_Up+AnyOfOrNone(all) {\ 856 | repeat= True;\ 857 | action= MovePtr(x=+0,y=-1);\ 858 | };\ 859 | interpret KP_9+AnyOfOrNone(all) {\ 860 | repeat= True;\ 861 | action= MovePtr(x=+1,y=-1);\ 862 | };\ 863 | interpret KP_Prior+AnyOfOrNone(all) {\ 864 | repeat= True;\ 865 | action= MovePtr(x=+1,y=-1);\ 866 | };\ 867 | interpret KP_5+AnyOfOrNone(all) {\ 868 | repeat= True;\ 869 | action= PtrBtn(button=default);\ 870 | };\ 871 | interpret KP_Begin+AnyOfOrNone(all) {\ 872 | repeat= True;\ 873 | action= PtrBtn(button=default);\ 874 | };\ 875 | interpret KP_F2+AnyOfOrNone(all) {\ 876 | repeat= True;\ 877 | action= SetPtrDflt(affect=button,button=1);\ 878 | };\ 879 | interpret KP_Divide+AnyOfOrNone(all) {\ 880 | repeat= True;\ 881 | action= SetPtrDflt(affect=button,button=1);\ 882 | };\ 883 | interpret KP_F3+AnyOfOrNone(all) {\ 884 | repeat= True;\ 885 | action= SetPtrDflt(affect=button,button=2);\ 886 | };\ 887 | interpret KP_Multiply+AnyOfOrNone(all) {\ 888 | repeat= True;\ 889 | action= SetPtrDflt(affect=button,button=2);\ 890 | };\ 891 | interpret KP_F4+AnyOfOrNone(all) {\ 892 | repeat= True;\ 893 | action= SetPtrDflt(affect=button,button=3);\ 894 | };\ 895 | interpret KP_Subtract+AnyOfOrNone(all) {\ 896 | repeat= True;\ 897 | action= SetPtrDflt(affect=button,button=3);\ 898 | };\ 899 | interpret KP_Separator+AnyOfOrNone(all) {\ 900 | repeat= True;\ 901 | action= PtrBtn(button=default,count=2);\ 902 | };\ 903 | interpret KP_Add+AnyOfOrNone(all) {\ 904 | repeat= True;\ 905 | action= PtrBtn(button=default,count=2);\ 906 | };\ 907 | interpret KP_0+AnyOfOrNone(all) {\ 908 | repeat= True;\ 909 | action= LockPtrBtn(button=default,affect=lock);\ 910 | };\ 911 | interpret KP_Insert+AnyOfOrNone(all) {\ 912 | repeat= True;\ 913 | action= LockPtrBtn(button=default,affect=lock);\ 914 | };\ 915 | interpret KP_Decimal+AnyOfOrNone(all) {\ 916 | repeat= True;\ 917 | action= LockPtrBtn(button=default,affect=unlock);\ 918 | };\ 919 | interpret KP_Delete+AnyOfOrNone(all) {\ 920 | repeat= True;\ 921 | action= LockPtrBtn(button=default,affect=unlock);\ 922 | };\ 923 | interpret F25+AnyOfOrNone(all) {\ 924 | repeat= True;\ 925 | action= SetPtrDflt(affect=button,button=1);\ 926 | };\ 927 | interpret F26+AnyOfOrNone(all) {\ 928 | repeat= True;\ 929 | action= SetPtrDflt(affect=button,button=2);\ 930 | };\ 931 | interpret F27+AnyOfOrNone(all) {\ 932 | repeat= True;\ 933 | action= MovePtr(x=-1,y=-1);\ 934 | };\ 935 | interpret F29+AnyOfOrNone(all) {\ 936 | repeat= True;\ 937 | action= MovePtr(x=+1,y=-1);\ 938 | };\ 939 | interpret F31+AnyOfOrNone(all) {\ 940 | repeat= True;\ 941 | action= PtrBtn(button=default);\ 942 | };\ 943 | interpret F33+AnyOfOrNone(all) {\ 944 | repeat= True;\ 945 | action= MovePtr(x=-1,y=+1);\ 946 | };\ 947 | interpret F35+AnyOfOrNone(all) {\ 948 | repeat= True;\ 949 | action= MovePtr(x=+1,y=+1);\ 950 | };\ 951 | interpret Pointer_Button_Dflt+AnyOfOrNone(all) {\ 952 | action= PtrBtn(button=default);\ 953 | };\ 954 | interpret Pointer_Button1+AnyOfOrNone(all) {\ 955 | action= PtrBtn(button=1);\ 956 | };\ 957 | interpret Pointer_Button2+AnyOfOrNone(all) {\ 958 | action= PtrBtn(button=2);\ 959 | };\ 960 | interpret Pointer_Button3+AnyOfOrNone(all) {\ 961 | action= PtrBtn(button=3);\ 962 | };\ 963 | interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) {\ 964 | action= PtrBtn(button=default,count=2);\ 965 | };\ 966 | interpret Pointer_DblClick1+AnyOfOrNone(all) {\ 967 | action= PtrBtn(button=1,count=2);\ 968 | };\ 969 | interpret Pointer_DblClick2+AnyOfOrNone(all) {\ 970 | action= PtrBtn(button=2,count=2);\ 971 | };\ 972 | interpret Pointer_DblClick3+AnyOfOrNone(all) {\ 973 | action= PtrBtn(button=3,count=2);\ 974 | };\ 975 | interpret Pointer_Drag_Dflt+AnyOfOrNone(all) {\ 976 | action= LockPtrBtn(button=default);\ 977 | };\ 978 | interpret Pointer_Drag1+AnyOfOrNone(all) {\ 979 | action= LockPtrBtn(button=1);\ 980 | };\ 981 | interpret Pointer_Drag2+AnyOfOrNone(all) {\ 982 | action= LockPtrBtn(button=2);\ 983 | };\ 984 | interpret Pointer_Drag3+AnyOfOrNone(all) {\ 985 | action= LockPtrBtn(button=3);\ 986 | };\ 987 | interpret Pointer_EnableKeys+AnyOfOrNone(all) {\ 988 | action= LockControls(controls=MouseKeys);\ 989 | };\ 990 | interpret Pointer_Accelerate+AnyOfOrNone(all) {\ 991 | action= LockControls(controls=MouseKeysAccel);\ 992 | };\ 993 | interpret Pointer_DfltBtnNext+AnyOfOrNone(all) {\ 994 | action= SetPtrDflt(affect=button,button=+1);\ 995 | };\ 996 | interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) {\ 997 | action= SetPtrDflt(affect=button,button=-1);\ 998 | };\ 999 | interpret AccessX_Enable+AnyOfOrNone(all) {\ 1000 | action= LockControls(controls=AccessXKeys);\ 1001 | };\ 1002 | interpret AccessX_Feedback_Enable+AnyOfOrNone(all) {\ 1003 | action= LockControls(controls=AccessXFeedback);\ 1004 | };\ 1005 | interpret RepeatKeys_Enable+AnyOfOrNone(all) {\ 1006 | action= LockControls(controls=RepeatKeys);\ 1007 | };\ 1008 | interpret SlowKeys_Enable+AnyOfOrNone(all) {\ 1009 | action= LockControls(controls=SlowKeys);\ 1010 | };\ 1011 | interpret BounceKeys_Enable+AnyOfOrNone(all) {\ 1012 | action= LockControls(controls=BounceKeys);\ 1013 | };\ 1014 | interpret StickyKeys_Enable+AnyOfOrNone(all) {\ 1015 | action= LockControls(controls=StickyKeys);\ 1016 | };\ 1017 | interpret MouseKeys_Enable+AnyOfOrNone(all) {\ 1018 | action= LockControls(controls=MouseKeys);\ 1019 | };\ 1020 | interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) {\ 1021 | action= LockControls(controls=MouseKeysAccel);\ 1022 | };\ 1023 | interpret Overlay1_Enable+AnyOfOrNone(all) {\ 1024 | action= LockControls(controls=none);\ 1025 | };\ 1026 | interpret Overlay2_Enable+AnyOfOrNone(all) {\ 1027 | action= LockControls(controls=none);\ 1028 | };\ 1029 | interpret AudibleBell_Enable+AnyOfOrNone(all) {\ 1030 | action= LockControls(controls=AudibleBell);\ 1031 | };\ 1032 | interpret Terminate_Server+AnyOfOrNone(all) {\ 1033 | action= Terminate();\ 1034 | };\ 1035 | interpret Alt_L+AnyOfOrNone(all) {\ 1036 | action= SetMods(modifiers=Alt,clearLocks);\ 1037 | };\ 1038 | interpret Alt_R+AnyOfOrNone(all) {\ 1039 | action= SetMods(modifiers=Alt,clearLocks);\ 1040 | };\ 1041 | interpret Meta_L+AnyOfOrNone(all) {\ 1042 | action= SetMods(modifiers=Meta,clearLocks);\ 1043 | };\ 1044 | interpret Meta_R+AnyOfOrNone(all) {\ 1045 | action= SetMods(modifiers=Meta,clearLocks);\ 1046 | };\ 1047 | interpret Super_L+AnyOfOrNone(all) {\ 1048 | action= SetMods(modifiers=Super,clearLocks);\ 1049 | };\ 1050 | interpret Super_R+AnyOfOrNone(all) {\ 1051 | action= SetMods(modifiers=Super,clearLocks);\ 1052 | };\ 1053 | interpret Hyper_L+AnyOfOrNone(all) {\ 1054 | action= SetMods(modifiers=Hyper,clearLocks);\ 1055 | };\ 1056 | interpret Hyper_R+AnyOfOrNone(all) {\ 1057 | action= SetMods(modifiers=Hyper,clearLocks);\ 1058 | };\ 1059 | interpret Shift_L+AnyOfOrNone(all) {\ 1060 | action= SetMods(modifiers=Shift,clearLocks);\ 1061 | };\ 1062 | interpret XF86Switch_VT_1+AnyOfOrNone(all) {\ 1063 | repeat= True;\ 1064 | action= SwitchScreen(screen=1,!same);\ 1065 | };\ 1066 | interpret XF86Switch_VT_2+AnyOfOrNone(all) {\ 1067 | repeat= True;\ 1068 | action= SwitchScreen(screen=2,!same);\ 1069 | };\ 1070 | interpret XF86Switch_VT_3+AnyOfOrNone(all) {\ 1071 | repeat= True;\ 1072 | action= SwitchScreen(screen=3,!same);\ 1073 | };\ 1074 | interpret XF86Switch_VT_4+AnyOfOrNone(all) {\ 1075 | repeat= True;\ 1076 | action= SwitchScreen(screen=4,!same);\ 1077 | };\ 1078 | interpret XF86Switch_VT_5+AnyOfOrNone(all) {\ 1079 | repeat= True;\ 1080 | action= SwitchScreen(screen=5,!same);\ 1081 | };\ 1082 | interpret XF86Switch_VT_6+AnyOfOrNone(all) {\ 1083 | repeat= True;\ 1084 | action= SwitchScreen(screen=6,!same);\ 1085 | };\ 1086 | interpret XF86Switch_VT_7+AnyOfOrNone(all) {\ 1087 | repeat= True;\ 1088 | action= SwitchScreen(screen=7,!same);\ 1089 | };\ 1090 | interpret XF86Switch_VT_8+AnyOfOrNone(all) {\ 1091 | repeat= True;\ 1092 | action= SwitchScreen(screen=8,!same);\ 1093 | };\ 1094 | interpret XF86Switch_VT_9+AnyOfOrNone(all) {\ 1095 | repeat= True;\ 1096 | action= SwitchScreen(screen=9,!same);\ 1097 | };\ 1098 | interpret XF86Switch_VT_10+AnyOfOrNone(all) {\ 1099 | repeat= True;\ 1100 | action= SwitchScreen(screen=10,!same);\ 1101 | };\ 1102 | interpret XF86Switch_VT_11+AnyOfOrNone(all) {\ 1103 | repeat= True;\ 1104 | action= SwitchScreen(screen=11,!same);\ 1105 | };\ 1106 | interpret XF86Switch_VT_12+AnyOfOrNone(all) {\ 1107 | repeat= True;\ 1108 | action= SwitchScreen(screen=12,!same);\ 1109 | };\ 1110 | interpret XF86LogGrabInfo+AnyOfOrNone(all) {\ 1111 | repeat= True;\ 1112 | action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00);\ 1113 | };\ 1114 | interpret XF86LogWindowTree+AnyOfOrNone(all) {\ 1115 | repeat= True;\ 1116 | action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00);\ 1117 | };\ 1118 | interpret XF86Next_VMode+AnyOfOrNone(all) {\ 1119 | repeat= True;\ 1120 | action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00);\ 1121 | };\ 1122 | interpret XF86Prev_VMode+AnyOfOrNone(all) {\ 1123 | repeat= True;\ 1124 | action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00);\ 1125 | };\ 1126 | interpret ISO_Level5_Shift+AnyOfOrNone(all) {\ 1127 | action= SetMods(modifiers=LevelFive,clearLocks);\ 1128 | };\ 1129 | interpret ISO_Level5_Latch+AnyOfOrNone(all) {\ 1130 | action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock);\ 1131 | };\ 1132 | interpret ISO_Level5_Lock+AnyOfOrNone(all) {\ 1133 | action= LockMods(modifiers=LevelFive);\ 1134 | };\ 1135 | interpret Caps_Lock+AnyOfOrNone(all) {\ 1136 | action= LockMods(modifiers=Lock);\ 1137 | };\ 1138 | interpret Any+Exactly(Lock) {\ 1139 | action= LockMods(modifiers=Lock);\ 1140 | };\ 1141 | interpret Any+AnyOf(all) {\ 1142 | action= SetMods(modifiers=modMapMods,clearLocks);\ 1143 | };\ 1144 | indicator \"Caps Lock\" {\ 1145 | whichModState= locked;\ 1146 | modifiers= Lock;\ 1147 | };\ 1148 | indicator \"Num Lock\" {\ 1149 | whichModState= locked;\ 1150 | modifiers= NumLock;\ 1151 | };\ 1152 | indicator \"Scroll Lock\" {\ 1153 | whichModState= locked;\ 1154 | modifiers= ScrollLock;\ 1155 | };\ 1156 | indicator \"Shift Lock\" {\ 1157 | whichModState= locked;\ 1158 | modifiers= Shift;\ 1159 | };\ 1160 | indicator \"Group 2\" {\ 1161 | groups= 0xfe;\ 1162 | };\ 1163 | indicator \"Mouse Keys\" {\ 1164 | controls= MouseKeys;\ 1165 | };\ 1166 | };\ 1167 | \ 1168 | xkb_symbols \"(unnamed)\" {\ 1169 | name[group1]=\"English (US)\";\ 1170 | \ 1171 | key { [ Escape ] };\ 1172 | key { [ 1, exclam ] };\ 1173 | key { [ 2, at ] };\ 1174 | key { [ 3, numbersign ] };\ 1175 | key { [ 4, dollar ] };\ 1176 | key { [ 5, percent ] };\ 1177 | key { [ 6, asciicircum ] };\ 1178 | key { [ 7, ampersand ] };\ 1179 | key { [ 8, asterisk ] };\ 1180 | key { [ 9, parenleft ] };\ 1181 | key { [ 0, parenright ] };\ 1182 | key { [ minus, underscore ] };\ 1183 | key { [ equal, plus ] };\ 1184 | key { [ BackSpace, BackSpace ] };\ 1185 | key { [ Tab, ISO_Left_Tab ] };\ 1186 | key { [ q, Q, 1 ] };\ 1187 | key { [ w, W, 2 ] };\ 1188 | key { [ e, E, 3 ] };\ 1189 | key { [ r, R, 4 ] };\ 1190 | key { [ t, T, 5 ] };\ 1191 | key { [ y, Y, 6 ] };\ 1192 | key { [ u, U, 7 ] };\ 1193 | key { [ i, I, 8 ] };\ 1194 | key { [ o, O, 9 ] };\ 1195 | key { [ p, P, 0 ] };\ 1196 | key { [ bracketleft, braceleft ] };\ 1197 | key { [ bracketright, braceright ] };\ 1198 | key { [ Return ] };\ 1199 | key { [ Control_L ] };\ 1200 | key { [ a, A, minus ] };\ 1201 | key { [ s, S, at ] };\ 1202 | key { [ d, D, asterisk ] };\ 1203 | key { [ f, F, asciicircum ] };\ 1204 | key { [ g, G, colon ] };\ 1205 | key { [ h, H, semicolon ] };\ 1206 | key { [ j, J, parenleft ] };\ 1207 | key { [ k, K, parenright ] };\ 1208 | key { [ l, L, asciitilde ] };\ 1209 | key { [ semicolon, colon ] };\ 1210 | key { [ apostrophe, quotedbl ] };\ 1211 | key { [ grave, asciitilde ] };\ 1212 | key { [ Shift_L ] };\ 1213 | key { [ backslash, bar ] };\ 1214 | key { [ z, Z, slash ] };\ 1215 | key { [ x, X, apostrophe ] };\ 1216 | key { [ c, C, quotedbl ] };\ 1217 | key { [ v, V, plus ] };\ 1218 | key { [ b, B, equal ] };\ 1219 | key { [ n, N, question ] };\ 1220 | key { [ m, M, exclam ] };\ 1221 | key { [ comma, less, backslash] };\ 1222 | key { [ period, greater, bar ] };\ 1223 | key { [ slash, question ] };\ 1224 | key { [ Shift_R ] };\ 1225 | key {\ 1226 | type= \"CTRL+ALT\",\ 1227 | symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ]\ 1228 | };\ 1229 | key { [ Alt_L, Meta_L ] };\ 1230 | key { [ space ] };\ 1231 | key { [ Caps_Lock ] };\ 1232 | key {\ 1233 | type= \"CTRL+ALT\",\ 1234 | symbols[Group1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ]\ 1235 | };\ 1236 | key {\ 1237 | type= \"CTRL+ALT\",\ 1238 | symbols[Group1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ]\ 1239 | };\ 1240 | key {\ 1241 | type= \"CTRL+ALT\",\ 1242 | symbols[Group1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ]\ 1243 | };\ 1244 | key {\ 1245 | type= \"CTRL+ALT\",\ 1246 | symbols[Group1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ]\ 1247 | };\ 1248 | key {\ 1249 | type= \"CTRL+ALT\",\ 1250 | symbols[Group1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ]\ 1251 | };\ 1252 | key {\ 1253 | type= \"CTRL+ALT\",\ 1254 | symbols[Group1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ]\ 1255 | };\ 1256 | key {\ 1257 | type= \"CTRL+ALT\",\ 1258 | symbols[Group1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ]\ 1259 | };\ 1260 | key {\ 1261 | type= \"CTRL+ALT\",\ 1262 | symbols[Group1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ]\ 1263 | };\ 1264 | key {\ 1265 | type= \"CTRL+ALT\",\ 1266 | symbols[Group1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ]\ 1267 | };\ 1268 | key {\ 1269 | type= \"CTRL+ALT\",\ 1270 | symbols[Group1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ]\ 1271 | };\ 1272 | key { [ Num_Lock ] };\ 1273 | key { [ Scroll_Lock ] };\ 1274 | key { [ KP_Home, KP_7 ] };\ 1275 | key { [ KP_Up, KP_8 ] };\ 1276 | key { [ KP_Prior, KP_9 ] };\ 1277 | key {\ 1278 | type= \"CTRL+ALT\",\ 1279 | symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ]\ 1280 | };\ 1281 | key { [ KP_Left, KP_4 ] };\ 1282 | key { [ KP_Begin, KP_5 ] };\ 1283 | key { [ KP_Right, KP_6 ] };\ 1284 | key {\ 1285 | type= \"CTRL+ALT\",\ 1286 | symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ]\ 1287 | };\ 1288 | key { [ KP_End, KP_1 ] };\ 1289 | key { [ KP_Down, KP_2 ] };\ 1290 | key { [ KP_Next, KP_3 ] };\ 1291 | key { [ KP_Insert, KP_0 ] };\ 1292 | key { [ KP_Delete, KP_Decimal ] };\ 1293 | key { [ ISO_Level3_Shift ] };\ 1294 | key { [ less, greater, bar, brokenbar ] };\ 1295 | key {\ 1296 | type= \"CTRL+ALT\",\ 1297 | symbols[Group1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ]\ 1298 | };\ 1299 | key {\ 1300 | type= \"CTRL+ALT\",\ 1301 | symbols[Group1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ]\ 1302 | };\ 1303 | key { [ Katakana ] };\ 1304 | key { [ Hiragana ] };\ 1305 | key { [ Henkan_Mode ] };\ 1306 | key { [ Hiragana_Katakana ] };\ 1307 | key { [ Muhenkan ] };\ 1308 | key { [ KP_Enter ] };\ 1309 | key { [ Control_R ] };\ 1310 | key {\ 1311 | type= \"CTRL+ALT\",\ 1312 | symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ]\ 1313 | };\ 1314 | key {\ 1315 | type= \"PC_ALT_LEVEL2\",\ 1316 | symbols[Group1]= [ Print, Sys_Req ]\ 1317 | };\ 1318 | key {\ 1319 | type= \"TWO_LEVEL\",\ 1320 | symbols[Group1]= [ Alt_R, Meta_R ]\ 1321 | };\ 1322 | key { [ Linefeed ] };\ 1323 | key { [ Home ] };\ 1324 | key { [ Up ] };\ 1325 | key { [ Prior ] };\ 1326 | key { [ Left ] };\ 1327 | key { [ Right ] };\ 1328 | key { [ End ] };\ 1329 | key { [ Down ] };\ 1330 | key { [ Next ] };\ 1331 | key { [ Insert ] };\ 1332 | key { [ Delete ] };\ 1333 | key { [ XF86AudioMute ] };\ 1334 | key { [ XF86AudioLowerVolume ] };\ 1335 | key { [ XF86AudioRaiseVolume ] };\ 1336 | key { [ XF86PowerOff ] };\ 1337 | key { [ KP_Equal ] };\ 1338 | key { [ plusminus ] };\ 1339 | key {\ 1340 | type= \"PC_CONTROL_LEVEL2\",\ 1341 | symbols[Group1]= [ Pause, Break ]\ 1342 | };\ 1343 | key { [ XF86LaunchA ] };\ 1344 | key { [ KP_Decimal, KP_Decimal ] };\ 1345 | key { [ Hangul ] };\ 1346 | key { [ Hangul_Hanja ] };\ 1347 | key { [ Super_L ] };\ 1348 | key { [ Super_R ] };\ 1349 | key { [ Menu ] };\ 1350 | key { [ Cancel ] };\ 1351 | key { [ Redo ] };\ 1352 | key { [ SunProps ] };\ 1353 | key { [ Undo ] };\ 1354 | key { [ SunFront ] };\ 1355 | key { [ XF86Copy ] };\ 1356 | key { [ XF86Open ] };\ 1357 | key { [ XF86Paste ] };\ 1358 | key { [ Find ] };\ 1359 | key { [ XF86Cut ] };\ 1360 | key { [ Help ] };\ 1361 | key { [ XF86MenuKB ] };\ 1362 | key { [ XF86Calculator ] };\ 1363 | key { [ XF86Sleep ] };\ 1364 | key { [ XF86WakeUp ] };\ 1365 | key { [ XF86Explorer ] };\ 1366 | key { [ XF86Send ] };\ 1367 | key { [ XF86Xfer ] };\ 1368 | key { [ XF86Launch1 ] };\ 1369 | key { [ XF86Launch2 ] };\ 1370 | key { [ XF86WWW ] };\ 1371 | key { [ XF86DOS ] };\ 1372 | key { [ XF86ScreenSaver ] };\ 1373 | key { [ XF86RotateWindows ] };\ 1374 | key { [ XF86TaskPane ] };\ 1375 | key { [ XF86Mail ] };\ 1376 | key { [ XF86Favorites ] };\ 1377 | key { [ XF86MyComputer ] };\ 1378 | key { [ XF86Back ] };\ 1379 | key { [ XF86Forward ] };\ 1380 | key { [ XF86Eject ] };\ 1381 | key { [ XF86Eject, XF86Eject ] };\ 1382 | key { [ XF86AudioNext ] };\ 1383 | key { [ XF86AudioPlay, XF86AudioPause ] };\ 1384 | key { [ XF86AudioPrev ] };\ 1385 | key { [ XF86AudioStop, XF86Eject ] };\ 1386 | key { [ XF86AudioRecord ] };\ 1387 | key { [ XF86AudioRewind ] };\ 1388 | key { [ XF86Phone ] };\ 1389 | key { [ XF86Tools ] };\ 1390 | key { [ XF86HomePage ] };\ 1391 | key { [ XF86Reload ] };\ 1392 | key { [ XF86Close ] };\ 1393 | key { [ XF86ScrollUp ] };\ 1394 | key { [ XF86ScrollDown ] };\ 1395 | key { [ parenleft ] };\ 1396 | key { [ parenright ] };\ 1397 | key { [ XF86New ] };\ 1398 | key { [ Redo ] };\ 1399 | key { [ XF86Tools ] };\ 1400 | key { [ XF86Launch5 ] };\ 1401 | key { [ XF86Launch6 ] };\ 1402 | key { [ XF86Launch7 ] };\ 1403 | key { [ XF86Launch8 ] };\ 1404 | key { [ XF86Launch9 ] };\ 1405 | key { [ XF86AudioMicMute ] };\ 1406 | key { [ XF86TouchpadToggle ] };\ 1407 | key { [ XF86TouchpadOn ] };\ 1408 | key { [ XF86TouchpadOff ] };\ 1409 | key { [ Mode_switch ] };\ 1410 | key { [ NoSymbol, Alt_L ] };\ 1411 | key { [ NoSymbol, Meta_L ] };\ 1412 | key { [ NoSymbol, Super_L ] };\ 1413 | key { [ NoSymbol, Hyper_L ] };\ 1414 | key { [ XF86AudioPlay ] };\ 1415 | key { [ XF86AudioPause ] };\ 1416 | key { [ XF86Launch3 ] };\ 1417 | key { [ XF86Launch4 ] };\ 1418 | key { [ XF86LaunchB ] };\ 1419 | key { [ XF86Suspend ] };\ 1420 | key { [ XF86Close ] };\ 1421 | key { [ XF86AudioPlay ] };\ 1422 | key { [ XF86AudioForward ] };\ 1423 | key { [ Print ] };\ 1424 | key { [ XF86WebCam ] };\ 1425 | key { [ XF86AudioPreset ] };\ 1426 | key { [ XF86Mail ] };\ 1427 | key { [ XF86Messenger ] };\ 1428 | key { [ XF86Search ] };\ 1429 | key { [ XF86Go ] };\ 1430 | key { [ XF86Finance ] };\ 1431 | key { [ XF86Game ] };\ 1432 | key { [ XF86Shop ] };\ 1433 | key { [ Cancel ] };\ 1434 | key { [ XF86MonBrightnessDown ] };\ 1435 | key { [ XF86MonBrightnessUp ] };\ 1436 | key { [ XF86AudioMedia ] };\ 1437 | key { [ XF86Display ] };\ 1438 | key { [ XF86KbdLightOnOff ] };\ 1439 | key { [ XF86KbdBrightnessDown ] };\ 1440 | key { [ XF86KbdBrightnessUp ] };\ 1441 | key { [ XF86Send ] };\ 1442 | key { [ XF86Reply ] };\ 1443 | key { [ XF86MailForward ] };\ 1444 | key { [ XF86Save ] };\ 1445 | key { [ XF86Documents ] };\ 1446 | key { [ XF86Battery ] };\ 1447 | key { [ XF86Bluetooth ] };\ 1448 | key { [ XF86WLAN ] };\ 1449 | key { [ XF86UWB ] };\ 1450 | key { [ XF86WWAN ] };\ 1451 | key { [ XF86RFKill ] };\ 1452 | modifier_map Shift { , };\ 1453 | modifier_map Lock { };\ 1454 | modifier_map Control { , };\ 1455 | modifier_map Mod1 { , , };\ 1456 | modifier_map Mod2 { };\ 1457 | modifier_map Mod4 { , , , };\ 1458 | modifier_map Mod5 { , };\ 1459 | };\ 1460 | \ 1461 | };\ 1462 | "; 1463 | --------------------------------------------------------------------------------