// File: tomfunkhouser[P]gaps/pkgs/fglut/freeglut_gamemode.c
// Function: glutEnterGameMode
int FGAPIENTRY glutEnterGameMode( void )
{
    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEnterGameMode" );

    if( fgStructure.GameModeWindow )
        fgAddToWindowDestroyList( fgStructure.GameModeWindow );
    else
        fghRememberState( );

    if( ! fghChangeDisplayMode( GL_FALSE ) )
    {
        fgWarning( "failed to change screen settings" );
        return 0;
    }

    fgStructure.GameModeWindow = fgCreateWindow(
        NULL, "FREEGLUT", GL_TRUE, 0, 0,
        GL_TRUE, fgState.GameModeSize.X, fgState.GameModeSize.Y,
        GL_TRUE, GL_FALSE
    );

    fgStructure.GameModeWindow->State.Width  = fgState.GameModeSize.X;
    fgStructure.GameModeWindow->State.Height = fgState.GameModeSize.Y;
    fgStructure.GameModeWindow->State.NeedToResize = GL_TRUE;

#if TARGET_HOST_POSIX_X11

    /*
     * Sync needed to avoid a real race, the Xserver must have really created
     * the window before we can grab the pointer into it:
     */
    XSync( fgDisplay.Display, False );

    /*
     * Grab the pointer to confine it into the window after the calls to
     * XWrapPointer() which ensure that the pointer really enters the window.
     *
     * We also need to wait here until XGrabPointer() returns GrabSuccess,
     * otherwise the new window is not viewable yet and if the next function
     * (XSetInputFocus) is called with a not yet viewable window, it will exit
     * the application which we have to aviod, so wait until it's viewable:
     */
    while( GrabSuccess != XGrabPointer(
               fgDisplay.Display, fgStructure.GameModeWindow->Window.Handle,
               TRUE,
               ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
               | PointerMotionMask,
               GrabModeAsync, GrabModeAsync,
               fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )
        usleep( 100 );

    /*
     * Change input focus to the new window. This will exit the application
     * if the new window is not viewable yet, see the XGrabPointer loop above.
     */
    XSetInputFocus(
        fgDisplay.Display,
        fgStructure.GameModeWindow->Window.Handle,
        RevertToNone,
        CurrentTime
    );

    /* Move the Pointer to the middle of the fullscreen window */
    XWarpPointer(
        fgDisplay.Display,
        None,
        fgDisplay.RootWindow,
        0, 0, 0, 0,
        fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
    );

#   ifdef X_XF86VidModeSetViewPort

    if( fgDisplay.DisplayModeValid )
    {
        int x, y;
        Window child;

        /* Change to viewport to the window topleft edge: */
        if( !XF86VidModeSetViewPort( fgDisplay.Display, fgDisplay.Screen, 0, 0 ) )
            fgWarning( "XF86VidModeSetViewPort failed" );

        /*
         * Final window repositioning: It could be avoided using an undecorated
         * window using override_redirect, but this * would possily require
         * more changes and investigation.
         */

        /* Get the current postion of the drawable area on screen */
        XTranslateCoordinates(
            fgDisplay.Display,
            fgStructure.CurrentWindow->Window.Handle,
            fgDisplay.RootWindow,
            0, 0, &x, &y,
            &child
        );

        /* Move the decorataions out of the topleft corner of the display */
        XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
                     -x, -y);
    }

#endif

    /* Grab the keyboard, too */
    XGrabKeyboard(
        fgDisplay.Display,
        fgStructure.GameModeWindow->Window.Handle,
        FALSE,
        GrabModeAsync, GrabModeAsync,
        CurrentTime
    );

#endif

    return fgStructure.GameModeWindow->ID;
}

