vigilem-evdev 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/ext/Rakefile +31 -0
  4. data/ext/rake_helper.rb +10 -0
  5. data/lib/vigilem/_evdev.rb +24 -0
  6. data/lib/vigilem/evdev.rb +14 -0
  7. data/lib/vigilem/evdev/at_exit.rb +8 -0
  8. data/lib/vigilem/evdev/context_filter.rb +92 -0
  9. data/lib/vigilem/evdev/demultiplexer.rb +26 -0
  10. data/lib/vigilem/evdev/device.rb +182 -0
  11. data/lib/vigilem/evdev/device_capabilities.rb +53 -0
  12. data/lib/vigilem/evdev/dom.rb +8 -0
  13. data/lib/vigilem/evdev/dom/adapter.rb +87 -0
  14. data/lib/vigilem/evdev/dom/code_values_tables.rb +172 -0
  15. data/lib/vigilem/evdev/dom/input_event_converter.rb +329 -0
  16. data/lib/vigilem/evdev/dom/input_event_utils.rb +48 -0
  17. data/lib/vigilem/evdev/dom/key_values_tables.rb +248 -0
  18. data/lib/vigilem/evdev/dom/kp_table.rb +52 -0
  19. data/lib/vigilem/evdev/focus_context_filter.rb +124 -0
  20. data/lib/vigilem/evdev/input_system_handler.rb +69 -0
  21. data/lib/vigilem/evdev/key_map_cache.rb +64 -0
  22. data/lib/vigilem/evdev/multiplexer.rb +73 -0
  23. data/lib/vigilem/evdev/system.rb +17 -0
  24. data/lib/vigilem/evdev/system/input.rb +1053 -0
  25. data/lib/vigilem/evdev/system/input/event.rb +4 -0
  26. data/lib/vigilem/evdev/system/input/input_event.rb +33 -0
  27. data/lib/vigilem/evdev/system/int.rb +9 -0
  28. data/lib/vigilem/evdev/system/ioctl.rb +143 -0
  29. data/lib/vigilem/evdev/system/keymap_loaders.rb +89 -0
  30. data/lib/vigilem/evdev/system/keymap_loaders/dumpkeys_loader.rb +98 -0
  31. data/lib/vigilem/evdev/system/keymap_loaders/kmap_loader.rb +74 -0
  32. data/lib/vigilem/evdev/system/posix_types.rb +5 -0
  33. data/lib/vigilem/evdev/system/time.rb +21 -0
  34. data/lib/vigilem/evdev/transfer_agent.rb +40 -0
  35. data/lib/vigilem/evdev/version.rb +5 -0
  36. data/lib/vigilem/evdev/vty_context_filter.rb +216 -0
  37. data/spec/after_each_example_group.rb +29 -0
  38. data/spec/delete_test_cache_after_group.rb +26 -0
  39. data/spec/spec_helper.rb +30 -0
  40. data/spec/vigilem/_evdev_spec.rb +11 -0
  41. data/spec/vigilem/evdev/context_filter_spec.rb +114 -0
  42. data/spec/vigilem/evdev/demultiplexer_spec.rb +44 -0
  43. data/spec/vigilem/evdev/device_capabilities_spec.rb +0 -0
  44. data/spec/vigilem/evdev/device_spec.rb +97 -0
  45. data/spec/vigilem/evdev/dom/adapter_spec.rb +5 -0
  46. data/spec/vigilem/evdev/dom/input_event_converter_spec.rb +253 -0
  47. data/spec/vigilem/evdev/dom/input_event_utils_spec.rb +23 -0
  48. data/spec/vigilem/evdev/focus_context_filter_spec.rb +112 -0
  49. data/spec/vigilem/evdev/input_system_handler_spec.rb +146 -0
  50. data/spec/vigilem/evdev/key_map_cache_spec.rb +65 -0
  51. data/spec/vigilem/evdev/multiplexer_spec.rb +55 -0
  52. data/spec/vigilem/evdev/system/input/input_event_spec.rb +33 -0
  53. data/spec/vigilem/evdev/system/input_spec.rb +274 -0
  54. data/spec/vigilem/evdev/system/int_spec.rb +30 -0
  55. data/spec/vigilem/evdev/system/ioctl_spec.rb +206 -0
  56. data/spec/vigilem/evdev/system/keymap_loaders/dumpkeys_loader_spec.rb +5 -0
  57. data/spec/vigilem/evdev/system/keymap_loaders/kmap_loader_spec.rb +24 -0
  58. data/spec/vigilem/evdev/system/keymap_loaders_spec.rb +22 -0
  59. data/spec/vigilem/evdev/system/posix_types_spec.rb +15 -0
  60. data/spec/vigilem/evdev/system/time_spec.rb +18 -0
  61. data/spec/vigilem/evdev/transfer_agent_spec.rb +57 -0
  62. data/spec/vigilem/evdev/vty_context_filter_spec.rb +282 -0
  63. metadata +286 -0
