]> git.tdb.fi Git - libs/gui.git/blobdiff - source/window.cpp
Win32 compatibility (for most things)
[libs/gui.git] / source / window.cpp
index f916d1c9e5312e4290d40224e076b0e9e776b5e1..7f6f6d8fa0e6c77463df993397d01b9dc10ff777 100644 (file)
@@ -6,14 +6,21 @@ Distributed under the LGPL
 */
 
 #include <vector>
+#ifndef WIN32
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
+#else
+#include <windowsx.h>
+#endif
+#include <msp/core/application.h>
 #include <msp/core/except.h>
 #include "display.h"
 #include "window.h"
 
 using namespace std;
 
+#include <iostream>
+
 namespace Msp {
 namespace Graphics {
 
@@ -45,7 +52,11 @@ Window::Window(Display &dpy, const WindowOptions &opts):
 Window::~Window()
 {
        if(window)
+#ifdef WIN32
+               CloseWindow(window);
+#else
                XDestroyWindow(display.get_display(), window);
+#endif
 
        display.remove_window(this);
 
@@ -55,6 +66,9 @@ Window::~Window()
 
 void Window::set_title(const string &title)
 {
+#ifdef WIN32
+       SetWindowText(window, title.c_str());
+#else
        vector<unsigned char> buf(title.begin(), title.end());
        XTextProperty prop;
        prop.value=&buf[0];
@@ -63,6 +77,7 @@ void Window::set_title(const string &title)
        prop.nitems=title.size();
        XSetWMName(display.get_display(), window, &prop);
        display.check_error();
+#endif
 }
 
 void Window::reconfigure(const WindowOptions &opts)
@@ -71,6 +86,12 @@ void Window::reconfigure(const WindowOptions &opts)
 
        options=opts;
 
+#ifdef WIN32
+       // XXX Preserve position
+       MoveWindow(window, 0, 0, options.width, options.height, false);
+
+       (void)fullscreen_changed;
+#else
        ::Display *dpy=display.get_display();
 
        XMoveResizeWindow(dpy, window, 0, 0, options.width, options.height);
@@ -88,22 +109,78 @@ void Window::reconfigure(const WindowOptions &opts)
                display.set_mode(VideoMode(options.width, options.height));
        else if(fullscreen_changed)
                display.restore_mode();
+#endif
 }
 
 void Window::show()
 {
+#ifdef WIN32
+       ShowWindow(window, SW_SHOWNORMAL);
+#else
        XMapRaised(display.get_display(), window);
        display.check_error();
+#endif
 }
 
 void Window::hide()
 {
+#ifdef WIN32
+       ShowWindow(window, SW_HIDE);
+#else
        XUnmapWindow(display.get_display(), window);
        display.check_error();
+#endif
 }
 
 void Window::init()
 {
+#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=0;
+               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;
+       rect.left=0;
+       rect.top=0;
+       rect.right=options.width;
+       rect.bottom=options.height;
+       AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
+
+       window=CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
+               "mspgbase",
+               "Window",
+               WS_OVERLAPPEDWINDOW,
+               CW_USEDEFAULT, CW_USEDEFAULT,
+               rect.right-rect.left, rect.bottom-rect.top,
+               0,
+               0,
+               reinterpret_cast<HINSTANCE>(Application::get_data()),
+               this);
+       if(!window)
+               throw Exception("CreateWindowEx failed");
+
+#else
        ::Display *dpy=display.get_display();
 
        wm_delete_window=XInternAtom(dpy, "WM_DELETE_WINDOW", true);
@@ -112,7 +189,15 @@ void Window::init()
        attr.override_redirect=options.fullscreen;
        attr.event_mask=ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask;
 
-       window=XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, options.width, options.height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWEventMask, &attr);
+       window=XCreateWindow(dpy,
+               DefaultRootWindow(dpy),
+               0, 0,
+               options.width, options.height,
+               0,
+               CopyFromParent,
+               InputOutput,
+               CopyFromParent,
+               CWOverrideRedirect|CWEventMask, &attr);
 
        XSetWMProtocols(dpy, window, &wm_delete_window, 1);
 
@@ -121,11 +206,13 @@ void Window::init()
                display.set_mode(VideoMode(options.width, options.height));
                XWarpPointer(dpy, None, window, 0, 0, 0, 0, options.width/2, options.height/2);
        }
+#endif
 
        display.add_window(this);
        display.check_error();
 }
 
+#ifndef WIN32
 void Window::event(const XEvent &ev)
 {
        switch(ev.type)
@@ -169,6 +256,67 @@ void Window::event(const XEvent &ev)
        default:;
        }
 }
+#endif
+
+#ifdef WIN32
+int Window::wndproc(UINT msg, WPARAM wp, LPARAM lp)
+{
+       switch(msg)
+       {
+       case WM_KEYDOWN:
+               signal_key_press.emit(wp, 0, wp);
+               break;
+       case WM_KEYUP:
+               signal_key_release.emit(wp, 0);
+               break;
+       case WM_LBUTTONDOWN:
+               signal_button_press.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 1, 0);
+               break;
+       case WM_LBUTTONUP:
+               signal_button_release.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 1, 0);
+               break;
+       case WM_MBUTTONDOWN:
+               signal_button_press.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 2, 0);
+               break;
+       case WM_MBUTTONUP:
+               signal_button_release.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 2, 0);
+               break;
+       case WM_RBUTTONDOWN:
+               signal_button_press.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 3, 0);
+               break;
+       case WM_RBUTTONUP:
+               signal_button_release.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 3, 0);
+               break;
+       case WM_MOUSEMOVE:
+               signal_pointer_motion.emit(GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
+               break;
+       case WM_CLOSE:
+               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));
+       }
+       else
+       {
+               Window *wnd=reinterpret_cast<Window *>(GetWindowLong(hwnd, 0));
+               if(wnd && wnd->wndproc(msg, wparam, lparam))
+                       return 0;
+       }
+
+       return DefWindowProc(hwnd, msg, wparam, lparam);
+}
+#endif
 
 } // namespace Graphics
 } // namespace Msp