From f50998c880851c8f3e787865c98285930c3c1839 Mon Sep 17 00:00:00 2001 From: Nicholas Parker Date: Sat, 22 Oct 2011 00:59:50 -0700 Subject: [PATCH] instead of all that margin math to get the window's exterior dimensions, lets just go by the parent dimensions --- src/window.cpp | 127 ++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index c5ba624..c75d502 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -54,89 +54,96 @@ namespace { } } + void print_window(Display* disp, Window win) { + if (!config::debug_enabled) { return; } + Window root; + int x, y; + unsigned int width, height, border, depth; + if (XGetGeometry(disp, win, &root, &x, &y, &width, + &height, &border, &depth) == 0) { + ERROR_DIR("get geometry failed"); + return; + } + DEBUG(" %dx %dy %uw %uh %ub", x, y, width, height, border); + } + bool get_window_size(Display* disp, Window win, ActiveWindow::Dimensions* out_exterior = NULL, unsigned int* out_margin_width = NULL, unsigned int* out_margin_height = NULL) { - unsigned int margin_width, margin_height; + Window root; + unsigned int internal_width, internal_height; { - size_t count = 0; - unsigned int* widths; - if (!(widths = (unsigned int*)x11_util::get_property(disp, win, - XA_CARDINAL, "_NET_FRAME_EXTENTS", &count))) { - //apparently fails with eg chrome, so just assume 0 and move on - //(yet chrome oddly works fine with unmaximize_unshade_window()) - DEBUG_DIR("get frame extents failed, assuming extents = 0"); - margin_width = margin_height = 0; - } else { - if (count != 4) { - ERROR("got size %lu, want %lu", count, 4); - x11_util::free_property(widths); - return false; - } - margin_width = widths[0] + widths[1];//left, right - margin_height = widths[2] + widths[3];//top, bottom - DEBUG("extents: width%u height%u", - margin_width, margin_height); - x11_util::free_property(widths); + /* first, get the interior width/height from this window + (so that we can calculate margins) */ + int x, y; + unsigned int border, depth; + if (XGetGeometry(disp, win, &root, &x, &y, &internal_width, + &internal_height, &border, &depth) == 0) { + ERROR_DIR("get geometry failed"); + return false; } } - //_NET_EXTENTS doesnt include window decoration (titlebar etc), get that here: + if (win == root) { + ERROR_DIR("this window is root! treating this as an error."); + return false; + } - long exterior_x, exterior_y; - unsigned int interior_width, interior_height; - Window rootwin; + /* now traverse up the parents until we reach the one JUST BEFORE root, + and get the external width/height and x/y from that. */ + Window just_before_root; { - unsigned int color_depth, border; - int margin_left_tmp, margin_top_tmp; - if (XGetGeometry(disp, win, &rootwin, &margin_left_tmp, &margin_top_tmp, - &interior_width, &interior_height, - &border, &color_depth) == 0) { - ERROR_DIR("get geometry failed"); - return false; - } - - //also get window coords (given as internal, subtract XGetGeo to get external) + int count = 1; + Window parent = win; + Window* children; + unsigned int children_count; + do { + just_before_root = parent; + if (XQueryTree(disp, just_before_root, &root, + &parent, &children, &children_count) == 0) { + ERROR_DIR("get query tree failed"); + return false; + } + if (children != NULL) { + XFree(children); + } + DEBUG("%d window=%lu, parent=%lu, root=%lu", + count, just_before_root, parent, root); + print_window(disp, just_before_root); + } while (++count < 50 && parent != root); + } - int interior_x, interior_y; - if (XTranslateCoordinates(disp, win, rootwin, 0, 0, - &interior_x, &interior_y, &rootwin) == 0) { - ERROR_DIR("coordinate transform failed"); + int x, y; + unsigned int external_width, external_height; + { + unsigned int border, depth; + if (XGetGeometry(disp, just_before_root, &root, &x, &y, &external_width, + &external_height, &border, &depth) == 0) { + ERROR_DIR("get geometry failed"); return false; } - - //only use XGetGeo margins when calculating exterior position: - exterior_x = interior_x - margin_left_tmp - border; - exterior_y = interior_y - margin_top_tmp - border; - DEBUG("pos: interior %ldx %ldy - geomargins %dw %dh %ub = exterior %ldx %ldy", - interior_x, interior_y, - margin_left_tmp, margin_top_tmp, border, - exterior_x, exterior_y); - - //but use BOTH XGetGeo AND _NET_EXTENTS in calculating overall margin: - margin_width += margin_left_tmp + border + border; - margin_height += margin_top_tmp + border + border; } if (out_exterior != NULL) { - out_exterior->x = exterior_x; - out_exterior->y = exterior_y; - out_exterior->width = interior_width + margin_width; - out_exterior->height = interior_height + margin_height; + out_exterior->x = x; + out_exterior->y = y; + out_exterior->width = external_width; + out_exterior->height = external_height; } if (out_margin_width != NULL) { - *out_margin_width = margin_width; + *out_margin_width = external_width - internal_width; } if (out_margin_height != NULL) { - *out_margin_height = margin_height; + *out_margin_height = external_height - internal_height; } - DEBUG("size: interior %luw %luh + summargins %dw %dh = %uw %uh", - interior_width, interior_height, margin_width, margin_height, - interior_width + margin_width, interior_height + margin_height); - + DEBUG("size: exterior %uw %uh - interior %uw %uh = margins %dw %dh", + external_width, external_height, + internal_width, internal_height, + external_width - internal_width, + external_height - internal_height); return true; } -- 2.45.2