Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/compositor/compositor.c

    rfbb2d0d rb8f1a349  
    9090typedef struct {
    9191        link_t link;
    92         atomic_t ref_cnt;
    9392        service_id_t in_dsid;
    9493        service_id_t out_dsid;
     
    139138} viewport_t;
    140139
    141 static desktop_rect_t viewport_bound_rect;
    142140static FIBRIL_MUTEX_INITIALIZE(viewport_list_mtx);
    143141static LIST_INITIALIZE(viewport_list);
    144 
    145 static FIBRIL_MUTEX_INITIALIZE(discovery_mtx);
    146142
    147143/** Input server proxy */
     
    219215
    220216        link_initialize(&win->link);
    221         atomic_set(&win->ref_cnt, 0);
    222217        prodcons_initialize(&win->queue);
    223218        transform_identity(&win->transform);
     
    237232static void window_destroy(window_t *win)
    238233{
    239         if (win && atomic_get(&win->ref_cnt) == 0) {
    240                 while (!list_empty(&win->queue.list)) {
    241                         window_event_t *event = (window_event_t *) list_first(&win->queue.list);
    242                         list_remove(&event->link);
    243                         free(event);
    244                 }
    245 
     234        if (win) {
    246235                if (win->surface) {
    247236                        surface_destroy(win->surface);
     
    321310}
    322311
    323 static void comp_restrict_pointers(void)
    324 {
    325         fibril_mutex_lock(&viewport_list_mtx);
    326 
    327         sysarg_t x_res = coord_origin;
    328         sysarg_t y_res = coord_origin;
    329         sysarg_t w_res = 0;
    330         sysarg_t h_res = 0;
    331 
    332         if (!list_empty(&viewport_list)) {
    333                 viewport_t *vp = (viewport_t *) list_first(&viewport_list);
    334                 x_res = vp->pos.x;
    335                 y_res = vp->pos.y;
    336                 surface_get_resolution(vp->surface, &w_res, &h_res);
    337         }
    338 
    339         list_foreach(viewport_list, link, viewport_t, vp) {
    340                 sysarg_t w_vp, h_vp;
    341                 surface_get_resolution(vp->surface, &w_vp, &h_vp);
    342                 rectangle_union(
    343                     x_res, y_res, w_res, h_res,
    344                     vp->pos.x, vp->pos.y, w_vp, h_vp,
    345                     &x_res, &y_res, &w_res, &h_res);
    346         }
    347 
    348         viewport_bound_rect.x = x_res;
    349         viewport_bound_rect.y = y_res;
    350         viewport_bound_rect.w = w_res;
    351         viewport_bound_rect.h = h_res;
    352 
    353         fibril_mutex_unlock(&viewport_list_mtx);
    354 
    355         fibril_mutex_lock(&pointer_list_mtx);
    356 
    357         list_foreach(pointer_list, link, pointer_t, ptr) {
    358                 ptr->pos.x = ptr->pos.x > viewport_bound_rect.x ? ptr->pos.x : viewport_bound_rect.x;
    359                 ptr->pos.y = ptr->pos.y > viewport_bound_rect.y ? ptr->pos.y : viewport_bound_rect.y;
    360                 ptr->pos.x = ptr->pos.x < viewport_bound_rect.x + viewport_bound_rect.w ?
    361                     ptr->pos.x : viewport_bound_rect.x + viewport_bound_rect.w;
    362                 ptr->pos.y = ptr->pos.y < viewport_bound_rect.y + viewport_bound_rect.h ?
    363                     ptr->pos.y : viewport_bound_rect.y + viewport_bound_rect.h;
    364         }
    365 
    366         fibril_mutex_unlock(&pointer_list_mtx);
    367 }
    368 
    369312static void comp_damage(sysarg_t x_dmg_glob, sysarg_t y_dmg_glob,
    370313    sysarg_t w_dmg_glob, sysarg_t h_dmg_glob)
     
    374317        fibril_mutex_lock(&pointer_list_mtx);
    375318
    376         list_foreach(viewport_list, link, viewport_t, vp) {
     319        list_foreach(viewport_list, link) {
     320
    377321                /* Determine what part of the viewport must be updated. */
     322                viewport_t *vp = list_get_instance(link, viewport_t, link);
    378323                sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
    379324                surface_get_resolution(vp->surface, &w_dmg_vp, &h_dmg_vp);
     
    444389                        }
    445390
    446                         list_foreach(pointer_list, link, pointer_t, ptr) {
     391                        list_foreach(pointer_list, link) {
     392
     393                                pointer_t *ptr = list_get_instance(link, pointer_t, link);
    447394                                if (ptr->ghost.surface) {
    448395
     
    518465                        }
    519466
    520                         list_foreach(pointer_list, link, pointer_t, ptr) {
     467                        list_foreach(pointer_list, link) {
    521468
    522469                                /* Determine what part of the pointer intersects with the
    523470                                 * updated area of the current viewport. */
     471                                pointer_t *ptr = list_get_instance(link, pointer_t, link);
    524472                                sysarg_t x_dmg_ptr, y_dmg_ptr, w_dmg_ptr, h_dmg_ptr;
    525473                                surface_t *sf_ptr = ptr->cursor.states[ptr->state];
     
    564512
    565513        /* Notify visualizers about updated regions. */
    566         list_foreach(viewport_list, link, viewport_t, vp) {
     514        list_foreach(viewport_list, link) {
     515                viewport_t *vp = list_get_instance(link, viewport_t, link);
    567516                sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
    568517                surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
     
    625574
    626575        fibril_mutex_lock(&pointer_list_mtx);
    627         list_foreach(pointer_list, link, pointer_t, pointer) {
     576        list_foreach(pointer_list, link) {
     577                pointer_t *pointer = list_get_instance(link, pointer_t, link);
    628578                if (pointer->id == pos_id) {
    629579                        pointer->grab_flags = pointer->pressed ? grab_flags : GF_EMPTY;
     
    703653{
    704654        fibril_mutex_lock(&window_list_mtx);
    705 
    706         list_foreach(window_list, link, window_t, window) {
     655        window_t *window = NULL;
     656        list_foreach(window_list, link) {
     657                window = list_get_instance(link, window_t, link);
    707658                if (window == target) {
    708659                        prodcons_produce(&window->queue, &event->link);
    709                         fibril_mutex_unlock(&window_list_mtx);
    710                         return;
    711                 }
    712         }
    713 
     660                }
     661        }
     662        if (!window) {
     663                free(event);
     664        }
    714665        fibril_mutex_unlock(&window_list_mtx);
    715         free(event);
    716666}
    717667
     
    743693        if (event_focus && win_focus) {
    744694                comp_post_event_win(event_focus, win_focus);
    745         }
    746 
    747         loc_service_unregister(win->in_dsid);
    748         loc_service_unregister(win->out_dsid);
    749 
    750         /* In case the client was killed, input fibril of the window might be
    751          * still blocked on the condition within comp_window_get_event. */
    752         window_event_t *event_dummy = (window_event_t *) malloc(sizeof(window_event_t));
    753         if (event_dummy) {
    754                 link_initialize(&event_dummy->link);
    755                 prodcons_produce(&win->queue, &event_dummy->link);
    756695        }
    757696
     
    767706        }
    768707
     708        /* Release window resources. */
     709        loc_service_unregister(win->in_dsid);
     710        loc_service_unregister(win->out_dsid);
     711        while (!list_empty(&win->queue.list)) {
     712                list_remove(list_first(&win->queue.list));
     713        }
     714        window_destroy(win);
     715
    769716        comp_damage(x, y, width, height);
    770717
     
    856803        window_t *win = NULL;
    857804        fibril_mutex_lock(&window_list_mtx);
    858         list_foreach(window_list, link, window_t, cur) {
     805        list_foreach(window_list, link) {
     806                window_t *cur = list_get_instance(link, window_t, link);
    859807                if (cur->in_dsid == service_id || cur->out_dsid == service_id) {
    860808                        win = cur;
     
    865813
    866814        if (win) {
    867                 atomic_inc(&win->ref_cnt);
    868815                async_answer_0(iid, EOK);
    869816        } else {
     
    878825
    879826                        if (!IPC_GET_IMETHOD(call)) {
    880                                 async_answer_0(callid, EOK);
    881                                 atomic_dec(&win->ref_cnt);
    882                                 window_destroy(win);
     827                                async_answer_0(callid, EINVAL);
    883828                                return;
    884829                        }
     
    897842
    898843                        if (!IPC_GET_IMETHOD(call)) {
    899                                 comp_window_close(win, callid, &call);
    900                                 atomic_dec(&win->ref_cnt);
    901                                 window_destroy(win);
     844                                async_answer_0(callid, EINVAL);
    902845                                return;
    903846                        }
     
    914857                                break;
    915858                        case WINDOW_CLOSE:
    916                                 /* Postpone the closing until the phone is hung up to cover
    917                                  * the case when the client is killed abruptly. */
    918                                 async_answer_0(callid, EOK);
     859                                comp_window_close(win, callid, &call);
    919860                                break;
    920861                        case WINDOW_CLOSE_REQUEST:
     
    970911        async_answer_0(iid, EOK);
    971912
    972         comp_restrict_pointers();
    973913        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    974914}
     
    999939                /* Close all clients and their windows. */
    1000940                fibril_mutex_lock(&window_list_mtx);
    1001                 list_foreach(window_list, link, window_t, win) {
     941                list_foreach(window_list, link) {
     942                        window_t *win = list_get_instance(link, window_t, link);
    1002943                        window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    1003944                        if (event) {
     
    1015956                fibril_mutex_unlock(&viewport_list_mtx);
    1016957                async_answer_0(iid, EOK);
    1017 
    1018                 comp_restrict_pointers();
    1019                 comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    1020958        }
    1021959}
     
    1025963        viewport_t *vp = NULL;
    1026964        fibril_mutex_lock(&viewport_list_mtx);
    1027         list_foreach(viewport_list, link, viewport_t, cur) {
     965        list_foreach(viewport_list, link) {
     966                viewport_t *cur = list_get_instance(link, viewport_t, link);
    1028967                if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
    1029968                        vp = cur;
     
    14521391        surface_get_resolution(pointer->cursor.states[pointer->state],
    14531392             &cursor_width, &cursor_height);
    1454         if (pointer->pos.x + dx < viewport_bound_rect.x) {
    1455                 dx = -1 * (pointer->pos.x - viewport_bound_rect.x);
    1456         }
    1457         if (pointer->pos.y + dy < viewport_bound_rect.y) {
    1458                 dy = -1 * (pointer->pos.y - viewport_bound_rect.y);
    1459         }
    1460         if (pointer->pos.x + dx > viewport_bound_rect.x + viewport_bound_rect.w) {
    1461                 dx = (viewport_bound_rect.x + viewport_bound_rect.w - pointer->pos.x);
    1462         }
    1463         if (pointer->pos.y + dy > viewport_bound_rect.y + viewport_bound_rect.h) {
    1464                 dy = (viewport_bound_rect.y + viewport_bound_rect.h - pointer->pos.y);
    1465         }
    14661393        pointer->pos.x += dx;
    14671394        pointer->pos.y += dy;
     
    15611488
    15621489        /* Determine the window which the mouse click belongs to. */
    1563         list_foreach(window_list, link, window_t, cw) {
    1564                 win = cw;
     1490        list_foreach(window_list, link) {
     1491                win = list_get_instance(link, window_t, link);
    15651492                if (win->surface) {
    15661493                        surface_get_resolution(win->surface, &width, &height);
     
    19831910                        fibril_mutex_unlock(&viewport_list_mtx);
    19841911
    1985                         comp_restrict_pointers();
    19861912                        comp_damage(x, y, width, height);
    19871913                } else {
     
    21162042}
    21172043
    2118 static int discover_viewports(void)
    2119 {
     2044static int compositor_srv_init(char *input_svc, char *name)
     2045{
     2046        /* Coordinates of the central pixel. */
     2047        coord_origin = UINT32_MAX / 4;
     2048       
     2049        /* Color of the viewport background. Must be opaque. */
     2050        bg_color = PIXEL(255, 75, 70, 75);
     2051       
     2052        /* Register compositor server. */
     2053        async_set_client_connection(client_connection);
     2054        int rc = loc_server_register(NAME);
     2055        if (rc != EOK) {
     2056                printf("%s: Unable to register server (%s)\n", NAME, str_error(rc));
     2057                return -1;
     2058        }
     2059       
     2060        /* Register interrupt handler to switch back from kconsole. */
     2061        async_set_interrupt_received(interrupt_received);
     2062        rc = event_subscribe(EVENT_KCONSOLE, 0);
     2063        if (rc != EOK) {
     2064                printf("%s: Failed to register kconsole notifications (%s)\n",
     2065                    NAME, str_error(rc));
     2066        }
     2067       
     2068        server_name = name;
     2069       
     2070        char svc[LOC_NAME_MAXLEN + 1];
     2071        snprintf(svc, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, server_name);
     2072       
     2073        service_id_t service_id;
     2074        rc = loc_service_register(svc, &service_id);
     2075        if (rc != EOK) {
     2076                printf("%s: Unable to register service %s\n", NAME, svc);
     2077                return rc;
     2078        }
     2079       
     2080        /* Prepare window registrator (entrypoint for clients). */
     2081        char winreg[LOC_NAME_MAXLEN + 1];
     2082        snprintf(winreg, LOC_NAME_MAXLEN, "%s%s/winreg", NAMESPACE, server_name);
     2083        if (loc_service_register(winreg, &winreg_id) != EOK) {
     2084                printf("%s: Unable to register service %s\n", NAME, winreg);
     2085                return -1;
     2086        }
     2087
     2088        /* Establish input bidirectional connection. */
     2089        rc = input_connect(input_svc);
     2090        if (rc != EOK)
     2091                return rc;
     2092
    21202093        /* Create viewports and connect them to visualizers. */
    21212094        category_id_t cat_id;
    2122         int rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
     2095        rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
    21232096        if (rc != EOK) {
    2124                 printf("%s: Failed to get visualizer category.\n", NAME);
     2097                input_disconnect();
    21252098                return -1;
    21262099        }
     
    21302103        rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
    21312104        if (rc != EOK || svcs_cnt == 0) {
    2132                 printf("%s: Failed to get visualizer category services.\n", NAME);
     2105                input_disconnect();
    21332106                return -1;
    21342107        }
    2135 
    2136         fibril_mutex_lock(&viewport_list_mtx); 
     2108       
    21372109        for (size_t i = 0; i < svcs_cnt; ++i) {
    2138                 bool exists = false;
    2139                 list_foreach(viewport_list, link, viewport_t, vp) {
    2140                         if (vp->dsid == svcs[i]) {
    2141                                 exists = true;
    2142                                 break;
    2143                         }
    2144                 }
    2145                
    2146                 if (exists)
    2147                         continue;
    2148                
    21492110                char *svc_name;
    21502111                rc = loc_service_get_name(svcs[i], &svc_name);
     
    21562117                }
    21572118        }
    2158         fibril_mutex_unlock(&viewport_list_mtx);
    2159        
    2160         /* TODO damage only newly added viewports */
    2161         comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    2162         return EOK;
    2163 }
    2164 
    2165 static void category_change_cb(void)
    2166 {
    2167         fibril_mutex_lock(&discovery_mtx);
    2168         discover_viewports();
    2169         fibril_mutex_unlock(&discovery_mtx);
    2170 }
    2171 
    2172 static int compositor_srv_init(char *input_svc, char *name)
    2173 {
    2174         /* Coordinates of the central pixel. */
    2175         coord_origin = UINT32_MAX / 4;
    2176        
    2177         /* Color of the viewport background. Must be opaque. */
    2178         bg_color = PIXEL(255, 69, 51, 103);
    2179        
    2180         /* Register compositor server. */
    2181         async_set_client_connection(client_connection);
    2182         int rc = loc_server_register(NAME);
    2183         if (rc != EOK) {
    2184                 printf("%s: Unable to register server (%s)\n", NAME, str_error(rc));
    2185                 return -1;
    2186         }
    2187        
    2188         /* Register interrupt handler to switch back from kconsole. */
    2189         async_set_interrupt_received(interrupt_received);
    2190         rc = event_subscribe(EVENT_KCONSOLE, 0);
    2191         if (rc != EOK) {
    2192                 printf("%s: Failed to register kconsole notifications (%s)\n",
    2193                     NAME, str_error(rc));
    2194         }
    2195        
    2196         server_name = name;
    2197        
    2198         char svc[LOC_NAME_MAXLEN + 1];
    2199         snprintf(svc, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, server_name);
    2200        
    2201         service_id_t service_id;
    2202         rc = loc_service_register(svc, &service_id);
    2203         if (rc != EOK) {
    2204                 printf("%s: Unable to register service %s\n", NAME, svc);
    2205                 return rc;
    2206         }
    2207        
    2208         /* Prepare window registrator (entrypoint for clients). */
    2209         char winreg[LOC_NAME_MAXLEN + 1];
    2210         snprintf(winreg, LOC_NAME_MAXLEN, "%s%s/winreg", NAMESPACE, server_name);
    2211         if (loc_service_register(winreg, &winreg_id) != EOK) {
    2212                 printf("%s: Unable to register service %s\n", NAME, winreg);
    2213                 return -1;
    2214         }
    2215 
    2216         /* Establish input bidirectional connection. */
    2217         rc = input_connect(input_svc);
    2218         if (rc != EOK) {
    2219                 printf("%s: Failed to connect to input service.\n", NAME);
    2220                 return rc;
    2221         }
    2222 
    2223         rc = loc_register_cat_change_cb(category_change_cb);
    2224         if (rc != EOK) {
    2225                 printf("%s: Failed to register category change callback\n", NAME);
    2226                 input_disconnect();
    2227                 return rc;
    2228         }       
    2229 
    2230         rc = discover_viewports();
    2231         if (rc != EOK) {
    2232                 input_disconnect();
    2233                 return rc;
    2234         }
    22352119       
    22362120        if (list_empty(&viewport_list)) {
    2237                 printf("%s: Failed to get viewports.\n", NAME);
    22382121                input_disconnect();
    22392122                return -1;
    22402123        }
    2241 
    2242         comp_restrict_pointers();
     2124       
    22432125        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    2244        
    22452126       
    22462127        return EOK;
Note: See TracChangeset for help on using the changeset viewer.