///////////////////////////////////////////////////////
| 892 | |
| 893 | //////////////////////////////////////////////////////////// |
| 894 | Vector2i WindowImplX11::getPosition() const |
| 895 | { |
| 896 | using namespace WindowImplX11Impl; |
| 897 | |
| 898 | // Get absolute position of our window relative to root window. This |
| 899 | // takes into account all information that X11 has, including X11 |
| 900 | // border widths and any decorations. It corresponds to where the |
| 901 | // window actually is, but not necessarily to where we told it to |
| 902 | // go using setPosition() and XMoveWindow(). To have the two match |
| 903 | // as expected, we may have to subtract decorations and borders. |
| 904 | ::Window child = 0; |
| 905 | int xAbsRelToRoot = 0; |
| 906 | int yAbsRelToRoot = 0; |
| 907 | |
| 908 | XTranslateCoordinates(m_display.get(), m_window, DefaultRootWindow(m_display.get()), 0, 0, &xAbsRelToRoot, &yAbsRelToRoot, &child); |
| 909 | |
| 910 | // CASE 1: some rare WMs actually put the window exactly where we tell |
| 911 | // it to, even with decorations and such, which get shifted back. |
| 912 | // In these rare cases, we can use the absolute value directly. |
| 913 | if (isWMAbsolutePositionGood()) |
| 914 | return {xAbsRelToRoot, yAbsRelToRoot}; |
| 915 | |
| 916 | // CASE 2: most modern WMs support EWMH and can define _NET_FRAME_EXTENTS |
| 917 | // with the exact frame size to subtract, so if present, we prefer it and |
| 918 | // query it first. According to spec, this already includes any borders. |
| 919 | long xFrameExtent = 0; |
| 920 | long yFrameExtent = 0; |
| 921 | |
| 922 | if (getEWMHFrameExtents(m_display.get(), m_window, xFrameExtent, yFrameExtent)) |
| 923 | { |
| 924 | // Get final X/Y coordinates: subtract EWMH frame extents from |
| 925 | // absolute window position. |
| 926 | return {(xAbsRelToRoot - static_cast<int>(xFrameExtent)), (yAbsRelToRoot - static_cast<int>(yFrameExtent))}; |
| 927 | } |
| 928 | |
| 929 | // CASE 3: EWMH frame extents were not available, use geometry. |
| 930 | // We climb back up to the window before the root and use its |
| 931 | // geometry information to extract X/Y position. This because |
| 932 | // re-parenting WMs may re-parent the window multiple times, so |
| 933 | // we'd have to climb up to the furthest ancestor and sum the |
| 934 | // relative differences and borders anyway; and doing that to |
| 935 | // subtract those values from the absolute coordinates of the |
| 936 | // window is equivalent to going up the tree and asking the |
| 937 | // furthest ancestor what it's relative distance to the root is. |
| 938 | // So we use that approach because it's simpler. |
| 939 | // This approach assumes that any window between the root and |
| 940 | // our window is part of decorations/borders in some way. This |
| 941 | // seems to hold true for most reasonable WM implementations. |
| 942 | ::Window ancestor = m_window; |
| 943 | ::Window root = DefaultRootWindow(m_display.get()); |
| 944 | |
| 945 | while (getParentWindow(m_display.get(), ancestor) != root) |
| 946 | { |
| 947 | // Next window up (parent window). |
| 948 | ancestor = getParentWindow(m_display.get(), ancestor); |
| 949 | } |
| 950 | |
| 951 | // Get final X/Y coordinates: take the relative position to |
nothing calls this directly
no test coverage detected