From a8e642edcf466cf92313cbf1f467a2d10de03fb4 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 26 Jul 2009 18:10:27 +0000 Subject: [PATCH] Support mouse wheel on win32 Fix fullscreen mode switching when the window is not visible Fix a memory leak in Image --- source/gbase/image.cpp | 1 + source/gbase/window.cpp | 236 ++++++++++++++++++++++------------------ source/gbase/window.h | 6 +- 3 files changed, 136 insertions(+), 107 deletions(-) diff --git a/source/gbase/image.cpp b/source/gbase/image.cpp index 81c1abe..0cd0aff 100644 --- a/source/gbase/image.cpp +++ b/source/gbase/image.cpp @@ -153,6 +153,7 @@ Image::~Image() #ifdef WITH_LIBPNG delete[] priv->data; #endif + delete priv; } void Image::load_file(const string &fn) diff --git a/source/gbase/window.cpp b/source/gbase/window.cpp index ac95b25..08cb74d 100644 --- a/source/gbase/window.cpp +++ b/source/gbase/window.cpp @@ -80,6 +80,97 @@ Window::Window(Display &dpy, const WindowOptions &opts): init(); } +void Window::init() +{ + visible=false; + kbd_autorepeat=true; + priv=new Private; + +#ifdef WIN32 + static bool wndclass_created=false; + + if(!wndclass_created) + { + WNDCLASSEX wndcl; + + wndcl.cbSize=sizeof(WNDCLASSEX); + wndcl.style=0; + wndcl.lpfnWndProc=&wndproc_; + wndcl.cbClsExtra=0; + wndcl.cbWndExtra=sizeof(Window *); + wndcl.hInstance=reinterpret_cast(Application::get_data()); + wndcl.hIcon=0; + wndcl.hCursor=LoadCursor(0, IDC_ARROW); + wndcl.hbrBackground=0; + wndcl.lpszMenuName=0; + wndcl.lpszClassName="mspgbase"; + wndcl.hIconSm=0; + + if(!RegisterClassEx(&wndcl)) + throw Exception("Couldn't register window class"); + + wndclass_created=true; + } + + 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); + + priv->window=CreateWindowEx(exstyle, + "mspgbase", + "Window", + style, + CW_USEDEFAULT, CW_USEDEFAULT, + rect.right-rect.left, rect.bottom-rect.top, + 0, + 0, + reinterpret_cast(Application::get_data()), + this); + if(!priv->window) + throw Exception("CreateWindowEx failed"); + +#else + ::Display *dpy=display.get_private().display; + + priv->wm_delete_window=XInternAtom(dpy, "WM_DELETE_WINDOW", true); + priv->invisible_cursor=0; + + XSetWindowAttributes attr; + attr.override_redirect=options.fullscreen; + attr.event_mask=ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask; + + priv->window=XCreateWindow(dpy, + DefaultRootWindow(dpy), + 0, 0, + options.width, options.height, + 0, + CopyFromParent, + InputOutput, + CopyFromParent, + CWOverrideRedirect|CWEventMask, &attr); + + XSetWMProtocols(dpy, priv->window, &priv->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, priv->window, &hints); + } + +#endif + + display.add_window(*this); + display.check_error(); +} + Window::~Window() { if(priv->window) @@ -149,16 +240,23 @@ void Window::reconfigure(const WindowOptions &opts) if(fullscreen_changed) { - hide(); + bool was_visible=visible; + + if(was_visible) + { + hide(); - // Wait for the window to be unmapped. This makes window managers happy. - XEvent ev; - XPeekIfEvent(dpy, &ev, match_event_type, reinterpret_cast(UnmapNotify)); + // Wait for the window to be unmapped. This makes window managers happy. + XEvent ev; + XPeekIfEvent(dpy, &ev, match_event_type, reinterpret_cast(UnmapNotify)); + } XSetWindowAttributes attr; attr.override_redirect=options.fullscreen; XChangeWindowAttributes(dpy, priv->window, CWOverrideRedirect, &attr); - show(); + + if(was_visible) + show(); } XSizeHints hints; @@ -178,10 +276,13 @@ void Window::reconfigure(const WindowOptions &opts) XResizeWindow(dpy, priv->window, options.width, options.height); #endif - if(options.fullscreen) - display.set_mode(VideoMode(options.width, options.height)); - else if(fullscreen_changed) - display.restore_mode(); + if(visible) + { + if(options.fullscreen) + display.set_mode(VideoMode(options.width, options.height)); + else if(fullscreen_changed) + display.restore_mode(); + } } void Window::set_keyboard_autorepeat(bool r) @@ -227,6 +328,9 @@ void Window::warp_pointer(int x, int y) { #ifndef WIN32 XWarpPointer(display.get_private().display, None, priv->window, 0, 0, 0, 0, x, y); +#else + (void)x; + (void)y; #endif } @@ -237,6 +341,15 @@ void Window::show() #else XMapRaised(display.get_private().display, priv->window); #endif + visible=true; + + if(options.fullscreen) + { + display.set_mode(VideoMode(options.width, options.height)); +#ifndef WIN32 + XWarpPointer(display.get_private().display, None, priv->window, 0, 0, 0, 0, options.width/2, options.height/2); +#endif + } } void Window::hide() @@ -246,104 +359,10 @@ void Window::hide() #else XUnmapWindow(display.get_private().display, priv->window); #endif -} - -void Window::init() -{ - kbd_autorepeat=true; - priv=new Private; - -#ifdef WIN32 - static bool wndclass_created=false; - - if(!wndclass_created) - { - WNDCLASSEX wndcl; - - wndcl.cbSize=sizeof(WNDCLASSEX); - wndcl.style=0; - wndcl.lpfnWndProc=&wndproc_; - wndcl.cbClsExtra=0; - wndcl.cbWndExtra=sizeof(Window *); - wndcl.hInstance=reinterpret_cast(Application::get_data()); - wndcl.hIcon=0; - wndcl.hCursor=LoadCursor(0, IDC_ARROW); - wndcl.hbrBackground=0; - wndcl.lpszMenuName=0; - wndcl.lpszClassName="mspgbase"; - wndcl.hIconSm=0; - - if(!RegisterClassEx(&wndcl)) - throw Exception("Couldn't register window class"); - - wndclass_created=true; - } - - 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); - - priv->window=CreateWindowEx(exstyle, - "mspgbase", - "Window", - style, - CW_USEDEFAULT, CW_USEDEFAULT, - rect.right-rect.left, rect.bottom-rect.top, - 0, - 0, - reinterpret_cast(Application::get_data()), - this); - if(!priv->window) - throw Exception("CreateWindowEx failed"); - - if(options.fullscreen) - display.set_mode(VideoMode(options.width, options.height)); - -#else - ::Display *dpy=display.get_private().display; - - priv->wm_delete_window=XInternAtom(dpy, "WM_DELETE_WINDOW", true); - priv->invisible_cursor=0; - - XSetWindowAttributes attr; - attr.override_redirect=options.fullscreen; - attr.event_mask=ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask; - - priv->window=XCreateWindow(dpy, - DefaultRootWindow(dpy), - 0, 0, - options.width, options.height, - 0, - CopyFromParent, - InputOutput, - CopyFromParent, - CWOverrideRedirect|CWEventMask, &attr); - - XSetWMProtocols(dpy, priv->window, &priv->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, priv->window, &hints); - } + visible=false; if(options.fullscreen) - { - display.set_mode(VideoMode(options.width, options.height)); - XWarpPointer(dpy, None, priv->window, 0, 0, 0, 0, options.width/2, options.height/2); - } -#endif - - display.add_window(*this); - display.check_error(); + display.restore_mode(); } bool Window::event(const Event &evnt) @@ -377,6 +396,13 @@ bool Window::event(const Event &evnt) case WM_RBUTTONUP: signal_button_release.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 3, 0); break; + case WM_MOUSEWHEEL: + { + unsigned btn = (HIWORD(wp)&0x8000) ? 5 : 4; + signal_button_press.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), btn, 0); + signal_button_release.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), btn, 0); + } + break; case WM_MOUSEMOVE: signal_pointer_motion.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp)); break; diff --git a/source/gbase/window.h b/source/gbase/window.h index 9dc84e4..ad575af 100644 --- a/source/gbase/window.h +++ b/source/gbase/window.h @@ -43,12 +43,16 @@ public: protected: Display &display; WindowOptions options; + bool visible; bool kbd_autorepeat; Private *priv; public: Window(Display &, unsigned w, unsigned h, bool fs=false); Window(Display &, const WindowOptions &); +private: + void init(); +public: ~Window(); void set_title(const std::string &); @@ -68,8 +72,6 @@ public: void hide(); bool event(const Event &evnt); -protected: - void init(); }; } // namespace Graphics -- 2.43.0