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: */