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

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

Display server needs to override cursor when resizing windows

Although the pointer moves, the window is not resized until button
is released. Therefore we need override the cursor from what it
would be just based on where the pointer is located.

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