繁体   English   中英

获取 X11 窗口标题高度

[英]Get X11 window caption height

如何在 X11 中获取窗口的标题/标题高度? 我正在使用以下内容来获取边框厚度:

XWindowAttributes wndattr;
::XGetWindowAttributes(display, wnd, &wndattr)
... = lWndAttr->border_width;

对于标题栏,我似乎找不到任何直接的东西。 这个答案似乎暗示我需要通过字体,但这不可能是对的,对吧?)

现代窗口管理器遵守扩展窗口管理器提示规范,因此您只需要检查_NET_FRAME_EXTENTS属性。

#include <X11/Xlib.h>
#include <stdio.h>

int main ()
{
    Display* d;
    Window w, root;
    Atom a, t;
    int s;
    long fg, bg;
    int f;
    unsigned long n, b;
    unsigned char *data = 0;
    long* extents;
    XEvent e;

    d = XOpenDisplay(0);
    s = DefaultScreen(d);
    root = DefaultRootWindow(d);
    fg = BlackPixel(d, s);
    bg = WhitePixel(d, s);
    w = XCreateSimpleWindow(d, root, 0, 0, 200, 200, 0, fg, bg);
    XSelectInput(d, w, ExposureMask|ButtonPressMask|KeyPressMask|PropertyChangeMask);

    XMapWindow(d,w);

    a = XInternAtom(d, "_NET_FRAME_EXTENTS", True); /* Property to check */

    /* Window manager doesn't set up the extents immediately */
    /* Wait until they are set up and there are 4 of them */
    while (XGetWindowProperty(d, w, a,
                   0, 4, False, AnyPropertyType,
                   &t, &f,
                   &n, &b, &data) != Success || n != 4 || b != 0) 
    {
        printf ("Waiting for extents\n");
        XNextEvent(d, &e);
    }

    /* OK got extents */
    extents = (long*) data;
    printf ("Got frame extents: left %ld right %ld top %ld bottom %ld\n",
            extents[0], extents[1], extents[2], extents[3]);

    return 0;
}

如果您使用的是不太现代的 WM,那么您就靠自己了。 尝试按照安德烈的回答中的建议走上窗户树。 这可能会奏效,但不能保证。 一些窗口管理器根本不使用单独的“框架”窗口(例如,它们可以在叠加视觉中的单个窗口上绘制所有框架)。

XGetWindowAttributes返回一个指向XWindowAttributes结构XGetWindowAttributes的指针,如下所示:

typedef struct {
    int x, y;                   /* location of window */
    int width, height;          /* width and height of window */
    int border_width;           /* border width of window */
    int depth;                  /* depth of window */
    Visual *visual;             /* the associated visual structure */
    Window root;                /* root of screen containing window */
#if defined(__cplusplus) || defined(c_plusplus)
    int c_class;                /* C++ InputOutput, InputOnly*/
#else
    int class;                  /* InputOutput, InputOnly*/
#endif
    int bit_gravity;            /* one of bit gravity values */
    int win_gravity;            /* one of the window gravity values */
    int backing_store;          /* NotUseful, WhenMapped, Always */
    unsigned long backing_planes;/* planes to be preserved if possible */
    unsigned long backing_pixel;/* value to be used when restoring planes */
    Bool save_under;            /* boolean, should bits under be saved? */
    Colormap colormap;          /* color map to be associated with window */
    Bool map_installed;         /* boolean, is color map currently installed*/
    int map_state;              /* IsUnmapped, IsUnviewable, IsViewable */
    long all_event_masks;       /* set of events all people have interest in*/
    long your_event_mask;       /* my event mask */
    long do_not_propagate_mask; /* set of events that should not propagate */
    Bool override_redirect;     /* boolean value for override-redirect */
    Screen *screen;             /* back pointer to correct screen */
} XWindowAttributes;

唯一有趣的部分是在开头,给出了小部件窗口的位置和大小。 标题不是该窗口的一部分。 它由窗口管理器管理,是所谓的“装饰”的一部分。

进一步阅读:

答案实际上取决于使用的窗口管理器,但大多数 WM 将目标窗口重新设置为框架的子窗口,因此算法将是:

  • 走到父窗口,直到到达 root。 root之前的那个可能是frame
  • 将目标窗口矩形与框架矩形进行比较。 框架顶部减去目标顶部会给你标题高度

所以为了咧嘴笑,我找到了根目录的窗口列表:

/* find frame window */
cw = win->xwhan; /* index current window */
do {

    /* find tree parameters */
    XQueryTree(padisplay, cw, &rw, &pw, &cwl, &ncw);
    cw = pw;

    XGetWindowAttributes(padisplay, cw, &xwa);
    dbg_printf(dlinfo, "Window: %d,%d\n", xwa.width, xwa.height);

} while (cw != rw);

/* get actual size of onscreen window, and set that as client space */
XWLOCK();
XGetWindowAttributes(padisplay, win->xwhan, &xwa);
XWUNLOCK();
*x = xwa.width;
*y = xwa.height;
dbg_printf(dlinfo, "Current window: %d,%d\n", xwa.width, xwa.height);

导致:

samiam@samiam-h-pc-2:~/projects/petit_ami$ ./testg
linux/graphics.c:pa_getsizg():8612: Window: 1480,1010
linux/graphics.c:pa_getsizg():8612: Window: 5120,5760
linux/graphics.c:pa_getsizg():8622: Current window: 1440,900

所以基本上框架是一个窗口,然后根窗口是整个屏幕。 这是在单个(非嵌套)窗口上完成的。

请注意,根据定义,窗口是嵌套的(相互包含),因此除了它可能是最接近当前窗口的顺序框架之外,没有什么特别标记框架。

让我们看看我是否可以旋转这个逻辑:

  1. 较旧的 Windows 管理器没有 _NET_FRAME_EXTENTS 属性。

  2. “走框架”算法也适用于较新的窗口管理器。

因此,在大多数情况下,查看父项会产生正确的答案,但无法确定。

我正在 Ubuntu 20.04 上尝试这个,所以我认为这符合“现代窗口管理器”的要求。

为什么我使用包括框架和客户区在内的窗口大小? 因为那是最通用的尺寸。 我不仅处理程序窗口,还处理任何子窗口(小部件、子窗口等),因此父尺寸是将子窗口作为组件进行跟踪的好方法。 我通过给定父窗口参数和子窗口特征(启用框架等)的函数确定客户区。

Scott Franco 加利福尼亚州圣何塞

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM