diff --git a/gfx/common/x11_common.c b/gfx/common/x11_common.c index 57133f344f..6de3e8a3d7 100644 --- a/gfx/common/x11_common.c +++ b/gfx/common/x11_common.c @@ -685,3 +685,106 @@ void x11_event_queue_check(XEvent *event) XIfEvent(g_x11_dpy, event, x11_wait_notify, NULL); } +static bool x11_check_atom_supported(Display *dpy, Atom atom) +{ + Atom XA_NET_SUPPORTED = XInternAtom(dpy, "_NET_SUPPORTED", True); + Atom type; + int format; + unsigned long nitems; + unsigned long bytes_after; + Atom *prop; + int i; + + if (XA_NET_SUPPORTED == None) + return false; + + XGetWindowProperty(dpy, DefaultRootWindow(dpy), XA_NET_SUPPORTED, 0, UINT_MAX, False, XA_ATOM, &type, &format,&nitems, &bytes_after, (unsigned char **) &prop); + + if (!prop || type != XA_ATOM) + { + return false; + } + + for (i = 0; i < nitems; i++) + { + if (prop[i] == atom) + { + XFree(prop); + return true; + } + } + + XFree(prop); + + return false; +} + +bool x11_has_net_wm_fullscreen(Display *dpy) +{ + XA_NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + + return x11_check_atom_supported(dpy, XA_NET_WM_STATE_FULLSCREEN); +} + +char *x11_get_wm_name(Display *dpy) +{ + Atom XA_NET_SUPPORTING_WM_CHECK = XInternAtom(g_x11_dpy, "_NET_SUPPORTING_WM_CHECK", False); + Atom XA_NET_WM_NAME = XInternAtom(g_x11_dpy, "_NET_WM_NAME", False); + Atom XA_UTF8_STRING = XInternAtom(g_x11_dpy, "UTF8_STRING", False); + int status; + Atom type; + int format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *propdata; + char *title; + Window window; + + if (!XA_NET_SUPPORTING_WM_CHECK || !XA_NET_WM_NAME) + return NULL; + + status = XGetWindowProperty(dpy, + DefaultRootWindow(dpy), + XA_NET_SUPPORTING_WM_CHECK, + 0, + 1, + False, + XA_WINDOW, + &type, + &format, + &nitems, + &bytes_after, + &propdata); + + if (status == Success && propdata) + window = ((Window *) propdata)[0]; + else + return NULL; + + XFree(propdata); + + status = XGetWindowProperty(dpy, + window, + XA_NET_WM_NAME, + 0, + 8192, + False, + XA_UTF8_STRING, + &type, + &format, + &nitems, + &bytes_after, + &propdata); + + if (status == Success && propdata) + { + title = strdup((char *) propdata); + } + else + return NULL; + + XFree(propdata); + + return title; +} + diff --git a/gfx/common/x11_common.h b/gfx/common/x11_common.h index 20d8d49080..6be78245d1 100644 --- a/gfx/common/x11_common.h +++ b/gfx/common/x11_common.h @@ -75,5 +75,9 @@ void x11_install_quit_atom(void); void x11_event_queue_check(XEvent *event); +char *x11_get_wm_name(Display *dpy); + +bool x11_has_net_wm_fullscreen(Display *dpy); + #endif diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 2940b50989..e623f6c287 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -632,6 +632,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, int y_off = 0; XVisualInfo *vi = NULL; XSetWindowAttributes swa = {0}; + char *wm_name = NULL; int (*old_handler)(Display*, XErrorEvent*) = NULL; gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data; Atom net_wm_icon = XInternAtom(g_x11_dpy, "_NET_WM_ICON", False); @@ -679,6 +680,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | LeaveWindowMask | EnterWindowMask | ButtonReleaseMask | ButtonPressMask; + swa.override_redirect = False; if (fullscreen && !windowed_full) { @@ -691,7 +693,20 @@ static bool gfx_ctx_x_set_video_mode(void *data, RARCH_ERR("[GLX]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } - swa.override_redirect = true_full ? True : False; + wm_name = x11_get_wm_name(g_x11_dpy); + if (wm_name) + { + RARCH_LOG("[GLX]: Window manager is %s.\n", wm_name); + + if (true_full && strcasestr(wm_name, "xfwm")) + { + RARCH_LOG("[GLX]: Using override-redirect workaround.\n"); + swa.override_redirect = True; + } + free(wm_name); + } + if (!x11_has_net_wm_fullscreen(g_x11_dpy) && true_full) + swa.override_redirect = True; if (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; @@ -722,7 +737,7 @@ static bool gfx_ctx_x_set_video_mode(void *data, g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &swa); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); @@ -781,7 +796,6 @@ static bool gfx_ctx_x_set_video_mode(void *data, RARCH_LOG("[GLX]: Using true fullscreen.\n"); XMapRaised(g_x11_dpy, g_x11_win); x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); - XChangeWindowAttributes(g_x11_dpy, g_x11_win, CWOverrideRedirect, &swa); } else if (fullscreen) { diff --git a/gfx/drivers_context/xegl_ctx.c b/gfx/drivers_context/xegl_ctx.c index 4338545999..04485648e2 100644 --- a/gfx/drivers_context/xegl_ctx.c +++ b/gfx/drivers_context/xegl_ctx.c @@ -272,6 +272,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; + char *wm_name = NULL; xegl_ctx_data_t *xegl = (xegl_ctx_data_t*)data; settings_t *settings = config_get_ptr(); @@ -298,6 +299,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask; + swa.override_redirect = False; if (fullscreen && !video_info->windowed_fullscreen) { @@ -310,7 +312,20 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } - swa.override_redirect = true_full ? True : False; + wm_name = x11_get_wm_name(g_x11_dpy); + if (wm_name) + { + RARCH_LOG("[X/EGL]: Window manager is %s.\n", wm_name); + + if (true_full && strcasestr(wm_name, "xfwm")) + { + RARCH_LOG("[X/EGL]: Using override-redirect workaround.\n"); + swa.override_redirect = True; + } + free(wm_name); + } + if (!x11_has_net_wm_fullscreen(g_x11_dpy) && true_full) + swa.override_redirect = True; if (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; @@ -341,7 +356,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &swa); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); @@ -375,7 +390,6 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, RARCH_LOG("[X/EGL]: Using true fullscreen.\n"); XMapRaised(g_x11_dpy, g_x11_win); x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win); - XChangeWindowAttributes(g_x11_dpy, g_x11_win, CWOverrideRedirect, &swa); } else if (fullscreen) {