- GUI and sys tray added

- merging layouts

- Major progress, unknowns completed

- Added more menu options

- Updated status placement and formatting

- Ported Tweaks from tray to GUI, added more submenus to tray

- GUI App icon improvements, desktop shortcut (linux), sys tray icon status improved

- Added debug switch to gui app, proper child termination for sys tray

- Updates to debug functionality

- Added support and about to sys tray

- Added more commands to sudoers & added version to about

- KB logic can now refresh when needed

- GUI and sys tray feature complete
This commit is contained in:
Ben Reaves
2020-10-13 17:13:20 -05:00
parent d4992fe00a
commit 1c9302cb7a
8 changed files with 1296 additions and 86 deletions

817
xkeysnail-config/gui/kinto-gui.py Executable file
View File

@@ -0,0 +1,817 @@
#!/usr/bin/env python3
import gi,os,time,fcntl,argparse,re
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk,Gdk,GdkPixbuf
from gi.repository import Vte,GLib
from subprocess import Popen,PIPE,CalledProcessError
class MyWindow(Gtk.Window):
label = Gtk.Label()
label.set_alignment(1, 0)
ostype = os.environ.get('XDG_CURRENT_DESKTOP')
kinto_status = Popen("while :; do clear; systemctl is-active xkeysnail; sleep 2; done", stdout=PIPE, shell=True)
winkb = Gtk.RadioMenuItem(label='Windows')
mackb = Gtk.RadioMenuItem(label='Apple',group=winkb)
chromekb = Gtk.RadioMenuItem(label='Chromebook',group=winkb)
ibmkb = Gtk.RadioMenuItem(label='IBM (No Super/Win key)',group=winkb)
winmackb = Gtk.RadioMenuItem(label='Windows & Apple*',group=winkb)
mackb.signal_id = 0
winkb.signal_id = 0
chromekb.signal_id = 0
ibmkb.signal_id = 0
winmackb.signal_id = 0
menuitem_auto = Gtk.CheckMenuItem(label="Autostart")
menuitem_auto.signal_id = 0
menuitem_enable = Gtk.CheckMenuItem(label="Enable")
menuitem_enable.signal_id = 0
def __init__(self):
Gtk.Window.__init__(self, title="Kinto.sh")
# self.set_icon_from_file(os.environ['HOME']+'/.config/kinto/kinto-color.svg')
# self.set_gravity(Gdk.Gravity.NORTH_WEST)
self.set_size_request(600, 360)
global restartsvc
restartsvc = False
homedir = os.path.expanduser("~")
self.kconfig = homedir+"/.config/kinto/kinto.py"
path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = 256
height = 256
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
# image = Gtk.Image()
# image.set_from_pixbuf(pixbuf)
self.set_default_icon_list([pixbuf])
# self.button = Gtk.Button("Do The Command")
# self.button2 = Gtk.Button("End Command")
# self.InputToTerm(self.cmdbytes)
# self.command2 = "send \003; echo 'hello'\n"
# # expect -c "send \003;"
# self.cmdbytes2 = str.encode(self.command2)
# self.button.connect("clicked", self.InputToTerm, self.cmdbytes)
# self.button2.connect("clicked", self.InputToTerm, self.cmdbytes2)
parser = argparse.ArgumentParser()
# parser.add_argument('-b', type=int, required=False, help="")
# parser.add_argument('-e', type=int, default=2, help="")
parser.add_argument('-d', dest='debug', action='store_true', help="runs kinto in debug mode")
parser.add_argument('--debug', dest='debug', action='store_true', help="runs kinto in debug mode")
args = parser.parse_args()
global terminal
terminal = Vte.Terminal()
terminal.spawn_sync(
Vte.PtyFlags.DEFAULT,
os.environ['HOME']+'/.config/kinto',
["/bin/bash"],
[],
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
None,
None,
)
if args.debug:
# print("run debug")
self.command = "sudo systemctl stop xkeysnail && sudo xkeysnail ~/.config/kinto/kinto.py\n"
else:
self.command = "journalctl -f --unit=xkeysnail.service -b\n"
self.cmdbytes = str.encode(self.command)
self.InputToTerm(self.cmdbytes)
grid = Gtk.Grid()
grid.modify_bg(Gtk.StateFlags.NORMAL, Gdk.color_parse("#2d303b"))
self.add(grid)
menubar = Gtk.MenuBar()
# menubar.set_hexpand(True)
grid.attach(menubar, 0, 0, 1, 1)
# grid.add(menubar)
# grid.add(self.button)
# grid.add(self.button2)
# grid.add(self.status)
# grid.attach(self.button, 0, 1, 1, 1)
# grid.attach(self.button2, 1, 1, 1, 1)
scroller = Gtk.ScrolledWindow()
# scroller.set_size_request(200,100)
scroller.set_hexpand(True)
scroller.set_vexpand(True)
scroller.add(terminal)
grid.attach(scroller, 0, 1, 1, 1)
# grid.add(scroller)
# grid.attach(scroller, 0, 0, 2, 2)
grid.attach_next_to(self.label, scroller, Gtk.PositionType.BOTTOM, 2, 1)
# grid.attach_next_to(self.label2, self.label, Gtk.PositionType.RIGHT, 2, 1)
# three labels
label_top_left = Gtk.Label(label="Top left")
another = Gtk.Label(label="another")
# label_top_right = Gtk.Label(label="This is Top Right")
# label_bottom = Gtk.Label(label="This is Bottom")
# some space between the columns of the grid
# grid.set_column_spacing(20)
# in the grid:
# attach the first label in the top left corner
# grid.add(label_top_left)
# grid.attach(label_top_left, 0, 0, 1, 1)
# attach the second label
# grid.attach(label_top_right, 1, 0, 1, 1)
# attach the third label below the first label
# grid.attach_next_to(label_bottom, label_top_left, Gtk.PositionType.BOTTOM, 2, 1)
# grid.attach_next_to(menubar, label_top_left, Gtk.PositionType.BOTTOM, 2, 1)
# sw = Gtk.ScrolledWindow()
# self.label.set_alignment(0, 0)
# self.label.set_selectable(True)
# self.label.set_line_wrap(True)
# self.label.set_max_width_chars(150)
# # sw.set_size_request(400,300)
# sw.set_hexpand(True)
# sw.set_vexpand(True)
# sw.add_with_viewport(self.label)
# # self.add(sw)
# # grid.add(sw)
# # grid.add(self.status)
# grid.attach(sw, 0, 0, 2, 2)
# # sub_proc = Popen("journalctl -f --unit=xkeysnail.service -b", stdout=PIPE, shell=True)
# # sub_outp = ""
with open(self.kconfig) as configfile:
autostart_line = configfile.read().split('\n')[1]
# Autostart
if "autostart = true" in autostart_line.casefold():
autostart_bool = True
if autostart_bool:
# Popen(['sudo', 'systemctl','restart','xkeysnail'])
self.menuitem_auto.set_active(True)
self.menuitem_auto.signal_id = self.menuitem_auto.connect('activate',self.setAutostart,False)
else:
self.menuitem_auto.set_active(False)
self.menuitem_auto.signal_id = self.menuitem_auto.connect('activate',self.setAutostart,True)
menuitem_file = Gtk.MenuItem(label="File")
menubar.append(menuitem_file)
submenu_file = Gtk.Menu()
menuitem_file.set_submenu(submenu_file)
submenu_file.append(self.menuitem_auto)
submenu_file.append(self.menuitem_enable)
# self.menuitem_enable.connect('activate', self.setEnable)
menuitem_restart = Gtk.MenuItem(label="Restart")
menuitem_restart.connect('activate',self.runRestart)
submenu_file.append(menuitem_restart)
menuitem_quit = Gtk.MenuItem(label="Quit")
submenu_file.append(menuitem_quit)
menuitem_quit.connect('activate', self.on_menu_quit)
menuitem_edit = Gtk.MenuItem(label="Edit")
menubar.append(menuitem_edit)
submenu_edit = Gtk.Menu()
menuitem_edit.set_submenu(submenu_edit)
edititem_tweaks = Gtk.MenuItem("Tweaks")
edititem_tweaks.connect('activate',self.setTweaks)
submenu_edit.append(edititem_tweaks)
edititem_config = Gtk.MenuItem("Kinto Config (shortcuts)")
edititem_config.connect('activate',self.setConfig)
submenu_edit.append(edititem_config)
edititem_service = Gtk.MenuItem("Kinto Service")
edititem_service.connect('activate',self.setService)
submenu_edit.append(edititem_service)
edititem_shortcuts = Gtk.MenuItem("System Shortcuts")
edititem_shortcuts.connect('activate',self.setSysKB)
submenu_edit.append(edititem_shortcuts)
edititem_language = Gtk.MenuItem("Change Language")
edititem_language.connect('activate',self.setRegion)
submenu_edit.append(edititem_language)
keyboards = Gtk.MenuItem(label="Keyboard")
keyboards.connect('activate',self.refresh)
menubar.append(keyboards)
# tweaks = Gtk.MenuItem(label="Tweaks")
# menubar.append(tweaks)
# submenu_tweaks = Gtk.Menu()
# tweaks.set_submenu(submenu_tweaks)
# tweakitem_rightmod = Gtk.CheckMenuItem("AltGr on Right Cmd")
# submenu_tweaks.append(tweakitem_rightmod)
# tweakitem_vsc2st3 = Gtk.CheckMenuItem("ST3 hotkeys for VS Code")
# submenu_tweaks.append(tweakitem_vsc2st3)
# tweakitem_caps2esc = Gtk.CheckMenuItem("Capslock is Escape when tapped, Cmd when held")
# submenu_tweaks.append(tweakitem_caps2esc)
# tweakitem_caps2cmd = Gtk.CheckMenuItem("Capslock is Cmd")
# submenu_tweaks.append(tweakitem_caps2cmd)
menuitem_help = Gtk.MenuItem(label="Help")
menubar.append(menuitem_help)
submenu_help = Gtk.Menu()
helpitem_debug = Gtk.MenuItem(label="Debug")
helpitem_debug.connect('activate',self.runDebug)
submenu_help.append(helpitem_debug)
helpitem_support = Gtk.MenuItem("Support")
helpitem_support.connect('activate',self.openSupport)
submenu_help.append(helpitem_support)
menuitem_help.set_submenu(submenu_help)
helpitem_about = Gtk.MenuItem("About")
helpitem_about.connect('activate',self.runAbout)
submenu_help.append(helpitem_about)
menu = Gtk.Menu()
keyboards.set_submenu(menu)
self.refreshKB()
self.mackb.signal_id = self.mackb.connect('activate',self.setKB,"mac")
self.winkb.signal_id = self.winkb.connect('activate',self.setKB,"win")
self.chromekb.signal_id = self.chromekb.connect('activate',self.setKB,"chrome")
self.ibmkb.signal_id = self.ibmkb.connect('activate',self.setKB,"ibm")
self.winmackb.signal_id = self.winmackb.connect('activate',self.setKB,"winmac")
menu.append(self.winkb)
menu.append(self.mackb)
menu.append(self.chromekb)
menu.append(self.ibmkb)
menu.append(self.winmackb)
# grid.add(another)
GLib.timeout_add(2000, self.update_terminal)
# self.show_all()
# radiomenuitem1 = Gtk.RadioMenuItem(label="Windows")
# radiomenuitem1.set_active(True)
# menu.append(radiomenuitem1)
# radiomenuitem2 = Gtk.RadioMenuItem(label="Apple", group=radiomenuitem1)
# menu.append(radiomenuitem2)
def refresh(self,button):
self.refreshKB()
def refreshKB(self):
# Keyboard Types
ismac = "perl -ne 'print if /^(\s{4})((?!#).*)(# Mac\n)/' ~/.config/kinto/kinto.py | wc -l"
iswin = "perl -ne 'print if /^(\s{4})(# -- Default Win)/' ~/.config/kinto/kinto.py | wc -l"
ischrome = "perl -ne 'print if /^(\s{4})((?!#).*)(# Chromebook\n)/' ~/.config/kinto/kinto.py | wc -l"
iswinmac = "perl -ne 'print if /^(\s{4})(# -- Default Mac)/' ~/.config/kinto/kinto.py | wc -l"
isibm = "perl -ne 'print if /^(\s{4})((?!#).*)(# IBM\n)/' ~/.config/kinto/kinto.py | wc -l"
mac_result = int(self.queryConfig(ismac))
win_result = int(self.queryConfig(iswin))
chrome_result = int(self.queryConfig(ischrome))
ibm_result = int(self.queryConfig(isibm))
winmac_result = int(self.queryConfig(iswinmac))
countkb = 0
if mac_result:
self.mackb.set_active(True)
countkb += 1
if win_result:
self.winkb.set_active(True)
countkb += 1
if chrome_result:
self.chromekb.set_active(True)
countkb += 1
if winmac_result:
self.winmackb.set_active(True)
countkb += 1
if ibm_result:
ibmkb.set_active(True)
countkb += 1
if countkb > 1:
Popen(['notify-send','Kinto: Remove ' + str(countkb-1) + ' kb type(s)','-i','budgie-desktop-symbolic'])
return
def runDebug(self,button):
# self.InputToTerm(self.cmdbytes)
# self.command2 = "send \003; echo 'hello'\n"
command = "send \003 sudo systemctl stop xkeysnail && sudo xkeysnail ~/.config/kinto/kinto.py\n"
cmdbytes = str.encode(command)
self.InputToTerm(cmdbytes)
def openSupport(self,button):
Gtk.show_uri_on_window(None, "https://github.com/rbreaves/kinto#table-of-contents", Gtk.get_current_event_time())
return
def runAbout(self,button):
win = Gtk.Window()
path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = -1
height = 128
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
win.set_default_icon_list([pixbuf])
win.set_title("About")
win.set_default_size(350, 200)
win.set_position(Gtk.WindowPosition.CENTER)
context = win.get_style_context()
default_background = str(context.get_background_color(Gtk.StateType.NORMAL))
tokenValue = re.search('red=(\d.\d+), green=(\d.\d+), blue=(\d.\d+), alpha=(\d.\d+)', default_background)
red = float(tokenValue.group(1))
green = float(tokenValue.group(2))
blue = float(tokenValue.group(3))
alpha = float(tokenValue.group(4))
bgAvg = (red + green + blue)/3
if(bgAvg > 0.5):
theme = "light"
else:
theme = "dark"
vbox = Gtk.VBox()
# innervbox = Gtk.VBox()
if theme == "dark":
path = os.environ['HOME']+'/.config/kinto/kinto-invert.svg'
else:
path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = -1
height = 128
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
image = Gtk.Image()
image.set_from_pixbuf(pixbuf)
with open(os.environ['HOME']+'/.config/kinto/version', 'r') as file:
verdata = file.read().replace('\n', '')
version = Gtk.Label('Kinto v' + verdata)
credits = Gtk.Label("Author: Ben Reaves")
spacer = Gtk.Label(" ")
copy = Gtk.Label("Copyrighted 2019, 2020 - GPLv2")
url = Gtk.LinkButton("http://kinto.sh", label="http://kinto.sh")
url2 = Gtk.Label("http://kinto.sh")
vbox.add(image)
vbox.add(version)
vbox.add(spacer)
vbox.add(credits)
vbox.add(copy)
vbox.add(url)
win.add(vbox)
win.show_all()
version.set_selectable(True)
win.connect('delete-event', self.on_delete_event)
return
def setKB(self,button,kbtype):
try:
if kbtype == "win":
setkb = 's/^(\s{3})(\s{1}#)(.*# WinMac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Mac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(IBM.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Chromebook.*)|^(\s{3})(\s{1}# )(-)( Default Win)|^(\s{3})(\s{1}# )(-)(- Default Mac*)/ $3$7$6$7$8$12$11$12$13$17$16$17$18$20$21$21$22$24$26/g'
elif kbtype == "winmac":
setkb = 's/^(\s{3})(\s{1}#)(.*# WinMac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Mac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(IBM.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Chromebook.*)|^(\s{3})(\s{1}# )(-)( Default Mac.*)|^(\s{3})(\s{1}# )(-)(- Default Win)/ $3$7$6$7$8$12$11$12$13$17$16$17$18$20$21$21$22$24$26/g'
if os.path.isfile('/sys/module/hid_apple/parameters/swap_opt_cmd'):
with open('/sys/module/applespi/parameters/swap_opt_cmd', 'r') as ocval:
optcmd = ocval.read().replace('\n', '')
if optcmd == '0':
# print("found hid_apple")
self.queryConfig("echo '1' | sudo tee /sys/module/hid_apple/parameters/swap_opt_cmd;echo 'options hid_apple swap_opt_cmd=1' | sudo tee /etc/modprobe.d/hid_apple.conf;sudo update-initramfs -u -k all")
if os.path.isfile('/sys/module/applespi/parameters/swap_opt_cmd'):
with open('/sys/module/applespi/parameters/swap_opt_cmd', 'r') as ocval:
optcmd = ocval.read().replace('\n', '')
if optcmd == '0':
# print("found applespi")
self.queryConfig("echo '1' | sudo tee /sys/module/applespi/parameters/swap_opt_cmd;echo 'options applespi swap_opt_cmd=1' | sudo tee /etc/modprobe.d/applespi.conf;sudo update-initramfs -u -k all")
elif kbtype == "mac":
if os.path.isfile('/sys/module/hid_apple/parameters/swap_opt_cmd'):
with open('/sys/module/hid_apple/parameters/swap_opt_cmd', 'r') as ocval:
optcmd = ocval.read().replace('\n', '')
if optcmd == '1':
# print("found hid_apple - remove")
self.queryConfig("echo '0' | sudo tee /sys/module/hid_apple/parameters/swap_opt_cmd;echo 'options hid_apple swap_opt_cmd=0' | sudo tee /etc/modprobe.d/hid_apple.conf;sudo update-initramfs -u -k all")
if os.path.isfile('/sys/module/applespi/parameters/swap_opt_cmd'):
with open('/sys/module/applespi/parameters/swap_opt_cmd', 'r') as ocval:
optcmd = ocval.read().replace('\n', '')
if optcmd == '1':
# print("found applespi - remove")
self.queryConfig("echo '0' | sudo tee /sys/module/applespi/parameters/swap_opt_cmd;echo 'options applespi swap_opt_cmd=0' | sudo tee /etc/modprobe.d/applespi.conf;sudo update-initramfs -u -k all")
setkb = 's/^(\s{3})(\s{1}#)(.*# Mac\n|.*# Mac -)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(WinMac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(IBM.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Chromebook.*)|^(\s{3})(\s{1}# )(-)(- Default (Win|Mac.*))/ $3$7$6$7$8$12$11$12$13$17$16$17$18$20$22/g'
elif kbtype == "chrome":
setkb = 's/^(\s{3})(\s{1}#)(.*# Chromebook.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(WinMac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Mac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(IBM.*)|^(\s{3})(\s{1}# )(-)(- Default (Win|Mac.*))/ $3$7$6$7$8$12$11$12$13$17$16$17$18$20$22/g'
elif kbtype == "ibm":
setkb ='s/^(\s{3})(\s{1}#)(.*# IBM.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(WinMac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Mac.*)|^(?!\s{4}#)(\s{3})(\s{1})(.*)( # )(Chromebook.*)|^(\s{3})(\s{1}# )(-)(- Default (Win|Mac.*))/ $3$7$6$7$8$12$11$12$13$17$16$17$18$20$22/g'
restart = ['sudo', 'systemctl','restart','xkeysnail']
cmds = ['perl','-pi','-e',setkb,self.kconfig]
cmdsTerm = Popen(cmds)
cmdsTerm.wait()
Popen(restart)
except CalledProcessError:
Popen(['notify-send','Kinto: Error Resetting KB Type!','-i','budgie-desktop-symbolic'])
def setTweaks(self,button):
win = Gtk.Window()
path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = -1
height = 128
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
win.set_default_icon_list([pixbuf])
win.set_title("Kinto Tweaks")
win.set_default_size(350, 200)
win.set_position(Gtk.WindowPosition.CENTER)
# Check AltGr - commented out is enabled
is_rightmod = "perl -ne 'print if /^(\s{4})(Key.*)(Multi-language)/' ~/.config/kinto/kinto.py | wc -l"
rightmod_result = int(self.queryConfig(is_rightmod))
# Sublime enabled for vscode
is_vsc2st3 = "perl -ne 'print if /^(\s{4}\w.*)(- Sublime)/' ~/.config/kinto/kinto.py | wc -l"
vsc2st3_result = int(self.queryConfig(is_vsc2st3))
# Caps2Esc enabled
is_caps2esc = "perl -ne 'print if /^(\s{4}{\w.*)(# Caps2Esc)/' ~/.config/kinto/kinto.py | wc -l"
caps2esc_result = int(self.queryConfig(is_caps2esc))
# Caps2Cmd enabled
is_caps2cmd = "perl -ne 'print if /^(\s{4}\w.*)(# Caps2Cmd)/' ~/.config/kinto/kinto.py | wc -l"
caps2cmd_result = int(self.queryConfig(is_caps2cmd))
# Enter2Cmd enabled
# (\s{4}{\w.*)(# Enter2Cmd)
vbox = Gtk.VBox()
self.lbl = Gtk.Label()
global restartsvc
restartsvc = False
self.rightmod = Gtk.CheckButton('AltGr on Right Cmd')
self.vsc2st3 = Gtk.CheckButton('ST3 hotkeys for VS Code')
self.caps2esc = Gtk.CheckButton('Capslock is Escape when tapped, Cmd when held')
self.caps2cmd = Gtk.CheckButton('Capslock is Cmd')
if rightmod_result == 0:
self.rightmod.set_active(True)
if vsc2st3_result > 0:
self.vsc2st3.set_active(True)
if caps2esc_result > 0:
self.caps2esc.set_active(True)
self.caps2cmd.set_sensitive(False)
if caps2cmd_result > 0:
self.caps2cmd.set_active(True)
self.caps2esc.set_sensitive(False)
self.rightmod.signal_id = self.rightmod.connect('toggled',self.setRightMod)
self.vsc2st3.signal_id = self.vsc2st3.connect('toggled',self.setVSC2ST3)
self.caps2esc.signal_id = self.caps2esc.connect('toggled',self.setCaps2Esc)
self.caps2cmd.signal_id = self.caps2cmd.connect('toggled',self.setCaps2Cmd)
vbox.add(self.rightmod)
vbox.add(self.vsc2st3)
vbox.add(self.caps2esc)
vbox.add(self.caps2cmd)
vbox.add(self.lbl)
win.add(vbox)
win.show_all()
win.connect('delete-event', self.on_delete_event)
return
__gsignals__ = {
"delete-event" : "override"
}
def on_delete_event(event, self, widget):
global restartsvc
if restartsvc == True:
try:
restartcmd = ['sudo', 'systemctl','restart','xkeysnail']
Popen(restartcmd)
restartsvc = False
except CalledProcessError:
Popen(['notify-send','Kinto: Error restarting Kinto after setting tweaks!','-i','budgie-desktop-symbolic'])
self.hide()
self.destroy()
return True
def queryConfig(self,query):
res = Popen(query, stdout=PIPE, stderr=None, shell=True)
res.wait()
return res.communicate()[0].strip().decode('UTF-8')
def setRightMod(self,button):
global restartsvc
try:
if self.winkb.get_active() or self.winmackb.get_active():
# print('winkb true')
setkb = 's/^(\s{4})((# )(.*)(# )(WinMac - Multi-language.*)|(K)(.*)(# )(WinMac - Multi-language.*))/ $4$5$6$9$7$8$9$10/g'
if self.mackb.get_active():
# print('mackb true')
setkb = 's/^(\s{4})((# )(.*)(# )(Mac - Multi-language.*)|(K)(.*)(# )(Mac - Multi-language.*))/ $4$5$6$9$7$8$9$10/g'
if self.chromekb.get_active():
# print('chromekb true')
setkb = 's/^(\s{4})((# )(.*)(# )(Chromebook - Multi-language.*)|(K)(.*)(# )(Chromebook - Multi-language.*))/ $4$5$6$9$7$8$9$10/g'
if self.ibmkb.get_active():
# print('ibmkb true')
setkb = 's/^(\s{4})((# )(.*)(# )(IBM - Multi-language.*)|(K)(.*)(# )(IBM - Multi-language.*))/ $4$5$6$9$7$8$9$10/g'
cmds = ['perl','-pi','-e',setkb,self.kconfig]
cmdsTerm = Popen(cmds)
restartsvc = True
except CalledProcessError:
Popen(['notify-send','Kinto: Error Resetting AltGr!','-i','budgie-desktop-symbolic'])
return
def setVSC2ST3(self,button):
global restartsvc
try:
if self.chromekb.get_active() or self.ibmkb.get_active():
setkb = 's/^(\s{4})(\w.*)(# )(Chromebook/IBM - Sublime)|^(\s{4})(# )(\w.*)(# Chromebook/IBM - Sublime)/$5$7$8$1$3$2$3$4/g'
else:
setkb = 's/^(\s{4})(\w.*)(# )(Default - Sublime)|^(\s{4})(# )(\w.*)(# Default - Sublime)/$5$7$8$1$3$2$3$4/g'
cmds = ['perl','-pi','-e',setkb,self.kconfig]
cmdsTerm = Popen(cmds)
restartsvc = True
except CalledProcessError:
Popen(['notify-send','Kinto: Error Resetting SublimeText remaps for VSCode!','-i','budgie-desktop-symbolic'])
return
def setCaps2Esc(self,button):
global restartsvc
try:
if self.winkb.get_active() or self.winmackb.get_active() or self.ibmkb.get_active() or self.mackb.get_active():
setkb = 's/^(\s{4})((# )(\{\w.*)(# Caps2Esc\n)|(\{\w.*)(# )(Caps2Esc - Chrome.*)|(\{.*)(# )(Caps2Esc\n|Placeholder)|(\w.*)(# )(Caps2Cmd.*)|(# )(\{.*)(# )(Placeholder))/ $4$5$7$6$7$8$10$9$10$11$13$12$13$14$16$17$18/g'
if self.chromekb.get_active():
setkb = 's/^(\s{4})((# )(\{\w.*)(# Caps2Esc - Chrome.*)|(\{\w.*)(# )(Caps2Esc\n)|(\{.*)(# )(Caps2Esc - Chrome.*|Placeholder)|(\w.*)(# )(Caps2Cmd.*)|(# )(\{.*)(# )(Placeholder))/ $4$5$7$6$7$8$10$9$10$11$13$12$13$14$16$17$18/g'
cmds = ['perl','-pi','-e',setkb,self.kconfig]
if self.caps2esc.get_active():
self.caps2cmd.set_sensitive(False)
else:
self.caps2cmd.set_sensitive(True)
cmdsTerm = Popen(cmds)
restartsvc = True
except CalledProcessError:
Popen(['notify-send','Kinto: Error resetting caps2esc!','-i','budgie-desktop-symbolic'])
return
def setCaps2Cmd(self,button):
global restartsvc
try:
if self.winkb.get_active() or self.winmackb.get_active() or self.ibmkb.get_active() or self.mackb.get_active():
setkb = 's/^(\s{4})((\w.*)(# )(Caps2Cmd\n)|(\w.*)(# )(Caps2Cmd - Chrome.*)|(# )(\w.*)(# )(Caps2Cmd\n)|(\{\w.*)(# )(Caps2Esc.*)|(# )(\{.*)(# )(Placeholder))/ $4$3$4$5$7$6$7$8$10$11$12$14$13$14$15$17$18$19/g'
if self.chromekb.get_active():
setkb = 's/^(\s{4})((\w.*)(# )(Caps2Cmd - Chrome.*)|(\w.*)(# )(Caps2Cmd\n)|(# )(\w.*)(# )(Caps2Cmd - Chrome.*)|(\{\w.*)(# )(Caps2Esc.*)|(# )(\{.*)(# )(Placeholder))/ $4$3$4$5$7$6$7$8$10$11$12$14$13$14$15$17$18$19/g'
cmds = ['perl','-pi','-e',setkb,self.kconfig]
if self.caps2cmd.get_active():
self.caps2esc.set_sensitive(False)
else:
self.caps2esc.set_sensitive(True)
cmdsTerm = Popen(cmds)
restartsvc = True
except CalledProcessError:
Popen(['notify-send','Kinto: Error resetting caps2cmd!','-i','budgie-desktop-symbolic'])
return
def runRestart(self,button):
try:
stop = Popen(['sudo', 'systemctl','stop','xkeysnail'])
stop.wait()
time.sleep(1)
res = Popen(['pgrep','xkeysnail'])
res.wait()
if res.returncode == 0:
pkillxkey = Popen(['sudo', 'pkill','-f','bin/xkeysnail'])
pkillxkey.wait()
Popen(['sudo', 'systemctl','start','xkeysnail'])
command = "send \003 journalctl -f --unit=xkeysnail.service -b\n"
cmdbytes = str.encode(command)
self.InputToTerm(cmdbytes)
except:
Popen(['notify-send','Kinto: Error restarting Kinto!','-i','budgie-desktop-symbolic'])
def setEnable(self,button,enableKinto):
try:
if enableKinto:
res = Popen(['pgrep','xkeysnail'])
res.wait()
print(res.returncode)
if res.returncode == 0:
# Popen(['notify-send','Kinto: Err in debug mode?','-i','budgie-desktop-symbolic'])
pkillxkey = Popen(['sudo', 'pkill','-f','bin/xkeysnail'])
pkillxkey.wait()
Popen(['sudo', 'systemctl','restart','xkeysnail'])
self.menuitem_enable.disconnect(self.menuitem_enable.signal_id)
self.menuitem_enable.set_active(True)
self.menuitem_enable.signal_id = self.menuitem_enable.connect('activate',self.setEnable,False)
command = "send \003 journalctl -f --unit=xkeysnail.service -b\n"
cmdbytes = str.encode(command)
self.InputToTerm(cmdbytes)
else:
Popen(['sudo', 'systemctl','stop','xkeysnail'])
self.menuitem_enable.disconnect(self.menuitem_enable.signal_id)
self.menuitem_enable.set_active(False)
self.menuitem_enable.signal_id = self.menuitem_enable.connect('activate',self.setEnable,True)
except CalledProcessError:
Popen(['notify-send','Kinto: Error enabling!','-i','budgie-desktop-symbolic'])
def setAutostart(self,button,autostart):
try:
if autostart == False:
Popen(['perl','-pi','-e','s/autostart = true/autostart = false/g',os.environ['HOME']+'/.config/kinto/kinto.py'])
self.menuitem_auto.set_active(False)
self.menuitem_auto.disconnect(self.menuitem_auto.signal_id)
self.menuitem_auto.signal_id = self.menuitem_auto.connect('activate',self.setAutostart,True)
else:
Popen(['perl','-pi','-e','s/autostart = false/autostart = true/g',os.environ['HOME']+'/.config/kinto/kinto.py'])
self.menuitem_auto.set_active(True)
self.menuitem_auto.disconnect(self.menuitem_auto.signal_id)
self.menuitem_auto.signal_id = self.menuitem_auto.connect('activate',self.setAutostart,False)
except CalledProcessError:
Popen(['notify-send','Kinto: Error setting autostart!','-i','budgie-desktop-symbolic'])
def setConfig(self,button):
try:
if os.path.exists('/opt/sublime_text/sublime_text'):
Popen(['/opt/sublime_text/sublime_text',os.environ['HOME']+'/.config/kinto/kinto.py'])
elif which(gedit) is not None:
Popen(['gedit',os.environ['HOME']+'/.config/kinto/kinto.py'])
elif which(mousepad) is not None:
Popen(['mousepad',os.environ['HOME']+'/.config/kinto/kinto.py'])
except CalledProcessError: # Notify user about error on running restart commands.
Popen(['notify-send','Kinto: Error could not open config file!','-i','budgie-desktop-symbolic'])
def setService(self,button):
try:
if os.path.exists('/opt/sublime_text/sublime_text'):
Popen(['/opt/sublime_text/sublime_text','/lib/systemd/system/xkeysnail.service'])
elif which(gedit) is not None:
Popen(['gedit','/lib/systemd/system/xkeysnail.service'])
elif which(mousepad) is not None:
Popen(['mousepad','/lib/systemd/system/xkeysnail.service'])
except CalledProcessError: # Notify user about error on running restart commands.
Popen(['notify-send','Kinto: Error could not open config file!','-i','budgie-desktop-symbolic'])
def setSysKB(self,button):
if self.ostype == "XFCE":
Popen(['xfce4-keyboard-settings'])
else:
Popen(['gnome-control-center','keyboard'])
def setRegion(self,button):
if self.ostype == "XFCE":
Popen(['gnome-language-selector'])
else:
Popen(['gnome-control-center','region'])
def remove_control_characters(self,s):
return "".join(ch for ch in s if unicodedata.category(ch)[0]!="C")
def non_block_read(self):
''' even in a thread, a normal read with block until the buffer is full '''
output = self.kinto_status.stdout
# with open('goodlines.txt') as f:
# mylist = list(f)
# output = '\n'.join(self.kinto_status.stdout.splitlines()[-1:])
# '\n'.join(stderr.splitlines()[-N:])
# .splitlines()[-1:]
fd = output.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
op = output.read()
if op == None:
return ''
# print(output.read())
# the_encoding = chardet.detect(output)['encoding']
# print(str(the_encoding) + " hello")
# full = self.status.get_text() + op.decode('utf-8')
# newstr = re.sub('[^A-Za-z0-9]+', '', op.decode('utf-8'))
# print(newstr)
status = op.decode('utf-8').rstrip()
if "inactive" in status or "failed" in status or "deactivating" in status:
if "journalctl" in self.command:
stats = "<span color='red'><b>inactive</b></span>"
else:
stats = "<span color='yellow'><b>Debug Mode</b></span>"
# elif "failed" in op.decode('utf-8').rstrip():
# stats = "<span color='red'><b>failed</b></span>"
else:
stats = "<span color='#66ff00'><b>active</b></span>"
# op.decode('utf-8').rstrip()
return stats
def remove_tags(self,raw_html):
cleanr = re.compile('<.*?>')
cleantext = re.sub(cleanr, '', raw_html).strip()
return cleantext
def update_terminal(self):
# subproc = self.sub_proc
# print(self.another.get_text())
# self.label.set_text(self.non_block_read())
status = self.non_block_read()
# print (self.label.get_text().strip() + ' ' + self.remove_tags(status))
if self.label.get_text().strip() != self.remove_tags(status):
self.label.set_markup(" " + status + " ")
if self.remove_tags(status) == 'active':
self.menuitem_enable.disconnect(self.menuitem_enable.signal_id)
self.menuitem_enable.set_active(True)
self.menuitem_enable.signal_id = self.menuitem_enable.connect('activate',self.setEnable,False)
else:
self.menuitem_enable.disconnect(self.menuitem_enable.signal_id)
self.menuitem_enable.set_active(False)
self.menuitem_enable.signal_id = self.menuitem_enable.connect('activate',self.setEnable,True)
return self.kinto_status.poll() is None
# def update_terminal(self):
# # subproc = self.sub_proc
# # print(self.another.get_text())
# self.label.set_text(self.label.get_text() + self.non_block_read())
# return self.sub_proc.poll() is None
def InputToTerm(self,cmd):
terminal.feed_child_binary(cmd)
print(Vte.get_minor_version())
# def on_menu_auto(self, widget):
# print("add file open dialog")
# def on_menu_enable(self, widget):
# print("add file open dialog")
def on_menu_quit(self, widget):
Gtk.main_quit()
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

