src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1659 14717b52abc0
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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