source: mainline/uspace/lib/gui/window.c@ 9242ad9

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

Switch to double-arrow cursors when pointer is above resize areas

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