Ignore:
File:
1 edited

Legend:

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

    r68a552f r49aaa0e  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 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>
    3940#include <io/input.h>
    4041#include <ipc/vfs.h>
     
    6364typedef struct {
    6465        atomic_flag refcnt;      /**< Connection reference count */
    65         prodcons_t input_pc;  /**< Incoming keyboard events */
     66        prodcons_t input_pc;  /**< Incoming console events */
    6667
    6768        /**
     
    8990} console_t;
    9091
     92static loc_srv_t *console_srv;
     93
    9194/** Input server proxy */
    9295static input_t *input;
     
    100103static sysarg_t rows;
    101104
     105/** Mouse pointer X coordinate */
     106static int pointer_x;
     107/** Mouse pointer Y coordinate */
     108static int pointer_y;
     109/** Character under mouse cursor */
     110static charfield_t pointer_bg;
     111
     112static int mouse_scale_x = 4;
     113static int mouse_scale_y = 8;
     114
    102115/** Array of data for virtual consoles */
    103116static console_t consoles[CONSOLE_COUNT];
     
    110123static errno_t input_ev_active(input_t *);
    111124static errno_t input_ev_deactive(input_t *);
    112 static errno_t input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, char32_t);
    113 static errno_t input_ev_move(input_t *, int, int);
    114 static errno_t input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
    115 static errno_t input_ev_button(input_t *, int, int);
     125static errno_t input_ev_key(input_t *, unsigned, kbd_event_type_t, keycode_t,
     126    keymod_t, char32_t);
     127static errno_t input_ev_move(input_t *, unsigned, int, int);
     128static errno_t input_ev_abs_move(input_t *, unsigned, unsigned, unsigned,
     129    unsigned, unsigned);
     130static errno_t input_ev_button(input_t *, unsigned, int, int);
     131static errno_t input_ev_dclick(input_t *, unsigned, int);
    116132
    117133static input_ev_ops_t input_ev_ops = {
     
    121137        .move = input_ev_move,
    122138        .abs_move = input_ev_abs_move,
    123         .button = input_ev_button
     139        .button = input_ev_button,
     140        .dclick = input_ev_dclick
    124141};
    125142
     
    139156static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
    140157static void cons_set_cursor_visibility(con_srv_t *, bool);
     158static errno_t cons_set_caption(con_srv_t *, const char *);
    141159static errno_t cons_get_event(con_srv_t *, cons_event_t *);
    142160static errno_t cons_map(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
     
    160178        .set_rgb_color = cons_set_rgb_color,
    161179        .set_cursor_visibility = cons_set_cursor_visibility,
     180        .set_caption = cons_set_caption,
    162181        .get_event = cons_get_event,
    163182        .map = cons_map,
     
    165184        .update = cons_buf_update
    166185};
     186
     187static void pointer_draw(void);
     188static void pointer_undraw(void);
    167189
    168190static console_t *srv_to_console(con_srv_t *srv)
     
    231253
    232254        fibril_mutex_lock(&switch_mtx);
     255        pointer_undraw();
    233256
    234257        if (cons == active_console) {
     
    239262        active_console = cons;
    240263
     264        pointer_draw();
    241265        fibril_mutex_unlock(&switch_mtx);
    242266
    243267        cons_damage(cons);
     268}
     269
     270/** Draw mouse pointer. */
     271static 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. */
     313static 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 */
     333static void console_queue_cons_event(console_t *cons, cons_event_t *ev)
     334{
     335        /* Got key press/release event */
     336        cons_event_t *event =
     337            (cons_event_t *) malloc(sizeof(cons_event_t));
     338        if (event == NULL)
     339                return;
     340
     341        *event = *ev;
     342        link_initialize(&event->link);
     343
     344        prodcons_produce(&cons->input_pc, &event->link);
    244345}
    245346
     
    261362}
    262363
    263 static errno_t input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
    264     keymod_t mods, char32_t c)
    265 {
     364static 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 */
    266375        if ((key >= KC_F1) && (key <= KC_F1 + CONSOLE_COUNT) &&
    267             ((mods & KM_CTRL) == 0)) {
     376            (alt || shift)) {
    268377                cons_switch(key - KC_F1);
    269378        } else {
    270379                /* 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;
    288 }
    289 
    290 static errno_t input_ev_move(input_t *input, int dx, int dy)
    291 {
    292         return EOK;
    293 }
    294 
    295 static 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 
    301 static errno_t input_ev_button(input_t *input, int bnum, int bpress)
    302 {
     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 */
     399static 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
     431static 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
     438static 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
     446static 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
     463static 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);
    303476        return EOK;
    304477}
     
    310483
    311484        fibril_mutex_lock(&cons->mtx);
     485        pointer_undraw();
    312486
    313487        switch (ch) {
     
    327501        }
    328502
     503        pointer_draw();
    329504        fibril_mutex_unlock(&cons->mtx);
    330505
     
    336511{
    337512        fibril_mutex_lock(&cons->mtx);
     513        pointer_undraw();
    338514        chargrid_set_cursor_visibility(cons->frontbuf, visible);
     515        pointer_draw();
    339516        fibril_mutex_unlock(&cons->mtx);
    340517
     
    379556                if (pos < size) {
    380557                        link_t *link = prodcons_consume(&cons->input_pc);
    381                         kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
     558                        cons_event_t *event = list_get_instance(link,
     559                            cons_event_t, link);
    382560
    383561                        /* Accept key presses of printable chars only. */
    384                         if ((event->type == KEY_PRESS) && (event->c != 0)) {
    385                                 char32_t tmp[2] = { event->c, 0 };
     562                        if (event->type == CEV_KEY && event->ev.key.type == KEY_PRESS &&
     563                            (event->ev.key.c != 0)) {
     564                                char32_t tmp[2] = { event->ev.key.c, 0 };
    386565                                wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
    387566                                cons->char_remains_len = str_size(cons->char_remains);
     
    420599
    421600        fibril_mutex_lock(&cons->mtx);
     601        pointer_undraw();
    422602        chargrid_clear(cons->frontbuf);
     603        pointer_draw();
    423604        fibril_mutex_unlock(&cons->mtx);
    424605
     
    431612
    432613        fibril_mutex_lock(&cons->mtx);
     614        pointer_undraw();
    433615        chargrid_set_cursor(cons->frontbuf, col, row);
     616        pointer_draw();
    434617        fibril_mutex_unlock(&cons->mtx);
    435618
     
    507690}
    508691
     692static errno_t cons_set_caption(con_srv_t *srv, const char *caption)
     693{
     694        console_t *cons = srv_to_console(srv);
     695
     696        (void) cons;
     697        (void) caption;
     698        return EOK;
     699}
     700
    509701static errno_t cons_get_event(con_srv_t *srv, cons_event_t *event)
    510702{
    511703        console_t *cons = srv_to_console(srv);
    512704        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);
     705        cons_event_t *cevent = list_get_instance(link, cons_event_t, link);
     706
     707        *event = *cevent;
     708        free(cevent);
    519709        return EOK;
    520710}
     
    621811        /* Update front buffer from user buffer */
    622812
     813        pointer_undraw();
     814
    623815        for (row = r0; row < r1; row++) {
    624816                for (col = c0; col < c1; col++) {
     
    628820        }
    629821
     822        pointer_draw();
    630823        fibril_mutex_unlock(&cons->mtx);
    631824
     
    718911        /* Register server */
    719912        async_set_fallback_port_handler(client_connection, NULL);
    720         rc = loc_server_register(NAME);
     913        rc = loc_server_register(NAME, &console_srv);
    721914        if (rc != EOK) {
    722915                printf("%s: Unable to register server (%s)\n", NAME,
     
    768961                        snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
    769962
    770                         if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
     963                        if (loc_service_register(console_srv, vc,
     964                            &consoles[i].dsid) != EOK) {
    771965                                printf("%s: Unable to register device %s\n", NAME, vc);
    772966                                return false;
Note: See TracChangeset for help on using the changeset viewer.