Compare commits

..

13 Commits

Author SHA1 Message Date
Ben Reaves
eac62fb605 - Improved Open Display function to timeout after 60 seconds, fixes possible startup failure on boot for some distros. 2020-02-11 17:36:08 -06:00
Ben Reaves
ab679ddf9d - Improved Open Display function in kintox11 to retry for 1 minute, may be helpful in some distro configs. 2020-02-11 17:29:05 -06:00
Ben Reaves
f4cef736be - Updated kintox11 binary to handle errors better in the get top window function 2020-02-11 15:40:16 -06:00
Ben Reaves
2179176881 - The beginnings of a python based xlib implementation of kintox11 2020-02-06 20:05:47 -06:00
Ben Reaves
26f70ccd31 - Updated kintox11 binary to handle errors better in the get top window function 2020-02-06 16:33:23 -06:00
Ben Reaves
0ff7a42f9b - Updated readme with more troubleshooting tips 2020-02-05 16:29:36 -06:00
Ben Reaves
58da4fcd90 Merge branch 'master' into dev 2020-02-05 16:06:41 -06:00
Ben Reaves
20170f0a7d - Removed the explicit reference to bin bash in the service file, also removed the Environment variable to avoid issues for when Display is not 0. 2020-02-05 16:05:41 -06:00
Ben Reaves
d90829928b Merge pull request #27 from rbreaves/dev
Fixes tweak selection during install
2020-02-05 21:35:03 +00:00
Ben Reaves
6f913538e8 - Fixed tweak selection in python installer 2020-02-05 15:33:51 -06:00
Ben Reaves
7dfbe884ff - Added medium article in readme 2020-02-05 14:11:13 -06:00
Ben Reaves
3a115f91ae Merge branch 'dev' 2020-02-05 14:06:57 -06:00
Ben Reaves
4c218b55bd - Updated uninstaller to remove kinto.desktop from startup 2020-02-05 14:06:37 -06:00
8 changed files with 170 additions and 19 deletions

View File

@@ -165,19 +165,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.
@@ -194,6 +216,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

View File

@@ -4,7 +4,7 @@ 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\ \/home\/`whoami`\/.config\/kinto\/xactive.sh"
swapcmd="\/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

115
kintopy/kinto.py Normal file
View 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.

View File

@@ -18,6 +18,7 @@
#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`
@@ -58,9 +59,20 @@ 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;
@@ -100,16 +112,15 @@ Window get_top_window(Display* d, Window start){
unsigned int nchildren;
Status s;
// printf("getting top window ... \n");
while (parent != root) {
while (parent != root && parent != 0) {
w = parent;
s = XQueryTree(d, w, &root, &parent, &children, &nchildren); // see man
if (s)
XFree(children);
if(xerror || w == 0){
printf("fail\n");
if(xerror){
printf("fail to get top window: %ld\n",w);
exit(1);
}

View File

@@ -130,23 +130,28 @@ 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
user_config['config'][0]['run'] = keyboardconfigs[defaultkb-1]['gui']
user_config['config'][1]['run'] = keyboardconfigs[defaultkb-1]['term']

View File

@@ -4,9 +4,6 @@ PartOf=graphical-session.target
[Service]
Type=simple
#User={username}
#Group={username}
Environment=DISPLAY=:0
Restart=always
RestartSec=1
WorkingDirectory=/home/{username}/.config/kinto

View File

@@ -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