Compare commits

..

8 Commits

11 changed files with 310 additions and 97 deletions

View File

@@ -5,11 +5,11 @@ An onscreen keyboard for the mouse.
* PyGObject * PyGObject
* python-xlib * python-xlib
* pyautogui * pyautogui
* setproctitle
# TODO * fast-autocomplete[levenshtein]
<li>Get save and execute of custom commands working.</li>
# Images # Images
![1 image of the alphabet. ](images/pic1.png) ![1 image of the alphabet. ](images/pic1.png)
![2 Image of the symbols. ](images/pic2.png) ![2 Image of the symbols. ](images/pic2.png)
![3 Image of the emoji. ](images/pic3.png) ![3 Image of list of commands. ](images/pic3.png)
![4 Image of the emoji. ](images/pic4.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 152 KiB

BIN
images/pic4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

View File

@@ -1,4 +1,5 @@
PyGObject PyGObject
pyautogui
python-xlib python-xlib
pyautogui
setproctitle setproctitle
fast-autocomplete[levenshtein]

View File

@@ -57,7 +57,7 @@ keys_json = {
}, },
"row4": { "row4": {
"pKeys": ['z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '?'], "pKeys": ['z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '?'],
"sKeys": ['', '', '<', '>', '[', ']', '(', ')', '{', '}'] "sKeys": ['', '', '<|shift+,', '>', '[', ']', '(', ')', '{', '}']
}, },
} }
} }
@@ -85,8 +85,9 @@ _USR_PATH = f"/usr/share/{app_name.lower()}"
_CONFIG_PATH = f"{_USER_HOME}/.config/{app_name.lower()}" _CONFIG_PATH = f"{_USER_HOME}/.config/{app_name.lower()}"
_ICON_FILE = f"{_CONFIG_PATH}/icons/{app_name.lower()}.png" _ICON_FILE = f"{_CONFIG_PATH}/icons/{app_name.lower()}.png"
_CSS_FILE = f"{_CONFIG_PATH}/stylesheet.css" _CSS_FILE = f"{_CONFIG_PATH}/stylesheet.css"
_DICT_FILE = f"{_CONFIG_PATH}/edmt_dictionary.json"
_EMOJI_FILE = f"{_CONFIG_PATH}/emoji.json" _EMOJI_FILE = f"{_CONFIG_PATH}/emoji.json"
_LOG_FILE = f"{_CONFIG_PATH}/application.log" _LOG_PATH = f"{_CONFIG_PATH}"
ch_log_lvl: int = 10 ch_log_lvl: int = 10
fh_log_lvl: int = 20 fh_log_lvl: int = 20
@@ -110,10 +111,11 @@ if not os.path.exists(_EMOJI_FILE):
builtins.CONFIG_PATH = _CONFIG_PATH builtins.CONFIG_PATH = _CONFIG_PATH
builtins.ICON_FILE = _ICON_FILE builtins.ICON_FILE = _ICON_FILE
builtins.CSS_FILE = _CSS_FILE builtins.CSS_FILE = _CSS_FILE
builtins.DICT_FILE = _DICT_FILE
builtins.EMOJI_FILE = _EMOJI_FILE builtins.EMOJI_FILE = _EMOJI_FILE
builtins.logger = Logger(_LOG_FILE, ch_log_lvl, fh_log_lvl).get_logger() builtins.logger = Logger(_LOG_PATH, ch_log_lvl, fh_log_lvl).get_logger()
builtins.endpoint_registry = EndpointRegistry() builtins.endpoint_registry = EndpointRegistry()
builtins.event_system = EventSystem() builtins.event_system = EventSystem()
builtins.typwriter = Pyautogui_Controller() builtins.typwriter = Pyautogui_Controller()

View File

