src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 27 Sep 2012 23:55:38 -0700
changeset 6481 fab4b15b17e9
parent 6476 9010d6830cdf
child 6487 b18a011ecc45
permissions -rw-r--r--
Compositing window managers can show and hide windows without ever affecting the mapped state. However they do send NetWM protocol messages to indicate this is happening.
Also refactored the netwm state code so it's consistent between the places that use it.
slouken@1951
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1951
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1951
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1951
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1951
    20
*/
slouken@1951
    21
#include "SDL_config.h"
slouken@1951
    22
slouken@5481
    23
#if SDL_VIDEO_DRIVER_X11
slouken@5481
    24
slouken@2046
    25
#include <sys/types.h>
slouken@2046
    26
#include <sys/time.h>
slouken@4465
    27
#include <signal.h>
slouken@2046
    28
#include <unistd.h>
slouken@4558
    29
#include <limits.h> /* For INT_MAX */
slouken@2046
    30
slouken@1951
    31
#include "SDL_x11video.h"
slouken@4934
    32
#include "SDL_x11touch.h"
dimitris@6316
    33
#include "SDL_x11xinput2.h"
slouken@1951
    34
#include "../../events/SDL_events_c.h"
slouken@2940
    35
#include "../../events/SDL_mouse_c.h"
jim@4642
    36
#include "../../events/SDL_touch_c.h"
slouken@1951
    37
slouken@4465
    38
#include "SDL_timer.h"
slouken@3241
    39
#include "SDL_syswm.h"
slouken@3241
    40
jim@4642
    41
#include <stdio.h>
jim@4642
    42
jim@4681
    43
#ifdef SDL_INPUT_LINUXEV
jim@4642
    44
//Touch Input/event* includes
jim@4642
    45
#include <linux/input.h>
jim@4642
    46
#include <fcntl.h>
jimtla@4669
    47
#endif
slouken@4508
    48
slouken@6474
    49
/*#define DEBUG_XEVENTS*/
slouken@6474
    50
slouken@4565
    51
/* Check to see if this is a repeated key.
slouken@4565
    52
   (idea shamelessly lifted from GII -- thanks guys! :)
slouken@4565
    53
 */
slouken@4565
    54
static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
slouken@4565
    55
{
slouken@4565
    56
    XEvent peekevent;
slouken@4565
    57
slouken@4565
    58
    if (XPending(display)) {
slouken@4565
    59
        XPeekEvent(display, &peekevent);
slouken@4565
    60
        if ((peekevent.type == KeyPress) &&
slouken@4565
    61
            (peekevent.xkey.keycode == event->xkey.keycode) &&
slouken@4565
    62
            ((peekevent.xkey.time-event->xkey.time) < 2)) {
slouken@4565
    63
            return SDL_TRUE;
slouken@4565
    64
        }
slouken@4565
    65
    }
slouken@4565
    66
    return SDL_FALSE;
slouken@4565
    67
}
slouken@4565
    68
slouken@5530
    69
static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks)
slouken@5530
    70
{
slouken@5530
    71
    XEvent peekevent;
slouken@5530
    72
    if (XPending(display)) {
slouken@5530
    73
        /* according to the xlib docs, no specific mouse wheel events exist.
slouken@5530
    74
           however, mouse wheel events trigger a button press and a button release
slouken@5530
    75
           immediately. thus, checking if the same button was released at the same
slouken@5530
    76
           time as it was pressed, should be an adequate hack to derive a mouse 
slouken@5530
    77
           wheel event. */
slouken@5530
    78
        XPeekEvent(display,&peekevent);
slouken@5530
    79
        if ((peekevent.type           == ButtonRelease) &&
slouken@5530
    80
            (peekevent.xbutton.button == event->xbutton.button) &&
slouken@5530
    81
            (peekevent.xbutton.time   == event->xbutton.time)) {
slouken@5530
    82
slouken@5530
    83
            /* by default, X11 only knows 5 buttons. on most 3 button + wheel mouse,
slouken@5530
    84
               Button4 maps to wheel up, Button5 maps to wheel down. */
slouken@5530
    85
            if (event->xbutton.button == Button4) {
slouken@5530
    86
                *ticks = 1;
slouken@5530
    87
            }
slouken@6184
    88
            else if (event->xbutton.button == Button5) {
slouken@5530
    89
                *ticks = -1;
slouken@5530
    90
            }
slouken@5530
    91
slouken@5530
    92
            /* remove the following release event, as this is now a wheel event */
slouken@5530
    93
            XNextEvent(display,&peekevent);
slouken@5530
    94
            return SDL_TRUE;
slouken@5530
    95
        }
slouken@5530
    96
    }
slouken@5530
    97
    return SDL_FALSE;
slouken@5530
    98
}
slouken@5530
    99
slouken@6311
   100
slouken@6311
   101
