mirror of
https://github.com/rbreaves/kinto.git
synced 2025-08-05 18:38:26 +02:00
Compare commits
70 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5a2299d8dc | ||
![]() |
83ae169fb7 | ||
![]() |
5c6e42b811 | ||
![]() |
cd57efd89b | ||
![]() |
28bad9ed42 | ||
![]() |
ddfcd57c6b | ||
![]() |
4b4fc7fc3f | ||
![]() |
16c4378c2e | ||
![]() |
9dc026695b | ||
![]() |
c65d68d816 | ||
![]() |
3983107be5 | ||
![]() |
56391169ff | ||
![]() |
ac5c5f6648 | ||
![]() |
778d1df1ba | ||
![]() |
fbe2451a3c | ||
![]() |
5a56ea823f | ||
![]() |
5d5d8de92e | ||
![]() |
086ab8bb35 | ||
![]() |
dc016d9270 | ||
![]() |
8f1795339e | ||
![]() |
4fb65d7025 | ||
![]() |
93daf8707e | ||
![]() |
50885a7e78 | ||
![]() |
ea60bb6db5 | ||
![]() |
4281d97c3d | ||
![]() |
364536b8ea | ||
![]() |
2585ab9f45 | ||
![]() |
7969bd007d | ||
![]() |
5d135afe5e | ||
![]() |
a4fa9b225e | ||
![]() |
eac62fb605 | ||
![]() |
ab679ddf9d | ||
![]() |
f4cef736be | ||
![]() |
2179176881 | ||
![]() |
26f70ccd31 | ||
![]() |
0ff7a42f9b | ||
![]() |
58da4fcd90 | ||
![]() |
20170f0a7d | ||
![]() |
d90829928b | ||
![]() |
6f913538e8 | ||
![]() |
7dfbe884ff | ||
![]() |
3a115f91ae | ||
![]() |
4c218b55bd | ||
![]() |
94cd3ed907 | ||
![]() |
b0bde4fecf | ||
![]() |
b930b96066 | ||
![]() |
2df4920344 | ||
![]() |
ce9c80a02f | ||
![]() |
e599562ec1 | ||
![]() |
b8b81bd907 | ||
![]() |
22e5462fbc | ||
![]() |
72d2007267 | ||
![]() |
3c5b49324c | ||
![]() |
3f37ef6e28 | ||
![]() |
35cfcce748 | ||
![]() |
d288048ed4 | ||
![]() |
a30671b08c | ||
![]() |
2f2afecb6d | ||
![]() |
072249d5d4 | ||
![]() |
a6b9b1ffbb | ||
![]() |
d8c516c13c | ||
![]() |
b763703d70 | ||
![]() |
ecaf413fa4 | ||
![]() |
48e01750e5 | ||
![]() |
5ec8c076a3 | ||
![]() |
c620b299bd | ||
![]() |
496cb4d340 | ||
![]() |
5f1e82fb24 | ||
![]() |
46e81640c6 | ||
![]() |
1c56c98ab9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.env/
|
||||
.DS_Store
|
||||
__pycache__/
|
||||
|
@@ -1,15 +1,15 @@
|
||||
default partial xkb_symbols "mac_levelssym" {
|
||||
// LEFT to Begin Line
|
||||
// LEFT to Begin Line or Beginning of word
|
||||
replace key <LEFT> {
|
||||
type[Group1]= "ONE_LEVEL_CTRL",
|
||||
symbols[Group1]= [ Left, Left, NoSymbol ],
|
||||
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<HOME>,clearmods=Control)]
|
||||
actions[Group1]= [ NoAction(), RedirectKey(key=<LEFT>,modifiers=Control,clearmods=Mod1), RedirectKey(key=<HOME>,clearmods=Control)]
|
||||
};
|
||||
// Right to End of Line
|
||||
// Right to End of Line or end of word
|
||||
replace key <RGHT> {
|
||||
type[Group1]= "ONE_LEVEL_CTRL",
|
||||
symbols[Group1]= [ Right, Right, NoSymbol ],
|
||||
actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<END>,clearmods=Control)]
|
||||
actions[Group1]= [ NoAction(), RedirectKey(key=<RGHT>,modifiers=Control,clearmods=Mod1), RedirectKey(key=<END>,clearmods=Control)]
|
||||
};
|
||||
// Up to Mac Home
|
||||
replace key <UP> {
|
||||
@@ -30,3 +30,17 @@ default partial xkb_symbols "mac_levelssym" {
|
||||
// actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<DELE>,clearmods=Control)]
|
||||
// };
|
||||
};
|
||||
partial xkb_symbols "mac_chrome" {
|
||||
// Back Button
|
||||
replace key <LEFT> {
|
||||
type[Group1]= "ONE_LEVEL_CTRL",
|
||||
symbols[Group1]= [ Left, Left, Left ],
|
||||
actions[Group1]= [ NoAction(), RedirectKey(key=<UP>), RedirectKey(key=<LEFT>,modifiers=Mod1,clearmods=Control)]
|
||||
};
|
||||
// Forwards Button
|
||||
replace key <RGHT> {
|
||||
type[Group1]= "ONE_LEVEL_CTRL",
|
||||
symbols[Group1]= [ Right, Right, Right ],
|
||||
actions[Group1]= [ NoAction(), RedirectKey(key=<DOWN>), RedirectKey(key=<RGHT>,modifiers=Mod1,clearmods=Control)]
|
||||
};
|
||||
};
|
14
.xkb/symbols/mac_term_chromebook
Normal file
14
.xkb/symbols/mac_term_chromebook
Normal file
@@ -0,0 +1,14 @@
|
||||
default partial xkb_symbols "mac_levelssym" {
|
||||
key <LALT> {
|
||||
repeat= no,
|
||||
type= "ONE_LEVEL",
|
||||
symbols[Group1]= [ Hyper_L ],
|
||||
actions[group1]=[ SetMods(modifiers=Shift+Control) ]
|
||||
};
|
||||
key <RALT> {
|
||||
repeat= no,
|
||||
type= "ONE_LEVEL",
|
||||
symbols[Group1]= [ Hyper_R ],
|
||||
actions[group1]=[ SetMods(modifiers=Shift+Control) ]
|
||||
};
|
||||
};
|
@@ -1,20 +1,11 @@
|
||||
default partial xkb_types "addmac_levels" {
|
||||
type "ONE_LEVEL_CTRL" {
|
||||
modifiers= Shift+Control;
|
||||
map[Shift]= Level2;
|
||||
modifiers= Mod1+Control;
|
||||
map[Mod1]= Level2;
|
||||
map[Control]= Level3;
|
||||
map[Shift+Control]= Level3;
|
||||
map[Mod1+Control]= Level3;
|
||||
level_name[Level1]= "Base";
|
||||
level_name[Level2]= "Caps";
|
||||
level_name[Level3]= "With Control";
|
||||
};
|
||||
type "TWO_LEVEL_CTRL" {
|
||||
modifiers= Shift+Control;
|
||||
map[Shift]= Level2;
|
||||
map[Control]= Level3;
|
||||
map[Shift+Control]= Level3;
|
||||
level_name[Level1]= "Base";
|
||||
level_name[Level2]= "Caps";
|
||||
level_name[Level2]= "Alt";
|
||||
level_name[Level3]= "With Control";
|
||||
};
|
||||
};
|
||||
|
48
README.md
48
README.md
@@ -2,15 +2,13 @@
|
||||
|
||||

|
||||
|
||||
[](https://github.com/rbreaves/kinto/releases)
|
||||
[](https://github.com/rbreaves/kinto/releases/latest)
|
||||
|
||||

|
||||
|
||||
\- Type in Linux like it's a Mac. \-
|
||||
|
||||
Memory muscle matters for programmers and developers.
|
||||
|
||||
If it happens on your mac keyboard then it should happen the same in linux.
|
||||
Cmd = Ctrl+Shift for all terminals.
|
||||
|
||||
Note: As of version 1.0 Kinto no longer maps Cmd/Alt to Super while using the Terminal, it is now mapping to Ctrl+Shift by default. Please reset your terminal's keymaps back to their defaults.
|
||||
|
||||
@@ -34,12 +32,21 @@ Kinto works for standard Windows, Apple and Chromebook keyboards. The following
|
||||
- Python (initial install only)
|
||||
- systemd
|
||||
- x11
|
||||
- IBus
|
||||
- Debian/Ubuntu based distro 16.04+
|
||||
|
||||
If you need kintox11 recompiled for your distro please let me know and I will add a binary for your distro if my binary fails.
|
||||
|
||||
You can also attempt to compile kintox11.c on your system as well, but you will need to compile and install json-c first as its libraries will be required to compile and run the program.
|
||||
|
||||
IBUS is needed to support wordwise during browser app usage as the keymap will need to change slightly depending if the cursor/caret is on screen waiting for input. You may install ibus with the following.
|
||||
|
||||
```
|
||||
ibus-setup
|
||||
```
|
||||
|
||||
And then navigate to your "Language Support" and set "Keyboard input method system:" to IBus for full word-wise support with web browsers.
|
||||
|
||||
Wayland support is planned, but not ready yet.
|
||||
|
||||
## How to install
|
||||
@@ -131,9 +138,9 @@ Status
|
||||
systemctl --user status keyswap
|
||||
```
|
||||
|
||||
Stop
|
||||
Stop (and reset keyboard to normal)
|
||||
```
|
||||
systemctl --user stop keyswap
|
||||
systemctl --user stop keyswap && setxkbmap -option
|
||||
```
|
||||
|
||||
Start
|
||||
@@ -167,19 +174,41 @@ systemctl --user stop keyswap && setxkbmap -option;setxkbmap -option altwin:swap
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Does not start when you log in or after you reboot?
|
||||
|
||||
1. Check the status
|
||||
```
|
||||
systemctl --user status keyswap
|
||||
```
|
||||
2. Check the service journal
|
||||
```
|
||||
journalctl -xe
|
||||
```
|
||||
|
||||
Open a ticket and send me the info.
|
||||
|
||||
### Keyswap is not occurring, but it was working.
|
||||
|
||||
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
|
||||
1. Get status
|
||||
```
|
||||
systemctl --user status keyswap
|
||||
```
|
||||
2. Restart Kinto
|
||||
```
|
||||
systemctl --user restart keyswap
|
||||
```
|
||||
2. Check the Status of Kinto and open a ticket with the output.
|
||||
3. Check the Status again and open a ticket if you need to.
|
||||
```
|
||||
systemctl --user status keyswap
|
||||
```
|
||||
|
||||
You can also do the following to see if it is an actual issue with kintox11 not running or your service file.
|
||||
```
|
||||
cd ~/.config/kinto
|
||||
./kintox11
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -196,6 +225,7 @@ https://superuser.com/questions/385748/binding-superc-superv-to-copy-and-paste
|
||||
|
||||
## More information about Kinto
|
||||
|
||||
https://medium.com/@benreaves/kinto-v1-0-released-2018e6401d2e
|
||||
https://medium.com/@benreaves/kinto-a-mac-inspired-keyboard-mapping-for-linux-58f731817c0
|
||||
|
||||
## License
|
||||
|
@@ -49,10 +49,10 @@
|
||||
"type":"chromebook",
|
||||
"active": false,
|
||||
"description":"Standard Chromebook Keyboards",
|
||||
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.chromebook.gui $DISPLAY",
|
||||
"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":"+chromebook(swap_lalt_lctrl)+mac_gui(mac_levelssym)",
|
||||
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
|
||||
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term_chromebook(mac_levelssym)",
|
||||
"xkb_types_gui":"+mac_gui(addmac_levels)",
|
||||
"xkb_types_term":""
|
||||
},
|
||||
@@ -62,11 +62,11 @@
|
||||
"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",
|
||||
"gui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.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",
|
||||
"fallbackgui":"setxkbmap -option;xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.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_symbols_term":"+altwin(swap_alt_win)+mac_term_chromebook(mac_levelssym)",
|
||||
"xkb_types_gui":"+mac_gui(addmac_levels)",
|
||||
"xkb_types_term":""
|
||||
},
|
||||
@@ -76,10 +76,10 @@
|
||||
"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",
|
||||
"gui":"setxkbmap -option;setxkbmap -option ctrl:swap_lwin_lctl; xkbcomp -w0 -i $internalid -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":"+chromebook(swap_lalt_lctrl)+mac_gui(mac_levelssym)",
|
||||
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term(mac_levelssym)",
|
||||
"xkb_symbols_term":"+altwin(swap_alt_win)+mac_term_chromebook(mac_levelssym)",
|
||||
"xkb_types_gui":"+mac_gui(addmac_levels)",
|
||||
"xkb_types_term":""
|
||||
}]
|
||||
|
@@ -1,13 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
swapcmd="\/bin\/bash\ \/home\/`whoami`\/.config\/kinto\/xactive.sh"
|
||||
systemctl --user stop keyswap >/dev/null 2>&1
|
||||
systemctl --user disable keyswap >/dev/null 2>&1
|
||||
systemctl --user stop keyswap.timer >/dev/null 2>&1
|
||||
systemctl --user disable keyswap.timer >/dev/null 2>&1
|
||||
swapcmd="\/bin\/bash -c \"\/home\/`whoami`\/.config\/kinto\/xactive.sh carrots\""
|
||||
swapstopcmd="\/bin\/bash \/home\/`whoami`\/.config\/kinto\/cleanup.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 ./system-config/kinto.desktop ~/.config/autostart/kinto.desktop
|
||||
cp ./kintox11/binary/kintox11 ~/.config/kinto/kintox11
|
||||
cp ./system-config/xactive.sh ~/.config/kinto/xactive.sh
|
||||
cp ./system-config/caret_status.sh ~/.config/kinto/caret_status.sh
|
||||
cp ./system-config/cleanup.sh ~/.config/kinto/cleanup.sh
|
||||
cp ./system-config/.firefox-nw ~/.config/kinto/.firefox-nw
|
||||
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 daemon-reload
|
||||
systemctl --user enable keyswap
|
||||
systemctl --user start keyswap
|
||||
systemctl --user start keyswap
|
||||
|
115
kintopy/kinto.py
Normal file
115
kintopy/kinto.py
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Kinto - Python implementation of Xlib
|
||||
#
|
||||
# Based on code by Stephan Sokolow
|
||||
# Source: https://gist.github.com/ssokolow/e7c9aae63fb7973e4d64cff969a78ae8
|
||||
from contextlib import contextmanager
|
||||
import Xlib
|
||||
import Xlib.display
|
||||
|
||||
# Connect to the X server and get the root window
|
||||
disp = Xlib.display.Display()
|
||||
root = disp.screen().root
|
||||
|
||||
# Prepare the property names we use so they can be fed into X11 APIs
|
||||
NET_ACTIVE_WINDOW = disp.intern_atom('_NET_ACTIVE_WINDOW')
|
||||
NET_WM_NAME = disp.intern_atom('_NET_WM_NAME') # UTF-8
|
||||
WM_NAME = disp.intern_atom('WM_NAME') # Legacy encoding
|
||||
NET_WM_CLASS = disp.intern_atom('_NET_WM_CLASS') # UTF-8
|
||||
WM_CLASS = disp.intern_atom('WM_CLASS')
|
||||
|
||||
last_seen = { 'xid': None, 'title': None }
|
||||
|
||||
@contextmanager
|
||||
def window_obj(win_id):
|
||||
"""Simplify dealing with BadWindow (make it either valid or None)"""
|
||||
window_obj = None
|
||||
if win_id:
|
||||
try:
|
||||
window_obj = disp.create_resource_object('window', win_id)
|
||||
except Xlib.error.XError:
|
||||
pass
|
||||
yield window_obj
|
||||
|
||||
def get_active_window():
|
||||
"""Return a (window_obj, focus_has_changed) tuple for the active window."""
|
||||
win_id = root.get_full_property(NET_ACTIVE_WINDOW,Xlib.X.AnyPropertyType).value[0]
|
||||
|
||||
focus_changed = (win_id != last_seen['xid'])
|
||||
if focus_changed:
|
||||
with window_obj(last_seen['xid']) as old_win:
|
||||
if old_win:
|
||||
old_win.change_attributes(event_mask=Xlib.X.NoEventMask)
|
||||
|
||||
last_seen['xid'] = win_id
|
||||
with window_obj(win_id) as new_win:
|
||||
if new_win:
|
||||
new_win.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
|
||||
|
||||
return win_id, focus_changed
|
||||
|
||||
def _get_window_class_inner(win_obj):
|
||||
for atom in (NET_WM_CLASS, WM_CLASS):
|
||||
try:
|
||||
window_class = win_obj.get_full_property(atom, 0)
|
||||
|
||||
except UnicodeDecodeError: # Apparently a Debian distro package bug
|
||||
title = "<could not decode characters>"
|
||||
else:
|
||||
if window_class:
|
||||
win_class = window_class.value.split('\x00')[1]
|
||||
if isinstance(win_class, bytes):
|
||||
# Apparently COMPOUND_TEXT is so arcane that this is how
|
||||
# tools like xprop deal with receiving it these days
|
||||
win_class = win_class.split('\x00')[1].decode('latin1', 'replace')
|
||||
return win_class
|
||||
else:
|
||||
title = "<unnamed window>"
|
||||
|
||||
return "{} (XID: {})".format(title, win_obj.id)
|
||||
|
||||
def get_window_class(win_id):
|
||||
"""Look up the window name for a given X11 window ID"""
|
||||
if not win_id:
|
||||
last_seen['title'] = "<no window id>"
|
||||
return last_seen['title']
|
||||
|
||||
title_changed = False
|
||||
with window_obj(win_id) as wobj:
|
||||
if wobj:
|
||||
win_title = _get_window_class_inner(wobj)
|
||||
title_changed = (win_title != last_seen['title'])
|
||||
last_seen['title'] = win_title
|
||||
|
||||
return last_seen['title'], title_changed
|
||||
|
||||
def handle_xevent(event):
|
||||
# Loop through, ignoring events until we're notified of focus/title change
|
||||
if event.type != Xlib.X.PropertyNotify:
|
||||
return
|
||||
|
||||
changed = False
|
||||
if event.atom == NET_ACTIVE_WINDOW:
|
||||
if get_active_window()[1]:
|
||||
changed = changed or get_window_class(last_seen['xid'])[1]
|
||||
elif event.atom in (NET_WM_CLASS, WM_CLASS):
|
||||
changed = changed or get_window_class(last_seen['xid'])[1]
|
||||
|
||||
if changed:
|
||||
handle_change(last_seen)
|
||||
|
||||
def handle_change(new_state):
|
||||
"""Replace this with whatever you want to actually do"""
|
||||
print(new_state['title'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Listen for _NET_ACTIVE_WINDOW changes
|
||||
root.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
|
||||
|
||||
# Prime last_seen with whatever window was active when we started this
|
||||
get_window_class(get_active_window()[0])
|
||||
handle_change(last_seen)
|
||||
|
||||
while True: # next_event() sleeps until we get an event
|
||||
handle_xevent(disp.next_event())
|
Binary file not shown.
5
kintox11/src/Makefile
Normal file
5
kintox11/src/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
CFLAGS=-g $(shell pkg-config --cflags json-c xmu)
|
||||
LDFLAGS=-g $(shell pkg-config --libs json-c xmu)
|
||||
|
||||
all:
|
||||
$(CC) kintox11.c $(CFLAGS) $(LDFLAGS) -lm -o kintox11
|
@@ -10,7 +10,7 @@
|
||||
//
|
||||
// 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
|
||||
// gcc -L/usr/local/lib/ kintox11.c -ljson-c -lXmu -lXt -lX11 -O2 -o kintox11
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -18,12 +18,116 @@
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.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`
|
||||
#include <sys/select.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
long long timeInMilliseconds(void) {
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000);
|
||||
}
|
||||
|
||||
static int wait_fd(int fd, double seconds)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set in_fds;
|
||||
FD_ZERO(&in_fds);
|
||||
FD_SET(fd, &in_fds);
|
||||
tv.tv_sec = trunc(seconds);
|
||||
tv.tv_usec = (seconds - trunc(seconds))*1000000;
|
||||
return select(fd+1, &in_fds, 0, 0, &tv);
|
||||
}
|
||||
|
||||
int XNextEventTimeout(Display *d, XEvent *e, double seconds, long long event_ts, int last_event, long long *event_ts_ptr, int *last_event_ptr)
|
||||
{
|
||||
if (XPending(d) || wait_fd(ConnectionNumber(d),seconds)) {
|
||||
// XNextEvent(d, e);
|
||||
// while (1) {
|
||||
// XNextEvent(d, e);
|
||||
// if(e->type != 16){
|
||||
// printf("Inside XNextEvent timeout\n");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
while (1) {
|
||||
XNextEvent(d, e);
|
||||
|
||||
long long int new_ts = timeInMilliseconds();
|
||||
|
||||
if(!(e->type == 22 && (e->type == last_event) && timeInMilliseconds()-event_ts < 419)){
|
||||
// printf("%d == %d\n",e->type, last_event);
|
||||
// printf("Timestamp: %lld\n",timeInMilliseconds()-event_ts);
|
||||
*event_ts_ptr = new_ts;
|
||||
*last_event_ptr = e->type;
|
||||
// printf("in event_ts_ptr: %lld\n",*event_ts_ptr);
|
||||
// printf("in last_event_ptr: %d\n",*last_event_ptr);
|
||||
break;
|
||||
}
|
||||
*event_ts_ptr = new_ts;
|
||||
*last_event_ptr = e->type;
|
||||
// printf("event_ts_ptr: %lld\n",*event_ts_ptr);
|
||||
// printf("last_event_ptr: %d\n",*last_event_ptr);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Bool xerror = False;
|
||||
|
||||
char *trimwhitespace(char *str)
|
||||
{
|
||||
char *end;
|
||||
// Trim leading space
|
||||
while(isspace((unsigned char)*str)) str++;
|
||||
if(*str == 0) // All spaces?
|
||||
return str;
|
||||
// Trim trailing space
|
||||
end = str + strlen(str) - 1;
|
||||
while(end > str && isspace((unsigned char)*end)) end--;
|
||||
// Write new null terminator character
|
||||
end[1] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
int check_caret()
|
||||
{
|
||||
int caretint;
|
||||
char * fpname;
|
||||
fpname = malloc(sizeof(char)*20);
|
||||
strcpy(fpname,"/tmp/kinto/caret");
|
||||
if( access( fpname, F_OK ) != -1 ) {
|
||||
char *buffer = NULL;
|
||||
size_t size = 0;
|
||||
FILE *fp = fopen(fpname, "r");
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = ftell(fp);
|
||||
rewind(fp);
|
||||
buffer = malloc((size + 1) * sizeof(*buffer));
|
||||
fread(buffer, size, 1, fp);
|
||||
buffer[size] = '\0';
|
||||
trimwhitespace(buffer);
|
||||
caretint = atoi(buffer);
|
||||
if(caretint == 1){
|
||||
// printf("caret: %s\n", buffer);
|
||||
return 1;
|
||||
}
|
||||
// printf("found nothing\n");
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
printf("file %s does not exist\n",fpname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int in_int(int a[],int size,int item)
|
||||
{
|
||||
int i,pos=-1;
|
||||
@@ -58,19 +162,30 @@ int strcicmp(char const *a, char const *b)
|
||||
}
|
||||
|
||||
Display* open_display(){
|
||||
int i;
|
||||
Display* d = XOpenDisplay(NULL);
|
||||
for (i = 0; i < 60; i++) {
|
||||
if(d == NULL){
|
||||
printf("fail to open X server display...\n");
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
if(d == NULL){
|
||||
printf("fail to open X server display...\n");
|
||||
printf("fail to open X server display for 1 minute...\n");
|
||||
printf("Kintox11 is now exiting...\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;
|
||||
printf("X11 error: type=%d, serial=%lu, code=%d\n",
|
||||
error->type, error->serial, (int)error->error_code);
|
||||
xerror = True;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Window get_focus_window(Display* d){
|
||||
@@ -88,6 +203,49 @@ Window get_focus_window(Display* d){
|
||||
return w;
|
||||
}
|
||||
|
||||
// get the top window.
|
||||
// a top window have the following specifications.
|
||||
// * the start window is contained the descendent windows.
|
||||
// * the parent window is the root window.
|
||||
Window get_top_window(Display* d, Window start){
|
||||
Window w = start;
|
||||
Window parent = start;
|
||||
Window root = None;
|
||||
Window *children;
|
||||
unsigned int nchildren;
|
||||
Status s;
|
||||
|
||||
while (parent != root && parent != 0) {
|
||||
w = parent;
|
||||
s = XQueryTree(d, w, &root, &parent, &children, &nchildren); // see man
|
||||
|
||||
if (s)
|
||||
XFree(children);
|
||||
|
||||
if(xerror){
|
||||
printf("fail to get top window: %ld\n",w);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// printf(" get parent (window: %d)\n", (int)w);
|
||||
}
|
||||
|
||||
// printf("success (window: %d)\n", (int)w);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
// search a named window (that has a WM_STATE prop)
|
||||
// on the descendent windows of the argment Window.
|
||||
Window get_named_window(Display* d, Window start){
|
||||
Window w;
|
||||
// printf("getting named window ... ");
|
||||
w = XmuClientWindow(d, start); // see man
|
||||
// if(w == start)
|
||||
// printf("fail\n");
|
||||
// printf("success (window: %d)\n", (int) w);
|
||||
return w;
|
||||
}
|
||||
|
||||
const char * str_window_class(Display* d, Window w, char *prior_app ){
|
||||
Status s;
|
||||
@@ -118,17 +276,18 @@ 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;
|
||||
*config_obj_name, *config_obj_run, *config_obj_run_oninput,
|
||||
*config_obj_run_offinput, *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;
|
||||
|
||||
|
||||
printf("Importing user_config.json...\n");
|
||||
fp = fopen("user_config.json","r");
|
||||
fread(buffer, 10240, 1, fp);
|
||||
fclose(fp);
|
||||
@@ -145,6 +304,8 @@ int main(void){
|
||||
|
||||
const char *name_array[arraylen];
|
||||
const char *run_array[arraylen];
|
||||
const char *run_oninput_array[arraylen];
|
||||
const char *run_offinput_array[arraylen];
|
||||
int init_array[init_len];
|
||||
|
||||
int de_id_array[de_len];
|
||||
@@ -193,10 +354,16 @@ int main(void){
|
||||
|
||||
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");
|
||||
config_obj_run_oninput = json_object_object_get(config_obj, "run_onInput");
|
||||
config_obj_run_offinput = json_object_object_get(config_obj, "run_offInput");
|
||||
|
||||
name_array[i] = json_object_get_string(config_obj_name);
|
||||
run_array[i] = json_object_get_string(config_obj_run);
|
||||
run_oninput_array[i] = json_object_get_string(config_obj_run_oninput);
|
||||
run_offinput_array[i] = json_object_get_string(config_obj_run_offinput);
|
||||
// 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");
|
||||
@@ -209,13 +376,13 @@ int main(void){
|
||||
}
|
||||
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]);
|
||||
//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]);
|
||||
//printf("%s i:%ld n:%ld %s\n",name_array[i],i,n,appnames_array[i][n]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,6 +400,8 @@ int main(void){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
printf("Data from user_config.json imported successfully.\n");
|
||||
|
||||
for (i = 0; i < init_len; i++) {
|
||||
init_array[i] = json_object_get_int(json_object_array_get_idx(init, i));
|
||||
@@ -243,6 +412,7 @@ int main(void){
|
||||
|
||||
Display* d;
|
||||
Window w;
|
||||
char *name;
|
||||
|
||||
// for XmbTextPropertyToTextList
|
||||
setlocale(LC_ALL, ""); // see man locale
|
||||
@@ -251,90 +421,149 @@ int main(void){
|
||||
XSelectInput(d, DefaultRootWindow(d), SubstructureNotifyMask);
|
||||
XSetErrorHandler(handle_error);
|
||||
|
||||
char * run_normal;
|
||||
char * run_onInput;
|
||||
char * run_offInput;
|
||||
char * prior_app;
|
||||
char * current_app;
|
||||
char * prior_category;
|
||||
char * current_category;
|
||||
run_onInput = malloc(sizeof(char)*400);
|
||||
run_offInput = malloc(sizeof(char)*400);
|
||||
run_normal = malloc(sizeof(char)*400);
|
||||
prior_app = malloc(sizeof(char)*100);
|
||||
current_app = malloc(sizeof(char)*100);
|
||||
prior_category = malloc(sizeof(char)*100);
|
||||
current_category = malloc(sizeof(char)*100);
|
||||
strcpy(prior_app,"none");
|
||||
strcpy(prior_category,"none");
|
||||
|
||||
int remap_bool = 2;
|
||||
|
||||
printf("Starting keyswap...\n");
|
||||
|
||||
// get active window
|
||||
w = get_focus_window(d);
|
||||
w = get_top_window(d, w);
|
||||
w = get_named_window(d, w);
|
||||
|
||||
// XFetchName(d, w, &name);
|
||||
// printf("window:%#x name:%s\n", w, name);
|
||||
printf("First window name: %s \n",str_window_class(d, w,prior_app));
|
||||
|
||||
int breakouter;
|
||||
int last_event=0;
|
||||
Bool ran_onInput = 0;
|
||||
long long int event_ts = timeInMilliseconds();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
strcpy(current_app,str_window_class(d, w,prior_app));
|
||||
int category_idx;
|
||||
// printf("current: %s\n",current_app);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Cycle through category name array
|
||||
// printf("%d\n",arraylen);
|
||||
for(i = 0; i < arraylen; ++i){
|
||||
// Cycle through the maximum App name array in each category
|
||||
for(n = 0; n < appnames_max; ++n){
|
||||
if (appnames_array[i][n] != NULL){
|
||||
// printf("%s\n",appnames_array[i][n]);
|
||||
if(strcicmp(appnames_array[i][n], current_app) == 0){
|
||||
strcpy(current_category,name_array[i]);
|
||||
category_idx = i;
|
||||
// printf("Match found: %s: %s\n",current_category,current_app);
|
||||
breakouter = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
else if(i == arraylen-1 && breakouter==0){
|
||||
// printf("No match found, default to gui");
|
||||
strcpy(current_category,"gui");
|
||||
category_idx = in(name_array, arraylen, current_category);
|
||||
// printf("Match found: %s: %s\n",current_category,current_app);
|
||||
break;
|
||||
}
|
||||
else if(appnames_array[i][n] == NULL){
|
||||
break;
|
||||
}
|
||||
if(breakouter==1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// printf("%s\n","5");
|
||||
strcpy(prior_app,str_window_class(d, w, prior_app));
|
||||
|
||||
if(strcicmp(prior_category, current_category) != 0){
|
||||
printf("%s: %s\n",current_category,current_app);
|
||||
// printf("run: %s\n",run_array[category_idx]);
|
||||
system(run_array[category_idx]);
|
||||
strcpy(run_normal,run_array[category_idx]);
|
||||
ran_onInput = 0;
|
||||
strcpy(run_onInput,run_oninput_array[category_idx]);
|
||||
strcpy(run_offInput,run_offinput_array[category_idx]);
|
||||
system(run_offInput);
|
||||
for(r = 0; r < config_de_max; r++){
|
||||
if(config_de_array[category_idx][r] != -1){
|
||||
int de_id_idx = in_int(de_id_array, de_len, config_de_array[category_idx][r]);
|
||||
if(strcicmp(current_category, "term") == 0){
|
||||
// printf("Running de term command: %s\n",de_runterm_array[de_id_idx]);
|
||||
system(de_runterm_array[de_id_idx]);
|
||||
}
|
||||
else{
|
||||
// printf("Running de gui command: %s\n",de_rungui_array[de_id_idx]);
|
||||
system(de_rungui_array[de_id_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strcicmp(prior_app, current_app) != 0){
|
||||
int indent = strlen(current_category)+2;
|
||||
printf("%*c%s\n", indent, ' ',current_app);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
strcpy(prior_app,current_app);
|
||||
strcpy(prior_category,current_category);
|
||||
|
||||
// printf("run_onInput: %ld\n",strlen(run_onInput));
|
||||
XEvent e;
|
||||
XNextEvent(d, &e);
|
||||
w = get_focus_window(d);
|
||||
if(strlen(run_onInput) > 0){
|
||||
while(XNextEventTimeout(d, &e, .5, event_ts, last_event, &event_ts, &last_event)){
|
||||
if(check_caret() && ran_onInput == 0){
|
||||
// printf("run_onInput: %s\n",run_onInput);
|
||||
system(run_onInput);
|
||||
ran_onInput = 1;
|
||||
}
|
||||
else if(!check_caret() && ran_onInput == 1){
|
||||
// printf("run_offInput: %s\n",run_offInput);
|
||||
system(run_offInput);
|
||||
ran_onInput = 0;
|
||||
}
|
||||
// e.type = Expose;
|
||||
// e.xexpose.count = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
// XNextEvent(d, &e);
|
||||
while (1) {
|
||||
XNextEvent(d, &e);
|
||||
|
||||
if(!(e.type == 22 && (e.type == last_event) && timeInMilliseconds()-event_ts < 300)){
|
||||
// printf("%d == %d\n",e.type, last_event);
|
||||
// printf("Timestamp: %lld\n",timeInMilliseconds()-event_ts);
|
||||
event_ts = timeInMilliseconds();
|
||||
last_event = e.type;
|
||||
break;
|
||||
}
|
||||
event_ts = timeInMilliseconds();
|
||||
last_event = e.type;
|
||||
}
|
||||
}
|
||||
|
||||
w = get_focus_window(d);
|
||||
w = get_top_window(d, w);
|
||||
w = get_named_window(d, w);
|
||||
}
|
||||
}
|
58
setup.py
58
setup.py
@@ -15,6 +15,32 @@ def cmdline(command):
|
||||
)
|
||||
return process.communicate()[0]
|
||||
|
||||
def requirements():
|
||||
print(bcolors.CYELLOW + "You need to install some packages, " +run_pkg+ ", for Kinto to fully remap browsers during input focus.\n" + bcolors.ENDC)
|
||||
print("sudo apt-get install -y " + run_pkg + "\n")
|
||||
run_install = yn_choice(bcolors.CYELLOW + "Would you like to run it now? (Will require sudo privileges.)\n" + bcolors.ENDC)
|
||||
if(run_install):
|
||||
os.system("sudo apt-get install -y " + run_pkg)
|
||||
print("\n")
|
||||
|
||||
check_xbind = symbols_gui_line = cmdline("which xbindkeys").strip()
|
||||
check_xdotool = symbols_gui_line = cmdline("which xdotool").strip()
|
||||
|
||||
runpkg = 0
|
||||
run_pkg = ""
|
||||
|
||||
if len(check_xbind) > 0 and len(check_xdotool) > 0:
|
||||
print("Xbindkeys, and xdotool requirement is installed.")
|
||||
if len(check_xbind) == 0:
|
||||
run_pkg = "xbindkeys"
|
||||
runpkg = 1
|
||||
if len(check_xdotool) == 0:
|
||||
run_pkg += " xdotool"
|
||||
runpkg = 1
|
||||
|
||||
if runpkg != 0:
|
||||
requirements()
|
||||
|
||||
try:
|
||||
f = open("defaults.json")
|
||||
except IOError:
|
||||
@@ -90,12 +116,14 @@ if 'hack' in keyboardconfigs[defaultkb-1]:
|
||||
os.system(keyboardconfigs[defaultkb-1]['hack'])
|
||||
|
||||
# Setup the selected keyboards config
|
||||
os.system("cp -rf ./.xkb ~/.xkb")
|
||||
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.gui.nw')
|
||||
os.system('setxkbmap -print > ~/.xkb/keymap/kbd.mac.gui.chrome')
|
||||
os.system('setxkbmap -print > ~/.xkb/keymap/kbd.mac.term')
|
||||
time.sleep(0.5)
|
||||
|
||||
@@ -107,6 +135,11 @@ cmdline('sed -i '' -e "' + symbols_gui_line + 's/\\"/' + keyboardconfigs[default
|
||||
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')
|
||||
|
||||
cmdline('sed -i '' -e "' + symbols_gui_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_symbols_gui'].replace("+mac_gui(mac_levelssym)","") + '\\"/2" ~/.xkb/keymap/kbd.mac.gui.nw')
|
||||
cmdline('sed -i '' -e "' + symbols_gui_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_symbols_gui'].replace("+mac_gui(mac_levelssym)","+mac_gui(mac_chrome)") + '\\"/2" ~/.xkb/keymap/kbd.mac.gui.chrome')
|
||||
cmdline('sed -i '' -e "' + types_gui_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_types_gui'] + '\\"/2" ~/.xkb/keymap/kbd.mac.gui.nw')
|
||||
cmdline('sed -i '' -e "' + types_gui_line + 's/\\"/' + keyboardconfigs[defaultkb-1]['xkb_types_gui'] + '\\"/2" ~/.xkb/keymap/kbd.mac.gui.chrome')
|
||||
|
||||
|
||||
user_file = homedir + '/.config/kinto/user_config.json'
|
||||
with open(user_file, 'r') as f:
|
||||
@@ -130,26 +163,37 @@ if(onetime):
|
||||
print("\nDynamic shortcut tweaks\n")
|
||||
|
||||
intents = [obj for obj in user_config['de'] if(obj['intent'] == "gui_term")]
|
||||
tweaks = []
|
||||
tweaks_selected = []
|
||||
|
||||
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')
|
||||
tweaks.append(k['id'])
|
||||
|
||||
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['de'][tweaks[d-1]]['active'] = True
|
||||
tweaks_selected.append(tweaks[d-1])
|
||||
|
||||
if len(defaultde) != 0:
|
||||
# gui
|
||||
user_config['config'][0]['de'] = tweaks_selected
|
||||
# term
|
||||
user_config['config'][1]['de'] = tweaks_selected
|
||||
# firefox
|
||||
user_config['config'][2]['de'] = tweaks_selected
|
||||
# chrome
|
||||
user_config['config'][3]['de'] = tweaks_selected
|
||||
|
||||
user_config['config'][0]['run'] = keyboardconfigs[defaultkb-1]['gui']
|
||||
user_config['config'][1]['run'] = keyboardconfigs[defaultkb-1]['term']
|
||||
user_config['config'][2]['run'] = keyboardconfigs[defaultkb-1]['gui']
|
||||
user_config['config'][3]['run'] = keyboardconfigs[defaultkb-1]['gui'].replace("kbd.mac.gui","kbd.mac.gui.chrome")
|
||||
|
||||
os.remove(user_file)
|
||||
with open(user_file, 'w') as f:
|
||||
|
7
system-config/.chrome-nw
Normal file
7
system-config/.chrome-nw
Normal file
@@ -0,0 +1,7 @@
|
||||
"xdotool key --delay 0 --clearmodifiers Alt+Left"
|
||||
Control + Left + Release
|
||||
#Home + release
|
||||
|
||||
"xdotool key --delay 0 --clearmodifiers Alt+Right"
|
||||
Control + Right + Release
|
||||
#End + release
|
5
system-config/.chrome-ww
Normal file
5
system-config/.chrome-ww
Normal file
@@ -0,0 +1,5 @@
|
||||
"xdotool key --delay 0 --clearmodifiers Home"
|
||||
Control + Left + Release
|
||||
|
||||
"xdotool key --delay 0 --clearmodifiers End"
|
||||
Control + Right + Release
|
7
system-config/.firefox-nw
Normal file
7
system-config/.firefox-nw
Normal file
@@ -0,0 +1,7 @@
|
||||
#"xte 'keydown Control_L' 'key bracketleft' 'keyup Control_L'"
|
||||
"xdotool key --delay 0 --clearmodifiers Control_L+bracketleft"
|
||||
Home + Release
|
||||
|
||||
#"xte 'keydown Control_R' 'key bracketright' 'keyup Control_R'"
|
||||
"xdotool key --delay 0 --clearmodifiers Control_L+bracketright"
|
||||
End + Release
|
10
system-config/caret_status.sh
Executable file
10
system-config/caret_status.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p /tmp/kinto
|
||||
|
||||
IBUSADD=$(cat ~/.config/ibus/bus/`ls ~/.config/ibus/bus -1rt | tail -n1` | awk -F'IBUS_ADDRESS=' '{print $2}' | xargs)
|
||||
dbus-monitor --address $IBUSADD "path='/org/freedesktop/IBus/Panel',interface='org.freedesktop.IBus.Panel',member='FocusOut'" 2> /dev/null | grep --line-buffered -o -P '(?<=object path \"/org/freedesktop/IBus/InputContext_).*(?=[\"])' |
|
||||
while read ln
|
||||
do
|
||||
printf '%s\n' "$ln" > /tmp/kinto/caret
|
||||
done
|
5
system-config/cleanup.sh
Normal file
5
system-config/cleanup.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
setxkbmap -option
|
||||
killall xbindkeys > /dev/null 2>&1
|
||||
rm /tmp/kinto/caret
|
@@ -4,12 +4,11 @@ PartOf=graphical-session.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
#User={username}
|
||||
#Group={username}
|
||||
Environment=DISPLAY=:0
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
WorkingDirectory=/home/{username}/.config/kinto
|
||||
ExecStart=
|
||||
ExecStart=/bin/bash -c "/home/{username}/.config/kinto/xactive.sh carrots"
|
||||
ExecStop=/bin/bash /home/{username}/.config/kinto/cleanup.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
@@ -1,3 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
systemctl --user start keyswap
|
8
system-config/kinto.desktop
Normal file
8
system-config/kinto.desktop
Normal file
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Name=Kinto
|
||||
GenericName=Kinto
|
||||
Comment=Make Linux Type Like it's a Mac
|
||||
Exec=/usr/bin/systemctl --user start keyswap
|
||||
Terminal=false
|
||||
Type=Application
|
||||
X-GNOME-Autostart-enabled=true
|
@@ -1,3 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
./caret_status.sh &
|
||||
./kintox11
|
@@ -2,7 +2,7 @@
|
||||
|
||||
systemctl --user stop keyswap
|
||||
systemctl --user disable keyswap
|
||||
rm -rf ~/.config/autostart/keyswap.sh
|
||||
rm -rf ~/.config/autostart/kinto.desktop
|
||||
rm -rf ~/.config/kinto
|
||||
rm -rf ~/.xkb
|
||||
|
||||
|
@@ -1,15 +1,43 @@
|
||||
{"config":[{
|
||||
"name":"gui",
|
||||
"run":"",
|
||||
"run_onInput":"",
|
||||
"run_offInput": "killall xbindkeys > /dev/null 2>&1",
|
||||
"symbols":"",
|
||||
"types":"",
|
||||
"de":[],
|
||||
"appnames":[ "" ]
|
||||
},
|
||||
{
|
||||
"name":"term",
|
||||
"run":"",
|
||||
"run_onInput":"",
|
||||
"run_offInput": "killall xbindkeys > /dev/null 2>&1",
|
||||
"symbols":"",
|
||||
"types":"",
|
||||
"de":[],
|
||||
"appnames":[ "Gnome-terminal","konsole","io.elementary.terminal","terminator","sakura","guake","tilda","xterm","eterm" ]
|
||||
}],
|
||||
},
|
||||
{
|
||||
"name": "firefox",
|
||||
"run": "",
|
||||
"run_onInput": "killall xbindkeys > /dev/null 2>&1",
|
||||
"run_offInput": "killall xbindkeys > /dev/null 2>&1;xbindkeys -f $HOME/.config/kinto/.firefox-nw",
|
||||
"symbols": "",
|
||||
"types": "",
|
||||
"de": [],
|
||||
"appnames": [ "Firefox" ]
|
||||
},
|
||||
{
|
||||
"name": "chrome",
|
||||
"run": "",
|
||||
"run_onInput": "xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui $DISPLAY",
|
||||
"run_offInput": "xkbcomp -w0 -I$HOME/.xkb ~/.xkb/keymap/kbd.mac.gui.chrome $DISPLAY",
|
||||
"symbols": "",
|
||||
"types": "",
|
||||
"de": [],
|
||||
"appnames": [ "Chromium","Chromium-browser" ]
|
||||
}],
|
||||
"init": [],
|
||||
"detypes":["gnome2","gnome3","kde4","kde5","xfce","i3wm"],
|
||||
"de":[{
|
||||
|
Reference in New Issue
Block a user