]> git.tdb.fi Git - libs/gui.git/blobdiff - source/graphics/window.cpp
Only set resizing flag to true in Window::reconfigure
[libs/gui.git] / source / graphics / window.cpp
index a1353acf8fe4000f6b5a35cce9624cd6b2d43399..658eb26f5aab722c2b1515a4c64c4f6f9334ec73 100644 (file)
@@ -1,53 +1,9 @@
-#include <vector>
-#ifndef WIN32
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#ifdef WITH_XF86VIDMODE
-#include <X11/extensions/xf86vmode.h>
-#endif
-#else
-#include <windowsx.h>
-#endif
-#include <msp/core/application.h>
-#include <msp/core/systemerror.h>
 #include "display.h"
 #include "window.h"
-#include "display_priv.h"
+#include "window_private.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);
-}
-#else
-Bool match_event_type(Display *, XEvent *event, XPointer arg)
-{
-       return event->type==*reinterpret_cast<int *>(arg);
-}
-#endif
-
-}
-
 namespace Msp {
 namespace Graphics {
 
@@ -83,86 +39,7 @@ void Window::init()
        resizing = false;
        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 = "mspgui";
-               wndcl.hIconSm = 0;
-
-               if(!RegisterClassEx(&wndcl))
-                       throw system_error("RegisterClassEx");
-
-               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,
-               "mspgui",
-               "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 system_error("CreateWindowEx");
-
-#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
+       platform_init();
 
        display.add_window(*this);
        display.check_error();
@@ -170,120 +47,32 @@ void Window::init()
 
 Window::~Window()
 {
-       if(priv->window)
-#ifdef WIN32
-               CloseWindow(priv->window);
-#else
-               XDestroyWindow(display.get_private().display, priv->window);
-
-       if(priv->invisible_cursor)
-               XFreeCursor(display.get_private().display, priv->invisible_cursor);
-#endif
+       platform_cleanup();
 
        display.remove_window(*this);
 
-       if(options.fullscreen)
+       if(options.fullscreen && visible)
                display.restore_mode();
 
        delete priv;
 }
 
-void Window::set_title(const string &title)
-{
-#ifdef WIN32
-       SetWindowText(priv->window, title.c_str());
-#else
-       vector<unsigned char> buf(title.begin(), title.end());
-       XTextProperty prop;
-       prop.value = &buf[0];
-       prop.encoding = XA_STRING;
-       prop.format = 8;
-       prop.nitems = title.size();
-       XSetWMName(display.get_private().display, priv->window, &prop);
-       display.check_error();
-#endif
-}
-
 void Window::reconfigure(const WindowOptions &opts)
 {
        bool fullscreen_changed = (opts.fullscreen!=options.fullscreen);
-       resizing = (opts.width!=options.width || opts.height!=options.height);
-
-       options = opts;
-
-#ifdef WIN32
-       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(priv->window, GWL_EXSTYLE, exstyle);
-               SetWindowLong(priv->window, GWL_STYLE, style);
-               show();
-       }
-
-       if(options.fullscreen)
-               SetWindowPos(priv->window, 0, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOZORDER);
-       else
-               SetWindowPos(priv->window, 0, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER);
-#else
-       ::Display *dpy = display.get_private().display;
-
-       bool was_visible = visible;
-       if(fullscreen_changed)
-       {
-               if(was_visible)
-               {
-                       hide();
-
-                       // Wait for the window to be unmapped.  This makes window managers happy.
-                       XEvent ev;
-                       int ev_type = UnmapNotify;
-                       XPeekIfEvent(dpy, &ev, match_event_type, reinterpret_cast<char *>(&ev_type));
-               }
-
-               XSetWindowAttributes attr;
-               attr.override_redirect = options.fullscreen;
-               XChangeWindowAttributes(dpy, priv->window, CWOverrideRedirect, &attr);
-       }
-
-       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, priv->window, &hints);
-
-       if(options.fullscreen)
-               XMoveResizeWindow(dpy, priv->window, 0, 0, options.width, options.height);
-       else
-               XResizeWindow(dpy, priv->window, options.width, options.height);
-
-       if(fullscreen_changed)
-       {
-               if(was_visible)
-                       show();
-       }
-#endif
+       if(opts.width!=options.width || opts.height!=options.height)
+               resizing = true;
 
        if(visible)
        {
-               if(options.fullscreen)
-                       display.set_mode(VideoMode(options.width, options.height));
+               if(opts.fullscreen)
+                       display.set_mode(VideoMode(opts.width, opts.height));
                else if(fullscreen_changed)
                        display.restore_mode();
        }
+
+       options = opts;
+       platform_reconfigure(fullscreen_changed);
 }
 
 void Window::set_keyboard_autorepeat(bool r)
