16

Linuxアプリケーション(この場合はスクリーンセーバー)を作成しようとしていますが、ウィンドウを全画面表示にするという単純なタスクに関する情報を見つけるのは非常に困難です。既存のスクリーンセーバーのコードでさえ、それらがどのようにそれを管理するかについては言及しておらず、私はまだのような明白な機能を見ていませんXRemoveDecoration()

何度もいじくり回した後、私はデスクトップと同じサイズのウィンドウを作成することができました。

Window win = DefaultRootWindow(disp);
XWindowAttributes getWinAttr;
XGetWindowAttributes(disp, win, &getWinAttr);
win = XCreateWindow(disp, win, 0, 0, getWinAttr.width, getWinAttr.height, 0, vInfo->depth, InputOutput, vInfo->visual, CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &winAttr );

しかし、それはタイトルバーと境界線を取り除くために何もしません。明らかに方法があることは知っていますが、他の大規模なライブラリが上に投げられることに依存しない、その方向を指しているものはまだ見つかりません(既存のスクリーンセーバーは間違いなく使用していません)。

編集:私の投稿から情報を削除しないでください。既存のスクリーンセーバーがオプションのライブラリを使用していないことを明示的に指摘したのには非常に理由があります。これは、過去1日のほとんどの期間ソースコードを分析してきたためです。

私は、質問に最も直接的に答え、一般的なアプリケーションに適用される答えを選択しました。

xscreensaversを調査しているこの質問を見つけた場合は、同じことが当てはまります。はい、xscreensaverには独自のAPIがあります。これは複雑で、実際にはより多くのコード行を記述する必要があります(はい、真剣に)。スクリーンセーバーにOpenGLが必要な場合は、別のAPI(xlockmore、競合システム)と、それをxscreensaverに変換する互換性レイヤーを使用する必要があります。

ただし、xscreensaverは、仮想ルートウィンドウ(vroot.hを調べる)をスクリーンセーバーとして使用できるすべてのプログラムを実行できます。ですから、私のアドバイスはそれを行うことです-より多くの制御、制限のないAPI、そしてより優れた移植性が得られます。(私が見た1つの例は、同じファイルでLinuxまたはWindows用にコンパイルすることもできます!)

4

6 に答える 6

13

1つの方法は、ウィンドウマネージャーをバイパスすることです。

XSetWindowAttributes wa;                                                     
wa.override_redirect = True;                                           
XCreateWindow( ..., &wa );
于 2012-01-30T14:51:28.597 に答える
4

あなたが不足している情報の一部は、スクリーンセーバーがフルスクリーンになる責任がないということです。スクリーンセーバーデーモンはスクリーンセーバーウィンドウを管理し、専用のスクリーンセーバーウィンドウレイヤーに配置してフルスクリーンにします。

したがって、スクリーンセーバーを作成するために、あなたは明確になります。フルスクリーンゲームを作成する場合は、ウィンドウがWMによって管理されないようにし、ウィンドウが画面全体をカバーするように、オーバーライドリダイレクト属性を設定する必要があります。

于 2012-01-30T17:58:10.727 に答える
2

これを実現するための最良かつ簡単な方法は、atom最新のウィンドウマネージャーで機能するICCCM仕様を使用することです。次のコードを使用するだけです。

Atom wm_state   = XInternAtom (display, "_NET_WM_STATE", true );
Atom wm_fullscreen = XInternAtom (display, "_NET_WM_STATE_FULLSCREEN", true );

XChangeProperty(display, window, wm_state, XA_ATOM, 32,
                PropModeReplace, (unsigned char *)&wm_fullscreen, 1);

ウィンドウが透明である可能性があります。その場合は、XSetBackground()必要な場所で関数を使用するだけで完了です。

于 2015-02-08T17:06:59.150 に答える
1

シェーダーベースのopenglアプリケーションを内部でホストしている場合でも、freeglutフルスクリーンがうまく機能することがわかりました。ここで呼び出される内部コード(X11ブランチ...)。HTH

#define _NET_WM_STATE_TOGGLE    2
static int fghResizeFullscrToggle(void)
{
    XWindowAttributes attributes;

    if(glutGet(GLUT_FULL_SCREEN)) {
        /* restore original window size */
        SFG_Window *win = fgStructure.CurrentWindow;
        fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
        fgStructure.CurrentWindow->State.Width  = win->State.OldWidth;
        fgStructure.CurrentWindow->State.Height = win->State.OldHeight;

    } else {
        /* resize the window to cover the entire screen */
        XGetWindowAttributes(fgDisplay.Display,
                fgStructure.CurrentWindow->Window.Handle,
                &attributes);

        /*
         * The "x" and "y" members of "attributes" are the window's coordinates
         * relative to its parent, i.e. to the decoration window.
         */
        XMoveResizeWindow(fgDisplay.Display,
                fgStructure.CurrentWindow->Window.Handle,
                -attributes.x,
                -attributes.y,
                fgDisplay.ScreenWidth,
                fgDisplay.ScreenHeight);
    }
    return 0;
}

static int fghEwmhFullscrToggle(void)
{
    XEvent xev;
    long evmask = SubstructureRedirectMask | SubstructureNotifyMask;

    if(!fgDisplay.State || !fgDisplay.StateFullScreen) {
        return -1;
    }

    xev.type = ClientMessage;
    xev.xclient.window = fgStructure.CurrentWindow->Window.Handle;
    xev.xclient.message_type = fgDisplay.State;
    xev.xclient.format = 32;
    xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
    xev.xclient.data.l[1] = fgDisplay.StateFullScreen;
    xev.xclient.data.l[2] = 0;  /* no second property to toggle */
    xev.xclient.data.l[3] = 1;  /* source indication: application */
    xev.xclient.data.l[4] = 0;  /* unused */

    if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) {
        return -1;
    }
    return 0;
}

static int fghToggleFullscreen(void)
{
    /* first try the EWMH (_NET_WM_STATE) method ... */
    if(fghEwmhFullscrToggle() != -1) {
        return 0;
    }

    /* fall back to resizing the window */
    if(fghResizeFullscrToggle() != -1) {
        return 0;
    }
    return -1;
}


#endif  /* TARGET_HOST_POSIX_X11 */
于 2012-01-30T15:01:32.197 に答える
1

例としてこれを見てみてください:

本当にスリックスクリーンセーバーをGLXに移植 http://rss-glx.sourceforge.net/

driver.cのcreateWindow()関数を見てください。

于 2012-01-30T15:13:11.767 に答える
1

それは絶対に難しいことではありません。ここで説明するように、適切なアトムを適切なリストに追加する必要があります。

于 2012-01-30T15:50:15.263 に答える