Ignore:
File:
1 edited

Legend:

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

    rd7f82635 r1543d4c  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939#include <gfx/render.h>
    4040#include <stdlib.h>
     41#include <str.h>
    4142#include "client.h"
    4243#include "cursor.h"
    4344#include "display.h"
     45#include "idevcfg.h"
    4446#include "seat.h"
    4547#include "window.h"
     
    5153 *
    5254 * @param display Parent display
     55 * @param name Seat name
    5356 * @param rseat Place to store pointer to new seat.
    5457 * @return EOK on success, ENOMEM if out of memory
    5558 */
    56 errno_t ds_seat_create(ds_display_t *display, ds_seat_t **rseat)
     59errno_t ds_seat_create(ds_display_t *display, const char *name,
     60    ds_seat_t **rseat)
    5761{
    5862        ds_seat_t *seat;
     63        ds_seat_t *s0;
     64
     65        s0 = ds_display_first_seat(display);
     66        while (s0 != NULL) {
     67                if (str_cmp(s0->name, name) == 0)
     68                        return EEXIST;
     69                s0 = ds_display_next_seat(s0);
     70        }
    5971
    6072        seat = calloc(1, sizeof(ds_seat_t));
     
    6274                return ENOMEM;
    6375
     76        seat->name = str_dup(name);
     77        if (seat->name == NULL) {
     78                free(seat);
     79                return ENOMEM;
     80        }
     81
     82        list_initialize(&seat->idevcfgs);
     83
    6484        ds_display_add_seat(display, seat);
    6585        seat->pntpos.x = 0;
     
    6888        seat->client_cursor = display->cursor[dcurs_arrow];
    6989        seat->wm_cursor = NULL;
     90        seat->focus = ds_display_first_window(display);
    7091
    7192        *rseat = seat;
     
    79100void ds_seat_destroy(ds_seat_t *seat)
    80101{
     102        ds_idevcfg_t *idevcfg;
     103
     104        /* Remove all input device configuration entries pointing to this seat */
     105        idevcfg = ds_seat_first_idevcfg(seat);
     106        while (idevcfg != NULL) {
     107                ds_idevcfg_destroy(idevcfg);
     108                idevcfg = ds_seat_first_idevcfg(seat);
     109        }
     110
     111        /* Remove this seat's focus */
     112        if (seat->focus != NULL)
     113                ds_window_post_unfocus_event(seat->focus);
     114
    81115        ds_display_remove_seat(seat);
     116
     117        free(seat->name);
    82118        free(seat);
    83119}
     
    90126void ds_seat_set_focus(ds_seat_t *seat, ds_window_t *wnd)
    91127{
     128        errno_t rc;
     129
    92130        if (wnd == seat->focus) {
    93131                /* Focus is not changing */
    94132                return;
     133        }
     134
     135        if (wnd != NULL) {
     136                rc = ds_window_unminimize(wnd);
     137                if (rc != EOK)
     138                        return;
    95139        }
    96140
     
    130174/** Evacuate seat references to window.
    131175 *
    132  * If seat's focus is @a wnd, it will be set to a different window.
     176 * If seat's focus is @a wnd, it will be set to NULL.
    133177 * If seat's popup window is @a wnd, it will be set to NULL.
    134178 *
    135179 * @param seat Seat
    136  * @param wnd Window to evacuate focus from
     180 * @param wnd Window to evacuate references from
    137181 */
    138182void ds_seat_evac_wnd_refs(ds_seat_t *seat, ds_window_t *wnd)
    139183{
    140         ds_window_t *nwnd;
    141 
    142         if (seat->focus == wnd) {
    143                 nwnd = ds_display_prev_window(wnd);
    144                 if (nwnd == NULL)
    145                         nwnd = ds_display_last_window(wnd->display);
    146                 if (nwnd == wnd)
    147                         nwnd = NULL;
    148 
    149                 ds_seat_set_focus(seat, nwnd);
    150         }
     184        if (seat->focus == wnd)
     185                ds_seat_set_focus(seat, NULL);
    151186
    152187        if (seat->popup == wnd)
     
    154189}
    155190
     191/** Unfocus window.
     192 *
     193 * If seat's focus is @a wnd, it will be set to a different window
     194 * that is not minimized, preferably not a system window.
     195 *
     196 * @param seat Seat
     197 * @param wnd Window to remove focus from
     198 */
     199void ds_seat_unfocus_wnd(ds_seat_t *seat, ds_window_t *wnd)
     200{
     201        ds_window_t *nwnd;
     202
     203        if (seat->focus != wnd)
     204                return;
     205
     206        /* Find alternate window that is neither system nor minimized */
     207        nwnd = ds_window_find_prev(wnd, ~(wndf_minimized | wndf_system));
     208
     209        if (nwnd == NULL) {
     210                /* Find alternate window that is not minimized */
     211                nwnd = ds_window_find_prev(wnd, ~wndf_minimized);
     212        }
     213
     214        ds_seat_set_focus(seat, nwnd);
     215}
     216
    156217/** Switch focus to another window.
    157218 *
     
    163224        ds_window_t *nwnd;
    164225
    165         if (seat->focus != NULL)
    166                 nwnd = ds_display_prev_window(seat->focus);
    167         else
    168                 nwnd = NULL;
    169 
    170         if (nwnd == NULL)
    171                 nwnd = ds_display_last_window(seat->display);
    172 
     226        if (seat->focus != NULL) {
     227                /* Find alternate window that is not a system window */
     228                nwnd = ds_window_find_next(seat->focus, ~wndf_system);
     229        } else {
     230                /* Currently no focus. Focus topmost window. */
     231                nwnd = ds_display_first_window(seat->display);
     232        }
     233
     234        /* Only switch focus if there is another window */
    173235        if (nwnd != NULL)
    174236                ds_seat_set_focus(seat, nwnd);
     
    362424        }
    363425
    364         if (event->type == PTD_PRESS || event->type == PTD_RELEASE) {
    365                 pevent.pos_id = 0;
    366                 pevent.type = (event->type == PTD_PRESS) ?
    367                     POS_PRESS : POS_RELEASE;
     426        if (event->type == PTD_PRESS || event->type == PTD_RELEASE ||
     427            event->type == PTD_DCLICK) {
     428                pevent.pos_id = event->pos_id;
     429                switch (event->type) {
     430                case PTD_PRESS:
     431                        pevent.type = POS_PRESS;
     432                        break;
     433                case PTD_RELEASE:
     434                        pevent.type = POS_RELEASE;
     435                        break;
     436                case PTD_DCLICK:
     437                        pevent.type = POS_DCLICK;
     438                        break;
     439                default:
     440                        assert(false);
     441                }
     442
    368443                pevent.btn_num = event->btn_num;
    369444                pevent.hpos = seat->pntpos.x;
     
    382457                seat->pntpos = npos;
    383458
    384                 pevent.pos_id = 0;
     459                pevent.pos_id = event->pos_id;
    385460                pevent.type = POS_UPDATE;
    386461                pevent.btn_num = 0;
     
    410485                seat->pntpos = npos;
    411486
    412                 pevent.pos_id = 0;
     487                pevent.pos_id = event->pos_id;
    413488                pevent.type = POS_UPDATE;
    414489                pevent.btn_num = 0;
     
    440515        wnd = ds_display_window_by_pos(seat->display, &seat->pntpos);
    441516
    442         /* Click outside popup window */
    443         if (event->type == POS_PRESS && wnd != seat->popup) {
    444                 /* Close popup window */
    445                 ds_seat_set_popup(seat, NULL);
    446         }
    447 
    448517        /* Deliver event to popup window. */
    449         if (seat->popup != NULL) {
     518        if (seat->popup != NULL && event->type != POS_PRESS) {
    450519                rc = ds_window_post_pos_event(seat->popup, event);
    451520                if (rc != EOK)
     
    471540                 * to the same window above.
    472541                 */
    473                 if (wnd != seat->popup) {
     542                if (wnd != seat->popup || event->type == POS_PRESS) {
    474543                        rc = ds_window_post_pos_event(wnd, event);
    475544                        if (rc != EOK)
     
    481550        }
    482551
     552        /* Click outside popup window */
     553        if (event->type == POS_PRESS && wnd != seat->popup) {
     554                /* Close popup window */
     555                ds_seat_set_popup(seat, NULL);
     556        }
     557
    483558        return EOK;
    484559}
     
    497572}
    498573
     574/** Add input device configuration entry to seat.
     575 *
     576 * @param seat Seat
     577 * @param idevcfg Input device configuration
     578 */
     579void ds_seat_add_idevcfg(ds_seat_t *seat, ds_idevcfg_t *idevcfg)
     580{
     581        assert(idevcfg->seat == NULL);
     582        assert(!link_used(&idevcfg->lseatidcfgs));
     583
     584        idevcfg->seat = seat;
     585        list_append(&idevcfg->lseatidcfgs, &seat->idevcfgs);
     586}
     587
     588/** Remove input device configuration entry from seat.
     589 *
     590 * @param idevcfg Input device configuration entry
     591 */
     592void ds_seat_remove_idevcfg(ds_idevcfg_t *idevcfg)
     593{
     594        list_remove(&idevcfg->lseatidcfgs);
     595        idevcfg->seat = NULL;
     596}
     597
     598/** Get first input device configuration entry in seat.
     599 *
     600 * @param disp Display
     601 * @return First input device configuration entry or @c NULL if there is none
     602 */
     603ds_idevcfg_t *ds_seat_first_idevcfg(ds_seat_t *seat)
     604{
     605        link_t *link = list_first(&seat->idevcfgs);
     606
     607        if (link == NULL)
     608                return NULL;
     609
     610        return list_get_instance(link, ds_idevcfg_t, lseatidcfgs);
     611}
     612
     613/** Get next input device configuration entry in seat.
     614 *
     615 * @param idevcfg Current input device configuration entry
     616 * @return Next input device configuration entry or @c NULL if there is none
     617 */
     618ds_idevcfg_t *ds_seat_next_idevcfg(ds_idevcfg_t *idevcfg)
     619{
     620        link_t *link = list_next(&idevcfg->lseatidcfgs, &idevcfg->seat->idevcfgs);
     621
     622        if (link == NULL)
     623                return NULL;
     624
     625        return list_get_instance(link, ds_idevcfg_t, lseatidcfgs);
     626}
     627
    499628/** @}
    500629 */
Note: See TracChangeset for help on using the changeset viewer.