src/video/x11/SDL_x11events.c
changeset 1951 7177581dc9fa
child 2046 da8332c8f480
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/x11/SDL_x11events.c	Thu Jul 27 06:53:23 2006 +0000
     1.3 @@ -0,0 +1,421 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2006 Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Lesser General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Lesser General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Lesser General Public
    1.19 +    License along with this library; if not, write to the Free Software
    1.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +*/
    1.25 +#include "SDL_config.h"
    1.26 +
    1.27 +#include "SDL_syswm.h"
    1.28 +#include "SDL_x11video.h"
    1.29 +#include "../../events/SDL_events_c.h"
    1.30 +
    1.31 +
    1.32 +static void
    1.33 +X11_DispatchEvent(_THIS)
    1.34 +{
    1.35 +    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    1.36 +    SDL_WindowData *data;
    1.37 +    XEvent xevent;
    1.38 +    int i;
    1.39 +
    1.40 +    SDL_zero(xevent);           /* valgrind fix. --ryan. */
    1.41 +    XNextEvent(videodata->display, &xevent);
    1.42 +
    1.43 +    /* Send a SDL_SYSWMEVENT if the application wants them */
    1.44 +    if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
    1.45 +        SDL_SysWMmsg wmmsg;
    1.46 +
    1.47 +        SDL_VERSION(&wmmsg.version);
    1.48 +        wmmsg.subsystem = SDL_SYSWM_X11;
    1.49 +        wmmsg.event.xevent = xevent;
    1.50 +        SDL_SendSysWMEvent(&wmmsg);
    1.51 +    }
    1.52 +
    1.53 +    data = NULL;
    1.54 +    for (i = 0; i < videodata->numwindows; ++i) {
    1.55 +        if (videodata->windowlist[i]->window == xevent.xany.window) {
    1.56 +            data = videodata->windowlist[i];
    1.57 +        }
    1.58 +    }
    1.59 +    if (!data) {
    1.60 +        return;
    1.61 +    }
    1.62 +
    1.63 +    switch (xevent.type) {
    1.64 +
    1.65 +        /* Gaining mouse coverage? */
    1.66 +    case EnterNotify:{
    1.67 +#ifdef DEBUG_XEVENTS
    1.68 +            printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x,
    1.69 +                   xevent.xcrossing.y);
    1.70 +            if (xevent.xcrossing.mode == NotifyGrab)
    1.71 +                printf("Mode: NotifyGrab\n");
    1.72 +            if (xevent.xcrossing.mode == NotifyUngrab)
    1.73 +                printf("Mode: NotifyUngrab\n");
    1.74 +#endif
    1.75 +            if ((xevent.xcrossing.mode != NotifyGrab) &&
    1.76 +                (xevent.xcrossing.mode != NotifyUngrab)) {
    1.77 +                SDL_SetMouseFocus(videodata->mouse, data->windowID);
    1.78 +                SDL_SendMouseMotion(videodata->mouse, 0, xevent.xcrossing.x,
    1.79 +                                    xevent.xcrossing.y);
    1.80 +            }
    1.81 +        }
    1.82 +        break;
    1.83 +
    1.84 +        /* Losing mouse coverage? */
    1.85 +    case LeaveNotify:{
    1.86 +#ifdef DEBUG_XEVENTS
    1.87 +            printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x,
    1.88 +                   xevent.xcrossing.y);
    1.89 +            if (xevent.xcrossing.mode == NotifyGrab)
    1.90 +                printf("Mode: NotifyGrab\n");
    1.91 +            if (xevent.xcrossing.mode == NotifyUngrab)
    1.92 +                printf("Mode: NotifyUngrab\n");
    1.93 +#endif
    1.94 +            if ((xevent.xcrossing.mode != NotifyGrab) &&
    1.95 +                (xevent.xcrossing.mode != NotifyUngrab) &&
    1.96 +                (xevent.xcrossing.detail != NotifyInferior)) {
    1.97 +                SDL_SendMouseMotion(videodata->mouse, 0,
    1.98 +                                    xevent.xcrossing.x, xevent.xcrossing.y);
    1.99 +                SDL_SetMouseFocus(videodata->mouse, 0);
   1.100 +            }
   1.101 +        }
   1.102 +        break;
   1.103 +
   1.104 +        /* Gaining input focus? */
   1.105 +    case FocusIn:{
   1.106 +#ifdef DEBUG_XEVENTS
   1.107 +            printf("FocusIn!\n");
   1.108 +#endif
   1.109 +            SDL_SetKeyboardFocus(videodata->keyboard, data->windowID);
   1.110 +#ifdef X_HAVE_UTF8_STRING
   1.111 +            if (data->ic) {
   1.112 +                XSetICFocus(data->ic);
   1.113 +            }
   1.114 +#endif
   1.115 +        }
   1.116 +        break;
   1.117 +
   1.118 +        /* Losing input focus? */
   1.119 +    case FocusOut:{
   1.120 +#ifdef DEBUG_XEVENTS
   1.121 +            printf("FocusOut!\n");
   1.122 +#endif
   1.123 +            SDL_SetKeyboardFocus(videodata->keyboard, 0);
   1.124 +#ifdef X_HAVE_UTF8_STRING
   1.125 +            if (data->ic) {
   1.126 +                XUnsetICFocus(data->ic);
   1.127 +            }
   1.128 +#endif
   1.129 +        }
   1.130 +        break;
   1.131 +
   1.132 +        /* Generated upon EnterWindow and FocusIn */
   1.133 +    case KeymapNotify:{
   1.134 +#ifdef DEBUG_XEVENTS
   1.135 +            printf("KeymapNotify!\n");
   1.136 +#endif
   1.137 +            /* FIXME:
   1.138 +               X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
   1.139 +             */
   1.140 +        }
   1.141 +        break;
   1.142 +
   1.143 +        /* Mouse motion? */
   1.144 +    case MotionNotify:{
   1.145 +#ifdef DEBUG_MOTION
   1.146 +            printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   1.147 +#endif
   1.148 +            SDL_SendMouseMotion(videodata->mouse, 0, xevent.xmotion.x,
   1.149 +                                xevent.xmotion.y);
   1.150 +        }
   1.151 +        break;
   1.152 +
   1.153 +        /* Mouse button press? */
   1.154 +    case ButtonPress:{
   1.155 +            SDL_SendMouseButton(videodata->mouse, SDL_PRESSED,
   1.156 +                                xevent.xbutton.button);
   1.157 +        }
   1.158 +        break;
   1.159 +
   1.160 +        /* Mouse button release? */
   1.161 +    case ButtonRelease:{
   1.162 +            SDL_SendMouseButton(videodata->mouse, SDL_RELEASED,
   1.163 +                                xevent.xbutton.button);
   1.164 +        }
   1.165 +        break;
   1.166 +
   1.167 +        /* Key press? */
   1.168 +    case KeyPress:{
   1.169 +#if 0                           /* FIXME */
   1.170 +            static SDL_keysym saved_keysym;
   1.171 +            SDL_keysym keysym;
   1.172 +            KeyCode keycode = xevent.xkey.keycode;
   1.173 +
   1.174 +#ifdef DEBUG_XEVENTS
   1.175 +            printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   1.176 +#endif
   1.177 +            /* Get the translated SDL virtual keysym */
   1.178 +            if (keycode) {
   1.179 +                keysym.scancode = keycode;
   1.180 +                keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   1.181 +                keysym.mod = KMOD_NONE;
   1.182 +                keysym.unicode = 0;
   1.183 +            } else {
   1.184 +                keysym = saved_keysym;
   1.185 +            }
   1.186 +
   1.187 +            /* If we're not doing translation, we're done! */
   1.188 +            if (!SDL_TranslateUNICODE) {
   1.189 +                posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   1.190 +                break;
   1.191 +            }
   1.192 +
   1.193 +            if (XFilterEvent(&xevent, None)) {
   1.194 +                if (xevent.xkey.keycode) {
   1.195 +                    posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   1.196 +                } else {
   1.197 +                    /* Save event to be associated with IM text
   1.198 +                       In 1.3 we'll have a text event instead.. */
   1.199 +                    saved_keysym = keysym;
   1.200 +                }
   1.201 +                break;
   1.202 +            }
   1.203 +
   1.204 +            /* Look up the translated value for the key event */
   1.205 +#ifdef X_HAVE_UTF8_STRING
   1.206 +            if (data->ic != NULL) {
   1.207 +                static Status state;
   1.208 +                /* A UTF-8 character can be at most 6 bytes */
   1.209 +                char keybuf[6];
   1.210 +                if (Xutf8LookupString(data->ic, &xevent.xkey,
   1.211 +                                      keybuf, sizeof(keybuf), NULL, &state)) {
   1.212 +                    keysym.unicode = Utf8ToUcs4((Uint8 *) keybuf);
   1.213 +                }
   1.214 +            } else
   1.215 +#endif
   1.216 +            {
   1.217 +                static XComposeStatus state;
   1.218 +                char keybuf[32];
   1.219 +
   1.220 +                if (XLookupString(&xevent.xkey,
   1.221 +                                  keybuf, sizeof(keybuf), NULL, &state)) {
   1.222 +                    /*
   1.223 +                     * FIXME: XLookupString() may yield more than one
   1.224 +                     * character, so we need a mechanism to allow for
   1.225 +                     * this (perhaps null keypress events with a
   1.226 +                     * unicode value)
   1.227 +                     */
   1.228 +                    keysym.unicode = (Uint8) keybuf[0];
   1.229 +                }
   1.230 +            }
   1.231 +            posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   1.232 +#endif // 0
   1.233 +        }
   1.234 +        break;
   1.235 +
   1.236 +        /* Key release? */
   1.237 +    case KeyRelease:{
   1.238 +#if 0                           /* FIXME */
   1.239 +            SDL_keysym keysym;
   1.240 +            KeyCode keycode = xevent.xkey.keycode;
   1.241 +
   1.242 +#ifdef DEBUG_XEVENTS
   1.243 +            printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   1.244 +#endif
   1.245 +            /* Check to see if this is a repeated key */
   1.246 +            if (X11_KeyRepeat(SDL_Display, &xevent)) {
   1.247 +                break;
   1.248 +            }
   1.249 +
   1.250 +            /* Get the translated SDL virtual keysym */
   1.251 +            keysym.scancode = keycode;
   1.252 +            keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   1.253 +            keysym.mod = KMOD_NONE;
   1.254 +            keysym.unicode = 0;
   1.255 +
   1.256 +            posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
   1.257 +#endif // 0
   1.258 +        }
   1.259 +        break;
   1.260 +
   1.261 +        /* Have we been iconified? */
   1.262 +    case UnmapNotify:{
   1.263 +#ifdef DEBUG_XEVENTS
   1.264 +            printf("UnmapNotify!\n");
   1.265 +#endif
   1.266 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   1.267 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0,
   1.268 +                                0);
   1.269 +        }
   1.270 +        break;
   1.271 +
   1.272 +        /* Have we been restored? */
   1.273 +    case MapNotify:{
   1.274 +#ifdef DEBUG_XEVENTS
   1.275 +            printf("MapNotify!\n");
   1.276 +#endif
   1.277 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0);
   1.278 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0,
   1.279 +                                0);
   1.280 +        }
   1.281 +        break;
   1.282 +
   1.283 +        /* Have we been resized or moved? */
   1.284 +    case ConfigureNotify:{
   1.285 +#ifdef DEBUG_XEVENTS
   1.286 +            printf("ConfigureNotify! (resize: %dx%d)\n",
   1.287 +                   xevent.xconfigure.width, xevent.xconfigure.height);
   1.288 +#endif
   1.289 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED,
   1.290 +                                xevent.xconfigure.x, xevent.xconfigure.y);
   1.291 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED,
   1.292 +                                xevent.xconfigure.width,
   1.293 +                                xevent.xconfigure.height);
   1.294 +        }
   1.295 +        break;
   1.296 +
   1.297 +        /* Have we been requested to quit (or another client message?) */
   1.298 +    case ClientMessage:{
   1.299 +            if ((xevent.xclient.format == 32) &&
   1.300 +                (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
   1.301 +
   1.302 +                SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0,
   1.303 +                                    0);
   1.304 +            }
   1.305 +        }
   1.306 +        break;
   1.307 +
   1.308 +        /* Do we need to refresh ourselves? */
   1.309 +    case Expose:{
   1.310 +#ifdef DEBUG_XEVENTS
   1.311 +            printf("Expose (count = %d)\n", xevent.xexpose.count);
   1.312 +#endif
   1.313 +            SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0,
   1.314 +                                0);
   1.315 +        }
   1.316 +        break;
   1.317 +
   1.318 +    default:{
   1.319 +#ifdef DEBUG_XEVENTS
   1.320 +            printf("Unhandled event %d\n", xevent.type);
   1.321 +#endif
   1.322 +        }
   1.323 +        break;
   1.324 +    }
   1.325 +}
   1.326 +
   1.327 +/* Ack!  XPending() actually performs a blocking read if no events available */
   1.328 +int
   1.329 +X11_Pending(Display * display)
   1.330 +{
   1.331 +    /* Flush the display connection and look to see if events are queued */
   1.332 +    XFlush(display);
   1.333 +    if (XEventsQueued(display, QueuedAlready)) {
   1.334 +        return (1);
   1.335 +    }
   1.336 +
   1.337 +    /* More drastic measures are required -- see if X is ready to talk */
   1.338 +    {
   1.339 +        static struct timeval zero_time;        /* static == 0 */
   1.340 +        int x11_fd;
   1.341 +        fd_set fdset;
   1.342 +
   1.343 +        x11_fd = ConnectionNumber(display);
   1.344 +        FD_ZERO(&fdset);
   1.345 +        FD_SET(x11_fd, &fdset);
   1.346 +        if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
   1.347 +            return (XPending(display));
   1.348 +        }
   1.349 +    }
   1.350 +
   1.351 +    /* Oh well, nothing is ready .. */
   1.352 +    return (0);
   1.353 +}
   1.354 +
   1.355 +void
   1.356 +X11_PumpEvents(_THIS)
   1.357 +{
   1.358 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   1.359 +
   1.360 +    /* Keep processing pending events */
   1.361 +    while (X11_Pending(data->display)) {
   1.362 +        X11_DispatchEvent(_this);
   1.363 +    }
   1.364 +}
   1.365 +
   1.366 +void
   1.367 +X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms)
   1.368 +{
   1.369 +    int timeout, interval, prefer_blank, allow_exp;
   1.370 +    XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
   1.371 +    *saved_timeout = timeout;
   1.372 +
   1.373 +#if SDL_VIDEO_DRIVER_X11_DPMS
   1.374 +    if (SDL_X11_HAVE_DPMS) {
   1.375 +        int dummy;
   1.376 +        if (DPMSQueryExtension(display, &dummy, &dummy)) {
   1.377 +            CARD16 state;
   1.378 +            DPMSInfo(display, &state, dpms);
   1.379 +        }
   1.380 +    }
   1.381 +#else
   1.382 +    *dpms = 0;
   1.383 +#endif /* SDL_VIDEO_DRIVER_X11_DPMS */
   1.384 +}
   1.385 +
   1.386 +void
   1.387 +X11_DisableScreenSaver(Display * display)
   1.388 +{
   1.389 +    int timeout, interval, prefer_blank, allow_exp;
   1.390 +    XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
   1.391 +    timeout = 0;
   1.392 +    XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
   1.393 +
   1.394 +#if SDL_VIDEO_DRIVER_X11_DPMS
   1.395 +    if (SDL_X11_HAVE_DPMS) {
   1.396 +        int dummy;
   1.397 +        if (DPMSQueryExtension(display, &dummy, &dummy)) {
   1.398 +            DPMSDisable(display);
   1.399 +        }
   1.400 +    }
   1.401 +#endif /* SDL_VIDEO_DRIVER_X11_DPMS */
   1.402 +}
   1.403 +
   1.404 +void
   1.405 +X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms)
   1.406 +{
   1.407 +    int timeout, interval, prefer_blank, allow_exp;
   1.408 +    XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
   1.409 +    timeout = saved_timeout;
   1.410 +    XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
   1.411 +
   1.412 +#if SDL_VIDEO_DRIVER_X11_DPMS
   1.413 +    if (SDL_X11_HAVE_DPMS) {
   1.414 +        int dummy;
   1.415 +        if (DPMSQueryExtension(display, &dummy, &dummy)) {
   1.416 +            if (dpms) {
   1.417 +                DPMSEnable(display);
   1.418 +            }
   1.419 +        }
   1.420 +    }
   1.421 +#endif /* SDL_VIDEO_DRIVER_X11_DPMS */
   1.422 +}
   1.423 +
   1.424 +/* vi: set ts=4 sw=4 expandtab: */