#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();
}
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)
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