2
Copyright 2010 Vincent Carmona
5
This file is part of rghk.
7
rghk is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
rghk is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with ZiK; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
#include <gdk/gdkevents.h>
27
//take a look at http://www.gnu.org/prep/standards/standards.html
34
RGHK_CONTROL_MASK=1<<2,
40
RGHK_NUM_LOCK_MASK=RGHK_MOD2_MASK//Is it true for all keyboards?
49
* call-seq: bind(key, modifier) {block}
51
* key: a key value. Gdk::Keyval constants can be used.
53
* modifier: a GlobalHotKeys::Modifier.
55
* Set a global hotkey.
56
* block will be called when the key and the modifier are hitted.
59
kb_bind(VALUE self, VALUE key, VALUE modifier)
64
/* uint ignored[]={0, RGHK_LOCK_MASK, RGHK_NUM_LOCK_MASK, RGHK_SCROLL_LOCK,
65
RGHK_LOCK_MASK|RGHK_NUM_LOCK_MASK, RGHK_LOCK_MASK|RGHK_SCROLL_LOCK, RGHK_NUM_LOCK_MASK|RGHK_SCROLL_LOCK,
66
RGHK_LOCK_MASK|RGHK_NUM_LOCK_MASK|RGHK_SCROLL_LOCK};*/
67
uint ignored[]={0, RGHK_LOCK_MASK, RGHK_NUM_LOCK_MASK, RGHK_LOCK_MASK|RGHK_NUM_LOCK_MASK};
70
if (rb_funcall(rb_iv_get(cKeyBinder, "stock"), rb_intern("include?"), 1, self)==Qtrue)
71
rb_raise(rb_eException, "KeyBinder allready binded.");
73
rb_iv_set(self, "@key", key);
74
rb_iv_set(self, "@mod", modifier);
75
rb_iv_set(self, "block", rb_block_proc());
76
rb_ary_push(rb_iv_get(cKeyBinder, "stock"), self);
78
rootwin=gdk_get_default_root_window();//stock this window in variable once for all?
79
xdisplay=GDK_WINDOW_XDISPLAY(rootwin);
81
keycode=XKeysymToKeycode(xdisplay, FIX2UINT(key));
83
rb_raise(rb_eException, "Invalid key value.");
88
mod=FIX2UINT(modifier);
93
XGrabKey(xdisplay, keycode, mod|ignored[i], GDK_WINDOW_XWINDOW(rootwin), False,
94
GrabModeAsync, GrabModeAsync);
96
//XGrabKey(xdisplay, keycode, AnyModifier, GDK_WINDOW_XWINDOW(rootwin), False, GrabModeAsync, GrabModeAsync);
101
* Unset a global hotkey.
104
kb_unbind(VALUE self)
110
uint ignored[]={0, RGHK_LOCK_MASK, RGHK_NUM_LOCK_MASK, RGHK_LOCK_MASK|RGHK_NUM_LOCK_MASK};
112
del=rb_funcall(rb_iv_get(cKeyBinder, "stock"), rb_intern("delete"), 1, self);
116
rootwin=gdk_get_default_root_window();
117
xdisplay=GDK_WINDOW_XDISPLAY(rootwin);
118
keycode=XKeysymToKeycode(xdisplay, FIX2UINT(rb_iv_get(self, "@key")));
119
mod=FIX2UINT(rb_iv_get(self, "@mod"));
123
XUngrabKey(xdisplay, keycode, mod|ignored[i], GDK_WINDOW_XWINDOW (rootwin));
128
* Unset a all global hotkeys.
131
kb_unbind_all(VALUE self)
133
rb_iterate(rb_each, rb_iv_get(cKeyBinder, "stock"), kb_unbind, Qnil);
138
process(VALUE kb_obj, VALUE xkey)
140
//rb_funcall(rb_stdout, rb_intern("puts"), 1, RARRAY(xkey)->ptr[1]);
141
uint keycode=XKeysymToKeycode(GDK_WINDOW_XDISPLAY(gdk_get_default_root_window()), FIX2UINT(rb_iv_get(kb_obj, "@key")));
143
if (keycode==FIX2UINT(RARRAY(xkey)->ptr[0]))
145
uint ignored=RGHK_LOCK_MASK|RGHK_NUM_LOCK_MASK;
146
uint mod=FIX2UINT(RARRAY(xkey)->ptr[1])&~ignored;
149
if NIL_P(rb_iv_get(kb_obj, "@mod"))
152
keymod=FIX2UINT(rb_iv_get(kb_obj, "@mod"));
155
rb_funcall(rb_iv_get(kb_obj, "block"), rb_intern("call"), 1, kb_obj);
161
filter_func(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
164
XEvent *xevent=(XEvent*)gdk_xevent;
166
if (xevent->type==KeyPress)
168
VALUE xev=rb_ary_new3(2, INT2FIX(xevent->xkey.keycode), INT2FIX(xevent->xkey.state));
170
rb_iterate(rb_each, rb_iv_get(cKeyBinder, "stock"), process, xev);
173
return GDK_FILTER_CONTINUE;
176
// :nodoc: It is called by rghk when it is required.
180
gdk_window_add_filter(gdk_get_default_root_window(), filter_func, NULL);
188
* rghk provides a simple way to set global hotkeys.
191
* kb=GlobalHotKeys::KeyBinder.new
192
* kb.bind(Gdk::Keyval::GDK_a, GlobalHotKeys::Modifier::CONTROL_MASK){puts 'Binded'}
195
* It probably a good idea to require 'gtk2' before 'rghk'.
196
* The librairy rghk was not tested without ruby/gtk2.
198
mGlobalHotKeys=rb_define_module("GlobalHotKeys");
199
rb_define_module_function(mGlobalHotKeys, "init", mInit, 0);
201
mModifier=rb_define_module_under(mGlobalHotKeys, "Modifier");
202
rb_define_const(mModifier, "SHIFT_MASK", INT2FIX(RGHK_SHIFT_MASK));
203
rb_define_const(mModifier, "CONTROL_MASK", INT2FIX(RGHK_CONTROL_MASK));
204
rb_define_const(mModifier, "MOD1_MASK", INT2FIX(RGHK_MOD1_MASK));//Alt
205
//rb_define_const(mModifier, "MOD2_MASK", INT2FIX(RGHK_MOD2_MASK));//NUM_LOCK
206
rb_define_const(mModifier, "MOD3_MASK", INT2FIX(RGHK_MOD3_MASK));
207
rb_define_const(mModifier, "MOD4_MASK", INT2FIX(RGHK_MOD4_MASK));
208
rb_define_const(mModifier, "MOD5_MASK", INT2FIX(RGHK_MOD5_MASK));//AltGr?
210
cKeyBinder=rb_define_class_under(mGlobalHotKeys, "KeyBinder", rb_cObject);
211
rb_iv_set(cKeyBinder, "stock", rb_ary_new());
212
rb_define_method(cKeyBinder, "bind", kb_bind, 2);
213
rb_define_method(cKeyBinder, "unbind", kb_unbind, 0);
214
rb_define_module_function(cKeyBinder, "unbind_all", kb_unbind_all,0);