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

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

Change the correct pointer's shape when resizing window

The request to resize a window originates from the client. The display
server forces the cursor to a double-arrow shape regardless of whether
it is over the window or not, until the resize is done. This is to
make sure the cursor keeps that shape even if it moves outside of
the current boundaries of the window. With multiple pointers we need
to know which one to change. This is done by passing the pos_id from
button press event that starts the resize all the way to
ds_window_start_resize(). Then it needs to be stored in the window
structure for use when it is time to restore the cursor.

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