2012-10-03 69 views
1

我正在用這個拉出我的頭髮。X11,更改分辨率並使窗口全屏

我改變了屏幕的分辨率編程方式使用下列內容:

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。

謝謝!

+0

如果您沒有使用XF86VidModeSwitch或XRandr切換顯示模式 - 那麼您仍然處於桌面分辨率狀態,並且只是創建沒有WM裝飾的窗口並將其放置在左上角。當你需要與桌面相同的分辨率時,它非常棒 - 你可以自由地切換窗口,並在這個窗口之上有其他窗口,但這不是完美的解決方案。 – keltar

+0

如果您不想使用SDL,則仍然可以讀取SDL源代碼以查看它是如何執行的,並在您的項目中複製該代碼。 –

回答

1

您遇到的問題是,您依賴窗口管理器來正確放置窗口。不幸的是,並非所有的WM都關心XF86VidMode或RandR。在視頻模式更改之後創建全屏窗口的規範解決方案是將窗口創建爲無邊框和「覆蓋重定向」,以使其不受WM管理,然後將其明確定位以覆蓋(0, 0)到(vidmode寬度,vidmode高度)。

+0

@HavocP:現在只有XF86VidMode比RandR支持更少。也可以相信或不相信,但在某些全屏應用程序中,比如實際上希望阻止其他程序捕捉熱鍵的遊戲(請記住Windows的關鍵問題,玩家將鍵盤拔出鍵盤,任何人?)。堆疊問題可以通過奇怪的方式解決,並在屏幕保護程序或組合層中創建窗口。 – datenwolf