src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1792 409974dedf2e
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* Handle the event stream, converting X11 events into SDL events */
slouken@0
    25
slouken@0
    26
#include <setjmp.h>
slouken@0
    27
#include <X11/Xlib.h>
slouken@0
    28
#include <X11/Xutil.h>
slouken@0
    29
#include <X11/keysym.h>
slouken@0
    30
#ifdef __SVR4
slouken@0
    31
#include <X11/Sunkeysym.h>
slouken@0
    32
#endif
slouken@75
    33
#include <sys/types.h>
slouken@0
    34
#include <sys/time.h>
slouken@75
    35
#include <unistd.h>
slouken@0
    36
slouken@1359
    37
#include "SDL_timer.h"
slouken@0
    38
#include "SDL_syswm.h"
slouken@1361
    39
#include "../SDL_sysvideo.h"
slouken@1361
    40
#include "../../events/SDL_sysevents.h"
slouken@1361
    41
#include "../../events/SDL_events_c.h"
slouken@0
    42
#include "SDL_x11video.h"
slouken@0
    43
#include "SDL_x11dga_c.h"
slouken@0
    44
#include "SDL_x11modes_c.h"
slouken@0
    45
#include "SDL_x11image_c.h"
slouken@0
    46
#include "SDL_x11gamma_c.h"
slouken@0
    47
#include "SDL_x11wm_c.h"
slouken@0
    48
#include "SDL_x11mouse_c.h"
slouken@0
    49
#include "SDL_x11events_c.h"
slouken@0
    50
slouken@0
    51
slouken@14
    52
/* Define this if you want to debug X11 events */
slouken@14
    53
/*#define DEBUG_XEVENTS*/
slouken@14
    54
slouken@0
    55
/* The translation tables from an X11 keysym to a SDL keysym */
slouken@0
    56
static SDLKey ODD_keymap[256];
slouken@0
    57
static SDLKey MISC_keymap[256];
slouken@1895
    58
SDLKey X11_TranslateKeycode(Display * display, KeyCode kc);
slouken@1327
    59
slouken@1327
    60
slouken@1327
    61
#ifdef X_HAVE_UTF8_STRING
slouken@1895
    62
Uint32
slouken@1895
    63
Utf8ToUcs4(const Uint8 * utf8)
slouken@1327
    64
{
slouken@1895
    65
    Uint32 c;
slouken@1895
    66
    int i = 1;
slouken@1895
    67
    int noOctets = 0;
slouken@1895
    68
    int firstOctetMask = 0;
slouken@1895
    69
    unsigned char firstOctet = utf8[0];
slouken@1895
    70
    if (firstOctet < 0x80) {
slouken@1895
    71
        /*
slouken@1895
    72
           Characters in the range:
slouken@1895
    73
           00000000 to 01111111 (ASCII Range)
slouken@1895
    74
           are stored in one octet:
slouken@1895
    75
           0xxxxxxx (The same as its ASCII representation)
slouken@1895
    76
           The least 6 significant bits of the first octet is the most 6 significant nonzero bits
slouken@1895
    77
           of the UCS4 representation.
slouken@1895
    78
         */
slouken@1895
    79
        noOctets = 1;
slouken@1895
    80
        firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
slouken@1895
    81
    } else if ((firstOctet & 0xE0)      /* get the most 3 significant bits by AND'ing with 11100000 */
slouken@1895
    82
               == 0xC0) {       /* see if those 3 bits are 110. If so, the char is in this range */
slouken@1895
    83
        /*
slouken@1895
    84
           Characters in the range:
slouken@1895
    85
           00000000 10000000 to 00000111 11111111
slouken@1895
    86
           are stored in two octets:
slouken@1895
    87
           110xxxxx 10xxxxxx
slouken@1895
    88
           The least 5 significant bits of the first octet is the most 5 significant nonzero bits
slouken@1895
    89
           of the UCS4 representation.
slouken@1895
    90
         */
slouken@1895
    91
        noOctets = 2;
slouken@1895
    92
        firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
slouken@1895
    93
    } else if ((firstOctet & 0xF0)      /* get the most 4 significant bits by AND'ing with 11110000 */
slouken@1895
    94
               == 0xE0) {       /* see if those 4 bits are 1110. If so, the char is in this range */
slouken@1895
    95
        /*
slouken@1895
    96
           Characters in the range:
slouken@1895
    97
           00001000 00000000 to 11111111 11111111
slouken@1895
    98
           are stored in three octets:
slouken@1895
    99
           1110xxxx 10xxxxxx 10xxxxxx
slouken@1895
   100
           The least 4 significant bits of the first octet is the most 4 significant nonzero bits
slouken@1895
   101
           of the UCS4 representation.
slouken@1895
   102
         */
slouken@1895
   103
        noOctets = 3;
slouken@1895
   104
        firstOctetMask = 0x0F;  /* 0000(1111) - The most 4 significant bits are ignored */
slouken@1895
   105
    } else if ((firstOctet & 0xF8)      /* get the most 5 significant bits by AND'ing with 11111000 */
slouken@1895
   106
               == 0xF0) {       /* see if those 5 bits are 11110. If so, the char is in this range */
slouken@1895
   107
        /*
slouken@1895
   108
           Characters in the range:
slouken@1895
   109
           00000001 00000000 00000000 to 00011111 11111111 11111111
slouken@1895
   110
           are stored in four octets:
slouken@1895
   111
           11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
slouken@1895
   112
           The least 3 significant bits of the first octet is the most 3 significant nonzero bits
slouken@1895
   113
           of the UCS4 representation.
slouken@1895
   114
         */
slouken@1895
   115
        noOctets = 4;
slouken@1895
   116
        firstOctetMask = 0x07;  /* 11110(111) - The most 5 significant bits are ignored */
slouken@1895
   117
    } else if ((firstOctet & 0xFC)      /* get the most 6 significant bits by AND'ing with 11111100 */
slouken@1895
   118
               == 0xF8) {       /* see if those 6 bits are 111110. If so, the char is in this range */
slouken@1895
   119
        /*
slouken@1895
   120
           Characters in the range:
slouken@1895
   121
           00000000 00100000 00000000 00000000 to
slouken@1895
   122
           00000011 11111111 11111111 11111111
slouken@1895
   123
           are stored in five octets:
slouken@1895
   124
           111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
slouken@1895
   125
           The least 2 significant bits of the first octet is the most 2 significant nonzero bits
slouken@1895
   126
           of the UCS4 representation.
slouken@1895
   127
         */
slouken@1895
   128
        noOctets = 5;
slouken@1895
   129
        firstOctetMask = 0x03;  /* 111110(11) - The most 6 significant bits are ignored */
slouken@1895
   130
    } else if ((firstOctet & 0xFE)      /* get the most 7 significant bits by AND'ing with 11111110 */
slouken@1895
   131
               == 0xFC) {       /* see if those 7 bits are 1111110. If so, the char is in this range */
slouken@1895
   132
        /*
slouken@1895
   133
           Characters in the range:
slouken@1895
   134
           00000100 00000000 00000000 00000000 to
slouken@1895
   135
           01111111 11111111 11111111 11111111
slouken@1895
   136
           are stored in six octets:
slouken@1895
   137
           1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
slouken@1895
   138
           The least significant bit of the first octet is the most significant nonzero bit
slouken@1895
   139
           of the UCS4 representation.
slouken@1895
   140
         */
slouken@1895
   141
        noOctets = 6;
slouken@1895
   142
        firstOctetMask = 0x01;  /* 1111110(1) - The most 7 significant bits are ignored */
slouken@1895
   143
    } else
slouken@1895
   144
        return 0;               /* The given chunk is not a valid UTF-8 encoded Unicode character */
slouken@1895
   145
slouken@1895
   146
    /*
slouken@1895
   147
       The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
slouken@1895
   148
       of the UCS4 representation.
slouken@1895
   149
       The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
slouken@1895
   150
       firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
slouken@1895
   151
       This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
slouken@1895
   152
       number of continuing octets (if any) and leave only the free bits (the x's)
slouken@1895
   153
       Sample:
slouken@1895
   154
       1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
slouken@1895
   155
       2-octets:  110xxxxx  &  00011111 = 000xxxxx
slouken@1895
   156
     */
slouken@1895
   157
    c = firstOctet & firstOctetMask;
slouken@1895
   158
slouken@1895
   159
    /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
slouken@1895
   160
    for (i = 1; i < noOctets; i++) {
slouken@1895
   161
        /* A valid continuing octet is of the form 10xxxxxx */
slouken@1895
   162
        if ((utf8[i] & 0xC0)    /* get the most 2 significant bits by AND'ing with 11000000 */
slouken@1895
   163
            !=0x80)
slouken@1895
   164
            /* see if those 2 bits are 10. If not, the is a malformed sequence. */
slouken@1895
   165
            /*The given chunk is a partial sequence at the end of a string that could
slouken@1895
   166
               begin a valid character */
slouken@1895
   167
            return 0;
slouken@1895
   168
slouken@1895
   169
        /* Make room for the next 6-bits */
slouken@1895
   170
        c <<= 6;
slouken@1895
   171
slouken@1895
   172
        /*
slouken@1895
   173
           Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
slouken@1895
   174
           of c.ucs4 with them.
slouken@1895
   175
           This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
slouken@1895
   176
         */
slouken@1895
   177
        c |= utf8[i] & 0x3F;
slouken@1895
   178
    }
slouken@1895
   179
    return c;
slouken@1327
   180
}
slouken@1327
   181
