[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libcvd-members] libcvd Makefile.in cvd/glwindow.h cvd_src/glwin...
From: |
Ethan Eade |
Subject: |
[libcvd-members] libcvd Makefile.in cvd/glwindow.h cvd_src/glwin... |
Date: |
Fri, 02 Mar 2007 15:31:19 +0000 |
CVSROOT: /cvsroot/libcvd
Module name: libcvd
Changes by: Ethan Eade <ethaneade> 07/03/02 15:31:19
Modified files:
. : Makefile.in
Added files:
cvd : glwindow.h
cvd_src : glwindow.cc
Log message:
Added GLWindow. This is a richer implementation of VideoDisplay that
hides
the XEvent system from the user.
The GLWindow class makes a window and an associated GL context. When
requested, events on the queue are either processed with a passed event
handler (with callback virtual methods such as on_key_down and
on_resize)
or enumerated in a vector<GLWindow::Event> or GLWindow::EventSummary.
Otherwise the functionality is the same as VideoDisplay.
Feel free to add to the interface; I just got tired of linking against a
separate library in order to have a reasonable display interface.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/glwindow.h?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd_src/glwindow.cc?cvsroot=libcvd&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libcvd/Makefile.in?cvsroot=libcvd&r1=1.51&r2=1.52
Patches:
Index: Makefile.in
===================================================================
RCS file: /cvsroot/libcvd/libcvd/Makefile.in,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -b -r1.51 -r1.52
--- Makefile.in 20 Jan 2007 15:42:21 -0000 1.51
+++ Makefile.in 2 Mar 2007 15:31:19 -0000 1.52
@@ -150,6 +150,7 @@
ifeq (@have_videodisplay@,yes)
CVD_OBJS+=cvd_src/videodisplay.o
+ CVD_OBJS+=cvd_src/glwindow.o
endif
################################################################################
Index: cvd/glwindow.h
===================================================================
RCS file: cvd/glwindow.h
diff -N cvd/glwindow.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cvd/glwindow.h 2 Mar 2007 15:31:19 -0000 1.1
@@ -0,0 +1,128 @@
+#ifndef GLWINDOW_H
+#define GLWINDOW_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <cvd/image_ref.h>
+
+namespace CVD {
+
+ namespace Exceptions
+ {
+ /// %Exceptions specific to CVD::GLWindow
+ /// @ingroup gException
+ namespace GLWindow
+ {
+ /// Base class for all CVD::GLWindow exceptions
+ /// @ingroup gException
+ struct All: public CVD::Exceptions::All{
+ };
+
+ /// An exception occurred during initialisation
+ /// @ingroup gException
+ struct CreationError: public All
+ {
+ CreationError(std::string w); ///< Construct from error string
+ };
+
+ /// An exception occurred during run-time
+ /// @ingroup gException
+ struct RuntimeError: public All
+ {
+ RuntimeError(std::string w); ///< Construct from error string
+ };
+ }
+ }
+
+ /// An object that creates a window and a GL context attached to that
window, and manages its events.
+ class GLWindow {
+ public:
+ /// Symbols for mouse buttons and modifiers
+ enum MouseButton { BUTTON_LEFT=1, BUTTON_MIDDLE=2, BUTTON_RIGHT=4,
BUTTON_MOD_CTRL=8, BUTTON_MOD_SHIFT=0x10 };
+ /// Symbols for window events
+ enum EventType { EVENT_CLOSE };
+
+ /// Abstract base class for event handlers. Subclass this and override
to implement a handler.
+ class EventHandler {
+ public:
+ virtual ~EventHandler() {}
+ /// Called for key press events
+ virtual void on_key_down(GLWindow& win, int key) {}
+ /// Called for key release events
+ virtual void on_key_up(GLWindow& win, int key) {}
+ /// Called for mouse movement events
+ virtual void on_mouse_move(GLWindow& win, ImageRef where, int
state) {}
+ /// Called for mouse button press events
+ virtual void on_mouse_down(GLWindow& win, ImageRef where, int
state, int button) {}
+ /// Called for mouse button release events
+ virtual void on_mouse_up(GLWindow& win, ImageRef where, int state,
int button) {}
+ /// Called for window resize events
+ virtual void on_resize(GLWindow& win, ImageRef size) {}
+ /// Called for general window events (such as EVENT_CLOSE)
+ virtual void on_event(GLWindow& win, int event) {}
+ };
+
+ struct Event {
+ enum Type { KEY_DOWN, KEY_UP, MOUSE_MOVE, MOUSE_DOWN, MOUSE_UP,
RESIZE, EVENT };
+ Type type;
+ int which, state;
+ ImageRef where, size;
+ };
+
+ /// A summary of multiple events
+ struct EventSummary {
+ /// key->frequency mapping for key presses and releases
+ std::map<int,int> key_down, key_up;
+ /// button->frequency mapping for mouse presses and releases
+ std::map<int,std::pair<ImageRef,int> > mouse_down, mouse_up;
+ /// Generic window events -> frequency
+ std::map<int,int> events;
+ /// Reset the summary
+ void clear() { *this = EventSummary(); }
+ /// Has escape been pressed or the close button pressed?
+ bool should_quit() const;
+ };
+
+ /// Construct a GLWindow of the given size and colour depth, with the
given title.
+ /// A double-buffered GL context is associated with the window.
+ GLWindow(const ImageRef& size, int bpp, const std::string&
title="GLWindow");
+ ~GLWindow();
+ /// Get the size
+ ImageRef size() const;
+ /// Set the mouse cursor position
+ void set_cursor_position(const ImageRef& where);
+ /// Get the mouse cursor position
+ ImageRef cursor_position() const;
+ /// Show (or hide) the cursor
+ void show_cursor(bool show=true);
+ /// Hide the cursor
+ void hide_cursor() { show_cursor(false); }
+ /// Get the title
+ std::string title() const;
+ /// Set the title
+ void set_title(const std::string& title);
+ /// Swap the front and back buffers
+ void swap_buffers();
+ /// Handle events in the event queue by calling back to the specified
handler.
+ void handle_events(EventHandler& handler);
+ /// Store all events in the event queue into Event objects.
+ void get_events(std::vector<Event>& events);
+ /// Make a summary of the events in the queue.
+ void get_events(EventSummary& summary);
+ /// @returns true if events are pending
+ bool has_events() const;
+ /// Make this GL context active
+ void activate();
+ /// Make this GL context active
+ void make_current() { activate(); }
+ private:
+ struct State;
+ State* state;
+ };
+
+
+}
+
+
+#endif
Index: cvd_src/glwindow.cc
===================================================================
RCS file: cvd_src/glwindow.cc
diff -N cvd_src/glwindow.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ cvd_src/glwindow.cc 2 Mar 2007 15:31:19 -0000 1.1
@@ -0,0 +1,340 @@
+#include <cvd/glwindow.h>
+#include <exception>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <GL/glx.h>
+
+using namespace CVD;
+
+CVD::Exceptions::GLWindow::CreationError::CreationError(std::string w)
+{
+ what="GLWindow creation error: " + w;
+}
+
+CVD::Exceptions::GLWindow::RuntimeError::RuntimeError(std::string w)
+{
+ what="GLWindow error: " + w;
+}
+
+struct GLWindow::State {
+ ImageRef size;
+ std::string title;
+ Display* display;
+ Window window;
+ Atom delete_atom;
+ Cursor null_cursor;
+ GLXContext context;
+ int font;
+};
+
+CVD::GLWindow::GLWindow(const ImageRef& size, int bpp, const std::string&
title)
+{
+ Display* display = XOpenDisplay(0);
+ if (display == 0)
+ throw Exceptions::GLWindow::CreationError("Cannot open X display");
+
+ int visualAttributes[] = {
+ GLX_RGBA,
+ GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, bpp/3,
+ GLX_GREEN_SIZE, bpp/3,
+ GLX_BLUE_SIZE, bpp/3,
+ GLX_DEPTH_SIZE, 8,
+ None
+ };
+ XVisualInfo* visualInfo = glXChooseVisual(display,
DefaultScreen(display),visualAttributes);
+ if(visualAttributes == 0) {
+ XCloseDisplay(display);
+ throw Exceptions::GLWindow::CreationError("glXChooseVisual failed");
+ }
+
+ Window rootWindow = RootWindow(display, visualInfo->screen);
+ XWindowAttributes windowAttributes;
+
+ XGetWindowAttributes(display, rootWindow, &windowAttributes);
+
+ XSetWindowAttributes attributes;
+ attributes.border_pixel = 0;
+ attributes.colormap = XCreateColormap(display, rootWindow,
visualInfo->visual, AllocNone);
+ attributes.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
+
+ Window window = XCreateWindow(display,
+ rootWindow,
+ 0, 0, size.x, size.y,
+ 0, visualInfo->depth,
+ InputOutput,
+ visualInfo->visual,
+ CWBorderPixel | CWColormap | CWEventMask,
+ &attributes);
+ XStoreName(display, window, title.c_str());
+ XMapWindow(display, window);
+ XEvent ev;
+ do {
+ XNextEvent(display,&ev);
+ } while (ev.type != MapNotify);
+
+ Atom delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
+ XSetWMProtocols(display, window, &delete_atom, 1);
+
+ GLXContext context = glXCreateContext(display, visualInfo, 0, True);
+ if (context == 0) {
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+ throw Exceptions::GLWindow::CreationError("glXCreateContext failed");
+ }
+
+ if (glXMakeCurrent(display, window, context) == False) {
+ glXDestroyContext(display, context);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+ throw Exceptions::GLWindow::CreationError("glXMakeCurrent failed");
+ }
+ glLoadIdentity();
+ glViewport(0, 0, size.x, size.y);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glColor3f(1.0f,1.0f,1.0f);
+ glRasterPos2f(-1, 1);
+ glOrtho(0, size.x, size.y, 0, -1 , 1);
+ glPixelZoom(1,-1);
+
+ int font = glGenLists(256);
+ XColor black = {0, 0, 0, 0, 0, 0};
+ XFontStruct* fixed = XLoadQueryFont(display,
"-misc-fixed-medium-r-*-*-12-*-*-*-*-*-*-1" );
+ Cursor null_cursor = XCreateGlyphCursor(display, fixed->fid, fixed->fid, '
', ' ', &black, &black);
+ glXUseXFont(fixed->fid, 0, 256, font);
+ XFreeFont(display, fixed);
+
+ state = new State();
+ state->size = size;
+ state->title = title;
+ state->display = display;
+ state->window = window;
+ state->delete_atom = delete_atom;
+ state->null_cursor = null_cursor;
+ state->context = context;
+ state->font = font;
+}
+
+CVD::GLWindow::~GLWindow()
+{
+ activate();
+ glDeleteLists(state->font,256);
+ glXDestroyContext(state->display, state->context);
+ XDestroyWindow(state->display, state->window);
+ XCloseDisplay(state->display);
+
+ delete state;
+}
+
+ImageRef CVD::GLWindow::size() const { return state->size; }
+
+void CVD::GLWindow::set_cursor_position(const ImageRef& where)
+{
+ XWarpPointer(state->display, None, state->window, 0, 0, 0, 0, where.x,
where.y);
+}
+
+ImageRef CVD::GLWindow::cursor_position() const
+{
+ Window wtmp;
+ int itmp;
+ unsigned int utmp;
+ ImageRef where;
+ XQueryPointer(state->display, state->window, &wtmp, &wtmp, &itmp, &itmp,
&where.x, &where.y, &utmp);
+ return where;
+}
+
+void CVD::GLWindow::show_cursor(bool show)
+{
+ if (show)
+ XUndefineCursor(state->display, state->window);
+ else
+ XDefineCursor(state->display, state->window, state->null_cursor);
+}
+
+std::string CVD::GLWindow::title() const
+{
+ return state->title;
+}
+
+void CVD::GLWindow::set_title(const std::string& title)
+{
+ state->title = title;
+ XStoreName(state->display, state->window, title.c_str());
+}
+
+void CVD::GLWindow::swap_buffers()
+{
+ glXSwapBuffers(state->display, state->window);
+}
+
+inline int convertButton(unsigned int button)
+{
+ switch (button) {
+ case Button1: return GLWindow::BUTTON_LEFT;
+ case Button2: return GLWindow::BUTTON_MIDDLE;
+ case Button3: return GLWindow::BUTTON_RIGHT;
+ }
+ return 0;
+}
+
+inline int convertButtonState(unsigned int state)
+{
+ int ret = 0;
+ if (state & Button1Mask) ret |= GLWindow::BUTTON_LEFT;
+ if (state & Button2Mask) ret |= GLWindow::BUTTON_MIDDLE;
+ if (state & Button3Mask) ret |= GLWindow::BUTTON_RIGHT;
+ if (state & ControlMask) ret |= GLWindow::BUTTON_MOD_CTRL;
+ if (state & ShiftMask) ret |= GLWindow::BUTTON_MOD_SHIFT;
+ return ret;
+}
+
+void CVD::GLWindow::handle_events(EventHandler& handler)
+{
+ XEvent event;
+ while (XPending(state->display)) {
+ XNextEvent(state->display, &event);
+ switch (event.type) {
+ case ButtonPress:
+ handler.on_mouse_down(*this, ImageRef(event.xbutton.x,
event.xbutton.y),
+ convertButtonState(event.xbutton.state),
convertButton(event.xbutton.button));
+ break;
+ case ButtonRelease:
+ handler.on_mouse_up(*this, ImageRef(event.xbutton.x,
event.xbutton.y),
+ convertButtonState(event.xbutton.state),
convertButton(event.xbutton.button));
+ break;
+ case MotionNotify:
+ handler.on_mouse_move(*this, ImageRef(event.xmotion.x,
event.xmotion.y), convertButtonState(event.xbutton.state));
+ break;
+ case KeyPress:
+ handler.on_key_down(*this, XLookupKeysym(&event.xkey, 0));
+ break;
+ case KeyRelease:
+ handler.on_key_up(*this, XLookupKeysym(&event.xkey, 0));
+ break;
+ //case UnmapNotify: active = 0; break;
+ //case MapNotify: active = 1; break;
+ case ConfigureNotify:
+ if (event.xconfigure.width != state->size.x ||
event.xconfigure.height != state->size.y) {
+ activate();
+ state->size = ImageRef(event.xconfigure.width & (~0x3),
event.xconfigure.height & (~0x3));
+ glViewport(0, 0, state->size.x, state->size.y);
+ //glRasterPos2f(0,0);
+
//glPixelZoom(float(event.xconfigure.width)/myWidth,-float(event.xconfigure.height)/myHeight);
+ handler.on_resize(*this, state->size);
+ }
+ break;
+ case ClientMessage:
+ if (event.xclient.data.l[0] == (int)state->delete_atom)
+ handler.on_event(*this, EVENT_CLOSE);
+ else
+ handler.on_event(*this, event.xclient.message_type);
+ break;
+ default:
+ handler.on_event(*this, event.type);
+ break;
+ }
+ }
+}
+
+class SaveEvents : public GLWindow::EventHandler {
+private:
+ std::vector<GLWindow::Event>& events;
+public:
+ SaveEvents(std::vector<GLWindow::Event>& events_) : events(events_) {}
+ void on_key_down(GLWindow& win, int key) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::KEY_DOWN;
+ e.which = key;
+ events.push_back(e);
+ }
+ void on_key_up(GLWindow& win, int key) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::KEY_UP;
+ e.which = key;
+ events.push_back(e);
+ }
+
+ void on_mouse_move(GLWindow& win, ImageRef where, int state) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::MOUSE_MOVE;
+ e.state = state;
+ e.where = where;
+ events.push_back(e);
+ }
+
+ void on_mouse_down(GLWindow& win, ImageRef where, int state, int button) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::MOUSE_DOWN;
+ e.state = state;
+ e.which = button;
+ e.where = where;
+ events.push_back(e);
+ }
+
+ void on_mouse_up(GLWindow& win, ImageRef where, int state, int button) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::MOUSE_UP;
+ e.state = state;
+ e.which = button;
+ e.where = where;
+ events.push_back(e);
+ }
+
+ void on_resize(GLWindow& win, ImageRef size) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::RESIZE;
+ e.size = size;
+ events.push_back(e);
+ }
+
+ void on_event(GLWindow& win, int event) {
+ GLWindow::Event e;
+ e.type = GLWindow::Event::EVENT;
+ e.which = event;
+ events.push_back(e);
+ }
+};
+
+void CVD::GLWindow::get_events(std::vector<Event>& events)
+{
+ SaveEvents saver(events);
+ handle_events(saver);
+}
+
+bool CVD::GLWindow::EventSummary::should_quit() const
+{
+ return key_down.count(XK_Escape) || events.count(GLWindow::EVENT_CLOSE);
+}
+
+class MakeSummary : public GLWindow::EventHandler {
+private:
+ GLWindow::EventSummary& summary;
+public:
+ MakeSummary(GLWindow::EventSummary& summary_) : summary(summary_) {}
+
+ void on_key_down(GLWindow& win, int key) { ++summary.key_down[key]; }
+ void on_key_up(GLWindow& win, int key) { ++summary.key_up[key]; }
+ void on_mouse_down(GLWindow& win, ImageRef where, int state, int button) {
summary.mouse_down[button] = std::make_pair(where,state); }
+ void on_mouse_up(GLWindow& win, ImageRef where, int state, int button) {
summary.mouse_up[button] = std::make_pair(where,state); }
+ void on_event(GLWindow& win, int event) { ++summary.events[event]; }
+};
+
+void GLWindow::get_events(EventSummary& summary)
+{
+ MakeSummary ms(summary);
+ handle_events(ms);
+}
+
+bool CVD::GLWindow::has_events() const
+{
+ return XPending(state->display);
+}
+
+void CVD::GLWindow::activate()
+{
+ if (glXMakeCurrent(state->display, state->window, state->context) == False)
+ throw Exceptions::GLWindow::RuntimeError("glXMakeCurrent failed");
+}
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libcvd-members] libcvd Makefile.in cvd/glwindow.h cvd_src/glwin...,
Ethan Eade <=