Changes in uspace/srv/hid/display/display.c [1215db9:6fbd1f9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/display/display.c
r1215db9 r6fbd1f9 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2024 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 41 41 #include <memgfx/memgc.h> 42 42 #include <stdlib.h> 43 #include <str.h> 43 44 #include "client.h" 44 45 #include "clonegc.h" 45 46 #include "cursimg.h" 46 47 #include "cursor.h" 48 #include "display.h" 49 #include "idevcfg.h" 47 50 #include "seat.h" 48 51 #include "window.h" 49 #include " display.h"52 #include "wmclient.h" 50 53 51 54 static gfx_context_t *ds_display_get_unbuf_gc(ds_display_t *); … … 96 99 fibril_mutex_initialize(&disp->lock); 97 100 list_initialize(&disp->clients); 101 list_initialize(&disp->wmclients); 102 list_initialize(&disp->cfgclients); 98 103 disp->next_wnd_id = 1; 104 disp->next_seat_id = 1; 99 105 list_initialize(&disp->ddevs); 106 list_initialize(&disp->idevcfgs); 107 list_initialize(&disp->ievents); 108 fibril_condvar_initialize(&disp->ievent_cv); 100 109 list_initialize(&disp->seats); 101 110 list_initialize(&disp->windows); … … 114 123 void ds_display_destroy(ds_display_t *disp) 115 124 { 125 int i; 126 116 127 assert(list_empty(&disp->clients)); 128 assert(list_empty(&disp->wmclients)); 129 assert(list_empty(&disp->cfgclients)); 117 130 assert(list_empty(&disp->seats)); 118 /* XXX destroy cursors */ 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 119 143 gfx_color_delete(disp->bg_color); 120 144 free(disp); 121 145 } 122 146 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 123 323 /** Lock display. 124 324 * … … 203 403 204 404 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); 205 484 } 206 485 … … 246 525 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect); 247 526 248 if (gfx_pix_inside_rect(pos, &drect)) 527 if (gfx_pix_inside_rect(pos, &drect) && 528 ds_window_is_visible(wnd)) 249 529 return wnd; 250 530 … … 255 535 } 256 536 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. 541 * 542 * @param display Display 543 * @param wnd Window 544 */ 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 257 569 /** Add window to display. 258 570 * … … 262 574 void ds_display_add_window(ds_display_t *display, ds_window_t *wnd) 263 575 { 576 ds_wmclient_t *wmclient; 577 264 578 assert(wnd->display == NULL); 265 579 assert(!link_used(&wnd->ldwindows)); 266 580 267 581 wnd->display = display; 268 list_prepend(&wnd->ldwindows, &display->windows); 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 } 269 590 } 270 591 … … 275 596 void ds_display_remove_window(ds_window_t *wnd) 276 597 { 598 ds_wmclient_t *wmclient; 599 ds_display_t *display; 600 601 display = wnd->display; 602 277 603 list_remove(&wnd->ldwindows); 278 604 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); 279 626 } 280 627 … … 352 699 ds_seat_t *seat; 353 700 354 / / TODO Determine which seat the event belongs to355 seat = ds_display_ first_seat(display);701 /* Determine which seat the event belongs to */ 702 seat = ds_display_seat_by_idev(display, event->kbd_id); 356 703 if (seat == NULL) 357 704 return EOK; … … 369 716 ds_seat_t *seat; 370 717 371 / / TODO Determine which seat the event belongs to372 seat = ds_display_ first_seat(display);718 /* Determine which seat the event belongs to */ 719 seat = ds_display_seat_by_idev(display, event->pos_id); 373 720 if (seat == NULL) 374 721 return EOK; … … 388 735 389 736 seat->display = disp; 737 seat->id = disp->next_seat_id++; 390 738 list_append(&seat->lseats, &disp->seats); 391 739 } … … 429 777 430 778 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); 431 836 } 432 837 … … 493 898 { 494 899 errno_t rc; 900 gfx_rect_t old_disp_rect; 495 901 496 902 assert(ddev->display == NULL); 497 903 assert(!link_used(&ddev->lddevs)); 904 905 old_disp_rect = disp->rect; 498 906 499 907 ddev->display = disp; … … 507 915 /* Create cloning GC */ 508 916 rc = ds_clonegc_create(ddev->gc, &disp->fbgc); 509 if (rc != EOK) { 510 // XXX Remove output 511 return ENOMEM; 512 } 917 if (rc != EOK) 918 goto error; 513 919 514 920 /* Allocate backbuffer */ 515 921 rc = ds_display_alloc_backbuf(disp); 516 922 if (rc != EOK) { 517 // XXX Remove output518 // XXX Delete clone GC923 ds_clonegc_delete(disp->fbgc); 924 disp->fbgc = NULL; 519 925 goto error; 520 926 } … … 526 932 } 527 933 934 ds_display_update_max_rect(disp); 935 528 936 return EOK; 529 937 error: 530 disp->rect.p0.x = 0; 531 disp->rect.p0.y = 0; 532 disp->rect.p1.x = 0; 533 disp->rect.p1.y = 0; 938 disp->rect = old_disp_rect; 534 939 list_remove(&ddev->lddevs); 535 940 return rc; … … 576 981 } 577 982 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 578 1037 /** Add cursor to display. 579 1038 * … … 598 1057 list_remove(&cursor->ldisplay); 599 1058 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 } 600 1124 } 601 1125
Note:
See TracChangeset
for help on using the changeset viewer.