#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
slouken@6311
   102
static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
slouken@6311
   103
{
slouken@6311
   104
    XGenericEventCookie *cookie = &event.xcookie;
slouken@6311
   105
    XGetEventData(videodata->display, cookie);
dimitris@6316
   106
    X11_HandleXinput2Event(videodata,cookie);
slouken@6311
   107
    XFreeEventData(videodata->display,cookie);
slouken@6311
   108
}
slouken@6311
   109
#endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
slouken@6311
   110
slouken@6311
   111
slouken@6481
   112
static void
slouken@6481
   113
X11_DispatchMapNotify(SDL_WindowData *data)
slouken@6481
   114
{
slouken@6481
   115
    SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@6481
   116
    SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@6481
   117
}
slouken@6481
   118
slouken@6481
   119
static void
slouken@6481
   120
X11_DispatchUnmapNotify(SDL_WindowData *data)
slouken@6481
   121
{
slouken@6481
   122
    SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@6481
   123
    SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@6481
   124
}
slouken@6311
   125
slouken@1951
   126
static void
slouken@1951
   127
X11_DispatchEvent(_THIS)
slouken@1951
   128
{
slouken@1951
   129
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@4518
   130
    Display *display = videodata->display;
slouken@1951
   131
    SDL_WindowData *data;
slouken@1951
   132
    XEvent xevent;
slouken@1951
   133
    int i;
slouken@1951
   134
slouken@1951
   135
    SDL_zero(xevent);           /* valgrind fix. --ryan. */
slouken@4518
   136
    XNextEvent(display, &xevent);
slouken@1951
   137
bob@2325
   138
    /* filter events catchs XIM events and sends them to the correct
bob@2325
   139
       handler */
bob@2325
   140
    if (XFilterEvent(&xevent, None) == True) {
bob@2327
   141
#if 0
bob@2328
   142
        printf("Filtered event type = %d display = %d window = %d\n",
bob@2328
   143
               xevent.type, xevent.xany.display, xevent.xany.window);
bob@2325
   144
#endif
bob@2325
   145
        return;
bob@2325
   146
    }
bob@2325
   147
slouken@1951
   148
    /* Send a SDL_SYSWMEVENT if the application wants them */
slouken@4429
   149
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1951
   150
        SDL_SysWMmsg wmmsg;
slouken@1951
   151
slouken@1951
   152
        SDL_VERSION(&wmmsg.version);
slouken@1951
   153
        wmmsg.subsystem = SDL_SYSWM_X11;
slouken@5056
   154
        wmmsg.msg.x11.event = xevent;
slouken@1951
   155
        SDL_SendSysWMEvent(&wmmsg);
slouken@1951
   156
    }
slouken@1951
   157
slouken@6311
   158
#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
slouken@6311
   159
    if(xevent.type == GenericEvent) {
slouken@6311
   160
        X11_HandleGenericEvent(videodata,xevent);
slouken@6311
   161
        return;
slouken@6311
   162
    }
slouken@6311
   163
#endif
slouken@6311
   164
slouken@6476
   165
#if 0
slouken@6476
   166
    printf("type = %d display = %d window = %d\n",
slouken@6476
   167
           xevent.type, xevent.xany.display, xevent.xany.window);
slouken@6476
   168
#endif
slouken@6476
   169
slouken@1951
   170
    data = NULL;
bob@2324
   171
    if (videodata && videodata->windowlist) {
bob@2324
   172
        for (i = 0; i < videodata->numwindows; ++i) {
bob@2324
   173
            if ((videodata->windowlist[i] != NULL) &&
slouken@3685
   174
                (videodata->windowlist[i]->xwindow == xevent.xany.window)) {
bob@2324
   175
                data = videodata->windowlist[i];
bob@2324
   176
                break;
bob@2324
   177
            }
slouken@1951
   178
        }
slouken@1951
   179
    }
slouken@1951
   180
    if (!data) {
slouken@1951
   181
        return;
slouken@1951
   182
    }
slouken@4518
   183
