-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkey_grabber.c
187 lines (160 loc) · 5.41 KB
/
key_grabber.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include <gtk/gtk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include "key_grabber.h"
#include "menu.h"
#include "config.h"
#include "stored_items.h"
typedef enum {
glipperus_ACTION_SHOW_MENU,
glipperus_ACTION_COPY,
glipperus_ACTION_PASTE,
} KeyAction;
typedef struct {
guchar keycode, modifier;
KeyAction action;
XEvent *current_event;
RuntimeSettings *rts;
} Key;
GSList *kList = NULL; //List of keys
Display *dpy;
Window root;
int NumLockMask, CapsLockMask, ScrollLockMask;
void init_keyboard()
{
XModifierKeymap *xmk=NULL;
KeyCode *map;
int m, k;
xmk=XGetModifierMapping(dpy);
if(xmk)
{
map=xmk->modifiermap;
for(m=0;m<8;m++)
for(k=0;k<xmk->max_keypermod; k++, map++)
{
if(*map==XKeysymToKeycode(dpy, XK_Num_Lock))
NumLockMask=(1<<m);
if(*map==XKeysymToKeycode(dpy, XK_Caps_Lock))
CapsLockMask=(1<<m);
if(*map==XKeysymToKeycode(dpy, XK_Scroll_Lock))
ScrollLockMask=(1<<m);
}
XFreeModifiermap(xmk);
}
}
void grab_key(guchar keycode, unsigned int modifiers, Window w, KeyAction assigned_action) {
Key *k;
k = g_new0(Key, 1);
k->keycode = keycode;
k->modifier = modifiers;
k->action = assigned_action;
kList = g_slist_append(kList, k);
glipperus_debug("Zarejestrowano do grabowania klawisz %d, z modifikatorem %d\n", k->keycode, k->modifier);
//rejestrujemy grabowniae klawiszy dl różnyc stanów NumLocka Srocka itp...
XGrabKey(dpy, keycode, modifiers, w, False, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, keycode, modifiers|NumLockMask, w, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, keycode, modifiers|CapsLockMask, w, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, keycode, modifiers|ScrollLockMask, w, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, keycode, modifiers|NumLockMask|CapsLockMask, w, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, keycode, modifiers|NumLockMask|ScrollLockMask, w, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, keycode, modifiers|NumLockMask|CapsLockMask|ScrollLockMask, w, True, GrabModeAsync, GrabModeAsync);
}
void initialize(void) {
//opens default display
dpy = XOpenDisplay(NULL);
if (!dpy) {
g_error(_("glipperus error: Cannot open default XDisplay.\n"));
}
//gets rootWindow
root = XDefaultRootWindow(dpy);
if (!root) {
g_error(_("glipperus error: Cannot open root window\n"));
}
init_keyboard();
}
void position_thy_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) {
XEvent *ev = user_data;
glipperus_debug("%s jest menu\n", GTK_IS_MENU(menu) ?"Tak to":"Nie to nie");
XNextEvent(dpy, ev); //zdejmujemy ten event
push_in = (gboolean *) TRUE;
x = (gint *) 100;
y = (gint *) 100;
}
static void do_key_acton(KeyAction action, XEvent *ev, RuntimeSettings *rts) {
glipperus_debug("Wykonujemy %d \n", action);
switch (action) {
case glipperus_ACTION_SHOW_MENU: {
GtkWidget *menu;
menu = glipperus_contextMenu_new(rts);
gtk_menu_popup(GTK_MENU(menu),
NULL,
NULL, (GtkMenuPositionFunc)position_thy_menu,
ev,
ev->xbutton.button,
ev->xbutton.time);
glipperus_debug("Żygaj menu \n");
break;
}
case glipperus_ACTION_PASTE:
glipperus_debug("Wklejasz ziom \n");
XNextEvent(dpy, ev); //zdejmujemy ten event
break;
case glipperus_ACTION_COPY:
glipperus_debug("Kopiujuesz ziom \n");
XNextEvent(dpy, ev); //zdejmujemy ten event
break;
default:
glipperus_debug("Printf próba wykonania nieznzny action nr. %d \n", action);
}
}
void porownaj_klawisze(gpointer stored_Key, gpointer EvData) {
Key *key = stored_Key;
Key *event_data = EvData;
XEvent *ev = event_data->current_event; //hmm..
ev->xkey.state=ev->xkey.state&(Mod1Mask|ControlMask|ShiftMask);
if (key->keycode == ev->xkey.keycode && key->modifier==ev->xkey.state) do_key_acton(key->action, ev, event_data->rts);
}
static void sprawdz_wcisk(XEvent *ev, RuntimeSettings *rts) {
Key *k = g_new0(Key, 1);
k->current_event = ev;
k->rts = rts;
glipperus_debug("Porownanie klaiwszy\n");
g_slist_foreach(kList, (GFunc)porownaj_klawisze, k);
g_free(k);
}
static gboolean nasluch_klawiszy(gpointer data) {
RuntimeSettings *rts = (RuntimeSettings*) data;
glipperus_debug("Początek działania w timoucie \n");
if(XPending(dpy)) {
XEvent ev;
//XPeekEvent(dpy, &ev);
XNextEvent(dpy, &ev);
if(ev.type==KeyPress) {
XPutBackEvent(dpy, &ev);
// czyli że prawie nie wiem o co chodzi: Do gtk_menu_popup musi
// być puszczony event aby mógł natysować to menu. Jeżeli byśmy go zdjęli
// i nie odłożyli (za pomocą XPutBackEvent) to manu się rysuje bardz-czasami. (Bez sensu).
//
//GtkWidget *menu;
//menu = glipperus_contextMenu_new(rts);
//gtk_menu_set_screen (GTK_MENU(menu), gdk_screen_get_default());
sprawdz_wcisk(&ev, rts);
} //koniec przetwarzania zdarzenia KeyPressed
glipperus_debug("Przetwarzamy zdzarznie typu %d \n", ev.type);
}
return TRUE;
}
void glipperus_assign_keygrab(RuntimeSettings *rts) {
initialize();
guchar modifier = 0;
modifier = modifier|ControlMask;
modifier = modifier|Mod1Mask;
guchar keycode = XKeysymToKeycode(dpy, XStringToKeysym("v"));
grab_key(keycode, modifier, root, glipperus_ACTION_SHOW_MENU);
/* Ahh byłoby pięknie
modifier = 0;
modifier = modifier|ControlMask;
grab_key(106, modifier, root, glipperus_ACTION_COPY); */
g_timeout_add(KEY_GRABBER_INTERVAL_MS, (GSourceFunc)nasluch_klawiszy, rts);
}