source: mainline/uspace/lib/ui/test/wdecor.c@ 58a67050

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

Centralize computation of window decoration geometry

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/*
2 * Copyright (c) 2020 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#include <gfx/context.h>
30#include <gfx/coord.h>
31#include <mem.h>
32#include <pcut/pcut.h>
33#include <stdbool.h>
34#include <ui/pbutton.h>
35#include <ui/resource.h>
36#include <ui/wdecor.h>
37#include "../private/wdecor.h"
38
39PCUT_INIT;
40
41PCUT_TEST_SUITE(wdecor);
42
43static errno_t testgc_set_color(void *, gfx_color_t *);
44static errno_t testgc_fill_rect(void *, gfx_rect_t *);
45static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
46 gfx_bitmap_alloc_t *, void **);
47static errno_t testgc_bitmap_destroy(void *);
48static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
49static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
50
51static gfx_context_ops_t ops = {
52 .set_color = testgc_set_color,
53 .fill_rect = testgc_fill_rect,
54 .bitmap_create = testgc_bitmap_create,
55 .bitmap_destroy = testgc_bitmap_destroy,
56 .bitmap_render = testgc_bitmap_render,
57 .bitmap_get_alloc = testgc_bitmap_get_alloc
58};
59
60static void test_wdecor_close(ui_wdecor_t *, void *);
61static void test_wdecor_move(ui_wdecor_t *, void *, gfx_coord2_t *);
62
63static ui_wdecor_cb_t test_wdecor_cb = {
64 .close = test_wdecor_close,
65 .move = test_wdecor_move
66};
67
68static ui_wdecor_cb_t dummy_wdecor_cb = {
69};
70
71typedef struct {
72 bool bm_created;
73 bool bm_destroyed;
74 gfx_bitmap_params_t bm_params;
75 void *bm_pixels;
76 gfx_rect_t bm_srect;
77 gfx_coord2_t bm_offs;
78 bool bm_rendered;
79 bool bm_got_alloc;
80} test_gc_t;
81
82typedef struct {
83 test_gc_t *tgc;
84 gfx_bitmap_alloc_t alloc;
85 bool myalloc;
86} testgc_bitmap_t;
87
88typedef struct {
89 bool close;
90 bool move;
91 gfx_coord2_t pos;
92} test_cb_resp_t;
93
94/** Create and destroy button */
95PCUT_TEST(create_destroy)
96{
97 ui_wdecor_t *wdecor = NULL;
98 errno_t rc;
99
100 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
101 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
102 PCUT_ASSERT_NOT_NULL(wdecor);
103
104 ui_wdecor_destroy(wdecor);
105}
106
107/** ui_wdecor_destroy() can take NULL argument (no-op) */
108PCUT_TEST(destroy_null)
109{
110 ui_wdecor_destroy(NULL);
111}
112
113/** Set window decoration rectangle sets internal field */
114PCUT_TEST(set_rect)
115{
116 ui_wdecor_t *wdecor;
117 gfx_rect_t rect;
118 errno_t rc;
119
120 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
121 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
122
123 rect.p0.x = 1;
124 rect.p0.y = 2;
125 rect.p1.x = 3;
126 rect.p1.y = 4;
127
128 ui_wdecor_set_rect(wdecor, &rect);
129 PCUT_ASSERT_INT_EQUALS(rect.p0.x, wdecor->rect.p0.x);
130 PCUT_ASSERT_INT_EQUALS(rect.p0.y, wdecor->rect.p0.y);
131 PCUT_ASSERT_INT_EQUALS(rect.p1.x, wdecor->rect.p1.x);
132 PCUT_ASSERT_INT_EQUALS(rect.p1.y, wdecor->rect.p1.y);
133
134 ui_wdecor_destroy(wdecor);
135}
136
137/** Set window decoration active sets internal field */
138PCUT_TEST(set_active)
139{
140 ui_wdecor_t *wdecor;
141 errno_t rc;
142
143 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
144 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
145
146 PCUT_ASSERT_TRUE(wdecor->active);
147
148 ui_wdecor_set_active(wdecor, false);
149 PCUT_ASSERT_FALSE(wdecor->active);
150
151 ui_wdecor_set_active(wdecor, true);
152 PCUT_ASSERT_TRUE(wdecor->active);
153
154 ui_wdecor_destroy(wdecor);
155}
156
157/** Paint button */
158PCUT_TEST(paint)
159{
160 errno_t rc;
161 gfx_context_t *gc = NULL;
162 test_gc_t tgc;
163 ui_resource_t *resource = NULL;
164 ui_wdecor_t *wdecor;
165
166 memset(&tgc, 0, sizeof(tgc));
167 rc = gfx_context_new(&ops, &tgc, &gc);
168 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
169
170 rc = ui_resource_create(gc, &resource);
171 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
172 PCUT_ASSERT_NOT_NULL(resource);
173
174 rc = ui_wdecor_create(resource, "Hello", &wdecor);
175 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
176
177 rc = ui_wdecor_paint(wdecor);
178 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
179
180 ui_wdecor_destroy(wdecor);
181 ui_resource_destroy(resource);
182
183 rc = gfx_context_delete(gc);
184 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
185}
186
187/** Test ui_wdecor_close() */
188PCUT_TEST(close)
189{
190 errno_t rc;
191 ui_wdecor_t *wdecor;
192 test_cb_resp_t resp;
193
194 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
195 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
196
197 /* Close callback with no callbacks set */
198 ui_wdecor_close(wdecor);
199
200 /* Close callback with close callback not implemented */
201 ui_wdecor_set_cb(wdecor, &dummy_wdecor_cb, NULL);
202 ui_wdecor_close(wdecor);
203
204 /* Close callback with real callback set */
205 resp.close = false;
206 ui_wdecor_set_cb(wdecor, &test_wdecor_cb, &resp);
207 ui_wdecor_close(wdecor);
208 PCUT_ASSERT_TRUE(resp.close);
209
210 ui_wdecor_destroy(wdecor);
211}
212
213/** Test ui_wdecor_move() */
214PCUT_TEST(move)
215{
216 errno_t rc;
217 ui_wdecor_t *wdecor;
218 test_cb_resp_t resp;
219 gfx_coord2_t pos;
220
221 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
222 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
223
224 pos.x = 3;
225 pos.y = 4;
226
227 /* Move callback with no callbacks set */
228 ui_wdecor_move(wdecor, &pos);
229
230 /* Move callback with move callback not implemented */
231 ui_wdecor_set_cb(wdecor, &dummy_wdecor_cb, NULL);
232 ui_wdecor_move(wdecor, &pos);
233
234 /* Move callback with real callback set */
235 resp.move = false;
236 resp.pos.x = 0;
237 resp.pos.y = 0;
238 ui_wdecor_set_cb(wdecor, &test_wdecor_cb, &resp);
239 ui_wdecor_move(wdecor, &pos);
240 PCUT_ASSERT_TRUE(resp.move);
241 PCUT_ASSERT_INT_EQUALS(pos.x, resp.pos.x);
242 PCUT_ASSERT_INT_EQUALS(pos.y, resp.pos.y);
243
244 ui_wdecor_destroy(wdecor);
245}
246
247/** Clicking the close button generates close callback */
248PCUT_TEST(close_btn_clicked)
249{
250 ui_wdecor_t *wdecor;
251 gfx_rect_t rect;
252 test_cb_resp_t resp;
253 errno_t rc;
254
255 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
256 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
257
258 rect.p0.x = 10;
259 rect.p0.y = 20;
260 rect.p1.x = 100;
261 rect.p1.y = 200;
262
263 ui_wdecor_set_rect(wdecor, &rect);
264
265 ui_wdecor_set_cb(wdecor, &test_wdecor_cb, (void *) &resp);
266
267 resp.close = false;
268
269 ui_pbutton_clicked(wdecor->btn_close);
270 PCUT_ASSERT_TRUE(resp.close);
271
272 ui_wdecor_destroy(wdecor);
273}
274
275/** Button press on title bar generates move callback */
276PCUT_TEST(pos_event_move)
277{
278 ui_wdecor_t *wdecor;
279 gfx_rect_t rect;
280 pos_event_t event;
281 test_cb_resp_t resp;
282 errno_t rc;
283
284 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
285 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
286
287 rect.p0.x = 10;
288 rect.p0.y = 20;
289 rect.p1.x = 100;
290 rect.p1.y = 200;
291
292 ui_wdecor_set_rect(wdecor, &rect);
293
294 ui_wdecor_set_cb(wdecor, &test_wdecor_cb, (void *) &resp);
295
296 resp.move = false;
297 resp.pos.x = 0;
298 resp.pos.y = 0;
299
300 event.type = POS_PRESS;
301 event.hpos = 50;
302 event.vpos = 25;
303 ui_wdecor_pos_event(wdecor, &event);
304
305 PCUT_ASSERT_TRUE(resp.move);
306 PCUT_ASSERT_INT_EQUALS(event.hpos, resp.pos.x);
307 PCUT_ASSERT_INT_EQUALS(event.vpos, resp.pos.y);
308
309 ui_wdecor_destroy(wdecor);
310}
311
312PCUT_TEST(get_geom)
313{
314 ui_wdecor_t *wdecor;
315 gfx_rect_t rect;
316 ui_wdecor_geom_t geom;
317 errno_t rc;
318
319 rc = ui_wdecor_create(NULL, "Hello", &wdecor);
320 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
321
322 rect.p0.x = 10;
323 rect.p0.y = 20;
324 rect.p1.x = 100;
325 rect.p1.y = 200;
326
327 ui_wdecor_set_rect(wdecor, &rect);
328 ui_wdecor_get_geom(wdecor, &geom);
329
330 PCUT_ASSERT_INT_EQUALS(14, geom.interior_rect.p0.x);
331 PCUT_ASSERT_INT_EQUALS(24, geom.interior_rect.p0.y);
332 PCUT_ASSERT_INT_EQUALS(96, geom.interior_rect.p1.x);
333 PCUT_ASSERT_INT_EQUALS(196, geom.interior_rect.p1.y);
334
335 PCUT_ASSERT_INT_EQUALS(14, geom.title_bar_rect.p0.x);
336 PCUT_ASSERT_INT_EQUALS(24, geom.title_bar_rect.p0.y);
337 PCUT_ASSERT_INT_EQUALS(96, geom.title_bar_rect.p1.x);
338 PCUT_ASSERT_INT_EQUALS(46, geom.title_bar_rect.p1.y);
339
340 PCUT_ASSERT_INT_EQUALS(75, geom.btn_close_rect.p0.x);
341 PCUT_ASSERT_INT_EQUALS(25, geom.btn_close_rect.p0.y);
342 PCUT_ASSERT_INT_EQUALS(95, geom.btn_close_rect.p1.x);
343 PCUT_ASSERT_INT_EQUALS(45, geom.btn_close_rect.p1.y);
344
345 PCUT_ASSERT_INT_EQUALS(14, geom.app_area_rect.p0.x);
346 PCUT_ASSERT_INT_EQUALS(46, geom.app_area_rect.p0.y);
347 PCUT_ASSERT_INT_EQUALS(96, geom.app_area_rect.p1.x);
348 PCUT_ASSERT_INT_EQUALS(196, geom.app_area_rect.p1.y);
349
350 ui_wdecor_destroy(wdecor);
351}
352
353static errno_t testgc_set_color(void *arg, gfx_color_t *color)
354{
355 (void) arg;
356 (void) color;
357 return EOK;
358}
359
360static errno_t testgc_fill_rect(void *arg, gfx_rect_t *rect)
361{
362 (void) arg;
363 (void) rect;
364 return EOK;
365}
366
367static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
368 gfx_bitmap_alloc_t *alloc, void **rbm)
369{
370 test_gc_t *tgc = (test_gc_t *) arg;
371 testgc_bitmap_t *tbm;
372
373 tbm = calloc(1, sizeof(testgc_bitmap_t));
374 if (tbm == NULL)
375 return ENOMEM;
376
377 if (alloc == NULL) {
378 tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
379 sizeof(uint32_t);
380 tbm->alloc.off0 = 0;
381 tbm->alloc.pixels = calloc(sizeof(uint32_t),
382 (params->rect.p1.x - params->rect.p0.x) *
383 (params->rect.p1.y - params->rect.p0.y));
384 tbm->myalloc = true;
385 if (tbm->alloc.pixels == NULL) {
386 free(tbm);
387 return ENOMEM;
388 }
389 } else {
390 tbm->alloc = *alloc;
391 }
392
393 tbm->tgc = tgc;
394 tgc->bm_created = true;
395 tgc->bm_params = *params;
396 tgc->bm_pixels = tbm->alloc.pixels;
397 *rbm = (void *)tbm;
398 return EOK;
399}
400
401static errno_t testgc_bitmap_destroy(void *bm)
402{
403 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
404 if (tbm->myalloc)
405 free(tbm->alloc.pixels);
406 tbm->tgc->bm_destroyed = true;
407 free(tbm);
408 return EOK;
409}
410
411static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
412 gfx_coord2_t *offs)
413{
414 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
415 tbm->tgc->bm_rendered = true;
416 tbm->tgc->bm_srect = *srect;
417 tbm->tgc->bm_offs = *offs;
418 return EOK;
419}
420
421static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
422{
423 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
424 *alloc = tbm->alloc;
425 tbm->tgc->bm_got_alloc = true;
426 return EOK;
427}
428
429static void test_wdecor_close(ui_wdecor_t *wdecor, void *arg)
430{
431 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
432
433 resp->close = true;
434}
435
436static void test_wdecor_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos)
437{
438 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
439
440 resp->move = true;
441 resp->pos = *pos;
442}
443
444PCUT_EXPORT(wdecor);
Note: See TracBrowser for help on using the repository browser.