Lines 7-15
Link Here
|
7 |
from .labelmanager import LabelManager |
7 |
from .labelmanager import LabelManager |
8 |
|
8 |
|
9 |
from threading import Timer |
9 |
from threading import Timer |
|
|
10 |
from datetime import datetime |
10 |
import json |
11 |
import json |
11 |
import os |
12 |
import os |
12 |
import subprocess |
13 |
import subprocess |
|
|
14 |
from tempfile import NamedTemporaryFile |
13 |
|
15 |
|
14 |
import gi |
16 |
import gi |
15 |
# gi.require_version('Gtk', '2.0') |
17 |
# gi.require_version('Gtk', '2.0') |
Lines 19-25
Link Here
|
19 |
from gi.repository import GLib |
21 |
from gi.repository import GLib |
20 |
GLib.threads_init() |
22 |
GLib.threads_init() |
21 |
|
23 |
|
22 |
from gi.repository import Gtk, Gdk, Pango |
24 |
from gi.repository import Gtk, Gdk, GdkPixbuf, Pango |
23 |
import cairo |
25 |
import cairo |
24 |
|
26 |
|
25 |
|
27 |
|
Lines 35-40
Link Here
|
35 |
VERTICAL = Gtk.Orientation.VERTICAL |
37 |
VERTICAL = Gtk.Orientation.VERTICAL |
36 |
IF_VALID = Gtk.SpinButtonUpdatePolicy.IF_VALID |
38 |
IF_VALID = Gtk.SpinButtonUpdatePolicy.IF_VALID |
37 |
|
39 |
|
|
|
40 |
BUTTONS_SVG = None |
41 |
|
42 |
def load_button_pixbufs(color): |
43 |
global BUTTONS_SVG |
44 |
|
45 |
if BUTTONS_SVG is None: |
46 |
with open('/usr/share/images/screenkey/mouse.svg', 'r') as svg_file: |
47 |
BUTTONS_SVG = svg_file.readlines() |
48 |
|
49 |
if not isinstance(color, str): |
50 |
# Gdk.Color |
51 |
color = 'rgb({}, {}, {})'.format( |
52 |
round(color.red_float * 255), |
53 |
round(color.green_float * 255), |
54 |
round(color.blue_float * 255) |
55 |
) |
56 |
button_pixbufs = [] |
57 |
svg = NamedTemporaryFile(mode='w', suffix='.svg') |
58 |
for line in BUTTONS_SVG[1:-1]: |
59 |
svg.seek(0) |
60 |
svg.truncate() |
61 |
svg.writelines(( |
62 |
BUTTONS_SVG[0], |
63 |
line.replace('#fff', color), |
64 |
BUTTONS_SVG[-1], |
65 |
)) |
66 |
svg.flush() |
67 |
os.fsync(svg.fileno()) |
68 |
button_pixbufs.append(GdkPixbuf.Pixbuf.new_from_file(svg.name)) |
69 |
svg.close() |
70 |
return button_pixbufs |
71 |
|
38 |
|
72 |
|
39 |
class Screenkey(Gtk.Window): |
73 |
class Screenkey(Gtk.Window): |
40 |
STATE_FILE = os.path.join(GLib.get_user_config_dir(), 'screenkey.json') |
74 |
STATE_FILE = os.path.join(GLib.get_user_config_dir(), 'screenkey.json') |
Lines 67-73
Link Here
|
67 |
'vis_shift': False, |
101 |
'vis_shift': False, |
68 |
'vis_space': True, |
102 |
'vis_space': True, |
69 |
'geometry': None, |
103 |
'geometry': None, |
70 |
'screen': 0}) |
104 |
'screen': 0, |
|
|
105 |
'mouse': False, |
106 |
'button_hide_duration': 1}) |
71 |
self.options = self.load_state() |
107 |
self.options = self.load_state() |
72 |
if self.options is None: |
108 |
if self.options is None: |
73 |
self.options = defaults |
109 |
self.options = defaults |
Lines 87-101
Link Here
|
87 |
self.set_focus_on_map(False) |
123 |
self.set_focus_on_map(False) |
88 |
self.set_app_paintable(True) |
124 |
self.set_app_paintable(True) |
89 |
|
125 |
|
|
|
126 |
self.button_pixbufs = [] |
127 |
self.button_states = [None] * 8 |
128 |
self.img = Gtk.Image() |
129 |
self.update_image_tag = None |
130 |
|
131 |
self.box = Gtk.HBox(homogeneous=False) |
132 |
self.box.show() |
133 |
self.add(self.box) |
134 |
|
90 |
self.label = Gtk.Label() |
135 |
self.label = Gtk.Label() |
91 |
self.label.set_attributes(Pango.AttrList()) |
136 |
self.label.set_attributes(Pango.AttrList()) |
92 |
self.label.set_ellipsize(Pango.EllipsizeMode.START) |
137 |
self.label.set_ellipsize(Pango.EllipsizeMode.START) |
93 |
self.label.set_justify(Gtk.Justification.CENTER) |
138 |
self.label.set_justify(Gtk.Justification.CENTER) |
94 |
self.label.show() |
139 |
self.label.show() |
95 |
self.add(self.label) |
|
|
96 |
|
140 |
|
97 |
self.font = Pango.FontDescription(self.options.font_desc) |
141 |
self.font = Pango.FontDescription(self.options.font_desc) |
98 |
self.update_colors() |
142 |
self.update_colors() |
|
|
143 |
self.update_mouse_enabled() |
99 |
|
144 |
|
100 |
self.set_size_request(0, 0) |
145 |
self.set_size_request(0, 0) |
101 |
self.set_gravity(Gdk.Gravity.CENTER) |
146 |
self.set_gravity(Gdk.Gravity.CENTER) |
Lines 111-116
Link Here
|
111 |
if visual is not None: |
156 |
if visual is not None: |
112 |
self.set_visual(visual) |
157 |
self.set_visual(visual) |
113 |
|
158 |
|
|
|
159 |
self.box.pack_start(self.img, expand=False, fill=True, padding=0) |
160 |
self.box.pack_end(self.label, expand=False, fill=True, padding=0) |
161 |
|
114 |
self.labelmngr = None |
162 |
self.labelmngr = None |
115 |
self.enabled = True |
163 |
self.enabled = True |
116 |
self.on_change_mode() |
164 |
self.on_change_mode() |
Lines 177-182
Link Here
|
177 |
self.set_active_monitor(self.monitor) |
225 |
self.set_active_monitor(self.monitor) |
178 |
|
226 |
|
179 |
|
227 |
|
|
|
228 |
def update_mouse_enabled(self): |
229 |
if self.options.mouse: |
230 |
if not self.button_pixbufs: |
231 |
self.button_pixbufs = load_button_pixbufs( |
232 |
Gdk.color_parse(self.options.font_color) |
233 |
) |
234 |
self.img.show() |
235 |
self.update_image_tag = GLib.idle_add(self.update_image) |
236 |
else: |
237 |
self.img.hide() |
238 |
if self.update_image_tag is not None: |
239 |
GLib.source_remove(self.update_image_tag) |
240 |
self.update_image_tag = None |
241 |
|
242 |
|
180 |
def update_font(self): |
243 |
def update_font(self): |
181 |
_, window_height = self.get_size() |
244 |
_, window_height = self.get_size() |
182 |
text = self.label.get_text() |
245 |
text = self.label.get_text() |
Lines 185-193
Link Here
|
185 |
self.label.get_pango_context().set_font_description(self.font) |
248 |
self.label.get_pango_context().set_font_description(self.font) |
186 |
|
249 |
|
187 |
|
250 |
|
|
|
251 |
def update_image(self): |
252 |
if not self.button_pixbufs: |
253 |
self.update_image_tag = None |
254 |
return False |
255 |
|
256 |
pixbuf = self.button_pixbufs[0] |
257 |
copied = False |
258 |
|
259 |
for index, button_state in enumerate(self.button_states): |
260 |
if button_state is None: |
261 |
continue |
262 |
if button_state.pressed: |
263 |
alpha = 255 |
264 |
else: |
265 |
if self.options.button_hide_duration > 0: |
266 |
delta_time = (datetime.now() - button_state.stamp).total_seconds() |
267 |
hide_time = delta_time / self.options.button_hide_duration |
268 |
else: |
269 |
hide_time = 1 |
270 |
if hide_time < 1: |
271 |
alpha = int(255 * (1 - hide_time)) |
272 |
else: |
273 |
self.button_states[index] = None |
274 |
continue |
275 |
|
276 |
if not copied: |
277 |
pixbuf = pixbuf.copy() |
278 |
copied = True |
279 |
self.button_pixbufs[button_state.btn].composite( |
280 |
pixbuf, 0, 0, pixbuf.get_width(), pixbuf.get_height(), |
281 |
0, 0, 1, 1, |
282 |
GdkPixbuf.InterpType.NEAREST, alpha |
283 |
) |
284 |
|
285 |
_, height = self.get_size() |
286 |
scale = height / pixbuf.get_height() |
287 |
if scale != 1: |
288 |
width = int(pixbuf.get_width() * scale) |
289 |
pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR) |
290 |
self.img.set_from_pixbuf(pixbuf) |
291 |
|
292 |
if not copied: |
293 |
self.update_image_tag = None |
294 |
return False |
295 |
return True |
296 |
|
297 |
|
188 |
def update_colors(self): |
298 |
def update_colors(self): |
189 |
self.label.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(self.options.font_color)) |
299 |
font_color = Gdk.color_parse(self.options.font_color) |
|
|
300 |
self.label.modify_fg(Gtk.StateFlags.NORMAL, font_color) |
190 |
self.bg_color = Gdk.color_parse(self.options.bg_color) |
301 |
self.bg_color = Gdk.color_parse(self.options.bg_color) |
|
|
302 |
if self.options.mouse and self.button_pixbufs: |
303 |
self.button_pixbufs = load_button_pixbufs(font_color) |
191 |
|
304 |
|
192 |
|
305 |
|
193 |
def on_draw(self, widget, cr): |
306 |
def on_draw(self, widget, cr): |
Lines 215-220
Link Here
|
215 |
self.label.set_padding(window_width // 100, 0) |
328 |
self.label.set_padding(window_width // 100, 0) |
216 |
|
329 |
|
217 |
self.update_font() |
330 |
self.update_font() |
|
|
331 |
self.update_image() |
218 |
|
332 |
|
219 |
|
333 |
|
220 |
def update_geometry(self, configure=False): |
334 |
def update_geometry(self, configure=False): |
Lines 273-278
Link Here
|
273 |
self.quit(exit_status=os.EX_SOFTWARE) |
387 |
self.quit(exit_status=os.EX_SOFTWARE) |
274 |
|
388 |
|
275 |
|
389 |
|
|
|
390 |
def timed_show(self): |
391 |
if not self.get_property('visible'): |
392 |
self.show() |
393 |
if self.timer_hide: |
394 |
self.timer_hide.cancel() |
395 |
if self.options.timeout > 0 and not any(b and b.pressed for b in self.button_states): |
396 |
self.timer_hide = Timer(self.options.timeout, self.on_timeout_main) |
397 |
self.timer_hide.start() |
398 |
|
399 |
|
276 |
def on_label_change(self, markup): |
400 |
def on_label_change(self, markup): |
277 |
if markup is None: |
401 |
if markup is None: |
278 |
self.on_labelmngr_error() |
402 |
self.on_labelmngr_error() |
Lines 283-301
Link Here
|
283 |
self.label.set_attributes(attr) |
407 |
self.label.set_attributes(attr) |
284 |
self.update_font() |
408 |
self.update_font() |
285 |
|
409 |
|
286 |
if not self.get_property('visible'): |
410 |
self.timed_show() |
287 |
self.show() |
|
|
288 |
if self.timer_hide: |
289 |
self.timer_hide.cancel() |
290 |
if self.options.timeout > 0: |
291 |
self.timer_hide = Timer(self.options.timeout, self.on_timeout_main) |
292 |
self.timer_hide.start() |
293 |
if self.timer_min: |
411 |
if self.timer_min: |
294 |
self.timer_min.cancel() |
412 |
self.timer_min.cancel() |
295 |
self.timer_min = Timer(self.options.recent_thr * 2, self.on_timeout_min) |
413 |
self.timer_min = Timer(self.options.recent_thr * 2, self.on_timeout_min) |
296 |
self.timer_min.start() |
414 |
self.timer_min.start() |
297 |
|
415 |
|
298 |
|
416 |
|
|
|
417 |
def on_image_change(self, button_state): |
418 |
self.button_states[button_state.btn] = button_state |
419 |
if self.options.mouse: |
420 |
if not self.update_image_tag: |
421 |
self.update_image_tag = GLib.idle_add(self.update_image) |
422 |
self.timed_show() |
423 |
|
424 |
|
299 |
def on_timeout_main(self): |
425 |
def on_timeout_main(self): |
300 |
if not self.options.persist: |
426 |
if not self.options.persist: |
301 |
self.hide() |
427 |
self.hide() |
Lines 311-317
Link Here
|
311 |
self.logger.debug("Restarting LabelManager.") |
437 |
self.logger.debug("Restarting LabelManager.") |
312 |
if self.labelmngr: |
438 |
if self.labelmngr: |
313 |
self.labelmngr.stop() |
439 |
self.labelmngr.stop() |
314 |
self.labelmngr = LabelManager(self.on_label_change, logger=self.logger, |
440 |
self.labelmngr = LabelManager(self.on_label_change, |
|
|
441 |
self.on_image_change, |
442 |
logger=self.logger, |
315 |
key_mode=self.options.key_mode, |
443 |
key_mode=self.options.key_mode, |
316 |
bak_mode=self.options.bak_mode, |
444 |
bak_mode=self.options.bak_mode, |
317 |
mods_mode=self.options.mods_mode, |
445 |
mods_mode=self.options.mods_mode, |
Lines 494-499
Link Here
|
494 |
self.font = widget.props.font_desc |
622 |
self.font = widget.props.font_desc |
495 |
self.update_font() |
623 |
self.update_font() |
496 |
|
624 |
|
|
|
625 |
def on_cbox_mouse_changed(widget, data=None): |
626 |
self.options.mouse = widget.get_active() |
627 |
self.logger.debug("Mouse changed: %s." % self.options.mouse) |
628 |
self.update_mouse_enabled() |
629 |
|
630 |
def on_sb_mouse_duration_changed(widget, data=None): |
631 |
self.options.button_hide_duration = widget.get_value() |
632 |
self.logger.debug("Button hide duration value changed: %f." % self.options.button_hide_duration) |
633 |
|
497 |
frm_time = Gtk.Frame(label_widget=Gtk.Label("<b>%s</b>" % _("Time"), |
634 |
frm_time = Gtk.Frame(label_widget=Gtk.Label("<b>%s</b>" % _("Time"), |
498 |
use_markup=True), |
635 |
use_markup=True), |
499 |
border_width=4, |
636 |
border_width=4, |
Lines 711-716
Link Here
|
711 |
grid_color.attach_next_to(adj_scale, lbl_opacity, RIGHT, 1, 1) |
848 |
grid_color.attach_next_to(adj_scale, lbl_opacity, RIGHT, 1, 1) |
712 |
frm_color.add(grid_color) |
849 |
frm_color.add(grid_color) |
713 |
|
850 |
|
|
|
851 |
frm_mouse = Gtk.Frame(label_widget=Gtk.Label("<b>%s</b>" % _("Mouse"), |
852 |
use_markup=True), |
853 |
border_width=4, |
854 |
shadow_type=Gtk.ShadowType.NONE, |
855 |
margin=6, hexpand=True) |
856 |
vbox_mouse = Gtk.VBox(spacing=6) |
857 |
|
858 |
chk_mouse = Gtk.CheckButton(_("Show Mouse")) |
859 |
chk_mouse.connect("toggled", on_cbox_mouse_changed) |
860 |
chk_mouse.set_active(self.options.mouse) |
861 |
vbox_mouse.pack_start(chk_mouse, expand=False, fill=True, padding=0) |
862 |
|
863 |
hbox_mouse = Gtk.HBox() |
864 |
lbl_mouse1 = Gtk.Label(_("Hide duration")) |
865 |
lbl_mouse2 = Gtk.Label(_("seconds")) |
866 |
sb_mouse = Gtk.SpinButton(digits=1) |
867 |
sb_mouse.set_increments(0.5, 1.0) |
868 |
sb_mouse.set_range(0.0, 2.0) |
869 |
sb_mouse.set_numeric(True) |
870 |
sb_mouse.set_update_policy(Gtk.SpinButtonUpdatePolicy.IF_VALID) |
871 |
sb_mouse.set_value(self.options.button_hide_duration) |
872 |
sb_mouse.connect("value-changed", on_sb_mouse_duration_changed) |
873 |
hbox_mouse.pack_start(lbl_mouse1, expand=False, fill=False, padding=6) |
874 |
hbox_mouse.pack_start(sb_mouse, expand=False, fill=False, padding=4) |
875 |
hbox_mouse.pack_start(lbl_mouse2, expand=False, fill=False, padding=4) |
876 |
vbox_mouse.pack_start(hbox_mouse, expand=False, fill=False, padding=6) |
877 |
|
878 |
frm_mouse.add(vbox_mouse) |
879 |
frm_mouse.show_all() |
880 |
|
714 |
hbox_main = Gtk.Grid(column_homogeneous=True) |
881 |
hbox_main = Gtk.Grid(column_homogeneous=True) |
715 |
vbox_main = Gtk.Grid(orientation=VERTICAL) |
882 |
vbox_main = Gtk.Grid(orientation=VERTICAL) |
716 |
vbox_main.add(frm_time) |
883 |
vbox_main.add(frm_time) |
Lines 720-725
Link Here
|
720 |
vbox_main = Gtk.Grid(orientation=VERTICAL) |
887 |
vbox_main = Gtk.Grid(orientation=VERTICAL) |
721 |
vbox_main.add(frm_kbd) |
888 |
vbox_main.add(frm_kbd) |
722 |
vbox_main.add(frm_color) |
889 |
vbox_main.add(frm_color) |
|
|
890 |
vbox_main.add(frm_mouse) |
723 |
hbox_main.add(vbox_main) |
891 |
hbox_main.add(vbox_main) |
724 |
|
892 |
|
725 |
box = prefs.get_content_area() |
893 |
box = prefs.get_content_area() |