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