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

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

Create menu windows in the correct seat

Add a mechanism to set the seat of a new display window, UI window,
UI popup - input device ID. This is set to the ID of the device which
activated the menu (mouse, keyboard). The display server determines
the correct seat from there.

This makes sure clicking outside closes the correct pop-up window.

  • Property mode set to 100644
File size: 14.9 KB
Line 
1/*
2 * Copyright (c) 2023 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_enc_t eparams;
66 display_wnd_params_t params;
67 char *caption;
68 size_t size;
69 errno_t rc;
70
71 if (!async_data_write_receive(&call, &size)) {
72 async_answer_0(&call, EREFUSED);
73 async_answer_0(icall, EREFUSED);
74 return;
75 }
76
77 if (size != sizeof(display_wnd_params_enc_t)) {
78 async_answer_0(&call, EINVAL);
79 async_answer_0(icall, EINVAL);
80 return;
81 }
82
83 rc = async_data_write_finalize(&call, &eparams, size);
84 if (rc != EOK) {
85 async_answer_0(&call, rc);
86 async_answer_0(icall, rc);
87 return;
88 }
89
90 caption = calloc(eparams.caption_size + 1, 1);
91 if (caption == NULL) {
92 async_answer_0(icall, ENOMEM);
93 return;
94 }
95
96 if (!async_data_write_receive(&call, &size)) {
97 free(caption);
98 async_answer_0(&call, EREFUSED);
99 async_answer_0(icall, EREFUSED);
100 return;
101 }
102
103 if (size != eparams.caption_size) {
104 free(caption);
105 async_answer_0(&call, EINVAL);
106 async_answer_0(icall, EINVAL);
107 return;
108 }
109
110 rc = async_data_write_finalize(&call, caption, eparams.caption_size);
111 if (rc != EOK) {
112 free(caption);
113 async_answer_0(&call, rc);
114 async_answer_0(icall, rc);
115 return;
116 }
117
118 if (srv->ops->window_create == NULL) {
119 free(caption);
120 async_answer_0(icall, ENOTSUP);
121 return;
122 }
123
124 /* Decode the parameters from transport */
125 params.rect = eparams.rect;
126 params.caption = caption;
127 params.min_size = eparams.min_size;
128 params.pos = eparams.pos;
129 params.flags = eparams.flags;
130 params.idev_id = eparams.idev_id;
131
132 rc = srv->ops->window_create(srv->arg, &params, &wnd_id);
133 async_answer_1(icall, rc, wnd_id);
134}
135
136static void display_window_destroy_srv(display_srv_t *srv, ipc_call_t *icall)
137{
138 sysarg_t wnd_id;
139 errno_t rc;
140
141 wnd_id = ipc_get_arg1(icall);
142
143 if (srv->ops->window_destroy == NULL) {
144 async_answer_0(icall, ENOTSUP);
145 return;
146 }
147
148 rc = srv->ops->window_destroy(srv->arg, wnd_id);
149 async_answer_0(icall, rc);
150}
151
152static void display_window_move_req_srv(display_srv_t *srv, ipc_call_t *icall)
153{
154 sysarg_t wnd_id;
155 sysarg_t pos_id;
156 ipc_call_t call;
157 gfx_coord2_t pos;
158 size_t size;
159 errno_t rc;
160
161 wnd_id = ipc_get_arg1(icall);
162 pos_id = ipc_get_arg2(icall);
163
164 if (!async_data_write_receive(&call, &size)) {
165 async_answer_0(&call, EREFUSED);
166 async_answer_0(icall, EREFUSED);
167 return;
168 }
169
170 if (size != sizeof(gfx_coord2_t)) {
171 async_answer_0(&call, EINVAL);
172 async_answer_0(icall, EINVAL);
173 return;
174 }
175
176 rc = async_data_write_finalize(&call, &pos, size);
177 if (rc != EOK) {
178 async_answer_0(&call, rc);
179 async_answer_0(icall, rc);
180 return;
181 }
182
183 if (srv->ops->window_move_req == NULL) {
184 async_answer_0(icall, ENOTSUP);
185 return;
186 }
187
188 rc = srv->ops->window_move_req(srv->arg, wnd_id, &pos, pos_id);
189 async_answer_0(icall, rc);
190}
191
192static void display_window_move_srv(display_srv_t *srv, ipc_call_t *icall)
193{
194 sysarg_t wnd_id;
195 ipc_call_t call;
196 gfx_coord2_t dpos;
197 size_t size;
198 errno_t rc;
199
200 wnd_id = ipc_get_arg1(icall);
201
202 if (!async_data_write_receive(&call, &size)) {
203 async_answer_0(&call, EREFUSED);
204 async_answer_0(icall, EREFUSED);
205 return;
206 }
207
208 if (size != sizeof(gfx_coord2_t)) {
209 async_answer_0(&call, EINVAL);
210 async_answer_0(icall, EINVAL);
211 return;
212 }
213
214 rc = async_data_write_finalize(&call, &dpos, size);
215 if (rc != EOK) {
216 async_answer_0(&call, rc);
217 async_answer_0(icall, rc);
218 return;
219 }
220
221 if (srv->ops->window_move == NULL) {
222 async_answer_0(icall, ENOTSUP);
223 return;
224 }
225
226 rc = srv->ops->window_move(srv->arg, wnd_id, &dpos);
227 async_answer_0(icall, rc);
228}
229
230static void display_window_get_pos_srv(display_srv_t *srv, ipc_call_t *icall)
231{
232 sysarg_t wnd_id;
233 ipc_call_t call;
234 gfx_coord2_t dpos;
235 size_t size;
236 errno_t rc;
237
238 wnd_id = ipc_get_arg1(icall);
239
240 if (srv->ops->window_get_pos == NULL) {
241 async_answer_0(icall, ENOTSUP);
242 return;
243 }
244
245 if (!async_data_read_receive(&call, &size)) {
246 async_answer_0(&call, EREFUSED);
247 async_answer_0(icall, EREFUSED);
248 return;
249 }
250
251 rc = srv->ops->window_get_pos(srv->arg, wnd_id, &dpos);
252 if (rc != EOK) {
253 async_answer_0(&call, rc);
254 async_answer_0(icall, rc);
255 return;
256 }
257
258 if (size != sizeof(gfx_coord2_t)) {
259 async_answer_0(&call, EINVAL);
260 async_answer_0(icall, EINVAL);
261 return;
262 }
263
264 rc = async_data_read_finalize(&call, &dpos, size);
265 if (rc != EOK) {
266 async_answer_0(&call, rc);
267 async_answer_0(icall, rc);
268 return;
269 }
270
271 async_answer_0(icall, EOK);
272}
273
274static void display_window_get_max_rect_srv(display_srv_t *srv,
275 ipc_call_t *icall)
276{
277 sysarg_t wnd_id;
278 ipc_call_t call;
279 gfx_rect_t rect;
280 size_t size;
281 errno_t rc;
282
283 wnd_id = ipc_get_arg1(icall);
284
285 if (srv->ops->window_get_max_rect == NULL) {
286 async_answer_0(icall, ENOTSUP);
287 return;
288 }
289
290 if (!async_data_read_receive(&call, &size)) {
291 async_answer_0(&call, EREFUSED);
292 async_answer_0(icall, EREFUSED);
293 return;
294 }
295
296 rc = srv->ops->window_get_max_rect(srv->arg, wnd_id, &rect);
297 if (rc != EOK) {
298 async_answer_0(&call, rc);
299 async_answer_0(icall, rc);
300 return;
301 }
302
303 if (size != sizeof(gfx_rect_t)) {
304 async_answer_0(&call, EINVAL);
305 async_answer_0(icall, EINVAL);
306 return;
307 }
308
309 rc = async_data_read_finalize(&call, &rect, size);
310 if (rc != EOK) {
311 async_answer_0(&call, rc);
312 async_answer_0(icall, rc);
313 return;
314 }
315
316 async_answer_0(icall, EOK);
317}
318
319static void display_window_resize_req_srv(display_srv_t *srv, ipc_call_t *icall)
320{
321 sysarg_t wnd_id;
322 ipc_call_t call;
323 display_wnd_rsztype_t rsztype;
324 gfx_coord2_t pos;
325 sysarg_t pos_id;
326 size_t size;
327 errno_t rc;
328
329 wnd_id = ipc_get_arg1(icall);
330 rsztype = (display_wnd_rsztype_t) ipc_get_arg2(icall);
331 pos_id = ipc_get_arg3(icall);
332
333 if (!async_data_write_receive(&call, &size)) {
334 async_answer_0(&call, EREFUSED);
335 async_answer_0(icall, EREFUSED);
336 return;
337 }
338
339 if (size != sizeof(gfx_coord2_t)) {
340 async_answer_0(&call, EINVAL);
341 async_answer_0(icall, EINVAL);
342 return;
343 }
344
345 rc = async_data_write_finalize(&call, &pos, size);
346 if (rc != EOK) {
347 async_answer_0(&call, rc);
348 async_answer_0(icall, rc);
349 return;
350 }
351
352 if (srv->ops->window_resize_req == NULL) {
353 async_answer_0(icall, ENOTSUP);
354 return;
355 }
356
357 rc = srv->ops->window_resize_req(srv->arg, wnd_id, rsztype, &pos,
358 pos_id);
359 async_answer_0(icall, rc);
360}
361
362static void display_window_resize_srv(display_srv_t *srv, ipc_call_t *icall)
363{
364 sysarg_t wnd_id;
365 ipc_call_t call;
366 display_wnd_resize_t wresize;
367 size_t size;
368 errno_t rc;
369
370 wnd_id = ipc_get_arg1(icall);
371
372 if (!async_data_write_receive(&call, &size)) {
373 async_answer_0(&call, EREFUSED);
374 async_answer_0(icall, EREFUSED);
375 return;
376 }
377
378 if (size != sizeof(display_wnd_resize_t)) {
379 async_answer_0(&call, EINVAL);
380 async_answer_0(icall, EINVAL);
381 return;
382 }
383
384 rc = async_data_write_finalize(&call, &wresize, size);
385 if (rc != EOK) {
386 async_answer_0(&call, rc);
387 async_answer_0(icall, rc);
388 return;
389 }
390
391 if (srv->ops->window_resize == NULL) {
392 async_answer_0(icall, ENOTSUP);
393 return;
394 }
395
396 rc = srv->ops->window_resize(srv->arg, wnd_id, &wresize.offs,
397 &wresize.nrect);
398 async_answer_0(icall, rc);
399}
400
401static void display_window_minimize_srv(display_srv_t *srv, ipc_call_t *icall)
402{
403 sysarg_t wnd_id;
404 errno_t rc;
405
406 wnd_id = ipc_get_arg1(icall);
407
408 if (srv->ops->window_minimize == NULL) {
409 async_answer_0(icall, ENOTSUP);
410 return;
411 }
412
413 rc = srv->ops->window_minimize(srv->arg, wnd_id);
414 async_answer_0(icall, rc);
415}
416
417static void display_window_maximize_srv(display_srv_t *srv, ipc_call_t *icall)
418{
419 sysarg_t wnd_id;
420 errno_t rc;
421
422 wnd_id = ipc_get_arg1(icall);
423
424 if (srv->ops->window_maximize == NULL) {
425 async_answer_0(icall, ENOTSUP);
426 return;
427 }
428
429 rc = srv->ops->window_maximize(srv->arg, wnd_id);
430 async_answer_0(icall, rc);
431}
432
433static void display_window_unmaximize_srv(display_srv_t *srv, ipc_call_t *icall)
434{
435 sysarg_t wnd_id;
436 errno_t rc;
437
438 wnd_id = ipc_get_arg1(icall);
439
440 if (srv->ops->window_unmaximize == NULL) {
441 async_answer_0(icall, ENOTSUP);
442 return;
443 }
444
445 rc = srv->ops->window_unmaximize(srv->arg, wnd_id);
446 async_answer_0(icall, rc);
447}
448
449static void display_window_set_cursor_srv(display_srv_t *srv, ipc_call_t *icall)
450{
451 sysarg_t wnd_id;
452 display_stock_cursor_t cursor;
453 errno_t rc;
454
455 wnd_id = ipc_get_arg1(icall);
456 cursor = ipc_get_arg2(icall);
457
458 if (srv->ops->window_set_cursor == NULL) {
459 async_answer_0(icall, ENOTSUP);
460 return;
461 }
462
463 rc = srv->ops->window_set_cursor(srv->arg, wnd_id, cursor);
464 async_answer_0(icall, rc);
465}
466
467static void display_window_set_caption_srv(display_srv_t *srv,
468 ipc_call_t *icall)
469{
470 sysarg_t wnd_id;
471 ipc_call_t call;
472 char *caption;
473 size_t size;
474 errno_t rc;
475
476 wnd_id = ipc_get_arg1(icall);
477
478 if (!async_data_write_receive(&call, &size)) {
479 async_answer_0(&call, EREFUSED);
480 async_answer_0(icall, EREFUSED);
481 return;
482 }
483
484 caption = calloc(size + 1, 1);
485 if (caption == NULL) {
486 async_answer_0(&call, ENOMEM);
487 async_answer_0(icall, ENOMEM);
488 return;
489 }
490
491 rc = async_data_write_finalize(&call, caption, size);
492 if (rc != EOK) {
493 free(caption);
494 async_answer_0(&call, rc);
495 async_answer_0(icall, rc);
496 return;
497 }
498
499 if (srv->ops->window_set_caption == NULL) {
500 free(caption);
501 async_answer_0(icall, ENOTSUP);
502 return;
503 }
504
505 rc = srv->ops->window_set_caption(srv->arg, wnd_id, caption);
506 async_answer_0(icall, rc);
507 free(caption);
508}
509
510static void display_get_event_srv(display_srv_t *srv, ipc_call_t *icall)
511{
512 sysarg_t wnd_id;
513 display_wnd_ev_t event;
514 ipc_call_t call;
515 size_t size;
516 errno_t rc;
517
518 if (srv->ops->get_event == NULL) {
519 async_answer_0(icall, ENOTSUP);
520 return;
521 }
522
523 rc = srv->ops->get_event(srv->arg, &wnd_id, &event);
524 if (rc != EOK) {
525 async_answer_0(icall, rc);
526 return;
527 }
528
529 /* Transfer event data */
530 if (!async_data_read_receive(&call, &size)) {
531 async_answer_0(&call, EREFUSED);
532 async_answer_0(icall, EREFUSED);
533 return;
534 }
535
536 if (size != sizeof(event)) {
537 async_answer_0(icall, EREFUSED);
538 async_answer_0(&call, EREFUSED);
539 return;
540 }
541
542 rc = async_data_read_finalize(&call, &event, sizeof(event));
543 if (rc != EOK) {
544 async_answer_0(icall, rc);
545 async_answer_0(&call, rc);
546 return;
547 }
548
549 async_answer_1(icall, EOK, wnd_id);
550}
551
552static void display_get_info_srv(display_srv_t *srv, ipc_call_t *icall)
553{
554 display_info_t info;
555 ipc_call_t call;
556 size_t size;
557 errno_t rc;
558
559 if (srv->ops->get_info == NULL) {
560 async_answer_0(icall, ENOTSUP);
561 return;
562 }
563
564 /* Transfer information */
565 if (!async_data_read_receive(&call, &size)) {
566 async_answer_0(&call, EREFUSED);
567 async_answer_0(icall, EREFUSED);
568 return;
569 }
570
571 if (size != sizeof(info)) {
572 async_answer_0(icall, EREFUSED);
573 async_answer_0(&call, EREFUSED);
574 return;
575 }
576
577 rc = srv->ops->get_info(srv->arg, &info);
578 if (rc != EOK) {
579 async_answer_0(icall, rc);
580 async_answer_0(&call, rc);
581 return;
582 }
583
584 rc = async_data_read_finalize(&call, &info, sizeof(info));
585 if (rc != EOK) {
586 async_answer_0(icall, rc);
587 async_answer_0(&call, rc);
588 return;
589 }
590
591 async_answer_0(icall, EOK);
592}
593
594void display_conn(ipc_call_t *icall, display_srv_t *srv)
595{
596 /* Accept the connection */
597 async_accept_0(icall);
598
599 while (true) {
600 ipc_call_t call;
601
602 async_get_call(&call);
603 sysarg_t method = ipc_get_imethod(&call);
604
605 if (!method) {
606 /* The other side has hung up */
607 async_answer_0(&call, EOK);
608 break;
609 }
610
611 switch (method) {
612 case DISPLAY_CALLBACK_CREATE:
613 display_callback_create_srv(srv, &call);
614 break;
615 case DISPLAY_WINDOW_CREATE:
616 display_window_create_srv(srv, &call);
617 break;
618 case DISPLAY_WINDOW_DESTROY:
619 display_window_destroy_srv(srv, &call);
620 break;
621 case DISPLAY_WINDOW_MOVE_REQ:
622 display_window_move_req_srv(srv, &call);
623 break;
624 case DISPLAY_WINDOW_MOVE:
625 display_window_move_srv(srv, &call);
626 break;
627 case DISPLAY_WINDOW_GET_POS:
628 display_window_get_pos_srv(srv, &call);
629 break;
630 case DISPLAY_WINDOW_GET_MAX_RECT:
631 display_window_get_max_rect_srv(srv, &call);
632 break;
633 case DISPLAY_WINDOW_RESIZE_REQ:
634 display_window_resize_req_srv(srv, &call);
635 break;
636 case DISPLAY_WINDOW_RESIZE:
637 display_window_resize_srv(srv, &call);
638 break;
639 case DISPLAY_WINDOW_MINIMIZE:
640 display_window_minimize_srv(srv, &call);
641 break;
642 case DISPLAY_WINDOW_MAXIMIZE:
643 display_window_maximize_srv(srv, &call);
644 break;
645 case DISPLAY_WINDOW_UNMAXIMIZE:
646 display_window_unmaximize_srv(srv, &call);
647 break;
648 case DISPLAY_WINDOW_SET_CURSOR:
649 display_window_set_cursor_srv(srv, &call);
650 break;
651 case DISPLAY_WINDOW_SET_CAPTION:
652 display_window_set_caption_srv(srv, &call);
653 break;
654 case DISPLAY_GET_EVENT:
655 display_get_event_srv(srv, &call);
656 break;
657 case DISPLAY_GET_INFO:
658 display_get_info_srv(srv, &call);
659 break;
660 default:
661 async_answer_0(&call, ENOTSUP);
662 }
663 }
664
665 /* Hang up callback session */
666 if (srv->client_sess != NULL) {
667 async_hangup(srv->client_sess);
668 srv->client_sess = NULL;
669 }
670}
671
672/** Initialize display server structure
673 *
674 * @param srv Display server structure to initialize
675 */
676void display_srv_initialize(display_srv_t *srv)
677{
678 memset(srv, 0, sizeof(*srv));
679}
680
681/** Send 'pending' event to client.
682 *
683 * @param srv Display server structure
684 */
685void display_srv_ev_pending(display_srv_t *srv)
686{
687 async_exch_t *exch;
688
689 exch = async_exchange_begin(srv->client_sess);
690 async_msg_0(exch, DISPLAY_EV_PENDING);
691 async_exchange_end(exch);
692}
693
694/** @}
695 */
Note: See TracBrowser for help on using the repository browser.