| | |
| | | /* |
| | | Simple DirectMedia Layer |
| | | Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> |
| | | Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> |
| | | |
| | | This software is provided 'as-is', without any express or implied |
| | | warranty. In no event will the authors be held liable for any damages |
| | |
| | | |
| | | #include "SDL_timer.h" |
| | | #include "SDL_syswm.h" |
| | | #include "SDL_assert.h" |
| | | #include "SDL_log.h" |
| | | |
| | | #define _NET_WM_STATE_REMOVE 0l |
| | | #define _NET_WM_STATE_ADD 1l |
| | | #define _NET_WM_STATE_TOGGLE 2l |
| | | |
| | | static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win) |
| | | { |
| | |
| | | if (fullscreen == 1) { |
| | | flags |= SDL_WINDOW_FULLSCREEN; |
| | | } |
| | | |
| | | /* If the window is unmapped, numItems will be zero and _NET_WM_STATE_HIDDEN |
| | | * will not be set. Do an additional check to see if the window is unmapped |
| | | * and mark it as SDL_WINDOW_HIDDEN if it is. |
| | | */ |
| | | { |
| | | XWindowAttributes attr; |
| | | SDL_memset(&attr,0,sizeof(attr)); |
| | | X11_XGetWindowAttributes(videodata->display, xwindow, &attr); |
| | | if (attr.map_state == IsUnmapped) { |
| | | flags |= SDL_WINDOW_HIDDEN; |
| | | } |
| | | } |
| | | X11_XFree(propertyValue); |
| | | } |
| | | |
| | |
| | | Atom _NET_WM_WINDOW_TYPE; |
| | | Atom wintype; |
| | | const char *wintype_name = NULL; |
| | | int compositor = 1; |
| | | long compositor = 1; |
| | | Atom _NET_WM_PID; |
| | | Atom XdndAware, xdnd_version = 5; |
| | | long fevent = 0; |
| | |
| | | #if SDL_VIDEO_OPENGL_EGL |
| | | if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES |
| | | #if SDL_VIDEO_OPENGL_GLX |
| | | && ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile ) |
| | | && ( !_this->gl_data || X11_GL_UseEGL(_this) ) |
| | | #endif |
| | | ) { |
| | | vinfo = X11_GLES_GetVisual(_this, display, screen); |
| | |
| | | wintype = X11_XInternAtom(display, wintype_name, False); |
| | | X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, |
| | | PropModeReplace, (unsigned char *)&wintype, 1); |
| | | |
| | | _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False); |
| | | X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, |
| | | PropModeReplace, |
| | | (unsigned char *)&compositor, 1); |
| | | if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, SDL_TRUE)) { |
| | | _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False); |
| | | X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, |
| | | PropModeReplace, |
| | | (unsigned char *)&compositor, 1); |
| | | } |
| | | |
| | | { |
| | | Atom protocols[3]; |
| | |
| | | if ((window->flags & SDL_WINDOW_OPENGL) && |
| | | _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES |
| | | #if SDL_VIDEO_OPENGL_GLX |
| | | && ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile ) |
| | | && ( !_this->gl_data || X11_GL_UseEGL(_this) ) |
| | | #endif |
| | | ) { |
| | | #if SDL_VIDEO_OPENGL_EGL |
| | |
| | | return SDL_SetError("Could not create GLES window surface"); |
| | | } |
| | | #else |
| | | return SDL_SetError("Could not create GLES window surface (no EGL support available)"); |
| | | return SDL_SetError("Could not create GLES window surface (EGL support not configured)"); |
| | | #endif /* SDL_VIDEO_OPENGL_EGL */ |
| | | } |
| | | #endif |
| | |
| | | /* Blocking wait for "MapNotify" event. |
| | | * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type, |
| | | * and XCheckTypedWindowEvent doesn't block */ |
| | | X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); |
| | | if(!(window->flags & SDL_WINDOW_FOREIGN)) |
| | | X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); |
| | | X11_XFlush(display); |
| | | } |
| | | |
| | |
| | | if (X11_IsWindowMapped(_this, window)) { |
| | | X11_XWithdrawWindow(display, data->xwindow, displaydata->screen); |
| | | /* Blocking wait for "UnmapNotify" event */ |
| | | X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); |
| | | if(!(window->flags & SDL_WINDOW_FOREIGN)) |
| | | X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); |
| | | X11_XFlush(display); |
| | | } |
| | | } |
| | |
| | | |
| | | if (oldstyle_fullscreen || grabbed) { |
| | | /* Try to grab the mouse */ |
| | | for (;;) { |
| | | int result = |
| | | X11_XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync, |
| | | GrabModeAsync, data->xwindow, None, CurrentTime); |
| | | if (result == GrabSuccess) { |
| | | break; |
| | | if (!data->videodata->broken_pointer_grab) { |
| | | const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; |
| | | int attempts; |
| | | int result; |
| | | |
| | | /* Try for up to 5000ms (5s) to grab. If it still fails, stop trying. */ |
| | | for (attempts = 0; attempts < 100; attempts++) { |
| | | result = X11_XGrabPointer(display, data->xwindow, True, mask, GrabModeAsync, |
| | | GrabModeAsync, data->xwindow, None, CurrentTime); |
| | | if (result == GrabSuccess) { |
| | | break; |
| | | } |
| | | SDL_Delay(50); |
| | | } |
| | | SDL_Delay(50); |
| | | |
| | | if (result != GrabSuccess) { |
| | | SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "The X server refused to let us grab the mouse. You might experience input bugs."); |
| | | data->videodata->broken_pointer_grab = SDL_TRUE; /* don't try again. */ |
| | | } |
| | | } |
| | | |
| | | /* Raise the window if we grab the mouse */ |
| | |
| | | info->info.x11.window = data->xwindow; |
| | | return SDL_TRUE; |
| | | } else { |
| | | SDL_SetError("Application not compiled with SDL %d.%d\n", |
| | | SDL_SetError("Application not compiled with SDL %d.%d", |
| | | SDL_MAJOR_VERSION, SDL_MINOR_VERSION); |
| | | return SDL_FALSE; |
| | | } |