slouken@1951
   184
    switch (xevent.type) {
slouken@1951
   185
slouken@1951
   186
        /* Gaining mouse coverage? */
slouken@1951
   187
    case EnterNotify:{
slouken@1951
   188
#ifdef DEBUG_XEVENTS
bob@3195
   189
            printf("EnterNotify! (%d,%d,%d)\n", 
slouken@4558
   190
                   xevent.xcrossing.x,
slouken@4558
   191
                   xevent.xcrossing.y,
bob@3195
   192
                   xevent.xcrossing.mode);
slouken@1951
   193
            if (xevent.xcrossing.mode == NotifyGrab)
slouken@1951
   194
                printf("Mode: NotifyGrab\n");
slouken@1951
   195
            if (xevent.xcrossing.mode == NotifyUngrab)
slouken@1951
   196
                printf("Mode: NotifyUngrab\n");
slouken@1951
   197
#endif
slouken@4465
   198
            SDL_SetMouseFocus(data->window);
slouken@1951
   199
        }
slouken@1951
   200
        break;
slouken@1951
   201
        /* Losing mouse coverage? */
slouken@1951
   202
    case LeaveNotify:{
slouken@1951
   203
#ifdef DEBUG_XEVENTS
bob@3195
   204
            printf("LeaveNotify! (%d,%d,%d)\n", 
slouken@4558
   205
                   xevent.xcrossing.x,
slouken@4558
   206
                   xevent.xcrossing.y,
bob@3195
   207
                   xevent.xcrossing.mode);
slouken@1951
   208
            if (xevent.xcrossing.mode == NotifyGrab)
slouken@1951
   209
                printf("Mode: NotifyGrab\n");
slouken@1951
   210
            if (xevent.xcrossing.mode == NotifyUngrab)
slouken@1951
   211
                printf("Mode: NotifyUngrab\n");
slouken@1951
   212
#endif
slouken@4558
   213
            if (xevent.xcrossing.mode != NotifyGrab &&
slouken@4558
   214
                xevent.xcrossing.mode != NotifyUngrab &&
slouken@4558
   215
                xevent.xcrossing.detail != NotifyInferior) {
slouken@4465
   216
                SDL_SetMouseFocus(NULL);
slouken@1951
   217
            }
slouken@1951
   218
        }
slouken@1951
   219
        break;
slouken@1951
   220
slouken@1951
   221
        /* Gaining input focus? */
slouken@1951
   222
    case FocusIn:{
slouken@1951
   223
#ifdef DEBUG_XEVENTS
slouken@1951
   224
            printf("FocusIn!\n");
slouken@1951
   225
#endif
slouken@4465
   226
            SDL_SetKeyboardFocus(data->window);
slouken@1951
   227
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   228
            if (data->ic) {
slouken@1951
   229
                XSetICFocus(data->ic);
slouken@1951
   230
            }
slouken@1951
   231
#endif
slouken@1951
   232
        }
slouken@1951
   233
        break;
slouken@1951
   234
slouken@1951
   235
        /* Losing input focus? */
slouken@1951
   236
    case FocusOut:{
slouken@1951
   237
#ifdef DEBUG_XEVENTS
slouken@1951
   238
            printf("FocusOut!\n");
slouken@1951
   239
#endif
slouken@4465
   240
            SDL_SetKeyboardFocus(NULL);
slouken@1951
   241
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   242
            if (data->ic) {
slouken@1951
   243
                XUnsetICFocus(data->ic);
slouken@1951
   244
            }
slouken@1951
   245
#endif
slouken@1951
   246
        }
slouken@1951
   247
        break;
slouken@1951
   248
slouken@1951
   249
        /* Generated upon EnterWindow and FocusIn */
slouken@1951
   250
    case KeymapNotify:{
slouken@1951
   251
#ifdef DEBUG_XEVENTS
slouken@1951
   252
            printf("KeymapNotify!\n");
slouken@1951
   253
#endif
slouken@1951
   254
            /* FIXME:
slouken@1951
   255
               X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
slouken@1951
   256
             */
slouken@1951
   257
        }
slouken@1951
   258
        break;
slouken@1951
   259
slouken@2305
   260
        /* Has the keyboard layout changed? */
slouken@2305
   261
    case MappingNotify:{
slouken@2305
   262
#ifdef DEBUG_XEVENTS
slouken@2305
   263
            printf("MappingNotify!\n");
slouken@2305
   264
#endif
slouken@2306
   265
            X11_UpdateKeymap(_this);
slouken@2305
   266
        }
slouken@2305
   267
        break;
slouken@2305
   268
slouken@1951
   269
        /* Key press? */
slouken@1951
   270
    case KeyPress:{
slouken@1951
   271
            KeyCode keycode = xevent.xkey.keycode;
bob@2300
   272
            KeySym keysym = NoSymbol;
slouken@2306
   273
            char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
bob@2325
   274
            Status status = 0;
slouken@1951
   275
slouken@1951
   276
#ifdef DEBUG_XEVENTS
slouken@1951
   277
            printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
slouken@1951
   278
#endif
slouken@4465
   279
            SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
slouken@4535
   280
#if 1
icculus@5981
   281
            if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN) {
slouken@2305
   282
                int min_keycode, max_keycode;
slouken@4518
   283
                XDisplayKeycodes(display, &min_keycode, &max_keycode);
dimitris@6318
   284
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
dimitris@6318
   285
                keysym = XkbKeycodeToKeysym(display, keycode, 0, 0);
dimitris@6318
   286
#else
slouken@4518
   287
                keysym = XKeycodeToKeysym(display, keycode, 0);
dimitris@6318
   288
#endif
bob@2299
   289
                fprintf(stderr,
slouken@4556
   290
                        "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",
slouken@2305
   291
                        keycode, keycode - min_keycode, keysym,
slouken@2305
   292
                        XKeysymToString(keysym));
bob@2299
   293
            }
bob@2295
   294
#endif
bob@2325
   295
            /* */
slouken@2305
   296
            SDL_zero(text);
bob@2325
   297
#ifdef X_HAVE_UTF8_STRING
bob@2325
   298
            if (data->ic) {
bob@2325
   299
                Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
slouken@2738
   300
                                  &keysym, &status);
bob@2325
   301
            }
