@@ -120,21 +120,6 @@ namespace Send::Type::Internal {
120120 bool unknown : 3 ;
121121 };
122122
123- struct MouseReport {
124- union {
125- MouseButton button;
126- Byte button_byte;
127- };
128- int8_t x;
129- int8_t y;
130- Byte unknown_W; // #TODO: Wheel?
131- Byte unknown_T; // #TODO: T?
132- private:
133- void assert_size () {
134- static_assert (sizeof MouseReport == 5 );
135- }
136- };
137-
138123 private:
139124 [[deprecated]] static LONG compensate_win_acceleration (LONG x) {
140125 // #TODO
@@ -167,40 +152,42 @@ namespace Send::Type::Internal {
167152 return x;
168153 }
169154
170- static int8_t compensate_lgs_acceleration (int8_t x) {
171- int8_t abs_x = abs (x);
172- int8_t sign = x > 0 ? 1 : -1 ;
155+ template <typename T>
156+ static T compensate_lgs_acceleration (T x) {
157+ T abs_x = abs (x);
158+ T sign = x > 0 ? 1 : -1 ;
173159
174160 if (abs_x <= 5 )
175161 return x;
176162 else if (abs_x <= 10 )
177163 return sign * (abs_x + 1 );
178164 else
179- return sign * (int8_t )round (0.6156218196 * abs_x + 4.45777444629 );
165+ return sign * (T )round (0.6156218196 * abs_x + 4.45777444629 );
180166 }
181167
182168 public:
183- bool report_mouse (MouseReport report, int8_t compensate_switch) const {
169+ template <class ReportType >
170+ bool report_mouse (ReportType report, int8_t compensate_switch) const {
184171 constexpr DWORD IOCTL_BUSENUM_PLAY_MOUSEMOVE = 0x2A2010 ;
185172 DWORD bytes_returned;
186173
187174 if (has_acceleration && (report.x || report.y )) {
188- MouseReport report11 = report;
175+ ReportType report11 = report;
189176 report11.x = report11.y = compensate_switch;
190- DeviceIoControl (device, IOCTL_BUSENUM_PLAY_MOUSEMOVE, &report11, sizeof MouseReport , nullptr , 0 , &bytes_returned, nullptr );
177+ DeviceIoControl (device, IOCTL_BUSENUM_PLAY_MOUSEMOVE, &report11, sizeof (ReportType) , nullptr , 0 , &bytes_returned, nullptr );
191178
192179 report.x = compensate_lgs_acceleration (report.x );
193180 report.y = compensate_lgs_acceleration (report.y );
194181 }
195182
196183 if constexpr (debug) {
197- bool success = DeviceIoControl (device, IOCTL_BUSENUM_PLAY_MOUSEMOVE, &report, sizeof MouseReport , nullptr , 0 , &bytes_returned, nullptr );
184+ bool success = DeviceIoControl (device, IOCTL_BUSENUM_PLAY_MOUSEMOVE, &report, sizeof (ReportType) , nullptr , 0 , &bytes_returned, nullptr );
198185 DWORD error = GetLastError ();
199186 DebugOStream () << L" report_mouse: " << report.button_byte << L" , " << report.x << L" , " << report.y << L" . "
200187 << success << L" , " << error << std::endl;
201188 return success;
202189 }
203- return DeviceIoControl (device, IOCTL_BUSENUM_PLAY_MOUSEMOVE, &report, sizeof MouseReport , nullptr , 0 , &bytes_returned, nullptr );
190+ return DeviceIoControl (device, IOCTL_BUSENUM_PLAY_MOUSEMOVE, &report, sizeof (ReportType) , nullptr , 0 , &bytes_returned, nullptr );
204191 }
205192
206193 struct KeyboardReport {
@@ -229,8 +216,22 @@ namespace Send::Type::Internal {
229216 }
230217 };
231218
232- class Logitech final : public VirtualKeyStates {
233- LogitechDriver driver;
219+ class Logitech : public VirtualKeyStates {
220+ struct MouseReport {
221+ union {
222+ LogitechDriver::MouseButton button;
223+ Byte button_byte;
224+ };
225+ int8_t x;
226+ int8_t y;
227+ Byte wheel;
228+ Byte unknown_T; // #TODO: T?
229+ private:
230+ void assert_size () {
231+ static_assert (sizeof MouseReport == 5 );
232+ }
233+ };
234+
234235 public:
235236 Logitech () : VirtualKeyStates(keyboard_report.modifiers, keyboard_mutex) {}
236237
@@ -242,44 +243,70 @@ namespace Send::Type::Internal {
242243 driver.destroy ();
243244 }
244245
245- private :
246- LogitechDriver::MouseReport mouse_report{} ;
246+ protected :
247+ LogitechDriver driver ;
247248 uint8_t compensate_switch = -1 ;
248249 std::mutex mouse_mutex;
249250
251+ template <typename T>
252+ static constexpr T max_value ()
253+ {
254+ if constexpr (std::is_same_v<T, int8_t >)
255+ return INT8_MAX;
256+ else
257+ {
258+ static_assert (std::is_same_v<T, int16_t >, " Unknown type" );
259+ return INT16_MAX;
260+ }
261+ }
262+
250263 public:
251264 uint32_t send_mouse_input (const INPUT inputs[], uint32_t n) override {
252- update_screen_resolution ();
253265 return Base::send_mouse_input (inputs, n);
254266 }
255267
256- bool send_mouse_input (const MOUSEINPUT& mi) override {
268+ virtual bool send_mouse_input (const MOUSEINPUT& mi) override {
269+ return send_mouse_report<MouseReport>(mi);
270+ }
271+
272+ template <class ReportType >
273+ bool send_mouse_report (const MOUSEINPUT& mi)
274+ {
257275 std::lock_guard lock (mouse_mutex);
258276
259277 if constexpr (debug)
260278 DebugOStream () << L" send_mouse_input: " << mi.dwFlags << L" , " << mi.dx << L" , " << mi.dy << std::endl;
261279
280+ ReportType mouse_report{};
281+
262282 // #TODO: move and then click, or click and then move? former?
263283
264- // #TODO: MOUSEEVENTF_MOVE_NOCOALESCE, MOUSEEVENTF_VIRTUALDESK
284+ // #TODO: MOUSEEVENTF_MOVE_NOCOALESCE
265285 if (mi.dwFlags & MOUSEEVENTF_MOVE) {
266- POINT move { mi.dx , mi.dy };
286+ POINT move{ mi.dx , mi.dy };
267287 if (mi.dwFlags & MOUSEEVENTF_ABSOLUTE) {
268- mouse_absolute_to_screen (move);
288+ if (mi.dwFlags & MOUSEEVENTF_VIRTUALDESK)
289+ mouse_virtual_desk_absolute_to_screen (move);
290+ else
291+ mouse_absolute_to_screen (move);
269292 mouse_screen_to_relative (move);
270293 }
271294
272- while (abs (move.x ) > 127 || abs (move.y ) > 127 ) {
273- if (abs (move.x ) > 127 ) {
274- mouse_report.x = move.x > 0 ? 127 : -127 ;
295+ static_assert (std::is_same_v<decltype (mouse_report.x ), decltype (mouse_report.y )>);
296+ using CoordinatesType = decltype (mouse_report.x );
297+ constexpr auto maxValue = max_value<CoordinatesType>();
298+
299+ while (abs (move.x ) > maxValue || abs (move.y ) > maxValue) {
300+ if (abs (move.x ) > maxValue) {
301+ mouse_report.x = move.x > 0 ? maxValue : -maxValue;
275302 move.x -= mouse_report.x ;
276303 }
277304 else {
278305 mouse_report.x = 0 ;
279306 }
280307
281- if (abs (move.y ) > 127 ) {
282- mouse_report.y = move.y > 0 ? 127 : -127 ;
308+ if (abs (move.y ) > maxValue ) {
309+ mouse_report.y = move.y > 0 ? maxValue : -maxValue ;
283310 move.y -= mouse_report.y ;
284311 }
285312 else {
@@ -289,13 +316,17 @@ namespace Send::Type::Internal {
289316 driver.report_mouse (mouse_report, compensate_switch = -compensate_switch);
290317 }
291318
292- mouse_report.x = (uint8_t )move.x ;
293- mouse_report.y = (uint8_t )move.y ;
319+ mouse_report.x = (CoordinatesType )move.x ;
320+ mouse_report.y = (CoordinatesType )move.y ;
294321 } else {
295322 mouse_report.x = 0 ;
296323 mouse_report.y = 0 ;
297324 }
298325
326+ if (mi.dwFlags & MOUSEEVENTF_WHEEL) { // TODO MOUSEEVENTF_HWHEEL
327+ mouse_report.wheel = std::bit_cast<int32_t >(mi.mouseData ) > 0 ? 1 : -1 ;
328+ }
329+
299330#define CODE_GENERATE (down, up, member ) \
300331 if (mi.dwFlags & down || mi.dwFlags & up) \
301332 mouse_report.button .##member = mi.dwFlags & down;
@@ -352,4 +383,29 @@ namespace Send::Type::Internal {
352383 }
353384#pragma warning(suppress : 4250) // 'class1' : inherits 'class2::member' via dominance
354385 };
386+
387+ // new Ghub send type, same as Logitech but with another types in MouseReport struct
388+ class LogitechGHubNew : public Logitech {
389+ struct MouseReport {
390+ union {
391+ LogitechDriver::MouseButton button;
392+ Byte button_byte;
393+ };
394+ int16_t x;
395+ int16_t y;
396+ Byte wheel;
397+ Byte unknown_T; // #TODO: T?
398+ private:
399+ void assert_size () {
400+ static_assert (sizeof MouseReport == 8 );
401+ }
402+ };
403+
404+ public:
405+ LogitechGHubNew () = default ;
406+
407+ bool send_mouse_input (const MOUSEINPUT& mi) override {
408+ return Logitech::send_mouse_report<MouseReport>(mi);
409+ }
410+ };
355411}
0 commit comments