source: mainline/uspace/lib/display/src/display.c@ b0ae23f

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b0ae23f was b0ae23f, checked in by Jiri Svoboda <jiri@…>, 3 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: 19.6 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#include <async.h>
30#include <display.h>
31#include <display/event.h>
32#include <errno.h>
33#include <fibril_synch.h>
34#include <ipc/display.h>
35#include <ipc/services.h>
36#include <ipcgfx/client.h>
37#include <loc.h>
38#include <mem.h>
39#include <stdlib.h>
40#include <str.h>
41#include "../private/display.h"
42#include "../private/params.h"
43
44static errno_t display_callback_create(display_t *);
45static void display_cb_conn(ipc_call_t *, void *);
46static errno_t display_get_window(display_t *, sysarg_t, display_window_t **);
47
48/** Open display service.
49 *
50 * @param dsname Display service name or @c NULL to use default display
51 * @param rdisplay Place to store pointer to display session
52 * @return EOK on success or an error code
53 */
54errno_t display_open(const char *dsname, display_t **rdisplay)
55{
56 service_id_t display_svc;
57 display_t *display;
58 errno_t rc;
59
60 display = calloc(1, sizeof(display_t));
61 if (display == NULL)
62 return ENOMEM;
63
64 fibril_mutex_initialize(&display->lock);
65 fibril_condvar_initialize(&display->cv);
66 list_initialize(&display->windows);
67
68 if (dsname == NULL)
69 dsname = SERVICE_NAME_DISPLAY;
70
71 rc = loc_service_get_id(dsname, &display_svc, 0);
72 if (rc != EOK) {
73 free(display);
74 return ENOENT;
75 }
76
77 display->sess = loc_service_connect(display_svc, INTERFACE_DISPLAY,
78 0);
79 if (display->sess == NULL) {
80 free(display);
81 return ENOENT;
82 }
83
84 rc = display_callback_create(display);
85 if (rc != EOK) {
86 async_hangup(display->sess);
87 free(display);
88 return EIO;
89 }
90
91 *rdisplay = display;
92 return EOK;
93}
94
95/** Create callback connection from display service.
96 *
97 * @param display Display session
98 * @return EOK on success or an error code
99 */
100static errno_t display_callback_create(display_t *display)
101{
102 async_exch_t *exch = async_exchange_begin(display->sess);
103
104 aid_t req = async_send_0(exch, DISPLAY_CALLBACK_CREATE, NULL);
105
106 port_id_t port;
107 errno_t rc = async_create_callback_port(exch, INTERFACE_DISPLAY_CB, 0, 0,
108 display_cb_conn, display, &port);
109
110 async_exchange_end(exch);
111
112 if (rc != EOK)
113 return rc;
114
115 errno_t retval;
116 async_wait_for(req, &retval);
117
118 return retval;
119}
120
121/** Close display service.
122 *
123 * @param display Display session
124 */
125void display_close(display_t *display)
126{
127 fibril_mutex_lock(&display->lock);
128 async_hangup(display->sess);
129 display->sess = NULL;
130
131 /* Wait for callback handler to terminate */
132
133 while (!display->cb_done)
134 fibril_condvar_wait(&display->cv, &display->lock);
135 fibril_mutex_unlock(&display->lock);
136
137 free(display);
138}
139
140/** Initialize window parameters structure.
141 *
142 * Window parameters structure must always be initialized using this function
143 * first.
144 *
145 * @param params Window parameters structure
146 */
147void display_wnd_params_init(display_wnd_params_t *params)
148{
149 memset(params, 0, sizeof(*params));
150 params->caption = "";
151}
152
153/** Create a display window.
154 *
155 * @param display Display
156 * @param params Window parameters
157 * @param cb Callback functions
158 * @param cb_arg Argument to callback functions
159 * @param rwindow Place to store pointer to new window
160 * @return EOK on success or an error code
161 */
162errno_t display_window_create(display_t *display, display_wnd_params_t *params,
163 display_wnd_cb_t *cb, void *cb_arg, display_window_t **rwindow)
164{
165 display_window_t *window;
166 display_wnd_params_enc_t eparams;
167 async_exch_t *exch;
168 aid_t req;
169 ipc_call_t answer;
170 errno_t rc;
171
172 /* Encode the parameters for transport */
173 eparams.rect = params->rect;
174 eparams.caption_size = str_size(params->caption);
175 eparams.min_size = params->min_size;
176 eparams.pos = params->pos;
177 eparams.flags = params->flags;
178
179 window = calloc(1, sizeof(display_window_t));
180 if (window == NULL)
181 return ENOMEM;
182
183 exch = async_exchange_begin(display->sess);
184 req = async_send_0(exch, DISPLAY_WINDOW_CREATE, &answer);
185
186 /* Write fixed fields */
187 rc = async_data_write_start(exch, &eparams,
188 sizeof (display_wnd_params_enc_t));
189 if (rc != EOK) {
190 async_exchange_end(exch);
191 async_forget(req);
192 free(window);
193 return rc;
194 }
195
196 /* Write caption */
197 rc = async_data_write_start(exch, params->caption,
198 eparams.caption_size);
199 async_exchange_end(exch);
200 if (rc != EOK) {
201 async_forget(req);
202 free(window);
203 return rc;
204 }
205
206 async_wait_for(req, &rc);
207 if (rc != EOK) {
208 free(window);
209 return rc;
210 }
211
212 window->display = display;
213 window->id = ipc_get_arg1(&answer);
214 window->cb = cb;
215 window->cb_arg = cb_arg;
216
217 list_append(&window->lwindows, &display->windows);
218 *rwindow = window;
219 return EOK;
220}
221
222/** Destroy display window.
223 *
224 * @param window Window or @c NULL
225 * @return EOK on success or an error code. In both cases @a window must
226 * not be accessed anymore
227 */
228errno_t display_window_destroy(display_window_t *window)
229{
230 async_exch_t *exch;
231 errno_t rc;
232
233 if (window == NULL)
234 return EOK;
235
236 exch = async_exchange_begin(window->display->sess);
237 rc = async_req_1_0(exch, DISPLAY_WINDOW_DESTROY, window->id);
238
239 async_exchange_end(exch);
240
241 list_remove(&window->lwindows);
242 free(window);
243 return rc;
244}
245
246/** Create graphics context for drawing into a window.
247 *
248 * @param window Window
249 * @param rgc Place to store pointer to new graphics context
250 * @return EOK on success or an error code
251 */
252errno_t display_window_get_gc(display_window_t *window, gfx_context_t **rgc)
253{
254 async_sess_t *sess;
255 async_exch_t *exch;
256 ipc_gc_t *gc;
257 errno_t rc;
258
259 exch = async_exchange_begin(window->display->sess);
260 sess = async_connect_me_to(exch, INTERFACE_GC, 0, window->id, &rc);
261 if (sess == NULL) {
262 async_exchange_end(exch);
263 return rc;
264 }
265
266 async_exchange_end(exch);
267
268 rc = ipc_gc_create(sess, &gc);
269 if (rc != EOK) {
270 async_hangup(sess);
271 return ENOMEM;
272 }
273
274 *rgc = ipc_gc_get_ctx(gc);
275 return EOK;
276}
277
278/** Request a window move.
279 *
280 * Request the display service to initiate a user window move operation
281 * (i.e. let the user move the window). Used when the client detects
282 * mouse press on the title bar or such.
283 *
284 * @param window Window
285 * @param pos Position in the window where the button was pressed
286 * @return EOK on success or an error code
287 */
288errno_t display_window_move_req(display_window_t *window, gfx_coord2_t *pos)
289{
290 async_exch_t *exch;
291 aid_t req;
292 ipc_call_t answer;
293 errno_t rc;
294
295 exch = async_exchange_begin(window->display->sess);
296 req = async_send_1(exch, DISPLAY_WINDOW_MOVE_REQ, window->id, &answer);
297 rc = async_data_write_start(exch, (void *)pos, sizeof (gfx_coord2_t));
298 async_exchange_end(exch);
299 if (rc != EOK) {
300 async_forget(req);
301 return rc;
302 }
303
304 async_wait_for(req, &rc);
305 if (rc != EOK)
306 return rc;
307
308 return EOK;
309}
310
311/** Move display window.
312 *
313 * Set new display position of a window. Display position determines where
314 * the origin of the window coordinate system lies. Note that the top left
315 * corner of the window need not coincide with the window's 0,0 point.
316 *
317 * @param window Window
318 * @param dpos New display position
319 * @return EOK on success or an error code
320 */
321errno_t display_window_move(display_window_t *window, gfx_coord2_t *dpos)
322{
323 async_exch_t *exch;
324 aid_t req;
325 ipc_call_t answer;
326 errno_t rc;
327
328 exch = async_exchange_begin(window->display->sess);
329 req = async_send_1(exch, DISPLAY_WINDOW_MOVE, window->id, &answer);
330 rc = async_data_write_start(exch, dpos, sizeof (gfx_coord2_t));
331 async_exchange_end(exch);
332 if (rc != EOK) {
333 async_forget(req);
334 return rc;
335 }
336
337 async_wait_for(req, &rc);
338 if (rc != EOK)
339 return rc;
340
341 return EOK;
342}
343
344/** Get display window position.
345 *
346 * Get display window position on the display.
347 *
348 * @param window Window
349 * @param dpos Place to store position
350 * @return EOK on success or an error code
351 */
352errno_t display_window_get_pos(display_window_t *window, gfx_coord2_t *dpos)
353{
354 async_exch_t *exch;
355 aid_t req;
356 ipc_call_t answer;
357 errno_t rc;
358
359 exch = async_exchange_begin(window->display->sess);
360 req = async_send_1(exch, DISPLAY_WINDOW_GET_POS, window->id, &answer);
361 rc = async_data_read_start(exch, dpos, sizeof (gfx_coord2_t));
362 async_exchange_end(exch);
363 if (rc != EOK) {
364 async_forget(req);
365 return rc;
366 }
367
368 async_wait_for(req, &rc);
369 if (rc != EOK)
370 return rc;
371
372 return EOK;
373}
374
375/** Get display window maximized rectangle.
376 *
377 * Get the rectangle to which a window would be maximized.
378 *
379 * @param window Window
380 * @param rect Place to store maximized rectangle
381 * @return EOK on success or an error code
382 */
383errno_t display_window_get_max_rect(display_window_t *window, gfx_rect_t *rect)
384{
385 async_exch_t *exch;
386 aid_t req;
387 ipc_call_t answer;
388 errno_t rc;
389
390 exch = async_exchange_begin(window->display->sess);
391 req = async_send_1(exch, DISPLAY_WINDOW_GET_MAX_RECT, window->id,
392 &answer);
393 rc = async_data_read_start(exch, rect, sizeof (gfx_rect_t));
394 async_exchange_end(exch);
395 if (rc != EOK) {
396 async_forget(req);
397 return rc;
398 }
399
400 async_wait_for(req, &rc);
401 if (rc != EOK)
402 return rc;
403
404 return EOK;
405}
406
407/** Request a window resize.
408 *
409 * Request the display service to initiate a user window resize operation
410 * (i.e. let the user resize the window). Used when the client detects
411 * mouse press on the window frame or such.
412 *
413 * @param window Window
414 * @param rsztype Resize type (which part of window frame is being dragged)
415 * @param pos Position in the window where the button was pressed
416 * @param pos_id Positioning device ID
417 * @return EOK on success or an error code
418 */
419errno_t display_window_resize_req(display_window_t *window,
420 display_wnd_rsztype_t rsztype, gfx_coord2_t *pos, sysarg_t pos_id)
421{
422 async_exch_t *exch;
423 aid_t req;
424 ipc_call_t answer;
425 errno_t rc;
426
427 exch = async_exchange_begin(window->display->sess);
428 req = async_send_3(exch, DISPLAY_WINDOW_RESIZE_REQ, window->id,
429 (sysarg_t) rsztype, pos_id, &answer);
430 rc = async_data_write_start(exch, (void *)pos, sizeof (gfx_coord2_t));
431 async_exchange_end(exch);
432 if (rc != EOK) {
433 async_forget(req);
434 return rc;
435 }
436
437 async_wait_for(req, &rc);
438 if (rc != EOK)
439 return rc;
440
441 return EOK;
442}
443
444/** Resize display window.
445 *
446 * It seems resizing windows should be easy with bounding rectangles.
447 * You have an old bounding rectangle and a new bounding rectangle (@a nrect).
448 * Change .p0 and top-left corner moves. Change .p1 and bottom-right corner
449 * moves. Piece of cake!
450 *
451 * There's always a catch, though. By series of resizes and moves .p0 could
452 * drift outside of the range of @c gfx_coord_t. Now what? @a offs to the
453 * rescue! @a offs moves the @em boundaries of the window with respect
454 * to the display, while keeping the @em contents of the window in the
455 * same place (with respect to the display). In other words, @a offs shifts
456 * the window's internal coordinate system.
457 *
458 * A few examples follow:
459 *
460 * Enlarge window by moving bottom-right corner 1 right, 1 down:
461 *
462 * bound = (0, 0, 10, 10)
463 * offs = (0, 0)
464 * nrect = (0, 0, 11, 11)
465 *
466 * Enlarge window by moving top-left corner, 1 up, 1 left, allowing the
467 * window-relative coordinate of the top-left corner to drift (undesirable)
468 *
469 * bound = (0, 0, 10, 10)
470 * offs = (0, 0)
471 * nrect = (-1, -1, 10, 10) <- this is the new bounding rectangle
472 *
473 * Enlarge window by moving top-left corner 1 up, 1 left, keeping top-left
474 * corner locked to (0,0) window-relative coordinates (desirable):
475 *
476 * bound = (0, 0, 10, 10)
477 * off = (-1,-1) <- top-left corner goes 1 up, 1 left
478 * nrect = (0, 0, 11, 11) <- window still starts at 0,0 window-relative
479 *
480 * @param window Window
481 * @param nrect New bounding rectangle
482 * @param offs
483 * @return EOK on success or an error code
484 */
485errno_t display_window_resize(display_window_t *window, gfx_coord2_t *offs,
486 gfx_rect_t *nrect)
487{
488 async_exch_t *exch;
489 aid_t req;
490 ipc_call_t answer;
491 display_wnd_resize_t wresize;
492 errno_t rc;
493
494 wresize.offs = *offs;
495 wresize.nrect = *nrect;
496
497 exch = async_exchange_begin(window->display->sess);
498 req = async_send_1(exch, DISPLAY_WINDOW_RESIZE, window->id, &answer);
499 rc = async_data_write_start(exch, &wresize, sizeof (display_wnd_resize_t));
500 async_exchange_end(exch);
501 if (rc != EOK) {
502 async_forget(req);
503 return rc;
504 }
505
506 async_wait_for(req, &rc);
507 if (rc != EOK)
508 return rc;
509
510 return EOK;
511}
512
513/** Minimize window.
514 *
515 * @param window Window
516 * @return EOK on success or an error code
517 */
518errno_t display_window_minimize(display_window_t *window)
519{
520 async_exch_t *exch;
521 errno_t rc;
522
523 exch = async_exchange_begin(window->display->sess);
524 rc = async_req_1_0(exch, DISPLAY_WINDOW_MINIMIZE, window->id);
525 async_exchange_end(exch);
526
527 return rc;
528}
529
530/** Maximize window.
531 *
532 * @param window Window
533 * @return EOK on success or an error code
534 */
535errno_t display_window_maximize(display_window_t *window)
536{
537 async_exch_t *exch;
538 errno_t rc;
539
540 exch = async_exchange_begin(window->display->sess);
541 rc = async_req_1_0(exch, DISPLAY_WINDOW_MAXIMIZE, window->id);
542 async_exchange_end(exch);
543
544 return rc;
545}
546
547/** Unmaximize window.
548 *
549 * @param window Window
550 * @return EOK on success or an error code
551 */
552errno_t display_window_unmaximize(display_window_t *window)
553{
554 async_exch_t *exch;
555 errno_t rc;
556
557 exch = async_exchange_begin(window->display->sess);
558 rc = async_req_1_0(exch, DISPLAY_WINDOW_UNMAXIMIZE, window->id);
559 async_exchange_end(exch);
560
561 return rc;
562}
563
564/** Set window cursor.
565 *
566 * Set cursor that is displayed when pointer is over the window. The default
567 * is the arrow pointer.
568 *
569 * @param window Window
570 * @param cursor Cursor to display
571 * @return EOK on success or an error code
572 */
573errno_t display_window_set_cursor(display_window_t *window,
574 display_stock_cursor_t cursor)
575{
576 async_exch_t *exch;
577 errno_t rc;
578
579 exch = async_exchange_begin(window->display->sess);
580 rc = async_req_2_0(exch, DISPLAY_WINDOW_SET_CURSOR, window->id,
581 cursor);
582 async_exchange_end(exch);
583 return rc;
584}
585
586/** Set display window caption.
587 *
588 * @param window Window
589 * @param caption New caption
590 * @return EOK on success or an error code
591 */
592errno_t display_window_set_caption(display_window_t *window,
593 const char *caption)
594{
595 async_exch_t *exch;
596 aid_t req;
597 ipc_call_t answer;
598 size_t cap_size;
599 errno_t rc;
600
601 cap_size = str_size(caption);
602
603 exch = async_exchange_begin(window->display->sess);
604 req = async_send_1(exch, DISPLAY_WINDOW_SET_CAPTION, window->id,
605 &answer);
606
607 /* Write caption */
608 rc = async_data_write_start(exch, caption, cap_size);
609 async_exchange_end(exch);
610 if (rc != EOK) {
611 async_forget(req);
612 return rc;
613 }
614
615 async_wait_for(req, &rc);
616 return rc;
617}
618
619/** Get display event.
620 *
621 * @param display Display
622 * @param rwindow Place to store pointer to window that received event
623 * @param event Place to store event
624 * @return EOK on success or an error code
625 */
626static errno_t display_get_event(display_t *display, display_window_t **rwindow,
627 display_wnd_ev_t *event)
628{
629 async_exch_t *exch;
630 ipc_call_t answer;
631 aid_t req;
632 errno_t rc;
633 sysarg_t wnd_id;
634 display_window_t *window;
635
636 exch = async_exchange_begin(display->sess);
637 req = async_send_0(exch, DISPLAY_GET_EVENT, &answer);
638 rc = async_data_read_start(exch, event, sizeof(*event));
639 async_exchange_end(exch);
640 if (rc != EOK) {
641 async_forget(req);
642 return rc;
643 }
644
645 async_wait_for(req, &rc);
646 if (rc != EOK)
647 return rc;
648
649 wnd_id = ipc_get_arg1(&answer);
650 rc = display_get_window(display, wnd_id, &window);
651 if (rc != EOK)
652 return EIO;
653
654 *rwindow = window;
655 return EOK;
656}
657
658/** Get display information.
659 *
660 * @param display Display
661 * @param info Place to store display information
662 * @return EOK on success or an error code
663 */
664errno_t display_get_info(display_t *display, display_info_t *info)
665{
666 async_exch_t *exch;
667 ipc_call_t answer;
668 aid_t req;
669 errno_t rc;
670
671 exch = async_exchange_begin(display->sess);
672 req = async_send_0(exch, DISPLAY_GET_INFO, &answer);
673 rc = async_data_read_start(exch, info, sizeof(*info));
674 async_exchange_end(exch);
675 if (rc != EOK) {
676 async_forget(req);
677 return rc;
678 }
679
680 async_wait_for(req, &rc);
681 if (rc != EOK)
682 return rc;
683
684 return EOK;
685}
686
687/** Display events are pending.
688 *
689 * @param display Display
690 * @param icall Call data
691 */
692static void display_ev_pending(display_t *display, ipc_call_t *icall)
693{
694 errno_t rc;
695 display_window_t *window = NULL;
696 display_wnd_ev_t event;
697
698 while (true) {
699 fibril_mutex_lock(&display->lock);
700
701 if (display->sess != NULL)
702 rc = display_get_event(display, &window, &event);
703 else
704 rc = ENOENT;
705
706 fibril_mutex_unlock(&display->lock);
707
708 if (rc != EOK)
709 break;
710
711 switch (event.etype) {
712 case wev_close:
713 if (window->cb != NULL && window->cb->close_event != NULL) {
714 window->cb->close_event(window->cb_arg);
715 }
716 break;
717 case wev_focus:
718 if (window->cb != NULL && window->cb->focus_event != NULL) {
719 window->cb->focus_event(window->cb_arg,
720 event.ev.focus.nfocus);
721 }
722 break;
723 case wev_kbd:
724 if (window->cb != NULL && window->cb->kbd_event != NULL) {
725 window->cb->kbd_event(window->cb_arg,
726 &event.ev.kbd);
727 }
728 break;
729 case wev_pos:
730 if (window->cb != NULL && window->cb->pos_event != NULL) {
731 window->cb->pos_event(window->cb_arg,
732 &event.ev.pos);
733 }
734 break;
735 case wev_resize:
736 if (window->cb != NULL && window->cb->resize_event != NULL) {
737 window->cb->resize_event(window->cb_arg,
738 &event.ev.resize.rect);
739 }
740 break;
741 case wev_unfocus:
742 if (window->cb != NULL && window->cb->unfocus_event != NULL) {
743 window->cb->unfocus_event(window->cb_arg,
744 event.ev.unfocus.nfocus);
745 }
746 break;
747 }
748 }
749
750 async_answer_0(icall, EOK);
751}
752
753/** Callback connection handler.
754 *
755 * @param icall Connect call data
756 * @param arg Argument, display_t *
757 */
758static void display_cb_conn(ipc_call_t *icall, void *arg)
759{
760 display_t *display = (display_t *) arg;
761
762 while (true) {
763 ipc_call_t call;
764 async_get_call(&call);
765
766 if (!ipc_get_imethod(&call)) {
767 /* Hangup */
768 async_answer_0(&call, EOK);
769 goto out;
770 }
771
772 switch (ipc_get_imethod(&call)) {
773 case DISPLAY_EV_PENDING:
774 display_ev_pending(display, &call);
775 break;
776 default:
777 async_answer_0(&call, ENOTSUP);
778 break;
779 }
780 }
781
782out:
783 fibril_mutex_lock(&display->lock);
784 display->cb_done = true;
785 fibril_mutex_unlock(&display->lock);
786 fibril_condvar_broadcast(&display->cv);
787}
788
789/** Find window by ID.
790 *
791 * @param display Display
792 * @param wnd_id Window ID
793 * @param rwindow Place to store pointer to window
794 * @return EOK on success, ENOENT if not found
795 */
796static errno_t display_get_window(display_t *display, sysarg_t wnd_id,
797 display_window_t **rwindow)
798{
799 link_t *link;
800 display_window_t *window;
801
802 link = list_first(&display->windows);
803 while (link != NULL) {
804 window = list_get_instance(link, display_window_t, lwindows);
805 if (window->id == wnd_id) {
806 *rwindow = window;
807 return EOK;
808 }
809
810 link = list_next(link, &display->windows);
811 }
812
813 return ENOENT;
814}
815
816/** @}
817 */
Note: See TracBrowser for help on using the repository browser.