2006-07-27 06:53:23 +00:00
|
|
|
/*
|
2011-04-08 13:03:26 -07:00
|
|
|
Simple DirectMedia Layer
|
2013-02-15 08:47:44 -08:00
|
|
|
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
2011-04-08 13:03:26 -07:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
2006-07-27 06:53:23 +00:00
|
|
|
*/
|
|
|
|
#include "SDL_config.h"
|
|
|
|
|
2011-03-12 13:21:57 -08:00
|
|
|
#if SDL_VIDEO_DRIVER_X11
|
|
|
|
|
2013-07-14 18:17:28 -07:00
|
|
|
#include "SDL_assert.h"
|
2012-11-07 15:55:43 -08:00
|
|
|
#include "SDL_hints.h"
|
2006-07-27 06:53:23 +00:00
|
|
|
#include "../SDL_sysvideo.h"
|
2010-05-09 20:47:22 -07:00
|
|
|
#include "../SDL_pixels_c.h"
|
2006-07-27 06:53:23 +00:00
|
|
|
#include "../../events/SDL_keyboard_c.h"
|
2009-01-01 07:59:08 +00:00
|
|
|
#include "../../events/SDL_mouse_c.h"
|
2006-07-27 06:53:23 +00:00
|
|
|
|
|
|
|
#include "SDL_x11video.h"
|
2009-01-01 07:59:08 +00:00
|
|
|
#include "SDL_x11mouse.h"
|
2010-06-30 16:19:44 -04:00
|
|
|
#include "SDL_x11shape.h"
|
2012-05-31 13:37:02 +03:00
|
|
|
#include "SDL_x11xinput2.h"
|
2006-07-27 06:53:23 +00:00
|
|
|
|
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11
Scott Percival 2011-07-03 06:41:51 PDT
This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.
The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION
So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.
The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.
I think that's about everything, let me know if there's anything I've
overlooked.
2012-01-08 02:23:37 -05:00
|
|
|
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
2009-05-31 11:53:12 +00:00
|
|
|
#include "SDL_x11opengles.h"
|
|
|
|
#endif
|
|
|
|
|
2010-05-09 20:47:22 -07:00
|
|
|
#include "SDL_timer.h"
|
2009-09-05 07:33:54 +00:00
|
|
|
#include "SDL_syswm.h"
|
2012-09-27 03:36:13 -04:00
|
|
|
#include "SDL_assert.h"
|
2009-09-05 07:33:54 +00:00
|
|
|
|
2009-02-19 06:48:25 +00:00
|
|
|
#define _NET_WM_STATE_REMOVE 0l
|
|
|
|
#define _NET_WM_STATE_ADD 1l
|
|
|
|
#define _NET_WM_STATE_TOGGLE 2l
|
|
|
|
|
2012-09-27 03:36:13 -04:00
|
|
|
static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
|
2010-07-13 23:11:10 -07:00
|
|
|
{
|
2012-09-27 03:36:13 -04:00
|
|
|
return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
|
|
|
|
}
|
|
|
|
static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
|
|
|
|
{
|
|
|
|
return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
|
|
|
|
}
|
|
|
|
static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
|
|
|
|
{
|
2012-09-27 17:17:33 -07:00
|
|
|
return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
|
|
|
|
}
|
2010-07-13 23:11:10 -07:00
|
|
|
|
2012-09-27 03:36:13 -04:00
|
|
|
static SDL_bool
|
|
|
|
X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
return (data->fswindow != 0);
|
2010-07-13 23:11:10 -07:00
|
|
|
}
|
|
|
|
|
2010-07-14 00:56:08 -07:00
|
|
|
static SDL_bool
|
|
|
|
X11_IsWindowMapped(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
|
|
|
XWindowAttributes attr;
|
|
|
|
|
|
|
|
XGetWindowAttributes(videodata->display, data->xwindow, &attr);
|
|
|
|
if (attr.map_state != IsUnmapped) {
|
|
|
|
return SDL_TRUE;
|
|
|
|
} else {
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-03 12:19:55 -07:00
|
|
|
#if 0
|
2012-09-27 23:55:38 -07:00
|
|
|
static SDL_bool
|
|
|
|
X11_IsActionAllowed(SDL_Window *window, Atom action)
|
2010-07-14 00:56:08 -07:00
|
|
|
{
|
2012-09-27 23:55:38 -07:00
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
|
|
|
|
Atom type;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
int form;
|
|
|
|
unsigned long remain;
|
|
|
|
unsigned long len, i;
|
|
|
|
Atom *list;
|
|
|
|
SDL_bool ret = SDL_FALSE;
|
|
|
|
|
|
|
|
if (XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
|
|
|
|
{
|
|
|
|
for (i=0; i<len; ++i)
|
|
|
|
{
|
|
|
|
if (list[i] == action) {
|
|
|
|
ret = SDL_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
XFree(list);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2012-10-03 12:19:55 -07:00
|
|
|
#endif /* 0 */
|
2012-09-27 23:55:38 -07:00
|
|
|
|
2012-09-28 01:51:51 -07:00
|
|
|
void
|
|
|
|
X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
|
2012-09-27 23:55:38 -07:00
|
|
|
{
|
|
|
|
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
2012-09-28 01:51:51 -07:00
|
|
|
Display *display = videodata->display;
|
|
|
|
Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
|
2012-09-28 01:36:26 -07:00
|
|
|
/*Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;*/
|
2012-09-27 23:55:38 -07:00
|
|
|
Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
|
|
|
|
Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
|
|
|
|
Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
|
|
|
|
Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
|
2012-09-28 01:51:51 -07:00
|
|
|
Atom atoms[5];
|
2010-07-14 00:56:08 -07:00
|
|
|
int count = 0;
|
|
|
|
|
2012-09-28 01:36:26 -07:00
|
|
|
/* The window manager sets this property, we shouldn't set it.
|
|
|
|
If we did, this would indicate to the window manager that we don't
|
|
|
|
actually want to be mapped during XMapRaised(), which would be bad.
|
|
|
|
*
|
2012-09-27 23:55:38 -07:00
|
|
|
if (flags & SDL_WINDOW_HIDDEN) {
|
|
|
|
atoms[count++] = _NET_WM_STATE_HIDDEN;
|
2010-07-14 00:56:08 -07:00
|
|
|
}
|
2012-09-28 01:36:26 -07:00
|
|
|
*/
|
2012-09-27 23:55:38 -07:00
|
|
|
if (flags & SDL_WINDOW_INPUT_FOCUS) {
|
|
|
|
atoms[count++] = _NET_WM_STATE_FOCUSED;
|
|
|
|
}
|
|
|
|
if (flags & SDL_WINDOW_MAXIMIZED) {
|
|
|
|
atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
|
|
|
|
atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
|
|
|
|
}
|
|
|
|
if (flags & SDL_WINDOW_FULLSCREEN) {
|
|
|
|
atoms[count++] = _NET_WM_STATE_FULLSCREEN;
|
2010-07-14 00:56:08 -07:00
|
|
|
}
|
2012-09-28 01:51:51 -07:00
|
|
|
if (count > 0) {
|
|
|
|
XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
|
|
|
|
PropModeReplace, (unsigned char *)atoms, count);
|
|
|
|
} else {
|
|
|
|
XDeleteProperty(display, xwindow, _NET_WM_STATE);
|
|
|
|
}
|
2010-07-14 00:56:08 -07:00
|
|
|
}
|
|
|
|
|
2012-09-27 23:55:38 -07:00
|
|
|
Uint32
|
2012-09-28 01:51:51 -07:00
|
|
|
X11_GetNetWMState(_THIS, Window xwindow)
|
2012-09-27 23:55:38 -07:00
|
|
|
{
|
|
|
|
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
2012-09-28 01:51:51 -07:00
|
|
|
Display *display = videodata->display;
|
2012-09-27 23:55:38 -07:00
|
|
|
Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
|
|
|
|
Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
|
|
|
|
Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
|
|
|
|
Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
|
|
|
|
Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
|
|
|
|
Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
|
|
|
|
Atom actualType;
|
|
|
|
int actualFormat;
|
|
|
|
unsigned long i, numItems, bytesAfter;
|
|
|
|
unsigned char *propertyValue = NULL;
|
|
|
|
long maxLength = 1024;
|
|
|
|
Uint32 flags = 0;
|
|
|
|
|
2012-09-28 01:51:51 -07:00
|
|
|
if (XGetWindowProperty(display, xwindow, _NET_WM_STATE,
|
2012-09-27 23:55:38 -07:00
|
|
|
0l, maxLength, False, XA_ATOM, &actualType,
|
|
|
|
&actualFormat, &numItems, &bytesAfter,
|
|
|
|
&propertyValue) == Success) {
|
|
|
|
Atom *atoms = (Atom *) propertyValue;
|
|
|
|
int maximized = 0;
|
|
|
|
int fullscreen = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < numItems; ++i) {
|
|
|
|
if (atoms[i] == _NET_WM_STATE_HIDDEN) {
|
2012-09-28 01:36:26 -07:00
|
|
|
flags |= SDL_WINDOW_HIDDEN;
|
2012-09-27 23:55:38 -07:00
|
|
|
} else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
|
|
|
|
flags |= SDL_WINDOW_INPUT_FOCUS;
|
|
|
|
} else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
|
|
|
|
maximized |= 1;
|
|
|
|
} else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
|
|
|
|
maximized |= 2;
|
|
|
|
} else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
|
|
|
|
fullscreen = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (maximized == 3) {
|
|
|
|
flags |= SDL_WINDOW_MAXIMIZED;
|
|
|
|
} else if (fullscreen == 1) {
|
|
|
|
flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
}
|
|
|
|
XFree(propertyValue);
|
|
|
|
}
|
|
|
|
|
2012-09-28 01:11:30 -07:00
|
|
|
/* FIXME, check the size hints for resizable */
|
|
|
|
/*flags |= SDL_WINDOW_RESIZABLE;*/
|
2012-09-27 23:55:38 -07:00
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
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;
|
2008-03-07 17:20:37 +00:00
|
|
|
int windowlistlength = videodata->windowlistlength;
|
2006-07-27 06:53:23 +00:00
|
|
|
SDL_WindowData **windowlist = videodata->windowlist;
|
|
|
|
|
|
|
|
/* Allocate the window data */
|
2008-03-06 23:07:02 +00:00
|
|
|
data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
|
2006-07-27 06:53:23 +00:00
|
|
|
if (!data) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_OutOfMemory();
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
2010-01-21 06:21:52 +00:00
|
|
|
data->window = window;
|
|
|
|
data->xwindow = w;
|
2006-07-27 06:53:23 +00:00
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
2013-03-15 11:59:16 -07:00
|
|
|
if (SDL_X11_HAVE_UTF8 && videodata->im) {
|
2006-07-27 06:53:23 +00:00
|
|
|
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;
|
|
|
|
|
2008-03-06 23:07:02 +00:00
|
|
|
/* Associate the data with the window */
|
|
|
|
|
2008-03-07 17:20:37 +00:00
|
|
|
if (numwindows < windowlistlength) {
|
|
|
|
windowlist[numwindows] = data;
|
|
|
|
videodata->numwindows++;
|
2008-03-06 23:07:02 +00:00
|
|
|
} else {
|
2008-03-07 17:20:37 +00:00
|
|
|
windowlist =
|
|
|
|
(SDL_WindowData **) SDL_realloc(windowlist,
|
|
|
|
(numwindows +
|
|
|
|
1) * sizeof(*windowlist));
|
|
|
|
if (!windowlist) {
|
|
|
|
SDL_free(data);
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_OutOfMemory();
|
2008-03-07 17:20:37 +00:00
|
|
|
}
|
|
|
|
windowlist[numwindows] = data;
|
|
|
|
videodata->numwindows++;
|
|
|
|
videodata->windowlistlength++;
|
|
|
|
videodata->windowlist = windowlist;
|
2008-03-06 23:07:02 +00:00
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2011-02-04 18:05:20 -08:00
|
|
|
data->visual = attrib.visual;
|
2011-03-11 08:49:20 -08:00
|
|
|
data->colormap = attrib.colormap;
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
2009-02-19 06:48:25 +00:00
|
|
|
|
2012-09-28 01:51:51 -07:00
|
|
|
window->flags |= X11_GetNetWMState(_this, w);
|
2009-02-19 06:48:25 +00:00
|
|
|
|
2011-10-22 02:14:57 -04:00
|
|
|
{
|
|
|
|
Window FocalWindow;
|
|
|
|
int RevertTo=0;
|
|
|
|
XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
|
|
|
|
if (FocalWindow==w)
|
|
|
|
{
|
|
|
|
window->flags |= SDL_WINDOW_INPUT_FOCUS;
|
2012-09-27 23:55:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
|
2011-10-22 02:14:57 -04:00
|
|
|
SDL_SetKeyboardFocus(data->window);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
|
|
|
|
/* Tell x11 to clip mouse */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
/* All done! */
|
2012-09-28 01:51:51 -07:00
|
|
|
window->driverdata = data;
|
2006-07-27 06:53:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-13 01:43:53 -04:00
|
|
|
static void
|
|
|
|
SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* this code used to check for KWM_WIN_DECORATION, but KDE hasn't
|
|
|
|
* supported it for years and years. It now respects _MOTIF_WM_HINTS.
|
|
|
|
* Gnome is similar: just use the Motif atom.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Atom WM_HINTS = XInternAtom(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, border ? 1 : 0, 0, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
|
|
|
|
PropModeReplace, (unsigned char *) &MWMHints,
|
|
|
|
sizeof(MWMHints) / 4);
|
|
|
|
} else { /* set the transient hints instead, if necessary */
|
|
|
|
XSetTransientForHint(display, window, RootWindow(display, screen));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
int
|
|
|
|
X11_CreateWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
|
|
|
SDL_DisplayData *displaydata =
|
2011-02-10 14:44:25 -08:00
|
|
|
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
2010-07-14 00:28:15 -07:00
|
|
|
Display *display = data->display;
|
|
|
|
int screen = displaydata->screen;
|
2006-07-27 06:53:23 +00:00
|
|
|
Visual *visual;
|
|
|
|
int depth;
|
|
|
|
XSetWindowAttributes xattr;
|
|
|
|
Window w;
|
2012-09-26 14:08:46 -04:00
|
|
|
XSizeHints *sizehints;
|
|
|
|
XWMHints *wmhints;
|
|
|
|
XClassHint *classhints;
|
2013-07-21 00:57:31 -04:00
|
|
|
const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
|
|
|
|
Atom _NET_WM_BYPASS_COMPOSITOR;
|
2010-07-14 00:28:15 -07:00
|
|
|
Atom _NET_WM_WINDOW_TYPE;
|
|
|
|
Atom _NET_WM_WINDOW_TYPE_NORMAL;
|
2011-06-27 19:30:52 +02:00
|
|
|
Atom _NET_WM_PID;
|
2013-03-13 21:41:43 -07:00
|
|
|
Atom XdndAware, xdnd_version = 5;
|
2011-10-31 23:37:57 -04:00
|
|
|
Uint32 fevent = 0;
|
2010-07-13 23:11:10 -07:00
|
|
|
|
2012-07-18 15:02:48 -07:00
|
|
|
#if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
2006-07-27 06:53:23 +00:00
|
|
|
if (window->flags & SDL_WINDOW_OPENGL) {
|
2006-07-28 08:43:17 +00:00
|
|
|
XVisualInfo *vinfo;
|
|
|
|
|
2013-05-18 14:17:52 -07:00
|
|
|
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
Improved simultaneous support for OpenGL and OpenGL ES
From Scott Percival
Okay, I think I have something for this. Tested it on GL and GLES
machines, it seems to work okay.
- Add a new SDL GL attribute SDL_GL_CONTEXT_EGL:
- Only useful for the X11 video driver at the moment
- Set to 1 for an EGL context, 0 to use the default for the video driver
- Default is 0, unless library is built for EGL only
- Should be set after SDL init, but before window/context
creation (i.e. same place you'd specify attributes for major/minor GL
version)
- After a lot of agony pondering the least-terrible way to go about
it, made it so that X11_GL_LoadLibrary and X11_GLES_LoadLibrary check
SDL_GL_CONTEXT_EGL. If no GL context exists yet, and the attribute
choice doesn't match with the checking function, then it changes all
the function pointers in the video driver and passes control on to the
new LoadLibrary method.
- Likewise, make X11_CreateWindow check this attribute before firing
off a call to X11_GL_GetVisual/X11_GLES_GetVisual
- Added a sanity check to the start of X11_GL_LoadLibrary
- Tidied up SDL_x11opengles.h
- Moved ownership of the gles_data structure over to
X11_GLES_LoadLibrary/UnloadLibrary
- Should incorporate the 3 fixes posted by Andre Heider
This is obviously quite a bit to take in, but is (at least) a proof of
concept for the approach I think EGL/GLX mingling should take. Any
comments/criticism is much appreciated.
2012-07-18 15:17:27 -07:00
|
|
|
if (_this->gl_config.use_egl == 1) {
|
2012-07-18 15:02:48 -07:00
|
|
|
vinfo = X11_GLES_GetVisual(_this, display, screen);
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
Improved simultaneous support for OpenGL and OpenGL ES
From Scott Percival
Okay, I think I have something for this. Tested it on GL and GLES
machines, it seems to work okay.
- Add a new SDL GL attribute SDL_GL_CONTEXT_EGL:
- Only useful for the X11 video driver at the moment
- Set to 1 for an EGL context, 0 to use the default for the video driver
- Default is 0, unless library is built for EGL only
- Should be set after SDL init, but before window/context
creation (i.e. same place you'd specify attributes for major/minor GL
version)
- After a lot of agony pondering the least-terrible way to go about
it, made it so that X11_GL_LoadLibrary and X11_GLES_LoadLibrary check
SDL_GL_CONTEXT_EGL. If no GL context exists yet, and the attribute
choice doesn't match with the checking function, then it changes all
the function pointers in the video driver and passes control on to the
new LoadLibrary method.
- Likewise, make X11_CreateWindow check this attribute before firing
off a call to X11_GL_GetVisual/X11_GLES_GetVisual
- Added a sanity check to the start of X11_GL_LoadLibrary
- Tidied up SDL_x11opengles.h
- Moved ownership of the gles_data structure over to
X11_GLES_LoadLibrary/UnloadLibrary
- Should incorporate the 3 fixes posted by Andre Heider
This is obviously quite a bit to take in, but is (at least) a proof of
concept for the approach I think EGL/GLX mingling should take. Any
comments/criticism is much appreciated.
2012-07-18 15:17:27 -07:00
|
|
|
#if SDL_VIDEO_OPENGL_GLX
|
2012-07-18 15:02:48 -07:00
|
|
|
vinfo = X11_GL_GetVisual(_this, display, screen);
|
Improved simultaneous support for OpenGL and OpenGL ES
From Scott Percival
Okay, I think I have something for this. Tested it on GL and GLES
machines, it seems to work okay.
- Add a new SDL GL attribute SDL_GL_CONTEXT_EGL:
- Only useful for the X11 video driver at the moment
- Set to 1 for an EGL context, 0 to use the default for the video driver
- Default is 0, unless library is built for EGL only
- Should be set after SDL init, but before window/context
creation (i.e. same place you'd specify attributes for major/minor GL
version)
- After a lot of agony pondering the least-terrible way to go about
it, made it so that X11_GL_LoadLibrary and X11_GLES_LoadLibrary check
SDL_GL_CONTEXT_EGL. If no GL context exists yet, and the attribute
choice doesn't match with the checking function, then it changes all
the function pointers in the video driver and passes control on to the
new LoadLibrary method.
- Likewise, make X11_CreateWindow check this attribute before firing
off a call to X11_GL_GetVisual/X11_GLES_GetVisual
- Added a sanity check to the start of X11_GL_LoadLibrary
- Tidied up SDL_x11opengles.h
- Moved ownership of the gles_data structure over to
X11_GLES_LoadLibrary/UnloadLibrary
- Should incorporate the 3 fixes posted by Andre Heider
This is obviously quite a bit to take in, but is (at least) a proof of
concept for the approach I think EGL/GLX mingling should take. Any
comments/criticism is much appreciated.
2012-07-18 15:17:27 -07:00
|
|
|
#endif
|
2012-07-18 15:02:48 -07:00
|
|
|
}
|
2009-05-31 11:53:12 +00:00
|
|
|
if (!vinfo) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
visual = vinfo->visual;
|
|
|
|
depth = vinfo->depth;
|
|
|
|
XFree(vinfo);
|
|
|
|
} else
|
2006-07-28 08:43:17 +00:00
|
|
|
#endif
|
|
|
|
{
|
2006-07-27 06:53:23 +00:00
|
|
|
visual = displaydata->visual;
|
|
|
|
depth = displaydata->depth;
|
|
|
|
}
|
|
|
|
|
2011-02-21 22:52:31 -08:00
|
|
|
xattr.override_redirect = False;
|
2006-07-27 06:53:23 +00:00
|
|
|
xattr.background_pixel = 0;
|
|
|
|
xattr.border_pixel = 0;
|
2011-03-11 08:49:20 -08:00
|
|
|
|
|
|
|
if (visual->class == DirectColor) {
|
|
|
|
XColor *colorcells;
|
|
|
|
int i;
|
|
|
|
int ncolors;
|
|
|
|
int rmax, gmax, bmax;
|
|
|
|
int rmask, gmask, bmask;
|
|
|
|
int rshift, gshift, bshift;
|
|
|
|
|
|
|
|
xattr.colormap =
|
|
|
|
XCreateColormap(display, RootWindow(display, screen),
|
|
|
|
visual, AllocAll);
|
|
|
|
|
|
|
|
/* If we can't create a colormap, then we must die */
|
|
|
|
if (!xattr.colormap) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Could not create writable colormap");
|
2011-03-11 08:49:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* OK, we got a colormap, now fill it in as best as we can */
|
|
|
|
colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
|
|
|
|
if (!colorcells) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_OutOfMemory();
|
2011-03-11 08:49:20 -08:00
|
|
|
}
|
|
|
|
ncolors = visual->map_entries;
|
|
|
|
rmax = 0xffff;
|
|
|
|
gmax = 0xffff;
|
|
|
|
bmax = 0xffff;
|
|
|
|
|
|
|
|
rshift = 0;
|
|
|
|
rmask = visual->red_mask;
|
|
|
|
while (0 == (rmask & 1)) {
|
|
|
|
rshift++;
|
|
|
|
rmask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gshift = 0;
|
|
|
|
gmask = visual->green_mask;
|
|
|
|
while (0 == (gmask & 1)) {
|
|
|
|
gshift++;
|
|
|
|
gmask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bshift = 0;
|
|
|
|
bmask = visual->blue_mask;
|
|
|
|
while (0 == (bmask & 1)) {
|
|
|
|
bshift++;
|
|
|
|
bmask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build the color table pixel values */
|
|
|
|
for (i = 0; i < ncolors; i++) {
|
|
|
|
Uint32 red = (rmax * i) / (ncolors - 1);
|
|
|
|
Uint32 green = (gmax * i) / (ncolors - 1);
|
|
|
|
Uint32 blue = (bmax * i) / (ncolors - 1);
|
|
|
|
|
|
|
|
Uint32 rbits = (rmask * i) / (ncolors - 1);
|
|
|
|
Uint32 gbits = (gmask * i) / (ncolors - 1);
|
|
|
|
Uint32 bbits = (bmask * i) / (ncolors - 1);
|
|
|
|
|
|
|
|
Uint32 pix =
|
|
|
|
(rbits << rshift) | (gbits << gshift) | (bbits << bshift);
|
|
|
|
|
|
|
|
colorcells[i].pixel = pix;
|
|
|
|
|
|
|
|
colorcells[i].red = red;
|
|
|
|
colorcells[i].green = green;
|
|
|
|
colorcells[i].blue = blue;
|
|
|
|
|
|
|
|
colorcells[i].flags = DoRed | DoGreen | DoBlue;
|
|
|
|
}
|
|
|
|
|
|
|
|
XStoreColors(display, xattr.colormap, colorcells, ncolors);
|
|
|
|
|
|
|
|
SDL_free(colorcells);
|
|
|
|
} else {
|
|
|
|
xattr.colormap =
|
|
|
|
XCreateColormap(display, RootWindow(display, screen),
|
|
|
|
visual, AllocNone);
|
|
|
|
}
|
2006-07-27 06:53:23 +00:00
|
|
|
|
2011-02-21 22:52:31 -08:00
|
|
|
w = XCreateWindow(display, RootWindow(display, screen),
|
|
|
|
window->x, window->y, window->w, window->h,
|
|
|
|
0, depth, InputOutput, visual,
|
2006-07-27 06:53:23 +00:00
|
|
|
(CWOverrideRedirect | CWBackPixel | CWBorderPixel |
|
|
|
|
CWColormap), &xattr);
|
2006-07-28 08:43:17 +00:00
|
|
|
if (!w) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Couldn't create window");
|
2006-07-28 08:43:17 +00:00
|
|
|
}
|
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11
Scott Percival 2011-07-03 06:41:51 PDT
This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.
The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION
So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.
The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.
I think that's about everything, let me know if there's anything I've
overlooked.
2012-01-08 02:23:37 -05:00
|
|
|
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
2012-07-19 09:36:58 -07:00
|
|
|
if ((window->flags & SDL_WINDOW_OPENGL) && (_this->gl_config.use_egl == 1)) {
|
|
|
|
if (!_this->gles_data) {
|
|
|
|
XDestroyWindow(display, w);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11
Scott Percival 2011-07-03 06:41:51 PDT
This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.
The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION
So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.
The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.
I think that's about everything, let me know if there's anything I've
overlooked.
2012-01-08 02:23:37 -05:00
|
|
|
/* Create the GLES window surface */
|
|
|
|
_this->gles_data->egl_surface =
|
|
|
|
_this->gles_data->eglCreateWindowSurface(_this->gles_data->
|
2009-05-31 11:53:12 +00:00
|
|
|
egl_display,
|
|
|
|
_this->gles_data->egl_config,
|
|
|
|
(NativeWindowType) w, NULL);
|
|
|
|
|
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11
Scott Percival 2011-07-03 06:41:51 PDT
This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.
The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION
So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.
The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.
I think that's about everything, let me know if there's anything I've
overlooked.
2012-01-08 02:23:37 -05:00
|
|
|
if (_this->gles_data->egl_surface == EGL_NO_SURFACE) {
|
2012-07-19 09:36:58 -07:00
|
|
|
XDestroyWindow(display, w);
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Could not create GLES window surface");
|
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11
Scott Percival 2011-07-03 06:41:51 PDT
This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.
The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION
So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.
The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.
I think that's about everything, let me know if there's anything I've
overlooked.
2012-01-08 02:23:37 -05:00
|
|
|
}
|
2009-05-31 11:53:12 +00:00
|
|
|
}
|
|
|
|
#endif
|
2006-07-27 06:53:23 +00:00
|
|
|
|
2012-09-13 01:43:53 -04:00
|
|
|
SetWindowBordered(display, screen, w,
|
|
|
|
(window->flags & SDL_WINDOW_BORDERLESS) == 0);
|
2006-07-27 06:53:23 +00:00
|
|
|
|
2012-09-26 14:08:46 -04:00
|
|
|
sizehints = XAllocSizeHints();
|
2011-06-27 19:30:52 +02:00
|
|
|
/* Setup the normal size hints */
|
2012-09-26 14:08:46 -04:00
|
|
|
sizehints->flags = 0;
|
2011-06-27 19:30:52 +02:00
|
|
|
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
2012-09-26 14:08:46 -04:00
|
|
|
sizehints->min_width = sizehints->max_width = window->w;
|
|
|
|
sizehints->min_height = sizehints->max_height = window->h;
|
|
|
|
sizehints->flags |= (PMaxSize | PMinSize);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
2012-09-26 14:08:46 -04:00
|
|
|
sizehints->x = window->x;
|
|
|
|
sizehints->y = window->y;
|
|
|
|
sizehints->flags |= USPosition;
|
2011-06-27 19:30:52 +02:00
|
|
|
|
|
|
|
/* Setup the input hints so we get keyboard input */
|
2012-09-26 14:08:46 -04:00
|
|
|
wmhints = XAllocWMHints();
|
|
|
|
wmhints->input = True;
|
|
|
|
wmhints->flags = InputHint;
|
2011-06-27 19:30:52 +02:00
|
|
|
|
|
|
|
/* Setup the class hints so we can get an icon (AfterStep) */
|
2012-09-26 14:08:46 -04:00
|
|
|
classhints = XAllocClassHint();
|
|
|
|
classhints->res_name = data->classname;
|
|
|
|
classhints->res_class = data->classname;
|
2011-06-27 19:30:52 +02:00
|
|
|
|
|
|
|
/* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
|
2012-09-26 14:08:46 -04:00
|
|
|
XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
|
2011-06-27 19:30:52 +02:00
|
|
|
|
2012-09-26 14:08:46 -04:00
|
|
|
XFree(sizehints);
|
|
|
|
XFree(wmhints);
|
|
|
|
XFree(classhints);
|
2011-06-27 19:30:52 +02:00
|
|
|
/* Set the PID related to the window for the given hostname, if possible */
|
|
|
|
if (data->pid > 0) {
|
|
|
|
_NET_WM_PID = XInternAtom(display, "_NET_WM_PID", False);
|
|
|
|
XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
|
|
|
|
(unsigned char *)&data->pid, 1);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
2010-07-14 00:56:08 -07:00
|
|
|
/* Set the window manager state */
|
2012-09-28 01:51:51 -07:00
|
|
|
X11_SetNetWMState(_this, w, window->flags);
|
2010-07-13 23:11:10 -07:00
|
|
|
|
2010-07-14 00:28:15 -07:00
|
|
|
/* Let the window manager know we're a "normal" window */
|
|
|
|
_NET_WM_WINDOW_TYPE = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
|
|
|
|
_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
|
|
|
|
XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
|
|
|
|
PropModeReplace,
|
|
|
|
(unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
|
|
|
|
|
2013-07-21 00:57:31 -04:00
|
|
|
_NET_WM_BYPASS_COMPOSITOR = XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
|
|
|
|
XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
|
|
|
|
PropModeReplace,
|
|
|
|
(unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
|
2013-05-18 14:17:52 -07:00
|
|
|
|
2012-11-02 15:22:37 -04:00
|
|
|
{
|
|
|
|
Atom protocols[] = {
|
|
|
|
data->WM_DELETE_WINDOW, /* Allow window to be deleted by the WM */
|
|
|
|
data->_NET_WM_PING, /* Respond so WM knows we're alive */
|
|
|
|
};
|
|
|
|
XSetWMProtocols(display, w, protocols, sizeof (protocols) / sizeof (protocols[0]));
|
|
|
|
}
|
2006-07-27 06:53:23 +00:00
|
|
|
|
|
|
|
if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
|
2010-07-14 00:28:15 -07:00
|
|
|
XDestroyWindow(display, w);
|
2006-07-27 06:53:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2011-02-21 22:52:31 -08:00
|
|
|
|
2008-03-07 20:54:11 +00:00
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
2011-10-31 23:37:57 -04:00
|
|
|
if (SDL_X11_HAVE_UTF8) {
|
2008-03-07 20:54:11 +00:00
|
|
|
pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
|
|
|
|
XNFilterEvents, &fevent, NULL);
|
2008-08-25 18:02:14 +00:00
|
|
|
}
|
2008-03-07 20:54:11 +00:00
|
|
|
#endif
|
|
|
|
|
2012-05-31 13:37:02 +03:00
|
|
|
X11_Xinput2SelectTouch(_this, window);
|
|
|
|
|
2011-10-31 23:37:57 -04:00
|
|
|
XSelectInput(display, w,
|
|
|
|
(FocusChangeMask | EnterWindowMask | LeaveWindowMask |
|
|
|
|
ExposureMask | ButtonPressMask | ButtonReleaseMask |
|
|
|
|
PointerMotionMask | KeyPressMask | KeyReleaseMask |
|
|
|
|
PropertyChangeMask | StructureNotifyMask |
|
|
|
|
KeymapStateMask | fevent));
|
|
|
|
|
2013-03-13 21:41:43 -07:00
|
|
|
XdndAware = XInternAtom(display, "XdndAware", False);
|
|
|
|
XChangeProperty(display, w, XdndAware, XA_ATOM, 32,
|
|
|
|
PropModeReplace,
|
2013-05-18 14:17:52 -07:00
|
|
|
(unsigned char*)&xdnd_version, 1);
|
2013-03-13 21:41:43 -07:00
|
|
|
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2008-03-07 17:20:37 +00:00
|
|
|
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
2006-07-27 06:53:23 +00:00
|
|
|
{
|
|
|
|
Window w = (Window) data;
|
|
|
|
|
2010-07-13 23:11:10 -07:00
|
|
|
window->title = X11_GetWindowTitle(_this, w);
|
2006-07-27 06:53:23 +00:00
|
|
|
|
|
|
|
if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-13 23:11:10 -07:00
|
|
|
char *
|
|
|
|
X11_GetWindowTitle(_THIS, Window xwindow)
|
|
|
|
{
|
|
|
|
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
|
|
|
Display *display = data->display;
|
|
|
|
int status, real_format;
|
|
|
|
Atom real_type;
|
|
|
|
unsigned long items_read, items_left;
|
|
|
|
unsigned char *propdata;
|
|
|
|
char *title = NULL;
|
|
|
|
|
|
|
|
status = XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
|
|
|
|
0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
|
|
|
|
&items_read, &items_left, &propdata);
|
2011-10-22 02:13:35 -04:00
|
|
|
if (status == Success && propdata) {
|
2010-07-13 23:11:10 -07:00
|
|
|
title = SDL_strdup(SDL_static_cast(char*, propdata));
|
|
|
|
XFree(propdata);
|
|
|
|
} else {
|
|
|
|
status = XGetWindowProperty(display, xwindow, XA_WM_NAME,
|
|
|
|
0L, 8192L, False, XA_STRING, &real_type, &real_format,
|
|
|
|
&items_read, &items_left, &propdata);
|
2011-10-22 02:13:35 -04:00
|
|
|
if (status == Success && propdata) {
|
2010-07-13 23:11:10 -07:00
|
|
|
title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
|
|
|
|
} else {
|
|
|
|
title = SDL_strdup("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return title;
|
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
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
|
2010-07-13 23:11:10 -07:00
|
|
|
Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
|
|
|
|
Atom _NET_WM_ICON_NAME = data->videodata->_NET_WM_ICON_NAME;
|
2006-07-27 06:53:23 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (title != NULL) {
|
2007-07-04 08:01:04 +00:00
|
|
|
char *title_locale = SDL_iconv_utf8_locale(title);
|
|
|
|
if (!title_locale) {
|
2006-07-27 06:53:23 +00:00
|
|
|
SDL_OutOfMemory();
|
|
|
|
return;
|
|
|
|
}
|
2007-07-04 08:01:04 +00:00
|
|
|
status = XStringListToTextProperty(&title_locale, 1, &titleprop);
|
|
|
|
SDL_free(title_locale);
|
2006-07-27 06:53:23 +00:00
|
|
|
if (status) {
|
2010-01-21 06:21:52 +00:00
|
|
|
XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
|
2006-07-27 06:53:23 +00:00
|
|
|
XFree(titleprop.value);
|
|
|
|
}
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
if (SDL_X11_HAVE_UTF8) {
|
|
|
|
status =
|
|
|
|
Xutf8TextListToTextProperty(display, (char **) &title, 1,
|
|
|
|
XUTF8StringStyle, &titleprop);
|
|
|
|
if (status == Success) {
|
2010-01-21 06:21:52 +00:00
|
|
|
XSetTextProperty(display, data->xwindow, &titleprop,
|
2006-07-27 06:53:23 +00:00
|
|
|
_NET_WM_NAME);
|
|
|
|
XFree(titleprop.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
if (icon != NULL) {
|
2007-07-04 08:01:04 +00:00
|
|
|
char *icon_locale = SDL_iconv_utf8_locale(icon);
|
|
|
|
if (!icon_locale) {
|
2006-07-27 06:53:23 +00:00
|
|
|
SDL_OutOfMemory();
|
|
|
|
return;
|
|
|
|
}
|
2007-07-04 08:01:04 +00:00
|
|
|
status = XStringListToTextProperty(&icon_locale, 1, &iconprop);
|
|
|
|
SDL_free(icon_locale);
|
2006-07-27 06:53:23 +00:00
|
|
|
if (status) {
|
2010-01-21 06:21:52 +00:00
|
|
|
XSetTextProperty(display, data->xwindow, &iconprop,
|
2006-07-27 06:53:23 +00:00
|
|
|
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) {
|
2010-01-21 06:21:52 +00:00
|
|
|
XSetTextProperty(display, data->xwindow, &iconprop,
|
2006-07-27 06:53:23 +00:00
|
|
|
_NET_WM_ICON_NAME);
|
|
|
|
XFree(iconprop.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 17:39:48 +00:00
|
|
|
void
|
|
|
|
X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
2010-07-13 23:11:10 -07:00
|
|
|
Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
|
2009-01-02 17:39:48 +00:00
|
|
|
|
|
|
|
if (icon) {
|
|
|
|
int propsize;
|
2010-07-17 18:44:34 -07:00
|
|
|
long *propdata;
|
2009-01-02 17:39:48 +00:00
|
|
|
|
|
|
|
/* Set the _NET_WM_ICON property */
|
2013-07-14 18:17:28 -07:00
|
|
|
SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
|
2009-01-04 17:14:27 +00:00
|
|
|
propsize = 2 + (icon->w * icon->h);
|
2010-07-21 21:53:41 -07:00
|
|
|
propdata = SDL_malloc(propsize * sizeof(long));
|
2009-01-02 17:39:48 +00:00
|
|
|
if (propdata) {
|
2010-07-17 18:44:34 -07:00
|
|
|
int x, y;
|
|
|
|
Uint32 *src;
|
|
|
|
long *dst;
|
|
|
|
|
2009-01-02 17:39:48 +00:00
|
|
|
propdata[0] = icon->w;
|
|
|
|
propdata[1] = icon->h;
|
2010-07-17 18:44:34 -07:00
|
|
|
dst = &propdata[2];
|
|
|
|
for (y = 0; y < icon->h; ++y) {
|
2013-07-14 18:17:28 -07:00
|
|
|
src = (Uint32*)((Uint8*)icon->pixels + y * icon->pitch);
|
2010-07-17 18:44:34 -07:00
|
|
|
for (x = 0; x < icon->w; ++x) {
|
|
|
|
*dst++ = *src++;
|
|
|
|
}
|
|
|
|
}
|
2010-01-21 06:21:52 +00:00
|
|
|
XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
|
2009-01-04 17:14:27 +00:00
|
|
|
32, PropModeReplace, (unsigned char *) propdata,
|
|
|
|
propsize);
|
2009-01-02 17:39:48 +00:00
|
|
|
}
|
2012-10-05 22:43:00 -04:00
|
|
|
SDL_free(propdata);
|
2009-01-02 17:39:48 +00:00
|
|
|
} else {
|
2010-01-21 06:21:52 +00:00
|
|
|
XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
|
2009-01-02 17:39:48 +00:00
|
|
|
}
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2009-01-02 17:39:48 +00:00
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
void
|
|
|
|
X11_SetWindowPosition(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
|
2011-03-11 16:54:43 -08:00
|
|
|
XMoveWindow(display, data->xwindow, window->x, window->y);
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
X11_SetWindowSize(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
|
2012-09-27 23:55:38 -07:00
|
|
|
if (SDL_IsShapedWindow(window)) {
|
2010-06-30 16:19:44 -04:00
|
|
|
X11_ResizeWindowShape(window);
|
2012-09-27 23:55:38 -07:00
|
|
|
}
|
2011-04-05 09:47:34 -07:00
|
|
|
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
|
|
|
/* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the XResizeWindow, thus
|
|
|
|
we must set the size hints to adjust the window size.*/
|
|
|
|
XSizeHints *sizehints = XAllocSizeHints();
|
|
|
|
long userhints;
|
|
|
|
|
|
|
|
XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
|
|
|
|
|
2012-06-22 23:31:22 -04:00
|
|
|
sizehints->min_width = sizehints->max_width = window->w;
|
2011-04-05 09:47:34 -07:00
|
|
|
sizehints->min_height = sizehints->max_height = window->h;
|
|
|
|
|
|
|
|
XSetWMNormalHints(display, data->xwindow, sizehints);
|
|
|
|
|
|
|
|
XFree(sizehints);
|
2012-10-03 12:33:42 -07:00
|
|
|
|
|
|
|
/* From Pierre-Loup:
|
2013-02-18 18:28:02 -08:00
|
|
|
WMs each have their little quirks with that. When you change the
|
|
|
|
size hints, they get a ConfigureNotify event with the
|
|
|
|
WM_NORMAL_SIZE_HINTS Atom. They all save the hints then, but they
|
|
|
|
don't all resize the window right away to enforce the new hints.
|
|
|
|
|
|
|
|
Some of them resize only after:
|
|
|
|
- A user-initiated move or resize
|
|
|
|
- A code-initiated move or resize
|
|
|
|
- Hiding & showing window (Unmap & map)
|
|
|
|
|
|
|
|
The following move & resize seems to help a lot of WMs that didn't
|
|
|
|
properly update after the hints were changed. We don't do a
|
|
|
|
hide/show, because there are supposedly subtle problems with doing so
|
|
|
|
and transitioning from windowed to fullscreen in Unity.
|
|
|
|
*/
|
|
|
|
XResizeWindow(display, data->xwindow, window->w, window->h);
|
|
|
|
XMoveWindow(display, data->xwindow, window->x, window->y);
|
2012-10-03 12:33:42 -07:00
|
|
|
XRaiseWindow(display, data->xwindow);
|
2012-09-27 23:55:38 -07:00
|
|
|
} else {
|
2011-04-05 09:47:34 -07:00
|
|
|
XResizeWindow(display, data->xwindow, window->w, window->h);
|
2012-09-27 23:55:38 -07:00
|
|
|
}
|
2013-02-18 18:28:02 -08:00
|
|
|
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
2012-09-13 01:43:53 -04:00
|
|
|
void
|
|
|
|
X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
|
|
|
|
{
|
2012-09-13 15:24:04 -04:00
|
|
|
const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
|
|
|
|
const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
|
2012-09-13 01:43:53 -04:00
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_DisplayData *displaydata =
|
|
|
|
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
XEvent event;
|
|
|
|
|
|
|
|
SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
|
2012-09-13 15:24:04 -04:00
|
|
|
XFlush(display);
|
2012-09-13 01:43:53 -04:00
|
|
|
XIfEvent(display, &event, &isConfigureNotify, (XPointer)&data->xwindow);
|
|
|
|
|
2012-09-13 15:24:04 -04:00
|
|
|
if (visible) {
|
|
|
|
XWindowAttributes attr;
|
|
|
|
do {
|
|
|
|
XSync(display, False);
|
|
|
|
XGetWindowAttributes(display, data->xwindow, &attr);
|
|
|
|
} while (attr.map_state != IsViewable);
|
2012-09-13 01:43:53 -04:00
|
|
|
|
2012-09-13 15:24:04 -04:00
|
|
|
if (focused) {
|
|
|
|
XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make sure these don't make it to the real event queue if they fired here. */
|
|
|
|
XSync(display, False);
|
|
|
|
XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
|
|
|
|
XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
|
2012-09-13 01:43:53 -04:00
|
|
|
}
|
2012-06-21 09:58:22 -04:00
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
void
|
|
|
|
X11_ShowWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
2012-06-21 09:58:22 -04:00
|
|
|
XEvent event;
|
2006-07-27 06:53:23 +00:00
|
|
|
|
2012-09-28 00:57:47 -07:00
|
|
|
if (!X11_IsWindowMapped(_this, window)) {
|
|
|
|
XMapRaised(display, data->xwindow);
|
|
|
|
/* Blocking wait for "MapNotify" event.
|
2013-05-18 14:17:52 -07:00
|
|
|
* We use XIfEvent because XWindowEvent takes a mask rather than a type,
|
2012-09-28 00:57:47 -07:00
|
|
|
* and XCheckTypedWindowEvent doesn't block */
|
|
|
|
XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
|
|
|
|
XFlush(display);
|
|
|
|
}
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
X11_HideWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
2013-07-27 00:49:34 -07:00
|
|
|
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
2006-07-27 06:53:23 +00:00
|
|
|
Display *display = data->videodata->display;
|
2012-06-21 09:58:22 -04:00
|
|
|
XEvent event;
|
2006-07-27 06:53:23 +00:00
|
|
|
|
2012-09-28 00:57:47 -07:00
|
|
|
if (X11_IsWindowMapped(_this, window)) {
|
2013-07-27 00:49:34 -07:00
|
|
|
XWithdrawWindow(display, data->xwindow, displaydata->screen);
|
2012-09-28 00:57:47 -07:00
|
|
|
/* Blocking wait for "UnmapNotify" event */
|
2013-05-18 14:17:52 -07:00
|
|
|
XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
|
2012-09-28 00:57:47 -07:00
|
|
|
XFlush(display);
|
|
|
|
}
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
X11_RaiseWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
|
2010-01-21 06:21:52 +00:00
|
|
|
XRaiseWindow(display, data->xwindow);
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
2009-02-19 06:48:25 +00:00
|
|
|
static void
|
2011-02-15 17:23:02 -08:00
|
|
|
SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
|
2009-02-19 06:48:25 +00:00
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_DisplayData *displaydata =
|
2011-02-10 14:44:25 -08:00
|
|
|
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
2009-02-19 06:48:25 +00:00
|
|
|
Display *display = data->videodata->display;
|
2010-07-13 23:11:10 -07:00
|
|
|
Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
|
|
|
|
Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
|
|
|
|
Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
|
2010-07-14 00:56:08 -07:00
|
|
|
|
|
|
|
if (X11_IsWindowMapped(_this, window)) {
|
|
|
|
XEvent e;
|
|
|
|
|
2010-07-14 07:25:07 -07:00
|
|
|
SDL_zero(e);
|
2010-07-14 00:56:08 -07:00
|
|
|
e.xany.type = ClientMessage;
|
|
|
|
e.xclient.message_type = _NET_WM_STATE;
|
|
|
|
e.xclient.format = 32;
|
|
|
|
e.xclient.window = data->xwindow;
|
|
|
|
e.xclient.data.l[0] =
|
|
|
|
maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
|
|
|
e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
|
|
|
|
e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
|
|
|
|
e.xclient.data.l[3] = 0l;
|
|
|
|
|
|
|
|
XSendEvent(display, RootWindow(display, displaydata->screen), 0,
|
|
|
|
SubstructureNotifyMask | SubstructureRedirectMask, &e);
|
|
|
|
} else {
|
2012-09-27 23:55:38 -07:00
|
|
|
Uint32 flags;
|
2010-07-14 00:56:08 -07:00
|
|
|
|
2012-09-27 23:55:38 -07:00
|
|
|
flags = window->flags;
|
2010-07-14 00:56:08 -07:00
|
|
|
if (maximized) {
|
2012-09-27 23:55:38 -07:00
|
|
|
flags |= SDL_WINDOW_MAXIMIZED;
|
|
|
|
} else {
|
|
|
|
flags &= ~SDL_WINDOW_MAXIMIZED;
|
2010-07-14 00:56:08 -07:00
|
|
|
}
|
2012-09-28 01:51:51 -07:00
|
|
|
X11_SetNetWMState(_this, data->xwindow, flags);
|
2010-07-14 00:56:08 -07:00
|
|
|
}
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2009-02-19 06:48:25 +00:00
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
void
|
|
|
|
X11_MaximizeWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
2011-02-15 17:23:02 -08:00
|
|
|
SetWindowMaximized(_this, window, SDL_TRUE);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
X11_MinimizeWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
2010-07-13 23:11:10 -07:00
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_DisplayData *displaydata =
|
2011-02-10 14:44:25 -08:00
|
|
|
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
2010-07-13 23:11:10 -07:00
|
|
|
Display *display = data->videodata->display;
|
2013-05-18 14:17:52 -07:00
|
|
|
|
2010-07-13 23:11:10 -07:00
|
|
|
XIconifyWindow(display, data->xwindow, displaydata->screen);
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-06 09:37:03 -08:00
|
|
|
static void
|
|
|
|
SetWindowActive(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_DisplayData *displaydata =
|
|
|
|
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
2013-05-18 14:17:52 -07:00
|
|
|
Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
|
2013-03-06 09:37:03 -08:00
|
|
|
|
|
|
|
if (X11_IsWindowMapped(_this, window)) {
|
|
|
|
XEvent e;
|
|
|
|
|
|
|
|
SDL_zero(e);
|
|
|
|
e.xany.type = ClientMessage;
|
|
|
|
e.xclient.message_type = _NET_ACTIVE_WINDOW;
|
|
|
|
e.xclient.format = 32;
|
|
|
|
e.xclient.window = data->xwindow;
|
|
|
|
e.xclient.data.l[0] = 1; /* source indication. 1 = application */
|
2013-05-18 14:17:52 -07:00
|
|
|
e.xclient.data.l[1] = CurrentTime;
|
|
|
|
e.xclient.data.l[2] = 0;
|
2013-03-06 09:37:03 -08:00
|
|
|
|
|
|
|
XSendEvent(display, RootWindow(display, displaydata->screen), 0,
|
|
|
|
SubstructureNotifyMask | SubstructureRedirectMask, &e);
|
|
|
|
|
2013-05-18 14:17:52 -07:00
|
|
|
XFlush(display);
|
2013-03-06 09:37:03 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
void
|
|
|
|
X11_RestoreWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
2011-02-15 17:23:02 -08:00
|
|
|
SetWindowMaximized(_this, window, SDL_FALSE);
|
2013-05-18 14:17:52 -07:00
|
|
|
SetWindowActive(_this, window);
|
2006-07-27 06:53:23 +00:00
|
|
|
X11_ShowWindow(_this, window);
|
|
|
|
}
|
|
|
|
|
2012-09-27 03:36:13 -04:00
|
|
|
/* This asks the Window Manager to handle fullscreen for us. Most don't do it right, though. */
|
|
|
|
static void
|
|
|
|
X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
|
2011-02-15 17:23:02 -08:00
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
2011-02-15 23:07:14 -08:00
|
|
|
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
|
2011-02-15 17:23:02 -08:00
|
|
|
Display *display = data->videodata->display;
|
|
|
|
Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
|
|
|
|
Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
|
|
|
|
|
|
|
|
if (X11_IsWindowMapped(_this, window)) {
|
|
|
|
XEvent e;
|
|
|
|
|
2012-10-03 12:14:04 -07:00
|
|
|
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
|
|
|
/* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
|
|
|
|
can be resized to the fullscreen resolution (or reset so we're not resizable again) */
|
|
|
|
XSizeHints *sizehints = XAllocSizeHints();
|
|
|
|
long flags = 0;
|
|
|
|
XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
|
|
|
|
/* set the resize flags on */
|
|
|
|
if (fullscreen) {
|
|
|
|
/* we are going fullscreen so turn the flags off */
|
|
|
|
sizehints->flags &= ~(PMinSize | PMaxSize);
|
|
|
|
} else {
|
|
|
|
/* Reset the min/max width height to make the window non-resizable again */
|
2012-09-27 00:53:37 -04:00
|
|
|
sizehints->flags |= PMinSize | PMaxSize;
|
2012-10-03 12:19:55 -07:00
|
|
|
sizehints->min_width = sizehints->max_width = window->windowed.w;
|
|
|
|
sizehints->min_height = sizehints->max_height = window->windowed.h;
|
2012-09-27 00:53:37 -04:00
|
|
|
}
|
2012-10-03 12:14:04 -07:00
|
|
|
XSetWMNormalHints(display, data->xwindow, sizehints);
|
|
|
|
XFree(sizehints);
|
2012-09-27 00:53:37 -04:00
|
|
|
}
|
2012-10-03 12:14:04 -07:00
|
|
|
|
2011-02-15 17:23:02 -08:00
|
|
|
SDL_zero(e);
|
|
|
|
e.xany.type = ClientMessage;
|
|
|
|
e.xclient.message_type = _NET_WM_STATE;
|
|
|
|
e.xclient.format = 32;
|
|
|
|
e.xclient.window = data->xwindow;
|
|
|
|
e.xclient.data.l[0] =
|
|
|
|
fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
|
|
|
e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
|
|
|
|
e.xclient.data.l[3] = 0l;
|
|
|
|
|
|
|
|
XSendEvent(display, RootWindow(display, displaydata->screen), 0,
|
|
|
|
SubstructureNotifyMask | SubstructureRedirectMask, &e);
|
|
|
|
} else {
|
2012-09-27 23:55:38 -07:00
|
|
|
Uint32 flags;
|
2011-02-15 17:23:02 -08:00
|
|
|
|
2012-09-27 23:55:38 -07:00
|
|
|
flags = window->flags;
|
2011-02-15 17:23:02 -08:00
|
|
|
if (fullscreen) {
|
2012-09-27 23:55:38 -07:00
|
|
|
flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
} else {
|
|
|
|
flags &= ~SDL_WINDOW_FULLSCREEN;
|
2011-02-15 17:23:02 -08:00
|
|
|
}
|
2012-09-28 01:51:51 -07:00
|
|
|
X11_SetNetWMState(_this, data->xwindow, flags);
|
2011-02-15 17:23:02 -08:00
|
|
|
}
|
2012-10-11 09:34:13 -07:00
|
|
|
|
2012-10-11 14:43:13 -07:00
|
|
|
if (data->visual->class == DirectColor) {
|
|
|
|
if ( fullscreen ) {
|
|
|
|
XInstallColormap(display, data->colormap);
|
|
|
|
} else {
|
|
|
|
XUninstallColormap(display, data->colormap);
|
|
|
|
}
|
|
|
|
}
|
2012-10-11 09:34:13 -07:00
|
|
|
|
2011-02-15 17:23:02 -08:00
|
|
|
XFlush(display);
|
|
|
|
}
|
|
|
|
|
2012-09-27 03:36:13 -04:00
|
|
|
/* This handles fullscreen itself, outside the Window Manager. */
|
|
|
|
static void
|
|
|
|
X11_BeginWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
|
|
|
|
Visual *visual = data->visual;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
const int screen = displaydata->screen;
|
|
|
|
Window root = RootWindow(display, screen);
|
|
|
|
const int def_vis = (visual == DefaultVisual(display, screen));
|
|
|
|
unsigned long xattrmask = 0;
|
|
|
|
XSetWindowAttributes xattr;
|
|
|
|
XEvent ev;
|
2012-09-27 13:23:34 -07:00
|
|
|
SDL_Rect rect;
|
2012-09-27 03:36:13 -04:00
|
|
|
|
|
|
|
if ( data->fswindow ) {
|
|
|
|
return; /* already fullscreen, I hope. */
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:23:34 -07:00
|
|
|
X11_GetDisplayBounds(_this, _display, &rect);
|
|
|
|
|
2012-09-27 03:36:13 -04:00
|
|
|
SDL_zero(xattr);
|
|
|
|
xattr.override_redirect = True;
|
|
|
|
xattrmask |= CWOverrideRedirect;
|
|
|
|
xattr.background_pixel = def_vis ? BlackPixel(display, screen) : 0;
|
|
|
|
xattrmask |= CWBackPixel;
|
|
|
|
xattr.border_pixel = 0;
|
|
|
|
xattrmask |= CWBorderPixel;
|
|
|
|
xattr.colormap = data->colormap;
|
|
|
|
xattrmask |= CWColormap;
|
|
|
|
|
2012-09-27 13:23:34 -07:00
|
|
|
data->fswindow = XCreateWindow(display, root,
|
|
|
|
rect.x, rect.y, rect.w, rect.h, 0,
|
2012-09-27 03:36:13 -04:00
|
|
|
displaydata->depth, InputOutput,
|
|
|
|
visual, xattrmask, &xattr);
|
|
|
|
|
|
|
|
XSelectInput(display, data->fswindow, StructureNotifyMask);
|
|
|
|
XSetWindowBackground(display, data->fswindow, 0);
|
2012-09-28 10:24:28 -07:00
|
|
|
XInstallColormap(display, data->colormap);
|
2012-09-27 03:36:13 -04:00
|
|
|
XClearWindow(display, data->fswindow);
|
|
|
|
XMapRaised(display, data->fswindow);
|
|
|
|
|
2012-09-27 17:17:33 -07:00
|
|
|
/* Make sure the fswindow is in view by warping mouse to the corner */
|
2012-09-28 10:24:28 -07:00
|
|
|
XUngrabPointer(display, CurrentTime);
|
2012-09-27 17:17:33 -07:00
|
|
|
XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
|
|
|
|
|
2012-09-27 03:36:13 -04:00
|
|
|
/* Wait to be mapped, filter Unmap event out if it arrives. */
|
|
|
|
XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
|
|
|
|
XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
|
|
|
|
|
|
|
|
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
|
|
|
|
if ( displaydata->use_vidmode ) {
|
|
|
|
XF86VidModeLockModeSwitch(display, screen, True);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
|
|
|
|
|
|
|
|
/* Center actual window within our cover-the-screen window. */
|
2012-09-28 10:54:26 -07:00
|
|
|
XReparentWindow(display, data->xwindow, data->fswindow,
|
|
|
|
(rect.w - window->w) / 2, (rect.h - window->h) / 2);
|
2012-09-27 03:36:13 -04:00
|
|
|
|
2012-09-28 10:54:26 -07:00
|
|
|
/* Center mouse in the fullscreen window. */
|
|
|
|
rect.x += (rect.w / 2);
|
|
|
|
rect.y += (rect.h / 2);
|
2012-09-27 13:23:34 -07:00
|
|
|
XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
|
2012-09-27 03:36:13 -04:00
|
|
|
|
|
|
|
/* Wait to be mapped, filter Unmap event out if it arrives. */
|
|
|
|
XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
|
2012-09-27 17:17:33 -07:00
|
|
|
XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
|
2012-09-27 03:36:13 -04:00
|
|
|
|
2012-11-07 15:55:43 -08:00
|
|
|
SDL_UpdateWindowGrab(window);
|
2012-09-27 03:36:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
const int screen = displaydata->screen;
|
|
|
|
Window root = RootWindow(display, screen);
|
2012-09-27 17:17:33 -07:00
|
|
|
Window fswindow = data->fswindow;
|
2012-09-27 03:36:13 -04:00
|
|
|
XEvent ev;
|
|
|
|
|
2012-09-27 17:17:33 -07:00
|
|
|
if (!data->fswindow) {
|
2012-09-27 03:36:13 -04:00
|
|
|
return; /* already not fullscreen, I hope. */
|
2012-09-27 17:17:33 -07:00
|
|
|
}
|
2012-09-27 03:36:13 -04:00
|
|
|
|
2012-09-27 17:17:33 -07:00
|
|
|
data->fswindow = None;
|
2012-09-27 03:36:13 -04:00
|
|
|
|
|
|
|
#if SDL_VIDEO_DRIVER_X11_VIDMODE
|
|
|
|
if ( displaydata->use_vidmode ) {
|
|
|
|
XF86VidModeLockModeSwitch(display, screen, False);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-07 15:55:43 -08:00
|
|
|
SDL_UpdateWindowGrab(window);
|
2012-09-27 17:17:33 -07:00
|
|
|
|
|
|
|
XReparentWindow(display, data->xwindow, root, window->x, window->y);
|
2012-09-27 03:36:13 -04:00
|
|
|
|
2012-09-27 17:17:33 -07:00
|
|
|
/* flush these events so they don't confuse normal event handling */
|
2012-09-27 03:36:13 -04:00
|
|
|
XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
|
|
|
|
XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
|
|
|
|
|
|
|
|
SetWindowBordered(display, screen, data->xwindow,
|
|
|
|
(window->flags & SDL_WINDOW_BORDERLESS) == 0);
|
|
|
|
|
2013-07-27 00:49:34 -07:00
|
|
|
XWithdrawWindow(display, fswindow, screen);
|
2012-09-27 17:17:33 -07:00
|
|
|
|
|
|
|
/* Wait to be unmapped. */
|
|
|
|
XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
|
|
|
|
XDestroyWindow(display, fswindow);
|
2012-09-27 03:36:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
|
|
|
|
{
|
|
|
|
/* !!! FIXME: SDL_Hint? */
|
|
|
|
SDL_bool legacy = SDL_FALSE;
|
|
|
|
const char *env = SDL_getenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN");
|
|
|
|
if (env) {
|
|
|
|
legacy = SDL_atoi(env);
|
|
|
|
} else {
|
2012-09-27 11:39:31 -07:00
|
|
|
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
2012-09-27 03:36:13 -04:00
|
|
|
SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
|
|
|
|
if ( displaydata->use_vidmode ) {
|
|
|
|
legacy = SDL_TRUE; /* the new stuff only works with XRandR. */
|
2012-09-27 11:39:31 -07:00
|
|
|
} else if ( !videodata->net_wm ) {
|
|
|
|
legacy = SDL_TRUE; /* The window manager doesn't support it */
|
2012-09-27 03:36:13 -04:00
|
|
|
} else {
|
|
|
|
/* !!! FIXME: look at the window manager name, and blacklist certain ones? */
|
|
|
|
/* http://stackoverflow.com/questions/758648/find-the-name-of-the-x-window-manager */
|
|
|
|
legacy = SDL_FALSE; /* try the new way. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (legacy) {
|
|
|
|
if (fullscreen) {
|
|
|
|
X11_BeginWindowFullscreenLegacy(_this, window, _display);
|
|
|
|
} else {
|
|
|
|
X11_EndWindowFullscreenLegacy(_this, window, _display);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-11 08:49:20 -08:00
|
|
|
int
|
|
|
|
X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
Visual *visual = data->visual;
|
|
|
|
Colormap colormap = data->colormap;
|
|
|
|
XColor *colorcells;
|
|
|
|
int ncolors;
|
|
|
|
int rmask, gmask, bmask;
|
|
|
|
int rshift, gshift, bshift;
|
2011-10-13 01:08:30 -04:00
|
|
|
int i;
|
2011-03-11 08:49:20 -08:00
|
|
|
|
|
|
|
if (visual->class != DirectColor) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Window doesn't have DirectColor visual");
|
2011-03-11 08:49:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ncolors = visual->map_entries;
|
|
|
|
colorcells = SDL_malloc(ncolors * sizeof(XColor));
|
|
|
|
if (!colorcells) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_OutOfMemory();
|
2011-03-11 08:49:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
rshift = 0;
|
|
|
|
rmask = visual->red_mask;
|
|
|
|
while (0 == (rmask & 1)) {
|
|
|
|
rshift++;
|
|
|
|
rmask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gshift = 0;
|
|
|
|
gmask = visual->green_mask;
|
|
|
|
while (0 == (gmask & 1)) {
|
|
|
|
gshift++;
|
|
|
|
gmask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bshift = 0;
|
|
|
|
bmask = visual->blue_mask;
|
|
|
|
while (0 == (bmask & 1)) {
|
|
|
|
bshift++;
|
|
|
|
bmask >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build the color table pixel values */
|
|
|
|
for (i = 0; i < ncolors; i++) {
|
|
|
|
Uint32 rbits = (rmask * i) / (ncolors - 1);
|
|
|
|
Uint32 gbits = (gmask * i) / (ncolors - 1);
|
|
|
|
Uint32 bbits = (bmask * i) / (ncolors - 1);
|
|
|
|
Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
|
|
|
|
|
|
|
|
colorcells[i].pixel = pix;
|
|
|
|
|
|
|
|
colorcells[i].red = ramp[(0 * 256) + i];
|
|
|
|
colorcells[i].green = ramp[(1 * 256) + i];
|
|
|
|
colorcells[i].blue = ramp[(2 * 256) + i];
|
|
|
|
|
|
|
|
colorcells[i].flags = DoRed | DoGreen | DoBlue;
|
|
|
|
}
|
|
|
|
|
|
|
|
XStoreColors(display, colormap, colorcells, ncolors);
|
|
|
|
XFlush(display);
|
|
|
|
SDL_free(colorcells);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
void
|
2012-11-07 15:55:43 -08:00
|
|
|
X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
|
2006-07-27 06:53:23 +00:00
|
|
|
{
|
2008-12-17 07:17:54 +00:00
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
2010-07-13 23:11:10 -07:00
|
|
|
SDL_bool oldstyle_fullscreen;
|
2012-11-07 15:55:43 -08:00
|
|
|
SDL_bool grab_keyboard;
|
|
|
|
const char *hint;
|
2010-07-13 23:11:10 -07:00
|
|
|
|
2012-11-07 15:55:43 -08:00
|
|
|
/* ICCCM2.0-compliant window managers can handle fullscreen windows
|
|
|
|
If we're using XVidMode to change resolution we need to confine
|
|
|
|
the cursor so we don't pan around the virtual desktop.
|
|
|
|
*/
|
2012-09-27 03:36:13 -04:00
|
|
|
oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
|
2008-12-17 07:17:54 +00:00
|
|
|
|
2012-11-07 15:55:43 -08:00
|
|
|
if (oldstyle_fullscreen || grabbed) {
|
2008-12-17 07:17:54 +00:00
|
|
|
/* Try to grab the mouse */
|
2008-12-17 07:19:55 +00:00
|
|
|
for (;;) {
|
|
|
|
int result =
|
2010-01-21 06:21:52 +00:00
|
|
|
XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
|
|
|
|
GrabModeAsync, data->xwindow, None, CurrentTime);
|
2008-12-17 07:19:55 +00:00
|
|
|
if (result == GrabSuccess) {
|
2008-12-17 07:17:54 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-11-07 15:55:43 -08:00
|
|
|
SDL_Delay(50);
|
2008-12-17 07:17:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Raise the window if we grab the mouse */
|
2010-01-21 06:21:52 +00:00
|
|
|
XRaiseWindow(display, data->xwindow);
|
2008-12-17 07:17:54 +00:00
|
|
|
|
|
|
|
/* Now grab the keyboard */
|
2012-11-07 15:55:43 -08:00
|
|
|
hint = SDL_GetHint(SDL_HINT_GRAB_KEYBOARD);
|
|
|
|
if (hint && SDL_atoi(hint)) {
|
|
|
|
grab_keyboard = SDL_TRUE;
|
|
|
|
} else {
|
|
|
|
/* We need to do this with the old style override_redirect
|
|
|
|
fullscreen window otherwise we won't get keyboard focus.
|
|
|
|
*/
|
|
|
|
grab_keyboard = oldstyle_fullscreen;
|
|
|
|
}
|
|
|
|
if (grab_keyboard) {
|
|
|
|
XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
|
|
|
|
GrabModeAsync, CurrentTime);
|
|
|
|
}
|
2008-12-17 07:17:54 +00:00
|
|
|
} else {
|
|
|
|
XUngrabPointer(display, CurrentTime);
|
|
|
|
XUngrabKeyboard(display, CurrentTime);
|
|
|
|
}
|
2012-09-28 10:24:28 -07:00
|
|
|
XSync(display, False);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
X11_DestroyWindow(_THIS, SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
2008-03-06 23:07:02 +00:00
|
|
|
window->driverdata = NULL;
|
2006-07-27 06:53:23 +00:00
|
|
|
|
|
|
|
if (data) {
|
2008-03-06 23:07:02 +00:00
|
|
|
SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
|
|
|
|
Display *display = videodata->display;
|
|
|
|
int numwindows = videodata->numwindows;
|
|
|
|
SDL_WindowData **windowlist = videodata->windowlist;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (windowlist) {
|
2008-03-07 17:20:37 +00:00
|
|
|
for (i = 0; i < numwindows; ++i) {
|
2010-01-21 06:21:52 +00:00
|
|
|
if (windowlist[i] && (windowlist[i]->window == window)) {
|
2008-03-07 17:20:37 +00:00
|
|
|
windowlist[i] = windowlist[numwindows - 1];
|
|
|
|
windowlist[numwindows - 1] = NULL;
|
|
|
|
videodata->numwindows--;
|
|
|
|
break;
|
|
|
|
}
|
2008-03-06 23:07:02 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-27 06:53:23 +00:00
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
if (data->ic) {
|
|
|
|
XDestroyIC(data->ic);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (data->created) {
|
2010-01-21 06:21:52 +00:00
|
|
|
XDestroyWindow(display, data->xwindow);
|
2011-01-19 10:14:11 -08:00
|
|
|
XFlush(display);
|
2006-07-27 06:53:23 +00:00
|
|
|
}
|
|
|
|
SDL_free(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_bool
|
|
|
|
X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|
|
|
{
|
2010-07-12 01:20:57 -07:00
|
|
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
|
|
Display *display = data->videodata->display;
|
|
|
|
|
|
|
|
if (info->version.major == SDL_MAJOR_VERSION &&
|
|
|
|
info->version.minor == SDL_MINOR_VERSION) {
|
|
|
|
info->subsystem = SDL_SYSWM_X11;
|
2011-01-20 16:05:59 -08:00
|
|
|
info->info.x11.display = display;
|
|
|
|
info->info.x11.window = data->xwindow;
|
2006-07-27 06:53:23 +00:00
|
|
|
return SDL_TRUE;
|
|
|
|
} else {
|
|
|
|
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
|
|
|
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-12 13:21:57 -08:00
|
|
|
#endif /* SDL_VIDEO_DRIVER_X11 */
|
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|