#endif
slouken@0
   182
slouken@0
   183
/* Check to see if this is a repeated key.
slouken@0
   184
   (idea shamelessly lifted from GII -- thanks guys! :)
slouken@0
   185
 */
slouken@1895
   186
static int
slouken@1895
   187
X11_KeyRepeat(Display * display, XEvent * event)
slouken@0
   188
{
slouken@1895
   189
    XEvent peekevent;
slouken@1895
   190
    int repeated;
slouken@0
   191
slouken@1895
   192
    repeated = 0;
slouken@1895
   193
    if (XPending(display)) {
slouken@1895
   194
        XPeekEvent(display, &peekevent);
slouken@1895
   195
        if ((peekevent.type == KeyPress) &&
slouken@1895
   196
            (peekevent.xkey.keycode == event->xkey.keycode) &&
slouken@1895
   197
            ((peekevent.xkey.time - event->xkey.time) < 2)) {
slouken@1895
   198
            repeated = 1;
slouken@1895
   199
            XNextEvent(display, &peekevent);
slouken@1895
   200
        }
slouken@1895
   201
    }
slouken@1895
   202
    return (repeated);
slouken@0
   203
}
slouken@0
   204
slouken@0
   205
/* Note:  The X server buffers and accumulates mouse motion events, so
slouken@0
   206
   the motion event generated by the warp may not appear exactly as we
slouken@0
   207
   expect it to.  We work around this (and improve performance) by only
slouken@0
   208
   warping the pointer when it reaches the edge, and then wait for it.
slouken@0
   209
*/
slouken@0
   210
#define MOUSE_FUDGE_FACTOR	8
slouken@0
   211
slouken@1895
   212
static __inline__ int
slouken@1895
   213
X11_WarpedMotion(_THIS, XEvent * xevent)
slouken@0
   214
{
slouken@1895
   215
    int w, h, i;
slouken@1895
   216
    int deltax, deltay;
slouken@1895
   217
    int posted;
slouken@0
   218
slouken@1895
   219
    w = SDL_VideoSurface->w;
slouken@1895
   220
    h = SDL_VideoSurface->h;
slouken@1895
   221
    deltax = xevent->xmotion.x - mouse_last.x;
slouken@1895
   222
    deltay = xevent->xmotion.y - mouse_last.y;
slouken@0
   223
#ifdef DEBUG_MOTION
slouken@1895
   224
    printf("Warped mouse motion: %d,%d\n", deltax, deltay);
slouken@0
   225
#endif
slouken@1895
   226
    mouse_last.x = xevent->xmotion.x;
slouken@1895
   227
    mouse_last.y = xevent->xmotion.y;
slouken@1895
   228
    posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
slouken@0
   229
slouken@1895
   230
    if ((xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
slouken@1895
   231
        (xevent->xmotion.x > (w - MOUSE_FUDGE_FACTOR)) ||
slouken@1895
   232
        (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
slouken@1895
   233
        (xevent->xmotion.y > (h - MOUSE_FUDGE_FACTOR))) {
slouken@1895
   234
        /* Get the events that have accumulated */
slouken@1895
   235
        while (XCheckTypedEvent(SDL_Display, MotionNotify, xevent)) {
slouken@1895
   236
            deltax = xevent->xmotion.x - mouse_last.x;
slouken@1895
   237
            deltay = xevent->xmotion.y - mouse_last.y;
slouken@0
   238
#ifdef DEBUG_MOTION
slouken@1895
   239
            printf("Extra mouse motion: %d,%d\n", deltax, deltay);
slouken@0
   240
#endif
slouken@1895
   241
            mouse_last.x = xevent->xmotion.x;
slouken@1895
   242
            mouse_last.y = xevent->xmotion.y;
slouken@1895
   243
            posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
slouken@1895
   244
        }
slouken@1895
   245
        mouse_last.x = w / 2;
slouken@1895
   246
        mouse_last.y = h / 2;
slouken@1895
   247
        XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
slouken@1895
   248
                     mouse_last.x, mouse_last.y);
slouken@1895
   249
        for (i = 0; i < 10; ++i) {
slouken@1895
   250
            XMaskEvent(SDL_Display, PointerMotionMask, xevent);
slouken@1895
   251
            if ((xevent->xmotion.x >
slouken@1895
   252
                 (mouse_last.x - MOUSE_FUDGE_FACTOR)) &&
slouken@1895
   253
                (xevent->xmotion.x <
slouken@1895
   254
                 (mouse_last.x + MOUSE_FUDGE_FACTOR)) &&
slouken@1895
   255
                (xevent->xmotion.y >
slouken@1895
   256
                 (mouse_last.y - MOUSE_FUDGE_FACTOR)) &&
slouken@1895
   257
                (xevent->xmotion.y < (mouse_last.y + MOUSE_FUDGE_FACTOR))) {
slouken@1895
   258
                break;
slouken@1895
   259
            }
slouken@0
   260
#ifdef DEBUG_XEVENTS
slouken@1895
   261
            printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x,
slouken@1895
   262
                   xevent->xmotion.y);
slouken@0
   263
#endif
slouken@1895
   264
        }
slouken@0
   265
#ifdef DEBUG_XEVENTS
slouken@1895
   266
        if (i == 10) {
slouken@1895
   267
            printf("Warning: didn't detect mouse warp motion\n");
slouken@1895
   268
        }
slouken@0
   269
#endif
slouken@1895
   270
    }
slouken@1895
   271
    return (posted);
slouken@0
   272
}
slouken@0
   273
slouken@1895
   274
static int
slouken@1895
   275
X11_DispatchEvent(_THIS)
slouken@0
   276
{
slouken@1895
   277
    int posted;
slouken@1895
   278
    XEvent xevent;
slouken@0
   279
slouken@1895
   280
    SDL_memset(&xevent, '\0', sizeof(XEvent));  /* valgrind fix. --ryan. */
slouken@1895
   281
    XNextEvent(SDL_Display, &xevent);
slouken@0
   282
slouken@1895
   283
    posted = 0;
slouken@1895
   284
    switch (xevent.type) {
slouken@0
   285
slouken@1895
   286
        /* Gaining mouse coverage? */
slouken@1895
   287
    case EnterNotify:
slouken@1895
   288
        {
slouken@0
   289
#ifdef DEBUG_XEVENTS
slouken@1895
   290
            printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x,
slouken@1895
   291
                   xevent.xcrossing.y);
slouken@1895
   292
            if (xevent.xcrossing.mode == NotifyGrab)
slouken@1895
   293
                printf("Mode: NotifyGrab\n");
slouken@1895
   294
            if (xevent.xcrossing.mode == NotifyUngrab)
slouken@1895
   295
                printf("Mode: NotifyUngrab\n");
slouken@0
   296
#endif
slouken@1895
   297
            if ((xevent.xcrossing.mode != NotifyGrab) &&
slouken@1895
   298
                (xevent.xcrossing.mode != NotifyUngrab)) {
slouken@1895
   299
                if (SDL_CurrentWindow.input_grab == SDL_GRAB_OFF) {
slouken@1895
   300
                    posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
slouken@1895
   301
                }
slouken@1895
   302
                posted = SDL_PrivateMouseMotion(0, 0,
slouken@1895
   303
                                                xevent.xcrossing.x,
slouken@1895
   304
                                                xevent.xcrossing.y);
slouken@1895
   305
            }
slouken@1895
   306
        }
slouken@1895
   307
        break;
slouken@0
   308
slouken@1895
   309
        /* Losing mouse coverage? */
slouken@1895
   310
    case LeaveNotify:
slouken@1895
   311
        {
slouken@0
   312
#ifdef DEBUG_XEVENTS
slouken@1895
   313
            printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x,
slouken@1895
   314
                   xevent.xcrossing.y);
slouken@1895
   315
            if (xevent.xcrossing.mode == NotifyGrab)
slouken@1895
   316
                printf("Mode: NotifyGrab\n");
slouken@1895
   317
            if (xevent.xcrossing.mode == NotifyUngrab)
slouken@1895
   318
                printf("Mode: NotifyUngrab\n");
slouken@0
   319
#endif
slouken@1895
   320
            if ((xevent.xcrossing.mode != NotifyGrab) &&
slouken@1895
   321
                (xevent.xcrossing.mode != NotifyUngrab) &&
slouken@1895
   322
                (xevent.xcrossing.detail != NotifyInferior)) {
slouken@1895
   323
                if (SDL_CurrentWindow.input_grab == SDL_GRAB_OFF) {
slouken@1895
   324
                    posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
slouken@1895
   325
                } else {
slouken@1895
   326
                    posted = SDL_PrivateMouseMotion(0, 0,
slouken@1895
   327
                                                    xevent.xcrossing.x,
slouken@1895
   328
                                                    xevent.xcrossing.y);
slouken@1895
   329
                }
slouken@1895
   330
            }
slouken@1895
   331
        }
