]> git.tdb.fi Git - libs/gui.git/commitdiff
Implement video mode changing and fullscreen on win32
authorMikko Rasa <tdb@tdb.fi>
Wed, 23 Jul 2008 15:14:27 +0000 (15:14 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 23 Jul 2008 15:14:27 +0000 (15:14 +0000)
Implement resizable flag of WindowOptions
Guard against FPE in refresh rate calculation on X11
Handle window resizing on win32

source/gbase/display.cpp
source/gbase/glcontext.cpp
source/gbase/window.cpp

index 3baf7c11a72e92eb1a1827666f247198d85e21aa..b39330be1c9fc3353cc387fad8f38241a8b7b765 100644 (file)
@@ -54,7 +54,27 @@ namespace Graphics {
 
 Display::Display(const string &disp_name)
 {
-#ifndef WIN32
+#ifdef WIN32
+       (void)disp_name;
+
+       for(unsigned i=0;; ++i)
+       {
+               DEVMODE info;
+               if(!EnumDisplaySettings(0, i, &info))
+                       break;
+
+               VideoMode mode(info.dmPelsWidth, info.dmPelsHeight);
+               mode.rate=info.dmDisplayFrequency;
+               modes.push_back(mode);
+       }
+       
+       DEVMODE info;
+       if(EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &info))
+       {
+               orig_mode=VideoMode(info.dmPelsWidth, info.dmPelsHeight);
+               orig_mode.rate=info.dmDisplayFrequency;
+       }
+#else
        if(disp_name.empty())
                display=XOpenDisplay(0);
        else
@@ -74,7 +94,8 @@ Display::Display(const string &disp_name)
                XF86VidModeModeInfo &info=*infos[i];
        
                VideoMode mode(info.hdisplay, info.vdisplay);
-               mode.rate=info.dotclock/(info.htotal*info.vtotal);
+               if(info.htotal && info.vtotal)
+                       mode.rate=info.dotclock/(info.htotal*info.vtotal);
                modes.push_back(mode);
        }
 
@@ -84,9 +105,8 @@ Display::Display(const string &disp_name)
        int dotclock;
        XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
        orig_mode=VideoMode(modeline.hdisplay, modeline.vdisplay);
-       orig_mode.rate=dotclock/(modeline.htotal*modeline.vtotal);
-#else
-       (void)disp_name;
+       if(modeline.htotal && modeline.vtotal)
+               orig_mode.rate=dotclock/(modeline.htotal*modeline.vtotal);
 #endif
 }
 