@@ -0,0 +1,48 @@
1
+ module Vigilem
2
+ module Evdev
3
+ module DOM
4
+ #
5
+ module InputEventUtils
6
+
7
+ include Vigilem::DOM::Utils
8
+
9
+ # takes a InputEvent#code and returns a String
10
+ # representing the keycode value
11
+ # @param [Integer] event_code, the number to convert
12
+ # @return [String] i.e. "keycode30"
13
+ def event_code_to_keycode_str(event_code)
14
+ "keycode#{event_code}"
15
+ end
16
+
17
+ # takes a keycode_name and returns a common location string
18
+ # if available
19
+ # @param [String || Symbol] keycode_name, i.e. KEY_RIGTHCTRL
20
+ # @return [String || NilClass] a common locaiton string i.e. 'Right'
21
+ def location_str_from_keycode_name(keycode_name)
22
+ if loc = keycode_name.to_s.gsub('KP', 'NUMPAD').scan(/LEFT|RIGHT|NUMPAD/i).first
23
+ loc.downcase.tap {|obj| obj[0] = obj[0].upcase }
24
+ end
25
+ end
26
+
27
+ # takes a keycode name and returns the keymap modifier name
28
+ # @todo meta
29
+ # @param [String ||Symbol] keycode_name, i.e. KEY_RIGHTCTRL
30
+ # @return [String] keymap_name of the modifier
31
+ def modifier_keymap_name(keycode_name)
32
+ if (keycode_name) =~ /caps|shift|alt|c(on)?tro?l/i
33
+ if keycode_name == :KEY_CAPSLOCK
34
+ 'capsshift'
35
+ else
36
+ keycode_name.to_s.gsub(/KEY_/, '').split(/ight|eft/i).reverse.join.downcase
37
+ end
38
+ end
39
+ end
40
+
41
+ extend self
42
+
43
+ extend Support::Utils
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,248 @@
1
+ require 'vigilem/support/key_map'
2
+
3
+ require 'vigilem/evdev/system'
4
+
5
+ module Vigilem
6
+ module Evdev::DOM
7
+ module KeyValuesTables
8
+
9
+ include Evdev::System::Input::KeysAndButtons
10
+
11
+ SpecialKeyValues = Support::KeyMap.new({'Unidentified' => nil })
12
+ ModifierKeys = Support::KeyMap.new.fuse!({
13
+ :'?' => 'Accel',
14
+ KEY_LEFTALT => 'Alt',
15
+ KEY_RIGHTALT => 'Alt'}, {
16
+ :'?' => 'AltGraph',
17
+ KEY_CAPSLOCK => 'CapsLock',
18
+ 'CtrlL_Lock' => 'CapsLock',
19
+ KEY_LEFTCTRL => 'Control',
20
+ KEY_RIGHTCTRL => 'Control',
21
+ 'Control' => 'Control'}, {
22
+ :'?' => ['Fn', 'FnLock', 'Hyper'],
23
+ KEY_LEFTMETA => 'Meta',
24
+ KEY_RIGHTMETA => 'Meta',
25
+ KEY_NUMLOCK => 'NumLock',
26
+ KEY_LEFTMETA => 'OS',
27
+ KEY_SCROLLLOCK => 'ScrollLock',
28
+ KEY_LEFTSHIFT => 'Shift',
29
+ KEY_RIGHTSHIFT => 'Shift'}, {
30
+ :'?' => ['Super', 'Symbol', 'SymbolLock']
31
+ })
32
+
33
+ WhitespaceKeys = Support::KeyMap.new({
34
+ KEY_ENTER => 'Enter',
35
+ 'KP_Enter' => 'Enter',
36
+ :'?' => 'Separator',
37
+ 'Tab' => 'Tab',
38
+ KEY_TAB => 'Tab'
39
+ })
40
+ # Space
41
+
42
+ NavigationKeys = Support::KeyMap.new({
43
+ KEY_DOWN => 'ArrowDown',
44
+ 'Down' => 'ArrowDown',
45
+ 'KP_2' => 'ArrowDown',
46
+ KEY_LEFT => 'ArrowLeft',
47
+ 'Left' => 'ArrowLeft',
48
+ 'KP_4' => 'ArrowLeft',
49
+ KEY_RIGHT => 'ArrowRight',
50
+ 'Right' => 'ArrowRight',
51
+ 'KP_6' => 'ArrowRight',
52
+ KEY_UP => 'ArrowUp',
53
+ 'Up' => 'ArrowUp',
54
+ 'KP_8' => 'ArrowUp',
55
+ KEY_END => 'End',
56
+ 'KP_1' => 'End',
57
+ KEY_HOME => 'Home',
58
+ 'KP_7' => 'Home',
59
+ KEY_PAGEDOWN => 'PageDown',
60
+ 'KP_3' => 'PageDown',
61
+ KEY_PAGEUP => 'PageUp',
62
+ 'KP_9' => 'PageUp'
63
+ })
64
+
65
+ EditingKeys = Support::KeyMap.new.fuse!({
66
+ KEY_BACKSPACE => 'Backspace',
67
+ KEY_CLEAR => 'Clear',
68
+ KEY_COPY => 'Copy',
69
+ :'?' => 'CrSel',
70
+ KEY_CUT => 'Cut',
71
+ KEY_DELETE => 'Delete'}, {
72
+ :'?' => ['EraseEof', 'ExSel'],
73
+ KEY_INSERT => 'Insert',
74
+ KEY_PASTE => 'Paste',
75
+ KEY_REDO => 'Redo',
76
+ KEY_UNDO => 'Undo'
77
+ })
78
+ UIKeys = Support::KeyMap.new.fuse!({
79
+ :'?' => 'Accept',
80
+ KEY_AGAIN => 'Again'}, {
81
+ :'?' => 'Attn',
82
+ KEY_CANCEL => 'Cancel',
83
+ KEY_COMPOSE => 'ContextMenu',
84
+ KEY_ESC => 'Escape'}, {
85
+ :'?' => 'Execute',
86
+ KEY_FIND => 'Find',
87
+ KEY_HELP => 'Help',
88
+ KEY_PAUSE => 'Pause',
89
+ KEY_PLAY => 'Play',
90
+ KEY_PROPS => 'Props',
91
+ KEY_SELECT => 'Select',
92
+ KEY_ZOOMIN => 'ZoomIn',
93
+ KEY_ZOOMOUT => 'ZoomOut'
94
+ })
95
+
96
+ DeviceKeys = Support::KeyMap.new.fuse!({
97
+ :'?' => ['BrightnessDown', 'BrightnessUp'],
98
+ KEY_CAMERA => 'Camera',
99
+ KEY_EJECTCD => 'Eject',
100
+ KEY_EJECTCLOSECD => 'Eject'}, {
101
+ :'?' => ['LogOff', 'Power', 'PowerOff'],
102
+ KEY_PRINT => 'PrintScreen'}, {
103
+ :'?' => ['Hibernate', 'Standby', 'WakeUp']
104
+ })
105
+ IMEandCompositionKeys = Support::KeyMap.new.fuse!({
106
+ :'?' => ['AllCandidates', 'Alphanumeric',
107
+ 'CodeInput'],
108
+ KEY_COMPOSE => 'Compose'}, {
109
+ :'?' => ['Convert', 'Dead', 'FinalMode',
110
+ 'GroupFirst', 'GroupLast'],
111
+ KEY_KBDINPUTASSIST_NEXTGROUP => 'GroupNext',
112
+ KEY_KBDINPUTASSIST_PREVGROUP => 'GroupPrevious',
113
+ KEY_MODE => 'ModeChange'}, {
114
+ :'?' => ['NextCandidate', 'NonConvert',
115
+ 'PreviousCandidate', 'Process',
116
+ 'SingleCandidate']
117
+ })
118
+ KeysspecifictoKoreankeyboards = Support::KeyMap.new.fuse!({
119
+ KEY_HANGEUL => 'HangulMode',
120
+ KEY_HANJA => 'HanjaMode',
121
+ :'?' => 'JunjaMode'
122
+ })
123
+ KeysspecifictoJapanesekeyboards = Support::KeyMap.new.fuse!({
124
+ :'?' => ['Eisu', 'Hankaku'],
125
+ KEY_HIRAGANA => 'Hiragana',
126
+ KEY_KATAKANAHIRAGANA => 'HiraganaKatakana'}, {
127
+ :'?' => ['KanaMode', 'KanjiMode'],
128
+ KEY_KATAKANA => 'Katakana'}, {
129
+ :'?' => ['Romaji', 'Zenkaku'],
130
+ KEY_ZENKAKUHANKAKU => 'ZenkakuHankaku'
131
+ })
132
+ General_PurposeFunctionKeys = Support::KeyMap.new({
133
+ KEY_F1 => 'F1',
134
+ KEY_F2 => 'F2',
135
+ KEY_F3 => 'F3',
136
+ KEY_F4 => 'F4',
137
+ KEY_F5 => 'F5',
138
+ KEY_F6 => 'F6',
139
+ KEY_F7 => 'F7',
140
+ KEY_F8 => 'F8',
141
+ KEY_F9 => 'F9',
142
+ KEY_F10 => 'F10',
143
+ KEY_F11 => 'F11',
144
+ KEY_F12 => 'F12',
145
+ :'?' => ['Soft1', 'Soft2', 'Soft3', 'Soft4']
146
+ })
147
+
148
+ MultimediaKeys = Support::KeyMap.new.fuse!({
149
+ KEY_CLOSECD => 'Close',
150
+ KEY_EJECTCLOSECD => 'Close',
151
+ KEY_FORWARDMAIL => 'MailForward',
152
+ KEY_REPLY => 'MailReply',
153
+ :'?' => 'MailSend'}, {
154
+ KEY_PLAYPAUSE => 'MediaPlayPause',
155
+ :'?' => 'MediaSelect', #too many option need to test
156
+ KEY_STOPCD => 'MediaStop',
157
+ KEY_NEXTSONG => 'MediaTrackNext',
158
+ KEY_PREVIOUSSONG => 'MediaTrackPrevious',
159
+ KEY_NEW => 'New',
160
+ KEY_OPEN => 'Open',
161
+ KEY_PRINT => 'Print',
162
+ KEY_SAVE => 'Save',
163
+ KEY_SPELLCHECK => 'SpellCheck',
164
+ KEY_VOLUMEDOWN => 'VolumeDown',
165
+ KEY_VOLUMEUP => 'VolumeUp',
166
+ KEY_MUTE => 'VolumeMute'
167
+ })
168
+
169
+ ApplicationKeys = Support::KeyMap.new({
170
+ KEY_CALC => 'LaunchCalculator',
171
+ KEY_CALENDAR => 'LaunchCalendar',
172
+ KEY_MAIL => 'LaunchMail',
173
+ KEY_PLAYER => ['LaunchMediaPlayer', 'LaunchMusicPlayer'],
174
+ KEY_PC => 'LaunchMyComputer',
175
+ KEY_COFFEE => 'LaunchScreenSaver',
176
+ KEY_SPREADSHEET => 'LaunchSpreadsheet',
177
+ KEY_WWW => 'LaunchWebBrowser',
178
+ :'?' => 'LaunchWebCam', #how's this differ from KEY_CAMERA?
179
+ KEY_WORDPROCESSOR => 'LaunchWordProcessor'
180
+ })
181
+
182
+ BrowserKeys = Support::KeyMap.new({
183
+ :'?' => ['BrowserBack','BrowserFavorites', 'BrowserForward',
184
+ 'BrowserHome', 'BrowserRefresh', 'BrowserSearch',
185
+ 'BrowserStop']
186
+ })
187
+
188
+ MediaControllerKeys = Support::KeyMap.new().fuse!({
189
+ :'?' => ['AudioBalanceLeft', 'AudioBalanceRight']}, {
190
+ KEY_BASSBOOST => ['AudioBassBoostDown', 'AudioBassBoostUp'],
191
+ :'?' => ['AudioFaderFront', 'AudioFaderRear',
192
+ 'AudioSurroundModeNext', 'AVRInput', 'AVRPower'],
193
+ KEY_CHANNELDOWN => 'ChannelDown',
194
+ KEY_CHANNELUP => 'ChannelUp',
195
+ KEY_RED => 'ColorF0Red',
196
+ KEY_GREEN => 'ColorF1Green',
197
+ KEY_YELLOW => 'ColorF2Yellow',
198
+ KEY_BLUE => 'ColorF3Blue'}, {
199
+ :'?' => ['ColorF4Grey', 'ColorF5Brown', 'ClosedCaptionToggle',
200
+ 'Dimmer', 'DisplaySwap', 'Exit',
201
+ 'FavoriteClear0', 'FavoriteClear1',
202
+ 'FavoriteClear2', 'FavoriteClear3',
203
+ 'FavoriteRecall0', 'FavoriteRecall1',
204
+ 'FavoriteRecall2', 'FavoriteRecall3',
205
+ 'FavoriteStore0', 'FavoriteStore1',
206
+ 'FavoriteStore2', 'FavoriteStore3',
207
+ 'Guide', 'GuideNextDay', 'GuidePreviousDay',
208
+ 'Info', 'InstantReplay', 'Link',
209
+ 'ListProgram', 'LiveContent', 'Lock',
210
+ 'MediaApps', 'MediaFastForward', 'MediaLast',
211
+ 'pMediaPause', 'MediaPlay', 'MediaRecord'],
212
+ KEY_REWIND => 'MediaRewind'}, {
213
+ :'?' => ['MediaSkip', 'NextFavoriteChannel',
214
+ 'NextUserProfile', 'OnDemand', 'PinPDown',
215
+ 'PinPMove', 'PinPToggle', 'PinPUp',
216
+ 'PlaySpeedDown', 'PlaySpeedReset',
217
+ 'PlaySpeedUp', 'RandomToggle', 'RcLowBattery',
218
+ 'RecordSpeedNext', 'RfBypass',
219
+ 'ScanChannelsToggle', 'ScreenModeNext',
220
+ 'Settings', 'SplitScreenToggle', 'STBInput',
221
+ 'STBPower', 'Subtitle', 'Teletext', 'TV',
222
+ 'TVInput', 'TVPower', 'VideoModeNext',
223
+ 'Wink', 'ZoomToggle', 'BrowserBack',
224
+ 'BrowserForward', 'ContextMenu', 'Eject',
225
+ 'End', 'Enter', 'Home', 'MediaPlayPause',
226
+ 'MediaStop', 'MediaNextTrack', 'MediaPreviousTrack',
227
+ 'Power', 'VolumeDown', 'VolumeUp', 'VolumeMute']
228
+ })
229
+ end
230
+
231
+ KeyTable = KeyValuesTables.constants.each_with_object(Support::KeyMap.new) do |table_name, memo|
232
+ if (key_map = KeyValuesTables.const_get(table_name)).is_a? Hash
233
+ key_map.right_side_alias(:dom_code)
234
+ key_map.right_side_alias(:dom_codes)
235
+ key_map.left_side_alias(:keycode)
236
+ key_map.left_side_alias(:keycodes)
237
+ key_map.left_side_alias(:keysym)
238
+ key_map.left_side_alias(:keysyms)
239
+ memo.merge! key_map
240
+ end
241
+ end
242
+
243
+ KeyTable.right_side_alias(:dom_code)
244
+ KeyTable.right_side_alias(:dom_codes)
245
+ KeyTable.left_side_alias(:keycode)
246
+ KeyTable.left_side_alias(:keycodes)
247
+ end
248
+ end
@@ -0,0 +1,52 @@
1
+ require 'vigilem/support/key_map'
2
+
3
+ require 'vigilem/evdev/system/input'
4
+
5
+ module Vigilem
6
+ module Evdev
7
+ module DOM
8
+ # keycode or sym...
9
+ KPTable = Support::KeyMap.new({
10
+ 'KP_Space' => "\u0020",
11
+ 'KP_Tab' => "\u0009",
12
+ 'KP_Enter' => "\u000d",
13
+ 'KP_F1' => "\u0000",
14
+ 'KP_F2' => "\u0000",
15
+ 'KP_F3' => "\u0000",
16
+ 'KP_F4' => "\u0000",
17
+ 'KP_Home' => "\u0000",
18
+ 'KP_Left' => "\u0000",
19
+ 'KP_Up' => "\u0000",
20
+ 'KP_Right' => "\u0000",
21
+ 'KP_Down' => "\u0000",
22
+ 'KP_Prior' => "\u0000",
23
+ 'KP_Next' => "\u0000",
24
+ 'KP_End' => "\u0000",
25
+ 'KP_Begin' => "\u0000",
26
+ 'KP_Insert' => "\u0000",
27
+ 'KP_Delete' => "\u0000",
28
+ 'KP_Multiply' => "\u002a",
29
+ 'KP_Add' => "\u002b",
30
+ 'KP_Separator' => "\u002c",
31
+ 'KP_Subtract' => "\u002d",
32
+ 'KP_Decimal' => "\u002e",
33
+ 'KP_Period' => "\u002e",
34
+ 'KP_Divide' => "\u002f",
35
+ 'KP_0' => "\u0030",
36
+ 'KP_1' => "\u0031",
37
+ 'KP_2' => "\u0032",
38
+ 'KP_3' => "\u0033",
39
+ 'KP_4' => "\u0034",
40
+ 'KP_5' => "\u0035",
41
+ 'KP_6' => "\u0036",
42
+ 'KP_7' => "\u0037",
43
+ 'KP_8' => "\u0038",
44
+ 'KP_9' => "\u0039",
45
+ 'KP_Equal' => "\u003d",
46
+ })
47
+ KPTable.right_side_alias(:char)
48
+ KPTable.left_side_alias(:sym)
49
+ KPTable.left_side_alias(:keysym)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,124 @@
1
+ require 'vigilem/_evdev'
2
+
3
+ require 'vigilem/evdev/context_filter'
4
+
5
+ require 'vigilem/x11/stat'
6
+
7
+ module Vigilem
8
+ module Evdev
9
+ #
10
+ # allows input_events through when the window has focus
11
+ class FocusContextFilter
12
+
13
+ include Evdev::ContextFilter
14
+
15
+ class << self
16
+
17
+ #
18
+ # @return [String || NilClass]
19
+ def env_display
20
+ ENV['DISPLAY']
21
+ end
22
+
23
+ #
24
+ #
25
+ def lazy_require
26
+ require 'vigilem/x11/terminal_window_utils'
27
+ require 'vigilem/x11/input_system_handler'
28
+ end
29
+
30
+ #
31
+ # @param [String] display
32
+ # @param [Integer ||NilClass] xwindow_id
33
+ # @param [FocusContextFilter || NilClass]
34
+ # @return [NilClass || self]
35
+ def new_if_installed(display=env_display, xwindow_id=nil)
36
+ if X11::Stat.default.installed?
37
+ new(display, xwindow_id)
38
+ end
39
+ end
40
+
41
+ #
42
+ # @param [String] display
43
+ # @param [Integer || NilClass] xwindow_id
44
+ # @raise [RuntimeError]
45
+ # @return [NilClass || self]
46
+ def new_if_installed!(display=env_display, xwindow_id=nil)
47
+ new_if_installed(display, xwindow_id) || raise('InputSystem unavailable')
48
+ end
49
+
50
+ end
51
+
52
+ attr_accessor :input_system_handler
53
+
54
+ def_delegators :input_system_handler, :display, :window_xid
55
+
56
+ #
57
+ # @param [String]
58
+ # @param [Integer || NilClass]
59
+ def initialize(display=self.class.env_display, xwindow_id=nil)
60
+ self.class.lazy_require
61
+ window_xid = xwindow_id || X11::TerminalWindowUtils.window_id
62
+
63
+ @input_system_handler = X11::InputSystemHandler.new(window_xid, display, Xlib::FocusChangeMask)
64
+ end
65
+
66
+ #
67
+ # @return [TrueClass || FalseClass]
68
+ def has_focus?
69
+ with_focus = X11.get_input_focus(self.display, window_xid)[1]
70
+ with_focus == self.window_xid or
71
+ self.window_xid == X11.query_tree(self.display, with_focus)[:parent_return]
72
+ end
73
+
74
+ alias_method :had_focus?, :was_off?
75
+
76
+ #
77
+ # @return [TrueClass || FalseClass]
78
+ def on?
79
+ if gained_focus?
80
+ on_change(OFF)
81
+ elsif lost_focus?
82
+ on_change(ON)
83
+ end
84
+ was_on?
85
+ end
86
+
87
+ #
88
+ # @return [TrueClass || FalseClass]
89
+ def off?
90
+ not on?
91
+ end
92
+
93
+ #
94
+ # @return [TrueClass || FalseClass]
95
+ def gained_focus?
96
+ (not had_focus?) and has_focus?
97
+ end
98
+
99
+ #
100
+ # @return [TrueClass || FalseClass]
101
+ def lost_focus?
102
+ had_focus? and not has_focus?
103
+ end
104
+
105
+ #
106
+ # @param [Array] events
107
+ # @return [Array]
108
+ def process(*events)
109
+ if on?
110
+ []
111
+ else
112
+ events
113
+ end
114
+ end
115
+
116
+ private
117
+ #
118
+ # @param [TrueClass || FalseClass] bool
119
+ # @return
120
+ alias_method :had_focus= ,:was_off=
121
+
122
+ end
123
+ end
124
+ end