Merge pull request #18 from rbreaves/dev

Kintox11 Update
This commit is contained in:
Ben Reaves
2020-02-03 04:13:55 +00:00
committed by GitHub
19 changed files with 740 additions and 279 deletions

View File

@@ -1,80 +1,8 @@
default partial xkb_symbols "mac_levelssym" {
// Cut
replace key <AB02> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ x, X, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatX>,mods=Control+Shift,clearmods=Super)]
key <LWIN> {
repeat= no,
type= "ONE_LEVEL",
symbols[Group1]= [ Hyper_L ],
actions[group1]=[ SetMods(modifiers=Shift+Control) ]
};
// Copy
replace key <AB03> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ c, C, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatC>,mods=Control+Shift,clearmods=Super)]
};
// Paste
replace key <AB04> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ v, V, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatV>,mods=Control+Shift,clearmods=Super)]
};
// New Tab
replace key <AD05> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ t, T, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatT>,mods=Control+Shift,clearmods=Super)]
};
// New Window
replace key <AB06> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ n, N, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatN>,mods=Control+Shift,clearmods=Super)]
};
// Close Tab
replace key <AD02> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ w, W, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatW>,mods=Control+Shift,clearmods=Super)]
};
// Close Window
replace key <AD01> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ q, Q, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatQ>,mods=Control+Shift,clearmods=Super)]
};
// Scroll back reset
replace key <AC08> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ k, K, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatK>,mods=Control+Shift,clearmods=Super)]
};
// Detach Tab
replace key <AC06> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ h, H, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatH>,mods=Control+Shift,clearmods=Super)]
};
// Find
replace key <AC04> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ f, F, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatF>,mods=Control+Shift,clearmods=Super)]
};
// Close Active
replace key <AC02> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ s, S, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatS>,mods=Control+Shift,clearmods=Super)]
};
// Close Others
replace key <AD09> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ o, O, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatO>,mods=Control+Shift,clearmods=Super)]
};
// Show Menu
replace key <AB07> {
type[Group1]= "ALPHABETIC_SUPER",
symbols[Group1]= [ m, M, NoSymbol ],
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<LatM>,mods=Control+Shift,clearmods=Super)]
};
};
};

View File

@@ -1,13 +0,0 @@
default partial xkb_types "addmac_levels" {
type "ALPHABETIC_SUPER" {
modifiers= Shift+Lock+Mod4;
map[Shift]= Level2;
map[Lock]= Level2;
map[Mod4]= Level3;
map[Shift+Mod4]= Level3;
map[Lock+Mod4]= Level3;
level_name[Level1]= "Base";
level_name[Level2]= "Caps";
level_name[Level3]= "With Super";
};
};

View File

