source: mainline/uspace/srv/hid/display/display.c@ 24cf391a

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

Switch window focus on mouse click

  • Property mode set to 100644
File size: 8.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 <io/log.h>
39#include <stdlib.h>
40#include "client.h"
41#include "seat.h"
42#include "window.h"
43#include "display.h"
44
45/** Create display.
46 *
47 * @param gc Graphics context for displaying output
48 * @param rdisp Place to store pointer to new display.
49 * @return EOK on success, ENOMEM if out of memory
50 */
51errno_t ds_display_create(gfx_context_t *gc, ds_display_t **rdisp)
52{
53 ds_display_t *disp;
54
55 disp = calloc(1, sizeof(ds_display_t));
56 if (disp == NULL)
57 return ENOMEM;
58
59 list_initialize(&disp->clients);
60 disp->gc = gc;
61 disp->next_wnd_id = 1;
62 list_initialize(&disp->seats);
63 list_initialize(&disp->windows);
64 *rdisp = disp;
65 return EOK;
66}
67
68/** Destroy display.
69 *
70 * @param disp Display
71 */
72void ds_display_destroy(ds_display_t *disp)
73{
74 assert(list_empty(&disp->clients));
75 assert(list_empty(&disp->seats));
76 free(disp);
77}
78
79/** Add client to display.
80 *
81 * @param disp Display
82 * @param client Client
83 */
84void ds_display_add_client(ds_display_t *disp, ds_client_t *client)
85{
86 assert(client->display == NULL);
87 assert(!link_used(&client->lclients));
88
89 client->display = disp;
90 list_append(&client->lclients, &disp->clients);
91}
92
93/** Remove client from display.
94 *
95 * @param client Client
96 */
97void ds_display_remove_client(ds_client_t *client)
98{
99 list_remove(&client->lclients);
100 client->display = NULL;
101}
102
103/** Get first client in display.
104 *
105 * @param disp Display
106 * @return First client or @c NULL if there is none
107 */
108ds_client_t *ds_display_first_client(ds_display_t *disp)
109{
110 link_t *link = list_first(&disp->clients);
111
112 if (link == NULL)
113 return NULL;
114
115 return list_get_instance(link, ds_client_t, lclients);
116}
117
118/** Get next client in display.
119 *
120 * @param client Current client
121 * @return Next client or @c NULL if there is none
122 */
123ds_client_t *ds_display_next_client(ds_client_t *client)
124{
125 link_t *link = list_next(&client->lclients, &client->display->clients);
126
127 if (link == NULL)
128 return NULL;
129
130 return list_get_instance(link, ds_client_t, lclients);
131}
132
133/** Find window in all clients by ID.
134 *
135 * XXX This is just a hack needed to match GC connection to a window,
136 * as we don't have a good safe way to pass the GC endpoint to our client
137 * on demand.
138 *
139 * @param display Display
140 * @param id Window ID
141 */
142#include <stdio.h>
143ds_window_t *ds_display_find_window(ds_display_t *display, ds_wnd_id_t id)
144{
145 ds_client_t *client;
146 ds_window_t *wnd;
147
148 printf("ds_display_find_window: id=0x%x\n", (unsigned) id);
149
150 client = ds_display_first_client(display);
151 while (client != NULL) {
152 printf("ds_display_find_window: client=%p\n", client);
153 wnd = ds_client_find_window(client, id);
154 if (wnd != NULL) {
155 printf("ds_display_find_window: found wnd=%p id=0x%x\n",
156 wnd, (unsigned) wnd->id);
157 return wnd;
158 }
159 client = ds_display_next_client(client);
160 }
161
162 printf("ds_display_find_window: not found\n");
163 return NULL;
164}
165
166/** Find window by display position.
167 *
168 * @param display Display
169 * @param pos Display position
170 */
171ds_window_t *ds_display_window_by_pos(ds_display_t *display, gfx_coord2_t *pos)
172{
173 ds_window_t *wnd;
174
175 wnd = ds_display_first_window(display);
176 while (wnd != NULL) {
177 // XXX Need to know window dimensions
178 if (pos->x >= wnd->dpos.x && pos->y >= wnd->dpos.y &&
179 pos->x <= wnd->dpos.x + 100 && pos->y <= wnd->dpos.y + 100) {
180 return wnd;
181 }
182
183 wnd = ds_display_next_window(wnd);
184 }
185
186 return NULL;
187}
188
189/** Add window to display.
190 *
191 * @param display Display
192 * @param wnd Window
193 */
194void ds_display_add_window(ds_display_t *display, ds_window_t *wnd)
195{
196 assert(wnd->display == NULL);
197 assert(!link_used(&wnd->ldwindows));
198
199 wnd->display = display;
200 list_prepend(&wnd->ldwindows, &display->windows);
201}
202
203/** Remove window from display.
204 *
205 * @param wnd Window
206 */
207void ds_display_remove_window(ds_window_t *wnd)
208{
209 list_remove(&wnd->ldwindows);
210 wnd->display = NULL;
211}
212
213/** Get first window in display.
214 *
215 * @param display Display
216 * @return First window or @c NULL if there is none
217 */
218ds_window_t *ds_display_first_window(ds_display_t *display)
219{
220 link_t *link = list_first(&display->windows);
221
222 if (link == NULL)
223 return NULL;
224
225 return list_get_instance(link, ds_window_t, ldwindows);
226}
227
228/** Get next window in client.
229 *
230 * @param wnd Current window
231 * @return Next window or @c NULL if there is none
232 */
233ds_window_t *ds_display_next_window(ds_window_t *wnd)
234{
235 link_t *link = list_next(&wnd->ldwindows, &wnd->display->windows);
236
237 if (link == NULL)
238 return NULL;
239
240 return list_get_instance(link, ds_window_t, ldwindows);
241}
242
243/** Post keyboard event to a display.
244 *
245 * The event is routed to the correct window by first determining the
246 * seat the keyboard device belongs to and then the event is sent to the
247 * window focused by that seat.
248 *
249 * @param display Display
250 * @param event Event
251 */
252errno_t ds_display_post_kbd_event(ds_display_t *display, kbd_event_t *event)
253{
254 ds_seat_t *seat;
255
256 // TODO Determine which seat the event belongs to
257 seat = ds_display_first_seat(display);
258 if (seat == NULL)
259 return EOK;
260
261 return ds_seat_post_kbd_event(seat, event);
262}
263
264/** Post position event to a display.
265 *
266 * @param display Display
267 * @param event Event
268 */
269errno_t ds_display_post_pos_event(ds_display_t *display, pos_event_t *event)
270{
271 gfx_coord2_t pos;
272 ds_window_t *wnd;
273 ds_seat_t *seat;
274
275 /* Focus window on button press */
276 if (event->type == POS_PRESS) {
277 printf("Button press\n");
278 pos.x = event->hpos;
279 pos.y = event->vpos;
280
281 wnd = ds_display_window_by_pos(display, &pos);
282 if (wnd != NULL) {
283 seat = ds_display_first_seat(display);
284 if (seat == NULL)
285 return EOK;
286
287 ds_seat_set_focus(seat, wnd);
288 return EOK;
289 }
290 }
291
292 return EOK;
293}
294
295/** Add seat to display.
296 *
297 * @param disp Display
298 * @param seat Seat
299 */
300void ds_display_add_seat(ds_display_t *disp, ds_seat_t *seat)
301{
302 assert(seat->display == NULL);
303 assert(!link_used(&seat->lseats));
304
305 seat->display = disp;
306 list_append(&seat->lseats, &disp->seats);
307}
308
309/** Remove seat from display.
310 *
311 * @param seat Seat
312 */
313void ds_display_remove_seat(ds_seat_t *seat)
314{
315 list_remove(&seat->lseats);
316 seat->display = NULL;
317}
318
319/** Get first seat in display.
320 *
321 * @param disp Display
322 * @return First seat or @c NULL if there is none
323 */
324ds_seat_t *ds_display_first_seat(ds_display_t *disp)
325{
326 link_t *link = list_first(&disp->seats);
327
328 if (link == NULL)
329 return NULL;
330
331 return list_get_instance(link, ds_seat_t, lseats);
332}
333
334/** Get next seat in display.
335 *
336 * @param seat Current seat
337 * @return Next seat or @c NULL if there is none
338 */
339ds_seat_t *ds_display_next_seat(ds_seat_t *seat)
340{
341 link_t *link = list_next(&seat->lseats, &seat->display->seats);
342
343 if (link == NULL)
344 return NULL;
345
346 return list_get_instance(link, ds_seat_t, lseats);
347}
348
349/** @}
350 */
Note: See TracBrowser for help on using the repository browser.