Changes in uspace/srv/hid/display/display.c [6fbd1f9:2ab8ab3] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/display/display.c
r6fbd1f9 r2ab8ab3 1 1 /* 2 * Copyright (c) 20 24Jiri Svoboda2 * Copyright (c) 2019 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 41 41 #include <memgfx/memgc.h> 42 42 #include <stdlib.h> 43 #include <str.h>44 43 #include "client.h" 45 44 #include "clonegc.h" 46 45 #include "cursimg.h" 47 46 #include "cursor.h" 48 #include "display.h"49 #include "idevcfg.h"50 47 #include "seat.h" 51 48 #include "window.h" 52 #include " wmclient.h"49 #include "display.h" 53 50 54 51 static gfx_context_t *ds_display_get_unbuf_gc(ds_display_t *); 55 52 static void ds_display_invalidate_cb(void *, gfx_rect_t *); 56 53 static 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_cb61 };62 54 63 55 /** Create display. … … 99 91 fibril_mutex_initialize(&disp->lock); 100 92 list_initialize(&disp->clients); 101 list_initialize(&disp->wmclients);102 list_initialize(&disp->cfgclients);103 93 disp->next_wnd_id = 1; 104 disp->next_seat_id = 1;105 94 list_initialize(&disp->ddevs); 106 list_initialize(&disp->idevcfgs);107 list_initialize(&disp->ievents);108 fibril_condvar_initialize(&disp->ievent_cv);109 95 list_initialize(&disp->seats); 110 96 list_initialize(&disp->windows); … … 123 109 void ds_display_destroy(ds_display_t *disp) 124 110 { 125 int i;126 127 111 assert(list_empty(&disp->clients)); 128 assert(list_empty(&disp->wmclients));129 assert(list_empty(&disp->cfgclients));130 112 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 */ 143 114 gfx_color_delete(disp->bg_color); 144 115 free(disp); 145 116 } 146 117 147 /** Load display configuration from SIF file.148 *149 * @param display Display150 * @param cfgpath Configuration file path151 *152 * @return EOK on success or an error code153 */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 device222 * 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 Display249 * @param cfgpath Configuration file path250 *251 * @return EOK on success or an error code252 */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 323 118 /** Lock display. 324 119 * … … 403 198 404 199 return list_get_instance(link, ds_client_t, lclients); 405 }406 407 /** Add WM client to display.408 *409 * @param disp Display410 * @param wmclient WM client411 */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 client424 */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 Display434 * @param cfgclient CFG client435 */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 client448 */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 Display458 * @return First WM client or @c NULL if there is none459 */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 client473 * @return Next WM client or @c NULL if there is none474 */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);484 200 } 485 201 … … 525 241 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect); 526 242 527 if (gfx_pix_inside_rect(pos, &drect) && 528 ds_window_is_visible(wnd)) 243 if (gfx_pix_inside_rect(pos, &drect)) 529 244 return wnd; 530 245 … … 535 250 } 536 251 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. 541 253 * 542 254 * @param display Display 543 255 * @param wnd Window 544 256 */ 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 else561 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 Display572 * @param wnd Window573 */574 257 void ds_display_add_window(ds_display_t *display, ds_window_t *wnd) 575 258 { 576 ds_wmclient_t *wmclient;577 578 259 assert(wnd->display == NULL); 579 260 assert(!link_used(&wnd->ldwindows)); 580 261 581 262 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); 590 264 } 591 265 … … 596 270 void ds_display_remove_window(ds_window_t *wnd) 597 271 { 598 ds_wmclient_t *wmclient;599 ds_display_t *display;600 601 display = wnd->display;602 603 272 list_remove(&wnd->ldwindows); 604 273 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 Display617 * @param wnd Window618 */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);626 274 } 627 275 … … 699 347 ds_seat_t *seat; 700 348 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); 703 351 if (seat == NULL) 704 352 return EOK; … … 716 364 ds_seat_t *seat; 717 365 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); 720 368 if (seat == NULL) 721 369 return EOK; … … 735 383 736 384 seat->display = disp; 737 seat->id = disp->next_seat_id++;738 385 list_append(&seat->lseats, &disp->seats); 739 386 } … … 777 424 778 425 return list_get_instance(link, ds_seat_t, lseats); 779 }780 781 /** Get default seat in display.782 *783 * @param disp Display784 * @return First seat or @c NULL if there is none785 */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 Display795 * @param id Seat ID796 */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 Display815 * @param idev_id Input device ID816 * @return Seat which owns device with ID @a idev_id or @c NULL if not found817 */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 device824 * 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);836 426 } 837 427 … … 869 459 goto error; 870 460 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); 873 464 if (rc != EOK) 874 465 goto error; … … 898 489 { 899 490 errno_t rc; 900 gfx_rect_t old_disp_rect;901 491 902 492 assert(ddev->display == NULL); 903 493 assert(!link_used(&ddev->lddevs)); 904 905 old_disp_rect = disp->rect;906 494 907 495 ddev->display = disp; … … 915 503 /* Create cloning GC */ 916 504 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 } 919 509 920 510 /* Allocate backbuffer */ 921 511 rc = ds_display_alloc_backbuf(disp); 922 512 if (rc != EOK) { 923 ds_clonegc_delete(disp->fbgc);924 disp->fbgc = NULL;513 // XXX Remove output 514 // XXX Delete clone GC 925 515 goto error; 926 516 } … … 932 522 } 933 523 934 ds_display_update_max_rect(disp);935 936 524 return EOK; 937 525 error: 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; 939 530 list_remove(&ddev->lddevs); 940 531 return rc; … … 981 572 } 982 573 983 /** Add input device configuration entry to display.984 *985 * @param disp Display986 * @param idevcfg Input device configuration987 */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 entry1000 */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 Display1010 * @return First input device configuration entry or @c NULL if there is none1011 */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 entry1025 * @return Next input device configuration entry or @c NULL if there is none1026 */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 1037 574 /** Add cursor to display. 1038 575 * … … 1057 594 list_remove(&cursor->ldisplay); 1058 595 cursor->display = NULL; 1059 }1060 1061 /** Update display maximize rectangle.1062 *1063 * Recalculate the maximize rectangle (the rectangle used for maximized1064 * windows).1065 *1066 * @param display Display1067 */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 rectangle1098 * @a mrect. If @a arect covers the top, bottom, left or right part1099 * of @a mrect, it will be cropped off. Otherwise there will be1100 * no effect.1101 *1102 * @param arect Avoid rectangle1103 * @param mrect Maximize rectangle to be modified1104 */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 }1124 596 } 1125 597
Note:
See TracChangeset
for help on using the changeset viewer.