// Assembly:
subq $0x38, %rsp
leaq 0x736d5(%rip), %rax     # 0x1fa390
cmpb $0x0, 0x1c(%rax)
jne 0x186cd6
leaq 0x16c0a(%rip), %rdi     # 0x19d8d2
leaq 0x286bc(%rip), %rsi     # 0x1af38b
movb $0x0, %al
callq 0x17de70
leaq 0x79203(%rip), %rax     # 0x1ffee0
cmpq $0x0, 0x48(%rax)
je 0x186cf6
leaq 0x791f5(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rdi
callq 0x1828c0
jmp 0x186cfb
callq 0x186f20
xorl %edi, %edi
callq 0x186f30
cmpb $0x0, %al
jne 0x186d21
leaq 0x287ed(%rip), %rdi     # 0x1af4fa
movb $0x0, %al
callq 0x17dfa0
movl $0x0, 0x34(%rsp)
jmp 0x186f13
leaq 0x73668(%rip), %rax     # 0x1fa390
movl 0x88(%rax), %r10d
leaq 0x7365a(%rip), %rax     # 0x1fa390
movl 0x8c(%rax), %eax
xorl %ecx, %ecx
movl %ecx, %edi
leaq 0x287d4(%rip), %rsi     # 0x1af51b
movl $0x1, %r9d
xorl %r8d, %r8d
movl %r9d, %edx
movl %r8d, %ecx
movl %r10d, (%rsp)
movl %eax, 0x8(%rsp)
movl $0x1, 0x10(%rsp)
movl $0x0, 0x18(%rsp)
callq 0x182510
movq %rax, %rcx
leaq 0x79163(%rip), %rax     # 0x1ffee0
movq %rcx, 0x48(%rax)
leaq 0x73608(%rip), %rax     # 0x1fa390
movl 0x88(%rax), %ecx
leaq 0x7914b(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movl %ecx, 0x38(%rax)
leaq 0x735ed(%rip), %rax     # 0x1fa390
movl 0x8c(%rax), %ecx
leaq 0x79130(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movl %ecx, 0x3c(%rax)
leaq 0x79122(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movb $0x1, 0x6a(%rax)
leaq 0x79063(%rip), %rax     # 0x1ffe30
movq (%rax), %rdi
xorl %esi, %esi
callq 0x23440
leaq 0x79052(%rip), %rax     # 0x1ffe30
movq (%rax), %rdi
leaq 0x790f8(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movq 0x18(%rax), %rsi
leaq 0x790e9(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movq 0x18(%rax), %rax
movl $0x1, %r9d
movl $0x204c, %ecx           # imm = 0x204C
xorl %edx, %edx
movl %r9d, %edx
movl %r9d, %r8d
movq %rax, (%rsp)
movq $0x0, 0x8(%rsp)
movq $0x0, 0x10(%rsp)
callq 0x22320
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x186e41
movl $0x64, %edi
callq 0x22f10
jmp 0x186dd7
leaq 0x78fe8(%rip), %rax     # 0x1ffe30
movq (%rax), %rdi
leaq 0x7908e(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movq 0x18(%rax), %rsi
xorl %edx, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0x22750
leaq 0x78fc4(%rip), %rax     # 0x1ffe30
movq (%rax), %rdi
leaq 0x78fba(%rip), %rax     # 0x1ffe30
movq 0x10(%rax), %rax
movq %rax, 0x28(%rsp)
leaq 0x7350a(%rip), %rax     # 0x1fa390
movl 0x88(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %r10d
leaq 0x734f2(%rip), %rax     # 0x1fa390
movl 0x8c(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movq 0x28(%rsp), %rdx
xorl %ecx, %ecx
movl %ecx, %esi
xorl %r9d, %r9d
movl %r9d, %ecx
movl %r9d, %r8d
movl $0x0, (%rsp)
movl %r10d, 0x8(%rsp)
movl %eax, 0x10(%rsp)
callq 0x23000
leaq 0x78f56(%rip), %rax     # 0x1ffe30
movq (%rax), %rdi
leaq 0x78ffc(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movq 0x18(%rax), %rsi
xorl %edx, %edx
movl $0x1, %r8d
xorl %eax, %eax
movl %eax, %r9d
movl %r8d, %ecx
callq 0x22cd0
leaq 0x78fd8(%rip), %rax     # 0x1ffee0
movq 0x48(%rax), %rax
movl 0x10(%rax), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
addq $0x38, %rsp
retq
nopl (%rax)