slouken@1895
   332
        break;
slouken@0
   333
slouken@1895
   334
        /* Gaining input focus? */
slouken@1895
   335
    case FocusIn:
slouken@1895
   336
        {
slouken@0
   337
#ifdef DEBUG_XEVENTS
slouken@1895
   338
            printf("FocusIn!\n");
slouken@0
   339
#endif
slouken@1895
   340
            posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
slouken@0
   341
slouken@1328
   342
#ifdef X_HAVE_UTF8_STRING
slouken@1895
   343
            if (SDL_IC != NULL) {
slouken@1895
   344
                XSetICFocus(SDL_IC);
slouken@1895
   345
            }
slouken@1328
   346
#endif
slouken@1895
   347
            /* Queue entry into fullscreen mode */
slouken@1895
   348
            switch_waiting = 0x01 | SDL_FULLSCREEN;
slouken@1895
   349
            switch_time = SDL_GetTicks() + 1500;
slouken@1895
   350
        }
slouken@1895
   351
        break;
slouken@0
   352
slouken@1895
   353
        /* Losing input focus? */
slouken@1895
   354
    case FocusOut:
slouken@1895
   355
        {
slouken@0
   356
#ifdef DEBUG_XEVENTS
slouken@1895
   357
            printf("FocusOut!\n");
slouken@0
   358
#endif
slouken@1895
   359
            posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
slouken@0
   360
slouken@1328
   361
#ifdef X_HAVE_UTF8_STRING
slouken@1895
   362
            if (SDL_IC != NULL) {
slouken@1895
   363
                XUnsetICFocus(SDL_IC);
slouken@1895
   364
            }
slouken@1328
   365
#endif
slouken@1895
   366
            /* Queue leaving fullscreen mode */
slouken@1895
   367
            switch_waiting = 0x01;
slouken@1895
   368
            switch_time = SDL_GetTicks() + 200;
slouken@1895
   369
        }
slouken@1895
   370
        break;
slouken@0
   371
slouken@1895
   372
        /* Generated upon EnterWindow and FocusIn */
slouken@1895
   373
    case KeymapNotify:
slouken@1895
   374
        {
slouken@14
   375
#ifdef DEBUG_XEVENTS
slouken@1895
   376
            printf("KeymapNotify!\n");
slouken@14
   377
#endif
slouken@1895
   378
            X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
slouken@1895
   379
        }
slouken@1895
   380
        break;
slouken@0
   381
slouken@1895
   382
        /* Mouse motion? */
slouken@1895
   383
    case MotionNotify:
slouken@1895
   384
        {
slouken@1895
   385
            if (SDL_VideoSurface) {
slouken@1895
   386
                if (mouse_relative) {
slouken@1895
   387
                    if (using_dga & DGA_MOUSE) {
slouken@0
   388
#ifdef DEBUG_MOTION
slouken@1895
   389
                        printf("DGA motion: %d,%d\n",
slouken@1895
   390
                               xevent.xmotion.x_root, xevent.xmotion.y_root);
slouken@0
   391
#endif
slouken@1895
   392
                        posted = SDL_PrivateMouseMotion(0, 1,
slouken@1895
   393
                                                        xevent.
slouken@1895
   394
                                                        xmotion.
slouken@1895
   395
                                                        x_root,
slouken@1895
   396
                                                        xevent.
slouken@1895
   397
                                                        xmotion.y_root);
slouken@1895
   398
                    } else {
slouken@1895
   399
                        posted = X11_WarpedMotion(_this, &xevent);
slouken@1895
   400
                    }
slouken@1895
   401
                } else {
slouken@82
   402
#ifdef DEBUG_MOTION
slouken@1895
   403
                    printf("X11 motion: %d,%d\n", xevent.xmotion.x,
slouken@1895
   404
                           xevent.xmotion.y);
slouken@82
   405
#endif
slouken@1895
   406
                    posted = SDL_PrivateMouseMotion(0, 0,
slouken@1895
   407
                                                    xevent.xmotion.x,
slouken@1895
   408
                                                    xevent.xmotion.y);
slouken@1895
   409
                }
slouken@1895
   410
            }
slouken@1895
   411
        }
slouken@1895
   412
        break;
slouken@0
   413
slouken@1895
   414
        /* Mouse button press? */
slouken@1895
   415
    case ButtonPress:
slouken@1895
   416
        {
slouken@1895
   417
            posted = SDL_PrivateMouseButton(SDL_PRESSED,
slouken@1895
   418
                                            xevent.xbutton.button, 0, 0);
slouken@1895
   419
        }
slouken@1895
   420
        break;
slouken@0
   421
slouken@1895
   422
        /* Mouse button release? */
slouken@1895
   423
    case ButtonRelease:
slouken@1895
   424
        {
slouken@1895
   425
            posted = SDL_PrivateMouseButton(SDL_RELEASED,
slouken@1895
   426
                                            xevent.xbutton.button, 0, 0);
slouken@1895
   427
        }
slouken@1895
   428
        break;
slouken@0
   429
slouken@1895
   430
        /* Key press? */
slouken@1895
   431
    case KeyPress:
slouken@1895
   432
        {
slouken@1895
   433
            static SDL_keysym saved_keysym;
slouken@1895
   434
            SDL_keysym keysym;
slouken@1895
   435
            KeyCode keycode = xevent.xkey.keycode;
slouken@14
   436
slouken@14
   437
#ifdef DEBUG_XEVENTS
slouken@1895
   438
            printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
slouken@14
   439
#endif
slouken@1895
   440
            /* Get the translated SDL virtual keysym */
slouken@1895
   441
            if (keycode) {
slouken@1895
   442
                keysym.scancode = keycode;
slouken@1895
   443
                keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
slouken@1895
   444
                keysym.mod = KMOD_NONE;
slouken@1895
   445
                keysym.unicode = 0;
slouken@1895
   446
            } else {
slouken@1895
   447
                keysym = saved_keysym;
slouken@1895
   448
            }
slouken@1327
   449
slouken@1895
   450
            /* If we're not doing translation, we're done! */
slouken@1895
   451
            if (!SDL_TranslateUNICODE) {
slouken@1895
   452
                posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
slouken@1895
   453
                break;
slouken@1895
   454
            }
slouken@1327
   455
slouken@1895
   456
            if (XFilterEvent(&xevent, None)) {
slouken@1895
   457
                if (xevent.xkey.keycode) {
slouken@1895
   458
                    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
slouken@1895
   459
                } else {
slouken@1895
   460
                    /* Save event to be associated with IM text
slouken@1895
   461
                       In 1.3 we'll have a text event instead.. */
slouken@1895
   462
                    saved_keysym = keysym;
slouken@1895
   463
                }
slouken@1895
   464
                break;
slouken@1895
   465
            }
slouken@1327
   466
slouken@1895
   467
            /* Look up the translated value for the key event */
slouken@1327
   468
#ifdef X_HAVE_UTF8_STRING
slouken@1895
   469
            if (SDL_IC != NULL) {
slouken@1895
   470
                static Status state;
slouken@1895
   471
                /* A UTF-8 character can be at most 6 bytes */
slouken@1895
   472
                char keybuf[6];
slouken@1895
   473
                if (Xutf8LookupString(SDL_IC, &xevent.xkey,
slouken@1895
   474
                                      keybuf, sizeof(keybuf), NULL, &state)) {
slouken@1895
   475
                    keysym.unicode = Utf8ToUcs4((Uint8 *) keybuf);
slouken@1895
   476
                }
slouken@1895
   477
            } else
slouken@1327
   478
#endif
slouken@1895
   479
            {
slouken@1895
   480
                static XComposeStatus state;
slouken@1895
   481
                char keybuf[32];
slouken@1327
   482
slouken@1895
   483
                if (XLookupString(&xevent.xkey,
slouken@1895
   484
                                  keybuf, sizeof(keybuf), NULL, &state)) {
slouken@1895
   485
                    /*
slouken@1895
   486
                     * FIXME: XLookupString() may yield more than one
slouken@1895
   487
                     * character, so we need a mechanism to allow for
slouken@1895
   488
                     * this (perhaps null keypress events with a
slouken@1895
   489
                     * unicode value)
slouken@1895
   490
                     */
slouken@1895
   491
                    keysym.unicode = (Uint8) keybuf[0];
slouken@1895
   492
                }
slouken@1895
   493
            }
slouken@1895
   494
            posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
slouken@1895
   495
        }
