Mercurial > sdl-ios-xcode
changeset 1951:7177581dc9fa
Initial work on X11 window code in.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 27 Jul 2006 06:53:23 +0000 |
parents | a344e42bce3b |
children | 420716272158 |
files | src/video/cocoa/SDL_cocoawindow.h src/video/cocoa/SDL_cocoawindow.m src/video/win32/SDL_win32events.c src/video/win32/SDL_win32window.c src/video/win32/SDL_win32window.h src/video/x11/SDL_x11events.c src/video/x11/SDL_x11events.h src/video/x11/SDL_x11modes.c src/video/x11/SDL_x11modes.h src/video/x11/SDL_x11video.c src/video/x11/SDL_x11video.h src/video/x11/SDL_x11window.c src/video/x11/SDL_x11window.h |
diffstat | 13 files changed, 1243 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- a/src/video/cocoa/SDL_cocoawindow.h Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/cocoa/SDL_cocoawindow.h Thu Jul 27 06:53:23 2006 +0000 @@ -66,7 +66,7 @@ { SDL_WindowID windowID; NSWindow *window; - BOOL created; + SDL_bool created; Cocoa_WindowListener *listener; struct SDL_VideoData *videodata; };
--- a/src/video/cocoa/SDL_cocoawindow.m Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/cocoa/SDL_cocoawindow.m Thu Jul 27 06:53:23 2006 +0000 @@ -242,9 +242,10 @@ @end static int -SetupWindowData(SDL_Window * window, NSWindow *nswindow, BOOL created) +SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created) { NSAutoreleasePool *pool; + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_WindowData *data; /* Allocate the window data */ @@ -256,7 +257,7 @@ data->windowID = window->id; data->window = nswindow; data->created = created; - data->videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata; + data->videodata = videodata; pool = [[NSAutoreleasePool alloc] init]; @@ -380,7 +381,7 @@ [pool release]; - if (SetupWindowData(window, nswindow, YES) < 0) { + if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) { [nswindow release]; return -1; } @@ -413,7 +414,7 @@ [pool release]; - return SetupWindowData(window, nswindow, NO); + return SetupWindowData(_this, window, nswindow, SDL_FALSE); } void
--- a/src/video/win32/SDL_win32events.c Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/win32/SDL_win32events.c Thu Jul 27 06:53:23 2006 +0000 @@ -22,7 +22,6 @@ #include "SDL_config.h" #include "SDL_win32video.h" -#include "SDL_version.h" #include "SDL_syswm.h" #include "SDL_vkeys.h" #include "../../events/SDL_events_c.h" @@ -393,6 +392,18 @@ { SDL_WindowData *data; + /* Send a SDL_SYSWMEVENT if the application wants them */ + if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.hwnd = hwnd; + wmmsg.msg = msg; + wmmsg.wParam = wParam; + wmmsg.lParam = lParam; + SDL_SendSysWMEvent(&wmmsg); + } + /* Get the window data for the window */ data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData")); if (!data) { @@ -412,18 +423,6 @@ } #endif - /* Send a SDL_SYSWMEVENT if the application wants them */ - if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { - SDL_SysWMmsg wmmsg; - - SDL_VERSION(&wmmsg.version); - wmmsg.hwnd = hwnd; - wmmsg.msg = msg; - wmmsg.wParam = wParam; - wmmsg.lParam = lParam; - SDL_SendSysWMEvent(&wmmsg); - } - switch (msg) { case WM_SHOWWINDOW:
--- a/src/video/win32/SDL_win32window.c Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/win32/SDL_win32window.c Thu Jul 27 06:53:23 2006 +0000 @@ -31,8 +31,9 @@ static int -SetupWindowData(SDL_Window * window, HWND hwnd, BOOL created) +SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) { + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_WindowData *data; /* Allocate the window data */ @@ -46,7 +47,7 @@ data->hdc = GetDC(hwnd); data->created = created; data->mouse_pressed = SDL_FALSE; - data->videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata; + data->videodata = videodata; /* Associate the data with the window */ if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) { @@ -208,7 +209,7 @@ return -1; } - if (SetupWindowData(window, hwnd, TRUE) < 0) { + if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) { DestroyWindow(hwnd); return -1; } @@ -245,7 +246,7 @@ SDL_stack_free(title); } - if (SetupWindowData(window, hwnd, FALSE) < 0) { + if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) { return -1; } return 0;
--- a/src/video/win32/SDL_win32window.h Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/win32/SDL_win32window.h Thu Jul 27 06:53:23 2006 +0000 @@ -30,7 +30,7 @@ HWND hwnd; HDC hdc; WNDPROC wndproc; - BOOL created; + SDL_bool created; int mouse_pressed; struct SDL_VideoData *videodata; } SDL_WindowData;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11events.c Thu Jul 27 06:53:23 2006 +0000 @@ -0,0 +1,421 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_syswm.h" +#include "SDL_x11video.h" +#include "../../events/SDL_events_c.h" + + +static void +X11_DispatchEvent(_THIS) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + SDL_WindowData *data; + XEvent xevent; + int i; + + SDL_zero(xevent); /* valgrind fix. --ryan. */ + XNextEvent(videodata->display, &xevent); + + /* Send a SDL_SYSWMEVENT if the application wants them */ + if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.subsystem = SDL_SYSWM_X11; + wmmsg.event.xevent = xevent; + SDL_SendSysWMEvent(&wmmsg); + } + + data = NULL; + for (i = 0; i < videodata->numwindows; ++i) { + if (videodata->windowlist[i]->window == xevent.xany.window) { + data = videodata->windowlist[i]; + } + } + if (!data) { + return; + } + + switch (xevent.type) { + + /* Gaining mouse coverage? */ + case EnterNotify:{ +#ifdef DEBUG_XEVENTS + printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, + xevent.xcrossing.y); + if (xevent.xcrossing.mode == NotifyGrab) + printf("Mode: NotifyGrab\n"); + if (xevent.xcrossing.mode == NotifyUngrab) + printf("Mode: NotifyUngrab\n"); +#endif + if ((xevent.xcrossing.mode != NotifyGrab) && + (xevent.xcrossing.mode != NotifyUngrab)) { + SDL_SetMouseFocus(videodata->mouse, data->windowID); + SDL_SendMouseMotion(videodata->mouse, 0, xevent.xcrossing.x, + xevent.xcrossing.y); + } + } + break; + + /* Losing mouse coverage? */ + case LeaveNotify:{ +#ifdef DEBUG_XEVENTS + printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, + xevent.xcrossing.y); + if (xevent.xcrossing.mode == NotifyGrab) + printf("Mode: NotifyGrab\n"); + if (xevent.xcrossing.mode == NotifyUngrab) + printf("Mode: NotifyUngrab\n"); +#endif + if ((xevent.xcrossing.mode != NotifyGrab) && + (xevent.xcrossing.mode != NotifyUngrab) && + (xevent.xcrossing.detail != NotifyInferior)) { + SDL_SendMouseMotion(videodata->mouse, 0, + xevent.xcrossing.x, xevent.xcrossing.y); + SDL_SetMouseFocus(videodata->mouse, 0); + } + } + break; + + /* Gaining input focus? */ + case FocusIn:{ +#ifdef DEBUG_XEVENTS + printf("FocusIn!\n"); +#endif + SDL_SetKeyboardFocus(videodata->keyboard, data->windowID); +#ifdef X_HAVE_UTF8_STRING + if (data->ic) { + XSetICFocus(data->ic); + } +#endif + } + break; + + /* Losing input focus? */ + case FocusOut:{ +#ifdef DEBUG_XEVENTS + printf("FocusOut!\n"); +#endif + SDL_SetKeyboardFocus(videodata->keyboard, 0); +#ifdef X_HAVE_UTF8_STRING + if (data->ic) { + XUnsetICFocus(data->ic); + } +#endif + } + break; + + /* Generated upon EnterWindow and FocusIn */ + case KeymapNotify:{ +#ifdef DEBUG_XEVENTS + printf("KeymapNotify!\n"); +#endif + /* FIXME: + X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); + */ + } + break; + + /* Mouse motion? */ + case MotionNotify:{ +#ifdef DEBUG_MOTION + printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); +#endif + SDL_SendMouseMotion(videodata->mouse, 0, xevent.xmotion.x, + xevent.xmotion.y); + } + break; + + /* Mouse button press? */ + case ButtonPress:{ + SDL_SendMouseButton(videodata->mouse, SDL_PRESSED, + xevent.xbutton.button); + } + break; + + /* Mouse button release? */ + case ButtonRelease:{ + SDL_SendMouseButton(videodata->mouse, SDL_RELEASED, + xevent.xbutton.button); + } + break; + + /* Key press? */ + case KeyPress:{ +#if 0 /* FIXME */ + static SDL_keysym saved_keysym; + SDL_keysym keysym; + KeyCode keycode = xevent.xkey.keycode; + +#ifdef DEBUG_XEVENTS + printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); +#endif + /* Get the translated SDL virtual keysym */ + if (keycode) { + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + } else { + keysym = saved_keysym; + } + + /* If we're not doing translation, we're done! */ + if (!SDL_TranslateUNICODE) { + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + if (XFilterEvent(&xevent, None)) { + if (xevent.xkey.keycode) { + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } else { + /* Save event to be associated with IM text + In 1.3 we'll have a text event instead.. */ + saved_keysym = keysym; + } + break; + } + + /* Look up the translated value for the key event */ +#ifdef X_HAVE_UTF8_STRING + if (data->ic != NULL) { + static Status state; + /* A UTF-8 character can be at most 6 bytes */ + char keybuf[6]; + if (Xutf8LookupString(data->ic, &xevent.xkey, + keybuf, sizeof(keybuf), NULL, &state)) { + keysym.unicode = Utf8ToUcs4((Uint8 *) keybuf); + } + } else +#endif + { + static XComposeStatus state; + char keybuf[32]; + + if (XLookupString(&xevent.xkey, + keybuf, sizeof(keybuf), NULL, &state)) { + /* + * FIXME: XLookupString() may yield more than one + * character, so we need a mechanism to allow for + * this (perhaps null keypress events with a + * unicode value) + */ + keysym.unicode = (Uint8) keybuf[0]; + } + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); +#endif // 0 + } + break; + + /* Key release? */ + case KeyRelease:{ +#if 0 /* FIXME */ + SDL_keysym keysym; + KeyCode keycode = xevent.xkey.keycode; + +#ifdef DEBUG_XEVENTS + printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); +#endif + /* Check to see if this is a repeated key */ + if (X11_KeyRepeat(SDL_Display, &xevent)) { + break; + } + + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); +#endif // 0 + } + break; + + /* Have we been iconified? */ + case UnmapNotify:{ +#ifdef DEBUG_XEVENTS + printf("UnmapNotify!\n"); +#endif + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0); + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, + 0); + } + break; + + /* Have we been restored? */ + case MapNotify:{ +#ifdef DEBUG_XEVENTS + printf("MapNotify!\n"); +#endif + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0, + 0); + } + break; + + /* Have we been resized or moved? */ + case ConfigureNotify:{ +#ifdef DEBUG_XEVENTS + printf("ConfigureNotify! (resize: %dx%d)\n", + xevent.xconfigure.width, xevent.xconfigure.height); +#endif + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, + xevent.xconfigure.x, xevent.xconfigure.y); + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, + xevent.xconfigure.width, + xevent.xconfigure.height); + } + break; + + /* Have we been requested to quit (or another client message?) */ + case ClientMessage:{ + if ((xevent.xclient.format == 32) && + (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { + + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, + 0); + } + } + break; + + /* Do we need to refresh ourselves? */ + case Expose:{ +#ifdef DEBUG_XEVENTS + printf("Expose (count = %d)\n", xevent.xexpose.count); +#endif + SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0, + 0); + } + break; + + default:{ +#ifdef DEBUG_XEVENTS + printf("Unhandled event %d\n", xevent.type); +#endif + } + break; + } +} + +/* Ack! XPending() actually performs a blocking read if no events available */ +int +X11_Pending(Display * display) +{ + /* Flush the display connection and look to see if events are queued */ + XFlush(display); + if (XEventsQueued(display, QueuedAlready)) { + return (1); + } + + /* More drastic measures are required -- see if X is ready to talk */ + { + static struct timeval zero_time; /* static == 0 */ + int x11_fd; + fd_set fdset; + + x11_fd = ConnectionNumber(display); + FD_ZERO(&fdset); + FD_SET(x11_fd, &fdset); + if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) { + return (XPending(display)); + } + } + + /* Oh well, nothing is ready .. */ + return (0); +} + +void +X11_PumpEvents(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + /* Keep processing pending events */ + while (X11_Pending(data->display)) { + X11_DispatchEvent(_this); + } +} + +void +X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms) +{ + int timeout, interval, prefer_blank, allow_exp; + XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); + *saved_timeout = timeout; + +#if SDL_VIDEO_DRIVER_X11_DPMS + if (SDL_X11_HAVE_DPMS) { + int dummy; + if (DPMSQueryExtension(display, &dummy, &dummy)) { + CARD16 state; + DPMSInfo(display, &state, dpms); + } + } +#else + *dpms = 0; +#endif /* SDL_VIDEO_DRIVER_X11_DPMS */ +} + +void +X11_DisableScreenSaver(Display * display) +{ + int timeout, interval, prefer_blank, allow_exp; + XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); + timeout = 0; + XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp); + +#if SDL_VIDEO_DRIVER_X11_DPMS + if (SDL_X11_HAVE_DPMS) { + int dummy; + if (DPMSQueryExtension(display, &dummy, &dummy)) { + DPMSDisable(display); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_DPMS */ +} + +void +X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms) +{ + int timeout, interval, prefer_blank, allow_exp; + XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); + timeout = saved_timeout; + XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp); + +#if SDL_VIDEO_DRIVER_X11_DPMS + if (SDL_X11_HAVE_DPMS) { + int dummy; + if (DPMSQueryExtension(display, &dummy, &dummy)) { + if (dpms) { + DPMSEnable(display); + } + } + } +#endif /* SDL_VIDEO_DRIVER_X11_DPMS */ +} + +/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11events.h Thu Jul 27 06:53:23 2006 +0000 @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11events_h +#define _SDL_x11events_h + +extern void X11_PumpEvents(_THIS); +extern void X11_SaveScreenSaver(Display * display, int *saved_timeout, + BOOL * dpms); +extern void X11_DisableScreenSaver(Display * display); +extern void X11_RestoreScreenSaver(Display * display, int saved_timeout, + BOOL dpms); + +#endif /* _SDL_x11events_h */ + +/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/x11/SDL_x11modes.c Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/x11/SDL_x11modes.c Thu Jul 27 06:53:23 2006 +0000 @@ -106,6 +106,7 @@ } displaydata->screen = screen; displaydata->visual = vinfo.visual; + displaydata->depth = vinfo.depth; SDL_zero(display); display.desktop_mode = mode;
--- a/src/video/x11/SDL_x11modes.h Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/x11/SDL_x11modes.h Thu Jul 27 06:53:23 2006 +0000 @@ -28,6 +28,7 @@ { int screen; Visual *visual; + int depth; } SDL_DisplayData; //typedef struct
--- a/src/video/x11/SDL_x11video.c Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/x11/SDL_x11video.c Thu Jul 27 06:53:23 2006 +0000 @@ -34,6 +34,49 @@ static int X11_VideoInit(_THIS); static void X11_VideoQuit(_THIS); +/* Find out what class name we should use */ +static char * +get_classname() +{ + char *spot; +#if defined(__LINUX__) || defined(__FREEBSD__) + char procfile[1024]; + char linkfile[1024]; + int linksize; +#endif + + /* First allow environment variable override */ + spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS"); + if (spot) { + return SDL_strdup(spot); + } + + /* Next look at the application's executable name */ +#if defined(__LINUX__) || defined(__FREEBSD__) +#if defined(__LINUX__) + SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid()); +#elif defined(__FREEBSD__) + SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", + getpid()); +#else +#error Where can we find the executable name? +#endif + linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1); + if (linksize > 0) { + linkfile[linksize] = '\0'; + spot = SDL_strrchr(linkfile, '/'); + if (spot) { + return SDL_strdup(spot + 1); + } else { + return SDL_strdup(linkfile); + } + } +#endif /* __LINUX__ || __FREEBSD__ */ + + /* Finally use the default we've used forever */ + return SDL_strdup("SDL_App"); +} + /* X11 driver bootstrap functions */ static int @@ -127,9 +170,8 @@ device->SetDisplayMode = X11_SetDisplayMode; // device->SetDisplayGammaRamp = X11_SetDisplayGammaRamp; // device->GetDisplayGammaRamp = X11_GetDisplayGammaRamp; -// device->PumpEvents = X11_PumpEvents; + device->PumpEvents = X11_PumpEvents; -/* device->CreateWindow = X11_CreateWindow; device->CreateWindowFrom = X11_CreateWindowFrom; device->SetWindowTitle = X11_SetWindowTitle; @@ -144,6 +186,7 @@ device->SetWindowGrab = X11_SetWindowGrab; device->DestroyWindow = X11_DestroyWindow; device->GetWindowWMInfo = X11_GetWindowWMInfo; +/* #ifdef SDL_VIDEO_OPENGL device->GL_LoadLibrary = X11_GL_LoadLibrary; device->GL_GetProcAddress = X11_GL_GetProcAddress; @@ -170,6 +213,28 @@ int X11_VideoInit(_THIS) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + /* Get the window class name, usually the name of the application */ + data->classname = get_classname(); + + /* Open a connection to the X input manager */ +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + data->im = + XOpenIM(data->display, NULL, data->classname, data->classname); + } +#endif + + /* Save DPMS and screensaver settings */ + X11_SaveScreenSaver(data->display, &data->screensaver_timeout, + &data->dpms_enabled); + X11_DisableScreenSaver(data->display); + + /* Look up some useful Atoms */ + data->WM_DELETE_WINDOW = + XInternAtom(data->display, "WM_DELETE_WINDOW", False); + X11_InitModes(_this); //#if SDL_VIDEO_RENDER_D3D @@ -188,6 +253,19 @@ void X11_VideoQuit(_THIS) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + if (data->classname) { + SDL_free(data->classname); + } +#ifdef X_HAVE_UTF8_STRING + if (data->im) { + XCloseIM(data->im); + } +#endif + X11_RestoreScreenSaver(data->display, data->screensaver_timeout, + data->dpms_enabled); + X11_QuitModes(_this); X11_QuitKeyboard(_this); X11_QuitMouse(_this);
--- a/src/video/x11/SDL_x11video.h Wed Jul 26 06:34:54 2006 +0000 +++ b/src/video/x11/SDL_x11video.h Thu Jul 27 06:53:23 2006 +0000 @@ -30,14 +30,6 @@ #include <X11/Xutil.h> #include <X11/Xatom.h> -//#include "SDL_x11events.h" -//#include "SDL_x11gamma.h" -#include "SDL_x11keyboard.h" -#include "SDL_x11modes.h" -#include "SDL_x11mouse.h" -//#include "SDL_x11opengl.h" -//#include "SDL_x11window.h" - #if SDL_VIDEO_DRIVER_X11_XINERAMA #include "../Xext/extensions/Xinerama.h" #endif @@ -56,13 +48,28 @@ #include "SDL_x11dyn.h" +#include "SDL_x11events.h" +//#include "SDL_x11gamma.h" +#include "SDL_x11keyboard.h" +#include "SDL_x11modes.h" +#include "SDL_x11mouse.h" +//#include "SDL_x11opengl.h" +#include "SDL_x11window.h" + /* Private display data */ typedef struct SDL_VideoData { Display *display; + char *classname; + XIM im; + int screensaver_timeout; + BOOL dpms_enabled; + int numwindows; + SDL_WindowData **windowlist; int mouse; int keyboard; + Atom WM_DELETE_WINDOW; } SDL_VideoData; #endif /* _SDL_x11video_h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11window.c Thu Jul 27 06:53:23 2006 +0000 @@ -0,0 +1,611 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_keyboard_c.h" + +#include "SDL_x11video.h" + + +static int +SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + SDL_WindowData *data; + int numwindows = videodata->numwindows; + SDL_WindowData **windowlist = videodata->windowlist; + + /* Allocate the window data */ + data = (SDL_WindowData *) SDL_malloc(sizeof(*data)); + if (!data) { + SDL_OutOfMemory(); + return -1; + } + data->windowID = window->id; + data->window = w; +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + data->ic = + pXCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNResourceName, videodata->classname, XNResourceClass, + videodata->classname, NULL); + } +#endif + data->created = created; + data->videodata = videodata; + + /* Associate the data with the window */ + windowlist = + (SDL_WindowData **) SDL_realloc(windowlist, + (numwindows + + 1) * sizeof(*windowlist)); + if (!windowlist) { + SDL_OutOfMemory(); + SDL_free(data); + return -1; + } + windowlist[numwindows++] = data; + videodata->numwindows = numwindows; + videodata->windowlist = windowlist; + + /* Fill in the SDL window with the window data */ + { + XWindowAttributes attrib; + + XGetWindowAttributes(data->videodata->display, w, &attrib); + window->x = attrib.x; + window->y = attrib.y; + window->w = attrib.width; + window->h = attrib.height; + if (attrib.map_state != IsUnmapped) { + window->flags |= SDL_WINDOW_SHOWN; + } else { + window->flags &= ~SDL_WINDOW_SHOWN; + } + } + /* FIXME: How can I tell? + { + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + if (style & WS_VISIBLE) { + if (style & (WS_BORDER | WS_THICKFRAME)) { + window->flags &= ~SDL_WINDOW_BORDERLESS; + } else { + window->flags |= SDL_WINDOW_BORDERLESS; + } + if (style & WS_THICKFRAME) { + window->flags |= SDL_WINDOW_RESIZABLE; + } else { + window->flags &= ~SDL_WINDOW_RESIZABLE; + } + if (style & WS_MAXIMIZE) { + window->flags |= SDL_WINDOW_MAXIMIZED; + } else { + window->flags &= ~SDL_WINDOW_MAXIMIZED; + } + if (style & WS_MINIMIZE) { + window->flags |= SDL_WINDOW_MINIMIZED; + } else { + window->flags &= ~SDL_WINDOW_MINIMIZED; + } + } + if (GetFocus() == hwnd) { + int index = data->videodata->keyboard; + window->flags |= SDL_WINDOW_INPUT_FOCUS; + SDL_SetKeyboardFocus(index, data->windowID); + + if (window->flags & SDL_WINDOW_INPUT_GRABBED) { + RECT rect; + GetClientRect(hwnd, &rect); + ClientToScreen(hwnd, (LPPOINT) & rect); + ClientToScreen(hwnd, (LPPOINT) & rect + 1); + ClipCursor(&rect); + } + } + */ + + /* All done! */ + window->driverdata = data; + return 0; +} + +int +X11_CreateWindow(_THIS, SDL_Window * window) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + SDL_DisplayData *displaydata = + (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; + Visual *visual; + int depth; + XSetWindowAttributes xattr; + int x, y; + Window w; + XSizeHints *sizehints; + XWMHints *wmhints; + XClassHint *classhints; + +#if SDL_VIDEO_DRIVER_X11_XINERAMA +/* FIXME + if ( use_xinerama ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +*/ +#endif + if (window->flags & SDL_WINDOW_OPENGL) { + /* FIXME: get the glx visual */ + } else { + visual = displaydata->visual; + depth = displaydata->depth; + } + + if (window->flags & SDL_WINDOW_FULLSCREEN) { + xattr.override_redirect = True; + } else { + xattr.override_redirect = False; + } + xattr.background_pixel = 0; + xattr.border_pixel = 0; + if (visual->class == PseudoColor || visual->class == DirectColor) { + xattr.colormap = + XCreateColormap(data->display, + RootWindow(data->display, displaydata->screen), + visual, AllocAll); + } else { + xattr.colormap = + XCreateColormap(data->display, + RootWindow(data->display, displaydata->screen), + visual, AllocNone); + } + + if ((window->flags & SDL_WINDOW_FULLSCREEN) || + window->x == SDL_WINDOWPOS_CENTERED) { + x = (DisplayWidth(data->display, displaydata->screen) - + window->w) / 2; + } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { + x = 0; + } else { + x = window->x; + } + if ((window->flags & SDL_WINDOW_FULLSCREEN) || + window->y == SDL_WINDOWPOS_CENTERED) { + y = (DisplayHeight(data->display, displaydata->screen) - + window->h) / 2; + } else if (window->y == SDL_WINDOWPOS_UNDEFINED) { + y = 0; + } else { + y = window->y; + } + + w = XCreateWindow(data->display, + RootWindow(data->display, displaydata->screen), x, y, + window->w, window->h, 0, depth, InputOutput, visual, + (CWOverrideRedirect | CWBackPixel | CWBorderPixel | + CWColormap), &xattr); + + sizehints = XAllocSizeHints(); + if (sizehints) { + if (window->flags & SDL_WINDOW_RESIZABLE) { + sizehints->min_width = 32; + sizehints->min_height = 32; + sizehints->max_height = 4096; + sizehints->max_width = 4096; + } else { + sizehints->min_width = sizehints->max_width = window->w; + sizehints->min_height = sizehints->max_height = window->h; + } + sizehints->flags = PMaxSize | PMinSize; + if (!(window->flags & SDL_WINDOW_FULLSCREEN) + && window->x != SDL_WINDOWPOS_UNDEFINED + && window->y != SDL_WINDOWPOS_UNDEFINED) { + sizehints->x = x; + sizehints->y = y; + sizehints->flags |= USPosition; + } + XSetWMNormalHints(data->display, w, sizehints); + XFree(sizehints); + } + + if (window->flags & SDL_WINDOW_BORDERLESS) { + SDL_bool set; + Atom WM_HINTS; + + /* We haven't modified the window manager hints yet */ + set = SDL_FALSE; + + /* First try to set MWM hints */ + WM_HINTS = XInternAtom(data->display, "_MOTIF_WM_HINTS", True); + if (WM_HINTS != None) { + /* Hints used by Motif compliant window managers */ + struct + { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; + } MWMHints = { + (1L << 1), 0, 0, 0, 0}; + + XChangeProperty(data->display, w, WM_HINTS, WM_HINTS, 32, + PropModeReplace, (unsigned char *) &MWMHints, + sizeof(MWMHints) / sizeof(long)); + set = SDL_TRUE; + } + /* Now try to set KWM hints */ + WM_HINTS = XInternAtom(data->display, "KWM_WIN_DECORATION", True); + if (WM_HINTS != None) { + long KWMHints = 0; + + XChangeProperty(data->display, w, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *) &KWMHints, + sizeof(KWMHints) / sizeof(long)); + set = SDL_TRUE; + } + /* Now try to set GNOME hints */ + WM_HINTS = XInternAtom(data->display, "_WIN_HINTS", True); + if (WM_HINTS != None) { + long GNOMEHints = 0; + + XChangeProperty(data->display, w, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *) &GNOMEHints, + sizeof(GNOMEHints) / sizeof(long)); + set = SDL_TRUE; + } + /* Finally set the transient hints if necessary */ + if (!set) { + XSetTransientForHint(data->display, w, + RootWindow(data->display, + displaydata->screen)); + } + } else { + SDL_bool set; + Atom WM_HINTS; + + /* We haven't modified the window manager hints yet */ + set = SDL_FALSE; + + /* First try to unset MWM hints */ + WM_HINTS = XInternAtom(data->display, "_MOTIF_WM_HINTS", True); + if (WM_HINTS != None) { + XDeleteProperty(data->display, w, WM_HINTS); + set = SDL_TRUE; + } + /* Now try to unset KWM hints */ + WM_HINTS = XInternAtom(data->display, "KWM_WIN_DECORATION", True); + if (WM_HINTS != None) { + XDeleteProperty(data->display, w, WM_HINTS); + set = SDL_TRUE; + } + /* Now try to unset GNOME hints */ + WM_HINTS = XInternAtom(data->display, "_WIN_HINTS", True); + if (WM_HINTS != None) { + XDeleteProperty(data->display, w, WM_HINTS); + set = SDL_TRUE; + } + /* Finally unset the transient hints if necessary */ + if (!set) { + /* NOTE: Does this work? */ + XSetTransientForHint(data->display, w, None); + } + } + + /* Tell KDE to keep fullscreen windows on top */ + if (window->flags & SDL_WINDOW_FULLSCREEN) { + XEvent ev; + long mask; + + SDL_zero(ev); + ev.xclient.type = ClientMessage; + ev.xclient.window = RootWindow(data->display, displaydata->screen); + ev.xclient.message_type = + XInternAtom(data->display, "KWM_KEEP_ON_TOP", False); + ev.xclient.format = 32; + ev.xclient.data.l[0] = w; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(data->display, + RootWindow(data->display, displaydata->screen), False, + SubstructureRedirectMask, &ev); + } + + /* Set the input hints so we get keyboard input */ + wmhints = XAllocWMHints(); + if (wmhints) { + wmhints->input = True; + if (window->flags & SDL_WINDOW_MINIMIZED) { + wmhints->initial_state = IconicState; + } else if (window->flags & SDL_WINDOW_SHOWN) { + wmhints->initial_state = NormalState; + } else { + wmhints->initial_state = WithdrawnState; + } + wmhints->flags = InputHint | StateHint; + XSetWMHints(data->display, w, wmhints); + XFree(wmhints); + } + + XSelectInput(data->display, w, + (FocusChangeMask | EnterWindowMask | LeaveWindowMask | + ExposureMask | ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | KeyPressMask | KeyReleaseMask | + PropertyChangeMask | StructureNotifyMask | + KeymapStateMask)); + + /* Set the class hints so we can get an icon (AfterStep) */ + classhints = XAllocClassHint(); + if (classhints != NULL) { + classhints->res_name = data->classname; + classhints->res_class = data->classname; + XSetClassHint(data->display, w, classhints); + XFree(classhints); + } + + /* Allow the window to be deleted by the window manager */ + XSetWMProtocols(data->display, w, &data->WM_DELETE_WINDOW, 1); + + /* Finally, show the window */ + if (window->flags & SDL_WINDOW_SHOWN) { + XMapRaised(data->display, w); + } + XSync(data->display, False); + + if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) { + XDestroyWindow(data->display, w); + return -1; + } + + X11_SetWindowTitle(_this, window); + +#ifdef SDL_VIDEO_OPENGL + /* + if (window->flags & SDL_WINDOW_OPENGL) { + if (X11_GL_SetupWindow(_this, window) < 0) { + X11_DestroyWindow(_this, window); + return -1; + } + } + */ +#endif + return 0; +} + +int +X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) +{ + Window w = (Window) data; + + /* FIXME: Query the title from the existing window */ + + if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) { + return -1; + } + return 0; +} + +void +X11_SetWindowTitle(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + XTextProperty titleprop, iconprop; + Status status; + const char *title = window->title; + const char *icon = NULL; + +#ifdef X_HAVE_UTF8_STRING + Atom _NET_WM_NAME = 0; + Atom _NET_WM_ICON_NAME = 0; + + /* Look up some useful Atoms */ + if (SDL_X11_HAVE_UTF8) { + _NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", False); + _NET_WM_ICON_NAME = XInternAtom(display, "_NET_WM_ICON_NAME", False); + } +#endif + + if (title != NULL) { + char *title_latin1 = SDL_iconv_utf8_latin1((char *) title); + if (!title_latin1) { + SDL_OutOfMemory(); + return; + } + status = XStringListToTextProperty(&title_latin1, 1, &titleprop); + SDL_free(title_latin1); + if (status) { + XSetTextProperty(display, data->window, &titleprop, XA_WM_NAME); + XFree(titleprop.value); + } +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + status = + Xutf8TextListToTextProperty(display, (char **) &title, 1, + XUTF8StringStyle, &titleprop); + if (status == Success) { + XSetTextProperty(display, data->window, &titleprop, + _NET_WM_NAME); + XFree(titleprop.value); + } + } +#endif + } + if (icon != NULL) { + char *icon_latin1 = SDL_iconv_utf8_latin1((char *) icon); + if (!icon_latin1) { + SDL_OutOfMemory(); + return; + } + status = XStringListToTextProperty(&icon_latin1, 1, &iconprop); + SDL_free(icon_latin1); + if (status) { + XSetTextProperty(display, data->window, &iconprop, + XA_WM_ICON_NAME); + XFree(iconprop.value); + } +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + status = + Xutf8TextListToTextProperty(display, (char **) &icon, 1, + XUTF8StringStyle, &iconprop); + if (status == Success) { + XSetTextProperty(display, data->window, &iconprop, + _NET_WM_ICON_NAME); + XFree(iconprop.value); + } + } +#endif + } +} + +void +X11_SetWindowPosition(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_DisplayData *displaydata = + (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; + Display *display = data->videodata->display; + int x, y; + + if ((window->flags & SDL_WINDOW_FULLSCREEN) || + window->x == SDL_WINDOWPOS_CENTERED) { + x = (DisplayWidth(display, displaydata->screen) - window->w) / 2; + } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { + x = 0; + } else { + x = window->x; + } + if ((window->flags & SDL_WINDOW_FULLSCREEN) || + window->y == SDL_WINDOWPOS_CENTERED) { + y = (DisplayHeight(display, displaydata->screen) - window->h) / 2; + } else if (window->y == SDL_WINDOWPOS_UNDEFINED) { + y = 0; + } else { + y = window->y; + } + XMoveWindow(display, data->window, x, y); +} + +void +X11_SetWindowSize(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + XMoveWindow(display, data->window, window->w, window->h); +} + +void +X11_ShowWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + XMapRaised(display, data->window); +} + +void +X11_HideWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + XUnmapWindow(display, data->window); +} + +void +X11_RaiseWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + XRaiseWindow(display, data->window); +} + +void +X11_MaximizeWindow(_THIS, SDL_Window * window) +{ + /* FIXME: is this even possible? */ +} + +void +X11_MinimizeWindow(_THIS, SDL_Window * window) +{ + X11_HideWindow(_this, window); +} + +void +X11_RestoreWindow(_THIS, SDL_Window * window) +{ + X11_ShowWindow(_this, window); +} + +void +X11_SetWindowGrab(_THIS, SDL_Window * window) +{ + /* FIXME */ +} + +void +X11_DestroyWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + + if (data) { + Display *display = data->videodata->display; +#ifdef SDL_VIDEO_OPENGL + /* + if (window->flags & SDL_WINDOW_OPENGL) { + X11_GL_CleanupWindow(_this, window); + } + */ +#endif +#ifdef X_HAVE_UTF8_STRING + if (data->ic) { + XDestroyIC(data->ic); + } +#endif + if (data->created) { + XDestroyWindow(display, data->window); + } + SDL_free(data); + } +} + +SDL_bool +X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) { + /* FIXME! */ + return SDL_TRUE; + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return SDL_FALSE; + } +} + +/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11window.h Thu Jul 27 06:53:23 2006 +0000 @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11window_h +#define _SDL_x11window_h + +typedef struct +{ + SDL_WindowID windowID; + Window window; + XIC ic; + SDL_bool created; + struct SDL_VideoData *videodata; +} SDL_WindowData; + +extern int X11_CreateWindow(_THIS, SDL_Window * window); +extern int X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data); +extern void X11_SetWindowTitle(_THIS, SDL_Window * window); +extern void X11_SetWindowPosition(_THIS, SDL_Window * window); +extern void X11_SetWindowSize(_THIS, SDL_Window * window); +extern void X11_ShowWindow(_THIS, SDL_Window * window); +extern void X11_HideWindow(_THIS, SDL_Window * window); +extern void X11_RaiseWindow(_THIS, SDL_Window * window); +extern void X11_MaximizeWindow(_THIS, SDL_Window * window); +extern void X11_MinimizeWindow(_THIS, SDL_Window * window); +extern void X11_RestoreWindow(_THIS, SDL_Window * window); +extern void X11_SetWindowGrab(_THIS, SDL_Window * window); +extern void X11_DestroyWindow(_THIS, SDL_Window * window); +extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window, + struct SDL_SysWMinfo *info); + +#endif /* _SDL_x11window_h */ + +/* vi: set ts=4 sw=4 expandtab: */