source: mainline/uspace/srv/hid/display/display.c@ cc90846

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cc90846 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
RevLine 
[c8cf261]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/**
[38e5f36c]33 * @file Display server display
[c8cf261]34 */
35
36#include <errno.h>
[159776f]37#include <gfx/context.h>
[c79545e]38#include <gfx/render.h>
[c8cf261]39#include <io/log.h>
[6af4b4f]40#include <stdlib.h>
[b3c185b6]41#include "client.h"
[cf32dbd]42#include "seat.h"
[6af4b4f]43#include "window.h"
[b3c185b6]44#include "display.h"
[c8cf261]45
[6af4b4f]46/** Create display.
47 *
[159776f]48 * @param gc Graphics context for displaying output
[6af4b4f]49 * @param rdisp Place to store pointer to new display.
50 * @return EOK on success, ENOMEM if out of memory
51 */
[159776f]52errno_t ds_display_create(gfx_context_t *gc, ds_display_t **rdisp)
[6af4b4f]53{
54 ds_display_t *disp;
[c79545e]55 errno_t rc;
[6af4b4f]56
57 disp = calloc(1, sizeof(ds_display_t));
58 if (disp == NULL)
59 return ENOMEM;
60
[c79545e]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
[b3c185b6]67 list_initialize(&disp->clients);
68 disp->next_wnd_id = 1;
[87a7cdb]69 list_initialize(&disp->ddevs);
[cf32dbd]70 list_initialize(&disp->seats);
[fd777a2]71 list_initialize(&disp->windows);
[6af4b4f]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{
[b3c185b6]82 assert(list_empty(&disp->clients));
[cf32dbd]83 assert(list_empty(&disp->seats));
[c79545e]84 gfx_color_delete(disp->bg_color);
[6af4b4f]85 free(disp);
86}
87
[b3c185b6]88/** Add client to display.
[6af4b4f]89 *
90 * @param disp Display
[cf32dbd]91 * @param client Client
[6af4b4f]92 */
[b3c185b6]93void ds_display_add_client(ds_display_t *disp, ds_client_t *client)
[6af4b4f]94{
[b3c185b6]95 assert(client->display == NULL);
96 assert(!link_used(&client->lclients));
[6af4b4f]97
[b3c185b6]98 client->display = disp;
99 list_append(&client->lclients, &disp->clients);
[c8cf261]100}
101
[b3c185b6]102/** Remove client from display.
[6af4b4f]103 *
[cf32dbd]104 * @param client Client
[6af4b4f]105 */
[b3c185b6]106void ds_display_remove_client(ds_client_t *client)
[6af4b4f]107{
[b3c185b6]108 list_remove(&client->lclients);
109 client->display = NULL;
[6af4b4f]110}
111
[b3c185b6]112/** Get first client in display.
[6af4b4f]113 *
114 * @param disp Display
[b3c185b6]115 * @return First client or @c NULL if there is none
[6af4b4f]116 */
[b3c185b6]117ds_client_t *ds_display_first_client(ds_display_t *disp)
[6af4b4f]118{
[b3c185b6]119 link_t *link = list_first(&disp->clients);
[6af4b4f]120
[b3c185b6]121 if (link == NULL)
122 return NULL;
[6af4b4f]123
[b3c185b6]124 return list_get_instance(link, ds_client_t, lclients);
[6af4b4f]125}
126
[b3c185b6]127/** Get next client in display.
[6af4b4f]128 *
[b3c185b6]129 * @param client Current client
130 * @return Next client or @c NULL if there is none
[6af4b4f]131 */
[b3c185b6]132ds_client_t *ds_display_next_client(ds_client_t *client)
[6af4b4f]133{
[b3c185b6]134 link_t *link = list_next(&client->lclients, &client->display->clients);
[6af4b4f]135
136 if (link == NULL)
137 return NULL;
138
[b3c185b6]139 return list_get_instance(link, ds_client_t, lclients);
[6af4b4f]140}
141
[b3c185b6]142/** Find window in all clients by ID.
[6af4b4f]143 *
[b3c185b6]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
[6af4b4f]150 */
[b3c185b6]151#include <stdio.h>
152ds_window_t *ds_display_find_window(ds_display_t *display, ds_wnd_id_t id)
[6af4b4f]153{
[b3c185b6]154 ds_client_t *client;
155 ds_window_t *wnd;
[6af4b4f]156
[bf22cb78]157 printf("ds_display_find_window: id=0x%x\n", (unsigned) id);
[b3c185b6]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) {
[bf22cb78]164 printf("ds_display_find_window: found wnd=%p id=0x%x\n",
165 wnd, (unsigned) wnd->id);
[b3c185b6]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
[24cf391a]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;
[fb420e48]183 gfx_rect_t drect;
[24cf391a]184
185 wnd = ds_display_first_window(display);
186 while (wnd != NULL) {
[fb420e48]187 /* Window bounding rectangle on display */
188 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
189
190 if (gfx_pix_inside_rect(pos, &drect))
[24cf391a]191 return wnd;
192
193 wnd = ds_display_next_window(wnd);
194 }
195
196 return NULL;
197}
198
[fd777a2]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
[2012fe0]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
[fd777a2]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
[2012fe0]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
[cf32dbd]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 */
[b3c185b6]292errno_t ds_display_post_kbd_event(ds_display_t *display, kbd_event_t *event)
293{
[cf32dbd]294 ds_seat_t *seat;
[b3c185b6]295
[cf32dbd]296 // TODO Determine which seat the event belongs to
297 seat = ds_display_first_seat(display);
298 if (seat == NULL)
[b3c185b6]299 return EOK;
300
[cf32dbd]301 return ds_seat_post_kbd_event(seat, event);
302}
303
[24cf391a]304/** Post position event to a display.
305 *
306 * @param display Display
307 * @param event Event
308 */
[4fbdc3d]309errno_t ds_display_post_ptd_event(ds_display_t *display, ptd_event_t *event)
[24cf391a]310{
311 ds_seat_t *seat;
312
[4fbdc3d]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;
[24cf391a]318
[4fbdc3d]319 return ds_seat_post_ptd_event(seat, event);
[24cf391a]320}
321
[cf32dbd]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;
[6af4b4f]372
[cf32dbd]373 return list_get_instance(link, ds_seat_t, lseats);
[6af4b4f]374}
375
[87a7cdb]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)
[4fbdc3d]437 return NULL;
[87a7cdb]438
439 return ddev->gc;
440}
441
[c79545e]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
[2012fe0]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
[c8cf261]501/** @}
502 */
Note: See TracBrowser for help on using the repository browser.