source: mainline/uspace/lib/gui/window.c@ 6feccae

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

Remove compositor, libgraph

Libgraph is the old display driver protocol library (replaced by libddev).
We need to keep libdraw/libsoftrend for now as they are required by libgui.

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