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
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
[84e74ea]86 dgc = ds_display_get_gc(wnd->display);
[946a666]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
[84e74ea]270 gc = ds_display_get_gc(wnd->display);
[1b443cc0]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
[84e74ea]697 dgc = ds_display_get_gc(wnd->display);
[0680854]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.