source: mainline/uspace/lib/gui/window.c@ 1e4a937

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

Add libdisplay method for initiating window resize

  • Property mode set to 100644
File size: 21.7 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;
69
70static pixel_t color_highlight = PIXEL(255, 255, 255, 255);
71static pixel_t color_shadow = PIXEL(255, 85, 85, 85);
72static pixel_t color_surface = PIXEL(255, 186, 186, 186);
73
74static pixel_t color_header_focus_highlight = PIXEL(255, 120, 145, 255);
75static pixel_t color_header_focus_shadow = PIXEL(255, 40, 48, 89);
76static pixel_t color_header_focus_surface = PIXEL(255, 88, 106, 196);
77
78static pixel_t color_header_unfocus_highlight = PIXEL(255, 16, 78, 126);
79static pixel_t color_header_unfocus_shadow = PIXEL(255, 5, 26, 42);
80static pixel_t color_header_unfocus_surface = PIXEL(255, 12, 57, 92);
81
82static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255);
83static pixel_t color_caption_unfocus = PIXEL(255, 207, 207, 207);
84
85static void window_close_event(void *);
86static void window_focus_event(void *);
87static void window_kbd_event(void *, kbd_event_t *);
88static void window_pos_event(void *, pos_event_t *);
89static void window_unfocus_event(void *);
90
91static display_wnd_cb_t window_cb = {
92 .close_event = window_close_event,
93 .focus_event = window_focus_event,
94 .kbd_event = window_kbd_event,
95 .pos_event = window_pos_event,
96 .unfocus_event = window_unfocus_event
97};
98
99static void paint_internal(widget_t *widget)
100{
101 surface_t *surface = window_claim(widget->window);
102 if (!surface)
103 window_yield(widget->window);
104
105 source_t source;
106 source_init(&source);
107
108 drawctx_t drawctx;
109 drawctx_init(&drawctx, surface);
110 drawctx_set_source(&drawctx, &source);
111
112 /* Window border outer bevel */
113
114 draw_bevel(&drawctx, &source, widget->vpos, widget->hpos,
115 widget->width, widget->height, color_highlight, color_shadow);
116
117 /* Window border surface */
118
119 source_set_color(&source, color_surface);
120 drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
121 widget->width - 2, 2);
122 drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
123 2, widget->height - 2);
124 drawctx_transfer(&drawctx, widget->hpos + 1,
125 widget->vpos + widget->height - 3, widget->width - 2, 2);
126 drawctx_transfer(&drawctx, widget->hpos + widget->width - 3,
127 widget->vpos + 1, 2, widget->height - 4);
128
129 /* Window border inner bevel */
130
131 draw_bevel(&drawctx, &source, widget->hpos + 3, widget->vpos + 3,
132 widget->width - 6, widget->height - 6, color_shadow,
133 color_highlight);
134
135 /* Header bevel */
136
137 sysarg_t header_hpos = widget->hpos + border_thickness;
138 sysarg_t header_vpos = widget->vpos + border_thickness;
139 sysarg_t header_width = widget->width - 2 * border_thickness -
140 close_thickness;
141
142 draw_bevel(&drawctx, &source, header_hpos, header_vpos,
143 header_width, header_height, widget->window->is_focused ?
144 color_header_focus_highlight : color_header_unfocus_highlight,
145 widget->window->is_focused ?
146 color_header_focus_shadow : color_header_unfocus_shadow);
147
148 /* Header surface */
149
150 source_set_color(&source, widget->window->is_focused ?
151 color_header_focus_surface : color_header_unfocus_surface);
152 drawctx_transfer(&drawctx, header_hpos + 1, header_vpos + 1,
153 header_width - 2, header_height - 2);
154
155 /* Close button bevel */
156
157 sysarg_t close_hpos = widget->hpos + widget->width -
158 border_thickness - close_thickness;
159 sysarg_t close_vpos = widget->vpos + border_thickness;
160
161 draw_bevel(&drawctx, &source, close_hpos, close_vpos,
162 close_thickness, close_thickness, color_highlight, color_shadow);
163
164 /* Close button surface */
165
166 source_set_color(&source, color_surface);
167 drawctx_transfer(&drawctx, close_hpos + 1, close_vpos + 1,
168 close_thickness - 2, close_thickness - 2);
169
170 /* Close button icon */
171
172 draw_icon_cross(surface, close_hpos + 3, close_vpos + 3,
173 color_highlight, color_shadow);
174
175 /* Window caption */
176
177 font_t *font;
178 errno_t rc = embedded_font_create(&font, 16);
179 if (rc != EOK) {
180 window_yield(widget->window);
181 return;
182 }
183
184 drawctx_set_font(&drawctx, font);
185 source_set_color(&source, widget->window->is_focused ?
186 color_caption_focus : color_caption_unfocus);
187
188 sysarg_t cpt_width;
189 sysarg_t cpt_height;
190 font_get_box(font, widget->window->caption, &cpt_width, &cpt_height);
191
192 bool draw_title =
193 (widget->width >= 2 * border_thickness + 2 * bevel_thickness +
194 close_thickness + cpt_width);
195 if (draw_title) {
196 sysarg_t cpt_x = ((widget->width - cpt_width) / 2) + widget->hpos;
197 sysarg_t cpt_y = ((header_height - cpt_height) / 2) +
198 widget->vpos + border_thickness;
199
200 if (widget->window->caption)
201 drawctx_print(&drawctx, widget->window->caption, cpt_x, cpt_y);
202 }
203
204 font_release(font);
205 window_yield(widget->window);
206}
207
208static void root_destroy(widget_t *widget)
209{
210 widget_deinit(widget);
211}
212
213static void root_reconfigure(widget_t *widget)
214{
215 if (widget->window->is_decorated) {
216 list_foreach(widget->children, link, widget_t, child) {
217 child->rearrange(child,
218 widget->hpos + border_thickness,
219 widget->vpos + border_thickness + header_height,
220 widget->width - 2 * border_thickness,
221 widget->height - 2 * border_thickness - header_height);
222 }
223 } else {
224 list_foreach(widget->children, link, widget_t, child) {
225 child->rearrange(child, widget->hpos, widget->vpos,
226 widget->width, widget->height);
227 }
228 }
229}
230
231static void root_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
232 sysarg_t width, sysarg_t height)
233{
234 widget_modify(widget, hpos, vpos, width, height);
235 if (widget->window->is_decorated) {
236 paint_internal(widget);
237 list_foreach(widget->children, link, widget_t, child) {
238 child->rearrange(child,
239 hpos + border_thickness,
240 vpos + border_thickness + header_height,
241 width - 2 * border_thickness,
242 height - 2 * border_thickness - header_height);
243 }
244 } else {
245 list_foreach(widget->children, link, widget_t, child) {
246 child->rearrange(child, hpos, vpos, width, height);
247 }
248 }
249}
250
251static void root_repaint(widget_t *widget)
252{
253 if (widget->window->is_decorated) {
254 paint_internal(widget);
255 }
256 list_foreach(widget->children, link, widget_t, child) {
257 child->repaint(child);
258 }
259 if (widget->window->is_decorated) {
260 window_damage(widget->window);
261 }
262}
263
264static void root_handle_keyboard_event(widget_t *widget, kbd_event_t event)
265{
266 if (!list_empty(&widget->children)) {
267 widget_t *child = (widget_t *) list_first(&widget->children);
268 child->handle_keyboard_event(child, event);
269 }
270}
271
272static void root_handle_position_event(widget_t *widget, pos_event_t event)
273{
274 gfx_coord2_t pos;
275
276 if (widget->window->is_decorated) {
277 sysarg_t width = widget->width;
278 sysarg_t height = widget->height;
279
280 bool btn_left = (event.btn_num == 1) && (event.type == POS_PRESS);
281 bool btn_right = (event.btn_num == 2) && (event.type == POS_PRESS);
282 bool allowed_button = btn_left || btn_right;
283
284 bool left = (event.hpos < border_thickness);
285 bool right = (event.hpos >= width - border_thickness);
286 bool top = (event.vpos < border_thickness);
287 bool bottom = (event.vpos >= height - border_thickness);
288 bool header = (event.hpos >= border_thickness) &&
289 (event.hpos < width - border_thickness) &&
290 (event.vpos >= border_thickness) &&
291 (event.vpos < border_thickness + header_height);
292 bool close = (header) &&
293 (event.hpos >= width - border_thickness - close_thickness);
294
295 pos.x = event.hpos;
296 pos.y = event.vpos;
297
298 if (top && left && btn_left) {
299 (void) display_window_resize_req(widget->window->dwindow,
300 display_wr_top_left, &pos);
301 } else if (bottom && left && btn_left) {
302 (void) display_window_resize_req(widget->window->dwindow,
303 display_wr_bottom_left, &pos);
304 } else if (bottom && right && btn_left) {
305 (void) display_window_resize_req(widget->window->dwindow,
306 display_wr_bottom_right, &pos);
307 } else if (top && right && allowed_button) {
308 (void) display_window_resize_req(widget->window->dwindow,
309 display_wr_top_right, &pos);
310 } else if (top && btn_left) {
311 (void) display_window_resize_req(widget->window->dwindow,
312 display_wr_top, &pos);
313 } else if (left && btn_left) {
314 (void) display_window_resize_req(widget->window->dwindow,
315 display_wr_bottom, &pos);
316 } else if (bottom && btn_left) {
317 (void) display_window_resize_req(widget->window->dwindow,
318 display_wr_bottom, &pos);
319 } else if (right && btn_left) {
320 (void) display_window_resize_req(widget->window->dwindow,
321 display_wr_bottom, &pos);
322 } else if (close && btn_left) {
323 window_close(widget->window);
324 } else if (header && btn_left) {
325 (void) display_window_move_req(widget->window->dwindow,
326 &pos);
327 } else {
328 list_foreach(widget->children, link, widget_t, child) {
329 child->handle_position_event(child, event);
330 }
331 }
332 } else {
333 list_foreach(widget->children, link, widget_t, child) {
334 child->handle_position_event(child, event);
335 }
336 }
337}
338
339static void deliver_keyboard_event(window_t *win, kbd_event_t event)
340{
341 if (win->focus) {
342 win->focus->handle_keyboard_event(win->focus, event);
343 } else {
344 win->root.handle_keyboard_event(&win->root, event);
345 }
346}
347
348static void deliver_position_event(window_t *win, pos_event_t event)
349{
350 if (win->grab) {
351 win->grab->handle_position_event(win->grab, event);
352 } else {
353 win->root.handle_position_event(&win->root, event);
354 }
355}
356
357static void handle_signal_event(window_t *win, signal_event_t event)
358{
359 widget_t *widget = (widget_t *) event.object;
360 slot_t slot = (slot_t) event.slot;
361 void *data = (void *) event.argument;
362
363 slot(widget, data);
364
365 free(data);
366}
367
368static void handle_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
369 sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
370{
371 gfx_bitmap_params_t params;
372 gfx_bitmap_alloc_t alloc;
373 gfx_bitmap_t *new_bitmap = NULL;
374 gfx_coord2_t offs;
375 gfx_rect_t nrect;
376 errno_t rc;
377
378 if (width < 2 * border_thickness + header_min_width) {
379 //win_damage(win->osess, 0, 0, 0, 0);
380 return;
381 }
382
383 if (height < 2 * border_thickness + header_height) {
384 //win_damage(win->osess, 0, 0, 0, 0);
385 return;
386 }
387
388 /* Allocate resources for new surface. */
389 surface_t *new_surface = surface_create(width, height, NULL,
390 SURFACE_FLAG_SHARED);
391 if (!new_surface)
392 return;
393
394 gfx_bitmap_params_init(&params);
395 params.rect.p0.x = 0;
396 params.rect.p0.y = 0;
397 params.rect.p1.x = width;
398 params.rect.p1.y = height;
399
400 alloc.pitch = width * sizeof(uint32_t);
401 alloc.off0 = 0;
402 alloc.pixels = surface_direct_access(new_surface);
403
404 rc = gfx_bitmap_create(win->gc, &params, &alloc, &new_bitmap);
405 if (rc != EOK) {
406 surface_destroy(new_surface);
407 return;
408 }
409
410 /* Switch new and old surface. */
411 fibril_mutex_lock(&win->guard);
412 surface_t *old_surface = win->surface;
413 gfx_bitmap_t *old_bitmap = win->bitmap;
414 win->surface = new_surface;
415 win->bitmap = new_bitmap;
416 fibril_mutex_unlock(&win->guard);
417
418 /*
419 * Let all widgets in the tree alter their position and size.
420 * Widgets might also paint themselves onto the new surface.
421 */
422 win->root.rearrange(&win->root, 0, 0, width, height);
423
424 fibril_mutex_lock(&win->guard);
425 surface_reset_damaged_region(win->surface);
426 fibril_mutex_unlock(&win->guard);
427
428 /* Resize the display window. */
429 offs.x = offset_x;
430 offs.y = offset_y;
431 nrect.p0.x = 0;
432 nrect.p0.y = 0;
433 nrect.p1.x = width;
434 nrect.p1.y = height;
435
436 rc = display_window_resize(win->dwindow, &offs, &nrect);
437 if (rc != EOK) {
438 /* Rollback to old surface. Reverse all changes. */
439
440 sysarg_t old_width = 0;
441 sysarg_t old_height = 0;
442 if (old_surface)
443 surface_get_resolution(old_surface, &old_width, &old_height);
444
445 fibril_mutex_lock(&win->guard);
446 new_surface = win->surface;
447 win->surface = old_surface;
448 win->bitmap = old_bitmap;
449 fibril_mutex_unlock(&win->guard);
450
451 win->root.rearrange(&win->root, 0, 0, old_width, old_height);
452
453 if (win->surface) {
454 fibril_mutex_lock(&win->guard);
455 surface_reset_damaged_region(win->surface);
456 fibril_mutex_unlock(&win->guard);
457 }
458
459 surface_destroy(new_surface);
460 } else {
461 if (old_bitmap != NULL)
462 gfx_bitmap_destroy(old_bitmap);
463 /* Deallocate old surface. */
464 if (old_surface)
465 surface_destroy(old_surface);
466
467 (void) gfx_bitmap_render(win->bitmap, NULL, NULL);
468 }
469}
470
471static void handle_refresh(window_t *win)
472{
473 win->root.repaint(&win->root);
474}
475
476static void handle_damage(window_t *win)
477{
478 sysarg_t x, y, width, height;
479 gfx_rect_t rect;
480 fibril_mutex_lock(&win->guard);
481 surface_get_damaged_region(win->surface, &x, &y, &width, &height);
482 surface_reset_damaged_region(win->surface);
483 fibril_mutex_unlock(&win->guard);
484
485 if (width > 0 && height > 0) {
486 /* Notify compositor. */
487 //win_damage(win->osess, x, y, width, height);
488
489 rect.p0.x = x;
490 rect.p0.y = y;
491 rect.p1.x = x + width;
492 rect.p1.y = y + height;
493
494 if (win->bitmap != NULL)
495 (void) gfx_bitmap_render(win->bitmap, &rect, NULL);
496 }
497}
498
499static void destroy_children(widget_t *widget)
500{
501 /* Recursively destroy widget tree in bottom-top order. */
502 while (!list_empty(&widget->children)) {
503 widget_t *child =
504 list_get_instance(list_first(&widget->children), widget_t, link);
505 destroy_children(child);
506 child->destroy(child);
507 }
508}
509
510static void handle_close(window_t *win)
511{
512 destroy_children(&win->root);
513 win->root.destroy(&win->root);
514 win->grab = NULL;
515 win->focus = NULL;
516
517 display_window_destroy(win->dwindow);
518 display_close(win->display);
519
520 while (!list_empty(&win->events.list)) {
521 window_event_t *event = (window_event_t *) list_first(&win->events.list);
522 list_remove(&event->link);
523 free(event);
524 }
525
526 if (win->surface) {
527 surface_destroy(win->surface);
528 }
529
530 free(win->caption);
531
532 free(win);
533}
534
535/* Window event loop. Runs in own dedicated fibril. */
536static errno_t event_loop(void *arg)
537{
538 bool is_main = false;
539 bool terminate = false;
540 window_t *win = (window_t *) arg;
541
542 while (true) {
543 window_event_t *event = (window_event_t *) prodcons_consume(&win->events);
544
545 switch (event->type) {
546 case ET_KEYBOARD_EVENT:
547 deliver_keyboard_event(win, event->data.kbd);
548 break;
549 case ET_POSITION_EVENT:
550 deliver_position_event(win, event->data.pos);
551 break;
552 case ET_SIGNAL_EVENT:
553 handle_signal_event(win, event->data.signal);
554 break;
555 case ET_WINDOW_RESIZE:
556 handle_resize(win, event->data.resize.offset_x,
557 event->data.resize.offset_y, event->data.resize.width,
558 event->data.resize.height, event->data.resize.placement_flags);
559 break;
560 case ET_WINDOW_FOCUS:
561 if (!win->is_focused) {
562 win->is_focused = true;
563 handle_refresh(win);
564 }
565 break;
566 case ET_WINDOW_UNFOCUS:
567 if (win->is_focused) {
568 win->is_focused = false;
569 handle_refresh(win);
570 }
571 break;
572 case ET_WINDOW_REFRESH:
573 handle_refresh(win);
574 break;
575 case ET_WINDOW_DAMAGE:
576 handle_damage(win);
577 break;
578 case ET_WINDOW_CLOSE:
579 is_main = win->is_main;
580 handle_close(win);
581 terminate = true;
582 break;
583 default:
584 break;
585 }
586
587 free(event);
588 if (terminate) {
589 break;
590 }
591 }
592
593 if (is_main) {
594 exit(0); /* Terminate whole task. */
595 }
596 return 0;
597}
598
599window_t *window_open(const char *winreg, const void *data,
600 window_flags_t flags, const char *caption)
601{
602 display_wnd_params_t wparams;
603
604 window_t *win = (window_t *) calloc(1, sizeof(window_t));
605 if (!win)
606 return NULL;
607
608 win->is_main = flags & WINDOW_MAIN;
609 win->is_decorated = flags & WINDOW_DECORATED;
610 win->is_focused = true;
611 prodcons_initialize(&win->events);
612 fibril_mutex_initialize(&win->guard);
613
614 widget_init(&win->root, NULL, data);
615 win->root.window = win;
616 win->root.destroy = root_destroy;
617 win->root.reconfigure = root_reconfigure;
618 win->root.rearrange = root_rearrange;
619 win->root.repaint = root_repaint;
620 win->root.handle_keyboard_event = root_handle_keyboard_event;
621 win->root.handle_position_event = root_handle_position_event;
622 win->grab = NULL;
623 win->focus = NULL;
624
625 /* Allocate resources for new surface. */
626 win->surface = surface_create(100, 100, NULL, SURFACE_FLAG_SHARED);
627 if (win->surface == NULL) {
628 free(win);
629 return NULL;
630 }
631
632 errno_t rc = display_open(winreg, &win->display);
633 if (rc != EOK) {
634 surface_destroy(win->surface);
635 free(win);
636 return NULL;
637 }
638
639 /* Window dimensions are not know at this time */
640 display_wnd_params_init(&wparams);
641 wparams.rect.p0.x = 0;
642 wparams.rect.p0.y = 0;
643 wparams.rect.p1.x = 100;
644 wparams.rect.p1.y = 100;
645
646 rc = display_window_create(win->display, &wparams, &window_cb,
647 (void *) win, &win->dwindow);
648 if (rc != EOK) {
649 display_close(win->display);
650 surface_destroy(win->surface);
651 free(win);
652 return NULL;
653 }
654
655 rc = display_window_get_gc(win->dwindow, &win->gc);
656 if (rc != EOK) {
657 display_window_destroy(win->dwindow);
658 display_close(win->display);
659 surface_destroy(win->surface);
660 free(win);
661 return NULL;
662 }
663
664 if (caption == NULL)
665 win->caption = NULL;
666 else
667 win->caption = str_dup(caption);
668
669 return win;
670}
671
672void window_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
673 sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
674{
675 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
676 if (event) {
677 link_initialize(&event->link);
678 event->type = ET_WINDOW_RESIZE;
679 event->data.resize.offset_x = offset_x;
680 event->data.resize.offset_y = offset_y;
681 event->data.resize.width = width;
682 event->data.resize.height = height;
683 event->data.resize.placement_flags = placement_flags;
684 prodcons_produce(&win->events, &event->link);
685 }
686}
687
688errno_t window_set_caption(window_t *win, const char *caption)
689{
690 char *cap;
691
692 if (caption == NULL) {
693 win->caption = NULL;
694 } else {
695 cap = str_dup(caption);
696 if (cap == NULL)
697 return ENOMEM;
698 free(win->caption);
699 win->caption = cap;
700 }
701
702 win->is_focused = false;
703 handle_refresh(win);
704
705 return EOK;
706}
707
708void window_refresh(window_t *win)
709{
710 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
711 if (event) {
712 link_initialize(&event->link);
713 event->type = ET_WINDOW_REFRESH;
714 prodcons_produce(&win->events, &event->link);
715 }
716}
717
718void window_damage(window_t *win)
719{
720 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
721 if (event) {
722 link_initialize(&event->link);
723 event->type = ET_WINDOW_DAMAGE;
724 prodcons_produce(&win->events, &event->link);
725 }
726}
727
728widget_t *window_root(window_t *win)
729{
730 return &win->root;
731}
732
733void window_exec(window_t *win)
734{
735 fid_t ev_fid = fibril_create(event_loop, win);
736 if (!ev_fid) {
737 return;
738 }
739 fibril_add_ready(ev_fid);
740}
741
742surface_t *window_claim(window_t *win)
743{
744 fibril_mutex_lock(&win->guard);
745 return win->surface;
746}
747
748void window_yield(window_t *win)
749{
750 fibril_mutex_unlock(&win->guard);
751}
752
753void window_close(window_t *win)
754{
755 window_event_t *event;
756
757 event = (window_event_t *) calloc(1, sizeof(window_event_t));
758 if (event == NULL)
759 return;
760
761 link_initialize(&event->link);
762 event->type = ET_WINDOW_CLOSE;
763 prodcons_produce(&win->events, &event->link);
764}
765
766static void window_close_event(void *arg)
767{
768 window_t *win = (window_t *) arg;
769
770 window_close(win);
771}
772
773static void window_focus_event(void *arg)
774{
775 window_t *win = (window_t *) arg;
776 window_event_t *event;
777
778 event = (window_event_t *) calloc(1, sizeof(window_event_t));
779 if (event == NULL)
780 return;
781
782 link_initialize(&event->link);
783 event->type = ET_WINDOW_FOCUS;
784 prodcons_produce(&win->events, &event->link);
785}
786
787static void window_kbd_event(void *arg, kbd_event_t *kevent)
788{
789 window_t *win = (window_t *) arg;
790 window_event_t *event;
791
792 event = (window_event_t *) calloc(1, sizeof(window_event_t));
793 if (event == NULL)
794 return;
795
796 link_initialize(&event->link);
797 event->type = ET_KEYBOARD_EVENT;
798 event->data.kbd = *kevent;
799 prodcons_produce(&win->events, &event->link);
800}
801
802static void window_pos_event(void *arg, pos_event_t *pevent)
803{
804 window_t *win = (window_t *) arg;
805 window_event_t *event;
806
807 event = (window_event_t *) calloc(1, sizeof(window_event_t));
808 if (event == NULL)
809 return;
810
811 link_initialize(&event->link);
812 event->type = ET_POSITION_EVENT;
813 event->data.pos = *pevent;
814 prodcons_produce(&win->events, &event->link);
815}
816
817static void window_unfocus_event(void *arg)
818{
819 window_t *win = (window_t *) arg;
820 window_event_t *event;
821
822 event = (window_event_t *) calloc(1, sizeof(window_event_t));
823 if (event == NULL)
824 return;
825
826 link_initialize(&event->link);
827 event->type = ET_WINDOW_UNFOCUS;
828 prodcons_produce(&win->events, &event->link);
829}
830
831/** @}
832 */
Note: See TracBrowser for help on using the repository browser.