slouken@1951: /* slouken@1951: SDL - Simple DirectMedia Layer slouken@1951: Copyright (C) 1997-2006 Sam Lantinga slouken@1951: slouken@1951: This library is free software; you can redistribute it and/or slouken@1951: modify it under the terms of the GNU Lesser General Public slouken@1951: License as published by the Free Software Foundation; either slouken@1951: version 2.1 of the License, or (at your option) any later version. slouken@1951: slouken@1951: This library is distributed in the hope that it will be useful, slouken@1951: but WITHOUT ANY WARRANTY; without even the implied warranty of slouken@1951: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU slouken@1951: Lesser General Public License for more details. slouken@1951: slouken@1951: You should have received a copy of the GNU Lesser General Public slouken@1951: License along with this library; if not, write to the Free Software slouken@1951: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA slouken@1951: slouken@1951: Sam Lantinga slouken@1951: slouken@libsdl.org slouken@1951: */ slouken@1951: #include "SDL_config.h" slouken@1951: slouken@2046: #include slouken@2046: #include slouken@2046: #include slouken@2046: slouken@1951: #include "SDL_syswm.h" slouken@1951: #include "SDL_x11video.h" slouken@1951: #include "../../events/SDL_events_c.h" slouken@1951: kazeuser@3760: //XEventClass *SDL_XEvents; kazeuser@3760: //int SDL_numOfEvents; kazeuser@3760: kazeuser@3761: extern int motion; kazeuser@3761: extern int button_pressed; kazeuser@3761: extern int button_released; kazeuser@3763: extern int proximity_in; kazeuser@3763: extern int proximity_out; kazeuser@3764: extern int x_max,y_max; kazeuser@3763: kazeuser@3761: slouken@1951: static void slouken@1951: X11_DispatchEvent(_THIS) slouken@1951: { slouken@1951: SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; slouken@1951: SDL_WindowData *data; slouken@1951: XEvent xevent; kazeuser@3760: int i,z; kazeuser@3761: //extern int motion; kazeuser@3761: //extern int button_pressed; kazeuser@3761: //extern int button_released; slouken@1951: slouken@1951: SDL_zero(xevent); /* valgrind fix. --ryan. */ slouken@1951: XNextEvent(videodata->display, &xevent); slouken@1951: bob@2325: /* filter events catchs XIM events and sends them to the correct bob@2325: handler */ bob@2325: if (XFilterEvent(&xevent, None) == True) { bob@2327: #if 0 bob@2328: printf("Filtered event type = %d display = %d window = %d\n", bob@2328: xevent.type, xevent.xany.display, xevent.xany.window); bob@2325: #endif bob@2325: return; bob@2325: } bob@2325: slouken@1951: /* Send a SDL_SYSWMEVENT if the application wants them */ slouken@1951: if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { slouken@1951: SDL_SysWMmsg wmmsg; slouken@1951: slouken@1951: SDL_VERSION(&wmmsg.version); slouken@1951: wmmsg.subsystem = SDL_SYSWM_X11; slouken@1951: wmmsg.event.xevent = xevent; slouken@1951: SDL_SendSysWMEvent(&wmmsg); slouken@1951: } slouken@1951: slouken@1951: data = NULL; bob@2324: if (videodata && videodata->windowlist) { bob@2324: for (i = 0; i < videodata->numwindows; ++i) { bob@2324: if ((videodata->windowlist[i] != NULL) && bob@2324: (videodata->windowlist[i]->window == xevent.xany.window)) { bob@2324: data = videodata->windowlist[i]; bob@2324: break; bob@2324: } slouken@1951: } slouken@1951: } slouken@1951: if (!data) { slouken@1951: return; slouken@1951: } bob@2327: #if 0 bob@2328: printf("type = %d display = %d window = %d\n", bob@2328: xevent.type, xevent.xany.display, xevent.xany.window); bob@2327: #endif slouken@1951: switch (xevent.type) { slouken@1951: slouken@1951: /* Gaining mouse coverage? */ slouken@1951: case EnterNotify:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, slouken@1951: xevent.xcrossing.y); slouken@1951: if (xevent.xcrossing.mode == NotifyGrab) slouken@1951: printf("Mode: NotifyGrab\n"); slouken@1951: if (xevent.xcrossing.mode == NotifyUngrab) slouken@1951: printf("Mode: NotifyUngrab\n"); slouken@1951: #endif slouken@1951: if ((xevent.xcrossing.mode != NotifyGrab) && slouken@1951: (xevent.xcrossing.mode != NotifyUngrab)) { kazeuser@3760: XDeviceMotionEvent* move=(XDeviceMotionEvent*)&xevent; kazeuser@3760: SDL_SetMouseFocus(move->deviceid, data->windowID); kazeuser@3760: SDL_SendMouseMotion(move->deviceid, 0, move->x, kazeuser@3760: move->y,move->axis_data[2]); slouken@1951: } slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Losing mouse coverage? */ slouken@1951: case LeaveNotify:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, slouken@1951: xevent.xcrossing.y); slouken@1951: if (xevent.xcrossing.mode == NotifyGrab) slouken@1951: printf("Mode: NotifyGrab\n"); slouken@1951: if (xevent.xcrossing.mode == NotifyUngrab) slouken@1951: printf("Mode: NotifyUngrab\n"); slouken@1951: #endif slouken@1951: if ((xevent.xcrossing.mode != NotifyGrab) && slouken@1951: (xevent.xcrossing.mode != NotifyUngrab) && slouken@1951: (xevent.xcrossing.detail != NotifyInferior)) { kazeuser@3760: XDeviceMotionEvent* move=(XDeviceMotionEvent*)&xevent; kazeuser@3764: //SDL_SendMouseMotion(move->deviceid, 0, kazeuser@3764: // move->x, move->y,move->axis_data[2]); kazeuser@3760: SDL_SetMouseFocus(move->deviceid, 0); slouken@1951: } slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Gaining input focus? */ slouken@1951: case FocusIn:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("FocusIn!\n"); slouken@1951: #endif slouken@1951: SDL_SetKeyboardFocus(videodata->keyboard, data->windowID); slouken@1951: #ifdef X_HAVE_UTF8_STRING slouken@1951: if (data->ic) { slouken@1951: XSetICFocus(data->ic); slouken@1951: } slouken@1951: #endif slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Losing input focus? */ slouken@1951: case FocusOut:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("FocusOut!\n"); slouken@1951: #endif slouken@1951: SDL_SetKeyboardFocus(videodata->keyboard, 0); slouken@1951: #ifdef X_HAVE_UTF8_STRING slouken@1951: if (data->ic) { slouken@1951: XUnsetICFocus(data->ic); slouken@1951: } slouken@1951: #endif slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Generated upon EnterWindow and FocusIn */ slouken@1951: case KeymapNotify:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("KeymapNotify!\n"); slouken@1951: #endif slouken@1951: /* FIXME: slouken@1951: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); slouken@1951: */ slouken@1951: } slouken@1951: break; slouken@1951: slouken@2305: /* Has the keyboard layout changed? */ slouken@2305: case MappingNotify:{ slouken@2305: #ifdef DEBUG_XEVENTS slouken@2305: printf("MappingNotify!\n"); slouken@2305: #endif slouken@2306: X11_UpdateKeymap(_this); slouken@2305: } slouken@2305: break; slouken@2305: slouken@1951: /* Key press? */ slouken@1951: case KeyPress:{ slouken@1951: KeyCode keycode = xevent.xkey.keycode; bob@2300: KeySym keysym = NoSymbol; slouken@2306: char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; bob@2325: Status status = 0; slouken@1951: slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); slouken@1951: #endif bob@2299: SDL_SendKeyboardKey(videodata->keyboard, SDL_PRESSED, slouken@2305: videodata->key_layout[keycode]); bob@2325: #if 0 slouken@2305: if (videodata->key_layout[keycode] == SDLK_UNKNOWN) { slouken@2305: int min_keycode, max_keycode; slouken@2305: XDisplayKeycodes(videodata->display, &min_keycode, slouken@2305: &max_keycode); slouken@2305: keysym = XKeycodeToKeysym(videodata->display, keycode, 0); bob@2299: fprintf(stderr, slouken@2305: "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list X11 KeyCode %d (%d), X11 KeySym 0x%X (%s).\n", slouken@2305: keycode, keycode - min_keycode, keysym, slouken@2305: XKeysymToString(keysym)); bob@2299: } bob@2295: #endif bob@2325: /* */ slouken@2305: SDL_zero(text); bob@2325: #ifdef X_HAVE_UTF8_STRING bob@2325: if (data->ic) { bob@2325: Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), bob@2325: &keysym, status); bob@2325: } bob@2325: #else slouken@2306: XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); bob@2325: #endif slouken@2305: if (*text) { slouken@2305: printf("Sending text event %s\n", text); bob@2300: SDL_SendKeyboardText(videodata->keyboard, text); bob@2300: } slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Key release? */ slouken@1951: case KeyRelease:{ slouken@1951: KeyCode keycode = xevent.xkey.keycode; slouken@1951: slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); slouken@1951: #endif bob@2295: SDL_SendKeyboardKey(videodata->keyboard, SDL_RELEASED, slouken@2305: videodata->key_layout[keycode]); slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Have we been iconified? */ slouken@1951: case UnmapNotify:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("UnmapNotify!\n"); slouken@1951: #endif slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0); slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, slouken@1951: 0); slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Have we been restored? */ slouken@1951: case MapNotify:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("MapNotify!\n"); slouken@1951: #endif slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0, slouken@1951: 0); slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Have we been resized or moved? */ slouken@1951: case ConfigureNotify:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("ConfigureNotify! (resize: %dx%d)\n", slouken@1951: xevent.xconfigure.width, xevent.xconfigure.height); slouken@1951: #endif slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, slouken@1951: xevent.xconfigure.x, xevent.xconfigure.y); slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, slouken@1951: xevent.xconfigure.width, slouken@1951: xevent.xconfigure.height); slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Have we been requested to quit (or another client message?) */ slouken@1951: case ClientMessage:{ slouken@1951: if ((xevent.xclient.format == 32) && slouken@1951: (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { slouken@1951: slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, slouken@1951: 0); slouken@1951: } slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: /* Do we need to refresh ourselves? */ slouken@1951: case Expose:{ slouken@1951: #ifdef DEBUG_XEVENTS slouken@1951: printf("Expose (count = %d)\n", xevent.xexpose.count); slouken@1951: #endif slouken@1951: SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0, slouken@1951: 0); slouken@1951: } slouken@1951: break; slouken@1951: slouken@1951: default:{ kazeuser@3761: if(xevent.type==motion)//MotionNotify kazeuser@3761: { kazeuser@3761: #ifdef DEBUG_MOTION kazeuser@3761: printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); kazeuser@3761: #endif kazeuser@3764: XWindowAttributes attrib; kazeuser@3764: XGetWindowAttributes(videodata->display, ((XAnyEvent*)&xevent)->window, &attrib); kazeuser@3764: /*x_max=attrib.width; kazeuser@3764: y_max=attrib.height;*/ kazeuser@3764: SDL_UpdateCoordinates(attrib.width, attrib.height); kazeuser@3761: XDeviceMotionEvent* move=(XDeviceMotionEvent*)&xevent; kazeuser@3761: SDL_SendMouseMotion(move->deviceid, 0, move->x, kazeuser@3761: move->y,move->axis_data[2]); kazeuser@3761: } kazeuser@3761: /* kazeuser@3761: kazeuser@3761: Mouse button press? */ kazeuser@3761: else if(xevent.type==button_pressed)//ButtonPress kazeuser@3761: { kazeuser@3761: XDeviceButtonPressedEvent* pressed=(XDeviceButtonPressedEvent*)&xevent; kazeuser@3761: SDL_SendMouseButton(pressed->deviceid, SDL_PRESSED, kazeuser@3761: pressed->button); kazeuser@3761: } kazeuser@3761: kazeuser@3761: /* Mouse button release? */ kazeuser@3761: else if(xevent.type==button_released)//ButtonRelease kazeuser@3761: { kazeuser@3761: XDeviceButtonReleasedEvent* released=(XDeviceButtonReleasedEvent*)&xevent; kazeuser@3761: SDL_SendMouseButton(released->deviceid, SDL_RELEASED, kazeuser@3761: released->button); kazeuser@3761: } kazeuser@3763: else if(xevent.type==proximity_in) kazeuser@3763: { kazeuser@3763: XProximityNotifyEvent* proximity = (XProximityNotifyEvent*)&xevent; kazeuser@3763: SDL_SendProximity(proximity->deviceid, proximity->x, proximity->y,SDL_PROXIMITYIN); kazeuser@3763: } kazeuser@3763: else if(xevent.type==proximity_out) kazeuser@3763: { kazeuser@3763: XProximityNotifyEvent* proximity = (XProximityNotifyEvent*)&xevent; kazeuser@3763: SDL_SendProximity(proximity->deviceid, proximity->x, proximity->y,SDL_PROXIMITYOUT); kazeuser@3763: } kazeuser@3761: else kazeuser@3761: { slouken@1951: #ifdef DEBUG_XEVENTS kazeuser@3761: printf("Unhandled event %d\n", xevent.type); slouken@1951: #endif kazeuser@3761: } slouken@1951: } slouken@1951: break; slouken@1951: } slouken@1951: } slouken@1951: kazeuser@3761: slouken@1951: /* Ack! XPending() actually performs a blocking read if no events available */ slouken@1951: int slouken@1951: X11_Pending(Display * display) slouken@1951: { slouken@1951: /* Flush the display connection and look to see if events are queued */ slouken@1951: XFlush(display); slouken@1951: if (XEventsQueued(display, QueuedAlready)) { slouken@1951: return (1); slouken@1951: } slouken@1951: slouken@1951: /* More drastic measures are required -- see if X is ready to talk */ slouken@1951: { slouken@1951: static struct timeval zero_time; /* static == 0 */ slouken@1951: int x11_fd; slouken@1951: fd_set fdset; slouken@1951: slouken@1951: x11_fd = ConnectionNumber(display); slouken@1951: FD_ZERO(&fdset); slouken@1951: FD_SET(x11_fd, &fdset); slouken@1951: if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) { slouken@1951: return (XPending(display)); slouken@1951: } slouken@1951: } slouken@1951: slouken@1951: /* Oh well, nothing is ready .. */ slouken@1951: return (0); slouken@1951: } slouken@1951: slouken@1951: void slouken@1951: X11_PumpEvents(_THIS) slouken@1951: { slouken@1951: SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; slouken@1951: slouken@1951: /* Keep processing pending events */ slouken@1951: while (X11_Pending(data->display)) { slouken@1951: X11_DispatchEvent(_this); slouken@1951: } slouken@1951: } slouken@1951: slouken@1951: void slouken@1951: X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms) slouken@1951: { slouken@1951: int timeout, interval, prefer_blank, allow_exp; slouken@1951: XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); slouken@1951: *saved_timeout = timeout; slouken@1951: slouken@1951: #if SDL_VIDEO_DRIVER_X11_DPMS slouken@1951: if (SDL_X11_HAVE_DPMS) { slouken@1951: int dummy; slouken@1951: if (DPMSQueryExtension(display, &dummy, &dummy)) { slouken@1951: CARD16 state; slouken@1951: DPMSInfo(display, &state, dpms); slouken@1951: } slouken@1951: } slouken@1951: #else slouken@1951: *dpms = 0; slouken@1951: #endif /* SDL_VIDEO_DRIVER_X11_DPMS */ slouken@1951: } slouken@1951: slouken@1951: void slouken@1951: X11_DisableScreenSaver(Display * display) slouken@1951: { slouken@1951: int timeout, interval, prefer_blank, allow_exp; slouken@1951: XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); slouken@1951: timeout = 0; slouken@1951: XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp); slouken@1951: slouken@1951: #if SDL_VIDEO_DRIVER_X11_DPMS slouken@1951: if (SDL_X11_HAVE_DPMS) { slouken@1951: int dummy; slouken@1951: if (DPMSQueryExtension(display, &dummy, &dummy)) { slouken@1951: DPMSDisable(display); slouken@1951: } slouken@1951: } slouken@1951: #endif /* SDL_VIDEO_DRIVER_X11_DPMS */ slouken@1951: } slouken@1951: slouken@1951: void slouken@1951: X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms) slouken@1951: { slouken@1951: int timeout, interval, prefer_blank, allow_exp; slouken@1951: XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); slouken@1951: timeout = saved_timeout; slouken@1951: XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp); slouken@1951: slouken@1951: #if SDL_VIDEO_DRIVER_X11_DPMS slouken@1951: if (SDL_X11_HAVE_DPMS) { slouken@1951: int dummy; slouken@1951: if (DPMSQueryExtension(display, &dummy, &dummy)) { slouken@1951: if (dpms) { slouken@1951: DPMSEnable(display); slouken@1951: } slouken@1951: } slouken@1951: } slouken@1951: #endif /* SDL_VIDEO_DRIVER_X11_DPMS */ slouken@1951: } slouken@1951: slouken@1951: /* vi: set ts=4 sw=4 expandtab: */