1 |
/* |
2 |
* window_gtk.c -- window handling, GTK |
3 |
*/ |
4 |
|
5 |
#include "gui.h" |
6 |
|
7 |
signed int gui_window_origin_x, gui_window_origin_y; |
8 |
GtkWidget *gui_redraw_widget; |
9 |
gui_window_id menu_window_id; |
10 |
|
11 |
|
12 |
gboolean gui_window_press(GtkWidget *widget, GdkEventButton *event, gpointer data) |
13 |
{ |
14 |
gui_window_id window_id; |
15 |
|
16 |
printf("gui_window_press: widget 0x%x, type %i, win 0x%x, %f %f, %i, data 0x%x\n", |
17 |
(unsigned int) widget, event->type, (unsigned int) event->window, event->x, event->y, event->button, (unsigned int) data); |
18 |
|
19 |
window_id = gui_handle_to_window_id(data); |
20 |
|
21 |
if (window_id != gui_WINDOW_UNKNOWN) |
22 |
{ |
23 |
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
24 |
if (gui_window_list[window_id].menu && event->button == 2) |
25 |
{ |
26 |
gtk_menu_popup(gui_window_list[window_id].menu->menu, NULL, NULL, NULL, |
27 |
NULL, event->button, event->time); |
28 |
menu_window_id = window_id; |
29 |
} |
30 |
else if (gui_window_list[window_id].click_fn) |
31 |
{ |
32 |
unsigned int z; |
33 |
|
34 |
z = (event->button == 1 ? gui_CLICK : |
35 |
(event->button == 3 ? gui_CLICK_RIGHT : 0)); |
36 |
gui_window_list[window_id].click_fn(window_id, event->x * 2, event->y * 2, z); |
37 |
} |
38 |
} |
39 |
|
40 |
} |
41 |
|
42 |
|
43 |
|
44 |
gboolean gui_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) |
45 |
{ |
46 |
gui_window_id window_id; |
47 |
signed int invalid[4]; |
48 |
|
49 |
window_id = gui_handle_to_window_id(data); |
50 |
|
51 |
gui_window_origin_x = 0; |
52 |
gui_window_origin_y = 0; |
53 |
gui_redraw_widget = widget; |
54 |
invalid[0] = event->area.x * 2; |
55 |
invalid[1] = event->area.y * 2; |
56 |
invalid[2] = (event->area.x + event->area.width) * 2; |
57 |
invalid[3] = (event->area.y + event->area.height) * 2; |
58 |
|
59 |
gdk_window_clear_area(widget->window, event->area.x, event->area.y, event->area.width, event->area.height); |
60 |
gdk_gc_set_clip_rectangle(widget->style->white_gc, &event->area); |
61 |
|
62 |
printf("gui_expose_event: id %i, rect %i %i %i %i\n", window_id, |
63 |
invalid[0], invalid[1], invalid[2], invalid[3]); |
64 |
|
65 |
gui_window_list[window_id].redraw_fn(window_id, invalid); |
66 |
|
67 |
gdk_gc_set_clip_rectangle(widget->style->white_gc, NULL); |
68 |
|
69 |
return TRUE; |
70 |
} |
71 |
|
72 |
|
73 |
void gui_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer data) |
74 |
{ |
75 |
gui_window_id window_id; |
76 |
|
77 |
window_id = gui_handle_to_window_id(data); |
78 |
printf("gui_size_allocate: id %i, %i %i %u %u\n", window_id, allocation->x, allocation->y, allocation->width, allocation->height); |
79 |
gui_window_list[window_id].resize_fn(window_id, allocation->width * 2, allocation->height * 2); |
80 |
} |
81 |
|
82 |
|
83 |
|
84 |
/* |
85 |
* gui_create_window -- create and display a window |
86 |
* |
87 |
* => flags -- window details |
88 |
* title -- window title |
89 |
* width -- width of window |
90 |
* height -- height of window |
91 |
* close_fn -- function called when an attempt is made to close the window, |
92 |
* NULL for default of closing and destroying window |
93 |
* redraw_fn -- function called when the window needs redrawing |
94 |
* click_fn -- function called when the mouse is clicked in the window or equivalent, |
95 |
* NULL for default of no action |
96 |
* |
97 |
* <= window id |
98 |
*/ |
99 |
|
100 |
gui_window_id gui_create_window(const unsigned int flags, |
101 |
char *title, |
102 |
const unsigned int width, const unsigned int height, |
103 |
void (*close_fn)(gui_window_id window_id), |
104 |
void (*redraw_fn)(gui_window_id window_id, unsigned int invalid[]), |
105 |
void (*click_fn)(gui_window_id window_id, unsigned int x, unsigned int y, |
106 |
unsigned int z), |
107 |
void (*resize_fn)(gui_window_id window_id, unsigned int width, unsigned int height), |
108 |
bool (*key_fn)(gui_window_id window_id, unsigned int key), |
109 |
void (*input_fn)(gui_window_id window_id, wchar_t key), |
110 |
void (*menu_fn)(gui_window_id window_id, unsigned int items[]), |
111 |
struct gui_menu_data *menu, |
112 |
const char *bbar, |
113 |
const char *help) |
114 |
{ |
115 |
GtkWidget *window; |
116 |
GtkWidget *scrolled_window; |
117 |
GtkWidget *event_box; |
118 |
GtkWidget *drawing_area; |
119 |
gui_window_id id; |
120 |
|
121 |
#ifdef DEBUG |
122 |
printf("gui_create_window: title = '%s'\n", title); |
123 |
fflush(stdout); |
124 |
#endif |
125 |
|
126 |
assert(redraw_fn != NULL); |
127 |
|
128 |
id = gui_get_free_window_id(); |
129 |
|
130 |
drawing_area = gtk_drawing_area_new(); |
131 |
event_box = gtk_event_box_new(); |
132 |
scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
133 |
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
134 |
|
135 |
gtk_drawing_area_size(drawing_area, flags & gui_H_SCROLL_BAR ? width / 2 : 0, flags & gui_V_SCROLL_BAR ? height / 2 : 0); |
136 |
|
137 |
gtk_container_set_border_width(GTK_CONTAINER (scrolled_window), 0); |
138 |
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
139 |
|
140 |
gtk_window_set_title(GTK_WINDOW (window), title); |
141 |
gtk_container_set_border_width(GTK_CONTAINER (window), 0); |
142 |
|
143 |
gtk_container_add(GTK_CONTAINER (event_box), drawing_area); |
144 |
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW (scrolled_window), event_box); |
145 |
gtk_container_add(GTK_CONTAINER (window), scrolled_window); |
146 |
|
147 |
gtk_widget_show(drawing_area); |
148 |
gtk_widget_show(event_box); |
149 |
gtk_widget_show(scrolled_window); |
150 |
gtk_widget_show(window); |
151 |
|
152 |
gui_window_list[id].used = 1; |
153 |
gui_window_list[id].handle = window; |
154 |
gui_window_list[id].close_fn = (close_fn == NULL ? gui_remove_window : close_fn); |
155 |
gui_window_list[id].redraw_fn = redraw_fn; |
156 |
gui_window_list[id].click_fn = click_fn; |
157 |
gui_window_list[id].resize_fn = resize_fn; |
158 |
gui_window_list[id].key_fn = key_fn; |
159 |
gui_window_list[id].input_fn = input_fn; |
160 |
gui_window_list[id].menu_fn = menu_fn; |
161 |
gui_window_list[id].width = width; |
162 |
gui_window_list[id].height = height; |
163 |
gui_window_list[id].menu = menu; |
164 |
gui_window_list[id].help = help; |
165 |
gui_window_list[id].drawing_area = drawing_area; |
166 |
|
167 |
gtk_signal_connect(event_box, "button-press-event", gui_window_press, window); |
168 |
gtk_signal_connect(drawing_area, "expose-event", gui_expose_event, window); |
169 |
gtk_signal_connect(drawing_area, "size-allocate", gui_size_allocate, window); |
170 |
|
171 |
#ifdef DEBUG |
172 |
printf("gui_create_window: id = 0x%x, handle = 0x%x\n", id, (unsigned int) window); |
173 |
fflush(stdout); |
174 |
#endif |
175 |
|
176 |
return id; |
177 |
} |
178 |
|
179 |
|
180 |
/* |
181 |
* gui_get_free_window_id -- allocate space and return a window id |
182 |
* |
183 |
* => nothing |
184 |
* |
185 |
* <= window id (gui_window_list index) |
186 |
*/ |
187 |
|
188 |
gui_window_id gui_get_free_window_id() |
189 |
{ |
190 |
static struct gui_window_data *new_gui_window_list; |
191 |
int i; |
192 |
|
193 |
#ifdef DEBUG |
194 |
printf("gui_get_free_window_id: gui_window_list_items = %i\n", gui_window_list_items); |
195 |
fflush(stdout); |
196 |
#endif |
197 |
|
198 |
for (i = 0; i < gui_window_list_items; i++) |
199 |
{ |
200 |
if (!gui_window_list[i].used) |
201 |
{ |
202 |
assert(i >= 0 && i < gui_window_list_items); |
203 |
return i; |
204 |
} |
205 |
} |
206 |
|
207 |
new_gui_window_list = realloc(gui_window_list, |
208 |
sizeof(struct gui_window_data) * (gui_window_list_items + WINDOW_LIST_CHUNK)); |
209 |
if (!new_gui_window_list) gui_raise_error("memory"); |
210 |
|
211 |
gui_window_list = new_gui_window_list; |
212 |
for (i = gui_window_list_items; i < gui_window_list_items + WINDOW_LIST_CHUNK; i++) |
213 |
gui_window_list[i].used = 0; |
214 |
|
215 |
i = gui_window_list_items; |
216 |
gui_window_list_items += WINDOW_LIST_CHUNK; |
217 |
|
218 |
#ifdef DEBUG |
219 |
printf("gui_get_free_window_id: increased gui_window_list_items = %i\n", gui_window_list_items); |
220 |
fflush(stdout); |
221 |
#endif |
222 |
|
223 |
assert(i >= 0 && i < gui_window_list_items); |
224 |
return i; |
225 |
} |
226 |
|
227 |
|
228 |
/* |
229 |
* gui_handle_to_window_id -- convert a window handle to a window id |
230 |
* |
231 |
* => handle -- wimp window handle |
232 |
* |
233 |
* <= window id |
234 |
*/ |
235 |
|
236 |
gui_window_id gui_handle_to_window_id(GtkWidget *handle) |
237 |
{ |
238 |
int i; |
239 |
|
240 |
for (i = 0; i < gui_window_list_items; i++) |
241 |
{ |
242 |
if ((gui_window_list[i].used) && (gui_window_list[i].handle == handle)) |
243 |
{ |
244 |
|
245 |
#ifdef DEBUG |
246 |
printf("gui_handle_to_window_id: handle = 0x%x, id = 0x%x\n", (unsigned int) handle, i); |
247 |
fflush(stdout); |
248 |
#endif |
249 |
return i; |
250 |
} |
251 |
} |
252 |
|
253 |
return gui_WINDOW_UNKNOWN; |
254 |
} |
255 |
|
256 |
|
257 |
/* |
258 |
* gui_remove_window -- close and destroy a window |
259 |
* |
260 |
* => window_id -- window id from gui_create_window |
261 |
* |
262 |
* <= nothing |
263 |
*/ |
264 |
|
265 |
void gui_remove_window(const gui_window_id window_id) |
266 |
{ |
267 |
assert(window_id >= 0 && window_id < gui_window_list_items && gui_window_list[window_id].used); |
268 |
|
269 |
#ifdef DEBUG |
270 |
printf("gui_remove_window: window_id = 0x%x\n", window_id); |
271 |
fflush(stdout); |
272 |
#endif |
273 |
|
274 |
/* gui_error = xwimp_delete_window(gui_window_list[window_id].handle); |
275 |
* gui_check_error(); |
276 |
* gui_window_list[window_id].used = 0; |
277 |
*/ |
278 |
} |
279 |
|
280 |
|
281 |
/* |
282 |
* gui_refresh_window -- update a window's contents |
283 |
* |
284 |
* => window_id -- window id from gui_create_window |
285 |
* |
286 |
* <= nothing |
287 |
*/ |
288 |
|
289 |
void gui_refresh_window(const gui_window_id window_id) |
290 |
{ |
291 |
assert(window_id >= 0 && window_id < gui_window_list_items && gui_window_list[window_id].used); |
292 |
|
293 |
#ifdef DEBUG |
294 |
printf("gui_refresh_window: window_id = 0x%x\n", window_id); |
295 |
fflush(stdout); |
296 |
#endif |
297 |
|
298 |
/* gui_refresh_box(window_id, 0, 0, gui_window_list[window_id].width, gui_window_list[window_id].height); */ |
299 |
} |
300 |
|
301 |
|
302 |
/* |
303 |
* gui_refresh_box -- update part of a window's contents |
304 |
* |
305 |
* => window_id -- window id from gui_create_window |
306 |
* x0, y0, x1, y1 -- area to update |
307 |
* |
308 |
* <= nothing |
309 |
*/ |
310 |
|
311 |
void gui_refresh_box(const gui_window_id window_id, unsigned int x0, unsigned int y0, |
312 |
unsigned int x1, unsigned int y1) |
313 |
{ |
314 |
signed int invalid[4]; |
315 |
bool more; |
316 |
/* wimp_window_state state; |
317 |
* wimp_draw update; |
318 |
*/ |
319 |
|
320 |
assert(window_id >= 0 && window_id < gui_window_list_items && gui_window_list[window_id].used); |
321 |
|
322 |
#ifdef DEBUG |
323 |
printf("gui_refresh_box: window_id = 0x%x, box %i %i %i %i\n", window_id, x0, y0, x1, y1); |
324 |
fflush(stdout); |
325 |
#endif |
326 |
|
327 |
/* state.w = gui_window_list[window_id].handle; |
328 |
* |
329 |
* gui_error = xwimp_get_window_state(&state); |
330 |
* gui_check_error(); |
331 |
* |
332 |
* gui_window_origin_x = state.visible.x0 - state.xscroll; |
333 |
* gui_window_origin_y = state.visible.y1 - state.yscroll; |
334 |
* |
335 |
* #ifdef DEBUG |
336 |
* printf("gui_refresh_box: redraw origin %i %i\n", gui_window_origin_x, gui_window_origin_y); |
337 |
* fflush(stdout); |
338 |
* #endif |
339 |
* |
340 |
* update.w = state.w; |
341 |
* update.box.x0 = x0; |
342 |
* update.box.y0 = -y1; |
343 |
* update.box.x1 = x1; |
344 |
* update.box.y1 = -y0; |
345 |
* gui_error = xwimp_update_window(&update, &more); |
346 |
* gui_check_error(); |
347 |
* |
348 |
* while (more) |
349 |
* { |
350 |
* invalid[0] = update.clip.x0 - gui_window_origin_x; |
351 |
* invalid[1] = gui_window_origin_y - update.clip.y1; |
352 |
* invalid[2] = update.clip.x1 - gui_window_origin_x; |
353 |
* invalid[3] = gui_window_origin_y - update.clip.y0; |
354 |
* |
355 |
* #ifdef DEBUG |
356 |
* printf("gui_refresh_box: redraw invalid %i %i %i %i\n", |
357 |
* invalid[0], invalid[1], invalid[2], invalid[3]); |
358 |
* fflush(stdout); |
359 |
* #endif |
360 |
* |
361 |
* gui_window_list[window_id].redraw_fn(window_id, invalid); |
362 |
* |
363 |
* gui_error = xwimp_get_rectangle(&update, &more); |
364 |
* gui_check_error(); |
365 |
* } |
366 |
*/ |
367 |
} |
368 |
|
369 |
|
370 |
/* |
371 |
* gui_window_extent -- set window size |
372 |
* |
373 |
* => window_id -- window id from gui_create_window |
374 |
* width, height -- new dimensions of window |
375 |
* |
376 |
* <= nothing |
377 |
*/ |
378 |
|
379 |
void gui_window_extent(const gui_window_id window_id, unsigned int width, unsigned int height) |
380 |
{ |
381 |
assert(window_id >= 0 && window_id < gui_window_list_items && gui_window_list[window_id].used); |
382 |
|
383 |
#ifdef DEBUG |
384 |
printf("gui_window_extent: window_id = 0x%x, extent = %i x %i\n", window_id, width, height); |
385 |
fflush(stdout); |
386 |
#endif |
387 |
|
388 |
gtk_drawing_area_size(gui_window_list[window_id].drawing_area, width / 2, height / 2); |
389 |
|
390 |
gui_window_list[window_id].width = width; |
391 |
gui_window_list[window_id].height = height; |
392 |
} |
393 |
|
394 |
|
395 |
/* |
396 |
* gui_fill -- fill a rectangular area during window redraw |
397 |
* |
398 |
* => colour -- 0xbbggrr format colour |
399 |
* x0, y0, x1, y1 -- coordinates of rectangle |
400 |
*/ |
401 |
|
402 |
void gui_fill(unsigned int colour, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1) |
403 |
{ |
404 |
GdkColor gdk_colour; |
405 |
|
406 |
printf("gui_fill: box %i %i %i %i\n", x0, y0, x1, y1); |
407 |
|
408 |
BGR_TO_GDK(colour, gdk_colour); |
409 |
gdk_colormap_alloc_color(gdk_window_get_colormap(gui_redraw_widget->window), &gdk_colour, FALSE, TRUE); |
410 |
gdk_gc_set_foreground(gui_redraw_widget->style->fg_gc[gui_redraw_widget->state], &gdk_colour); |
411 |
|
412 |
gdk_draw_rectangle(gui_redraw_widget->window, gui_redraw_widget->style->fg_gc[gui_redraw_widget->state], |
413 |
TRUE, x0 / 2, y0 / 2, (x1-x0) / 2, (y1-y0) / 2); |
414 |
} |
415 |
|
416 |
|
417 |
/* |
418 |
* gui_move_box -- copy a rectangular area within a window |
419 |
* |
420 |
* => window_id -- window id from gui_create_window |
421 |
* x0, y0, x1, y1 -- source area |
422 |
* x2, y2 -- destination |
423 |
*/ |
424 |
|
425 |
void gui_move_box(const gui_window_id window_id, unsigned int x0, unsigned int y0, |
426 |
unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) |
427 |
{ |
428 |
|
429 |
assert(window_id >= 0 && window_id < gui_window_list_items && gui_window_list[window_id].used); |
430 |
|
431 |
#ifdef DEBUG |
432 |
printf("gui_move_box: window_id = 0x%x, box = %i %i %i %i, dest = %i %i\n", |
433 |
window_id, x0, y0, x1, y1, x2, y2); |
434 |
fflush(stdout); |
435 |
#endif |
436 |
|
437 |
/* gui_error = xwimp_block_copy(gui_window_list[window_id].handle, x0, -y1, x1, -y0, x2, -(y1 + (y2 - y0))); |
438 |
* gui_check_error(); |
439 |
*/ |
440 |
} |