bob@2325
   302
#else
slouken@2306
   303
            XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
bob@2325
   304
#endif
slouken@2305
   305
            if (*text) {
slouken@4465
   306
                SDL_SendKeyboardText(text);
bob@2300
   307
            }
slouken@1951
   308
        }
slouken@1951
   309
        break;
slouken@1951
   310
slouken@1951
   311
        /* Key release? */
slouken@1951
   312
    case KeyRelease:{
slouken@1951
   313
            KeyCode keycode = xevent.xkey.keycode;
slouken@1951
   314
slouken@1951
   315
#ifdef DEBUG_XEVENTS
slouken@1951
   316
            printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
slouken@1951
   317
#endif
slouken@4565
   318
            if (X11_KeyRepeat(display, &xevent)) {
slouken@4565
   319
                /* We're about to get a repeated key down, ignore the key up */
slouken@4565
   320
                break;
slouken@4565
   321
            }
slouken@4465
   322
            SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
slouken@1951
   323
        }
slouken@1951
   324
        break;
slouken@1951
   325
slouken@1951
   326
        /* Have we been iconified? */
slouken@1951
   327
    case UnmapNotify:{
slouken@1951
   328
#ifdef DEBUG_XEVENTS
slouken@1951
   329
            printf("UnmapNotify!\n");
slouken@1951
   330
#endif
slouken@6481
   331
            X11_DispatchUnmapNotify(data);
slouken@1951
   332
        }
slouken@1951
   333
        break;
slouken@1951
   334
slouken@1951
   335
        /* Have we been restored? */
slouken@1951
   336
    case MapNotify:{
slouken@1951
   337
#ifdef DEBUG_XEVENTS
slouken@1951
   338
            printf("MapNotify!\n");
slouken@1951
   339
#endif
slouken@6481
   340
            X11_DispatchMapNotify(data);
slouken@1951
   341
        }
slouken@1951
   342
        break;
slouken@1951
   343
slouken@1951
   344
        /* Have we been resized or moved? */
slouken@1951
   345
    case ConfigureNotify:{
slouken@1951
   346
#ifdef DEBUG_XEVENTS
slouken@1951
   347
            printf("ConfigureNotify! (resize: %dx%d)\n",
slouken@1951
   348
                   xevent.xconfigure.width, xevent.xconfigure.height);
slouken@1951
   349
#endif
slouken@3685
   350
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
slouken@1951
   351
                                xevent.xconfigure.x, xevent.xconfigure.y);
slouken@3685
   352
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED,
slouken@1951
   353
                                xevent.xconfigure.width,
slouken@1951
   354
                                xevent.xconfigure.height);
slouken@1951
   355
        }
slouken@1951
   356
        break;
slouken@1951
   357
slouken@1951
   358
        /* Have we been requested to quit (or another client message?) */
slouken@1951
   359
    case ClientMessage:{
slouken@1951
   360
            if ((xevent.xclient.format == 32) &&
slouken@1951
   361
                (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
slouken@1951
   362
slouken@3685
   363
                SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1951
   364
            }
slouken@1951
   365
        }
slouken@1951
   366
        break;
slouken@1951
   367
slouken@1951
   368
        /* Do we need to refresh ourselves? */
slouken@1951
   369
    case Expose:{
slouken@1951
   370
#ifdef DEBUG_XEVENTS
slouken@1951
   371
            printf("Expose (count = %d)\n", xevent.xexpose.count);
slouken@1951
   372
#endif
slouken@3685
   373
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
slouken@1951
   374
        }
slouken@1951
   375
        break;
slouken@1951
   376
slouken@4465
   377
    case MotionNotify:{
slouken@6311
   378
            SDL_Mouse *mouse = SDL_GetMouse();  
slouken@6311
   379
            if(!mouse->relative_mode) {
slouken@4465
   380
#ifdef DEBUG_MOTION
slouken@6311
   381
                printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
slouken@4465
   382
#endif
slouken@6311
   383
slouken@6311
   384
                SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
slouken@6311
   385
            }
slouken@4465
   386
        }
slouken@4465
   387
        break;
slouken@4465
   388
slouken@4465
   389
    case ButtonPress:{
slouken@5530
   390
            int ticks = 0;
slouken@5530
   391
            if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) {
slouken@5530
   392
                SDL_SendMouseWheel(data->window, 0, ticks);
slouken@5530
   393
            }
slouken@5530
   394
            else {
slouken@5530
   395
                SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button);
slouken@5530
   396
            }
