source: mainline/uspace/lib/display/src/disp_srv.c@ 552b69f

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 552b69f was c9927c66, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

Set menu popup position based on parent window position

Added a method for getting the position of a display window.
This is then combined with the menu bar entry rectangle (which is
relative to the parent window) to compute a screen-relative
rectangle close to which the popup should be placed.

  • Property mode set to 100644
File size: 10.8 KB
Line 
1/*
2 * Copyright (c) 2021 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 libdisplay
30 * @{
31 */
32/**
33 * @file
34 * @brief Display protocol server stub
35 */
36
37#include <disp_srv.h>
38#include <display/event.h>
39#include <display/info.h>
40#include <display/wndresize.h>
41#include <errno.h>
42#include <io/log.h>
43#include <ipc/display.h>
44#include <mem.h>
45#include <stdlib.h>
46#include <stddef.h>
47#include "../private/params.h"
48
49static void display_callback_create_srv(display_srv_t *srv, ipc_call_t *call)
50{
51 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
52 if (sess == NULL) {
53 async_answer_0(call, ENOMEM);
54 return;
55 }
56
57 srv->client_sess = sess;
58 async_answer_0(call, EOK);
59}
60
61static void display_window_create_srv(display_srv_t *srv, ipc_call_t *icall)
62{
63 sysarg_t wnd_id;
64 ipc_call_t call;
65 display_wnd_params_t params;
66 size_t size;
67 errno_t rc;
68
69 if (!async_data_write_receive(&call, &size)) {
70 async_answer_0(&call, EREFUSED);
71 async_answer_0(icall, EREFUSED);
72 return;
73 }
74
75 if (size != sizeof(display_wnd_params_t)) {
76 async_answer_0(&call, EINVAL);
77 async_answer_0(icall, EINVAL);
78 return;
79 }
80
81 rc = async_data_write_finalize(&call, &params, size);
82 if (rc != EOK) {
83 async_answer_0(&call, rc);
84 async_answer_0(icall, rc);
85 return;
86 }
87
88 if (srv->ops->window_create == NULL) {
89 async_answer_0(icall, ENOTSUP);
90 return;
91 }
92
93 rc = srv->ops->window_create(srv->arg, &params, &wnd_id);
94 async_answer_1(icall, rc, wnd_id);
95}
96
97static void display_window_destroy_srv(display_srv_t *srv, ipc_call_t *icall)
98{
99 sysarg_t wnd_id;
100 errno_t rc;
101
102 wnd_id = ipc_get_arg1(icall);
103
104 if (srv->ops->window_destroy == NULL) {
105 async_answer_0(icall, ENOTSUP);
106 return;
107 }
108
109 rc = srv->ops->window_destroy(srv->arg, wnd_id);
110 async_answer_0(icall, rc);
111}
112
113static void display_window_move_req_srv(display_srv_t *srv, ipc_call_t *icall)
114{
115 sysarg_t wnd_id;
116 ipc_call_t call;
117 gfx_coord2_t pos;
118 size_t size;
119 errno_t rc;
120
121 wnd_id = ipc_get_arg1(icall);
122
123 if (!async_data_write_receive(&call, &size)) {
124 async_answer_0(&call, EREFUSED);
125 async_answer_0(icall, EREFUSED);
126 return;
127 }
128
129 if (size != sizeof(gfx_coord2_t)) {
130 async_answer_0(&call, EINVAL);
131 async_answer_0(icall, EINVAL);
132 return;
133 }
134
135 rc = async_data_write_finalize(&call, &pos, size);
136 if (rc != EOK) {
137 async_answer_0(&call, rc);
138 async_answer_0(icall, rc);
139 return;
140 }
141
142 if (srv->ops->window_move_req == NULL) {
143 async_answer_0(icall, ENOTSUP);
144 return;
145 }
146
147 rc = srv->ops->window_move_req(srv->arg, wnd_id, &pos);
148 async_answer_0(icall, rc);
149}
150
151static void display_window_move_srv(display_srv_t *srv, ipc_call_t *icall)
152{
153 sysarg_t wnd_id;
154 ipc_call_t call;
155 gfx_coord2_t dpos;
156 size_t size;
157 errno_t rc;
158
159 wnd_id = ipc_get_arg1(icall);
160
161 if (!async_data_write_receive(&call, &size)) {
162 async_answer_0(&call, EREFUSED);
163 async_answer_0(icall, EREFUSED);
164 return;
165 }
166
167 if (size != sizeof(gfx_coord2_t)) {
168 async_answer_0(&call, EINVAL);
169 async_answer_0(icall, EINVAL);
170 return;
171 }
172
173 rc = async_data_write_finalize(&call, &dpos, size);
174 if (rc != EOK) {
175 async_answer_0(&call, rc);
176 async_answer_0(icall, rc);
177 return;
178 }
179
180 if (srv->ops->window_move == NULL) {
181 async_answer_0(icall, ENOTSUP);
182 return;
183 }
184
185 rc = srv->ops->window_move(srv->arg, wnd_id, &dpos);
186 async_answer_0(icall, rc);
187}
188
189static void display_window_get_pos_srv(display_srv_t *srv, ipc_call_t *icall)
190{
191 sysarg_t wnd_id;
192 ipc_call_t call;
193 gfx_coord2_t dpos;
194 size_t size;
195 errno_t rc;
196
197 wnd_id = ipc_get_arg1(icall);
198
199 if (srv->ops->window_get_pos == NULL) {
200 async_answer_0(icall, ENOTSUP);
201 return;
202 }
203
204 if (!async_data_read_receive(&call, &size)) {
205 async_answer_0(icall, EREFUSED);
206 return;
207 }
208
209 rc = srv->ops->window_get_pos(srv->arg, wnd_id, &dpos);
210 if (rc != EOK) {
211 async_answer_0(&call, rc);
212 async_answer_0(icall, rc);
213 return;
214 }
215
216 if (size != sizeof(gfx_coord2_t)) {
217 async_answer_0(&call, EINVAL);
218 async_answer_0(icall, EINVAL);
219 return;
220 }
221
222 rc = async_data_read_finalize(&call, &dpos, size);
223 if (rc != EOK) {
224 async_answer_0(&call, rc);
225 async_answer_0(icall, rc);
226 return;
227 }
228
229 async_answer_0(icall, EOK);
230}
231
232static void display_window_resize_req_srv(display_srv_t *srv, ipc_call_t *icall)
233{
234 sysarg_t wnd_id;
235 ipc_call_t call;
236 display_wnd_rsztype_t rsztype;
237 gfx_coord2_t pos;
238 size_t size;
239 errno_t rc;
240
241 wnd_id = ipc_get_arg1(icall);
242 rsztype = (display_wnd_rsztype_t) ipc_get_arg2(icall);
243
244 if (!async_data_write_receive(&call, &size)) {
245 async_answer_0(&call, EREFUSED);
246 async_answer_0(icall, EREFUSED);
247 return;
248 }
249
250 if (size != sizeof(gfx_coord2_t)) {
251 async_answer_0(&call, EINVAL);
252 async_answer_0(icall, EINVAL);
253 return;
254 }
255
256 rc = async_data_write_finalize(&call, &pos, size);
257 if (rc != EOK) {
258 async_answer_0(&call, rc);
259 async_answer_0(icall, rc);
260 return;
261 }
262
263 if (srv->ops->window_resize_req == NULL) {
264 async_answer_0(icall, ENOTSUP);
265 return;
266 }
267
268 rc = srv->ops->window_resize_req(srv->arg, wnd_id, rsztype, &pos);
269 async_answer_0(icall, rc);
270}
271
272static void display_window_resize_srv(display_srv_t *srv, ipc_call_t *icall)
273{
274 sysarg_t wnd_id;
275 ipc_call_t call;
276 display_wnd_resize_t wresize;
277 size_t size;
278 errno_t rc;
279
280 wnd_id = ipc_get_arg1(icall);
281
282 if (!async_data_write_receive(&call, &size)) {
283 async_answer_0(&call, EREFUSED);
284 async_answer_0(icall, EREFUSED);
285 return;
286 }
287
288 if (size != sizeof(display_wnd_resize_t)) {
289 async_answer_0(&call, EINVAL);
290 async_answer_0(icall, EINVAL);
291 return;
292 }
293
294 rc = async_data_write_finalize(&call, &wresize, size);
295 if (rc != EOK) {
296 async_answer_0(&call, rc);
297 async_answer_0(icall, rc);
298 return;
299 }
300
301 if (srv->ops->window_resize == NULL) {
302 async_answer_0(icall, ENOTSUP);
303 return;
304 }
305
306 rc = srv->ops->window_resize(srv->arg, wnd_id, &wresize.offs,
307 &wresize.nrect);
308 async_answer_0(icall, rc);
309}
310
311static void display_window_set_cursor_srv(display_srv_t *srv, ipc_call_t *icall)
312{
313 sysarg_t wnd_id;
314 display_stock_cursor_t cursor;
315 errno_t rc;
316
317 wnd_id = ipc_get_arg1(icall);
318 cursor = ipc_get_arg2(icall);
319
320 if (srv->ops->window_set_cursor == NULL) {
321 async_answer_0(icall, ENOTSUP);
322 return;
323 }
324
325 rc = srv->ops->window_set_cursor(srv->arg, wnd_id, cursor);
326 async_answer_0(icall, rc);
327}
328
329static void display_get_event_srv(display_srv_t *srv, ipc_call_t *icall)
330{
331 sysarg_t wnd_id;
332 display_wnd_ev_t event;
333 ipc_call_t call;
334 size_t size;
335 errno_t rc;
336
337 if (srv->ops->get_event == NULL) {
338 async_answer_0(icall, ENOTSUP);
339 return;
340 }
341
342 rc = srv->ops->get_event(srv->arg, &wnd_id, &event);
343 if (rc != EOK) {
344 async_answer_0(icall, rc);
345 return;
346 }
347
348 /* Transfer event data */
349 if (!async_data_read_receive(&call, &size)) {
350 async_answer_0(icall, EREFUSED);
351 return;
352 }
353
354 if (size != sizeof(event)) {
355 async_answer_0(icall, EREFUSED);
356 async_answer_0(&call, EREFUSED);
357 return;
358 }
359
360 rc = async_data_read_finalize(&call, &event, sizeof(event));
361 if (rc != EOK) {
362 async_answer_0(icall, rc);
363 async_answer_0(&call, rc);
364 return;
365 }
366
367 async_answer_1(icall, EOK, wnd_id);
368}
369
370static void display_get_info_srv(display_srv_t *srv, ipc_call_t *icall)
371{
372 display_info_t info;
373 ipc_call_t call;
374 size_t size;
375 errno_t rc;
376
377 if (srv->ops->get_info == NULL) {
378 async_answer_0(icall, ENOTSUP);
379 return;
380 }
381
382 /* Transfer information */
383 if (!async_data_read_receive(&call, &size)) {
384 async_answer_0(icall, EREFUSED);
385 return;
386 }
387
388 if (size != sizeof(info)) {
389 async_answer_0(icall, EREFUSED);
390 async_answer_0(&call, EREFUSED);
391 return;
392 }
393
394 rc = srv->ops->get_info(srv->arg, &info);
395 if (rc != EOK) {
396 async_answer_0(icall, rc);
397 async_answer_0(&call, rc);
398 return;
399 }
400
401 rc = async_data_read_finalize(&call, &info, sizeof(info));
402 if (rc != EOK) {
403 async_answer_0(icall, rc);
404 async_answer_0(&call, rc);
405 return;
406 }
407
408 async_answer_0(icall, EOK);
409}
410
411void display_conn(ipc_call_t *icall, display_srv_t *srv)
412{
413 /* Accept the connection */
414 async_accept_0(icall);
415
416 while (true) {
417 ipc_call_t call;
418
419 async_get_call(&call);
420 sysarg_t method = ipc_get_imethod(&call);
421
422 if (!method) {
423 /* The other side has hung up */
424 async_answer_0(&call, EOK);
425 break;
426 }
427
428 switch (method) {
429 case DISPLAY_CALLBACK_CREATE:
430 display_callback_create_srv(srv, &call);
431 break;
432 case DISPLAY_WINDOW_CREATE:
433 display_window_create_srv(srv, &call);
434 break;
435 case DISPLAY_WINDOW_DESTROY:
436 display_window_destroy_srv(srv, &call);
437 break;
438 case DISPLAY_WINDOW_MOVE_REQ:
439 display_window_move_req_srv(srv, &call);
440 break;
441 case DISPLAY_WINDOW_MOVE:
442 display_window_move_srv(srv, &call);
443 break;
444 case DISPLAY_WINDOW_GET_POS:
445 display_window_get_pos_srv(srv, &call);
446 break;
447 case DISPLAY_WINDOW_RESIZE_REQ:
448 display_window_resize_req_srv(srv, &call);
449 break;
450 case DISPLAY_WINDOW_RESIZE:
451 display_window_resize_srv(srv, &call);
452 break;
453 case DISPLAY_WINDOW_SET_CURSOR:
454 display_window_set_cursor_srv(srv, &call);
455 break;
456 case DISPLAY_GET_EVENT:
457 display_get_event_srv(srv, &call);
458 break;
459 case DISPLAY_GET_INFO:
460 display_get_info_srv(srv, &call);
461 break;
462 default:
463 async_answer_0(&call, ENOTSUP);
464 }
465 }
466
467 /* Hang up callback session */
468 if (srv->client_sess != NULL) {
469 async_hangup(srv->client_sess);
470 srv->client_sess = NULL;
471 }
472}
473
474/** Initialize display server structure
475 *
476 * @param srv Display server structure to initialize
477 */
478void display_srv_initialize(display_srv_t *srv)
479{
480 memset(srv, 0, sizeof(*srv));
481}
482
483/** Send 'pending' event to client.
484 *
485 * @param srv Display server structure
486 */
487void display_srv_ev_pending(display_srv_t *srv)
488{
489 async_exch_t *exch;
490
491 exch = async_exchange_begin(srv->client_sess);
492 async_msg_0(exch, DISPLAY_EV_PENDING);
493 async_exchange_end(exch);
494}
495
496/** @}
497 */
Note: See TracBrowser for help on using the repository browser.