View File

@@ -0,0 +1,11 @@
[Desktop Entry]
# /.local/share/applications
Name=Kinto.sh
GenericName=Kinto.sh
Categories=Utility;
Type=Application
Exec={path}/kinto-gui.py
Icon={home}/.config/kinto/kinto-color-48.svg
# Icon=/usr/share/icons/Pocillo/kinto-color.svg
Terminal=false
NoDisplay=false

53
xkeysnail-config/gui/term.py Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import gi
# import textwrap
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject
import os
from subprocess import Popen, PIPE
import fcntl
wnd = Gtk.Window()
wnd.set_default_size(400, 400)
wnd.connect("destroy", Gtk.main_quit)
sw = Gtk.ScrolledWindow()
label = Gtk.Label()
label.set_alignment(0, 0)
label.set_selectable(True)
label.set_line_wrap(True)
label.set_max_width_chars(150)
sw.add_with_viewport(label)
wnd.add(sw)
wnd.show_all()
sub_proc = Popen("journalctl -f --unit=xkeysnail.service -b", stdout=PIPE, shell=True)
# sub_proc2 = Popen('fold', stdin=sub_proc.stdout, stdout=PIPE)
# sub_proc2.communicate()
sub_outp = ""
def non_block_read(output):
''' even in a thread, a normal read with block until the buffer is full '''
fd = output.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
op = output.read()
if op == None:
return ''
return op.decode('utf-8')
# def wrap(s, w):
# return textwrap.fill(s, w)
# def wrap(s, w):
# return [s[i:i + w] for i in range(0, len(s), w)]
def update_terminal():
# wrapper = textwrap.TextWrapper(width=50)
# word_list = wrapper.wrap(text=sub_proc.stdout)
label.set_text(label.get_text() + non_block_read(sub_proc.stdout))
return sub_proc.poll() is None
GObject.timeout_add(100, update_terminal)
Gtk.main()

