]> git.tdb.fi Git - libs/gui.git/commitdiff
Reorganize files to separate gbase and input
authorMikko Rasa <tdb@tdb.fi>
Thu, 6 Mar 2008 12:54:18 +0000 (12:54 +0000)
committerMikko Rasa <tdb@tdb.fi>
Thu, 6 Mar 2008 12:54:18 +0000 (12:54 +0000)
47 files changed:
Build
source/binarycontrol.cpp [deleted file]
source/binarycontrol.h [deleted file]
source/control.cpp [deleted file]
source/control.h [deleted file]
source/display.cpp [deleted file]
source/display.h [deleted file]
source/drawcontext.cpp [deleted file]
source/drawcontext.h [deleted file]
source/gbase/display.cpp [new file with mode: 0644]
source/gbase/display.h [new file with mode: 0644]
source/gbase/drawcontext.cpp [new file with mode: 0644]
source/gbase/drawcontext.h [new file with mode: 0644]
source/gbase/glcontext.cpp [new file with mode: 0644]
source/gbase/glcontext.h [new file with mode: 0644]
source/gbase/types.h [new file with mode: 0644]
source/gbase/window.cpp [new file with mode: 0644]
source/gbase/window.h [new file with mode: 0644]
source/glcontext.cpp [deleted file]
source/glcontext.h [deleted file]
source/input/binarycontrol.cpp [new file with mode: 0644]
source/input/binarycontrol.h [new file with mode: 0644]
source/input/control.cpp [new file with mode: 0644]
source/input/control.h [new file with mode: 0644]
source/input/device.cpp [new file with mode: 0644]
source/input/device.h [new file with mode: 0644]
source/input/hub.cpp [new file with mode: 0644]
source/input/hub.h [new file with mode: 0644]
source/input/keyboard.cpp [new file with mode: 0644]
source/input/keyboard.h [new file with mode: 0644]
source/input/mouse.cpp [new file with mode: 0644]
source/input/mouse.h [new file with mode: 0644]
source/input/smoothcontrol.cpp [new file with mode: 0644]
source/input/smoothcontrol.h [new file with mode: 0644]
source/inputdevice.cpp [deleted file]
source/inputdevice.h [deleted file]
source/inputhub.cpp [deleted file]
source/inputhub.h [deleted file]
source/keyboard.cpp [deleted file]
source/keyboard.h [deleted file]
source/mouse.cpp [deleted file]
source/mouse.h [deleted file]
source/smoothcontrol.cpp [deleted file]
source/smoothcontrol.h [deleted file]
source/types.h [deleted file]
source/window.cpp [deleted file]
source/window.h [deleted file]

diff --git a/Build b/Build
index 338611954e8895141c2d05f90761d77c71302709..17a6fdc19fe005d24e4302b5f487ca83d42da53b 100644 (file)
--- a/Build
+++ b/Build
@@ -27,10 +27,22 @@ package "mspgbase"
                };
        };
 
                };
        };
 
+       headers "gbase"
+       {
+               source "source/gbase";
+               install_headers "msp/gbase";
+       };
+
+       headers "input"
+       {
+               source "source/input";
+               install_headers "msp/input";
+       };
+
        library "mspgbase"
        {
        library "mspgbase"
        {
-               source "source";
+               source "source/gbase";
+               source "source/input";
                install true;
                install true;
-               install_headers "msp/gbase";
        };
 };
        };
 };