slouken@4465
   397
        }
slouken@4465
   398
        break;
slouken@4465
   399
slouken@4465
   400
    case ButtonRelease:{
slouken@4484
   401
            SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button);
slouken@4465
   402
        }
slouken@4465
   403
        break;
slouken@4465
   404
slouken@4518
   405
    case PropertyNotify:{
slouken@4518
   406
#ifdef DEBUG_XEVENTS
slouken@4520
   407
            unsigned char *propdata;
slouken@4520
   408
            int status, real_format;
slouken@4520
   409
            Atom real_type;
slouken@4520
   410
            unsigned long items_read, items_left, i;
slouken@4520
   411
slouken@4518
   412
            char *name = XGetAtomName(display, xevent.xproperty.atom);
slouken@4518
   413
            if (name) {
slouken@4556
   414
                printf("PropertyNotify: %s %s\n", name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
slouken@4518
   415
                XFree(name);
slouken@4518
   416
            }
slouken@4518
   417
slouken@4520
   418
            status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
slouken@4556
   419
            if (status == Success && items_read > 0) {
slouken@4520
   420
                if (real_type == XA_INTEGER) {
slouken@4520
   421
                    int *values = (int *)propdata;
slouken@4520
   422
slouken@4520
   423
                    printf("{");
slouken@4520
   424
                    for (i = 0; i < items_read; i++) {
slouken@4520
   425
                        printf(" %d", values[i]);
slouken@4520
   426
                    }
slouken@4520
   427
                    printf(" }\n");
slouken@4520
   428
                } else if (real_type == XA_CARDINAL) {
slouken@4520
   429
                    if (real_format == 32) {
slouken@4520
   430
                        Uint32 *values = (Uint32 *)propdata;
slouken@4520
   431
slouken@4520
   432
                        printf("{");
slouken@4520
   433
                        for (i = 0; i < items_read; i++) {
slouken@4520
   434
                            printf(" %d", values[i]);
slouken@4520
   435
                        }
slouken@4520
   436
                        printf(" }\n");
slouken@4520
   437
                    } else if (real_format == 16) {
slouken@4520
   438
                        Uint16 *values = (Uint16 *)propdata;
slouken@4520
   439
slouken@4520
   440
                        printf("{");
slouken@4520
   441
                        for (i = 0; i < items_read; i++) {
slouken@4520
   442
                            printf(" %d", values[i]);
slouken@4520
   443
                        }
slouken@4520
   444
                        printf(" }\n");
slouken@4520
   445
                    } else if (real_format == 8) {
slouken@4520
   446
                        Uint8 *values = (Uint8 *)propdata;
slouken@4520
   447
slouken@4520
   448
                        printf("{");
slouken@4520
   449
                        for (i = 0; i < items_read; i++) {
slouken@4520
   450
                            printf(" %d", values[i]);
slouken@4520
   451
                        }
slouken@4520
   452
                        printf(" }\n");
slouken@4520
   453
                    }
slouken@4520
   454
                } else if (real_type == XA_STRING ||
slouken@4520
   455
                           real_type == videodata->UTF8_STRING) {
slouken@4520
   456
                    printf("{ \"%s\" }\n", propdata);
slouken@4520
   457
                } else if (real_type == XA_ATOM) {
slouken@4518
   458
                    Atom *atoms = (Atom *)propdata;
slouken@4520
   459
slouken@4520
   460
                    printf("{");
slouken@4518
   461
                    for (i = 0; i < items_read; i++) {
slouken@4520
   462
                        char *name = XGetAtomName(display, atoms[i]);
slouken@4520
   463
                        if (name) {
slouken@4520
   464
                            printf(" %s", name);
slouken@4520
   465
                            XFree(name);
slouken@4518
   466
                        }
slouken@4518
   467
                    }
slouken@4520
   468
                    printf(" }\n");
slouken@4520
   469
                } else {
slouken@4520
   470
                    char *name = XGetAtomName(display, real_type);
slouken@4520
   471
                    printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN");
slouken@4520
   472
                    if (name) {
slouken@4520
   473
                        XFree(name);
slouken@4520
   474
                    }
slouken@4518
   475
                }
slouken@4520
   476
            }
slouken@6481
   477
            if (status == Success) {
slouken@6481
   478
                XFree(propdata);
slouken@6481
   479
            }
slouken@6481
   480
#endif /* DEBUG_XEVENTS */
slouken@6481
   481
slouken@6481
   482
            if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
slouken@6481
   483
                /* Get the new state from the window manager.
slouken@6481
   484
                   Compositing window managers can alter visibility of windows
slouken@6481
   485
                   without ever mapping / unmapping them, so we handle that here,
slouken@6481
   486
                   because they use the NETWM protocol to notify us of changes.
slouken@6481
   487
                 */
slouken@6481
   488
                Uint32 flags = X11_GetNetWMState(_this, data->window);
slouken@6481
   489
                if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) {
slouken@6481
   490
                    if (flags & SDL_WINDOW_HIDDEN) {
slouken@6481
   491
                        X11_DispatchUnmapNotify(data);
slouken@6481
   492
                    } else {
slouken@6481
   493
                        X11_DispatchMapNotify(data);
slouken@6481
   494
                    }
slouken@6481
   495
                }
slouken@6481
   496
            }