54
xkeysnail-config/gui/vte.py Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
from gi.repository import Gtk,GObject, Vte
from gi.repository import GLib
import os
class TheWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="inherited cell renderer")
self.set_default_size(600, 300)
global terminal
terminal = Vte.Terminal()
terminal.spawn_sync(
Vte.PtyFlags.DEFAULT,
os.environ['HOME'],
["/bin/bash"],
[],
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
None,
None,
)
self.button = Gtk.Button("Do The Command")
self.button2 = Gtk.Button("End Command")
self.command = "journalctl -f --unit=xkeysnail.service -b\n"
self.command2 = "send \003; echo 'hello'\n"
# expect -c "send \003;"
self.cmdbytes = str.encode(self.command)
self.cmdbytes2 = str.encode(self.command2)
command = Gtk.Label("The command: "+self.command)
self.button.connect("clicked", self.InputToTerm, self.cmdbytes)
self.button2.connect("clicked", self.InputToTerm, self.cmdbytes2)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.pack_start(self.button, False, True, 0)
box.pack_start(self.button2, False, True, 0)
box.pack_start(command, False, True, 1)
scroller = Gtk.ScrolledWindow()
scroller.set_hexpand(True)
scroller.set_vexpand(True)
scroller.add(terminal)
box.pack_start(scroller, False, True, 2)
self.add(box)
def InputToTerm(self, clicker, cmd):
terminal.feed_child_binary(cmd)
print(Vte.get_minor_version())
win = TheWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

