xlib_ruby 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/.gitignore +5 -0
- data/ext/Makefile.test +4 -0
- data/ext/extconf.rb +26 -0
- data/ext/x11.c +512 -0
- data/ext/x11.h +76 -0
- data/ext/x11_wrap.c +712 -0
- data/lib/ruby-x11.rb +119 -0
- data/lib/windowmanager.rb +56 -0
- metadata +56 -0
data/ext/x11.h
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#ifndef X11_RUBY_H
|
2
|
+
#define X11_RUBY_H
|
3
|
+
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <unistd.h>
|
7
|
+
#include <string.h>
|
8
|
+
#include <X11/keysym.h>
|
9
|
+
#include <X11/Xatom.h>
|
10
|
+
#include <X11/Xlib.h>
|
11
|
+
#include <X11/Xproto.h>
|
12
|
+
#include <X11/Xutil.h>
|
13
|
+
#include <locale.h>
|
14
|
+
|
15
|
+
enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
|
16
|
+
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
|
17
|
+
|
18
|
+
typedef struct Client_t Client;
|
19
|
+
typedef struct WM_t WM;
|
20
|
+
|
21
|
+
struct Client_t {
|
22
|
+
char name[256];
|
23
|
+
char class[256];
|
24
|
+
int x,y,w,h;
|
25
|
+
int rx,ry,rw,rh; //revert geo
|
26
|
+
int basew,baseh,incw,inch,maxw,maxh,minw,minh;
|
27
|
+
int minax,maxax,minay,maxay;
|
28
|
+
long flags;
|
29
|
+
unsigned int border, oldborder;
|
30
|
+
Bool isbanned, isfixed, ismax, isfloating, wasfloating;
|
31
|
+
WM *manager;
|
32
|
+
Window win;
|
33
|
+
};
|
34
|
+
|
35
|
+
typedef struct Key_t {
|
36
|
+
unsigned long mod;
|
37
|
+
KeySym keysym;
|
38
|
+
const char *arg;
|
39
|
+
void (*func)(const char *arg);
|
40
|
+
} Key;
|
41
|
+
|
42
|
+
struct WM_t {
|
43
|
+
int screen, sx, sy, sw, sh, wax, way, waw, wah;
|
44
|
+
Client *selected;
|
45
|
+
Client* order;
|
46
|
+
Display *dpy;
|
47
|
+
Window root;
|
48
|
+
Bool running;
|
49
|
+
Bool otherwm;
|
50
|
+
Bool manage_override_redirect_windows;
|
51
|
+
int (*xerrorxlib)(Display *, XErrorEvent *);
|
52
|
+
Atom wmatom[WMLast];
|
53
|
+
Atom netatom[NetLast];
|
54
|
+
unsigned int clients_num;
|
55
|
+
Client* clients;
|
56
|
+
};
|
57
|
+
|
58
|
+
int manageable_p(WM* wm, Window w);
|
59
|
+
void init_client(WM* wm, Window w, Client* c);
|
60
|
+
void manage_client(WM* wm, XWindowAttributes *wa, Client* c);
|
61
|
+
void resize(WM* winman, Client *c, int x, int y, int w, int h, int sizehints);
|
62
|
+
Client* query_clients(WM* winman);
|
63
|
+
void raise_client(Client* c);
|
64
|
+
void ban_client(Client* c);
|
65
|
+
void unban_client(Client* c);
|
66
|
+
void unborder_client(Client* c);
|
67
|
+
void border_client(Client* c, int w);
|
68
|
+
WM* Init_WM();
|
69
|
+
int event_pending(WM* winman);
|
70
|
+
int event_next_source(WM* winman);
|
71
|
+
char* event_next_type(WM* winman);
|
72
|
+
void event_pop(WM* winman);
|
73
|
+
void Destroy_WM(WM* winman);
|
74
|
+
Client* client_ftw(WM* wm, Window w);
|
75
|
+
|
76
|
+
#endif
|
data/ext/x11_wrap.c
ADDED
@@ -0,0 +1,712 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <x11.h>
|
3
|
+
|
4
|
+
// Main module
|
5
|
+
VALUE mX11,
|
6
|
+
|
7
|
+
// Classes
|
8
|
+
cClient, cWM,
|
9
|
+
cEvent, cKeyEvent, cButtonEvent, cMotionEvent, cCrossingEvent, cFocusEvent,
|
10
|
+
cFocusChangeEvent, cCreateWindowEvent, cDestroyWindowEvent, cUnmapEvent, cMapRequestEvent,
|
11
|
+
cResizeRequestEvent, cConfigureRequestEvent;
|
12
|
+
|
13
|
+
#define numKeyMasks 13
|
14
|
+
|
15
|
+
// Symbols
|
16
|
+
static ID id_client, id_x, id_y, id_button, id_keycode, id_keysym, id_state, id_mods,
|
17
|
+
id_keymasks[numKeyMasks];
|
18
|
+
// id_Button1,id_Button2,id_Button3,id_Button4,id_Button5,
|
19
|
+
// id_Shift,id_Lock,id_Control,
|
20
|
+
// id_Mod1,id_Mod2,id_Mod3,id_Mod4,id_Mod5;
|
21
|
+
|
22
|
+
static VALUE client_make(VALUE klass, Client* c); // I need this alot
|
23
|
+
static VALUE event_wrap(VALUE klass, XEvent* ev);
|
24
|
+
|
25
|
+
|
26
|
+
static VALUE x11_error_handler(VALUE self) {
|
27
|
+
return rb_iv_get(mX11,"error_handler");
|
28
|
+
}
|
29
|
+
|
30
|
+
static VALUE x11_error_handler_set(VALUE self, VALUE proc) {
|
31
|
+
if (!(NIL_P(proc) || RTEST(rb_respond_to(proc,rb_intern("call"))))) {
|
32
|
+
rb_raise(rb_eArgError,"Error handler must be a Proc or nil");
|
33
|
+
return Qnil;
|
34
|
+
}
|
35
|
+
rb_iv_set(mX11,"error_handler",proc);
|
36
|
+
return proc;
|
37
|
+
}
|
38
|
+
|
39
|
+
static int x11_internal_error_handler(Display* dpy, XErrorEvent* err) {
|
40
|
+
char message[255];
|
41
|
+
VALUE handler = rb_iv_get(mX11,"error_handler");
|
42
|
+
|
43
|
+
XGetErrorText(err->display, err->error_code, message, 254);
|
44
|
+
if (NIL_P(handler) || !RTEST(rb_respond_to(handler,rb_intern("call")))) {
|
45
|
+
fprintf(stderr,"X11 Error: %s\n", message);
|
46
|
+
} else {
|
47
|
+
rb_funcall(handler, rb_intern("call"), 2, INT2NUM(err->error_code), rb_str_new2(message));
|
48
|
+
}
|
49
|
+
return 0; // ignored
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
// Allocate a new WindowManager object
|
54
|
+
// using the supplied Init_WM
|
55
|
+
// Also do a first query
|
56
|
+
static VALUE wm_alloc(VALUE klass) {
|
57
|
+
WM* newwm;
|
58
|
+
VALUE obj;
|
59
|
+
newwm = Init_WM();
|
60
|
+
newwm->clients = query_clients(newwm);
|
61
|
+
obj = Data_Wrap_Struct(klass, 0, Destroy_WM, newwm);
|
62
|
+
return obj;
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE wm_query(VALUE self) {
|
66
|
+
WM *newwm;
|
67
|
+
Data_Get_Struct(self, WM, newwm);
|
68
|
+
newwm->clients = query_clients(newwm);
|
69
|
+
return Qnil;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE wm_sx(VALUE self) {
|
73
|
+
WM *newwm;
|
74
|
+
Data_Get_Struct(self, WM, newwm);
|
75
|
+
return INT2NUM(newwm->sx);
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE wm_sy(VALUE self) {
|
79
|
+
WM *newwm;
|
80
|
+
Data_Get_Struct(self, WM, newwm);
|
81
|
+
return INT2NUM(newwm->sy);
|
82
|
+
}
|
83
|
+
|
84
|
+
static VALUE wm_sw(VALUE self) {
|
85
|
+
WM *newwm;
|
86
|
+
Data_Get_Struct(self, WM, newwm);
|
87
|
+
return INT2NUM(newwm->sw);
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE wm_sh(VALUE self) {
|
91
|
+
WM *newwm;
|
92
|
+
Data_Get_Struct(self, WM, newwm);
|
93
|
+
return INT2NUM(newwm->sh);
|
94
|
+
}
|
95
|
+
|
96
|
+
static VALUE wm_wax(VALUE self) {
|
97
|
+
WM *newwm;
|
98
|
+
Data_Get_Struct(self, WM, newwm);
|
99
|
+
return INT2NUM(newwm->wax);
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE wm_wax_set(VALUE self, VALUE newval) {
|
103
|
+
WM *newwm;
|
104
|
+
Data_Get_Struct(self, WM, newwm);
|
105
|
+
newwm->wax = NUM2INT(newval);
|
106
|
+
return Qnil;
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE wm_manage_override_redirect_windows(VALUE self) {
|
110
|
+
WM *newwm;
|
111
|
+
Data_Get_Struct(self, WM, newwm);
|
112
|
+
return newwm->manage_override_redirect_windows ? Qtrue : Qfalse;
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE wm_manage_override_redirect_windows_set(VALUE self, VALUE flag) {
|
116
|
+
WM *newwm;
|
117
|
+
Data_Get_Struct(self, WM, newwm);
|
118
|
+
newwm->manage_override_redirect_windows = (flag == Qtrue ? 1 : 0);
|
119
|
+
return newwm->manage_override_redirect_windows ? Qtrue : Qfalse;
|
120
|
+
}
|
121
|
+
|
122
|
+
static VALUE wm_way(VALUE self) {
|
123
|
+
WM *newwm;
|
124
|
+
Data_Get_Struct(self, WM, newwm);
|
125
|
+
return INT2NUM(newwm->way);
|
126
|
+
}
|
127
|
+
|
128
|
+
static VALUE wm_way_set(VALUE self, VALUE newval) {
|
129
|
+
WM *newwm;
|
130
|
+
Data_Get_Struct(self, WM, newwm);
|
131
|
+
newwm->way = NUM2INT(newval);
|
132
|
+
return Qnil;
|
133
|
+
}
|
134
|
+
|
135
|
+
static VALUE wm_waw(VALUE self) {
|
136
|
+
WM *newwm;
|
137
|
+
Data_Get_Struct(self, WM, newwm);
|
138
|
+
return INT2NUM(newwm->waw);
|
139
|
+
}
|
140
|
+
|
141
|
+
static VALUE wm_waw_set(VALUE self, VALUE newval) {
|
142
|
+
WM *newwm;
|
143
|
+
Data_Get_Struct(self, WM, newwm);
|
144
|
+
newwm->waw = NUM2INT(newval);
|
145
|
+
return Qnil;
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE wm_wah(VALUE self) {
|
149
|
+
WM *newwm;
|
150
|
+
Data_Get_Struct(self, WM, newwm);
|
151
|
+
return INT2NUM(newwm->wah);
|
152
|
+
}
|
153
|
+
|
154
|
+
static VALUE wm_wah_set(VALUE self, VALUE newval) {
|
155
|
+
WM *newwm;
|
156
|
+
Data_Get_Struct(self, WM, newwm);
|
157
|
+
newwm->wah = NUM2INT(newval);
|
158
|
+
return Qnil;
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE wm_num_clients(VALUE self) {
|
162
|
+
WM *newwm;
|
163
|
+
Data_Get_Struct(self, WM, newwm);
|
164
|
+
return INT2NUM(newwm->clients_num);
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE wm_selected(VALUE self) {
|
168
|
+
WM *newwm;
|
169
|
+
XEvent event_return, event_saviour;
|
170
|
+
int i;
|
171
|
+
|
172
|
+
Data_Get_Struct(self, WM, newwm);
|
173
|
+
|
174
|
+
// Cycle through focus events and get the most recent
|
175
|
+
XCheckTypedEvent(newwm->dpy, FocusIn, &event_return);
|
176
|
+
/*
|
177
|
+
while (XCheckTypedEvent(newwm->dpy, FocusIn, &event_return))
|
178
|
+
*/
|
179
|
+
event_saviour = event_return;
|
180
|
+
for (i=0; i<newwm->clients_num; i++)
|
181
|
+
if (&newwm->clients[i].win == &event_saviour.xany.window)
|
182
|
+
newwm->selected = &newwm->clients[i];
|
183
|
+
return client_make(cClient, newwm->selected);
|
184
|
+
}
|
185
|
+
|
186
|
+
static VALUE wm_clients(VALUE self) {
|
187
|
+
WM *newwm;
|
188
|
+
//Client *c;
|
189
|
+
VALUE obj;
|
190
|
+
VALUE arr;
|
191
|
+
int i;
|
192
|
+
|
193
|
+
arr = rb_ary_new();
|
194
|
+
Data_Get_Struct(self, WM, newwm);
|
195
|
+
for (i=0; i<newwm->clients_num; i++) {
|
196
|
+
obj = client_make(cClient, &newwm->clients[i]);
|
197
|
+
rb_ary_push(arr, obj);
|
198
|
+
}
|
199
|
+
return arr;
|
200
|
+
}
|
201
|
+
|
202
|
+
static VALUE wm_pending_event_count(VALUE self) {
|
203
|
+
WM *newwm;
|
204
|
+
Data_Get_Struct(self, WM, newwm);
|
205
|
+
return INT2NUM(XPending(newwm->dpy));
|
206
|
+
}
|
207
|
+
|
208
|
+
static VALUE wm_event_next_source(VALUE self) {
|
209
|
+
WM *newwm;
|
210
|
+
int c;
|
211
|
+
|
212
|
+
Data_Get_Struct(self, WM, newwm);
|
213
|
+
c = event_next_source(newwm);
|
214
|
+
if (c > 0)
|
215
|
+
return client_make(cClient, &newwm->clients[c]);
|
216
|
+
else
|
217
|
+
return Qnil;
|
218
|
+
}
|
219
|
+
|
220
|
+
static VALUE wm_event_next_type(VALUE self) {
|
221
|
+
WM *newwm;
|
222
|
+
|
223
|
+
Data_Get_Struct(self, WM, newwm);
|
224
|
+
if (event_next_type(newwm) != NULL)
|
225
|
+
return rb_str_new2(event_next_type(newwm));
|
226
|
+
else {
|
227
|
+
return Qnil;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
static VALUE wm_event_pop(VALUE self) {
|
232
|
+
WM *newwm;
|
233
|
+
|
234
|
+
Data_Get_Struct(self, WM, newwm);
|
235
|
+
event_pop(newwm);
|
236
|
+
return Qnil;
|
237
|
+
}
|
238
|
+
|
239
|
+
static KeySym keysym_to_c(VALUE r_keysym) {
|
240
|
+
return XStringToKeysym(StringValueCStr(r_keysym));
|
241
|
+
}
|
242
|
+
|
243
|
+
static int keymask_to_c(VALUE r_mods) {
|
244
|
+
int mods = 0, i;
|
245
|
+
for (i = 0; i < numKeyMasks; i++) {
|
246
|
+
if (RTEST(rb_funcall(r_mods,rb_intern("key?"),1,ID2SYM(id_keymasks[i])))) {
|
247
|
+
mods = mods | (1 << i);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
return mods;
|
251
|
+
}
|
252
|
+
|
253
|
+
static Client* client_to_c(VALUE r_client) {
|
254
|
+
Client* c;
|
255
|
+
Data_Get_Struct(r_client,Client,c);
|
256
|
+
return c;
|
257
|
+
}
|
258
|
+
|
259
|
+
static WM* wm_to_c(VALUE r_wm) {
|
260
|
+
WM* wm;
|
261
|
+
Data_Get_Struct(r_wm,WM,wm);
|
262
|
+
return wm;
|
263
|
+
}
|
264
|
+
|
265
|
+
static VALUE wm_manage(VALUE self, VALUE r_client, VALUE x, VALUE y, VALUE w, VALUE h) {
|
266
|
+
WM* wm = wm_to_c(self);
|
267
|
+
Client* c = client_to_c(r_client);
|
268
|
+
XWindowAttributes wa;
|
269
|
+
wa.x = NUM2INT(x);
|
270
|
+
wa.y = NUM2INT(y);
|
271
|
+
wa.width = NUM2INT(w);
|
272
|
+
wa.height = NUM2INT(h);
|
273
|
+
manage_client(wm,&wa,c);
|
274
|
+
return Qtrue;
|
275
|
+
}
|
276
|
+
|
277
|
+
VALUE r_client_for_window(WM* wm, Window w) {
|
278
|
+
Client* c;
|
279
|
+
c = client_ftw(wm,w);
|
280
|
+
if (!c && manageable_p(wm,w)) {
|
281
|
+
c = (Client*) calloc(1,sizeof(Client));
|
282
|
+
init_client(wm,w,c);
|
283
|
+
}
|
284
|
+
return c ? client_make(cClient,c) : Qnil;
|
285
|
+
}
|
286
|
+
|
287
|
+
static VALUE wm_get_event(VALUE self) {
|
288
|
+
WM* wm;
|
289
|
+
XEvent* pev;
|
290
|
+
VALUE r_ev,r_mods,r_keysym;
|
291
|
+
int i;
|
292
|
+
|
293
|
+
Data_Get_Struct(self,WM,wm);
|
294
|
+
pev = (XEvent*) calloc(1,sizeof(XEvent));
|
295
|
+
XNextEvent(wm->dpy,pev);
|
296
|
+
r_ev = event_wrap(cEvent,pev);
|
297
|
+
|
298
|
+
|
299
|
+
switch(pev->type) {
|
300
|
+
|
301
|
+
case ButtonPress:
|
302
|
+
case ButtonRelease:
|
303
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xbutton.window));
|
304
|
+
rb_ivar_set(r_ev,id_x,INT2NUM(pev->xbutton.x));
|
305
|
+
rb_ivar_set(r_ev,id_y,INT2NUM(pev->xbutton.y));
|
306
|
+
break;
|
307
|
+
|
308
|
+
case KeyPress:
|
309
|
+
case KeyRelease:
|
310
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xkey.window));
|
311
|
+
rb_ivar_set(r_ev,id_keycode,INT2NUM(pev->xkey.keycode));
|
312
|
+
rb_ivar_set(r_ev,id_state,INT2NUM(pev->xkey.state));
|
313
|
+
|
314
|
+
r_keysym = rb_str_new2(XKeysymToString(XLookupKeysym((XKeyEvent*)pev,0)));
|
315
|
+
r_mods = rb_hash_new();
|
316
|
+
for (i = 0; i < numKeyMasks; i++) {
|
317
|
+
if (pev->xkey.state & (1 << i))
|
318
|
+
rb_hash_aset(r_mods,ID2SYM(id_keymasks[i]),Qtrue);
|
319
|
+
}
|
320
|
+
|
321
|
+
rb_ivar_set(r_ev,id_keysym,r_keysym);
|
322
|
+
rb_ivar_set(r_ev,id_mods,r_mods);
|
323
|
+
break;
|
324
|
+
|
325
|
+
case ConfigureNotify:
|
326
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xconfigure.window));
|
327
|
+
break;
|
328
|
+
|
329
|
+
case FocusIn:
|
330
|
+
case FocusOut:
|
331
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xfocus.window));
|
332
|
+
break;
|
333
|
+
|
334
|
+
case EnterNotify:
|
335
|
+
case LeaveNotify:
|
336
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xcrossing.window));
|
337
|
+
break;
|
338
|
+
|
339
|
+
case CreateNotify:
|
340
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xcreatewindow.window));
|
341
|
+
break;
|
342
|
+
|
343
|
+
case DestroyNotify:
|
344
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xdestroywindow.window));
|
345
|
+
break;
|
346
|
+
|
347
|
+
case MapRequest:
|
348
|
+
rb_ivar_set(r_ev, id_client, r_client_for_window(wm,pev->xmaprequest.window));
|
349
|
+
break;
|
350
|
+
}
|
351
|
+
return r_ev;
|
352
|
+
}
|
353
|
+
|
354
|
+
static VALUE wm_grab_key(VALUE self, VALUE r_keysym, VALUE r_mods) {
|
355
|
+
KeySym keysym = keysym_to_c(r_keysym);
|
356
|
+
KeyCode keycode;
|
357
|
+
int mods = keymask_to_c(r_mods);
|
358
|
+
WM* wm;
|
359
|
+
|
360
|
+
Data_Get_Struct(self,WM,wm);
|
361
|
+
keycode = XKeysymToKeycode(wm->dpy, keysym);
|
362
|
+
XGrabKey(wm->dpy, keycode, mods, wm->root, True, GrabModeAsync, GrabModeAsync);
|
363
|
+
return Qnil;
|
364
|
+
}
|
365
|
+
|
366
|
+
static VALUE wm_ungrab_key(VALUE self, VALUE r_keysym, VALUE r_mods) {
|
367
|
+
KeySym keysym = keysym_to_c(r_keysym);
|
368
|
+
KeyCode keycode;
|
369
|
+
int mods = keymask_to_c(r_mods);
|
370
|
+
WM* wm;
|
371
|
+
|
372
|
+
Data_Get_Struct(self,WM,wm);
|
373
|
+
keycode = XKeysymToKeycode(wm->dpy, keysym);
|
374
|
+
XUngrabKey(wm->dpy, keycode, mods, wm->root);
|
375
|
+
return Qnil;
|
376
|
+
}
|
377
|
+
|
378
|
+
static void client_free(void *p) {
|
379
|
+
//free(p);
|
380
|
+
}
|
381
|
+
|
382
|
+
static VALUE client_alloc(VALUE klass) {
|
383
|
+
Client *c;
|
384
|
+
VALUE obj;
|
385
|
+
c = (Client*)calloc(1, sizeof(Client));
|
386
|
+
obj = Data_Wrap_Struct(klass, 0, client_free, c);
|
387
|
+
return obj;
|
388
|
+
}
|
389
|
+
|
390
|
+
static VALUE client_make(VALUE klass, Client* c) {
|
391
|
+
VALUE obj;
|
392
|
+
obj = Data_Wrap_Struct(klass, 0, client_free, c);
|
393
|
+
return obj;
|
394
|
+
}
|
395
|
+
|
396
|
+
static VALUE client_wid(VALUE self) {
|
397
|
+
Client *c;
|
398
|
+
Data_Get_Struct(self, Client, c);
|
399
|
+
return INT2NUM(c->win);
|
400
|
+
}
|
401
|
+
|
402
|
+
static VALUE client_name(VALUE self) {
|
403
|
+
Client *c;
|
404
|
+
Data_Get_Struct(self, Client, c);
|
405
|
+
return rb_str_new2(c->name);
|
406
|
+
}
|
407
|
+
|
408
|
+
static VALUE client_class(VALUE self) {
|
409
|
+
Client *c;
|
410
|
+
Data_Get_Struct(self, Client, c);
|
411
|
+
return rb_str_new2(c->class);
|
412
|
+
}
|
413
|
+
|
414
|
+
static VALUE client_border(VALUE self) {
|
415
|
+
Client* c;
|
416
|
+
Data_Get_Struct(self, Client, c);
|
417
|
+
return INT2NUM(c->border);
|
418
|
+
}
|
419
|
+
|
420
|
+
static VALUE client_border_set(VALUE self, VALUE width) {
|
421
|
+
Client* c;
|
422
|
+
Data_Get_Struct(self, Client, c);
|
423
|
+
border_client(c, NUM2INT(width));
|
424
|
+
return Qnil;
|
425
|
+
}
|
426
|
+
|
427
|
+
static VALUE client_border_dset(VALUE self) {
|
428
|
+
Client* c;
|
429
|
+
Data_Get_Struct(self, Client, c);
|
430
|
+
unborder_client(c);
|
431
|
+
return Qnil;
|
432
|
+
}
|
433
|
+
|
434
|
+
static VALUE client_x(VALUE self) {
|
435
|
+
Client *c;
|
436
|
+
Data_Get_Struct(self, Client, c);
|
437
|
+
return INT2NUM(c->x);
|
438
|
+
}
|
439
|
+
|
440
|
+
static VALUE client_x_set(VALUE self, VALUE nv) {
|
441
|
+
Client *c;
|
442
|
+
Data_Get_Struct(self, Client, c);
|
443
|
+
resize(c->manager, c, NUM2INT(nv), c->y, c->w, c->h, False);
|
444
|
+
|
445
|
+
return Qnil;
|
446
|
+
}
|
447
|
+
|
448
|
+
static VALUE client_y(VALUE self) {
|
449
|
+
Client *c;
|
450
|
+
Data_Get_Struct(self, Client, c);
|
451
|
+
return INT2NUM(c->y);
|
452
|
+
}
|
453
|
+
|
454
|
+
static VALUE client_y_set(VALUE self, VALUE nv) {
|
455
|
+
Client *c;
|
456
|
+
Data_Get_Struct(self, Client, c);
|
457
|
+
resize(c->manager, c, c->x, NUM2INT(nv), c->w, c->h, False);
|
458
|
+
|
459
|
+
return Qnil;
|
460
|
+
}
|
461
|
+
|
462
|
+
static VALUE client_w(VALUE self) {
|
463
|
+
Client *c;
|
464
|
+
Data_Get_Struct(self, Client, c);
|
465
|
+
return INT2NUM(c->w);
|
466
|
+
}
|
467
|
+
|
468
|
+
static VALUE client_w_set(VALUE self, VALUE nv) {
|
469
|
+
Client *c;
|
470
|
+
Data_Get_Struct(self, Client, c);
|
471
|
+
resize(c->manager, c, c->x, c->y, NUM2INT(nv), c->h, False);
|
472
|
+
|
473
|
+
return Qnil;
|
474
|
+
}
|
475
|
+
|
476
|
+
static VALUE client_h(VALUE self) {
|
477
|
+
Client *c;
|
478
|
+
Data_Get_Struct(self, Client, c);
|
479
|
+
return INT2NUM(c->h);
|
480
|
+
}
|
481
|
+
|
482
|
+
static VALUE client_h_set(VALUE self, VALUE nv) {
|
483
|
+
Client *c;
|
484
|
+
Data_Get_Struct(self, Client, c);
|
485
|
+
resize(c->manager, c, c->x, c->y, c->w, NUM2INT(nv), False);
|
486
|
+
|
487
|
+
return Qnil;
|
488
|
+
}
|
489
|
+
|
490
|
+
static VALUE client_size(VALUE self) {
|
491
|
+
Client *c;
|
492
|
+
int sizes[4];
|
493
|
+
|
494
|
+
Data_Get_Struct(self, Client, c);
|
495
|
+
sizes[0] = c->x;
|
496
|
+
sizes[1] = c->y;
|
497
|
+
sizes[2] = c->w;
|
498
|
+
sizes[3] = c->h;
|
499
|
+
return rb_ary_new3(4, INT2NUM(sizes[0]), INT2NUM(sizes[1]), INT2NUM(sizes[2]), INT2NUM(sizes[3]));
|
500
|
+
}
|
501
|
+
|
502
|
+
static VALUE client_raise(VALUE self) {
|
503
|
+
Client *c;
|
504
|
+
Data_Get_Struct(self, Client, c);
|
505
|
+
raise_client(c);
|
506
|
+
return client_make(cClient, c);
|
507
|
+
}
|
508
|
+
|
509
|
+
static VALUE client_ban(VALUE self) {
|
510
|
+
Client* c;
|
511
|
+
Data_Get_Struct(self, Client, c);
|
512
|
+
ban_client(c);
|
513
|
+
return Qnil;
|
514
|
+
}
|
515
|
+
|
516
|
+
static VALUE client_unban(VALUE self) {
|
517
|
+
Client* c;
|
518
|
+
Data_Get_Struct(self, Client, c);
|
519
|
+
unban_client(c);
|
520
|
+
return client_make(cClient, c);
|
521
|
+
}
|
522
|
+
|
523
|
+
static VALUE client_size_set(VALUE self, VALUE valarray) {
|
524
|
+
Client *c;
|
525
|
+
Data_Get_Struct(self, Client, c);
|
526
|
+
int x,y,w,h;
|
527
|
+
|
528
|
+
if (RARRAY_LEN(valarray) >= 4) {
|
529
|
+
x = RARRAY_PTR(valarray)[0];
|
530
|
+
y = RARRAY_PTR(valarray)[1];
|
531
|
+
w = RARRAY_PTR(valarray)[2];
|
532
|
+
h = RARRAY_PTR(valarray)[3];
|
533
|
+
resize(c->manager, c, x, y, w, h, False);
|
534
|
+
}
|
535
|
+
else
|
536
|
+
rb_raise(rb_eArgError, "wrong number of arguments [x,y,w,h]");
|
537
|
+
return Qnil;
|
538
|
+
}
|
539
|
+
|
540
|
+
static VALUE event_alloc(VALUE klass) {
|
541
|
+
XEvent *ev = (XEvent*) calloc(1,sizeof(XEvent));
|
542
|
+
return Data_Wrap_Struct(klass, 0, free, ev);
|
543
|
+
}
|
544
|
+
|
545
|
+
static VALUE event_wrap(VALUE klass, XEvent* ev) {
|
546
|
+
return Data_Wrap_Struct(klass, 0, free, ev);
|
547
|
+
}
|
548
|
+
|
549
|
+
static VALUE event_type(VALUE self) {
|
550
|
+
XEvent* ev;
|
551
|
+
Data_Get_Struct(self,XEvent,ev);
|
552
|
+
//if (ev->type < LASTEvent && !NIL_P(id_events[ev->type])) {
|
553
|
+
// return id_events[ev->type];
|
554
|
+
//} else {
|
555
|
+
return INT2NUM(ev->type);
|
556
|
+
//}
|
557
|
+
}
|
558
|
+
|
559
|
+
static VALUE event_serial(VALUE self) {
|
560
|
+
XEvent* ev;
|
561
|
+
Data_Get_Struct(self,XEvent,ev);
|
562
|
+
return INT2NUM(ev->xany.serial);
|
563
|
+
}
|
564
|
+
|
565
|
+
static VALUE event_wid(VALUE self) {
|
566
|
+
XEvent* ev;
|
567
|
+
Data_Get_Struct(self,XEvent,ev);
|
568
|
+
return INT2NUM(ev->xany.window);
|
569
|
+
}
|
570
|
+
|
571
|
+
static VALUE event_client(VALUE self) {
|
572
|
+
return rb_ivar_get(self,id_client);
|
573
|
+
}
|
574
|
+
|
575
|
+
static VALUE event_button(VALUE self) {
|
576
|
+
return rb_ivar_get(self,id_button);
|
577
|
+
}
|
578
|
+
|
579
|
+
static VALUE event_x(VALUE self) {
|
580
|
+
return rb_ivar_get(self,id_x);
|
581
|
+
}
|
582
|
+
|
583
|
+
static VALUE event_y(VALUE self) {
|
584
|
+
return rb_ivar_get(self,id_y);
|
585
|
+
}
|
586
|
+
|
587
|
+
static VALUE event_keycode(VALUE self) {
|
588
|
+
return rb_ivar_get(self,id_keycode);
|
589
|
+
}
|
590
|
+
|
591
|
+
static VALUE event_keysym(VALUE self) {
|
592
|
+
return rb_ivar_get(self,id_keysym);
|
593
|
+
}
|
594
|
+
|
595
|
+
static VALUE event_state(VALUE self) {
|
596
|
+
return rb_ivar_get(self,id_state);
|
597
|
+
}
|
598
|
+
|
599
|
+
static VALUE event_mods(VALUE self) {
|
600
|
+
return rb_ivar_get(self,id_mods);
|
601
|
+
}
|
602
|
+
|
603
|
+
void Init_x11() {
|
604
|
+
|
605
|
+
// Main module
|
606
|
+
mX11 = rb_define_module("X11");
|
607
|
+
|
608
|
+
rb_define_singleton_method(mX11, "error_handler", x11_error_handler, 0);
|
609
|
+
rb_define_singleton_method(mX11, "error_handler=", x11_error_handler_set, 1);
|
610
|
+
|
611
|
+
XSetErrorHandler(x11_internal_error_handler);
|
612
|
+
|
613
|
+
// WindowManager
|
614
|
+
|
615
|
+
cWM = rb_define_class_under(mX11, "WindowManager", rb_cObject);
|
616
|
+
rb_define_alloc_func(cWM, wm_alloc);
|
617
|
+
|
618
|
+
rb_define_method(cWM, "query", wm_query, 0);
|
619
|
+
rb_define_method(cWM, "selected", wm_selected, 0);
|
620
|
+
rb_define_method(cWM, "screenxpos", wm_sx, 0);
|
621
|
+
rb_define_method(cWM, "screenypos", wm_sy, 0);
|
622
|
+
rb_define_method(cWM, "screenwidth", wm_sw, 0);
|
623
|
+
rb_define_method(cWM, "screenheight", wm_sh, 0);
|
624
|
+
rb_define_method(cWM, "windowareaxpos", wm_wax, 0);
|
625
|
+
rb_define_method(cWM, "windowareaypos", wm_way, 0);
|
626
|
+
rb_define_method(cWM, "windowareawidth", wm_waw, 0);
|
627
|
+
rb_define_method(cWM, "windowareaheight", wm_wah, 0);
|
628
|
+
rb_define_method(cWM, "windowareaxpos=", wm_wax_set, 1);
|
629
|
+
rb_define_method(cWM, "windowareaypos=", wm_way_set, 1);
|
630
|
+
rb_define_method(cWM, "windowareawidth=", wm_waw_set, 1);
|
631
|
+
rb_define_method(cWM, "windowareaheight=", wm_wah_set, 1);
|
632
|
+
rb_define_method(cWM, "number_of_clients", wm_num_clients, 0);
|
633
|
+
rb_define_method(cWM, "clients", wm_clients, 0);
|
634
|
+
rb_define_method(cWM, "pending_event_count", wm_pending_event_count, 0);
|
635
|
+
rb_define_method(cWM, "next_event", wm_event_next_type, 0);
|
636
|
+
rb_define_method(cWM, "next_event_source", wm_event_next_source, 0);
|
637
|
+
rb_define_method(cWM, "event_pop", wm_event_pop, 0);
|
638
|
+
rb_define_method(cWM, "get_event", wm_get_event, 0);
|
639
|
+
rb_define_method(cWM, "get_grab_key", wm_grab_key, 2);
|
640
|
+
rb_define_method(cWM, "get_ungrab_key", wm_ungrab_key, 2);
|
641
|
+
rb_define_method(cWM, "manage", wm_manage, 5);
|
642
|
+
rb_define_method(cWM, "manage_override_redirect_windows", wm_manage_override_redirect_windows, 0);
|
643
|
+
rb_define_method(cWM, "manage_override_redirect_windows=", wm_manage_override_redirect_windows_set, 1);
|
644
|
+
|
645
|
+
// Client
|
646
|
+
|
647
|
+
cClient = rb_define_class_under(cWM, "Client", rb_cObject);
|
648
|
+
rb_define_alloc_func(cClient, client_alloc);
|
649
|
+
|
650
|
+
rb_define_method(cClient, "size=", client_size_set, 1);
|
651
|
+
rb_define_method(cClient, "size", client_size, 0);
|
652
|
+
rb_define_method(cClient, "name", client_name, 0);
|
653
|
+
rb_define_method(cClient, "window_class", client_class, 0);
|
654
|
+
rb_define_method(cClient, "wid", client_wid, 0);
|
655
|
+
|
656
|
+
rb_define_method(cClient, "xpos", client_x, 0);
|
657
|
+
rb_define_method(cClient, "ypos", client_y, 0);
|
658
|
+
rb_define_method(cClient, "width", client_w, 0);
|
659
|
+
rb_define_method(cClient, "height", client_h, 0);
|
660
|
+
rb_define_method(cClient, "xpos=", client_x_set, 1);
|
661
|
+
rb_define_method(cClient, "ypos=", client_y_set, 1);
|
662
|
+
rb_define_method(cClient, "width=", client_w_set, 1);
|
663
|
+
rb_define_method(cClient, "height=", client_h_set, 1);
|
664
|
+
rb_define_method(cClient, "raise", client_raise, 0);
|
665
|
+
rb_define_method(cClient, "ban", client_ban, 0);
|
666
|
+
rb_define_method(cClient, "unban", client_unban, 0);
|
667
|
+
rb_define_method(cClient, "border", client_border, 0);
|
668
|
+
rb_define_method(cClient, "border=", client_border_set, 1);
|
669
|
+
rb_define_method(cClient, "border_reset", client_border_dset, 0);
|
670
|
+
|
671
|
+
|
672
|
+
// Event
|
673
|
+
|
674
|
+
id_keymasks[0] = rb_intern("Shift");
|
675
|
+
id_keymasks[1] = rb_intern("Lock");
|
676
|
+
id_keymasks[2] = rb_intern("Control");
|
677
|
+
id_keymasks[3] = rb_intern("Mod1");
|
678
|
+
id_keymasks[4] = rb_intern("Mod2");
|
679
|
+
id_keymasks[5] = rb_intern("Mod3");
|
680
|
+
id_keymasks[6] = rb_intern("Mod4");
|
681
|
+
id_keymasks[7] = rb_intern("Mod5");
|
682
|
+
id_keymasks[8] = rb_intern("Button1");
|
683
|
+
id_keymasks[9] = rb_intern("Button2");
|
684
|
+
id_keymasks[10] = rb_intern("Button3");
|
685
|
+
id_keymasks[11] = rb_intern("Button4");
|
686
|
+
id_keymasks[12] = rb_intern("Button5");
|
687
|
+
|
688
|
+
id_client = rb_intern("client");
|
689
|
+
id_x = rb_intern("x");
|
690
|
+
id_y = rb_intern("y");
|
691
|
+
id_button = rb_intern("button");
|
692
|
+
id_keycode = rb_intern("keycode");
|
693
|
+
id_keysym = rb_intern("keysym");
|
694
|
+
id_state = rb_intern("state");
|
695
|
+
id_mods = rb_intern("mods");
|
696
|
+
|
697
|
+
cEvent = rb_define_class_under(mX11,"Event",rb_cObject);
|
698
|
+
rb_define_alloc_func(cEvent, event_alloc);
|
699
|
+
|
700
|
+
rb_define_method(cEvent,"type",event_type,0);
|
701
|
+
rb_define_method(cEvent,"serial",event_serial,0);
|
702
|
+
rb_define_method(cEvent,"wid",event_wid,0);
|
703
|
+
rb_define_method(cEvent,"client",event_client,0);
|
704
|
+
rb_define_method(cEvent,"button",event_button,0);
|
705
|
+
rb_define_method(cEvent,"x",event_x,0);
|
706
|
+
rb_define_method(cEvent,"y",event_y,0);
|
707
|
+
rb_define_method(cEvent,"keycode",event_keycode,0);
|
708
|
+
rb_define_method(cEvent,"keysym",event_keysym,0);
|
709
|
+
rb_define_method(cEvent,"state",event_state,0);
|
710
|
+
rb_define_method(cEvent,"mods",event_mods,0);
|
711
|
+
}
|
712
|
+
|