source: mainline/uspace/lib/gui/window.c@ 2cc1ec0

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2cc1ec0 was 2cc1ec0, checked in by Martin Sucha <sucha14@…>, 11 years ago

Refactor drawing of fonts into multiple layers.

This will need further work to split glyph resolution
process to separate functions in order to support ligatures,
addition of kerning support, separate text layout functions,
etc.

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