diff --git a/doomsday/client/include/clientapp.h b/doomsday/client/include/clientapp.h index e8dda2ec36..e177fee33a 100644 --- a/doomsday/client/include/clientapp.h +++ b/doomsday/client/include/clientapp.h @@ -21,6 +21,7 @@ #include #include "network/serverlink.h" +#include "ui/windowsystem.h" /** * The client application. @@ -42,6 +43,7 @@ class ClientApp : public de::GuiApp public: static ClientApp &app(); static ServerLink &serverLink(); + static WindowSystem &windowSystem(); private: DENG2_PRIVATE(d) diff --git a/doomsday/client/include/de_system.h b/doomsday/client/include/de_system.h index ddf6158a73..872e4cc27c 100644 --- a/doomsday/client/include/de_system.h +++ b/doomsday/client/include/de_system.h @@ -29,8 +29,8 @@ #ifdef __CLIENT__ # include "network/sys_network.h" # include "gl/sys_opengl.h" -# include "ui/window.h" # include "ui/sys_input.h" +# include "ui/clientwindow.h" #endif #ifdef __SERVER__ diff --git a/doomsday/client/include/de_ui.h b/doomsday/client/include/de_ui.h index f95ac90d29..7959c27068 100644 --- a/doomsday/client/include/de_ui.h +++ b/doomsday/client/include/de_ui.h @@ -28,6 +28,8 @@ #include "ui/fi_main.h" #ifdef __CLIENT__ +# include +# include "ui/windowsystem.h" # include "ui/ui_main.h" # include "ui/ui_panel.h" # include "network/ui_mpi.h" diff --git a/doomsday/client/include/gl/sys_opengl.h b/doomsday/client/include/gl/sys_opengl.h index e559dcf349..fa798d11f8 100644 --- a/doomsday/client/include/gl/sys_opengl.h +++ b/doomsday/client/include/gl/sys_opengl.h @@ -78,7 +78,7 @@ #include #include "gl_deferredapi.h" #ifdef __CLIENT__ -# include "ui/window.h" +# include "ui/clientwindow.h" #endif /** diff --git a/doomsday/client/include/ui/windowsystem.h b/doomsday/client/include/ui/windowsystem.h index e8636154a3..b2c7f78261 100644 --- a/doomsday/client/include/ui/windowsystem.h +++ b/doomsday/client/include/ui/windowsystem.h @@ -1,4 +1,8 @@ /** @file windowsystem.h Window management subsystem. + * + * @todo Deferred window changes should be done using a queue-type solution + * where it is possible to schedule multiple tasks into the future separately + * for each window. Each window could have its own queue. * * @authors Copyright (c) 2013 Jaakko Keränen * @@ -20,6 +24,9 @@ #define CLIENT_WINDOWSYSTEM_H #include +#include + +class ClientWindow; /** * Window management subsystem. @@ -31,11 +38,60 @@ */ class WindowSystem : public de::System { +public: + /// Required/referenced Window instance is missing. @ingroup errors + DENG2_ERROR(MissingWindowError); + public: WindowSystem(); - bool processEvent(de::Event const &); + /** + * Constructs a new window using the default configuration. Note that the + * default configuration is saved persistently when the engine shuts down + * and is restored when the engine is restarted. + * + * Command line options (e.g., -xpos) can be used to modify the window + * configuration. + * + * @param id Identifier of the window ("main" for the main window). + * + * @return ClientWindow instance. Ownership is retained by the window system. + */ + ClientWindow *createWindow(de::String const &id = "main"); + + /** + * Returns @c true iff a main window is available. + */ + static bool haveMain(); + /** + * Returns the main window. + */ + static ClientWindow &main(); + + /** + * Returns a pointer to the @em main window. + * + * @see haveMain() + */ + inline static ClientWindow *mainPtr() { return haveMain()? &main() : 0; } + + /** + * Find a window. + * + * @param id Window identifier. "main" for the main window. + * + * @return Window instance or @c NULL if not found. + */ + ClientWindow *find(de::String const &id) const; + + /** + * Closes all windows, including the main window. + */ + void closeAll(); + + // System. + bool processEvent(de::Event const &); void timeChanged(de::Clock const &); private: diff --git a/doomsday/client/src/busymode.cpp b/doomsday/client/src/busymode.cpp index 40122a8541..069092defc 100644 --- a/doomsday/client/src/busymode.cpp +++ b/doomsday/client/src/busymode.cpp @@ -36,8 +36,8 @@ #include #ifdef __CLIENT__ - #include "clientapp.h" +#include "ui/windowsystem.h" static void BusyMode_Exit(void); @@ -245,7 +245,7 @@ static void preBusySetup(int initialMode) ClientApp::app().loop().setRate(60); // Switch the window to busy mode UI. - Window::main().canvasWindow().setMode(CanvasWindow::Busy); + WindowSystem::main().setMode(ClientWindow::Busy); #else DENG_UNUSED(initialMode); @@ -265,7 +265,7 @@ static void postBusyCleanup() ClientApp::app().loop().setRate(0); // Switch the window to normal UI. - Window::main().canvasWindow().setMode(CanvasWindow::Normal); + WindowSystem::main().setMode(ClientWindow::Normal); #endif } @@ -437,7 +437,7 @@ void BusyMode_Loop(void) if(canUpload) { - Window::main().glActivate(); + WindowSystem::main().glActivate(); // Any deferred content needs to get uploaded. GL_ProcessDeferredTasks(15); @@ -460,7 +460,7 @@ void BusyMode_Loop(void) !Con_IsProgressAnimationCompleted()) { // Let's keep running the busy loop. - Window::main().draw(); + WindowSystem::main().draw(); return; } diff --git a/doomsday/client/src/clientapp.cpp b/doomsday/client/src/clientapp.cpp index 34ecacd3e8..59ba623109 100644 --- a/doomsday/client/src/clientapp.cpp +++ b/doomsday/client/src/clientapp.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -37,9 +38,8 @@ #include "sys_system.h" #include "audio/s_main.h" #include "gl/gl_main.h" -#include "ui/displaymode.h" #include "ui/windowsystem.h" -#include "ui/window.h" +#include "ui/clientwindow.h" #include "updater.h" #if WIN32 @@ -61,20 +61,21 @@ static void continueInitWithEventLoopRunning() { // Show the main window. This causes initialization to finish (in busy mode) // as the canvas is visible and ready for initialization. - Window::main().show(); + WindowSystem::main().show(); } DENG2_PIMPL(ClientApp) { LegacyCore *legacyCore; QMenuBar *menuBar; - WindowSystem winSys; + WindowSystem *winSys; ServerLink *svLink; Instance(Public *i) : Base(i), legacyCore(0), menuBar(0), + winSys(0), svLink(0) { clientAppSingleton = thisPublic; @@ -88,6 +89,7 @@ DENG2_PIMPL(ClientApp) LegacyCore_Delete(legacyCore); delete svLink; + delete winSys; delete menuBar; clientAppSingleton = 0; } @@ -125,9 +127,6 @@ ClientApp::ClientApp(int &argc, char **argv) QCoreApplication::setApplicationVersion (DOOMSDAY_VERSION_BASE); setTerminateFunc(handleLegacyCoreTerminate); - - // Subsystems. - addSystem(d->winSys); } void ClientApp::initialize() @@ -161,10 +160,16 @@ void ClientApp::initialize() } #endif + // Create the window system. + d->winSys = new WindowSystem; + addSystem(*d->winSys); + + Plug_LoadAll(); + // Create the main window. char title[256]; DD_ComposeMainWindowTitle(title); - Window::create(title); + d->winSys->createWindow()->setWindowTitle(title); LegacyCore_Timer(1, continueInitWithEventLoopRunning); } @@ -208,3 +213,10 @@ ServerLink &ClientApp::serverLink() DENG2_ASSERT(a.d->svLink != 0); return *a.d->svLink; } + +WindowSystem &ClientApp::windowSystem() +{ + ClientApp &a = ClientApp::app(); + DENG2_ASSERT(a.d->winSys != 0); + return *a.d->winSys; +} diff --git a/doomsday/client/src/con_main.cpp b/doomsday/client/src/con_main.cpp index 16f31274af..803dc5ae51 100644 --- a/doomsday/client/src/con_main.cpp +++ b/doomsday/client/src/con_main.cpp @@ -54,14 +54,15 @@ #include "de_filesys.h" #include "resource/fonts.h" -#include "ui/displaymode.h" #include "ui/busyvisual.h" #include "cbuffer.h" #include "Game" #ifdef __CLIENT__ +# include +# include "clientapp.h" +# include "ui/windowsystem.h" # include "updater/downloaddialog.h" -# include #endif using namespace de; @@ -2005,13 +2006,15 @@ void Con_Error(char const *error, ...) va_list argptr; #ifdef __CLIENT__ - Window::main().trapMouse(false); + ClientWindow::main().canvas().trapMouse(false); #endif // Already in an error? if(!ConsoleInited || errorInProgress) { +#ifdef __CLIENT__ DisplayMode_Shutdown(); +#endif va_start(argptr, error); dd_vsnprintf(buff, sizeof(buff), error, argptr); @@ -2074,10 +2077,9 @@ void Con_Error(char const *error, ...) void Con_AbnormalShutdown(char const *message) { Sys_Shutdown(); - DisplayMode_Shutdown(); #ifdef __CLIENT__ - Window::main().trapMouse(false); + DisplayMode_Shutdown(); DENG2_GUI_APP->loop().pause(); @@ -2085,7 +2087,7 @@ void Con_AbnormalShutdown(char const *message) // windows. (Alternatively could hide/disable drawing of the windows.) Note // that the app's event loop is running normally while we show the native // message box below. - Window::shutdown(); + ClientApp::app().windowSystem().closeAll(); #endif if(message) // Only show if a message given. diff --git a/doomsday/client/src/dd_loop.cpp b/doomsday/client/src/dd_loop.cpp index cf949b76a7..87ee5b56aa 100644 --- a/doomsday/client/src/dd_loop.cpp +++ b/doomsday/client/src/dd_loop.cpp @@ -39,7 +39,7 @@ #ifdef __CLIENT__ # include "ui/busyvisual.h" -# include "ui/window.h" +# include "ui/clientwindow.h" #endif /// Development utility: on sharp tics, print player 0 movement state. @@ -102,7 +102,7 @@ int DD_GameLoopExitCode(void) float DD_GetFrameRate() { #ifdef __CLIENT__ - return Window::main().canvasWindow().frameRate(); + return ClientWindow::main().frameRate(); #else return 0; #endif diff --git a/doomsday/client/src/dd_main.cpp b/doomsday/client/src/dd_main.cpp index f57aa379fd..e9c0d1179c 100644 --- a/doomsday/client/src/dd_main.cpp +++ b/doomsday/client/src/dd_main.cpp @@ -34,6 +34,9 @@ #include #include #include +#ifdef __CLIENT__ +# include +#endif #include "de_platform.h" @@ -60,7 +63,6 @@ #include "map/p_players.h" #include "map/p_maputil.h" #include "map/p_objlink.h" -#include "ui/displaymode.h" #include "ui/p_control.h" #include "updater.h" #include "m_misc.h" @@ -1564,7 +1566,7 @@ bool DD_ChangeGame(de::Game& game, bool allowReload = false) #ifdef __CLIENT__ char buf[256]; DD_ComposeMainWindowTitle(buf); - DENG_WINDOW->setTitle(buf); + DENG_WINDOW->setWindowTitle(buf); #endif if(!DD_IsShuttingDown()) @@ -1588,7 +1590,7 @@ bool DD_ChangeGame(de::Game& game, bool allowReload = false) #ifdef __CLIENT__ DD_ComposeMainWindowTitle(buf); - DENG_WINDOW->setTitle(buf); + DENG_WINDOW->setWindowTitle(buf); #endif /** @@ -1743,11 +1745,6 @@ int DD_EarlyInit() // Register the engine's console commands and variables. DD_Register(); -#ifdef __CLIENT__ - // Bring the window manager online. - Window::initialize(); -#endif - // Instantiate the Games collection. games = new Games(); @@ -1775,7 +1772,7 @@ void DD_FinishInitializationAfterWindowReady() { char buf[256]; DD_ComposeMainWindowTitle(buf); - DENG_WINDOW->setTitle(buf); + DENG_WINDOW->setWindowTitle(buf); } #endif diff --git a/doomsday/client/src/dd_pinit.cpp b/doomsday/client/src/dd_pinit.cpp index 0c3ef47eae..0ef7826565 100644 --- a/doomsday/client/src/dd_pinit.cpp +++ b/doomsday/client/src/dd_pinit.cpp @@ -192,7 +192,4 @@ void DD_ShutdownAll(void) F_Shutdown(); DD_ClearResourceClasses(); Libdeng_Shutdown(); -#ifdef __CLIENT__ - Window::shutdown(); -#endif } diff --git a/doomsday/client/src/gl/gl_main.cpp b/doomsday/client/src/gl/gl_main.cpp index c0e54dd6ff..9ef3ee5ef8 100644 --- a/doomsday/client/src/gl/gl_main.cpp +++ b/doomsday/client/src/gl/gl_main.cpp @@ -37,14 +37,16 @@ #include "map/gamemap.h" #include "gl/texturecontent.h" +#include "ui/windowsystem.h" #include "resource/colorpalettes.h" #include "resource/hq2x.h" #include "MaterialSnapshot" #include "MaterialVariantSpec" #include "Texture" -#include "ui/displaymode.h" #include "api_render.h" +#include + D_CMD(Fog); D_CMD(SetBPP); D_CMD(SetRes); @@ -87,18 +89,18 @@ static viewport_t currentView; static void videoFSAAChanged() { - if(novideo || !Window::haveMain()) return; - Window::main().updateCanvasFormat(); + if(novideo || !WindowSystem::haveMain()) return; + WindowSystem::main().updateCanvasFormat(); } static void videoVsyncChanged() { - if(novideo || !Window::haveMain()) return; + if(novideo || !WindowSystem::haveMain()) return; #if defined(WIN32) || defined(MACOSX) GL_SetVSync(Con_GetByte("vid-vsync") != 0); #else - Window::main().updateCanvasFormat(); + WindowSystem::main().updateCanvasFormat(); #endif } @@ -188,14 +190,14 @@ void GL_DoUpdate() Mouse_Poll(); } -void GL_GetGammaRamp(displaycolortransfer_t *ramp) +void GL_GetGammaRamp(DisplayColorTransfer *ramp) { if(!gamma_support) return; DisplayMode_GetColorTransfer(ramp); } -void GL_SetGammaRamp(displaycolortransfer_t const *ramp) +void GL_SetGammaRamp(DisplayColorTransfer const *ramp) { if(!gamma_support) return; @@ -265,7 +267,7 @@ void GL_MakeGammaRamp(ushort *ramp, float gamma, float contrast, float bright) */ void GL_SetGamma() { - displaycolortransfer_t myramp; + DisplayColorTransfer myramp; oldgamma = vid_gamma; oldcontrast = vid_contrast; @@ -1145,86 +1147,102 @@ D_CMD(SetRes) { DENG2_UNUSED3(src, argc, argv); - if(!Window::haveMain()) + ClientWindow *win = WindowSystem::mainPtr(); + + if(!win) return false; + bool isFull = win->isFullScreen(); + int attribs[] = { - Window::Width, atoi(argv[1]), - Window::Height, atoi(argv[2]), - Window::End + isFull? ClientWindow::FullscreenWidth : ClientWindow::Width, + atoi(argv[1]), + + isFull? ClientWindow::FullscreenHeight : ClientWindow::Height, + atoi(argv[2]), + + ClientWindow::End }; - return Window::main().changeAttributes(attribs); + return win->changeAttributes(attribs); } D_CMD(SetFullRes) { DENG2_UNUSED2(src, argc); - if(!Window::haveMain()) + ClientWindow *win = WindowSystem::mainPtr(); + + if(!win) return false; int attribs[] = { - Window::Width, atoi(argv[1]), - Window::Height, atoi(argv[2]), - Window::Fullscreen, true, - Window::End + ClientWindow::FullscreenWidth, atoi(argv[1]), + ClientWindow::FullscreenHeight, atoi(argv[2]), + ClientWindow::Fullscreen, true, + ClientWindow::End }; - return Window::main().changeAttributes(attribs); + return win->changeAttributes(attribs); } D_CMD(SetWinRes) { DENG2_UNUSED2(src, argc); - if(!Window::haveMain()) + ClientWindow *win = WindowSystem::mainPtr(); + + if(!win) return false; int attribs[] = { - Window::Width, atoi(argv[1]), - Window::Height, atoi(argv[2]), - Window::Fullscreen, false, - Window::End + ClientWindow::Width, atoi(argv[1]), + ClientWindow::Height, atoi(argv[2]), + ClientWindow::Fullscreen, false, + ClientWindow::End }; - return Window::main().changeAttributes(attribs); + return win->changeAttributes(attribs); } D_CMD(ToggleFullscreen) { DENG2_UNUSED3(src, argc, argv); - if(!Window::haveMain()) + ClientWindow *win = WindowSystem::mainPtr(); + + if(!win) return false; - Window &mainWindow = Window::main(); int attribs[] = { - Window::Fullscreen, !mainWindow.isFullscreen(), - Window::End + ClientWindow::Fullscreen, !win->isFullScreen(), + ClientWindow::End }; - return mainWindow.changeAttributes(attribs); + return win->changeAttributes(attribs); } D_CMD(SetBPP) { DENG2_UNUSED2(src, argc); - if(!Window::haveMain()) + ClientWindow *win = WindowSystem::mainPtr(); + + if(!win) return false; int attribs[] = { - Window::ColorDepthBits, atoi(argv[1]), - Window::End + ClientWindow::ColorDepthBits, atoi(argv[1]), + ClientWindow::End }; - return Window::main().changeAttributes(attribs); + return win->changeAttributes(attribs); } D_CMD(DisplayModeInfo) { DENG2_UNUSED3(src, argc, argv); - if(!Window::haveMain()) + ClientWindow *win = WindowSystem::mainPtr(); + + if(!win) return false; - Window const &mainWindow = Window::main(); DisplayMode const *mode = DisplayMode_Current(); QString str = QString("Current display mode:%1 depth:%2 (%3:%4") @@ -1234,17 +1252,16 @@ D_CMD(DisplayModeInfo) .arg(mode->ratioY); if(mode->refreshRate > 0) { - str += QString(", refresh: %1 Hz").arg(mode->refreshRate, 0, 'f', 3); + str += QString(", refresh: %1 Hz").arg(mode->refreshRate, 0, 'f', 1); } - str += QString(")\nMain window:\n origin:%1 dimensions:%2\n windowed-origin:%1 windowed-dimensions:%2") - .arg(de::Vector2i(mainWindow.x(), mainWindow.y()).asText()) - .arg(de::Vector2i(mainWindow.width(), mainWindow.height()).asText()) - .arg(de::Vector2i(mainWindow.normalX(), mainWindow.normalY()).asText()) - .arg(de::Vector2i(mainWindow.normalWidth(), mainWindow.normalHeight()).asText()); - str += QString("\n fullscreen:%3 centered:%4 maximized:%5") - .arg(mainWindow.isFullscreen() ? "yes" : "no") - .arg(mainWindow.isCentered() ? "yes" : "no") - .arg(mainWindow.isMaximized() ? "yes" : "no"); + str += QString(")\nMain window:\n origin:%1 dimensions:%2\n fullscreen-dimensions:%3") + .arg(de::Vector2i(win->x(), win->y()).asText()) + .arg(de::Vector2i(win->width(), win->height()).asText()) + .arg(de::Vector2i(win->fullscreenWidth(), win->fullscreenHeight()).asText()); + str += QString("\n fullscreen:%1 centered:%2 maximized:%3") + .arg(win->isFullScreen() ? "yes" : "no") + .arg(win->isCentered() ? "yes" : "no") + .arg(win->isMaximized() ? "yes" : "no"); Con_Message(str.toUtf8().constData()); return true; diff --git a/doomsday/client/src/m_misc.cpp b/doomsday/client/src/m_misc.cpp index 547532976a..047234b3b3 100644 --- a/doomsday/client/src/m_misc.cpp +++ b/doomsday/client/src/m_misc.cpp @@ -414,7 +414,7 @@ DENG_EXTERN_C int M_ScreenShot(char const *name, int bits) } F_ToNativeSlashes(&fullName, &fullName); - bool result = Window::main().grabToFile(Str_Text(&fullName)); + bool result = ClientWindow::main().grabToFile(Str_Text(&fullName)); Str_Free(&fullName); return result? 1 : 0; diff --git a/doomsday/client/src/ui/busyvisual.cpp b/doomsday/client/src/ui/busyvisual.cpp index ce52e4d4ba..9da6faab1b 100644 --- a/doomsday/client/src/ui/busyvisual.cpp +++ b/doomsday/client/src/ui/busyvisual.cpp @@ -63,7 +63,7 @@ static void acquireScreenshotTexture() startTime = Timer_RealSeconds(); #endif - texScreenshot = Window::main().grabAsTexture(true /*halfsized*/); + texScreenshot = ClientWindow::main().grabAsTexture(ClientWindow::GrabHalfSized); DEBUG_Message(("Busy Mode: Took %.2f seconds acquiring screenshot texture #%i.\n", Timer_RealSeconds() - startTime, texScreenshot)); diff --git a/doomsday/client/src/ui/busywidget.cpp b/doomsday/client/src/ui/busywidget.cpp index b626ea9e2a..d8013b3e4d 100644 --- a/doomsday/client/src/ui/busywidget.cpp +++ b/doomsday/client/src/ui/busywidget.cpp @@ -23,7 +23,7 @@ #include "sys_system.h" #include "render/r_main.h" #include "ui/ui_main.h" -#include "ui/window.h" +#include "ui/clientwindow.h" #include @@ -43,7 +43,7 @@ void BusyWidget::viewResized() { if(!BusyMode_Active() || isDisabled() || Sys_IsShuttingDown()) return; - Window::main().glActivate(); // needed for legacy stuff + ClientWindow::main().glActivate(); // needed for legacy stuff //DENG_ASSERT(BusyMode_Active()); diff --git a/doomsday/client/src/ui/dd_input.cpp b/doomsday/client/src/ui/dd_input.cpp index 53fca4127a..3a7882a68e 100644 --- a/doomsday/client/src/ui/dd_input.cpp +++ b/doomsday/client/src/ui/dd_input.cpp @@ -33,6 +33,8 @@ #include "dd_main.h" #include "dd_loop.h" +#include "ui/windowsystem.h" + // For the debug visuals: #if _DEBUG # include "de_graphics.h" @@ -103,9 +105,9 @@ static char defaultShiftTable[96] = // Contains characters 32 to 127. }; static repeater_t keyReps[MAX_DOWNKEYS]; -#ifdef __CLIENT__ + static float oldPOV = IJOY_POV_CENTER; -#endif + static char* eventStrings[MAXEVENTS]; static boolean uiMouseMode = false; // Can mouse data be modified? @@ -210,8 +212,6 @@ void I_InitVirtualInputDevices(void) strcpy(dev->name, "key"); I_DeviceAllocKeys(dev, 256); -#ifdef __CLIENT__ - // The mouse may not be active. dev = &inputDevices[IDEV_MOUSE]; strcpy(dev->niceName, "Mouse"); @@ -295,8 +295,6 @@ void I_InitVirtualInputDevices(void) // The joystick may not be active. if(Joystick_IsPresent()) dev->flags = ID_ACTIVE; - -#endif // __CLIENT__ } /** @@ -1366,8 +1364,6 @@ void I_SetUIMouseMode(boolean on) #endif } -#ifdef __CLIENT__ - /** * Checks the current mouse state (axis, buttons and wheel). * Generates events and mickeys and posts them. @@ -2229,7 +2225,6 @@ void Rend_AllInputDeviceStateVisuals(void) #undef SPACING } #endif // _DEBUG -#endif // __CLIENT__ static void I_PrintAxisConfig(inputdev_t* device, inputdevaxis_t* axis) { @@ -2367,12 +2362,11 @@ D_CMD(ListInputDevices) D_CMD(ReleaseMouse) { DENG2_UNUSED3(src, argc, argv); -#ifdef __CLIENT__ - if(Window::haveMain()) + + if(WindowSystem::haveMain()) { - Window::main().trapMouse(false); + WindowSystem::main().canvas().trapMouse(false); return true; } -#endif return false; } diff --git a/doomsday/client/src/ui/legacywidget.cpp b/doomsday/client/src/ui/legacywidget.cpp index a784d30345..80a8d69699 100644 --- a/doomsday/client/src/ui/legacywidget.cpp +++ b/doomsday/client/src/ui/legacywidget.cpp @@ -22,6 +22,7 @@ #include "ui/ui_main.h" #include "ui/ui2_main.h" #include "ui/busyvisual.h" +#include "ui/windowsystem.h" #include "dd_def.h" #include "dd_main.h" #include "dd_loop.h" @@ -87,7 +88,7 @@ void LegacyWidget::update() DENG2_ASSERT(!BusyMode_Active()); // We may be performing GL operations. - Window::main().glActivate(); + ClientWindow::main().glActivate(); // Run at least one (fractional) tic. Loop_RunTics(); @@ -100,7 +101,7 @@ void LegacyWidget::update() GL_ProcessDeferredTasks(FRAME_DEFERRED_UPLOAD_TIMEOUT); // Request update of window contents. - Window::main().draw(); + root().window().draw(); // After the first frame, start timedemo. //DD_CheckTimeDemo(); diff --git a/doomsday/client/src/ui/mouse_qt.cpp b/doomsday/client/src/ui/mouse_qt.cpp index 9ef743107f..7cafd65af3 100644 --- a/doomsday/client/src/ui/mouse_qt.cpp +++ b/doomsday/client/src/ui/mouse_qt.cpp @@ -24,9 +24,9 @@ #include "de_base.h" #include "con_main.h" #include "ui/sys_input.h" -#include "ui/window.h" +#include "ui/windowsystem.h" +#include "ui/clientwindow.h" #include "ui/mouse_qt.h" -#include "ui/canvas.h" #include #include @@ -62,11 +62,10 @@ static void Mouse_Qt_Poll() { if(!mouseTrapped) return; - Window &mainWindow = Window::main(); - QWidget *widget = mainWindow.widgetPtr(); - if(!widget) return; // Hmm? + ClientWindow *win = WindowSystem::mainPtr(); + if(!win) return; // Hmm? - QPoint curPos = widget->mapFromGlobal(QCursor::pos()); + QPoint curPos = win->mapFromGlobal(QCursor::pos()); if(!prevMousePos.isNull()) { QPoint delta = curPos - prevMousePos; @@ -75,8 +74,8 @@ static void Mouse_Qt_Poll() Mouse_Qt_SubmitMotion(IMA_POINTER, delta.x(), delta.y()); // Keep the cursor centered. - QPoint mid(mainWindow.width() / 2, mainWindow.height() / 2); - QCursor::setPos(widget->mapToGlobal(mid)); + QPoint mid(win->width() / 2, win->height() / 2); + QCursor::setPos(win->mapToGlobal(mid)); prevMousePos = mid; } } diff --git a/doomsday/client/src/ui/ui_main.cpp b/doomsday/client/src/ui/ui_main.cpp index 8f53bb5b3e..5b8cb7fd95 100644 --- a/doomsday/client/src/ui/ui_main.cpp +++ b/doomsday/client/src/ui/ui_main.cpp @@ -493,7 +493,7 @@ void UI_Drawer(void) uiCurrentPage->drawer(uiCurrentPage); // Draw mouse cursor? - if(!uiNoMouse && DENG_WINDOW->isMouseTrapped()) + if(!uiNoMouse && DENG_WINDOW->canvas().isMouseTrapped()) { Point2Raw origin; Size2Raw size; diff --git a/doomsday/client/src/ui/ui_panel.cpp b/doomsday/client/src/ui/ui_panel.cpp index 628b596016..e65e09c786 100644 --- a/doomsday/client/src/ui/ui_panel.cpp +++ b/doomsday/client/src/ui/ui_panel.cpp @@ -31,9 +31,10 @@ #include "de_graphics.h" #include "de_ui.h" -#include "ui/displaymode.h" #include "render/rend_font.h" +#include + // MACROS ------------------------------------------------------------------ #define NUM_CP_BUTTONS 11 @@ -871,12 +872,12 @@ void CP_VideoModeInfo(ui_object_t *ob) } else { - Window const &mainWindow = Window::main(); + ClientWindow const &mainWindow = WindowSystem::main(); sprintf(buf, "%i x %i x %i (%s)", mainWindow.width(), mainWindow.height(), mainWindow.colorDepthBits(), - (mainWindow.isFullscreen()? "fullscreen" : "windowed")); + (mainWindow.isFullScreen()? "fullscreen" : "windowed")); } DENG_ASSERT_IN_MAIN_THREAD(); @@ -896,8 +897,8 @@ void CP_VideoModeInfo(ui_object_t *ob) void CP_UpdateSetVidModeButton(int w, int h, int bpp, bool fullscreen) { - Window &mainWindow = Window::main(); - bool cFullscreen = mainWindow.isFullscreen(); + ClientWindow &mainWindow = WindowSystem::main(); + bool isFull = mainWindow.isFullScreen(); ui_object_t* ob; ob = UI_FindObject(ob_panel, CPG_VIDEO, CPID_SET_RES); @@ -906,8 +907,11 @@ void CP_UpdateSetVidModeButton(int w, int h, int bpp, bool fullscreen) sprintf(ob->text, "%i x %i x %i (%s)", w, h, bpp, fullscreen? "fullscreen" : "windowed"); - if(w == mainWindow.width() && h == mainWindow.height() && - bpp == mainWindow.colorDepthBits() && fullscreen == cFullscreen) + int winWidth = (isFull? mainWindow.fullscreenWidth() : mainWindow.width()); + int winHeight = (isFull? mainWindow.fullscreenHeight() : mainWindow.height()); + + if(w == winWidth && h == winHeight && + bpp == mainWindow.colorDepthBits() && fullscreen == isFull) ob->flags |= UIF_DISABLED; else ob->flags &= ~UIF_DISABLED; @@ -948,16 +952,16 @@ void CP_SetVidMode(ui_object_t* ob) ob->flags |= UIF_DISABLED; - if(Window::haveMain()) + if(WindowSystem::haveMain()) { int attribs[] = { - Window::Width, x, - Window::Height, y, - Window::ColorDepthBits, bpp, - Window::Fullscreen, panel_fullscreen != 0, - Window::End + ClientWindow::Fullscreen, panel_fullscreen != 0, + panel_fullscreen? ClientWindow::FullscreenWidth : ClientWindow::Width, x, + panel_fullscreen? ClientWindow::FullscreenHeight : ClientWindow::Height, y, + ClientWindow::ColorDepthBits, bpp, + ClientWindow::End }; - Window::main().changeAttributes(attribs); + WindowSystem::main().changeAttributes(attribs); } } @@ -1315,19 +1319,20 @@ D_CMD(OpenPanel) CP_InitCvarSliders(ob_panel); // Update width the current resolution. - Window &mainWindow = Window::main(); - bool cFullscreen = mainWindow.isFullscreen(); + ClientWindow &mainWindow = ClientWindow::main(); + bool isFull = mainWindow.isFullScreen(); ob = UI_FindObject(ob_panel, CPG_VIDEO, CPID_RES_LIST); list = (uidata_list_t *) ob->data; list->selection = UI_ListFindItem(ob, - RES(mainWindow.width(), mainWindow.height())); + RES(isFull? mainWindow.fullscreenWidth() : mainWindow.width(), + isFull? mainWindow.fullscreenHeight() : mainWindow.height())); if(list->selection == -1) { // Then use a reasonable default. list->selection = UI_ListFindItem(ob, RES(640, 480)); } - panel_fullscreen = cFullscreen; + panel_fullscreen = isFull; panel_bpp = (mainWindow.colorDepthBits() == 32? 1 : 0); CP_ResolutionList(ob); diff --git a/doomsday/client/src/ui/windowsystem.cpp b/doomsday/client/src/ui/windowsystem.cpp index 5456d124c1..778d1648d9 100644 --- a/doomsday/client/src/ui/windowsystem.cpp +++ b/doomsday/client/src/ui/windowsystem.cpp @@ -18,28 +18,74 @@ #include "de_platform.h" #include "ui/windowsystem.h" -#include "ui/window.h" +#include "ui/clientwindow.h" +#include "clientapp.h" + +#include using namespace de; DENG2_PIMPL(WindowSystem) { - /// @todo Creation and ownership of windows belongs here (from window.cpp). + typedef QMap Windows; + Windows windows; Instance(Public *i) : Base(i) {} + + ~Instance() + { + self.closeAll(); + } }; WindowSystem::WindowSystem() : System(ObservesTime | ReceivesInputEvents), d(new Instance(this)) -{} +{ + ClientWindow::setDefaultGLFormat(); +} + +ClientWindow *WindowSystem::createWindow(String const &id) +{ + DENG2_ASSERT(!d->windows.contains(id)); + + ClientWindow *win = new ClientWindow(id); + d->windows.insert(id, win); + return win; +} + +bool WindowSystem::haveMain() // static +{ + return ClientApp::app().windowSystem().d->windows.contains("main"); +} + +ClientWindow &WindowSystem::main() // static +{ + return static_cast(PersistentCanvasWindow::main()); +} + +ClientWindow *WindowSystem::find(String const &id) const +{ + Instance::Windows::const_iterator found = d->windows.constFind(id); + if(found != d->windows.constEnd()) + { + return found.value(); + } + return 0; +} + +void WindowSystem::closeAll() +{ + qDeleteAll(d->windows.values()); + d->windows.clear(); +} bool WindowSystem::processEvent(Event const &event) { - return Window::main().canvasWindow().root().processEvent(event); + return main().root().processEvent(event); } void WindowSystem::timeChanged(Clock const &/*clock*/) { - Window::main().canvasWindow().root().update(); + main().root().update(); } diff --git a/doomsday/client/src/unix/dd_uinit.cpp b/doomsday/client/src/unix/dd_uinit.cpp index c974e64279..76835a7fb7 100644 --- a/doomsday/client/src/unix/dd_uinit.cpp +++ b/doomsday/client/src/unix/dd_uinit.cpp @@ -1,4 +1,4 @@ -/**\file dd_uinit.cpp +/** @file dd_uinit.cpp Engine Initialization (Unix). * * @authors Copyright © 2004-2013 Jaakko Keränen * @authors Copyright © 2006-2013 Daniel Swanson @@ -18,14 +18,6 @@ * http://www.gnu.org/licenses */ -/** - * Engine Initialization - Unix. - * - * Load libraries and set up APIs. - */ - -// HEADER FILES ------------------------------------------------------------ - #include #include #include @@ -46,30 +38,15 @@ #include "de_network.h" #include "de_misc.h" -#include "ui/displaymode.h" #include "filesys/fs_util.h" #include "dd_uinit.h" -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ +#ifdef __CLIENT__ +# include +#endif application_t app; -// CODE -------------------------------------------------------------------- - #ifdef __CLIENT__ static int initDGL(void) { @@ -190,8 +167,6 @@ boolean DD_Unix_Init(void) failed = false; } - Plug_LoadAll(); - return !failed; } @@ -205,5 +180,7 @@ void DD_Shutdown(void) Plug_UnloadAll(); Library_Shutdown(); +#ifdef __CLIENT__ DisplayMode_Shutdown(); +#endif } diff --git a/doomsday/client/src/updater/downloaddialog.cpp b/doomsday/client/src/updater/downloaddialog.cpp index df1c49bed3..ffc8fd3ba9 100644 --- a/doomsday/client/src/updater/downloaddialog.cpp +++ b/doomsday/client/src/updater/downloaddialog.cpp @@ -24,7 +24,6 @@ #include "downloaddialog.h" #include "updatersettings.h" #include "dd_version.h" -#include "ui/window.h" #include #include #include diff --git a/doomsday/client/src/updater/updateavailabledialog.cpp b/doomsday/client/src/updater/updateavailabledialog.cpp index 1fd1bf15c4..c846be248d 100644 --- a/doomsday/client/src/updater/updateavailabledialog.cpp +++ b/doomsday/client/src/updater/updateavailabledialog.cpp @@ -24,7 +24,6 @@ #include "updatersettings.h" #include "updatersettingsdialog.h" #include "versioninfo.h" -#include "ui/window.h" #include #include #include diff --git a/doomsday/client/src/updater/updater.cpp b/doomsday/client/src/updater/updater.cpp index 054e12d093..de1dd1a5d7 100644 --- a/doomsday/client/src/updater/updater.cpp +++ b/doomsday/client/src/updater/updater.cpp @@ -49,7 +49,8 @@ #include "dd_main.h" #include "con_main.h" #include "ui/nativeui.h" -#include "ui/window.h" +#include "ui/windowsystem.h" +#include "ui/clientwindow.h" #include "updater.h" #include "downloaddialog.h" #include "processcheckdialog.h" @@ -107,11 +108,11 @@ static void runInstallerCommand(void) static bool switchToWindowedMode() { - Window &mainWindow = Window::main(); - bool wasFull = mainWindow.isFullscreen(); + ClientWindow &mainWindow = WindowSystem::main(); + bool wasFull = mainWindow.isFullScreen(); if(wasFull) { - int attribs[] = { Window::Fullscreen, false, Window::End }; + int attribs[] = { ClientWindow::Fullscreen, false, ClientWindow::End }; mainWindow.changeAttributes(attribs); } return wasFull; @@ -121,8 +122,8 @@ static void switchBackToFullscreen(bool wasFull) { if(wasFull) { - int attribs[] = { Window::Fullscreen, true, Window::End }; - Window::main().changeAttributes(attribs); + int attribs[] = { ClientWindow::Fullscreen, true, ClientWindow::End }; + ClientWindow::main().changeAttributes(attribs); } } @@ -242,7 +243,7 @@ DENG2_PIMPL(Updater) { if(!settingsDlg) { - settingsDlg = new UpdaterSettingsDialog(Window::main().widgetPtr()); + settingsDlg = new UpdaterSettingsDialog(&ClientWindow::main()); QObject::connect(settingsDlg, SIGNAL(finished(int)), thisPublic, SLOT(settingsDialogClosed(int))); } else @@ -313,7 +314,7 @@ DENG2_PIMPL(Updater) // Automatically switch to windowed mode for convenience. bool wasFull = switchToWindowedMode(); - UpdateAvailableDialog dlg(latestVersion, latestLogUri, Window::main().widgetPtr()); + UpdateAvailableDialog dlg(latestVersion, latestLogUri, &ClientWindow::main()); availableDlg = &dlg; execAvailableDialog(wasFull); } @@ -536,7 +537,7 @@ void Updater::checkNowShowingProgress() // Not if there is an ongoing download. if(d->download) return; - d->availableDlg = new UpdateAvailableDialog(Window::main().widgetPtr()); + d->availableDlg = new UpdateAvailableDialog(&ClientWindow::main()); d->queryLatestVersion(true); d->execAvailableDialog(false); diff --git a/doomsday/client/src/windows/dd_winit.cpp b/doomsday/client/src/windows/dd_winit.cpp index d7f759e7fe..cdccfc2152 100644 --- a/doomsday/client/src/windows/dd_winit.cpp +++ b/doomsday/client/src/windows/dd_winit.cpp @@ -1,4 +1,4 @@ -/** @file dd_winit.cpp +/** @file dd_winit.cpp Engine Initialization (Windows). * * @authors Copyright © 2003-2013 Jaakko Keränen * @authors Copyright © 2005-2013 Daniel Swanson @@ -17,14 +17,6 @@ * http://www.gnu.org/licenses */ -/** - * Engine Initialization - Windows. - * - * Create windows, load DLLs, setup APIs. - */ - -// HEADER FILES ------------------------------------------------------------ - #define WIN32_LEAN_AND_MEAN #define _WIN32_DCOM #define STRICT @@ -50,33 +42,15 @@ #include "filesys/fs_util.h" #include "dd_winit.h" -#include "ui/displaymode.h" - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- +#include application_t app; -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - #ifdef UNICODE static LPWSTR convBuf; static LPSTR utf8ConvBuf; #endif -// CODE -------------------------------------------------------------------- - #ifdef UNICODE LPCWSTR ToWideString(const char* str) { @@ -111,8 +85,8 @@ LPCSTR ToAnsiString(const wchar_t* wstr) * \note GetLastError() should only be called when we *know* an error was thrown. * The result of calling this any other time is undefined. * - * @return Ptr to a string containing a textual representation of - * the last error thrown in the current thread else @c NULL. + * @return Ptr to a string containing a textual representation of the last + * error thrown in the current thread else @c NULL. */ const char* DD_Win32_GetLastErrorMessage(void) { @@ -267,8 +241,6 @@ boolean DD_Win32_Init(void) failed = FALSE; } - Plug_LoadAll(); - #ifdef __CLIENT__ // No Windows system keys? if(CommandLine_Check("-nowsk"))