slouken@4518
   497
        }
slouken@4518
   498
        break;
slouken@4518
   499
slouken@4508
   500
    /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
slouken@4508
   501
    case SelectionRequest: {
slouken@4508
   502
            XSelectionRequestEvent *req;
slouken@4508
   503
            XEvent sevent;
slouken@4508
   504
            int seln_format;
slouken@4508
   505
            unsigned long nbytes;
slouken@4508
   506
            unsigned long overflow;
slouken@4508
   507
            unsigned char *seln_data;
slouken@4508
   508
slouken@4508
   509
            req = &xevent.xselectionrequest;
slouken@4508
   510
#ifdef DEBUG_XEVENTS
slouken@4508
   511
            printf("SelectionRequest (requestor = %ld, target = %ld)\n",
slouken@4508
   512
                req->requestor, req->target);
slouken@4508
   513
#endif
slouken@4508
   514
slouken@4524
   515
            SDL_zero(sevent);
slouken@4520
   516
            sevent.xany.type = SelectionNotify;
slouken@4508
   517
            sevent.xselection.selection = req->selection;
slouken@4508
   518
            sevent.xselection.target = None;
slouken@4508
   519
            sevent.xselection.property = None;
slouken@4508
   520
            sevent.xselection.requestor = req->requestor;
slouken@4508
   521
            sevent.xselection.time = req->time;
slouken@4508
   522
            if (XGetWindowProperty(display, DefaultRootWindow(display),
slouken@4508
   523
                    XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
slouken@4508
   524
                    &sevent.xselection.target, &seln_format, &nbytes,
slouken@4508
   525
                    &overflow, &seln_data) == Success) {
slouken@4508
   526
                if (sevent.xselection.target == req->target) {
slouken@4508
   527
                    XChangeProperty(display, req->requestor, req->property,
slouken@4508
   528
                        sevent.xselection.target, seln_format, PropModeReplace,
slouken@4508
   529
                        seln_data, nbytes);
slouken@4508
   530
                    sevent.xselection.property = req->property;
slouken@4508
   531
                }
slouken@4508
   532
                XFree(seln_data);
slouken@4508
   533
            }
slouken@4508
   534
            XSendEvent(display, req->requestor, False, 0, &sevent);
slouken@4508
   535
            XSync(display, False);
slouken@4508
   536
        }
slouken@4508
   537
        break;
slouken@4508
   538
slouken@4508
   539
    case SelectionNotify: {
slouken@4508
   540
#ifdef DEBUG_XEVENTS
slouken@4508
   541
            printf("SelectionNotify (requestor = %ld, target = %ld)\n",
slouken@4508
   542
                xevent.xselection.requestor, xevent.xselection.target);
slouken@4508
   543
#endif
slouken@4508
   544
            videodata->selection_waiting = SDL_FALSE;
slouken@4508
   545
        }
slouken@4508
   546
        break;
slouken@4508
   547
slouken@1951
   548
    default:{
slouken@1951
   549
#ifdef DEBUG_XEVENTS
slouken@2940
   550
            printf("Unhandled event %d\n", xevent.type);
slouken@1951
   551
#endif
slouken@1951
   552
        }
slouken@1951
   553
        break;
slouken@1951
   554
    }
slouken@1951
   555
}
slouken@1951
   556
slouken@1951
   557
/* Ack!  XPending() actually performs a blocking read if no events available */
slouken@4472
   558
static int
slouken@1951
   559
X11_Pending(Display * display)
slouken@1951
   560
{
slouken@1951
   561
    /* Flush the display connection and look to see if events are queued */
slouken@1951
   562
    XFlush(display);
slouken@1951
   563
    if (XEventsQueued(display, QueuedAlready)) {
slouken@1951
   564
        return (1);
slouken@1951
   565
    }
slouken@1951
   566
slouken@1951
   567
    /* More drastic measures are required -- see if X is ready to talk */
slouken@1951
   568
    {
slouken@1951
   569
        static struct timeval zero_time;        /* static == 0 */
slouken@1951
   570
        int x11_fd;
slouken@1951
   571
        fd_set fdset;
slouken@1951
   572
slouken@1951
   573
        x11_fd = ConnectionNumber(display);
slouken@1951
   574
        FD_ZERO(&fdset);
slouken@1951
   575
        FD_SET(x11_fd, &fdset);
slouken@1951
   576
        if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
slouken@1951
   577
            return (XPending(display));
slouken@1951
   578
        }
slouken@1951
   579
    }
