Changeset b3c185b6 in mainline for uspace/lib/display/src/display.c


Ignore:
Timestamp:
2019-11-04T14:05:35Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
be15256
Parents:
22faaf2
git-author:
Jiri Svoboda <jiri@…> (2019-10-03 18:05:09)
git-committer:
Jiri Svoboda <jiri@…> (2019-11-04 14:05:35)
Message:

Window event delivery mechanism

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/display/src/display.c

    r22faaf2 rb3c185b6  
    3030#include <display.h>
    3131#include <errno.h>
     32#include <fibril_synch.h>
    3233#include <ipc/display.h>
    3334#include <ipc/services.h>
     
    3637#include <stdlib.h>
    3738
     39static errno_t display_callback_create(display_t *);
     40static void display_cb_conn(ipc_call_t *, void *);
     41static errno_t display_get_window(display_t *, sysarg_t, display_window_t **);
     42
    3843/** Open display service.
    3944 *
     
    5156        if (display == NULL)
    5257                return ENOMEM;
     58
     59        list_initialize(&display->windows);
    5360
    5461        if (dsname == NULL)
     
    6875        }
    6976
     77        rc = display_callback_create(display);
     78        if (rc != EOK) {
     79                async_hangup(display->sess);
     80                free(display);
     81                return EIO;
     82        }
     83
    7084        *rdisplay = display;
    7185        return EOK;
    7286}
    7387
     88/** Create callback connection from display service.
     89 *
     90 * @param display Display session
     91 * @return EOK on success or an error code
     92 */
     93static errno_t display_callback_create(display_t *display)
     94{
     95        async_exch_t *exch = async_exchange_begin(display->sess);
     96
     97        aid_t req = async_send_0(exch, DISPLAY_CALLBACK_CREATE, NULL);
     98
     99        port_id_t port;
     100        errno_t rc = async_create_callback_port(exch, INTERFACE_DISPLAY_CB, 0, 0,
     101            display_cb_conn, display, &port);
     102
     103        async_exchange_end(exch);
     104
     105        if (rc != EOK)
     106                return rc;
     107
     108        errno_t retval;
     109        async_wait_for(req, &retval);
     110
     111        return retval;
     112}
     113
    74114/** Close display service.
    75115 *
     
    79119{
    80120        async_hangup(display->sess);
     121
     122        /* Wait for callback handler to terminate */
     123
     124        fibril_mutex_lock(&display->lock);
     125        while (!display->cb_done)
     126                fibril_condvar_wait(&display->cv, &display->lock);
     127        fibril_mutex_unlock(&display->lock);
     128
    81129        free(display);
    82130}
     
    85133 *
    86134 * @param display Display
     135 * @param cb Callback functions
     136 * @param cb_arg Argument to callback functions
    87137 * @param rwindow Place to store pointer to new window
    88138 * @return EOK on success or an error code
    89139 */
    90 errno_t display_window_create(display_t *display, display_window_t **rwindow)
     140errno_t display_window_create(display_t *display, display_wnd_cb_t *cb,
     141    void *cb_arg, display_window_t **rwindow)
    91142{
    92143        display_window_t *window;
     
    111162        window->display = display;
    112163        window->id = wnd_id;
     164        window->cb = cb;
     165        window->cb_arg = cb_arg;
     166
     167        list_append(&window->lwindows, &display->windows);
    113168        *rwindow = window;
    114169        return EOK;
     
    166221}
    167222
     223/** Get display event.
     224 *
     225 * @param display Display
     226 * @param rwindow Place to store pointe to window that received event
     227 * @param event Place to store event
     228 * @return EOK on success or an error code
     229 */
     230static errno_t display_get_event(display_t *display, display_window_t **rwindow,
     231    display_wnd_ev_t *event)
     232{
     233        async_exch_t *exch;
     234        ipc_call_t answer;
     235        aid_t req;
     236        errno_t rc;
     237        sysarg_t wnd_id;
     238        display_window_t *window;
     239
     240        exch = async_exchange_begin(display->sess);
     241        req = async_send_0(exch, DISPLAY_GET_EVENT, &answer);
     242        rc = async_data_read_start(exch, event, sizeof(*event));
     243        if (rc != EOK) {
     244                async_forget(req);
     245                return rc;
     246        }
     247
     248        async_exchange_end(exch);
     249
     250        async_wait_for(req, &rc);
     251        if (rc != EOK)
     252                return rc;
     253
     254        wnd_id = ipc_get_arg1(&answer);
     255        rc = display_get_window(display, wnd_id, &window);
     256        if (rc != EOK)
     257                return EIO;
     258
     259        *rwindow = window;
     260        return EOK;
     261}
     262
     263/** Display events are pending.
     264 *
     265 * @param display Display
     266 * @param icall Call data
     267 */
     268static void display_ev_pending(display_t *display, ipc_call_t *icall)
     269{
     270        errno_t rc;
     271        display_window_t *window = NULL;
     272        display_wnd_ev_t event;
     273
     274        while (true) {
     275                rc = display_get_event(display, &window, &event);
     276                if (rc != EOK)
     277                        break;
     278
     279                if (window->cb->kbd_event != NULL)
     280                        window->cb->kbd_event(window->cb_arg, &event.kbd_event);
     281        }
     282
     283        async_answer_0(icall, EOK);
     284}
     285
     286/** Callback connection handler.
     287 *
     288 * @param icall Connect call data
     289 * @param arg   Argument, display_t *
     290 */
     291static void display_cb_conn(ipc_call_t *icall, void *arg)
     292{
     293        display_t *display = (display_t *) arg;
     294
     295        while (true) {
     296                ipc_call_t call;
     297                async_get_call(&call);
     298
     299                if (!ipc_get_imethod(&call)) {
     300                        /* Hangup */
     301                        async_answer_0(&call, EOK);
     302                        goto out;
     303                }
     304
     305                switch (ipc_get_imethod(&call)) {
     306                case DISPLAY_EV_PENDING:
     307                        display_ev_pending(display, &call);
     308                        break;
     309                default:
     310                        async_answer_0(&call, ENOTSUP);
     311                        break;
     312                }
     313        }
     314
     315out:
     316        fibril_mutex_lock(&display->lock);
     317        display->cb_done = true;
     318        fibril_mutex_unlock(&display->lock);
     319        fibril_condvar_broadcast(&display->cv);
     320}
     321
     322/** Find window by ID.
     323 *
     324 * @param display Display
     325 * @param wnd_id Window ID
     326 * @param rwindow Place to store pointer to window
     327 * @return EOK on success, ENOENT if not found
     328 */
     329static errno_t display_get_window(display_t *display, sysarg_t wnd_id,
     330    display_window_t **rwindow)
     331{
     332        link_t *link;
     333        display_window_t *window;
     334
     335        link = list_first(&display->windows);
     336        while (link != NULL) {
     337                window = list_get_instance(link, display_window_t, lwindows);
     338                if (window->id == wnd_id) {
     339                        *rwindow = window;
     340                        return EOK;
     341                }
     342
     343                link = list_next(link, &display->windows);
     344        }
     345
     346        return ENOENT;
     347}
     348
    168349/** @}
    169350 */
Note: See TracChangeset for help on using the changeset viewer.