]> git.tdb.fi Git - libs/gui.git/blobdiff - source/window.cpp
Redesign and refactor
[libs/gui.git] / source / window.cpp
index ee5bec90d93f6165c742e13316fca7d621d79d10..f867faf6e58e3a775c08248f943eb17c1159b71e 100644 (file)
@@ -9,38 +9,35 @@ Distributed under the LGPL
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
 #include <msp/core/except.h>
+#include "display.h"
 #include "window.h"
 
 using namespace std;
 
 namespace Msp {
+namespace Graphics {
 
-DisplayOptions::DisplayOptions():
+WindowOptions::WindowOptions():
        width(640),
        height(480),
-       fullscreen(false)
+       fullscreen(false),
+       resizable(false)
 { }
 
 
-/**
-Initializes the class but does not open the window.  Intended for use by
-derived classes.
-*/
-Window::Window():
-       display(0),
-       window(0)
-{ }
-
-Window::Window(unsigned w, unsigned h)
+Window::Window(Display &dpy, unsigned w, unsigned h, bool fs):
+       display(dpy)
 {
        options.width=w;
        options.height=h;
+       options.fullscreen=fs;
 
        init();
 }
 
-Window::Window(const DisplayOptions &dopt):
-       options(dopt)
+Window::Window(Display &dpy, const WindowOptions &opts):
+       display(dpy),
+       options(opts)
 {
        init();
 }
@@ -48,9 +45,9 @@ Window::Window(const DisplayOptions &dopt):
 Window::~Window()
 {
        if(window)
-               XDestroyWindow(display, window);
-       if(display)
-               XCloseDisplay(display);
+               XDestroyWindow(display.get_display(), window);
+
+       display.remove_window(this);
 }
 
 void Window::set_title(const string &title)
@@ -61,123 +58,79 @@ void Window::set_title(const string &title)
        prop.encoding=XA_STRING;
        prop.format=8;
        prop.nitems=title.size();
-       XSetWMName(display, window, &prop);
+       XSetWMName(display.get_display(), window, &prop);
+       display.check_error();
 }
 
 void Window::show()
 {
-       XMapRaised(display, window);
+       XMapRaised(display.get_display(), window);
+       display.check_error();
 }
 
 void Window::hide()
 {
-       XUnmapWindow(display, window);
-}
-
-void Window::tick()
-{
-       while(1)
-       {
-               int pending=XPending(display);
-               if(pending==0)
-                       break;
-
-               for(int i=0; i<pending; ++i)
-               {
-                       XEvent event;
-                       XNextEvent(display, &event);
-                       process_event(event);
-               }
-       }
-}
-
-void Window::prepare()
-{
-       if(options.display.empty())
-               display=XOpenDisplay(0);
-       else
-               display=XOpenDisplay(options.display.c_str());
-       if(!display)
-               throw Exception("Couldn't open X display");
-
-       wm_delete_window=XInternAtom(display, "WM_DELETE_WINDOW", true);
-
-       /* Throwing from the error handler doesn't work too well and I don't know
-          how to dig up all the information that Xlib gives by default, so disable
-               custom error handling for now. */
-       //XSetErrorHandler(x_error_handler);
-}
-
-void Window::set_window(Handle wnd)
-{
-       window=wnd;
-
-       XSelectInput(display, window, ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask);
-
-       XSetWMProtocols(display, window, &wm_delete_window, 1);
+       XUnmapWindow(display.get_display(), window);
+       display.check_error();
 }
 
 void Window::init()
 {
-       prepare();
+       ::Display *dpy=display.get_display();
+
+       wm_delete_window=XInternAtom(dpy, "WM_DELETE_WINDOW", true);
 
        XSetWindowAttributes attr;
        attr.override_redirect=options.fullscreen;
+       attr.event_mask=ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask;
 
-       Handle wnd=XCreateWindow(display, DefaultRootWindow(display), 0, 0, options.width, options.height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &attr);
-       set_window(wnd);
+       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);
+
+       display.add_window(this);
+       display.check_error();
 }
 
-void Window::process_event(const XEvent &event)
+void Window::event(const XEvent &ev)
 {
-       switch(event.type)
+       switch(ev.type)
        {
        case ButtonPress:
-               signal_button_press.emit(event.xbutton.x, event.xbutton.y, event.xbutton.button, event.xbutton.state);
+               signal_button_press.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
                break;
        case ButtonRelease:
-               signal_button_release.emit(event.xbutton.x, event.xbutton.y, event.xbutton.button, event.xbutton.state);
+               signal_button_release.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
                break;
        case MotionNotify:
-               signal_pointer_motion.emit(event.xmotion.x, event.xmotion.y);
+               signal_pointer_motion.emit(ev.xmotion.x, ev.xmotion.y);
                break;
        case KeyPress:
                {
                        char buf[16];
-                       XLookupString(const_cast<XKeyEvent *>(&event.xkey), buf, sizeof(buf), 0, 0);
+                       XLookupString(const_cast<XKeyEvent *>(&ev.xkey), buf, sizeof(buf), 0, 0);
                        // XXX Handle the result according to locale
-                       signal_key_press.emit(event.xkey.keycode, event.xkey.state, buf[0]);
+                       signal_key_press.emit(ev.xkey.keycode, ev.xkey.state, buf[0]);
                }
                break;
        case KeyRelease:
-               signal_key_release.emit(event.xkey.keycode, event.xkey.state);
+               signal_key_release.emit(ev.xkey.keycode, ev.xkey.state);
                break;
        case ConfigureNotify:
-               options.width=event.xconfigure.width;
-               options.height=event.xconfigure.height;
+               options.width=ev.xconfigure.width;
+               options.height=ev.xconfigure.height;
                signal_resize.emit(options.width, options.height);
                break;
        case ClientMessage:
-               if(event.xclient.data.l[0]==static_cast<long>(wm_delete_window))
+               if(ev.xclient.data.l[0]==static_cast<long>(wm_delete_window))
                        signal_close.emit();
                break;
        case EnterNotify:
-               XSetInputFocus(display, window, RevertToParent, CurrentTime);
+               XSetInputFocus(display.get_display(), window, RevertToParent, CurrentTime);
                break;
        default:;
        }
-
-       on_event(event);
-}
-
-int Window::x_error_handler(Display *display, XErrorEvent *error)
-{
-       char buf[128];
-       XGetErrorText(display, error->error_code, buf, sizeof(buf));
-       /*string request_code=lexical_cast(error->request_code);
-       char buf2[1024];
-       XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), buf, buf2, sizeof(buf2));*/
-       throw Exception(buf);
 }
 
+} // namespace Graphics
 } // namespace Msp