slouken@1895
   496
        break;
slouken@0
   497
slouken@1895
   498
        /* Key release? */
slouken@1895
   499
    case KeyRelease:
slouken@1895
   500
        {
slouken@1895
   501
            SDL_keysym keysym;
slouken@1895
   502
            KeyCode keycode = xevent.xkey.keycode;
slouken@0
   503
slouken@14
   504
#ifdef DEBUG_XEVENTS
slouken@1895
   505
            printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
slouken@14
   506
#endif
slouken@1895
   507
            /* Check to see if this is a repeated key */
slouken@1895
   508
            if (X11_KeyRepeat(SDL_Display, &xevent)) {
slouken@1895
   509
                break;
slouken@1895
   510
            }
slouken@1327
   511
slouken@1895
   512
            /* Get the translated SDL virtual keysym */
slouken@1895
   513
            keysym.scancode = keycode;
slouken@1895
   514
            keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
slouken@1895
   515
            keysym.mod = KMOD_NONE;
slouken@1895
   516
            keysym.unicode = 0;
slouken@1327
   517
slouken@1895
   518
            posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
slouken@1895
   519
        }
slouken@1895
   520
        break;
slouken@0
   521
slouken@1895
   522
        /* Have we been iconified? */
slouken@1895
   523
    case UnmapNotify:
slouken@1895
   524
        {
slouken@0
   525
#ifdef DEBUG_XEVENTS
slouken@1895
   526
            printf("UnmapNotify!\n");
slouken@0
   527
#endif
slouken@1895
   528
            /* If we're active, make ourselves inactive */
slouken@1895
   529
            if (SDL_GetAppState() & SDL_APPACTIVE) {
slouken@1895
   530
                /* Swap out the gamma before we go inactive */
slouken@1895
   531
                X11_SwapVidModeGamma(_this);
slouken@0
   532
slouken@1895
   533
                /* Send an internal deactivate event */
slouken@1895
   534
                posted = SDL_PrivateAppActive(0,
slouken@1895
   535
                                              SDL_APPACTIVE |
slouken@1895
   536
                                              SDL_APPINPUTFOCUS);
slouken@1895
   537
            }
slouken@1895
   538
        }
slouken@1895
   539
        break;
slouken@0
   540
slouken@1895
   541
        /* Have we been restored? */
slouken@1895
   542
    case MapNotify:
slouken@1895
   543
        {
slouken@0
   544
#ifdef DEBUG_XEVENTS
slouken@1895
   545
            printf("MapNotify!\n");
slouken@0
   546
#endif
slouken@1895
   547
            /* If we're not active, make ourselves active */
slouken@1895
   548
            if (!(SDL_GetAppState() & SDL_APPACTIVE)) {
slouken@1895
   549
                /* Send an internal activate event */
slouken@1895
   550
                posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
slouken@0
   551
slouken@1895
   552
                /* Now that we're active, swap the gamma back */
slouken@1895
   553
                X11_SwapVidModeGamma(_this);
slouken@1895
   554
            }
slouken@0
   555
slouken@1895
   556
            if (SDL_VideoSurface &&
slouken@1895
   557
                (SDL_VideoSurface->flags & SDL_FULLSCREEN)) {
slouken@1895
   558
                X11_EnterFullScreen(_this);
slouken@1895
   559
            } else {
slouken@1895
   560
                X11_GrabInputNoLock(_this, SDL_CurrentWindow.input_grab);
slouken@1895
   561
            }
slouken@1895
   562
            X11_CheckMouseModeNoLock(_this);
slouken@8
   563
slouken@1895
   564
            if (SDL_VideoSurface) {
slouken@1895
   565
                X11_RefreshDisplay(_this);
slouken@1895
   566
            }
slouken@1895
   567
        }
slouken@1895
   568
        break;
slouken@0
   569
slouken@1895
   570
        /* Have we been resized or moved? */
slouken@1895
   571
    case ConfigureNotify:
slouken@1895
   572
        {
slouken@0
   573
#ifdef DEBUG_XEVENTS
slouken@1895
   574
            printf("ConfigureNotify! (resize: %dx%d)\n",
slouken@1895
   575
                   xevent.xconfigure.width, xevent.xconfigure.height);
slouken@0
   576
#endif
slouken@1895
   577
            if (SDL_VideoSurface) {
slouken@1895
   578
                if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
slouken@1895
   579
                    (xevent.xconfigure.height != SDL_VideoSurface->h)) {
slouken@1895
   580
                    /* FIXME: Find a better fix for the bug with KDE 1.2 */
slouken@1895
   581
                    if (!((xevent.xconfigure.width == 32) &&
slouken@1895
   582
                          (xevent.xconfigure.height == 32))) {
slouken@1895
   583
                        SDL_PrivateResize(xevent.xconfigure.width,
slouken@1895
   584
                                          xevent.xconfigure.height);
slouken@1895
   585
                    }
slouken@1895
   586
                } else {
slouken@1895
   587
                    /* OpenGL windows need to know about the change */
slouken@1895
   588
                    if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) {
slouken@1895
   589
                        SDL_PrivateExpose();
slouken@1895
   590
                    }
slouken@1895
   591
                }
slouken@1895
   592
            }
slouken@1895
   593
        }
slouken@1895
   594
        break;
slouken@0
   595
slouken@1895
   596
        /* Have we been requested to quit (or another client message?) */
slouken@1895
   597
    case ClientMessage:
slouken@1895
   598
        {
slouken@1895
   599
            if ((xevent.xclient.format == 32) &&
slouken@1895
   600
                (xevent.xclient.data.l[0] == WM_DELETE_WINDOW)) {
slouken@1895
   601
                posted = SDL_PrivateQuit();
slouken@1895
   602
            } else if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
slouken@1895
   603
                SDL_SysWMmsg wmmsg;
slouken@0
   604
slouken@1895
   605
                SDL_VERSION(&wmmsg.version);
slouken@1895
   606
                wmmsg.subsystem = SDL_SYSWM_X11;
slouken@1895
   607
                wmmsg.event.xevent = xevent;
slouken@1895
   608
                posted = SDL_PrivateSysWMEvent(&wmmsg);
slouken@1895
   609
            }
slouken@1895
   610
        }
slouken@1895
   611
        break;
slouken@0
   612
slouken@1895
   613
        /* Do we need to refresh ourselves? */
slouken@1895
   614
    case Expose:
slouken@1895
   615
        {
slouken@0
   616
#ifdef DEBUG_XEVENTS
slouken@1895
   617
            printf("Expose (count = %d)\n", xevent.xexpose.count);
slouken@0
   618
#endif
slouken@1895
   619
            if (SDL_VideoSurface && (xevent.xexpose.count == 0)) {
slouken@1895
   620
                X11_RefreshDisplay(_this);
slouken@1895
   621
            }
slouken@1895
   622
        }
slouken@1895
   623
        break;
slouken@0
   624
slouken@1895
   625
    default:
slouken@1895
   626
        {
slouken@0
   627
#ifdef DEBUG_XEVENTS
slouken@1895
   628
            printf("Unhandled event %d\n", xevent.type);
slouken@0
   629
#endif
slouken@1895
   630
            /* Only post the event if we're watching for it */
slouken@1895
   631
            if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
slouken@1895
   632
                SDL_SysWMmsg wmmsg;
slouken@0
   633
slouken@1895
   634
                SDL_VERSION(&wmmsg.version);
slouken@1895
   635
                wmmsg.subsystem = SDL_SYSWM_X11;
slouken@1895
   636
                wmmsg.event.xevent = xevent;
slouken@1895
   637
                posted = SDL_PrivateSysWMEvent(&wmmsg);
slouken@1895
   638
            }
slouken@1895
   639
        }
slouken@1895
   640
        break;
slouken@1895
   641
    }
slouken@1895
   642
    return (posted);
slouken@0
   643
}
slouken@0
   644
slouken@0
   645
/* Ack!  XPending() actually performs a blocking read if no events available */
slouken@1895
   646
int
slouken@1895
   647
X11_Pending(Display * display)
slouken@0
   648
{
slouken@1895
   649
    /* Flush the display connection and look to see if events are queued */
slouken@1895
   650
    XFlush(display);
slouken@1895
   651
    if (XEventsQueued(display, QueuedAlready)) {
slouken@1895
   652
        return (1);
slouken@1895
   653
    }
slouken@0
   654
slouken@1895
   655
    /* More drastic measures are required -- see if X is ready to talk */
slouken@1895
   656
    {
slouken@1895
   657
        static struct timeval zero_time;        /* static == 0 */
slouken@1895
   658
        int x11_fd;
slouken@1895
   659
        fd_set fdset;
slouken@0
   660
slouken@1895
   661
        x11_fd = ConnectionNumber(display);
slouken@1895
   662
        FD_ZERO(&fdset);
slouken@1895
   663
        FD_SET(x11_fd, &fdset);
slouken@1895
   664
        if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
slouken@1895
   665
            return (XPending(display));
slouken@1895
   666
        }
slouken@1895
   667
    }
