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

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

Repaint desktop when window is brought to front

Libgui used to repaint the entire window when it received focus so this
went unnoticed. Libui currently only repaints the window decoration.
Repainting the entire desktop is probably not necessary, but I am
mimicking the other places where we do this (e.g. moving window).
All of these cases can be revisited and, perhaps, optimized to
repaint just a part of the desktop.

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