C++ X11,更改分辨率并使窗口全屏显示
我要用这个把头发拔出来 我正在使用以下程序更改屏幕的分辨率:C++ X11,更改分辨率并使窗口全屏显示,c++,linux,fullscreen,x11,xlib,C++,Linux,Fullscreen,X11,Xlib,我要用这个把头发拔出来 我正在使用以下程序更改屏幕的分辨率: int FindBestVideoMode(int screen, unsigned int &width, unsigned int &height) { int modeCount; XF86VidModeModeInfo** modes; if (XF86VidModeGetAllModeLines(display, screen, &modeCount, &modes)
int FindBestVideoMode(int screen, unsigned int &width, unsigned int &height)
{
int modeCount;
XF86VidModeModeInfo** modes;
if (XF86VidModeGetAllModeLines(display, screen, &modeCount, &modes))
{
int bestMode = -1;
int bestMatch = INT_MAX;
for(int i = 0; i < modeCount; i ++)
{
int match = (width - modes[i]->hdisplay) *
(width - modes[i]->hdisplay) +
(height - modes[i]->vdisplay) *
(height - modes[i]->vdisplay);
if(match < bestMatch)
{
bestMatch = match;
bestMode = i;
}
}
width = modes[bestMode]->hdisplay;
height = modes[bestMode]->vdisplay;
XFree(modes);
return bestMode;
}
return -1;
}
void SwitchVideoMode(int screen, int mode)
{
if (mode >= 0)
{
int modeCount;
XF86VidModeModeInfo** modes;
if (XF86VidModeGetAllModeLines(display, screen, &modeCount, &modes))
{
if (mode < modeCount)
{
XF86VidModeSwitchToMode(display, screen, modes[mode]);
XF86VidModeSetViewPort(display, screen, 0, 0);
XFlush(display);
}
XFree(modes);
}
}
}
void SwitchToBestVideoMode(int screen, unsigned int &width, unsigned int &height)
{
SwitchVideoMode(screen, FindBestVideoMode(screen, width, height));
}
void RestoreVideoMode(int screen)
{
auto iVideoMode = DefaultVideoModes.Find(screen);
if (iVideoMode != nullptr)
{
XF86VidModeSwitchToMode(display, screen, &iVideoMode->value);
XF86VidModeSetViewPort(display, screen, 0, 0);
XFlush(display);
}
}
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.window = window;
e.xclient.message_type = _NET_WM_STATE;
e.xclient.format = 32;
e.xclient.data.l[0] = 2; // _NET_WM_STATE_TOGGLE
e.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True);
e.xclient.data.l[2] = 0; // no second property to toggle
e.xclient.data.l[3] = 1;
e.xclient.data.l[4] = 0;
XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &e);
XMoveResizeWindow(display, window, 0, 0, width, height);
现在的问题是,在进行编程分辨率更改时,窗口的大小调整为桌面分辨率,而不是新的分辨率集。我所期望的,事实上我所追求的,是将窗口的大小调整到新的分辨率
我想我只是误解了一些简单的事情,但对此的任何想法都非常感谢。我不想在这里使用外部库,比如SDL
谢谢 您遇到的问题是,您依赖窗口管理器来正确放置窗口。不幸的是,并非所有WMs都关心XF86VidMode或RandR。在视频模式更改后创建全屏窗口的标准解决方案是将窗口创建为无边界和“覆盖重定向”,这样它就不会被WM管理,然后将其明确定位以覆盖从(0,0)到(视频模式宽度,视频模式高度)的区域.如果您没有使用XF86VidModeSwitch或XRandr切换显示模式,那么您仍然处于桌面分辨率,只需创建带有WM装饰的窗口并将其放置在左上角。当您需要与桌面相同的分辨率时,这非常好-您可以自由切换窗口,并在该窗口上方有其他窗口,但这不是完美的解决方案,ofc。如果您不想使用SDL,您仍然可以阅读SDL source来了解它是如何工作的,并在您的项目中复制这些代码。@HavocP:只是XF86VidMode现在比RandR更不受支持。信不信由你,但在一些全屏应用程序中,比如游戏,你实际上想阻止其他程序捕捉热键(还记得该死的Windows键问题,玩家从键盘上拔出键,有人吗?)。堆叠问题可以通过在屏幕保护程序或合成层中创建窗口来解决。