special_input_device 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b44c0a6bb776cfd6e6119e3bcfdbf996c4f171bc
4
- data.tar.gz: f7fd051facd9a1e21472ab1d20e61a052d0276e2
3
+ metadata.gz: be0868fbceeb98ef86c51bf95099a3ba60e6ee80
4
+ data.tar.gz: 726061d79c40698e7bc9d09f3f2dd61fc564f2fa
5
5
  SHA512:
6
- metadata.gz: 3f46cf44515c0ee093b00a3527cefe3776ddcddfa393a4f56e48ce90dd810400128dee1d3ea8e50ae44fc70bb5014ba269b1343766249526126d32767bcf6ee7
7
- data.tar.gz: c131d93e96fc5e5193ba57a7b57ef88e99dce999d7faca7aeb7bb37798e996660467013a3087f5682391ba96452220c300e05d13be85aca6b5d0a9cc3f6b002e
6
+ metadata.gz: 94035fa8ecb71c41153232256ad261ecc4436aaef1a0f8fb721997c8b022c70758a10942d366084e8ba09894d6feaefde4ad5ae9caa080a5d1f740db063f80c3
7
+ data.tar.gz: d3eec4a2ba8c5f598a9c888a56b2529990fd1b9cb924cb3e7df607c0bac01a395ae95702ce03618ce5bdc59c0e006be9c05bde33a54d16d48637cb74a6fa0508
@@ -272,7 +272,7 @@ static VALUE ruby__load(VALUE self, VALUE path) {
272
272
  case 24:
273
273
  case 32: {
274
274
  BYTE *cPixel;
275
- INT cBytePrePixel = cDIBHeader.v1.biBitCount / 8;
275
+ UINT cBytePrePixel = (UINT) cDIBHeader.v1.biBitCount / 8;
276
276
  LONG cValue;
277
277
  LONG cMask;
278
278
  LONG cBuffer;
@@ -354,8 +354,8 @@ static VALUE ruby_initialize(VALUE self, VALUE width, VALUE height) {
354
354
  UINT cWidth = NUM2UINT(width);
355
355
  UINT cHeight = NUM2UINT(height);
356
356
  SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
357
- INT cT0;
358
- INT cT1;
357
+ UINT cT0;
358
+ UINT cT1;
359
359
  cData->height = cHeight;
360
360
  cData->pixelTable = ALLOC_N(LPRGBQUAD, cHeight);
361
361
  for (cT0 = 0; cT0 < cHeight; cT0++) {
@@ -389,7 +389,7 @@ static VALUE ruby_save(VALUE self, VALUE path) {
389
389
  BITMAPFILEHEADER cFileHeader;
390
390
  BITMAPV5HEADER cDIBHeader;
391
391
  DWORD cByteWritten;
392
- INT cT;
392
+ UINT cT;
393
393
  cFile = CreateFile(cPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
394
394
  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
395
395
  if (cFile == INVALID_HANDLE_VALUE)
@@ -453,7 +453,7 @@ static VALUE ruby_OS_CS(VALUE self, VALUE x, VALUE y) {
453
453
  rb_raise(rb_eRangeError, "The image only has %d columns. x = %d is out of range.", cWidth, cX);
454
454
  if (cX < 0)
455
455
  cX += cWidth;
456
- if (cY < (INT) -cData->height || cY >= cData->height)
456
+ if (cY < (INT) -cData->height || cY >= (INT) cData->height)
457
457
  rb_raise(rb_eRangeError, "The image only has %d rows. y = %d is out of range.", cData->height, cY);
458
458
  if (cY < 0)
459
459
  cY += cData->height;
@@ -477,7 +477,7 @@ static VALUE ruby_OS_CS_EQ(VALUE self, VALUE x, VALUE y, VALUE value) {
477
477
  rb_raise(rb_eRangeError, "The image only has %d columns. x = %d is out of range.", cWidth, cX);
478
478
  if (cX < 0)
479
479
  cX += cWidth;
480
- if (cY < (INT) -cData->height || cY >= cData->height)
480
+ if (cY < (INT) -cData->height || cY >= (INT) cData->height)
481
481
  rb_raise(rb_eRangeError, "The image only has %d rows. y = %d is out of range.", cData->height, cY);
482
482
  if (cY < 0)
483
483
  cY += cData->height;
@@ -496,7 +496,7 @@ static VALUE ruby_try_get(VALUE self, VALUE x, VALUE y) {
496
496
  INT cX = NUM2INT(x);
497
497
  INT cY = NUM2INT(y);
498
498
  SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
499
- if (cX < -cWidth || cX >= cWidth || cY < (INT) -cData->height || cY >= cData->height)
499
+ if (cX < -cWidth || cX >= cWidth || cY < (INT) -cData->height || cY >= (INT) cData->height)
500
500
  return Qnil;
501
501
  if (cX < 0)
502
502
  cX += cWidth;
@@ -518,7 +518,7 @@ static VALUE ruby_try_set(VALUE self, VALUE x, VALUE y, VALUE value) {
518
518
  INT cY = NUM2INT(y);
519
519
  RGBQUAD cVALUE = ruby___color_to_rgb_quad(value);
520
520
  SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
521
- if (cX >= -cWidth && cX < cWidth && cY >= (INT) -cData->height && cY < cData->height) {
521
+ if (cX >= -cWidth && cX < cWidth && cY >= (INT) -cData->height && cY < (INT) cData->height) {
522
522
  if (cX < 0)
523
523
  cX += cWidth;
524
524
  if (cY < 0)
@@ -574,7 +574,7 @@ static VALUE ruby_each_row(VARIABLE_ARGUMENTS_C) {
574
574
  SCAN_ARGUMENTS("&", &block);
575
575
  if (RTEST(block)) {
576
576
  UINT cT0;
577
- UINT cT1;
577
+ LONG cT1;
578
578
  VALUE *cRow = ALLOC_N(VALUE, cWidth);
579
579
  for (cT0 = 0; cT0 < cData->height; cT0++) {
580
580
  for (cT1 = 0; cT1 < cWidth; cT1++) {
@@ -602,7 +602,7 @@ static VALUE ruby_each_row(VARIABLE_ARGUMENTS_C) {
602
602
  static VALUE ruby_each_column(VARIABLE_ARGUMENTS_C) {
603
603
  VALUE block;
604
604
  SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
605
- LONG cWidth = NUM2LONG(rb_iv_get(self, "@width"));
605
+ UINT cWidth = NUM2UINT(rb_iv_get(self, "@width"));
606
606
  SCAN_ARGUMENTS("&", &block);
607
607
  if (RTEST(block)) {
608
608
  UINT cT0;
@@ -637,15 +637,15 @@ static VALUE ruby_each_in_row(VARIABLE_ARGUMENTS_C) {
637
637
  VALUE block;
638
638
  SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
639
639
  INT cY;
640
- LONG cWidth = NUM2LONG(rb_iv_get(self, "@width"));
640
+ INT cWidth = NUM2INT(rb_iv_get(self, "@width"));
641
641
  SCAN_ARGUMENTS("1&", &y, &block);
642
642
  cY = NUM2INT(y);
643
- if (cY < (INT) -cData->height || cY >= cData->height)
643
+ if (cY < (INT) -cData->height || cY >= (INT) cData->height)
644
644
  rb_raise(rb_eRangeError, "The image only has %d rows. y = %d is out of range.", cData->height, cY);
645
645
  if (cY < 0)
646
646
  cY += cWidth;
647
647
  if (RTEST(block)) {
648
- UINT cT;
648
+ INT cT;
649
649
  VALUE cPixel;
650
650
  for (cT = 0; cT < cWidth; cT++) {
651
651
  cPixel = ruby___color_new_from_rgb_quad(&PixelAt(cT, cY));
@@ -1,5 +1,7 @@
1
1
  #include "special_input_device.h"
2
2
  #include "_vendor__interception.h"
3
+ #include "keyboard.h"
4
+ #include "mouse.h"
3
5
 
4
6
  #define MAXIMUM_HARDWARE_IDENTIFIER_LENGTH 512
5
7
 
@@ -7,9 +9,13 @@ typedef struct {
7
9
  InterceptionContext context;
8
10
  InterceptionDevice keyboard;
9
11
  InterceptionDevice mouse;
12
+ BOOL lockMouse;
13
+ BOOL lockKeyboard;
10
14
  } SID_INTERCEPTION_DATA;
11
15
 
12
16
  static SID_INTERCEPTION_DATA *cData;
17
+ static BOOL cCustomExitKeysDown[CUSTOM_EXIT_KEY_SIZE] = {FALSE};
18
+ static BOOL cDefaultExitKeysDown[DEFAULT_EXIT_KEY_SIZE] = {FALSE};
13
19
 
14
20
  inline InterceptionContext ruby___interception_get_context() {
15
21
  return cData->context;
@@ -18,12 +24,12 @@ inline InterceptionContext ruby___interception_get_context() {
18
24
  InterceptionDevice ruby___interception_find_keyboard() {
19
25
  TCHAR cHardwareIdentifier[MAXIMUM_HARDWARE_IDENTIFIER_LENGTH];
20
26
  if (interceptionGetHardwareIdentifier(cData->context, cData->keyboard, cHardwareIdentifier,
21
- MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
27
+ MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
22
28
  return cData->keyboard;
23
29
  for (cData->keyboard = INTERCEPTION_KEYBOARD(0);
24
30
  cData->keyboard < INTERCEPTION_KEYBOARD(INTERCEPTION_MAX_KEYBOARD); cData->keyboard++) {
25
31
  if (interceptionGetHardwareIdentifier(cData->context, cData->keyboard, cHardwareIdentifier,
26
- MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
32
+ MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
27
33
  return cData->keyboard;
28
34
  }
29
35
  rb_raise(rb_eRuntimeError, "Can not find any keyboard connected. Make sure you have at least one keyboard connected"
@@ -34,12 +40,12 @@ InterceptionDevice ruby___interception_find_keyboard() {
34
40
  InterceptionDevice ruby___interception_find_mouse() {
35
41
  TCHAR cHardwareIdentifier[MAXIMUM_HARDWARE_IDENTIFIER_LENGTH];
36
42
  if (interceptionGetHardwareIdentifier(cData->context, cData->mouse, cHardwareIdentifier,
37
- MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
43
+ MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
38
44
  return cData->mouse;
39
45
  for (cData->mouse = INTERCEPTION_MOUSE(0);
40
46
  cData->mouse < INTERCEPTION_MOUSE(INTERCEPTION_MAX_MOUSE); cData->mouse++) {
41
47
  if (interceptionGetHardwareIdentifier(cData->context, cData->mouse, cHardwareIdentifier,
42
- MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
48
+ MAXIMUM_HARDWARE_IDENTIFIER_LENGTH))
43
49
  return cData->mouse;
44
50
  }
45
51
  rb_raise(rb_eRuntimeError, "Can not find any mouse connected. Make sure you have at least one keyboard connected"
@@ -47,15 +53,152 @@ InterceptionDevice ruby___interception_find_mouse() {
47
53
  " interception mode.");
48
54
  }
49
55
 
56
+ VOID ruby___interception_exit_keys_updated() {
57
+ UINT *cExitKeys = ruby___special_input_device_get_exit_keys();
58
+ INT cT;
59
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++)
60
+ cCustomExitKeysDown[cT] = !cExitKeys[cT];
61
+ }
62
+
50
63
  static VOID callback_interception_free(SID_INTERCEPTION_DATA *cData) {
51
64
  interceptionDestroyContext(cData->context);
52
65
  xfree(cData);
53
66
  }
54
67
 
55
68
  static VALUE ruby__alloc(VALUE self) {
56
- VALUE instance = Data_Make_Struct(self, SID_INTERCEPTION_DATA, NULL, callback_interception_free, cData);
57
- cData->context = interceptionCreateContext();
58
- return instance;
69
+ return NEW_DATA_OBJECT(self, SID_INTERCEPTION_DATA, NULL, callback_interception_free);
70
+ }
71
+
72
+ static VALUE ruby_initialize_thread() {
73
+ InterceptionStroke cStroke;
74
+ InterceptionDevice cDevice;
75
+ UINT *cCustomExitKeys;
76
+ INT cT;
77
+ interceptionSetFilter(cData->context, interceptionIsKeyboard, INTERCEPTION_FILTER_KEY_ALL);
78
+ interceptionSetFilter(cData->context, interceptionIsMouse, INTERCEPTION_FILTER_MOUSE_ALL);
79
+ while (TRUE) {
80
+ cDevice = interceptionWait(cData->context);
81
+ if (!interceptionReceive(cData->context, cDevice, &cStroke, 1))
82
+ break;
83
+ cCustomExitKeys = ruby___special_input_device_get_exit_keys();
84
+ if (interceptionIsMouse(cDevice)) {
85
+ InterceptionMouseStroke *cMouseStroke = (InterceptionMouseStroke *) &cStroke;
86
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
87
+ switch (cCustomExitKeys[cT]) {
88
+ case VK_LBUTTON:
89
+ switch (cMouseStroke->state) {
90
+ case INTERCEPTION_MOUSE_BUTTON_1_DOWN:
91
+ cCustomExitKeysDown[cT] = TRUE;
92
+ break;
93
+ case INTERCEPTION_MOUSE_BUTTON_1_UP:
94
+ cCustomExitKeysDown[cT] = FALSE;
95
+ break;
96
+ default:
97
+ break;
98
+ }
99
+ break;
100
+ case VK_RBUTTON:
101
+ switch (cMouseStroke->state) {
102
+ case INTERCEPTION_MOUSE_BUTTON_2_DOWN:
103
+ cCustomExitKeysDown[cT] = TRUE;
104
+ break;
105
+ case INTERCEPTION_MOUSE_BUTTON_2_UP:
106
+ cCustomExitKeysDown[cT] = FALSE;
107
+ break;
108
+ default:
109
+ break;
110
+ }
111
+ break;
112
+ case VK_MBUTTON:
113
+ switch (cMouseStroke->state) {
114
+ case INTERCEPTION_MOUSE_BUTTON_3_DOWN:
115
+ cCustomExitKeysDown[cT] = TRUE;
116
+ break;
117
+ case INTERCEPTION_MOUSE_BUTTON_3_UP:
118
+ cCustomExitKeysDown[cT] = FALSE;
119
+ break;
120
+ default:
121
+ break;
122
+ }
123
+ break;
124
+ case VK_XBUTTON1:
125
+ switch (cMouseStroke->state) {
126
+ case INTERCEPTION_MOUSE_BUTTON_4_DOWN:
127
+ cCustomExitKeysDown[cT] = TRUE;
128
+ break;
129
+ case INTERCEPTION_MOUSE_BUTTON_4_UP:
130
+ cCustomExitKeysDown[cT] = FALSE;
131
+ break;
132
+ default:
133
+ break;
134
+ }
135
+ break;
136
+ case VK_XBUTTON2:
137
+ switch (cMouseStroke->state) {
138
+ case INTERCEPTION_MOUSE_BUTTON_5_DOWN:
139
+ cCustomExitKeysDown[cT] = TRUE;
140
+ break;
141
+ case INTERCEPTION_MOUSE_BUTTON_5_UP:
142
+ cCustomExitKeysDown[cT] = FALSE;
143
+ break;
144
+ default:
145
+ break;
146
+ }
147
+ break;
148
+ default:
149
+ break;
150
+ }
151
+ }
152
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
153
+ if (!cCustomExitKeysDown[cT])
154
+ break;
155
+ }
156
+ if (cT == CUSTOM_EXIT_KEY_SIZE)
157
+ rb_raise(rb_eSystemExit, "Exit keys pressed.");
158
+ if (!ruby___mouse_is_locked())
159
+ interceptionSend(cData->context, cDevice, (InterceptionStroke const *) &cStroke, 1);
160
+ }
161
+ if (interceptionIsKeyboard(cDevice)) {
162
+ InterceptionKeyStroke *cKeyStroke = (InterceptionKeyStroke *) (InterceptionMouseStroke *) &cStroke;
163
+ for (cT = 0; cT < DEFAULT_EXIT_KEY_SIZE; cT++) {
164
+ if (cKeyStroke->code == MapVirtualKeyA(cDefaultExitKeys[cT], MAPVK_VK_TO_VSC))
165
+ cDefaultExitKeysDown[cT] = !(cKeyStroke->state & INTERCEPTION_KEY_UP);
166
+ }
167
+ for (cT = 0; cT < DEFAULT_EXIT_KEY_SIZE; cT++) {
168
+ if (!cDefaultExitKeysDown[cT])
169
+ break;
170
+ }
171
+ if (cT == DEFAULT_EXIT_KEY_SIZE)
172
+ rb_raise(rb_eSystemExit, "Exit keys pressed.");
173
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
174
+ if (cKeyStroke->code == MapVirtualKeyA(cCustomExitKeys[cT], MAPVK_VK_TO_VSC))
175
+ cCustomExitKeysDown[cT] = !(cKeyStroke->state & INTERCEPTION_KEY_UP);
176
+ }
177
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
178
+ if (!cCustomExitKeysDown[cT])
179
+ break;
180
+ }
181
+ if (cT == CUSTOM_EXIT_KEY_SIZE)
182
+ rb_raise(rb_eSystemExit, "Exit keys pressed.");
183
+ if (!ruby___keyboard_is_locked())
184
+ interceptionSend(cData->context, cDevice, (InterceptionStroke const *) &cStroke, 1);
185
+ }
186
+ }
187
+ return Qnil;
188
+ }
189
+
190
+ /*
191
+ * @!visibility private
192
+ */
193
+ static VALUE ruby_initialize(VALUE self) {
194
+ cData = GET_SELF_DATA_OBJECT();
195
+ cData->context = interceptionCreateContext();
196
+ cData->mouse = 0;
197
+ cData->keyboard = 0;
198
+ cData->lockMouse = FALSE;
199
+ cData->lockKeyboard = FALSE;
200
+ rb_thread_create(ruby_initialize_thread, NULL);
201
+ return Qnil;
59
202
  }
60
203
 
61
204
  VOID Init_interception() {
@@ -71,6 +214,7 @@ VOID Init_interception() {
71
214
  */
72
215
  VALUE specialInputDevice_interception = rb_define_class_under(specialInputDevice, "Interception", rb_cData);
73
216
  rb_define_alloc_func(specialInputDevice_interception, (rb_alloc_func_t) ruby__alloc);
217
+ rb_define_method(specialInputDevice_interception, "initialize", ruby_initialize, 0);
74
218
 
75
219
  rb_require("singleton");
76
220
  singleton = RUBY_MODULE_CONST_GET(rb_mKernel, rb_intern_const("Singleton"));
@@ -10,4 +10,6 @@ InterceptionDevice ruby___interception_find_keyboard();
10
10
 
11
11
  InterceptionDevice ruby___interception_find_mouse();
12
12
 
13
+ VOID ruby___interception_exit_keys_updated();
14
+
13
15
  #endif //SPECIAL_INPUT_DEVICE_INTERCEPTION_H
@@ -1,6 +1,50 @@
1
1
  #include "special_input_device.h"
2
2
  #include "interception.h"
3
3
 
4
+ static BOOL cLocked;
5
+
6
+ inline BOOL ruby___keyboard_is_locked() {
7
+ return cLocked;
8
+ }
9
+
10
+ /*
11
+ * Lock the keyboard.
12
+ * @return [Module] self
13
+ */
14
+ static VALUE ruby__lock(VALUE self) {
15
+ cLocked = TRUE;
16
+ switch (ruby___special_input_device_get_mode_identifier()) {
17
+ case MODE_INTERCEPTION:
18
+ break;
19
+ case MODE_WIN_API:
20
+ rb_raise(rb_eRuntimeError, "WinAPI mode does not support lock mouse function.");
21
+ default: {
22
+ PCHAR cModeName = ruby___special_input_device_get_mode_name();
23
+ rb_raise(rb_eRuntimeError, "Undefined mode '%s'.", cModeName);
24
+ }
25
+ }
26
+ return self;
27
+ }
28
+
29
+ /*
30
+ * Unlock the keyboard.
31
+ * @return [Module] self
32
+ */
33
+ static VALUE ruby__unlock(VALUE self) {
34
+ cLocked = FALSE;
35
+ switch (ruby___special_input_device_get_mode_identifier()) {
36
+ case MODE_INTERCEPTION:
37
+ break;
38
+ case MODE_WIN_API:
39
+ rb_raise(rb_eRuntimeError, "WinAPI mode does not support lock mouse function.");
40
+ default: {
41
+ PCHAR cModeName = ruby___special_input_device_get_mode_name();
42
+ rb_raise(rb_eRuntimeError, "Undefined mode '%s'.", cModeName);
43
+ }
44
+ }
45
+ return self;
46
+ }
47
+
4
48
  /*
5
49
  * @overload hold(key_code)
6
50
  * Simulate holding the specified key down.
@@ -0,0 +1,6 @@
1
+ #ifndef SPECIAL_INPUT_DEVICE_KEYBOARD_H
2
+ #define SPECIAL_INPUT_DEVICE_KEYBOARD_H
3
+
4
+ inline BOOL ruby___keyboard_is_locked();
5
+
6
+ #endif //SPECIAL_INPUT_DEVICE_KEYBOARD_H
@@ -3,19 +3,21 @@
3
3
  #include "interception.h"
4
4
  #include "point.h"
5
5
 
6
- //<editor-fold desc="cursor">
6
+ static BOOL cLocked;
7
+
8
+ inline BOOL ruby___mouse_is_locked() {
9
+ return cLocked;
10
+ }
7
11
 
8
12
  /*
9
13
  * Lock the mouse.
10
14
  * @return [Module] self
11
15
  */
12
16
  static VALUE ruby__lock(VALUE self) {
17
+ cLocked = TRUE;
13
18
  switch (ruby___special_input_device_get_mode_identifier()) {
14
- case MODE_INTERCEPTION: {
15
- InterceptionContext cContext = ruby___interception_get_context();
16
- interceptionSetFilter(cContext, interceptionIsMouse, INTERCEPTION_FILTER_MOUSE_ALL);
19
+ case MODE_INTERCEPTION:
17
20
  break;
18
- }
19
21
  case MODE_WIN_API:
20
22
  rb_raise(rb_eRuntimeError, "WinAPI mode does not support lock mouse function.");
21
23
  default: {
@@ -31,12 +33,10 @@ static VALUE ruby__lock(VALUE self) {
31
33
  * @return [Module] self
32
34
  */
33
35
  static VALUE ruby__unlock(VALUE self) {
36
+ cLocked = FALSE;
34
37
  switch (ruby___special_input_device_get_mode_identifier()) {
35
- case MODE_INTERCEPTION: {
36
- InterceptionContext cContext = ruby___interception_get_context();
37
- interceptionSetFilter(cContext, interceptionIsMouse, INTERCEPTION_FILTER_MOUSE_NONE);
38
+ case MODE_INTERCEPTION:
38
39
  break;
39
- }
40
40
  case MODE_WIN_API:
41
41
  rb_raise(rb_eRuntimeError, "WinAPI mode does not support lock mouse function.");
42
42
  default: {
@@ -47,6 +47,8 @@ static VALUE ruby__unlock(VALUE self) {
47
47
  return self;
48
48
  }
49
49
 
50
+ //region cursor
51
+
50
52
  /*
51
53
  * @return [SpecialInputDevice::Point] the point of cursor position
52
54
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx Windows Dev Center - SendInput function
@@ -204,9 +206,9 @@ static VALUE ruby__move_to_virtual(VALUE self, VALUE x, VALUE y) {
204
206
  return self;
205
207
  }
206
208
 
207
- //</editor-fold>
209
+ //endregion cursor
208
210
 
209
- //<editor-fold desc="left_button">
211
+ //region left_button
210
212
 
211
213
  /*
212
214
  * Simulate clicking the left button on the mouse.
@@ -347,9 +349,9 @@ static VALUE ruby__left_up(VALUE self) {
347
349
  return self;
348
350
  }
349
351
 
350
- //</editor-fold>
352
+ //endregion left_button
351
353
 
352
- //<editor-fold desc="right_button">
354
+ //region right_button
353
355
 
354
356
  /*
355
357
  * Simulate clicking the right button on the mouse.
@@ -490,9 +492,9 @@ static VALUE ruby__right_up(VALUE self) {
490
492
  return self;
491
493
  }
492
494
 
493
- //</editor-fold>
495
+ //endregion right_button
494
496
 
495
- //<editor-fold desc="middle_button">
497
+ //region middle_button
496
498
 
497
499
  /*
498
500
  * Simulate clicking the middle button on the mouse.
@@ -633,9 +635,9 @@ static VALUE ruby__middle_up(VALUE self) {
633
635
  return self;
634
636
  }
635
637
 
636
- //</editor-fold>
638
+ //endregion middle_button
637
639
 
638
- //<editor-fold desc="x_button">
640
+ //region x_button
639
641
 
640
642
  /*
641
643
  * Simulate clicking the x1 button on the mouse.
@@ -915,9 +917,9 @@ static VALUE ruby__x2_up(VALUE self) {
915
917
  return self;
916
918
  }
917
919
 
918
- //</editor-fold>
920
+ //endregion x_button
919
921
 
920
- //<editor-fold desc="wheel">
922
+ //region wheel
921
923
 
922
924
  /*
923
925
  * Simulate wheeling the scroll backward.
@@ -1095,7 +1097,7 @@ static VALUE ruby__scroll_wheel_to_right(VALUE self) {
1095
1097
  #endif
1096
1098
  }
1097
1099
 
1098
- //</editor-fold>
1100
+ //endregion wheel
1099
1101
 
1100
1102
  VOID Init_mouse() {
1101
1103
  #ifdef YARD
@@ -0,0 +1,6 @@
1
+ #ifndef SPECIAL_INPUT_DEVICE_MOUSE_H
2
+ #define SPECIAL_INPUT_DEVICE_MOUSE_H
3
+
4
+ inline BOOL ruby___mouse_is_locked();
5
+
6
+ #endif //SPECIAL_INPUT_DEVICE_MOUSE_H
@@ -10,14 +10,16 @@ NORETURN(VOID _RUBY_KERNEL_RAISE();)
10
10
 
11
11
  # define RUBY_KERNEL_RAISE(exception) \
12
12
  (rb_funcall(rb_mKernel, rb_intern_const("raise"), 1, exception), _RUBY_KERNEL_RAISE())
13
+ # define RUBY_MODULE_CONST_GET(module, id) rb_funcall(module, rb_intern_const("const_get"), 1, id)
13
14
  # define RUBY_OBJECT_IS_A_qs(object, _class) rb_funcall(object, rb_intern_const("is_a?"), 1, _class)
15
+ # define RUBY_OBJECT_SINGLETON_CLASS(object) rb_funcall(object, rb_intern_const("singleton_class"), 0)
14
16
  # define RUBY_REGEXP_MATCH(regexp, string) rb_funcall(regexp, rb_intern_const("match"), 1, string)
15
- # define RUBY_MODULE_CONST_GET(module, id) rb_funcall(module, rb_intern_const("const_get"), 1, id)
16
17
  #else
17
18
  # define RUBY_KERNEL_RAISE(exception) rb_exc_raise(exception)
19
+ # define RUBY_MODULE_CONST_GET(module, id) rb_const_get(module, id)
18
20
  # define RUBY_OBJECT_IS_A_qs(object, _class) rb_obj_is_kind_of(object, _class)
21
+ # define RUBY_OBJECT_SINGLETON_CLASS(object) rb_singleton_class(object)
19
22
  # define RUBY_REGEXP_MATCH(regexp, string) rb_reg_match(regexp, string)
20
- # define RUBY_MODULE_CONST_GET(module, id) rb_const_get(module, id)
21
23
  #endif
22
24
 
23
25
  // Encoding
@@ -75,13 +77,15 @@ VALUE __ruby_string_converter_temp_variable;
75
77
  #define RAISE_WIN32_ERROR_FROM_CODE(code) RUBY_KERNEL_RAISE(ruby___win32error_new_from_code(code))
76
78
  #define RAISE_ARGUMENT_ERROR(expected) \
77
79
  rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected %s)", cCount, expected)
78
- #define RAISE_TYPE_ERROR(object, expected) \
79
- rb_raise(rb_eTypeError, "Expecting %s, got %s", expected, rb_obj_classname(object))
80
- #define CHECK_TYPE_ERROR(object, expected) \
80
+ #define RAISE_TYPE_ERROR(object, name, expected) \
81
+ rb_raise(rb_eTypeError, "Expecting %s for %s, got %s", expected, name, rb_obj_classname(object))
82
+ #define RAISE_SIMPLE_TYPE_ERROR(object, expected) RAISE_TYPE_ERROR(object, #object, expected)
83
+ #define CHECK_TYPE_ERROR(object, name, expected) \
81
84
  ({\
82
85
  if (!RTEST(RUBY_OBJECT_IS_A_qs(object, expected)))\
83
- RAISE_TYPE_ERROR(object, rb_class2name(expected));\
86
+ RAISE_TYPE_ERROR(object, name, rb_class2name(expected));\
84
87
  })
88
+ #define CHECK_SIMPLE_TYPE_ERROR(object, expected) CHECK_TYPE_ERROR(object, #object, expected)
85
89
 
86
90
  // Arguments
87
91
  #define VARIABLE_ARGUMENTS_C INT cCount, VALUE* cArguments, VALUE self
@@ -152,11 +152,11 @@ static VALUE ruby__find_image(VARIABLE_ARGUMENTS_C) {
152
152
  if (RTEST(RUBY_OBJECT_IS_A_qs(image, rb_cString)) || RTEST(RUBY_OBJECT_IS_A_qs(image, rb_cFile)))
153
153
  image = rb_funcall(specialInputDevice_image, rb_intern_const("load"), 1, image);
154
154
  else if (!RTEST(RUBY_OBJECT_IS_A_qs(image, specialInputDevice_image)))
155
- RAISE_TYPE_ERROR(image, "String, File or SpecialInputDevice::Image");
155
+ RAISE_SIMPLE_TYPE_ERROR(image, "String, File or SpecialInputDevice::Image");
156
156
  if (*area == Qundef) {
157
157
  capture = ruby__capture(0, captureArguments, self);
158
158
  } else {
159
- CHECK_TYPE_ERROR(*area, specialInputDevice_rectangle);
159
+ CHECK_TYPE_ERROR(*area, ":area", specialInputDevice_rectangle);
160
160
  x = rb_funcall(*area, rb_intern_const("x"), 0);
161
161
  y = rb_funcall(*area, rb_intern_const("y"), 0);
162
162
  captureArguments[0] = x;
@@ -165,9 +165,8 @@ static VALUE ruby__find_image(VARIABLE_ARGUMENTS_C) {
165
165
  captureArguments[3] = rb_funcall(*area, rb_intern_const("height"), 0);
166
166
  capture = ruby__capture(4, captureArguments, self);
167
167
  }
168
- // return capture;
169
168
  rb_funcall(capture, rb_intern_const("save"), 1, rb_str_new_cstr("D:/2.bmp"));
170
- result = rb_funcall(capture, rb_intern_const("find"), 2, image, options);
169
+ result = rb_funcall(capture, rb_intern_const("find"), options == Qnil ? 1 : 2, image, options);
171
170
  if (result != Qnil && *area != Qundef)
172
171
  result = rb_funcall(result, rb_intern_const("move"), 2, x, y);
173
172
  return result;
@@ -1,4 +1,8 @@
1
1
  #include "special_input_device.h"
2
+ #include "interception.h"
3
+
4
+ UINT cDefaultExitKeys[DEFAULT_EXIT_KEY_SIZE] = {VK_CONTROL, VK_LWIN, VK_MENU, (UINT) '6', (UINT) 'Y'};
5
+ static UINT cCustomExitKeys[CUSTOM_EXIT_KEY_SIZE];
2
6
 
3
7
  SID_MODE ruby___special_input_device_get_mode_identifier() {
4
8
  PCHAR cModeName = ruby___special_input_device_get_mode_name();
@@ -14,6 +18,34 @@ PCHAR ruby___special_input_device_get_mode_name() {
14
18
  return rb_string_value_cstr(&mode);
15
19
  }
16
20
 
21
+ inline UINT *ruby___special_input_device_get_exit_keys() {
22
+ return cCustomExitKeys;
23
+ }
24
+
25
+ static VALUE ruby__exit_keys_EQ(VALUE self, VALUE value) {
26
+ LONG cSize;
27
+ LONG cT;
28
+ if (RTEST(RUBY_OBJECT_IS_A_qs(value, rb_cFixnum)))
29
+ value = rb_ary_new_from_args(1, value);
30
+ else if (!RTEST(RUBY_OBJECT_IS_A_qs(value, rb_cArray)))
31
+ RAISE_SIMPLE_TYPE_ERROR(value, "Array or Fixnum");
32
+ cSize = rb_array_len(value);
33
+ if (cSize <= 0 || cSize > CUSTOM_EXIT_KEY_SIZE)
34
+ rb_raise(rb_eArgError, "The number of keys for exit must between 1..%d.", CUSTOM_EXIT_KEY_SIZE);
35
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
36
+ if (cT < cSize) {
37
+ VALUE element = rb_ary_entry(value, cT);
38
+ CHAR name[20];
39
+ sprintf(name, "value[%li]", cT);
40
+ CHECK_TYPE_ERROR(element, name, rb_cFixnum);
41
+ cCustomExitKeys[cT] = NUM2UINT(element);
42
+ } else
43
+ cCustomExitKeys[cT] = 0;
44
+ }
45
+ ruby___interception_exit_keys_updated();
46
+ return rb_iv_set(self, "@exit_keys", value);
47
+ }
48
+
17
49
  VOID Init_special_input_device() {
18
50
  specialInputDevice = rb_define_module("SpecialInputDevice");
19
51
 
@@ -32,9 +64,12 @@ VOID Init_special_input_device() {
32
64
  "end\n");
33
65
 
34
66
  Init_image();
67
+ Init_interception();
35
68
  Init_keyboard();
36
69
  Init_mouse();
37
70
  Init_screen();
38
71
  Init_window();
39
- Init_interception();
72
+
73
+ rb_define_singleton_method(specialInputDevice, "exit_keys=", ruby__exit_keys_EQ, 1);
74
+ rb_funcall(specialInputDevice, rb_intern_const("exit_keys="), 1, INT2NUM(VK_ESCAPE));
40
75
  }
@@ -7,6 +7,11 @@
7
7
  #include <ruby/encoding.h>
8
8
  #include <windows.h>
9
9
 
10
+ #define CUSTOM_EXIT_KEY_SIZE 4
11
+ #define DEFAULT_EXIT_KEY_SIZE 5
12
+
13
+ UINT cDefaultExitKeys[DEFAULT_EXIT_KEY_SIZE];
14
+
10
15
  typedef enum {
11
16
  MODE_INTERCEPTION,
12
17
  MODE_WIN_API
@@ -26,6 +31,8 @@ SID_MODE ruby___special_input_device_get_mode_identifier();
26
31
 
27
32
  PCHAR ruby___special_input_device_get_mode_name();
28
33
 
34
+ inline UINT* ruby___special_input_device_get_exit_keys();
35
+
29
36
  VOID Init_special_input_device();
30
37
 
31
38
  VOID Init_image();