Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 5d1ff11 in mainline for uspace/srv/hid/console/console.c


Ignore:
Timestamp:
2021-06-29T19:25:50Z (5 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
61bf9dd9
Parents:
e87415e6
Message:

Implement mouse/tablet support in the console

That is, we can now draw text based cursor in the console and deliver
button press events to the application.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/console/console.c

    re87415e6 r5d1ff11  
    6363typedef struct {
    6464        atomic_flag refcnt;      /**< Connection reference count */
    65         prodcons_t input_pc;  /**< Incoming keyboard events */
     65        prodcons_t input_pc;  /**< Incoming console events */
    6666
    6767        /**
     
    9999static sysarg_t cols;
    100100static sysarg_t rows;
     101
     102/** Mouse pointer X coordinate */
     103static int pointer_x;
     104/** Mouse pointer Y coordinate */
     105static int pointer_y;
     106/** Character under mouse cursor */
     107static charfield_t pointer_bg;
     108
     109static int mouse_scale_x = 4;
     110static int mouse_scale_y = 8;
    101111
    102112/** Array of data for virtual consoles */
     
    166176};
    167177
     178static void pointer_draw(void);
     179static void pointer_undraw(void);
     180
    168181static console_t *srv_to_console(con_srv_t *srv)
    169182{
     
    231244
    232245        fibril_mutex_lock(&switch_mtx);
     246        pointer_undraw();
    233247
    234248        if (cons == active_console) {
     
    239253        active_console = cons;
    240254
     255        pointer_draw();
    241256        fibril_mutex_unlock(&switch_mtx);
    242257
    243258        cons_damage(cons);
     259}
     260
     261/** Draw mouse pointer. */
     262static void pointer_draw(void)
     263{
     264        charfield_t *ch;
     265        int col, row;
     266
     267        /* Downscale coordinates to text resolution */
     268        col = pointer_x / mouse_scale_x;
     269        row = pointer_y / mouse_scale_y;
     270
     271        /* Make sure they are in range */
     272        if (col < 0 || row < 0 || col >= (int)cols || row >= (int)rows)
     273                return;
     274
     275        ch = chargrid_charfield_at(active_console->frontbuf, col, row);
     276
     277        /*
     278         * Store background attributes for undrawing the pointer.
     279         * This is necessary as styles cannot be inverted with
     280         * round trip (unlike RGB or INDEX)
     281         */
     282        pointer_bg = *ch;
     283
     284        /* In general the color should be a one's complement of the background */
     285        if (ch->attrs.type == CHAR_ATTR_INDEX) {
     286                ch->attrs.val.index.bgcolor ^= 0xf;
     287                ch->attrs.val.index.fgcolor ^= 0xf;
     288        } else if (ch->attrs.type == CHAR_ATTR_RGB) {
     289                ch->attrs.val.rgb.fgcolor ^= 0xffffff;
     290                ch->attrs.val.rgb.bgcolor ^= 0xffffff;
     291        } else if (ch->attrs.type == CHAR_ATTR_STYLE) {
     292                /* Don't have a proper inverse for each style */
     293                if (ch->attrs.val.style == STYLE_INVERTED)
     294                        ch->attrs.val.style = STYLE_NORMAL;
     295                else
     296                        ch->attrs.val.style = STYLE_INVERTED;
     297        }
     298
     299        /* Make sure the cell gets updated */
     300        ch->flags |= CHAR_FLAG_DIRTY;
     301}
     302
     303/** Undraw mouse pointer. */
     304static void pointer_undraw(void)
     305{
     306        charfield_t *ch;
     307        int col, row;
     308
     309        col = pointer_x / mouse_scale_x;
     310        row = pointer_y / mouse_scale_y;
     311        if (col < 0 || row < 0 || col >= (int)cols || row >= (int)rows)
     312                return;
     313
     314        ch = chargrid_charfield_at(active_console->frontbuf, col, row);
     315        *ch = pointer_bg;
     316        ch->flags |= CHAR_FLAG_DIRTY;
     317}
     318
     319/** Queue console event.
     320 *
     321 * @param cons Console
     322 * @param ev Console event
     323 */
     324static void console_queue_cons_event(console_t *cons, cons_event_t *ev)
     325{
     326        /* Got key press/release event */
     327        cons_event_t *event =
     328            (cons_event_t *) malloc(sizeof(cons_event_t));
     329        if (event == NULL)
     330                return;
     331
     332        *event = *ev;
     333        link_initialize(&event->link);
     334
     335        prodcons_produce(&cons->input_pc, &event->link);
    244336}
    245337
     
    264356    keymod_t mods, char32_t c)
    265357{
     358        cons_event_t event;
     359
    266360        if ((key >= KC_F1) && (key <= KC_F1 + CONSOLE_COUNT) &&
    267361            ((mods & KM_CTRL) == 0)) {
     
    269363        } else {
    270364                /* Got key press/release event */
    271                 kbd_event_t *event =
    272                     (kbd_event_t *) malloc(sizeof(kbd_event_t));
    273                 if (event == NULL) {
    274                         return ENOMEM;
    275                 }
    276 
    277                 link_initialize(&event->link);
    278                 event->type = type;
    279                 event->key = key;
    280                 event->mods = mods;
    281                 event->c = c;
    282 
    283                 prodcons_produce(&active_console->input_pc,
    284                     &event->link);
    285         }
    286 
    287         return EOK;
     365                event.type = CEV_KEY;
     366
     367                event.ev.key.type = type;
     368                event.ev.key.key = key;
     369                event.ev.key.mods = mods;
     370                event.ev.key.c = c;
     371
     372                console_queue_cons_event(active_console, &event);
     373        }
     374
     375        return EOK;
     376}
     377
     378/** Update pointer position.
     379 *
     380 * @param new_x New X coordinate (in pixels)
     381 * @param new_y New Y coordinate (in pixels)
     382 */
     383static void pointer_update(int new_x, int new_y)
     384{
     385        bool upd_pointer;
     386
     387        /* Make sure coordinates are in range */
     388
     389        if (new_x < 0)
     390                new_x = 0;
     391        if (new_x >= (int)cols * mouse_scale_x)
     392                new_x = cols * mouse_scale_x - 1;
     393        if (new_y < 0)
     394                new_y = 0;
     395        if (new_y >= (int)rows * mouse_scale_y)
     396                new_y = rows * mouse_scale_y - 1;
     397
     398        /* Determine if pointer moved to a different character cell */
     399        upd_pointer = (new_x / mouse_scale_x != pointer_x / mouse_scale_x) ||
     400            (new_y / mouse_scale_y != pointer_y / mouse_scale_y);
     401
     402        if (upd_pointer)
     403                pointer_undraw();
     404
     405        /* Store new pointer position */
     406        pointer_x = new_x;
     407        pointer_y = new_y;
     408
     409        if (upd_pointer) {
     410                pointer_draw();
     411                cons_update(active_console);
     412        }
    288413}
    289414
    290415static errno_t input_ev_move(input_t *input, int dx, int dy)
    291416{
     417        pointer_update(pointer_x + dx, pointer_y + dy);
    292418        return EOK;
    293419}
     
    296422    unsigned max_x, unsigned max_y)
    297423{
     424        pointer_update(mouse_scale_x * cols * x / max_x, mouse_scale_y * rows * y / max_y);
    298425        return EOK;
    299426}
     
    301428static errno_t input_ev_button(input_t *input, int bnum, int bpress)
    302429{
     430        cons_event_t event;
     431
     432        event.type = CEV_POS;
     433        event.ev.pos.type = bpress ? POS_PRESS : POS_RELEASE;
     434        event.ev.pos.btn_num = bnum;
     435        event.ev.pos.hpos = pointer_x / mouse_scale_x;
     436        event.ev.pos.vpos = pointer_y / mouse_scale_y;
     437
     438        console_queue_cons_event(active_console, &event);
    303439        return EOK;
    304440}
     
    310446
    311447        fibril_mutex_lock(&cons->mtx);
     448        pointer_undraw();
    312449
    313450        switch (ch) {
     
    327464        }
    328465
     466        pointer_draw();
    329467        fibril_mutex_unlock(&cons->mtx);
    330468
     
    336474{
    337475        fibril_mutex_lock(&cons->mtx);
     476        pointer_undraw();
    338477        chargrid_set_cursor_visibility(cons->frontbuf, visible);
     478        pointer_draw();
    339479        fibril_mutex_unlock(&cons->mtx);
    340480
     
    379519                if (pos < size) {
    380520                        link_t *link = prodcons_consume(&cons->input_pc);
    381                         kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
     521                        cons_event_t *event = list_get_instance(link,
     522                            cons_event_t, link);
    382523
    383524                        /* Accept key presses of printable chars only. */
    384                         if ((event->type == KEY_PRESS) && (event->c != 0)) {
    385                                 char32_t tmp[2] = { event->c, 0 };
     525                        if (event->type == CEV_KEY && event->ev.key.type == KEY_PRESS &&
     526                            (event->ev.key.c != 0)) {
     527                                char32_t tmp[2] = { event->ev.key.c, 0 };
    386528                                wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
    387529                                cons->char_remains_len = str_size(cons->char_remains);
     
    420562
    421563        fibril_mutex_lock(&cons->mtx);
     564        pointer_undraw();
    422565        chargrid_clear(cons->frontbuf);
     566        pointer_draw();
    423567        fibril_mutex_unlock(&cons->mtx);
    424568
     
    431575
    432576        fibril_mutex_lock(&cons->mtx);
     577        pointer_undraw();
    433578        chargrid_set_cursor(cons->frontbuf, col, row);
     579        pointer_draw();
    434580        fibril_mutex_unlock(&cons->mtx);
    435581
     
    511657        console_t *cons = srv_to_console(srv);
    512658        link_t *link = prodcons_consume(&cons->input_pc);
    513         kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
    514 
    515         event->type = CEV_KEY;
    516         event->ev.key = *kevent;
    517 
    518         free(kevent);
     659        cons_event_t *cevent = list_get_instance(link, cons_event_t, link);
     660
     661        *event = *cevent;
     662        free(cevent);
    519663        return EOK;
    520664}
     
    621765        /* Update front buffer from user buffer */
    622766
     767        pointer_undraw();
     768
    623769        for (row = r0; row < r1; row++) {
    624770                for (col = c0; col < c1; col++) {
     
    628774        }
    629775
     776        pointer_draw();
    630777        fibril_mutex_unlock(&cons->mtx);
    631778
Note: See TracChangeset for help on using the changeset viewer.