*in progress*
[winnie] / src / wm.cc
1 #include <algorithm>
2 #include <stdexcept>
3
4 #include "gfx.h"
5 #include "wm.h"
6 #include "window.h"
7 #include "mouse.h"
8 #include "mouse_cursor.h"
9
10 WindowManager *wm;
11 static WindowManager wminst;
12
13 static void display(Window *win);
14 static void mouse(Window *win, int key, bool pressed);
15 static void motion(Window *win, int x, int y);
16
17 void WindowManager::create_frame(Window *win)
18 {
19         Window *frame = new Window;
20         Window *parent = win->get_parent();
21
22         frame->set_display_callback(display);
23 //      frame->set_mouse_button_callback(mouse);
24 //      frame->set_mouse_motion_callback(motion);
25
26         frame->add_child(win);
27         frames.push_back(frame);
28
29         Rect win_rect = win->get_rect();
30         frame->move(win_rect.x - frame_thickness, 
31                         win_rect.y - frame_thickness - titlebar_thickness);
32         frame->resize(win_rect.width + frame_thickness * 2, 
33                         win_rect.height + frame_thickness * 2 + titlebar_thickness);
34
35         parent->add_child(frame);
36 }
37
38 void WindowManager::destroy_frame(Window *win)
39 {
40         Window *frame = win->parent;
41         if(!frame) {
42                 return;
43         }
44
45         std::list<Window*>::iterator it;
46         it = std::find(frames.begin(), frames.end(), frame);
47         if(it != frames.end()) {
48                 root_win->add_child(win);
49                 frames.erase(it);
50                 delete frame;
51         }
52 }
53
54 WindowManager::WindowManager()
55 {
56         if(!wm) {
57                 wm = this;
58         } else {
59                 throw std::runtime_error("Trying to create a second instance of WindowManager!\n");
60         }
61
62         root_win = new Window;
63         root_win->resize(get_screen_size().width, get_screen_size().height);
64         root_win->move(0, 0);
65         root_win->set_managed(false);
66
67         focused_win = 0;
68
69         bg_color[0] = 210;
70         bg_color[1] = 106;
71         bg_color[2] = 106;
72
73         frame_thickness = 2;
74         titlebar_thickness = 4;
75
76         frame_fcolor[0] = frame_fcolor[1] = frame_fcolor[2] = 142;
77         frame_ucolor[0] = frame_ucolor[1] = frame_ucolor[2] = 210;
78
79         mouse_cursor.set_image(mouse_cursor_width, mouse_cursor_height);
80         unsigned char *pixels = mouse_cursor.get_image();
81
82         for(int i=0; i<mouse_cursor_height; i++) {
83                 for(int j=0; j<mouse_cursor_width; j++) {
84                         int val = mouse_cursor_bw[i * mouse_cursor_width + j];
85                         *pixels++ = val;
86                         *pixels++ = val;
87                         *pixels++ = val;
88                         *pixels++ = 255;
89                 }
90         }
91 }
92
93 WindowManager::~WindowManager()
94 {
95         delete root_win;
96 }
97
98 void WindowManager::invalidate_region(const Rect &rect)
99 {
100         dirty_rects.push_back(rect);
101 }
102
103 void WindowManager::process_windows()
104 {
105         if(dirty_rects.empty()) {
106                 return;
107         }
108
109         std::list<Rect>::iterator drit = dirty_rects.begin();
110         Rect uni = *drit++;
111         while(drit != dirty_rects.end()) {
112                 uni = rect_union(uni, *drit++);
113         }
114         dirty_rects.clear();
115
116         fill_rect(uni, bg_color[0], bg_color[1], bg_color[2]);
117
118         root_win->draw_children(uni);
119
120         // draw mouse cursor
121         int mouse_x, mouse_y;
122         get_pointer_pos(&mouse_x, &mouse_y);
123
124         blit_key(mouse_cursor.get_image(), mouse_cursor.get_rect(),
125                         get_framebuffer(), get_screen_size(), mouse_x, mouse_y,
126                         0, 0, 0);
127
128         Rect mouse_rect = {mouse_x, mouse_y, mouse_cursor.get_width(), mouse_cursor.get_height()};
129         invalidate_region(mouse_rect);
130 }
131
132 void WindowManager::add_window(Window *win)
133 {
134         if(!win || win == root_win) {
135                 return;
136         }
137
138         root_win->add_child(win);
139
140         if(windows.empty()) {
141                 focused_win = win;
142         }
143
144         if(win->get_managed()) {
145                 create_frame(win);
146         }
147
148         windows.push_back(win);
149 }
150
151 void WindowManager::remove_window(Window *win)
152 {
153         std::list<Window*>::iterator it;
154         it = std::find(windows.begin(), windows.end(), win);
155
156         if(it != windows.end()) {
157                 windows.erase(it);
158         }
159 }
160
161 void WindowManager::set_focused_window(Window *win)
162 {
163         focused_win = win;
164 }
165
166 const Window *WindowManager::get_focused_window() const
167 {
168         return focused_win;
169 }
170
171 Window *WindowManager::get_focused_window()
172 {
173         return focused_win;
174 }
175
176 Window *WindowManager::get_window_at_pos(int pointer_x, int pointer_y)
177 {
178         Window *win = 0;
179         std::list<Window*>::reverse_iterator rit = windows.rbegin();
180         while(rit != windows.rend()) {
181                 if((*rit)->contains_point(pointer_x, pointer_y)) {
182                         win = *rit;
183                         break;
184                 }
185                 rit++;
186         }
187
188         return win;
189 }
190
191 static void display(Window *win)
192 {
193         if(win->get_managed()) {
194                 fill_rect(win->get_rect(), 255, 211, 5);
195                 win->draw(win->get_parent()->get_rect());
196         }
197 }
198
199 //static void mouse(Window *win, int key, bool pressed);
200 //static void motion(Window *win, int x, int y);