source: mainline/uspace/srv/hid/display/window.c@ a65b0c8

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

Preview window with a non-filled rectangle

  • Property mode set to 100644
File size: 19.5 KB
RevLine 
[c8cf261]1/*
2 * Copyright (c) 2019 Jiri Svoboda
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 display
30 * @{
31 */
32/**
[4d8002d]33 * @file Display server window
[c8cf261]34 */
35
[0008c0f]36#include <gfx/bitmap.h>
[c8cf261]37#include <gfx/color.h>
[0008c0f]38#include <gfx/coord.h>
[c8cf261]39#include <gfx/context.h>
40#include <gfx/render.h>
41#include <io/log.h>
[946a666]42#include <io/pixelmap.h>
[9b502dd]43#include <macros.h>
[dbef30f]44#include <memgfx/memgc.h>
[c8cf261]45#include <stdlib.h>
[b3c185b6]46#include "client.h"
[6af4b4f]47#include "display.h"
[9901f267]48#include "seat.h"
[6af4b4f]49#include "window.h"
[c8cf261]50
[dbef30f]51static void ds_window_update_cb(void *, gfx_rect_t *);
[6301a24f]52static void ds_window_get_preview_rect(ds_window_t *, gfx_rect_t *);
[0008c0f]53
[6af4b4f]54/** Create window.
[c8cf261]55 *
56 * Create graphics context for rendering into a window.
57 *
[8e9781f]58 * @param client Client owning the window
[3434233]59 * @param params Window parameters
[c8cf261]60 * @param rgc Place to store pointer to new GC.
61 *
62 * @return EOK on success or an error code
63 */
[3434233]64errno_t ds_window_create(ds_client_t *client, display_wnd_params_t *params,
65 ds_window_t **rgc)
[c8cf261]66{
[6af4b4f]67 ds_window_t *wnd = NULL;
[946a666]68 gfx_context_t *dgc;
69 gfx_coord2_t dims;
70 gfx_bitmap_params_t bparams;
71 gfx_bitmap_alloc_t alloc;
[c8cf261]72 errno_t rc;
73
[6af4b4f]74 wnd = calloc(1, sizeof(ds_window_t));
75 if (wnd == NULL) {
[c8cf261]76 rc = ENOMEM;
77 goto error;
78 }
79
[b3c185b6]80 ds_client_add_window(client, wnd);
[fd777a2]81 ds_display_add_window(client->display, wnd);
[6af4b4f]82
[a8eed5f]83 gfx_bitmap_params_init(&bparams);
[946a666]84 bparams.rect = params->rect;
85
86 dgc = ds_display_get_gc(wnd->display); // XXX
87 if (dgc != NULL) {
88 rc = gfx_bitmap_create(dgc, &bparams, NULL, &wnd->bitmap);
89 if (rc != EOK)
90 goto error;
91
92 rc = gfx_bitmap_get_alloc(wnd->bitmap, &alloc);
93 if (rc != EOK)
94 goto error;
95
[0e6e77f]96 gfx_rect_dims(&params->rect, &dims);
[946a666]97 wnd->pixelmap.width = dims.x;
98 wnd->pixelmap.height = dims.y;
99 wnd->pixelmap.data = alloc.pixels;
[dbef30f]100 } else {
101 /* This is just for unit tests */
102 gfx_rect_dims(&params->rect, &dims);
103 alloc.pitch = dims.x * sizeof(uint32_t);
104 alloc.off0 = 0;
105 alloc.pixels = calloc(1, alloc.pitch * dims.y);
[946a666]106 }
107
[dbef30f]108 rc = mem_gc_create(&params->rect, &alloc, ds_window_update_cb,
109 (void *)wnd, &wnd->mgc);
110 if (rc != EOK)
111 goto error;
112
[3434233]113 wnd->rect = params->rect;
[9b502dd]114 wnd->min_size = params->min_size;
[dbef30f]115 wnd->gc = mem_gc_get_ctx(wnd->mgc);
[9242ad9]116 wnd->cursor = wnd->display->cursor[dcurs_arrow];
[6af4b4f]117 *rgc = wnd;
[c8cf261]118 return EOK;
119error:
[946a666]120 if (wnd != NULL) {
121 if (wnd->bitmap != NULL)
122 gfx_bitmap_destroy(wnd->bitmap);
[6af4b4f]123 free(wnd);
[946a666]124 }
125
[c8cf261]126 return rc;
127}
128
[0e6e77f]129/** Destroy window.
[c8cf261]130 *
[0e6e77f]131 * @param wnd Window
[c8cf261]132 */
[da412547]133void ds_window_destroy(ds_window_t *wnd)
[c8cf261]134{
[cc90846]135 ds_display_t *disp;
136
137 disp = wnd->display;
138
[b3c185b6]139 ds_client_remove_window(wnd);
[fd777a2]140 ds_display_remove_window(wnd);
[cc90846]141
[dbef30f]142 mem_gc_delete(wnd->mgc);
143
[946a666]144 if (wnd->bitmap != NULL)
145 gfx_bitmap_destroy(wnd->bitmap);
[c8cf261]146
[6af4b4f]147 free(wnd);
[cc90846]148
149 (void) ds_display_paint(disp, NULL);
[c8cf261]150}
151
[1a1271d]152/** Bring window to top.
153 *
154 * @param wnd Window
155 */
[b5c7cee]156void ds_window_bring_to_top(ds_window_t *wnd)
157{
158 ds_display_t *disp = wnd->display;
159
160 ds_display_remove_window(wnd);
161 ds_display_add_window(disp, wnd);
162}
163
[6af4b4f]164/** Get generic graphic context from window.
[c8cf261]165 *
[6af4b4f]166 * @param wnd Window
[c8cf261]167 * @return Graphic context
168 */
[6af4b4f]169gfx_context_t *ds_window_get_ctx(ds_window_t *wnd)
[c8cf261]170{
[6af4b4f]171 return wnd->gc;
[c8cf261]172}
173
[2012fe0]174/** Paint a window using its backing bitmap.
[946a666]175 *
[2012fe0]176 * @param wnd Window to paint
177 * @param rect Display rectangle to paint to
[946a666]178 * @return EOK on success or an error code
179 */
[2012fe0]180errno_t ds_window_paint(ds_window_t *wnd, gfx_rect_t *rect)
[946a666]181{
[2012fe0]182 gfx_rect_t srect;
183 gfx_rect_t *brect;
184 gfx_rect_t crect;
185
186 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint");
187
188 if (rect != NULL) {
189 gfx_rect_rtranslate(&wnd->dpos, rect, &srect);
190
191 /* Determine if we have anything to do */
[01c2759]192 gfx_rect_clip(&srect, &wnd->rect, &crect);
[2012fe0]193 if (gfx_rect_is_empty(&crect))
194 return EOK;
195
196 brect = &srect;
197 } else {
198 brect = NULL;
199 }
200
[f5191b4]201 /* This can happen in unit tests */
202 if (wnd->bitmap == NULL)
203 return EOK;
204
[2012fe0]205 return gfx_bitmap_render(wnd->bitmap, brect, &wnd->dpos);
[946a666]206}
207
[6301a24f]208/** Get the preview rectangle for a window.
209 *
210 * Get the preview rectangle if the window is being resized or moved.
211 * If the window is not being resized or moved, return an empty rectangle.
[a40ae0d]212 *
213 * @param wnd Window
[6301a24f]214 * @param rect Place to store preview rectangle
[a40ae0d]215 */
[6301a24f]216static void ds_window_get_preview_rect(ds_window_t *wnd, gfx_rect_t *rect)
217{
218 switch (wnd->state) {
219 case dsw_idle:
220 break;
221 case dsw_moving:
222 gfx_rect_translate(&wnd->preview_pos, &wnd->rect, rect);
223 return;
224 case dsw_resizing:
225 gfx_rect_translate(&wnd->dpos, &wnd->preview_rect, rect);
226 return;
227 }
228
229 rect->p0.x = 0;
230 rect->p0.y = 0;
231 rect->p1.x = 0;
232 rect->p1.y = 0;
233}
234
235/** Paint window preview if the window is being moved or resized.
236 *
237 * If the window is not being resized or moved, take no action and return
238 * success.
239 *
240 * @param wnd Window for which to paint preview
241 * @param rect Clipping rectangle
242 * @return EOK on success or an error code
243 */
244errno_t ds_window_paint_preview(ds_window_t *wnd, gfx_rect_t *rect)
[a40ae0d]245{
[6301a24f]246 errno_t rc;
[1b443cc0]247 gfx_color_t *color;
[6301a24f]248 gfx_rect_t prect;
[a65b0c8]249 gfx_rect_t dr;
250 gfx_rect_t pr;
[6301a24f]251 gfx_context_t *gc;
[1b443cc0]252
[6301a24f]253 /*
254 * Get preview rectangle. If the window is not being resized/moved,
255 * we should get an empty rectangle.
256 */
257 ds_window_get_preview_rect(wnd, &prect);
258 if (gfx_rect_is_empty(&prect)) {
259 /* There is nothing to paint */
260 return EOK;
261 }
[a40ae0d]262
[a65b0c8]263 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint_preview");
264 prect.p0.x, prect.p0.y, prect.p1.x, prect.p1.y);
[1b443cc0]265
266 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
267 if (rc != EOK)
[6301a24f]268 return rc;
[1b443cc0]269
270 gc = ds_display_get_gc(wnd->display); // XXX
271 if (gc != NULL) {
272 gfx_set_color(gc, color);
[a65b0c8]273
274 /*
275 * TODO: Ideally we'd want XOR operation to make the preview
276 * frame visible on any background. If we wanted to get really
277 * fancy, we'd fill it with a pattern
278 */
279
280 pr.p0.x = prect.p0.x;
281 pr.p0.y = prect.p0.y;
282 pr.p1.x = prect.p1.x;
283 pr.p1.y = prect.p0.y + 1;
284 gfx_rect_clip(&pr, rect, &dr);
285 gfx_fill_rect(gc, &dr);
286
287 pr.p0.x = prect.p0.x;
288 pr.p0.y = prect.p1.y - 1;
289 pr.p1.x = prect.p1.x;
290 pr.p1.y = prect.p1.y;
291 gfx_rect_clip(&pr, rect, &dr);
292 gfx_fill_rect(gc, &dr);
293
294 pr.p0.x = prect.p0.x;
295 pr.p0.y = prect.p0.y;
296 pr.p1.x = prect.p0.x + 1;
297 pr.p1.y = prect.p1.y;
298 gfx_rect_clip(&pr, rect, &dr);
299 gfx_fill_rect(gc, &dr);
300
301 pr.p0.x = prect.p1.x - 1;
302 pr.p0.y = prect.p0.y;
303 pr.p1.x = prect.p1.x;
304 pr.p1.y = prect.p1.y;
305 gfx_rect_clip(&pr, rect, &dr);
306 gfx_fill_rect(gc, &dr);
307
[1b443cc0]308 }
309
310 gfx_color_delete(color);
[6301a24f]311 return EOK;
312}
313
314/** Repaint window preview when resizing or moving.
315 *
316 * Repaint the window preview wich was previously at rectangle @a old_rect.
317 * The current preview rectangle is determined from window state. If
318 * the window did not previously have a preview, @a old_rect should point
319 * to an empty rectangle or be NULL. When window has finished
320 * moving or resizing, the preview will be cleared.
321 *
322 * @param wnd Window for which to paint preview
323 * @param rect Clipping rectangle
324 * @return EOK on success or an error code
325 */
326static errno_t ds_window_repaint_preview(ds_window_t *wnd, gfx_rect_t *old_rect)
327{
328 errno_t rc;
329 gfx_rect_t prect;
330 gfx_rect_t envelope;
331 bool oldr;
332 bool newr;
333
334 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_repaint_preview");
335
336 /*
337 * Get current preview rectangle. If the window is not being resized/moved,
338 * we should get an empty rectangle.
339 */
340 ds_window_get_preview_rect(wnd, &prect);
341
342 oldr = (old_rect != NULL) && !gfx_rect_is_empty(old_rect);
343 newr = !gfx_rect_is_empty(&prect);
344
345 if (oldr && newr && gfx_rect_is_incident(old_rect, &prect)) {
346 /*
347 * As an optimization, repaint both rectangles in a single
348 * operation.
349 */
350
351 gfx_rect_envelope(old_rect, &prect, &envelope);
352
353 rc = ds_display_paint(wnd->display, &envelope);
354 if (rc != EOK)
355 return rc;
356 } else {
357 /* Repaint each rectangle separately */
358 if (oldr) {
359 rc = ds_display_paint(wnd->display, old_rect);
360 if (rc != EOK)
361 return rc;
362 }
363
364 if (newr) {
365 rc = ds_display_paint(wnd->display, &prect);
366 if (rc != EOK)
367 return rc;
368 }
369 }
370
371 return EOK;
372}
373
374/** Start moving a window by mouse drag.
375 *
376 * @param wnd Window
377 * @param pos Position where mouse button was pressed
378 */
379static void ds_window_start_move(ds_window_t *wnd, gfx_coord2_t *pos)
380{
381 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
382 (int) pos->x, (int) pos->y);
383
384 if (wnd->state != dsw_idle)
385 return;
386
387 wnd->orig_pos = *pos;
388 wnd->state = dsw_moving;
389 wnd->preview_pos = wnd->dpos;
390
391 (void) ds_window_repaint_preview(wnd, NULL);
[a40ae0d]392}
393
394/** Finish moving a window by mouse drag.
395 *
396 * @param wnd Window
[76a02db]397 * @param pos Position where mouse button was released
[a40ae0d]398 */
[76a02db]399static void ds_window_finish_move(ds_window_t *wnd, gfx_coord2_t *pos)
[a40ae0d]400{
401 gfx_coord2_t dmove;
402 gfx_coord2_t nwpos;
[6301a24f]403 gfx_rect_t old_rect;
[a40ae0d]404
405 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
[76a02db]406 (int) pos->x, (int) pos->y);
[a40ae0d]407
[5f483be]408 assert(wnd->state == dsw_moving);
[a2e104e]409
[76a02db]410 gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
[a40ae0d]411 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
[6301a24f]412
413 ds_window_get_preview_rect(wnd, &old_rect);
414
[a40ae0d]415 wnd->dpos = nwpos;
416 wnd->state = dsw_idle;
[946a666]417
[2012fe0]418 (void) ds_display_paint(wnd->display, NULL);
[a40ae0d]419}
420
421/** Update window position when moving by mouse drag.
422 *
423 * @param wnd Window
[76a02db]424 * @param pos Current mouse position
[a40ae0d]425 */
[76a02db]426static void ds_window_update_move(ds_window_t *wnd, gfx_coord2_t *pos)
[a40ae0d]427{
428 gfx_coord2_t dmove;
429 gfx_coord2_t nwpos;
[6301a24f]430 gfx_rect_t old_rect;
[a40ae0d]431
432 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
[76a02db]433 (int) pos->x, (int) pos->y);
[a40ae0d]434
[5f483be]435 assert(wnd->state == dsw_moving);
[a2e104e]436
[76a02db]437 gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
[a40ae0d]438 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
[c79545e]439
[6301a24f]440 ds_window_get_preview_rect(wnd, &old_rect);
441 wnd->preview_pos = nwpos;
[a40ae0d]442
[6301a24f]443 (void) ds_window_repaint_preview(wnd, &old_rect);
[a40ae0d]444}
445
[76a02db]446/** Start resizing a window by mouse drag.
447 *
448 * @param wnd Window
449 * @param rsztype Resize type (which part of window is being dragged)
450 * @param pos Position where mouse button was pressed
451 */
452static void ds_window_start_resize(ds_window_t *wnd,
453 display_wnd_rsztype_t rsztype, gfx_coord2_t *pos)
454{
[9901f267]455 ds_seat_t *seat;
456 display_stock_cursor_t ctype;
457
[76a02db]458 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_resize (%d, %d)",
459 (int) pos->x, (int) pos->y);
460
461 if (wnd->state != dsw_idle)
462 return;
463
464 wnd->orig_pos = *pos;
465 wnd->state = dsw_resizing;
466 wnd->rsztype = rsztype;
[71eff34]467 wnd->preview_rect = wnd->rect;
[9901f267]468
469 // XXX Need client to tell us which seat started the resize!
470 seat = ds_display_first_seat(wnd->display);
471 ctype = display_cursor_from_wrsz(rsztype);
472 ds_seat_set_wm_cursor(seat, wnd->display->cursor[ctype]);
[6301a24f]473
474 (void) ds_window_repaint_preview(wnd, NULL);
[76a02db]475}
476
[e022819]477/** Finish resizing a window by mouse drag.
478 *
479 * @param wnd Window
[76a02db]480 * @param pos Position where mouse button was released
[e022819]481 */
[76a02db]482static void ds_window_finish_resize(ds_window_t *wnd, gfx_coord2_t *pos)
[e022819]483{
484 gfx_coord2_t dresize;
485 gfx_rect_t nrect;
[9901f267]486 ds_seat_t *seat;
[e022819]487
488 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_resize (%d, %d)",
[76a02db]489 (int) pos->x, (int) pos->y);
[e022819]490
[5f483be]491 assert(wnd->state == dsw_resizing);
[76a02db]492 gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
[e022819]493
494 /* Compute new rectangle */
495 ds_window_calc_resize(wnd, &dresize, &nrect);
496
497 wnd->state = dsw_idle;
498 ds_client_post_resize_event(wnd->client, wnd, &nrect);
[9901f267]499
500 // XXX Need to know which seat started the resize!
501 seat = ds_display_first_seat(wnd->display);
502 ds_seat_set_wm_cursor(seat, NULL);
[6301a24f]503
504 (void) ds_display_paint(wnd->display, NULL);
[e022819]505}
506
507/** Update window position when resizing by mouse drag.
508 *
509 * @param wnd Window
[76a02db]510 * @param pos Current mouse position
[e022819]511 */
[76a02db]512static void ds_window_update_resize(ds_window_t *wnd, gfx_coord2_t *pos)
[e022819]513{
514 gfx_coord2_t dresize;
515 gfx_rect_t nrect;
[6301a24f]516 gfx_rect_t old_rect;
[e022819]517
518 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
[76a02db]519 (int) pos->x, (int) pos->y);
[e022819]520
[5f483be]521 assert(wnd->state == dsw_resizing);
[e022819]522
[76a02db]523 gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
[e022819]524 ds_window_calc_resize(wnd, &dresize, &nrect);
525
[6301a24f]526 ds_window_get_preview_rect(wnd, &old_rect);
527 wnd->preview_rect = nrect;
528 (void) ds_window_repaint_preview(wnd, &old_rect);
[e022819]529}
530
[338d0935]531/** Post keyboard event to window.
532 *
533 * @param wnd Window
534 * @param event Event
535 *
536 * @return EOK on success or an error code
537 */
538errno_t ds_window_post_kbd_event(ds_window_t *wnd, kbd_event_t *event)
539{
540 bool alt_or_shift;
541
542 alt_or_shift = event->mods & (KM_SHIFT | KM_ALT);
543
544 if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_F4) {
545 /* On Alt-F4 or Shift-F4 send close event to the window */
546 ds_client_post_close_event(wnd->client, wnd);
547 return EOK;
548 }
549
550 return ds_client_post_kbd_event(wnd->client, wnd, event);
551}
552
[a40ae0d]553/** Post position event to window.
554 *
555 * @param wnd Window
556 * @param event Position event
557 */
558errno_t ds_window_post_pos_event(ds_window_t *wnd, pos_event_t *event)
559{
[f7fb2b21]560 pos_event_t tevent;
[a2e104e]561 gfx_coord2_t pos;
562 gfx_rect_t drect;
563 bool inside;
[f7fb2b21]564
[a40ae0d]565 log_msg(LOG_DEFAULT, LVL_DEBUG,
566 "ds_window_post_pos_event type=%d pos=%d,%d\n", event->type,
567 (int) event->hpos, (int) event->vpos);
568
[a2e104e]569 pos.x = event->hpos;
570 pos.y = event->vpos;
571 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
572 inside = gfx_pix_inside_rect(&pos, &drect);
[a40ae0d]573
[5f483be]574 if (event->type == POS_PRESS && event->btn_num == 2 && inside) {
[76a02db]575 ds_window_start_move(wnd, &pos);
[5f483be]576 return EOK;
577 }
[a40ae0d]578
[e022819]579 if (event->type == POS_RELEASE) {
[5f483be]580 if (wnd->state == dsw_moving) {
581 ds_window_finish_move(wnd, &pos);
582 return EOK;
583 }
584
585 if (wnd->state == dsw_resizing) {
586 ds_window_finish_resize(wnd, &pos);
587 return EOK;
588 }
[e022819]589 }
[a2e104e]590
[e022819]591 if (event->type == POS_UPDATE) {
[5f483be]592 if (wnd->state == dsw_moving) {
593 ds_window_update_move(wnd, &pos);
594 return EOK;
595 }
596
597 if (wnd->state == dsw_resizing) {
598 ds_window_update_resize(wnd, &pos);
599 return EOK;
600 }
[e022819]601 }
[a40ae0d]602
[f7fb2b21]603 /* Transform event coordinates to window-local */
604 tevent = *event;
605 tevent.hpos -= wnd->dpos.x;
606 tevent.vpos -= wnd->dpos.y;
607
608 return ds_client_post_pos_event(wnd->client, wnd, &tevent);
[a40ae0d]609}
610
[b0a94854]611/** Post focus event to window.
612 *
613 * @param wnd Window
614 */
615errno_t ds_window_post_focus_event(ds_window_t *wnd)
616{
617 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_focus_event\n");
618
619 return ds_client_post_focus_event(wnd->client, wnd);
620}
621
622/** Post unfocus event to window.
623 *
624 * @param wnd Window
625 */
626errno_t ds_window_post_unfocus_event(ds_window_t *wnd)
627{
628 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_unfocus_event\n");
629
630 return ds_client_post_unfocus_event(wnd->client, wnd);
631}
632
[e022819]633/** Start moving a window, detected by client.
634 *
635 * @param wnd Window
636 * @param pos Position where the pointer was when the move started
637 * relative to the window
638 * @param event Button press event
639 */
640void ds_window_move_req(ds_window_t *wnd, gfx_coord2_t *pos)
641{
[76a02db]642 gfx_coord2_t orig_pos;
643
[e022819]644 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_move_req (%d, %d)",
645 (int) pos->x, (int) pos->y);
646
[76a02db]647 gfx_coord2_add(&wnd->dpos, pos, &orig_pos);
648 ds_window_start_move(wnd, &orig_pos);
[e022819]649}
650
[0680854]651/** Move window.
652 *
653 * @param wnd Window
654 */
655void ds_window_move(ds_window_t *wnd, gfx_coord2_t *dpos)
656{
657 wnd->dpos = *dpos;
658 (void) ds_display_paint(wnd->display, NULL);
659}
660
[e022819]661/** Start resizing a window, detected by client.
662 *
663 * @param wnd Window
664 * @param rsztype Resize type (which part of window is being dragged)
665 * @param pos Position where the pointer was when the resize started
666 * relative to the window
667 * @param event Button press event
668 */
669void ds_window_resize_req(ds_window_t *wnd, display_wnd_rsztype_t rsztype,
670 gfx_coord2_t *pos)
671{
[76a02db]672 gfx_coord2_t orig_pos;
673
[e022819]674 log_msg(LOG_DEFAULT, LVL_NOTE, "ds_window_resize_req (%d, %d, %d)",
675 (int) rsztype, (int) pos->x, (int) pos->y);
676
[76a02db]677 gfx_coord2_add(&wnd->dpos, pos, &orig_pos);
678 ds_window_start_resize(wnd, rsztype, &orig_pos);
[e022819]679}
680
[0680854]681/** Resize window.
682 *
683 * @param wnd Window
684 */
685errno_t ds_window_resize(ds_window_t *wnd, gfx_coord2_t *offs,
686 gfx_rect_t *nrect)
687{
688 gfx_context_t *dgc;
689 gfx_bitmap_params_t bparams;
690 gfx_bitmap_t *nbitmap;
691 pixelmap_t npixelmap;
692 gfx_coord2_t dims;
693 gfx_bitmap_alloc_t alloc;
694 gfx_coord2_t ndpos;
695 errno_t rc;
696
697 dgc = ds_display_get_gc(wnd->display); // XXX
698 if (dgc != NULL) {
699 gfx_bitmap_params_init(&bparams);
700 bparams.rect = *nrect;
701
702 rc = gfx_bitmap_create(dgc, &bparams, NULL, &nbitmap);
703 if (rc != EOK)
704 return ENOMEM;
705
706 rc = gfx_bitmap_get_alloc(nbitmap, &alloc);
707 if (rc != EOK) {
708 gfx_bitmap_destroy(nbitmap);
709 return ENOMEM;
710 }
711
712 gfx_rect_dims(nrect, &dims);
713 npixelmap.width = dims.x;
714 npixelmap.height = dims.y;
715 npixelmap.data = alloc.pixels;
716
717 /* TODO: Transfer contents within overlap */
718
719 if (wnd->bitmap != NULL)
720 gfx_bitmap_destroy(wnd->bitmap);
721
722 wnd->bitmap = nbitmap;
723 wnd->pixelmap = npixelmap;
[dbef30f]724
725 /* Point memory GC to the new bitmap */
726 mem_gc_retarget(wnd->mgc, nrect, &alloc);
[0680854]727 }
728
729 gfx_coord2_add(&wnd->dpos, offs, &ndpos);
730
731 wnd->dpos = ndpos;
732 wnd->rect = *nrect;
733
734 (void) ds_display_paint(wnd->display, NULL);
735 return EOK;
736}
737
[e022819]738/** Compute new window rectangle after resize operation.
739 *
740 * @param wnd Window which is being resized (in dsw_resizing state and thus
741 * has rsztype set)
742 * @param dresize Amount by which to resize
743 * @param nrect Place to store new rectangle
744 */
745void ds_window_calc_resize(ds_window_t *wnd, gfx_coord2_t *dresize,
746 gfx_rect_t *nrect)
747{
[9b502dd]748 if ((wnd->rsztype & display_wr_top) != 0) {
749 nrect->p0.y = min(wnd->rect.p0.y + dresize->y,
750 wnd->rect.p1.y - wnd->min_size.y);
751 } else {
752 nrect->p0.y = wnd->rect.p0.y;
753 }
754
755 if ((wnd->rsztype & display_wr_left) != 0) {
756 nrect->p0.x = min(wnd->rect.p0.x + dresize->x,
757 wnd->rect.p1.x - wnd->min_size.x);
758 } else {
759 nrect->p0.x = wnd->rect.p0.x;
760 }
761
762 if ((wnd->rsztype & display_wr_bottom) != 0) {
763 nrect->p1.y = max(wnd->rect.p1.y + dresize->y,
764 wnd->rect.p0.y + wnd->min_size.y);
765 } else {
766 nrect->p1.y = wnd->rect.p1.y;
767 }
768
769 if ((wnd->rsztype & display_wr_right) != 0) {
770 nrect->p1.x = max(wnd->rect.p1.x + dresize->x,
771 wnd->rect.p0.x + wnd->min_size.x);
772 } else {
773 nrect->p1.x = wnd->rect.p1.x;
774 }
[e022819]775}
776
[9242ad9]777/** Set window cursor.
778 *
779 * @param wnd Window
780 * @return EOK on success, EINVAL if @a cursor is invalid
781 */
782errno_t ds_window_set_cursor(ds_window_t *wnd, display_stock_cursor_t cursor)
783{
784 if (cursor >= dcurs_arrow &&
785 cursor < (display_stock_cursor_t) dcurs_limit) {
786 wnd->cursor = wnd->display->cursor[cursor];
787 return EOK;
788 } else {
789 return EINVAL;
790 }
791}
792
[d70e7b7b]793/** Window memory GC update callback.
[dbef30f]794 *
795 * This is called by the window's memory GC when a rectangle us updated.
796 */
797static void ds_window_update_cb(void *arg, gfx_rect_t *rect)
798{
799 ds_window_t *wnd = (ds_window_t *)arg;
800 gfx_rect_t drect;
801
802 /* Repaint the corresponding part of the display */
803 gfx_rect_translate(&wnd->dpos, rect, &drect);
804 (void) ds_display_paint(wnd->display, &drect);
805}
806
[c8cf261]807/** @}
808 */
Note: See TracBrowser for help on using the repository browser.