Ignore:
File:
1 edited

Legend:

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

    re273e9e r68a552f  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * Copyright (c) 2011 Martin Decky
    44 * All rights reserved.
     
    3737#include <stdio.h>
    3838#include <adt/prodcons.h>
    39 #include <io/console.h>
    4039#include <io/input.h>
    4140#include <ipc/vfs.h>
     
    6463typedef struct {
    6564        atomic_flag refcnt;      /**< Connection reference count */
    66         prodcons_t input_pc;  /**< Incoming console events */
     65        prodcons_t input_pc;  /**< Incoming keyboard events */
    6766
    6867        /**
     
    9089} console_t;
    9190
    92 static loc_srv_t *console_srv;
    93 
    9491/** Input server proxy */
    9592static input_t *input;
     
    103100static sysarg_t rows;
    104101
    105 /** Mouse pointer X coordinate */
    106 static int pointer_x;
    107 /** Mouse pointer Y coordinate */
    108 static int pointer_y;
    109 /** Character under mouse cursor */
    110 static charfield_t pointer_bg;
    111 
    112 static int mouse_scale_x = 4;
    113 static int mouse_scale_y = 8;
    114 
    115102/** Array of data for virtual consoles */
    116103static console_t consoles[CONSOLE_COUNT];
     
    123110static errno_t input_ev_active(input_t *);
    124111static errno_t input_ev_deactive(input_t *);
    125 static errno_t input_ev_key(input_t *, unsigned, kbd_event_type_t, keycode_t,
    126     keymod_t, char32_t);
    127 static errno_t input_ev_move(input_t *, unsigned, int, int);
    128 static errno_t input_ev_abs_move(input_t *, unsigned, unsigned, unsigned,
    129     unsigned, unsigned);
    130 static errno_t input_ev_button(input_t *, unsigned, int, int);
    131 static errno_t input_ev_dclick(input_t *, unsigned, int);
     112static errno_t input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, char32_t);
     113static errno_t input_ev_move(input_t *, int, int);
     114static errno_t input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
     115static errno_t input_ev_button(input_t *, int, int);
    132116
    133117static input_ev_ops_t input_ev_ops = {
     
    137121        .move = input_ev_move,
    138122        .abs_move = input_ev_abs_move,
    139         .button = input_ev_button,
    140         .dclick = input_ev_dclick
     123        .button = input_ev_button
    141124};
    142125
     
    156139static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
    157140static void cons_set_cursor_visibility(con_srv_t *, bool);
    158 static errno_t cons_set_caption(con_srv_t *, const char *);
    159141static errno_t cons_get_event(con_srv_t *, cons_event_t *);
    160142static errno_t cons_map(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
     
    178160        .set_rgb_color = cons_set_rgb_color,
    179161        .set_cursor_visibility = cons_set_cursor_visibility,
    180         .set_caption = cons_set_caption,
    181162        .get_event = cons_get_event,
    182163        .map = cons_map,
     
    184165        .update = cons_buf_update
    185166};
    186 
    187 static void pointer_draw(void);
    188 static void pointer_undraw(void);
    189167
    190168static console_t *srv_to_console(con_srv_t *srv)
     
    253231
    254232        fibril_mutex_lock(&switch_mtx);
    255         pointer_undraw();
    256233
    257234        if (cons == active_console) {
     
    262239        active_console = cons;
    263240
    264         pointer_draw();
    265241        fibril_mutex_unlock(&switch_mtx);
    266242
    267243        cons_damage(cons);
    268 }
    269 
    270 /** Draw mouse pointer. */
    271 static void pointer_draw(void)
    272 {
    273         charfield_t *ch;
    274         int col, row;
    275 
    276         /* Downscale coordinates to text resolution */
    277         col = pointer_x / mouse_scale_x;
    278         row = pointer_y / mouse_scale_y;
    279 
    280         /* Make sure they are in range */
    281         if (col < 0 || row < 0 || col >= (int)cols || row >= (int)rows)
    282                 return;
    283 
    284         ch = chargrid_charfield_at(active_console->frontbuf, col, row);
    285 
    286         /*
    287          * Store background attributes for undrawing the pointer.
    288          * This is necessary as styles cannot be inverted with
    289          * round trip (unlike RGB or INDEX)
    290          */
    291         pointer_bg = *ch;
    292 
    293         /* In general the color should be a one's complement of the background */
    294         if (ch->attrs.type == CHAR_ATTR_INDEX) {
    295                 ch->attrs.val.index.bgcolor ^= 0xf;
    296                 ch->attrs.val.index.fgcolor ^= 0xf;
    297         } else if (ch->attrs.type == CHAR_ATTR_RGB) {
    298                 ch->attrs.val.rgb.fgcolor ^= 0xffffff;
    299                 ch->attrs.val.rgb.bgcolor ^= 0xffffff;
    300         } else if (ch->attrs.type == CHAR_ATTR_STYLE) {
    301                 /* Don't have a proper inverse for each style */
    302                 if (ch->attrs.val.style == STYLE_INVERTED)
    303                         ch->attrs.val.style = STYLE_NORMAL;
    304                 else
    305                         ch->attrs.val.style = STYLE_INVERTED;
    306         }
    307 
    308         /* Make sure the cell gets updated */
    309         ch->flags |= CHAR_FLAG_DIRTY;
    310 }
    311 
    312 /** Undraw mouse pointer. */
    313 static void pointer_undraw(void)
    314 {
    315         charfield_t *ch;
    316         int col, row;
    317 
    318         col = pointer_x / mouse_scale_x;
    319         row = pointer_y / mouse_scale_y;
    320         if (col < 0 || row < 0 || col >= (int)cols || row >= (int)rows)
    321                 return;
    322 
    323         ch = chargrid_charfield_at(active_console->frontbuf, col, row);
    324         *ch = pointer_bg;
    325         ch->flags |= CHAR_FLAG_DIRTY;
    326 }
    327 
    328 /** Queue console event.
    329  *
    330  * @param cons Console
    331  * @param ev Console event
    332  */
    333 static void console_queue_cons_event(console_t *cons, cons_event_t *ev)
    334 {
    335         /* Got key press/release event */
    336         cons_qevent_t *event =
    337             (cons_qevent_t *) malloc(sizeof(cons_qevent_t));
    338         if (event == NULL)
    339                 return;
    340 
    341         event->ev = *ev;
    342         link_initialize(&event->link);
    343 
    344         prodcons_produce(&cons->input_pc, &event->link);
    345244}
    346245
     
    362261}
    363262
    364 static errno_t input_ev_key(input_t *input, unsigned kbd_id,
    365     kbd_event_type_t type, keycode_t key, keymod_t mods, char32_t c)
    366 {
    367         cons_event_t event;
    368         bool alt;
    369         bool shift;
    370 
    371         alt = (mods & KM_ALT) != 0 && (mods & (KM_CTRL | KM_SHIFT)) == 0;
    372         shift = (mods & KM_SHIFT) != 0 && (mods & (KM_CTRL | KM_ALT)) == 0;
    373 
    374         /* Switch console on Alt+Fn or Shift+Fn */
     263static errno_t input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
     264    keymod_t mods, char32_t c)
     265{
    375266        if ((key >= KC_F1) && (key <= KC_F1 + CONSOLE_COUNT) &&
    376             (alt || shift)) {
     267            ((mods & KM_CTRL) == 0)) {
    377268                cons_switch(key - KC_F1);
    378269        } else {
    379270                /* Got key press/release event */
    380                 event.type = CEV_KEY;
    381 
    382                 (void)kbd_id;
    383                 event.ev.key.type = type;
    384                 event.ev.key.key = key;
    385                 event.ev.key.mods = mods;
    386                 event.ev.key.c = c;
    387 
    388                 console_queue_cons_event(active_console, &event);
    389         }
    390 
    391         return EOK;
    392 }
    393 
    394 /** Update pointer position.
    395  *
    396  * @param new_x New X coordinate (in pixels)
    397  * @param new_y New Y coordinate (in pixels)
    398  */
    399 static void pointer_update(int new_x, int new_y)
    400 {
    401         bool upd_pointer;
    402 
    403         /* Make sure coordinates are in range */
    404 
    405         if (new_x < 0)
    406                 new_x = 0;
    407         if (new_x >= (int)cols * mouse_scale_x)
    408                 new_x = cols * mouse_scale_x - 1;
    409         if (new_y < 0)
    410                 new_y = 0;
    411         if (new_y >= (int)rows * mouse_scale_y)
    412                 new_y = rows * mouse_scale_y - 1;
    413 
    414         /* Determine if pointer moved to a different character cell */
    415         upd_pointer = (new_x / mouse_scale_x != pointer_x / mouse_scale_x) ||
    416             (new_y / mouse_scale_y != pointer_y / mouse_scale_y);
    417 
    418         if (upd_pointer)
    419                 pointer_undraw();
    420 
    421         /* Store new pointer position */
    422         pointer_x = new_x;
    423         pointer_y = new_y;
    424 
    425         if (upd_pointer) {
    426                 pointer_draw();
    427                 cons_update(active_console);
    428         }
    429 }
    430 
    431 static errno_t input_ev_move(input_t *input, unsigned pos_id, int dx, int dy)
    432 {
    433         (void) pos_id;
    434         pointer_update(pointer_x + dx, pointer_y + dy);
    435         return EOK;
    436 }
    437 
    438 static errno_t input_ev_abs_move(input_t *input, unsigned pos_id, unsigned x,
    439     unsigned y, unsigned max_x, unsigned max_y)
    440 {
    441         (void)pos_id;
    442         pointer_update(mouse_scale_x * cols * x / max_x, mouse_scale_y * rows * y / max_y);
    443         return EOK;
    444 }
    445 
    446 static errno_t input_ev_button(input_t *input, unsigned pos_id, int bnum,
    447     int bpress)
    448 {
    449         cons_event_t event;
    450 
    451         (void)pos_id;
    452 
    453         event.type = CEV_POS;
    454         event.ev.pos.type = bpress ? POS_PRESS : POS_RELEASE;
    455         event.ev.pos.btn_num = bnum;
    456         event.ev.pos.hpos = pointer_x / mouse_scale_x;
    457         event.ev.pos.vpos = pointer_y / mouse_scale_y;
    458 
    459         console_queue_cons_event(active_console, &event);
    460         return EOK;
    461 }
    462 
    463 static errno_t input_ev_dclick(input_t *input, unsigned pos_id, int bnum)
    464 {
    465         cons_event_t event;
    466 
    467         (void)pos_id;
    468 
    469         event.type = CEV_POS;
    470         event.ev.pos.type = POS_DCLICK;
    471         event.ev.pos.btn_num = bnum;
    472         event.ev.pos.hpos = pointer_x / mouse_scale_x;
    473         event.ev.pos.vpos = pointer_y / mouse_scale_y;
    474 
    475         console_queue_cons_event(active_console, &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;
     288}
     289
     290static errno_t input_ev_move(input_t *input, int dx, int dy)
     291{
     292        return EOK;
     293}
     294
     295static errno_t input_ev_abs_move(input_t *input, unsigned x, unsigned y,
     296    unsigned max_x, unsigned max_y)
     297{
     298        return EOK;
     299}
     300
     301static errno_t input_ev_button(input_t *input, int bnum, int bpress)
     302{
    476303        return EOK;
    477304}
     
    483310
    484311        fibril_mutex_lock(&cons->mtx);
    485         pointer_undraw();
    486312
    487313        switch (ch) {
     
    501327        }
    502328
    503         pointer_draw();
    504329        fibril_mutex_unlock(&cons->mtx);
    505330
     
    511336{
    512337        fibril_mutex_lock(&cons->mtx);
    513         pointer_undraw();
    514338        chargrid_set_cursor_visibility(cons->frontbuf, visible);
    515         pointer_draw();
    516339        fibril_mutex_unlock(&cons->mtx);
    517340
     
    556379                if (pos < size) {
    557380                        link_t *link = prodcons_consume(&cons->input_pc);
    558                         cons_qevent_t *qevent = list_get_instance(link,
    559                             cons_qevent_t, link);
    560                         cons_event_t *event = &qevent->ev;
     381                        kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
    561382
    562383                        /* Accept key presses of printable chars only. */
    563                         if (event->type == CEV_KEY && event->ev.key.type == KEY_PRESS &&
    564                             (event->ev.key.c != 0)) {
    565                                 char32_t tmp[2] = { event->ev.key.c, 0 };
     384                        if ((event->type == KEY_PRESS) && (event->c != 0)) {
     385                                char32_t tmp[2] = { event->c, 0 };
    566386                                wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
    567387                                cons->char_remains_len = str_size(cons->char_remains);
    568388                        }
    569389
    570                         free(qevent);
     390                        free(event);
    571391                }
    572392        }
     
    600420
    601421        fibril_mutex_lock(&cons->mtx);
    602         pointer_undraw();
    603422        chargrid_clear(cons->frontbuf);
    604         pointer_draw();
    605423        fibril_mutex_unlock(&cons->mtx);
    606424
     
    613431
    614432        fibril_mutex_lock(&cons->mtx);
    615         pointer_undraw();
    616433        chargrid_set_cursor(cons->frontbuf, col, row);
    617         pointer_draw();
    618434        fibril_mutex_unlock(&cons->mtx);
    619435
     
    691507}
    692508
    693 static errno_t cons_set_caption(con_srv_t *srv, const char *caption)
    694 {
    695         console_t *cons = srv_to_console(srv);
    696 
    697         (void) cons;
    698         (void) caption;
    699         return EOK;
    700 }
    701 
    702509static errno_t cons_get_event(con_srv_t *srv, cons_event_t *event)
    703510{
    704511        console_t *cons = srv_to_console(srv);
    705512        link_t *link = prodcons_consume(&cons->input_pc);
    706         cons_qevent_t *qevent = list_get_instance(link, cons_qevent_t, link);
    707 
    708         *event = qevent->ev;
    709         free(qevent);
     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);
    710519        return EOK;
    711520}
     
    812621        /* Update front buffer from user buffer */
    813622
    814         pointer_undraw();
    815 
    816623        for (row = r0; row < r1; row++) {
    817624                for (col = c0; col < c1; col++) {
     
    821628        }
    822629
    823         pointer_draw();
    824630        fibril_mutex_unlock(&cons->mtx);
    825631
     
    912718        /* Register server */
    913719        async_set_fallback_port_handler(client_connection, NULL);
    914         rc = loc_server_register(NAME, &console_srv);
     720        rc = loc_server_register(NAME);
    915721        if (rc != EOK) {
    916722                printf("%s: Unable to register server (%s)\n", NAME,
     
    962768                        snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
    963769
    964                         if (loc_service_register(console_srv, vc,
    965                             &consoles[i].dsid) != EOK) {
     770                        if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
    966771                                printf("%s: Unable to register device %s\n", NAME, vc);
    967772                                return false;
Note: See TracChangeset for help on using the changeset viewer.