xlib_ruby 0.1
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.
- 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
|
+
|