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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ef20a91 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
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 <stdlib.h>
45#include "client.h"
46#include "display.h"
47#include "seat.h"
48#include "window.h"
49
50static errno_t ds_window_set_color(void *, gfx_color_t *);
51static errno_t ds_window_fill_rect(void *, gfx_rect_t *);
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 *);
57
58gfx_context_ops_t ds_window_ops = {
59 .set_color = ds_window_set_color,
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
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 */
76static errno_t ds_window_set_color(void *arg, gfx_color_t *color)
77{
78 ds_window_t *wnd = (ds_window_t *) arg;
79 uint16_t r, g, b;
80
81 log_msg(LOG_DEFAULT, LVL_NOTE, "gc_set_color gc=%p",
82 ds_display_get_gc(wnd->display));
83
84 gfx_color_get_rgb_i16(color, &r, &g, &b);
85 wnd->color = PIXEL(0, r >> 8, g >> 8, b >> 8);
86
87 return gfx_set_color(ds_display_get_gc(wnd->display), color);
88}
89
90/** Fill rectangle on window GC.
91 *
92 * @param arg Window GC
93 * @param rect Rectangle
94 *
95 * @return EOK on success or an error code
96 */
97static errno_t ds_window_fill_rect(void *arg, gfx_rect_t *rect)
98{
99 ds_window_t *wnd = (ds_window_t *) arg;
100 gfx_rect_t crect;
101 gfx_rect_t drect;
102 gfx_coord_t x, y;
103
104 log_msg(LOG_DEFAULT, LVL_NOTE, "gc_fill_rect");
105
106 gfx_rect_clip(rect, &wnd->rect, &crect);
107 gfx_rect_translate(&wnd->dpos, &crect, &drect);
108
109 /* Render into the backbuffer */
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
117 /* Repaint this area of the display */
118 return ds_display_paint(wnd->display, &drect);
119}
120
121/** Create bitmap in window GC.
122 *
123 * @param arg Window GC
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
140 rc = gfx_bitmap_create(ds_display_get_gc(wnd->display), params, alloc,
141 &cbm->bitmap);
142 if (rc != EOK)
143 goto error;
144
145 cbm->wnd = wnd;
146 cbm->rect = params->rect;
147 *rbm = (void *)cbm;
148 return EOK;
149error:
150 if (cbm != NULL)
151 free(cbm);
152 return rc;
153}
154
155/** Destroy bitmap in window GC.
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
169/** Render bitmap in window GC.
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;
180 gfx_coord2_t doffs;
181 gfx_coord2_t offs;
182 gfx_rect_t srect;
183 gfx_rect_t swrect;
184 gfx_rect_t crect;
185 gfx_rect_t drect;
186 gfx_coord_t x, y;
187 pixelmap_t pixelmap;
188 gfx_bitmap_alloc_t alloc;
189 pixel_t pixel;
190 errno_t rc;
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);
215
216 /* Resulting rectangle on the screen we are drawing into */
217 gfx_rect_translate(&doffs, &crect, &drect);
218
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
239 /* Repaint this area of the display */
240 return ds_display_paint(cbm->wnd->display, &drect);
241}
242
243/** Get allocation info for bitmap in window GC.
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
256/** Create window.
257 *
258 * Create graphics context for rendering into a window.
259 *
260 * @param client Client owning the window
261 * @param params Window parameters
262 * @param rgc Place to store pointer to new GC.
263 *
264 * @return EOK on success or an error code
265 */
266errno_t ds_window_create(ds_client_t *client, display_wnd_params_t *params,
267 ds_window_t **rgc)
268{
269 ds_window_t *wnd = NULL;
270 gfx_context_t *gc = NULL;
271 gfx_context_t *dgc;
272 gfx_coord2_t dims;
273 gfx_bitmap_params_t bparams;
274 gfx_bitmap_alloc_t alloc;
275 errno_t rc;
276
277 wnd = calloc(1, sizeof(ds_window_t));
278 if (wnd == NULL) {
279 rc = ENOMEM;
280 goto error;
281 }
282
283 rc = gfx_context_new(&ds_window_ops, wnd, &gc);
284 if (rc != EOK)
285 goto error;
286
287 ds_client_add_window(client, wnd);
288 ds_display_add_window(client->display, wnd);
289
290 gfx_bitmap_params_init(&bparams);
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
303 gfx_rect_dims(&params->rect, &dims);
304 wnd->pixelmap.width = dims.x;
305 wnd->pixelmap.height = dims.y;
306 wnd->pixelmap.data = alloc.pixels;
307 }
308
309 wnd->rect = params->rect;
310 wnd->min_size = params->min_size;
311 wnd->gc = gc;
312 wnd->cursor = wnd->display->cursor[dcurs_arrow];
313 *rgc = wnd;
314 return EOK;
315error:
316 if (wnd != NULL) {
317 if (wnd->bitmap != NULL)
318 gfx_bitmap_destroy(wnd->bitmap);
319 free(wnd);
320 }
321
322 gfx_context_delete(gc);
323 return rc;
324}
325
326/** Destroy window.
327 *
328 * @param wnd Window
329 */
330void ds_window_destroy(ds_window_t *wnd)
331{
332 ds_display_t *disp;
333
334 disp = wnd->display;
335
336 ds_client_remove_window(wnd);
337 ds_display_remove_window(wnd);
338
339 (void) gfx_context_delete(wnd->gc);
340 if (wnd->bitmap != NULL)
341 gfx_bitmap_destroy(wnd->bitmap);
342
343 free(wnd);
344
345 (void) ds_display_paint(disp, NULL);
346}
347
348/** Bring window to top.
349 *
350 * @param wnd Window
351 */
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
360/** Get generic graphic context from window.
361 *
362 * @param wnd Window
363 * @return Graphic context
364 */
365gfx_context_t *ds_window_get_ctx(ds_window_t *wnd)
366{
367 return wnd->gc;
368}
369
370/** Paint a window using its backing bitmap.
371 *
372 * @param wnd Window to paint
373 * @param rect Display rectangle to paint to
374 * @return EOK on success or an error code
375 */
376errno_t ds_window_paint(ds_window_t *wnd, gfx_rect_t *rect)
377{
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 */
388 gfx_rect_clip(&srect, &wnd->rect, &crect);
389 if (gfx_rect_is_empty(&crect))
390 return EOK;
391
392 brect = &srect;
393 } else {
394 brect = NULL;
395 }
396
397 /* This can happen in unit tests */
398 if (wnd->bitmap == NULL)
399 return EOK;
400
401 return gfx_bitmap_render(wnd->bitmap, brect, &wnd->dpos);
402}
403
404/** Start moving a window by mouse drag.
405 *
406 * @param wnd Window
407 * @param pos Position where mouse button was pressed
408 */
409static void ds_window_start_move(ds_window_t *wnd, gfx_coord2_t *pos)
410{
411 gfx_color_t *color;
412 gfx_context_t *gc;
413 gfx_rect_t drect;
414 errno_t rc;
415
416 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
417 (int) pos->x, (int) pos->y);
418
419 if (wnd->state != dsw_idle)
420 return;
421
422 wnd->orig_pos = *pos;
423 wnd->state = dsw_moving;
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);
439}
440
441/** Finish moving a window by mouse drag.
442 *
443 * @param wnd Window
444 * @param pos Position where mouse button was released
445 */
446static void ds_window_finish_move(ds_window_t *wnd, gfx_coord2_t *pos)
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)",
452 (int) pos->x, (int) pos->y);
453
454 if (wnd->state != dsw_moving)
455 return;
456
457 gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
458
459 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
460 wnd->dpos = nwpos;
461 wnd->state = dsw_idle;
462
463 (void) ds_display_paint(wnd->display, NULL);
464}
465
466/** Update window position when moving by mouse drag.
467 *
468 * @param wnd Window
469 * @param pos Current mouse position
470 */
471static void ds_window_update_move(ds_window_t *wnd, gfx_coord2_t *pos)
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)",
481 (int) pos->x, (int) pos->y);
482
483 if (wnd->state != dsw_moving)
484 return;
485
486 gfx_rect_translate(&wnd->preview_pos, &wnd->rect, &drect);
487 ds_display_paint(wnd->display, &drect);
488
489 gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
490
491 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
492 wnd->preview_pos = nwpos;
493
494 gfx_rect_translate(&nwpos, &wnd->rect, &drect);
495
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) {
502 gfx_set_color(gc, color);
503 gfx_fill_rect(gc, &drect);
504 }
505
506 gfx_color_delete(color);
507}
508
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{
518 ds_seat_t *seat;
519 display_stock_cursor_t ctype;
520
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;
530 wnd->preview_rect = wnd->rect;
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]);
536}
537
538/** Finish resizing a window by mouse drag.
539 *
540 * @param wnd Window
541 * @param pos Position where mouse button was released
542 */
543static void ds_window_finish_resize(ds_window_t *wnd, gfx_coord2_t *pos)
544{
545 gfx_coord2_t dresize;
546 gfx_rect_t nrect;
547 ds_seat_t *seat;
548
549 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_resize (%d, %d)",
550 (int) pos->x, (int) pos->y);
551
552 if (wnd->state != dsw_resizing)
553 return;
554
555 (void) ds_display_paint(wnd->display, NULL);
556
557 gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
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);
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);
568}
569
570/** Update window position when resizing by mouse drag.
571 *
572 * @param wnd Window
573 * @param pos Current mouse position
574 */
575static void ds_window_update_resize(ds_window_t *wnd, gfx_coord2_t *pos)
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)",
585 (int) pos->x, (int) pos->y);
586
587 if (wnd->state != dsw_resizing)
588 return;
589
590 gfx_rect_translate(&wnd->dpos, &wnd->preview_rect, &drect);
591 (void) ds_display_paint(wnd->display, &drect);
592
593 gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
594
595 ds_window_calc_resize(wnd, &dresize, &nrect);
596 gfx_rect_translate(&wnd->dpos, &nrect, &drect);
597 wnd->preview_rect = nrect;
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
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
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{
641 pos_event_t tevent;
642 gfx_coord2_t pos;
643 gfx_rect_t drect;
644 bool inside;
645
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
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);
654
655 if (event->type == POS_PRESS && event->btn_num == 2 && inside)
656 ds_window_start_move(wnd, &pos);
657
658 if (event->type == POS_RELEASE) {
659 ds_window_finish_move(wnd, &pos);
660 ds_window_finish_resize(wnd, &pos);
661 }
662
663 if (event->type == POS_UPDATE) {
664 ds_window_update_move(wnd, &pos);
665 ds_window_update_resize(wnd, &pos);
666 }
667
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);
674}
675
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
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{
707 gfx_coord2_t orig_pos;
708
709 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_move_req (%d, %d)",
710 (int) pos->x, (int) pos->y);
711
712 gfx_coord2_add(&wnd->dpos, pos, &orig_pos);
713 ds_window_start_move(wnd, &orig_pos);
714}
715
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
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{
737 gfx_coord2_t orig_pos;
738
739 log_msg(LOG_DEFAULT, LVL_NOTE, "ds_window_resize_req (%d, %d, %d)",
740 (int) rsztype, (int) pos->x, (int) pos->y);
741
742 gfx_coord2_add(&wnd->dpos, pos, &orig_pos);
743 ds_window_start_resize(wnd, rsztype, &orig_pos);
744}
745
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
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{
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 }
837}
838
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
855/** @}
856 */
Note: See TracBrowser for help on using the repository browser.