source: mainline/uspace/lib/gui/window.c@ afcf704

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since afcf704 was afcf704, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Allow GUI direct access to window buffer

  • Property mode set to 100644
File size: 23.2 KB
Line 
1/*
2 * Copyright (c) 2012 Petr Koupy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup gui
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <stdbool.h>
37#include <errno.h>
38#include <stdio.h>
39#include <stdlib.h>
40
41#include <as.h>
42#include <stdlib.h>
43#include <str.h>
44
45#include <fibril.h>
46#include <task.h>
47#include <adt/prodcons.h>
48#include <adt/list.h>
49
50#include <loc.h>
51
52#include <io/pixel.h>
53#include <draw/source.h>
54#include <draw/font.h>
55#include <draw/drawctx.h>
56#include <draw/surface.h>
57#include <display.h>
58
59#include "common.h"
60#include "connection.h"
61#include "widget.h"
62#include "window.h"
63
64static sysarg_t border_thickness = 4;
65static sysarg_t bevel_thickness = 1;
66static sysarg_t header_height = 20;
67static sysarg_t header_min_width = 40;
68static sysarg_t close_thickness = 20;
69static sysarg_t corner_size = 24;
70
71static pixel_t color_highlight = PIXEL(255, 255, 255, 255);
72static pixel_t color_shadow = PIXEL(255, 85, 85, 85);
73static pixel_t color_surface = PIXEL(255, 186, 186, 186);
74
75static pixel_t color_header_focus_highlight = PIXEL(255, 120, 145, 255);
76static pixel_t color_header_focus_shadow = PIXEL(255, 40, 48, 89);
77static pixel_t color_header_focus_surface = PIXEL(255, 88, 106, 196);
78
79static pixel_t color_header_unfocus_highlight = PIXEL(255, 16, 78, 126);
80static pixel_t color_header_unfocus_shadow = PIXEL(255, 5, 26, 42);
81static pixel_t color_header_unfocus_surface = PIXEL(255, 12, 57, 92);
82
83static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255);
84static pixel_t color_caption_unfocus = PIXEL(255, 207, 207, 207);
85
86static void window_close_event(void *);
87static void window_focus_event(void *);
88static void window_kbd_event(void *, kbd_event_t *);
89static void window_pos_event(void *, pos_event_t *);
90static void window_resize_event(void *, gfx_rect_t *);
91static void window_unfocus_event(void *);
92
93static display_wnd_cb_t window_cb = {
94 .close_event = window_close_event,
95 .focus_event = window_focus_event,
96 .kbd_event = window_kbd_event,
97 .pos_event = window_pos_event,
98 .resize_event = window_resize_event,
99 .unfocus_event = window_unfocus_event
100};
101
102static void set_cursor(window_t *window, display_stock_cursor_t cursor)
103{
104 if (cursor != window->cursor) {
105 (void) display_window_set_cursor(window->dwindow, cursor);
106 window->cursor = cursor;
107 }
108}
109
110static void paint_internal(widget_t *widget)
111{
112 surface_t *surface = window_claim(widget->window);
113 if (!surface)
114 window_yield(widget->window);
115
116 source_t source;
117 source_init(&source);
118
119 drawctx_t drawctx;
120 drawctx_init(&drawctx, surface);
121 drawctx_set_source(&drawctx, &source);
122
123 /* Window border outer bevel */
124
125 draw_bevel(&drawctx, &source, widget->vpos, widget->hpos,
126 widget->width, widget->height, color_highlight, color_shadow);
127
128 /* Window border surface */
129
130 source_set_color(&source, color_surface);
131 drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
132 widget->width - 2, 2);
133 drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
134 2, widget->height - 2);
135 drawctx_transfer(&drawctx, widget->hpos + 1,
136 widget->vpos + widget->height - 3, widget->width - 2, 2);
137 drawctx_transfer(&drawctx, widget->hpos + widget->width - 3,
138 widget->vpos + 1, 2, widget->height - 4);
139
140 /* Window border inner bevel */
141
142 draw_bevel(&drawctx, &source, widget->hpos + 3, widget->vpos + 3,
143 widget->width - 6, widget->height - 6, color_shadow,
144 color_highlight);
145
146 /* Header bevel */
147
148 sysarg_t header_hpos = widget->hpos + border_thickness;
149 sysarg_t header_vpos = widget->vpos + border_thickness;
150 sysarg_t header_width = widget->width - 2 * border_thickness -
151 close_thickness;
152
153 draw_bevel(&drawctx, &source, header_hpos, header_vpos,
154 header_width, header_height, widget->window->is_focused ?
155 color_header_focus_highlight : color_header_unfocus_highlight,
156 widget->window->is_focused ?
157 color_header_focus_shadow : color_header_unfocus_shadow);
158
159 /* Header surface */
160
161 source_set_color(&source, widget->window->is_focused ?
162 color_header_focus_surface : color_header_unfocus_surface);
163 drawctx_transfer(&drawctx, header_hpos + 1, header_vpos + 1,
164 header_width - 2, header_height - 2);
165
166 /* Close button bevel */
167
168 sysarg_t close_hpos = widget->hpos + widget->width -
169 border_thickness - close_thickness;
170 sysarg_t close_vpos = widget->vpos + border_thickness;
171
172 draw_bevel(&drawctx, &source, close_hpos, close_vpos,
173 close_thickness, close_thickness, color_highlight, color_shadow);
174
175 /* Close button surface */
176
177 source_set_color(&source, color_surface);
178 drawctx_transfer(&drawctx, close_hpos + 1, close_vpos + 1,
179 close_thickness - 2, close_thickness - 2);
180
181 /* Close button icon */
182
183 draw_icon_cross(surface, close_hpos + 3, close_vpos + 3,
184 color_highlight, color_shadow);
185
186 /* Window caption */
187
188 font_t *font;
189 errno_t rc = embedded_font_create(&font, 16);
190 if (rc != EOK) {
191 window_yield(widget->window);
192 return;
193 }
194
195 drawctx_set_font(&drawctx, font);
196 source_set_color(&source, widget->window->is_focused ?
197 color_caption_focus : color_caption_unfocus);
198
199 sysarg_t cpt_width;
200 sysarg_t cpt_height;
201 font_get_box(font, widget->window->caption, &cpt_width, &cpt_height);
202
203 bool draw_title =
204 (widget->width >= 2 * border_thickness + 2 * bevel_thickness +
205 close_thickness + cpt_width);
206 if (draw_title) {
207 sysarg_t cpt_x = ((widget->width - cpt_width) / 2) + widget->hpos;
208 sysarg_t cpt_y = ((header_height - cpt_height) / 2) +
209 widget->vpos + border_thickness;
210
211 if (widget->window->caption)
212 drawctx_print(&drawctx, widget->window->caption, cpt_x, cpt_y);
213 }
214
215 font_release(font);
216 window_yield(widget->window);
217}
218
219static void root_destroy(widget_t *widget)
220{
221 widget_deinit(widget);
222}
223
224static void root_reconfigure(widget_t *widget)
225{
226 if (widget->window->is_decorated) {
227 list_foreach(widget->children, link, widget_t, child) {
228 child->rearrange(child,
229 widget->hpos + border_thickness,
230 widget->vpos + border_thickness + header_height,
231 widget->width - 2 * border_thickness,
232 widget->height - 2 * border_thickness - header_height);
233 }
234 } else {
235 list_foreach(widget->children, link, widget_t, child) {
236 child->rearrange(child, widget->hpos, widget->vpos,
237 widget->width, widget->height);
238 }
239 }
240}
241
242static void root_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
243 sysarg_t width, sysarg_t height)
244{
245 widget_modify(widget, hpos, vpos, width, height);
246 if (widget->window->is_decorated) {
247 paint_internal(widget);
248 list_foreach(widget->children, link, widget_t, child) {
249 child->rearrange(child,
250 hpos + border_thickness,
251 vpos + border_thickness + header_height,
252 width - 2 * border_thickness,
253 height - 2 * border_thickness - header_height);
254 }
255 } else {
256 list_foreach(widget->children, link, widget_t, child) {
257 child->rearrange(child, hpos, vpos, width, height);
258 }
259 }
260}
261
262static void root_repaint(widget_t *widget)
263{
264 if (widget->window->is_decorated) {
265 paint_internal(widget);
266 }
267 list_foreach(widget->children, link, widget_t, child) {
268 child->repaint(child);
269 }
270 if (widget->window->is_decorated) {
271 window_damage(widget->window);
272 }
273}
274
275static void root_handle_keyboard_event(widget_t *widget, kbd_event_t event)
276{
277 if (!list_empty(&widget->children)) {
278 widget_t *child = (widget_t *) list_first(&widget->children);
279 child->handle_keyboard_event(child, event);
280 }
281}
282
283static void root_handle_position_event(widget_t *widget, pos_event_t event)
284{
285 gfx_coord2_t pos;
286
287 if (widget->window->is_decorated) {
288 sysarg_t width = widget->width;
289 sysarg_t height = widget->height;
290
291 bool btn_left = (event.btn_num == 1) && (event.type == POS_PRESS);
292
293 bool left = (event.hpos < border_thickness);
294 bool right = (event.hpos >= width - border_thickness);
295 bool top = (event.vpos < border_thickness);
296 bool bottom = (event.vpos >= height - border_thickness);
297 bool edge = left || right || top || bottom;
298
299 bool cleft = (event.hpos < corner_size);
300 bool cright = (event.hpos >= width - corner_size);
301 bool ctop = (event.vpos < corner_size);
302 bool cbottom = (event.vpos >= height - corner_size);
303
304 bool header = (event.hpos >= border_thickness) &&
305 (event.hpos < width - border_thickness) &&
306 (event.vpos >= border_thickness) &&
307 (event.vpos < border_thickness + header_height);
308 bool close = (header) &&
309 (event.hpos >= width - border_thickness - close_thickness);
310
311 bool isresize = true;
312 display_wnd_rsztype_t rsztype = 0;
313
314 if (edge && ctop && cleft) {
315 rsztype = display_wr_top_left;
316 } else if (edge && cbottom && cleft) {
317 rsztype = display_wr_bottom_left;
318 } else if (edge && cbottom && cright) {
319 rsztype = display_wr_bottom_right;
320 } else if (edge && ctop && cright) {
321 rsztype = display_wr_top_right;
322 } else if (top) {
323 rsztype = display_wr_top;
324 } else if (left) {
325 rsztype = display_wr_left;
326 } else if (bottom) {
327 rsztype = display_wr_bottom;
328 } else if (right) {
329 rsztype = display_wr_right;
330 } else {
331 isresize = false;
332 }
333
334 if (isresize) {
335 (void) set_cursor(widget->window,
336 display_cursor_from_wrsz(rsztype));
337 } else {
338 (void) set_cursor(widget->window, dcurs_arrow);
339 }
340
341 pos.x = event.hpos;
342 pos.y = event.vpos;
343
344 if (isresize && btn_left) {
345 (void) display_window_resize_req(
346 widget->window->dwindow, rsztype, &pos);
347 } else if (close && btn_left) {
348 window_close(widget->window);
349 } else if (header && btn_left) {
350 (void) display_window_move_req(widget->window->dwindow,
351 &pos);
352 } else {
353 list_foreach(widget->children, link, widget_t, child) {
354 child->handle_position_event(child, event);
355 }
356 }
357 } else {
358 list_foreach(widget->children, link, widget_t, child) {
359 child->handle_position_event(child, event);
360 }
361 }
362}
363
364static void deliver_keyboard_event(window_t *win, kbd_event_t event)
365{
366 if (win->focus) {
367 win->focus->handle_keyboard_event(win->focus, event);
368 } else {
369 win->root.handle_keyboard_event(&win->root, event);
370 }
371}
372
373static void deliver_position_event(window_t *win, pos_event_t event)
374{
375 if (win->grab) {
376 win->grab->handle_position_event(win->grab, event);
377 } else {
378 win->root.handle_position_event(&win->root, event);
379 }
380}
381
382static void handle_signal_event(window_t *win, signal_event_t event)
383{
384 widget_t *widget = (widget_t *) event.object;
385 slot_t slot = (slot_t) event.slot;
386 void *data = (void *) event.argument;
387
388 slot(widget, data);
389
390 free(data);
391}
392
393static void handle_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
394 sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
395{
396 gfx_bitmap_params_t params;
397 gfx_bitmap_alloc_t alloc;
398 gfx_bitmap_t *new_bitmap = NULL;
399 gfx_coord2_t offs;
400 gfx_coord2_t dpos;
401 display_info_t dinfo;
402 gfx_rect_t drect;
403 gfx_rect_t nrect;
404 errno_t rc;
405
406 if (width < 2 * border_thickness + header_min_width) {
407 //win_damage(win->osess, 0, 0, 0, 0);
408 return;
409 }
410
411 if (height < 2 * border_thickness + header_height) {
412 //win_damage(win->osess, 0, 0, 0, 0);
413 return;
414 }
415
416 fibril_mutex_lock(&win->guard);
417
418 /* Deallocate old bitmap. */
419 if (win->bitmap != NULL) {
420 gfx_bitmap_destroy(win->bitmap);
421 win->bitmap = NULL;
422 }
423
424 /* Deallocate old surface. */
425 if (win->surface != NULL) {
426 surface_destroy(win->surface);
427 win->surface = NULL;
428 }
429
430 /* Resize the display window. */
431 offs.x = offset_x;
432 offs.y = offset_y;
433 nrect.p0.x = 0;
434 nrect.p0.y = 0;
435 nrect.p1.x = width;
436 nrect.p1.y = height;
437
438 rc = display_window_resize(win->dwindow, &offs, &nrect);
439 if (rc != EOK)
440 return;
441
442 gfx_bitmap_params_init(&params);
443#ifndef CONFIG_WIN_DOUBLE_BUF
444 params.flags = bmpf_direct_output;
445#else
446 params.flags = 0;
447#endif
448 params.rect.p0.x = 0;
449 params.rect.p0.y = 0;
450 params.rect.p1.x = width;
451 params.rect.p1.y = height;
452
453 rc = gfx_bitmap_create(win->gc, &params, NULL, &new_bitmap);
454 if (rc != EOK) {
455 if (rc == ENOTSUP) {
456 /* Direct output is not supported */
457 params.flags &= ~bmpf_direct_output;
458 rc = gfx_bitmap_create(win->gc, &params, NULL, &new_bitmap);
459 if (rc != EOK) {
460 fibril_mutex_unlock(&win->guard);
461 return;
462 }
463 }
464 }
465
466 rc = gfx_bitmap_get_alloc(new_bitmap, &alloc);
467 if (rc != EOK) {
468 fibril_mutex_unlock(&win->guard);
469 return;
470 }
471
472 /* Allocate new surface. */
473 surface_t *new_surface = surface_create(width, height, alloc.pixels, 0);
474 if (!new_surface) {
475 gfx_bitmap_destroy(new_bitmap);
476 fibril_mutex_unlock(&win->guard);
477 return;
478 }
479
480 /* Switch in new surface and bitmap. */
481 win->surface = new_surface;
482 win->bitmap = new_bitmap;
483 fibril_mutex_unlock(&win->guard);
484
485 /*
486 * Let all widgets in the tree alter their position and size.
487 * Widgets might also paint themselves onto the new surface.
488 */
489 win->root.rearrange(&win->root, 0, 0, width, height);
490
491 fibril_mutex_lock(&win->guard);
492 surface_reset_damaged_region(win->surface);
493 fibril_mutex_unlock(&win->guard);
494
495 if (placement_flags != WINDOW_PLACEMENT_ANY) {
496 dpos.x = 0;
497 dpos.y = 0;
498
499 rc = display_get_info(win->display, &dinfo);
500 if (rc != EOK) {
501 (void) gfx_bitmap_render(win->bitmap, NULL, NULL);
502 return;
503 }
504
505 drect = dinfo.rect;
506
507 if (placement_flags & WINDOW_PLACEMENT_LEFT)
508 dpos.x = drect.p0.x;
509 else if (placement_flags & WINDOW_PLACEMENT_CENTER_X)
510 dpos.x = (drect.p0.x + drect.p0.y - width) / 2;
511 else
512 dpos.x = drect.p1.x - width;
513
514 if (placement_flags & WINDOW_PLACEMENT_TOP)
515 dpos.y = drect.p0.y;
516 else if (placement_flags & WINDOW_PLACEMENT_CENTER_Y)
517 dpos.y = (drect.p0.y + drect.p1.y - height) / 2;
518 else
519 dpos.y = drect.p1.y - height;
520
521 (void) display_window_move(win->dwindow, &dpos);
522 }
523
524 (void) gfx_bitmap_render(win->bitmap, NULL, NULL);
525}
526
527static void handle_refresh(window_t *win)
528{
529 win->root.repaint(&win->root);
530}
531
532static void handle_damage(window_t *win)
533{
534 sysarg_t x, y, width, height;
535 gfx_rect_t rect;
536 fibril_mutex_lock(&win->guard);
537 surface_get_damaged_region(win->surface, &x, &y, &width, &height);
538 surface_reset_damaged_region(win->surface);
539 fibril_mutex_unlock(&win->guard);
540
541 if (width > 0 && height > 0) {
542 rect.p0.x = x;
543 rect.p0.y = y;
544 rect.p1.x = x + width;
545 rect.p1.y = y + height;
546
547 if (win->bitmap != NULL)
548 (void) gfx_bitmap_render(win->bitmap, &rect, NULL);
549 }
550}
551
552static void destroy_children(widget_t *widget)
553{
554 /* Recursively destroy widget tree in bottom-top order. */
555 while (!list_empty(&widget->children)) {
556 widget_t *child =
557 list_get_instance(list_first(&widget->children), widget_t, link);
558 destroy_children(child);
559 child->destroy(child);
560 }
561}
562
563static void handle_close(window_t *win)
564{
565 destroy_children(&win->root);
566 win->root.destroy(&win->root);
567 win->grab = NULL;
568 win->focus = NULL;
569
570 display_window_destroy(win->dwindow);
571 display_close(win->display);
572
573 while (!list_empty(&win->events.list)) {
574 window_event_t *event = (window_event_t *) list_first(&win->events.list);
575 list_remove(&event->link);
576 free(event);
577 }
578
579 if (win->surface) {
580 surface_destroy(win->surface);
581 }
582
583 free(win->caption);
584
585 free(win);
586}
587
588/* Window event loop. Runs in own dedicated fibril. */
589static errno_t event_loop(void *arg)
590{
591 bool is_main = false;
592 bool terminate = false;
593 window_t *win = (window_t *) arg;
594
595 while (true) {
596 window_event_t *event = (window_event_t *) prodcons_consume(&win->events);
597
598 switch (event->type) {
599 case ET_KEYBOARD_EVENT:
600 deliver_keyboard_event(win, event->data.kbd);
601 break;
602 case ET_POSITION_EVENT:
603 deliver_position_event(win, event->data.pos);
604 break;
605 case ET_SIGNAL_EVENT:
606 handle_signal_event(win, event->data.signal);
607 break;
608 case ET_WINDOW_RESIZE:
609 handle_resize(win, event->data.resize.offset_x,
610 event->data.resize.offset_y, event->data.resize.width,
611 event->data.resize.height, event->data.resize.placement_flags);
612 break;
613 case ET_WINDOW_FOCUS:
614 if (!win->is_focused) {
615 win->is_focused = true;
616 handle_refresh(win);
617 }
618 break;
619 case ET_WINDOW_UNFOCUS:
620 if (win->is_focused) {
621 win->is_focused = false;
622 handle_refresh(win);
623 }
624 break;
625 case ET_WINDOW_REFRESH:
626 handle_refresh(win);
627 break;
628 case ET_WINDOW_DAMAGE:
629 handle_damage(win);
630 break;
631 case ET_WINDOW_CLOSE:
632 is_main = win->is_main;
633 handle_close(win);
634 terminate = true;
635 break;
636 default:
637 break;
638 }
639
640 free(event);
641 if (terminate) {
642 break;
643 }
644 }
645
646 if (is_main) {
647 exit(0); /* Terminate whole task. */
648 }
649 return 0;
650}
651
652window_t *window_open(const char *winreg, const void *data,
653 window_flags_t flags, const char *caption)
654{
655 display_wnd_params_t wparams;
656
657 window_t *win = (window_t *) calloc(1, sizeof(window_t));
658 if (!win)
659 return NULL;
660
661 win->is_main = flags & WINDOW_MAIN;
662 win->is_decorated = flags & WINDOW_DECORATED;
663 win->is_focused = true;
664 prodcons_initialize(&win->events);
665 fibril_mutex_initialize(&win->guard);
666
667 widget_init(&win->root, NULL, data);
668 win->root.window = win;
669 win->root.destroy = root_destroy;
670 win->root.reconfigure = root_reconfigure;
671 win->root.rearrange = root_rearrange;
672 win->root.repaint = root_repaint;
673 win->root.handle_keyboard_event = root_handle_keyboard_event;
674 win->root.handle_position_event = root_handle_position_event;
675 win->grab = NULL;
676 win->focus = NULL;
677 win->cursor = dcurs_arrow;
678
679 /* Allocate resources for new surface. */
680 win->surface = surface_create(100, 100, NULL, SURFACE_FLAG_SHARED);
681 if (win->surface == NULL) {
682 free(win);
683 return NULL;
684 }
685
686 errno_t rc = display_open(winreg, &win->display);
687 if (rc != EOK) {
688 surface_destroy(win->surface);
689 free(win);
690 return NULL;
691 }
692
693 /* Window dimensions are not know at this time */
694 display_wnd_params_init(&wparams);
695 wparams.rect.p0.x = 0;
696 wparams.rect.p0.y = 0;
697 wparams.rect.p1.x = 100;
698 wparams.rect.p1.y = 100;
699 wparams.min_size.x = 2 * border_thickness + header_min_width;
700 wparams.min_size.y = 2 * border_thickness + header_height;
701
702 rc = display_window_create(win->display, &wparams, &window_cb,
703 (void *) win, &win->dwindow);
704 if (rc != EOK) {
705 display_close(win->display);
706 surface_destroy(win->surface);
707 free(win);
708 return NULL;
709 }
710
711 rc = display_window_get_gc(win->dwindow, &win->gc);
712 if (rc != EOK) {
713 display_window_destroy(win->dwindow);
714 display_close(win->display);
715 surface_destroy(win->surface);
716 free(win);
717 return NULL;
718 }
719
720 if (caption == NULL)
721 win->caption = NULL;
722 else
723 win->caption = str_dup(caption);
724
725 return win;
726}
727
728void window_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
729 sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
730{
731 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
732 if (event) {
733 link_initialize(&event->link);
734 event->type = ET_WINDOW_RESIZE;
735 event->data.resize.offset_x = offset_x;
736 event->data.resize.offset_y = offset_y;
737 event->data.resize.width = width;
738 event->data.resize.height = height;
739 event->data.resize.placement_flags = placement_flags;
740 prodcons_produce(&win->events, &event->link);
741 }
742}
743
744errno_t window_set_caption(window_t *win, const char *caption)
745{
746 char *cap;
747
748 if (caption == NULL) {
749 win->caption = NULL;
750 } else {
751 cap = str_dup(caption);
752 if (cap == NULL)
753 return ENOMEM;
754 free(win->caption);
755 win->caption = cap;
756 }
757
758 win->is_focused = false;
759 handle_refresh(win);
760
761 return EOK;
762}
763
764void window_refresh(window_t *win)
765{
766 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
767 if (event) {
768 link_initialize(&event->link);
769 event->type = ET_WINDOW_REFRESH;
770 prodcons_produce(&win->events, &event->link);
771 }
772}
773
774void window_damage(window_t *win)
775{
776 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
777 if (event) {
778 link_initialize(&event->link);
779 event->type = ET_WINDOW_DAMAGE;
780 prodcons_produce(&win->events, &event->link);
781 }
782}
783
784widget_t *window_root(window_t *win)
785{
786 return &win->root;
787}
788
789void window_exec(window_t *win)
790{
791 fid_t ev_fid = fibril_create(event_loop, win);
792 if (!ev_fid) {
793 return;
794 }
795 fibril_add_ready(ev_fid);
796}
797
798surface_t *window_claim(window_t *win)
799{
800 fibril_mutex_lock(&win->guard);
801 return win->surface;
802}
803
804void window_yield(window_t *win)
805{
806 fibril_mutex_unlock(&win->guard);
807}
808
809void window_close(window_t *win)
810{
811 window_event_t *event;
812
813 event = (window_event_t *) calloc(1, sizeof(window_event_t));
814 if (event == NULL)
815 return;
816
817 link_initialize(&event->link);
818 event->type = ET_WINDOW_CLOSE;
819 prodcons_produce(&win->events, &event->link);
820}
821
822static void window_close_event(void *arg)
823{
824 window_t *win = (window_t *) arg;
825
826 window_close(win);
827}
828
829static void window_focus_event(void *arg)
830{
831 window_t *win = (window_t *) arg;
832 window_event_t *event;
833
834 event = (window_event_t *) calloc(1, sizeof(window_event_t));
835 if (event == NULL)
836 return;
837
838 link_initialize(&event->link);
839 event->type = ET_WINDOW_FOCUS;
840 prodcons_produce(&win->events, &event->link);
841}
842
843static void window_kbd_event(void *arg, kbd_event_t *kevent)
844{
845 window_t *win = (window_t *) arg;
846 window_event_t *event;
847
848 event = (window_event_t *) calloc(1, sizeof(window_event_t));
849 if (event == NULL)
850 return;
851
852 link_initialize(&event->link);
853 event->type = ET_KEYBOARD_EVENT;
854 event->data.kbd = *kevent;
855 prodcons_produce(&win->events, &event->link);
856}
857
858static void window_pos_event(void *arg, pos_event_t *pevent)
859{
860 window_t *win = (window_t *) arg;
861 window_event_t *event;
862
863 event = (window_event_t *) calloc(1, sizeof(window_event_t));
864 if (event == NULL)
865 return;
866
867 link_initialize(&event->link);
868 event->type = ET_POSITION_EVENT;
869 event->data.pos = *pevent;
870 prodcons_produce(&win->events, &event->link);
871}
872
873static void window_resize_event(void *arg, gfx_rect_t *nrect)
874{
875 window_t *win = (window_t *) arg;
876 window_event_t *event;
877
878 event = (window_event_t *) calloc(1, sizeof(window_event_t));
879 if (event == NULL)
880 return;
881
882 link_initialize(&event->link);
883 event->type = ET_WINDOW_RESIZE;
884 event->data.resize.offset_x = nrect->p0.x;
885 event->data.resize.offset_y = nrect->p0.y;
886 event->data.resize.width = nrect->p1.x - nrect->p0.x;
887 event->data.resize.height = nrect->p1.y - nrect->p0.y;
888 event->data.resize.placement_flags = WINDOW_PLACEMENT_ANY;
889 prodcons_produce(&win->events, &event->link);
890}
891
892static void window_unfocus_event(void *arg)
893{
894 window_t *win = (window_t *) arg;
895 window_event_t *event;
896
897 event = (window_event_t *) calloc(1, sizeof(window_event_t));
898 if (event == NULL)
899 return;
900
901 link_initialize(&event->link);
902 event->type = ET_WINDOW_UNFOCUS;
903 prodcons_produce(&win->events, &event->link);
904}
905
906/** @}
907 */
Note: See TracBrowser for help on using the repository browser.