]> git.tdb.fi Git - libs/gui.git/commitdiff
Initial revision
authorMikko Rasa <tdb@tdb.fi>
Sat, 25 Aug 2007 22:02:01 +0000 (22:02 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sat, 25 Aug 2007 22:02:01 +0000 (22:02 +0000)
12 files changed:
Build [new file with mode: 0644]
source/glwindow.cpp [new file with mode: 0644]
source/glwindow.h [new file with mode: 0644]
source/inputdevice.cpp [new file with mode: 0644]
source/inputdevice.h [new file with mode: 0644]
source/inputhub.h [new file with mode: 0644]
source/keyboard.cpp [new file with mode: 0644]
source/keyboard.h [new file with mode: 0644]
source/mouse.cpp [new file with mode: 0644]
source/mouse.h [new file with mode: 0644]
source/window.cpp [new file with mode: 0644]
source/window.h [new file with mode: 0644]

diff --git a/Build b/Build
new file mode 100644 (file)
index 0000000..612f9be
--- /dev/null
+++ b/Build
@@ -0,0 +1,18 @@
+/* $Id$ */
+
+package "mspgbase"
+{
+       description "Mikkosoft Productions graphics base library";
+       version "0.0";
+
+       require "mspcore";
+       require "sigc++-2.0";
+       require "Xlib";
+
+       library "mspgbase"
+       {
+               source "source";
+               install true;
+               install_headers "msp/gbase";
+       };
+};
diff --git a/source/glwindow.cpp b/source/glwindow.cpp
new file mode 100644 (file)
index 0000000..530d337
--- /dev/null
@@ -0,0 +1,89 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <vector>
+#include <msp/core/error.h>
+#include "glwindow.h"
+
+using namespace std;
+
+#include <iostream>
+
+namespace Msp {
+
+GLDisplayOptions::GLDisplayOptions():
+       alpha(false),
+       doublebuffer(true),
+       multisample(0)
+{ }
+
+
+GLWindow::GLWindow(unsigned w, unsigned h)
+{
+       options.width=w;
+       options.height=h;
+       init();
+}
+
+GLWindow::GLWindow(const DisplayOptions &dopt, const GLDisplayOptions &gl_dopt)
+{
+       options=dopt;
+       gl_options=gl_dopt;
+       init();
+}
+
+GLWindow::~GLWindow()
+{
+       glXMakeCurrent(display, window, 0);
+       glXDestroyContext(display, context);
+}
+
+void GLWindow::swap_buffers()
+{
+       glXSwapBuffers(display, window);
+}
+
+void GLWindow::init()
+{
+       prepare();
+
+       vector<int> attribs;
+       attribs.push_back(GLX_RGBA);
+       attribs.push_back(GLX_BUFFER_SIZE);
+       attribs.push_back(24);
+       if(gl_options.alpha)
+       {
+               attribs.push_back(GLX_ALPHA_SIZE);
+               attribs.push_back(1);
+       }
+       if(gl_options.doublebuffer)
+               attribs.push_back(GLX_DOUBLEBUFFER);
+       if(gl_options.multisample>0)
+       {
+               attribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
+               attribs.push_back(gl_options.multisample);
+       }
+       attribs.push_back(0);
+
+       XVisualInfo *visual=glXChooseVisual(display, DefaultScreen(display), &attribs.front());
+       if(!visual)
+               throw Exception("Couldn't get a matching GLX visual");
+
+       context=glXCreateContext(display, visual, 0, true);
+       if(!context)
+               throw Exception("Couldn't create a GLX context");
+
+       window=XCreateWindow(display, DefaultRootWindow(display), 0, 0, options.width, options.height, 0, CopyFromParent, InputOutput, CopyFromParent, 0, 0);
+       if(!window)
+               throw Exception("Couldn't create a window");
+
+       XSelectInput(display, window, ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask);
+
+       glXMakeCurrent(display, window, context);
+}
+
+} // namespace Msp
diff --git a/source/glwindow.h b/source/glwindow.h
new file mode 100644 (file)
index 0000000..f79c673
--- /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_GLWINDOW_H_
+#define MSP_GBASE_GLWINDOW_H_
+
+#include <GL/glx.h>
+#include "window.h"
+
+namespace Msp {
+
+struct GLDisplayOptions
+{
+       bool alpha;
+       bool doublebuffer;
+       unsigned multisample;
+
+       GLDisplayOptions();
+};
+
+class GLWindow: public Window
+{
+protected:
+       typedef GLXContext Context;
+
+       GLDisplayOptions gl_options;
+       Context context;
+
+public:
+       GLWindow(unsigned, unsigned);
+       GLWindow(const DisplayOptions &, const GLDisplayOptions &);
+       ~GLWindow();
+
+       void swap_buffers();
+protected:
+       void init();
+};
+
+} // namespace Msp
+
+#endif
diff --git a/source/inputdevice.cpp b/source/inputdevice.cpp
new file mode 100644 (file)
index 0000000..f0f9aac
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "inputdevice.h"
+
+namespace Msp {
+namespace Input {
+
+bool Device::get_button_state(unsigned btn)
+{
+       if(btn>buttons.size())
+               return false;
+
+       return buttons[btn];
+}
+
+float Device::get_axis_value(unsigned axis)
+{
+       if(axis>axes.size())
+               return 0;
+
+       return axes[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
new file mode 100644 (file)
index 0000000..60b25e9
--- /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_INPUTDEVICE_H_
+#define MSP_GBASE_INPUTDEVICE_H_
+
+#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::vector<char>  buttons;
+       std::vector<float> axes;
+
+public:
+       virtual ~Device() { }
+       bool  get_button_state(unsigned);
+       float get_axis_value(unsigned);
+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.h b/source/inputhub.h
new file mode 100644 (file)
index 0000000..1d4b465
--- /dev/null
@@ -0,0 +1,23 @@
+/* $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 {
+
+class Hub: public Device
+{
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/keyboard.cpp b/source/keyboard.cpp
new file mode 100644 (file)
index 0000000..4bc586c
--- /dev/null
@@ -0,0 +1,32 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "keyboard.h"
+#include "window.h"
+
+namespace Msp {
+namespace Input {
+
+Keyboard::Keyboard(Window &window)
+{
+       buttons.resize(256, false);
+
+       window.signal_key_press.connect(sigc::mem_fun(this, &Keyboard::key_press));
+}
+
+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
new file mode 100644 (file)
index 0000000..65b3dba
--- /dev/null
@@ -0,0 +1,31 @@
+/* $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"
+
+namespace Msp {
+
+class Window;
+
+namespace Input {
+
+class Keyboard: public Device
+{
+public:
+       Keyboard(Window &);
+protected:
+       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
new file mode 100644 (file)
index 0000000..b32b70f
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "mouse.h"
+#include "window.h"
+
+namespace Msp {
+namespace Input {
+
+Mouse::Mouse(Window &w):
+       window(w),
+       axis_scale(0.01)
+{
+       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));
+}
+
+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
new file mode 100644 (file)
index 0000000..6260f3b
--- /dev/null
@@ -0,0 +1,36 @@
+/* $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"
+
+namespace Msp {
+
+class Window;
+
+namespace Input {
+
+class Mouse: public Device
+{
+private:
+       Window &window;
+       float axis_scale;
+
+public:
+       Mouse(Window &);
+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/window.cpp b/source/window.cpp
new file mode 100644 (file)
index 0000000..75a88dc
--- /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>
+#include <GL/glx.h>
+#include <msp/core/error.h>
+#include "window.h"
+
+using namespace std;
+
+#include <msp/strings/lexicalcast.h>
+
+namespace Msp {
+
+DisplayOptions::DisplayOptions():
+       width(640),
+       height(480),
+       fullscreen(false)
+{ }
+
+
+/**
+Initializes the class but does not open the window.  Intended for use by
+derived classes.
+*/
+Window::Window():
+       display(0),
+       window(0)
+{ }
+
+Window::Window(unsigned w, unsigned h)
+{
+       options.width=w;
+       options.height=h;
+
+       init();
+}
+
+Window::Window(const DisplayOptions &dopt):
+       options(dopt)
+{
+       init();
+}
+
+Window::~Window()
+{
+       if(window)
+               XDestroyWindow(display, window);
+       if(display)
+               XCloseDisplay(display);
+}
+
+void Window::show()
+{
+       XMapRaised(display, window);
+}
+
+void Window::hide()
+{
+       XUnmapWindow(display, window);
+}
+
+void Window::tick()
+{
+       while(1)
+       {
+               int pending=XPending(display);
+               if(pending==0)
+                       break;
+
+               for(int i=0; i<pending; ++i)
+               {
+                       XEvent event;
+                       XNextEvent(display, &event);
+                       process_event(event);
+               }
+       }
+}
+
+void Window::prepare()
+{
+       if(options.display.empty())
+               display=XOpenDisplay(0);
+       else
+               display=XOpenDisplay(options.display.c_str());
+       if(!display)
+               throw Exception("Couldn't open X display");
+
+       //XSetErrorHandler(x_error_handler);
+}
+
+void Window::init()
+{
+       prepare();
+
+       window=XCreateWindow(display, DefaultRootWindow(display), 0, 0, options.width, options.height, 0, CopyFromParent, InputOutput, CopyFromParent, 0, 0);
+       if(!window)
+               throw Exception("Couldn't create a window");
+
+       XSelectInput(display, window, ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask);
+}
+
+void Window::process_event(const XEvent &event)
+{
+       switch(event.type)
+       {
+       case ButtonPress:
+               signal_button_press.emit(event.xbutton.x, event.xbutton.y, event.xbutton.button, event.xbutton.state);
+               break;
+       case ButtonRelease:
+               signal_button_release.emit(event.xbutton.x, event.xbutton.y, event.xbutton.button, event.xbutton.state);
+               break;
+       case MotionNotify:
+               signal_pointer_motion.emit(event.xmotion.x, event.xmotion.y);
+               break;
+       case KeyPress:
+               {
+                       char buf[16];
+                       XLookupString(const_cast<XKeyEvent *>(&event.xkey), buf, sizeof(buf), 0, 0);
+                       // XXX Handle the result according to locale
+                       signal_key_press.emit(event.xkey.keycode, event.xkey.state, buf[0]);
+               }
+               break;
+       case KeyRelease:
+               signal_key_release.emit(event.xkey.keycode, event.xkey.state);
+               break;
+       case ConfigureNotify:
+               options.width=event.xconfigure.width;
+               options.height=event.xconfigure.height;
+               break;
+       default:;
+       }
+}
+
+int Window::x_error_handler(Display *display, XErrorEvent *error)
+{
+       char buf[128];
+       XGetErrorText(display, error->error_code, buf, sizeof(buf));
+       /*string request_code=lexical_cast(error->request_code);
+       char buf2[1024];
+       XGetErrorDatabaseText(display, "XRequest", request_code.c_str(), buf, buf2, sizeof(buf2));*/
+       throw Exception(buf);
+}
+
+} // namespace Msp
diff --git a/source/window.h b/source/window.h
new file mode 100644 (file)
index 0000000..6f1f0d1
--- /dev/null
@@ -0,0 +1,64 @@
+/* $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 <X11/Xlib.h>
+#include <sigc++/signal.h>
+
+namespace Msp {
+
+struct DisplayOptions
+{
+       std::string display;
+       unsigned width;
+       unsigned height;
+       bool fullscreen;
+
+       DisplayOptions();
+};
+
+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;
+
+protected:
+       typedef ::Window Handle;
+
+       Display *display;
+       DisplayOptions options;
+       Handle  window;
+
+       Window();
+public:
+       Window(unsigned, unsigned);
+       Window(const DisplayOptions &);
+       virtual ~Window();
+
+       unsigned get_width() const  { return options.width; }
+       unsigned get_height() const { return options.height; }
+       void show();
+       void hide();
+       void tick();
+protected:
+       void prepare();
+       void init();
+       void process_event(const XEvent &);
+
+       static int x_error_handler(Display *, XErrorEvent *);
+};
+
+} // namespace Msp
+
+#endif