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

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

Remove XXX comment from each call to display_get_gc()

These were added with the intent that each piece of code that does rendering
in the display server is augmented with a loop over all display devices.
The better solution seems to be to introduce a virtualization layer in the
form of a cloning GC that clones the rendering operations to each display
device. It makes the business code simpler and separates concerns better.
It could also allow having more types of output GCs, than just display
devices (such as an 'observer' for RFB).

  • 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}
163
164/** Get generic graphic context from window.
165 *
166 * @param wnd Window
167 * @return Graphic context
168 */
169gfx_context_t *ds_window_get_ctx(ds_window_t *wnd)
170{
171 return wnd->gc;
172}
173
174/** Paint a window using its backing bitmap.
175 *
176 * @param wnd Window to paint
177 * @param rect Display rectangle to paint to
178 * @return EOK on success or an error code
179 */
180errno_t ds_window_paint(ds_window_t *wnd, gfx_rect_t *rect)
181{
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 */
192 gfx_rect_clip(&srect, &wnd->rect, &crect);
193 if (gfx_rect_is_empty(&crect))
194 return EOK;
195
196 brect = &srect;
197 } else {
198 brect = NULL;
199 }
200
201 /* This can happen in unit tests */
202 if (wnd->bitmap == NULL)
203 return EOK;
204
205 return gfx_bitmap_render(wnd->bitmap, brect, &wnd->dpos);
206}
207
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.
212 *
213 * @param wnd Window
214 * @param rect Place to store preview rectangle
215 */
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)
245{
246 errno_t rc;
247 gfx_color_t *color;
248 gfx_rect_t prect;
249 gfx_rect_t dr;
250 gfx_rect_t pr;
251 gfx_context_t *gc;
252
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 }
262
263 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint_preview");
264 prect.p0.x, prect.p0.y, prect.p1.x, prect.p1.y);
265
266 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
267 if (rc != EOK)
268 return rc;
269
270 gc = ds_display_get_gc(wnd->display);
271 if (gc != NULL) {
272 gfx_set_color(gc, color);
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
308 }
309
310 gfx_color_delete(color);
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);
392}
393
394/** Finish moving a window by mouse drag.
395 *
396 * @param wnd Window
397 * @param pos Position where mouse button was released
398 */
399static void ds_window_finish_move(ds_window_t *wnd, gfx_coord2_t *pos)
400{
401 gfx_coord2_t dmove;
402 gfx_coord2_t nwpos;
403 gfx_rect_t old_rect;
404
405 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
406 (int) pos->x, (int) pos->y);
407
408 assert(wnd->state == dsw_moving);
409
410 gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
411 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
412
413 ds_window_get_preview_rect(wnd, &old_rect);
414
415 wnd->dpos = nwpos;
416 wnd->state = dsw_idle;
417
418 (void) ds_display_paint(wnd->display, NULL);
419}
420
421/** Update window position when moving by mouse drag.
422 *
423 * @param wnd Window
424 * @param pos Current mouse position
425 */
426static void ds_window_update_move(ds_window_t *wnd, gfx_coord2_t *pos)
427{
428 gfx_coord2_t dmove;
429 gfx_coord2_t nwpos;
430 gfx_rect_t old_rect;
431
432 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
433 (int) pos->x, (int) pos->y);
434
435 assert(wnd->state == dsw_moving);
436
437 gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
438 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
439
440 ds_window_get_preview_rect(wnd, &old_rect);
441 wnd->preview_pos = nwpos;
442
443 (void) ds_window_repaint_preview(wnd, &old_rect);
444}
445
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{
455 ds_seat_t *seat;
456 display_stock_cursor_t ctype;
457
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;
467 wnd->preview_rect = wnd->rect;
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]);
473
474 (void) ds_window_repaint_preview(wnd, NULL);
475}
476
477/** Finish resizing a window by mouse drag.
478 *
479 * @param wnd Window
480 * @param pos Position where mouse button was released
481 */
482static void ds_window_finish_resize(ds_window_t *wnd, gfx_coord2_t *pos)
483{
484 gfx_coord2_t dresize;
485 gfx_rect_t nrect;
486 ds_seat_t *seat;
487
488 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_resize (%d, %d)",
489 (int) pos->x, (int) pos->y);
490
491 assert(wnd->state == dsw_resizing);
492 gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
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);
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);
503
504 (void) ds_display_paint(wnd->display, NULL);
505}
506
507/** Update window position when resizing by mouse drag.
508 *
509 * @param wnd Window
510 * @param pos Current mouse position
511 */
512static void ds_window_update_resize(ds_window_t *wnd, gfx_coord2_t *pos)
513{
514 gfx_coord2_t dresize;
515 gfx_rect_t nrect;
516 gfx_rect_t old_rect;
517
518 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
519 (int) pos->x, (int) pos->y);
520
521 assert(wnd->state == dsw_resizing);
522
523 gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
524 ds_window_calc_resize(wnd, &dresize, &nrect);
525
526 ds_window_get_preview_rect(wnd, &old_rect);
527 wnd->preview_rect = nrect;
528 (void) ds_window_repaint_preview(wnd, &old_rect);
529}
530
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
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{
560 pos_event_t tevent;
561 gfx_coord2_t pos;
562 gfx_rect_t drect;
563 bool inside;
564
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
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);
573
574 if (event->type == POS_PRESS && event->btn_num == 2 && inside) {
575 ds_window_start_move(wnd, &pos);
576 return EOK;
577 }
578
579 if (event->type == POS_RELEASE) {
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 }
589 }
590
591 if (event->type == POS_UPDATE) {
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 }
601 }
602
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);
609}
610
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
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{
642 gfx_coord2_t orig_pos;
643
644 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_move_req (%d, %d)",
645 (int) pos->x, (int) pos->y);
646
647 gfx_coord2_add(&wnd->dpos, pos, &orig_pos);
648 ds_window_start_move(wnd, &orig_pos);
649}
650
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
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{
672 gfx_coord2_t orig_pos;
673
674 log_msg(LOG_DEFAULT, LVL_NOTE, "ds_window_resize_req (%d, %d, %d)",
675 (int) rsztype, (int) pos->x, (int) pos->y);
676
677 gfx_coord2_add(&wnd->dpos, pos, &orig_pos);
678 ds_window_start_resize(wnd, rsztype, &orig_pos);
679}
680
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);
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;
724
725 /* Point memory GC to the new bitmap */
726 mem_gc_retarget(wnd->mgc, nrect, &alloc);
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
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{
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 }
775}
776
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
793/** Window memory GC update callback.
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
807/** @}
808 */
Note: See TracBrowser for help on using the repository browser.