slouken@0
   668
slouken@1895
   669
    /* Oh well, nothing is ready .. */
slouken@1895
   670
    return (0);
slouken@0
   671
}
slouken@0
   672
slouken@1895
   673
void
slouken@1895
   674
X11_PumpEvents(_THIS)
slouken@0
   675
{
slouken@1895
   676
    int pending;
slouken@0
   677
slouken@1895
   678
    /* Keep processing pending events */
slouken@1895
   679
    pending = 0;
slouken@1895
   680
    while (X11_Pending(SDL_Display)) {
slouken@1895
   681
        X11_DispatchEvent(_this);
slouken@1895
   682
        ++pending;
slouken@1895
   683
    }
slouken@1895
   684
    if (switch_waiting) {
slouken@1895
   685
        Uint32 now;
slouken@0
   686
slouken@1895
   687
        now = SDL_GetTicks();
slouken@1895
   688
        if (pending || !SDL_VideoSurface) {
slouken@1895
   689
            /* Try again later... */
slouken@1895
   690
            if (switch_waiting & SDL_FULLSCREEN) {
slouken@1895
   691
                switch_time = now + 1500;
slouken@1895
   692
            } else {
slouken@1895
   693
                switch_time = now + 200;
slouken@1895
   694
            }
slouken@1895
   695
        } else if ((int) (switch_time - now) <= 0) {
slouken@1895
   696
            Uint32 go_fullscreen;
slouken@0
   697
slouken@1895
   698
            go_fullscreen = switch_waiting & SDL_FULLSCREEN;
slouken@1895
   699
            switch_waiting = 0;
slouken@1895
   700
            if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
slouken@1895
   701
                if (go_fullscreen) {
slouken@1895
   702
                    X11_EnterFullScreen(_this);
slouken@1895
   703
                } else {
slouken@1895
   704
                    X11_LeaveFullScreen(_this);
slouken@1895
   705
                }
slouken@1895
   706
            }
slouken@1895
   707
            /* Handle focus in/out when grabbed */
slouken@1895
   708
            if (go_fullscreen) {
slouken@1895
   709
                X11_GrabInputNoLock(_this, SDL_CurrentWindow.input_grab);
slouken@1895
   710
            } else {
slouken@1895
   711
                X11_GrabInputNoLock(_this, SDL_GRAB_OFF);
slouken@1895
   712
            }
slouken@1895
   713
            X11_CheckMouseModeNoLock(_this);
slouken@1895
   714
        }
slouken@1895
   715
    }
slouken@0
   716
}
slouken@0
   717
slouken@1895
   718
void
slouken@1895
   719
