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

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

Fix cstyle

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