I am trying to create a fullscreen window with X11. I managed to get a basic window and event handling. According to 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 but when I try using a simple one like "_WM_NAME" or "_NET_WM_NAME" I get a BadValue
error.
I'm on Wayland currently but I do have installed xorg-xwayland.
Specificaly i get this error message:
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
The code in question is below:
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);
}
}
Is this a code related problem or my display manager is interfering?
I found a solution! It seems that the client needs to call XSendEvent
and it can't be done through XChangeProperty
.
According to this the first 4 bytes of the data
union can be:
_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);
}