View File

@@ -7,7 +7,7 @@ from xkeysnail.transform import *
# Use the following for testing terminal keymaps # Use the following for testing terminal keymaps
# terminals = [ "", ... ] # terminals = [ "", ... ]
# xbindkeys -mk # xbindkeys -mk
terminals = ["gnome-terminal","konsole","io.elementary.terminal","terminator","sakura","guake","tilda","xterm","eterm","kitty","alacritty","mate-terminal","tilix","xfce4-terminal"] terminals = ["kinto-gui.py","gnome-terminal","konsole","io.elementary.terminal","terminator","sakura","guake","tilda","xterm","eterm","kitty","alacritty","mate-terminal","tilix","xfce4-terminal"]
terminals = [term.casefold() for term in terminals] terminals = [term.casefold() for term in terminals]
termStr = "|".join(str(x) for x in terminals) termStr = "|".join(str(x) for x in terminals)

View File

@@ -5,4 +5,6 @@
%{username} ALL=NOPASSWD: {systemctl} status xkeysnail %{username} ALL=NOPASSWD: {systemctl} status xkeysnail
%{username} ALL=(root) NOPASSWD: /usr/local/bin/logoff.sh %{username} ALL=(root) NOPASSWD: /usr/local/bin/logoff.sh
%{username} ALL=NOPASSWD: {pkill} -f logoff %{username} ALL=NOPASSWD: {pkill} -f logoff
%{username} ALL=NOPASSWD: {pkill} -f bin/xkeysnail
%{username} ALL=NOPASSWD: {xkeysnail} /home/{username}/.config/kinto/kinto.py
%{username} ALL=NOPASSWD: {systemctl} is-active --quiet xkeysnail %{username} ALL=NOPASSWD: {systemctl} is-active --quiet xkeysnail

