gpt4 book ai didi

linux - Xlib中心窗口

转载 作者:IT王子 更新时间:2023-10-29 00:13:20 24 4
gpt4 key购买 nike

我正在编写Xlib应用程序,我希望窗口居中。我已将XMoveWindow(desktopWidth - width) / 2, (desktopHeight - height) / 2一起使用,并且它大致在正确的位置。

但是,问题在于宽度和高度是客户区域,而不是总区域。我有什么办法可以获取窗口的总面积吗?

我需要使用Xlib,因为我正在使用GlxOpenGL。我不想使用SDL,也不想拥有庞大的图形库。

最佳答案

有多种解决方法,具体取决于您执行此操作的原因。前两个由大多数窗口管理器“官方支持”并在规范中进行了描述,然后又归类为易碎的骇客。

语义的

规范鼓励您使用_NET_WM_WINDOW_TYPE而不是设置位置(如果有必要的话)。参见http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2507144

例如,DIALOG类型(或设置了WM_TRANSIENT_FOR提示的窗口)通常将在其父窗口或屏幕上居中,而_NET_WM_WINDOW_TYPE_SPLASH(闪屏)类型通常将在屏幕上居中。 “通常”在这里表示“明智的窗口管理器可能居中,使用奇怪的窗口管理器的人不是您的问题,要让他们受苦”。

(虽然不是您想要的,但同样的提示是_NET_WM_STATE_FULLSCREEN,它避免了手动调整大小/位置以便全屏显示。)

如果语义提示起作用,则希望用于处理定位的窗口管理器代码比任何人可以手工轻松编写的代码都要聪明,例如,它可以处理多头设置。设置适当的语义类型还可以使WM在定位之外的其他方面变得更聪明。

重力

如果规范中没有语义提示可以帮助您,那么您可以手动进行居中。重要的是要注意,窗口管理器被允许忽略手动位置请求,其中一些会被忽略。有些人可能只有在WM_NORMAL_HINTS中设置了USPosition标志时才接受该请求(仅当用户明确要求该位置(例如,使用-geometry命令行选项)时,才应设置此标志)。其他人可能总是忽略该请求。但是,您可能会忽略执行此操作的WM。用户选择使用该WM。

补偿窗口装饰(标题栏等)的方法是使用WM_NORMAL_HINTS的win_gravity字段,该字段最初在ICCCM中(请参阅http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.2.3),但在EWMH中的实现说明中有更好的指定:http://standards.freedesktop.org/wm-spec/latest/ar01s09.html#id2570420

对于WM_NORMAL_HINTS,请参见http://tronche.com/gui/x/xlib/ICC/client-to-window-manager/wm-normal-hints.html#XSizeHints(注意:属性的类型为WM_SIZE_HINTS,属性的名称为WM_NORMAL_HINTS,因此涉及两个不同的原子名称)。

要居中,可以将win_gravity设置为Center,这可以让您定位窗口的中心(包括其装饰)而不是左上角。

win_gravity并不经常使用,并且在某些窗口管理器中可能会出现问题,因为没有人去打扰对其进行编码/测试,但是它应该在更主流的窗口中工作。

更新,可能的困惑点:X协议(protocol)中还有其他“重力”,特别是CreateWindow请求可让您设置“bit_gravity”和“win_gravity”;这些与XSizeHints.win_gravity不同。 CreateWindow重力描述了调整窗口大小时如何处理窗口的内容(像素/子窗口)。

基于猜测装饰大小的技巧

这是一个脆弱的技巧,但是...您可以尝试找出装饰的大小,然后将其合并到您的位置中。

要获取窗户装饰物的大小,一种方法是_NET_FRAME_EXTENTS提示,请参见http://standards.freedesktop.org/wm-spec/latest/ar01s05.html#id2569862

对于较老的窗口管理器(但不希望使用新的合成器,但希望它们支持_NET_FRAME_EXTENTS),窗口装饰是X窗口,因此您可以获取父窗口并查看其大小。

这两种方法的问题在于,在添加装饰之前必须先映射窗口,因此必须进行映射。等待获取MapNotify事件;然后得到装饰尺寸;然后移动窗口。不幸的是,这将导致用户可见的闪烁(窗口将首先出现然后移动)。我认为没有一种方法可以不首先映射就获得窗户装饰的尺寸。

进一步讲到可怕的骇客世界,您可以假设对于映射第一个窗口之后的窗口,装饰将匹配先前映射的窗口。 (并不是说这是一个合理的假设:不同类型的窗户可能具有不同的装饰。)

实现注意事项:请记住,装饰窗口可以随时销毁,这会在您提到该窗口的所有未完成Xlib请求中导致X错误,并且默认情况下退出您的程序。为避免这种情况,请在触摸不属于客户端的窗口时设置X错误处理程序。

覆盖重定向

使用重写重定向是一种具有不良副作用的火箭筒,如果您的目标只是将窗口居中,则根本不是一个好主意。

如果在创建窗口时设置了重写重定向标志,则窗口管理器将无法管理其大小,位置,堆叠顺序,装饰或 map 状态(覆盖了窗口管理器对ConfigureRequest和MapRequest的重定向)。

对于用户将其视为窗口的任何事情,这都是一个非常糟糕的主意。通常用于工具提示和 pop 菜单。如果在窗口上设置了重写重定向,则所有常规的窗口管理UI都将被破坏,堆栈顺序最终将基本上是随机的(窗口将倾向于卡在顶部或底部,或更糟的是陷入无限循环与其他客户重新战斗)。

但是,重写重定向的窗口将没有装饰或不会被WM触摸,因此您可以确保将其居中放置而不会受到干扰。

(如果只希望不进行修饰,请使用SPLASH之类的语义类型或使用“MWM”提示,请不要使用覆盖重定向。)

概要

简短的答案是设置语义提示(如果有的话),否则使用XSizeHints.win_gravity = Center。

您可以看到为什么人们通常在客户端到窗口-经理的交互中使用工具包和SDL ;-)很多古怪的历史包and和极端案例,设置窗口位置仅仅是激动的开始!

关于linux - Xlib中心窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8867715/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com