slouken@1951
   580
slouken@1951
   581
    /* Oh well, nothing is ready .. */
slouken@1951
   582
    return (0);
slouken@1951
   583
}
slouken@1951
   584
icculus@5981
   585
icculus@5981
   586
/* !!! FIXME: this should be exposed in a header, or something. */
icculus@5981
   587
int SDL_GetNumTouch(void);
icculus@5981
   588
icculus@5981
   589
slouken@1951
   590
void
slouken@1951
   591
X11_PumpEvents(_THIS)
slouken@1951
   592
{
slouken@1951
   593
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1951
   594
slouken@3025
   595
    /* Update activity every 30 seconds to prevent screensaver */
slouken@3025
   596
    if (_this->suspend_screensaver) {
slouken@3025
   597
        Uint32 now = SDL_GetTicks();
slouken@3025
   598
        if (!data->screensaver_activity ||
slouken@3040
   599
            (int) (now - data->screensaver_activity) >= 30000) {
slouken@3025
   600
            XResetScreenSaver(data->display);
slouken@3025
   601
            data->screensaver_activity = now;
slouken@3025
   602
        }
dimitris@6318
   603
    }   
slouken@3025
   604
slouken@1951
   605
    /* Keep processing pending events */
slouken@1951
   606
    while (X11_Pending(data->display)) {
slouken@1951
   607
        X11_DispatchEvent(_this);
slouken@1951
   608
    }
dimitris@6316
   609
    /*Dont process evtouch events if XInput2 multitouch is supported*/
icculus@6432
   610
    if(X11_Xinput2IsMultitouchSupported()) {
dimitris@6316
   611
        return;
dimitris@6316
   612
    }
jim@4640
   613
jim@4681
   614
#ifdef SDL_INPUT_LINUXEV
dimitris@6316
   615
    /* Process Touch events*/
jim@4642
   616
    int i = 0,rd;
jim@4642
   617
    struct input_event ev[64];
jim@4642
   618
    int size = sizeof (struct input_event);
jim@4645
   619
icculus@5603
   620
/* !!! FIXME: clean the tabstops out of here. */
jim@4642
   621
    for(i = 0;i < SDL_GetNumTouch();++i) {
jim@4642
   622
	SDL_Touch* touch = SDL_GetTouchIndex(i);
jim@4642
   623
	if(!touch) printf("Touch %i/%i DNE\n",i,SDL_GetNumTouch());
jim@4642
   624
	EventTouchData* data;
jim@4645
   625
	data = (EventTouchData*)(touch->driverdata);
jim@4645
   626
	if(data == NULL) {
jim@4645
   627
	  printf("No driver data\n");
jim@4645
   628
	  continue;
jim@4642
   629
	}
jim@4642
   630
	if(data->eventStream <= 0) 
jim@4642
   631
	    printf("Error: Couldn't open stream\n");
jim@4642
   632
	rd = read(data->eventStream, ev, size * 64);
jim@4642
   633
	if(rd >= size) {
jim@4642
   634
	    for (i = 0; i < rd / sizeof(struct input_event); i++) {
jim@4642
   635
		switch (ev[i].type) {
jim@4642
   636
		case EV_ABS:
jim@4644
   637
		    switch (ev[i].code) {
jim@4644
   638
			case ABS_X:
jim@4644
   639
			    data->x = ev[i].value;
jim@4644
   640
			    break;
jim@4644
   641
			case ABS_Y:
jim@4644
   642
			    data->y = ev[i].value;
jim@4644
   643
			    break;
jim@4644
   644
			case ABS_PRESSURE:
jim@4644
   645
			    data->pressure = ev[i].value;
jim@4646
   646
			    if(data->pressure < 0) data->pressure = 0;
jim@4644
   647
			    break;
jim@4644
   648
			case ABS_MISC:
jim@4683
   649
			    if(ev[i].value == 0)
jim@4683
   650
			        data->up = SDL_TRUE;			    
jim@4644
   651
			    break;
jim@4644
   652
			}
jim@4642
   653
		    break;
jim@4642
   654
		case EV_MSC:
icculus@5603
   655
			if(ev[i].code == MSC_SERIAL)
icculus@5603
   656
				data->finger = ev[i].value;
icculus@5603
   657
			break;
icculus@5603
   658
		case EV_KEY:
icculus@5603
   659
			if(ev[i].code == BTN_TOUCH)
icculus@5603
   660
			    if(ev[i].value == 0)
icculus@5603
   661
			        data->up = SDL_TRUE;
icculus@5603
   662
			break;
jim@4642
   663
		case EV_SYN:
icculus@5603
   664
		  if(!data->down) {
icculus@5603
   665
		      data->down = SDL_TRUE;
jim@4655
   666
		      SDL_SendFingerDown(touch->id,data->finger,
icculus@5603
   667
		    		  data->down, data->x, data->y,
icculus@5603
   668
		    		  data->pressure);
jim@4655
   669
		  }
icculus@5603
   670
		  else if(!data->up)
jim@4683
   671
		    SDL_SendTouchMotion(touch->id,data->finger, 
icculus@5603
   672
					SDL_FALSE, data->x,data->y,
jim@4683
   673
					data->pressure);
icculus@5603
   674
		  else
icculus@5603
   675
		  {
icculus@5603
   676
		      data->down = SDL_FALSE;
icculus@5603
   677
			  SDL_SendFingerDown(touch->id,data->finger,
icculus@5603
   678
					  data->down, data->x,data->y,
icculus@5603
   679
					  data->pressure);
icculus@5603
   680
			  data->x = -1;
icculus@5603
   681
			  data->y = -1;
icculus@5603
   682
			  data->pressure = -1;
icculus@5603
   683
			  data->finger = 0;
icculus@5603
   684
			  data->up = SDL_FALSE;
icculus@5603
   685
		  }
jim@4683
   686
		  break;		
jim@4642
   687
		}
jim@4642
   688
	    }
jim@4642
   689
	}
jim@4642
   690
    }
jimtla@4669
   691
#endif
slouken@1951
   692
}
slouken@1951
   693
