source: mainline/uspace/lib/gui/window.c@ 7bb45e3

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

Future-proof gfx_bitmap_params_t with initialization function

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