@@ -54,9 +54,9 @@ class Keys_Column(Gtk.Box):
row_box = self.add_row() row_box = self.add_row()
if len(pKeys) == len(sKeys): if len(pKeys) == len(sKeys):
for i in range(10): for i in range(10):
pkey = pKeys[i] pKey = pKeys[i]
sKey = sKeys[i] sKey = sKeys[i]
row_box.add(Key(pkey, sKey)) row_box.add(Key(pKey, sKey))
else: else:
raise KeyboardRowMatchError("A row in keys_json has missmatched pKeys to sKeys lengths.") raise KeyboardRowMatchError("A row in keys_json has missmatched pKeys to sKeys lengths.")

View File

@@ -1,10 +1,19 @@
# Python imports # Python imports
import json
import time
# Lib imports # Lib imports
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
try:
from fast_autocomplete import AutoComplete
auto_completion = True
except Exception as e:
print( repr(e) )
auto_completion = False
# Application imports # Application imports
from .columns import Left_Column from .columns import Left_Column
from .columns import Keys_Column from .columns import Keys_Column
@@ -20,8 +29,10 @@ class Auto_Type(Gtk.Box):
def __init__(self): def __init__(self):
super(Auto_Type, self).__init__() super(Auto_Type, self).__init__()
self._processing_dictionary = False
pad1 = Gtk.Label() pad1 = Gtk.Label()
pad2 = Gtk.Label() pad2 = Gtk.Label()
self._res_popover = Gtk.Popover()
self._auto_typer = Gtk.SearchEntry() self._auto_typer = Gtk.SearchEntry()
self._type_btn = Gtk.Button(label = "Type") self._type_btn = Gtk.Button(label = "Type")
@@ -38,15 +49,67 @@ class Auto_Type(Gtk.Box):
self.add(self._type_btn) self.add(self._type_btn)
self.add(pad2) self.add(pad2)
self.setup_auto_completion()
self.setup_styling() self.setup_styling()
self.setup_signals() self.setup_signals()
self.show_all() self.show_all()
def setup_auto_completion(self):
if auto_completion:
self._word_list = Gtk.Box()
scrolled_win = Gtk.ScrolledWindow()
viewport = Gtk.Viewport()
viewport.add(self._word_list)
scrolled_win.add(viewport)
scrolled_win.show_all()
self._res_popover.set_size_request(200, 400)
self._res_popover.set_relative_to(self._auto_typer)
self._res_popover.set_modal(False)
self._res_popover.add(scrolled_win)
self._res_popover.set_default_widget(scrolled_win)
self._word_list.set_orientation(Gtk.Orientation.VERTICAL)
self.setup_dictionary()
@daemon_threaded
def setup_dictionary(self):
self._processing_dictionary = True
_words = set()
words = {}
with open(DICT_FILE, 'r') as f:
dict_data = json.load(f)
self._auto_typer.set_progress_fraction(0.25)
for field in dict_data:
_words.add( field["word"] )
_words.add( field["word"].lower() )
self._auto_typer.set_progress_fraction(0.5)
del dict_data
for word in _words:
words[word] = {}
self._auto_typer.set_progress_fraction(0.75)
self.autocomplete = AutoComplete(words=words)
del _words
del words
self._auto_typer.set_progress_fraction(1.0)
time.sleep(1)
self._auto_typer.set_progress_fraction(0.0)
self._processing_dictionary = False
def setup_styling(self): def setup_styling(self):
self.set_margin_bottom(5) self.set_margin_bottom(5)
def setup_signals(self): def setup_signals(self):
if auto_completion:
self._auto_typer.connect("search-changed", self.search_changed)
self._auto_typer.connect("enter-notify-event", self.focus_entry) self._auto_typer.connect("enter-notify-event", self.focus_entry)
self._auto_typer.connect("leave-notify-event", self.unfocus_entry) self._auto_typer.connect("leave-notify-event", self.unfocus_entry)
self._type_btn.connect("released", self.type_out) self._type_btn.connect("released", self.type_out)
@@ -61,8 +124,39 @@ class Auto_Type(Gtk.Box):
widget.grab_remove() widget.grab_remove()
event_system.emit("unset_focusable") event_system.emit("unset_focusable")
def search_changed(self, widget = None, eve = None):
if self._processing_dictionary: return
text = widget.get_text()
if not text:
self._res_popover.hide()
return
words = self.autocomplete.search(word=text, max_cost=3, size=100)
if not words:
self._res_popover.hide()
return
self._clear_children(self._word_list)
for word in words:
button = Gtk.Button(label=word[0])
button.connect("clicked", self.type_out)
self._word_list.add(button)
self._word_list.show_all()
self._res_popover.show()
def _clear_children(self, widget):
for child in widget.get_children():
widget.remove(child)
def type_out(self, widget = None, eve = None): def type_out(self, widget = None, eve = None):
text = self._auto_typer.get_text() text = self._auto_typer.get_text()
if isinstance(widget, Gtk.Button):
if not widget.get_label().lower() == "type":
text = widget.get_label()
typwriter.type_string(text) typwriter.type_string(text)

