Skip to content

Commit 3abf776

Browse files
Merge pull request #203 from ceccopierangiolieugenio/Multithreaded_input
Multithreaded input
2 parents 7e7c697 + 8a7fb6f commit 3abf776

File tree

11 files changed

+1031
-591
lines changed

11 files changed

+1031
-591
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ deploySandbox:
9797

9898
git checkout gh-pages
9999
cp tmp/sandbox/*.html sandbox
100+
cp -r tmp/sandbox/js sandbox
100101

101102
git submodule foreach git pull
102103
git add sandbox

TermTk/TTkCore/TTkTerm/input.py

Lines changed: 2 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -20,164 +20,5 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222

23-
__all__ = ['TTkInput']
24-
25-
import re
26-
from time import time
27-
28-
import platform
29-
30-
from ..drivers import TTkInputDriver
31-
32-
from TermTk.TTkCore.log import TTkLog
33-
from TermTk.TTkCore.constant import TTkK
34-
from TermTk.TTkCore.signal import pyTTkSignal
35-
from TermTk.TTkCore.TTkTerm.term import TTkTerm
36-
from TermTk.TTkCore.TTkTerm.inputkey import TTkKeyEvent
37-
from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent
38-
39-
40-
class TTkInput:
41-
inputEvent = pyTTkSignal(TTkKeyEvent, TTkMouseEvent)
42-
pasteEvent = pyTTkSignal(str)
43-
_pasteBuffer = ""
44-
_bracketedPaste = False
45-
_readInput = None
46-
_leftLastTime = 0
47-
_midLastTime = 0
48-
_rightLastTime = 0
49-
_leftTap = 0
50-
_midTap = 0
51-
_rightTap = 0
52-
_mouse_re = re.compile(r"\033\[<(\d+);(\d+);(\d+)([mM])")
53-
54-
class Mouse(int):
55-
ON = 0x01
56-
DIRECT = 0x02
57-
58-
@staticmethod
59-
def init(mouse:bool=False, directMouse:bool=False) -> None:
60-
TTkInput._readInput = TTkInputDriver()
61-
TTkTerm.setMouse(mouse, directMouse)
62-
63-
@staticmethod
64-
def close() -> None:
65-
TTkTerm.setMouse(False, False)
66-
if TTkInput._readInput:
67-
TTkInput._readInput.close()
68-
69-
@staticmethod
70-
def stop() -> None:
71-
pass
72-
73-
@staticmethod
74-
def cont() -> None:
75-
if TTkInput._readInput:
76-
TTkInput._readInput.cont()
77-
78-
@staticmethod
79-
def start() -> None:
80-
for stdinRead in TTkInput._readInput.read():
81-
TTkInput.key_process(stdinRead)
82-
TTkLog.debug("Close TTkInput")
83-
84-
@staticmethod
85-
def key_process(stdinRead:str) -> None:
86-
if TTkInput._bracketedPaste:
87-
if stdinRead.endswith("\033[201~"):
88-
TTkInput._pasteBuffer += stdinRead[:-6]
89-
TTkInput._bracketedPaste = False
90-
# due to the CRNL methos (don't ask me why) the terminal
91-
# is substituting all the \n with \r
92-
TTkInput.pasteEvent.emit(TTkInput._pasteBuffer.replace('\r','\n'))
93-
TTkInput._pasteBuffer = ""
94-
else:
95-
TTkInput._pasteBuffer += stdinRead
96-
return
97-
98-
mevt,kevt = None, None
99-
100-
if not stdinRead.startswith("\033[<"):
101-
# Key Event
102-
kevt = TTkKeyEvent.parse(stdinRead)
103-
else:
104-
# Mouse Event
105-
m = TTkInput._mouse_re.match(stdinRead)
106-
if not m:
107-
# TODO: Return Error
108-
hex = [f"0x{ord(x):02x}" for x in stdinRead]
109-
TTkLog.error("UNHANDLED (mouse): "+stdinRead.replace("\033","<ESC>") + " - "+",".join(hex))
110-
return None, None
111-
code = int(m.group(1))
112-
x = int(m.group(2))-1
113-
y = int(m.group(3))-1
114-
state = m.group(4)
115-
key = TTkMouseEvent.NoButton
116-
evt = TTkMouseEvent.Move
117-
tap = 0
118-
119-
def _checkTap(lastTime, tap):
120-
if state=="M":
121-
t = time()
122-
if (t-lastTime) < 0.4:
123-
return t, tap+1
124-
else:
125-
return t, 1
126-
return lastTime, tap
127-
128-
mod = TTkK.NoModifier
129-
if code & 0x10:
130-
code &= ~0x10
131-
mod |= TTkK.ControlModifier
132-
if code & 0x08:
133-
code &= ~0x08
134-
mod |= TTkK.AltModifier
135-
136-
if code == 0x00:
137-
TTkInput._leftLastTime, TTkInput._leftTap = _checkTap(TTkInput._leftLastTime, TTkInput._leftTap)
138-
tap = TTkInput._leftTap
139-
key = TTkMouseEvent.LeftButton
140-
evt = TTkMouseEvent.Press if state=="M" else TTkMouseEvent.Release
141-
elif code == 0x01:
142-
TTkInput._midLastTime, TTkInput._midTap = _checkTap(TTkInput._midLastTime, TTkInput._midTap)
143-
tap = TTkInput._midTap
144-
key = TTkMouseEvent.MidButton
145-
evt = TTkMouseEvent.Press if state=="M" else TTkMouseEvent.Release
146-
elif code == 0x02:
147-
TTkInput._rightLastTime, TTkInput._rightTap = _checkTap(TTkInput._rightLastTime, TTkInput._rightTap)
148-
tap = TTkInput._rightTap
149-
key = TTkMouseEvent.RightButton
150-
evt = TTkMouseEvent.Press if state=="M" else TTkMouseEvent.Release
151-
elif code == 0x20:
152-
key = TTkMouseEvent.LeftButton
153-
evt = TTkMouseEvent.Drag
154-
elif code == 0x21:
155-
key = TTkMouseEvent.MidButton
156-
evt = TTkMouseEvent.Drag
157-
elif code == 0x22:
158-
key = TTkMouseEvent.RightButton
159-
evt = TTkMouseEvent.Drag
160-
elif code == 0x40:
161-
key = TTkMouseEvent.Wheel
162-
evt = TTkMouseEvent.Up
163-
elif code == 0x41:
164-
key = TTkMouseEvent.Wheel
165-
evt = TTkMouseEvent.Down
166-
elif code == 0x23:
167-
evt = TTkMouseEvent.Move
168-
elif code == 0x27:
169-
mod |= TTkK.ShiftModifier
170-
evt = TTkMouseEvent.Move
171-
172-
mevt = TTkMouseEvent(x, y, key, evt, mod, tap, m.group(0).replace("\033", "<ESC>"))
173-
if kevt or mevt:
174-
TTkInput.inputEvent.emit(kevt, mevt)
175-
return
176-
177-
if stdinRead.startswith("\033[200~"):
178-
TTkInput._pasteBuffer = stdinRead[6:]
179-
TTkInput._bracketedPaste = True
180-
return
181-
182-
hex = [f"0x{ord(x):02x}" for x in stdinRead]
183-
TTkLog.error("UNHANDLED: "+stdinRead.replace("\033","<ESC>") + " - "+",".join(hex))
23+
# from .input_mono import *
24+
from .input_thread import *

TermTk/TTkCore/TTkTerm/input_mono.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
__all__ = ['TTkInput']
24+
25+
import re
26+
from time import time
27+
28+
import platform
29+
30+
from ..drivers import TTkInputDriver
31+
32+
from TermTk.TTkCore.log import TTkLog
33+
from TermTk.TTkCore.constant import TTkK
34+
from TermTk.TTkCore.signal import pyTTkSignal
35+
from TermTk.TTkCore.TTkTerm.term import TTkTerm
36+
from TermTk.TTkCore.TTkTerm.inputkey import TTkKeyEvent
37+
from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent
38+
39+
40+
class TTkInput:
41+
inputEvent = pyTTkSignal(TTkKeyEvent, TTkMouseEvent)
42+
pasteEvent = pyTTkSignal(str)
43+
_pasteBuffer = ""
44+
_bracketedPaste = False
45+
_readInput = None
46+
_leftLastTime = 0
47+
_midLastTime = 0
48+
_rightLastTime = 0
49+
_leftTap = 0
50+
_midTap = 0
51+
_rightTap = 0
52+
_mouse_re = re.compile(r"\033\[<(\d+);(\d+);(\d+)([mM])")
53+
54+
class Mouse(int):
55+
ON = 0x01
56+
DIRECT = 0x02
57+
58+
@staticmethod
59+
def init(mouse:bool=False, directMouse:bool=False) -> None:
60+
TTkInput._readInput = TTkInputDriver()
61+
TTkTerm.setMouse(mouse, directMouse)
62+
63+
@staticmethod
64+
def close() -> None:
65+
TTkTerm.setMouse(False, False)
66+
if TTkInput._readInput:
67+
TTkInput._readInput.close()
68+
69+
@staticmethod
70+
def stop() -> None:
71+
pass
72+
73+
@staticmethod
74+
def cont() -> None:
75+
if TTkInput._readInput:
76+
TTkInput._readInput.cont()
77+
78+
@staticmethod
79+
def start() -> None:
80+
for stdinRead in TTkInput._readInput.read():
81+
TTkInput.key_process(stdinRead)
82+
TTkLog.debug("Close TTkInput")
83+
84+
@staticmethod
85+
def key_process(stdinRead:str) -> None:
86+
if TTkInput._bracketedPaste:
87+
if stdinRead.endswith("\033[201~"):
88+
TTkInput._pasteBuffer += stdinRead[:-6]
89+
TTkInput._bracketedPaste = False
90+
# due to the CRNL methos (don't ask me why) the terminal
91+
# is substituting all the \n with \r
92+
TTkInput.pasteEvent.emit(TTkInput._pasteBuffer.replace('\r','\n'))
93+
TTkInput._pasteBuffer = ""
94+
else:
95+
TTkInput._pasteBuffer += stdinRead
96+
return
97+
98+
mevt,kevt = None, None
99+
100+
if not stdinRead.startswith("\033[<"):
101+
# Key Event
102+
kevt = TTkKeyEvent.parse(stdinRead)
103+
else:
104+
# Mouse Event
105+
m = TTkInput._mouse_re.match(stdinRead)
106+
if not m:
107+
# TODO: Return Error
108+
hex = [f"0x{ord(x):02x}" for x in stdinRead]
109+
TTkLog.error("UNHANDLED (mouse): "+stdinRead.replace("\033","<ESC>") + " - "+",".join(hex))
110+
return None, None
111+
code = int(m.group(1))
112+
x = int(m.group(2))-1
113+
y = int(m.group(3))-1
114+
state = m.group(4)
115+
key = TTkMouseEvent.NoButton
116+
evt = TTkMouseEvent.Move
117+
tap = 0
118+
119+
def _checkTap(lastTime, tap):
120+
if state=="M":
121+
t = time()
122+
if (t-lastTime) < 0.4:
123+
return t, tap+1
124+
else:
125+
return t, 1
126+
return lastTime, tap
127+
128+
mod = TTkK.NoModifier
129+
if code & 0x10:
130+
code &= ~0x10
131+
mod |= TTkK.ControlModifier
132+
if code & 0x08:
133+
code &= ~0x08
134+
mod |= TTkK.AltModifier
135+
136+
if code == 0x00:
137+
TTkInput._leftLastTime, TTkInput._leftTap = _checkTap(TTkInput._leftLastTime, TTkInput._leftTap)
138+
tap = TTkInput._leftTap
139+
key = TTkMouseEvent.LeftButton
140+
evt = TTkMouseEvent.Press if state=="M" else TTkMouseEvent.Release
141+
elif code == 0x01:
142+
TTkInput._midLastTime, TTkInput._midTap = _checkTap(TTkInput._midLastTime, TTkInput._midTap)
143+
tap = TTkInput._midTap
144+
key = TTkMouseEvent.MidButton
145+
evt = TTkMouseEvent.Press if state=="M" else TTkMouseEvent.Release
146+
elif code == 0x02:
147+
TTkInput._rightLastTime, TTkInput._rightTap = _checkTap(TTkInput._rightLastTime, TTkInput._rightTap)
148+
tap = TTkInput._rightTap
149+
key = TTkMouseEvent.RightButton
150+
evt = TTkMouseEvent.Press if state=="M" else TTkMouseEvent.Release
151+
elif code == 0x20:
152+
key = TTkMouseEvent.LeftButton
153+
evt = TTkMouseEvent.Drag
154+
elif code == 0x21:
155+
key = TTkMouseEvent.MidButton
156+
evt = TTkMouseEvent.Drag
157+
elif code == 0x22:
158+
key = TTkMouseEvent.RightButton
159+
evt = TTkMouseEvent.Drag
160+
elif code == 0x40:
161+
key = TTkMouseEvent.Wheel
162+
evt = TTkMouseEvent.Up
163+
elif code == 0x41:
164+
key = TTkMouseEvent.Wheel
165+
evt = TTkMouseEvent.Down
166+
elif code == 0x23:
167+
evt = TTkMouseEvent.Move
168+
elif code == 0x27:
169+
mod |= TTkK.ShiftModifier
170+
evt = TTkMouseEvent.Move
171+
172+
mevt = TTkMouseEvent(x, y, key, evt, mod, tap, m.group(0).replace("\033", "<ESC>"))
173+
if kevt or mevt:
174+
TTkInput.inputEvent.emit(kevt, mevt)
175+
return
176+
177+
if stdinRead.startswith("\033[200~"):
178+
TTkInput._pasteBuffer = stdinRead[6:]
179+
TTkInput._bracketedPaste = True
180+
return
181+
182+
hex = [f"0x{ord(x):02x}" for x in stdinRead]
183+
TTkLog.error("UNHANDLED: "+stdinRead.replace("\033","<ESC>") + " - "+",".join(hex))

0 commit comments

Comments
 (0)