Files

176 lines
6.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright (C) 2017, Tianjin KYLIN Information Technology Co., Ltd.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
from PyQt5.QtCore import QThread, pyqtSignal
from Xlib import X, XK, display
from Xlib.ext import record
from Xlib.protocol import rq
# python X global event, need python-xlib
class KeyServiceXlib(QThread):
local_dpy = display.Display()
record_dpy = display.Display()
main_window = None
ctx = None
is_modify_key_press = False
is_active = False
is_shown = False
press_time = 0
signal_switch_select = pyqtSignal(int)
signal_switch_confirm = pyqtSignal()
signal_switch_esc = pyqtSignal()
signal_switch_esc2 = pyqtSignal(int, int)
signal_tip_capslock = pyqtSignal()
signal_tip_numlock = pyqtSignal()
def __init__(self, main_window):
QThread.__init__(self)
self.main_window = main_window
self.signal_switch_select.connect(self.main_window.slot_switch_select)
self.signal_switch_confirm.connect(self.main_window.slot_switch_confirm)
self.signal_switch_esc.connect(self.main_window.slot_switch_esc)
self.signal_switch_esc2.connect(self.main_window.slot_switch_esc2)
self.signal_tip_capslock.connect(self.main_window.slot_tip_capslock)
self.signal_tip_numlock.connect(self.main_window.slot_tip_numlock)
def run(self):
self.check_record_extension()
# Create a recording context; we only want key and mouse events
self.ctx = self.record_dpy.record_create_context(
0,
[record.AllClients],
[{
'core_requests': (0, 0),
'core_replies': (0, 0),
'ext_requests': (0, 0, 0, 0),
'ext_replies': (0, 0, 0, 0),
'delivered_events': (0, 0),
'device_events': (X.KeyPress, X.MotionNotify),
'errors': (0, 0),
'client_started': False,
'client_died': False,
}])
# Enable the context; this only returns after a call to record_disable_context,
# while calling the callback function in the meantime
self.record_dpy.record_enable_context(self.ctx, self.record_callback)
# Finally free the context
self.record_dpy.record_free_context(self.ctx)
def check_record_extension(self):
if not self.record_dpy.has_extension("RECORD"):
print("RECORD extension not found")
sys.exit(1)
def lookup_keysym(self, keysym):
for name in dir(XK):
if name[:3] == "XK_" and getattr(XK, name) == keysym:
return name[3:]
else:
return keysym
def record_callback(self, reply):
if reply.category != record.FromServer:
return
if reply.client_swapped:
return
if not len(reply.data) or reply.data[0] < 2:
return
data = reply.data
while len(data):
event, data = rq.EventField(None).parse_binary_value(data, self.record_dpy.display, None, None)
if event.type in [X.KeyPress, X.KeyRelease, X.ButtonPress, X.ButtonRelease]:
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0)
if event.type == X.KeyPress:
if keysym == XK.XK_Super_L:
self.is_modify_key_press = True
self.press_time = 0
elif keysym == XK.XK_F3 or keysym == XK.XK_F7 or keysym == XK.XK_p:
if self.is_modify_key_press == True and self.is_shown == False:
self.is_active = True
self.press_time = self.press_time + 1
self.signal_switch_select.emit(1)
elif self.is_modify_key_press == True and self.is_shown == True:
self.signal_switch_select.emit(1)
# left button
elif keysym == XK.XK_Up and self.is_shown == True:
self.signal_switch_select.emit(2)
# right button
elif keysym == XK.XK_Down and self.is_shown == True:
self.signal_switch_select.emit(1)
# enter button
elif (keysym == XK.XK_KP_Enter or keysym == XK.XK_Return) and self.is_shown == True:
self.is_active = False
self.is_shown = False
self.signal_switch_confirm.emit()
else:
self.is_active = False
self.is_shown = False
self.signal_switch_esc.emit()
# dev, press ESC to exit
#if keysym == XK.XK_Escape:
# self.local_dpy.record_disable_context(self.ctx)
# self.local_dpy.flush()
# sys.exit(0)
elif event.type == X.KeyRelease:
if(keysym == XK.XK_Super_L):
self.is_modify_key_press = False
if self.is_active == True:
self.is_shown = True
if self.press_time > 1:
self.is_active = False
self.is_shown = False
self.signal_switch_confirm.emit()
if keysym == XK.XK_Caps_Lock:
self.signal_tip_capslock.emit()
if keysym == XK.XK_Num_Lock:
self.signal_tip_numlock.emit()
elif event.type == X.ButtonPress:
#self.is_active = False
#self.is_shown = False
rootPointX = event.root_x
rootPointY = event.root_y
self.signal_switch_esc2.emit(rootPointX, rootPointY)
def main():
# app = QApplication(sys.argv)
# sys.exit(app.exec_())
k = KeyServiceXlib(None)
k.run()
if __name__ == '__main__':
main()