--- /dev/null
+#ifndef GEOM_H_
+#define GEOM_H_
+
+struct Rect {
+ int x, y;
+ int width, height;
+};
+
+// TODO probably need to implement something like this:
+/*
+Rect rect_union(const Rect &a, const Rect &b);
+Rect rect_intersection(const Rect &a, const Rect &b);
+*/
+
+#endif // GEOM_H_
--- /dev/null
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "keyboard.h"
+
+static int tty_fd = -1;
+static enum {RAW, CANONICAL} ttystate = CANONICAL;
+
+static int keyb_fd = -1;
+
+bool init_keyboard()
+{
+ if((tty_fd = open("/dev/tty", O_RDWR)) == -1) {
+ fprintf(stderr, "Cannot open /dev/tty : %s\n", strerror(errno));
+ return false;
+ }
+
+ struct termios buf;
+
+ if(tcgetattr(tty_fd, &buf) < 0) {
+ fprintf(stderr, "Cannot get the tty parameters : %s\n", strerror(errno));
+ return false;
+ }
+
+ buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+ buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ buf.c_cflag &= ~(CSIZE | PARENB);
+ buf.c_cflag |= CS8;
+ buf.c_oflag &= ~(OPOST);
+ buf.c_cc[VMIN] = 1;
+ buf.c_cc[VTIME] = 0;
+
+ if(tcsetattr(tty_fd, TCSAFLUSH, &buf) < 0) {
+ return false;
+ }
+
+ ttystate = RAW;
+ return true;
+}
+
+void destroy_keyboard()
+{
+ struct termios buf;
+
+ buf.c_lflag |= (ECHO | ICANON | IEXTEN | ISIG);
+ buf.c_iflag |= (BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ buf.c_cflag |= (CSIZE | PARENB);
+ buf.c_cflag &= CS8;
+ buf.c_oflag |= (OPOST);
+ buf.c_cc[VMIN] = 1;
+ buf.c_cc[VTIME] = 0;
+
+ ttystate = CANONICAL;
+ close(tty_fd);
+
+ tty_fd = -1;
+}
+
+int get_keyboard_fd()
+{
+ return tty_fd;
+}
+
+void process_keyboard_event()
+{
+ char key;
+ if(read(tty_fd, &key, 1) < 1) {
+ return;
+ }
+
+ if(key == 'q') {
+ exit(0);
+ }
+ /* TODO:
+ * - handle system-wide key combinations (alt-tab?)
+ * - otherwise send keypress/release to focused window
+ */
+}
--- /dev/null
+#ifndef KEYBOARD_H_
+#define KEYBOARD_H_
+
+bool init_keyboard();
+void destroy_keyboard();
+
+int get_keyboard_fd();
+void process_keyboard_event();
+
+#endif // KEYBOARD_H_
--- /dev/null
+#include "mouse.h"
+#include "geom.h"
+
+static int dev_fd = -1; // file descriptor for /dev/psaux
+static Rect bounds;
+static int pointer_x, pointer_y;
+
+bool init_mouse()
+{
+ // TODO open /dev/psaux (see O_NONBLOCK comment below)
+ return true;
+}
+
+void destroy_mouse()
+{
+ // TODO close /dev/psaux
+}
+
+void set_mouse_bounds(const Rect &rect)
+{
+ bounds = rect;
+}
+
+int get_mouse_fd()
+{
+ return dev_fd;
+}
+
+void process_mouse_event()
+{
+ /* TODO:
+ * - read all pending events from mouse fd (use O_NONBLOCK so that
+ * read will return -1 when there are no more events instead of blocking).
+ * - process each event and update the pointer and button state
+ * - send each pointer move and button press/release to the tompost window
+ * with the pointer on it.
+ */
+}
+
+void get_pointer_pos(int *x, int *y)
+{
+ *x = pointer_x;
+ *y = pointer_y;
+}
+
+int get_button_state(int bn)
+{
+ // TODO
+ return 0;
+}
--- /dev/null
+#ifndef MOUSE_H_
+#define MOUSE_H_
+
+struct Rect;
+
+bool init_mouse();
+void destroy_mouse();
+
+void set_mouse_bounds(const Rect &rect);
+
+int get_mouse_fd();
+void process_mouse_event();
+
+void get_pointer_pos(int *x, int *y);
+int get_button_state(int bn);
+
+#endif // MOUSE_H_
--- /dev/null
+#include <string.h>
+#include "gfx.h"
+#include "window.h"
+#include "wm.h"
+
+Window::Window()
+{
+ title = 0;
+ rect.x = rect.y = 0;
+ rect.width = rect.height = 128;
+ memset(&callbacks, 0, sizeof callbacks);
+ dirty = true;
+}
+
+Window::~Window()
+{
+ delete [] title;
+}
+
+const Rect &Window::get_rect() const
+{
+ return rect;
+}
+
+void Window::move(int x, int y)
+{
+ invalidate(); // moved, should redraw, MUST BE CALLED FIRST
+ rect.x = x;
+ rect.y = y;
+}
+
+void Window::resize(int x, int y)
+{
+ invalidate(); // resized, should redraw, MUST BE CALLED FIRST
+ rect.width = x;
+ rect.height = y;
+}
+
+void Window::set_title(const char *s)
+{
+ delete [] title;
+
+ title = new char[strlen(s) + 1];
+ strcpy(title, s);
+}
+
+const char *Window::get_title() const
+{
+ return title;
+}
+
+void Window::invalidate()
+{
+ dirty = true;
+ wm->invalidate_region(rect);
+}
+
+void Window::draw()
+{
+ callbacks.display(this);
+ dirty = false;
+}
+
+unsigned char *Window::get_win_start_on_fb()
+{
+ unsigned char *fb = get_framebuffer();
+ return fb + get_color_depth() * (get_screen_size().x * rect.y + rect.x) / 8;
+}
+
+int Window::get_scanline_width()
+{
+ return get_screen_size().x;
+}
--- /dev/null
+#ifndef WINDOW_H_
+#define WINDOW_H_
+
+#include "geom.h"
+#include "event.h"
+
+class Window {
+private:
+ char *title;
+ Rect rect;
+ Callbacks callbacks;
+
+ bool dirty;
+
+public:
+ Window();
+ ~Window();
+
+ const Rect &get_rect() const;
+
+ void move(int x, int y);
+ void resize(int x, int y);
+
+ void set_title(const char *s);
+ const char *get_title() const;
+
+ /* mark this window as dirty, and notify the window manager
+ * to repaint it, and anything it used to cover.
+ */
+ void invalidate();
+
+ void draw();
+
+ unsigned char *get_win_start_on_fb();
+ int get_scanline_width();
+
+ void set_display_callback(DisplayFuncType func);
+ void set_keyboard_callback(KeyboardFuncType func);
+ void set_mouse_button_callback(MouseButtonFuncType func);
+ void set_mouse_motion_callback(MouseMotionFuncType func);
+
+ // XXX remove if not needed
+ friend class WindowManager;
+};
+
+#endif // WINDOW_H_
--- /dev/null
+#include <stdexcept>
+#include "wm.h"
+#include "window.h"
+
+
+WindowManager *wm;
+static WindowManager wminst;
+
+WindowManager::WindowManager()
+{
+ if(!wm) {
+ wm = this;
+ } else {
+ throw std::runtime_error("Trying to create a second instance of WindowManager!\n");
+ }
+}
+
+void WindowManager::invalidate_region(const Rect &rect)
+{
+ dirty_rects.push_back(rect);
+}
+
+void WindowManager::process_windows()
+{
+ //TODO:
+ //sta dirty rectangles na brw to union
+ //na eleg3w poia einai sto dirty area k na ta kanw dirty
+ //na ka8arizw ta dirty areas
+ //prwta render to bg
+ //meta ola ta dirty:
+ std::list<Window*>::iterator it = windows.begin();
+ while(it != windows.end()) {
+ if((*it)->dirty) {
+ (*it)->draw();
+ }
+ }
+}
--- /dev/null
+#ifndef WM_H_
+#define WM_H_
+
+#include <list>
+#include "geom.h"
+
+class Window;
+
+class WindowManager {
+private:
+ std::list<Window*> windows;
+ std::list<Rect> dirty_rects;
+
+public:
+ WindowManager();
+
+ void invalidate_region(const Rect &rect);
+ void process_windows();
+};
+
+extern WindowManager *wm;
+
+#endif // WM_H_