Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/display/seat.c

    r9546146 r554a5f1  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2019 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3838#include <gfx/color.h>
    3939#include <gfx/render.h>
    40 #include <sif.h>
    41 #include <stdio.h>
    4240#include <stdlib.h>
    43 #include <str.h>
    4441#include "client.h"
    4542#include "cursor.h"
    4643#include "display.h"
    47 #include "idevcfg.h"
    4844#include "seat.h"
    4945#include "window.h"
     
    5551 *
    5652 * @param display Parent display
    57  * @param name Seat name
    5853 * @param rseat Place to store pointer to new seat.
    5954 * @return EOK on success, ENOMEM if out of memory
    6055 */
    61 errno_t ds_seat_create(ds_display_t *display, const char *name,
    62     ds_seat_t **rseat)
     56errno_t ds_seat_create(ds_display_t *display, ds_seat_t **rseat)
    6357{
    6458        ds_seat_t *seat;
    65         ds_seat_t *s0;
    66 
    67         s0 = ds_display_first_seat(display);
    68         while (s0 != NULL) {
    69                 if (str_cmp(s0->name, name) == 0)
    70                         return EEXIST;
    71                 s0 = ds_display_next_seat(s0);
    72         }
    7359
    7460        seat = calloc(1, sizeof(ds_seat_t));
     
    7662                return ENOMEM;
    7763
    78         seat->name = str_dup(name);
    79         if (seat->name == NULL) {
    80                 free(seat);
    81                 return ENOMEM;
    82         }
    83 
    84         list_initialize(&seat->idevcfgs);
    85 
    8664        ds_display_add_seat(display, seat);
    8765        seat->pntpos.x = 0;
     
    9068        seat->client_cursor = display->cursor[dcurs_arrow];
    9169        seat->wm_cursor = NULL;
    92         seat->focus = ds_display_first_window(display);
    9370
    9471        *rseat = seat;
     
    10279void ds_seat_destroy(ds_seat_t *seat)
    10380{
    104         ds_idevcfg_t *idevcfg;
    105 
    106         /* Remove all input device configuration entries pointing to this seat */
    107         idevcfg = ds_seat_first_idevcfg(seat);
    108         while (idevcfg != NULL) {
    109                 ds_idevcfg_destroy(idevcfg);
    110                 idevcfg = ds_seat_first_idevcfg(seat);
    111         }
    112 
    113         /* Remove this seat's focus */
    114         if (seat->focus != NULL)
    115                 ds_window_post_unfocus_event(seat->focus);
    116 
    11781        ds_display_remove_seat(seat);
    118 
    119         free(seat->name);
    12082        free(seat);
    12183}
    12284
    123 /** Load seat from SIF node.
    124  *
    125  * @param display Display
    126  * @param snode Seat node from which to load the seat
    127  * @param rseat Place to store pointer to the newly loaded seat
    128  *
    129  * @return EOK on success or an error code
    130  */
    131 errno_t ds_seat_load(ds_display_t *display, sif_node_t *snode,
    132     ds_seat_t **rseat)
    133 {
    134         const char *sid;
    135         const char *name;
    136         char *endptr;
    137         unsigned long id;
    138         errno_t rc;
    139 
    140         sid = sif_node_get_attr(snode, "id");
    141         if (sid == NULL)
    142                 return EIO;
    143 
    144         name = sif_node_get_attr(snode, "name");
    145         if (name == NULL)
    146                 return EIO;
    147 
    148         id = strtoul(sid, &endptr, 10);
    149         if (*endptr != '\0')
    150                 return EIO;
    151 
    152         rc = ds_seat_create(display, name, rseat);
    153         if (rc != EOK)
    154                 return EIO;
    155 
    156         (*rseat)->id = id;
    157         return EOK;
    158 }
    159 
    160 /** Save seat to SIF node.
    161  *
    162  * @param seat Seat
    163  * @param snode Seat node into which the seat should be saved
    164  *
    165  * @return EOK on success or an error code
    166  */
    167 errno_t ds_seat_save(ds_seat_t *seat, sif_node_t *snode)
    168 {
    169         char *sid;
    170         errno_t rc;
    171         int rv;
    172 
    173         rv = asprintf(&sid, "%lu", (unsigned long)seat->id);
    174         if (rv < 0) {
    175                 rc = ENOMEM;
    176                 return rc;
    177         }
    178 
    179         rc = sif_node_set_attr(snode, "id", sid);
    180         if (rc != EOK) {
    181                 free(sid);
    182                 return rc;
    183         }
    184 
    185         free(sid);
    186 
    187         rc = sif_node_set_attr(snode, "name", seat->name);
    188         if (rc != EOK)
    189                 return rc;
    190 
    191         return EOK;
    192 }
    193 
    19485/** Set seat focus to a window.
    19586 *
     
    19990void ds_seat_set_focus(ds_seat_t *seat, ds_window_t *wnd)
    20091{
    201         errno_t rc;
    202 
    20392        if (wnd == seat->focus) {
    20493                /* Focus is not changing */
     
    20695        }
    20796
    208         if (wnd != NULL) {
    209                 rc = ds_window_unminimize(wnd);
    210                 if (rc != EOK)
    211                         return;
    212         }
    213 
    21497        if (seat->focus != NULL)
    21598                ds_window_post_unfocus_event(seat->focus);
     
    221104                ds_window_bring_to_top(wnd);
    222105        }
    223 
    224         /* When focus changes, popup window should be closed */
    225         ds_seat_set_popup(seat, NULL);
    226 }
    227 
    228 /** Set seat popup window.
    229  *
    230  * @param seat Seat
    231  * @param wnd Popup window
    232  */
    233 void ds_seat_set_popup(ds_seat_t *seat, ds_window_t *wnd)
    234 {
    235         if (wnd == seat->popup)
    236                 return;
    237 
    238         if (seat->popup != NULL) {
    239                 /* Window is no longer the popup window, send close request */
    240                 ds_client_post_close_event(seat->popup->client,
    241                     seat->popup);
    242         }
    243 
    244         seat->popup = wnd;
    245 }
    246 
    247 /** Evacuate seat references to window.
    248  *
    249  * If seat's focus is @a wnd, it will be set to NULL.
    250  * If seat's popup window is @a wnd, it will be set to NULL.
    251  *
    252  * @param seat Seat
    253  * @param wnd Window to evacuate references from
    254  */
    255 void ds_seat_evac_wnd_refs(ds_seat_t *seat, ds_window_t *wnd)
    256 {
    257         if (seat->focus == wnd)
    258                 ds_seat_set_focus(seat, NULL);
    259 
    260         if (seat->popup == wnd)
    261                 ds_seat_set_popup(seat, NULL);
    262 }
    263 
    264 /** Unfocus window.
    265  *
    266  * If seat's focus is @a wnd, it will be set to a different window
    267  * that is not minimized, preferably not a system window.
    268  *
    269  * @param seat Seat
    270  * @param wnd Window to remove focus from
    271  */
    272 void ds_seat_unfocus_wnd(ds_seat_t *seat, ds_window_t *wnd)
     106}
     107
     108/** Evacuate focus from window.
     109 *
     110 * If seat's focus is @a wnd, it will be set to a different window.
     111 *
     112 * @param seat Seat
     113 * @param wnd Window to evacuate focus from
     114 */
     115void ds_seat_evac_focus(ds_seat_t *seat, ds_window_t *wnd)
    273116{
    274117        ds_window_t *nwnd;
    275118
    276         if (seat->focus != wnd)
    277                 return;
    278 
    279         /* Find alternate window that is neither system nor minimized */
    280         nwnd = ds_window_find_prev(wnd, ~(wndf_minimized | wndf_system));
    281 
    282         if (nwnd == NULL) {
    283                 /* Find alternate window that is not minimized */
    284                 nwnd = ds_window_find_prev(wnd, ~wndf_minimized);
    285         }
    286 
    287         ds_seat_set_focus(seat, nwnd);
    288 }
    289 
    290 /** Switch focus to another window.
    291  *
    292  * @param seat Seat
    293  * @param wnd Window to evacuate focus from
    294  */
    295 void ds_seat_switch_focus(ds_seat_t *seat)
    296 {
    297         ds_window_t *nwnd;
    298 
    299         if (seat->focus != NULL) {
    300                 /* Find alternate window that is not a system window */
    301                 nwnd = ds_window_find_next(seat->focus, ~wndf_system);
    302         } else {
    303                 /* Currently no focus. Focus topmost window. */
    304                 nwnd = ds_display_first_window(seat->display);
    305         }
    306 
    307         /* Only switch focus if there is another window */
    308         if (nwnd != NULL)
     119        if (seat->focus == wnd) {
     120                nwnd = ds_display_next_window(wnd);
     121                if (nwnd == NULL)
     122                        nwnd = ds_display_first_window(wnd->display);
     123                if (nwnd == wnd)
     124                        nwnd = NULL;
     125
    309126                ds_seat_set_focus(seat, nwnd);
     127        }
    310128}
    311129
     
    325143        if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_TAB) {
    326144                /* On Alt-Tab or Shift-Tab, switch focus to next window */
    327                 ds_seat_switch_focus(seat);
     145                ds_seat_evac_focus(seat, seat->focus);
    328146                return EOK;
    329147        }
    330148
    331         dwindow = seat->popup;
    332         if (dwindow == NULL)
    333                 dwindow = seat->focus;
    334 
     149        dwindow = seat->focus;
    335150        if (dwindow == NULL)
    336151                return EOK;
     
    492307        /* Focus window on button press */
    493308        if (event->type == PTD_PRESS && event->btn_num == 1) {
    494                 if (wnd != NULL && (wnd->flags & wndf_popup) == 0) {
     309                if (wnd != NULL) {
    495310                        ds_seat_set_focus(seat, wnd);
    496311                }
    497312        }
    498313
    499         if (event->type == PTD_PRESS || event->type == PTD_RELEASE ||
    500             event->type == PTD_DCLICK) {
    501                 pevent.pos_id = event->pos_id;
    502                 switch (event->type) {
    503                 case PTD_PRESS:
    504                         pevent.type = POS_PRESS;
    505                         break;
    506                 case PTD_RELEASE:
    507                         pevent.type = POS_RELEASE;
    508                         break;
    509                 case PTD_DCLICK:
    510                         pevent.type = POS_DCLICK;
    511                         break;
    512                 default:
    513                         assert(false);
    514                 }
    515 
     314        if (event->type == PTD_PRESS || event->type == PTD_RELEASE) {
     315                pevent.pos_id = 0;
     316                pevent.type = (event->type == PTD_PRESS) ?
     317                    POS_PRESS : POS_RELEASE;
    516318                pevent.btn_num = event->btn_num;
    517319                pevent.hpos = seat->pntpos.x;
     
    530332                seat->pntpos = npos;
    531333
    532                 pevent.pos_id = event->pos_id;
     334                pevent.pos_id = 0;
    533335                pevent.type = POS_UPDATE;
    534336                pevent.btn_num = 0;
     
    558360                seat->pntpos = npos;
    559361
    560                 pevent.pos_id = event->pos_id;
     362                pevent.pos_id = 0;
    561363                pevent.type = POS_UPDATE;
    562364                pevent.btn_num = 0;
     
    583385errno_t ds_seat_post_pos_event(ds_seat_t *seat, pos_event_t *event)
    584386{
    585         ds_window_t *pwindow;
    586         ds_window_t *cwindow;
     387        ds_window_t *wnd;
    587388        errno_t rc;
    588389
    589         /* Window under pointer */
    590         pwindow = ds_display_window_by_pos(seat->display, &seat->pntpos);
    591 
    592         /* Current window: popup or focused */
    593         cwindow = seat->popup;
    594         if (cwindow == NULL)
    595                 cwindow = seat->focus;
    596 
    597         /*
    598          * Deliver move and release event to current window if different
    599          * from pwindow
    600          */
    601         if (event->type != POS_PRESS && cwindow != NULL &&
    602             cwindow != pwindow) {
    603                 rc = ds_window_post_pos_event(cwindow, event);
    604                 if (rc != EOK)
    605                         return rc;
    606         }
    607 
    608         if (pwindow != NULL) {
     390        wnd = ds_display_window_by_pos(seat->display, &seat->pntpos);
     391
     392        if (seat->focus != wnd) {
     393                rc = ds_window_post_pos_event(seat->focus, event);
     394                if (rc != EOK)
     395                        return rc;
     396
     397                /* Only deliver release events to the focused window */
     398                if (event->type == POS_RELEASE)
     399                        return EOK;
     400        }
     401
     402        if (wnd != NULL) {
    609403                /* Moving over a window */
    610                 ds_seat_set_client_cursor(seat, pwindow->cursor);
    611 
    612                 rc = ds_window_post_pos_event(pwindow, event);
     404                ds_seat_set_client_cursor(seat, wnd->cursor);
     405
     406                rc = ds_window_post_pos_event(wnd, event);
    613407                if (rc != EOK)
    614408                        return rc;
    615409        } else {
    616410                /* Not over a window */
    617                 ds_seat_set_client_cursor(seat,
    618                     seat->display->cursor[dcurs_arrow]);
    619         }
    620 
    621         /* Click outside popup window */
    622         if (event->type == POS_PRESS && pwindow != seat->popup) {
    623                 /* Close popup window */
    624                 ds_seat_set_popup(seat, NULL);
     411                ds_seat_set_client_cursor(seat, seat->display->cursor[dcurs_arrow]);
    625412        }
    626413
     
    641428}
    642429
    643 /** Add input device configuration entry to seat.
    644  *
    645  * @param seat Seat
    646  * @param idevcfg Input device configuration
    647  */
    648 void ds_seat_add_idevcfg(ds_seat_t *seat, ds_idevcfg_t *idevcfg)
    649 {
    650         assert(idevcfg->seat == NULL);
    651         assert(!link_used(&idevcfg->lseatidcfgs));
    652 
    653         idevcfg->seat = seat;
    654         list_append(&idevcfg->lseatidcfgs, &seat->idevcfgs);
    655 }
    656 
    657 /** Remove input device configuration entry from seat.
    658  *
    659  * @param idevcfg Input device configuration entry
    660  */
    661 void ds_seat_remove_idevcfg(ds_idevcfg_t *idevcfg)
    662 {
    663         list_remove(&idevcfg->lseatidcfgs);
    664         idevcfg->seat = NULL;
    665 }
    666 
    667 /** Get first input device configuration entry in seat.
    668  *
    669  * @param disp Display
    670  * @return First input device configuration entry or @c NULL if there is none
    671  */
    672 ds_idevcfg_t *ds_seat_first_idevcfg(ds_seat_t *seat)
    673 {
    674         link_t *link = list_first(&seat->idevcfgs);
    675 
    676         if (link == NULL)
    677                 return NULL;
    678 
    679         return list_get_instance(link, ds_idevcfg_t, lseatidcfgs);
    680 }
    681 
    682 /** Get next input device configuration entry in seat.
    683  *
    684  * @param idevcfg Current input device configuration entry
    685  * @return Next input device configuration entry or @c NULL if there is none
    686  */
    687 ds_idevcfg_t *ds_seat_next_idevcfg(ds_idevcfg_t *idevcfg)
    688 {
    689         link_t *link = list_next(&idevcfg->lseatidcfgs, &idevcfg->seat->idevcfgs);
    690 
    691         if (link == NULL)
    692                 return NULL;
    693 
    694         return list_get_instance(link, ds_idevcfg_t, lseatidcfgs);
    695 }
    696 
    697430/** @}
    698431 */
Note: See TracChangeset for help on using the changeset viewer.