source: mainline/uspace/lib/ui/src/wdecor.c@ 35cffea

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

Maximizing/unmaximizing a window

  • Property mode set to 100644
File size: 21.0 KB
Line 
1/*
2 * Copyright (c) 2022 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 libui
30 * @{
31 */
32/**
33 * @file Window decoration
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <gfx/color.h>
39#include <gfx/context.h>
40#include <gfx/render.h>
41#include <gfx/text.h>
42#include <io/pos_event.h>
43#include <stdlib.h>
44#include <str.h>
45#include <ui/paint.h>
46#include <ui/pbutton.h>
47#include <ui/wdecor.h>
48#include "../private/resource.h"
49#include "../private/wdecor.h"
50
51static void ui_wdecor_btn_max_clicked(ui_pbutton_t *, void *);
52static errno_t ui_wdecor_btn_max_paint(ui_pbutton_t *, void *,
53 gfx_coord2_t *);
54
55static void ui_wdecor_btn_close_clicked(ui_pbutton_t *, void *);
56static errno_t ui_wdecor_btn_close_paint(ui_pbutton_t *, void *,
57 gfx_coord2_t *);
58
59static ui_pbutton_cb_t ui_wdecor_btn_max_cb = {
60 .clicked = ui_wdecor_btn_max_clicked
61};
62
63static ui_pbutton_decor_ops_t ui_wdecor_btn_max_decor_ops = {
64 .paint = ui_wdecor_btn_max_paint
65};
66
67static ui_pbutton_cb_t ui_wdecor_btn_close_cb = {
68 .clicked = ui_wdecor_btn_close_clicked
69};
70
71static ui_pbutton_decor_ops_t ui_wdecor_btn_close_decor_ops = {
72 .paint = ui_wdecor_btn_close_paint
73};
74
75enum {
76 /** Width of corner drag area */
77 wdecor_corner_w = 24,
78 /** Height of corner drag area */
79 wdecor_corner_h = 24,
80 /** Window resizing edge witdth */
81 wdecor_edge_w = 4,
82 /** Window resizing edge height */
83 wdecor_edge_h = 4,
84 /** Title bar height */
85 wdecor_tbar_h = 22,
86 /** Window width */
87 wdecor_frame_w = 4,
88 /** Window frame width in text mode */
89 wdecor_frame_w_text = 1,
90 /** Close button cross leg length */
91 wdecor_close_cross_n = 5,
92 /** Close button cross pen width */
93 wdecor_close_cross_w = 2,
94 /** Close button cross pen height */
95 wdecor_close_cross_h = 1,
96 /** Maximize icon width */
97 wdecor_max_w = 10,
98 /** Maximize icon height */
99 wdecor_max_h = 10,
100 /** Unmaximize icon window width */
101 wdecor_unmax_w = 8,
102 /** Unmaximize icon window height */
103 wdecor_unmax_h = 8,
104 /** Unmaximize icon window horizontal distance */
105 wdecor_unmax_dw = 4,
106 /** Unmaximize icon window vertical distance */
107 wdecor_unmax_dh = 4
108};
109
110/** Create new window decoration.
111 *
112 * @param resource UI resource
113 * @param caption Window caption
114 * @param style Style
115 * @param rwdecor Place to store pointer to new window decoration
116 * @return EOK on success, ENOMEM if out of memory
117 */
118errno_t ui_wdecor_create(ui_resource_t *resource, const char *caption,
119 ui_wdecor_style_t style, ui_wdecor_t **rwdecor)
120{
121 ui_wdecor_t *wdecor;
122 errno_t rc;
123
124 wdecor = calloc(1, sizeof(ui_wdecor_t));
125 if (wdecor == NULL)
126 return ENOMEM;
127
128 wdecor->caption = str_dup(caption);
129 if (wdecor->caption == NULL) {
130 free(wdecor);
131 return ENOMEM;
132 }
133
134 if ((style & ui_wds_maximize_btn) != 0) {
135 rc = ui_pbutton_create(resource, "^", &wdecor->btn_max);
136 if (rc != EOK) {
137 ui_wdecor_destroy(wdecor);
138 return rc;
139 }
140
141 ui_pbutton_set_cb(wdecor->btn_max, &ui_wdecor_btn_max_cb,
142 (void *)wdecor);
143
144 ui_pbutton_set_decor_ops(wdecor->btn_max,
145 &ui_wdecor_btn_max_decor_ops, (void *)wdecor);
146 }
147
148 if ((style & ui_wds_close_btn) != 0) {
149 rc = ui_pbutton_create(resource, "X", &wdecor->btn_close);
150 if (rc != EOK) {
151 ui_wdecor_destroy(wdecor);
152 return rc;
153 }
154
155 ui_pbutton_set_cb(wdecor->btn_close, &ui_wdecor_btn_close_cb,
156 (void *)wdecor);
157
158 ui_pbutton_set_decor_ops(wdecor->btn_close,
159 &ui_wdecor_btn_close_decor_ops, (void *)wdecor);
160 }
161
162 wdecor->res = resource;
163 wdecor->active = true;
164 wdecor->style = style;
165 *rwdecor = wdecor;
166 return EOK;
167}
168
169/** Destroy window decoration.
170 *
171 * @param wdecor Window decoration or @c NULL
172 */
173void ui_wdecor_destroy(ui_wdecor_t *wdecor)
174{
175 if (wdecor == NULL)
176 return;
177
178 ui_pbutton_destroy(wdecor->btn_max);
179 ui_pbutton_destroy(wdecor->btn_close);
180 free(wdecor->caption);
181 free(wdecor);
182}
183
184/** Set window decoration callbacks.
185 *
186 * @param wdecor Window decoration
187 * @param cb Window decoration callbacks
188 * @param arg Callback argument
189 */
190void ui_wdecor_set_cb(ui_wdecor_t *wdecor, ui_wdecor_cb_t *cb, void *arg)
191{
192 wdecor->cb = cb;
193 wdecor->arg = arg;
194}
195
196/** Set window decoration rectangle.
197 *
198 * @param wdecor Window decoration
199 * @param rect New window decoration rectangle
200 */
201void ui_wdecor_set_rect(ui_wdecor_t *wdecor, gfx_rect_t *rect)
202{
203 ui_wdecor_geom_t geom;
204
205 wdecor->rect = *rect;
206
207 ui_wdecor_get_geom(wdecor, &geom);
208
209 if (wdecor->btn_max != NULL)
210 ui_pbutton_set_rect(wdecor->btn_max, &geom.btn_max_rect);
211 if (wdecor->btn_close != NULL)
212 ui_pbutton_set_rect(wdecor->btn_close, &geom.btn_close_rect);
213}
214
215/** Set active flag.
216 *
217 * Active window is the one receiving keyboard events.
218 *
219 * @param wdecor Window decoration
220 * @param active @c true iff window is active
221 */
222void ui_wdecor_set_active(ui_wdecor_t *wdecor, bool active)
223{
224 wdecor->active = active;
225}
226
227/** Set maximized flag.
228 *
229 * Active window is the one receiving keyboard events.
230 *
231 * @param wdecor Window decoration
232 * @param maximized @c true iff window is maximized
233 */
234void ui_wdecor_set_maximized(ui_wdecor_t *wdecor, bool maximized)
235{
236 wdecor->maximized = maximized;
237}
238
239/** Change caption.
240 *
241 * @param wdecor Window decoration
242 * @param caption New caption
243 *
244 * @return EOK on success or an error code
245 */
246errno_t ui_wdecor_set_caption(ui_wdecor_t *wdecor, const char *caption)
247{
248 char *cdup;
249
250 cdup = str_dup(caption);
251 if (cdup == NULL)
252 return ENOMEM;
253
254 free(wdecor->caption);
255 wdecor->caption = cdup;
256
257 ui_wdecor_paint(wdecor);
258 return EOK;
259}
260
261/** Paint window decoration.
262 *
263 * @param wdecor Window decoration
264 * @return EOK on success or an error code
265 */
266errno_t ui_wdecor_paint(ui_wdecor_t *wdecor)
267{
268 errno_t rc;
269 gfx_rect_t rect;
270 gfx_rect_t trect;
271 gfx_rect_t text_rect;
272 gfx_text_fmt_t fmt;
273 gfx_coord2_t pos;
274 ui_wdecor_geom_t geom;
275
276 rect = wdecor->rect;
277 ui_wdecor_get_geom(wdecor, &geom);
278
279 if ((wdecor->style & ui_wds_frame) != 0) {
280
281 if (wdecor->res->textmode != false) {
282 rc = ui_paint_text_box(wdecor->res, &rect,
283 ui_box_double, wdecor->res->wnd_face_color);
284 if (rc != EOK)
285 return rc;
286 } else {
287 rc = ui_paint_outset_frame(wdecor->res, &rect,
288 &rect);
289 if (rc != EOK)
290 return rc;
291
292 rc = ui_paint_bevel(wdecor->res->gc, &rect,
293 wdecor->res->wnd_face_color,
294 wdecor->res->wnd_face_color, 2, &rect);
295 if (rc != EOK)
296 return rc;
297 }
298 }
299
300 if ((wdecor->style & ui_wds_titlebar) != 0) {
301 trect = geom.title_bar_rect;
302
303 if (wdecor->res->textmode == false) {
304 rc = ui_paint_bevel(wdecor->res->gc, &trect,
305 wdecor->res->wnd_shadow_color,
306 wdecor->res->wnd_highlight_color, 1, &trect);
307 if (rc != EOK)
308 return rc;
309
310 rc = gfx_set_color(wdecor->res->gc, wdecor->active ?
311 wdecor->res->tbar_act_bg_color :
312 wdecor->res->tbar_inact_bg_color);
313 if (rc != EOK)
314 return rc;
315
316 rc = gfx_fill_rect(wdecor->res->gc, &trect);
317 if (rc != EOK)
318 return rc;
319 }
320
321 gfx_text_fmt_init(&fmt);
322 fmt.font = wdecor->res->font;
323 fmt.color = wdecor->active ?
324 wdecor->res->tbar_act_text_color :
325 wdecor->res->tbar_inact_text_color;
326 fmt.halign = gfx_halign_center;
327 fmt.valign = gfx_valign_center;
328
329 pos.x = (trect.p0.x + trect.p1.x) / 2;
330 pos.y = (trect.p0.y + trect.p1.y) / 2;
331
332 if (wdecor->res->textmode) {
333 /* Make space around caption text */
334 gfx_text_rect(&pos, &fmt, wdecor->caption, &text_rect);
335
336 /* Only make space if caption is non-empty */
337 if (text_rect.p0.x < text_rect.p1.x) {
338 text_rect.p0.x -= 1;
339 text_rect.p1.x += 1;
340 }
341
342 rc = gfx_set_color(wdecor->res->gc, wdecor->active ?
343 wdecor->res->tbar_act_bg_color :
344 wdecor->res->tbar_inact_bg_color);
345 if (rc != EOK)
346 return rc;
347
348 rc = gfx_fill_rect(wdecor->res->gc, &text_rect);
349 if (rc != EOK)
350 return rc;
351 }
352
353 rc = gfx_puttext(&pos, &fmt, wdecor->caption);
354 if (rc != EOK)
355 return rc;
356
357 if (wdecor->btn_max != NULL) {
358 rc = ui_pbutton_paint(wdecor->btn_max);
359 if (rc != EOK)
360 return rc;
361 }
362
363 if (wdecor->btn_close != NULL) {
364 rc = ui_pbutton_paint(wdecor->btn_close);
365 if (rc != EOK)
366 return rc;
367 }
368 }
369
370 rc = gfx_update(wdecor->res->gc);
371 if (rc != EOK)
372 return rc;
373
374 return EOK;
375}
376
377/** Send decoration maximize event.
378 *
379 * @param wdecor Window decoration
380 */
381void ui_wdecor_maximize(ui_wdecor_t *wdecor)
382{
383 if (wdecor->cb != NULL && wdecor->cb->maximize != NULL)
384 wdecor->cb->maximize(wdecor, wdecor->arg);
385}
386
387/** Send decoration unmaximize event.
388 *
389 * @param wdecor Window decoration
390 */
391void ui_wdecor_unmaximize(ui_wdecor_t *wdecor)
392{
393 if (wdecor->cb != NULL && wdecor->cb->unmaximize != NULL)
394 wdecor->cb->unmaximize(wdecor, wdecor->arg);
395}
396
397/** Send decoration close event.
398 *
399 * @param wdecor Window decoration
400 */
401void ui_wdecor_close(ui_wdecor_t *wdecor)
402{
403 if (wdecor->cb != NULL && wdecor->cb->close != NULL)
404 wdecor->cb->close(wdecor, wdecor->arg);
405}
406
407/** Send decoration move event.
408 *
409 * @param wdecor Window decoration
410 * @param pos Position where the title bar was pressed
411 */
412void ui_wdecor_move(ui_wdecor_t *wdecor, gfx_coord2_t *pos)
413{
414 if (wdecor->cb != NULL && wdecor->cb->move != NULL)
415 wdecor->cb->move(wdecor, wdecor->arg, pos);
416}
417
418/** Send decoration resize event.
419 *
420 * @param wdecor Window decoration
421 * @param rsztype Resize type
422 * @param pos Position where the button was pressed
423 */
424void ui_wdecor_resize(ui_wdecor_t *wdecor, ui_wdecor_rsztype_t rsztype,
425 gfx_coord2_t *pos)
426{
427 if (wdecor->cb != NULL && wdecor->cb->resize != NULL)
428 wdecor->cb->resize(wdecor, wdecor->arg, rsztype, pos);
429}
430
431/** Send cursor change event.
432 *
433 * @param wdecor Window decoration
434 * @param cursor Cursor
435 */
436void ui_wdecor_set_cursor(ui_wdecor_t *wdecor, ui_stock_cursor_t cursor)
437{
438 if (wdecor->cb != NULL && wdecor->cb->set_cursor != NULL)
439 wdecor->cb->set_cursor(wdecor, wdecor->arg, cursor);
440}
441
442/** Get window decoration geometry.
443 *
444 * @param wdecor Window decoration
445 * @param geom Structure to fill in with computed geometry
446 */
447void ui_wdecor_get_geom(ui_wdecor_t *wdecor, ui_wdecor_geom_t *geom)
448{
449 gfx_coord_t frame_w;
450 gfx_coord_t btn_x;
451 gfx_coord_t btn_y;
452
453 /* Does window have a frame? */
454 if ((wdecor->style & ui_wds_frame) != 0) {
455 frame_w = wdecor->res->textmode ?
456 wdecor_frame_w_text : wdecor_frame_w;
457
458 geom->interior_rect.p0.x = wdecor->rect.p0.x + frame_w;
459 geom->interior_rect.p0.y = wdecor->rect.p0.y + frame_w;
460 geom->interior_rect.p1.x = wdecor->rect.p1.x - frame_w;
461 geom->interior_rect.p1.y = wdecor->rect.p1.y - frame_w;
462 } else {
463 geom->interior_rect = wdecor->rect;
464 }
465
466 /* Does window have a title bar? */
467 if ((wdecor->style & ui_wds_titlebar) != 0) {
468 if (wdecor->res->textmode) {
469 geom->title_bar_rect.p0 = wdecor->rect.p0;
470 geom->title_bar_rect.p1.x = wdecor->rect.p1.x;
471 geom->title_bar_rect.p1.y = wdecor->rect.p0.y + 1;
472
473 btn_x = geom->title_bar_rect.p1.x - 1;
474 btn_y = geom->title_bar_rect.p0.y;
475 } else {
476 geom->title_bar_rect.p0 = geom->interior_rect.p0;
477 geom->title_bar_rect.p1.x = geom->interior_rect.p1.x;
478 geom->title_bar_rect.p1.y = geom->interior_rect.p0.y +
479 wdecor_tbar_h;
480
481 btn_x = geom->title_bar_rect.p1.x - 1;
482 btn_y = geom->title_bar_rect.p0.y + 1;
483 }
484
485 geom->app_area_rect.p0.x = geom->interior_rect.p0.x;
486 geom->app_area_rect.p0.y = geom->title_bar_rect.p1.y;
487 geom->app_area_rect.p1 = geom->interior_rect.p1;
488
489 } else {
490 geom->title_bar_rect.p0.x = 0;
491 geom->title_bar_rect.p0.y = 0;
492 geom->title_bar_rect.p1.x = 0;
493 geom->title_bar_rect.p1.y = 0;
494
495 geom->app_area_rect = geom->interior_rect;
496 btn_x = 0;
497 btn_y = 0;
498 }
499
500 /* Does window have a close button? */
501 if ((wdecor->style & ui_wds_close_btn) != 0) {
502 if (wdecor->res->textmode == false) {
503 geom->btn_close_rect.p0.x = btn_x - 20;
504 geom->btn_close_rect.p0.y = btn_y;
505 geom->btn_close_rect.p1.x = btn_x;
506 geom->btn_close_rect.p1.y = btn_y + 20;
507
508 btn_x -= 20;
509 } else {
510 geom->btn_close_rect.p0.x = btn_x - 3;
511 geom->btn_close_rect.p0.y = btn_y;
512 geom->btn_close_rect.p1.x = btn_x;
513 geom->btn_close_rect.p1.y = btn_y + 1;
514
515 btn_x -= 3;
516 }
517 } else {
518 geom->btn_close_rect.p0.x = 0;
519 geom->btn_close_rect.p0.y = 0;
520 geom->btn_close_rect.p1.x = 0;
521 geom->btn_close_rect.p1.y = 0;
522 }
523
524 /* Does window have a (un)maximize button? */
525 if ((wdecor->style & ui_wds_maximize_btn) != 0) {
526 if (wdecor->res->textmode == false) {
527 geom->btn_max_rect.p0.x = btn_x - 20;
528 geom->btn_max_rect.p0.y = btn_y;
529 geom->btn_max_rect.p1.x = btn_x;
530 geom->btn_max_rect.p1.y = btn_y + 20;
531 } else {
532 geom->btn_max_rect.p0.x = btn_x - 3;
533 geom->btn_max_rect.p0.y = btn_y;
534 geom->btn_max_rect.p1.x = btn_x;
535 geom->btn_max_rect.p1.y = btn_y + 1;
536 }
537 } else {
538 geom->btn_max_rect.p0.x = 0;
539 geom->btn_max_rect.p0.y = 0;
540 geom->btn_max_rect.p1.x = 0;
541 geom->btn_max_rect.p1.y = 0;
542 }
543}
544
545/** Get outer rectangle from application area rectangle.
546 *
547 * Note that this needs to work just based on a UI, without having an actual
548 * window decoration, since we need it in order to create the window
549 * and its decoration.
550 *
551 * @param style Decoration style
552 * @param app Application area rectangle
553 * @param rect Place to store (outer) window decoration rectangle
554 */
555void ui_wdecor_rect_from_app(ui_wdecor_style_t style, gfx_rect_t *app,
556 gfx_rect_t *rect)
557{
558 *rect = *app;
559
560 if ((style & ui_wds_frame) != 0) {
561 rect->p0.x -= wdecor_edge_w;
562 rect->p0.y -= wdecor_edge_h;
563 rect->p1.x += wdecor_edge_w;
564 rect->p1.y += wdecor_edge_h;
565 }
566
567 if ((style & ui_wds_titlebar) != 0)
568 rect->p0.y -= 22;
569}
570
571/** Application area rectangle from window rectangle.
572 *
573 * Note that this needs to work just based on a UI, without having an actual
574 * window decoration, since we need it in process of resizing the window,
575 * before it is actually resized.
576 *
577 * @param style Decoration style
578 * @param rect Window decoration rectangle
579 * @param app Place to store application area rectangle
580 */
581void ui_wdecor_app_from_rect(ui_wdecor_style_t style, gfx_rect_t *rect,
582 gfx_rect_t *app)
583{
584 *app = *rect;
585
586 if ((style & ui_wds_frame) != 0) {
587 app->p0.x += wdecor_edge_w;
588 app->p0.y += wdecor_edge_h;
589 app->p1.x -= wdecor_edge_w;
590 app->p1.y -= wdecor_edge_h;
591 }
592
593 if ((style & ui_wds_titlebar) != 0)
594 app->p0.y += 22;
595}
596
597/** Get resize type for pointer at the specified position.
598 *
599 * @param wdecor Window decoration
600 * @param pos Pointer position
601 * @return Resize type
602 */
603ui_wdecor_rsztype_t ui_wdecor_get_rsztype(ui_wdecor_t *wdecor,
604 gfx_coord2_t *pos)
605{
606 bool eleft, eright;
607 bool etop, ebottom;
608 bool edge;
609 bool cleft, cright;
610 bool ctop, cbottom;
611
612 /* Window not resizable? */
613 if ((wdecor->style & ui_wds_resizable) == 0)
614 return ui_wr_none;
615
616 /* Window is maximized? */
617 if (wdecor->maximized)
618 return ui_wr_none;
619
620 /* Position not inside window? */
621 if (!gfx_pix_inside_rect(pos, &wdecor->rect))
622 return ui_wr_none;
623
624 /* Position is within edge width from the outside */
625 eleft = (pos->x < wdecor->rect.p0.x + wdecor_edge_w);
626 eright = (pos->x >= wdecor->rect.p1.x - wdecor_edge_w);
627 etop = (pos->y < wdecor->rect.p0.y + wdecor_edge_h);
628 ebottom = (pos->y >= wdecor->rect.p1.y - wdecor_edge_h);
629
630 /* Position is on one of the four edges */
631 edge = eleft || eright || etop || ebottom;
632
633 /* Position is within resize-corner distance from the outside */
634 cleft = (pos->x < wdecor->rect.p0.x + wdecor_corner_w);
635 cright = (pos->x >= wdecor->rect.p1.x - wdecor_corner_w);
636 ctop = (pos->y < wdecor->rect.p0.y + wdecor_corner_h);
637 cbottom = (pos->y >= wdecor->rect.p1.y - wdecor_corner_h);
638
639 /* Top-left corner */
640 if (edge && cleft && ctop)
641 return ui_wr_top_left;
642
643 /* Top-right corner */
644 if (edge && cright && ctop)
645 return ui_wr_top_right;
646
647 /* Bottom-left corner */
648 if (edge && cleft && cbottom)
649 return ui_wr_bottom_left;
650
651 /* Bottom-right corner */
652 if (edge && cright && cbottom)
653 return ui_wr_bottom_right;
654
655 /* Left edge */
656 if (eleft)
657 return ui_wr_left;
658
659 /* Right edge */
660 if (eright)
661 return ui_wr_right;
662
663 /* Top edge */
664 if (etop)
665 return ui_wr_top;
666
667 /* Bottom edge */
668 if (ebottom)
669 return ui_wr_bottom;
670
671 return ui_wr_none;
672}
673
674/** Get stock cursor to use for the specified window resize type.
675 *
676 * The resize type must be valid, otherwise behavior is undefined.
677 *
678 * @param rsztype Resize type
679 * @return Cursor to use for this resize type
680 */
681ui_stock_cursor_t ui_wdecor_cursor_from_rsztype(ui_wdecor_rsztype_t rsztype)
682{
683 switch (rsztype) {
684 case ui_wr_none:
685 return ui_curs_arrow;
686
687 case ui_wr_top:
688 case ui_wr_bottom:
689 return ui_curs_size_ud;
690
691 case ui_wr_left:
692 case ui_wr_right:
693 return ui_curs_size_lr;
694
695 case ui_wr_top_left:
696 case ui_wr_bottom_right:
697 return ui_curs_size_uldr;
698
699 case ui_wr_top_right:
700 case ui_wr_bottom_left:
701 return ui_curs_size_urdl;
702
703 default:
704 assert(false);
705 return ui_curs_arrow;
706 }
707}
708
709/** Handle window frame position event.
710 *
711 * @param wdecor Window decoration
712 * @param pos_event Position event
713 */
714void ui_wdecor_frame_pos_event(ui_wdecor_t *wdecor, pos_event_t *event)
715{
716 gfx_coord2_t pos;
717 ui_wdecor_rsztype_t rsztype;
718 ui_stock_cursor_t cursor;
719
720 pos.x = event->hpos;
721 pos.y = event->vpos;
722
723 /* Set appropriate resizing cursor, or set arrow cursor */
724
725 rsztype = ui_wdecor_get_rsztype(wdecor, &pos);
726 cursor = ui_wdecor_cursor_from_rsztype(rsztype);
727
728 ui_wdecor_set_cursor(wdecor, cursor);
729
730 /* Press on window border? */
731 if (rsztype != ui_wr_none && event->type == POS_PRESS)
732 ui_wdecor_resize(wdecor, rsztype, &pos);
733}
734
735/** Handle window decoration position event.
736 *
737 * @param wdecor Window decoration
738 * @param pos_event Position event
739 * @return @c ui_claimed iff event was claimed
740 */
741ui_evclaim_t ui_wdecor_pos_event(ui_wdecor_t *wdecor, pos_event_t *event)
742{
743 gfx_coord2_t pos;
744 ui_wdecor_geom_t geom;
745 ui_evclaim_t claim;
746
747 pos.x = event->hpos;
748 pos.y = event->vpos;
749
750 ui_wdecor_get_geom(wdecor, &geom);
751
752 if (wdecor->btn_max != NULL) {
753 claim = ui_pbutton_pos_event(wdecor->btn_max, event);
754 if (claim == ui_claimed)
755 return ui_claimed;
756 }
757
758 if (wdecor->btn_close != NULL) {
759 claim = ui_pbutton_pos_event(wdecor->btn_close, event);
760 if (claim == ui_claimed)
761 return ui_claimed;
762 }
763
764 ui_wdecor_frame_pos_event(wdecor, event);
765
766 if ((wdecor->style & ui_wds_titlebar) != 0 && !wdecor->maximized) {
767 if (event->type == POS_PRESS &&
768 gfx_pix_inside_rect(&pos, &geom.title_bar_rect)) {
769 ui_wdecor_move(wdecor, &pos);
770 return ui_claimed;
771 }
772 }
773
774 return ui_unclaimed;
775}
776
777/** Window decoration (un)maximize button was clicked.
778 *
779 * @param pbutton Close button
780 * @param arg Argument (ui_wdecor_t)
781 */
782static void ui_wdecor_btn_max_clicked(ui_pbutton_t *pbutton, void *arg)
783{
784 ui_wdecor_t *wdecor = (ui_wdecor_t *) arg;
785
786 (void) pbutton;
787
788 if (wdecor->maximized)
789 ui_wdecor_unmaximize(wdecor);
790 else
791 ui_wdecor_maximize(wdecor);
792}
793
794/** Paint (un)maximize button decoration.
795 *
796 * @param pbutton Push button
797 * @param arg Argument (ui_wdecor_t *)
798 * @param pos Center position
799 */
800static errno_t ui_wdecor_btn_max_paint(ui_pbutton_t *pbutton,
801 void *arg, gfx_coord2_t *pos)
802{
803 ui_wdecor_t *wdecor = (ui_wdecor_t *)arg;
804 errno_t rc;
805
806 if (wdecor->maximized) {
807 rc = ui_paint_unmaxicon(wdecor->res, pos, wdecor_unmax_w,
808 wdecor_unmax_h, wdecor_unmax_dw, wdecor_unmax_dh);
809 } else {
810 rc = ui_paint_maxicon(wdecor->res, pos, wdecor_max_w,
811 wdecor_max_h);
812 }
813
814 return rc;
815}
816
817/** Window decoration close button was clicked.
818 *
819 * @param pbutton Close button
820 * @param arg Argument (ui_wdecor_t)
821 */
822static void ui_wdecor_btn_close_clicked(ui_pbutton_t *pbutton, void *arg)
823{
824 ui_wdecor_t *wdecor = (ui_wdecor_t *) arg;
825
826 (void) pbutton;
827 ui_wdecor_close(wdecor);
828}
829
830/** Paint close button decoration.
831 *
832 * @param pbutton Push button
833 * @param arg Argument (ui_wdecor_t *)
834 * @param pos Center position
835 */
836static errno_t ui_wdecor_btn_close_paint(ui_pbutton_t *pbutton,
837 void *arg, gfx_coord2_t *pos)
838{
839 ui_wdecor_t *wdecor = (ui_wdecor_t *)arg;
840 gfx_coord2_t p;
841 errno_t rc;
842
843 rc = gfx_set_color(wdecor->res->gc, wdecor->res->btn_text_color);
844 if (rc != EOK)
845 return rc;
846
847 p.x = pos->x - 1;
848 p.y = pos->y - 1;
849 return ui_paint_cross(wdecor->res->gc, &p, wdecor_close_cross_n,
850 wdecor_close_cross_w, wdecor_close_cross_h);
851}
852
853/** @}
854 */
Note: See TracBrowser for help on using the repository browser.