source: mainline/uspace/srv/hid/display/client.c@ 6301a24f

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

Resizing windows

  • Property mode set to 100644
File size: 9.3 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 client
34 */
35
36#include <adt/list.h>
37#include <errno.h>
38#include <stdlib.h>
39#include "client.h"
40#include "display.h"
41#include "seat.h"
42#include "window.h"
43
44/** Create client.
45 *
46 * @param display Parent display
47 * @param cb Client callbacks
48 * @param cb_arg Callback argument
49 * @param rclient Place to store pointer to new client.
50 * @return EOK on success, ENOMEM if out of memory
51 */
52errno_t ds_client_create(ds_display_t *display, ds_client_cb_t *cb,
53 void *cb_arg, ds_client_t **rclient)
54{
55 ds_client_t *client;
56
57 client = calloc(1, sizeof(ds_client_t));
58 if (client == NULL)
59 return ENOMEM;
60
61 list_initialize(&client->windows);
62 list_initialize(&client->events);
63 client->cb = cb;
64 client->cb_arg = cb_arg;
65
66 ds_display_add_client(display, client);
67
68 *rclient = client;
69 return EOK;
70}
71
72/** Destroy client.
73 *
74 * @param client Client
75 */
76void ds_client_destroy(ds_client_t *client)
77{
78 ds_window_t *window;
79
80 window = ds_client_first_window(client);
81 while (window != NULL) {
82 ds_window_destroy(window);
83 window = ds_client_first_window(client);
84 }
85
86 assert(list_empty(&client->windows));
87 ds_display_remove_client(client);
88 free(client);
89}
90
91/** Add window to client.
92 *
93 * @param client client
94 * @param wnd Window
95 */
96void ds_client_add_window(ds_client_t *client, ds_window_t *wnd)
97{
98 assert(wnd->client == NULL);
99 assert(!link_used(&wnd->lcwindows));
100
101 wnd->client = client;
102 wnd->id = client->display->next_wnd_id++;
103 list_append(&wnd->lcwindows, &client->windows);
104}
105
106/** Remove window from client.
107 *
108 * @param wnd Window
109 */
110void ds_client_remove_window(ds_window_t *wnd)
111{
112 ds_seat_t *seat;
113
114 /* Make sure window is no longer focused in any seat */
115 seat = ds_display_first_seat(wnd->display);
116 while (seat != NULL) {
117 ds_seat_evac_focus(seat, wnd);
118 seat = ds_display_next_seat(seat);
119 }
120
121 list_remove(&wnd->lcwindows);
122 wnd->client = NULL;
123}
124
125/** Find window by ID.
126 *
127 * @param client Client
128 * @param id Window ID
129 */
130#include <stdio.h>
131ds_window_t *ds_client_find_window(ds_client_t *client, ds_wnd_id_t id)
132{
133 ds_window_t *wnd;
134
135 // TODO Make this faster
136 printf("ds_client_find_window: id=0x%x\n", (unsigned) id);
137 wnd = ds_client_first_window(client);
138 while (wnd != NULL) {
139 printf("ds_client_find_window: wnd=%p wnd->id=0x%x\n", wnd,
140 (unsigned) wnd->id);
141 if (wnd->id == id)
142 return wnd;
143 wnd = ds_client_next_window(wnd);
144 }
145
146 return NULL;
147}
148
149/** Get first window in client.
150 *
151 * @param client Client
152 * @return First window or @c NULL if there is none
153 */
154ds_window_t *ds_client_first_window(ds_client_t *client)
155{
156 link_t *link = list_first(&client->windows);
157
158 if (link == NULL)
159 return NULL;
160
161 return list_get_instance(link, ds_window_t, lcwindows);
162}
163
164/** Get next window in client.
165 *
166 * @param wnd Current window
167 * @return Next window or @c NULL if there is none
168 */
169ds_window_t *ds_client_next_window(ds_window_t *wnd)
170{
171 link_t *link = list_next(&wnd->lcwindows, &wnd->client->windows);
172
173 if (link == NULL)
174 return NULL;
175
176 return list_get_instance(link, ds_window_t, lcwindows);
177}
178
179/** Get next event from client event queue.
180 *
181 * @param client Client
182 * @param ewindow Place to store pointer to window receiving the event
183 * @param event Place to store event
184 * @return Graphic context
185 */
186errno_t ds_client_get_event(ds_client_t *client, ds_window_t **ewindow,
187 display_wnd_ev_t *event)
188{
189 link_t *link;
190 ds_window_ev_t *wevent;
191
192 link = list_first(&client->events);
193 if (link == NULL)
194 return ENOENT;
195
196 wevent = list_get_instance(link, ds_window_ev_t, levents);
197 list_remove(link);
198
199 *ewindow = wevent->window;
200 *event = wevent->event;
201 free(wevent);
202 return EOK;
203}
204
205/** Post close event to the client's message queue.
206 *
207 * @param client Client
208 * @param ewindow Window that the message is targetted to
209 *
210 * @return EOK on success or an error code
211 */
212errno_t ds_client_post_close_event(ds_client_t *client, ds_window_t *ewindow)
213{
214 ds_window_ev_t *wevent;
215
216 wevent = calloc(1, sizeof(ds_window_ev_t));
217 if (wevent == NULL)
218 return ENOMEM;
219
220 wevent->window = ewindow;
221 wevent->event.etype = wev_close;
222 list_append(&wevent->levents, &client->events);
223
224 /* Notify the client */
225 // TODO Do not send more than once until client drains the queue
226 if (client->cb != NULL && client->cb->ev_pending != NULL)
227 client->cb->ev_pending(client->cb_arg);
228
229 return EOK;
230}
231
232/** Post focus event to the client's message queue.
233 *
234 * @param client Client
235 * @param ewindow Window that the message is targetted to
236 *
237 * @return EOK on success or an error code
238 */
239errno_t ds_client_post_focus_event(ds_client_t *client, ds_window_t *ewindow)
240{
241 ds_window_ev_t *wevent;
242
243 wevent = calloc(1, sizeof(ds_window_ev_t));
244 if (wevent == NULL)
245 return ENOMEM;
246
247 wevent->window = ewindow;
248 wevent->event.etype = wev_focus;
249 list_append(&wevent->levents, &client->events);
250
251 /* Notify the client */
252 // TODO Do not send more than once until client drains the queue
253 if (client->cb != NULL && client->cb->ev_pending != NULL)
254 client->cb->ev_pending(client->cb_arg);
255
256 return EOK;
257}
258
259/** Post keyboard event to the client's message queue.
260 *
261 * @param client Client
262 * @param ewindow Window that the message is targetted to
263 * @param event Event
264 *
265 * @return EOK on success or an error code
266 */
267errno_t ds_client_post_kbd_event(ds_client_t *client, ds_window_t *ewindow,
268 kbd_event_t *event)
269{
270 ds_window_ev_t *wevent;
271
272 wevent = calloc(1, sizeof(ds_window_ev_t));
273 if (wevent == NULL)
274 return ENOMEM;
275
276 wevent->window = ewindow;
277 wevent->event.etype = wev_kbd;
278 wevent->event.ev.kbd = *event;
279 list_append(&wevent->levents, &client->events);
280
281 /* Notify the client */
282 // TODO Do not send more than once until client drains the queue
283 client->cb->ev_pending(client->cb_arg);
284
285 return EOK;
286}
287
288/** Post position event to the client's message queue.
289 *
290 * @param client Client
291 * @param ewindow Window that the message is targetted to
292 * @param event Event
293 *
294 * @return EOK on success or an error code
295 */
296errno_t ds_client_post_pos_event(ds_client_t *client, ds_window_t *ewindow,
297 pos_event_t *event)
298{
299 ds_window_ev_t *wevent;
300
301 wevent = calloc(1, sizeof(ds_window_ev_t));
302 if (wevent == NULL)
303 return ENOMEM;
304
305 wevent->window = ewindow;
306 wevent->event.etype = wev_pos;
307 wevent->event.ev.pos = *event;
308 list_append(&wevent->levents, &client->events);
309
310 /* Notify the client */
311 // TODO Do not send more than once until client drains the queue
312 if (client->cb != NULL && client->cb->ev_pending != NULL)
313 client->cb->ev_pending(client->cb_arg);
314
315 return EOK;
316}
317
318/** Post resize event to the client's message queue.
319 *
320 * @param client Client
321 * @param ewindow Window that the message is targetted to
322 * @param rect New window rectangle
323 *
324 * @return EOK on success or an error code
325 */
326errno_t ds_client_post_resize_event(ds_client_t *client, ds_window_t *ewindow,
327 gfx_rect_t *rect)
328{
329 ds_window_ev_t *wevent;
330
331 wevent = calloc(1, sizeof(ds_window_ev_t));
332 if (wevent == NULL)
333 return ENOMEM;
334
335 wevent->window = ewindow;
336 wevent->event.etype = wev_resize;
337 wevent->event.ev.resize.rect = *rect;
338 list_append(&wevent->levents, &client->events);
339
340 /* Notify the client */
341 // TODO Do not send more than once until client drains the queue
342 if (client->cb != NULL && client->cb->ev_pending != NULL)
343 client->cb->ev_pending(client->cb_arg);
344
345 return EOK;
346}
347
348/** Post unfocus event to the client's message queue.
349 *
350 * @param client Client
351 * @param ewindow Window that the message is targetted to
352 *
353 * @return EOK on success or an error code
354 */
355errno_t ds_client_post_unfocus_event(ds_client_t *client, ds_window_t *ewindow)
356{
357 ds_window_ev_t *wevent;
358
359 wevent = calloc(1, sizeof(ds_window_ev_t));
360 if (wevent == NULL)
361 return ENOMEM;
362
363 wevent->window = ewindow;
364 wevent->event.etype = wev_unfocus;
365 list_append(&wevent->levents, &client->events);
366
367 /* Notify the client */
368 // TODO Do not send more than once until client drains the queue
369 if (client->cb != NULL && client->cb->ev_pending != NULL)
370 client->cb->ev_pending(client->cb_arg);
371
372 return EOK;
373}
374
375/** @}
376 */
Note: See TracBrowser for help on using the repository browser.