/* * The window must be created in the same thread that * runs the message loop. */ static void display_thread_proc(void *arg) { WGL_DISPLAY_PARAMETERS *ndp = arg; ALLEGRO_DISPLAY *disp = (ALLEGRO_DISPLAY*)ndp->display; ALLEGRO_DISPLAY_WGL *wgl_disp = (void*)disp; ALLEGRO_DISPLAY_WIN *win_disp = (void*)disp; MSG msg; al_set_new_window_position(ndp->window_x, ndp->window_y); /* So that we can call the functions using TLS from this thread. */ al_set_new_display_flags(disp->flags); if (disp->flags & ALLEGRO_FULLSCREEN) { if (!change_display_mode(disp)) { win_disp->thread_ended = true; destroy_display_internals(wgl_disp); SetEvent(ndp->AckEvent); return; } } else if (disp->flags & ALLEGRO_FULLSCREEN_WINDOW) { ALLEGRO_MONITOR_INFO mi; int adapter = win_disp->adapter; al_get_monitor_info(adapter, &mi); win_disp->toggle_w = disp->w; win_disp->toggle_h = disp->h; disp->w = mi.x2 - mi.x1; disp->h = mi.y2 - mi.y1; } else { win_disp->toggle_w = disp->w; win_disp->toggle_h = disp->h; } win_disp->window = _al_win_create_window(disp, disp->w, disp->h, disp->flags); if (!win_disp->window) { win_disp->thread_ended = true; destroy_display_internals(wgl_disp); SetEvent(ndp->AckEvent); return; } /* FIXME: can't _al_win_create_window() do this? */ if ((disp->flags & ALLEGRO_FULLSCREEN) || (disp->flags & ALLEGRO_FULLSCREEN_WINDOW)) { RECT rect; rect.left = 0; rect.right = disp->w; rect.top = 0; rect.bottom = disp->h; SetWindowPos(win_disp->window, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); } if (disp->flags & ALLEGRO_FULLSCREEN_WINDOW) { bool frameless = true; _al_win_set_window_frameless(disp, win_disp->window, disp->w, disp->h, frameless); } /* Yep, the following is really needed sometimes. */ /* ... Or is it now that we have dumped DInput? */ /* <rohannessian> Win98/2k/XP's window forground rules don't let us * make our window the topmost window on launch. This causes issues on * full-screen apps, as DInput loses input focus on them. * We use this trick to force the window to be topmost, when switching * to full-screen only. Note that this only works for Win98 and greater. * Win95 will ignore our SystemParametersInfo() calls. * * See http://support.microsoft.com:80/support/kb/articles/Q97/9/25.asp * for details. */ { DWORD lock_time; HWND wnd = win_disp->window; #define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000 #define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001 if (disp->flags & ALLEGRO_FULLSCREEN) { SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&lock_time, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); } ShowWindow(wnd, SW_SHOWNORMAL); SetForegroundWindow(wnd); /* In some rare cases, it doesn't seem to work without the loop. And we * absolutely need this to succeed, else we trap the user in a * fullscreen window without input. */ while (GetForegroundWindow() != wnd) { al_rest(0.01); SetForegroundWindow(wnd); } UpdateWindow(wnd); if (disp->flags & ALLEGRO_FULLSCREEN) { SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)(DWORD)lock_time, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); } #undef SPI_GETFOREGROUNDLOCKTIMEOUT #undef SPI_SETFOREGROUNDLOCKTIMEOUT } #if 0 if (disp->flags & ALLEGRO_FULLSCREEN && al_is_mouse_installed()) { RAWINPUTDEVICE rid[1]; rid[0].usUsagePage = 0x01; rid[0].usUsage = 0x02; rid[0].dwFlags = RIDEV_NOLEGACY; rid[0].hwndTarget = 0; if (RegisterRawInputDevices(rid, 1, sizeof(rid[0])) == FALSE) { ALLEGRO_ERROR( "Failed to init mouse. %s\n", get_error_desc(GetLastError())); } } #endif /* get the device context of our window */ wgl_disp->dc = GetDC(win_disp->window); win_disp->thread_ended = false; win_disp->end_thread = false; ndp->init_failed = false; SetEvent(ndp->AckEvent); while (!win_disp->end_thread) { /* get a message from the queue */ if (GetMessage(&msg, NULL, 0, 0) != 0) DispatchMessage(&msg); else break; /* WM_QUIT received or error (GetMessage returned -1) */ } if (wgl_disp->glrc) { wglDeleteContext(wgl_disp->glrc); wgl_disp->glrc = NULL; } if (wgl_disp->dc) { ReleaseDC(win_disp->window, wgl_disp->dc); wgl_disp->dc = NULL; } if (disp->flags & ALLEGRO_FULLSCREEN && !_wgl_do_not_change_display_mode) { ChangeDisplaySettings(NULL, 0); } if (win_disp->window) { DestroyWindow(win_disp->window); win_disp->window = NULL; } ALLEGRO_INFO("wgl display thread exits\n"); win_disp->thread_ended = true; }
bool _al_win_set_display_flag(ALLEGRO_DISPLAY *display, int flag, bool onoff) { ALLEGRO_DISPLAY_WIN *win_display = (void*)display; //double timeout; ALLEGRO_MONITOR_INFO mi; memset(&mi, 0, sizeof(mi)); switch (flag) { case ALLEGRO_FRAMELESS: { if (onoff) { display->flags |= ALLEGRO_FRAMELESS; } else { display->flags &= ~ALLEGRO_FRAMELESS; } _al_win_set_window_frameless(display, win_display->window, (display->flags & ALLEGRO_FRAMELESS)); return true; } case ALLEGRO_FULLSCREEN_WINDOW: if ((display->flags & ALLEGRO_FULLSCREEN_WINDOW) && onoff) { ALLEGRO_DEBUG("Already a fullscreen window\n"); return true; } if (!(display->flags & ALLEGRO_FULLSCREEN_WINDOW) && !onoff) { ALLEGRO_DEBUG("Already a non-fullscreen window\n"); return true; } if (onoff) { /* Switch off frame in fullscreen window mode. */ _al_win_set_window_frameless(display, win_display->window, true); } else { /* Respect display flag in windowed mode. */ _al_win_set_window_frameless(display, win_display->window, (display->flags & ALLEGRO_FRAMELESS)); } if (onoff) { int adapter = win_display->adapter; al_get_monitor_info(adapter, &mi); display->flags |= ALLEGRO_FULLSCREEN_WINDOW; display->w = mi.x2 - mi.x1; display->h = mi.y2 - mi.y1; } else { display->flags &= ~ALLEGRO_FULLSCREEN_WINDOW; display->w = win_display->toggle_w; display->h = win_display->toggle_h; } ASSERT(!!(display->flags & ALLEGRO_FULLSCREEN_WINDOW) == onoff); // Hide the window temporarily SetWindowPos(win_display->window, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE); al_resize_display(display, display->w, display->h); if (onoff) { // Re-set the TOPMOST flag and move to position SetWindowPos(win_display->window, HWND_TOPMOST, mi.x1, mi.y1, 0, 0, SWP_NOSIZE); // Hide the taskbar if fullscreening on primary monitor if (win_display->adapter == 0) { SetWindowPos( FindWindow("Shell_traywnd", ""), 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE); } } else { int pos_x = 0; int pos_y = 0; WINDOWINFO wi; int bw, bh; // Unset the topmost flag SetWindowPos(win_display->window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // Show the taskbar SetWindowPos( FindWindow("Shell_traywnd", ""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE); // Center the window _al_win_get_window_center(win_display, display->w, display->h, &pos_x, &pos_y); GetWindowInfo(win_display->window, &wi); bw = (wi.rcClient.left - wi.rcWindow.left) + (wi.rcWindow.right - wi.rcClient.right), bh = (wi.rcClient.top - wi.rcWindow.top) + (wi.rcWindow.bottom - wi.rcClient.bottom), SetWindowPos( win_display->window, HWND_TOP, 0, 0, display->w+bw, display->h+bh, SWP_NOMOVE ); SetWindowPos( win_display->window, HWND_TOP, pos_x-bw/2, pos_y-bh/2, 0, 0, SWP_NOSIZE ); } // Show the window again SetWindowPos(win_display->window, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE); ASSERT(!!(display->flags & ALLEGRO_FULLSCREEN_WINDOW) == onoff); return true; } return false; }