@@ -110,7 +130,20 @@ void Display::remove_window(Window *wnd)
 
 void Display::set_mode(const VideoMode &mode)
 {
-#ifndef WIN32
+#ifdef WIN32
+       DEVMODE info;
+       info.dmSize=sizeof(DEVMODE);
+       info.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT;
+       info.dmPelsWidth=mode.width;
+       info.dmPelsHeight=mode.height;
+       if(mode.rate)
+       {
+               info.dmFields|=DM_DISPLAYFREQUENCY;
+               info.dmDisplayFrequency=mode.rate;
+       }
+
+       ChangeDisplaySettings(&info, CDS_FULLSCREEN);
+#else
        int screen=DefaultScreen(display);
 
        int nmodes;
@@ -120,7 +153,9 @@ void Display::set_mode(const VideoMode &mode)
        {
                XF86VidModeModeInfo &info=*infos[i];
 
-               unsigned rate=info.dotclock/(info.htotal*info.vtotal);
+               unsigned rate=0;
+               if(info.htotal && info.vtotal)
+                       rate=info.dotclock/(info.htotal*info.vtotal);
                if(info.hdisplay==mode.width && info.vdisplay==mode.height && (mode.rate==0 || rate==mode.rate))
                {
                        XF86VidModeSwitchToMode(display, screen, &info);
@@ -130,8 +165,6 @@ void Display::set_mode(const VideoMode &mode)
        }
 
        throw InvalidParameterValue("Requested mode not supported");
-#else
-       (void)mode;
 #endif
 }
 
index a749c6ce8f3966dbfc7514180a25a76603e29724..c002a39dd0c3c41d43ddec5670969cc599f47f7e 100644 (file)
@@ -16,9 +16,6 @@ Distributed under the LGPL
 #include "glcontext.h"
 #include "window.h"
 
-#include <iostream>
-using namespace std;
-
 namespace Msp {
 namespace Graphics {
 
@@ -107,9 +104,9 @@ GLContext::GLContext(Window &wnd, const GLOptions &opts):
        XFree(vi);
 
        glXMakeCurrent(dpy, subwnd, context);
+#endif
 
        window.signal_resize.connect(sigc::mem_fun(this, &GLContext::window_resized));
-#endif
 }
 
 GLContext::~GLContext()
index 4a14441e9c3704507520135239ac63ae729ea14d..3ba8d767a90e9edf5b9392bd2ef5d3d5b4f62e2d 100644 (file)
@@ -85,15 +85,32 @@ void Window::reconfigure(const WindowOptions &opts)
        options=opts;
 
 #ifdef WIN32
-       // XXX Preserve position
-       MoveWindow(window, 0, 0, options.width, options.height, false);
+       RECT rect;
+       SetRect(&rect, 0, 0, options.width, options.height);
+
+       int style=(options.fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW);
+       if(!options.resizable)
+               style&=~WS_THICKFRAME;
+       int exstyle=(options.fullscreen ? WS_EX_APPWINDOW : WS_EX_OVERLAPPEDWINDOW);
+       AdjustWindowRectEx(&rect, style, false, exstyle);
+
+       if(fullscreen_changed)
+       {
+               hide();
+               SetWindowLong(window, GWL_EXSTYLE, exstyle);
+               SetWindowLong(window, GWL_STYLE, style);
+               show();
+       }
+
+       if(options.fullscreen)
+               SetWindowPos(window, 0, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOZORDER);
+       else
+               SetWindowPos(window, 0, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER);
 
        (void)fullscreen_changed;
 #else
        ::Display *dpy=display.get_display();
 
-       XMoveResizeWindow(dpy, window, 0, 0, options.width, options.height);
-
        if(fullscreen_changed)
        {
                hide();
@@ -103,11 +120,27 @@ void Window::reconfigure(const WindowOptions &opts)
                show();
        }
 
+       XSizeHints hints;
+       if(options.resizable)
+               hints.flags=0;
+       else
+       {
+               hints.flags=PMinSize|PMaxSize;
+               hints.min_width=hints.max_width=options.width;
+               hints.min_height=hints.max_height=options.height;
+       }
+       XSetWMNormalHints(dpy, window, &hints);
+
+       if(options.fullscreen)
+               XMoveResizeWindow(dpy, window, 0, 0, options.width, options.height);
+       else
+               XResizeWindow(dpy, window, options.width, options.height);
+#endif
+
        if(options.fullscreen)
                display.set_mode(VideoMode(options.width, options.height));
        else if(fullscreen_changed)
                display.restore_mode();
-#endif
 }
 
 void Window::show()
@@ -159,16 +192,18 @@ void Window::init()
        }
 
        RECT rect;
-       rect.left=0;
-       rect.top=0;
-       rect.right=options.width;
-       rect.bottom=options.height;
-       AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
+       SetRect(&rect, 0, 0, options.width, options.height);
 
-       window=CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
+       int style=(options.fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW);
+       if(!options.resizable)
+               style&=~WS_THICKFRAME;
+       int exstyle=(options.fullscreen ? WS_EX_APPWINDOW : WS_EX_OVERLAPPEDWINDOW);
+       AdjustWindowRectEx(&rect, style, false, exstyle);
+
+       window=CreateWindowEx(exstyle,
                "mspgbase",
                "Window",
-               WS_OVERLAPPEDWINDOW,
+               style,
                CW_USEDEFAULT, CW_USEDEFAULT,
                rect.right-rect.left, rect.bottom-rect.top,
                0,
@@ -178,6 +213,9 @@ void Window::init()
        if(!window)
                throw Exception("CreateWindowEx failed");
 
+       if(options.fullscreen)
+               display.set_mode(VideoMode(options.width, options.height));
+
 #else
        ::Display *dpy=display.get_display();
 
@@ -199,6 +237,15 @@ void Window::init()
 
        XSetWMProtocols(dpy, window, &wm_delete_window, 1);
 
+       if(!options.resizable)
+       {
+               XSizeHints hints;
+               hints.flags=PMinSize|PMaxSize;
+               hints.min_width=hints.max_width=options.width;
+               hints.min_height=hints.max_height=options.height;
+               XSetWMNormalHints(dpy, window, &hints);
+       }
+
        if(options.fullscreen)
        {
                display.set_mode(VideoMode(options.width, options.height));
@@ -288,6 +335,11 @@ int Window::wndproc(UINT msg, WPARAM wp, LPARAM lp)
        case WM_MOUSEMOVE:
                signal_pointer_motion.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
                break;
+       case WM_SIZE:
+               options.width=LOWORD(lp);
+               options.height=HIWORD(lp);
+               signal_resize.emit(options.width, options.height);
+               break;
        case WM_CLOSE:
                signal_close.emit();
                break;