X11_InitKeymap(void)
slouken@0
   720
{
slouken@1895
   721
    int i;
slouken@0
   722
slouken@1895
   723
    /* Odd keys used in international keyboards */
slouken@1895
   724
    for (i = 0; i < SDL_arraysize(ODD_keymap); ++i)
slouken@1895
   725
        ODD_keymap[i] = SDLK_UNKNOWN;
slouken@0
   726
slouken@1895
   727
    /* Some of these might be mappable to an existing SDLK_ code */
slouken@1895
   728
    ODD_keymap[XK_dead_grave & 0xFF] = SDLK_COMPOSE;
slouken@1895
   729
    ODD_keymap[XK_dead_acute & 0xFF] = SDLK_COMPOSE;
slouken@1895
   730
    ODD_keymap[XK_dead_tilde & 0xFF] = SDLK_COMPOSE;
slouken@1895
   731
    ODD_keymap[XK_dead_macron & 0xFF] = SDLK_COMPOSE;
slouken@1895
   732
    ODD_keymap[XK_dead_breve & 0xFF] = SDLK_COMPOSE;
slouken@1895
   733
    ODD_keymap[XK_dead_abovedot & 0xFF] = SDLK_COMPOSE;
slouken@1895
   734
    ODD_keymap[XK_dead_diaeresis & 0xFF] = SDLK_COMPOSE;
slouken@1895
   735
    ODD_keymap[XK_dead_abovering & 0xFF] = SDLK_COMPOSE;
slouken@1895
   736
    ODD_keymap[XK_dead_doubleacute & 0xFF] = SDLK_COMPOSE;
slouken@1895
   737
    ODD_keymap[XK_dead_caron & 0xFF] = SDLK_COMPOSE;
slouken@1895
   738
    ODD_keymap[XK_dead_cedilla & 0xFF] = SDLK_COMPOSE;
slouken@1895
   739
    ODD_keymap[XK_dead_ogonek & 0xFF] = SDLK_COMPOSE;
slouken@1895
   740
    ODD_keymap[XK_dead_iota & 0xFF] = SDLK_COMPOSE;
slouken@1895
   741
    ODD_keymap[XK_dead_voiced_sound & 0xFF] = SDLK_COMPOSE;
slouken@1895
   742
    ODD_keymap[XK_dead_semivoiced_sound & 0xFF] = SDLK_COMPOSE;
slouken@1895
   743
    ODD_keymap[XK_dead_belowdot & 0xFF] = SDLK_COMPOSE;
slouken@1328
   744
#ifdef XK_dead_hook
slouken@1895
   745
    ODD_keymap[XK_dead_hook & 0xFF] = SDLK_COMPOSE;
slouken@1328
   746
#endif
slouken@1328
   747
#ifdef XK_dead_horn
slouken@1895
   748
    ODD_keymap[XK_dead_horn & 0xFF] = SDLK_COMPOSE;
slouken@1328
   749
#endif
slouken@1327
   750
slouken@0
   751
#ifdef XK_dead_circumflex
slouken@1895
   752
    /* These X keysyms have 0xFE as the high byte */
slouken@1895
   753
    ODD_keymap[XK_dead_circumflex & 0xFF] = SDLK_CARET;
slouken@0
   754
#endif
slouken@805
   755
#ifdef XK_ISO_Level3_Shift
slouken@1895
   756
    ODD_keymap[XK_ISO_Level3_Shift & 0xFF] = SDLK_MODE; /* "Alt Gr" key */
slouken@805
   757
#endif
slouken@0
   758
slouken@1895
   759
    /* Map the miscellaneous keys */
slouken@1895
   760
    for (i = 0; i < SDL_arraysize(MISC_keymap); ++i)
slouken@1895
   761
        MISC_keymap[i] = SDLK_UNKNOWN;
slouken@0
   762
slouken@1895
   763
    /* These X keysyms have 0xFF as the high byte */
slouken@1895
   764
    MISC_keymap[XK_BackSpace & 0xFF] = SDLK_BACKSPACE;
slouken@1895
   765
    MISC_keymap[XK_Tab & 0xFF] = SDLK_TAB;
slouken@1895
   766
    MISC_keymap[XK_Clear & 0xFF] = SDLK_CLEAR;
slouken@1895
   767
    MISC_keymap[XK_Return & 0xFF] = SDLK_RETURN;
slouken@1895
   768
    MISC_keymap[XK_Pause & 0xFF] = SDLK_PAUSE;
slouken@1895
   769
    MISC_keymap[XK_Escape & 0xFF] = SDLK_ESCAPE;
slouken@1895
   770
    MISC_keymap[XK_Delete & 0xFF] = SDLK_DELETE;
slouken@0
   771
slouken@1895
   772
    MISC_keymap[XK_KP_0 & 0xFF] = SDLK_KP0;     /* Keypad 0-9 */
slouken@1895
   773
    MISC_keymap[XK_KP_1 & 0xFF] = SDLK_KP1;
slouken@1895
   774
    MISC_keymap[XK_KP_2 & 0xFF] = SDLK_KP2;
slouken@1895
   775
    MISC_keymap[XK_KP_3 & 0xFF] = SDLK_KP3;
slouken@1895
   776
    MISC_keymap[XK_KP_4 & 0xFF] = SDLK_KP4;
slouken@1895
   777
    MISC_keymap[XK_KP_5 & 0xFF] = SDLK_KP5;
slouken@1895
   778
    MISC_keymap[XK_KP_6 & 0xFF] = SDLK_KP6;
slouken@1895
   779
    MISC_keymap[XK_KP_7 & 0xFF] = SDLK_KP7;
slouken@1895
   780
    MISC_keymap[XK_KP_8 & 0xFF] = SDLK_KP8;
slouken@1895
   781
    MISC_keymap[XK_KP_9 & 0xFF] = SDLK_KP9;
slouken@1895
   782
    MISC_keymap[XK_KP_Insert & 0xFF] = SDLK_KP0;
slouken@1895
   783
    MISC_keymap[XK_KP_End & 0xFF] = SDLK_KP1;
slouken@1895
   784
    MISC_keymap[XK_KP_Down & 0xFF] = SDLK_KP2;
slouken@1895
   785
    MISC_keymap[XK_KP_Page_Down & 0xFF] = SDLK_KP3;
slouken@1895
   786
    MISC_keymap[XK_KP_Left & 0xFF] = SDLK_KP4;
slouken@1895
   787
    MISC_keymap[XK_KP_Begin & 0xFF] = SDLK_KP5;
slouken@1895
   788
    MISC_keymap[XK_KP_Right & 0xFF] = SDLK_KP6;
slouken@1895
   789
    MISC_keymap[XK_KP_Home & 0xFF] = SDLK_KP7;
slouken@1895
   790
    MISC_keymap[XK_KP_Up & 0xFF] = SDLK_KP8;
slouken@1895
   791
    MISC_keymap[XK_KP_Page_Up & 0xFF] = SDLK_KP9;
slouken@1895
   792
    MISC_keymap[XK_KP_Delete & 0xFF] = SDLK_KP_PERIOD;
slouken@1895
   793
    MISC_keymap[XK_KP_Decimal & 0xFF] = SDLK_KP_PERIOD;
slouken@1895
   794
    MISC_keymap[XK_KP_Divide & 0xFF] = SDLK_KP_DIVIDE;
slouken@1895
   795
    MISC_keymap[XK_KP_Multiply & 0xFF] = SDLK_KP_MULTIPLY;
slouken@1895
   796
    MISC_keymap[XK_KP_Subtract & 0xFF] = SDLK_KP_MINUS;
slouken@1895
   797
    MISC_keymap[XK_KP_Add & 0xFF] = SDLK_KP_PLUS;
slouken@1895
   798
    MISC_keymap[XK_KP_Enter & 0xFF] = SDLK_KP_ENTER;
slouken@1895
   799
    MISC_keymap[XK_KP_Equal & 0xFF] = SDLK_KP_EQUALS;
slouken@0
   800
slouken@1895
   801
    MISC_keymap[XK_Up & 0xFF] = SDLK_UP;
slouken@1895
   802
    MISC_keymap[XK_Down & 0xFF] = SDLK_DOWN;
slouken@1895
   803
    MISC_keymap[XK_Right & 0xFF] = SDLK_RIGHT;
slouken@1895
   804
    MISC_keymap[XK_Left & 0xFF] = SDLK_LEFT;
slouken@1895
   805
    MISC_keymap[XK_Insert & 0xFF] = SDLK_INSERT;
slouken@1895
   806
    MISC_keymap[XK_Home & 0xFF] = SDLK_HOME;
slouken@1895
   807
    MISC_keymap[XK_End & 0xFF] = SDLK_END;
slouken@1895
   808
    MISC_keymap[XK_Page_Up & 0xFF] = SDLK_PAGEUP;
slouken@1895
   809
    MISC_keymap[XK_Page_Down & 0xFF] = SDLK_PAGEDOWN;
slouken@0
   810
slouken@1895
   811
    MISC_keymap[XK_F1 & 0xFF] = SDLK_F1;
slouken@1895
   812
    MISC_keymap[XK_F2 & 0xFF] = SDLK_F2;
slouken@1895
   813
    MISC_keymap[XK_F3 & 0xFF] = SDLK_F3;
slouken@1895
   814
    MISC_keymap[XK_F4 & 0xFF] = SDLK_F4;
slouken@1895
   815
    MISC_keymap[XK_F5 & 0xFF] = SDLK_F5;
slouken@1895
   816
    MISC_keymap[XK_F6 & 0xFF] = SDLK_F6;
slouken@1895
   817
    MISC_keymap[XK_F7 & 0xFF] = SDLK_F7;
slouken@1895
   818
    MISC_keymap[XK_F8 & 0xFF] = SDLK_F8;
slouken@1895
   819
    MISC_keymap[XK_F9 & 0xFF] = SDLK_F9;
slouken@1895
   820
    MISC_keymap[XK_F10 & 0xFF] = SDLK_F10;
slouken@1895
   821
    MISC_keymap[XK_F11 & 0xFF] = SDLK_F11;
slouken@1895
   822
    MISC_keymap[XK_F12 & 0xFF] = SDLK_F12;
slouken@1895
   823
    MISC_keymap[XK_F13 & 0xFF] = SDLK_F13;
slouken@1895
   824
    MISC_keymap[XK_F14 & 0xFF] = SDLK_F14;
slouken@1895
   825
    MISC_keymap[XK_F15 & 0xFF] = SDLK_F15;
slouken@0
   826
slouken@1895
   827
    MISC_keymap[XK_Num_Lock & 0xFF] = SDLK_NUMLOCK;
slouken@1895
   828
    MISC_keymap[XK_Caps_Lock & 0xFF] = SDLK_CAPSLOCK;
slouken@1895
   829
    MISC_keymap[XK_Scroll_Lock & 0xFF] = SDLK_SCROLLOCK;
slouken@1895
   830
    MISC_keymap[XK_Shift_R & 0xFF] = SDLK_RSHIFT;
slouken@1895
   831
    MISC_keymap[XK_Shift_L & 0xFF] = SDLK_LSHIFT;
slouken@1895
   832
    MISC_keymap[XK_Control_R & 0xFF] = SDLK_RCTRL;
slouken@1895
   833
    MISC_keymap[XK_Control_L & 0xFF] = SDLK_LCTRL;
slouken@1895
   834
    MISC_keymap[XK_Alt_R & 0xFF] = SDLK_RALT;
slouken@1895
   835
    MISC_keymap[XK_Alt_L & 0xFF] = SDLK_LALT;
slouken@1895
   836
    MISC_keymap[XK_Meta_R & 0xFF] = SDLK_RMETA;
slouken@1895
   837
    MISC_keymap[XK_Meta_L & 0xFF] = SDLK_LMETA;
slouken@1895
   838
    MISC_keymap[XK_Super_L & 0xFF] = SDLK_LSUPER;       /* Left "Windows" */
slouken@1895
   839
    MISC_keymap[XK_Super_R & 0xFF] = SDLK_RSUPER;       /* Right "Windows */
slouken@1895
   840
    MISC_keymap[XK_Mode_switch & 0xFF] = SDLK_MODE;     /* "Alt Gr" key */
slouken@1895
   841
    MISC_keymap[XK_Multi_key & 0xFF] = SDLK_COMPOSE;    /* Multi-key compose */
slouken@0
   842
slouken@1895
   843
    MISC_keymap[XK_Help & 0xFF] = SDLK_HELP;
slouken@1895
   844
    MISC_keymap[XK_Print & 0xFF] = SDLK_PRINT;
slouken@1895
   845
    MISC_keymap[XK_Sys_Req & 0xFF] = SDLK_SYSREQ;
slouken@1895
   846
    MISC_keymap[XK_Break & 0xFF] = SDLK_BREAK;
slouken@1895
   847
    MISC_keymap[XK_Menu & 0xFF] = SDLK_MENU;
slouken@1895
   848
    MISC_keymap[XK_Hyper_R & 0xFF] = SDLK_MENU; /* Windows "Menu" key */
slouken@0
   849
}
slouken@0
   850
slouken@1327
   851
/* Get the translated SDL virtual keysym */
slouken@1895
   852
SDLKey
slouken@1895
   853
