From 881ad898c45954f95972091554af25d775b8c2a8 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 23 Jul 2008 15:14:27 +0000 Subject: [PATCH] Implement video mode changing and fullscreen on win32 Implement resizable flag of WindowOptions Guard against FPE in refresh rate calculation on X11 Handle window resizing on win32 --- source/gbase/display.cpp | 51 ++++++++++++++++++++----- source/gbase/glcontext.cpp | 5 +-- source/gbase/window.cpp | 76 ++++++++++++++++++++++++++++++++------ 3 files changed, 107 insertions(+), 25 deletions(-) diff --git a/source/gbase/display.cpp b/source/gbase/display.cpp index 3baf7c1..b39330b 100644 --- a/source/gbase/display.cpp +++ b/source/gbase/display.cpp @@ -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 } diff --git a/source/gbase/glcontext.cpp b/source/gbase/glcontext.cpp index a749c6c..c002a39 100644 --- a/source/gbase/glcontext.cpp +++ b/source/gbase/glcontext.cpp @@ -16,9 +16,6 @@ Distributed under the LGPL #include "glcontext.h" #include "window.h" -#include -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() diff --git a/source/gbase/window.cpp b/source/gbase/window.cpp index 4a14441..3ba8d76 100644 --- a/source/gbase/window.cpp +++ b/source/gbase/window.cpp @@ -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; -- 2.45.2