slouken@3030
   694
/* This is so wrong it hurts */
slouken@3030
   695
#define GNOME_SCREENSAVER_HACK
slouken@3030
   696
#ifdef GNOME_SCREENSAVER_HACK
slouken@3030
   697
#include <unistd.h>
slouken@3030
   698
static pid_t screensaver_inhibit_pid;
slouken@3040
   699
static void
slouken@3040
   700
gnome_screensaver_disable()
slouken@3030
   701
{
slouken@3030
   702
    screensaver_inhibit_pid = fork();
slouken@3030
   703
    if (screensaver_inhibit_pid == 0) {
slouken@3031
   704
        close(0);
slouken@3031
   705
        close(1);
slouken@3031
   706
        close(2);
slouken@3030
   707
        execl("/usr/bin/gnome-screensaver-command",
slouken@3030
   708
              "gnome-screensaver-command",
slouken@3030
   709
              "--inhibit",
slouken@3030
   710
              "--reason",
slouken@3040
   711
              "GNOME screensaver doesn't respect MIT-SCREEN-SAVER", NULL);
slouken@3030
   712
        exit(2);
slouken@3030
   713
    }
slouken@3030
   714
}
slouken@3040
   715
static void
slouken@3040
   716
gnome_screensaver_enable()
slouken@3030
   717
{
slouken@3030
   718
    kill(screensaver_inhibit_pid, 15);
slouken@3030
   719
}
slouken@3030
   720
#endif
slouken@3030
   721
slouken@1951
   722
void
slouken@3025
   723
X11_SuspendScreenSaver(_THIS)
slouken@1951
   724
{
slouken@5408
   725
#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
slouken@3025
   726
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@3025
   727
    int dummy;
slouken@3025
   728
    int major_version, minor_version;
slouken@1951
   729
slouken@3030
   730
    if (SDL_X11_HAVE_XSS) {
slouken@3030
   731
        /* XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
slouken@3030
   732
        if (!XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
slouken@3030
   733
            !XScreenSaverQueryVersion(data->display,
slouken@3030
   734
                                      &major_version, &minor_version) ||
slouken@3030
   735
            major_version < 1 || (major_version == 1 && minor_version < 1)) {
slouken@3030
   736
            return;
slouken@3030
   737
        }
slouken@3030
   738
slouken@3030
   739
        XScreenSaverSuspend(data->display, _this->suspend_screensaver);
slouken@3030
   740
        XResetScreenSaver(data->display);
slouken@1951
   741
    }
slouken@3030
   742
#endif
slouken@1951
   743
slouken@3030
   744
#ifdef GNOME_SCREENSAVER_HACK
slouken@3030
   745
    if (_this->suspend_screensaver) {
slouken@3030
   746
        gnome_screensaver_disable();
slouken@3030
   747
    } else {
slouken@3030
   748
        gnome_screensaver_enable();
slouken@3025
   749
    }
slouken@3025
   750
#endif
slouken@1951
   751
}
slouken@1951
   752
slouken@5481
   753
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
   754
slouken@1951
   755
/* vi: set ts=4 sw=4 expandtab: */