View File

@@ -6,16 +6,32 @@ gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1') gi.require_version('AppIndicator3', '0.1')
gi.require_version('Notify', '0.7') gi.require_version('Notify', '0.7')
import signal,subprocess,time,os import signal,time,os,fcntl,datetime,re
from subprocess import Popen, PIPE, CalledProcessError
from shutil import which from shutil import which
from gi.repository import Gtk from gi.repository import Gtk,GLib,GdkPixbuf
from gi.repository import AppIndicator3 as appindicator from gi.repository import AppIndicator3 as appindicator
from gi.repository import Notify as notify from gi.repository import Notify as notify
import signal
def kill_child():
if child_pid is None:
pass
else:
os.kill(child_pid, signal.SIGTERM)
import atexit
atexit.register(kill_child)
APPINDICATOR_ID = 'Kinto' APPINDICATOR_ID = 'Kinto'
class Indicator(): class Indicator():
global child_pid
kinto_status = Popen("while :; do clear; systemctl is-active xkeysnail; sleep 2s; done", stdout=PIPE, shell=True)
child_pid = kinto_status.pid
homedir = os.path.expanduser("~") homedir = os.path.expanduser("~")
kconfig = homedir+"/.config/kinto/kinto.py" kconfig = homedir+"/.config/kinto/kinto.py"
ostype = os.environ.get('XDG_CURRENT_DESKTOP') ostype = os.environ.get('XDG_CURRENT_DESKTOP')
@@ -26,9 +42,9 @@ class Indicator():
autostart_bool = False autostart_bool = False
menu = Gtk.Menu() menu = Gtk.Menu()
menukb = Gtk.Menu() menukb = Gtk.Menu()
tweaks = Gtk.MenuItem('Tweaks')
checkbox_autostart = Gtk.CheckMenuItem('Autostart') checkbox_autostart = Gtk.CheckMenuItem('Autostart')
checkbox_enable = Gtk.CheckMenuItem('Kinto Enabled') checkbox_enable = Gtk.CheckMenuItem('Kinto Enabled')
restart = Gtk.MenuItem('Restart')
keyboards = Gtk.MenuItem('Keyboard Types') keyboards = Gtk.MenuItem('Keyboard Types')
keyboards.set_submenu(menukb) keyboards.set_submenu(menukb)
winkb = Gtk.RadioMenuItem(label='Windows') winkb = Gtk.RadioMenuItem(label='Windows')
@@ -36,24 +52,48 @@ class Indicator():
chromekb = Gtk.RadioMenuItem(label='Chromebook',group=winkb) chromekb = Gtk.RadioMenuItem(label='Chromebook',group=winkb)
ibmkb = Gtk.RadioMenuItem(label='IBM (No Super/Win key)',group=winkb) ibmkb = Gtk.RadioMenuItem(label='IBM (No Super/Win key)',group=winkb)
winmackb = Gtk.RadioMenuItem(label='Windows & Apple*',group=winkb) winmackb = Gtk.RadioMenuItem(label='Windows & Apple*',group=winkb)
edit = Gtk.MenuItem('Customize')
edit_submenu = Gtk.Menu()
edit.set_submenu(edit_submenu)
tweaks = Gtk.MenuItem('Tweaks')
rightmod = Gtk.CheckButton('AltGr on Right Cmd') rightmod = Gtk.CheckButton('AltGr on Right Cmd')
vsc2st3 = Gtk.CheckButton('ST3 hotkeys for VS Code') vsc2st3 = Gtk.CheckButton('ST3 hotkeys for VS Code')
caps2esc = Gtk.CheckButton('Capslock is Escape when tapped, Cmd when held') caps2esc = Gtk.CheckButton('Capslock is Escape when tapped, Cmd when held')
caps2cmd = Gtk.CheckButton('Capslock is Cmd') caps2cmd = Gtk.CheckButton('Capslock is Cmd')
button_config = Gtk.MenuItem('Edit Config') button_config = Gtk.MenuItem('Kinto Config (shortcuts)')
service = Gtk.MenuItem('Kinto Service')
# Keyboard type set below # Keyboard type set below
button_syskb = Gtk.MenuItem('System Shortcuts') button_syskb = Gtk.MenuItem('System Shortcuts')
button_region = Gtk.MenuItem('Change Language') button_region = Gtk.MenuItem('Change Language')
button_support = Gtk.MenuItem('Support') helpm = Gtk.MenuItem('Help')
help_submenu = Gtk.Menu()
helpm.set_submenu(help_submenu)
debug = Gtk.MenuItem('Debug')
support = Gtk.MenuItem("Support")
about = Gtk.MenuItem('About')
global restartsvc global restartsvc
restartsvc = False
unixts = int(time.time())
last_status = ""
def __init__(self): def __init__(self):
self.indicator = appindicator.Indicator.new(APPINDICATOR_ID, self.homedir+'/.config/kinto/kinto-invert.svg', appindicator.IndicatorCategory.SYSTEM_SERVICES) res = Popen(['sudo', 'systemctl','is-active','--quiet','xkeysnail'])
res.wait()
if res.returncode == 0:
self.last_status = 'active'
self.indicator = appindicator.Indicator.new(APPINDICATOR_ID, os.environ['HOME']+'/.config/kinto/kinto-invert.svg', appindicator.IndicatorCategory.SYSTEM_SERVICES)
else:
self.last_status = 'inactive'
self.indicator = appindicator.Indicator.new(APPINDICATOR_ID, os.environ['HOME']+'/.config/kinto/kinto.svg', appindicator.IndicatorCategory.SYSTEM_SERVICES)
self.indicator.set_status(appindicator.IndicatorStatus.ACTIVE) self.indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.build_menu()) self.indicator.set_menu(self.build_menu(res))
notify.init(APPINDICATOR_ID) notify.init(APPINDICATOR_ID)
def build_menu(self): GLib.timeout_add(2000, self.update_terminal)
def build_menu(self,res):
with open(self.kconfig) as configfile: with open(self.kconfig) as configfile:
autostart_line = configfile.read().split('\n')[1] autostart_line = configfile.read().split('\n')[1]
@@ -63,7 +103,7 @@ class Indicator():
autostart_bool = True autostart_bool = True
if autostart_bool: if autostart_bool:
subprocess.Popen(['sudo', 'systemctl','restart','xkeysnail']) # Popen(['sudo', 'systemctl','restart','xkeysnail'])
self.checkbox_autostart.set_active(True) self.checkbox_autostart.set_active(True)
self.chkautostart_id = self.checkbox_autostart.connect('activate',self.setAutostart,False) self.chkautostart_id = self.checkbox_autostart.connect('activate',self.setAutostart,False)
else: else:
@@ -73,22 +113,104 @@ class Indicator():
# Kinto Enable # Kinto Enable
res = subprocess.Popen(['sudo', 'systemctl','is-active','--quiet','xkeysnail']) # res = Popen(['sudo', 'systemctl','is-active','--quiet','xkeysnail'])
res.wait() # res.wait()
time.sleep(5) # time.sleep(5)
self.checkbox_enable.set_label("Kinto Enabled") # self.checkbox_enable.set_label("Kinto Enabled")
# self.checkbox_enable.set_active(True)
# self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,False)
if res.returncode == 0: if res.returncode == 0:
self.checkbox_enable.set_active(True) self.checkbox_enable.set_active(True)
self.indicator.set_icon(self.homedir+'/.config/kinto/kinto-invert.svg') # self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto-invert.svg')
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,False) self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,False)
else: else:
self.checkbox_enable.set_active(False) self.checkbox_enable.set_active(False)
self.indicator.set_icon(self.homedir+'/.config/kinto/kinto-color.svg') # self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto-color.svg')
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True) self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True)
self.menu.append(self.checkbox_enable) self.menu.append(self.checkbox_enable)
self.restart.connect('activate',self.runRestart)
self.menu.append(self.restart)
self.refreshKB()
self.mackb.signal_id = self.mackb.connect('activate',self.setKB,"mac")
self.winkb.signal_id = self.winkb.connect('activate',self.setKB,"win")
self.chromekb.signal_id = self.chromekb.connect('activate',self.setKB,"chrome")
self.ibmkb.signal_id = self.ibmkb.connect('activate',self.setKB,"ibm")
self.winmackb.signal_id = self.winmackb.connect('activate',self.setKB,"winmac")
self.menukb.append(self.winkb)
self.menukb.append(self.mackb)
self.menukb.append(self.chromekb)
self.menukb.append(self.ibmkb)
self.menukb.append(self.winmackb)
self.menu.append(self.keyboards)
self.tweaks.connect('activate',self.setTweaks)
self.edit_submenu.append(self.tweaks)
self.button_config.connect('activate',self.setConfig)
self.edit_submenu.append(self.button_config)
self.service.connect('activate',self.setService)
self.edit_submenu.append(self.service)
# Set System Keyboard Shortcuts
self.button_syskb.connect('activate',self.setSysKB)
self.edit_submenu.append(self.button_syskb)
# Set Language
self.button_region.connect('activate',self.setRegion)
self.edit_submenu.append(self.button_region)
self.menu.append(self.edit)
self.debug.connect('activate',self.runDebug)
self.help_submenu.append(self.debug)
self.support.connect('activate',self.openSupport)
self.help_submenu.append(self.support)
self.about.connect('activate',self.runAbout)
self.help_submenu.append(self.about)
self.menu.append(self.helpm)
self.keyboards.connect('activate',self.refresh)
# self.debug.connect('activate',self.runDebug)
# self.menu.append(self.debug)
# self.tweaks.connect('activate',self.setTweaks)
# self.menu.append(self.tweaks)
# Edit Config
# self.button_config.connect('activate',self.setConfig)
# self.menu.append(self.button_config)
# # Set System Keyboard Shortcuts
# self.button_syskb.connect('activate',self.setSysKB)
# self.menu.append(self.button_syskb)
# # Set Language
# self.button_region.connect('activate',self.setRegion)
# self.menu.append(self.button_region)
item_quit = Gtk.MenuItem('Close')
item_quit.connect('activate', quit)
self.menu.append(item_quit)
self.menu.show_all()
return self.menu
# def refresh(self, widget, event):
# print('refresh!!!')
# if event.button != 1:
# return False #only intercept left mouse button
# md = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "herp derp, I only needed one click")
# md.run()
# md.destroy()
# return True
def refresh(self,button):
self.refreshKB()
def refreshKB(self):
# Keyboard Types # Keyboard Types
ismac = "perl -ne 'print if /^(\s{4})((?!#).*)(# Mac\n)/' ~/.config/kinto/kinto.py | wc -l" ismac = "perl -ne 'print if /^(\s{4})((?!#).*)(# Mac\n)/' ~/.config/kinto/kinto.py | wc -l"
iswin = "perl -ne 'print if /^(\s{4})(# -- Default Win)/' ~/.config/kinto/kinto.py | wc -l" iswin = "perl -ne 'print if /^(\s{4})(# -- Default Win)/' ~/.config/kinto/kinto.py | wc -l"
@@ -116,50 +238,145 @@ class Indicator():
self.winmackb.set_active(True) self.winmackb.set_active(True)
countkb += 1 countkb += 1
if ibm_result: if ibm_result:
self.ibmkb.set_active(True) ibmkb.set_active(True)
countkb += 1 countkb += 1
if countkb > 1: if countkb > 1:
subprocess.Popen(['notify-send','Kinto: Remove ' + str(countkb-1) + ' kb type(s)','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Remove ' + str(countkb-1) + ' kb type(s)','-i','budgie-desktop-symbolic'])
self.mackb.signal_id = self.mackb.connect('activate',self.setKB,"mac") return
self.winkb.signal_id = self.winkb.connect('activate',self.setKB,"win")
self.chromekb.signal_id = self.chromekb.connect('activate',self.setKB,"chrome")
self.ibmkb.signal_id = self.ibmkb.connect('activate',self.setKB,"ibm")
self.winmackb.signal_id = self.winmackb.connect('activate',self.setKB,"winmac")
self.menukb.append(self.winkb) def non_block_read(self):
self.menukb.append(self.mackb) ''' even in a thread, a normal read with block until the buffer is full '''
self.menukb.append(self.chromekb) output = self.kinto_status.stdout
self.menukb.append(self.ibmkb) # with open('goodlines.txt') as f:
self.menukb.append(self.winmackb) # mylist = list(f)
self.menu.append(self.keyboards) # output = '\n'.join(self.kinto_status.stdout.splitlines()[-1:])
# '\n'.join(stderr.splitlines()[-N:])
# .splitlines()[-1:]
fd = output.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
op = output.read()
if op == None:
return ''
status = op.decode('utf-8').rstrip()
if "inactive" in status or "failed" in status or "deactivating" in status or "activating" in status:
stats = "inactive"
else:
stats = "active"
return stats
self.tweaks.connect('activate',self.setTweaks) def update_terminal(self):
status = self.non_block_read().strip()
nowts = int(time.time())
if (nowts - self.unixts) > 5 and (status=='active' and self.indicator.get_icon() != os.environ['HOME']+'/.config/kinto/kinto-invert.svg'):
self.checkbox_enable.disconnect(self.enable_id)
self.checkbox_enable.set_active(True)
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,False)
self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto-invert.svg')
elif (nowts - self.unixts) > 5 and (status == 'inactive' and self.indicator.get_icon() != os.environ['HOME']+'/.config/kinto/kinto.svg'):
self.checkbox_enable.disconnect(self.enable_id)
self.checkbox_enable.set_active(False)
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True)
self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto.svg')
self.menu.append(self.tweaks) # print('stats: ' + status + ' last: ' + self.last_status)
# if status != self.last_status and status == 'active':
# # print('inside')
# self.refreshKB()
# Edit Config self.last_status = status
self.button_config.connect('activate',self.setConfig)
self.menu.append(self.button_config)
# Set System Keyboard Shortcuts return self.kinto_status.poll() is None
self.button_syskb.connect('activate',self.setSysKB)
self.menu.append(self.button_syskb)
# Set Language def openSupport(self,button):
self.button_region.connect('activate',self.setRegion) Gtk.show_uri_on_window(None, "https://github.com/rbreaves/kinto#table-of-contents", Gtk.get_current_event_time())
self.menu.append(self.button_region) return
item_quit = Gtk.MenuItem('Close') def runAbout(self,button):
item_quit.connect('activate', quit) win = Gtk.Window()
self.menu.append(item_quit)
self.menu.show_all()
return self.menu path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = -1
height = 128
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
win.set_default_icon_list([pixbuf])
win.set_title("About")
win.set_default_size(350, 200)
win.set_position(Gtk.WindowPosition.CENTER)
context = win.get_style_context()
default_background = str(context.get_background_color(Gtk.StateType.NORMAL))
tokenValue = re.search('red=(\d.\d+), green=(\d.\d+), blue=(\d.\d+), alpha=(\d.\d+)', default_background)
red = float(tokenValue.group(1))
green = float(tokenValue.group(2))
blue = float(tokenValue.group(3))
alpha = float(tokenValue.group(4))
bgAvg = (red + green + blue)/3
if(bgAvg > 0.5):
theme = "light"
else:
theme = "dark"
vbox = Gtk.VBox()
# innervbox = Gtk.VBox()
if theme == "dark":
path = os.environ['HOME']+'/.config/kinto/kinto-invert.svg'
else:
path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = -1
height = 128
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
image = Gtk.Image()
image.set_from_pixbuf(pixbuf)
with open('version', 'r') as file:
verdata = file.read().replace('\n', '')
version = Gtk.Label('Kinto v' + verdata)
credits = Gtk.Label("Author: Ben Reaves")
spacer = Gtk.Label(" ")
copy = Gtk.Label("Copyrighted 2019, 2020 - GPLv2")
url = Gtk.LinkButton("http://kinto.sh", label="http://kinto.sh")
url2 = Gtk.Label("http://kinto.sh")
vbox.add(image)
vbox.add(version)
vbox.add(spacer)
vbox.add(credits)
vbox.add(copy)
vbox.add(url)
win.add(vbox)
win.show_all()
version.set_selectable(True)
win.connect('delete-event', self.on_delete_event)
return
def setTweaks(self,button): def setTweaks(self,button):
win = Gtk.Window() win = Gtk.Window()
path = os.environ['HOME']+'/.config/kinto/kinto-color.svg'
width = -1
height = 128
preserve_aspect_ratio = True
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, preserve_aspect_ratio)
win.set_default_icon_list([pixbuf])
win.set_title("Kinto Tweaks") win.set_title("Kinto Tweaks")
win.set_default_size(350, 200) win.set_default_size(350, 200)
win.set_position(Gtk.WindowPosition.CENTER) win.set_position(Gtk.WindowPosition.CENTER)
@@ -234,11 +451,11 @@ class Indicator():
if restartsvc == True: if restartsvc == True:
try: try:
restartcmd = ['sudo', 'systemctl','restart','xkeysnail'] restartcmd = ['sudo', 'systemctl','restart','xkeysnail']
subprocess.Popen(restartcmd) Popen(restartcmd)
restartsvc = False restartsvc = False
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error restarting Kinto after setting tweaks!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error restarting Kinto after setting tweaks!','-i','budgie-desktop-symbolic'])
self.hide() self.hide()
self.destroy() self.destroy()
@@ -262,12 +479,12 @@ class Indicator():
cmds = ['perl','-pi','-e',setkb,self.kconfig] cmds = ['perl','-pi','-e',setkb,self.kconfig]
cmdsTerm = subprocess.Popen(cmds) cmdsTerm = Popen(cmds)
restartsvc = True restartsvc = True
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error Resetting AltGr!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error Resetting AltGr!','-i','budgie-desktop-symbolic'])
return return
@@ -282,12 +499,12 @@ class Indicator():
cmds = ['perl','-pi','-e',setkb,self.kconfig] cmds = ['perl','-pi','-e',setkb,self.kconfig]
cmdsTerm = subprocess.Popen(cmds) cmdsTerm = Popen(cmds)
restartsvc = True restartsvc = True
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error Resetting SublimeText remaps for VSCode!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error Resetting SublimeText remaps for VSCode!','-i','budgie-desktop-symbolic'])
return return
def setCaps2Esc(self,button): def setCaps2Esc(self,button):
@@ -306,12 +523,12 @@ class Indicator():
else: else:
self.caps2cmd.set_sensitive(True) self.caps2cmd.set_sensitive(True)
cmdsTerm = subprocess.Popen(cmds) cmdsTerm = Popen(cmds)
restartsvc = True restartsvc = True
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error resetting caps2esc!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error resetting caps2esc!','-i','budgie-desktop-symbolic'])
return return
@@ -332,66 +549,120 @@ class Indicator():
else: else:
self.caps2esc.set_sensitive(True) self.caps2esc.set_sensitive(True)
cmdsTerm = subprocess.Popen(cmds) cmdsTerm = Popen(cmds)
restartsvc = True restartsvc = True
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error resetting caps2cmd!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error resetting caps2cmd!','-i','budgie-desktop-symbolic'])
return return
def runRestart(self,button):
try:
stop = Popen(['sudo', 'systemctl','stop','xkeysnail'])
stop.wait()
time.sleep(1)
res = Popen(['pgrep','xkeysnail'])
res.wait()
if res.returncode == 0:
# Popen(['notify-send','Kinto: Ending Debug','-i','budgie-desktop-symbolic'])
pkillxkey = Popen(['sudo', 'pkill','-f','bin/xkeysnail'])
pkillxkey.wait()
Popen(['sudo', 'systemctl','start','xkeysnail'])
except:
Popen(['notify-send','Kinto: Error restarting Kinto!','-i','budgie-desktop-symbolic'])
# self.checkbox_enable.set_active(False)
# self.checkbox_enable.disconnect(self.enable_id)
# self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True)
# self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto-color.svg')
def runDebug(self,button):
try:
Popen([os.environ['HOME']+'/Documents/git-projects/kinto/xkeysnail-config/gui/kinto-gui.py','-d'])
except:
Popen(['notify-send','Kinto: Error restarting Kinto!','-i','budgie-desktop-symbolic'])
self.checkbox_enable.set_active(False)
self.checkbox_enable.disconnect(self.enable_id)
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True)
# self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto-color.svg')
def queryConfig(self,query): def queryConfig(self,query):
res = subprocess.Popen(query, stdout=subprocess.PIPE, stderr=None, shell=True) res = Popen(query, stdout=PIPE, stderr=None, shell=True)
res.wait() res.wait()
return res.communicate()[0].strip().decode('UTF-8') return res.communicate()[0].strip().decode('UTF-8')
def setEnable(self,button,enableKinto): def setEnable(self,button,enableKinto):
try: try:
if enableKinto: if enableKinto:
subprocess.Popen(['sudo', 'systemctl','restart','xkeysnail']) res = Popen(['pgrep','xkeysnail'])
self.checkbox_enable.set_active(True) res.wait()
print(res.returncode)
if res.returncode == 0:
# Popen(['notify-send','Kinto: Err in debug mode?','-i','budgie-desktop-symbolic'])
pkillxkey = Popen(['sudo', 'pkill','-f','bin/xkeysnail'])
pkillxkey.wait()
Popen(['sudo', 'systemctl','restart','xkeysnail'])
self.checkbox_enable.disconnect(self.enable_id) self.checkbox_enable.disconnect(self.enable_id)
self.checkbox_enable.set_active(True)
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,False) self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,False)
self.indicator.set_icon(self.homedir+'/.config/kinto/kinto-invert.svg') self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto-invert.svg')
else: else:
subprocess.Popen(['sudo', 'systemctl','stop','xkeysnail']) Popen(['sudo', 'systemctl','stop','xkeysnail'])
self.checkbox_enable.set_active(False)
self.checkbox_enable.disconnect(self.enable_id) self.checkbox_enable.disconnect(self.enable_id)
self.checkbox_enable.set_active(False)
self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True) self.enable_id = self.checkbox_enable.connect('activate',self.setEnable,True)
self.indicator.set_icon(self.homedir+'/.config/kinto/kinto-color.svg') self.indicator.set_icon(os.environ['HOME']+'/.config/kinto/kinto.svg')
except subprocess.CalledProcessError: self.unixts = int(time.time())
subprocess.Popen(['notify-send','Kinto: Error enabling!','-i','budgie-desktop-symbolic'])
except CalledProcessError:
Popen(['notify-send','Kinto: Error enabling!','-i','budgie-desktop-symbolic'])
def setAutostart(self,button,autostart): def setAutostart(self,button,autostart):
try: try:
if autostart == False: if autostart == False:
subprocess.Popen(['perl','-pi','-e','s/autostart = true/autostart = false/g',self.homedir+'/.config/kinto/kinto.py']) Popen(['perl','-pi','-e','s/autostart = true/autostart = false/g',os.environ['HOME']+'/.config/kinto/kinto.py'])
self.checkbox_autostart.set_active(False) self.checkbox_autostart.set_active(False)
self.checkbox_autostart.disconnect(self.chkautostart_id) self.checkbox_autostart.disconnect(self.chkautostart_id)
self.chkautostart_id = self.checkbox_autostart.connect('activate',self.setAutostart,True) self.chkautostart_id = self.checkbox_autostart.connect('activate',self.setAutostart,True)
else: else:
subprocess.Popen(['perl','-pi','-e','s/autostart = false/autostart = true/g',self.homedir+'/.config/kinto/kinto.py']) Popen(['perl','-pi','-e','s/autostart = false/autostart = true/g',os.environ['HOME']+'/.config/kinto/kinto.py'])
self.checkbox_autostart.set_active(True) self.checkbox_autostart.set_active(True)
self.checkbox_autostart.disconnect(self.chkautostart_id) self.checkbox_autostart.disconnect(self.chkautostart_id)
self.chkautostart_id = self.checkbox_autostart.connect('activate',self.setAutostart,False) self.chkautostart_id = self.checkbox_autostart.connect('activate',self.setAutostart,False)
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error setting autostart!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error setting autostart!','-i','budgie-desktop-symbolic'])
def setConfig(self,button): def setConfig(self,button):
try: try:
if os.path.exists('/opt/sublime_text/sublime_text'): if os.path.exists('/opt/sublime_text/sublime_text'):
subprocess.Popen(['/opt/sublime_text/sublime_text',self.homedir+'/.config/kinto/kinto.py']) Popen(['/opt/sublime_text/sublime_text',os.environ['HOME']+'/.config/kinto/kinto.py'])
elif which(gedit) is not None: elif which(gedit) is not None:
subprocess.Popen(['gedit',self.homedir+'/.config/kinto/kinto.py']) Popen(['gedit',os.environ['HOME']+'/.config/kinto/kinto.py'])
elif which(mousepad) is not None: elif which(mousepad) is not None:
subprocess.Popen(['mousepad',self.homedir+'/.config/kinto/kinto.py']) Popen(['mousepad',os.environ['HOME']+'/.config/kinto/kinto.py'])
except subprocess.CalledProcessError: # Notify user about error on running restart commands. except CalledProcessError: # Notify user about error on running restart commands.
subprocess.Popen(['notify-send','Kinto: Error could not open config file!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error could not open config file!','-i','budgie-desktop-symbolic'])
def setService(self,button):
try:
if os.path.exists('/opt/sublime_text/sublime_text'):
Popen(['/opt/sublime_text/sublime_text','/lib/systemd/system/xkeysnail.service'])
elif which(gedit) is not None:
Popen(['gedit','/lib/systemd/system/xkeysnail.service'])
elif which(mousepad) is not None:
Popen(['mousepad','/lib/systemd/system/xkeysnail.service'])
except CalledProcessError: # Notify user about error on running restart commands.
Popen(['notify-send','Kinto: Error could not open config file!','-i','budgie-desktop-symbolic'])
def setKB(self,button,kbtype): def setKB(self,button,kbtype):
try: try:
@@ -433,25 +704,25 @@ class Indicator():
restart = ['sudo', 'systemctl','restart','xkeysnail'] restart = ['sudo', 'systemctl','restart','xkeysnail']
cmds = ['perl','-pi','-e',setkb,self.kconfig] cmds = ['perl','-pi','-e',setkb,self.kconfig]
cmdsTerm = subprocess.Popen(cmds) cmdsTerm = Popen(cmds)
cmdsTerm.wait() cmdsTerm.wait()
subprocess.Popen(restart) Popen(restart)
except subprocess.CalledProcessError: except CalledProcessError:
subprocess.Popen(['notify-send','Kinto: Error Resetting KB Type!','-i','budgie-desktop-symbolic']) Popen(['notify-send','Kinto: Error Resetting KB Type!','-i','budgie-desktop-symbolic'])
def setSysKB(self,button): def setSysKB(self,button):
if self.ostype == "XFCE": if self.ostype == "XFCE":
subprocess.Popen(['xfce4-keyboard-settings']) Popen(['xfce4-keyboard-settings'])
else: else:
subprocess.Popen(['gnome-control-center','keyboard']) Popen(['gnome-control-center','keyboard'])
def setRegion(self,button): def setRegion(self,button):
if self.ostype == "XFCE": if self.ostype == "XFCE":
subprocess.Popen(['gnome-language-selector']) Popen(['gnome-language-selector'])
else: else:
subprocess.Popen(['gnome-control-center','region']) Popen(['gnome-control-center','region'])
def quit(source): def quit(source):
Gtk.main_quit() Gtk.main_quit()

