special_input_device 0.1.0 → 0.2.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: be0868fbceeb98ef86c51bf95099a3ba60e6ee80
4
- data.tar.gz: 726061d79c40698e7bc9d09f3f2dd61fc564f2fa
3
+ metadata.gz: a121ec84d3ab7c53e8e10c86efe86ff24d25ce07
4
+ data.tar.gz: e36b09142e83769a40bba02da6fb92de44f9cf62
5
5
  SHA512:
6
- metadata.gz: 94035fa8ecb71c41153232256ad261ecc4436aaef1a0f8fb721997c8b022c70758a10942d366084e8ba09894d6feaefde4ad5ae9caa080a5d1f740db063f80c3
7
- data.tar.gz: d3eec4a2ba8c5f598a9c888a56b2529990fd1b9cb924cb3e7df607c0bac01a395ae95702ce03618ce5bdc59c0e006be9c05bde33a54d16d48637cb74a6fa0508
6
+ metadata.gz: 4987339ea7d2ff4648c3141c631ad79d774727c430059fd16619670b5e8c1acaf0994f6c2fd37980f52421ec20792ea42a163e8048c0c5522f5ea43bd5ffee96
7
+ data.tar.gz: 8dfdf490278e48264878633ccd2c27349e0b3c9d73fcffb8e02a212d638696aba9490ba106f1a39ea4df684195922ba74e13ca7bf8b9b5fe2718836346507110
@@ -0,0 +1,22 @@
1
+ #include <windows.h>
2
+ #include "_screen.h"
3
+
4
+ LONG getCursorPrimaryX() {
5
+ POINT cPoint;
6
+ GetCursorPos(&cPoint);
7
+ return cPoint.x;
8
+ }
9
+
10
+ LONG getCursorPrimaryY() {
11
+ POINT cPoint;
12
+ GetCursorPos(&cPoint);
13
+ return cPoint.y;
14
+ }
15
+
16
+ LONG getCursorVirtualX() {
17
+ return getCursorPrimaryX() - getVirtualScreenX();
18
+ }
19
+
20
+ LONG getCursorVirtualY() {
21
+ return getCursorPrimaryY() - getVirtualScreenY();
22
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef SPECIAL_INPUT_DEVICE_MOUSE_H
2
+ #define SPECIAL_INPUT_DEVICE_MOUSE_H
3
+
4
+ LONG getCursorPrimaryX();
5
+
6
+ LONG getCursorPrimaryY();
7
+
8
+ LONG getCursorVirtualX();
9
+
10
+ LONG getCursorVirtualY();
11
+
12
+ #endif //SPECIAL_INPUT_DEVICE_MOUSE_H
@@ -180,7 +180,7 @@ InterceptionDevice interceptionWaitWithTimeout(InterceptionContext context, ULON
180
180
  return 0;
181
181
  }
182
182
 
183
- INT interceptionSend(InterceptionContext context, InterceptionDevice device, const InterceptionStroke *strokeValue,
183
+ INT interceptionSend(InterceptionContext context, InterceptionDevice device, InterceptionStroke *strokeValue,
184
184
  UINT strokeCount) {
185
185
  InterceptionDeviceArray deviceArray = (InterceptionDeviceArray) context;
186
186
  DWORD strokesWritten = 0;
@@ -172,7 +172,7 @@ InterceptionDevice INTERCEPTION_API interceptionWait(InterceptionContext context
172
172
  InterceptionDevice INTERCEPTION_API interceptionWaitWithTimeout(InterceptionContext context, ULONG milliseconds);
173
173
 
174
174
  INT INTERCEPTION_API
175
- interceptionSend(InterceptionContext context, InterceptionDevice device, const InterceptionStroke *strokeValue,
175
+ interceptionSend(InterceptionContext context, InterceptionDevice device, InterceptionStroke *strokeValue,
176
176
  UINT strokeCount);
177
177
 
178
178
  INT INTERCEPTION_API
@@ -228,7 +228,7 @@ static VALUE ruby__load(VALUE self, VALUE path) {
228
228
  UINT cMaxColorTableSize = (UINT) (1 << cDIBHeader.v1.biBitCount);
229
229
  if (cColorTableSize > cMaxColorTableSize)
230
230
  rb_raise(rb_eArgError, "The bitmap file has been damaged. (clrUsed too large)");
231
- if (cColorTableSize == 0)
231
+ if (!cColorTableSize)
232
232
  cColorTableSize = cMaxColorTableSize;
233
233
  cColorTable = ALLOC_N(RGBQUAD, cColorTableSize);
234
234
  ReadFile(cFile, cColorTable, sizeof(RGBQUAD) * cColorTableSize, &cByteRead, NULL);
@@ -69,7 +69,7 @@ static VALUE ruby__alloc(VALUE self) {
69
69
  return NEW_DATA_OBJECT(self, SID_INTERCEPTION_DATA, NULL, callback_interception_free);
70
70
  }
71
71
 
72
- static VALUE ruby_initialize_thread() {
72
+ static VALUE ruby_initialize_thread(VALUE *self) {
73
73
  InterceptionStroke cStroke;
74
74
  InterceptionDevice cDevice;
75
75
  UINT *cCustomExitKeys;
@@ -77,9 +77,11 @@ static VALUE ruby_initialize_thread() {
77
77
  interceptionSetFilter(cData->context, interceptionIsKeyboard, INTERCEPTION_FILTER_KEY_ALL);
78
78
  interceptionSetFilter(cData->context, interceptionIsMouse, INTERCEPTION_FILTER_MOUSE_ALL);
79
79
  while (TRUE) {
80
- cDevice = interceptionWait(cData->context);
81
- if (!interceptionReceive(cData->context, cDevice, &cStroke, 1))
82
- break;
80
+ cDevice = interceptionWaitWithTimeout(cData->context, 10);
81
+ if (!cDevice || !interceptionReceive(cData->context, cDevice, &cStroke, 1)) {
82
+ rb_thread_schedule();
83
+ continue;
84
+ }
83
85
  cCustomExitKeys = ruby___special_input_device_get_exit_keys();
84
86
  if (interceptionIsMouse(cDevice)) {
85
87
  InterceptionMouseStroke *cMouseStroke = (InterceptionMouseStroke *) &cStroke;
@@ -156,10 +158,10 @@ static VALUE ruby_initialize_thread() {
156
158
  if (cT == CUSTOM_EXIT_KEY_SIZE)
157
159
  rb_raise(rb_eSystemExit, "Exit keys pressed.");
158
160
  if (!ruby___mouse_is_locked())
159
- interceptionSend(cData->context, cDevice, (InterceptionStroke const *) &cStroke, 1);
161
+ interceptionSend(cData->context, cDevice, &cStroke, 1);
160
162
  }
161
163
  if (interceptionIsKeyboard(cDevice)) {
162
- InterceptionKeyStroke *cKeyStroke = (InterceptionKeyStroke *) (InterceptionMouseStroke *) &cStroke;
164
+ InterceptionKeyStroke *cKeyStroke = (InterceptionKeyStroke *) &cStroke;
163
165
  for (cT = 0; cT < DEFAULT_EXIT_KEY_SIZE; cT++) {
164
166
  if (cKeyStroke->code == MapVirtualKeyA(cDefaultExitKeys[cT], MAPVK_VK_TO_VSC))
165
167
  cDefaultExitKeysDown[cT] = !(cKeyStroke->state & INTERCEPTION_KEY_UP);
@@ -170,7 +172,7 @@ static VALUE ruby_initialize_thread() {
170
172
  }
171
173
  if (cT == DEFAULT_EXIT_KEY_SIZE)
172
174
  rb_raise(rb_eSystemExit, "Exit keys pressed.");
173
- for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
175
+ for (cT = 0; cT < CUSTOM_EXIT_KEY_SIZE; cT++) {
174
176
  if (cKeyStroke->code == MapVirtualKeyA(cCustomExitKeys[cT], MAPVK_VK_TO_VSC))
175
177
  cCustomExitKeysDown[cT] = !(cKeyStroke->state & INTERCEPTION_KEY_UP);
176
178
  }
@@ -181,7 +183,7 @@ static VALUE ruby_initialize_thread() {
181
183
  if (cT == CUSTOM_EXIT_KEY_SIZE)
182
184
  rb_raise(rb_eSystemExit, "Exit keys pressed.");
183
185
  if (!ruby___keyboard_is_locked())
184
- interceptionSend(cData->context, cDevice, (InterceptionStroke const *) &cStroke, 1);
186
+ interceptionSend(cData->context, cDevice, &cStroke, 1);
185
187
  }
186
188
  }
187
189
  return Qnil;
@@ -197,7 +199,7 @@ static VALUE ruby_initialize(VALUE self) {
197
199
  cData->keyboard = 0;
198
200
  cData->lockMouse = FALSE;
199
201
  cData->lockKeyboard = FALSE;
200
- rb_thread_create(ruby_initialize_thread, NULL);
202
+ rb_thread_create(ruby_initialize_thread, &self);
201
203
  return Qnil;
202
204
  }
203
205
 
@@ -7,23 +7,26 @@ inline BOOL ruby___keyboard_is_locked() {
7
7
  return cLocked;
8
8
  }
9
9
 
10
+ #define RUBY___LOCK(flag) \
11
+ cLocked = flag;\
12
+ switch (ruby___special_input_device_get_mode_identifier()) {\
13
+ case MODE_INTERCEPTION:\
14
+ break;\
15
+ case MODE_WIN_API:\
16
+ rb_raise(rb_eRuntimeError, "WinAPI mode does not support lock mouse function.");\
17
+ default: {\
18
+ PCHAR cModeName = ruby___special_input_device_get_mode_name();\
19
+ rb_raise(rb_eRuntimeError, "Undefined mode '%s'.", cModeName);\
20
+ }\
21
+ }\
22
+ return self;
23
+
10
24
  /*
11
25
  * Lock the keyboard.
12
26
  * @return [Module] self
13
27
  */
14
28
  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;
29
+ RUBY___LOCK(TRUE)
27
30
  }
28
31
 
29
32
  /*
@@ -31,102 +34,114 @@ static VALUE ruby__lock(VALUE self) {
31
34
  * @return [Module] self
32
35
  */
33
36
  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;
37
+ RUBY___LOCK(FALSE)
46
38
  }
47
39
 
40
+ //region key
41
+
42
+ #define RUBY___GET_KEY_CODE() \
43
+ WORD cKeyCodes[cCount];\
44
+ UINT cScanCodes[cCount];\
45
+ INT cT;\
46
+ SCAN_ARGUMENTS("1*", NULL, NULL);\
47
+ for (cT = 0; cT < cCount; cT++) {\
48
+ cKeyCodes[cT] = NUM2USHORT(cArguments[cT]);\
49
+ cScanCodes[cT] = MapVirtualKeyA(cKeyCodes[cT], MAPVK_VK_TO_VSC);\
50
+ }\
51
+
52
+ #define RUBY___HOLD_RELEASE(interceptionState, winAPIFlag) \
53
+ RUBY___GET_KEY_CODE();\
54
+ switch (ruby___special_input_device_get_mode_identifier()) {\
55
+ case MODE_INTERCEPTION: {\
56
+ InterceptionContext cContext = ruby___interception_get_context();\
57
+ InterceptionDevice cDevice = ruby___interception_find_keyboard();\
58
+ InterceptionKeyStroke cStroke[cCount];\
59
+ for (cT = 0; cT < cCount; cT++) {\
60
+ cStroke[cT].code = (USHORT) cScanCodes[cT];\
61
+ cStroke[cT].information = 0;\
62
+ cStroke[cT].state = interceptionState;\
63
+ }\
64
+ interceptionSend(cContext, cDevice, (InterceptionStroke *) cStroke, (UINT) cCount);\
65
+ break;\
66
+ }\
67
+ case MODE_WIN_API: {\
68
+ INPUT cInput[cCount];\
69
+ for (cT = 0; cT < cCount; cT++) {\
70
+ cInput[cT].type = INPUT_KEYBOARD;\
71
+ cInput[cT].ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();\
72
+ cInput[cT].ki.dwFlags = winAPIFlag;\
73
+ cInput[cT].ki.time = 0;\
74
+ cInput[cT].ki.wScan = (WORD) cScanCodes[cT];\
75
+ cInput[cT].ki.wVk = cKeyCodes[cT];\
76
+ }\
77
+ if (!SendInput((UINT) cCount, cInput, sizeof(INPUT)))\
78
+ RAISE_WIN32_ERROR();\
79
+ break;\
80
+ }\
81
+ default: {\
82
+ PCHAR cModeName = ruby___special_input_device_get_mode_name();\
83
+ rb_raise(rb_eRuntimeError, "Undefined mode '%s'.", cModeName);\
84
+ }\
85
+ }\
86
+ return self;
87
+
48
88
  /*
49
- * @overload hold(key_code)
89
+ * @overload hold(key_code, *more)
50
90
  * Simulate holding the specified key down.
51
91
  * @param [Integer] key_code virtual key code. Use a value of constant in {SpecialInputDevice::KeyCode}.
92
+ * @param [Array[Integer]] more more key codes
52
93
  * @return [Module] self
53
94
  * @see SpecialInputDevice::Window#key_hold
54
95
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx Windows Dev Center - SendInput function
55
96
  */
56
- static VALUE ruby__hold(VALUE self, VALUE keyCode) {
57
- WORD cKeyCode = NUM2USHORT(keyCode);
58
- UINT cScanCode = MapVirtualKeyA(cKeyCode, MAPVK_VK_TO_VSC);
59
- switch (ruby___special_input_device_get_mode_identifier()) {
60
- case MODE_INTERCEPTION: {
61
- InterceptionContext cContext = ruby___interception_get_context();
62
- InterceptionDevice cDevice = ruby___interception_find_keyboard();
63
- InterceptionKeyStroke cStroke;
64
- cStroke.code = (USHORT) cScanCode;
65
- cStroke.information = 0;
66
- cStroke.state = INTERCEPTION_KEY_DOWN;
67
- interceptionSend(cContext, cDevice, (InterceptionStroke const *) &cStroke, 1);
68
- break;
69
- }
70
- case MODE_WIN_API: {
71
- INPUT cInput;
72
- cInput.type = INPUT_KEYBOARD;
73
- cInput.ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();
74
- cInput.ki.dwFlags = 0;
75
- cInput.ki.time = 0;
76
- cInput.ki.wScan = (WORD) cScanCode;
77
- cInput.ki.wVk = cKeyCode;
78
- if (SendInput(1, &cInput, sizeof(INPUT)) == 0)
79
- RAISE_WIN32_ERROR();
80
- break;
81
- }
82
- default: {
83
- PCHAR cModeName = ruby___special_input_device_get_mode_name();
84
- rb_raise(rb_eRuntimeError, "Undefined mode '%s'.", cModeName);
85
- }
86
- }
87
- return self;
97
+ static VALUE ruby__hold(VARIABLE_ARGUMENTS_C) {
98
+ RUBY___HOLD_RELEASE(INTERCEPTION_KEY_DOWN, 0)
88
99
  }
89
100
 
90
101
  /*
91
- * @overload press(key_code)
102
+ * @overload press(key_code, *more)
92
103
  * Simulate pressing the specified key.
93
104
  * @param [Integer] key_code virtual key code. Use a value of constant in {SpecialInputDevice::KeyCode}.
105
+ * @param [Array[Integer]] more more key codes
94
106
  * @return [Module] self
95
107
  * @see SpecialInputDevice::Window#key_press
96
108
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx Windows Dev Center - SendInput function
97
109
  */
98
- static VALUE ruby__press(VALUE self, VALUE keyCode) {
99
- WORD cKeyCode = NUM2USHORT(keyCode);
100
- UINT cScanCode = MapVirtualKeyA(cKeyCode, MAPVK_VK_TO_VSC);
110
+ static VALUE ruby__press(VARIABLE_ARGUMENTS_C) {
111
+ RUBY___GET_KEY_CODE()
101
112
  switch (ruby___special_input_device_get_mode_identifier()) {
102
113
  case MODE_INTERCEPTION: {
103
114
  InterceptionContext cContext = ruby___interception_get_context();
104
115
  InterceptionDevice cDevice = ruby___interception_find_keyboard();
105
- InterceptionKeyStroke cStroke[2];
106
- cStroke[0].code = (USHORT) cScanCode;
107
- cStroke[0].information = 0;
108
- cStroke[0].state = INTERCEPTION_KEY_DOWN;
109
- cStroke[1].code = (USHORT) cScanCode;
110
- cStroke[1].information = 0;
111
- cStroke[1].state = INTERCEPTION_KEY_UP;
112
- interceptionSend(cContext, cDevice, (InterceptionStroke const *) cStroke, 2);
116
+ InterceptionKeyStroke cStroke[cCount * 2];
117
+ for (cT = 0; cT < cCount; cT++) {
118
+ cStroke[cT * 2 + 0].code = (USHORT) cScanCodes[cT];
119
+ cStroke[cT * 2 + 0].information = 0;
120
+ cStroke[cT * 2 + 0].state = INTERCEPTION_KEY_DOWN;
121
+ cStroke[cT * 2 + 1].code = (USHORT) cScanCodes[cT];
122
+ cStroke[cT * 2 + 1].information = 0;
123
+ cStroke[cT * 2 + 1].state = INTERCEPTION_KEY_UP;
124
+ }
125
+ interceptionSend(cContext, cDevice, (InterceptionStroke *) cStroke, (UINT) cCount * 2);
113
126
  break;
114
127
  }
115
128
  case MODE_WIN_API: {
116
- INPUT cInput[2];
117
- cInput[0].type = INPUT_KEYBOARD;
118
- cInput[0].ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();
119
- cInput[0].ki.dwFlags = 0;
120
- cInput[0].ki.time = 0;
121
- cInput[0].ki.wScan = (WORD) cScanCode;
122
- cInput[0].ki.wVk = cKeyCode;
123
- cInput[1].type = INPUT_KEYBOARD;
124
- cInput[1].ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();
125
- cInput[1].ki.dwFlags = KEYEVENTF_KEYUP;
126
- cInput[1].ki.time = 0;
127
- cInput[1].ki.wScan = (WORD) cScanCode;
128
- cInput[1].ki.wVk = cKeyCode;
129
- if (SendInput(2, cInput, sizeof(INPUT)) == 0)
129
+ INPUT cInput[cCount * 2];
130
+ for (cT = 0; cT < cCount; cT++) {
131
+ cInput[cT * 2 + 0].type = INPUT_KEYBOARD;
132
+ cInput[cT * 2 + 0].ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();
133
+ cInput[cT * 2 + 0].ki.dwFlags = 0;
134
+ cInput[cT * 2 + 0].ki.time = 0;
135
+ cInput[cT * 2 + 0].ki.wScan = (WORD) cScanCodes[cT];
136
+ cInput[cT * 2 + 0].ki.wVk = cKeyCodes[cT];
137
+ cInput[cT * 2 + 1].type = INPUT_KEYBOARD;
138
+ cInput[cT * 2 + 1].ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();
139
+ cInput[cT * 2 + 1].ki.dwFlags = KEYEVENTF_KEYUP;
140
+ cInput[cT * 2 + 1].ki.time = 0;
141
+ cInput[cT * 2 + 1].ki.wScan = (WORD) cScanCodes[cT];
142
+ cInput[cT * 2 + 1].ki.wVk = cKeyCodes[cT];
143
+ }
144
+ if (!SendInput((UINT) cCount * 2, cInput, sizeof(INPUT)))
130
145
  RAISE_WIN32_ERROR();
131
146
  break;
132
147
  }
@@ -139,47 +154,20 @@ static VALUE ruby__press(VALUE self, VALUE keyCode) {
139
154
  }
140
155
 
141
156
  /*
142
- * @overload release(key_code)
157
+ * @overload release(key_code, *more)
143
158
  * Simulate releasing the specified key.
144
159
  * @param [Integer] key_code virtual key code. Use a value of constant in {SpecialInputDevice::KeyCode}.
160
+ * @param [Array[Integer]] more more key codes
145
161
  * @return [Module] self
146
162
  * @see SpecialInputDevice::Window#key_release
147
163
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx Windows Dev Center - SendInput function
148
164
  */
149
- static VALUE ruby__release(VALUE self, VALUE keyCode) {
150
- WORD cKeyCode = NUM2USHORT(keyCode);
151
- UINT cScanCode = MapVirtualKeyA(cKeyCode, MAPVK_VK_TO_VSC);
152
- switch (ruby___special_input_device_get_mode_identifier()) {
153
- case MODE_INTERCEPTION: {
154
- InterceptionContext cContext = ruby___interception_get_context();
155
- InterceptionDevice cDevice = ruby___interception_find_keyboard();
156
- InterceptionKeyStroke cStroke;
157
- cStroke.code = (USHORT) cScanCode;
158
- cStroke.information = 0;
159
- cStroke.state = INTERCEPTION_KEY_UP;
160
- interceptionSend(cContext, cDevice, (InterceptionStroke const *) &cStroke, 2);
161
- break;
162
- }
163
- case MODE_WIN_API: {
164
- INPUT cInput;
165
- cInput.type = INPUT_KEYBOARD;
166
- cInput.ki.dwExtraInfo = (ULONG_PTR) GetMessageExtraInfo();
167
- cInput.ki.dwFlags = KEYEVENTF_KEYUP;
168
- cInput.ki.time = 0;
169
- cInput.ki.wScan = (WORD) cScanCode;
170
- cInput.ki.wVk = cKeyCode;
171
- if (SendInput(1, &cInput, sizeof(INPUT)) == 0)
172
- RAISE_WIN32_ERROR();
173
- break;
174
- }
175
- default: {
176
- PCHAR cModeName = ruby___special_input_device_get_mode_name();
177
- rb_raise(rb_eRuntimeError, "Undefined mode '%s'.", cModeName);
178
- }
179
- }
180
- return self;
165
+ static VALUE ruby__release(VARIABLE_ARGUMENTS_C) {
166
+ RUBY___HOLD_RELEASE(INTERCEPTION_KEY_UP, KEYEVENTF_KEYUP)
181
167
  }
182
168
 
169
+ //endregion key
170
+
183
171
  VOID Init_keyboard() {
184
172
  #ifdef YARD
185
173
  specialInputDevice = rb_define_module("SpecialInputDevice");
@@ -190,7 +178,9 @@ VOID Init_keyboard() {
190
178
  * The <code>Keyboard</code> module provides an interface to simulate the signal form keyboard.
191
179
  */
192
180
  VALUE specialInputDevice_keyboard = rb_define_module_under(specialInputDevice, "Keyboard");
193
- rb_define_singleton_method(specialInputDevice_keyboard, "hold", ruby__hold, 1);
194
- rb_define_singleton_method(specialInputDevice_keyboard, "press", ruby__press, 1);
195
- rb_define_singleton_method(specialInputDevice_keyboard, "release", ruby__release, 1);
181
+ rb_define_singleton_method(specialInputDevice_keyboard, "lock", ruby__lock, 0);
182
+ rb_define_singleton_method(specialInputDevice_keyboard, "unlock", ruby__unlock, 0);
183
+ rb_define_singleton_method(specialInputDevice_keyboard, "hold", ruby__hold, -1);
184
+ rb_define_singleton_method(specialInputDevice_keyboard, "press", ruby__press, -1);
185
+ rb_define_singleton_method(specialInputDevice_keyboard, "release", ruby__release, -1);
196
186
  }