Ignore:
File:
1 edited

Legend:

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

    r6fbd1f9 r2ab8ab3  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2019 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4141#include <memgfx/memgc.h>
    4242#include <stdlib.h>
    43 #include <str.h>
    4443#include "client.h"
    4544#include "clonegc.h"
    4645#include "cursimg.h"
    4746#include "cursor.h"
    48 #include "display.h"
    49 #include "idevcfg.h"
    5047#include "seat.h"
    5148#include "window.h"
    52 #include "wmclient.h"
     49#include "display.h"
    5350
    5451static gfx_context_t *ds_display_get_unbuf_gc(ds_display_t *);
    5552static void ds_display_invalidate_cb(void *, gfx_rect_t *);
    5653static void ds_display_update_cb(void *);
    57 
    58 static mem_gc_cb_t ds_display_mem_gc_cb = {
    59         .invalidate = ds_display_invalidate_cb,
    60         .update = ds_display_update_cb
    61 };
    6254
    6355/** Create display.
     
    9991        fibril_mutex_initialize(&disp->lock);
    10092        list_initialize(&disp->clients);
    101         list_initialize(&disp->wmclients);
    102         list_initialize(&disp->cfgclients);
    10393        disp->next_wnd_id = 1;
    104         disp->next_seat_id = 1;
    10594        list_initialize(&disp->ddevs);
    106         list_initialize(&disp->idevcfgs);
    107         list_initialize(&disp->ievents);
    108         fibril_condvar_initialize(&disp->ievent_cv);
    10995        list_initialize(&disp->seats);
    11096        list_initialize(&disp->windows);
     
    123109void ds_display_destroy(ds_display_t *disp)
    124110{
    125         int i;
    126 
    127111        assert(list_empty(&disp->clients));
    128         assert(list_empty(&disp->wmclients));
    129         assert(list_empty(&disp->cfgclients));
    130112        assert(list_empty(&disp->seats));
    131         assert(list_empty(&disp->ddevs));
    132         assert(list_empty(&disp->idevcfgs));
    133         assert(list_empty(&disp->ievents));
    134         assert(list_empty(&disp->seats));
    135         assert(list_empty(&disp->windows));
    136 
    137         /* Destroy cursors */
    138         for (i = 0; i < dcurs_limit; i++) {
    139                 ds_cursor_destroy(disp->cursor[i]);
    140                 disp->cursor[i] = NULL;
    141         }
    142 
     113        /* XXX destroy cursors */
    143114        gfx_color_delete(disp->bg_color);
    144115        free(disp);
    145116}
    146117
    147 /** Load display configuration from SIF file.
    148  *
    149  * @param display Display
    150  * @param cfgpath Configuration file path
    151  *
    152  * @return EOK on success or an error code
    153  */
    154 errno_t ds_display_load_cfg(ds_display_t *display, const char *cfgpath)
    155 {
    156         sif_doc_t *doc = NULL;
    157         sif_node_t *rnode;
    158         sif_node_t *ndisplay;
    159         sif_node_t *nseats;
    160         sif_node_t *nseat;
    161         ds_seat_t *seat;
    162         sif_node_t *nidevcfgs;
    163         sif_node_t *nidevcfg;
    164         const char *ntype;
    165         ds_idevcfg_t *idevcfg;
    166         errno_t rc;
    167 
    168         rc = sif_load(cfgpath, &doc);
    169         if (rc != EOK)
    170                 goto error;
    171 
    172         rnode = sif_get_root(doc);
    173         ndisplay = sif_node_first_child(rnode);
    174         ntype = sif_node_get_type(ndisplay);
    175         if (str_cmp(ntype, "display") != 0) {
    176                 rc = EIO;
    177                 goto error;
    178         }
    179 
    180         nseats = sif_node_first_child(ndisplay);
    181         ntype = sif_node_get_type(nseats);
    182         if (str_cmp(ntype, "seats") != 0) {
    183                 rc = EIO;
    184                 goto error;
    185         }
    186 
    187         /* Load individual seats */
    188         nseat = sif_node_first_child(nseats);
    189         while (nseat != NULL) {
    190                 ntype = sif_node_get_type(nseat);
    191                 if (str_cmp(ntype, "seat") != 0) {
    192                         rc = EIO;
    193                         goto error;
    194                 }
    195 
    196                 rc = ds_seat_load(display, nseat, &seat);
    197                 if (rc != EOK)
    198                         goto error;
    199 
    200                 (void)seat;
    201                 nseat = sif_node_next_child(nseat);
    202         }
    203 
    204         nidevcfgs = sif_node_next_child(nseats);
    205         ntype = sif_node_get_type(nidevcfgs);
    206         if (str_cmp(ntype, "idevcfgs") != 0) {
    207                 rc = EIO;
    208                 goto error;
    209         }
    210 
    211         /* Load individual input device configuration entries */
    212         nidevcfg = sif_node_first_child(nidevcfgs);
    213         while (nidevcfg != NULL) {
    214                 ntype = sif_node_get_type(nidevcfg);
    215                 if (str_cmp(ntype, "idevcfg") != 0) {
    216                         rc = EIO;
    217                         goto error;
    218                 }
    219 
    220                 /*
    221                  * Load device configuration entry. If the device
    222                  * is not currently connected (ENOENT), skip it.
    223                  */
    224                 rc = ds_idevcfg_load(display, nidevcfg, &idevcfg);
    225                 if (rc != EOK && rc != ENOENT)
    226                         goto error;
    227 
    228                 (void)idevcfg;
    229                 nidevcfg = sif_node_next_child(nidevcfg);
    230         }
    231 
    232         sif_delete(doc);
    233         return EOK;
    234 error:
    235         if (doc != NULL)
    236                 sif_delete(doc);
    237 
    238         seat = ds_display_first_seat(display);
    239         while (seat != NULL) {
    240                 ds_seat_destroy(seat);
    241                 seat = ds_display_first_seat(display);
    242         }
    243         return rc;
    244 }
    245 
    246 /** Save display configuration to SIF file.
    247  *
    248  * @param display Display
    249  * @param cfgpath Configuration file path
    250  *
    251  * @return EOK on success or an error code
    252  */
    253 errno_t ds_display_save_cfg(ds_display_t *display, const char *cfgpath)
    254 {
    255         sif_doc_t *doc = NULL;
    256         sif_node_t *rnode;
    257         sif_node_t *ndisplay;
    258         sif_node_t *nseats;
    259         sif_node_t *nseat;
    260         ds_seat_t *seat;
    261         sif_node_t *nidevcfgs;
    262         sif_node_t *nidevcfg;
    263         ds_idevcfg_t *idevcfg;
    264         errno_t rc;
    265 
    266         rc = sif_new(&doc);
    267         if (rc != EOK)
    268                 goto error;
    269 
    270         rnode = sif_get_root(doc);
    271         rc = sif_node_append_child(rnode, "display", &ndisplay);
    272         if (rc != EOK)
    273                 goto error;
    274 
    275         rc = sif_node_append_child(ndisplay, "seats", &nseats);
    276         if (rc != EOK)
    277                 goto error;
    278 
    279         /* Save individual seats */
    280         seat = ds_display_first_seat(display);
    281         while (seat != NULL) {
    282                 rc = sif_node_append_child(nseats, "seat", &nseat);
    283                 if (rc != EOK)
    284                         goto error;
    285 
    286                 rc = ds_seat_save(seat, nseat);
    287                 if (rc != EOK)
    288                         goto error;
    289 
    290                 seat = ds_display_next_seat(seat);
    291         }
    292 
    293         rc = sif_node_append_child(ndisplay, "idevcfgs", &nidevcfgs);
    294         if (rc != EOK)
    295                 goto error;
    296 
    297         /* Save individual input device configuration entries */
    298         idevcfg = ds_display_first_idevcfg(display);
    299         while (idevcfg != NULL) {
    300                 rc = sif_node_append_child(nidevcfgs, "idevcfg", &nidevcfg);
    301                 if (rc != EOK)
    302                         goto error;
    303 
    304                 rc = ds_idevcfg_save(idevcfg, nidevcfg);
    305                 if (rc != EOK)
    306                         goto error;
    307 
    308                 idevcfg = ds_display_next_idevcfg(idevcfg);
    309         }
    310 
    311         rc = sif_save(doc, cfgpath);
    312         if (rc != EOK)
    313                 goto error;
    314 
    315         sif_delete(doc);
    316         return EOK;
    317 error:
    318         if (doc != NULL)
    319                 sif_delete(doc);
    320         return rc;
    321 }
    322 
    323118/** Lock display.
    324119 *
     
    403198
    404199        return list_get_instance(link, ds_client_t, lclients);
    405 }
    406 
    407 /** Add WM client to display.
    408  *
    409  * @param disp Display
    410  * @param wmclient WM client
    411  */
    412 void ds_display_add_wmclient(ds_display_t *disp, ds_wmclient_t *wmclient)
    413 {
    414         assert(wmclient->display == NULL);
    415         assert(!link_used(&wmclient->lwmclients));
    416 
    417         wmclient->display = disp;
    418         list_append(&wmclient->lwmclients, &disp->wmclients);
    419 }
    420 
    421 /** Remove WM client from display.
    422  *
    423  * @param wmclient WM client
    424  */
    425 void ds_display_remove_wmclient(ds_wmclient_t *wmclient)
    426 {
    427         list_remove(&wmclient->lwmclients);
    428         wmclient->display = NULL;
    429 }
    430 
    431 /** Add CFG client to display.
    432  *
    433  * @param disp Display
    434  * @param cfgclient CFG client
    435  */
    436 void ds_display_add_cfgclient(ds_display_t *disp, ds_cfgclient_t *cfgclient)
    437 {
    438         assert(cfgclient->display == NULL);
    439         assert(!link_used(&cfgclient->lcfgclients));
    440 
    441         cfgclient->display = disp;
    442         list_append(&cfgclient->lcfgclients, &disp->cfgclients);
    443 }
    444 
    445 /** Remove CFG client from display.
    446  *
    447  * @param cfgclient CFG client
    448  */
    449 void ds_display_remove_cfgclient(ds_cfgclient_t *cfgclient)
    450 {
    451         list_remove(&cfgclient->lcfgclients);
    452         cfgclient->display = NULL;
    453 }
    454 
    455 /** Get first WM client in display.
    456  *
    457  * @param disp Display
    458  * @return First WM client or @c NULL if there is none
    459  */
    460 ds_wmclient_t *ds_display_first_wmclient(ds_display_t *disp)
    461 {
    462         link_t *link = list_first(&disp->wmclients);
    463 
    464         if (link == NULL)
    465                 return NULL;
    466 
    467         return list_get_instance(link, ds_wmclient_t, lwmclients);
    468 }
    469 
    470 /** Get next WM client in display.
    471  *
    472  * @param wmclient Current WM client
    473  * @return Next WM client or @c NULL if there is none
    474  */
    475 ds_wmclient_t *ds_display_next_wmclient(ds_wmclient_t *wmclient)
    476 {
    477         link_t *link = list_next(&wmclient->lwmclients,
    478             &wmclient->display->wmclients);
    479 
    480         if (link == NULL)
    481                 return NULL;
    482 
    483         return list_get_instance(link, ds_wmclient_t, lwmclients);
    484200}
    485201
     
    525241                gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
    526242
    527                 if (gfx_pix_inside_rect(pos, &drect) &&
    528                     ds_window_is_visible(wnd))
     243                if (gfx_pix_inside_rect(pos, &drect))
    529244                        return wnd;
    530245
     
    535250}
    536251
    537 /** Add window to window list.
    538  *
    539  * Topmost windows are enlisted before any other window. Non-topmost
    540  * windows are enlisted before any other non-topmost window.
     252/** Add window to display.
    541253 *
    542254 * @param display Display
    543255 * @param wnd Window
    544256 */
    545 void ds_display_enlist_window(ds_display_t *display, ds_window_t *wnd)
    546 {
    547         ds_window_t *w;
    548 
    549         assert(wnd->display == display);
    550         assert(!link_used(&wnd->ldwindows));
    551 
    552         if ((wnd->flags & wndf_topmost) == 0) {
    553                 /* Find the first non-topmost window */
    554                 w = ds_display_first_window(display);
    555                 while (w != NULL && (w->flags & wndf_topmost) != 0)
    556                         w = ds_display_next_window(w);
    557 
    558                 if (w != NULL)
    559                         list_insert_before(&wnd->ldwindows, &w->ldwindows);
    560                 else
    561                         list_append(&wnd->ldwindows, &display->windows);
    562         } else {
    563                 /* Insert at the beginning */
    564                 list_prepend(&wnd->ldwindows, &display->windows);
    565         }
    566 
    567 }
    568 
    569 /** Add window to display.
    570  *
    571  * @param display Display
    572  * @param wnd Window
    573  */
    574257void ds_display_add_window(ds_display_t *display, ds_window_t *wnd)
    575258{
    576         ds_wmclient_t *wmclient;
    577 
    578259        assert(wnd->display == NULL);
    579260        assert(!link_used(&wnd->ldwindows));
    580261
    581262        wnd->display = display;
    582         ds_display_enlist_window(display, wnd);
    583 
    584         /* Notify window managers about the new window */
    585         wmclient = ds_display_first_wmclient(display);
    586         while (wmclient != NULL) {
    587                 ds_wmclient_post_wnd_added_event(wmclient, wnd->id);
    588                 wmclient = ds_display_next_wmclient(wmclient);
    589         }
     263        list_prepend(&wnd->ldwindows, &display->windows);
    590264}
    591265
     
    596270void ds_display_remove_window(ds_window_t *wnd)
    597271{
    598         ds_wmclient_t *wmclient;
    599         ds_display_t *display;
    600 
    601         display = wnd->display;
    602 
    603272        list_remove(&wnd->ldwindows);
    604273        wnd->display = NULL;
    605 
    606         /* Notify window managers about the removed window */
    607         wmclient = ds_display_first_wmclient(display);
    608         while (wmclient != NULL) {
    609                 ds_wmclient_post_wnd_removed_event(wmclient, wnd->id);
    610                 wmclient = ds_display_next_wmclient(wmclient);
    611         }
    612 }
    613 
    614 /** Move window to top.
    615  *
    616  * @param display Display
    617  * @param wnd Window
    618  */
    619 void ds_display_window_to_top(ds_window_t *wnd)
    620 {
    621         assert(wnd->display != NULL);
    622         assert(link_used(&wnd->ldwindows));
    623 
    624         list_remove(&wnd->ldwindows);
    625         ds_display_enlist_window(wnd->display, wnd);
    626274}
    627275
     
    699347        ds_seat_t *seat;
    700348
    701         /* Determine which seat the event belongs to */
    702         seat = ds_display_seat_by_idev(display, event->kbd_id);
     349        // TODO Determine which seat the event belongs to
     350        seat = ds_display_first_seat(display);
    703351        if (seat == NULL)
    704352                return EOK;
     
    716364        ds_seat_t *seat;
    717365
    718         /* Determine which seat the event belongs to */
    719         seat = ds_display_seat_by_idev(display, event->pos_id);
     366        // TODO Determine which seat the event belongs to
     367        seat = ds_display_first_seat(display);
    720368        if (seat == NULL)
    721369                return EOK;
     
    735383
    736384        seat->display = disp;
    737         seat->id = disp->next_seat_id++;
    738385        list_append(&seat->lseats, &disp->seats);
    739386}
     
    777424
    778425        return list_get_instance(link, ds_seat_t, lseats);
    779 }
    780 
    781 /** Get default seat in display.
    782  *
    783  * @param disp Display
    784  * @return First seat or @c NULL if there is none
    785  */
    786 ds_seat_t *ds_display_default_seat(ds_display_t *disp)
    787 {
    788         /* XXX Probably not the best solution */
    789         return ds_display_first_seat(disp);
    790 }
    791 
    792 /** Find seat by ID.
    793  *
    794  * @param display Display
    795  * @param id Seat ID
    796  */
    797 ds_seat_t *ds_display_find_seat(ds_display_t *display, ds_seat_id_t id)
    798 {
    799         ds_seat_t *seat;
    800 
    801         seat = ds_display_first_seat(display);
    802         while (seat != NULL) {
    803                 if (seat->id == id)
    804                         return seat;
    805 
    806                 seat = ds_display_next_seat(seat);
    807         }
    808 
    809         return NULL;
    810 }
    811 
    812 /** Get seat which owns the specified input device.
    813  *
    814  * @param disp Display
    815  * @param idev_id Input device ID
    816  * @return Seat which owns device with ID @a idev_id or @c NULL if not found
    817  */
    818 ds_seat_t *ds_display_seat_by_idev(ds_display_t *disp, ds_idev_id_t idev_id)
    819 {
    820         ds_idevcfg_t *idevcfg;
    821 
    822         /*
    823          * Find input device configuration entry that maps this input device
    824          * to a seat.
    825          */
    826         idevcfg = ds_display_first_idevcfg(disp);
    827         while (idevcfg != NULL) {
    828                 if (idevcfg->svc_id == idev_id)
    829                         return idevcfg->seat;
    830 
    831                 idevcfg = ds_display_next_idevcfg(idevcfg);
    832         }
    833 
    834         /* If none was found, return the default seat */
    835         return ds_display_default_seat(disp);
    836426}
    837427
     
    869459                goto error;
    870460
    871         rc = mem_gc_create(&disp->rect, &alloc, &ds_display_mem_gc_cb,
    872             (void *) disp, &disp->bbgc);
     461        rc = mem_gc_create(&disp->rect, &alloc,
     462            ds_display_invalidate_cb, ds_display_update_cb, (void *) disp,
     463            &disp->bbgc);
    873464        if (rc != EOK)
    874465                goto error;
     
    898489{
    899490        errno_t rc;
    900         gfx_rect_t old_disp_rect;
    901491
    902492        assert(ddev->display == NULL);
    903493        assert(!link_used(&ddev->lddevs));
    904 
    905         old_disp_rect = disp->rect;
    906494
    907495        ddev->display = disp;
     
    915503                /* Create cloning GC */
    916504                rc = ds_clonegc_create(ddev->gc, &disp->fbgc);
    917                 if (rc != EOK)
    918                         goto error;
     505                if (rc != EOK) {
     506                        // XXX Remove output
     507                        return ENOMEM;
     508                }
    919509
    920510                /* Allocate backbuffer */
    921511                rc = ds_display_alloc_backbuf(disp);
    922512                if (rc != EOK) {
    923                         ds_clonegc_delete(disp->fbgc);
    924                         disp->fbgc = NULL;
     513                        // XXX Remove output
     514                        // XXX Delete clone GC
    925515                        goto error;
    926516                }
     
    932522        }
    933523
    934         ds_display_update_max_rect(disp);
    935 
    936524        return EOK;
    937525error:
    938         disp->rect = old_disp_rect;
     526        disp->rect.p0.x = 0;
     527        disp->rect.p0.y = 0;
     528        disp->rect.p1.x = 0;
     529        disp->rect.p1.y = 0;
    939530        list_remove(&ddev->lddevs);
    940531        return rc;
     
    981572}
    982573
    983 /** Add input device configuration entry to display.
    984  *
    985  * @param disp Display
    986  * @param idevcfg Input device configuration
    987  */
    988 void ds_display_add_idevcfg(ds_display_t *disp, ds_idevcfg_t *idevcfg)
    989 {
    990         assert(idevcfg->display == NULL);
    991         assert(!link_used(&idevcfg->ldispidcfgs));
    992 
    993         idevcfg->display = disp;
    994         list_append(&idevcfg->ldispidcfgs, &disp->idevcfgs);
    995 }
    996 
    997 /** Remove input device configuration entry from display.
    998  *
    999  * @param idevcfg Input device configuration entry
    1000  */
    1001 void ds_display_remove_idevcfg(ds_idevcfg_t *idevcfg)
    1002 {
    1003         list_remove(&idevcfg->ldispidcfgs);
    1004         idevcfg->display = NULL;
    1005 }
    1006 
    1007 /** Get first input device configuration entry in display.
    1008  *
    1009  * @param disp Display
    1010  * @return First input device configuration entry or @c NULL if there is none
    1011  */
    1012 ds_idevcfg_t *ds_display_first_idevcfg(ds_display_t *disp)
    1013 {
    1014         link_t *link = list_first(&disp->idevcfgs);
    1015 
    1016         if (link == NULL)
    1017                 return NULL;
    1018 
    1019         return list_get_instance(link, ds_idevcfg_t, ldispidcfgs);
    1020 }
    1021 
    1022 /** Get next input device configuration entry in display.
    1023  *
    1024  * @param idevcfg Current input device configuration entry
    1025  * @return Next input device configuration entry or @c NULL if there is none
    1026  */
    1027 ds_idevcfg_t *ds_display_next_idevcfg(ds_idevcfg_t *idevcfg)
    1028 {
    1029         link_t *link = list_next(&idevcfg->ldispidcfgs, &idevcfg->display->idevcfgs);
    1030 
    1031         if (link == NULL)
    1032                 return NULL;
    1033 
    1034         return list_get_instance(link, ds_idevcfg_t, ldispidcfgs);
    1035 }
    1036 
    1037574/** Add cursor to display.
    1038575 *
     
    1057594        list_remove(&cursor->ldisplay);
    1058595        cursor->display = NULL;
    1059 }
    1060 
    1061 /** Update display maximize rectangle.
    1062  *
    1063  * Recalculate the maximize rectangle (the rectangle used for maximized
    1064  * windows).
    1065  *
    1066  * @param display Display
    1067  */
    1068 void ds_display_update_max_rect(ds_display_t *display)
    1069 {
    1070         ds_window_t *wnd;
    1071         gfx_rect_t max_rect;
    1072         gfx_rect_t drect;
    1073 
    1074         /* Start with the entire display */
    1075         max_rect = display->rect;
    1076 
    1077         wnd = ds_display_first_window(display);
    1078         while (wnd != NULL) {
    1079                 /* Should maximized windows avoid this window? */
    1080                 if ((wnd->flags & wndf_avoid) != 0) {
    1081                         /* Window bounding rectangle on display */
    1082                         gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
    1083 
    1084                         /* Crop maximized rectangle */
    1085                         ds_display_crop_max_rect(&drect, &max_rect);
    1086                 }
    1087 
    1088                 wnd = ds_display_next_window(wnd);
    1089         }
    1090 
    1091         /* Update the maximize rectangle */
    1092         display->max_rect = max_rect;
    1093 }
    1094 
    1095 /** Crop maximize rectangle.
    1096  *
    1097  * Use the avoid rectangle @a arect to crop off maximization rectangle
    1098  * @a mrect. If @a arect covers the top, bottom, left or right part
    1099  * of @a mrect, it will be cropped off. Otherwise there will be
    1100  * no effect.
    1101  *
    1102  * @param arect Avoid rectangle
    1103  * @param mrect Maximize rectangle to be modified
    1104  */
    1105 void ds_display_crop_max_rect(gfx_rect_t *arect, gfx_rect_t *mrect)
    1106 {
    1107         if (arect->p0.x == mrect->p0.x && arect->p0.y == mrect->p0.y &&
    1108             arect->p1.x == mrect->p1.x) {
    1109                 /* Cropp off top part */
    1110                 mrect->p0.y = arect->p1.y;
    1111         } else if (arect->p0.x == mrect->p0.x && arect->p1.x == mrect->p1.x &&
    1112             arect->p1.y == mrect->p1.y) {
    1113                 /* Cropp off bottom part */
    1114                 mrect->p1.y = arect->p0.y;
    1115         } else if (arect->p0.x == mrect->p0.x && arect->p0.y == mrect->p0.y &&
    1116             arect->p1.y == mrect->p1.y) {
    1117                 /* Cropp off left part */
    1118                 mrect->p0.x = arect->p1.x;
    1119         } else if (arect->p0.y == mrect->p0.y && arect->p1.x == mrect->p1.x &&
    1120             arect->p1.y == mrect->p1.y) {
    1121                 /* Cropp off right part */
    1122                 mrect->p1.x = arect->p0.x;
    1123         }
    1124596}
    1125597
Note: See TracChangeset for help on using the changeset viewer.