created libwinnie (library), winnie (the server application) and clients
[winnie] / libwinnie / src / window.cc
1 /*
2 winnie - an experimental window system
3
4 Copyright (C) 2013 Eleni Maria Stea
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 Author: Eleni Maria Stea <elene.mst@gmail.com>
20 */
21
22 #include <algorithm>
23 #include <stdio.h> //TODO
24 #include <string.h>
25
26 #include "gfx.h"
27 #include "window.h"
28 #include "wm.h"
29
30 Window::Window()
31 {
32         parent = 0;
33         title = 0;
34         rect.x = rect.y = 0;
35         rect.width = rect.height = 128;
36         memset(&callbacks, 0, sizeof callbacks);
37         dirty = true;
38         managed = true;
39         focusable = true;
40         state = STATE_NORMAL;
41 }
42
43 Window::~Window()
44 {
45         for(size_t i=0; i<children.size(); i++) {
46                 wm->remove_window(children[i]);
47                 delete children[i];
48         }
49
50         delete [] title;
51 }
52
53 const Rect &Window::get_rect() const
54 {
55         return rect;
56 }
57
58 Rect Window::get_absolute_rect() const
59 {
60         if(!parent) {
61                 return rect;
62         }
63
64         Rect absolute_rect;
65         absolute_rect = parent->get_absolute_rect();
66
67         absolute_rect.x += rect.x;
68         absolute_rect.y += rect.y;
69         absolute_rect.width = rect.width;
70         absolute_rect.height = rect.height;
71
72         return absolute_rect;
73 }
74
75 bool Window::contains_point(int ptr_x, int ptr_y)
76 {
77         Rect abs_rect = get_absolute_rect();
78         return ptr_x >= abs_rect.x && ptr_x < abs_rect.x + abs_rect.width &&
79                         ptr_y >= abs_rect.y && ptr_y < abs_rect.y + abs_rect.height;
80 }
81
82 void Window::move(int x, int y)
83 {
84         invalidate();   // moved, should redraw, MUST BE CALLED FIRST
85         rect.x = x;
86         rect.y = y;
87 }
88
89 void Window::resize(int x, int y)
90 {
91         invalidate();   // resized, should redraw, MUST BE CALLED FIRST
92         rect.width = x;
93         rect.height = y;
94 }
95
96 void Window::set_title(const char *s)
97 {
98         delete [] title;
99
100         title = new char[strlen(s) + 1];
101         strcpy(title, s);
102 }
103
104 const char *Window::get_title() const
105 {
106         return title;
107 }
108
109 void Window::invalidate()
110 {
111         dirty = true;
112         Rect abs_rect = get_absolute_rect();
113         wm->invalidate_region(abs_rect);
114 }
115
116 void Window::draw(Rect *dirty_region)
117 {
118         Rect abs_rect = get_absolute_rect();
119         Rect intersect = rect_intersection(abs_rect, *dirty_region);
120         if(intersect.width && intersect.height) {
121                 Rect prev_clip = get_clipping_rect();
122                 set_clipping_rect(abs_rect);
123                 
124                 if(callbacks.display) {
125                         callbacks.display(this);
126                 }
127                 dirty = false;
128
129                 draw_children(abs_rect);
130                 
131                 *dirty_region = rect_union(*dirty_region, abs_rect);
132                 set_clipping_rect(prev_clip);
133         }
134 }
135
136 void Window::draw_children(const Rect &dirty_region)
137 {
138         Rect drect = dirty_region;
139         for(size_t i=0; i<children.size(); i++) {
140                 children[i]->draw(&drect);
141         }
142 }
143
144 unsigned char *Window::get_win_start_on_fb()
145 {
146         unsigned char *fb = get_framebuffer();
147         Rect abs_rect = get_absolute_rect();
148         return fb + get_color_depth() * (get_screen_size().x * abs_rect.y + abs_rect.x) / 8;
149 }
150
151 int Window::get_scanline_width()
152 {
153         return get_screen_size().x;
154 }
155
156 void Window::set_managed(bool managed)
157 {
158         this->managed = managed;
159 }
160
161 bool Window::get_managed() const
162 {
163         return managed;
164 }
165
166 void Window::set_focusable(bool focusable)
167 {
168         this->focusable = focusable;
169 }
170
171 bool Window::get_focusable() const
172 {
173         return focusable;
174 }
175
176 bool Window::get_dirty() const
177 {
178         return dirty;
179 }
180
181 void Window::set_display_callback(DisplayFuncType func)
182 {
183         callbacks.display = func;
184 }
185
186 void Window::set_keyboard_callback(KeyboardFuncType func)
187 {
188         callbacks.keyboard = func;
189 }
190
191 void Window::set_mouse_button_callback(MouseButtonFuncType func)
192 {
193         callbacks.button = func;
194 }
195
196 void Window::set_mouse_motion_callback(MouseMotionFuncType func)
197 {
198         callbacks.motion = func;
199 }
200
201 const DisplayFuncType Window::get_display_callback() const
202 {
203         return callbacks.display;
204 }
205
206 const KeyboardFuncType Window::get_keyboard_callback() const
207 {
208         return callbacks.keyboard;
209 }
210
211 const MouseButtonFuncType Window::get_mouse_button_callback() const
212 {
213         return callbacks.button;
214 }
215
216 const MouseMotionFuncType Window::get_mouse_motion_callback() const
217 {
218         return callbacks.motion;
219 }
220
221 void Window::add_child(Window *win)
222 {
223         children.push_back(win);
224         if(win->parent) {
225                 win->parent->remove_child(win);
226         }
227         win->parent = this;
228 }
229
230 void Window::remove_child(Window *win)
231 {
232         std::vector<Window*>::iterator it;
233         it = std::find(children.begin(), children.end(), win);
234         if(it != children.end()) {
235                 children.erase(it);
236                 win->parent = 0;
237         }
238 }
239
240 Window **Window::get_children()
241 {
242         if(children.empty()) {
243                 return 0;
244         }
245         return &children[0];
246 }
247
248 int Window::get_children_count() const
249 {
250         return (int)children.size();
251 }
252
253 const Window *Window::get_parent() const
254 {
255         return parent;
256 }
257
258 Window *Window::get_parent()
259 {
260         return parent;
261 }
262
263 void Window::set_state(State state)
264 {
265         this->state = state;
266 }
267
268 Window::State Window::get_state() const
269 {
270         return state;
271 }