diff --git a/source/binarycontrol.cpp b/source/binarycontrol.cpp
deleted file mode 100644 (file)
index daafd95..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include "binarycontrol.h"
-#include "inputdevice.h"
-
-namespace Msp {
-namespace Input {
-
-BinaryControl::BinaryControl():
-       state(false)
-{ }
-
-BinaryControl::BinaryControl(const ControlSource &s):
-       Control(s),
-       state(false)
-{ }
-
-BinaryControl::BinaryControl(Device &d, ControlSrcType t, unsigned i):
-       Control(d, t, i),
-       state(false)
-{ }
-
-void BinaryControl::on_press()
-{
-       if(!state)
-       {
-               state=true;
-               signal_press.emit();
-       }
-}
-
-void BinaryControl::on_release()
-{
-       if(state)
-       {
-               state=false;
-               signal_release.emit();
-       }
-}
-
-void BinaryControl::on_motion(float value, float)
-{
-       if(value>src.dev->get_axis_threshold())
-               on_press();
-       else
-               on_release();
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/binarycontrol.h b/source/binarycontrol.h
deleted file mode 100644 (file)
index 44aaef4..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_BINARYCONTROL_H_
-#define MSP_GBASE_BINARYCONTROL_H_
-
-#include "control.h"
-
-namespace Msp {
-namespace Input {
-
-/**
-A control with two possible states.  Button state is mapped directly.  An axis
-is considered to be active when its value is above a threshold (defined by the
-input device).
-*/
-class BinaryControl: public Control
-{
-public:
-       sigc::signal<void> signal_press;
-       sigc::signal<void> signal_release;
-
-private:
-       bool state;
-
-public:
-       BinaryControl();
-       BinaryControl(const ControlSource &);
-       BinaryControl(Device &, ControlSrcType, unsigned);
-       bool get_state() const { return state; }
-
-private:
-       virtual void on_press();
-       virtual void on_release();
-       virtual void on_motion(float, float);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/control.cpp b/source/control.cpp
deleted file mode 100644 (file)
index 823202d..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/core/except.h>
-#include <msp/strings/lexicalcast.h>
-#include "control.h"
-#include "inputdevice.h"
-
-namespace Msp {
-namespace Input {
-
-ControlSource::ControlSource():
-       dev(0),
-       type(NONE),
-       index(0)
-{ }
-
-ControlSource::ControlSource(Device &d, ControlSrcType t, unsigned i):
-       dev(&d),
-       type(t),
-       index(i)
-{ }
-
-std::string ControlSource::str() const
-{
-       if(type==BUTTON)
-               return dev->get_button_name(index);
-       else if(type==AXIS_POS || type==AXIS_NEG)
-               return dev->get_axis_name(index);
-       else if(type==NONE)
-               return "None";
-
-       return lexical_cast(index);
-}
-
-
-Control::Control():
-       capture_dev(0)
-{ }
-
-Control::Control(const ControlSource &s):
-       src(s),
-       capture_dev(0)
-{ }
-
-Control::Control(Device &d, ControlSrcType t, unsigned i):
-       src(d, t, i),
-       capture_dev(0)
-{
-       connect_signals();
-}
-
-Control::Control(const Control &c):
-       trackable(c),
-       src(c.src),
-       capture_dev(0)
-{
-       connect_signals();
-}
-
-Control &Control::operator=(const Control &c)
-{
-       notify_callbacks();
-       src=c.src;
-       capture_dev=0;
-       connect_signals();
-
-       return *this;
-}
-
-void Control::capture(Device &d)
-{
-       notify_callbacks();
-       capture_dev=&d;
-       capture_dev->signal_button_press.connect(sigc::mem_fun(this, &Control::button_press));
-       capture_dev->signal_axis_motion.connect(sigc::mem_fun(this, &Control::axis_motion));
-}
-
-void Control::cancel_capture()
-{
-       notify_callbacks();
-       capture_dev=0;
-       connect_signals();
-}
-
-void Control::connect_signals()
-{
-       switch(src.type)
-       {
-       case NONE:
-               break;
-       case BUTTON:
-               src.dev->signal_button_press.connect(sigc::mem_fun(this, &Control::button_press));
-               src.dev->signal_button_release.connect(sigc::mem_fun(this, &Control::button_release));
-               break;
-       case AXIS_POS:
-       case AXIS_NEG:
-               src.dev->signal_axis_motion.connect(sigc::mem_fun(this, &Control::axis_motion));
-               break;
-       default:
-               throw Exception("Invalid source in Control");
-       }
-}
-
-void Control::button_press(unsigned i)
-{
-       if(capture_dev)
-       {
-               src.dev=capture_dev;
-               src.type=BUTTON;
-               src.index=i;
-
-               notify_callbacks();
-               capture_dev=0;
-               connect_signals();
-               signal_capture_complete.emit();
-       }
-       else if(src.type==BUTTON && i==src.index)
-               on_press();
-}
-
-void Control::button_release(unsigned i)
-{
-       if(src.type==BUTTON && i==src.index)
-               on_release();
-}
-
-void Control::axis_motion(unsigned i, float v, float r)
-{
-       if(capture_dev)
-       {
-               ControlSrcType type=NONE;
-               if(v<-src.dev->get_axis_threshold())
-                       type=AXIS_NEG;
-               else if(v>src.dev->get_axis_threshold())
-                       type=AXIS_POS;
-
-               if(type!=NONE)
-               {
-                       src.dev=capture_dev;
-                       src.type=type;
-                       src.index=i;
-
-                       notify_callbacks();
-                       capture_dev=0;
-                       connect_signals();
-                       signal_capture_complete.emit();
-               }
-       }
-       else if(src.type==AXIS_POS && i==src.index && v>=0)
-               on_motion(v, r);
-       else if(src.type==AXIS_NEG && i==src.index && v<=0)
-               on_motion(-v, -r);
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/control.h b/source/control.h
deleted file mode 100644 (file)
index f7146b4..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_CONTROL_H_
-#define MSP_GBASE_CONTROL_H_
-
-#include <sigc++/signal.h>
-#include <sigc++/trackable.h>
-
-namespace Msp {
-namespace Input {
-
-class Device;
-
-enum ControlSrcType
-{
-       NONE,
-       BUTTON,
-       AXIS_POS,
-       AXIS_NEG
-};
-
-/**
-Specifies the source of a control.  This provides a way for setting sources for
-different types of controls in a uniform way.
-*/
-struct ControlSource
-{
-       Device *dev;
-       ControlSrcType type;
-       unsigned index;
-
-       ControlSource();
-       ControlSource(Device &, ControlSrcType, unsigned);
-       std::string str() const;
-};
-
-/**
-Provides further abstraction on top of input devices.  There are two types of
-controls currently defined: BinaryControl and SmoothControl.
-
-A control uses either a button or half of an axis (positive or negative) as its
-source.  How the source values are interpreted depends on the exact type of the
-control.  Controls also support interactive binding by capturing a button press
-or axis motion.
-*/
-class Control: public sigc::trackable
-{
-public:
-       sigc::signal<void> signal_capture_complete;
-
-protected:
-       ControlSource src;
-       Device *capture_dev;
-
-       Control();
-       Control(const ControlSource &);
-       Control(Device &, ControlSrcType, unsigned);
-       Control(const Control &);
-public:
-       Control &operator=(const Control &);
-       virtual ~Control() { }
-
-       void capture(Device &);
-       void cancel_capture();
-       const ControlSource &get_source() const { return src; }
-protected:
-       virtual void on_press() =0;
-       virtual void on_release() =0;
-       virtual void on_motion(float, float) =0;
-
-private:
-       void connect_signals();
-       void button_press(unsigned);
-       void button_release(unsigned);
-       void axis_motion(unsigned, float, float);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/display.cpp b/source/display.cpp
deleted file mode 100644 (file)
index 3baf7c1..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <iostream>
-#ifndef WIN32
-#include <X11/Xlib.h>
-#include <X11/extensions/xf86vmode.h>
-#endif
-#include <msp/core/except.h>
-#include <msp/strings/formatter.h>
-#include <msp/strings/lexicalcast.h>
-#include "display.h"
-#include "window.h"
-
-using namespace std;
-
-namespace {
-
-bool error_flag=false;
-std::string error_msg;
-
-#ifndef WIN32
-int x_error_handler(Display *display, XErrorEvent *event)
-{
-       char err[128];
-       XGetErrorText(display, event->error_code, err, sizeof(err));
-
-       string request_code=Msp::lexical_cast(static_cast<int>(event->request_code));
-       char req[128];
-       XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), request_code.c_str(), req, sizeof(req));
-
-       string msg=Msp::format("Request %s failed with %s [%08X]", req, err, event->resourceid);
-       if(error_flag)
-               cerr<<"Discarding error: "<<msg<<'\n';
-       else
-       {
-               cerr<<msg<<'\n';
-               error_msg=msg;
-               error_flag=true;
-       }
-
-       return 0;
-}
-#endif
-
-}
-
-namespace Msp {
-namespace Graphics {
-
-Display::Display(const string &disp_name)
-{
-#ifndef WIN32
-       if(disp_name.empty())
-               display=XOpenDisplay(0);
-       else
-               display=XOpenDisplay(disp_name.c_str());
-       if(!display)
-               throw Exception("Couldn't open X display");
-
-       XSetErrorHandler(x_error_handler);
-
-       int screen=DefaultScreen(display);
-
-       int nmodes;
-       XF86VidModeModeInfo **infos;
-       XF86VidModeGetAllModeLines(display, screen, &nmodes, &infos);
-       for(int i=0; i<nmodes; ++i)
-       {
-               XF86VidModeModeInfo &info=*infos[i];
-       
-               VideoMode mode(info.hdisplay, info.vdisplay);
-               mode.rate=info.dotclock/(info.htotal*info.vtotal);
-               modes.push_back(mode);
-       }
-
-       XFree(infos);
-
-       XF86VidModeModeLine modeline;
-       int dotclock;
-       XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
-       orig_mode=VideoMode(modeline.hdisplay, modeline.vdisplay);
-       orig_mode.rate=dotclock/(modeline.htotal*modeline.vtotal);
-#else
-       (void)disp_name;
-#endif
-}
-
-Display::~Display()
-{
-#ifndef WIN32
-       XCloseDisplay(display);
-       display=0;
-#endif
-}
-
-void Display::add_window(Window *wnd)
-{
-       windows[wnd->get_handle()]=wnd;
-}
-
-void Display::remove_window(Window *wnd)
-{
-       windows.erase(wnd->get_handle());
-}
-
-void Display::set_mode(const VideoMode &mode)
-{
-#ifndef WIN32
-       int screen=DefaultScreen(display);
-
-       int nmodes;
-       XF86VidModeModeInfo **infos;
-       XF86VidModeGetAllModeLines(display, screen, &nmodes, &infos);
-       for(int i=0; i<nmodes; ++i)
-       {
-               XF86VidModeModeInfo &info=*infos[i];
-
-               unsigned rate=info.dotclock/(info.htotal*info.vtotal);
-               if(info.hdisplay==mode.width && info.vdisplay==mode.height && (mode.rate==0 || rate==mode.rate))
-               {
-                       XF86VidModeSwitchToMode(display, screen, &info);
-                       XF86VidModeSetViewPort(display, screen, 0, 0);
-                       return;
-               }
-       }
-
-       throw InvalidParameterValue("Requested mode not supported");
-#else
-       (void)mode;
-#endif
-}
-
-void Display::tick()
-{
-       check_error();
-
-       while(1)
-       {
-#ifdef WIN32
-               MSG msg;
-               if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
-                       DispatchMessage(&msg);
-               else
-                       break;
-#else
-               int pending=XPending(display);
-               if(pending==0)
-                       break;
-
-               for(int i=0; i<pending; ++i)
-               {
-                       XEvent event;
-                       XNextEvent(display, &event);
-
-                       check_error();
-
-                       map<WindowHandle, Window *>::iterator j=windows.find(event.xany.window);
-                       if(j!=windows.end())
-                               j->second->event(event);
-               }
-#endif
-       }
-}
-
-void Display::check_error()
-{
-       if(error_flag)
-       {
-               error_flag=false;
-               throw Exception(error_msg);
-       }
-}
-
-} // namespace Graphics
-} // namespace Msp
diff --git a/source/display.h b/source/display.h
deleted file mode 100644 (file)
index 70efd20..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_DISPLAY_H_
-#define MSP_GBASE_DISPLAY_H_
-
-#include <list>
-#include <map>
-#include <string>
-#include "types.h"
-
-namespace Msp {
-namespace Graphics {
-
-class Window;
-
-struct VideoMode
-{
-       unsigned width;
-       unsigned height;
-       unsigned rate;
-
-       VideoMode(): width(0), height(0), rate(0) { }
-       VideoMode(unsigned w, unsigned h): width(w), height(h), rate(0) { }
-};
-
-class Display
-{
-private:
-#ifndef WIN32
-       ::Display *display;
-#endif
-       std::list<VideoMode> modes;
-       VideoMode orig_mode;
-       std::map<WindowHandle, Window *> windows;
-
-public:
-       Display(const std::string &disp_name=std::string());
-       ~Display();
-
-#ifndef WIN32
-       ::Display *get_display() const { return display; }
-#endif
-
-       void add_window(Window *);
-       void remove_window(Window *);
-
-       const std::list<VideoMode> &get_modes() const { return modes; }
-       void set_mode(const VideoMode &);
-       void restore_mode() { set_mode(orig_mode); }
-
-       void tick();
-       void check_error();
-};
-
-} // namespace Graphics
-} // namespace Msp
-
-#endif
diff --git a/source/drawcontext.cpp b/source/drawcontext.cpp
deleted file mode 100644 (file)
index d3ac485..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef WIN32
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/Xutil.h>
-#endif
-#include <msp/core/except.h>
-#include "display.h"
-#include "drawcontext.h"
-#include "window.h"
-
-namespace Msp {
-namespace Graphics {
-
-DrawContext::DrawContext(Window &w):
-       display(w.get_display()),
-       window(w),
-       image(0)
-{
-#ifndef WIN32
-       ::Display *dpy=display.get_display();
-
-       use_shm=XShmQueryExtension(dpy);
-
-       XWindowAttributes wa;
-       XGetWindowAttributes(dpy, window.get_handle(), &wa);
-
-       if(use_shm)
-       {
-               image=XShmCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, &shminfo, wa.width, wa.height);
-               if(!image)
-                       throw Exception("Could not create shared memory XImage");
-
-               shminfo.shmid=shmget(IPC_PRIVATE, image->bytes_per_line*image->height, IPC_CREAT|0666);
-               shminfo.shmaddr=image->data=reinterpret_cast<char *>(shmat(shminfo.shmid, 0, 0));
-               shminfo.readOnly=false;
-
-               XShmAttach(dpy, &shminfo);
-
-               XSync(dpy, false);
-               display.check_error();
-       }
-       else
-       {
-               image=XCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, 0, wa.width, wa.height, 8, 0);
-               if(!image)
-                       throw Exception("Could not create XImage");
-               image->data=new char[image->bytes_per_line*image->height];
-       }
-#endif
-}
-
-DrawContext::~DrawContext()
-{
-#ifndef WIN32
-       if(use_shm)
-       {
-               XShmDetach(display.get_display(), &shminfo);
-               shmdt(shminfo.shmaddr);
-               shmctl(shminfo.shmid, IPC_RMID, 0);
-       }
-
-       XDestroyImage(image);
-#endif
-}
-
-void DrawContext::update()
-{
-#ifndef WIN32
-       ::Display *dpy=display.get_display();
-
-       GC gc=XCreateGC(dpy, window.get_handle(), 0, 0);
-
-       if(use_shm)
-               XShmPutImage(dpy, window.get_handle(), gc, image, 0, 0, 0, 0, image->width, image->height, false);
-       else
-               XPutImage(dpy, window.get_handle(), gc, image, 0, 0, 0, 0, image->width, image->height);
-
-       XFreeGC(dpy, gc);
-#endif
-}
-
-} // namespace Graphics
-} // namespace Msp
diff --git a/source/drawcontext.h b/source/drawcontext.h
deleted file mode 100644 (file)
index 54ae3b3..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_DRAWCONTEXT_H_
-#define MSP_GBASE_DRAWCONTEXT_H_
-
-#ifndef WIN32
-#include <X11/Xlib.h>
-#include <X11/extensions/XShm.h>
-#endif
-
-namespace Msp {
-namespace Graphics {
-
-class Display;
-class Window;
-
-class DrawContext
-{
-private:
-       Display &display;
-       Window &window;
-#ifndef WIN32
-       XImage *image;
-       bool use_shm;
-       XShmSegmentInfo shminfo;
-#endif
-
-public:
-       DrawContext(Window &);
-       ~DrawContext();
-
-       Window &get_window() const { return window; }
-       unsigned get_depth() const { return image->bits_per_pixel; }
-       unsigned char *get_data() { return reinterpret_cast<unsigned char *>(image->data); }
-       void update();
-};
-
-} // namespace Graphics
-} // namespace Msp
-
-#endif
diff --git a/source/gbase/display.cpp b/source/gbase/display.cpp
new file mode 100644 (file)
index 0000000..3baf7c1
--- /dev/null
@@ -0,0 +1,180 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <iostream>
+#ifndef WIN32
+#include <X11/Xlib.h>
+#include <X11/extensions/xf86vmode.h>
+#endif
+#include <msp/core/except.h>
+#include <msp/strings/formatter.h>
+#include <msp/strings/lexicalcast.h>
+#include "display.h"
+#include "window.h"
+
+using namespace std;
+
+namespace {
+
+bool error_flag=false;
+std::string error_msg;
+
+#ifndef WIN32
+int x_error_handler(Display *display, XErrorEvent *event)
+{
+       char err[128];
+       XGetErrorText(display, event->error_code, err, sizeof(err));
+
+       string request_code=Msp::lexical_cast(static_cast<int>(event->request_code));
+       char req[128];
+       XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), request_code.c_str(), req, sizeof(req));
+
+       string msg=Msp::format("Request %s failed with %s [%08X]", req, err, event->resourceid);
+       if(error_flag)
+               cerr<<"Discarding error: "<<msg<<'\n';
+       else
+       {
+               cerr<<msg<<'\n';
+               error_msg=msg;
+               error_flag=true;
+       }
+
+       return 0;
+}
+#endif
+
+}
+
+namespace Msp {
+namespace Graphics {
+
+Display::Display(const string &disp_name)
+{
+#ifndef WIN32
+       if(disp_name.empty())
+               display=XOpenDisplay(0);
+       else
+               display=XOpenDisplay(disp_name.c_str());
+       if(!display)
+               throw Exception("Couldn't open X display");
+
+       XSetErrorHandler(x_error_handler);
+
+       int screen=DefaultScreen(display);
+
+       int nmodes;
+       XF86VidModeModeInfo **infos;
+       XF86VidModeGetAllModeLines(display, screen, &nmodes, &infos);
+       for(int i=0; i<nmodes; ++i)
+       {
+               XF86VidModeModeInfo &info=*infos[i];
+       
+               VideoMode mode(info.hdisplay, info.vdisplay);
+               mode.rate=info.dotclock/(info.htotal*info.vtotal);
+               modes.push_back(mode);
+       }
+
+       XFree(infos);
+
+       XF86VidModeModeLine modeline;
+       int dotclock;
+       XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
+       orig_mode=VideoMode(modeline.hdisplay, modeline.vdisplay);
+       orig_mode.rate=dotclock/(modeline.htotal*modeline.vtotal);
+#else
+       (void)disp_name;
+#endif
+}
+
+Display::~Display()
+{
+#ifndef WIN32
+       XCloseDisplay(display);
+       display=0;
+#endif
+}
+
+void Display::add_window(Window *wnd)
+{
+       windows[wnd->get_handle()]=wnd;
+}
+
+void Display::remove_window(Window *wnd)
+{
+       windows.erase(wnd->get_handle());
+}
+
+void Display::set_mode(const VideoMode &mode)
+{
+#ifndef WIN32
+       int screen=DefaultScreen(display);
+
+       int nmodes;
+       XF86VidModeModeInfo **infos;
+       XF86VidModeGetAllModeLines(display, screen, &nmodes, &infos);
+       for(int i=0; i<nmodes; ++i)
+       {
+               XF86VidModeModeInfo &info=*infos[i];
+
+               unsigned rate=info.dotclock/(info.htotal*info.vtotal);
+               if(info.hdisplay==mode.width && info.vdisplay==mode.height && (mode.rate==0 || rate==mode.rate))
+               {
+                       XF86VidModeSwitchToMode(display, screen, &info);
+                       XF86VidModeSetViewPort(display, screen, 0, 0);
+                       return;
+               }
+       }
+
+       throw InvalidParameterValue("Requested mode not supported");
+#else
+       (void)mode;
+#endif
+}
+
+void Display::tick()
+{
+       check_error();
+
+       while(1)
+       {
+#ifdef WIN32
+               MSG msg;
+               if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+                       DispatchMessage(&msg);
+               else
+                       break;
+#else
+               int pending=XPending(display);
+               if(pending==0)
+                       break;
+
+               for(int i=0; i<pending; ++i)
+               {
+                       XEvent event;
+                       XNextEvent(display, &event);
+
+                       check_error();
+
+                       map<WindowHandle, Window *>::iterator j=windows.find(event.xany.window);
+                       if(j!=windows.end())
+                               j->second->event(event);
+               }
+#endif
+       }
+}
+
+void Display::check_error()
+{
+       if(error_flag)
+       {
+               error_flag=false;
+               throw Exception(error_msg);
+       }
+}
+
+} // namespace Graphics
+} // namespace Msp
diff --git a/source/gbase/display.h b/source/gbase/display.h
new file mode 100644 (file)
index 0000000..70efd20
--- /dev/null
@@ -0,0 +1,63 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_DISPLAY_H_
+#define MSP_GBASE_DISPLAY_H_
+
+#include <list>
+#include <map>
+#include <string>
+#include "types.h"
+
+namespace Msp {
+namespace Graphics {
+
+class Window;
+
+struct VideoMode
+{
+       unsigned width;
+       unsigned height;
+       unsigned rate;
+
+       VideoMode(): width(0), height(0), rate(0) { }
+       VideoMode(unsigned w, unsigned h): width(w), height(h), rate(0) { }
+};
+
+class Display
+{
+private:
+#ifndef WIN32
+       ::Display *display;
+#endif
+       std::list<VideoMode> modes;
+       VideoMode orig_mode;
+       std::map<WindowHandle, Window *> windows;
+
+public:
+       Display(const std::string &disp_name=std::string());
+       ~Display();
+
+#ifndef WIN32
+       ::Display *get_display() const { return display; }
+#endif
+
+       void add_window(Window *);
+       void remove_window(Window *);
+
+       const std::list<VideoMode> &get_modes() const { return modes; }
+       void set_mode(const VideoMode &);
+       void restore_mode() { set_mode(orig_mode); }
+
+       void tick();
+       void check_error();
+};
+
+} // namespace Graphics
+} // namespace Msp
+
+#endif
diff --git a/source/gbase/drawcontext.cpp b/source/gbase/drawcontext.cpp
new file mode 100644 (file)
index 0000000..d3ac485
--- /dev/null
@@ -0,0 +1,90 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef WIN32
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/Xutil.h>
+#endif
+#include <msp/core/except.h>
+#include "display.h"
+#include "drawcontext.h"
+#include "window.h"
+
+namespace Msp {
+namespace Graphics {
+
+DrawContext::DrawContext(Window &w):
+       display(w.get_display()),
+       window(w),
+       image(0)
+{
+#ifndef WIN32
+       ::Display *dpy=display.get_display();
+
+       use_shm=XShmQueryExtension(dpy);
+
+       XWindowAttributes wa;
+       XGetWindowAttributes(dpy, window.get_handle(), &wa);
+
+       if(use_shm)
+       {
+               image=XShmCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, &shminfo, wa.width, wa.height);
+               if(!image)
+                       throw Exception("Could not create shared memory XImage");
+
+               shminfo.shmid=shmget(IPC_PRIVATE, image->bytes_per_line*image->height, IPC_CREAT|0666);
+               shminfo.shmaddr=image->data=reinterpret_cast<char *>(shmat(shminfo.shmid, 0, 0));
+               shminfo.readOnly=false;
+
+               XShmAttach(dpy, &shminfo);
+
+               XSync(dpy, false);
+               display.check_error();
+       }
+       else
+       {
+               image=XCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, 0, wa.width, wa.height, 8, 0);
+               if(!image)
+                       throw Exception("Could not create XImage");
+               image->data=new char[image->bytes_per_line*image->height];
+       }
+#endif
+}
+
+DrawContext::~DrawContext()
+{
+#ifndef WIN32
+       if(use_shm)
+       {
+               XShmDetach(display.get_display(), &shminfo);
+               shmdt(shminfo.shmaddr);
+               shmctl(shminfo.shmid, IPC_RMID, 0);
+       }
+
+       XDestroyImage(image);
+#endif
+}
+
+void DrawContext::update()
+{
+#ifndef WIN32
+       ::Display *dpy=display.get_display();
+
+       GC gc=XCreateGC(dpy, window.get_handle(), 0, 0);
+
+       if(use_shm)
+               XShmPutImage(dpy, window.get_handle(), gc, image, 0, 0, 0, 0, image->width, image->height, false);
+       else
+               XPutImage(dpy, window.get_handle(), gc, image, 0, 0, 0, 0, image->width, image->height);
+
+       XFreeGC(dpy, gc);
+#endif
+}
+
+} // namespace Graphics
+} // namespace Msp
diff --git a/source/gbase/drawcontext.h b/source/gbase/drawcontext.h
new file mode 100644 (file)
index 0000000..54ae3b3
--- /dev/null
@@ -0,0 +1,46 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_DRAWCONTEXT_H_
+#define MSP_GBASE_DRAWCONTEXT_H_
+
+#ifndef WIN32
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+#endif
+
+namespace Msp {
+namespace Graphics {
+
+class Display;
+class Window;
+
+class DrawContext
+{
+private:
+       Display &display;
+       Window &window;
+#ifndef WIN32
+       XImage *image;
+       bool use_shm;
+       XShmSegmentInfo shminfo;
+#endif
+
+public:
+       DrawContext(Window &);
+       ~DrawContext();
+
+       Window &get_window() const { return window; }
+       unsigned get_depth() const { return image->bits_per_pixel; }
+       unsigned char *get_data() { return reinterpret_cast<unsigned char *>(image->data); }
+       void update();
+};
+
+} // namespace Graphics
+} // namespace Msp
+
+#endif
diff --git a/source/gbase/glcontext.cpp b/source/gbase/glcontext.cpp
new file mode 100644 (file)
index 0000000..a749c6c
--- /dev/null
@@ -0,0 +1,149 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <vector>
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <GL/gl.h>
+#include <msp/core/application.h>
+#include <msp/core/except.h>
+#include "display.h"
+#include "glcontext.h"
+#include "window.h"
+
+#include <iostream>
+using namespace std;
+
+namespace Msp {
+namespace Graphics {
+
+GLOptions::GLOptions():
+       alpha(false),
+       stencil(false),
+       doublebuffer(true),
+       multisample(0)
+{ }
+
+
+GLContext::GLContext(Window &wnd, const GLOptions &opts):
+       display(wnd.get_display()),
+       window(wnd)
+{
+#ifdef WIN32
+       HDC dc=GetDC(window.get_handle());
+
+       PIXELFORMATDESCRIPTOR pfd;
+       memset(&pfd, 0, sizeof(pfd));
+
+       pfd.nSize=sizeof(pfd);
+       pfd.nVersion=1;
+       pfd.dwFlags=PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+       if(opts.doublebuffer)
+               pfd.dwFlags|=PFD_DOUBLEBUFFER;
+       pfd.iPixelType=PFD_TYPE_RGBA;
+       if(opts.alpha)
+               pfd.cAlphaBits=1;
+       pfd.cDepthBits=1;
+       if(opts.stencil)
+               pfd.cStencilBits=1;
+
+       int pf_index=ChoosePixelFormat(dc, &pfd);
+       if(!pf_index)
+               throw Exception("Couldn't find a suitable pixel format");
+       SetPixelFormat(dc, pf_index, &pfd);
+
+       context=wglCreateContext(dc);
+       wglMakeCurrent(dc, context);
+
+       ReleaseDC(window.get_handle(), dc);
+#else
+       std::vector<int> attribs;
+       
+       attribs.push_back(GLX_RGBA);
+       attribs.push_back(GLX_DEPTH_SIZE);
+       attribs.push_back(1);
+       
+       if(opts.alpha)
+       {
+               attribs.push_back(GLX_ALPHA_SIZE);
+               attribs.push_back(1);
+       }
+       
+       if(opts.stencil)
+       {
+               attribs.push_back(GLX_STENCIL_SIZE);
+               attribs.push_back(1);
+       }
+       
+       if(opts.doublebuffer)
+               attribs.push_back(GLX_DOUBLEBUFFER);
+       
+       if(opts.multisample>0)
+       {
+               attribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
+               attribs.push_back(opts.multisample);
+       }
+       
+       attribs.push_back(0);
+
+       ::Display *dpy=display.get_display();
+
+       XVisualInfo *vi=glXChooseVisual(dpy, DefaultScreen(dpy), &attribs.front());
+       if(!vi)
+               throw Exception("Couldn't find a suitable GLX visual");
+       context=glXCreateContext(dpy, vi, 0, true);
+
+       XSetWindowAttributes attr;
+       attr.colormap=XCreateColormap(dpy, DefaultRootWindow(dpy), vi->visual, AllocNone);
+
+       subwnd=XCreateWindow(dpy, window.get_handle(), 0, 0, window.get_width(), window.get_height(), 0, vi->depth, InputOutput, vi->visual, CWColormap, &attr);
+       XMapWindow(display.get_display(), subwnd);
+
+       XFree(vi);
+
+       glXMakeCurrent(dpy, subwnd, context);
+
+       window.signal_resize.connect(sigc::mem_fun(this, &GLContext::window_resized));
+#endif
+}
+
+GLContext::~GLContext()
+{
+#ifdef WIN32
+       wglMakeCurrent(0, 0);
+       wglDeleteContext(context);
+#else
+       ::Display *dpy=display.get_display();
+
+       glXMakeCurrent(dpy, 0, 0);
+       glXDestroyContext(dpy, context);
+       XDestroyWindow(dpy, subwnd);
+#endif
+}
+
+void GLContext::swap_buffers()
+{
+#ifdef WIN32
+       HDC dc=GetDC(window.get_handle());
+       SwapBuffers(dc);
+       ReleaseDC(window.get_handle(), dc);
+#else
+       glXSwapBuffers(display.get_display(), subwnd);
+#endif
+}
+
+void GLContext::window_resized(unsigned w, unsigned h)
+{
+#ifndef WIN32
+       XMoveResizeWindow(display.get_display(), subwnd, 0, 0, w, h);
+#endif
+       glViewport(0, 0, w, h);
+}
+
+} // namespace Graphics
+} // namespace Msp
diff --git a/source/gbase/glcontext.h b/source/gbase/glcontext.h
new file mode 100644 (file)
index 0000000..297bc34
--- /dev/null
@@ -0,0 +1,59 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_GLCONTEXT_H_
+#define MSP_GBASE_GLCONTEXT_H_
+
+#ifndef WIN32
+#include <GL/glx.h>
+#endif
+#include "types.h"
+
+namespace Msp {
+namespace Graphics {
+
+class Display;
+
+struct GLOptions
+{
+       bool alpha;
+       bool stencil;
+       bool doublebuffer;
+       unsigned multisample;
+
+       GLOptions();
+};
+
+class GLContext
+{
+private:
+#ifdef WIN32
+       typedef HGLRC Context;
+#else
+       typedef GLXContext Context;
+#endif
+
+       Display &display;
+       Window &window;
+       Context context;
+#ifndef WIN32
+       WindowHandle subwnd;
+#endif
+
+public:
+       GLContext(Window &wnd, const GLOptions &opts=GLOptions());
+       ~GLContext();
+
+       void swap_buffers();
+private:
+       void window_resized(unsigned, unsigned);
+};
+
+} // namespace Graphics
+} // namespace Msp
+
+#endif
diff --git a/source/gbase/types.h b/source/gbase/types.h
new file mode 100644 (file)
index 0000000..e3524f3
--- /dev/null
@@ -0,0 +1,29 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_TYPES_H_
+#define MSP_GBASE_TYPES_H_
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <X11/Xlib.h>
+#endif
+
+namespace Msp {
+namespace Graphics {
+
+#ifdef WIN32
+typedef HWND WindowHandle;
+#else
+typedef ::Window WindowHandle;
+#endif
+
+} // namespace Graphics
+} // namespace Msp
+
+#endif
diff --git a/source/gbase/window.cpp b/source/gbase/window.cpp
new file mode 100644 (file)
index 0000000..da877e9
--- /dev/null
@@ -0,0 +1,322 @@
+/* $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
diff --git a/source/gbase/window.h b/source/gbase/window.h
new file mode 100644 (file)
index 0000000..e85f86a
--- /dev/null
@@ -0,0 +1,80 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_WINDOW_H_
+#define MSP_GBASE_WINDOW_H_
+
+#include <string>
+#include <sigc++/signal.h>
+#include "types.h"
+
+namespace Msp {
+namespace Graphics {
+
+class Display;
+
+struct WindowOptions
+{
+       unsigned width;
+       unsigned height;
+       bool fullscreen;
+       bool resizable;
+
+       WindowOptions();
+};
+
+class Window
+{
+public:
+       sigc::signal<void, int, int, unsigned, unsigned> signal_button_press;
+       sigc::signal<void, int, int, unsigned, unsigned> signal_button_release;
+       sigc::signal<void, int, int> signal_pointer_motion;
+       sigc::signal<void, unsigned, unsigned, unsigned> signal_key_press;
+       sigc::signal<void, unsigned, unsigned> signal_key_release;
+       sigc::signal<void, unsigned, unsigned> signal_resize;
+       sigc::signal<void> signal_close;
+
+protected:
+       Display &display;
+       WindowOptions options;
+       WindowHandle window;
+#ifndef WIN32
+       Atom wm_delete_window;
+#endif
+
+public:
+       Window(Display &, unsigned w, unsigned h, bool fs=false);
+       Window(Display &, const WindowOptions &);
+       ~Window();
+
+       void set_title(const std::string &);
+       void reconfigure(const WindowOptions &);
+
+       Display &get_display() const { return display; }
+       const WindowOptions &get_options() const { return options; }
+       unsigned get_width() const  { return options.width; }
+       unsigned get_height() const { return options.height; }
+       WindowHandle get_handle() const { return window; }
+
+       void show();
+       void hide();
+
+#ifndef WIN32
+       void event(const XEvent &ev);
+#endif
+protected:
+       void init();
+#ifdef WIN32
+       int wndproc(UINT, WPARAM, LPARAM);
+       static LRESULT CALLBACK wndproc_(HWND, UINT, WPARAM, LPARAM);
+#endif
+};
+
+} // namespace Graphics
+} // namespace Msp
+
+#endif
diff --git a/source/glcontext.cpp b/source/glcontext.cpp
deleted file mode 100644 (file)
index a749c6c..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <vector>
-#ifdef WIN32
-#include <windows.h>
-#endif
-#include <GL/gl.h>
-#include <msp/core/application.h>
-#include <msp/core/except.h>
-#include "display.h"
-#include "glcontext.h"
-#include "window.h"
-
-#include <iostream>
-using namespace std;
-
-namespace Msp {
-namespace Graphics {
-
-GLOptions::GLOptions():
-       alpha(false),
-       stencil(false),
-       doublebuffer(true),
-       multisample(0)
-{ }
-
-
-GLContext::GLContext(Window &wnd, const GLOptions &opts):
-       display(wnd.get_display()),
-       window(wnd)
-{
-#ifdef WIN32
-       HDC dc=GetDC(window.get_handle());
-
-       PIXELFORMATDESCRIPTOR pfd;
-       memset(&pfd, 0, sizeof(pfd));
-
-       pfd.nSize=sizeof(pfd);
-       pfd.nVersion=1;
-       pfd.dwFlags=PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
-       if(opts.doublebuffer)
-               pfd.dwFlags|=PFD_DOUBLEBUFFER;
-       pfd.iPixelType=PFD_TYPE_RGBA;
-       if(opts.alpha)
-               pfd.cAlphaBits=1;
-       pfd.cDepthBits=1;
-       if(opts.stencil)
-               pfd.cStencilBits=1;
-
-       int pf_index=ChoosePixelFormat(dc, &pfd);
-       if(!pf_index)
-               throw Exception("Couldn't find a suitable pixel format");
-       SetPixelFormat(dc, pf_index, &pfd);
-
-       context=wglCreateContext(dc);
-       wglMakeCurrent(dc, context);
-
-       ReleaseDC(window.get_handle(), dc);
-#else
-       std::vector<int> attribs;
-       
-       attribs.push_back(GLX_RGBA);
-       attribs.push_back(GLX_DEPTH_SIZE);
-       attribs.push_back(1);
-       
-       if(opts.alpha)
-       {
-               attribs.push_back(GLX_ALPHA_SIZE);
-               attribs.push_back(1);
-       }
-       
-       if(opts.stencil)
-       {
-               attribs.push_back(GLX_STENCIL_SIZE);
-               attribs.push_back(1);
-       }
-       
-       if(opts.doublebuffer)
-               attribs.push_back(GLX_DOUBLEBUFFER);
-       
-       if(opts.multisample>0)
-       {
-               attribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
-               attribs.push_back(opts.multisample);
-       }
-       
-       attribs.push_back(0);
-
-       ::Display *dpy=display.get_display();
-
-       XVisualInfo *vi=glXChooseVisual(dpy, DefaultScreen(dpy), &attribs.front());
-       if(!vi)
-               throw Exception("Couldn't find a suitable GLX visual");
-       context=glXCreateContext(dpy, vi, 0, true);
-
-       XSetWindowAttributes attr;
-       attr.colormap=XCreateColormap(dpy, DefaultRootWindow(dpy), vi->visual, AllocNone);
-
-       subwnd=XCreateWindow(dpy, window.get_handle(), 0, 0, window.get_width(), window.get_height(), 0, vi->depth, InputOutput, vi->visual, CWColormap, &attr);
-       XMapWindow(display.get_display(), subwnd);
-
-       XFree(vi);
-
-       glXMakeCurrent(dpy, subwnd, context);
-
-       window.signal_resize.connect(sigc::mem_fun(this, &GLContext::window_resized));
-#endif
-}
-
-GLContext::~GLContext()
-{
-#ifdef WIN32
-       wglMakeCurrent(0, 0);
-       wglDeleteContext(context);
-#else
-       ::Display *dpy=display.get_display();
-
-       glXMakeCurrent(dpy, 0, 0);
-       glXDestroyContext(dpy, context);
-       XDestroyWindow(dpy, subwnd);
-#endif
-}
-
-void GLContext::swap_buffers()
-{
-#ifdef WIN32
-       HDC dc=GetDC(window.get_handle());
-       SwapBuffers(dc);
-       ReleaseDC(window.get_handle(), dc);
-#else
-       glXSwapBuffers(display.get_display(), subwnd);
-#endif
-}
-
-void GLContext::window_resized(unsigned w, unsigned h)
-{
-#ifndef WIN32
-       XMoveResizeWindow(display.get_display(), subwnd, 0, 0, w, h);
-#endif
-       glViewport(0, 0, w, h);
-}
-
-} // namespace Graphics
-} // namespace Msp
diff --git a/source/glcontext.h b/source/glcontext.h
deleted file mode 100644 (file)
index 297bc34..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_GLCONTEXT_H_
-#define MSP_GBASE_GLCONTEXT_H_
-
-#ifndef WIN32
-#include <GL/glx.h>
-#endif
-#include "types.h"
-
-namespace Msp {
-namespace Graphics {
-
-class Display;
-
-struct GLOptions
-{
-       bool alpha;
-       bool stencil;
-       bool doublebuffer;
-       unsigned multisample;
-
-       GLOptions();
-};
-
-class GLContext
-{
-private:
-#ifdef WIN32
-       typedef HGLRC Context;
-#else
-       typedef GLXContext Context;
-#endif
-
-       Display &display;
-       Window &window;
-       Context context;
-#ifndef WIN32
-       WindowHandle subwnd;
-#endif
-
-public:
-       GLContext(Window &wnd, const GLOptions &opts=GLOptions());
-       ~GLContext();
-
-       void swap_buffers();
-private:
-       void window_resized(unsigned, unsigned);
-};
-
-} // namespace Graphics
-} // namespace Msp
-
-#endif
diff --git a/source/input/binarycontrol.cpp b/source/input/binarycontrol.cpp
new file mode 100644 (file)
index 0000000..9bf2408
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "binarycontrol.h"
+#include "device.h"
+
+namespace Msp {
+namespace Input {
+
+BinaryControl::BinaryControl():
+       state(false)
+{ }
+
+BinaryControl::BinaryControl(const ControlSource &s):
+       Control(s),
+       state(false)
+{ }
+
+BinaryControl::BinaryControl(Device &d, ControlSrcType t, unsigned i):
+       Control(d, t, i),
+       state(false)
+{ }
+
+void BinaryControl::on_press()
+{
+       if(!state)
+       {
+               state=true;
+               signal_press.emit();
+       }
+}
+
+void BinaryControl::on_release()
+{
+       if(state)
+       {
+               state=false;
+               signal_release.emit();
+       }
+}
+
+void BinaryControl::on_motion(float value, float)
+{
+       if(value>src.dev->get_axis_threshold())
+               on_press();
+       else
+               on_release();
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/binarycontrol.h b/source/input/binarycontrol.h
new file mode 100644 (file)
index 0000000..44aaef4
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_BINARYCONTROL_H_
+#define MSP_GBASE_BINARYCONTROL_H_
+
+#include "control.h"
+
+namespace Msp {
+namespace Input {
+
+/**
+A control with two possible states.  Button state is mapped directly.  An axis
+is considered to be active when its value is above a threshold (defined by the
+input device).
+*/
+class BinaryControl: public Control
+{
+public:
+       sigc::signal<void> signal_press;
+       sigc::signal<void> signal_release;
+
+private:
+       bool state;
+
+public:
+       BinaryControl();
+       BinaryControl(const ControlSource &);
+       BinaryControl(Device &, ControlSrcType, unsigned);
+       bool get_state() const { return state; }
+
+private:
+       virtual void on_press();
+       virtual void on_release();
+       virtual void on_motion(float, float);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/control.cpp b/source/input/control.cpp
new file mode 100644 (file)
index 0000000..8ddcdd7
--- /dev/null
@@ -0,0 +1,161 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/core/except.h>
+#include <msp/strings/lexicalcast.h>
+#include "control.h"
+#include "device.h"
+
+namespace Msp {
+namespace Input {
+
+ControlSource::ControlSource():
+       dev(0),
+       type(NONE),
+       index(0)
+{ }
+
+ControlSource::ControlSource(Device &d, ControlSrcType t, unsigned i):
+       dev(&d),
+       type(t),
+       index(i)
+{ }
+
+std::string ControlSource::str() const
+{
+       if(type==BUTTON)
+               return dev->get_button_name(index);
+       else if(type==AXIS_POS || type==AXIS_NEG)
+               return dev->get_axis_name(index);
+       else if(type==NONE)
+               return "None";
+
+       return lexical_cast(index);
+}
+
+
+Control::Control():
+       capture_dev(0)
+{ }
+
+Control::Control(const ControlSource &s):
+       src(s),
+       capture_dev(0)
+{ }
+
+Control::Control(Device &d, ControlSrcType t, unsigned i):
+       src(d, t, i),
+       capture_dev(0)
+{
+       connect_signals();
+}
+
+Control::Control(const Control &c):
+       trackable(c),
+       src(c.src),
+       capture_dev(0)
+{
+       connect_signals();
+}
+
+Control &Control::operator=(const Control &c)
+{
+       notify_callbacks();
+       src=c.src;
+       capture_dev=0;
+       connect_signals();
+
+       return *this;
+}
+
+void Control::capture(Device &d)
+{
+       notify_callbacks();
+       capture_dev=&d;
+       capture_dev->signal_button_press.connect(sigc::mem_fun(this, &Control::button_press));
+       capture_dev->signal_axis_motion.connect(sigc::mem_fun(this, &Control::axis_motion));
+}
+
+void Control::cancel_capture()
+{
+       notify_callbacks();
+       capture_dev=0;
+       connect_signals();
+}
+
+void Control::connect_signals()
+{
+       switch(src.type)
+       {
+       case NONE:
+               break;
+       case BUTTON:
+               src.dev->signal_button_press.connect(sigc::mem_fun(this, &Control::button_press));
+               src.dev->signal_button_release.connect(sigc::mem_fun(this, &Control::button_release));
+               break;
+       case AXIS_POS:
+       case AXIS_NEG:
+               src.dev->signal_axis_motion.connect(sigc::mem_fun(this, &Control::axis_motion));
+               break;
+       default:
+               throw Exception("Invalid source in Control");
+       }
+}
+
+void Control::button_press(unsigned i)
+{
+       if(capture_dev)
+       {
+               src.dev=capture_dev;
+               src.type=BUTTON;
+               src.index=i;
+
+               notify_callbacks();
+               capture_dev=0;
+               connect_signals();
+               signal_capture_complete.emit();
+       }
+       else if(src.type==BUTTON && i==src.index)
+               on_press();
+}
+
+void Control::button_release(unsigned i)
+{
+       if(src.type==BUTTON && i==src.index)
+               on_release();
+}
+
+void Control::axis_motion(unsigned i, float v, float r)
+{
+       if(capture_dev)
+       {
+               ControlSrcType type=NONE;
+               if(v<-src.dev->get_axis_threshold())
+                       type=AXIS_NEG;
+               else if(v>src.dev->get_axis_threshold())
+                       type=AXIS_POS;
+
+               if(type!=NONE)
+               {
+                       src.dev=capture_dev;
+                       src.type=type;
+                       src.index=i;
+
+                       notify_callbacks();
+                       capture_dev=0;
+                       connect_signals();
+                       signal_capture_complete.emit();
+               }
+       }
+       else if(src.type==AXIS_POS && i==src.index && v>=0)
+               on_motion(v, r);
+       else if(src.type==AXIS_NEG && i==src.index && v<=0)
+               on_motion(-v, -r);
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/control.h b/source/input/control.h
new file mode 100644 (file)
index 0000000..f7146b4
--- /dev/null
@@ -0,0 +1,86 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_CONTROL_H_
+#define MSP_GBASE_CONTROL_H_
+
+#include <sigc++/signal.h>
+#include <sigc++/trackable.h>
+
+namespace Msp {
+namespace Input {
+
+class Device;
+
+enum ControlSrcType
+{
+       NONE,
+       BUTTON,
+       AXIS_POS,
+       AXIS_NEG
+};
+
+/**
+Specifies the source of a control.  This provides a way for setting sources for
+different types of controls in a uniform way.
+*/
+struct ControlSource
+{
+       Device *dev;
+       ControlSrcType type;
+       unsigned index;
+
+       ControlSource();
+       ControlSource(Device &, ControlSrcType, unsigned);
+       std::string str() const;
+};
+
+/**
+Provides further abstraction on top of input devices.  There are two types of
+controls currently defined: BinaryControl and SmoothControl.
+
+A control uses either a button or half of an axis (positive or negative) as its
+source.  How the source values are interpreted depends on the exact type of the
+control.  Controls also support interactive binding by capturing a button press
+or axis motion.
+*/
+class Control: public sigc::trackable
+{
+public:
+       sigc::signal<void> signal_capture_complete;
+
+protected:
+       ControlSource src;
+       Device *capture_dev;
+
+       Control();
+       Control(const ControlSource &);
+       Control(Device &, ControlSrcType, unsigned);
+       Control(const Control &);
+public:
+       Control &operator=(const Control &);
+       virtual ~Control() { }
+
+       void capture(Device &);
+       void cancel_capture();
+       const ControlSource &get_source() const { return src; }
+protected:
+       virtual void on_press() =0;
+       virtual void on_release() =0;
+       virtual void on_motion(float, float) =0;
+
+private:
+       void connect_signals();
+       void button_press(unsigned);
+       void button_release(unsigned);
+       void axis_motion(unsigned, float, float);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/device.cpp b/source/input/device.cpp
new file mode 100644 (file)
index 0000000..23393de
--- /dev/null
@@ -0,0 +1,75 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/strings/formatter.h>
+#include "device.h"
+
+namespace Msp {
+namespace Input {
+
+bool Device::get_button_state(unsigned btn) const
+{
+       if(btn>buttons.size())
+               return false;
+
+       return buttons[btn];
+}
+
+float Device::get_axis_value(unsigned axis) const
+{
+       if(axis>axes.size())
+               return 0;
+
+       return axes[axis];
+}
+
+std::string Device::get_button_name(unsigned btn) const
+{
+       return format("Button %d", btn);
+}
+
+std::string Device::get_axis_name(unsigned axis) const
+{
+       return format("Axis %d", axis);
+}
+
+void Device::set_button_state(unsigned btn, bool state, bool event)
+{
+       if(btn>=buttons.size())
+               buttons.resize(btn+1, false);
+
+       if(state!=buttons[btn])
+       {
+               buttons[btn]=state;
+
+               if(event)
+               {
+                       if(state)
+                               signal_button_press.emit(btn);
+                       else
+                               signal_button_release.emit(btn);
+               }
+       }
+}
+
+void Device::set_axis_value(unsigned axis, float value, bool event)
+{
+       if(axis>=axes.size())
+               axes.resize(axis+1, 0);
+
+       if(value!=axes[axis])
+       {
+               float old=axes[axis];
+               axes[axis]=value;
+
+               if(event)
+                       signal_axis_motion.emit(axis, value, value-old);
+       }
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/device.h b/source/input/device.h
new file mode 100644 (file)
index 0000000..d1c96f2
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_INPUTDEVICE_H_
+#define MSP_GBASE_INPUTDEVICE_H_
+
+#include <string>
+#include <vector>
+#include <sigc++/signal.h>
+
+namespace Msp {
+namespace Input {
+
+/**
+Base class for input devices.  Input devices have two types of controls:
+buttons and axes.  Buttons are either on or off.  Axes have a floating-point
+value, with range depending on the device.
+*/
+class Device
+{
+public:
+       sigc::signal<void, unsigned> signal_button_press;
+       sigc::signal<void, unsigned> signal_button_release;
+       sigc::signal<void, unsigned, float, float> signal_axis_motion;
+
+protected:
+       std::string name;
+       std::vector<char>  buttons;
+       std::vector<float> axes;
+       float axis_threshold;
+       float axis_dead_zone;
+
+       Device() { }
+public:
+       virtual ~Device() { }
+       const std::string &get_name() const { return name; }
+       bool  get_button_state(unsigned) const;
+       float get_axis_value(unsigned) const;
+       float get_axis_threshold() const { return axis_threshold; }
+
+       virtual std::string get_button_name(unsigned) const;
+       virtual std::string get_axis_name(unsigned) const;
+protected:
+       void set_button_state(unsigned, bool, bool);
+       void set_axis_value(unsigned, float, bool);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/hub.cpp b/source/input/hub.cpp
new file mode 100644 (file)
index 0000000..51b9717
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <sigc++/bind.h>
+#include <msp/core/except.h>
+#include "hub.h"
+
+namespace Msp {
+namespace Input {
+
+Hub::Hub()
+{
+       name="Hub";
+}
+
+unsigned Hub::attach(Device &dev)
+{
+       unsigned index=devices.size();
+       devices.push_back(&dev);
+       dev.signal_button_press.connect(sigc::bind(sigc::mem_fun(this, &Hub::button_press), index));
+       dev.signal_button_release.connect(sigc::bind(sigc::mem_fun(this, &Hub::button_release), index));
+       dev.signal_axis_motion.connect(sigc::bind(sigc::mem_fun(this, &Hub::axis_motion), index));
+       return index;
+}
+
+std::string Hub::get_button_name(unsigned btn) const
+{
+       unsigned dev_index=btn>>12;
+       if(dev_index>devices.size())
+               throw InvalidParameterValue("Button does not exist");
+
+       const Device &dev=*devices[dev_index];
+       return dev.get_name()+": "+dev.get_button_name(btn&0xFFF);
+}
+
+void Hub::button_press(unsigned btn, unsigned index)
+{
+       set_button_state(index<<12 | btn&0xFFF, true, true);
+}
+
+void Hub::button_release(unsigned btn, unsigned index)
+{
+       set_button_state(index<<12 | btn&0xFFF, false, true);
+}
+
+void Hub::axis_motion(unsigned axis, float value, float, unsigned index)
+{
+       set_axis_value(index<<12 | axis&0xFFF, value, true);
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/hub.h b/source/input/hub.h
new file mode 100644 (file)
index 0000000..4385f27
--- /dev/null
@@ -0,0 +1,47 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_INPUTHUB_H_
+#define MSP_GBASE_INPUTHUB_H_
+
+#include "device.h"
+
+namespace Msp {
+namespace Input {
+
+/**
+The Hub device collects events from multiple input devices and presents an
+aggregate of them.  Button and axis numbers are mapped to unique values.
+*/
+class Hub: public Device
+{
+protected:
+       std::vector<Device *> devices;
+
+public:
+       Hub();
+
+       /**
+       Attaches an input device to the hub.
+
+       @param   dev  Device to attach
+
+       @return  Index of the device within the hub
+       */
+       unsigned attach(Device &dev);
+
+       virtual std::string get_button_name(unsigned) const;
+protected:
+       void button_press(unsigned, unsigned);
+       void button_release(unsigned, unsigned);
+       void axis_motion(unsigned, float, float, unsigned);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/keyboard.cpp b/source/input/keyboard.cpp
new file mode 100644 (file)
index 0000000..240d700
--- /dev/null
@@ -0,0 +1,50 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/strings/formatter.h>
+#include "../gbase/display.h"
+#include "keyboard.h"
+
+namespace Msp {
+namespace Input {
+
+Keyboard::Keyboard(Graphics::Window &w):
+       window(w)
+{
+       name="Keyboard";
+
+       buttons.resize(256, false);
+
+       window.signal_key_press.connect(sigc::mem_fun(this, &Keyboard::key_press));
+       window.signal_key_release.connect(sigc::mem_fun(this, &Keyboard::key_release));
+}
+
+std::string Keyboard::get_button_name(unsigned btn) const
+{
+#ifndef WIN32
+       KeySym ksym=XKeycodeToKeysym(window.get_display().get_display(), btn, 0);
+       return XKeysymToString(ksym);
+#else
+       char buf[128];
+       if(!GetKeyNameText(btn<<16, buf, sizeof(buf)))
+               return format("Key %d", btn);
+       return buf;
+#endif
+}
+
+void Keyboard::key_press(unsigned key, unsigned, unsigned)
+{
+       set_button_state(key, true, true);
+}
+
+void Keyboard::key_release(unsigned key, unsigned)
+{
+       set_button_state(key, false, true);
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/keyboard.h b/source/input/keyboard.h
new file mode 100644 (file)
index 0000000..54479ea
--- /dev/null
@@ -0,0 +1,34 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_KEYBOARD_H_
+#define MSP_GBASE_KEYBOARD_H_
+
+#include "device.h"
+#include "../gbase/window.h"
+
+namespace Msp {
+namespace Input {
+
+class Keyboard: public Device
+{
+private:
+       Graphics::Window &window;
+
+public:
+       Keyboard(Graphics::Window &);
+
+       virtual std::string get_button_name(unsigned) const;
+private:
+       void key_press(unsigned, unsigned, unsigned);
+       void key_release(unsigned, unsigned);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/mouse.cpp b/source/input/mouse.cpp
new file mode 100644 (file)
index 0000000..931b204
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/strings/formatter.h>
+#include "mouse.h"
+
+namespace Msp {
+namespace Input {
+
+Mouse::Mouse(Graphics::Window &w):
+       window(w),
+       axis_scale(0.01)
+{
+       name="Mouse";
+
+       buttons.resize(3);
+       axes.resize(2);
+
+       window.signal_button_press.connect(sigc::mem_fun(this, &Mouse::button_press));
+       window.signal_button_release.connect(sigc::mem_fun(this, &Mouse::button_release));
+       window.signal_pointer_motion.connect(sigc::mem_fun(this, &Mouse::pointer_motion));
+}
+
+std::string Mouse::get_button_name(unsigned btn) const
+{
+       switch(btn)
+       {
+       case 1:
+               return "Left";
+       case 2:
+               return "Middle";
+       case 3:
+               return "Right";
+       case 4:
+               return "Wheel Up";
+       case 5:
+               return "Wheel Down";
+       default:
+               return format("Button %d", btn);
+       }
+}
+
+void Mouse::button_press(int, int, unsigned btn, unsigned)
+{
+       set_button_state(btn, true, true);
+}
+
+void Mouse::button_release(int, int, unsigned btn, unsigned)
+{
+       set_button_state(btn, false, true);
+}
+
+void Mouse::pointer_motion(int x, int y)
+{
+       set_axis_value(0, x*axis_scale, true);
+       set_axis_value(1, y*axis_scale, true);
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/mouse.h b/source/input/mouse.h
new file mode 100644 (file)
index 0000000..8d5086f
--- /dev/null
@@ -0,0 +1,35 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_MOUSE_H_
+#define MSP_GBASE_MOUSE_H_
+
+#include "device.h"
+#include "../gbase/window.h"
+
+namespace Msp {
+namespace Input {
+
+class Mouse: public Device
+{
+private:
+       Graphics::Window &window;
+       float axis_scale;
+
+public:
+       Mouse(Graphics::Window &);
+       virtual std::string get_button_name(unsigned) const;
+private:
+       void button_press(int, int, unsigned, unsigned);
+       void button_release(int, int, unsigned, unsigned);
+       void pointer_motion(int, int);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/smoothcontrol.cpp b/source/input/smoothcontrol.cpp
new file mode 100644 (file)
index 0000000..69dfacf
--- /dev/null
@@ -0,0 +1,81 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "smoothcontrol.h"
+
+namespace Msp {
+namespace Input {
+
+SmoothControl::SmoothControl():
+       value(0),
+       paired_ctrl(0)
+{ }
+
+SmoothControl::SmoothControl(const ControlSource &s):
+       Control(s),
+       value(0),
+       paired_ctrl(0)
+{ }
+
+SmoothControl::SmoothControl(Device &d, ControlSrcType t, unsigned i):
+       Control(d, t, i),
+       value(0),
+       paired_ctrl(0)
+{ }
+
+SmoothControl &SmoothControl::operator=(const SmoothControl &sc)
+{
+       Control::operator=(sc);
+
+       return *this;
+}
+
+SmoothControl::~SmoothControl()
+{
+       pair(0);
+}
+
+void SmoothControl::pair(SmoothControl *ctrl)
+{
+       if(ctrl==paired_ctrl)
+               return;
+
+       if(paired_ctrl)
+       {
+               SmoothControl *old_pair=paired_ctrl;
+               paired_ctrl=0;
+               old_pair->pair(0);
+       }
+
+       paired_ctrl=ctrl;
+
+       if(paired_ctrl)
+               paired_ctrl->pair(this);
+}
+
+void SmoothControl::on_press()
+{
+       on_motion(1, 1-value);
+}
+
+void SmoothControl::on_release()
+{
+       if(value>0)
+               on_motion(0, -value);
+}
+
+void SmoothControl::on_motion(float v, float)
+{
+       value=v;
+       signal_motion.emit(value);
+       
+       if(paired_ctrl && paired_ctrl->get_value()!=-value)
+               paired_ctrl->on_motion(-value, -value-paired_ctrl->get_value());
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/smoothcontrol.h b/source/input/smoothcontrol.h
new file mode 100644 (file)
index 0000000..26484a9
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GBASE_SMOOTHCONTROL_H_
+#define MSP_GBASE_SMOOTHCONTROL_H_
+
+#include "control.h"
+
+namespace Msp {
+namespace Input {
+
+/**
+A control with a continuous range of values.  A button is treated as either 1
+or 0.  Axis values are mapped to absolute value.
+
+Two smooth controls can also be paired to each other.  Motion on one control of
+the pair will cause negative motion on the other.  This works best when the
+controls are bound to the opposite sides of the same joystick axis.
+*/
+class SmoothControl: public Control
+{
+public:
+       sigc::signal<void, float> signal_motion;
+
+private:
+       float value;
+       SmoothControl *paired_ctrl;
+
+public:
+       SmoothControl();
+       SmoothControl(const ControlSource &);
+       SmoothControl(Device &, ControlSrcType, unsigned);
+       SmoothControl &operator=(const SmoothControl &);
+       virtual ~SmoothControl();
+
+       void pair(SmoothControl *ctrl);
+       float get_value() const { return value; }
+
+private:
+       virtual void on_press();
+       virtual void on_release();
+       virtual void on_motion(float, float);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/inputdevice.cpp b/source/inputdevice.cpp
deleted file mode 100644 (file)
index f3092e1..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/strings/formatter.h>
-#include "inputdevice.h"
-
-namespace Msp {
-namespace Input {
-
-bool Device::get_button_state(unsigned btn) const
-{
-       if(btn>buttons.size())
-               return false;
-
-       return buttons[btn];
-}
-
-float Device::get_axis_value(unsigned axis) const
-{
-       if(axis>axes.size())
-               return 0;
-
-       return axes[axis];
-}
-
-std::string Device::get_button_name(unsigned btn) const
-{
-       return format("Button %d", btn);
-}
-
-std::string Device::get_axis_name(unsigned axis) const
-{
-       return format("Axis %d", axis);
-}
-
-void Device::set_button_state(unsigned btn, bool state, bool event)
-{
-       if(btn>=buttons.size())
-               buttons.resize(btn+1, false);
-
-       if(state!=buttons[btn])
-       {
-               buttons[btn]=state;
-
-               if(event)
-               {
-                       if(state)
-                               signal_button_press.emit(btn);
-                       else
-                               signal_button_release.emit(btn);
-               }
-       }
-}
-
-void Device::set_axis_value(unsigned axis, float value, bool event)
-{
-       if(axis>=axes.size())
-               axes.resize(axis+1, 0);
-
-       if(value!=axes[axis])
-       {
-               float old=axes[axis];
-               axes[axis]=value;
-
-               if(event)
-                       signal_axis_motion.emit(axis, value, value-old);
-       }
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/inputdevice.h b/source/inputdevice.h
deleted file mode 100644 (file)
index d1c96f2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_INPUTDEVICE_H_
-#define MSP_GBASE_INPUTDEVICE_H_
-
-#include <string>
-#include <vector>
-#include <sigc++/signal.h>
-
-namespace Msp {
-namespace Input {
-
-/**
-Base class for input devices.  Input devices have two types of controls:
-buttons and axes.  Buttons are either on or off.  Axes have a floating-point
-value, with range depending on the device.
-*/
-class Device
-{
-public:
-       sigc::signal<void, unsigned> signal_button_press;
-       sigc::signal<void, unsigned> signal_button_release;
-       sigc::signal<void, unsigned, float, float> signal_axis_motion;
-
-protected:
-       std::string name;
-       std::vector<char>  buttons;
-       std::vector<float> axes;
-       float axis_threshold;
-       float axis_dead_zone;
-
-       Device() { }
-public:
-       virtual ~Device() { }
-       const std::string &get_name() const { return name; }
-       bool  get_button_state(unsigned) const;
-       float get_axis_value(unsigned) const;
-       float get_axis_threshold() const { return axis_threshold; }
-
-       virtual std::string get_button_name(unsigned) const;
-       virtual std::string get_axis_name(unsigned) const;
-protected:
-       void set_button_state(unsigned, bool, bool);
-       void set_axis_value(unsigned, float, bool);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/inputhub.cpp b/source/inputhub.cpp
deleted file mode 100644 (file)
index 1fa95d0..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <sigc++/bind.h>
-#include <msp/core/except.h>
-#include "inputhub.h"
-
-namespace Msp {
-namespace Input {
-
-Hub::Hub()
-{
-       name="Hub";
-}
-
-unsigned Hub::attach(Device &dev)
-{
-       unsigned index=devices.size();
-       devices.push_back(&dev);
-       dev.signal_button_press.connect(sigc::bind(sigc::mem_fun(this, &Hub::button_press), index));
-       dev.signal_button_release.connect(sigc::bind(sigc::mem_fun(this, &Hub::button_release), index));
-       dev.signal_axis_motion.connect(sigc::bind(sigc::mem_fun(this, &Hub::axis_motion), index));
-       return index;
-}
-
-std::string Hub::get_button_name(unsigned btn) const
-{
-       unsigned dev_index=btn>>12;
-       if(dev_index>devices.size())
-               throw InvalidParameterValue("Button does not exist");
-
-       const Device &dev=*devices[dev_index];
-       return dev.get_name()+": "+dev.get_button_name(btn&0xFFF);
-}
-
-void Hub::button_press(unsigned btn, unsigned index)
-{
-       set_button_state(index<<12 | btn&0xFFF, true, true);
-}
-
-void Hub::button_release(unsigned btn, unsigned index)
-{
-       set_button_state(index<<12 | btn&0xFFF, false, true);
-}
-
-void Hub::axis_motion(unsigned axis, float value, float, unsigned index)
-{
-       set_axis_value(index<<12 | axis&0xFFF, value, true);
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/inputhub.h b/source/inputhub.h
deleted file mode 100644 (file)
index c66ae98..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_INPUTHUB_H_
-#define MSP_GBASE_INPUTHUB_H_
-
-#include "inputdevice.h"
-
-namespace Msp {
-namespace Input {
-
-/**
-The Hub device collects events from multiple input devices and presents an
-aggregate of them.  Button and axis numbers are mapped to unique values.
-*/
-class Hub: public Device
-{
-protected:
-       std::vector<Device *> devices;
-
-public:
-       Hub();
-
-       /**
-       Attaches an input device to the hub.
-
-       @param   dev  Device to attach
-
-       @return  Index of the device within the hub
-       */
-       unsigned attach(Device &dev);
-
-       virtual std::string get_button_name(unsigned) const;
-protected:
-       void button_press(unsigned, unsigned);
-       void button_release(unsigned, unsigned);
-       void axis_motion(unsigned, float, float, unsigned);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/keyboard.cpp b/source/keyboard.cpp
deleted file mode 100644 (file)
index 2e3c92d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/strings/formatter.h>
-#include "display.h"
-#include "keyboard.h"
-
-namespace Msp {
-namespace Input {
-
-Keyboard::Keyboard(Graphics::Window &w):
-       window(w)
-{
-       name="Keyboard";
-
-       buttons.resize(256, false);
-
-       window.signal_key_press.connect(sigc::mem_fun(this, &Keyboard::key_press));
-       window.signal_key_release.connect(sigc::mem_fun(this, &Keyboard::key_release));
-}
-
-std::string Keyboard::get_button_name(unsigned btn) const
-{
-#ifndef WIN32
-       KeySym ksym=XKeycodeToKeysym(window.get_display().get_display(), btn, 0);
-       return XKeysymToString(ksym);
-#else
-       char buf[128];
-       if(!GetKeyNameText(btn<<16, buf, sizeof(buf)))
-               return format("Key %d", btn);
-       return buf;
-#endif
-}
-
-void Keyboard::key_press(unsigned key, unsigned, unsigned)
-{
-       set_button_state(key, true, true);
-}
-
-void Keyboard::key_release(unsigned key, unsigned)
-{
-       set_button_state(key, false, true);
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/keyboard.h b/source/keyboard.h
deleted file mode 100644 (file)
index 3e0efa2..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_KEYBOARD_H_
-#define MSP_GBASE_KEYBOARD_H_
-
-#include "inputdevice.h"
-#include "window.h"
-
-namespace Msp {
-namespace Input {
-
-class Keyboard: public Device
-{
-private:
-       Graphics::Window &window;
-
-public:
-       Keyboard(Graphics::Window &);
-
-       virtual std::string get_button_name(unsigned) const;
-private:
-       void key_press(unsigned, unsigned, unsigned);
-       void key_release(unsigned, unsigned);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/mouse.cpp b/source/mouse.cpp
deleted file mode 100644 (file)
index 931b204..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/strings/formatter.h>
-#include "mouse.h"
-
-namespace Msp {
-namespace Input {
-
-Mouse::Mouse(Graphics::Window &w):
-       window(w),
-       axis_scale(0.01)
-{
-       name="Mouse";
-
-       buttons.resize(3);
-       axes.resize(2);
-
-       window.signal_button_press.connect(sigc::mem_fun(this, &Mouse::button_press));
-       window.signal_button_release.connect(sigc::mem_fun(this, &Mouse::button_release));
-       window.signal_pointer_motion.connect(sigc::mem_fun(this, &Mouse::pointer_motion));
-}
-
-std::string Mouse::get_button_name(unsigned btn) const
-{
-       switch(btn)
-       {
-       case 1:
-               return "Left";
-       case 2:
-               return "Middle";
-       case 3:
-               return "Right";
-       case 4:
-               return "Wheel Up";
-       case 5:
-               return "Wheel Down";
-       default:
-               return format("Button %d", btn);
-       }
-}
-
-void Mouse::button_press(int, int, unsigned btn, unsigned)
-{
-       set_button_state(btn, true, true);
-}
-
-void Mouse::button_release(int, int, unsigned btn, unsigned)
-{
-       set_button_state(btn, false, true);
-}
-
-void Mouse::pointer_motion(int x, int y)
-{
-       set_axis_value(0, x*axis_scale, true);
-       set_axis_value(1, y*axis_scale, true);
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/mouse.h b/source/mouse.h
deleted file mode 100644 (file)
index ccc2e8e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_MOUSE_H_
-#define MSP_GBASE_MOUSE_H_
-
-#include "inputdevice.h"
-#include "window.h"
-
-namespace Msp {
-namespace Input {
-
-class Mouse: public Device
-{
-private:
-       Graphics::Window &window;
-       float axis_scale;
-
-public:
-       Mouse(Graphics::Window &);
-       virtual std::string get_button_name(unsigned) const;
-private:
-       void button_press(int, int, unsigned, unsigned);
-       void button_release(int, int, unsigned, unsigned);
-       void pointer_motion(int, int);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/smoothcontrol.cpp b/source/smoothcontrol.cpp
deleted file mode 100644 (file)
index 69dfacf..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include "smoothcontrol.h"
-
-namespace Msp {
-namespace Input {
-
-SmoothControl::SmoothControl():
-       value(0),
-       paired_ctrl(0)
-{ }
-
-SmoothControl::SmoothControl(const ControlSource &s):
-       Control(s),
-       value(0),
-       paired_ctrl(0)
-{ }
-
-SmoothControl::SmoothControl(Device &d, ControlSrcType t, unsigned i):
-       Control(d, t, i),
-       value(0),
-       paired_ctrl(0)
-{ }
-
-SmoothControl &SmoothControl::operator=(const SmoothControl &sc)
-{
-       Control::operator=(sc);
-
-       return *this;
-}
-
-SmoothControl::~SmoothControl()
-{
-       pair(0);
-}
-
-void SmoothControl::pair(SmoothControl *ctrl)
-{
-       if(ctrl==paired_ctrl)
-               return;
-
-       if(paired_ctrl)
-       {
-               SmoothControl *old_pair=paired_ctrl;
-               paired_ctrl=0;
-               old_pair->pair(0);
-       }
-
-       paired_ctrl=ctrl;
-
-       if(paired_ctrl)
-               paired_ctrl->pair(this);
-}
-
-void SmoothControl::on_press()
-{
-       on_motion(1, 1-value);
-}
-
-void SmoothControl::on_release()
-{
-       if(value>0)
-               on_motion(0, -value);
-}
-
-void SmoothControl::on_motion(float v, float)
-{
-       value=v;
-       signal_motion.emit(value);
-       
-       if(paired_ctrl && paired_ctrl->get_value()!=-value)
-               paired_ctrl->on_motion(-value, -value-paired_ctrl->get_value());
-}
-
-} // namespace Input
-} // namespace Msp
diff --git a/source/smoothcontrol.h b/source/smoothcontrol.h
deleted file mode 100644 (file)
index 26484a9..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_SMOOTHCONTROL_H_
-#define MSP_GBASE_SMOOTHCONTROL_H_
-
-#include "control.h"
-
-namespace Msp {
-namespace Input {
-
-/**
-A control with a continuous range of values.  A button is treated as either 1
-or 0.  Axis values are mapped to absolute value.
-
-Two smooth controls can also be paired to each other.  Motion on one control of
-the pair will cause negative motion on the other.  This works best when the
-controls are bound to the opposite sides of the same joystick axis.
-*/
-class SmoothControl: public Control
-{
-public:
-       sigc::signal<void, float> signal_motion;
-
-private:
-       float value;
-       SmoothControl *paired_ctrl;
-
-public:
-       SmoothControl();
-       SmoothControl(const ControlSource &);
-       SmoothControl(Device &, ControlSrcType, unsigned);
-       SmoothControl &operator=(const SmoothControl &);
-       virtual ~SmoothControl();
-
-       void pair(SmoothControl *ctrl);
-       float get_value() const { return value; }
-
-private:
-       virtual void on_press();
-       virtual void on_release();
-       virtual void on_motion(float, float);
-};
-
-} // namespace Input
-} // namespace Msp
-
-#endif
diff --git a/source/types.h b/source/types.h
deleted file mode 100644 (file)
index e3524f3..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_TYPES_H_
-#define MSP_GBASE_TYPES_H_
-
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <X11/Xlib.h>
-#endif
-
-namespace Msp {
-namespace Graphics {
-
-#ifdef WIN32
-typedef HWND WindowHandle;
-#else
-typedef ::Window WindowHandle;
-#endif
-
-} // namespace Graphics
-} // namespace Msp
-
-#endif
diff --git a/source/window.cpp b/source/window.cpp
deleted file mode 100644 (file)
index da877e9..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-/* $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
diff --git a/source/window.h b/source/window.h
deleted file mode 100644 (file)
index e85f86a..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $Id$
-
-This file is part of libmspgbase
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GBASE_WINDOW_H_
-#define MSP_GBASE_WINDOW_H_
-
-#include <string>
-#include <sigc++/signal.h>
-#include "types.h"
-
-namespace Msp {
-namespace Graphics {
-
-class Display;
-
-struct WindowOptions
-{
-       unsigned width;
-       unsigned height;
-       bool fullscreen;
-       bool resizable;
-
-       WindowOptions();
-};
-
-class Window
-{
-public:
-       sigc::signal<void, int, int, unsigned, unsigned> signal_button_press;
-       sigc::signal<void, int, int, unsigned, unsigned> signal_button_release;
-       sigc::signal<void, int, int> signal_pointer_motion;
-       sigc::signal<void, unsigned, unsigned, unsigned> signal_key_press;
-       sigc::signal<void, unsigned, unsigned> signal_key_release;
-       sigc::signal<void, unsigned, unsigned> signal_resize;
-       sigc::signal<void> signal_close;
-
-protected:
-       Display &display;
-       WindowOptions options;
-       WindowHandle window;
-#ifndef WIN32
-       Atom wm_delete_window;
-#endif
-
-public:
-       Window(Display &, unsigned w, unsigned h, bool fs=false);
-       Window(Display &, const WindowOptions &);
-       ~Window();
-
-       void set_title(const std::string &);
-       void reconfigure(const WindowOptions &);
-
-       Display &get_display() const { return display; }
-       const WindowOptions &get_options() const { return options; }
-       unsigned get_width() const  { return options.width; }
-       unsigned get_height() const { return options.height; }
-       WindowHandle get_handle() const { return window; }
-
-       void show();
-       void hide();
-
-#ifndef WIN32
-       void event(const XEvent &ev);
-#endif
-protected:
-       void init();
-#ifdef WIN32
-       int wndproc(UINT, WPARAM, LPARAM);
-       static LRESULT CALLBACK wndproc_(HWND, UINT, WPARAM, LPARAM);
-#endif
-};
-
-} // namespace Graphics
-} // namespace Msp
-
-#endif