From 0a5e65dc06f5bb07f2d02974727d9df0a101032a Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 2 Apr 2018 20:01:14 -0500 Subject: [PATCH 1/2] Add workarounds based on window manager for override-redirect. --- gfx/common/x11_common.c | 62 ++++++++++++++++++++++++++++++++++ gfx/common/x11_common.h | 2 ++ gfx/drivers_context/x_ctx.c | 18 ++++++++-- gfx/drivers_context/xegl_ctx.c | 18 ++++++++-- 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/gfx/common/x11_common.c b/gfx/common/x11_common.c index 57133f344f..1ab16b90b7 100644 --- a/gfx/common/x11_common.c +++ b/gfx/common/x11_common.c @@ -685,3 +685,65 @@ void x11_event_queue_check(XEvent *event) XIfEvent(g_x11_dpy, event, x11_wait_notify, NULL); } +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..ec4fa0dc28 100644 --- a/gfx/common/x11_common.h +++ b/gfx/common/x11_common.h @@ -75,5 +75,7 @@ void x11_install_quit_atom(void); void x11_event_queue_check(XEvent *event); +char *x11_get_wm_name(Display *dpy); + #endif diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 2940b50989..387336f6a9 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,18 @@ 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 (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; @@ -722,7 +735,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 +794,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..2f120ad956 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,18 @@ 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 (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; @@ -341,7 +354,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 +388,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) { From 9f15e39114430299ab66a143f81dd338f3e9c24f Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 2 Apr 2018 20:21:32 -0500 Subject: [PATCH 2/2] Also use the original fallback designed for older window managers. --- gfx/common/x11_common.c | 41 ++++++++++++++++++++++++++++++++++ gfx/common/x11_common.h | 2 ++ gfx/drivers_context/x_ctx.c | 2 ++ gfx/drivers_context/xegl_ctx.c | 2 ++ 4 files changed, 47 insertions(+) diff --git a/gfx/common/x11_common.c b/gfx/common/x11_common.c index 1ab16b90b7..6de3e8a3d7 100644 --- a/gfx/common/x11_common.c +++ b/gfx/common/x11_common.c @@ -685,6 +685,47 @@ 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); diff --git a/gfx/common/x11_common.h b/gfx/common/x11_common.h index ec4fa0dc28..6be78245d1 100644 --- a/gfx/common/x11_common.h +++ b/gfx/common/x11_common.h @@ -77,5 +77,7 @@ 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 387336f6a9..e623f6c287 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -705,6 +705,8 @@ static bool gfx_ctx_x_set_video_mode(void *data, } 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; diff --git a/gfx/drivers_context/xegl_ctx.c b/gfx/drivers_context/xegl_ctx.c index 2f120ad956..04485648e2 100644 --- a/gfx/drivers_context/xegl_ctx.c +++ b/gfx/drivers_context/xegl_ctx.c @@ -324,6 +324,8 @@ static bool gfx_ctx_xegl_set_video_mode(void *data, } 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;