source: mainline/uspace/srv/hid/display/display.c@ 1e4a937

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

Tone down on message verbosity

  • Property mode set to 100644
File size: 11.2 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 display
34 */
35
36#include <errno.h>
37#include <gfx/context.h>
38#include <gfx/render.h>
39#include <io/log.h>
40#include <stdlib.h>
41#include "client.h"
42#include "seat.h"
43#include "window.h"
44#include "display.h"
45
46/** Create display.
47 *
48 * @param gc Graphics context for displaying output
49 * @param rdisp Place to store pointer to new display.
50 * @return EOK on success, ENOMEM if out of memory
51 */
52errno_t ds_display_create(gfx_context_t *gc, ds_display_t **rdisp)
53{
54 ds_display_t *disp;
55 errno_t rc;
56
57 disp = calloc(1, sizeof(ds_display_t));
58 if (disp == NULL)
59 return ENOMEM;
60
61 rc = gfx_color_new_rgb_i16(0x8000, 0xc800, 0xffff, &disp->bg_color);
62 if (rc != EOK) {
63 free(disp);
64 return ENOMEM;
65 }
66
67 list_initialize(&disp->clients);
68 disp->next_wnd_id = 1;
69 list_initialize(&disp->ddevs);
70 list_initialize(&disp->seats);
71 list_initialize(&disp->windows);
72 *rdisp = disp;
73 return EOK;
74}
75
76/** Destroy display.
77 *
78 * @param disp Display
79 */
80void ds_display_destroy(ds_display_t *disp)
81{
82 assert(list_empty(&disp->clients));
83 assert(list_empty(&disp->seats));
84 gfx_color_delete(disp->bg_color);
85 free(disp);
86}
87
88/** Add client to display.
89 *
90 * @param disp Display
91 * @param client Client
92 */
93void ds_display_add_client(ds_display_t *disp, ds_client_t *client)
94{
95 assert(client->display == NULL);
96 assert(!link_used(&client->lclients));
97
98 client->display = disp;
99 list_append(&client->lclients, &disp->clients);
100}
101
102/** Remove client from display.
103 *
104 * @param client Client
105 */
106void ds_display_remove_client(ds_client_t *client)
107{
108 list_remove(&client->lclients);
109 client->display = NULL;
110}
111
112/** Get first client in display.
113 *
114 * @param disp Display
115 * @return First client or @c NULL if there is none
116 */
117ds_client_t *ds_display_first_client(ds_display_t *disp)
118{
119 link_t *link = list_first(&disp->clients);
120
121 if (link == NULL)
122 return NULL;
123
124 return list_get_instance(link, ds_client_t, lclients);
125}
126
127/** Get next client in display.
128 *
129 * @param client Current client
130 * @return Next client or @c NULL if there is none
131 */
132ds_client_t *ds_display_next_client(ds_client_t *client)
133{
134 link_t *link = list_next(&client->lclients, &client->display->clients);
135
136 if (link == NULL)
137 return NULL;
138
139 return list_get_instance(link, ds_client_t, lclients);
140}
141
142/** Find window in all clients by ID.
143 *
144 * XXX This is just a hack needed to match GC connection to a window,
145 * as we don't have a good safe way to pass the GC endpoint to our client
146 * on demand.
147 *
148 * @param display Display
149 * @param id Window ID
150 */
151#include <stdio.h>
152ds_window_t *ds_display_find_window(ds_display_t *display, ds_wnd_id_t id)
153{
154 ds_client_t *client;
155 ds_window_t *wnd;
156
157 printf("ds_display_find_window: id=0x%x\n", (unsigned) id);
158
159 client = ds_display_first_client(display);
160 while (client != NULL) {
161 printf("ds_display_find_window: client=%p\n", client);
162 wnd = ds_client_find_window(client, id);
163 if (wnd != NULL) {
164 printf("ds_display_find_window: found wnd=%p id=0x%x\n",
165 wnd, (unsigned) wnd->id);
166 return wnd;
167 }
168 client = ds_display_next_client(client);
169 }
170
171 printf("ds_display_find_window: not found\n");
172 return NULL;
173}
174
175/** Find window by display position.
176 *
177 * @param display Display
178 * @param pos Display position
179 */
180ds_window_t *ds_display_window_by_pos(ds_display_t *display, gfx_coord2_t *pos)
181{
182 ds_window_t *wnd;
183 gfx_rect_t drect;
184
185 wnd = ds_display_first_window(display);
186 while (wnd != NULL) {
187 /* Window bounding rectangle on display */
188 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
189
190 if (gfx_pix_inside_rect(pos, &drect))
191 return wnd;
192
193 wnd = ds_display_next_window(wnd);
194 }
195
196 return NULL;
197}
198
199/** Add window to display.
200 *
201 * @param display Display
202 * @param wnd Window
203 */
204void ds_display_add_window(ds_display_t *display, ds_window_t *wnd)
205{
206 assert(wnd->display == NULL);
207 assert(!link_used(&wnd->ldwindows));
208
209 wnd->display = display;
210 list_prepend(&wnd->ldwindows, &display->windows);
211}
212
213/** Remove window from display.
214 *
215 * @param wnd Window
216 */
217void ds_display_remove_window(ds_window_t *wnd)
218{
219 list_remove(&wnd->ldwindows);
220 wnd->display = NULL;
221}
222
223/** Get first window in display.
224 *
225 * @param display Display
226 * @return First window or @c NULL if there is none
227 */
228ds_window_t *ds_display_first_window(ds_display_t *display)
229{
230 link_t *link = list_first(&display->windows);
231
232 if (link == NULL)
233 return NULL;
234
235 return list_get_instance(link, ds_window_t, ldwindows);
236}
237
238/** Get last window in display.
239 *
240 * @param display Display
241 * @return Last window or @c NULL if there is none
242 */
243ds_window_t *ds_display_last_window(ds_display_t *display)
244{
245 link_t *link = list_last(&display->windows);
246
247 if (link == NULL)
248 return NULL;
249
250 return list_get_instance(link, ds_window_t, ldwindows);
251}
252
253/** Get next window in client.
254 *
255 * @param wnd Current window
256 * @return Next window or @c NULL if there is none
257 */
258ds_window_t *ds_display_next_window(ds_window_t *wnd)
259{
260 link_t *link = list_next(&wnd->ldwindows, &wnd->display->windows);
261
262 if (link == NULL)
263 return NULL;
264
265 return list_get_instance(link, ds_window_t, ldwindows);
266}
267
268/** Get previous window in client.
269 *
270 * @param wnd Current window
271 * @return Previous window or @c NULL if there is none
272 */
273ds_window_t *ds_display_prev_window(ds_window_t *wnd)
274{
275 link_t *link = list_prev(&wnd->ldwindows, &wnd->display->windows);
276
277 if (link == NULL)
278 return NULL;
279
280 return list_get_instance(link, ds_window_t, ldwindows);
281}
282
283/** Post keyboard event to a display.
284 *
285 * The event is routed to the correct window by first determining the
286 * seat the keyboard device belongs to and then the event is sent to the
287 * window focused by that seat.
288 *
289 * @param display Display
290 * @param event Event
291 */
292errno_t ds_display_post_kbd_event(ds_display_t *display, kbd_event_t *event)
293{
294 ds_seat_t *seat;
295
296 // TODO Determine which seat the event belongs to
297 seat = ds_display_first_seat(display);
298 if (seat == NULL)
299 return EOK;
300
301 return ds_seat_post_kbd_event(seat, event);
302}
303
304/** Post position event to a display.
305 *
306 * @param display Display
307 * @param event Event
308 */
309errno_t ds_display_post_ptd_event(ds_display_t *display, ptd_event_t *event)
310{
311 ds_seat_t *seat;
312
313 // TODO Determine which seat the event belongs to
314 seat = ds_display_first_seat(display);
315 if (seat == NULL)
316 return EOK;
317
318 return ds_seat_post_ptd_event(seat, event);
319}
320
321/** Add seat to display.
322 *
323 * @param disp Display
324 * @param seat Seat
325 */
326void ds_display_add_seat(ds_display_t *disp, ds_seat_t *seat)
327{
328 assert(seat->display == NULL);
329 assert(!link_used(&seat->lseats));
330
331 seat->display = disp;
332 list_append(&seat->lseats, &disp->seats);
333}
334
335/** Remove seat from display.
336 *
337 * @param seat Seat
338 */
339void ds_display_remove_seat(ds_seat_t *seat)
340{
341 list_remove(&seat->lseats);
342 seat->display = NULL;
343}
344
345/** Get first seat in display.
346 *
347 * @param disp Display
348 * @return First seat or @c NULL if there is none
349 */
350ds_seat_t *ds_display_first_seat(ds_display_t *disp)
351{
352 link_t *link = list_first(&disp->seats);
353
354 if (link == NULL)
355 return NULL;
356
357 return list_get_instance(link, ds_seat_t, lseats);
358}
359
360/** Get next seat in display.
361 *
362 * @param seat Current seat
363 * @return Next seat or @c NULL if there is none
364 */
365ds_seat_t *ds_display_next_seat(ds_seat_t *seat)
366{
367 link_t *link = list_next(&seat->lseats, &seat->display->seats);
368
369 if (link == NULL)
370 return NULL;
371
372 return list_get_instance(link, ds_seat_t, lseats);
373}
374
375/** Add display device to display.
376 *
377 * @param disp Display
378 * @param ddev Display device
379 */
380void ds_display_add_ddev(ds_display_t *disp, ds_ddev_t *ddev)
381{
382 assert(ddev->display == NULL);
383 assert(!link_used(&ddev->lddevs));
384
385 /* Set display dimensions to dimensions of first display device */
386 if (gfx_rect_is_empty(&disp->rect))
387 disp->rect = ddev->info.rect;
388
389 ddev->display = disp;
390 list_append(&ddev->lddevs, &disp->ddevs);
391}
392
393/** Remove display device from display.
394 *
395 * @param ddev Display device
396 */
397void ds_display_remove_ddev(ds_ddev_t *ddev)
398{
399 list_remove(&ddev->lddevs);
400 ddev->display = NULL;
401}
402
403/** Get first display device in display.
404 *
405 * @param disp Display
406 * @return First display device or @c NULL if there is none
407 */
408ds_ddev_t *ds_display_first_ddev(ds_display_t *disp)
409{
410 link_t *link = list_first(&disp->ddevs);
411
412 if (link == NULL)
413 return NULL;
414
415 return list_get_instance(link, ds_ddev_t, lddevs);
416}
417
418/** Get next display device in display.
419 *
420 * @param ddev Current display device
421 * @return Next display device or @c NULL if there is none
422 */
423ds_ddev_t *ds_display_next_ddev(ds_ddev_t *ddev)
424{
425 link_t *link = list_next(&ddev->lddevs, &ddev->display->ddevs);
426
427 if (link == NULL)
428 return NULL;
429
430 return list_get_instance(link, ds_ddev_t, lddevs);
431}
432
433// XXX
434gfx_context_t *ds_display_get_gc(ds_display_t *display)
435{
436 ds_ddev_t *ddev;
437
438 ddev = ds_display_first_ddev(display);
439 if (ddev == NULL)
440 return NULL;
441
442 return ddev->gc;
443}
444
445/** Paint display background.
446 *
447 * @param display Display
448 * @param rect Bounding rectangle or @c NULL to repaint entire display
449 */
450errno_t ds_display_paint_bg(ds_display_t *disp, gfx_rect_t *rect)
451{
452 gfx_rect_t crect;
453 gfx_context_t *gc;
454 errno_t rc;
455
456 if (rect != NULL)
457 gfx_rect_clip(&disp->rect, rect, &crect);
458 else
459 crect = disp->rect;
460
461 gc = ds_display_get_gc(disp); // XXX
462 if (gc == NULL)
463 return EOK;
464
465 rc = gfx_set_color(gc, disp->bg_color);
466 if (rc != EOK)
467 return rc;
468
469 return gfx_fill_rect(gc, &crect);
470}
471
472/** Paint display.
473 *
474 * @param display Display
475 * @param rect Bounding rectangle or @c NULL to repaint entire display
476 */
477errno_t ds_display_paint(ds_display_t *disp, gfx_rect_t *rect)
478{
479 errno_t rc;
480 ds_window_t *wnd;
481
482 /* Paint background */
483 rc = ds_display_paint_bg(disp, rect);
484 if (rc != EOK)
485 return rc;
486
487 /* Paint windows bottom to top */
488 wnd = ds_display_last_window(disp);
489 while (wnd != NULL) {
490 rc = ds_window_paint(wnd, rect);
491 if (rc != EOK)
492 return rc;
493
494 wnd = ds_display_prev_window(wnd);
495 }
496
497 return EOK;
498}
499
500/** @}
501 */
Note: See TracBrowser for help on using the repository browser.