x11 XChangeProperty 因 BadValue 而失败
x11 XChangeProperty fails with BadValue
我正在尝试使用 X11 创建全屏 window。我设法获得了基本的 window 和事件处理。根据 this I have to use the property name "_MOTIF_WM_HINTS" in order to hide window decorations, along with the custom type Hints
(wherever that may reside or is user created). Nevertheless I found a list of property names 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,
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, screen_id, video_mode);
// Move the window to top left corner.
XF86VidModeSetViewPort(display, screen_id, 0, 0);
// Resize the window to the coresponding dimensions.
XResizeWindow(display, window,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, window, info->width, info->heigth);
XMoveWindow(display, window, width_center, heigth_center);
}
}
这是与代码相关的问题还是我的显示管理器在干扰?
如果你想最大化 window,我可以提供另一种方法。
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;
}
Window 句柄作为参数提供给此函数。
我用这个和另一个示例创建了一个 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, "_NET_WM_STATE", True),
.format = 32,
.data = { .l = {
*fullscreen,
XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True),
None,
0,
1
}}
};
XSendEvent(dpy, XRootWindow(dpy, XDefaultScreen(dpy)), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*) &msg);
*fullscreen = !(*fullscreen);
}
我正在尝试使用 X11 创建全屏 window。我设法获得了基本的 window 和事件处理。根据 this I have to use the property name "_MOTIF_WM_HINTS" in order to hide window decorations, along with the custom type Hints
(wherever that may reside or is user created). Nevertheless I found a list of property names 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,
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, screen_id, video_mode);
// Move the window to top left corner.
XF86VidModeSetViewPort(display, screen_id, 0, 0);
// Resize the window to the coresponding dimensions.
XResizeWindow(display, window,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, window, info->width, info->heigth);
XMoveWindow(display, window, width_center, heigth_center);
}
}
这是与代码相关的问题还是我的显示管理器在干扰?
如果你想最大化 window,我可以提供另一种方法。
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;
}
Window 句柄作为参数提供给此函数。
我用这个和另一个示例创建了一个 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, "_NET_WM_STATE", True),
.format = 32,
.data = { .l = {
*fullscreen,
XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True),
None,
0,
1
}}
};
XSendEvent(dpy, XRootWindow(dpy, XDefaultScreen(dpy)), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*) &msg);
*fullscreen = !(*fullscreen);
}