如何解决x11 XChangeProperty 因 BadValue 而失败
我正在尝试使用 X11 创建一个全屏窗口。我设法获得了一个基本的窗口和事件处理。根据 this,我必须使用属性名称“_MOTIF_WM_HINTS”来隐藏窗口装饰以及自定义类型 Hints
(无论它位于何处或由用户创建)。尽管如此,我还是找到了一个属性名称列表 here,但是当我尝试使用诸如“_WM_NAME”或“_NET_WM_NAME”之类的简单名称时,我收到了 BadValue
错误。
我目前在 Wayland 上,但我确实安装了 xorg-xwayland。
特别是我收到此错误消息:
X Error of Failed request: BadValue (integer parameter out of range for operation)
Major opcode of Failed request: 18 (X_ChangeProperty)
Value in Failed request: 0x8
Serial number of Failed request: 16
Current serial number in output stream: 17
有问题的代码如下:
void fgd_window_toggle_fullscreen(fgd_window_t* win)
{
display* display = win->dsp;
Window window = win->window;
int screen_id = win->screen_id;
fgd_window_info_t* info = &win->info;
info->is_fullscreen = (info->is_fullscreen == 1) ? 0 : 1;
if (info->is_fullscreen)
{
Atom name_property = XInternAtom(display,"_NET_WM_NAME",False);
if (name_property == None)
{
printf("Failed to create property.\n");
return;
}
unsigned char some_text[21] = "My fullscreen window.";
XChangeProperty(display,window,name_property,PropModeReplace,8,some_text,10);
int video_modes_count = 0;
XF86VidModeModeInfo** infos = NULL;
XF86VidModeGetAllModeLines(display,screen_id,&video_modes_count,&infos);
printf("Number of video modes: %d\n",video_modes_count);
for (int idx = 0; idx < video_modes_count; idx++)
{
XF86VidModeModeInfo* current_info = infos[idx];
printf("ModeInfo[%d] = (%d,%d)\n",idx,current_info->hdisplay,current_info->vdisplay);
}
// Switch to another video mode so we can fullscreen the window.
XF86VidModeModeInfo* video_mode = *infos;
XF86VidModeSwitchToMode(display,video_mode);
// Move the window to top left corner.
XF86VidModeSetViewPort(display,0);
// Resize the window to the coresponding dimensions.
XResizeWindow(display,info->max_width,info->max_heigth);
XFree(infos);
}
else
{
int width_center = (info->max_width >> 1) - (info->width >> 1);
int heigth_center = (info->max_heigth >> 1) - (info->heigth >> 1);
XResizeWindow(display,info->width,info->heigth);
XMoveWindow(display,width_center,heigth_center);
}
}
解决方法
如果你想最大化窗口,我可以提供另一种方法来做到这一点。
int MaximizeWindow(Window window)
{
Display *display = XOpenDisplay(NULL);
XClientMessageEvent ev = {};
Atom wmState = XInternAtom(display,"_NET_WM_STATE",False);
Atom maxH = XInternAtom(display,"_NET_WM_STATE_MAXIMIZED_HORZ",False);
Atom maxV = XInternAtom(display,"_NET_WM_STATE_MAXIMIZED_VERT",False);
if (wmState == None)
return 0;
ev.type = ClientMessage;
ev.format = 32;
ev.window = window;
ev.message_type = wmState;
ev.data.l[0] = 1;
ev.data.l[1] = maxH;
ev.data.l[2] = maxV;
ev.data.l[3] = 1;
int rv = XSendEvent(display,DefaultRootWindow(display),False,SubstructureNotifyMask,(XEvent *)&ev);
XFlush(display);
XCloseDisplay(display);
return rv;
}
窗口句柄作为参数提供给这个函数。
我用这个和另一个例子创建了一个 git repo。
,我找到了解决方案!好像客户端需要调用XSendEvent
,不能通过XChangeProperty
实现。
根据this,data
联合的前4个字节可以是:
_NET_WM_STATE_REMOVE 0 /* remove/unset property */
_NET_WM_STATE_ADD 1 /* add/set property */
_NET_WM_STATE_TOGGLE 2 /* toggle property */
void toggle_fullscreen(Display* dpy,Window win,b32* fullscreen)
{
XClientMessageEvent msg = {
.type = ClientMessage,.display = dpy,.window = win,.message_type = XInternAtom(dpy,True),.format = 32,.data = { .l = {
*fullscreen,XInternAtom(dpy,"_NET_WM_STATE_FULLSCREEN",None,1
}}
};
XSendEvent(dpy,XRootWindow(dpy,XDefaultScreen(dpy)),SubstructureRedirectMask | SubstructureNotifyMask,(XEvent*) &msg);
*fullscreen = !(*fullscreen);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。