source: mainline/uspace/lib/gui/window.c@ 36f0738

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

Prefer to get memory allocation functions through the standard stdlib header.

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