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

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

Maintain minimum window size in display server

  • Property mode set to 100644
File size: 18.9 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 GFX window backend
34 *
35 * This implements a graphics context over display server window.
36 */
37
38#include <gfx/bitmap.h>
39#include <gfx/color.h>
40#include <gfx/coord.h>
41#include <gfx/context.h>
42#include <gfx/render.h>
43#include <io/log.h>
44#include <io/pixelmap.h>
45#include <macros.h>
46#include <stdlib.h>
47#include "client.h"
48#include "display.h"
49#include "window.h"
50
51static errno_t ds_window_set_color(void *, gfx_color_t *);
52static errno_t ds_window_fill_rect(void *, gfx_rect_t *);
53static errno_t ds_window_bitmap_create(void *, gfx_bitmap_params_t *,
54 gfx_bitmap_alloc_t *, void **);
55static errno_t ds_window_bitmap_destroy(void *);
56static errno_t ds_window_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
57static errno_t ds_window_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
58
59gfx_context_ops_t ds_window_ops = {
60 .set_color = ds_window_set_color,
61 .fill_rect = ds_window_fill_rect,
62 .bitmap_create = ds_window_bitmap_create,
63 .bitmap_destroy = ds_window_bitmap_destroy,
64 .bitmap_render = ds_window_bitmap_render,
65 .bitmap_get_alloc = ds_window_bitmap_get_alloc
66};
67
68/** Set color on window GC.
69 *
70 * Set drawing color on window GC.
71 *
72 * @param arg Console GC
73 * @param color Color
74 *
75 * @return EOK on success or an error code
76 */
77static errno_t ds_window_set_color(void *arg, gfx_color_t *color)
78{
79 ds_window_t *wnd = (ds_window_t *) arg;
80 uint16_t r, g, b;
81
82 log_msg(LOG_DEFAULT, LVL_NOTE, "gc_set_color gc=%p",
83 ds_display_get_gc(wnd->display));
84
85 gfx_color_get_rgb_i16(color, &r, &g, &b);
86 wnd->color = PIXEL(0, r >> 8, g >> 8, b >> 8);
87
88 return gfx_set_color(ds_display_get_gc(wnd->display), color);
89}
90
91/** Fill rectangle on window GC.
92 *
93 * @param arg Window GC
94 * @param rect Rectangle
95 *
96 * @return EOK on success or an error code
97 */
98static errno_t ds_window_fill_rect(void *arg, gfx_rect_t *rect)
99{
100 ds_window_t *wnd = (ds_window_t *) arg;
101 gfx_rect_t crect;
102 gfx_rect_t drect;
103 gfx_coord_t x, y;
104
105 log_msg(LOG_DEFAULT, LVL_NOTE, "gc_fill_rect");
106
107 gfx_rect_clip(rect, &wnd->rect, &crect);
108 gfx_rect_translate(&wnd->dpos, &crect, &drect);
109
110 /* Render a copy to the backbuffer */
111 for (y = crect.p0.y; y < crect.p1.y; y++) {
112 for (x = crect.p0.x; x < crect.p1.x; x++) {
113 pixelmap_put_pixel(&wnd->pixelmap, x - wnd->rect.p0.x,
114 y - wnd->rect.p0.y, wnd->color);
115 }
116 }
117
118 return gfx_fill_rect(ds_display_get_gc(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_coord_t x, y;
186 pixelmap_t pixelmap;
187 gfx_bitmap_alloc_t alloc;
188 pixel_t pixel;
189 errno_t rc;
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);
214
215 rc = gfx_bitmap_get_alloc(cbm->bitmap, &alloc);
216 if (rc != EOK)
217 return rc;
218
219 pixelmap.width = cbm->rect.p1.x - cbm->rect.p0.x;
220 pixelmap.height = cbm->rect.p1.y - cbm->rect.p0.y;
221 pixelmap.data = alloc.pixels;
222
223 /* Render a copy to the backbuffer */
224 for (y = crect.p0.y; y < crect.p1.y; y++) {
225 for (x = crect.p0.x; x < crect.p1.x; x++) {
226 pixel = pixelmap_get_pixel(&pixelmap,
227 x - cbm->rect.p0.x, y - cbm->rect.p0.y);
228 pixelmap_put_pixel(&cbm->wnd->pixelmap,
229 x + offs.x - cbm->rect.p0.x + cbm->wnd->rect.p0.x,
230 y + offs.y - cbm->rect.p0.y + cbm->wnd->rect.p0.y,
231 pixel);
232 }
233 }
234
235 return gfx_bitmap_render(cbm->bitmap, &crect, &doffs);
236}
237
238/** Get allocation info for bitmap in window GC.
239 *
240 * @param bm Bitmap
241 * @param alloc Place to store allocation info
242 * @return EOK on success or an error code
243 */
244static errno_t ds_window_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
245{
246 ds_window_bitmap_t *cbm = (ds_window_bitmap_t *)bm;
247
248 return gfx_bitmap_get_alloc(cbm->bitmap, alloc);
249}
250
251/** Create window.
252 *
253 * Create graphics context for rendering into a window.
254 *
255 * @param client Client owning the window
256 * @param params Window parameters
257 * @param rgc Place to store pointer to new GC.
258 *
259 * @return EOK on success or an error code
260 */
261errno_t ds_window_create(ds_client_t *client, display_wnd_params_t *params,
262 ds_window_t **rgc)
263{
264 ds_window_t *wnd = NULL;
265 gfx_context_t *gc = NULL;
266 gfx_context_t *dgc;
267 gfx_coord2_t dims;
268 gfx_bitmap_params_t bparams;
269 gfx_bitmap_alloc_t alloc;
270 errno_t rc;
271
272 wnd = calloc(1, sizeof(ds_window_t));
273 if (wnd == NULL) {
274 rc = ENOMEM;
275 goto error;
276 }
277
278 rc = gfx_context_new(&ds_window_ops, wnd, &gc);
279 if (rc != EOK)
280 goto error;
281
282 ds_client_add_window(client, wnd);
283 ds_display_add_window(client->display, wnd);
284
285 gfx_bitmap_params_init(&bparams);
286 bparams.rect = params->rect;
287
288 dgc = ds_display_get_gc(wnd->display); // XXX
289 if (dgc != NULL) {
290 rc = gfx_bitmap_create(dgc, &bparams, NULL, &wnd->bitmap);
291 if (rc != EOK)
292 goto error;
293
294 rc = gfx_bitmap_get_alloc(wnd->bitmap, &alloc);
295 if (rc != EOK)
296 goto error;
297
298 gfx_rect_dims(&params->rect, &dims);
299 wnd->pixelmap.width = dims.x;
300 wnd->pixelmap.height = dims.y;
301 wnd->pixelmap.data = alloc.pixels;
302 }
303
304 wnd->rect = params->rect;
305 wnd->min_size = params->min_size;
306 wnd->gc = gc;
307 *rgc = wnd;
308 return EOK;
309error:
310 if (wnd != NULL) {
311 if (wnd->bitmap != NULL)
312 gfx_bitmap_destroy(wnd->bitmap);
313 free(wnd);
314 }
315
316 gfx_context_delete(gc);
317 return rc;
318}
319
320/** Destroy window.
321 *
322 * @param wnd Window
323 */
324void ds_window_destroy(ds_window_t *wnd)
325{
326 ds_display_t *disp;
327
328 disp = wnd->display;
329
330 ds_client_remove_window(wnd);
331 ds_display_remove_window(wnd);
332
333 (void) gfx_context_delete(wnd->gc);
334 if (wnd->bitmap != NULL)
335 gfx_bitmap_destroy(wnd->bitmap);
336
337 free(wnd);
338
339 (void) ds_display_paint(disp, NULL);
340}
341
342/** Resize window.
343 *
344 * @param wnd Window
345 */
346errno_t ds_window_resize(ds_window_t *wnd, gfx_coord2_t *offs,
347 gfx_rect_t *nrect)
348{
349 gfx_context_t *dgc;
350 gfx_bitmap_params_t bparams;
351 gfx_bitmap_t *nbitmap;
352 pixelmap_t npixelmap;
353 gfx_coord2_t dims;
354 gfx_bitmap_alloc_t alloc;
355 gfx_coord2_t ndpos;
356 errno_t rc;
357
358 dgc = ds_display_get_gc(wnd->display); // XXX
359 if (dgc != NULL) {
360 gfx_bitmap_params_init(&bparams);
361 bparams.rect = *nrect;
362
363 rc = gfx_bitmap_create(dgc, &bparams, NULL, &nbitmap);
364 if (rc != EOK)
365 return ENOMEM;
366
367 rc = gfx_bitmap_get_alloc(nbitmap, &alloc);
368 if (rc != EOK) {
369 gfx_bitmap_destroy(nbitmap);
370 return ENOMEM;
371 }
372
373 gfx_rect_dims(nrect, &dims);
374 npixelmap.width = dims.x;
375 npixelmap.height = dims.y;
376 npixelmap.data = alloc.pixels;
377
378 /* TODO: Transfer contents within overlap */
379
380 if (wnd->bitmap != NULL)
381 gfx_bitmap_destroy(wnd->bitmap);
382
383 wnd->bitmap = nbitmap;
384 wnd->pixelmap = npixelmap;
385 }
386
387 gfx_coord2_add(&wnd->dpos, offs, &ndpos);
388
389 wnd->dpos = ndpos;
390 wnd->rect = *nrect;
391
392 (void) ds_display_paint(wnd->display, NULL);
393 return EOK;
394}
395
396/** Get generic graphic context from window.
397 *
398 * @param wnd Window
399 * @return Graphic context
400 */
401gfx_context_t *ds_window_get_ctx(ds_window_t *wnd)
402{
403 return wnd->gc;
404}
405
406/** Paint a window using its backing bitmap.
407 *
408 * @param wnd Window to paint
409 * @param rect Display rectangle to paint to
410 * @return EOK on success or an error code
411 */
412errno_t ds_window_paint(ds_window_t *wnd, gfx_rect_t *rect)
413{
414 gfx_rect_t srect;
415 gfx_rect_t *brect;
416 gfx_rect_t crect;
417
418 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint");
419
420 if (rect != NULL) {
421 gfx_rect_rtranslate(&wnd->dpos, rect, &srect);
422
423 /* Determine if we have anything to do */
424 gfx_rect_clip(&srect, &wnd->rect, &crect);
425 if (gfx_rect_is_empty(&crect))
426 return EOK;
427
428 brect = &srect;
429 } else {
430 brect = NULL;
431 }
432
433 /* This can happen in unit tests */
434 if (wnd->bitmap == NULL)
435 return EOK;
436
437 return gfx_bitmap_render(wnd->bitmap, brect, &wnd->dpos);
438}
439
440/** Start moving a window by mouse drag.
441 *
442 * @param wnd Window
443 * @param event Button press event
444 */
445static void ds_window_start_move(ds_window_t *wnd, pos_event_t *event)
446{
447 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
448 (int) event->hpos, (int) event->vpos);
449
450 if (wnd->state != dsw_idle)
451 return;
452
453 wnd->orig_pos.x = event->hpos;
454 wnd->orig_pos.y = event->vpos;
455 wnd->state = dsw_moving;
456}
457
458/** Finish moving a window by mouse drag.
459 *
460 * @param wnd Window
461 * @param event Button release event
462 */
463static void ds_window_finish_move(ds_window_t *wnd, pos_event_t *event)
464{
465 gfx_coord2_t pos;
466 gfx_coord2_t dmove;
467 gfx_coord2_t nwpos;
468
469 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
470 (int) event->hpos, (int) event->vpos);
471
472 if (wnd->state != dsw_moving)
473 return;
474
475 pos.x = event->hpos;
476 pos.y = event->vpos;
477 gfx_coord2_subtract(&pos, &wnd->orig_pos, &dmove);
478
479 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
480 wnd->dpos = nwpos;
481 wnd->state = dsw_idle;
482
483 (void) ds_display_paint(wnd->display, NULL);
484}
485
486/** Update window position when moving by mouse drag.
487 *
488 * @param wnd Window
489 * @param event Position update event
490 */
491static void ds_window_update_move(ds_window_t *wnd, pos_event_t *event)
492{
493 gfx_coord2_t pos;
494 gfx_coord2_t dmove;
495 gfx_coord2_t nwpos;
496 gfx_rect_t drect;
497 gfx_color_t *color;
498 gfx_context_t *gc;
499 errno_t rc;
500
501 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
502 (int) event->hpos, (int) event->vpos);
503
504 if (wnd->state != dsw_moving)
505 return;
506
507 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
508
509 gc = ds_display_get_gc(wnd->display); // XXX
510 if (gc != NULL) {
511 gfx_set_color(gc, wnd->display->bg_color);
512 gfx_fill_rect(gc, &drect);
513 }
514
515 pos.x = event->hpos;
516 pos.y = event->vpos;
517 gfx_coord2_subtract(&pos, &wnd->orig_pos, &dmove);
518
519 gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
520 gfx_rect_translate(&nwpos, &wnd->rect, &drect);
521
522 wnd->orig_pos = pos;
523 wnd->dpos = nwpos;
524
525 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
526 if (rc != EOK)
527 return;
528
529 gc = ds_display_get_gc(wnd->display); // XXX
530 if (gc != NULL) {
531 gfx_set_color(gc, color);
532 gfx_fill_rect(gc, &drect);
533 }
534
535 gfx_color_delete(color);
536}
537
538/** Finish resizing a window by mouse drag.
539 *
540 * @param wnd Window
541 * @param event Button release event
542 */
543static void ds_window_finish_resize(ds_window_t *wnd, pos_event_t *event)
544{
545 gfx_coord2_t pos;
546 gfx_coord2_t dresize;
547 gfx_rect_t nrect;
548
549 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_resize (%d, %d)",
550 (int) event->hpos, (int) event->vpos);
551
552 if (wnd->state != dsw_resizing)
553 return;
554
555 (void) ds_display_paint(wnd->display, NULL);
556
557 pos.x = event->hpos;
558 pos.y = event->vpos;
559 gfx_coord2_subtract(&pos, &wnd->orig_pos, &dresize);
560
561 /* Compute new rectangle */
562 ds_window_calc_resize(wnd, &dresize, &nrect);
563
564 wnd->state = dsw_idle;
565 ds_client_post_resize_event(wnd->client, wnd, &nrect);
566}
567
568/** Update window position when resizing by mouse drag.
569 *
570 * @param wnd Window
571 * @param event Position update event
572 */
573static void ds_window_update_resize(ds_window_t *wnd, pos_event_t *event)
574{
575 gfx_coord2_t pos;
576 gfx_coord2_t dresize;
577 gfx_rect_t nrect;
578 gfx_rect_t drect;
579 gfx_color_t *color;
580 gfx_context_t *gc;
581 errno_t rc;
582
583 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
584 (int) event->hpos, (int) event->vpos);
585
586 if (wnd->state != dsw_resizing)
587 return;
588
589 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
590
591 gc = ds_display_get_gc(wnd->display); // XXX
592 if (gc != NULL) {
593 gfx_set_color(gc, wnd->display->bg_color);
594 gfx_fill_rect(gc, &drect);
595 }
596
597 pos.x = event->hpos;
598 pos.y = event->vpos;
599 gfx_coord2_subtract(&pos, &wnd->orig_pos, &dresize);
600
601 ds_window_calc_resize(wnd, &dresize, &nrect);
602 gfx_rect_translate(&wnd->dpos, &nrect, &drect);
603
604 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
605 if (rc != EOK)
606 return;
607
608 gc = ds_display_get_gc(wnd->display); // XXX
609 if (gc != NULL) {
610 gfx_set_color(gc, color);
611 gfx_fill_rect(gc, &drect);
612 }
613
614 gfx_color_delete(color);
615}
616
617/** Post keyboard event to window.
618 *
619 * @param wnd Window
620 * @param event Event
621 *
622 * @return EOK on success or an error code
623 */
624errno_t ds_window_post_kbd_event(ds_window_t *wnd, kbd_event_t *event)
625{
626 bool alt_or_shift;
627
628 alt_or_shift = event->mods & (KM_SHIFT | KM_ALT);
629
630 if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_F4) {
631 /* On Alt-F4 or Shift-F4 send close event to the window */
632 ds_client_post_close_event(wnd->client, wnd);
633 return EOK;
634 }
635
636 return ds_client_post_kbd_event(wnd->client, wnd, event);
637}
638
639/** Post position event to window.
640 *
641 * @param wnd Window
642 * @param event Position event
643 */
644errno_t ds_window_post_pos_event(ds_window_t *wnd, pos_event_t *event)
645{
646 pos_event_t tevent;
647 gfx_coord2_t pos;
648 gfx_rect_t drect;
649 bool inside;
650
651 log_msg(LOG_DEFAULT, LVL_DEBUG,
652 "ds_window_post_pos_event type=%d pos=%d,%d\n", event->type,
653 (int) event->hpos, (int) event->vpos);
654
655 pos.x = event->hpos;
656 pos.y = event->vpos;
657 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
658 inside = gfx_pix_inside_rect(&pos, &drect);
659
660 if (event->type == POS_PRESS && event->btn_num == 2 && inside)
661 ds_window_start_move(wnd, event);
662
663 if (event->type == POS_RELEASE) {
664 ds_window_finish_move(wnd, event);
665 ds_window_finish_resize(wnd, event);
666 }
667
668 if (event->type == POS_UPDATE) {
669 ds_window_update_move(wnd, event);
670 ds_window_update_resize(wnd, event);
671 }
672
673 /* Transform event coordinates to window-local */
674 tevent = *event;
675 tevent.hpos -= wnd->dpos.x;
676 tevent.vpos -= wnd->dpos.y;
677
678 return ds_client_post_pos_event(wnd->client, wnd, &tevent);
679}
680
681/** Post focus event to window.
682 *
683 * @param wnd Window
684 */
685errno_t ds_window_post_focus_event(ds_window_t *wnd)
686{
687 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_focus_event\n");
688
689 return ds_client_post_focus_event(wnd->client, wnd);
690}
691
692/** Post unfocus event to window.
693 *
694 * @param wnd Window
695 */
696errno_t ds_window_post_unfocus_event(ds_window_t *wnd)
697{
698 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_unfocus_event\n");
699
700 return ds_client_post_unfocus_event(wnd->client, wnd);
701}
702
703/** Start moving a window, detected by client.
704 *
705 * @param wnd Window
706 * @param pos Position where the pointer was when the move started
707 * relative to the window
708 * @param event Button press event
709 */
710void ds_window_move_req(ds_window_t *wnd, gfx_coord2_t *pos)
711{
712 log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_move_req (%d, %d)",
713 (int) pos->x, (int) pos->y);
714
715 if (wnd->state != dsw_idle)
716 return;
717
718 gfx_coord2_add(&wnd->dpos, pos, &wnd->orig_pos);
719 wnd->state = dsw_moving;
720}
721
722/** Start resizing a window, detected by client.
723 *
724 * @param wnd Window
725 * @param rsztype Resize type (which part of window is being dragged)
726 * @param pos Position where the pointer was when the resize started
727 * relative to the window
728 * @param event Button press event
729 */
730void ds_window_resize_req(ds_window_t *wnd, display_wnd_rsztype_t rsztype,
731 gfx_coord2_t *pos)
732{
733 log_msg(LOG_DEFAULT, LVL_NOTE, "ds_window_resize_req (%d, %d, %d)",
734 (int) rsztype, (int) pos->x, (int) pos->y);
735
736 if (wnd->state != dsw_idle)
737 return;
738
739 gfx_coord2_add(&wnd->dpos, pos, &wnd->orig_pos);
740 wnd->state = dsw_resizing;
741 wnd->rsztype = rsztype;
742}
743
744/** Compute new window rectangle after resize operation.
745 *
746 * @param wnd Window which is being resized (in dsw_resizing state and thus
747 * has rsztype set)
748 * @param dresize Amount by which to resize
749 * @param nrect Place to store new rectangle
750 */
751void ds_window_calc_resize(ds_window_t *wnd, gfx_coord2_t *dresize,
752 gfx_rect_t *nrect)
753{
754 if ((wnd->rsztype & display_wr_top) != 0) {
755 nrect->p0.y = min(wnd->rect.p0.y + dresize->y,
756 wnd->rect.p1.y - wnd->min_size.y);
757 } else {
758 nrect->p0.y = wnd->rect.p0.y;
759 }
760
761 if ((wnd->rsztype & display_wr_left) != 0) {
762 nrect->p0.x = min(wnd->rect.p0.x + dresize->x,
763 wnd->rect.p1.x - wnd->min_size.x);
764 } else {
765 nrect->p0.x = wnd->rect.p0.x;
766 }
767
768 if ((wnd->rsztype & display_wr_bottom) != 0) {
769 nrect->p1.y = max(wnd->rect.p1.y + dresize->y,
770 wnd->rect.p0.y + wnd->min_size.y);
771 } else {
772 nrect->p1.y = wnd->rect.p1.y;
773 }
774
775 if ((wnd->rsztype & display_wr_right) != 0) {
776 nrect->p1.x = max(wnd->rect.p1.x + dresize->x,
777 wnd->rect.p0.x + wnd->min_size.x);
778 } else {
779 nrect->p1.x = wnd->rect.p1.x;
780 }
781}
782
783/** @}
784 */
Note: See TracBrowser for help on using the repository browser.