From d49be40fd387e3372c06eb15626b4324425e67ba Mon Sep 17 00:00:00 2001 From: Jarcode Date: Sat, 8 Sep 2018 21:06:18 -0700 Subject: [PATCH] Added --desktop flag with presets, added setclickthrough option, removed kde previous kde changes, updated readme --- Makefile | 4 +- README.md | 19 ++++++---- glava.c | 12 ++++-- glfw_wcb.c | 7 +++- glx_wcb.c | 11 +++--- render.c | 82 +++++++++++++++++++++++++++++++--------- render.h | 8 +++- shaders/env_KWin.glsl | 8 ++++ shaders/env_Openbox.glsl | 2 + shaders/env_Xfwm4.glsl | 3 ++ shaders/env_awesome.glsl | 2 + shaders/env_default.glsl | 1 + shaders/rc.glsl | 35 ++++++++++------- xwin.c | 39 +++++++++++++++++++ xwin.h | 1 + 15 files changed, 181 insertions(+), 53 deletions(-) create mode 100644 shaders/env_KWin.glsl create mode 100644 shaders/env_Openbox.glsl create mode 100644 shaders/env_Xfwm4.glsl create mode 100644 shaders/env_awesome.glsl create mode 100644 shaders/env_default.glsl diff --git a/Makefile b/Makefile index 92f9722..2403497 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ifeq ($(BUILD),debug) GLAD_GEN = c-debug # ASAN = -lasan else - CFLAGS_BUILD = -O2 -march=native + CFLAGS_BUILD = -O2 -march=native -Wstringop-overflow=0 GLAD_GEN = c endif @@ -38,7 +38,7 @@ ifeq ($(INSTALL),unix) endif endif -ifndef DISABLE_GLFW +ifdef ENABLE_GLFW CFLAGS_GLFW = -DGLAVA_GLFW LDFLAGS_GLFW = -lglfw endif diff --git a/README.md b/README.md index c42cc56..d807f92 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla - X11 - PulseAudio -- GLFW 3.1+ (optional, disable with `DISABLE_GLFW=1`) - Linux or BSD **Additional compile time requirements:** @@ -28,6 +27,10 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla - python (required to generate bindings with glad) - GCC (this program uses GNU C features) +**Optional requirements:** + +- GLFW 3.1+ (optional, enable with `ENABLE_GLFW=1`) + **Ubuntu/Debian users:** the following command ensures you have all the needed packages and headers to compile GLava: ```bash sudo apt-get install libpulse0 libpulse-dev libglfw3 libglfw3-dev libxext6 libxext-dev libxcomposite-dev python make gcc @@ -39,9 +42,9 @@ GLava will start by looking for an entry point in the user configuration folder You should start by running `glava --copy-config`. This will copy over default configuration files and create symlinks to modules in your user config folder. GLava will either load system configuration files or the user provided ones, so it's not advised to copy these files selectively. -To embed GLava in your desktop (for EWMH compliant window managers), use `#request setxwintype "desktop"` and then position it accordingly with `#request setgeometry x y width height`. You may want to also use `#request setforcegeometry true` for some window managers. +To embed GLava in your desktop (for EWMH compliant window managers), run it with the `--desktop` flag and then position it accordingly with `#request setgeometry x y width height` in your `rc.glsl`. -\* On an XDG compliant Linux or BSD system. OSX will use `/Library/glava` and `~/Library/Preferences/glava` instead. +\* On an XDG compliant Linux or BSD system. ## Desktop window compatibility @@ -50,21 +53,23 @@ GLava aims to be compatible with _most_ EWMH compliant window managers. Below is | WM | ! | Details | :---: | --- | --- | | Mutter (GNOME, Budgie) | ![-](https://placehold.it/15/118932/000000?text=+) | `"native"` (default) opacity should be used +| KWin (KDE) | ![-](https://placehold.it/15/118932/000000?text=+) | No issues | Openbox (LXDE or standalone) | ![-](https://placehold.it/15/118932/000000?text=+) | No issues -| Xfwm (XFCE) | ![-](https://placehold.it/15/118932/000000?text=+) | Desktop windows need `#request addxwinstate "pinned"` and `#request addxwinstate "below"` -| Fluxbox | ![-](https://placehold.it/15/118932/000000?text=+) | Untested, but should work without issues +| Xfwm (XFCE) | ![-](https://placehold.it/15/118932/000000?text=+) | No issues +| Fluxbox | ![-](https://placehold.it/15/118932/000000?text=+) | No issues | IceWM | ![-](https://placehold.it/15/118932/000000?text=+) | No issues | Bspwm | ![-](https://placehold.it/15/118932/000000?text=+) | No issues | Herbstluftwm | ![-](https://placehold.it/15/118932/000000?text=+) | `hc rule windowtype~'_NET_WM_WINDOW_TYPE_DESKTOP' manage=off` can be used to unmanage desktop windows | Unity | ![-](https://placehold.it/15/118932/000000?text=+) | No issues | AwesomeWM | ![-](https://placehold.it/15/f09c00/000000?text=+) | Can still be focused, may require other changes to config depending on layout -| kwin (KDE) | ![-](https://placehold.it/15/f09c00/000000?text=+) | [Issues with workspaces and stacking](https://github.com/wacossusca34/glava/issues/4), needs further testing | i3 (and i3-gaps) | ![-](https://placehold.it/15/f03c15/000000?text=+) | [i3 does not respect the `"desktop"` window type](https://github.com/wacossusca34/glava/issues/6) | EXWM | ![-](https://placehold.it/15/f03c15/000000?text=+) | EXWM does not have a desktop, and forces window decorations | Enlightenment | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing | Xmonad | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing | Any non EWMH-compliant WM | ![-](https://placehold.it/15/f03c15/000000?text=+) | Window types and hints will not work if the window manager does not support the EWMH standards. +Note that some WMs listed without issues have specific overrides when using the `--desktop` flag. See `shaders/env_*.glsl` files for details. + ## Licensing GLava is licensed under the terms of the GPLv3. GLava includes some (heavily modified) source code that originated from [cava](https://github.com/karlstav/cava), which was initially provided under the MIT license. The source files that originated from cava are the following: @@ -86,4 +91,4 @@ The below copyright applies for the modifications to the files listed above, and ## Porting -GLava was built with GLFW, making the graphics frontend mostly compatible if it were to be ported to Windows, and I have taken all the Xlib-specific code and placed it into `xwin.c` if anyone decides they wish to attempt at a port. +GLava was built with GLFW, making the graphics frontend mostly compatible if it were to be ported to Windows, and I have taken most of the Xlib-specific code and placed it into `xwin.c` if anyone decides they wish to attempt at a port. diff --git a/glava.c b/glava.c index 3404faf..2570593 100644 --- a/glava.c +++ b/glava.c @@ -159,6 +159,9 @@ static const char* help_str = "Available arguments:\n" "-h, --help show this help and exit\n" "-v, --verbose enables printing of detailed information about execution\n" + "-d, --desktop enables running glava as a desktop window by detecting the\n" + " desktop environment and setting the appropriate properties\n" + " automatically. Can override properties in \"rc.glsl\".\n" "-m, --force-mod=NAME forces the specified module to load instead, ignoring any\n" " `#request mod` instances in the entry point.\n" "-e, --entry=NAME specifies the name of the file to look for when loading shaders,\n" @@ -174,10 +177,11 @@ static const char* help_str = GLAVA_VERSION_STRING "\n" " -- Copyright (C) 2017 Levi Webb\n"; -static const char* opt_str = "hvVe:Cm:b:"; +static const char* opt_str = "dhvVe:Cm:b:"; static struct option p_opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, + {"desktop", no_argument, 0, 'd'}, {"entry", required_argument, 0, 'e'}, {"force-mod", required_argument, 0, 'm'}, {"copy-config", no_argument, 0, 'C'}, @@ -195,14 +199,14 @@ int main(int argc, char** argv) { const char* force = NULL; const char* backend = NULL; const char* system_shader_paths[] = { user_path, install_path, NULL }; - bool verbose = false; - bool copy_mode = false; + bool verbose = false, copy_mode = false, desktop = false; int c, idx; while ((c = getopt_long(argc, argv, opt_str, p_opts, &idx)) != -1) { switch (c) { case 'v': verbose = true; break; case 'C': copy_mode = true; break; + case 'd': desktop = true; break; case 'e': entry = optarg; break; case 'm': force = optarg; break; case 'b': backend = optarg; break; @@ -224,7 +228,7 @@ int main(int argc, char** argv) { exit(EXIT_SUCCESS); } - renderer* r = rd_new(system_shader_paths, entry, force, backend); + renderer* r = rd_new(system_shader_paths, entry, force, backend, desktop); float b0[r->bufsize_request], b1[r->bufsize_request]; size_t t; diff --git a/glfw_wcb.c b/glfw_wcb.c index cf56065..8d4f4e9 100644 --- a/glfw_wcb.c +++ b/glfw_wcb.c @@ -70,7 +70,8 @@ static void* create_and_bind(const char* name, const char* class, size_t states_sz, int d, int h, int x, int y, - int version_major, int version_minor) { + int version_major, int version_minor, + bool clickthrough) { GLFWwindow* w; @@ -123,7 +124,7 @@ static void swap_buffers(GLFWwindow* w) { glfwSwapBuffers(w); glfwPollEvents(); } - + static Display* get_x11_display(void) { return glfwGetX11Display(); } static Window get_x11_window (GLFWwindow* w) { return glfwGetX11Window(w); } static bool should_close (GLFWwindow* w) { return glfwWindowShouldClose(w); } @@ -134,6 +135,8 @@ static void set_time (GLFWwindow* w, double time) { glfwSetTime(tim static void set_swap (int i) { glfwSwapInterval(i); } static void raise (GLFWwindow* w) { glfwShowWindow(w); } +static const char* get_environment(void) { return xwin_detect_wm(&wcb_glfw); } + WCB_ATTACH("glfw", wcb_glfw); #endif /* GLAVA_GLFW */ diff --git a/glx_wcb.c b/glx_wcb.c index bc6b950..4600ce1 100644 --- a/glx_wcb.c +++ b/glx_wcb.c @@ -253,7 +253,8 @@ static void* create_and_bind(const char* name, const char* class, size_t states_sz, int d, int h, int x, int y, - int version_major, int version_minor) { + int version_major, int version_minor, + bool clickthrough) { struct glxwin* w = malloc(sizeof(struct glxwin)); w->time = 0.0D; w->should_close = false; @@ -323,7 +324,7 @@ static void* create_and_bind(const char* name, const char* class, attr.background_pixmap = None; attr.border_pixel = 0; - if (!(w->w = XCreateWindow(display, *xwin_get_desktop_layer(&wcb_glx), + if (!(w->w = XCreateWindow(display, DefaultRootWindow(display)/**xwin_get_desktop_layer(&wcb_glx)*/, x, y, d, h, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel, @@ -356,10 +357,8 @@ static void* create_and_bind(const char* name, const char* class, XSetWMProtocols(display, w->w, &ATOM_WM_DELETE_WINDOW, 1); - // XReparentWindow(display, w->w, DefaultRootWindow(display), 0, 0); - /* Eliminate the window's effective region */ - if (desktop){ + if (desktop || clickthrough) { int ignored; if (XShapeQueryExtension(display, &ignored, &ignored)) { Region region; @@ -487,6 +486,8 @@ static void set_time (struct glxwin* w, double time) { w->time = get_t static Display* get_x11_display(struct glxwin* w) { return display; } static Window get_x11_window (struct glxwin* w) { return w->w; } +static const char* get_environment(void) { return xwin_detect_wm(&wcb_glx); } + WCB_ATTACH("glx", wcb_glx); #endif /* GLAVA_GLX */ diff --git a/render.c b/render.c index c66c1ce..bdcf793 100644 --- a/render.c +++ b/render.c @@ -109,7 +109,8 @@ struct gl_data { double tcounter; int fcounter, ucounter, kcounter; bool print_fps, avg_window, interpolate, force_geometry, force_raised, - copy_desktop, smooth_pass, premultiply_alpha, check_fullscreen; + copy_desktop, smooth_pass, premultiply_alpha, check_fullscreen, + clickthrough; void** t_data; float gravity_step, target_spu, fr, ur, smooth_distance, smooth_ratio, smooth_factor, fft_scale, fft_cutoff; @@ -680,7 +681,8 @@ static struct gl_bind_src* lookup_bind_src(const char* str) { } struct renderer* rd_new(const char** paths, const char* entry, - const char* force_mod, const char* force_backend) { + const char* force_mod, const char* force_backend, + bool auto_desktop) { xwin_wait_for_wm(); @@ -727,7 +729,8 @@ struct renderer* rd_new(const char** paths, const char* entry, .fft_scale = 10.2F, .fft_cutoff = 0.3F, .geometry = { 0, 0, 500, 400 }, - .clear_color = { 0.0F, 0.0F, 0.0F, 0.0F } + .clear_color = { 0.0F, 0.0F, 0.0F, 0.0F }, + .clickthrough = false }; bool forced = force_backend != NULL; @@ -791,7 +794,7 @@ struct renderer* rd_new(const char** paths, const char* entry, char* xwintype = NULL, * wintitle = "GLava"; char** xwinstates = malloc(1); size_t xwinstates_sz = 0; - bool loading_module = true, loading_smooth_pass = false; + bool loading_module = true, loading_smooth_pass = false, loading_presets = false;; struct gl_sfbo* current = NULL; size_t t_count = 0; @@ -858,7 +861,7 @@ struct renderer* rd_new(const char** paths, const char* entry, .handler = RHANDLER(name, args, { if (loading_module && !force_mod) { size_t len = strlen((char*) args[0]); - char* str = malloc(sizeof(char) * (strlen((char*) args[0]) + 1)); + char* str = malloc(sizeof(char) * (len + 1)); strncpy(str, (char*) args[0], len + 1); module = str; } @@ -898,14 +901,18 @@ struct renderer* rd_new(const char** paths, const char* entry, { .name = "addxwinstate", .fmt = "s", .handler = RHANDLER(name, args, { - ++xwinstates_sz; - xwinstates = realloc(xwinstates, sizeof(*xwinstates) * xwinstates_sz); - xwinstates[xwinstates_sz - 1] = strdup((char*) args[0]); + if (!auto_desktop || loading_presets) { + ++xwinstates_sz; + xwinstates = realloc(xwinstates, sizeof(*xwinstates) * xwinstates_sz); + xwinstates[xwinstates_sz - 1] = strdup((char*) args[0]); + } }) }, { .name = "setsource", .fmt = "s", .handler = RHANDLER(name, args, { r->audio_source_request = strdup((char*) args[0]); }) }, + { .name = "setclickthrough", .fmt = "b", + .handler = RHANDLER(name, args, { gl->clickthrough = *(bool*) args[0]; }) }, { .name = "setforcegeometry", .fmt = "b", .handler = RHANDLER(name, args, { gl->force_geometry = *(bool*) args[0]; }) }, { .name = "setforceraised", .fmt = "b", @@ -1038,12 +1045,18 @@ struct renderer* rd_new(const char** paths, const char* entry, directories will be populated with symlinks to the installed modules. */ const char* data; - size_t d_len; + const char* env = gl->wcb->get_environment(); + size_t d_len, e_len; for (const char** i = paths; (data = *i) != NULL; ++i) { d_len = strlen(data); + e_len = env ? strlen(env) : 0; size_t se_len = strlen(entry); - size_t bsz = se_len + d_len + 2; + /* '/' + \0 + "env_" + ".glsl" = 11 char padding, min 7 for "default" */ + size_t bsz = se_len + 11; + if (d_len > e_len && d_len >= 7) bsz += d_len; + else if (e_len >= 7) bsz += e_len; + else bsz += 7; char se_buf[bsz]; snprintf(se_buf, bsz, "%s/%s", data, entry); @@ -1055,7 +1068,7 @@ struct renderer* rd_new(const char** paths, const char* entry, if (errno != ENOENT && errno != ENOTDIR && errno != ELOOP ) { - fprintf(stderr, "failed to load entry '%s': %s\n", se_buf, strerror(errno)); + fprintf(stderr, "Failed to load entry '%s': %s\n", se_buf, strerror(errno)); exit(EXIT_FAILURE); } else continue; } @@ -1073,6 +1086,42 @@ struct renderer* rd_new(const char** paths, const char* entry, ext_process(&ext, se_buf); munmap((void*) map, st.st_size); + + if (auto_desktop) { + if (env) { + snprintf(se_buf, bsz, "%s/env_%s.glsl", data, env); + fd = open(se_buf, O_RDONLY); + if (fd == -1) { + if (errno != ENOENT && + errno != ENOTDIR && + errno != ELOOP) { + fprintf(stderr, "Failed to load desktop environment specific presets at '%s': %s\n", se_buf, strerror(errno)); + exit(EXIT_FAILURE); + } else { + printf("No presets for current desktop environment (\"%s\"), using default presets for embedding\n", env); + snprintf(se_buf, bsz, "%s/env_default.glsl", data); + fd = open(se_buf, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Failed to load default presets at '%s': %s\n", se_buf, strerror(errno)); + exit(EXIT_FAILURE); + } + } + } + fstat(fd, &st); + map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + + ext.source = map; + ext.source_len = st.st_size; + + loading_presets = true; + ext_process(&ext, se_buf); + loading_presets = false; + + munmap((void*) map, st.st_size); + } else { + fprintf(stderr, "Failed to detect the desktop environment! Is the window manager EWMH compliant?"); + } + } break; } @@ -1085,13 +1134,10 @@ struct renderer* rd_new(const char** paths, const char* entry, exit(EXIT_FAILURE); } - if (!(gl->w = gl->wcb->create_and_bind(wintitle, "GLava", xwintype, - (const char**) xwinstates, xwinstates_sz, - gl->geometry[2], gl->geometry[3], - gl->geometry[0], gl->geometry[1], - context_version_major, context_version_minor))) { - abort(); - } + gl->w = gl->wcb->create_and_bind(wintitle, "GLava", xwintype, (const char**) xwinstates, xwinstates_sz, + gl->geometry[2], gl->geometry[3], gl->geometry[0], gl->geometry[1], + context_version_major, context_version_minor, gl->clickthrough); + if (!gl->w) abort(); if (xwintype) free(xwintype); if (xwinstates) free(xwinstates); diff --git a/render.h b/render.h index dee849b..1b4821b 100644 --- a/render.h +++ b/render.h @@ -12,7 +12,8 @@ typedef struct renderer { } renderer; struct renderer* rd_new (const char** paths, const char* entry, - const char* force_mod, const char* force_backend); + const char* force_mod, const char* force_backend, + bool auto_desktop); bool rd_update (struct renderer*, float* lb, float* rb, size_t bsz, bool modified); void rd_destroy (struct renderer*); @@ -29,7 +30,8 @@ struct gl_wcb { size_t states_sz, int w, int h, int x, int y, - int version_major, int version_minor); + int version_major, int version_minor, + bool clickthrough); bool (*should_close) (void* ptr); void (*swap_buffers) (void* ptr); void (*raise) (void* ptr); @@ -45,6 +47,7 @@ struct gl_wcb { double (*get_time) (void* ptr); void (*set_time) (void* ptr, double time); void (*set_visible) (void* ptr, bool visible); + const char* (*get_environment) (void); #ifdef GLAVA_RDX11 Display* (*get_x11_display)(void); Window (*get_x11_window) (void* ptr); @@ -77,6 +80,7 @@ struct gl_wcb { WCB_FUNC(set_time), \ WCB_FUNC(get_time), \ WCB_FUNC(set_visible), \ + WCB_FUNC(get_environment), \ WCB_FUNC(get_x11_display), \ WCB_FUNC(get_x11_window) \ } diff --git a/shaders/env_KWin.glsl b/shaders/env_KWin.glsl new file mode 100644 index 0000000..aa168ba --- /dev/null +++ b/shaders/env_KWin.glsl @@ -0,0 +1,8 @@ +#request setdecorated false +#request setxwintype "normal" +#request addxwinstate "below" +#request addxwinstate "skip_taskbar" +#request addxwinstate "skip_pager" +#request addxwinstate "pinned" +#request setclickthrough true + diff --git a/shaders/env_Openbox.glsl b/shaders/env_Openbox.glsl new file mode 100644 index 0000000..c95c616 --- /dev/null +++ b/shaders/env_Openbox.glsl @@ -0,0 +1,2 @@ +#request setxwintype "desktop" +#request addxwinstate "pinned" diff --git a/shaders/env_Xfwm4.glsl b/shaders/env_Xfwm4.glsl new file mode 100644 index 0000000..1c20359 --- /dev/null +++ b/shaders/env_Xfwm4.glsl @@ -0,0 +1,3 @@ +#request setxwintype "desktop" +#request addxwinstate "pinned" +#request addxwinstate "below" diff --git a/shaders/env_awesome.glsl b/shaders/env_awesome.glsl new file mode 100644 index 0000000..c95c616 --- /dev/null +++ b/shaders/env_awesome.glsl @@ -0,0 +1,2 @@ +#request setxwintype "desktop" +#request addxwinstate "pinned" diff --git a/shaders/env_default.glsl b/shaders/env_default.glsl new file mode 100644 index 0000000..90336cc --- /dev/null +++ b/shaders/env_default.glsl @@ -0,0 +1 @@ +#request setxwintype "desktop" diff --git a/shaders/rc.glsl b/shaders/rc.glsl index bfc6866..ca4d0e8 100644 --- a/shaders/rc.glsl +++ b/shaders/rc.glsl @@ -21,15 +21,6 @@ #request setfocused false #request setmaximized false -/* Force window geometry (locking the window in place), useful - for some pesky WMs that try to reposition the window when - 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 @@ -70,10 +61,7 @@ This will set _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_(TYPE), where (TYPE) is the one of the window types listed (after being - converted to uppercase). More information can be found at: - - https://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317606816 -*/ + converted to uppercase). */ #request setxwintype "normal" /* (X11 only) EWMH Window state atoms (multiple can be specified). @@ -98,6 +86,12 @@ // #request addxwinstate "above" // #request addxwinstate "pinned" +/* (X11 only) Use the XShape extension to support clicking through + the GLava window. Useful when you want to interact with other + desktop windows (icons, menus, desktop shells). Enabled by + default when GLava itself is a desktop window. */ +#request setclickthrough false + /* PulseAudio source. Can be a number or a name of an audio sink or device to record from. Set to "auto" to use the default output device. */ @@ -189,6 +183,21 @@ value unless you have a strange PulseAudio configuration. */ #request setsamplerate 22050 +/* ** DEPRECATED ** + Force window geometry (locking the window in place), useful + for some pesky WMs that try to reposition the window when + embedding in the desktop. + + This routinely sends X11 events and should be avoided. */ +#request setforcegeometry false + +/* ** DEPRECATED ** + Force window to be raised (focused in some WMs), useful for + WMs that have their own stacking order for desktop windows. + + This routinely sends X11 events and should be avoided. */ +#request setforceraised false + /* ** DEPRECATED ** Scale down the audio buffer before any operations are performed on the data. Higher values are faster. diff --git a/xwin.c b/xwin.c index 4b6c271..f2c9fd4 100644 --- a/xwin.c +++ b/xwin.c @@ -25,6 +25,7 @@ #include "render.h" #include "xwin.h" +/* Note: currently unused */ Window* xwin_get_desktop_layer(struct gl_wcb* wcb) { static Window desktop; static bool searched = false; @@ -102,6 +103,44 @@ void xwin_wait_for_wm(void) { XCloseDisplay(d); } +const char* xwin_detect_wm(struct gl_wcb* wcb) { + Display* d = wcb->get_x11_display(); + Atom check = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", false); + Atom name = XInternAtom(d, "_NET_WM_NAME", false); + Atom type = XInternAtom(d, "UTF8_STRING", false); + union { + Atom a; + int i; + long unsigned int lui; + } ignored; + + unsigned long nitems = 0; + unsigned char* wm_name = NULL; + Window* wm_check; + if (Success != XGetWindowProperty(d, DefaultRootWindow(d), check, 0, 1024, false, XA_WINDOW, + &ignored.a, &ignored.i, &nitems, &ignored.lui, (unsigned char**) &wm_check)) { + return NULL; + } + + if (nitems > 0 && Success == XGetWindowProperty(d, *wm_check, name, 0, 1024, false, type, + &ignored.a, &ignored.i, &nitems, &ignored.lui, &wm_name)) { + if (nitems > 0) { + static const char* wm_name_store = NULL; + if (wm_name_store) XFree((unsigned char*) wm_name_store); + wm_name_store = (const char*) wm_name; + } else { + XFree(wm_name); + wm_name = NULL; + } + } + + XFree(wm_check); + printf("wm_name: \"%s\"\n", wm_name); + + return (const char*) wm_name; + +} + bool xwin_should_render(struct renderer* rd) { bool ret = true, should_close = false; Display* d = rd_get_wcb(rd)->get_x11_display(); diff --git a/xwin.h b/xwin.h index 2540f9d..7e8f01b 100644 --- a/xwin.h +++ b/xwin.h @@ -13,5 +13,6 @@ 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); +const char* xwin_detect_wm(struct gl_wcb* wcb); #endif