*/
#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 {
Window::~Window()
{
if(window)
+#ifdef WIN32
+ CloseWindow(window);
+#else
XDestroyWindow(display.get_display(), window);
+#endif
display.remove_window(this);
+
+ if(options.fullscreen)
+ display.restore_mode();
}
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];
prop.nitems=title.size();
XSetWMName(display.get_display(), window, &prop);
display.check_error();
+#endif
+}
+
+void Window::reconfigure(const WindowOptions &opts)
+{
+ bool fullscreen_changed=(opts.fullscreen!=options.fullscreen);
+
+ 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);
+
+ if(fullscreen_changed)
+ {
+ hide();
+ XSetWindowAttributes attr;
+ attr.override_redirect=options.fullscreen;
+ XChangeWindowAttributes(dpy, window, CWOverrideRedirect, &attr);
+ show();
+ }
+
+ if(options.fullscreen)
+ 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);
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);
+ 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);
+ }
+#endif
+
display.add_window(this);
display.check_error();
}
+#ifndef WIN32
void Window::event(const XEvent &ev)
{
switch(ev.type)
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)
+ {
+ 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