]> git.tdb.fi Git - libs/gui.git/blobdiff - source/gbase/window.cpp
Hide the platform-specific parts of other classes as well
[libs/gui.git] / source / gbase / window.cpp
index 9f2361e4e3c90ab93243294d0d206cf648e15ffb..4aebc27e0c1384688d0a82c1519f42844df77693 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -16,9 +16,37 @@ Distributed under the LGPL
 #include <msp/core/except.h>
 #include "display.h"
 #include "window.h"
+#include "display_priv.h"
 
 using namespace std;
 
+namespace {
+
+#ifdef WIN32
+LRESULT CALLBACK wndproc_(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+       if(msg==WM_CREATE)
+       {
+               CREATESTRUCT *cs=reinterpret_cast<CREATESTRUCT *>(lparam);
+               SetWindowLong(hwnd, 0, reinterpret_cast<LONG>(cs->lpCreateParams));
+       }
+       else
+       {
+               Msp::Graphics::Window *wnd=reinterpret_cast<Msp::Graphics::Window *>(GetWindowLong(hwnd, 0));
+               Msp::Graphics::Window::Event ev;
+               ev.msg=msg;
+               ev.wparam=wparam;
+               ev.lparam=lparam;
+               if(wnd && wnd->event(ev))
+                       return 0;
+       }
+
+       return DefWindowProc(hwnd, msg, wparam, lparam);
+}
+#endif
+
+}
+
 namespace Msp {
 namespace Graphics {
 
@@ -49,17 +77,17 @@ Window::Window(Display &dpy, const WindowOptions &opts):
 
 Window::~Window()
 {
-       if(window)
+       if(priv->window)
 #ifdef WIN32
-               CloseWindow(window);
+               CloseWindow(priv->window);
 #else
-               XDestroyWindow(display.get_display(), window);
+               XDestroyWindow(display.get_private().display, priv->window);
 
-       if(invisible_cursor)
-               XFreeCursor(display.get_display(), invisible_cursor);
+       if(priv->invisible_cursor)
+               XFreeCursor(display.get_private().display, priv->invisible_cursor);
 #endif
 
-       display.remove_window(this);
+       display.remove_window(*this);
 
        if(options.fullscreen)
                display.restore_mode();
@@ -68,7 +96,7 @@ Window::~Window()
 void Window::set_title(const string &title)
 {
 #ifdef WIN32
-       SetWindowText(window, title.c_str());
+       SetWindowText(priv->window, title.c_str());
 #else
        vector<unsigned char> buf(title.begin(), title.end());
        XTextProperty prop;
@@ -76,7 +104,7 @@ void Window::set_title(const string &title)
        prop.encoding=XA_STRING;
        prop.format=8;
        prop.nitems=title.size();
-       XSetWMName(display.get_display(), window, &prop);
+       XSetWMName(display.get_private().display, priv->window, &prop);
        display.check_error();
 #endif
 }
@@ -100,26 +128,24 @@ void Window::reconfigure(const WindowOptions &opts)
        if(fullscreen_changed)
        {
                hide();
-               SetWindowLong(window, GWL_EXSTYLE, exstyle);
-               SetWindowLong(window, GWL_STYLE, style);
+               SetWindowLong(priv->window, GWL_EXSTYLE, exstyle);
+               SetWindowLong(priv->window, GWL_STYLE, style);
                show();
        }
 
        if(options.fullscreen)
-               SetWindowPos(window, 0, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOZORDER);
+               SetWindowPos(priv->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;
+               SetWindowPos(priv->window, 0, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER);
 #else
-       ::Display *dpy=display.get_display();
+       ::Display *dpy=display.get_private().display;
 
        if(fullscreen_changed)
        {
                hide();
                XSetWindowAttributes attr;
                attr.override_redirect=options.fullscreen;
-               XChangeWindowAttributes(dpy, window, CWOverrideRedirect, &attr);
+               XChangeWindowAttributes(dpy, priv->window, CWOverrideRedirect, &attr);
                show();
        }
 
@@ -132,12 +158,12 @@ void Window::reconfigure(const WindowOptions &opts)
                hints.min_width=hints.max_width=options.width;
                hints.min_height=hints.max_height=options.height;
        }
-       XSetWMNormalHints(dpy, window, &hints);
+       XSetWMNormalHints(dpy, priv->window, &hints);
 
        if(options.fullscreen)
-               XMoveResizeWindow(dpy, window, 0, 0, options.width, options.height);
+               XMoveResizeWindow(dpy, priv->window, 0, 0, options.width, options.height);
        else
-               XResizeWindow(dpy, window, options.width, options.height);
+               XResizeWindow(dpy, priv->window, options.width, options.height);
 #endif
 
        if(options.fullscreen)
@@ -151,19 +177,19 @@ void Window::show_cursor(bool s)
 #ifdef WIN32
        ShowCursor(s);
 #else
-       ::Display *dpy=display.get_display();
+       ::Display *dpy=display.get_private().display;
 
        if(s)
-               XUndefineCursor(dpy, window);
+               XUndefineCursor(dpy, priv->window);
        else
        {
-               if(!invisible_cursor)
+               if(!priv->invisible_cursor)
                {
                        int screen=DefaultScreen(dpy);
                        char data=0;
                        XImage *img=XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0, &data, 1, 1, 8, 1);
 
-                       Pixmap pm=XCreatePixmap(dpy, window, 1, 1, 1);
+                       Pixmap pm=XCreatePixmap(dpy, priv->window, 1, 1, 1);
                        GC gc=XCreateGC(dpy, pm, 0, 0);
                        XPutImage(dpy, pm, gc, img, 0, 0, 0, 0, 1, 1);
 
@@ -171,14 +197,14 @@ void Window::show_cursor(bool s)
                        black.pixel=BlackPixel(dpy, screen);
                        XQueryColor(dpy, DefaultColormap(dpy, screen), &black);
 
-                       invisible_cursor=XCreatePixmapCursor(dpy, pm, pm, &black, &black, 0, 0);
+                       priv->invisible_cursor=XCreatePixmapCursor(dpy, pm, pm, &black, &black, 0, 0);
 
                        XFreeGC(dpy, gc);
                        XFreePixmap(dpy, pm);
                        img->data=0;
                        XDestroyImage(img);
                }
-               XDefineCursor(dpy, window, invisible_cursor);
+               XDefineCursor(dpy, priv->window, priv->invisible_cursor);
        }
 #endif
 }
@@ -186,9 +212,9 @@ void Window::show_cursor(bool s)
 void Window::show()
 {
 #ifdef WIN32
-       ShowWindow(window, SW_SHOWNORMAL);
+       ShowWindow(priv->window, SW_SHOWNORMAL);
 #else
-       XMapRaised(display.get_display(), window);
+       XMapRaised(display.get_private().display, priv->window);
        display.check_error();
 #endif
 }
@@ -196,15 +222,17 @@ void Window::show()
 void Window::hide()
 {
 #ifdef WIN32
-       ShowWindow(window, SW_HIDE);
+       ShowWindow(priv->window, SW_HIDE);
 #else
-       XUnmapWindow(display.get_display(), window);
+       XUnmapWindow(display.get_private().display, priv->window);
        display.check_error();
 #endif
 }
 
 void Window::init()
 {
+       priv=new Private;
+
 #ifdef WIN32
        static bool wndclass_created=false;
 
@@ -240,7 +268,7 @@ void Window::init()
        int exstyle=(options.fullscreen ? WS_EX_APPWINDOW : WS_EX_OVERLAPPEDWINDOW);
        AdjustWindowRectEx(&rect, style, false, exstyle);
 
-       window=CreateWindowEx(exstyle,
+       priv->window=CreateWindowEx(exstyle,
                "mspgbase",
                "Window",
                style,
@@ -250,23 +278,23 @@ void Window::init()
                0,
                reinterpret_cast<HINSTANCE>(Application::get_data()),
                this);
-       if(!window)
+       if(!priv->window)
                throw Exception("CreateWindowEx failed");
 
        if(options.fullscreen)
                display.set_mode(VideoMode(options.width, options.height));
 
 #else
-       ::Display *dpy=display.get_display();
+       ::Display *dpy=display.get_private().display;
 
-       wm_delete_window=XInternAtom(dpy, "WM_DELETE_WINDOW", true);
-       invisible_cursor=0;
+       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;
 
-       window=XCreateWindow(dpy,
+       priv->window=XCreateWindow(dpy,
                DefaultRootWindow(dpy),
                0, 0,
                options.width, options.height,
@@ -276,7 +304,7 @@ void Window::init()
                CopyFromParent,
                CWOverrideRedirect|CWEventMask, &attr);
 
-       XSetWMProtocols(dpy, window, &wm_delete_window, 1);
+       XSetWMProtocols(dpy, priv->window, &priv->wm_delete_window, 1);
 
        if(!options.resizable)
        {
@@ -284,70 +312,26 @@ void Window::init()
                hints.flags=PMinSize|PMaxSize;
                hints.min_width=hints.max_width=options.width;
                hints.min_height=hints.max_height=options.height;
-               XSetWMNormalHints(dpy, window, &hints);
+               XSetWMNormalHints(dpy, priv->window, &hints);
        }
 
        if(options.fullscreen)
        {
                display.set_mode(VideoMode(options.width, options.height));
-               XWarpPointer(dpy, None, window, 0, 0, 0, 0, options.width/2, options.height/2);
+               XWarpPointer(dpy, None, priv->window, 0, 0, 0, 0, options.width/2, options.height/2);
        }
 #endif
 
-       display.add_window(this);
+       display.add_window(*this);
        display.check_error();
 }
 
-#ifndef WIN32
-void Window::event(const XEvent &ev)
+bool Window::event(const Event &evnt)
 {
-       switch(ev.type)
-       {
-       case ButtonPress:
-               signal_button_press.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
-               break;
-       case ButtonRelease:
-               signal_button_release.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
-               break;
-       case MotionNotify:
-               signal_pointer_motion.emit(ev.xmotion.x, ev.xmotion.y);
-               break;
-       case KeyPress:
-               {
-                       char buf[16];
-                       XLookupString(const_cast<XKeyEvent *>(&ev.xkey), buf, sizeof(buf), 0, 0);
-                       // XXX Handle the result according to locale
-                       signal_key_press.emit(XKeycodeToKeysym(display.get_display(), ev.xkey.keycode, 0), ev.xkey.state, buf[0]);
-               }
-               break;
-       case KeyRelease:
-               signal_key_release.emit(XKeycodeToKeysym(display.get_display(), ev.xkey.keycode, 0), ev.xkey.state);
-               break;
-       case ConfigureNotify:
-               options.width=ev.xconfigure.width;
-               options.height=ev.xconfigure.height;
-               signal_resize.emit(options.width, options.height);
-               break;
-       case ClientMessage:
-               if(ev.xclient.data.l[0]==static_cast<long>(wm_delete_window))
-                       signal_close.emit();
-               break;
-       case EnterNotify:
-               XSetInputFocus(display.get_display(), window, RevertToParent, CurrentTime);
-               break;
-       case MapNotify:
-               if(options.fullscreen)
-                       XGrabPointer(display.get_display(), window, true, None, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
-               break;
-       default:;
-       }
-}
-#endif
-
 #ifdef WIN32
-int Window::wndproc(UINT msg, WPARAM wp, LPARAM lp)
-{
-       switch(msg)
+       WPARAM wp=evnt.wparam;
+       LPARAM lp=evnt.lparam;
+       switch(evnt.msg)
        {
        case WM_KEYDOWN:
                signal_key_press.emit(wp, 0, wp);
@@ -385,29 +369,54 @@ int Window::wndproc(UINT msg, WPARAM wp, LPARAM lp)
                signal_close.emit();
                break;
        default:
-               return 0;
-       }
-
-       return 1;
-}
-
-LRESULT CALLBACK Window::wndproc_(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
-{
-       if(msg==WM_CREATE)
-       {
-               CREATESTRUCT *cs=reinterpret_cast<CREATESTRUCT *>(lparam);
-               SetWindowLong(hwnd, 0, reinterpret_cast<LONG>(cs->lpCreateParams));
+               return false;
        }
-       else
+#else
+       const XEvent &ev=evnt.xevent;
+       switch(ev.type)
        {
-               Window *wnd=reinterpret_cast<Window *>(GetWindowLong(hwnd, 0));
-               if(wnd && wnd->wndproc(msg, wparam, lparam))
-                       return 0;
+       case ButtonPress:
+               signal_button_press.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
+               break;
+       case ButtonRelease:
+               signal_button_release.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
+               break;
+       case MotionNotify:
+               signal_pointer_motion.emit(ev.xmotion.x, ev.xmotion.y);
+               break;
+       case KeyPress:
+               {
+                       char buf[16];
+                       XLookupString(const_cast<XKeyEvent *>(&ev.xkey), buf, sizeof(buf), 0, 0);
+                       // XXX Handle the result according to locale
+                       signal_key_press.emit(XKeycodeToKeysym(display.get_private().display, ev.xkey.keycode, 0), ev.xkey.state, buf[0]);
+               }
+               break;
+       case KeyRelease:
+               signal_key_release.emit(XKeycodeToKeysym(display.get_private().display, ev.xkey.keycode, 0), ev.xkey.state);
+               break;
+       case ConfigureNotify:
+               options.width=ev.xconfigure.width;
+               options.height=ev.xconfigure.height;
+               signal_resize.emit(options.width, options.height);
+               break;
+       case ClientMessage:
+               if(ev.xclient.data.l[0]==static_cast<long>(priv->wm_delete_window))
+                       signal_close.emit();
+               break;
+       case EnterNotify:
+               XSetInputFocus(display.get_private().display, priv->window, RevertToParent, CurrentTime);
+               break;
+       case MapNotify:
+               if(options.fullscreen)
+                       XGrabPointer(display.get_private().display, priv->window, true, None, GrabModeAsync, GrabModeAsync, priv->window, None, CurrentTime);
+               break;
+       default:
+               return false;
        }
-
-       return DefWindowProc(hwnd, msg, wparam, lparam);
-}
 #endif
+       return true;
+}
 
 } // namespace Graphics
 } // namespace Msp