source: mainline/uspace/srv/hid/display/display.c@ 2012fe0

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

Repaint display when finished moving a window

  • Property mode set to 100644
File size: 11.1 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 printf("ds_display_post_ptd_event: seat=%p\n", seat);
316 if (seat == NULL)
317 return EOK;
318
319 return ds_seat_post_ptd_event(seat, event);
320}
321
322/** Add seat to display.
323 *
324 * @param disp Display
325 * @param seat Seat
326 */
327void ds_display_add_seat(ds_display_t *disp, ds_seat_t *seat)
328{
329 assert(seat->display == NULL);
330 assert(!link_used(&seat->lseats));
331
332 seat->display = disp;
333 list_append(&seat->lseats, &disp->seats);
334}
335
336/** Remove seat from display.
337 *
338 * @param seat Seat
339 */
340void ds_display_remove_seat(ds_seat_t *seat)
341{
342 list_remove(&seat->lseats);
343 seat->display = NULL;
344}
345
346/** Get first seat in display.
347 *
348 * @param disp Display
349 * @return First seat or @c NULL if there is none
350 */
351ds_seat_t *ds_display_first_seat(ds_display_t *disp)
352{
353 link_t *link = list_first(&disp->seats);
354
355 if (link == NULL)
356 return NULL;
357
358 return list_get_instance(link, ds_seat_t, lseats);
359}
360
361/** Get next seat in display.
362 *
363 * @param seat Current seat
364 * @return Next seat or @c NULL if there is none
365 */
366ds_seat_t *ds_display_next_seat(ds_seat_t *seat)
367{
368 link_t *link = list_next(&seat->lseats, &seat->display->seats);
369
370 if (link == NULL)
371 return NULL;
372
373 return list_get_instance(link, ds_seat_t, lseats);
374}
375
376/** Add display device to display.
377 *
378 * @param disp Display
379 * @param ddev Display device
380 */
381void ds_display_add_ddev(ds_display_t *disp, ds_ddev_t *ddev)
382{
383 assert(ddev->display == NULL);
384 assert(!link_used(&ddev->lddevs));
385
386 ddev->display = disp;
387 list_append(&ddev->lddevs, &disp->ddevs);
388}
389
390/** Remove display device from display.
391 *
392 * @param ddev Display device
393 */
394void ds_display_remove_ddev(ds_ddev_t *ddev)
395{
396 list_remove(&ddev->lddevs);
397 ddev->display = NULL;
398}
399
400/** Get first display device in display.
401 *
402 * @param disp Display
403 * @return First display device or @c NULL if there is none
404 */
405ds_ddev_t *ds_display_first_ddev(ds_display_t *disp)
406{
407 link_t *link = list_first(&disp->ddevs);
408
409 if (link == NULL)
410 return NULL;
411
412 return list_get_instance(link, ds_ddev_t, lddevs);
413}
414
415/** Get next display device in display.
416 *
417 * @param ddev Current display device
418 * @return Next display device or @c NULL if there is none
419 */
420ds_ddev_t *ds_display_next_ddev(ds_ddev_t *ddev)
421{
422 link_t *link = list_next(&ddev->lddevs, &ddev->display->ddevs);
423
424 if (link == NULL)
425 return NULL;
426
427 return list_get_instance(link, ds_ddev_t, lddevs);
428}
429
430// XXX
431gfx_context_t *ds_display_get_gc(ds_display_t *display)
432{
433 ds_ddev_t *ddev;
434
435 ddev = ds_display_first_ddev(display);
436 if (ddev == NULL)
437 return NULL;
438
439 return ddev->gc;
440}
441
442/** Paint display background.
443 *
444 * @param display Display
445 * @param rect Bounding rectangle or @c NULL to repaint entire display
446 */
447errno_t ds_display_paint_bg(ds_display_t *disp, gfx_rect_t *rect)
448{
449 gfx_rect_t dsrect;
450 gfx_rect_t crect;
451 gfx_context_t *gc;
452 errno_t rc;
453
454 dsrect.p0.x = 0;
455 dsrect.p0.y = 0;
456 dsrect.p1.x = 1024;
457 dsrect.p1.y = 768;
458
459 if (rect != NULL)
460 gfx_rect_clip(&dsrect, rect, &crect);
461 else
462 crect = dsrect;
463
464 gc = ds_display_get_gc(disp); // XXX
465
466 rc = gfx_set_color(gc, disp->bg_color);
467 if (rc != EOK)
468 return rc;
469
470 return gfx_fill_rect(gc, &crect);
471}
472
473/** Paint display.
474 *
475 * @param display Display
476 * @param rect Bounding rectangle or @c NULL to repaint entire display
477 */
478errno_t ds_display_paint(ds_display_t *disp, gfx_rect_t *rect)
479{
480 errno_t rc;
481 ds_window_t *wnd;
482
483 /* Paint background */
484 rc = ds_display_paint_bg(disp, rect);
485 if (rc != EOK)
486 return rc;
487
488 /* Paint windows bottom to top */
489 wnd = ds_display_last_window(disp);
490 while (wnd != NULL) {
491 rc = ds_window_paint(wnd, rect);
492 if (rc != EOK)
493 return rc;
494
495 wnd = ds_display_prev_window(wnd);
496 }
497
498 return EOK;
499}
500
501/** @}
502 */
Note: See TracBrowser for help on using the repository browser.