获取 X11 window 标题高度
Get X11 window caption height
如何在 X11 中获取 window 的 title/caption 高度?我正在使用以下方法获取边框粗细:
XWindowAttributes wndattr;
::XGetWindowAttributes(display, wnd, &wndattr)
... = lWndAttr->border_width;
我似乎找不到标题栏的 straight-forward。 (This 答案似乎暗示我需要检查字体,但这不对,对吧?)
XGetWindowAttributes
returns 指向 XWindowAttributes
structurex 的指针,如下所示:
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;
唯一有趣的部分是开头,给出了小部件 window 的位置和大小。 标题 不是 window 的一部分。它由 window 经理管理,是所谓的 "decoration".
的一部分
进一步阅读:
答案实际上取决于所使用的 window 管理器,但是大多数 WM 都将 parent 目标 windows 设为帧的 child,因此算法将是:
- 走到 parent windows 直到你到达 root。 root 之前的可能是 frame
- 将您的目标 window 矩形与框架矩形进行比较。 Frame top 减去 target top 会得到标题高度
现代 window 经理遵守 Extended Window Manager Hints 规范,因此您只需检查 _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,那您只能靠自己了。尝试按照 Andrey 的回答中的建议走上 window 树。这可能会奏效,但不能保证。一些 window 经理根本不使用单独的 "frame" windows(例如,他们可以在叠加视觉中的单个 window 上绘制所有框架)。
所以为了 grins,我找到了 windows 到根目录的列表:
/* 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
所以基本上frame是一个window向上,然后根window就是整屏了。这是在单个(未嵌套)window.
上完成的
请注意,根据定义 windows 是嵌套的(彼此包含),因此除了它可能是最接近当前 window 的顺序框架之外,没有什么特别标记框架。
让我们看看我是否可以旋转这个逻辑:
年长的 windows 经理没有 _NET_FRAME_EXTENTS 属性.
“遍历框架”算法也适用于较新的 windows 经理。
因此,在大多数情况下,查看父项会得出正确答案,但无法确定。
我在 Ubuntu 20.04 上尝试这个,所以我认为这符合“现代 window 经理”的条件。
为什么我要使用 window 尺寸,包括边框和客户区?因为那是最通用的尺寸。我不仅处理程序 window,还处理任何子 windows(小部件、子 windows 等),因此父维度是跟踪子 [=41] 的好方法=] 作为组件。我通过给定父 window 参数和子 window 特征(启用框架等)的函数确定客户区。
斯科特·佛朗哥
加利福尼亚州圣何塞
如何在 X11 中获取 window 的 title/caption 高度?我正在使用以下方法获取边框粗细:
XWindowAttributes wndattr;
::XGetWindowAttributes(display, wnd, &wndattr)
... = lWndAttr->border_width;
我似乎找不到标题栏的 straight-forward。 (This 答案似乎暗示我需要检查字体,但这不对,对吧?)
XGetWindowAttributes
returns 指向 XWindowAttributes
structurex 的指针,如下所示:
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;
唯一有趣的部分是开头,给出了小部件 window 的位置和大小。 标题 不是 window 的一部分。它由 window 经理管理,是所谓的 "decoration".
的一部分进一步阅读:
答案实际上取决于所使用的 window 管理器,但是大多数 WM 都将 parent 目标 windows 设为帧的 child,因此算法将是:
- 走到 parent windows 直到你到达 root。 root 之前的可能是 frame
- 将您的目标 window 矩形与框架矩形进行比较。 Frame top 减去 target top 会得到标题高度
现代 window 经理遵守 Extended Window Manager Hints 规范,因此您只需检查 _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,那您只能靠自己了。尝试按照 Andrey 的回答中的建议走上 window 树。这可能会奏效,但不能保证。一些 window 经理根本不使用单独的 "frame" windows(例如,他们可以在叠加视觉中的单个 window 上绘制所有框架)。
所以为了 grins,我找到了 windows 到根目录的列表:
/* 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
所以基本上frame是一个window向上,然后根window就是整屏了。这是在单个(未嵌套)window.
上完成的请注意,根据定义 windows 是嵌套的(彼此包含),因此除了它可能是最接近当前 window 的顺序框架之外,没有什么特别标记框架。
让我们看看我是否可以旋转这个逻辑:
年长的 windows 经理没有 _NET_FRAME_EXTENTS 属性.
“遍历框架”算法也适用于较新的 windows 经理。
因此,在大多数情况下,查看父项会得出正确答案,但无法确定。
我在 Ubuntu 20.04 上尝试这个,所以我认为这符合“现代 window 经理”的条件。
为什么我要使用 window 尺寸,包括边框和客户区?因为那是最通用的尺寸。我不仅处理程序 window,还处理任何子 windows(小部件、子 windows 等),因此父维度是跟踪子 [=41] 的好方法=] 作为组件。我通过给定父 window 参数和子 window 特征(启用框架等)的函数确定客户区。
斯科特·佛朗哥 加利福尼亚州圣何塞