View File

@@ -324,6 +324,7 @@ if [[ $1 == "1" || $1 == "2" || $1 == "3" || $1 == "4" || $1 == "winmac" || $1 =
sed -i "s/{username}/`whoami`/g" ./xkeysnail-config/limitedadmins.new sed -i "s/{username}/`whoami`/g" ./xkeysnail-config/limitedadmins.new
sed -i "s#{systemctl}#`\\which systemctl`#g" ./xkeysnail-config/limitedadmins.new sed -i "s#{systemctl}#`\\which systemctl`#g" ./xkeysnail-config/limitedadmins.new
sed -i "s#{pkill}#`\\which pkill`#g" ./xkeysnail-config/limitedadmins.new sed -i "s#{pkill}#`\\which pkill`#g" ./xkeysnail-config/limitedadmins.new
sed -i "s#{xkeysnail}#/usr/local/bin/xkeysnail#g" ./xkeysnail-config/limitedadmins.new
sudo chown root:root ./xkeysnail-config/limitedadmins.new sudo chown root:root ./xkeysnail-config/limitedadmins.new
sudo mv ./xkeysnail-config/limitedadmins.new /etc/sudoers.d/limitedadmins sudo mv ./xkeysnail-config/limitedadmins.new /etc/sudoers.d/limitedadmins
sed -i "s#{systemctl}#`\\which systemctl`#g" ~/.config/autostart/xkeysnail.desktop sed -i "s#{systemctl}#`\\which systemctl`#g" ~/.config/autostart/xkeysnail.desktop
@@ -394,6 +395,7 @@ fi
if [[ $1 == "1" || $1 == "2" || $1 == "3" || $1 == "winmac" || $1 == "mac" || $1 == "chromebook" ]]; then if [[ $1 == "1" || $1 == "2" || $1 == "3" || $1 == "winmac" || $1 == "mac" || $1 == "chromebook" ]]; then
mv ./xkeysnail-config/kinto.py.new ~/.config/kinto/kinto.py mv ./xkeysnail-config/kinto.py.new ~/.config/kinto/kinto.py
git describe --tags | perl -ne "print \"\$1 build `git rev-parse --short HEAD`\n\" for m/\b(.*)-\w+-\w{8}/" > ~/.config/kinto/version
# if [ "$distro" == "fedora" ];then # if [ "$distro" == "fedora" ];then
sudo rm /etc/systemd/system/xkeysnail.service sudo rm /etc/systemd/system/xkeysnail.service
if [ -d /usr/lib/systemd/system ];then if [ -d /usr/lib/systemd/system ];then