+++ /dev/null
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-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 {
-
-WindowOptions::WindowOptions():
- width(640),
- height(480),
- fullscreen(false),
- resizable(false)
-{ }
-
-
-Window::Window(Display &dpy, unsigned w, unsigned h, bool fs):
- display(dpy)
-{
- options.width=w;
- options.height=h;
- options.fullscreen=fs;
-
- init();
-}
-
-Window::Window(Display &dpy, const WindowOptions &opts):
- display(dpy),
- options(opts)
-{
- init();
-}
-
-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.encoding=XA_STRING;
- prop.format=8;
- 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=LoadCursor(0, IDC_ARROW);
- 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);
-
- XSetWindowAttributes attr;
- 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);
-
- 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 ButtonPress:
- signal_button_press.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
- break;
- case ButtonRelease:
- signal_button_release.emit(ev.xbutton.x, ev.xbutton.y, ev.xbutton.button, ev.xbutton.state);
- break;
- case MotionNotify:
- signal_pointer_motion.emit(ev.xmotion.x, ev.xmotion.y);
- break;
- case KeyPress:
- {
- char buf[16];
- XLookupString(const_cast<XKeyEvent *>(&ev.xkey), buf, sizeof(buf), 0, 0);
- // XXX Handle the result according to locale
- signal_key_press.emit(ev.xkey.keycode, ev.xkey.state, buf[0]);
- }
- break;
- case KeyRelease:
- signal_key_release.emit(ev.xkey.keycode, ev.xkey.state);
- break;
- case ConfigureNotify:
- options.width=ev.xconfigure.width;
- options.height=ev.xconfigure.height;
- signal_resize.emit(options.width, options.height);
- break;
- case ClientMessage:
- if(ev.xclient.data.l[0]==static_cast<long>(wm_delete_window))
- signal_close.emit();
- break;
- 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((lp>>16)&0x1FF, 0, wp);
- break;
- case WM_KEYUP:
- signal_key_release.emit((lp>>16)&0x1FF, 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