]> git.tdb.fi Git - libs/gui.git/commitdiff
Support mouse wheel on win32
authorMikko Rasa <tdb@tdb.fi>
Sun, 26 Jul 2009 18:10:27 +0000 (18:10 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sun, 26 Jul 2009 18:10:27 +0000 (18:10 +0000)
Fix fullscreen mode switching when the window is not visible
Fix a memory leak in Image

source/gbase/image.cpp
source/gbase/window.cpp
source/gbase/window.h

index 81c1abef340e05c95ab3243789eb3bf8b9b369a0..0cd0aff4c78340e16c64ce38fcb8ece76075e194 100644 (file)
@@ -153,6 +153,7 @@ Image::~Image()
 #ifdef WITH_LIBPNG
        delete[] priv->data;
 #endif
+       delete priv;
 }
 
 void Image::load_file(const string &fn)
index ac95b25ec1019e82812ac80a0f48cac327b528d6..08cb74db081807edd765c6a0115a40684c913696 100644 (file)
@@ -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<HINSTANCE>(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<HINSTANCE>(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<XPointer>(UnmapNotify));
+                       // Wait for the window to be unmapped.  This makes window managers happy.
+                       XEvent ev;
+                       XPeekIfEvent(dpy, &ev, match_event_type, reinterpret_cast<XPointer>(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<HINSTANCE>(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<HINSTANCE>(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;
index 9dc84e4e623cd45bbf90dc08f348b7139da85c11..ad575af1ab236cbf92d2e77aaa192cf87b67b72e 100644 (file)
@@ -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