24
24
from typing import Dict
25
25
from typing import Iterable
26
26
from typing import AsyncGenerator
27
+ from typing import Optional
27
28
from typing import Any
28
29
30
+ from .... import tools
29
31
from .... import aiomulti
30
32
31
33
from ....yamlconf import Option
43
45
44
46
45
47
# =====
46
- class Plugin (BaseHid ):
48
+ class Plugin (BaseHid ): # pylint: disable=too-many-instance-attributes
47
49
def __init__ ( # pylint: disable=super-init-not-called
48
50
self ,
49
51
keyboard : Dict [str , Any ],
50
52
mouse : Dict [str , Any ],
53
+ mouse_alt : Dict [str , Any ],
51
54
noop : bool ,
52
55
udc : str , # XXX: Not from options, see /kvmd/apps/kvmd/__init__.py for details
53
56
) -> None :
@@ -56,8 +59,25 @@ def __init__( # pylint: disable=super-init-not-called
56
59
57
60
self .__udc = UsbDeviceController (udc )
58
61
59
- self .__keyboard_proc = KeyboardProcess (udc = self .__udc , noop = noop , notifier = self .__notifier , ** keyboard )
60
- self .__mouse_proc = MouseProcess (udc = self .__udc , noop = noop , notifier = self .__notifier , ** mouse )
62
+ common = {
63
+ "udc" : self .__udc ,
64
+ "noop" : noop ,
65
+ "notifier" : self .__notifier ,
66
+ }
67
+
68
+ self .__keyboard_proc = KeyboardProcess (** common , ** keyboard )
69
+ self .__mouse_current = self .__mouse_proc = MouseProcess (** common , ** mouse )
70
+
71
+ self .__mouse_alt_proc : Optional [MouseProcess ] = None
72
+ self .__output_to_mouse : Dict [str , MouseProcess ] = {}
73
+ self .__mouse_to_output : Dict [MouseProcess , str ] = {}
74
+ if mouse_alt ["device_path" ]:
75
+ self .__mouse_alt_proc = MouseProcess (absolute = (not mouse ["absolute" ]), ** common , ** mouse_alt )
76
+ self .__output_to_mouse = {
77
+ "usb" : (self .__mouse_proc if mouse ["absolute" ] else self .__mouse_alt_proc ),
78
+ "usb_rel" : (self .__mouse_alt_proc if mouse ["absolute" ] else self .__mouse_proc ),
79
+ }
80
+ self .__mouse_to_output = tools .swapped_kvs (self .__output_to_mouse )
61
81
62
82
@classmethod
63
83
def get_plugin_options (cls ) -> Dict :
@@ -76,18 +96,27 @@ def get_plugin_options(cls) -> Dict:
76
96
"absolute" : Option (True , type = valid_bool ),
77
97
"horizontal_wheel" : Option (True , type = valid_bool ),
78
98
},
99
+ "mouse_alt" : {
100
+ "device" : Option ("" , type = valid_abs_path , if_empty = "" , unpack_as = "device_path" ),
101
+ "select_timeout" : Option (0.1 , type = valid_float_f01 ),
102
+ "queue_timeout" : Option (0.1 , type = valid_float_f01 ),
103
+ "write_retries" : Option (150 , type = valid_int_f1 ),
104
+ # No absolute option here, initialized by (not mouse.absolute)
105
+ "horizontal_wheel" : Option (True , type = valid_bool ),
106
+ },
79
107
"noop" : Option (False , type = valid_bool ),
80
108
}
81
109
82
110
def sysprep (self ) -> None :
83
111
self .__udc .find ()
84
112
self .__keyboard_proc .start ()
85
113
self .__mouse_proc .start ()
114
+ if self .__mouse_alt_proc :
115
+ self .__mouse_alt_proc .start ()
86
116
87
117
async def get_state (self ) -> Dict :
88
118
keyboard_state = await self .__keyboard_proc .get_state ()
89
- mouse_state = await self .__mouse_proc .get_state ()
90
- outputs : Dict = {"available" : [], "active" : "" }
119
+ mouse_state = await self .__mouse_current .get_state ()
91
120
return {
92
121
"online" : True ,
93
122
"busy" : False ,
@@ -99,9 +128,15 @@ async def get_state(self) -> Dict:
99
128
"scroll" : keyboard_state ["scroll" ],
100
129
"num" : keyboard_state ["num" ],
101
130
},
102
- "outputs" : outputs ,
131
+ "outputs" : {"available" : [], "active" : "" },
132
+ },
133
+ "mouse" : {
134
+ "outputs" : {
135
+ "available" : list (self .__output_to_mouse ),
136
+ "active" : (self .__mouse_to_output [self .__mouse_current ] if self .__mouse_alt_proc else "" ),
137
+ },
138
+ ** mouse_state ,
103
139
},
104
- "mouse" : {** mouse_state , "outputs" : outputs },
105
140
}
106
141
107
142
async def poll_state (self ) -> AsyncGenerator [Dict , None ]:
@@ -115,31 +150,43 @@ async def poll_state(self) -> AsyncGenerator[Dict, None]:
115
150
116
151
async def reset (self ) -> None :
117
152
self .__keyboard_proc .send_reset_event ()
118
- self .__mouse_proc .send_reset_event ()
153
+ self .__mouse_current .send_reset_event ()
119
154
120
155
async def cleanup (self ) -> None :
121
156
try :
122
157
self .__keyboard_proc .cleanup ()
123
158
finally :
124
- self .__mouse_proc .cleanup ()
159
+ try :
160
+ self .__mouse_proc .cleanup ()
161
+ finally :
162
+ if self .__mouse_alt_proc :
163
+ self .__mouse_alt_proc .cleanup ()
125
164
126
165
# =====
127
166
128
167
def send_key_events (self , keys : Iterable [Tuple [str , bool ]]) -> None :
129
168
self .__keyboard_proc .send_key_events (keys )
130
169
131
170
def send_mouse_button_event (self , button : str , state : bool ) -> None :
132
- self .__mouse_proc .send_button_event (button , state )
171
+ self .__mouse_current .send_button_event (button , state )
133
172
134
173
def send_mouse_move_event (self , to_x : int , to_y : int ) -> None :
135
- self .__mouse_proc .send_move_event (to_x , to_y )
174
+ self .__mouse_current .send_move_event (to_x , to_y )
136
175
137
176
def send_mouse_relative_event (self , delta_x : int , delta_y : int ) -> None :
138
- self .__mouse_proc .send_relative_event (delta_x , delta_y )
177
+ self .__mouse_current .send_relative_event (delta_x , delta_y )
139
178
140
179
def send_mouse_wheel_event (self , delta_x : int , delta_y : int ) -> None :
141
- self .__mouse_proc .send_wheel_event (delta_x , delta_y )
180
+ self .__mouse_current .send_wheel_event (delta_x , delta_y )
181
+
182
+ def set_params (self , keyboard_output : Optional [str ]= None , mouse_output : Optional [str ]= None ) -> None :
183
+ _ = keyboard_output
184
+ if mouse_output != self .__mouse_to_output [self .__mouse_current ]:
185
+ if mouse_output in self .__output_to_mouse :
186
+ self .__mouse_current .send_clear_event ()
187
+ self .__mouse_current = self .__output_to_mouse [mouse_output ]
188
+ self .__notifier .notify ()
142
189
143
190
def clear_events (self ) -> None :
144
191
self .__keyboard_proc .send_clear_event ()
145
- self .__mouse_proc .send_clear_event ()
192
+ self .__mouse_current .send_clear_event ()
0 commit comments