Changes in uspace/srv/hid/display/display.c [1215db9:e90019d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/display/display.c
r1215db9 re90019d 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); 100 107 list_initialize(&disp->seats); 101 108 list_initialize(&disp->windows); … … 114 121 void ds_display_destroy(ds_display_t *disp) 115 122 { 123 int i; 124 116 125 assert(list_empty(&disp->clients)); 126 assert(list_empty(&disp->wmclients)); 127 assert(list_empty(&disp->cfgclients)); 117 128 assert(list_empty(&disp->seats)); 118 /* XXX destroy cursors */ 129 assert(list_empty(&disp->ddevs)); 130 assert(list_empty(&disp->idevcfgs)); 131 assert(list_empty(&disp->seats)); 132 assert(list_empty(&disp->windows)); 133 134 /* Destroy cursors */ 135 for (i = 0; i < dcurs_limit; i++) { 136 ds_cursor_destroy(disp->cursor[i]); 137 disp->cursor[i] = NULL; 138 } 139 119 140 gfx_color_delete(disp->bg_color); 120 141 free(disp); 121 142 } 122 143 144 /** Load display configuration from SIF file. 145 * 146 * @param display Display 147 * @param cfgpath Configuration file path 148 * 149 * @return EOK on success or an error code 150 */ 151 errno_t ds_display_load_cfg(ds_display_t *display, const char *cfgpath) 152 { 153 sif_doc_t *doc = NULL; 154 sif_node_t *rnode; 155 sif_node_t *ndisplay; 156 sif_node_t *nseats; 157 sif_node_t *nseat; 158 ds_seat_t *seat; 159 sif_node_t *nidevcfgs; 160 sif_node_t *nidevcfg; 161 const char *ntype; 162 ds_idevcfg_t *idevcfg; 163 errno_t rc; 164 165 rc = sif_load(cfgpath, &doc); 166 if (rc != EOK) 167 goto error; 168 169 rnode = sif_get_root(doc); 170 ndisplay = sif_node_first_child(rnode); 171 ntype = sif_node_get_type(ndisplay); 172 if (str_cmp(ntype, "display") != 0) { 173 rc = EIO; 174 goto error; 175 } 176 177 nseats = sif_node_first_child(ndisplay); 178 ntype = sif_node_get_type(nseats); 179 if (str_cmp(ntype, "seats") != 0) { 180 rc = EIO; 181 goto error; 182 } 183 184 /* Load individual seats */ 185 nseat = sif_node_first_child(nseats); 186 while (nseat != NULL) { 187 ntype = sif_node_get_type(nseat); 188 if (str_cmp(ntype, "seat") != 0) { 189 rc = EIO; 190 goto error; 191 } 192 193 rc = ds_seat_load(display, nseat, &seat); 194 if (rc != EOK) 195 goto error; 196 197 (void)seat; 198 nseat = sif_node_next_child(nseat); 199 } 200 201 nidevcfgs = sif_node_next_child(nseats); 202 ntype = sif_node_get_type(nidevcfgs); 203 if (str_cmp(ntype, "idevcfgs") != 0) { 204 rc = EIO; 205 goto error; 206 } 207 208 /* Load individual input device configuration entries */ 209 nidevcfg = sif_node_first_child(nidevcfgs); 210 while (nidevcfg != NULL) { 211 ntype = sif_node_get_type(nidevcfg); 212 if (str_cmp(ntype, "idevcfg") != 0) { 213 rc = EIO; 214 goto error; 215 } 216 217 /* 218 * Load device configuration entry. If the device 219 * is not currently connected (ENOENT), skip it. 220 */ 221 rc = ds_idevcfg_load(display, nidevcfg, &idevcfg); 222 if (rc != EOK && rc != ENOENT) 223 goto error; 224 225 (void)idevcfg; 226 nidevcfg = sif_node_next_child(nidevcfg); 227 } 228 229 sif_delete(doc); 230 return EOK; 231 error: 232 if (doc != NULL) 233 sif_delete(doc); 234 235 seat = ds_display_first_seat(display); 236 while (seat != NULL) { 237 ds_seat_destroy(seat); 238 seat = ds_display_first_seat(display); 239 } 240 return rc; 241 } 242 243 /** Save display configuration to SIF file. 244 * 245 * @param display Display 246 * @param cfgpath Configuration file path 247 * 248 * @return EOK on success or an error code 249 */ 250 errno_t ds_display_save_cfg(ds_display_t *display, const char *cfgpath) 251 { 252 sif_doc_t *doc = NULL; 253 sif_node_t *rnode; 254 sif_node_t *ndisplay; 255 sif_node_t *nseats; 256 sif_node_t *nseat; 257 ds_seat_t *seat; 258 sif_node_t *nidevcfgs; 259 sif_node_t *nidevcfg; 260 ds_idevcfg_t *idevcfg; 261 errno_t rc; 262 263 rc = sif_new(&doc); 264 if (rc != EOK) 265 goto error; 266 267 rnode = sif_get_root(doc); 268 rc = sif_node_append_child(rnode, "display", &ndisplay); 269 if (rc != EOK) 270 goto error; 271 272 rc = sif_node_append_child(ndisplay, "seats", &nseats); 273 if (rc != EOK) 274 goto error; 275 276 /* Save individual seats */ 277 seat = ds_display_first_seat(display); 278 while (seat != NULL) { 279 rc = sif_node_append_child(nseats, "seat", &nseat); 280 if (rc != EOK) 281 goto error; 282 283 rc = ds_seat_save(seat, nseat); 284 if (rc != EOK) 285 goto error; 286 287 seat = ds_display_next_seat(seat); 288 } 289 290 rc = sif_node_append_child(ndisplay, "idevcfgs", &nidevcfgs); 291 if (rc != EOK) 292 goto error; 293 294 /* Save individual input device configuration entries */ 295 idevcfg = ds_display_first_idevcfg(display); 296 while (idevcfg != NULL) { 297 rc = sif_node_append_child(nidevcfgs, "idevcfg", &nidevcfg); 298 if (rc != EOK) 299 goto error; 300 301 rc = ds_idevcfg_save(idevcfg, nidevcfg); 302 if (rc != EOK) 303 goto error; 304 305 idevcfg = ds_display_next_idevcfg(idevcfg); 306 } 307 308 rc = sif_save(doc, cfgpath); 309 if (rc != EOK) 310 goto error; 311 312 sif_delete(doc); 313 return EOK; 314 error: 315 if (doc != NULL) 316 sif_delete(doc); 317 return rc; 318 } 319 123 320 /** Lock display. 124 321 * … … 203 400 204 401 return list_get_instance(link, ds_client_t, lclients); 402 } 403 404 /** Add WM client to display. 405 * 406 * @param disp Display 407 * @param wmclient WM client 408 */ 409 void ds_display_add_wmclient(ds_display_t *disp, ds_wmclient_t *wmclient) 410 { 411 assert(wmclient->display == NULL); 412 assert(!link_used(&wmclient->lwmclients)); 413 414 wmclient->display = disp; 415 list_append(&wmclient->lwmclients, &disp->wmclients); 416 } 417 418 /** Remove WM client from display. 419 * 420 * @param wmclient WM client 421 */ 422 void ds_display_remove_wmclient(ds_wmclient_t *wmclient) 423 { 424 list_remove(&wmclient->lwmclients); 425 wmclient->display = NULL; 426 } 427 428 /** Add CFG client to display. 429 * 430 * @param disp Display 431 * @param cfgclient CFG client 432 */ 433 void ds_display_add_cfgclient(ds_display_t *disp, ds_cfgclient_t *cfgclient) 434 { 435 assert(cfgclient->display == NULL); 436 assert(!link_used(&cfgclient->lcfgclients)); 437 438 cfgclient->display = disp; 439 list_append(&cfgclient->lcfgclients, &disp->cfgclients); 440 } 441 442 /** Remove CFG client from display. 443 * 444 * @param cfgclient CFG client 445 */ 446 void ds_display_remove_cfgclient(ds_cfgclient_t *cfgclient) 447 { 448 list_remove(&cfgclient->lcfgclients); 449 cfgclient->display = NULL; 450 } 451 452 /** Get first WM client in display. 453 * 454 * @param disp Display 455 * @return First WM client or @c NULL if there is none 456 */ 457 ds_wmclient_t *ds_display_first_wmclient(ds_display_t *disp) 458 { 459 link_t *link = list_first(&disp->wmclients); 460 461 if (link == NULL) 462 return NULL; 463 464 return list_get_instance(link, ds_wmclient_t, lwmclients); 465 } 466 467 /** Get next WM client in display. 468 * 469 * @param wmclient Current WM client 470 * @return Next WM client or @c NULL if there is none 471 */ 472 ds_wmclient_t *ds_display_next_wmclient(ds_wmclient_t *wmclient) 473 { 474 link_t *link = list_next(&wmclient->lwmclients, 475 &wmclient->display->wmclients); 476 477 if (link == NULL) 478 return NULL; 479 480 return list_get_instance(link, ds_wmclient_t, lwmclients); 205 481 } 206 482 … … 246 522 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect); 247 523 248 if (gfx_pix_inside_rect(pos, &drect)) 524 if (gfx_pix_inside_rect(pos, &drect) && 525 ds_window_is_visible(wnd)) 249 526 return wnd; 250 527 … … 255 532 } 256 533 534 /** Add window to window list. 535 * 536 * Topmost windows are enlisted before any other window. Non-topmost 537 * windows are enlisted before any other non-topmost window. 538 * 539 * @param display Display 540 * @param wnd Window 541 */ 542 void ds_display_enlist_window(ds_display_t *display, ds_window_t *wnd) 543 { 544 ds_window_t *w; 545 546 assert(wnd->display == display); 547 assert(!link_used(&wnd->ldwindows)); 548 549 if ((wnd->flags & wndf_topmost) == 0) { 550 /* Find the first non-topmost window */ 551 w = ds_display_first_window(display); 552 while (w != NULL && (w->flags & wndf_topmost) != 0) 553 w = ds_display_next_window(w); 554 555 if (w != NULL) 556 list_insert_before(&wnd->ldwindows, &w->ldwindows); 557 else 558 list_append(&wnd->ldwindows, &display->windows); 559 } else { 560 /* Insert at the beginning */ 561 list_prepend(&wnd->ldwindows, &display->windows); 562 } 563 564 } 565 257 566 /** Add window to display. 258 567 * … … 262 571 void ds_display_add_window(ds_display_t *display, ds_window_t *wnd) 263 572 { 573 ds_wmclient_t *wmclient; 574 264 575 assert(wnd->display == NULL); 265 576 assert(!link_used(&wnd->ldwindows)); 266 577 267 578 wnd->display = display; 268 list_prepend(&wnd->ldwindows, &display->windows); 579 ds_display_enlist_window(display, wnd); 580 581 /* Notify window managers about the new window */ 582 wmclient = ds_display_first_wmclient(display); 583 while (wmclient != NULL) { 584 ds_wmclient_post_wnd_added_event(wmclient, wnd->id); 585 wmclient = ds_display_next_wmclient(wmclient); 586 } 269 587 } 270 588 … … 275 593 void ds_display_remove_window(ds_window_t *wnd) 276 594 { 595 ds_wmclient_t *wmclient; 596 ds_display_t *display; 597 598 display = wnd->display; 599 277 600 list_remove(&wnd->ldwindows); 278 601 wnd->display = NULL; 602 603 /* Notify window managers about the removed window */ 604 wmclient = ds_display_first_wmclient(display); 605 while (wmclient != NULL) { 606 ds_wmclient_post_wnd_removed_event(wmclient, wnd->id); 607 wmclient = ds_display_next_wmclient(wmclient); 608 } 609 } 610 611 /** Move window to top. 612 * 613 * @param display Display 614 * @param wnd Window 615 */ 616 void ds_display_window_to_top(ds_window_t *wnd) 617 { 618 assert(wnd->display != NULL); 619 assert(link_used(&wnd->ldwindows)); 620 621 list_remove(&wnd->ldwindows); 622 ds_display_enlist_window(wnd->display, wnd); 279 623 } 280 624 … … 352 696 ds_seat_t *seat; 353 697 354 / / TODO Determine which seat the event belongs to355 seat = ds_display_ first_seat(display);698 /* Determine which seat the event belongs to */ 699 seat = ds_display_seat_by_idev(display, event->kbd_id); 356 700 if (seat == NULL) 357 701 return EOK; … … 369 713 ds_seat_t *seat; 370 714 371 / / TODO Determine which seat the event belongs to372 seat = ds_display_ first_seat(display);715 /* Determine which seat the event belongs to */ 716 seat = ds_display_seat_by_idev(display, event->pos_id); 373 717 if (seat == NULL) 374 718 return EOK; … … 388 732 389 733 seat->display = disp; 734 seat->id = disp->next_seat_id++; 390 735 list_append(&seat->lseats, &disp->seats); 391 736 } … … 429 774 430 775 return list_get_instance(link, ds_seat_t, lseats); 776 } 777 778 /** Get default seat in display. 779 * 780 * @param disp Display 781 * @return First seat or @c NULL if there is none 782 */ 783 ds_seat_t *ds_display_default_seat(ds_display_t *disp) 784 { 785 /* XXX Probably not the best solution */ 786 return ds_display_first_seat(disp); 787 } 788 789 /** Find seat by ID. 790 * 791 * @param display Display 792 * @param id Seat ID 793 */ 794 ds_seat_t *ds_display_find_seat(ds_display_t *display, ds_seat_id_t id) 795 { 796 ds_seat_t *seat; 797 798 seat = ds_display_first_seat(display); 799 while (seat != NULL) { 800 if (seat->id == id) 801 return seat; 802 803 seat = ds_display_next_seat(seat); 804 } 805 806 return NULL; 807 } 808 809 /** Get seat which owns the specified input device. 810 * 811 * @param disp Display 812 * @param idev_id Input device ID 813 * @return Seat which owns device with ID @a idev_id or @c NULL if not found 814 */ 815 ds_seat_t *ds_display_seat_by_idev(ds_display_t *disp, ds_idev_id_t idev_id) 816 { 817 ds_idevcfg_t *idevcfg; 818 819 /* 820 * Find input device configuration entry that maps this input device 821 * to a seat. 822 */ 823 idevcfg = ds_display_first_idevcfg(disp); 824 while (idevcfg != NULL) { 825 if (idevcfg->svc_id == idev_id) 826 return idevcfg->seat; 827 828 idevcfg = ds_display_next_idevcfg(idevcfg); 829 } 830 831 /* If none was found, return the default seat */ 832 return ds_display_default_seat(disp); 431 833 } 432 834 … … 493 895 { 494 896 errno_t rc; 897 gfx_rect_t old_disp_rect; 495 898 496 899 assert(ddev->display == NULL); 497 900 assert(!link_used(&ddev->lddevs)); 901 902 old_disp_rect = disp->rect; 498 903 499 904 ddev->display = disp; … … 507 912 /* Create cloning GC */ 508 913 rc = ds_clonegc_create(ddev->gc, &disp->fbgc); 509 if (rc != EOK) { 510 // XXX Remove output 511 return ENOMEM; 512 } 914 if (rc != EOK) 915 goto error; 513 916 514 917 /* Allocate backbuffer */ 515 918 rc = ds_display_alloc_backbuf(disp); 516 919 if (rc != EOK) { 517 // XXX Remove output518 // XXX Delete clone GC920 ds_clonegc_delete(disp->fbgc); 921 disp->fbgc = NULL; 519 922 goto error; 520 923 } … … 526 929 } 527 930 931 ds_display_update_max_rect(disp); 932 528 933 return EOK; 529 934 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; 935 disp->rect = old_disp_rect; 534 936 list_remove(&ddev->lddevs); 535 937 return rc; … … 576 978 } 577 979 980 /** Add input device configuration entry to display. 981 * 982 * @param disp Display 983 * @param idevcfg Input device configuration 984 */ 985 void ds_display_add_idevcfg(ds_display_t *disp, ds_idevcfg_t *idevcfg) 986 { 987 assert(idevcfg->display == NULL); 988 assert(!link_used(&idevcfg->ldispidcfgs)); 989 990 idevcfg->display = disp; 991 list_append(&idevcfg->ldispidcfgs, &disp->idevcfgs); 992 } 993 994 /** Remove input device configuration entry from display. 995 * 996 * @param idevcfg Input device configuration entry 997 */ 998 void ds_display_remove_idevcfg(ds_idevcfg_t *idevcfg) 999 { 1000 list_remove(&idevcfg->ldispidcfgs); 1001 idevcfg->display = NULL; 1002 } 1003 1004 /** Get first input device configuration entry in display. 1005 * 1006 * @param disp Display 1007 * @return First input device configuration entry or @c NULL if there is none 1008 */ 1009 ds_idevcfg_t *ds_display_first_idevcfg(ds_display_t *disp) 1010 { 1011 link_t *link = list_first(&disp->idevcfgs); 1012 1013 if (link == NULL) 1014 return NULL; 1015 1016 return list_get_instance(link, ds_idevcfg_t, ldispidcfgs); 1017 } 1018 1019 /** Get next input device configuration entry in display. 1020 * 1021 * @param idevcfg Current input device configuration entry 1022 * @return Next input device configuration entry or @c NULL if there is none 1023 */ 1024 ds_idevcfg_t *ds_display_next_idevcfg(ds_idevcfg_t *idevcfg) 1025 { 1026 link_t *link = list_next(&idevcfg->ldispidcfgs, &idevcfg->display->idevcfgs); 1027 1028 if (link == NULL) 1029 return NULL; 1030 1031 return list_get_instance(link, ds_idevcfg_t, ldispidcfgs); 1032 } 1033 578 1034 /** Add cursor to display. 579 1035 * … … 598 1054 list_remove(&cursor->ldisplay); 599 1055 cursor->display = NULL; 1056 } 1057 1058 /** Update display maximize rectangle. 1059 * 1060 * Recalculate the maximize rectangle (the rectangle used for maximized 1061 * windows). 1062 * 1063 * @param display Display 1064 */ 1065 void ds_display_update_max_rect(ds_display_t *display) 1066 { 1067 ds_window_t *wnd; 1068 gfx_rect_t max_rect; 1069 gfx_rect_t drect; 1070 1071 /* Start with the entire display */ 1072 max_rect = display->rect; 1073 1074 wnd = ds_display_first_window(display); 1075 while (wnd != NULL) { 1076 /* Should maximized windows avoid this window? */ 1077 if ((wnd->flags & wndf_avoid) != 0) { 1078 /* Window bounding rectangle on display */ 1079 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect); 1080 1081 /* Crop maximized rectangle */ 1082 ds_display_crop_max_rect(&drect, &max_rect); 1083 } 1084 1085 wnd = ds_display_next_window(wnd); 1086 } 1087 1088 /* Update the maximize rectangle */ 1089 display->max_rect = max_rect; 1090 } 1091 1092 /** Crop maximize rectangle. 1093 * 1094 * Use the avoid rectangle @a arect to crop off maximization rectangle 1095 * @a mrect. If @a arect covers the top, bottom, left or right part 1096 * of @a mrect, it will be cropped off. Otherwise there will be 1097 * no effect. 1098 * 1099 * @param arect Avoid rectangle 1100 * @param mrect Maximize rectangle to be modified 1101 */ 1102 void ds_display_crop_max_rect(gfx_rect_t *arect, gfx_rect_t *mrect) 1103 { 1104 if (arect->p0.x == mrect->p0.x && arect->p0.y == mrect->p0.y && 1105 arect->p1.x == mrect->p1.x) { 1106 /* Cropp off top part */ 1107 mrect->p0.y = arect->p1.y; 1108 } else if (arect->p0.x == mrect->p0.x && arect->p1.x == mrect->p1.x && 1109 arect->p1.y == mrect->p1.y) { 1110 /* Cropp off bottom part */ 1111 mrect->p1.y = arect->p0.y; 1112 } else if (arect->p0.x == mrect->p0.x && arect->p0.y == mrect->p0.y && 1113 arect->p1.y == mrect->p1.y) { 1114 /* Cropp off left part */ 1115 mrect->p0.x = arect->p1.x; 1116 } else if (arect->p0.y == mrect->p0.y && arect->p1.x == mrect->p1.x && 1117 arect->p1.y == mrect->p1.y) { 1118 /* Cropp off right part */ 1119 mrect->p1.x = arect->p0.x; 1120 } 600 1121 } 601 1122
Note:
See TracChangeset
for help on using the changeset viewer.