From fb1d85dbf9bfe23600f82474e5d0d223bd6d3b71 Mon Sep 17 00:00:00 2001 From: Jarcode Date: Sat, 8 Sep 2018 14:05:40 -0700 Subject: [PATCH] Added potential fixes for KDE --- Makefile | 4 ++-- glfw_wcb.c | 1 + glx_wcb.c | 55 +++++++++++++++++++++++++++++++++++++++---------- render.c | 11 ++++++++-- render.h | 2 ++ shaders/rc.glsl | 4 ++++ xwin.c | 31 ++++++++++++++++++++++------ xwin.h | 8 +++++++ 8 files changed, 95 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index c0337a7..92f9722 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,9 @@ obj = $(src:.c=.o) # Build type parameter ifeq ($(BUILD),debug) - CFLAGS_BUILD = -O0 -ggdb -Wall -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls + CFLAGS_BUILD = -O0 -ggdb -Wall #-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls GLAD_GEN = c-debug - ASAN = -lasan +# ASAN = -lasan else CFLAGS_BUILD = -O2 -march=native GLAD_GEN = c diff --git a/glfw_wcb.c b/glfw_wcb.c index 6fe001a..cf56065 100644 --- a/glfw_wcb.c +++ b/glfw_wcb.c @@ -132,6 +132,7 @@ static void get_pos (GLFWwindow* w, int* x, int* y) { glfwGetWindowPo static double get_time (GLFWwindow* w) { return glfwGetTime(); } static void set_time (GLFWwindow* w, double time) { glfwSetTime(time); } static void set_swap (int i) { glfwSwapInterval(i); } +static void raise (GLFWwindow* w) { glfwShowWindow(w); } WCB_ATTACH("glfw", wcb_glfw); diff --git a/glx_wcb.c b/glx_wcb.c index 7206131..bc6b950 100644 --- a/glx_wcb.c +++ b/glx_wcb.c @@ -176,6 +176,8 @@ struct glxwin { bool should_close; }; +static Atom ATOM__MOTIF_WM_HINTS, ATOM_WM_DELETE_WINDOW, ATOM_WM_PROTOCOLS, ATOM__NET_ACTIVE_WINDOW; + static void init(void) { display = XOpenDisplay(NULL); if (!display) { @@ -210,6 +212,8 @@ static void init(void) { } #define resolve(name) do { name = (typeof(name)) resolve_f(#name); } while (0) + #define intern(name, only_if_exists) \ + do { ATOM_##name = XInternAtom(display, #name, only_if_exists); } while (0) resolve(glXChooseFBConfig); resolve(glXGetVisualFromFBConfig); @@ -218,7 +222,13 @@ static void init(void) { resolve(glXGetCurrentDrawable); resolve(glXGetProcAddressARB); resolve(glXSwapBuffers); - + + intern(_MOTIF_WM_HINTS, false); + intern(WM_DELETE_WINDOW, true); + intern(WM_PROTOCOLS, true); + intern(_NET_ACTIVE_WINDOW, false); + + #undef intern #undef resolve } @@ -232,10 +242,8 @@ static void apply_decorations(Window w) { hints.flags = 2; hints.decorations = 0; - - Atom motif = XInternAtom(display, "_MOTIF_WM_HINTS", false); - XChangeProperty(display, w, motif, motif, 32, PropModeReplace, + XChangeProperty(display, w, ATOM__MOTIF_WM_HINTS, ATOM__MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char*) &hints, sizeof(hints) / sizeof(long)); } } @@ -311,11 +319,11 @@ static void* create_and_bind(const char* name, const char* class, vi = glXGetVisualFromFBConfig(display, config); attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vi->visual, AllocNone); - attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask; + attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | PropertyChangeMask; attr.background_pixmap = None; attr.border_pixel = 0; - if (!(w->w = XCreateWindow(display, DefaultRootWindow(display), + if (!(w->w = XCreateWindow(display, *xwin_get_desktop_layer(&wcb_glx), x, y, d, h, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel, @@ -345,9 +353,8 @@ static void* create_and_bind(const char* name, const char* class, XFree(vi); XStoreName(display, w->w, name); - - Atom dwin = XInternAtom(display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(display, w->w, &dwin, 1); + + XSetWMProtocols(display, w->w, &ATOM_WM_DELETE_WINDOW, 1); // XReparentWindow(display, w->w, DefaultRootWindow(display), 0, 0); @@ -389,9 +396,34 @@ static void* create_and_bind(const char* name, const char* class, if (glXSwapIntervalEXT) glXSwapIntervalEXT(display, drawable, swap); + // XSelectInput(display, DefaultRootWindow(display), VisibilityChangeMask | PropertyChangeMask); + return w; } +static void raise(struct glxwin* w) { + XClientMessageEvent ev = { + .type = ClientMessage, + .serial = 0, + .send_event = true, + .display = display, + .window = w->w, + .message_type = ATOM__NET_ACTIVE_WINDOW, + .format = 32, + .data = { .l = { + [0] = 1, /* source indication -- `1` when coming from an application */ + [1] = 0, /* timestamp -- `0` to (attempt to) ignore */ + [2] = w->w /* requestor's currently active window -- `0` for none */ + } + } + }; + /* Send the client message as defined by EWMH standards (usually works) */ + XSendEvent(display, DefaultRootWindow(display), false, StructureNotifyMask, (XEvent*) &ev); + /* Raise the client in the X11 stacking order (sometimes works, can be blocked by the WM) */ + XRaiseWindow(display, w->w); + XFlush(display); +} + static void set_swap (int _swap) { swap = _swap; } static void set_floating (bool _floating) { floating = _floating; } static void set_decorated (bool _decorated) { decorated = _decorated; } @@ -420,10 +452,11 @@ static void swap_buffers(struct glxwin* w) { XNextEvent(display, &ev); switch (ev.type) { case ClientMessage: - if (ev.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1) - && ev.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1)) { + if (ev.xclient.message_type == ATOM_WM_PROTOCOLS + && ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW) { w->should_close = true; } + break; default: break; } } diff --git a/render.c b/render.c index cc58538..c66c1ce 100644 --- a/render.c +++ b/render.c @@ -108,8 +108,8 @@ struct gl_data { int rate; /* framerate */ double tcounter; int fcounter, ucounter, kcounter; - bool print_fps, avg_window, interpolate, force_geometry, copy_desktop, - smooth_pass, premultiply_alpha, check_fullscreen; + bool print_fps, avg_window, interpolate, force_geometry, force_raised, + copy_desktop, smooth_pass, premultiply_alpha, check_fullscreen; void** t_data; float gravity_step, target_spu, fr, ur, smooth_distance, smooth_ratio, smooth_factor, fft_scale, fft_cutoff; @@ -714,6 +714,7 @@ struct renderer* rd_new(const char** paths, const char* entry, .gravity_step = 4.2, .interpolate = true, .force_geometry = false, + .force_raised = false, .smooth_factor = 0.025, .smooth_distance = 0.01, .smooth_ratio = 4, @@ -907,6 +908,8 @@ struct renderer* rd_new(const char** paths, const char* entry, r->audio_source_request = strdup((char*) args[0]); }) }, { .name = "setforcegeometry", .fmt = "b", .handler = RHANDLER(name, args, { gl->force_geometry = *(bool*) args[0]; }) }, + { .name = "setforceraised", .fmt = "b", + .handler = RHANDLER(name, args, { gl->force_raised = *(bool*) args[0]; }) }, { .name = "setxwintype", .fmt = "s", .handler = RHANDLER(name, args, { xwintype = strdup((char*) args[0]); }) }, { .name = "setshaderversion", .fmt = "i", @@ -1633,6 +1636,10 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi gl->geometry[0], gl->geometry[1], gl->geometry[2], gl->geometry[3]); } + + if (gl->force_raised) { + gl->wcb->raise(gl->w); + } } /* Restore interpolation settings */ diff --git a/render.h b/render.h index 3bca309..dee849b 100644 --- a/render.h +++ b/render.h @@ -32,6 +32,7 @@ struct gl_wcb { int version_major, int version_minor); bool (*should_close) (void* ptr); void (*swap_buffers) (void* ptr); + void (*raise) (void* ptr); void (*get_pos) (void* ptr, int* x, int* y); void (*get_fbsize) (void* ptr, int* w, int* h); void (*set_geometry) (void* ptr, int x, int y, int w, int h); @@ -63,6 +64,7 @@ struct gl_wcb { WCB_FUNC(create_and_bind), \ WCB_FUNC(should_close), \ WCB_FUNC(swap_buffers), \ + WCB_FUNC(raise), \ WCB_FUNC(set_swap), \ WCB_FUNC(get_pos), \ WCB_FUNC(get_fbsize), \ diff --git a/shaders/rc.glsl b/shaders/rc.glsl index 417244c..bfc6866 100644 --- a/shaders/rc.glsl +++ b/shaders/rc.glsl @@ -26,6 +26,10 @@ embedding in the desktop. */ #request setforcegeometry false +/* Force window to be raised (focused in some WMs), useful for + WMs that have their own stacking order for desktop windows. */ +#request setforceraised false + /* Set window background opacity mode. Possible values are: "native" - True transparency provided by the compositor. Can diff --git a/xwin.c b/xwin.c index 05a243f..4b6c271 100644 --- a/xwin.c +++ b/xwin.c @@ -25,11 +25,12 @@ #include "render.h" #include "xwin.h" -static Window find_desktop(struct renderer* r) { +Window* xwin_get_desktop_layer(struct gl_wcb* wcb) { static Window desktop; static bool searched = false; if (!searched) { - Display* d = rd_get_wcb(r)->get_x11_display(); + Display* d = wcb->get_x11_display(); + Atom class = XInternAtom(d, "WM_CLASS", false); desktop = DefaultRootWindow(d); Window _ignored, * children; unsigned int nret; @@ -41,18 +42,36 @@ static Window find_desktop(struct renderer* r) { if (name) { /* Mutter-based window managers */ if (!strcmp(name, "mutter guard window")) { - printf("Using mutter guard window instead of root window\n"); - // desktop = children[t]; + printf("Reparenting to mutter guard window instead of root window\n"); + desktop = children[t]; t = nret; /* break after */ } XFree(name); } + unsigned long bytes; + XTextProperty text = {}; + char** list; + int list_sz; + /* Get WM_CLASS property */ + if (Success == XGetWindowProperty(d, children[t], class, 0, 512, false, AnyPropertyType, + &text.encoding, &text.format, &text.nitems, &bytes, + &text.value)) { + /* decode string array */ + if (Success == XmbTextPropertyToTextList(d, &text, &list, &list_sz)) { + if (list_sz >= 1 && !strcmp(list[0], "plasmashell")) { + desktop = children[t]; + t = nret; + } + XFreeStringList(list); + } + XFree(text.value); + } } XFree(children); } searched = true; } - return desktop; + return &desktop; } void xwin_wait_for_wm(void) { @@ -219,7 +238,7 @@ unsigned int xwin_copyglbg(struct renderer* rd, unsigned int tex) { rd_get_wcb(rd)->get_pos(rd_get_impl_window(rd), &x, &y); XColor c; Display* d = rd_get_wcb(rd)->get_x11_display(); - Drawable src = get_drawable(d, find_desktop(rd)); + Drawable src = get_drawable(d, DefaultRootWindow(d)); bool use_shm = XShmQueryExtension(d); /* Obtain section of root pixmap */ diff --git a/xwin.h b/xwin.h index 6e0049a..2540f9d 100644 --- a/xwin.h +++ b/xwin.h @@ -1,9 +1,17 @@ #define XWIN_ALL_DESKTOPS 0xFFFFFFFF +#ifndef XWIN_H +#define XWIN_H + +typedef unsigned long int Window; + bool xwin_should_render(struct renderer* rd); void xwin_wait_for_wm(void); bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* type); void xwin_setdesktop(struct gl_wcb* wcb, void* impl, unsigned long desktop); void xwin_addstate(struct gl_wcb* wcb, void* impl, const char* state); unsigned int xwin_copyglbg(struct renderer* rd, unsigned int texture); +Window* xwin_get_desktop_layer(struct gl_wcb* wcb); + +#endif