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

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

Propagate position event to display clients

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