@@ -4,7 +4,9 @@
[![GitHub release](https://img.shields.io/github/release/rbreaves/kinto.svg)](https://github.com/rbreaves/kinto/releases)
\- A better linux keyboard layout for professional mac users \-
![alt text](https://raw.githubusercontent.com/rbreaves/kinto/master/splash.png)
\- Type in Linux like it's a Mac. \-
Memory muscle matters for programmers and developers.
@@ -18,9 +20,9 @@ Kinto works for standard Windows, Apple and Chromebook keyboards. The following
- Normal apps - Alt will be Ctrl, Win/Super will be Alt, Ctrl will be Win/Super
- Terminal apps (optional) - Alt will be Win/Super, Win/Super will be Alt, Ctrl will be Ctrl
- Terminal apps - Alt will be Ctrl+Shift, Win/Super will be Alt, Ctrl will be Ctrl
- New Features - Cursor/word-wise shortcut keys have been added to align with macOS keyboard shortcuts.
- Cursor/word-wise shortcut keys have been added to align with macOS keyboard shortcuts.
## What does Kinto require?
@@ -41,7 +43,7 @@ git clone https://github.com/rbreaves/kinto.git
Debian or Ubuntu 16.04 or 18.04
```
sudo apt update
sudo apt install python3 x11-utils
sudo apt install python3
```
3. Follow the prompts and the script will guide you through the rest of the setup.
@@ -83,91 +85,41 @@ Disable
systemctl --user disable keyswap
```
## Manually Toggling Kinto via hotkey
I have not automated this part of the install due to the wide range of DE's and each one needing the shortcut setup to be a little different.
Here's what you will want to do, if you want to set this up.
1. Run a Status check on Kinto
```
systemctl --user status keyswap
```
and pay attention to the values that come after xactive.sh in the output.
2. Run the following command, replacing the 4 values below with yours.
```
~/.config/keyswap_toggle.sh win 0 0 0
```
3. Run this command a few more times and make sure it is swapping between "gui to term" and "term to gui"
4. Go into the DE system settings and bind the hotkeys you want to use to activate it.
## Learning macOS style hotkeys on Linux
You can use websites like https://www.shortcutfoo.com in Google Chrome while using the terminal style keymap, but Firefox is not compatible due to detecting "cmd" as keycode 224. Chrome detects Win/Super/Cmd as keycode 91 on all OS's.
To make sure you are in the terminal style keymap you can just simply open the terminal and turn off the kinto service, and then switch back to Chrome.
```
systemctl --user stop keyswap
systemctl --user stop keyswap && setxkbmap -option;setxkbmap -option altwin:swap_alt_win
```
or alternatively, you can follow the instructions about how to manually trigger a toggle of the keyswap.
## Troubleshooting
### Keyswap is not occurring, but it was working.
Sometimes something about the Desktop Environment may throw xprop for a loop, it's rare, but if this occurs then you have 2 options.
Now that Kinto is using a custom written C program I am not aware of any specific bugs or issues, but you can start here if you having difficulties and please report it if it is reproducible.
1. Restart Kinto
```
systemctl --user restart keyswap
```
2. Check the Status of Kinto and open a ticket with the output, especially if you can reliably reproduce the problem.
2. Check the Status of Kinto and open a ticket with the output.
```
systemctl --user status keyswap
```
### Chromebook with external keyboard not being detected
If your keyboard is not being autodetected and configured then please run `xinput list`, if you are on linux, and copy the output into a ticket under issues.
## Language Support
I'd appreciate any help from people with non-US based keyboards, to help ensure that these keymaps and keyswap methods work in all or most languages.
If you would like to attempt adding additional custom keymaps for other languages then I strongly recommend reading Glen Whitney's post here.
https://superuser.com/questions/385748/binding-superc-superv-to-copy-and-paste
## Known Issues
### USB Hubs
No longer an issue. USB hubs may prevent Apple keyboards from loading an official driver, but Kinto will adapt if this occurs. The benefit of an official Apple driver is that it can allow Kinto to support a mix of Windows and Mac based keyboards simultaneously.
## Debugging
You can output the xactive.sh script with parameters with following command.
```
cat ~/.config/systemd/user/keyswap.service
```
After that just stop the service as described and run the xactive.sh script with parameters.
```
systemctl --user disable keyswap
systemctl --user stop keyswap
~/.config/xactive.sh mac 12 0 none
```
You can also refer to this Gist file to better understand what Kinto is doing and the simplicity of it. (The gist does not make use of any custom keymaps.)
https://gist.github.com/rbreaves/f4cf8a991eaeea893999964f5e83eebb
## Contributing
I welcome any and all contributors who want to contribute something to this project.
If you are specifically wanting to contribute additional custom keymaps to help with aligning Kinto's behavior to that of a mac keyboard then I would strongly recommend that you read Glen Whitney's comment on Superuser (the link is below). You may also look at the .xkb directory, mac_worsewise.sh and xactive.sh files to better understand how Kinto operates so that you can test your own keymaps without having to use the systemd service or running the xactive.sh script.
If you are specifically wanting to contribute additional custom keymaps to help with aligning Kinto's behavior to that of a mac keyboard then I would strongly recommend that you read Glen Whitney's comment on Superuser (the link is below). You may also look at the .xkb directory, mac_wordwise.sh and xactive.sh files to better understand how Kinto operates so that you can test your own keymaps without having to use the systemd service or running the xactive.sh script.
https://superuser.com/questions/385748/binding-superc-superv-to-copy-and-paste

View File

@@ -13,4 +13,4 @@ line=$(cat ~/.xkb/keymap/kbd.chromebook.gui | grep -n 'xkb_types' | cut -f1 -d:)
sed -ie "${line}s/\"/+mac_gui(addmac_levels)\"/2" ~/.xkb/keymap/kbd.chromebook.gui
sleep 1
line=$(cat ~/.xkb/keymap/kbd.chromebook.term | grep -n 'xkb_symbols' | cut -f1 -d:)
sed -ie "${line}s/\"/+altwin(swap_alt_win)\"/2" ~/.xkb/keymap/kbd.chromebook.term
sed -ie "${line}s/\"/+altwin(swap_alt_win)+mac_term(mac_levelssym)\"/2" ~/.xkb/keymap/kbd.chromebook.term

86
defaults.json Normal file
View File

@@ -0,0 +1,86 @@
{"defaultapps":[{
"name":"term",
"appnames":[ "Gnome-terminal","konsole","io.elementary.terminal","terminator","sakura","guake","tilda","xterm","eterm" ]
}],
"defaulttypes":["windows","mac","chromebook"],
"defaults":[{
"id": 1,
"name":"Windows",
"type":"windows",
"active": false,
"description":"Standard Windows 104 Keyboards",
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui $DISPLAY",
"term":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.term $DISPLAY",
"xkb_symbols_gui":"+altwin(ctrl_alt_win)+mac_gui(mac_levelssym)",
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
"xkb_types_gui":"+mac_gui(addmac_levels)",
"xkb_types_term":""
},
{
"id": 2,
"name":"Mac - hid driver",
"type":"mac",
"active": false,
"description":"Standard Mac Keyboards with Apple driver",
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui $DISPLAY",
"term":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.term $DISPLAY",
"xkb_symbols_gui":"+altwin(ctrl_alt_win)+mac_gui(mac_levelssym)",
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
"xkb_types_gui":"+mac_gui(addmac_levels)",
"xkb_types_term":"",
"hack": "echo '1' | sudo tee -a /sys/module/hid_apple/parameters/swap_opt_cmd;echo 'options hid_apple swap_opt_cmd=1' | sudo tee -a /etc/modprobe.d/hid_apple.conf;sudo update-initramfs -u -k all"
},
{
"id": 3,
"name":"Mac Only",
"type":"mac",
"active": true,
"description":"Standard Mac Keyboards",
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui $DISPLAY",
"term":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.term $DISPLAY",
"xkb_symbols_gui":"+ctrl(swap_lwin_lctl)+ctrl(swap_rwin_rctl)+mac_gui(mac_levelssym)",
"xkb_symbols_term":"+altwin(alt_super_win)+mac_term(mac_levelssym)",
"xkb_types_gui":"+mac_gui(addmac_levels)",
"xkb_types_term":""
},
{
"id": 4,
"name":"Chromebook",
"type":"chromebook",
"active": false,
"description":"Standard Chromebook Keyboards",
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY",
"term":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.term $DISPLAY",
"xkb_symbols_gui":"+chromebook(swap_lalt_lctrl)+mac_gui(mac_levelssym)",
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
"xkb_types_gui":"+mac_gui(addmac_levels)",
"xkb_types_term":""
},
{
"id": 5,
"name":"Chromebook - Windows",
"type":"chromebook",
"active": false,
"description":"Chromebook with Windows 104 Keyboard",
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY; setxkbmap -device $usbid -option altwin:ctrl_alt_win",
"term":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.term $DISPLAY",
"fallbackgui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY",
"xkb_symbols_gui":"+chromebook(swap_lalt_lctrl)+mac_gui(mac_levelssym)",
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
"xkb_types_gui":"+mac_gui(addmac_levels)",
"xkb_types_term":""
},
{
"id": 6,
"name":"Chromebook - Mac",
"type":"chromebook",
"active": false,
"description":"Chromebook with Mac Keyboard",
"gui":"setxkbmap -option;setxkbmap -option ctrl:swap_lwin_lctl; xkbcomp -w0 -i $internalid -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY",
"term":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.term $DISPLAY",
"xkb_symbols_gui":"+chromebook(swap_lalt_lctrl)+mac_gui(mac_levelssym)",
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
"xkb_types_gui":"+mac_gui(addmac_levels)",
"xkb_types_term":""
}]
}

View File

@@ -1,34 +1,13 @@
#!/bin/bash
swapbehavior=$1
noswapcmd=$2
systemtype=$3
internalid=$4
usbid=$5
chromeswap=$6
if [[ "$swapbehavior" == "1" ]]; then
swapcmd="\/bin\/bash\ \/home\/`whoami`\/.config\/xactive.sh\ ${systemtype}\ ${internalid}\ ${usbid}\ ${chromeswap}"
mkdir -p ~/.config/systemd/user
mkdir -p ~/.config/autostart
cp ./system-config/keyswap.service ~/.config/systemd/user/keyswap.service
cp ./system-config/keyswap.sh ~/.config/autostart/keyswap.sh
cp ./system-config/xactive.sh ~/.config/xactive.sh
cp ./system-config/keyswap_toggle.sh ~/.config/keyswap_toggle.sh
sed -i "s/{username}/`whoami`/g" ~/.config/systemd/user/keyswap.service
sed -i "s/ExecStart=/ExecStart=${swapcmd}/g" ~/.config/systemd/user/keyswap.service
systemctl --user enable keyswap
systemctl --user start keyswap
else
#/usr/bin/setxkbmap
#/usr/bin/xkbcomp
#echo $XDG_SESSION_TYPE
if [ ! -f "~/.Xsession" ]; then
echo "$noswapcmd" > ~/.Xsession
fi
grep "xkb" ~/.Xsession 1>/dev/null
if [ $? -eq 1 ]; then
echo "$noswapcmd" >> ~/.Xsession
fi
fi
swapcmd="\/bin\/bash\ \/home\/`whoami`\/.config\/kinto\/xactive.sh"
mkdir -p ~/.config/systemd/user
mkdir -p ~/.config/autostart
cp ./system-config/keyswap.service ~/.config/systemd/user/keyswap.service
cp ./system-config/keyswap.sh ~/.config/autostart/keyswap.sh
cp ./kintox11/binary/kintox11 ~/.config/kinto/kintox11
cp ./system-config/xactive.sh ~/.config/kinto/xactive.sh
sed -i "s/{username}/`whoami`/g" ~/.config/systemd/user/keyswap.service
sed -i "s/ExecStart=/ExecStart=${swapcmd}/g" ~/.config/systemd/user/keyswap.service
systemctl --user enable keyswap
systemctl --user start keyswap

BIN
kintox11/binary/kintox11 Executable file

Binary file not shown.

340
kintox11/src/kintox11.c Normal file
View File

@@ -0,0 +1,340 @@
// -*- coding:utf-8-unix; mode:c; -*-
// Kinto x11 command line
/*
Reference material
get the active window on X window system
http://k-ui.jp/blog/2012/05/07/get-active-window-on-x-window-system/
*/
// To compile without static libraries
// gcc kintox11.c -lX11 -lXmu -ljson-c
//
// To compile with static library json-c
// Make sure archive with object files exist ar -t /usr/local/lib/libjson-c.a
// gcc -L/usr/local/lib/ kintox11.c -ljson-c -lXmu -lXt -lX11 -o kintox11
//
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <ctype.h>
#include <X11/Xlib.h> // `apt-get install libx11-dev`
#include <X11/Xmu/WinUtil.h> // `apt-get install libxmu-dev`
#include <json-c/json.h> // `apt install libjson-c-dev`
Bool xerror = False;
int in_int(int a[],int size,int item)
{
int i,pos=-1;
for(i=0;i< size;i++)
{
if(a[i]==item)
{
pos=i;
break;
}
}
return pos;
}
int in(const char **arr, int len, char *target) {
int i;
for(i = 0; i < len; i++) {
if(strncmp(arr[i], target, strlen(target)) == 0) {
return i;
}
}
return -1;
}
int strcicmp(char const *a, char const *b)
{
for (;; a++, b++) {
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
if (d != 0 || !*a)
return d;
}
}
Display* open_display(){
Display* d = XOpenDisplay(NULL);
if(d == NULL){
printf("fail to open X server display...\n");
exit(1);
}
return d;
}
int handle_error(Display* display, XErrorEvent* error){
// printf("X11 error: type=%d, serial=%lu, code=%d\n",
// error->type, error->serial, (int)error->error_code);
// xerror = True;
return 0;
}
Window get_focus_window(Display* d){
Window w;
int revert_to;
XGetInputFocus(d, &w, &revert_to); // see man
if(xerror){
printf("Error getting focused window\n");
exit(1);
}else if(w == None){
printf("no focus window\n");
exit(1);
}
return w;
}
const char * str_window_class(Display* d, Window w, char *prior_app ){
Status s;
XClassHint* class;
class = XAllocClassHint(); // see man
if(xerror){
// printf("ERROR: XAllocClassHint\n");
}
s = XGetClassHint(d, w, class); // see man
if(xerror || s){
char * app_class;
app_class = malloc(sizeof(char)*100);
strcpy(app_class,class->res_class);
// printf("\tname: %s\n\tclass: %s\n", class->res_name, class->res_class);
return app_class;
}else{
// char * error_msg;
// error_msg = malloc(sizeof(char)*50);
// strcpy(error_msg, "ERROR: XGetClassHint");
return prior_app;
}
}
int main(void){
FILE *fp;
char buffer[10240];
struct json_object *parsed_json, *config, *config_obj,
*config_obj_name, *config_obj_run, *config_obj_de,
*config_obj_appnames, *appnames_obj, *init, *de,
*de_obj, *de_obj_id, *de_obj_active, *de_obj_run,
*de_obj_runterm,*de_obj_rungui;
int arraylen;
int appnames_len, init_len, de_len, config_de_len;
int system(const char *command);
size_t i,n,r;
fp = fopen("user_config.json","r");
fread(buffer, 10240, 1, fp);
fclose(fp);
parsed_json = json_tokener_parse(buffer);
config = json_object_object_get(parsed_json, "config");
init = json_object_object_get(parsed_json, "init");
de = json_object_object_get(parsed_json, "de");
arraylen = json_object_array_length(config);
init_len = json_object_array_length(init);
de_len = json_object_array_length(de);
const char *name_array[arraylen];
const char *run_array[arraylen];
int init_array[init_len];
int de_id_array[de_len];
Bool de_active_array[de_len];
const char *de_run_array[de_len];
const char *de_runterm_array[de_len];
const char *de_rungui_array[de_len];
// Grab all de variable info needed
for (i = 0; i < de_len; i++) {
de_obj = json_object_array_get_idx(de, i);
de_obj_id = json_object_object_get(de_obj, "id");
de_id_array[i] = json_object_get_int(de_obj_id);
de_obj_active = json_object_object_get(de_obj, "active");
de_active_array[i] = json_object_get_int(de_obj_active);
de_obj_run = json_object_object_get(de_obj, "run");
de_run_array[i] = json_object_get_string(de_obj_run);
de_obj_runterm = json_object_object_get(de_obj, "run_term");
de_runterm_array[i] = json_object_get_string(de_obj_runterm);
de_obj_rungui = json_object_object_get(de_obj, "run_gui");
de_rungui_array[i] = json_object_get_string(de_obj_rungui);
// printf("de_run_array[%ld]: %s\n",i,de_run_array[i]);
}
// de ends
int appnames_max = 0;
int config_de_max = 0;
for (i = 0; i < arraylen; i++) {
config_obj = json_object_array_get_idx(config, i);
config_obj_appnames = json_object_object_get(config_obj, "appnames");
config_obj_de = json_object_object_get(config_obj, "de");
appnames_len = json_object_array_length(config_obj_appnames);
if (appnames_len > appnames_max){
appnames_max = appnames_len;
}
config_de_len = json_object_array_length(config_obj_de);
if(config_de_len > config_de_max){
config_de_max = config_de_len;
}
}
const char *appnames_array[arraylen][appnames_max];
int config_de_array[arraylen][config_de_max];
for (i = 0; i < arraylen; i++) {
config_obj = json_object_array_get_idx(config, i);
config_obj_name = json_object_object_get(config_obj, "name");
config_obj_run = json_object_object_get(config_obj, "run");
name_array[i] = json_object_get_string(config_obj_name);
run_array[i] = json_object_get_string(config_obj_run);
// printf("%s\n%s\n", json_object_get_string(config_obj_name), json_object_get_string(config_obj_run));
config_obj_appnames = json_object_object_get(config_obj, "appnames");
appnames_len = json_object_array_length(config_obj_appnames);
for (n = 0; n < appnames_len; n++) {
// printf("name_array[i]: %s\n",name_array[i]);
if(!strcicmp(name_array[i], "gui")){
appnames_array[i][n] = NULL;
// printf("%s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
}
else{
appnames_array[i][n] = json_object_get_string(json_object_array_get_idx(config_obj_appnames, n));
// printf("%s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
}
}
if(appnames_max > appnames_len){
for (n = appnames_len; n < appnames_max; n++){
appnames_array[i][n] = NULL;
// printf("%s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
}
}
config_obj_de = json_object_object_get(config_obj, "de");
config_de_len = json_object_array_length(config_obj_de);
for (n = 0; n < config_de_max; n++) {
if(n < config_de_len){
// printf("de value: %d\n",json_object_get_int(json_object_array_get_idx(config_obj_de, n)));
config_de_array[i][n] = json_object_get_int(json_object_array_get_idx(config_obj_de, n));
}
else{
// printf("de -1 value: %d\n",json_object_get_int(json_object_array_get_idx(config_obj_de, n)));
config_de_array[i][n] = -1;
}
}
}
for (i = 0; i < init_len; i++) {
init_array[i] = json_object_get_int(json_object_array_get_idx(init, i));
int de_id_idx = in_int(de_id_array, de_len, init_array[i]);
printf("Running init command: %s\n",de_run_array[de_id_idx]);
system(de_run_array[de_id_idx]);
}
Display* d;
Window w;
// for XmbTextPropertyToTextList
setlocale(LC_ALL, ""); // see man locale
d = open_display();
XSelectInput(d, DefaultRootWindow(d), SubstructureNotifyMask);
XSetErrorHandler(handle_error);
char * prior_app;
prior_app = malloc(sizeof(char)*100);
strcpy(prior_app,"none");
int remap_bool = 2;
// get active window
w = get_focus_window(d);
int breakouter;
for (;;)
{
breakouter = 0;
// printf("%s\n","1");
// printf("%s\n",str_window_class(d, w,prior_app));
if(strcmp(str_window_class(d, w,prior_app),prior_app)){
// printf("%s\n","2");
for(i = 0; i < arraylen; ++i){
if(breakouter == 0){
if(strcmp(name_array[i],"gui")){
// printf("%s\n","3");
for(n = 0; n < appnames_max; ++n){
if (appnames_array[i][n] != NULL){
// printf("%s\n",appnames_array[i][n]);
// If statement for triggering terminal config
if((strcicmp(appnames_array[i][n], str_window_class(d, w,prior_app)) == 0 && (remap_bool == 1 || remap_bool == 2))) {
// printf("1st if %s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
printf("%s\n",name_array[i]);
system(run_array[i]);
for(r = 0; r < config_de_max; r++){
if(config_de_array[i][r] != -1){
int de_id_idx = in_int(de_id_array, de_len, config_de_array[i][r]);
// printf("Running de command: %s\n",de_run_array[de_id_idx]);
system(de_runterm_array[de_id_idx]);
}
}
remap_bool = 0;
fflush(stdout);
breakouter = 1;
break;
} // Else command for ignoring similar app category based on config
else if((strcicmp(appnames_array[i][n], str_window_class(d, w,prior_app)) == 0 && remap_bool == 0)){
// printf("2nd elseif %s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
// printf("%s\n","4");
breakouter = 1;
break;
} // Else command for triggering gui config
else if ((i == arraylen-1 || appnames_array[i][n+1] == NULL) && (remap_bool == 0 || remap_bool == 2)){
char *find = "gui";
int gui_idx = in(name_array, arraylen, find);
if(gui_idx >= 0) {
printf("%s\n",name_array[gui_idx]);
system(run_array[gui_idx]);
}
for(r = 0; r < config_de_max; r++){
if(config_de_array[gui_idx][r] != -1){
int de_id_idx = in_int(de_id_array, de_len, config_de_array[gui_idx][r]);
// printf("Running de command: %s\n",de_run_array[de_id_idx]);
system(de_rungui_array[de_id_idx]);
}
}
// printf("3rd elseif %s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
remap_bool = 1;
fflush(stdout);
breakouter = 1;
break;
}
}
}
}
}
else{
break;
}
}
}
// printf("%s\n","5");
strcpy(prior_app,str_window_class(d, w, prior_app));
XEvent e;
XNextEvent(d, &e);
w = get_focus_window(d);
}
}

View File

@@ -12,4 +12,4 @@ line=$(cat ~/.xkb/keymap/kbd.mac.gui | grep -n 'xkb_types' | cut -f1 -d:)
sed -ie "${line}s/\"/+mac_gui(addmac_levels)\"/2" ~/.xkb/keymap/kbd.mac.gui
sleep 1
line=$(cat ~/.xkb/keymap/kbd.mac.term | grep -n 'xkb_symbols' | cut -f1 -d:)
sed -ie "${line}s/\"/+altwin(alt_super_win)\"/2" ~/.xkb/keymap/kbd.mac.term
sed -ie "${line}s/\"/+altwin(alt_super_win)+mac_term(mac_levelssym)\"/2" ~/.xkb/keymap/kbd.mac.term

View File

@@ -12,4 +12,4 @@ line=$(cat ~/.xkb/keymap/kbd.mac.gui | grep -n 'xkb_types' | cut -f1 -d:)
sed -ie "${line}s/\"/+mac_gui(addmac_levels)\"/2" ~/.xkb/keymap/kbd.mac.gui
sleep 1
line=$(cat ~/.xkb/keymap/kbd.mac.term | grep -n 'xkb_symbols' | cut -f1 -d:)
sed -ie "${line}s/\"/+altwin(swap_alt_win)\"/2" ~/.xkb/keymap/kbd.mac.term
sed -ie "${line}s/\"/+altwin(swap_alt_win)+mac_term(mac_levelssym)\"/2" ~/.xkb/keymap/kbd.mac.term

9
old_uninstall.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
systemctl --user stop keyswap
systemctl --user disable keyswap
rm -rf ~/.config/autostart/keyswap.sh
rm -rf ~/.config/xactive.sh
rm -rf ~/.xkb
sed -i '/xkb/d' ~/.Xsession

57
prekinto.py Normal file
View File

@@ -0,0 +1,57 @@
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
CBOLD = '\033[1m'
CITALIC = '\033[3m'
CURL = '\033[4m'
CBLINK = '\033[5m'
CBLINK2 = '\033[6m'
CSELECTED = '\033[7m'
CBLACK = '\033[30m'
CRED = '\033[31m'
CGREEN = '\033[32m'
CYELLOW = '\033[33m'
CBLUE = '\033[34m'
CVIOLET = '\033[35m'
CBEIGE = '\033[36m'
CWHITE = '\033[37m'
CBLACKBG = '\033[40m'
CREDBG = '\033[41m'
CGREENBG = '\033[42m'
CYELLOWBG = '\033[43m'
CBLUEBG = '\033[44m'
CVIOLETBG = '\033[45m'
CBEIGEBG = '\033[46m'
CWHITEBG = '\033[47m'
CGREY = '\033[90m'
CRED2 = '\033[91m'
CGREEN2 = '\033[92m'
CYELLOW2 = '\033[93m'
CBLUE2 = '\033[94m'
CVIOLET2 = '\033[95m'
CBEIGE2 = '\033[96m'
CWHITE2 = '\033[97m'
CGREYBG = '\033[100m'
CREDBG2 = '\033[101m'
CGREENBG2 = '\033[102m'
CYELLOWBG2 = '\033[103m'
CBLUEBG2 = '\033[104m'
CVIOLETBG2 = '\033[105m'
CBEIGEBG2 = '\033[106m'
CWHITEBG2 = '\033[107m'
def yn_choice(message, default='y'):
choices = 'Y/n' if default.lower() in ('y', 'yes') else 'y/N'
choice = input("%s (%s) " % (message, choices))
values = ('y', 'yes', '') if choices == 'Y/n' else ('y', 'yes')
return choice.strip().lower() in values

165
setup.py Executable file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env python3
import json, time, os
from shutil import copyfile
from subprocess import PIPE, Popen
from prekinto import *
homedir = os.path.expanduser("~")
def cmdline(command):
process = Popen(
args=command,
stdout=PIPE,
universal_newlines=True,
shell=True
)
return process.communicate()[0]
try:
f = open("defaults.json")
except IOError:
print("defaults.json file is missing. Will exit.\n")
exit()
f.close()
try:
f = open("user_config.json")
except IOError:
print("user_config.json file is missing. Will exit.\n")
exit()
f.close()
if os.path.isdir(homedir + "/.config/kinto") == False:
os.mkdir(homedir + "/.config/kinto")
time.sleep(0.5)
try:
f = open(homedir + "/.config/kinto/user_config.json")
rewrite = yn_choice("~/.config/kinto/user_config.json already exists. Do you want to overwrite it with a new config?")
print("")
if(rewrite):
copyfile("user_config.json", homedir + "/.config/kinto/user_config.json")
else:
exit()
except IOError:
pass
copyfile("user_config.json", homedir + "/.config/kinto/user_config.json")
finally:
f.close()
with open('defaults.json') as json_file:
data = json.load(json_file)
color_arr = [bcolors.CBLUE,bcolors.CRED,bcolors.CGREEN]
print("\nKinto - Type in Linux like it's a Mac.\n")
for index, item in enumerate(data['defaulttypes']):
ossym = ""
if item == "windows":
ossym = u'\u2756'
elif item == "mac":
ossym = u'\u2318'
elif item == "chromebook":
ossym = u'\u2707'
print("%s %i. %s %s %s" % (color_arr[index], index+1, ossym, item.capitalize(), bcolors.ENDC))
default = 0
while not int(default) in range(1,len(data['defaulttypes'])+1):
default = int(input(bcolors.CYELLOW + "\nPlease enter your keyboard type (1 - " + str(len(data['defaulttypes'])) + ") : " + bcolors.ENDC))
print("")
keyboardconfigs = [obj for obj in data['defaults'] if(obj['type'] == data['defaulttypes'][default-1])]
# for k in keyboardconfigs:
for index, k in enumerate(keyboardconfigs):
print(color_arr[default-1] + bcolors.BOLD + str(index+1) + '. ' + k['name'] + bcolors.ENDC)
print(bcolors.CYELLOW + 'Description: ' + k['description'] + bcolors.ENDC)
print("")
defaultkb = 0
while not int(defaultkb) in range(1,len(keyboardconfigs)+1):
defaultkb = int(input(bcolors.CYELLOW + "Please enter your keyboard config (1 - " + str(len(keyboardconfigs)) + ") : " + bcolors.ENDC))
print("")
if 'hack' in keyboardconfigs[defaultkb-1]:
print(bcolors.CYELLOW + "You have selected a keyboard config that needs the following command to be ran.\n" + bcolors.ENDC)
print(keyboardconfigs[defaultkb-1]['hack'].replace(";", "\n") + "\n")
runhack = yn_choice(bcolors.CYELLOW + "Would you like to run it now? (Will require sudo privileges. Will exit on No.)" + bcolors.ENDC)
if(runhack):
os.system(keyboardconfigs[defaultkb-1]['hack'])
# Setup the selected keyboards config
os.system("cp -rf ./.xkb ~/.xkb")
if os.path.isdir(homedir + "/.xkb/keymap") == False:
os.mkdir(homedir + "/.xkb/keymap")
time.sleep(0.5)
os.system('setxkbmap -option')
os.system('setxkbmap -print > ~/.xkb/keymap/kbd.mac.gui')
os.system('setxkbmap -print > ~/.xkb/keymap/kbd.mac.term')
time.sleep(0.5)
symbols_gui_line = cmdline("cat ~/.xkb/keymap/kbd.mac.gui | grep -n 'xkb_symbols' | cut -f1 -d:").strip()
types_gui_line = cmdline("cat ~/.xkb/keymap/kbd.mac.gui | grep -n 'xkb_types' | cut -f1 -d:").strip()
symbols_term_line = cmdline("cat ~/.xkb/keymap/kbd.mac.term | grep -n 'xkb_symbols' | cut -f1 -d:").strip()
cmdline('sed -i '' -e "' + symbols_gui_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_symbols_gui'] + '\\"/2" ~/.xkb/keymap/kbd.mac.gui')
cmdline('sed -i '' -e "' + types_gui_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_types_gui'] + '\\"/2" ~/.xkb/keymap/kbd.mac.gui')
cmdline('sed -i '' -e "' + symbols_term_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_symbols_term'] + '\\"/2" ~/.xkb/keymap/kbd.mac.term')
user_file = homedir + '/.config/kinto/user_config.json'
with open(user_file, 'r') as f:
user_config = json.load(f)
onetime = yn_choice("One time initialization tweaks are available. Would you like to view them?")
print("")
if(onetime):
intents = [obj for obj in user_config['de'] if(obj['intent'] == "init")]
for index, k in enumerate(intents):
print(color_arr[default-1] + bcolors.BOLD + str(index+1) + '. ' + k['name'] + bcolors.ENDC)
print(bcolors.CYELLOW + 'Description: ' + k['description'] + bcolors.ENDC)
print(bcolors.CYELLOW + 'run: ' + k['run'].replace(";", "\n") + bcolors.ENDC + '\n')
print(bcolors.CYELLOW + "Please enter your init tweak(s) (eg 1 or 1 2 3 - leave blank to skip): " + bcolors.ENDC)
defaultinit = [int(i) for i in input().split()]
if len(defaultinit) != 0:
user_config['init'] = defaultinit
print("\nDynamic shortcut tweaks\n")
intents = [obj for obj in user_config['de'] if(obj['intent'] == "gui_term")]
for index, k in enumerate(intents):
print(color_arr[default-1] + bcolors.BOLD + str(index+1) + '. ' + k['name'] + bcolors.ENDC)
print(bcolors.CYELLOW + 'Description: ' + k['description'] + bcolors.ENDC)
print(bcolors.CYELLOW + 'run in gui mode: ' + k['run_gui'].replace(";", "\n") + bcolors.ENDC)
print(bcolors.CYELLOW + 'run in terminal mode: ' + k['run_term'].replace(";", "\n") + bcolors.ENDC + '\n')
print(bcolors.CYELLOW + "Please enter your dynamic shortcut tweak(s) (eg 1 or 1 2 3 - leave blank to skip): " + bcolors.ENDC)
defaultde = [int(i) for i in input().split()]
if len(defaultde) != 0:
# gui
user_config['config'][0]['de'] = defaultde
# term
user_config['config'][1]['de'] = defaultde
for d in defaultde:
user_config['de'][d-1]['active'] = True
user_config['config'][0]['run'] = keyboardconfigs[defaultkb-1]['gui']
user_config['config'][1]['run'] = keyboardconfigs[defaultkb-1]['term']
os.remove(user_file)
with open(user_file, 'w') as f:
json.dump(user_config, f, indent=4)
print("Saved configuration to ~/.config/kinto/user_config.json\n")
print("Now running keyswap_service.sh to setup the keyswap service...")
print("Keyswap will be configured to run on user login\n")
print("You may start, stop, restart or view the status of the service with following commands\n")
print("systemctl --user start keyswap")
print("systemctl --user stop keyswap")
print("systemctl --user restart keyswap")
print("systemctl --user status keyswap")
os.system("./keyswap_service.sh")

BIN
splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -8,7 +8,7 @@ Type=simple
#Group={username}
Environment=DISPLAY=:0
Restart=always
WorkingDirectory=/home/{username}/.config/
WorkingDirectory=/home/{username}/.config/kinto
ExecStart=
[Install]

View File

@@ -1,93 +1,3 @@
#!/bin/bash
# How to add more terminal editors
# run this command while using the terminal
# and add the name to class_name
# xprop -id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2) WM_CLASS
class_name='konsole\|Gnome-terminal\|terminator\|sakura\|guake\|tilda\|xterm\|eterm'
systemtype=$1
internalid=$2
usbid=$3
swapbehavior=$4
# echo $1 $2 $3 $4
swapcmd_term="setxkbmap -option;setxkbmap -option altwin:swap_alt_win"
fallbackcmd_gui=""
if [[ "$systemtype" == "windows" || "$systemtype" == "mac" ]]; then
swapcmd_gui="setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui $DISPLAY"
check_gt="setxkbmap -query | grep -v 'swap_alt_win' 1>/dev/null"
check_tg="setxkbmap -query | grep -q 'swap_alt_win'"
# mac_only is for apple keyboards without an apple hid driver
elif [[ "$systemtype" == "mac_only" ]]; then
swapcmd_gui="setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui $DISPLAY"
check_gt="setxkbmap -query | grep -v 'alt_super_win' 1>/dev/null"
check_tg="setxkbmap -query | grep -q 'alt_super_win'"
swapcmd_term="setxkbmap -option"
# Chromebook options
elif [[ "$swapbehavior" == "both_mac" ]]; then
swapcmd_gui="setxkbmap -option;setxkbmap -option ctrl:swap_lwin_lctl; xkbcomp -w0 -i $internalid -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY"
swapcmd_term="setxkbmap -option;setxkbmap -device $internalid -option 'altwin:swap_alt_win'"
check_gt="setxkbmap -query | grep -v 'swap_alt_win' 1>/dev/null"
check_tg="setxkbmap -query | grep -q 'swap_alt_win'"
elif [[ "$swapbehavior" == "both_win" ]]; then
swapcmd_gui="setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY; setxkbmap -device $usbid -option altwin:ctrl_alt_win"
fallbackcmd_gui="setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY"
check_gt="setxkbmap -query | grep -q 'ctrl_alt_win'"
check_tg="setxkbmap -query | grep -v 'ctrl_alt_win' 1>/dev/null"
elif [[ "$swapbehavior" == "none" ]]; then
swapcmd_gui="setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY"
check_gt="setxkbmap -query | grep -v 'swap_alt_win' 1>/dev/null"
check_tg="setxkbmap -query | grep -q 'swap_alt_win'"
fi
# echo "$systemtype $swapbehavior"
# echo "$swapcmd_gui"
eval "$swapcmd_gui"
# regex for extracting hex id's
grep_id='0[xX][a-zA-Z0-9]\+'
#Storing timestamp and will use timediff to prevent xprop duplicates
timestp=$(date +%s)
xprop -spy -root _NET_ACTIVE_WINDOW | grep --line-buffered -o $grep_id |
while read -r id; do
class="`xprop -id $id WM_CLASS | grep $class_name`"
newtime=$(date +%s)
timediff=$((newtime-timestp))
if [ $timediff -gt 0 ]; then
if [ -n "$class" ]; then
# Set keymap for terminal, Alt is Super, Ctrl is Ctrl, Super is Alt
eval "$check_gt"
echo $?
if [ $? -eq 0 ]; then
echo "internal gui to term"
eval "$swapcmd_term"
# Quick hack, will want to refactor later
# just resets required checks, for chromebooks that
# use usb windows keyboards
if [[ "$swapbehavior" == "both_win" ]]; then
check_gt="setxkbmap -query | grep -q 'ctrl_alt_win'"
check_tg="setxkbmap -query | grep -v 'ctrl_alt_win' 1>/dev/null"
fi
fi
else
# Set keymap for gui, Alt is Ctrl,Super is Alt, Ctrl is Super
eval "$check_tg"
echo $?
if [ $? -eq 0 ]; then
echo "internal term to gui"
eval "$swapcmd_gui"
if [ $? -eq 0 ] && [[ "$swapbehavior" == "both_win" ]]; then
eval "$fallbackcmd_gui"
check_gt="setxkbmap -query | grep -v 'swap_alt_win' 1>/dev/null"
check_tg="setxkbmap -query | grep -q 'swap_alt_win'"
fi
fi
fi
timestp=$(date +%s)
fi
done
./kintox11

View File

@@ -3,7 +3,7 @@
systemctl --user stop keyswap
systemctl --user disable keyswap
rm -rf ~/.config/autostart/keyswap.sh
rm -rf ~/.config/xactive.sh
rm -rf ~/.config/kinto
rm -rf ~/.xkb
sed -i '/xkb/d' ~/.Xsession

48
user_config.json Normal file
View File

@@ -0,0 +1,48 @@
{"config":[{
"name":"gui",
"run":"",
"de":[],
"appnames":[ "" ]
},
{
"name":"term",
"run":"",
"de":[],
"appnames":[ "Gnome-terminal","konsole","io.elementary.terminal","terminator","sakura","guake","tilda","xterm","eterm" ]
}],
"init": [],
"detypes":["gnome2","gnome3","kde4","kde5","xfce","i3wm"],
"de":[{
"id": 1,
"type": ["gnome3"],
"active": false,
"intent":"init",
"name":"gnome-init",
"description":"Gnome - Remove Superkey Overlay keybinding to Activities Overview",
"run":"gsettings set org.gnome.mutter overlay-key ''",
"run_term":"",
"run_gui":""
},
{
"id": 2,
"type": ["gnome3"],
"active": false,
"intent":"gui_term",
"name":"Gnome Activities Overview",
"description":"Cmd+Space activates Activities Overview",
"run":"",
"run_term":"gsettings set org.gnome.desktop.wm.keybindings panel-main-menu \"['<Control><Shift>Space']\"",
"run_gui":"gsettings set org.gnome.desktop.wm.keybindings panel-main-menu \"['<Ctrl>Space']\""
},
{
"id": 3,
"type": ["kde5"],
"active": false,
"intent":"init",
"name":"kde-init",
"description":"KDE Plasma 5 - Removes Superkey Overlay from the Launcher Menu",
"run":"kwriteconfig5 --file ~/.config/kwinrc --group ModifierOnlyShortcuts --key Meta \"\";qdbus org.kde.KWin /KWin reconfigure",
"run_term":"",
"run_gui":""
}]
}