X11_TranslateKeycode(Display * display, KeyCode kc)
slouken@0
   854
{
slouken@1895
   855
    KeySym xsym;
slouken@1895
   856
    SDLKey key;
slouken@0
   857
slouken@1895
   858
    xsym = XKeycodeToKeysym(display, kc, 0);
slouken@0
   859
#ifdef DEBUG_KEYS
slouken@1895
   860
    fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
slouken@0
   861
#endif
slouken@1895
   862
    key = SDLK_UNKNOWN;
slouken@1895
   863
    if (xsym) {
slouken@1895
   864
        switch (xsym >> 8) {
slouken@1895
   865
        case 0x1005FF:
slouken@0
   866
#ifdef SunXK_F36
slouken@1895
   867
            if (xsym == SunXK_F36)
slouken@1895
   868
                key = SDLK_F11;
slouken@0
   869
#endif
slouken@0
   870
#ifdef SunXK_F37
slouken@1895
   871
            if (xsym == SunXK_F37)
slouken@1895
   872
                key = SDLK_F12;
slouken@0
   873
#endif
slouken@1895
   874
            break;
slouken@1895
   875
        case 0x00:             /* Latin 1 */
slouken@1895
   876
            key = (SDLKey) (xsym & 0xFF);
slouken@1895
   877
            break;
slouken@1895
   878
        case 0x01:             /* Latin 2 */
slouken@1895
   879
        case 0x02:             /* Latin 3 */
slouken@1895
   880
        case 0x03:             /* Latin 4 */
slouken@1895
   881
        case 0x04:             /* Katakana */
slouken@1895
   882
        case 0x05:             /* Arabic */
slouken@1895
   883
        case 0x06:             /* Cyrillic */
slouken@1895
   884
        case 0x07:             /* Greek */
slouken@1895
   885
        case 0x08:             /* Technical */
slouken@1895
   886
        case 0x0A:             /* Publishing */
slouken@1895
   887
        case 0x0C:             /* Hebrew */
slouken@1895
   888
        case 0x0D:             /* Thai */
slouken@1895
   889
            /* These are wrong, but it's better than nothing */
slouken@1895
   890
            key = (SDLKey) (xsym & 0xFF);
slouken@1895
   891
            break;
slouken@1895
   892
        case 0xFE:
slouken@1895
   893
            key = ODD_keymap[xsym & 0xFF];
slouken@1895
   894
            break;
slouken@1895
   895
        case 0xFF:
slouken@1895
   896
            key = MISC_keymap[xsym & 0xFF];
slouken@1895
   897
            break;
slouken@1895
   898
        default:
slouken@1895
   899
            /*
slouken@1895
   900
               fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
slouken@1895
   901
               (unsigned int)xsym);
slouken@1895
   902
             */
slouken@1895
   903
            break;
slouken@1895
   904
        }
slouken@1895
   905
    } else {
slouken@1895
   906
        /* X11 doesn't know how to translate the key! */
slouken@1895
   907
        switch (kc) {
slouken@1895
   908
            /* Caution:
slouken@1895
   909
               These keycodes are from the Microsoft Keyboard
slouken@1895
   910
             */
slouken@1895
   911
        case 115:
slouken@1895
   912
            key = SDLK_LSUPER;
slouken@1895
   913
            break;
slouken@1895
   914
        case 116:
slouken@1895
   915
            key = SDLK_RSUPER;
slouken@1895
   916
            break;
slouken@1895
   917
        case 117:
slouken@1895
   918
            key = SDLK_MENU;
slouken@1895
   919
            break;
slouken@1895
   920
        default:
slouken@1895
   921
            /*
slouken@1895
   922
             * no point in an error message; happens for
slouken@1895
   923
             * several keys when we get a keymap notify
slouken@1895
   924
             */
slouken@1895
   925
            break;
slouken@1895
   926
        }
slouken@1895
   927
    }
slouken@1895
   928
    return key;
slouken@0
   929
}
slouken@0
   930
slouken@0
   931
/* X11 modifier masks for various keys */
slouken@0
   932
static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
slouken@0
   933
static unsigned num_mask, mode_switch_mask;
slouken@0
   934
slouken@1895
   935
static void
slouken@1895
   936
get_modifier_masks(Display * display)
slouken@0
   937
{
slouken@1895
   938
    static unsigned got_masks;
slouken@1895
   939
    int i, j;
slouken@1895
   940
    XModifierKeymap *xmods;
slouken@1895
   941
    unsigned n;
slouken@0
   942
slouken@1895
   943
    if (got_masks)
slouken@1895
   944
        return;
slouken@0
   945
slouken@1895
   946
    xmods = XGetModifierMapping(display);
slouken@1895
   947
    n = xmods->max_keypermod;
slouken@1895
   948
    for (i = 3; i < 8; i++) {
slouken@1895
   949
        for (j = 0; j < n; j++) {
slouken@1895
   950
            KeyCode kc = xmods->modifiermap[i * n + j];
slouken@1895
   951
            KeySym ks = XKeycodeToKeysym(display, kc, 0);
slouken@1895
   952
            unsigned mask = 1 << i;
slouken@1895
   953
            switch (ks) {
slouken@1895
   954
            case XK_Num_Lock:
slouken@1895
   955
                num_mask = mask;
slouken@1895
   956
                break;
slouken@1895
   957
            case XK_Alt_L:
slouken@1895
   958
                alt_l_mask = mask;
slouken@1895
   959
                break;
slouken@1895
   960
            case XK_Alt_R:
slouken@1895
   961
                alt_r_mask = mask;
slouken@1895
   962
                break;
slouken@1895
   963
            case XK_Meta_L:
slouken@1895
   964
                meta_l_mask = mask;
slouken@1895
   965
                break;
slouken@1895
   966
            case XK_Meta_R:
slouken@1895
   967
                meta_r_mask = mask;
slouken@1895
   968
                break;
slouken@1895
   969
            case XK_Mode_switch:
slouken@1895
   970
                mode_switch_mask = mask;
slouken@1895
   971
                break;
slouken@1895
   972
            }
slouken@1895
   973
        }
slouken@1895
   974
    }
slouken@1895
   975
    XFreeModifiermap(xmods);
slouken@1895
   976
    got_masks = 1;
slouken@0
   977
}
slouken@0
   978
slouken@0
   979
slouken@0
   980
/*
slouken@0
   981
 * This function is semi-official; it is not officially exported and should
slouken@0
   982
 * not be considered part of the SDL API, but may be used by client code
slouken@0
   983
 * that *really* needs it (including legacy code).
slouken@0
   984
 * It is slow, though, and should be avoided if possible.
slouken@0
   985
 *
slouken@0
   986
 * Note that it isn't completely accurate either; in particular, multi-key
slouken@0
   987
 * sequences (dead accents, compose key sequences) will not work since the
slouken@0
   988
 * state has been irrevocably lost.
slouken@0
   989
 */
slouken@1895
   990
Uint16
slouken@1895
   991
X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
slouken@0
   992
{
slouken@1895
   993
    SDL_VideoDevice *_this = SDL_GetVideoDevice();
slouken@1895
   994
    char keybuf[32];
slouken@1895
   995
    int i;
slouken@1895
   996
    KeySym xsym = 0;
slouken@1895
   997
    XKeyEvent xkey;
slouken@1895
   998
    Uint16 unicode;
slouken@0
   999
slouken@1895
  1000
    if (!_this || !SDL_Display) {
slouken@1895
  1001
        return 0;
slouken@1895
  1002
    }
slouken@0
  1003
slouken@1895
  1004
    SDL_memset(&xkey, 0, sizeof(xkey));
slouken@1895
  1005
    xkey.display = SDL_Display;
slouken@0
  1006
slouken@1895
  1007
    xsym = keysym;              /* last resort if not found */
slouken@1895
  1008
    for (i = 0; i < 256; ++i) {
slouken@1895
  1009
        if (MISC_keymap[i] == keysym) {
slouken@1895
  1010
            xsym = 0xFF00 | i;
slouken@1895
  1011
            break;
slouken@1895
  1012
        } else if (ODD_keymap[i] == keysym) {
slouken@1895
  1013
            xsym = 0xFE00 | i;
slouken@1895
  1014
            break;
slouken@1895
  1015
        }
slouken@1895
  1016
    }
slouken@0
  1017
slouken@1895
  1018
    xkey.keycode = XKeysymToKeycode(xkey.display, xsym);
slouken@0
  1019
slouken@1895
  1020
    get_modifier_masks(SDL_Display);
slouken@1895
  1021
    if (modifiers & KMOD_SHIFT)
slouken@1895
  1022
        xkey.state |= ShiftMask;
slouken@1895
  1023
    if (modifiers & KMOD_CAPS)
slouken@1895
  1024
        xkey.state |= LockMask;
slouken@1895
  1025
    if (modifiers & KMOD_CTRL)
slouken@1895
  1026
        xkey.state |= ControlMask;
slouken@1895
  1027
    if (modifiers & KMOD_MODE)
slouken@1895
  1028
        xkey.state |= mode_switch_mask;
slouken@1895
  1029
    if (modifiers & KMOD_LALT)
slouken@1895
  1030
        xkey.state |= alt_l_mask;
slouken@1895
  1031
    if (modifiers & KMOD_RALT)
slouken@1895
  1032
        xkey.state |= alt_r_mask;
slouken@1895
  1033
    if (modifiers & KMOD_LMETA)
slouken@1895
  1034
        xkey.state |= meta_l_mask;
slouken@1895
  1035
    if (modifiers & KMOD_RMETA)
slouken@1895
  1036
        xkey.state |= meta_r_mask;
slouken@1895
  1037
    if (modifiers & KMOD_NUM)
slouken@1895
  1038
        xkey.state |= num_mask;
slouken@0
  1039
slouken@1895
  1040
    unicode = 0;
slouken@1895
  1041
    if (XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL))
slouken@1895
  1042
        unicode = (unsigned char) keybuf[0];
slouken@1895
  1043
    return (unicode);
slouken@0
  1044
}
slouken@0
  1045
icculus@1178
  1046
slouken@0
  1047
/*
slouken@0
  1048
 * Called when focus is regained, to read the keyboard state and generate
slouken@0
  1049
 * synthetic keypress/release events.
slouken@0
  1050
 * key_vec is a bit vector of keycodes (256 bits)
slouken@0
  1051
 */
slouken@1895
  1052
void
slouken@1895
  1053
