Changes in uspace/lib/ui/src/ui.c [899bdfd:3d10a2f] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified uspace/lib/ui/src/ui.c

    r899bdfd r3d10a2f  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939#include <errno.h>
    4040#include <fibril.h>
    41 #include <fibril_synch.h>
    4241#include <gfx/color.h>
    43 #include <gfx/cursor.h>
    4442#include <gfx/render.h>
    4543#include <io/console.h>
     
    4846#include <str.h>
    4947#include <task.h>
    50 #include <types/common.h>
    51 #include <ui/clickmatic.h>
    5248#include <ui/ui.h>
    5349#include <ui/wdecor.h>
    5450#include <ui/window.h>
    55 #include "../private/wdecor.h"
    5651#include "../private/window.h"
    5752#include "../private/ui.h"
     
    6661 * @param ws Place to store window system type (protocol)
    6762 * @param osvc Place to store pointer to output service name
    68  * @param ridev_id Place to store input device ID
    69  * @return EOK on success, EINVAL if syntax is invalid, ENOMEM if out of
    70  *         memory
    71  */
    72 static errno_t ui_ospec_parse(const char *ospec, ui_winsys_t *ws,
    73     char **osvc, sysarg_t *ridev_id)
     63 */
     64static void ui_ospec_parse(const char *ospec, ui_winsys_t *ws,
     65    const char **osvc)
    7466{
    7567        const char *cp;
    76         const char *qm;
    77         const char *endptr;
    78         uint64_t idev_id;
    79         errno_t rc;
    80 
    81         *ridev_id = 0;
     68
     69        if (ospec == UI_DISPLAY_DEFAULT) {
     70                *ws = ui_ws_display;
     71                *osvc = DISPLAY_DEFAULT;
     72                return;
     73        }
    8274
    8375        cp = ospec;
     
    8577                ++cp;
    8678
    87         /* Window system / protocol */
    8879        if (*cp == '@') {
    8980                if (str_lcmp(ospec, "disp@", str_length("disp@")) == 0) {
     
    9384                } else if (str_lcmp(ospec, "null@", str_length("null@")) == 0) {
    9485                        *ws = ui_ws_null;
    95                 } else if (str_lcmp(ospec, "@", str_length("@")) == 0) {
    96                         *ws = ui_ws_any;
    9786                } else {
    9887                        *ws = ui_ws_unknown;
    9988                }
    10089
    101                 ++cp;
     90                if (cp[1] != '\0')
     91                        *osvc = cp + 1;
     92                else
     93                        *osvc = NULL;
    10294        } else {
    10395                *ws = ui_ws_display;
    104         }
    105 
    106         /* Output service is the part before question mark */
    107         qm = str_chr(cp, '?');
    108         if (qm != NULL) {
    109                 *osvc = str_ndup(cp, qm - cp);
    110         } else {
    111                 /* No question mark */
    112                 *osvc = str_dup(cp);
    113         }
    114 
    115         if (*osvc == NULL)
    116                 return ENOMEM;
    117 
    118         if (qm != NULL) {
    119                 /* The part after the question mark */
    120                 cp = qm + 1;
    121 
    122                 /* Input device ID parameter */
    123                 if (str_lcmp(cp, "idev=", str_length("idev=")) == 0) {
    124                         cp += str_length("idev=");
    125 
    126                         rc = str_uint64_t(cp, &endptr, 10, false, &idev_id);
    127                         if (rc != EOK)
    128                                 goto error;
    129 
    130                         *ridev_id = idev_id;
    131                         cp = endptr;
    132                 }
    133         }
    134 
    135         if (*cp != '\0') {
    136                 rc = EINVAL;
    137                 goto error;
    138         }
    139 
    140         return EOK;
    141 error:
    142         free(*osvc);
    143         *osvc = NULL;
    144         return rc;
     96                *osvc = ospec;
     97        }
    14598}
    14699
     
    161114        console_gc_t *cgc;
    162115        ui_winsys_t ws;
    163         char *osvc;
     116        const char *osvc;
    164117        sysarg_t cols;
    165118        sysarg_t rows;
    166         sysarg_t idev_id;
    167119        ui_t *ui;
    168120
    169         rc = ui_ospec_parse(ospec, &ws, &osvc, &idev_id);
    170         if (rc != EOK)
    171                 return rc;
    172 
    173         if (ws == ui_ws_display || ws == ui_ws_any) {
    174                 rc = display_open((str_cmp(osvc, "") != 0) ? osvc :
    175                     DISPLAY_DEFAULT, &display);
     121        ui_ospec_parse(ospec, &ws, &osvc);
     122
     123        if (ws == ui_ws_display) {
     124                rc = display_open(osvc, &display);
    176125                if (rc != EOK)
    177                         goto disp_fail;
     126                        return rc;
    178127
    179128                rc = ui_create_disp(display, &ui);
    180129                if (rc != EOK) {
    181130                        display_close(display);
    182                         goto disp_fail;
    183                 }
    184 
    185                 free(osvc);
    186                 ui->myoutput = true;
    187                 ui->idev_id = idev_id;
    188                 *rui = ui;
    189                 return EOK;
    190         }
    191 
    192 disp_fail:
    193         if (ws == ui_ws_console || ws == ui_ws_any) {
     131                        return rc;
     132                }
     133        } else if (ws == ui_ws_console) {
    194134                console = console_init(stdin, stdout);
    195135                if (console == NULL)
    196                         goto cons_fail;
     136                        return EIO;
    197137
    198138                rc = console_get_size(console, &cols, &rows);
    199139                if (rc != EOK) {
    200140                        console_done(console);
    201                         goto cons_fail;
     141                        return rc;
    202142                }
    203143
     
    208148                if (rc != EOK) {
    209149                        console_done(console);
    210                         goto cons_fail;
     150                        return rc;
    211151                }
    212152
     
    215155                        ui_destroy(ui);
    216156                        console_done(console);
    217                         goto cons_fail;
    218                 }
    219 
    220                 free(osvc);
     157                        return rc;
     158                }
    221159
    222160                ui->cgc = cgc;
     
    227165
    228166                (void) ui_paint(ui);
    229                 ui->myoutput = true;
    230                 *rui = ui;
    231                 return EOK;
    232         }
    233 
    234 cons_fail:
    235         if (ws == ui_ws_null) {
    236                 free(osvc);
     167        } else if (ws == ui_ws_null) {
    237168                rc = ui_create_disp(NULL, &ui);
    238169                if (rc != EOK)
    239170                        return rc;
    240 
    241                 ui->myoutput = true;
    242                 *rui = ui;
    243                 return EOK;
    244         }
    245 
    246         free(osvc);
    247         return EINVAL;
     171        } else {
     172                return EINVAL;
     173        }
     174
     175        ui->myoutput = true;
     176        *rui = ui;
     177        return EOK;
    248178}
    249179
     
    256186{
    257187        ui_t *ui;
    258         errno_t rc;
    259188
    260189        ui = calloc(1, sizeof(ui_t));
     
    262191                return ENOMEM;
    263192
    264         rc = ui_clickmatic_create(ui, &ui->clickmatic);
    265         if (rc != EOK) {
    266                 free(ui);
    267                 return rc;
    268         }
    269 
    270193        ui->console = console;
    271194        list_initialize(&ui->windows);
    272         fibril_mutex_initialize(&ui->lock);
    273195        *rui = ui;
    274196        return EOK;
     
    284206{
    285207        ui_t *ui;
    286         errno_t rc;
    287208
    288209        ui = calloc(1, sizeof(ui_t));
     
    290211                return ENOMEM;
    291212
    292         rc = ui_clickmatic_create(ui, &ui->clickmatic);
    293         if (rc != EOK) {
    294                 free(ui);
    295                 return rc;
    296         }
    297 
    298213        ui->display = disp;
    299214        list_initialize(&ui->windows);
    300         fibril_mutex_initialize(&ui->lock);
    301215        *rui = ui;
    302216        return EOK;
     
    338252        switch (event->type) {
    339253        case CEV_KEY:
    340                 ui_lock(ui);
    341254                ui_window_send_kbd(awnd, &event->ev.key);
    342                 ui_unlock(ui);
    343255                break;
    344256        case CEV_POS:
     
    350262                claim = ui_wdecor_pos_event(awnd->wdecor, &pos);
    351263                /* Note: If event is claimed, awnd might not be valid anymore */
    352                 if (claim == ui_unclaimed) {
    353                         ui_lock(ui);
     264                if (claim == ui_unclaimed)
    354265                        ui_window_send_pos(awnd, &pos);
    355                         ui_unlock(ui);
    356                 }
    357 
    358                 break;
    359         case CEV_RESIZE:
    360                 ui_lock(ui);
    361                 ui_window_send_resize(awnd);
    362                 ui_unlock(ui);
     266
    363267                break;
    364268        }
     
    451355}
    452356
    453 /** Free up console for other users.
    454  *
    455  * Release console resources for another application (that the current
    456  * task is starting). After the other application finishes, resume
    457  * operation with ui_resume(). No calls to UI must happen inbetween
    458  * and no events must be processed (i.e. the calling function must not
    459  * return control to UI.
    460  *
    461  * @param ui UI
    462  * @return EOK on success or an error code
    463  */
    464 errno_t ui_suspend(ui_t *ui)
    465 {
    466         errno_t rc;
    467 
    468         assert(!ui->suspended);
    469 
    470         if (ui->cgc == NULL) {
    471                 ui->suspended = true;
    472                 return EOK;
    473         }
    474 
    475         (void) console_set_caption(ui->console, "");
    476         rc = console_gc_suspend(ui->cgc);
    477         if (rc != EOK)
    478                 return rc;
    479 
    480         ui->suspended = true;
    481         return EOK;
    482 }
    483 
    484 /** Resume suspended UI.
    485  *
    486  * Reclaim console resources (after child application has finished running)
    487  * and restore UI operation previously suspended by calling ui_suspend().
    488  *
    489  * @param ui UI
    490  * @return EOK on success or an error code
    491  */
    492 errno_t ui_resume(ui_t *ui)
    493 {
    494         errno_t rc;
    495         ui_window_t *awnd;
    496         sysarg_t col;
    497         sysarg_t row;
    498         cons_event_t ev;
    499 
    500         assert(ui->suspended);
    501 
    502         if (ui->cgc == NULL) {
    503                 ui->suspended = false;
    504                 return EOK;
    505         }
    506 
    507         rc = console_get_pos(ui->console, &col, &row);
    508         if (rc != EOK)
    509                 return rc;
    510 
    511         /*
    512          * Here's a little heuristic to help determine if we need
    513          * to pause before returning to the UI. If we are in the
    514          * top-left corner, chances are the screen is empty and
    515          * there is no need to pause.
    516          */
    517         if (col != 0 || row != 0) {
    518                 printf("Press any key or button to continue...\n");
    519 
    520                 while (true) {
    521                         rc = console_get_event(ui->console, &ev);
    522                         if (rc != EOK)
    523                                 return EIO;
    524 
    525                         if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS)
    526                                 break;
    527 
    528                         if (ev.type == CEV_POS && ev.ev.pos.type == POS_PRESS)
    529                                 break;
    530                 }
    531         }
    532 
    533         rc = console_gc_resume(ui->cgc);
    534         if (rc != EOK)
    535                 return rc;
    536 
    537         ui->suspended = false;
    538 
    539         awnd = ui_window_get_active(ui);
    540         if (awnd != NULL)
    541                 (void) console_set_caption(ui->console, awnd->wdecor->caption);
    542 
    543         rc = gfx_cursor_set_visible(console_gc_get_ctx(ui->cgc), false);
    544         if (rc != EOK)
    545                 return rc;
    546 
    547         return EOK;
    548 }
    549 
    550 /** Determine if UI is suspended.
    551  *
    552  * @param ui UI
    553  * @return @c true iff UI is suspended
    554  */
    555 bool ui_is_suspended(ui_t *ui)
    556 {
    557         return ui->suspended;
    558 }
    559 
    560 /** Lock UI.
    561  *
    562  * Block UI from calling window callbacks. @c ui_lock() and @c ui_unlock()
    563  * must be used when accessing UI resources from a fibril (as opposed to
    564  * from a window callback).
    565  *
    566  * @param ui UI
    567  */
    568 void ui_lock(ui_t *ui)
    569 {
    570         fibril_mutex_lock(&ui->lock);
    571 }
    572 
    573 /** Unlock UI.
    574  *
    575  * Allow UI to call window callbacks. @c ui_lock() and @c ui_unlock()
    576  * must be used when accessing window resources from a fibril (as opposed to
    577  * from a window callback).
    578  *
    579  * @param ui UI
    580  */
    581 void ui_unlock(ui_t *ui)
    582 {
    583         fibril_mutex_unlock(&ui->lock);
    584 }
    585 
    586357/** Terminate user interface.
    587358 *
     
    621392}
    622393
    623 /** Get UI screen rectangle.
    624  *
    625  * @param ui User interface
    626  * @param rect Place to store bounding rectangle
    627  */
    628 errno_t ui_get_rect(ui_t *ui, gfx_rect_t *rect)
    629 {
    630         display_info_t info;
    631         sysarg_t cols, rows;
    632         errno_t rc;
    633 
    634         if (ui->display != NULL) {
    635                 rc = display_get_info(ui->display, &info);
    636                 if (rc != EOK)
    637                         return rc;
    638 
    639                 *rect = info.rect;
    640         } else if (ui->console != NULL) {
    641                 rc = console_get_size(ui->console, &cols, &rows);
    642                 if (rc != EOK)
    643                         return rc;
    644 
    645                 rect->p0.x = 0;
    646                 rect->p0.y = 0;
    647                 rect->p1.x = cols;
    648                 rect->p1.y = rows;
    649         } else {
    650                 return ENOTSUP;
    651         }
    652 
    653         return EOK;
    654 }
    655 
    656 /** Get clickmatic from UI.
    657  *
    658  * @pararm ui UI
    659  * @return Clickmatic
    660  */
    661 ui_clickmatic_t *ui_get_clickmatic(ui_t *ui)
    662 {
    663         return ui->clickmatic;
    664 }
    665 
    666394/** @}
    667395 */
Note: See TracChangeset for help on using the changeset viewer.