Changes in uspace/srv/hid/display/seat.c [554a5f1:0d00e53] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/display/seat.c
r554a5f1 r0d00e53 1 1 /* 2 * Copyright (c) 20 19Jiri Svoboda2 * Copyright (c) 2024 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 38 38 #include <gfx/color.h> 39 39 #include <gfx/render.h> 40 #include <sif.h> 41 #include <stdio.h> 40 42 #include <stdlib.h> 43 #include <str.h> 41 44 #include "client.h" 42 45 #include "cursor.h" 43 46 #include "display.h" 47 #include "idevcfg.h" 44 48 #include "seat.h" 45 49 #include "window.h" … … 51 55 * 52 56 * @param display Parent display 57 * @param name Seat name 53 58 * @param rseat Place to store pointer to new seat. 54 59 * @return EOK on success, ENOMEM if out of memory 55 60 */ 56 errno_t ds_seat_create(ds_display_t *display, ds_seat_t **rseat) 61 errno_t ds_seat_create(ds_display_t *display, const char *name, 62 ds_seat_t **rseat) 57 63 { 58 64 ds_seat_t *seat; 65 ds_seat_t *s0; 66 67 s0 = ds_display_first_seat(display); 68 while (s0 != NULL) { 69 if (str_cmp(s0->name, name) == 0) 70 return EEXIST; 71 s0 = ds_display_next_seat(s0); 72 } 59 73 60 74 seat = calloc(1, sizeof(ds_seat_t)); … … 62 76 return ENOMEM; 63 77 78 seat->name = str_dup(name); 79 if (seat->name == NULL) { 80 free(seat); 81 return ENOMEM; 82 } 83 84 list_initialize(&seat->idevcfgs); 85 64 86 ds_display_add_seat(display, seat); 65 87 seat->pntpos.x = 0; … … 68 90 seat->client_cursor = display->cursor[dcurs_arrow]; 69 91 seat->wm_cursor = NULL; 92 seat->focus = ds_display_first_window(display); 70 93 71 94 *rseat = seat; … … 79 102 void ds_seat_destroy(ds_seat_t *seat) 80 103 { 104 ds_idevcfg_t *idevcfg; 105 106 /* Remove all input device configuration entries pointing to this seat */ 107 idevcfg = ds_seat_first_idevcfg(seat); 108 while (idevcfg != NULL) { 109 ds_idevcfg_destroy(idevcfg); 110 idevcfg = ds_seat_first_idevcfg(seat); 111 } 112 113 /* Remove this seat's focus */ 114 if (seat->focus != NULL) 115 ds_window_post_unfocus_event(seat->focus); 116 81 117 ds_display_remove_seat(seat); 118 119 free(seat->name); 82 120 free(seat); 83 121 } 84 122 123 /** Load seat from SIF node. 124 * 125 * @param display Display 126 * @param snode Seat node from which to load the seat 127 * @param rseat Place to store pointer to the newly loaded seat 128 * 129 * @return EOK on success or an error code 130 */ 131 errno_t ds_seat_load(ds_display_t *display, sif_node_t *snode, 132 ds_seat_t **rseat) 133 { 134 const char *sid; 135 const char *name; 136 char *endptr; 137 unsigned long id; 138 errno_t rc; 139 140 sid = sif_node_get_attr(snode, "id"); 141 if (sid == NULL) 142 return EIO; 143 144 name = sif_node_get_attr(snode, "name"); 145 if (name == NULL) 146 return EIO; 147 148 id = strtoul(sid, &endptr, 10); 149 if (*endptr != '\0') 150 return EIO; 151 152 rc = ds_seat_create(display, name, rseat); 153 if (rc != EOK) 154 return EIO; 155 156 (*rseat)->id = id; 157 return EOK; 158 } 159 160 /** Save seat to SIF node. 161 * 162 * @param seat Seat 163 * @param snode Seat node into which the seat should be saved 164 * 165 * @return EOK on success or an error code 166 */ 167 errno_t ds_seat_save(ds_seat_t *seat, sif_node_t *snode) 168 { 169 char *sid; 170 errno_t rc; 171 int rv; 172 173 rv = asprintf(&sid, "%lu", (unsigned long)seat->id); 174 if (rv < 0) { 175 rc = ENOMEM; 176 return rc; 177 } 178 179 rc = sif_node_set_attr(snode, "id", sid); 180 if (rc != EOK) { 181 free(sid); 182 return rc; 183 } 184 185 free(sid); 186 187 rc = sif_node_set_attr(snode, "name", seat->name); 188 if (rc != EOK) 189 return rc; 190 191 return EOK; 192 } 193 85 194 /** Set seat focus to a window. 86 195 * … … 90 199 void ds_seat_set_focus(ds_seat_t *seat, ds_window_t *wnd) 91 200 { 201 errno_t rc; 202 92 203 if (wnd == seat->focus) { 93 204 /* Focus is not changing */ … … 95 206 } 96 207 208 if (wnd != NULL) { 209 rc = ds_window_unminimize(wnd); 210 if (rc != EOK) 211 return; 212 } 213 97 214 if (seat->focus != NULL) 98 215 ds_window_post_unfocus_event(seat->focus); … … 104 221 ds_window_bring_to_top(wnd); 105 222 } 106 } 107 108 /** Evacuate focus from window. 109 * 110 * If seat's focus is @a wnd, it will be set to a different window. 223 224 /* When focus changes, popup window should be closed */ 225 ds_seat_set_popup(seat, NULL); 226 } 227 228 /** Set seat popup window. 229 * 230 * @param seat Seat 231 * @param wnd Popup window 232 */ 233 void ds_seat_set_popup(ds_seat_t *seat, ds_window_t *wnd) 234 { 235 if (wnd == seat->popup) 236 return; 237 238 if (seat->popup != NULL) { 239 /* Window is no longer the popup window, send close request */ 240 ds_client_post_close_event(seat->popup->client, 241 seat->popup); 242 } 243 244 seat->popup = wnd; 245 } 246 247 /** Evacuate seat references to window. 248 * 249 * If seat's focus is @a wnd, it will be set to NULL. 250 * If seat's popup window is @a wnd, it will be set to NULL. 251 * 252 * @param seat Seat 253 * @param wnd Window to evacuate references from 254 */ 255 void ds_seat_evac_wnd_refs(ds_seat_t *seat, ds_window_t *wnd) 256 { 257 if (seat->focus == wnd) 258 ds_seat_set_focus(seat, NULL); 259 260 if (seat->popup == wnd) 261 ds_seat_set_popup(seat, NULL); 262 } 263 264 /** Unfocus window. 265 * 266 * If seat's focus is @a wnd, it will be set to a different window 267 * that is not minimized, preferably not a system window. 268 * 269 * @param seat Seat 270 * @param wnd Window to remove focus from 271 */ 272 void ds_seat_unfocus_wnd(ds_seat_t *seat, ds_window_t *wnd) 273 { 274 ds_window_t *nwnd; 275 276 if (seat->focus != wnd) 277 return; 278 279 /* Find alternate window that is neither system nor minimized */ 280 nwnd = ds_window_find_prev(wnd, ~(wndf_minimized | wndf_system)); 281 282 if (nwnd == NULL) { 283 /* Find alternate window that is not minimized */ 284 nwnd = ds_window_find_prev(wnd, ~wndf_minimized); 285 } 286 287 ds_seat_set_focus(seat, nwnd); 288 } 289 290 /** Switch focus to another window. 111 291 * 112 292 * @param seat Seat 113 293 * @param wnd Window to evacuate focus from 114 294 */ 115 void ds_seat_ evac_focus(ds_seat_t *seat, ds_window_t *wnd)295 void ds_seat_switch_focus(ds_seat_t *seat) 116 296 { 117 297 ds_window_t *nwnd; 118 298 119 if (seat->focus == wnd) { 120 nwnd = ds_display_next_window(wnd); 121 if (nwnd == NULL) 122 nwnd = ds_display_first_window(wnd->display); 123 if (nwnd == wnd) 124 nwnd = NULL; 125 299 if (seat->focus != NULL) { 300 /* Find alternate window that is not a system window */ 301 nwnd = ds_window_find_next(seat->focus, ~wndf_system); 302 } else { 303 /* Currently no focus. Focus topmost window. */ 304 nwnd = ds_display_first_window(seat->display); 305 } 306 307 /* Only switch focus if there is another window */ 308 if (nwnd != NULL) 126 309 ds_seat_set_focus(seat, nwnd); 127 }128 310 } 129 311 … … 143 325 if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_TAB) { 144 326 /* On Alt-Tab or Shift-Tab, switch focus to next window */ 145 ds_seat_ evac_focus(seat, seat->focus);327 ds_seat_switch_focus(seat); 146 328 return EOK; 147 329 } 148 330 149 dwindow = seat->focus; 331 dwindow = seat->popup; 332 if (dwindow == NULL) 333 dwindow = seat->focus; 334 150 335 if (dwindow == NULL) 151 336 return EOK; … … 307 492 /* Focus window on button press */ 308 493 if (event->type == PTD_PRESS && event->btn_num == 1) { 309 if (wnd != NULL) { 494 if (wnd != NULL && (wnd->flags & wndf_popup) == 0 && 495 (wnd->flags & wndf_nofocus) == 0) { 310 496 ds_seat_set_focus(seat, wnd); 311 497 } 312 498 } 313 499 314 if (event->type == PTD_PRESS || event->type == PTD_RELEASE) { 315 pevent.pos_id = 0; 316 pevent.type = (event->type == PTD_PRESS) ? 317 POS_PRESS : POS_RELEASE; 500 if (event->type == PTD_PRESS || event->type == PTD_RELEASE || 501 event->type == PTD_DCLICK) { 502 pevent.pos_id = event->pos_id; 503 switch (event->type) { 504 case PTD_PRESS: 505 pevent.type = POS_PRESS; 506 break; 507 case PTD_RELEASE: 508 pevent.type = POS_RELEASE; 509 break; 510 case PTD_DCLICK: 511 pevent.type = POS_DCLICK; 512 break; 513 default: 514 assert(false); 515 } 516 318 517 pevent.btn_num = event->btn_num; 319 518 pevent.hpos = seat->pntpos.x; … … 332 531 seat->pntpos = npos; 333 532 334 pevent.pos_id = 0;533 pevent.pos_id = event->pos_id; 335 534 pevent.type = POS_UPDATE; 336 535 pevent.btn_num = 0; … … 360 559 seat->pntpos = npos; 361 560 362 pevent.pos_id = 0;561 pevent.pos_id = event->pos_id; 363 562 pevent.type = POS_UPDATE; 364 563 pevent.btn_num = 0; … … 385 584 errno_t ds_seat_post_pos_event(ds_seat_t *seat, pos_event_t *event) 386 585 { 387 ds_window_t *wnd; 586 ds_window_t *pwindow; 587 ds_window_t *cwindow; 388 588 errno_t rc; 389 589 390 wnd = ds_display_window_by_pos(seat->display, &seat->pntpos); 391 392 if (seat->focus != wnd) { 393 rc = ds_window_post_pos_event(seat->focus, event); 394 if (rc != EOK) 395 return rc; 396 397 /* Only deliver release events to the focused window */ 398 if (event->type == POS_RELEASE) 399 return EOK; 400 } 401 402 if (wnd != NULL) { 590 /* Window under pointer */ 591 pwindow = ds_display_window_by_pos(seat->display, &seat->pntpos); 592 593 /* Current window: popup or focused */ 594 cwindow = seat->popup; 595 if (cwindow == NULL) 596 cwindow = seat->focus; 597 598 /* 599 * Deliver move and release event to current window if different 600 * from pwindow 601 */ 602 if (event->type != POS_PRESS && cwindow != NULL && 603 cwindow != pwindow) { 604 rc = ds_window_post_pos_event(cwindow, event); 605 if (rc != EOK) 606 return rc; 607 } 608 609 if (pwindow != NULL) { 403 610 /* Moving over a window */ 404 ds_seat_set_client_cursor(seat, wnd->cursor);405 406 rc = ds_window_post_pos_event( wnd, event);611 ds_seat_set_client_cursor(seat, pwindow->cursor); 612 613 rc = ds_window_post_pos_event(pwindow, event); 407 614 if (rc != EOK) 408 615 return rc; 409 616 } else { 410 617 /* Not over a window */ 411 ds_seat_set_client_cursor(seat, seat->display->cursor[dcurs_arrow]); 618 ds_seat_set_client_cursor(seat, 619 seat->display->cursor[dcurs_arrow]); 620 } 621 622 /* Click outside popup window */ 623 if (event->type == POS_PRESS && pwindow != seat->popup) { 624 /* Close popup window */ 625 ds_seat_set_popup(seat, NULL); 412 626 } 413 627 … … 428 642 } 429 643 644 /** Add input device configuration entry to seat. 645 * 646 * @param seat Seat 647 * @param idevcfg Input device configuration 648 */ 649 void ds_seat_add_idevcfg(ds_seat_t *seat, ds_idevcfg_t *idevcfg) 650 { 651 assert(idevcfg->seat == NULL); 652 assert(!link_used(&idevcfg->lseatidcfgs)); 653 654 idevcfg->seat = seat; 655 list_append(&idevcfg->lseatidcfgs, &seat->idevcfgs); 656 } 657 658 /** Remove input device configuration entry from seat. 659 * 660 * @param idevcfg Input device configuration entry 661 */ 662 void ds_seat_remove_idevcfg(ds_idevcfg_t *idevcfg) 663 { 664 list_remove(&idevcfg->lseatidcfgs); 665 idevcfg->seat = NULL; 666 } 667 668 /** Get first input device configuration entry in seat. 669 * 670 * @param disp Display 671 * @return First input device configuration entry or @c NULL if there is none 672 */ 673 ds_idevcfg_t *ds_seat_first_idevcfg(ds_seat_t *seat) 674 { 675 link_t *link = list_first(&seat->idevcfgs); 676 677 if (link == NULL) 678 return NULL; 679 680 return list_get_instance(link, ds_idevcfg_t, lseatidcfgs); 681 } 682 683 /** Get next input device configuration entry in seat. 684 * 685 * @param idevcfg Current input device configuration entry 686 * @return Next input device configuration entry or @c NULL if there is none 687 */ 688 ds_idevcfg_t *ds_seat_next_idevcfg(ds_idevcfg_t *idevcfg) 689 { 690 link_t *link = list_next(&idevcfg->lseatidcfgs, &idevcfg->seat->idevcfgs); 691 692 if (link == NULL) 693 return NULL; 694 695 return list_get_instance(link, ds_idevcfg_t, lseatidcfgs); 696 } 697 430 698 /** @} 431 699 */
Note:
See TracChangeset
for help on using the changeset viewer.