source: mainline/uspace/lib/gui/window.c@ 56dcf53

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

Avoid display artifacts when creating windows

Now the window only becomes noticeable when it's in the right place
and has the right size (it has 1x1 pixels before that). Still,
it first appears black. Ideally we'd only make if visible after
the client has painted the contents.

  • Property mode set to 100644
File size: 23.7 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;
[ef20a91]69static sysarg_t corner_size = 24;
[56dcf53]70static sysarg_t window_initial_size = 1;
[6d5e378]71
[296e124e]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);
[6d5e378]75
[296e124e]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);
[6d5e378]79
[296e124e]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);
[6d5e378]83
[296e124e]84static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255);
85static pixel_t color_caption_unfocus = PIXEL(255, 207, 207, 207);
86
[338d0935]87static void window_close_event(void *);
[b0a94854]88static void window_focus_event(void *);
[287688f2]89static void window_kbd_event(void *, kbd_event_t *);
[f7fb2b21]90static void window_pos_event(void *, pos_event_t *);
[e022819]91static void window_resize_event(void *, gfx_rect_t *);
[b0a94854]92static void window_unfocus_event(void *);
[287688f2]93
94static display_wnd_cb_t window_cb = {
[338d0935]95 .close_event = window_close_event,
[b0a94854]96 .focus_event = window_focus_event,
[f7fb2b21]97 .kbd_event = window_kbd_event,
[b0a94854]98 .pos_event = window_pos_event,
[e022819]99 .resize_event = window_resize_event,
[b0a94854]100 .unfocus_event = window_unfocus_event
[287688f2]101};
102
[9242ad9]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
[296e124e]111static void paint_internal(widget_t *widget)
112{
113 surface_t *surface = window_claim(widget->window);
114 if (!surface)
115 window_yield(widget->window);
[a35b458]116
[296e124e]117 source_t source;
[6d5e378]118 source_init(&source);
[a35b458]119
[296e124e]120 drawctx_t drawctx;
[6d5e378]121 drawctx_init(&drawctx, surface);
122 drawctx_set_source(&drawctx, &source);
[a35b458]123
[296e124e]124 /* Window border outer bevel */
[a35b458]125
[296e124e]126 draw_bevel(&drawctx, &source, widget->vpos, widget->hpos,
127 widget->width, widget->height, color_highlight, color_shadow);
[a35b458]128
[296e124e]129 /* Window border surface */
[a35b458]130
[296e124e]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);
[a35b458]140
[296e124e]141 /* Window border inner bevel */
[a35b458]142
[296e124e]143 draw_bevel(&drawctx, &source, widget->hpos + 3, widget->vpos + 3,
144 widget->width - 6, widget->height - 6, color_shadow,
145 color_highlight);
[a35b458]146
[296e124e]147 /* Header bevel */
[a35b458]148
[296e124e]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;
[a35b458]153
[296e124e]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);
[a35b458]159
[296e124e]160 /* Header surface */
[a35b458]161
[296e124e]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);
[a35b458]166
[296e124e]167 /* Close button bevel */
[a35b458]168
[296e124e]169 sysarg_t close_hpos = widget->hpos + widget->width -
170 border_thickness - close_thickness;
171 sysarg_t close_vpos = widget->vpos + border_thickness;
[a35b458]172
[296e124e]173 draw_bevel(&drawctx, &source, close_hpos, close_vpos,
174 close_thickness, close_thickness, color_highlight, color_shadow);
[a35b458]175
[296e124e]176 /* Close button surface */
[a35b458]177
[296e124e]178 source_set_color(&source, color_surface);
179 drawctx_transfer(&drawctx, close_hpos + 1, close_vpos + 1,
180 close_thickness - 2, close_thickness - 2);
[a35b458]181
[296e124e]182 /* Close button icon */
[a35b458]183
[61b5b73d]184 draw_icon_cross(surface, close_hpos + 3, close_vpos + 3,
185 color_highlight, color_shadow);
[a35b458]186
[296e124e]187 /* Window caption */
[a35b458]188
[2cc1ec0]189 font_t *font;
[b7fd2a0]190 errno_t rc = embedded_font_create(&font, 16);
[2cc1ec0]191 if (rc != EOK) {
192 window_yield(widget->window);
193 return;
194 }
[a35b458]195
[2cc1ec0]196 drawctx_set_font(&drawctx, font);
[296e124e]197 source_set_color(&source, widget->window->is_focused ?
198 color_caption_focus : color_caption_unfocus);
[a35b458]199
[6d5e378]200 sysarg_t cpt_width;
201 sysarg_t cpt_height;
[2cc1ec0]202 font_get_box(font, widget->window->caption, &cpt_width, &cpt_height);
[a35b458]203
[296e124e]204 bool draw_title =
205 (widget->width >= 2 * border_thickness + 2 * bevel_thickness +
206 close_thickness + cpt_width);
[6d5e378]207 if (draw_title) {
[296e124e]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;
[a35b458]211
[296e124e]212 if (widget->window->caption)
213 drawctx_print(&drawctx, widget->window->caption, cpt_x, cpt_y);
[6d5e378]214 }
[a35b458]215
[2cc1ec0]216 font_release(font);
[296e124e]217 window_yield(widget->window);
[6d5e378]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) {
[feeac0d]228 list_foreach(widget->children, link, widget_t, child) {
[296e124e]229 child->rearrange(child,
[6d5e378]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 {
[feeac0d]236 list_foreach(widget->children, link, widget_t, child) {
[6d5e378]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);
[feeac0d]249 list_foreach(widget->children, link, widget_t, child) {
[1b20da0]250 child->rearrange(child,
[6d5e378]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 {
[feeac0d]257 list_foreach(widget->children, link, widget_t, child) {
[6d5e378]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 }
[feeac0d]268 list_foreach(widget->children, link, widget_t, child) {
[6d5e378]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{
[a2e104e]286 gfx_coord2_t pos;
287
[6d5e378]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);
[ef20a91]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
[6d5e378]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);
[296e124e]309 bool close = (header) &&
310 (event.hpos >= width - border_thickness - close_thickness);
[6d5e378]311
[66a408f7]312 bool isresize = widget->window->is_resizable;
[ef20a91]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 {
[9242ad9]339 (void) set_cursor(widget->window, dcurs_arrow);
[ef20a91]340 }
[9242ad9]341
[1e4a937]342 pos.x = event.hpos;
343 pos.y = event.vpos;
344
[ef20a91]345 if (isresize && btn_left) {
346 (void) display_window_resize_req(
347 widget->window->dwindow, rsztype, &pos);
[6d5e378]348 } else if (close && btn_left) {
[338d0935]349 window_close(widget->window);
[6d5e378]350 } else if (header && btn_left) {
[a2e104e]351 (void) display_window_move_req(widget->window->dwindow,
352 &pos);
[6d5e378]353 } else {
[feeac0d]354 list_foreach(widget->children, link, widget_t, child) {
[6d5e378]355 child->handle_position_event(child, event);
356 }
357 }
358 } else {
[feeac0d]359 list_foreach(widget->children, link, widget_t, child) {
[6d5e378]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
[62fbb7e]383static void handle_signal_event(window_t *win, signal_event_t event)
[6d5e378]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
[62fbb7e]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)
[6d5e378]396{
[4645b2c]397 gfx_bitmap_params_t params;
398 gfx_bitmap_alloc_t alloc;
[3275736]399 gfx_bitmap_t *new_bitmap = NULL;
[0e6e77f]400 gfx_coord2_t offs;
[0680854]401 gfx_coord2_t dpos;
402 display_info_t dinfo;
403 gfx_rect_t drect;
[0e6e77f]404 gfx_rect_t nrect;
[3275736]405 errno_t rc;
[4645b2c]406
[6d5e378]407 if (width < 2 * border_thickness + header_min_width) {
[4645b2c]408 //win_damage(win->osess, 0, 0, 0, 0);
[6d5e378]409 return;
410 }
[a35b458]411
[6d5e378]412 if (height < 2 * border_thickness + header_height) {
[4645b2c]413 //win_damage(win->osess, 0, 0, 0, 0);
[6d5e378]414 return;
415 }
[a35b458]416
[afcf704]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
[56dcf53]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
[afcf704]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);
[56dcf53]470 if (rc != EOK) {
471 fibril_mutex_unlock(&win->guard);
[6d5e378]472 return;
[56dcf53]473 }
[a35b458]474
[a8eed5f]475 gfx_bitmap_params_init(&params);
[afcf704]476#ifndef CONFIG_WIN_DOUBLE_BUF
477 params.flags = bmpf_direct_output;
478#else
479 params.flags = 0;
480#endif
[4645b2c]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
[afcf704]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 }
[4645b2c]498
[afcf704]499 rc = gfx_bitmap_get_alloc(new_bitmap, &alloc);
[4645b2c]500 if (rc != EOK) {
[afcf704]501 fibril_mutex_unlock(&win->guard);
[4645b2c]502 return;
503 }
504
[afcf704]505 /* Allocate new surface. */
[c45d8696]506 surface_t *new_surface = surface_create(width, height, alloc.pixels,
507 SURFACE_FLAG_SHARED);
[afcf704]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. */
[6d5e378]515 win->surface = new_surface;
[4645b2c]516 win->bitmap = new_bitmap;
[6d5e378]517 fibril_mutex_unlock(&win->guard);
[a35b458]518
[62fbb7e]519 /*
520 * Let all widgets in the tree alter their position and size.
521 * Widgets might also paint themselves onto the new surface.
522 */
[6d5e378]523 win->root.rearrange(&win->root, 0, 0, width, height);
[a35b458]524
[6d5e378]525 fibril_mutex_lock(&win->guard);
526 surface_reset_damaged_region(win->surface);
527 fibril_mutex_unlock(&win->guard);
[a35b458]528
[0680854]529 (void) gfx_bitmap_render(win->bitmap, NULL, NULL);
[6d5e378]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;
[4645b2c]540 gfx_rect_t rect;
[6d5e378]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) {
[4645b2c]547 rect.p0.x = x;
548 rect.p0.y = y;
549 rect.p1.x = x + width;
550 rect.p1.y = y + height;
551
[3275736]552 if (win->bitmap != NULL)
553 (void) gfx_bitmap_render(win->bitmap, &rect, NULL);
[6d5e378]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
[94f3747]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
[4645b2c]583 display_window_destroy(win->dwindow);
584 display_close(win->display);
[6d5e378]585
586 while (!list_empty(&win->events.list)) {
[21eeb653]587 window_event_t *event = (window_event_t *) list_first(&win->events.list);
588 list_remove(&event->link);
589 free(event);
[6d5e378]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. */
[b7fd2a0]602static errno_t event_loop(void *arg)
[6d5e378]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:
[62fbb7e]619 handle_signal_event(win, event->data.signal);
[6d5e378]620 break;
621 case ET_WINDOW_RESIZE:
[62fbb7e]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);
[6d5e378]625 break;
[290a0f0]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;
[6d5e378]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
[10cb47e]665window_t *window_open(const char *winreg, const void *data,
666 window_flags_t flags, const char *caption)
[6d5e378]667{
[0e6e77f]668 display_wnd_params_t wparams;
669
[3275736]670 window_t *win = (window_t *) calloc(1, sizeof(window_t));
[ba02baa]671 if (!win)
[6d5e378]672 return NULL;
[a35b458]673
[2c7fdaa]674 win->is_main = flags & WINDOW_MAIN;
675 win->is_decorated = flags & WINDOW_DECORATED;
[66a408f7]676 win->is_resizable = flags & WINDOW_RESIZEABLE;
[290a0f0]677 win->is_focused = true;
[6d5e378]678 prodcons_initialize(&win->events);
679 fibril_mutex_initialize(&win->guard);
[a35b458]680
[10cb47e]681 widget_init(&win->root, NULL, data);
[6d5e378]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;
[9242ad9]691 win->cursor = dcurs_arrow;
[0e6e77f]692
693 /* Allocate resources for new surface. */
[56dcf53]694 win->surface = surface_create( window_initial_size,
695 window_initial_size, NULL, SURFACE_FLAG_SHARED);
[0e6e77f]696 if (win->surface == NULL) {
697 free(win);
698 return NULL;
699 }
[a35b458]700
[4645b2c]701 errno_t rc = display_open(winreg, &win->display);
[6d5e378]702 if (rc != EOK) {
[0e6e77f]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;
[56dcf53]712 wparams.rect.p1.x = window_initial_size;
713 wparams.rect.p1.y = window_initial_size;
[9b502dd]714 wparams.min_size.x = 2 * border_thickness + header_min_width;
715 wparams.min_size.y = 2 * border_thickness + header_height;
[0e6e77f]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);
[6d5e378]731 free(win);
732 return NULL;
733 }
[a35b458]734
[ba02baa]735 if (caption == NULL)
[6d5e378]736 win->caption = NULL;
[ba02baa]737 else
[6d5e378]738 win->caption = str_dup(caption);
[a35b458]739
[6d5e378]740 return win;
741}
742
[62fbb7e]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)
[6d5e378]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;
[62fbb7e]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;
[6d5e378]755 prodcons_produce(&win->events, &event->link);
756 }
757}
758
[b7fd2a0]759errno_t window_set_caption(window_t *win, const char *caption)
[78188e5]760{
761 char *cap;
[a35b458]762
[78188e5]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 }
[a35b458]772
[78188e5]773 win->is_focused = false;
774 handle_refresh(win);
[a35b458]775
[78188e5]776 return EOK;
777}
778
[6d5e378]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);
[b43edabe]807 if (!ev_fid) {
[6d5e378]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{
[338d0935]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);
[6d5e378]842}
843
[b0a94854]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
[287688f2]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
[f7fb2b21]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
[e022819]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
[66a408f7]893 if (!win->is_resizable)
894 return;
895
[e022819]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
[b0a94854]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
[6d5e378]924/** @}
925 */
Note: See TracBrowser for help on using the repository browser.