From cbebe447078e28c50957d568303f42d6b8aae126 Mon Sep 17 00:00:00 2001 From: Tin Date: Fri, 10 Nov 2023 21:25:45 +0100 Subject: [PATCH] Fix DependentOptions splitting arguments on spaces Fix broken x11.cc Signed-off-by: Tin --- cmake/ConkyBuildOptions.cmake | 20 +- cmake/DependentOption.cmake | 52 +- src/x11.cc | 1239 ++++++++++++++++----------------- 3 files changed, 664 insertions(+), 647 deletions(-) diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index 97c6eba8..d82db150 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -109,8 +109,9 @@ cmake_dependent_option(BUILD_HDDTEMP "Support for hddtemp" true cmake_dependent_option(BUILD_IPV6 "Enable if you want IPv6 support" true "OS_LINUX" false) # nvidia may also work on FreeBSD, not sure -cmake_dependent_option(BUILD_NVIDIA "Enable nvidia support" false - "OS_LINUX" false) +dependent_option(BUILD_NVIDIA "Enable Nvidia stat support on Linux" false + "OS_LINUX;BUILD_X11" false + "Nvidia stat supports only Linux and requires X11") # macOS Only cmake_dependent_option( @@ -165,6 +166,9 @@ else() "Xfixes support requires X11") endif(OS_DARWIN) +dependent_option(BUILD_ARGB "Build ARGB (real transparency) support" true + "OWN_WINDOW" false + "ARGB support requires OWN_WINDOW enabled") dependent_option(BUILD_XINERAMA "Build Xinerama support" true "BUILD_X11" false "Xinerama support requires X11") @@ -180,6 +184,9 @@ dependent_option(BUILD_IMLIB2 "Enable Imlib2 support" true dependent_option(BUILD_XSHAPE "Enable Xshape support" true "BUILD_X11" false "Xshape support requires X11") +dependent_option(BUILD_XINPUT "Build Xinput 2 support" true + "BUILD_X11;BUILD_MOUSE_EVENTS" false + "Xinput 2 support requires X11 and BUILD_MOUSE_EVENTS enabled") # if we build with any GUI support if(BUILD_X11) @@ -192,13 +199,6 @@ endif(BUILD_WAYLAND) dependent_option(BUILD_MOUSE_EVENTS "Enable mouse event support" true "BUILD_WAYLAND OR OWN_WINDOW" false "Mouse event support requires Wayland or OWN_WINDOW enabled") -dependent_option(BUILD_XINPUT "Build Xinput 2 support" true - "BUILD_X11;BUILD_MOUSE_EVENTS" false - "Xinput 2 support requires X11 and BUILD_MOUSE_EVENTS enabled") - -dependent_option(BUILD_ARGB "Build ARGB (real transparency) support" true - "OWN_WINDOW" false - "ARGB support requires OWN_WINDOW enabled") # Lua library options option(BUILD_LUA_CAIRO "Build cairo bindings for Lua" false) @@ -247,6 +247,8 @@ option(BUILD_PULSEAUDIO option(BUILD_INTEL_BACKLIGHT "Enable support for Intel backlight" false) +run_dependency_checks() + message(STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS}) message(STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS}) diff --git a/cmake/DependentOption.cmake b/cmake/DependentOption.cmake index bd651d04..e5044f93 100644 --- a/cmake/DependentOption.cmake +++ b/cmake/DependentOption.cmake @@ -9,28 +9,52 @@ https://github.com/Kitware/CMake/blob/master/Modules/CMakeDependentOption.cmake Modified to so it produces warnings instead of hiding an option completely and sets a default value. +Difference is that `depends` argument is ALWAYS a semicolon separated list of + tokens. Argument meaning and order are the same, and there's an additional (warn) argument which is the message printed if the end-user enabled a feature which isn't "possible". + +Actual checks are deferred until RUN_DEPENDENCY_CHECKS() is called in order to +allow out of order declaration of dependencies and dependecy graph cycles. +As the checks can affect each other they're run in a loop until the graph settles. +That means CMake can end up in an infinite loop, though it shouldn't happen with +normal use... (i.e. disable A if B not present) #]=======================================================================] +set(__DEPENDENT_OPTIONS_CHANGE_HAPPENED true) +set(__DEPENDENT_OPTIONS_LATER_INVOKED_CODE "") + macro(DEPENDENT_OPTION option doc default depends else warn) - set(${option}_POSSIBLE 1) - foreach(d ${depends}) - cmake_language(EVAL CODE " - if (${d}) + option(${option} "${doc}" "${default}") + + string(APPEND __DEPENDENT_OPTIONS_LATER_INVOKED_CODE " + set(${option}_POSSIBLE 1) + string(REGEX MATCHALL \"[^;]+\" __${option}_TOKENS \"${depends}\") + foreach(it \${__${option}_TOKENS}) + cmake_language(EVAL CODE \" + if (\${it}) else() set(${option}_POSSIBLE 0) - endif()" - ) - endforeach() - option(${option} "${doc}" "${default}") - if(NOT ${option}_POSSIBLE) - if(NOT ${option} MATCHES ${else}) - message(NOTICE "${warn}; setting to '${else}'.") + endif()\") + endforeach() + unset(__${option}_TOKENS) + if(NOT ${option}_POSSIBLE) + if(NOT \"\${${option}}\" STREQUAL \"${else}\") + message(NOTICE \"${warn}; setting to '${else}'.\") + set(${option} ${else} CACHE BOOL \"${doc}\" FORCE) + set(__DEPENDENT_OPTIONS_CHANGE_HAPPENED true) + endif() endif() - set(${option} ${else} CACHE BOOL "${doc}" FORCE) - endif() - unset(${option}_POSSIBLE) + unset(${option}_POSSIBLE)") endmacro() + +macro(RUN_DEPENDENCY_CHECKS) + while(__DEPENDENT_OPTIONS_CHANGE_HAPPENED) + set(__DEPENDENT_OPTIONS_CHANGE_HAPPENED false) + cmake_language(EVAL CODE "${__DEPENDENT_OPTIONS_LATER_INVOKED_CODE}") + endwhile() + set(__DEPENDENT_OPTIONS_CHANGE_HAPPENED true) + set(__DEPENDENT_OPTIONS_LATER_INVOKED_CODE "") +endmacro() \ No newline at end of file diff --git a/src/x11.cc b/src/x11.cc index 39e5ff7d..b2b913c5 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -93,7 +93,7 @@ xcb_errors_context_t *xcb_errors_ctx; struct conky_x11_window window; #ifdef BUILD_ARGB -bool have_argb_visual = false; +bool have_argb_visual; #endif /* BUILD_ARGB */ conky::simple_config_setting display_name("display", std::string(), @@ -696,603 +696,595 @@ void x11_init_window(lua::state &l, bool own) { attrs.colormap = window.colourmap; flags &= ~CWBackPixel; flags |= CWBorderPixel | CWColormap; - } else { + } #endif /* BUILD_ARGB */ - if (own_window_type.get(l) == TYPE_DOCK) { window.x = window.y = 0; } - /* Parent is root window so WM can take control */ - window.window = - XCreateWindow(display, window.root, window.x, window.y, b, b, 0, - depth, InputOutput, visual, flags, &attrs); + if (own_window_type.get(l) == TYPE_DOCK) { window.x = window.y = 0; } + /* Parent is root window so WM can take control */ + window.window = + XCreateWindow(display, window.root, window.x, window.y, b, b, 0, + depth, InputOutput, visual, flags, &attrs); - uint16_t hints = own_window_hints.get(l); + uint16_t hints = own_window_hints.get(l); - wmHint.flags = InputHint | StateHint; - /* allow decorated windows to be given input focus by WM */ - wmHint.input = TEST_HINT(hints, HINT_UNDECORATED) ? False : True; + wmHint.flags = InputHint | StateHint; + /* allow decorated windows to be given input focus by WM */ + wmHint.input = TEST_HINT(hints, HINT_UNDECORATED) ? False : True; #ifdef BUILD_XSHAPE #ifdef BUILD_XFIXES - if (own_window_type.get(l) == TYPE_UTILITY) { - XRectangle rect; - XserverRegion region = XFixesCreateRegion(display, &rect, 1); - XFixesSetWindowShapeRegion(display, window.window, ShapeInput, 0, 0, - region); - XFixesDestroyRegion(display, region); - } + if (own_window_type.get(l) == TYPE_UTILITY) { + XRectangle rect; + XserverRegion region = XFixesCreateRegion(display, &rect, 1); + XFixesSetWindowShapeRegion(display, window.window, ShapeInput, 0, 0, + region); + XFixesDestroyRegion(display, region); + } #endif /* BUILD_XFIXES */ - if (!wmHint.input) { - /* allow only decorated windows to be given mouse input */ - int major_version; - int minor_version; - if (XShapeQueryVersion(display, &major_version, &minor_version) == - 0) { - NORM_ERR("Input shapes are not supported"); - } else { - if (own_window.get(*state) && - (own_window_type.get(*state) != TYPE_NORMAL || - ((TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) != - 0))) { - XShapeCombineRectangles(display, window.window, ShapeInput, 0, 0, - nullptr, 0, ShapeSet, Unsorted); - } - } - } -#endif /* BUILD_XSHAPE */ - if (own_window_type.get(l) == TYPE_DOCK || - own_window_type.get(l) == TYPE_PANEL) { - wmHint.initial_state = WithdrawnState; + if (!wmHint.input) { + /* allow only decorated windows to be given mouse input */ + int major_version; + int minor_version; + if (XShapeQueryVersion(display, &major_version, &minor_version) == 0) { + NORM_ERR("Input shapes are not supported"); } else { - wmHint.initial_state = NormalState; - } - - XmbSetWMProperties(display, window.window, nullptr, nullptr, argv_copy, - argc_copy, nullptr, &wmHint, &classHint); - XStoreName(display, window.window, own_window_title.get(l).c_str()); - - /* Sets an empty WM_PROTOCOLS property */ - XSetWMProtocols(display, window.window, nullptr, 0); - - /* Set window type */ - if ((xa = ATOM(_NET_WM_WINDOW_TYPE)) != None) { - Atom prop; - - switch (own_window_type.get(l)) { - case TYPE_DESKTOP: - prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP); - fprintf(stderr, PACKAGE_NAME ": window type - desktop\n"); - fflush(stderr); - break; - case TYPE_DOCK: - prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); - fprintf(stderr, PACKAGE_NAME ": window type - dock\n"); - fflush(stderr); - break; - case TYPE_PANEL: - prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); - fprintf(stderr, PACKAGE_NAME ": window type - panel\n"); - fflush(stderr); - break; - case TYPE_UTILITY: - prop = ATOM(_NET_WM_WINDOW_TYPE_UTILITY); - fprintf(stderr, PACKAGE_NAME ": window type - utility\n"); - fflush(stderr); - break; - case TYPE_NORMAL: - default: - prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); - fprintf(stderr, PACKAGE_NAME ": window type - normal\n"); - fflush(stderr); - break; + if (own_window.get(*state) && + (own_window_type.get(*state) != TYPE_NORMAL || + ((TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) != + 0))) { + XShapeCombineRectangles(display, window.window, ShapeInput, 0, 0, + nullptr, 0, ShapeSet, Unsorted); } - XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeReplace, + } + } +#endif /* BUILD_XSHAPE */ + if (own_window_type.get(l) == TYPE_DOCK || + own_window_type.get(l) == TYPE_PANEL) { + wmHint.initial_state = WithdrawnState; + } else { + wmHint.initial_state = NormalState; + } + + XmbSetWMProperties(display, window.window, nullptr, nullptr, argv_copy, + argc_copy, nullptr, &wmHint, &classHint); + XStoreName(display, window.window, own_window_title.get(l).c_str()); + + /* Sets an empty WM_PROTOCOLS property */ + XSetWMProtocols(display, window.window, nullptr, 0); + + /* Set window type */ + if ((xa = ATOM(_NET_WM_WINDOW_TYPE)) != None) { + Atom prop; + + switch (own_window_type.get(l)) { + case TYPE_DESKTOP: + prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP); + fprintf(stderr, PACKAGE_NAME ": window type - desktop\n"); + fflush(stderr); + break; + case TYPE_DOCK: + prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); + fprintf(stderr, PACKAGE_NAME ": window type - dock\n"); + fflush(stderr); + break; + case TYPE_PANEL: + prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK); + fprintf(stderr, PACKAGE_NAME ": window type - panel\n"); + fflush(stderr); + break; + case TYPE_UTILITY: + prop = ATOM(_NET_WM_WINDOW_TYPE_UTILITY); + fprintf(stderr, PACKAGE_NAME ": window type - utility\n"); + fflush(stderr); + break; + case TYPE_NORMAL: + default: + prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); + fprintf(stderr, PACKAGE_NAME ": window type - normal\n"); + fflush(stderr); + break; + } + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeReplace, + reinterpret_cast(&prop), 1); + } + + /* Set desired hints */ + + /* Window decorations */ + if (TEST_HINT(hints, HINT_UNDECORATED)) { + /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n"); + fflush(stderr); */ + + xa = ATOM(_MOTIF_WM_HINTS); + if (xa != None) { + long prop[5] = {2, 0, 0, 0, 0}; + XChangeProperty(display, window.window, xa, xa, 32, PropModeReplace, + reinterpret_cast(prop), 5); + } + } + + /* Below other windows */ + if (TEST_HINT(hints, HINT_BELOW)) { + /* fprintf(stderr, PACKAGE_NAME": hint - below\n"); + fflush(stderr); */ + + xa = ATOM(_WIN_LAYER); + if (xa != None) { + long prop = 0; + + XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, + PropModeAppend, reinterpret_cast(&prop), 1); } - /* Set desired hints */ + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); - /* Window decorations */ - if (TEST_HINT(hints, HINT_UNDECORATED)) { - /* fprintf(stderr, PACKAGE_NAME": hint - undecorated\n"); - fflush(stderr); */ - - xa = ATOM(_MOTIF_WM_HINTS); - if (xa != None) { - long prop[5] = {2, 0, 0, 0, 0}; - XChangeProperty(display, window.window, xa, xa, 32, PropModeReplace, - reinterpret_cast(prop), 5); - } - } - - /* Below other windows */ - if (TEST_HINT(hints, HINT_BELOW)) { - /* fprintf(stderr, PACKAGE_NAME": hint - below\n"); - fflush(stderr); */ - - xa = ATOM(_WIN_LAYER); - if (xa != None) { - long prop = 0; - - XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, - PropModeAppend, - reinterpret_cast(&prop), 1); - } - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); - - XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, - reinterpret_cast(&xa_prop), 1); - } - } - - /* Above other windows */ - if (TEST_HINT(hints, HINT_ABOVE)) { - /* fprintf(stderr, PACKAGE_NAME": hint - above\n"); - fflush(stderr); */ - - xa = ATOM(_WIN_LAYER); - if (xa != None) { - long prop = 6; - - XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, - PropModeAppend, - reinterpret_cast(&prop), 1); - } - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); - - XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, - reinterpret_cast(&xa_prop), 1); - } - } - - /* Sticky */ - if (TEST_HINT(hints, HINT_STICKY)) { - /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n"); - fflush(stderr); */ - - xa = ATOM(_NET_WM_DESKTOP); - if (xa != None) { - CARD32 xa_prop = 0xFFFFFFFF; - - XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, - PropModeAppend, - reinterpret_cast(&xa_prop), 1); - } - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); - - XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, - reinterpret_cast(&xa_prop), 1); - } - } - - /* Skip taskbar */ - if (TEST_HINT(hints, HINT_SKIP_TASKBAR)) { - /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n"); - fflush(stderr); */ - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR); - - XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, - reinterpret_cast(&xa_prop), 1); - } - } - - /* Skip pager */ - if (TEST_HINT(hints, HINT_SKIP_PAGER)) { - /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n"); - fflush(stderr); */ - - xa = ATOM(_NET_WM_STATE); - if (xa != None) { - Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER); - - XChangeProperty(display, window.window, xa, XA_ATOM, 32, - PropModeAppend, - reinterpret_cast(&xa_prop), 1); - } + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, + reinterpret_cast(&xa_prop), 1); } } - fprintf(stderr, PACKAGE_NAME ": drawing to created window (0x%lx)\n", - window.window); - fflush(stderr); + /* Above other windows */ + if (TEST_HINT(hints, HINT_ABOVE)) { + /* fprintf(stderr, PACKAGE_NAME": hint - above\n"); + fflush(stderr); */ - XMapWindow(display, window.window); + xa = ATOM(_WIN_LAYER); + if (xa != None) { + long prop = 6; + + XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, + PropModeAppend, + reinterpret_cast(&prop), 1); + } + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, + reinterpret_cast(&xa_prop), 1); + } + } + + /* Sticky */ + if (TEST_HINT(hints, HINT_STICKY)) { + /* fprintf(stderr, PACKAGE_NAME": hint - sticky\n"); + fflush(stderr); */ + + xa = ATOM(_NET_WM_DESKTOP); + if (xa != None) { + CARD32 xa_prop = 0xFFFFFFFF; + + XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, + PropModeAppend, + reinterpret_cast(&xa_prop), 1); + } + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, + reinterpret_cast(&xa_prop), 1); + } + } + + /* Skip taskbar */ + if (TEST_HINT(hints, HINT_SKIP_TASKBAR)) { + /* fprintf(stderr, PACKAGE_NAME": hint - skip_taskbar\n"); + fflush(stderr); */ + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, + reinterpret_cast(&xa_prop), 1); + } + } + + /* Skip pager */ + if (TEST_HINT(hints, HINT_SKIP_PAGER)) { + /* fprintf(stderr, PACKAGE_NAME": hint - skip_pager\n"); + fflush(stderr); */ + + xa = ATOM(_NET_WM_STATE); + if (xa != None) { + Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER); + + XChangeProperty(display, window.window, xa, XA_ATOM, 32, + PropModeAppend, + reinterpret_cast(&xa_prop), 1); + } + } } - else + + fprintf(stderr, PACKAGE_NAME ": drawing to created window (0x%lx)\n", + window.window); + fflush(stderr); + + XMapWindow(display, window.window); + } else #endif /* OWN_WINDOW */ - { - XWindowAttributes attrs; + { + XWindowAttributes attrs; - if (window.window == 0u) { - window.window = find_desktop_window(&window.root, &window.desktop); - } - if (window.window == 0u) { - DBGP2("no root window found"); - return; - } - - window.visual = DefaultVisual(display, screen); - window.colourmap = DefaultColormap(display, screen); - - if (XGetWindowAttributes(display, window.window, &attrs) != 0) { - window.width = attrs.width; - window.height = attrs.height; - } - - fprintf(stderr, PACKAGE_NAME ": drawing to desktop window\n"); + if (window.window == 0u) { + window.window = find_desktop_window(&window.root, &window.desktop); + } + if (window.window == 0u) { + DBGP2("no root window found"); + return; } - /* Drawable is same as window. This may be changed by double buffering. */ - window.drawable = window.window; + window.visual = DefaultVisual(display, screen); + window.colourmap = DefaultColormap(display, screen); - XFlush(display); + if (XGetWindowAttributes(display, window.window, &attrs) != 0) { + window.width = attrs.width; + window.height = attrs.height; + } - int64_t input_mask = ExposureMask | PropertyChangeMask; + fprintf(stderr, PACKAGE_NAME ": drawing to desktop window\n"); + } + + /* Drawable is same as window. This may be changed by double buffering. */ + window.drawable = window.window; + + XFlush(display); + + int64_t input_mask = ExposureMask | PropertyChangeMask; #ifdef OWN_WINDOW - if (own_window.get(l)) { - input_mask |= StructureNotifyMask | ButtonPressMask | ButtonReleaseMask; - } + if (own_window.get(l)) { + input_mask |= StructureNotifyMask | ButtonPressMask | ButtonReleaseMask; + } #ifdef BUILD_MOUSE_EVENTS - /* it's not recommended to add event masks to special windows in X; causes a - * crash */ - if (own && own_window_type.get(l) != TYPE_DESKTOP) { - input_mask |= ButtonPressMask | ButtonReleaseMask; - } - bool xinput_ok = false; + /* it's not recommended to add event masks to special windows in X; causes a + * crash */ + if (own && own_window_type.get(l) != TYPE_DESKTOP) { + input_mask |= ButtonPressMask | ButtonReleaseMask; + } + bool xinput_ok = false; #ifdef BUILD_XINPUT - do { // not loop - int _ignored; // segfault if NULL - if (!XQueryExtension(display, "XInputExtension", &window.xi_opcode, - &_ignored, &_ignored)) { - // events will still ~work but let the user know why they're buggy - NORM_ERR("XInput extension is not supported by X11!"); - break; - } - - int32_t major = 2, minor = 0; - uint32_t retval = XIQueryVersion(display, &major, &minor); - if (retval != Success) { - NORM_ERR("Error: XInput 2.0 is not supported!"); - break; - } - - const size_t mask_size = (XI_LASTEVENT + 7) / 8; - unsigned char mask_bytes[mask_size] = {0}; /* must be zeroed! */ - XISetMask(mask_bytes, XI_Motion); - - XIEventMask ev_masks[1]; - ev_masks[0].deviceid = XIAllDevices; - ev_masks[0].mask_len = sizeof(mask_bytes); - ev_masks[0].mask = mask_bytes; - XISelectEvents(display, window.root, ev_masks, 1); - xinput_ok = true; - } while (false); -#endif /* BUILD_XINPUT */ - if (!xinput_ok && own && own_window_type.get(l) != TYPE_DESKTOP) { - input_mask |= PointerMotionMask | EnterWindowMask | LeaveWindowMask; + do { // not loop + int _ignored; // segfault if NULL + if (!XQueryExtension(display, "XInputExtension", &window.xi_opcode, + &_ignored, &_ignored)) { + // events will still ~work but let the user know why they're buggy + NORM_ERR("XInput extension is not supported by X11!"); + break; } + + int32_t major = 2, minor = 0; + uint32_t retval = XIQueryVersion(display, &major, &minor); + if (retval != Success) { + NORM_ERR("Error: XInput 2.0 is not supported!"); + break; + } + + const size_t mask_size = (XI_LASTEVENT + 7) / 8; + unsigned char mask_bytes[mask_size] = {0}; /* must be zeroed! */ + XISetMask(mask_bytes, XI_Motion); + + XIEventMask ev_masks[1]; + ev_masks[0].deviceid = XIAllDevices; + ev_masks[0].mask_len = sizeof(mask_bytes); + ev_masks[0].mask = mask_bytes; + XISelectEvents(display, window.root, ev_masks, 1); + xinput_ok = true; + } while (false); +#endif /* BUILD_XINPUT */ + if (!xinput_ok && own && own_window_type.get(l) != TYPE_DESKTOP) { + input_mask |= PointerMotionMask | EnterWindowMask | LeaveWindowMask; + } #endif /* BUILD_MOUSE_EVENTS */ #endif /* OWN_WINDOW */ - window.event_mask = input_mask; - XSelectInput(display, window.window, input_mask); + window.event_mask = input_mask; + XSelectInput(display, window.window, input_mask); - window_created = 1; - DBGP("leave x11_init_window()"); - } + window_created = 1; + DBGP("leave x11_init_window()"); +} - static Window find_subwindow(Window win, int w, int h) { - unsigned int i, j; - Window troot, parent, *children; - unsigned int n; +static Window find_subwindow(Window win, int w, int h) { + unsigned int i, j; + Window troot, parent, *children; + unsigned int n; - /* search subwindows with same size as display or work area */ + /* search subwindows with same size as display or work area */ - for (i = 0; i < 10; i++) { - XQueryTree(display, win, &troot, &parent, &children, &n); + for (i = 0; i < 10; i++) { + XQueryTree(display, win, &troot, &parent, &children, &n); - for (j = 0; j < n; j++) { - XWindowAttributes attrs; + for (j = 0; j < n; j++) { + XWindowAttributes attrs; - if (XGetWindowAttributes(display, children[j], &attrs) != 0) { - /* Window must be mapped and same size as display or - * work space */ - if (attrs.map_state != 0 && - ((attrs.width == display_width && - attrs.height == display_height) || - (attrs.width == w && attrs.height == h))) { - win = children[j]; - break; - } - } - } - - XFree(children); - if (j == n) { break; } - } - - return win; - } - - void create_gc() { - XGCValues values; - - values.graphics_exposures = 0; - values.function = GXcopy; - window.gc = XCreateGC(display, window.drawable, - GCFunction | GCGraphicsExposures, &values); - } - - // Get current desktop number - static inline void get_x11_desktop_current(Display * current_display, - Window root, Atom atom) { - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop = nullptr; - struct information *current_info = &info; - - if (atom == None) { return; } - - if ((XGetWindowProperty(current_display, root, atom, 0, 1L, False, - XA_CARDINAL, &actual_type, &actual_format, &nitems, - &bytes_after, &prop) == Success) && - (actual_type == XA_CARDINAL) && (nitems == 1L) && - (actual_format == 32)) { - current_info->x11.desktop.current = prop[0] + 1; - } - if (prop != nullptr) { XFree(prop); } - } - - // Get total number of available desktops - static inline void get_x11_desktop_number(Display * current_display, - Window root, Atom atom) { - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop = nullptr; - struct information *current_info = &info; - - if (atom == None) { return; } - - if ((XGetWindowProperty(current_display, root, atom, 0, 1L, False, - XA_CARDINAL, &actual_type, &actual_format, &nitems, - &bytes_after, &prop) == Success) && - (actual_type == XA_CARDINAL) && (nitems == 1L) && - (actual_format == 32)) { - current_info->x11.desktop.number = prop[0]; - } - if (prop != nullptr) { XFree(prop); } - } - - // Get all desktop names - static inline void get_x11_desktop_names(Display * current_display, - Window root, Atom atom) { - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop = nullptr; - struct information *current_info = &info; - - if (atom == None) { return; } - - if ((XGetWindowProperty(current_display, root, atom, 0, (~0L), False, - ATOM(UTF8_STRING), &actual_type, &actual_format, - &nitems, &bytes_after, &prop) == Success) && - (actual_type == ATOM(UTF8_STRING)) && (nitems > 0L) && - (actual_format == 8)) { - current_info->x11.desktop.all_names.assign( - reinterpret_cast(prop), nitems); - } - if (prop != nullptr) { XFree(prop); } - } - - // Get current desktop name - static inline void get_x11_desktop_current_name(const std::string &names) { - struct information *current_info = &info; - unsigned int i = 0, j = 0; - int k = 0; - - while (i < names.size()) { - if (names[i++] == '\0') { - if (++k == current_info->x11.desktop.current) { - current_info->x11.desktop.name.assign(names.c_str() + j); + if (XGetWindowAttributes(display, children[j], &attrs) != 0) { + /* Window must be mapped and same size as display or + * work space */ + if (attrs.map_state != 0 && + ((attrs.width == display_width && attrs.height == display_height) || + (attrs.width == w && attrs.height == h))) { + win = children[j]; break; } - j = i; } } + + XFree(children); + if (j == n) { break; } } - void get_x11_desktop_info(Display * current_display, Atom atom) { - Window root; - static Atom atom_current, atom_number, atom_names; - struct information *current_info = &info; - XWindowAttributes window_attributes; + return win; +} - root = RootWindow(current_display, current_info->x11.monitor.current); +void create_gc() { + XGCValues values; - /* Check if we initialise else retrieve changed property */ - if (atom == 0) { - atom_current = XInternAtom(current_display, "_NET_CURRENT_DESKTOP", True); - atom_number = - XInternAtom(current_display, "_NET_NUMBER_OF_DESKTOPS", True); - atom_names = XInternAtom(current_display, "_NET_DESKTOP_NAMES", True); + values.graphics_exposures = 0; + values.function = GXcopy; + window.gc = XCreateGC(display, window.drawable, + GCFunction | GCGraphicsExposures, &values); +} + +// Get current desktop number +static inline void get_x11_desktop_current(Display *current_display, + Window root, Atom atom) { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = nullptr; + struct information *current_info = &info; + + if (atom == None) { return; } + + if ((XGetWindowProperty(current_display, root, atom, 0, 1L, False, + XA_CARDINAL, &actual_type, &actual_format, &nitems, + &bytes_after, &prop) == Success) && + (actual_type == XA_CARDINAL) && (nitems == 1L) && (actual_format == 32)) { + current_info->x11.desktop.current = prop[0] + 1; + } + if (prop != nullptr) { XFree(prop); } +} + +// Get total number of available desktops +static inline void get_x11_desktop_number(Display *current_display, Window root, + Atom atom) { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = nullptr; + struct information *current_info = &info; + + if (atom == None) { return; } + + if ((XGetWindowProperty(current_display, root, atom, 0, 1L, False, + XA_CARDINAL, &actual_type, &actual_format, &nitems, + &bytes_after, &prop) == Success) && + (actual_type == XA_CARDINAL) && (nitems == 1L) && (actual_format == 32)) { + current_info->x11.desktop.number = prop[0]; + } + if (prop != nullptr) { XFree(prop); } +} + +// Get all desktop names +static inline void get_x11_desktop_names(Display *current_display, Window root, + Atom atom) { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = nullptr; + struct information *current_info = &info; + + if (atom == None) { return; } + + if ((XGetWindowProperty(current_display, root, atom, 0, (~0L), False, + ATOM(UTF8_STRING), &actual_type, &actual_format, + &nitems, &bytes_after, &prop) == Success) && + (actual_type == ATOM(UTF8_STRING)) && (nitems > 0L) && + (actual_format == 8)) { + current_info->x11.desktop.all_names.assign( + reinterpret_cast(prop), nitems); + } + if (prop != nullptr) { XFree(prop); } +} + +// Get current desktop name +static inline void get_x11_desktop_current_name(const std::string &names) { + struct information *current_info = &info; + unsigned int i = 0, j = 0; + int k = 0; + + while (i < names.size()) { + if (names[i++] == '\0') { + if (++k == current_info->x11.desktop.current) { + current_info->x11.desktop.name.assign(names.c_str() + j); + break; + } + j = i; + } + } +} + +void get_x11_desktop_info(Display *current_display, Atom atom) { + Window root; + static Atom atom_current, atom_number, atom_names; + struct information *current_info = &info; + XWindowAttributes window_attributes; + + root = RootWindow(current_display, current_info->x11.monitor.current); + + /* Check if we initialise else retrieve changed property */ + if (atom == 0) { + atom_current = XInternAtom(current_display, "_NET_CURRENT_DESKTOP", True); + atom_number = XInternAtom(current_display, "_NET_NUMBER_OF_DESKTOPS", True); + atom_names = XInternAtom(current_display, "_NET_DESKTOP_NAMES", True); + get_x11_desktop_current(current_display, root, atom_current); + get_x11_desktop_number(current_display, root, atom_number); + get_x11_desktop_names(current_display, root, atom_names); + get_x11_desktop_current_name(current_info->x11.desktop.all_names); + + /* Set the PropertyChangeMask on the root window, if not set */ + XGetWindowAttributes(display, root, &window_attributes); + if ((window_attributes.your_event_mask & PropertyChangeMask) == 0) { + XSetWindowAttributes attributes; + attributes.event_mask = + window_attributes.your_event_mask | PropertyChangeMask; + XChangeWindowAttributes(display, root, CWEventMask, &attributes); + XGetWindowAttributes(display, root, &window_attributes); + } + } else { + if (atom == atom_current) { get_x11_desktop_current(current_display, root, atom_current); + get_x11_desktop_current_name(current_info->x11.desktop.all_names); + } else if (atom == atom_number) { get_x11_desktop_number(current_display, root, atom_number); + } else if (atom == atom_names) { get_x11_desktop_names(current_display, root, atom_names); get_x11_desktop_current_name(current_info->x11.desktop.all_names); - - /* Set the PropertyChangeMask on the root window, if not set */ - XGetWindowAttributes(display, root, &window_attributes); - if ((window_attributes.your_event_mask & PropertyChangeMask) == 0) { - XSetWindowAttributes attributes; - attributes.event_mask = - window_attributes.your_event_mask | PropertyChangeMask; - XChangeWindowAttributes(display, root, CWEventMask, &attributes); - XGetWindowAttributes(display, root, &window_attributes); - } - } else { - if (atom == atom_current) { - get_x11_desktop_current(current_display, root, atom_current); - get_x11_desktop_current_name(current_info->x11.desktop.all_names); - } else if (atom == atom_number) { - get_x11_desktop_number(current_display, root, atom_number); - } else if (atom == atom_names) { - get_x11_desktop_names(current_display, root, atom_names); - get_x11_desktop_current_name(current_info->x11.desktop.all_names); - } } } +} - static const char NOT_IN_X[] = "Not running in X"; +static const char NOT_IN_X[] = "Not running in X"; - void print_monitor(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; +void print_monitor(struct text_object *obj, char *p, unsigned int p_max_size) { + (void)obj; - if (!out_to_x.get(*state)) { - strncpy(p, NOT_IN_X, p_max_size); - return; - } - snprintf(p, p_max_size, "%d", XDefaultScreen(display)); + if (!out_to_x.get(*state)) { + strncpy(p, NOT_IN_X, p_max_size); + return; } + snprintf(p, p_max_size, "%d", XDefaultScreen(display)); +} - void print_monitor_number(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - - if (!out_to_x.get(*state)) { - strncpy(p, NOT_IN_X, p_max_size); - return; - } - snprintf(p, p_max_size, "%d", XScreenCount(display)); - } - - void print_desktop(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - - if (!out_to_x.get(*state)) { - strncpy(p, NOT_IN_X, p_max_size); - return; - } - snprintf(p, p_max_size, "%d", info.x11.desktop.current); - } - - void print_desktop_number(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - - if (!out_to_x.get(*state)) { - strncpy(p, NOT_IN_X, p_max_size); - return; - } - snprintf(p, p_max_size, "%d", info.x11.desktop.number); - } - - void print_desktop_name(struct text_object * obj, char *p, +void print_monitor_number(struct text_object *obj, char *p, unsigned int p_max_size) { - (void)obj; + (void)obj; - if (!out_to_x.get(*state)) { - strncpy(p, NOT_IN_X, p_max_size); - } else { - strncpy(p, info.x11.desktop.name.c_str(), p_max_size); - } + if (!out_to_x.get(*state)) { + strncpy(p, NOT_IN_X, p_max_size); + return; } + snprintf(p, p_max_size, "%d", XScreenCount(display)); +} + +void print_desktop(struct text_object *obj, char *p, unsigned int p_max_size) { + (void)obj; + + if (!out_to_x.get(*state)) { + strncpy(p, NOT_IN_X, p_max_size); + return; + } + snprintf(p, p_max_size, "%d", info.x11.desktop.current); +} + +void print_desktop_number(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + + if (!out_to_x.get(*state)) { + strncpy(p, NOT_IN_X, p_max_size); + return; + } + snprintf(p, p_max_size, "%d", info.x11.desktop.number); +} + +void print_desktop_name(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + + if (!out_to_x.get(*state)) { + strncpy(p, NOT_IN_X, p_max_size); + } else { + strncpy(p, info.x11.desktop.name.c_str(), p_max_size); + } +} #ifdef OWN_WINDOW - /* reserve window manager space */ - void set_struts(int sidenum) { - Atom strut; - if ((strut = ATOM(_NET_WM_STRUT)) != None) { - /* reserve space at left, right, top, bottom */ - signed long sizes[12] = {0}; - int i; +/* reserve window manager space */ +void set_struts(int sidenum) { + Atom strut; + if ((strut = ATOM(_NET_WM_STRUT)) != None) { + /* reserve space at left, right, top, bottom */ + signed long sizes[12] = {0}; + int i; - /* define strut depth */ - switch (sidenum) { - case 0: - /* left side */ - sizes[0] = window.x + window.width; - break; - case 1: - /* right side */ - sizes[1] = display_width - window.x; - break; - case 2: - /* top side */ - sizes[2] = window.y + window.height; - break; - case 3: - /* bottom side */ - sizes[3] = display_height - window.y; - break; - } + /* define strut depth */ + switch (sidenum) { + case 0: + /* left side */ + sizes[0] = window.x + window.width; + break; + case 1: + /* right side */ + sizes[1] = display_width - window.x; + break; + case 2: + /* top side */ + sizes[2] = window.y + window.height; + break; + case 3: + /* bottom side */ + sizes[3] = display_height - window.y; + break; + } - /* define partial strut length */ - if (sidenum <= 1) { - sizes[4 + (sidenum * 2)] = window.y; - sizes[5 + (sidenum * 2)] = window.y + window.height; - } else if (sidenum <= 3) { - sizes[4 + (sidenum * 2)] = window.x; - sizes[5 + (sidenum * 2)] = window.x + window.width; - } + /* define partial strut length */ + if (sidenum <= 1) { + sizes[4 + (sidenum * 2)] = window.y; + sizes[5 + (sidenum * 2)] = window.y + window.height; + } else if (sidenum <= 3) { + sizes[4 + (sidenum * 2)] = window.x; + sizes[5 + (sidenum * 2)] = window.x + window.width; + } - /* check constraints */ - for (i = 0; i < 12; i++) { - if (sizes[i] < 0) { - sizes[i] = 0; + /* check constraints */ + for (i = 0; i < 12; i++) { + if (sizes[i] < 0) { + sizes[i] = 0; + } else { + if (i <= 1 || i >= 8) { + if (sizes[i] > display_width) { sizes[i] = display_width; } } else { - if (i <= 1 || i >= 8) { - if (sizes[i] > display_width) { sizes[i] = display_width; } - } else { - if (sizes[i] > display_height) { sizes[i] = display_height; } - } + if (sizes[i] > display_height) { sizes[i] = display_height; } } } + } + XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, + PropModeReplace, reinterpret_cast(&sizes), + 4); + + if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) { XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, PropModeReplace, - reinterpret_cast(&sizes), 4); - - if ((strut = ATOM(_NET_WM_STRUT_PARTIAL)) != None) { - XChangeProperty(display, window.window, strut, XA_CARDINAL, 32, - PropModeReplace, - reinterpret_cast(&sizes), 12); - } + reinterpret_cast(&sizes), 12); } } +} #endif /* OWN_WINDOW */ #ifdef BUILD_XDBE - void xdbe_swap_buffers() { - if (use_xdbe.get(*state)) { - XdbeSwapInfo swap; +void xdbe_swap_buffers() { + if (use_xdbe.get(*state)) { + XdbeSwapInfo swap; - swap.swap_window = window.window; - swap.swap_action = XdbeBackground; - XdbeSwapBuffers(display, &swap, 1); - } + swap.swap_window = window.window; + swap.swap_action = XdbeBackground; + XdbeSwapBuffers(display, &swap, 1); } +} #else void xpmdb_swap_buffers(void) { if (use_xpmdb.get(*state)) { @@ -1306,123 +1298,122 @@ void xpmdb_swap_buffers(void) { } #endif /* BUILD_XDBE */ - void print_kdb_led(const int keybit, char *p, unsigned int p_max_size) { - XKeyboardState x; - XGetKeyboardControl(display, &x); - snprintf(p, p_max_size, "%s", (x.led_mask & keybit ? "On" : "Off")); - } - void print_key_caps_lock(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - print_kdb_led(1, p, p_max_size); - } - - void print_key_num_lock(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - print_kdb_led(2, p, p_max_size); - } - - void print_key_scroll_lock(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - print_kdb_led(4, p, p_max_size); - } - - void print_keyboard_layout(struct text_object * obj, char *p, - unsigned int p_max_size) { - (void)obj; - - char *group = NULL; - XkbStateRec state; - XkbDescPtr desc; - - XkbGetState(display, XkbUseCoreKbd, &state); - desc = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd); - group = XGetAtomName(display, desc->names->groups[state.group]); - - snprintf(p, p_max_size, "%s", (group != NULL ? group : "unknown")); - XFree(group); - XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); - } - - void print_mouse_speed(struct text_object * obj, char *p, +void print_kdb_led(const int keybit, char *p, unsigned int p_max_size) { + XKeyboardState x; + XGetKeyboardControl(display, &x); + snprintf(p, p_max_size, "%s", (x.led_mask & keybit ? "On" : "Off")); +} +void print_key_caps_lock(struct text_object *obj, char *p, unsigned int p_max_size) { - (void)obj; - int acc_num = 0; - int acc_denom = 0; - int threshold = 0; + (void)obj; + print_kdb_led(1, p, p_max_size); +} - XGetPointerControl(display, &acc_num, &acc_denom, &threshold); - snprintf(p, p_max_size, "%d%%", (110 - threshold)); +void print_key_num_lock(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + print_kdb_led(2, p, p_max_size); +} + +void print_key_scroll_lock(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + print_kdb_led(4, p, p_max_size); +} + +void print_keyboard_layout(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + + char *group = NULL; + XkbStateRec state; + XkbDescPtr desc; + + XkbGetState(display, XkbUseCoreKbd, &state); + desc = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd); + group = XGetAtomName(display, desc->names->groups[state.group]); + + snprintf(p, p_max_size, "%s", (group != NULL ? group : "unknown")); + XFree(group); + XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); +} + +void print_mouse_speed(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + int acc_num = 0; + int acc_denom = 0; + int threshold = 0; + + XGetPointerControl(display, &acc_num, &acc_denom, &threshold); + snprintf(p, p_max_size, "%d%%", (110 - threshold)); +} + +InputEvent *xev_as_input_event(XEvent &ev) { + if (ev.type == KeyPress || ev.type == KeyRelease || ev.type == ButtonPress || + ev.type == ButtonRelease || ev.type == MotionNotify || + ev.type == EnterNotify || ev.type == LeaveNotify) { + return reinterpret_cast(&ev); + } else { + return nullptr; } +} - InputEvent *xev_as_input_event(XEvent & ev) { - if (ev.type == KeyPress || ev.type == KeyRelease || - ev.type == ButtonPress || ev.type == ButtonRelease || - ev.type == MotionNotify || ev.type == EnterNotify || - ev.type == LeaveNotify) { - return reinterpret_cast(&ev); - } else { - return nullptr; - } +void propagate_x11_event(XEvent &ev) { + InputEvent *i_ev = xev_as_input_event(ev); + /* forward the event to the desktop window */ + if (i_ev != nullptr) { + i_ev->common.window = window.desktop; + i_ev->common.x = i_ev->common.x_root; + i_ev->common.y = i_ev->common.y_root; } + XSendEvent(display, window.desktop, False, window.event_mask, &ev); - void propagate_x11_event(XEvent & ev) { - InputEvent *i_ev = xev_as_input_event(ev); - /* forward the event to the desktop window */ - if (i_ev != nullptr) { - i_ev->common.window = window.desktop; - i_ev->common.x = i_ev->common.x_root; - i_ev->common.y = i_ev->common.y_root; - } - XSendEvent(display, window.desktop, False, window.event_mask, &ev); - - int _revert_to; - Window focused; - XGetInputFocus(display, &focused, &_revert_to); - if (focused == window.window) { - Time time = CurrentTime; - if (i_ev != nullptr) { time = i_ev->common.time; } - XSetInputFocus(display, window.desktop, RevertToPointerRoot, time); - } + int _revert_to; + Window focused; + XGetInputFocus(display, &focused, &_revert_to); + if (focused == window.window) { + Time time = CurrentTime; + if (i_ev != nullptr) { time = i_ev->common.time; } + XSetInputFocus(display, window.desktop, RevertToPointerRoot, time); } +} #ifdef BUILD_MOUSE_EVENTS - // Assuming parent has a simple linear stack of descendants, this function - // returns the last leaf on the graph. - inline Window last_descendant(Display * display, Window parent) { - Window _ignored, *children; - uint32_t count; +// Assuming parent has a simple linear stack of descendants, this function +// returns the last leaf on the graph. +inline Window last_descendant(Display *display, Window parent) { + Window _ignored, *children; + uint32_t count; - Window current = parent; + Window current = parent; - while ( - XQueryTree(display, current, &_ignored, &_ignored, &children, &count) && - count != 0) { - current = children[count - 1]; - XFree(children); - } - - return current; + while ( + XQueryTree(display, current, &_ignored, &_ignored, &children, &count) && + count != 0) { + current = children[count - 1]; + XFree(children); } - Window query_x11_window_at_pos(Display * display, int x, int y) { - Window root = DefaultRootWindow(display); + return current; +} - // these values are ignored but NULL can't be passed - Window root_return; - int root_x_return, root_y_return, win_x_return, win_y_return; - unsigned int mask_return; +Window query_x11_window_at_pos(Display *display, int x, int y) { + Window root = DefaultRootWindow(display); - Window last = None; - XQueryPointer(display, window.root, &root_return, &last, &root_x_return, - &root_y_return, &win_x_return, &win_y_return, &mask_return); + // these values are ignored but NULL can't be passed + Window root_return; + int root_x_return, root_y_return, win_x_return, win_y_return; + unsigned int mask_return; - // X11 correctly returns a window which covers conky area, but returned - // window is not window.window, but instead a parent node in some cases and - // the window.window we want to check for is a 1x1 child of that window. - return last_descendant(display, last); - } + Window last = None; + XQueryPointer(display, window.root, &root_return, &last, &root_x_return, + &root_y_return, &win_x_return, &win_y_return, &mask_return); + + // X11 correctly returns a window which covers conky area, but returned + // window is not window.window, but instead a parent node in some cases and + // the window.window we want to check for is a 1x1 child of that window. + return last_descendant(display, last); +} #endif /* BUILD_MOUSE_EVENTS */