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

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

Move windows by dragging decoration

Or dragging anywhere with button 2. Need to add Ctrl/Alt/Shift state
to pos_event_t and change the latter to Alt-drag/Shift-drag.

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