X11_SetKeyboardState(Display * display, const char *key_vec)
slouken@0
  1054
{
slouken@1895
  1055
    char keys_return[32];
slouken@1895
  1056
    int i;
slouken@1895
  1057
    Uint8 *kstate = SDL_GetKeyState(NULL);
slouken@1895
  1058
    SDLMod modstate;
slouken@1895
  1059
    Window junk_window;
slouken@1895
  1060
    int x, y;
slouken@1895
  1061
    unsigned int mask;
slouken@0
  1062
slouken@1895
  1063
    /* The first time the window is mapped, we initialize key state */
slouken@1895
  1064
    if (!key_vec) {
slouken@1895
  1065
        XQueryKeymap(display, keys_return);
slouken@1895
  1066
        key_vec = keys_return;
slouken@1895
  1067
    }
slouken@0
  1068
slouken@1895
  1069
    /* Get the keyboard modifier state */
slouken@1895
  1070
    modstate = 0;
slouken@1895
  1071
    get_modifier_masks(display);
slouken@1895
  1072
    if (XQueryPointer(display, DefaultRootWindow(display),
slouken@1895
  1073
                      &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
slouken@1895
  1074
        if (mask & LockMask) {
slouken@1895
  1075
            modstate |= KMOD_CAPS;
slouken@1895
  1076
        }
slouken@1895
  1077
        if (mask & mode_switch_mask) {
slouken@1895
  1078
            modstate |= KMOD_MODE;
slouken@1895
  1079
        }
slouken@1895
  1080
        if (mask & num_mask) {
slouken@1895
  1081
            modstate |= KMOD_NUM;
slouken@1895
  1082
        }
slouken@1895
  1083
    }
slouken@111
  1084
slouken@1895
  1085
    /* Zero the new keyboard state and generate it */
slouken@1895
  1086
    SDL_memset(kstate, 0, SDLK_LAST);
slouken@1895
  1087
    /*
slouken@1895
  1088
     * An obvious optimisation is to check entire longwords at a time in
slouken@1895
  1089
     * both loops, but we can't be sure the arrays are aligned so it's not
slouken@1895
  1090
     * worth the extra complexity
slouken@1895
  1091
     */
slouken@1895
  1092
    for (i = 0; i < 32; i++) {
slouken@1895
  1093
        int j;
slouken@1895
  1094
        if (!key_vec[i])
slouken@1895
  1095
            continue;
slouken@1895
  1096
        for (j = 0; j < 8; j++) {
slouken@1895
  1097
            if (key_vec[i] & (1 << j)) {
slouken@1895
  1098
                SDLKey key;
slouken@1895
  1099
                KeyCode kc = (i << 3 | j);
slouken@1895
  1100
                key = X11_TranslateKeycode(display, kc);
slouken@1895
  1101
                if (key == SDLK_UNKNOWN) {
slouken@1895
  1102
                    continue;
slouken@1895
  1103
                }
slouken@1895
  1104
                kstate[key] = SDL_PRESSED;
slouken@1895
  1105
                switch (key) {
slouken@1895
  1106
                case SDLK_LSHIFT:
slouken@1895
  1107
                    modstate |= KMOD_LSHIFT;
slouken@1895
  1108
                    break;
slouken@1895
  1109
                case SDLK_RSHIFT:
slouken@1895
  1110
                    modstate |= KMOD_RSHIFT;
slouken@1895
  1111
                    break;
slouken@1895
  1112
                case SDLK_LCTRL:
slouken@1895
  1113
                    modstate |= KMOD_LCTRL;
slouken@1895
  1114
                    break;
slouken@1895
  1115
                case SDLK_RCTRL:
slouken@1895
  1116
                    modstate |= KMOD_RCTRL;
slouken@1895
  1117
                    break;
slouken@1895
  1118
                case SDLK_LALT:
slouken@1895
  1119
                    modstate |= KMOD_LALT;
slouken@1895
  1120
                    break;
slouken@1895
  1121
                case SDLK_RALT:
slouken@1895
  1122
                    modstate |= KMOD_RALT;
slouken@1895
  1123
                    break;
slouken@1895
  1124
                case SDLK_LMETA:
slouken@1895
  1125
                    modstate |= KMOD_LMETA;
slouken@1895
  1126
                    break;
slouken@1895
  1127
                case SDLK_RMETA:
slouken@1895
  1128
                    modstate |= KMOD_RMETA;
slouken@1895
  1129
                    break;
slouken@1895
  1130
                default:
slouken@1895
  1131
                    break;
slouken@1895
  1132
                }
slouken@1895
  1133
            }
slouken@1895
  1134
        }
slouken@1895
  1135
    }
slouken@111
  1136
slouken@1895
  1137
    /* Hack - set toggle key state */
slouken@1895
  1138
    if (modstate & KMOD_CAPS) {
slouken@1895
  1139
        kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
slouken@1895
  1140
    } else {
slouken@1895
  1141
        kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
slouken@1895
  1142
    }
slouken@1895
  1143
    if (modstate & KMOD_NUM) {
slouken@1895
  1144
        kstate[SDLK_NUMLOCK] = SDL_PRESSED;
slouken@1895
  1145
    } else {
slouken@1895
  1146
        kstate[SDLK_NUMLOCK] = SDL_RELEASED;
slouken@1895
  1147
    }
slouken@111
  1148
slouken@1895
  1149
    /* Set the final modifier state */
slouken@1895
  1150
    SDL_SetModState(modstate);
slouken@0
  1151
}
slouken@0
  1152
slouken@1895
  1153
void
slouken@1895
  1154
X11_InitOSKeymap(_THIS)
slouken@0
  1155
{
slouken@1895
  1156
    X11_InitKeymap();
slouken@0
  1157
}
slouken@0
  1158
slouken@1895
  1159
void
slouken@1895
  1160
X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms)
slouken@1783
  1161
{
slouken@1895
  1162
    int timeout, interval, prefer_blank, allow_exp;
slouken@1895
  1163
    XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
slouken@1895
  1164
    *saved_timeout = timeout;
slouken@1783
  1165
slouken@1783
  1166
#if SDL_VIDEO_DRIVER_X11_DPMS
slouken@1895
  1167
    if (SDL_X11_HAVE_DPMS) {
slouken@1895
  1168
        int dummy;
slouken@1895
  1169
        if (DPMSQueryExtension(display, &dummy, &dummy)) {
slouken@1895
  1170
            CARD16 state;
slouken@1895
  1171
            DPMSInfo(display, &state, dpms);
slouken@1895
  1172
        }
slouken@1895
  1173
    }
slouken@1792
  1174
#else
slouken@1895
  1175
    *dpms = 0;
slouken@1783
  1176
#endif /* SDL_VIDEO_DRIVER_X11_DPMS */
slouken@1783
  1177
}
slouken@1783
  1178
slouken@1895
  1179
void
slouken@1895
  1180
X11_DisableScreenSaver(Display * display)
slouken@1783
  1181
{
slouken@1895
  1182
    int timeout, interval, prefer_blank, allow_exp;
slouken@1895
  1183
    XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
slouken@1895
  1184
    timeout = 0;
slouken@1895
  1185
    XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
slouken@1783
  1186
slouken@1783
  1187
#if SDL_VIDEO_DRIVER_X11_DPMS
slouken@1895
  1188
    if (SDL_X11_HAVE_DPMS) {
slouken@1895
  1189
        int dummy;
slouken@1895
  1190
        if (DPMSQueryExtension(display, &dummy, &dummy)) {
slouken@1895
  1191
            DPMSDisable(display);
slouken@1895
  1192
        }
slouken@1895
  1193
    }
slouken@1783
  1194
#endif /* SDL_VIDEO_DRIVER_X11_DPMS */
slouken@1783
  1195
}
slouken@1783
  1196
slouken@1895
  1197
void
slouken@1895
  1198
X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms)
slouken@1783
  1199
{
slouken@1895
  1200
    int timeout, interval, prefer_blank, allow_exp;
slouken@1895
  1201
    XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
slouken@1895
  1202
    timeout = saved_timeout;
slouken@1895
  1203
    XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
slouken@1783
  1204
slouken@1783
  1205
#if SDL_VIDEO_DRIVER_X11_DPMS
slouken@1895
  1206
    if (SDL_X11_HAVE_DPMS) {
slouken@1895
  1207
        int dummy;
slouken@1895
  1208
        if (DPMSQueryExtension(display, &dummy, &dummy)) {
slouken@1895
  1209
            if (dpms) {
slouken@1895
  1210
                DPMSEnable(display);
slouken@1895
  1211
            }
slouken@1895
  1212
        }
slouken@1895
  1213
    }
slouken@1783
  1214
#endif /* SDL_VIDEO_DRIVER_X11_DPMS */
slouken@1783
  1215
}
slouken@1895
  1216
slouken@1895
  1217
/* vi: set ts=4 sw=4 expandtab: */