@@ -291,155 +80,26 @@ void Window::set_keyboard_autorepeat(bool r)
        kbd_autorepeat = r;
 }
 
-void Window::show_cursor(bool s)
-{
-#ifdef WIN32
-       ShowCursor(s);
-#else
-       ::Display *dpy = display.get_private().display;
-
-       if(s)
-               XUndefineCursor(dpy, priv->window);
-       else
-       {
-               if(!priv->invisible_cursor)
-               {
-                       int screen = DefaultScreen(dpy);
-
-                       Pixmap pm = XCreatePixmap(dpy, priv->window, 1, 1, 1);
-                       GC gc = XCreateGC(dpy, pm, 0, 0);
-                       XSetFunction(dpy, gc, GXclear);
-                       XDrawPoint(dpy, pm, gc, 0, 0);
-                       XFreeGC(dpy, gc);
-
-                       XColor black;
-                       black.pixel = BlackPixel(dpy, screen);
-                       XQueryColor(dpy, DefaultColormap(dpy, screen), &black);
-
-                       priv->invisible_cursor = XCreatePixmapCursor(dpy, pm, pm, &black, &black, 0, 0);
-
-                       XFreePixmap(dpy, pm);
-               }
-               XDefineCursor(dpy, priv->window, priv->invisible_cursor);
-       }
-#endif
-}
-
-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
-}
-
 void Window::show()
 {
-#ifdef WIN32
-       ShowWindow(priv->window, SW_SHOWNORMAL);
-#else
-       XMapRaised(display.get_private().display, priv->window);
-#endif
+       platform_show();
        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
+               display.set_mode(VideoMode(options.width, options.height), true);
+               warp_pointer(options.width/2, options.height/2);
        }
 }
 
 void Window::hide()
 {
-#ifdef WIN32
-       ShowWindow(priv->window, SW_HIDE);
-#else
-       XUnmapWindow(display.get_private().display, priv->window);
-#endif
+       platform_hide();
        visible = false;
 
        if(options.fullscreen)
                display.restore_mode();
 }
 
-bool Window::event(const Event &evnt)
-{
-#ifdef WIN32
-       switch(evnt.msg)
-       {
-       case WM_KEYDOWN:
-       case WM_KEYUP:
-       case WM_LBUTTONDOWN:
-       case WM_LBUTTONUP:
-       case WM_MBUTTONDOWN:
-       case WM_MBUTTONUP:
-       case WM_RBUTTONDOWN:
-       case WM_RBUTTONUP:
-       case WM_MOUSEWHEEL:
-       case WM_MOUSEMOVE:
-               signal_input_event.emit(evnt);
-               break;
-       case WM_SIZE:
-               options.width = LOWORD(evnt.lparam);
-               options.height = HIWORD(evnt.lparam);
-               signal_resize.emit(options.width, options.height);
-               break;
-       case WM_CLOSE:
-               signal_close.emit();
-               break;
-       default:
-               return false;
-       }
-#else
-       const XEvent &ev = evnt.xevent;
-       switch(ev.type)
-       {
-       case ButtonPress:
-       case ButtonRelease:
-       case MotionNotify:
-       case KeyPress:
-       case KeyRelease:
-               signal_input_event.emit(evnt);
-               break;
-       case ConfigureNotify:
-               if((ev.xconfigure.width==static_cast<int>(options.width) && ev.xconfigure.height==static_cast<int>(options.height)) == resizing)
-               {
-                       options.width = ev.xconfigure.width;
-                       options.height = ev.xconfigure.height;
-                       resizing = false;
-                       signal_resize.emit(options.width, options.height);
-               }
-#ifdef WITH_XF86VIDMODE
-               if(options.fullscreen)
-               {
-                       ::Display *dpy = display.get_private().display;
-                       int screen = DefaultScreen(dpy);
-                       XF86VidModeSetViewPort(dpy, screen, ev.xconfigure.x, ev.xconfigure.y);
-               }
-#endif
-               break;
-       case ClientMessage:
-               if(ev.xclient.data.l[0]==static_cast<long>(priv->wm_delete_window))
-                       signal_close.emit();
-               break;
-       case EnterNotify:
-               if(options.fullscreen)
-                       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;
-       }
-#endif
-       return true;
-}
-
 } // namespace Graphics
 } // namespace Msp