fixed focus: get_window_at_pos now searches back to front in root_window
[winnie] / src / window.cc
1 #include <algorithm>
2 #include <stdio.h> //TODO
3 #include <string.h>
4
5 #include "gfx.h"
6 #include "window.h"
7 #include "wm.h"
8
9 Window::Window()
10 {
11         parent = 0;
12         title = 0;
13         rect.x = rect.y = 0;
14         rect.width = rect.height = 128;
15         memset(&callbacks, 0, sizeof callbacks);
16         dirty = true;
17         managed = true;
18         focusable = true;
19 }
20
21 Window::~Window()
22 {
23         for(size_t i=0; i<children.size(); i++) {
24                 wm->remove_window(children[i]);
25                 delete children[i];
26         }
27
28         delete [] title;
29 }
30
31 const Rect &Window::get_rect() const
32 {
33         return rect;
34 }
35
36 Rect Window::get_absolute_rect() const
37 {
38         if(!parent) {
39                 return rect;
40         }
41
42         Rect absolute_rect;
43         absolute_rect = parent->get_absolute_rect();
44
45         absolute_rect.x += rect.x;
46         absolute_rect.y += rect.y;
47         absolute_rect.width = rect.width;
48         absolute_rect.height = rect.height;
49
50         return absolute_rect;
51 }
52
53 bool Window::contains_point(int ptr_x, int ptr_y)
54 {
55         Rect abs_rect = get_absolute_rect();
56         return ptr_x >= abs_rect.x && ptr_x < abs_rect.x + abs_rect.width &&
57                         ptr_y >= abs_rect.y && ptr_y < abs_rect.y + abs_rect.height;
58 }
59
60 void Window::move(int x, int y)
61 {
62         invalidate();   // moved, should redraw, MUST BE CALLED FIRST
63         rect.x = x;
64         rect.y = y;
65 }
66
67 void Window::resize(int x, int y)
68 {
69         invalidate();   // resized, should redraw, MUST BE CALLED FIRST
70         rect.width = x;
71         rect.height = y;
72 }
73
74 void Window::set_title(const char *s)
75 {
76         delete [] title;
77
78         title = new char[strlen(s) + 1];
79         strcpy(title, s);
80 }
81
82 const char *Window::get_title() const
83 {
84         return title;
85 }
86
87 void Window::invalidate()
88 {
89         dirty = true;
90         Rect abs_rect = get_absolute_rect();
91         wm->invalidate_region(abs_rect);
92 }
93
94 void Window::draw(Rect *dirty_region)
95 {
96         Rect abs_rect = get_absolute_rect();
97         Rect intersect = rect_intersection(abs_rect, *dirty_region);
98         if(intersect.width && intersect.height) {
99                 if(callbacks.display) {
100                         callbacks.display(this);
101                 }
102                 dirty = false;
103
104                 draw_children(abs_rect);
105
106                 *dirty_region = rect_union(*dirty_region, abs_rect);
107         }
108 }
109
110 void Window::draw_children(const Rect &dirty_region)
111 {
112         Rect drect = dirty_region;
113         for(size_t i=0; i<children.size(); i++) {
114                 children[i]->draw(&drect);
115         }
116 }
117
118 unsigned char *Window::get_win_start_on_fb()
119 {
120         unsigned char *fb = get_framebuffer();
121         Rect abs_rect = get_absolute_rect();
122         return fb + get_color_depth() * (get_screen_size().x * abs_rect.y + abs_rect.x) / 8;
123 }
124
125 int Window::get_scanline_width()
126 {
127         return get_screen_size().x;
128 }
129
130 void Window::set_managed(bool managed)
131 {
132         this->managed = managed;
133 }
134
135 bool Window::get_managed() const
136 {
137         return managed;
138 }
139
140 void Window::set_focusable(bool focusable)
141 {
142         this->focusable = focusable;
143 }
144
145 bool Window::get_focusable() const
146 {
147         return focusable;
148 }
149
150 bool Window::get_dirty() const
151 {
152         return dirty;
153 }
154
155 void Window::set_display_callback(DisplayFuncType func)
156 {
157         callbacks.display = func;
158 }
159
160 void Window::set_keyboard_callback(KeyboardFuncType func)
161 {
162         callbacks.keyboard = func;
163 }
164
165 void Window::set_mouse_button_callback(MouseButtonFuncType func)
166 {
167         callbacks.button = func;
168 }
169
170 void Window::set_mouse_motion_callback(MouseMotionFuncType func)
171 {
172         callbacks.motion = func;
173 }
174
175 const DisplayFuncType Window::get_display_callback() const
176 {
177         return callbacks.display;
178 }
179
180 const KeyboardFuncType Window::get_keyboard_callback() const
181 {
182         return callbacks.keyboard;
183 }
184
185 const MouseButtonFuncType Window::get_mouse_button_callback() const
186 {
187         return callbacks.button;
188 }
189
190 const MouseMotionFuncType Window::get_mouse_motion_callback() const
191 {
192         return callbacks.motion;
193 }
194
195 void Window::add_child(Window *win)
196 {
197         children.push_back(win);
198         if(win->parent) {
199                 win->parent->remove_child(win);
200         }
201         win->parent = this;
202 }
203
204 void Window::remove_child(Window *win)
205 {
206         std::vector<Window*>::iterator it;
207         it = std::find(children.begin(), children.end(), win);
208         if(it != children.end()) {
209                 children.erase(it);
210                 win->parent = 0;
211         }
212 }
213
214 Window **Window::get_children()
215 {
216         if(children.empty()) {
217                 return 0;
218         }
219         return &children[0];
220 }
221
222 int Window::get_children_count() const
223 {
224         return (int)children.size();
225 }
226
227 const Window *Window::get_parent() const
228 {
229         return parent;
230 }
231
232 Window *Window::get_parent()
233 {
234         return parent;
235 }