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

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

Switch to double-arrow cursors when pointer is above resize areas

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