Changes in uspace/srv/hid/display/display.c [2ab8ab3:6fbd1f9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/display/display.c
r2ab8ab3 r6fbd1f9 1 1 /* 2 * Copyright (c) 20 19Jiri 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 *); 52 55 static void ds_display_invalidate_cb(void *, gfx_rect_t *); 53 56 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_cb 61 }; 54 62 55 63 /** Create display. … … 91 99 fibril_mutex_initialize(&disp->lock); 92 100 list_initialize(&disp->clients); 101 list_initialize(&disp->wmclients); 102 list_initialize(&disp->cfgclients); 93 103 disp->next_wnd_id = 1; 104 disp->next_seat_id = 1; 94 105 list_initialize(&disp->ddevs); 106 list_initialize(&disp->idevcfgs); 107 list_initialize(&disp->ievents); 108 fibril_condvar_initialize(&disp->ievent_cv); 95 109 list_initialize(&disp->seats); 96 110 list_initialize(&disp->windows); … … 109 123 void ds_display_destroy(ds_display_t *disp) 110 124 { 125 int i; 126 111 127 assert(list_empty(&disp->clients)); 128 assert(list_empty(&disp->wmclients)); 129 assert(list_empty(&disp->cfgclients)); 112 130 assert(list_empty(&disp->seats)); 113 /* 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 114 143 gfx_color_delete(disp->bg_color); 115 144 free(disp); 116 145 } 117 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 118 323 /** Lock display. 119 324 * … … 198 403 199 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); 200 484 } 201 485 … … 241 525 gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect); 242 526 243 if (gfx_pix_inside_rect(pos, &drect)) 527 if (gfx_pix_inside_rect(pos, &drect) && 528 ds_window_is_visible(wnd)) 244 529 return wnd; 245 530 … … 250 535 } 251 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 252 569 /** Add window to display. 253 570 * … … 257 574 void ds_display_add_window(ds_display_t *display, ds_window_t *wnd) 258 575 { 576 ds_wmclient_t *wmclient; 577 259 578 assert(wnd->display == NULL); 260 579 assert(!link_used(&wnd->ldwindows)); 261 580 262 581 wnd->display = display; 263 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 } 264 590 } 265 591 … … 270 596 void ds_display_remove_window(ds_window_t *wnd) 271 597 { 598 ds_wmclient_t *wmclient; 599 ds_display_t *display; 600 601 display = wnd->display; 602 272 603 list_remove(&wnd->ldwindows); 273 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); 274 626 } 275 627 … … 347 699 ds_seat_t *seat; 348 700 349 / / TODO Determine which seat the event belongs to350 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); 351 703 if (seat == NULL) 352 704 return EOK; … … 364 716 ds_seat_t *seat; 365 717 366 / / TODO Determine which seat the event belongs to367 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); 368 720 if (seat == NULL) 369 721 return EOK; … … 383 735 384 736 seat->display = disp; 737 seat->id = disp->next_seat_id++; 385 738 list_append(&seat->lseats, &disp->seats); 386 739 } … … 424 777 425 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); 426 836 } 427 837 … … 459 869 goto error; 460 870 461 rc = mem_gc_create(&disp->rect, &alloc, 462 ds_display_invalidate_cb, ds_display_update_cb, (void *) disp, 463 &disp->bbgc); 871 rc = mem_gc_create(&disp->rect, &alloc, &ds_display_mem_gc_cb, 872 (void *) disp, &disp->bbgc); 464 873 if (rc != EOK) 465 874 goto error; … … 489 898 { 490 899 errno_t rc; 900 gfx_rect_t old_disp_rect; 491 901 492 902 assert(ddev->display == NULL); 493 903 assert(!link_used(&ddev->lddevs)); 904 905 old_disp_rect = disp->rect; 494 906 495 907 ddev->display = disp; … … 503 915 /* Create cloning GC */ 504 916 rc = ds_clonegc_create(ddev->gc, &disp->fbgc); 505 if (rc != EOK) { 506 // XXX Remove output 507 return ENOMEM; 508 } 917 if (rc != EOK) 918 goto error; 509 919 510 920 /* Allocate backbuffer */ 511 921 rc = ds_display_alloc_backbuf(disp); 512 922 if (rc != EOK) { 513 // XXX Remove output514 // XXX Delete clone GC923 ds_clonegc_delete(disp->fbgc); 924 disp->fbgc = NULL; 515 925 goto error; 516 926 } … … 522 932 } 523 933 934 ds_display_update_max_rect(disp); 935 524 936 return EOK; 525 937 error: 526 disp->rect.p0.x = 0; 527 disp->rect.p0.y = 0; 528 disp->rect.p1.x = 0; 529 disp->rect.p1.y = 0; 938 disp->rect = old_disp_rect; 530 939 list_remove(&ddev->lddevs); 531 940 return rc; … … 572 981 } 573 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 574 1037 /** Add cursor to display. 575 1038 * … … 594 1057 list_remove(&cursor->ldisplay); 595 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 } 596 1124 } 597 1125
Note:
See TracChangeset
for help on using the changeset viewer.