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

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

cstyle (no change in functionality)

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