View File

@@ -17,20 +17,21 @@ class Esc_Key(Key):
def __init__(self): def __init__(self):
super(Esc_Key, self).__init__("Esc", "Esc", iscontrol = True) super(Esc_Key, self).__init__("Esc", "Esc", iscontrol = True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class CAPS_Key(Key): class CAPS_Key(Key):
def __init__(self): def __init__(self):
super(CAPS_Key, self).__init__("Caps", "Caps", iscontrol = True) super(CAPS_Key, self).__init__("Caps", "Caps", iscontrol = True)
self.setup_styling() self._setup_styling()
self.show_all()
def setup_styling(self): def _setup_styling(self):
self.set_vexpand(True) self.set_vexpand(True)
super()._setup_styling()
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._clicked) self.connect("released", self._clicked)
def _clicked(self, widget = None): def _clicked(self, widget = None):
@@ -45,11 +46,9 @@ class Backspace_Key(Key):
def __init__(self): def __init__(self):
super(Backspace_Key, self).__init__("Backspace", "Backspace", iscontrol=True) super(Backspace_Key, self).__init__("Backspace", "Backspace", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._clicked) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
def _clicked(self, widget = None):
typwriter.press_special_keys(self.get_label())
class Emoji_Key(Key): class Emoji_Key(Key):
def __init__(self, emoji_popover): def __init__(self, emoji_popover):
@@ -58,7 +57,7 @@ class Emoji_Key(Key):
self._ctx = self.get_style_context() self._ctx = self.get_style_context()
self._emoji_popover = emoji_popover self._emoji_popover = emoji_popover
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._clicked) self.connect("released", self._clicked)
def _clicked(self, widget = None): def _clicked(self, widget = None):
@@ -73,7 +72,7 @@ class Symbols_Key(Key):
super(Symbols_Key, self).__init__("Symbols", "Symbols", iscontrol = True) super(Symbols_Key, self).__init__("Symbols", "Symbols", iscontrol = True)
self.setup_custom_signals() self.setup_custom_signals()
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._clicked) self.connect("released", self._clicked)
def setup_custom_signals(self): def setup_custom_signals(self):
@@ -92,30 +91,26 @@ class Symbols_Key(Key):
class Enter_Key(Key): class Enter_Key(Key):
def __init__(self): def __init__(self):
super(Enter_Key, self).__init__("Enter", "Enter", iscontrol=True) super(Enter_Key, self).__init__("Enter", "Enter", iscontrol=True)
self.setup_styling() self._setup_styling()
def setup_styling(self): def _setup_styling(self):
self.set_vexpand(True) self.set_vexpand(True)
super()._setup_styling()
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
############################# Bottom_Key_Row Keys ############################# ############################# Bottom_Key_Row Keys #############################
class Esc_Key(Key):
def __init__(self):
super(Esc_Key, self).__init__("Esc", "Esc", iscontrol=True)
def setup_signals(self):
self.connect("released", self._do_press_special_key)
class Space_Key(Key): class Space_Key(Key):
def __init__(self): def __init__(self):
super(Space_Key, self).__init__("Space", "Space", iscontrol=True) super(Space_Key, self).__init__("Space", "Space", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class AT_Key(Key): class AT_Key(Key):
def __init__(self): def __init__(self):
@@ -132,68 +127,78 @@ class Tab_Key(Key):
def __init__(self): def __init__(self):
super(Tab_Key, self).__init__("Tab", "Tab", iscontrol=True) super(Tab_Key, self).__init__("Tab", "Tab", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Del_Key(Key): class Del_Key(Key):
def __init__(self): def __init__(self):
super(Del_Key, self).__init__("Del", "Del", iscontrol=True) super(Del_Key, self).__init__("Del", "Del", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Ctrl_Key(Key): class Ctrl_Key(Key):
def __init__(self): def __init__(self):
super(Ctrl_Key, self).__init__("Ctrl", "Ctrl", iscontrol=True) super(Ctrl_Key, self).__init__("Ctrl", "Ctrl", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Shift_Key(Key): class Shift_Key(Key):
def __init__(self): def __init__(self):
super(Shift_Key, self).__init__("Shift", "Shift", iscontrol=True) super(Shift_Key, self).__init__("Shift", "Shift", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Alt_Key(Key): class Alt_Key(Key):
def __init__(self): def __init__(self):
super(Alt_Key, self).__init__("Alt", "Alt", iscontrol=True) super(Alt_Key, self).__init__("Alt", "Alt", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class PrtSc_Key(Key): class PrtSc_Key(Key):
def __init__(self): def __init__(self):
super(PrtSc_Key, self).__init__("PrtSc", "PrtSc", iscontrol=True) super(PrtSc_Key, self).__init__("PrtSc", "PrtSc", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Up_Key(Key): class Up_Key(Key):
def __init__(self): def __init__(self):
super(Up_Key, self).__init__("Up", "Up", iscontrol=True) super(Up_Key, self).__init__("Up", "Up", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Down_Key(Key): class Down_Key(Key):
def __init__(self): def __init__(self):
super(Down_Key, self).__init__("Down", "Down", iscontrol=True) super(Down_Key, self).__init__("Down", "Down", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Left_Key(Key): class Left_Key(Key):
def __init__(self): def __init__(self):
super(Left_Key, self).__init__("Left", "Left", iscontrol=True) super(Left_Key, self).__init__("Left", "Left", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)
class Right_Key(Key): class Right_Key(Key):
def __init__(self): def __init__(self):
super(Right_Key, self).__init__("Right", "Right", iscontrol=True) super(Right_Key, self).__init__("Right", "Right", iscontrol=True)
def setup_signals(self): def _setup_signals(self):
self.connect("released", self._do_press_special_key) self.connect("button-press-event", self._do_press_special_key)
self.connect("button-release-event", self._do_release_special_key)

View File

@@ -1,11 +1,13 @@
# Python imports # Python imports
from collections import defaultdict
import json import json
import asyncio
from collections import defaultdict
# Lib imports # Lib imports
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import GLib
# Application imports # Application imports
from .key import Key from .key import Key
@@ -19,7 +21,7 @@ class Emoji_Notebook(Gtk.Notebook):
def __init__(self): def __init__(self):
super(Emoji_Notebook, self).__init__() super(Emoji_Notebook, self).__init__()
self.load_ui( self.get_data(EMOJI_FILE) ) self.load_ui()
self.setup_styling() self.setup_styling()
self.show_all() self.show_all()
@@ -29,26 +31,51 @@ class Emoji_Notebook(Gtk.Notebook):
self.set_current_page(0) self.set_current_page(0)
self.set_scrollable(True) self.set_scrollable(True)
def get_data(self, file): def load_ui(self):
emoji_grouping = defaultdict(list) emoji_data = None
with open(EMOJI_FILE, 'r') as f:
with open(file, 'r') as f:
emoji_data = json.load(f) emoji_data = json.load(f)
for emoji in emoji_data:
if not emoji_data:
print("No emoji data found in file...")
return
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None
if loop and loop.is_running():
loop = asyncio.get_event_loop()
loop.create_task( self._async_load_ui(emoji_data) )
else:
asyncio.run( self._async_load_ui(emoji_data) )
async def _async_load_ui(self, emoji_data):
emoji_grouping = await self._get_emoji_grouping(emoji_data)
GLib.idle_add(self._populate_ui, emoji_grouping)
async def _get_emoji_grouping(self, emoji_data):
emoji_grouping = defaultdict(list)
async def add_to_group(emoji):
category = emoji['category'] category = emoji['category']
del emoji['category'] key = Key( emoji["emoji"], emoji["emoji"] )
del emoji['unicode_version'] key._is_emoji = True
del emoji['ios_version']
emoji_grouping[category].append(emoji) emoji_grouping[category].append(key)
tasks = [ add_to_group(emoji) for emoji in emoji_data]
await asyncio.gather(*tasks)
return emoji_grouping return emoji_grouping
def load_ui(self, emoji_grouping): def _populate_ui(self, emoji_grouping):
width = 1 width = 1
height = 1 height = 1
for group in emoji_grouping: for group in emoji_grouping:
tab_widget = Gtk.Label(label=group) tab_widget = Gtk.Label(label=group)
scroll, grid = self.create_scroll_and_grid() scroll, grid = self.create_scroll_and_grid()
self.append_page(scroll, tab_widget) self.append_page(scroll, tab_widget)
self.set_tab_reorderable(scroll, False) self.set_tab_reorderable(scroll, False)
self.set_tab_detachable(scroll, False) self.set_tab_detachable(scroll, False)
@@ -56,16 +83,15 @@ class Emoji_Notebook(Gtk.Notebook):
top = 0 top = 0
left = 0 left = 0
for emoji in emoji_grouping[group]: for emoji in emoji_grouping[group]:
key = Key(emoji["emoji"], emoji["emoji"]) grid.attach(emoji, left, top, width, height)
key._is_emoji = True
key.show()
grid.attach(key, left, top, width, height)
left += 1 left += 1
if left > 8: if left > 8:
left = 0 left = 0
top += 1 top += 1
self.show_all()
del emoji_grouping
def create_scroll_and_grid(self): def create_scroll_and_grid(self):
scroll = Gtk.ScrolledWindow() scroll = Gtk.ScrolledWindow()

View File

@@ -4,50 +4,134 @@
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import GLib
# Application imports # Application imports
class Key(Gtk.Button or Gtk.ToggleButton): class Key(Gtk.Button or Gtk.ToggleButton):
def __init__(self, primary = "NULL", secondary = "NULL", iscontrol=False): def __init__(self, primary = "NULL", secondary = "NULL", iscontrol = False):
super(Key, self).__init__() super(Key, self).__init__()
self.timer_id = None
self.iscontrol = iscontrol self.iscontrol = iscontrol
self._primary_symbol = primary self._primary_symbol = primary
self._secondary_symbol = secondary self._secondary_symbol = secondary
self._alt_symbol = ''
self._is_upper = False self._is_upper = False
self._is_symbol = False self._is_symbol = False
self._is_emoji = False self._is_emoji = False
self.isShiftOn = False
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._setup_if_keycombo(secondary)
def _setup_styling(self):
self.set_label(self._primary_symbol) self.set_label(self._primary_symbol)
self.setup_custom_signals()
self.setup_signals()
def setup_custom_signals(self): def _setup_signals(self):
self.connect("button-press-event", self._do_press)
self.connect("button-release-event", self._do_release)
self.connect("toggle-emoji-keys", self.toggle_emoji_keys)
def _subscribe_to_events(self):
event_system.subscribe("toggle_caps", self.toggle_caps) event_system.subscribe("toggle_caps", self.toggle_caps)
event_system.subscribe("toggle_symbol_keys", self.toggle_symbol_keys) event_system.subscribe("toggle_symbol_keys", self.toggle_symbol_keys)
def setup_signals(self): def _setup_if_keycombo(self, secondary: str):
self.connect("released", self._do_type) if not self.iscontrol and (len(secondary) > 1 and '|' in secondary):
self.connect("toggle-emoji-keys", self.toggle_emoji_keys) self._secondary_symbol = secondary[0]
parts = secondary.split("|")[1].split("+")
for part in parts:
if "shift" == part.lower():
self.isShiftOn = True
self._alt_symbol = parts[-1]
def _do_press(self, widget = None, eve = None):
if not self.timer_id:
self.did_loop_type = False
self.timer_id = GLib.timeout_add(500, self._do_wait_loop_type)
def _do_release(self, widget = None, eve = None):
if self.did_loop_type:
GLib.source_remove(self.timer_id)
self.timer_id = None
self.did_loop_type = False
return
self._do_type()
GLib.source_remove(self.timer_id)
self.timer_id = None
def _do_wait_loop_type(self):
if not self.timer_id: return False
self.did_loop_type = True
self.timer_id = GLib.timeout_add(200, self._do_type)
return False
def _do_type(self):
if not self.timer_id: return False
def _do_type(self, widget = None):
key = self.get_label().strip() key = self.get_label().strip()
if not self._is_emoji: if self._is_emoji:
typwriter.type(key)
else:
typwriter.set_clipboard_data(key, "utf-16") typwriter.set_clipboard_data(key, "utf-16")
typwriter.isCtrlOn = True typwriter.isCtrlOn = True
typwriter.type('v') typwriter.type('v')
typwriter.isCtrlOn = False typwriter.isCtrlOn = False
def _do_press_special_key(self, widget = None): return True
if self._alt_symbol and self._is_symbol:
typwriter.isShiftOn = self.isShiftOn
typwriter.type(self._alt_symbol)
typwriter.isShiftOn = False
return True
typwriter.type(key)
return True
def _do_press_special_key(self, widget = None, eve = None):
if not self.timer_id:
self.did_loop_type = False
self.timer_id = GLib.timeout_add(500, self._do_wait_loop_special_type)
def _do_release_special_key(self, widget = None, eve = None):
if self.did_loop_type:
GLib.source_remove(self.timer_id)
self.timer_id = None
self.did_loop_type = False
return
self._do_type_special_key()
GLib.source_remove(self.timer_id)
self.timer_id = None
def _do_wait_loop_special_type(self):
if not self.timer_id: return False
self.did_loop_type = True
self.timer_id = GLib.timeout_add(200, self._do_type_special_key)
return False
def _do_type_special_key(self):
if not self.timer_id: return False
key = self.get_label() key = self.get_label()
if key in ["Ctrl", "Shift", "Alt"]: if key in ["Ctrl", "Shift", "Alt"]:
ctx = widget.get_style_context() ctx = self.get_style_context()
ctx.remove_class("toggled_bttn") if ctx.has_class("toggled_bttn") else ctx.add_class("toggled_bttn") ctx.remove_class("toggled_bttn") if ctx.has_class("toggled_bttn") else ctx.add_class("toggled_bttn")
typwriter.press_special_keys(key) typwriter.press_special_keys(key)
return True
def toggle_symbol_keys(self, widget = None, eve = None): def toggle_symbol_keys(self, widget = None, eve = None):
if not self.iscontrol: if not self.iscontrol:

File diff suppressed because one or more lines are too long