This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_x11events.c
640 lines (574 loc) · 19.5 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2011 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
24
25
#include <sys/types.h>
#include <sys/time.h>
26
#include <signal.h>
27
#include <unistd.h>
28
#include <limits.h> /* For INT_MAX */
29
30
#include "SDL_x11video.h"
31
#include "SDL_x11touch.h"
32
#include "../../events/SDL_events_c.h"
33
#include "../../events/SDL_mouse_c.h"
34
#include "../../events/SDL_touch_c.h"
35
36
#include "SDL_timer.h"
37
38
#include "SDL_syswm.h"
39
40
#include <stdio.h>
41
#ifdef SDL_INPUT_LINUXEV
42
43
44
//Touch Input/event* includes
#include <linux/input.h>
#include <fcntl.h>
45
#endif
46
47
/*#define DEBUG_XEVENTS*/
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* Check to see if this is a repeated key.
(idea shamelessly lifted from GII -- thanks guys! :)
*/
static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
{
XEvent peekevent;
if (XPending(display)) {
XPeekEvent(display, &peekevent);
if ((peekevent.type == KeyPress) &&
(peekevent.xkey.keycode == event->xkey.keycode) &&
((peekevent.xkey.time-event->xkey.time) < 2)) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
66
67
68
69
static void
X11_DispatchEvent(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
70
Display *display = videodata->display;
71
72
73
74
75
SDL_WindowData *data;
XEvent xevent;
int i;
SDL_zero(xevent); /* valgrind fix. --ryan. */
76
XNextEvent(display, &xevent);
77
78
79
80
/* filter events catchs XIM events and sends them to the correct
handler */
if (XFilterEvent(&xevent, None) == True) {
81
#if 0
82
83
printf("Filtered event type = %d display = %d window = %d\n",
xevent.type, xevent.xany.display, xevent.xany.window);
84
85
86
87
#endif
return;
}
88
/* Send a SDL_SYSWMEVENT if the application wants them */
89
if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
90
91
92
93
SDL_SysWMmsg wmmsg;
SDL_VERSION(&wmmsg.version);
wmmsg.subsystem = SDL_SYSWM_X11;
94
wmmsg.msg.x11.event = xevent;
95
96
97
98
SDL_SendSysWMEvent(&wmmsg);
}
data = NULL;
99
100
101
if (videodata && videodata->windowlist) {
for (i = 0; i < videodata->numwindows; ++i) {
if ((videodata->windowlist[i] != NULL) &&
102
(videodata->windowlist[i]->xwindow == xevent.xany.window)) {
103
104
105
data = videodata->windowlist[i];
break;
}
106
107
108
109
110
}
}
if (!data) {
return;
}
111
112
#if 0
113
114
printf("type = %d display = %d window = %d\n",
xevent.type, xevent.xany.display, xevent.xany.window);
115
#endif
116
117
118
119
120
switch (xevent.type) {
/* Gaining mouse coverage? */
case EnterNotify:{
#ifdef DEBUG_XEVENTS
121
printf("EnterNotify! (%d,%d,%d)\n",
122
123
xevent.xcrossing.x,
xevent.xcrossing.y,
124
xevent.xcrossing.mode);
125
126
127
128
129
if (xevent.xcrossing.mode == NotifyGrab)
printf("Mode: NotifyGrab\n");
if (xevent.xcrossing.mode == NotifyUngrab)
printf("Mode: NotifyUngrab\n");
#endif
130
SDL_SetMouseFocus(data->window);
131
132
133
134
135
}
break;
/* Losing mouse coverage? */
case LeaveNotify:{
#ifdef DEBUG_XEVENTS
136
printf("LeaveNotify! (%d,%d,%d)\n",
137
138
xevent.xcrossing.x,
xevent.xcrossing.y,
139
xevent.xcrossing.mode);
140
141
142
143
144
if (xevent.xcrossing.mode == NotifyGrab)
printf("Mode: NotifyGrab\n");
if (xevent.xcrossing.mode == NotifyUngrab)
printf("Mode: NotifyUngrab\n");
#endif
145
146
147
if (xevent.xcrossing.mode != NotifyGrab &&
xevent.xcrossing.mode != NotifyUngrab &&
xevent.xcrossing.detail != NotifyInferior) {
148
SDL_SetMouseFocus(NULL);
149
150
151
152
153
154
155
156
157
}
}
break;
/* Gaining input focus? */
case FocusIn:{
#ifdef DEBUG_XEVENTS
printf("FocusIn!\n");
#endif
158
SDL_SetKeyboardFocus(data->window);
159
160
161
162
163
164
165
166
167
168
169
170
171
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
XSetICFocus(data->ic);
}
#endif
}
break;
/* Losing input focus? */
case FocusOut:{
#ifdef DEBUG_XEVENTS
printf("FocusOut!\n");
#endif
172
SDL_SetKeyboardFocus(NULL);
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
XUnsetICFocus(data->ic);
}
#endif
}
break;
/* Generated upon EnterWindow and FocusIn */
case KeymapNotify:{
#ifdef DEBUG_XEVENTS
printf("KeymapNotify!\n");
#endif
/* FIXME:
X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
*/
}
break;
192
193
194
195
196
/* Has the keyboard layout changed? */
case MappingNotify:{
#ifdef DEBUG_XEVENTS
printf("MappingNotify!\n");
#endif
197
X11_UpdateKeymap(_this);
198
199
200
}
break;
201
202
203
/* Key press? */
case KeyPress:{
KeyCode keycode = xevent.xkey.keycode;
204
KeySym keysym = NoSymbol;
205
SDL_Scancode scancode;
206
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
207
Status status = 0;
208
209
210
211
#ifdef DEBUG_XEVENTS
printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
#endif
212
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
213
#if 1
214
215
if (videodata->key_layout[keycode] == SDLK_UNKNOWN) {
int min_keycode, max_keycode;
216
217
XDisplayKeycodes(display, &min_keycode, &max_keycode);
keysym = XKeycodeToKeysym(display, keycode, 0);
218
fprintf(stderr,
219
"The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
220
221
keycode, keycode - min_keycode, keysym,
XKeysymToString(keysym));
222
}
223
#endif
224
/* */
225
SDL_zero(text);
226
227
228
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
229
&keysym, &status);
230
231
}
#else
232
XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
233
#endif
234
if (*text) {
235
SDL_SendKeyboardText(text);
236
}
237
238
239
240
241
242
243
244
245
246
}
break;
/* Key release? */
case KeyRelease:{
KeyCode keycode = xevent.xkey.keycode;
#ifdef DEBUG_XEVENTS
printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
#endif
247
248
249
250
if (X11_KeyRepeat(display, &xevent)) {
/* We're about to get a repeated key down, ignore the key up */
break;
}
251
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
252
253
254
255
256
257
258
259
}
break;
/* Have we been iconified? */
case UnmapNotify:{
#ifdef DEBUG_XEVENTS
printf("UnmapNotify!\n");
#endif
260
261
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
262
263
264
265
266
267
268
269
}
break;
/* Have we been restored? */
case MapNotify:{
#ifdef DEBUG_XEVENTS
printf("MapNotify!\n");
#endif
270
271
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
272
273
274
275
276
277
278
279
280
}
break;
/* Have we been resized or moved? */
case ConfigureNotify:{
#ifdef DEBUG_XEVENTS
printf("ConfigureNotify! (resize: %dx%d)\n",
xevent.xconfigure.width, xevent.xconfigure.height);
#endif
281
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
282
xevent.xconfigure.x, xevent.xconfigure.y);
283
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED,
284
285
286
287
288
289
290
291
292
293
xevent.xconfigure.width,
xevent.xconfigure.height);
}
break;
/* Have we been requested to quit (or another client message?) */
case ClientMessage:{
if ((xevent.xclient.format == 32) &&
(xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
294
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
295
296
297
298
299
300
301
302
303
}
}
break;
/* Do we need to refresh ourselves? */
case Expose:{
#ifdef DEBUG_XEVENTS
printf("Expose (count = %d)\n", xevent.xexpose.count);
#endif
304
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
305
306
307
}
break;
308
case MotionNotify:{
309
#ifdef DEBUG_MOTION
310
printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
311
#endif
312
SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
313
314
315
316
}
break;
case ButtonPress:{
317
SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button);
318
319
320
321
}
break;
case ButtonRelease:{
322
SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button);
323
324
325
}
break;
326
327
case PropertyNotify:{
#ifdef DEBUG_XEVENTS
328
329
330
331
332
unsigned char *propdata;
int status, real_format;
Atom real_type;
unsigned long items_read, items_left, i;
333
334
char *name = XGetAtomName(display, xevent.xproperty.atom);
if (name) {
335
printf("PropertyNotify: %s %s\n", name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
336
337
338
XFree(name);
}
339
status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
340
if (status == Success && items_read > 0) {
341
342
343
344
if (real_type == XA_INTEGER) {
int *values = (int *)propdata;
printf("{");
345
for (i = 0; i < items_read; i++) {
346
347
348
349
350
351
352
353
354
355
printf(" %d", values[i]);
}
printf(" }\n");
} else if (real_type == XA_CARDINAL) {
if (real_format == 32) {
Uint32 *values = (Uint32 *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
356
}
357
358
359
360
361
362
363
printf(" }\n");
} else if (real_format == 16) {
Uint16 *values = (Uint16 *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
364
}
365
366
367
368
369
370
371
printf(" }\n");
} else if (real_format == 8) {
Uint8 *values = (Uint8 *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
printf(" %d", values[i]);
372
}
373
374
375
376
377
378
379
380
381
382
383
384
385
386
printf(" }\n");
}
} else if (real_type == XA_STRING ||
real_type == videodata->UTF8_STRING) {
printf("{ \"%s\" }\n", propdata);
} else if (real_type == XA_ATOM) {
Atom *atoms = (Atom *)propdata;
printf("{");
for (i = 0; i < items_read; i++) {
char *name = XGetAtomName(display, atoms[i]);
if (name) {
printf(" %s", name);
XFree(name);
387
388
}
}
389
390
391
392
393
394
395
printf(" }\n");
} else {
char *name = XGetAtomName(display, real_type);
printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN");
if (name) {
XFree(name);
}
396
397
}
}
398
#endif
399
400
401
}
break;
402
403
404
405
406
407
408
409
410
411
412
413
414
/* Copy the selection from XA_CUT_BUFFER0 to the requested property */
case SelectionRequest: {
XSelectionRequestEvent *req;
XEvent sevent;
int seln_format;
unsigned long nbytes;
unsigned long overflow;
unsigned char *seln_data;
req = &xevent.xselectionrequest;
#ifdef DEBUG_XEVENTS
printf("SelectionRequest (requestor = %ld, target = %ld)\n",
req->requestor, req->target);
415
#endif
416
417
SDL_zero(sevent);
418
sevent.xany.type = SelectionNotify;
419
420
421
422
423
424
425
426
427
428
429
430
431
432
sevent.xselection.selection = req->selection;
sevent.xselection.target = None;
sevent.xselection.property = None;
sevent.xselection.requestor = req->requestor;
sevent.xselection.time = req->time;
if (XGetWindowProperty(display, DefaultRootWindow(display),
XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
&sevent.xselection.target, &seln_format, &nbytes,
&overflow, &seln_data) == Success) {
if (sevent.xselection.target == req->target) {
XChangeProperty(display, req->requestor, req->property,
sevent.xselection.target, seln_format, PropModeReplace,
seln_data, nbytes);
sevent.xselection.property = req->property;
433
}
434
XFree(seln_data);
435
}
436
437
438
439
440
441
442
443
444
445
446
447
448
449
XSendEvent(display, req->requestor, False, 0, &sevent);
XSync(display, False);
}
break;
case SelectionNotify: {
#ifdef DEBUG_XEVENTS
printf("SelectionNotify (requestor = %ld, target = %ld)\n",
xevent.xselection.requestor, xevent.xselection.target);
#endif
videodata->selection_waiting = SDL_FALSE;
}
break;
450
default:{
451
#ifdef DEBUG_XEVENTS
452
printf("Unhandled event %d\n", xevent.type);
453
454
455
456
457
458
459
#endif
}
break;
}
}
/* Ack! XPending() actually performs a blocking read if no events available */
460
static int
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
X11_Pending(Display * display)
{
/* Flush the display connection and look to see if events are queued */
XFlush(display);
if (XEventsQueued(display, QueuedAlready)) {
return (1);
}
/* More drastic measures are required -- see if X is ready to talk */
{
static struct timeval zero_time; /* static == 0 */
int x11_fd;
fd_set fdset;
x11_fd = ConnectionNumber(display);
FD_ZERO(&fdset);
FD_SET(x11_fd, &fdset);
if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
return (XPending(display));
}
}
/* Oh well, nothing is ready .. */
return (0);
}
void
X11_PumpEvents(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
492
493
494
495
/* Update activity every 30 seconds to prevent screensaver */
if (_this->suspend_screensaver) {
Uint32 now = SDL_GetTicks();
if (!data->screensaver_activity ||
496
(int) (now - data->screensaver_activity) >= 30000) {
497
498
499
500
501
XResetScreenSaver(data->display);
data->screensaver_activity = now;
}
}
502
503
504
505
/* Keep processing pending events */
while (X11_Pending(data->display)) {
X11_DispatchEvent(_this);
}
506
507
#ifdef SDL_INPUT_LINUXEV
508
509
/* Process Touch events - TODO When X gets touch support, use that instead*/
int i = 0,rd;
510
char name[256];
511
512
struct input_event ev[64];
int size = sizeof (struct input_event);
513
514
515
516
517
for(i = 0;i < SDL_GetNumTouch();++i) {
SDL_Touch* touch = SDL_GetTouchIndex(i);
if(!touch) printf("Touch %i/%i DNE\n",i,SDL_GetNumTouch());
EventTouchData* data;
518
519
520
521
data = (EventTouchData*)(touch->driverdata);
if(data == NULL) {
printf("No driver data\n");
continue;
522
523
524
525
526
527
528
529
530
531
}
if(data->eventStream <= 0)
printf("Error: Couldn't open stream\n");
rd = read(data->eventStream, ev, size * 64);
//printf("Got %i/%i bytes\n",rd,size);
if(rd >= size) {
for (i = 0; i < rd / sizeof(struct input_event); i++) {
switch (ev[i].type) {
case EV_ABS:
//printf("Got position x: %i!\n",data->x);
532
533
534
535
536
537
538
539
540
switch (ev[i].code) {
case ABS_X:
data->x = ev[i].value;
break;
case ABS_Y:
data->y = ev[i].value;
break;
case ABS_PRESSURE:
data->pressure = ev[i].value;
541
if(data->pressure < 0) data->pressure = 0;
542
543
break;
case ABS_MISC:
544
545
if(ev[i].value == 0)
data->up = SDL_TRUE;
546
547
break;
}
548
549
550
551
552
553
break;
case EV_MSC:
if(ev[i].code == MSC_SERIAL)
data->finger = ev[i].value;
break;
case EV_SYN:
554
//printf("Id: %i\n",touch->id);
555
556
557
if(data->up) {
SDL_SendFingerDown(touch->id,data->finger,
SDL_FALSE,data->x,data->y,
558
data->pressure);
559
560
}
else if(data->x >= 0 || data->y >= 0)
561
SDL_SendTouchMotion(touch->id,data->finger,
562
SDL_FALSE,data->x,data->y,
563
data->pressure);
564
565
566
//printf("Synched: %i tx: %i, ty: %i\n",
// data->finger,data->x,data->y);
567
568
569
570
571
data->x = -1;
data->y = -1;
data->pressure = -1;
data->finger = 0;
data->up = SDL_FALSE;
572
573
break;
574
575
576
577
}
}
}
}
578
#endif
579
580
}
581
582
583
584
585
/* This is so wrong it hurts */
#define GNOME_SCREENSAVER_HACK
#ifdef GNOME_SCREENSAVER_HACK
#include <unistd.h>
static pid_t screensaver_inhibit_pid;
586
587
static void
gnome_screensaver_disable()
588
589
590
{
screensaver_inhibit_pid = fork();
if (screensaver_inhibit_pid == 0) {
591
592
593
close(0);
close(1);
close(2);
594
595
596
597
execl("/usr/bin/gnome-screensaver-command",
"gnome-screensaver-command",
"--inhibit",
"--reason",
598
"GNOME screensaver doesn't respect MIT-SCREEN-SAVER", NULL);
599
600
601
exit(2);
}
}
602
603
static void
gnome_screensaver_enable()
604
605
606
607
608
{
kill(screensaver_inhibit_pid, 15);
}
#endif
609
void
610
X11_SuspendScreenSaver(_THIS)
611
{
612
#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
613
614
615
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
int dummy;
int major_version, minor_version;
616
617
618
619
620
621
622
623
624
if (SDL_X11_HAVE_XSS) {
/* XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
if (!XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
!XScreenSaverQueryVersion(data->display,
&major_version, &minor_version) ||
major_version < 1 || (major_version == 1 && minor_version < 1)) {
return;
}
625
626
627
XScreenSaverSuspend(data->display, _this->suspend_screensaver);
XResetScreenSaver(data->display);
628
}
629
#endif
630
631
632
633
634
635
636
#ifdef GNOME_SCREENSAVER_HACK
if (_this->suspend_screensaver) {
gnome_screensaver_disable();
} else {
gnome_screensaver_enable();
}
637
#endif
638
639
640
}
/* vi: set ts=4 sw=4 expandtab: */