created libwinnie (library), winnie (the server application) and clients
[winnie] / libwinnie / src / window.cc
diff --git a/libwinnie/src/window.cc b/libwinnie/src/window.cc
new file mode 100644 (file)
index 0000000..04f72cd
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+winnie - an experimental window system
+
+Copyright (C) 2013 Eleni Maria Stea
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Author: Eleni Maria Stea <elene.mst@gmail.com>
+*/
+
+#include <algorithm>
+#include <stdio.h> //TODO
+#include <string.h>
+
+#include "gfx.h"
+#include "window.h"
+#include "wm.h"
+
+Window::Window()
+{
+       parent = 0;
+       title = 0;
+       rect.x = rect.y = 0;
+       rect.width = rect.height = 128;
+       memset(&callbacks, 0, sizeof callbacks);
+       dirty = true;
+       managed = true;
+       focusable = true;
+       state = STATE_NORMAL;
+}
+
+Window::~Window()
+{
+       for(size_t i=0; i<children.size(); i++) {
+               wm->remove_window(children[i]);
+               delete children[i];
+       }
+
+       delete [] title;
+}
+
+const Rect &Window::get_rect() const
+{
+       return rect;
+}
+
+Rect Window::get_absolute_rect() const
+{
+       if(!parent) {
+               return rect;
+       }
+
+       Rect absolute_rect;
+       absolute_rect = parent->get_absolute_rect();
+
+       absolute_rect.x += rect.x;
+       absolute_rect.y += rect.y;
+       absolute_rect.width = rect.width;
+       absolute_rect.height = rect.height;
+
+       return absolute_rect;
+}
+
+bool Window::contains_point(int ptr_x, int ptr_y)
+{
+       Rect abs_rect = get_absolute_rect();
+       return ptr_x >= abs_rect.x && ptr_x < abs_rect.x + abs_rect.width &&
+                       ptr_y >= abs_rect.y && ptr_y < abs_rect.y + abs_rect.height;
+}
+
+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;
+       Rect abs_rect = get_absolute_rect();
+       wm->invalidate_region(abs_rect);
+}
+
+void Window::draw(Rect *dirty_region)
+{
+       Rect abs_rect = get_absolute_rect();
+       Rect intersect = rect_intersection(abs_rect, *dirty_region);
+       if(intersect.width && intersect.height) {
+               Rect prev_clip = get_clipping_rect();
+               set_clipping_rect(abs_rect);
+               
+               if(callbacks.display) {
+                       callbacks.display(this);
+               }
+               dirty = false;
+
+               draw_children(abs_rect);
+               
+               *dirty_region = rect_union(*dirty_region, abs_rect);
+               set_clipping_rect(prev_clip);
+       }
+}
+
+void Window::draw_children(const Rect &dirty_region)
+{
+       Rect drect = dirty_region;
+       for(size_t i=0; i<children.size(); i++) {
+               children[i]->draw(&drect);
+       }
+}
+
+unsigned char *Window::get_win_start_on_fb()
+{
+       unsigned char *fb = get_framebuffer();
+       Rect abs_rect = get_absolute_rect();
+       return fb + get_color_depth() * (get_screen_size().x * abs_rect.y + abs_rect.x) / 8;
+}
+
+int Window::get_scanline_width()
+{
+       return get_screen_size().x;
+}
+
+void Window::set_managed(bool managed)
+{
+       this->managed = managed;
+}
+
+bool Window::get_managed() const
+{
+       return managed;
+}
+
+void Window::set_focusable(bool focusable)
+{
+       this->focusable = focusable;
+}
+
+bool Window::get_focusable() const
+{
+       return focusable;
+}
+
+bool Window::get_dirty() const
+{
+       return dirty;
+}
+
+void Window::set_display_callback(DisplayFuncType func)
+{
+       callbacks.display = func;
+}
+
+void Window::set_keyboard_callback(KeyboardFuncType func)
+{
+       callbacks.keyboard = func;
+}
+
+void Window::set_mouse_button_callback(MouseButtonFuncType func)
+{
+       callbacks.button = func;
+}
+
+void Window::set_mouse_motion_callback(MouseMotionFuncType func)
+{
+       callbacks.motion = func;
+}
+
+const DisplayFuncType Window::get_display_callback() const
+{
+       return callbacks.display;
+}
+
+const KeyboardFuncType Window::get_keyboard_callback() const
+{
+       return callbacks.keyboard;
+}
+
+const MouseButtonFuncType Window::get_mouse_button_callback() const
+{
+       return callbacks.button;
+}
+
+const MouseMotionFuncType Window::get_mouse_motion_callback() const
+{
+       return callbacks.motion;
+}
+
+void Window::add_child(Window *win)
+{
+       children.push_back(win);
+       if(win->parent) {
+               win->parent->remove_child(win);
+       }
+       win->parent = this;
+}
+
+void Window::remove_child(Window *win)
+{
+       std::vector<Window*>::iterator it;
+       it = std::find(children.begin(), children.end(), win);
+       if(it != children.end()) {
+               children.erase(it);
+               win->parent = 0;
+       }
+}
+
+Window **Window::get_children()
+{
+       if(children.empty()) {
+               return 0;
+       }
+       return &children[0];
+}
+
+int Window::get_children_count() const
+{
+       return (int)children.size();
+}
+
+const Window *Window::get_parent() const
+{
+       return parent;
+}
+
+Window *Window::get_parent()
+{
+       return parent;
+}
+
+void Window::set_state(State state)
+{
+       this->state = state;
+}
+
+Window::State Window::get_state() const
+{
+       return state;
+}