Ignore:
File:
1 edited

Legend:

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

    r00ddb40 r8e4a408  
    5656#include <loc.h>
    5757
     58#include <event.h>
    5859#include <io/keycode.h>
    5960#include <io/mode.h>
    6061#include <io/visualizer.h>
    6162#include <io/window.h>
    62 #include <io/console.h>
    6363
    6464#include <transform.h>
     
    8484static sysarg_t coord_origin;
    8585static pixel_t bg_color;
    86 static filter_t filter = filter_bilinear;
    87 static unsigned int filter_index = 1;
    8886
    8987typedef struct {
     
    146144/** Input server proxy */
    147145static input_t *input;
    148 static bool active = false;
    149 
    150 static int comp_active(input_t *);
    151 static int comp_deactive(input_t *);
     146
    152147static int comp_key_press(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
    153148static int comp_mouse_move(input_t *, int, int);
     
    156151
    157152static input_ev_ops_t input_ev_ops = {
    158         .active = comp_active,
    159         .deactive = comp_deactive,
    160153        .key = comp_key_press,
    161154        .move = comp_mouse_move,
     
    163156        .button = comp_mouse_button
    164157};
     158
     159static void input_disconnect(void);
    165160
    166161static pointer_t *input_pointer(input_t *input)
     
    235230static void window_destroy(window_t *win)
    236231{
    237         if ((win) && (atomic_get(&win->ref_cnt) == 0)) {
     232        if (win && atomic_get(&win->ref_cnt) == 0) {
    238233                while (!list_empty(&win->queue.list)) {
    239234                        window_event_t *event = (window_event_t *) list_first(&win->queue.list);
     
    241236                        free(event);
    242237                }
    243                
    244                 if (win->surface)
     238
     239                if (win->surface) {
    245240                        surface_destroy(win->surface);
    246                
     241                }
    247242                free(win);
    248243        }
     
    256251        transform_invert(&win_trans);
    257252        transform_apply_affine(&win_trans, &x, &y);
    258        
    259         /*
    260          * Since client coordinate origin is (0, 0), it is necessary to check
     253
     254        /* Since client coordinate origin is (0, 0), it is necessary to check
    261255         * coordinates to avoid underflow. Moreover, it is convenient to also
    262256         * check against provided upper limits to determine whether the converted
    263          * coordinates are within the client window.
    264          */
    265         if ((x < 0) || (y < 0))
     257         * coordinates are within the client window.  */
     258        if (x < 0 || y < 0) {
    266259                return false;
    267        
    268         (*x_out) = (sysarg_t) (x + 0.5);
    269         (*y_out) = (sysarg_t) (y + 0.5);
    270        
    271         if (((*x_out) >= x_lim) || ((*y_out) >= y_lim))
    272                 return false;
    273        
    274         return true;
     260        } else {
     261                (*x_out) = (sysarg_t) (x + 0.5);
     262                (*y_out) = (sysarg_t) (y + 0.5);
     263
     264                if ((*x_out) >= x_lim || (*y_out) >= y_lim) {
     265                        return false;
     266                } else {
     267                        return true;
     268                }
     269        }
    275270}
    276271
     
    282277        transform_apply_affine(&win_trans, &x, &y);
    283278       
    284         /*
    285          * It is assumed that compositor coordinate origin is chosen in such way,
    286          * that underflow/overflow here would be unlikely.
    287          */
     279        /* It is assumed that compositor coordinate origin is chosen in such way,
     280         * that underflow/overflow here would be unlikely. */
    288281        (*x_out) = (sysarg_t) (x + 0.5);
    289282        (*y_out) = (sysarg_t) (y + 0.5);
     
    410403
    411404                        source_init(&source);
    412                         source_set_filter(&source, filter);
     405                        source_set_filter(&source, filter_nearest);
    413406                        drawctx_init(&context, vp->surface);
    414407                        drawctx_set_compose(&context, compose_over);
     
    443436                                        transform_translate(&transform, -pos.x, -pos.y);
    444437
    445                                         source_set_transform(&source, transform);
    446                                         source_set_texture(&source, win->surface,
    447                                             PIXELMAP_EXTEND_TRANSPARENT_SIDES);
     438                                        source_set_transform(&source, transform);                               
     439                                        source_set_texture(&source, win->surface, false);
    448440                                        source_set_alpha(&source, PIXEL(win->opacity, 0, 0, 0));
    449441
     
    573565
    574566        /* Notify visualizers about updated regions. */
    575         if (active) {
    576                 list_foreach(viewport_list, link, viewport_t, vp) {
    577                         sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
    578                         surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
    579                         surface_reset_damaged_region(vp->surface);
    580                         visualizer_update_damaged_region(vp->sess,
    581                             x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp, 0, 0);
    582                 }
    583         }
    584        
     567        list_foreach(viewport_list, link, viewport_t, vp) {
     568                sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
     569                surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
     570                surface_reset_damaged_region(vp->surface);
     571                visualizer_update_damaged_region(
     572                    vp->sess, x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp, 0, 0);
     573        }
     574
    585575        fibril_mutex_unlock(&viewport_list_mtx);
    586576}
     
    598588                return;
    599589        }
    600        
    601590        int rc = async_data_read_finalize(callid, event, len);
    602591        if (rc != EOK) {
     
    605594                return;
    606595        }
    607        
    608596        async_answer_0(iid, EOK);
     597       
    609598        free(event);
    610599}
     
    617606        double height = IPC_GET_ARG4(*icall);
    618607
    619         if ((width == 0) || (height == 0)) {
     608        if (width == 0 || height == 0) {
    620609                comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    621610        } else {
     
    866855
    867856        comp_damage(x, y, width, height);
     857
    868858        async_answer_0(iid, EOK);
    869859}
     
    871861static void comp_window_close_request(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
    872862{
    873         window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     863    window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    874864        if (event == NULL) {
    875865                async_answer_0(iid, ENOMEM);
     
    10111001                                break;
    10121002                        case WINDOW_CLOSE:
    1013                                 /*
    1014                                  * Postpone the closing until the phone is hung up to cover
    1015                                  * the case when the client is killed abruptly.
    1016                                  */
     1003                                /* Postpone the closing until the phone is hung up to cover
     1004                                 * the case when the client is killed abruptly. */
    10171005                                async_answer_0(callid, EOK);
    10181006                                break;
     
    10291017static void comp_mode_change(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
    10301018{
     1019        int rc;
    10311020        sysarg_t mode_idx = IPC_GET_ARG2(*icall);
    10321021        fibril_mutex_lock(&viewport_list_mtx);
     
    10341023        /* Retrieve the mode that shall be set. */
    10351024        vslmode_t new_mode;
    1036         int rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
     1025        rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
    10371026        if (rc != EOK) {
    10381027                fibril_mutex_unlock(&viewport_list_mtx);
     
    10521041        /* Try to set the mode and share out the surface. */
    10531042        rc = visualizer_set_mode(vp->sess,
    1054             new_mode.index, new_mode.version, surface_direct_access(new_surface));
     1043                new_mode.index, new_mode.version, surface_direct_access(new_surface));
    10551044        if (rc != EOK) {
    10561045                surface_destroy(new_surface);
     
    10821071}
    10831072
    1084 #if 0
    1085 static void comp_shutdown(void)
    1086 {
    1087         loc_service_unregister(winreg_id);
    1088         input_disconnect();
    1089        
    1090         /* Close all clients and their windows. */
    1091         fibril_mutex_lock(&window_list_mtx);
    1092         list_foreach(window_list, link, window_t, win) {
    1093                 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    1094                 if (event) {
    1095                         link_initialize(&event->link);
    1096                         event->type = WINDOW_CLOSE;
    1097                         prodcons_produce(&win->queue, &event->link);
    1098                 }
    1099         }
    1100         fibril_mutex_unlock(&window_list_mtx);
    1101        
    1102         async_answer_0(iid, EOK);
    1103        
    1104         /* All fibrils of the compositor will terminate soon. */
    1105 }
    1106 #endif
    1107 
    11081073static void comp_visualizer_disconnect(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
    11091074{
    11101075        /* Release viewport resources. */
    11111076        fibril_mutex_lock(&viewport_list_mtx);
    1112        
    11131077        list_remove(&vp->link);
    11141078        viewport_destroy(vp);
    1115        
    1116         fibril_mutex_unlock(&viewport_list_mtx);
    1117        
    1118         async_answer_0(iid, EOK);
    1119        
    1120         comp_restrict_pointers();
    1121         comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     1079
     1080        /* Terminate compositor if there are no more viewports. */
     1081        if (list_empty(&viewport_list)) {
     1082                fibril_mutex_unlock(&viewport_list_mtx);
     1083                loc_service_unregister(winreg_id);
     1084                input_disconnect();
     1085
     1086                /* Close all clients and their windows. */
     1087                fibril_mutex_lock(&window_list_mtx);
     1088                list_foreach(window_list, link, window_t, win) {
     1089                        window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     1090                        if (event) {
     1091                                link_initialize(&event->link);
     1092                                event->type = WINDOW_CLOSE;
     1093                                prodcons_produce(&win->queue, &event->link);
     1094                        }
     1095                }
     1096                fibril_mutex_unlock(&window_list_mtx);
     1097
     1098                async_answer_0(iid, EOK);
     1099
     1100                /* All fibrils of the compositor will terminate soon. */
     1101        } else {
     1102                fibril_mutex_unlock(&viewport_list_mtx);
     1103                async_answer_0(iid, EOK);
     1104
     1105                comp_restrict_pointers();
     1106                comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     1107        }
    11221108}
    11231109
     
    11341120        fibril_mutex_unlock(&viewport_list_mtx);
    11351121
    1136         if (!vp)
     1122        if (!vp) {
    11371123                return;
     1124        }
    11381125
    11391126        /* Ignore parameters, the connection is already opened. */
     
    12361223        /* Try to set the mode and share out the surface. */
    12371224        rc = visualizer_set_mode(vp->sess,
    1238             vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
     1225                vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
    12391226        if (rc != EOK) {
    12401227                printf("%s: Unable to set mode (%s)\n", NAME, str_error(rc));
     
    12461233        if (claimed)
    12471234                visualizer_yield(vp->sess);
    1248        
    12491235        if (vp->sess != NULL)
    12501236                async_hangup(vp->sess);
    1251        
    12521237        free(vp);
    12531238        free(vsl_name);
     
    17901775}
    17911776
    1792 static int comp_active(input_t *input)
    1793 {
    1794         active = true;
    1795         comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
    1796        
    1797         return EOK;
    1798 }
    1799 
    1800 static int comp_deactive(input_t *input)
    1801 {
    1802         active = false;
    1803         return EOK;
    1804 }
    1805 
    18061777static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
    18071778    keymod_t mods, wchar_t c)
     
    18211792            key == KC_O || key == KC_P);
    18221793        bool kconsole_switch = (mods & KM_ALT) && (key == KC_M);
    1823         bool filter_switch = (mods & KM_ALT) && (key == KC_Y);
    1824 
    1825         bool key_filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
     1794
     1795        bool filter = (type == KEY_RELEASE) && (win_transform || win_resize ||
    18261796            win_opacity || win_close || win_switch || viewport_move ||
    1827             viewport_change || kconsole_switch || filter_switch);
    1828 
    1829         if (key_filter) {
     1797            viewport_change || kconsole_switch);
     1798
     1799        if (filter) {
    18301800                /* no-op */
    18311801        } else if (win_transform) {
     
    20932063                fibril_mutex_unlock(&viewport_list_mtx);
    20942064        } else if (kconsole_switch) {
    2095                 if (console_kcon())
    2096                         active = false;
    2097         } else if (filter_switch) {
    2098                 filter_index++;
    2099                 if (filter_index > 1)
    2100                         filter_index = 0;
    2101                 if (filter_index == 0) {
    2102                         filter = filter_nearest;
    2103                 }
    2104                 else {
    2105                         filter = filter_bilinear;
    2106                 }
    2107                 comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2065                __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
    21082066        } else {
    21092067                window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     
    21742132}
    21752133
    2176 static void discover_viewports(void)
    2177 {
    2178         fibril_mutex_lock(&discovery_mtx);
    2179        
     2134static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
     2135{
     2136        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2137}
     2138
     2139static int discover_viewports(void)
     2140{
    21802141        /* Create viewports and connect them to visualizers. */
    21812142        category_id_t cat_id;
    21822143        int rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
    2183         if (rc != EOK)
    2184                 goto ret;
     2144        if (rc != EOK) {
     2145                printf("%s: Failed to get visualizer category.\n", NAME);
     2146                return -1;
     2147        }
    21852148       
    21862149        service_id_t *svcs;
    21872150        size_t svcs_cnt = 0;
    21882151        rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
    2189         if (rc != EOK)
    2190                 goto ret;
    2191        
    2192         fibril_mutex_lock(&viewport_list_mtx);
     2152        if (rc != EOK || svcs_cnt == 0) {
     2153                printf("%s: Failed to get visualizer category services.\n", NAME);
     2154                return -1;
     2155        }
     2156
     2157        fibril_mutex_lock(&viewport_list_mtx); 
    21932158        for (size_t i = 0; i < svcs_cnt; ++i) {
    21942159                bool exists = false;
     
    22092174        fibril_mutex_unlock(&viewport_list_mtx);
    22102175       
    2211         if (!list_empty(&viewport_list))
    2212                 input_activate(input);
    2213        
    2214 ret:
     2176        /* TODO damage only newly added viewports */
     2177        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2178        return EOK;
     2179}
     2180
     2181static void category_change_cb(void)
     2182{
     2183        fibril_mutex_lock(&discovery_mtx);
     2184        discover_viewports();
    22152185        fibril_mutex_unlock(&discovery_mtx);
    2216 }
    2217 
    2218 static void category_change_cb(void)
    2219 {
    2220         discover_viewports();
    22212186}
    22222187
     
    22312196        /* Register compositor server. */
    22322197        async_set_client_connection(client_connection);
    2233        
    22342198        int rc = loc_server_register(NAME);
    22352199        if (rc != EOK) {
    22362200                printf("%s: Unable to register server (%s)\n", NAME, str_error(rc));
    22372201                return -1;
     2202        }
     2203       
     2204        /* Register interrupt handler to switch back from kconsole. */
     2205        async_set_interrupt_received(interrupt_received);
     2206        rc = event_subscribe(EVENT_KCONSOLE, 0);
     2207        if (rc != EOK) {
     2208                printf("%s: Failed to register kconsole notifications (%s)\n",
     2209                    NAME, str_error(rc));
    22382210        }
    22392211       
     
    22572229                return -1;
    22582230        }
    2259        
     2231
    22602232        /* Establish input bidirectional connection. */
    22612233        rc = input_connect(input_svc);
     
    22642236                return rc;
    22652237        }
    2266        
     2238
    22672239        rc = loc_register_cat_change_cb(category_change_cb);
    22682240        if (rc != EOK) {
     
    22702242                input_disconnect();
    22712243                return rc;
    2272         }
    2273        
    2274         discover_viewports();
    2275        
     2244        }       
     2245
     2246        rc = discover_viewports();
     2247        if (rc != EOK) {
     2248                input_disconnect();
     2249                return rc;
     2250        }
     2251       
     2252        if (list_empty(&viewport_list)) {
     2253                printf("%s: Failed to get viewports.\n", NAME);
     2254                input_disconnect();
     2255                return -1;
     2256        }
     2257
    22762258        comp_restrict_pointers();
    22772259        comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
     2260       
    22782261       
    22792262        return EOK;
Note: See TracChangeset for help on using the changeset viewer.