Ignore:
Timestamp:
2013-09-29T06:56:33Z (12 years ago)
Author:
Beniamino Galvani <b.galvani@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a9bd960d
Parents:
3deb0155 (diff), 13be2583 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    r3deb0155 rdd0c8a0  
    9090typedef struct {
    9191        link_t link;
     92        atomic_t ref_cnt;
    9293        service_id_t in_dsid;
    9394        service_id_t out_dsid;
     
    138139} viewport_t;
    139140
     141static desktop_rect_t viewport_bound_rect;
    140142static FIBRIL_MUTEX_INITIALIZE(viewport_list_mtx);
    141143static LIST_INITIALIZE(viewport_list);
     144
     145static FIBRIL_MUTEX_INITIALIZE(discovery_mtx);
    142146
    143147/** Input server proxy */
     
    215219
    216220        link_initialize(&win->link);
     221        atomic_set(&win->ref_cnt, 0);
    217222        prodcons_initialize(&win->queue);
    218223        transform_identity(&win->transform);
     
    232237static void window_destroy(window_t *win)
    233238{
    234         if (win) {
     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
    235246                if (win->surface) {
    236247                        surface_destroy(win->surface);
     
    310321}
    311322
     323static 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
    312369static void comp_damage(sysarg_t x_dmg_glob, sysarg_t y_dmg_glob,
    313370    sysarg_t w_dmg_glob, sysarg_t h_dmg_glob)
     
    317374        fibril_mutex_lock(&pointer_list_mtx);
    318375
    319         list_foreach(viewport_list, link) {
    320 
     376        list_foreach(viewport_list, link, viewport_t, vp) {
    321377                /* Determine what part of the viewport must be updated. */
    322                 viewport_t *vp = list_get_instance(link, viewport_t, link);
    323378                sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
    324379                surface_get_resolution(vp->surface, &w_dmg_vp, &h_dmg_vp);
     
    389444                        }
    390445
    391                         list_foreach(pointer_list, link) {
    392 
    393                                 pointer_t *ptr = list_get_instance(link, pointer_t, link);
     446                        list_foreach(pointer_list, link, pointer_t, ptr) {
    394447                                if (ptr->ghost.surface) {
    395448
     
    465518                        }
    466519
    467                         list_foreach(pointer_list, link) {
     520                        list_foreach(pointer_list, link, pointer_t, ptr) {
    468521
    469522                                /* Determine what part of the pointer intersects with the
    470523                                 * updated area of the current viewport. */
    471                                 pointer_t *ptr = list_get_instance(link, pointer_t, link);
    472524                                sysarg_t x_dmg_ptr, y_dmg_ptr, w_dmg_ptr, h_dmg_ptr;
    473525                                surface_t *sf_ptr = ptr->cursor.states[ptr->state];
     
    512564
    513565        /* Notify visualizers about updated regions. */
    514         list_foreach(viewport_list, link) {
    515                 viewport_t *vp = list_get_instance(link, viewport_t, link);
     566        list_foreach(viewport_list, link, viewport_t, vp) {
    516567                sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
    517568                surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
     
    574625
    575626        fibril_mutex_lock(&pointer_list_mtx);
    576         list_foreach(pointer_list, link) {
    577                 pointer_t *pointer = list_get_instance(link, pointer_t, link);
     627        list_foreach(pointer_list, link, pointer_t, pointer) {
    578628                if (pointer->id == pos_id) {
    579629                        pointer->grab_flags = pointer->pressed ? grab_flags : GF_EMPTY;
     
    653703{
    654704        fibril_mutex_lock(&window_list_mtx);
    655         window_t *window = NULL;
    656         list_foreach(window_list, link) {
    657                 window = list_get_instance(link, window_t, link);
     705
     706        list_foreach(window_list, link, window_t, window) {
    658707                if (window == target) {
    659708                        prodcons_produce(&window->queue, &event->link);
    660                 }
    661         }
    662         if (!window) {
    663                 free(event);
    664         }
     709                        fibril_mutex_unlock(&window_list_mtx);
     710                        return;
     711                }
     712        }
     713
    665714        fibril_mutex_unlock(&window_list_mtx);
     715        free(event);
    666716}
    667717
     
    693743        if (event_focus && win_focus) {
    694744                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);
    695756        }
    696757
     
    706767        }
    707768
    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 
    716769        comp_damage(x, y, width, height);
    717770
     
    803856        window_t *win = NULL;
    804857        fibril_mutex_lock(&window_list_mtx);
    805         list_foreach(window_list, link) {
    806                 window_t *cur = list_get_instance(link, window_t, link);
     858        list_foreach(window_list, link, window_t, cur) {
    807859                if (cur->in_dsid == service_id || cur->out_dsid == service_id) {
    808860                        win = cur;
     
    813865
    814866        if (win) {
     867                atomic_inc(&win->ref_cnt);
    815868                async_answer_0(iid, EOK);
    816869        } else {
     
    825878
    826879                        if (!IPC_GET_IMETHOD(call)) {
    827                                 async_answer_0(callid, EINVAL);
     880                                async_answer_0(callid, EOK);
     881                                atomic_dec(&win->ref_cnt);
     882                                window_destroy(win);
    828883                                return;
    829884                        }
     
    842897
    843898                        if (!IPC_GET_IMETHOD(call)) {
    844                                 async_answer_0(callid, EINVAL);
     899                                comp_window_close(win, callid, &call);
     900                                atomic_dec(&win->ref_cnt);
     901                                window_destroy(win);
    845902                                return;
    846903                        }
     
    857914                                break;
    858915                        case WINDOW_CLOSE:
    859                                 comp_window_close(win, callid, &call);
     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);
    860919                                break;
    861920                        case WINDOW_CLOSE_REQUEST:
     
    911970        async_answer_0(iid, EOK);
    912971
     972        comp_restrict_pointers();
    913973        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    914974}
     
    939999                /* Close all clients and their windows. */
    9401000                fibril_mutex_lock(&window_list_mtx);
    941                 list_foreach(window_list, link) {
    942                         window_t *win = list_get_instance(link, window_t, link);
     1001                list_foreach(window_list, link, window_t, win) {
    9431002                        window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    9441003                        if (event) {
     
    9561015                fibril_mutex_unlock(&viewport_list_mtx);
    9571016                async_answer_0(iid, EOK);
     1017
     1018                comp_restrict_pointers();
     1019                comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    9581020        }
    9591021}
     
    9631025        viewport_t *vp = NULL;
    9641026        fibril_mutex_lock(&viewport_list_mtx);
    965         list_foreach(viewport_list, link) {
    966                 viewport_t *cur = list_get_instance(link, viewport_t, link);
     1027        list_foreach(viewport_list, link, viewport_t, cur) {
    9671028                if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
    9681029                        vp = cur;
     
    13911452        surface_get_resolution(pointer->cursor.states[pointer->state],
    13921453             &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        }
    13931466        pointer->pos.x += dx;
    13941467        pointer->pos.y += dy;
     
    14881561
    14891562        /* Determine the window which the mouse click belongs to. */
    1490         list_foreach(window_list, link) {
    1491                 win = list_get_instance(link, window_t, link);
     1563        list_foreach(window_list, link, window_t, cw) {
     1564                win = cw;
    14921565                if (win->surface) {
    14931566                        surface_get_resolution(win->surface, &width, &height);
     
    19101983                        fibril_mutex_unlock(&viewport_list_mtx);
    19111984
     1985                        comp_restrict_pointers();
    19121986                        comp_damage(x, y, width, height);
    19131987                } else {
     
    20422116}
    20432117
     2118static int discover_viewports(void)
     2119{
     2120        /* Create viewports and connect them to visualizers. */
     2121        category_id_t cat_id;
     2122        int rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
     2123        if (rc != EOK) {
     2124                printf("%s: Failed to get visualizer category.\n", NAME);
     2125                return -1;
     2126        }
     2127       
     2128        service_id_t *svcs;
     2129        size_t svcs_cnt = 0;
     2130        rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
     2131        if (rc != EOK || svcs_cnt == 0) {
     2132                printf("%s: Failed to get visualizer category services.\n", NAME);
     2133                return -1;
     2134        }
     2135
     2136        fibril_mutex_lock(&viewport_list_mtx); 
     2137        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               
     2149                char *svc_name;
     2150                rc = loc_service_get_name(svcs[i], &svc_name);
     2151                if (rc == EOK) {
     2152                        viewport_t *vp = viewport_create(svc_name);
     2153                        if (vp != NULL) {
     2154                                list_append(&vp->link, &viewport_list);
     2155                        }
     2156                }
     2157        }
     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
     2165static void category_change_cb(void)
     2166{
     2167        fibril_mutex_lock(&discovery_mtx);
     2168        discover_viewports();
     2169        fibril_mutex_unlock(&discovery_mtx);
     2170}
     2171
    20442172static int compositor_srv_init(char *input_svc, char *name)
    20452173{
     
    20482176       
    20492177        /* Color of the viewport background. Must be opaque. */
    2050         bg_color = PIXEL(255, 75, 70, 75);
     2178        bg_color = PIXEL(255, 69, 51, 103);
    20512179       
    20522180        /* Register compositor server. */
     
    20882216        /* Establish input bidirectional connection. */
    20892217        rc = input_connect(input_svc);
    2090         if (rc != EOK)
     2218        if (rc != EOK) {
     2219                printf("%s: Failed to connect to input service.\n", NAME);
    20912220                return rc;
    2092 
    2093         /* Create viewports and connect them to visualizers. */
    2094         category_id_t cat_id;
    2095         rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
     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();
    20962231        if (rc != EOK) {
    20972232                input_disconnect();
    2098                 return -1;
    2099         }
    2100        
    2101         service_id_t *svcs;
    2102         size_t svcs_cnt = 0;
    2103         rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
    2104         if (rc != EOK || svcs_cnt == 0) {
     2233                return rc;
     2234        }
     2235       
     2236        if (list_empty(&viewport_list)) {
     2237                printf("%s: Failed to get viewports.\n", NAME);
    21052238                input_disconnect();
    21062239                return -1;
    21072240        }
    2108        
    2109         for (size_t i = 0; i < svcs_cnt; ++i) {
    2110                 char *svc_name;
    2111                 rc = loc_service_get_name(svcs[i], &svc_name);
    2112                 if (rc == EOK) {
    2113                         viewport_t *vp = viewport_create(svc_name);
    2114                         if (vp != NULL) {
    2115                                 list_append(&vp->link, &viewport_list);
    2116                         }
    2117                 }
    2118         }
    2119        
    2120         if (list_empty(&viewport_list)) {
    2121                 input_disconnect();
    2122                 return -1;
    2123         }
    2124        
     2241
     2242        comp_restrict_pointers();
    21252243        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2244       
    21262245       
    21272246        return EOK;
Note: See TracChangeset for help on using the changeset viewer.