C++ 中的 X11 - 只要在 window 调整大小时设置 ResizeRedirectMask,就会发生裁剪
X11 in C++ - Cropping happens whenever ResizeRedirectMask is set when the window is resized
故事
我使用 X11/Xlib 为 Linux 系统 制作了一个显示图形的简单绘图程序。
它有一个菜单和一个绘图编辑器。
它需要知道window的大小,所以,一开始我用XGetWindowAttributes()
但是,我发现它对我来说太慢了。
因为我每帧都执行函数,所以我的程序很慢。
然后,我 尝试 到 运行 函数 较少 , 类似每 4 帧 但这是造成 闪烁 .
我想要一个可以在每次 window 的大小更改为 运行 时生成的事件,函数仅在大小更改时发生 .
原始修复:
我发现 ResizeRequest
做我想做的事情 并输出 window 的大小作为奖励。
所以我不再需要 XGetWindowAttributes()
了。这 大大加快了程序速度。
在缩小 window.
时效果很好
新一期:
我发现当windows调整大小比原始大小大时,每个对象在原始范围外 绘制得到 裁剪,如图所示。
我们可以看到 应该在 window 周围的灰色边框被裁剪掉了 全部变成黑色 。尤其是 右上角 调色板有 16 种颜色,但 4 种颜色被半裁剪了 而 8 种颜色没有在这里完全可见。
我想做的事情:
我想知道如何通过解决以下问题之一来解决裁剪问题:
- 如果我必须批准调整大小 发送事件,我该怎么办?
- 如果我必须弄乱 缓冲区,我该怎么办?
曲目:
我的程序有一个菜单仍然使用 XGetWindowAttributes()
,编辑器 (如图所示) 使用 ResizeRequest
事件,比XGetWindowAttributes()
.
快
正如预期的那样,裁剪发生在编辑器中而不是菜单中。
但我注意到我可以 更改 window 的大小而无需裁剪 如果我在菜单中然后在编辑器中更改它,并且 它有效 !
然后我发现 只要在 XSelectInput()
函数中设置 ResizeRedirectMask
,就会发生裁剪。
引用自 10.11.4 ResizeRequest 事件页面的 Xlib Programming Manual。
Any attempts to change the size by other clients are then redirected.
我想,这意味着它不会影响 windows 大小(这是我用 XGetWindowAttributes()
并行测试时的结果)。那么,我必须批准调整大小,但是如何?
引自的回答。
I would clear the front buffer and await resize to complete.
我该怎么做?
示例代码:
我制作了一个简短的程序,可以在任何地方显示随机彩色方块,甚至在 window 之外。 程序运行如果你复制它。
有一个#if
声明,您可以更改以查看预期(false
)与实际(true
)之间的差异
#include <X11/Xlib.h>
#include <cstdint>
#include <unistd.h>
#if true //Make it true to set ResizeRedirectMask and false to disable.
#define Masks KeyPressMask|ResizeRedirectMask
#else
#define Masks KeyPressMask
#endif
int main(){
uint32_t RDM=0;
uint16_t i=0;
bool RunLoop=true;
Display* XDisplay=XOpenDisplay(0);//Create a display
Window XWindow=XCreateSimpleWindow(XDisplay,DefaultRootWindow(XDisplay),0,0,480,360,0,0,0);//Create a Window
XMapWindow(XDisplay,XWindow);//Make the Window visible
GC XGraphicCTX=XCreateGC(XDisplay,XWindow,0,0);//Create a Graphics Context
//v Wait for a MapNotify XEvent for next commands
XSelectInput(XDisplay,XWindow,StructureNotifyMask);
while(1){
XEvent e;
XNextEvent(XDisplay,&e);
if(e.type==MapNotify)break;
}
XSelectInput(XDisplay,XWindow,Masks); //Here is part of the magic error
while(RunLoop){
while(XPending(XDisplay)){//Get key changes
XEvent Event;
XNextEvent(XDisplay,&Event);
if(Event.type==KeyPress){
RunLoop=false;
}
}
for(i=0;i<4096;i++){
RDM=(RDM+1841)*9245; //Not perfect but good enough
XSetForeground(XDisplay,XGraphicCTX,RDM&0xFFFFFF);
RDM=(RDM+1841)*9245; //Not perfect but good enough
XFillRectangle(XDisplay,XWindow,XGraphicCTX,RDM&0xFFFF,(RDM>>16),64,64);
}
XFlush(XDisplay);
usleep(16667); //AHHH there is 666!
}
return 0;
}
正如我们所见,只要设置 ResizeRedirectMask
就会发生裁剪,您甚至不需要响应事件就可以实现!
将 #if
语句切换为 false
给出了所需的行为 因为它会禁用 ResizeRedirectMask
.
该特定程序不关心 window 的大小,我的大多数程序都需要知道大小,否则它会失败。
一些细节:
我曾经使用XGetWindowAttributes()
得到window的大小,有点慢,我仍然在菜单中使用它 因为它很好用。
这就是为什么在编辑器中,我使用 ResizeRequest
事件。
ConfigureNotify
事件似乎效果很好,但它闪烁的方式比使用XGetWindowAttributes()
要多得多。
为什么会闪烁?
闪烁是因为ConfigureNotify
在调整完成后发送,这意味着它作为一般在调整后发送一帧。
这是 linked 到 。
至少不会浪费很多性能
我正在寻找一种方法来修复闪烁,因为它可能更容易。
请注意,问题完全改变了,因为问题与原来不同。但仍处于 link 原始问题中。
ResizeRedirectMask
与您的目的无关。除非您正在编写 window 管理器,否则您永远不需要它。你需要StructureNotifyMask
。你几乎应该总是 select 这个面具(也许除非你的 window 永远不会调整大小)。
如果您不 select StructureNotifyMask
,您的 window 永远不会收到实际的调整大小事件,也没有机会响应它们。
当你得到一个 ConfigureNotify
事件时,只有你 select StructureNotifyMask
才会发生,它会包含新的实际几何体,所以你的 window 可以更新本身。
故事
我使用 X11/Xlib 为 Linux 系统 制作了一个显示图形的简单绘图程序。
它有一个菜单和一个绘图编辑器。
它需要知道window的大小,所以,一开始我用XGetWindowAttributes()
但是,我发现它对我来说太慢了。
因为我每帧都执行函数,所以我的程序很慢。
然后,我 尝试 到 运行 函数 较少 , 类似每 4 帧 但这是造成 闪烁 .
我想要一个可以在每次 window 的大小更改为 运行 时生成的事件,函数仅在大小更改时发生 .
原始修复:
我发现 ResizeRequest
做我想做的事情 并输出 window 的大小作为奖励。
所以我不再需要 XGetWindowAttributes()
了。这 大大加快了程序速度。
在缩小 window.
新一期:
我发现当windows调整大小比原始大小大时,每个对象在原始范围外 绘制得到 裁剪,如图所示。
我们可以看到 应该在 window 周围的灰色边框被裁剪掉了 全部变成黑色 。尤其是 右上角 调色板有 16 种颜色,但 4 种颜色被半裁剪了 而 8 种颜色没有在这里完全可见。
我想做的事情:
我想知道如何通过解决以下问题之一来解决裁剪问题:
- 如果我必须批准调整大小 发送事件,我该怎么办?
- 如果我必须弄乱 缓冲区,我该怎么办?
曲目:
我的程序有一个菜单仍然使用 XGetWindowAttributes()
,编辑器 (如图所示) 使用 ResizeRequest
事件,比XGetWindowAttributes()
.
快
正如预期的那样,裁剪发生在编辑器中而不是菜单中。
但我注意到我可以 更改 window 的大小而无需裁剪 如果我在菜单中然后在编辑器中更改它,并且 它有效 !
然后我发现 只要在 XSelectInput()
函数中设置 ResizeRedirectMask
,就会发生裁剪。
引用自 10.11.4 ResizeRequest 事件页面的 Xlib Programming Manual。
Any attempts to change the size by other clients are then redirected.
我想,这意味着它不会影响 windows 大小(这是我用 XGetWindowAttributes()
并行测试时的结果)。那么,我必须批准调整大小,但是如何?
引自
I would clear the front buffer and await resize to complete.
我该怎么做?
示例代码:
我制作了一个简短的程序,可以在任何地方显示随机彩色方块,甚至在 window 之外。 程序运行如果你复制它。
有一个#if
声明,您可以更改以查看预期(false
)与实际(true
)之间的差异
#include <X11/Xlib.h>
#include <cstdint>
#include <unistd.h>
#if true //Make it true to set ResizeRedirectMask and false to disable.
#define Masks KeyPressMask|ResizeRedirectMask
#else
#define Masks KeyPressMask
#endif
int main(){
uint32_t RDM=0;
uint16_t i=0;
bool RunLoop=true;
Display* XDisplay=XOpenDisplay(0);//Create a display
Window XWindow=XCreateSimpleWindow(XDisplay,DefaultRootWindow(XDisplay),0,0,480,360,0,0,0);//Create a Window
XMapWindow(XDisplay,XWindow);//Make the Window visible
GC XGraphicCTX=XCreateGC(XDisplay,XWindow,0,0);//Create a Graphics Context
//v Wait for a MapNotify XEvent for next commands
XSelectInput(XDisplay,XWindow,StructureNotifyMask);
while(1){
XEvent e;
XNextEvent(XDisplay,&e);
if(e.type==MapNotify)break;
}
XSelectInput(XDisplay,XWindow,Masks); //Here is part of the magic error
while(RunLoop){
while(XPending(XDisplay)){//Get key changes
XEvent Event;
XNextEvent(XDisplay,&Event);
if(Event.type==KeyPress){
RunLoop=false;
}
}
for(i=0;i<4096;i++){
RDM=(RDM+1841)*9245; //Not perfect but good enough
XSetForeground(XDisplay,XGraphicCTX,RDM&0xFFFFFF);
RDM=(RDM+1841)*9245; //Not perfect but good enough
XFillRectangle(XDisplay,XWindow,XGraphicCTX,RDM&0xFFFF,(RDM>>16),64,64);
}
XFlush(XDisplay);
usleep(16667); //AHHH there is 666!
}
return 0;
}
正如我们所见,只要设置 ResizeRedirectMask
就会发生裁剪,您甚至不需要响应事件就可以实现!
将 #if
语句切换为 false
给出了所需的行为 因为它会禁用 ResizeRedirectMask
.
该特定程序不关心 window 的大小,我的大多数程序都需要知道大小,否则它会失败。
一些细节:
我曾经使用XGetWindowAttributes()
得到window的大小,有点慢,我仍然在菜单中使用它 因为它很好用。
这就是为什么在编辑器中,我使用 ResizeRequest
事件。
ConfigureNotify
事件似乎效果很好,但它闪烁的方式比使用XGetWindowAttributes()
要多得多。
为什么会闪烁?
闪烁是因为ConfigureNotify
在调整完成后发送,这意味着它作为一般在调整后发送一帧。
这是 linked 到
至少不会浪费很多性能
我正在寻找一种方法来修复闪烁,因为它可能更容易。
请注意,问题完全改变了,因为问题与原来不同。但仍处于 link 原始问题中。
ResizeRedirectMask
与您的目的无关。除非您正在编写 window 管理器,否则您永远不需要它。你需要StructureNotifyMask
。你几乎应该总是 select 这个面具(也许除非你的 window 永远不会调整大小)。
如果您不 select StructureNotifyMask
,您的 window 永远不会收到实际的调整大小事件,也没有机会响应它们。
当你得到一个 ConfigureNotify
事件时,只有你 select StructureNotifyMask
才会发生,它会包含新的实际几何体,所以你的 window 可以更新本身。