Ignore:
File:
1 edited

Legend:

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

    r6d5e378 rd17a4a9  
    4949#include <adt/prodcons.h>
    5050#include <adt/list.h>
     51#include <io/input.h>
    5152#include <ipc/graph.h>
    52 #include <ipc/input.h>
    5353#include <ipc/window.h>
    5454
     
    9292        sysarg_t id;
    9393        uint8_t state;
    94         sysarg_t hpos;
    95         sysarg_t vpos;
     94        desktop_point_t pos;
    9695        sysarg_t btn_num;
    97         sysarg_t btn_hpos;
    98         sysarg_t btn_vpos;
    99         int accum_dx;
    100         int accum_dy;
     96        desktop_point_t btn_pos;
     97        desktop_vector_t accum;
    10198        sysarg_t grab_flags;
    10299        bool pressed;
     
    135132        vslmode_t mode;
    136133        async_sess_t *sess;
    137         sysarg_t hpos;
    138         sysarg_t vpos;
     134        desktop_point_t pos;
    139135        surface_t *surface;
    140136} viewport_t;
     
    143139static LIST_INITIALIZE(viewport_list);
    144140
    145 static async_sess_t *input_sess;
     141/** Input server proxy */
     142static input_t *input;
     143
     144static int comp_key_press(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
     145static int comp_mouse_move(input_t *, int, int);
     146static int comp_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
     147static int comp_mouse_button(input_t *, int, int);
     148
     149static input_ev_ops_t input_ev_ops = {
     150        .key = comp_key_press,
     151        .move = comp_mouse_move,
     152        .abs_move = comp_abs_move,
     153        .button = comp_mouse_button
     154};
     155
     156static void input_disconnect(void);
     157
     158
     159static pointer_t *input_pointer(input_t *input)
     160{
     161        return input->user;
     162}
    146163
    147164static pointer_t *pointer_create()
     
    153170
    154171        link_initialize(&p->link);
    155         p->hpos = coord_origin;
    156         p->vpos = coord_origin;
     172        p->pos.x = coord_origin;
     173        p->pos.y = coord_origin;
    157174        p->btn_num = 1;
    158         p->btn_hpos = p->hpos;
    159         p->btn_vpos = p->vpos;
    160         p->accum_dx = 0;
    161         p->accum_dy = 0;
     175        p->btn_pos = p->pos;
     176        p->accum.x = 0;
     177        p->accum.y = 0;
    162178        p->grab_flags = GF_EMPTY;
    163179        p->pressed = false;
     
    286302                bool isec_vp = rectangle_intersect(
    287303                    x_dmg_glob, y_dmg_glob, w_dmg_glob, h_dmg_glob,
    288                     vp->hpos, vp->vpos, w_dmg_vp, h_dmg_vp,
     304                    vp->pos.x, vp->pos.y, w_dmg_vp, h_dmg_vp,
    289305                    &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
    290306
     
    292308
    293309                        /* Paint background color. */
    294                         for (sysarg_t y = y_dmg_vp - vp->vpos; y <  y_dmg_vp - vp->vpos + h_dmg_vp; ++y) {
    295                                 for (sysarg_t x = x_dmg_vp - vp->hpos; x < x_dmg_vp - vp->hpos + w_dmg_vp; ++x) {
     310                        for (sysarg_t y = y_dmg_vp - vp->pos.y; y <  y_dmg_vp - vp->pos.y + h_dmg_vp; ++y) {
     311                                for (sysarg_t x = x_dmg_vp - vp->pos.x; x < x_dmg_vp - vp->pos.x + w_dmg_vp; ++x) {
    296312                                        surface_put_pixel(vp->surface, x, y, bg_color);
    297313                                }
     
    331347                                         * coordinates. */
    332348                                        transform = win->transform;
    333                                         double hpos = vp->hpos;
    334                                         double vpos = vp->vpos;
    335                                         transform_translate(&transform, -hpos, -vpos);
     349                                        double_point_t pos;
     350                                        pos.x = vp->pos.x;
     351                                        pos.y = vp->pos.y;
     352                                        transform_translate(&transform, -pos.x, -pos.y);
    336353
    337354                                        source_set_transform(&source, transform);                               
     
    340357
    341358                                        drawctx_transfer(&context,
    342                                             x_dmg_win - vp->hpos, y_dmg_win - vp->vpos, w_dmg_win, h_dmg_win);
     359                                            x_dmg_win - vp->pos.x, y_dmg_win - vp->pos.y, w_dmg_win, h_dmg_win);
    343360                                }
    344361                        }
     
    354371                                bool isec_ptr = rectangle_intersect(
    355372                                    x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
    356                                     ptr->hpos, ptr->vpos, w_dmg_ptr, h_dmg_ptr,
     373                                    ptr->pos.x, ptr->pos.y, w_dmg_ptr, h_dmg_ptr,
    357374                                    &x_dmg_ptr, &y_dmg_ptr, &w_dmg_ptr, &h_dmg_ptr);
    358375
     
    365382
    366383                                        pixel_t pix = 0;
    367                                         sysarg_t x_vp = x_dmg_ptr - vp->hpos;
    368                                         sysarg_t y_vp = y_dmg_ptr - vp->vpos;
    369                                         sysarg_t x_ptr = x_dmg_ptr - ptr->hpos;
    370                                         sysarg_t y_ptr = y_dmg_ptr - ptr->vpos;
     384                                        sysarg_t x_vp = x_dmg_ptr - vp->pos.x;
     385                                        sysarg_t y_vp = y_dmg_ptr - vp->pos.y;
     386                                        sysarg_t x_ptr = x_dmg_ptr - ptr->pos.x;
     387                                        sysarg_t y_ptr = y_dmg_ptr - ptr->pos.y;
    371388
    372389                                        for (sysarg_t y = 0; y < h_dmg_ptr; ++y) {
     
    759776                fibril_mutex_unlock(&viewport_list_mtx);
    760777                loc_service_unregister(winreg_id);
    761                 async_hangup(input_sess);
     778                input_disconnect();
    762779
    763780                /* Close all clients and their windows. */
     
    880897
    881898        link_initialize(&vp->link);
    882         vp->hpos = coord_origin;
    883         vp->vpos = coord_origin;
     899        vp->pos.x = coord_origin;
     900        vp->pos.y = coord_origin;
    884901
    885902        /* Establish output bidirectional connection. */
     
    981998        /* window_list_mtx locked by caller */
    982999
    983         int dx = pointer->accum_dx;
    984         int dy = pointer->accum_dy;
    985         pointer->accum_dx = 0;
    986         pointer->accum_dy = 0;
     1000        int dx = pointer->accum.x;
     1001        int dy = pointer->accum.y;
     1002        pointer->accum.x = 0;
     1003        pointer->accum.y = 0;
    9871004
    9881005        bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
     
    10551072}
    10561073
    1057 static void comp_mouse_move(pointer_t *pointer, ipc_callid_t iid, ipc_call_t *icall)
    1058 {
    1059         int dx = (int) IPC_GET_ARG1(*icall);
    1060         int dy = (int) IPC_GET_ARG2(*icall);
     1074static int comp_abs_move(input_t *input, unsigned x , unsigned y,
     1075    unsigned max_x, unsigned max_y)
     1076{
     1077        /* XXX TODO Use absolute coordinates directly */
     1078       
     1079        pointer_t *pointer = input_pointer(input);
     1080       
     1081        sysarg_t width, height;
     1082       
     1083        fibril_mutex_lock(&viewport_list_mtx);
     1084        if (list_empty(&viewport_list)) {
     1085                printf("No viewport found\n");
     1086                fibril_mutex_unlock(&viewport_list_mtx);
     1087                return EOK; /* XXX */
     1088        }
     1089        link_t *link = list_first(&viewport_list);
     1090        viewport_t *vp = list_get_instance(link, viewport_t, link);
     1091        surface_get_resolution(vp->surface, &width, &height);
     1092        desktop_point_t vp_pos = vp->pos;
     1093        fibril_mutex_unlock(&viewport_list_mtx);
     1094
     1095        desktop_point_t pos_in_viewport;
     1096        pos_in_viewport.x = x * width / max_x;
     1097        pos_in_viewport.y = y * height / max_y;
     1098       
     1099        /* Calculate offset from pointer */
     1100        fibril_mutex_lock(&pointer_list_mtx);
     1101        desktop_vector_t delta;
     1102        delta.x = (vp_pos.x + pos_in_viewport.x) - pointer->pos.x;
     1103        delta.y = (vp_pos.y + pos_in_viewport.y) - pointer->pos.y;
     1104        fibril_mutex_unlock(&pointer_list_mtx);
     1105       
     1106        return comp_mouse_move(input, delta.x, delta.y);
     1107}
     1108
     1109static int comp_mouse_move(input_t *input, int dx, int dy)
     1110{
     1111        pointer_t *pointer = input_pointer(input);
    10611112
    10621113        /* Update pointer position. */
    10631114        fibril_mutex_lock(&pointer_list_mtx);
    1064         sysarg_t old_hpos = pointer->hpos;
    1065         sysarg_t old_vpos = pointer->vpos;
     1115        desktop_point_t old_pos = pointer->pos;
    10661116        sysarg_t cursor_width;
    10671117        sysarg_t cursor_height;
    10681118        surface_get_resolution(pointer->cursor.states[pointer->state],
    10691119             &cursor_width, &cursor_height);
    1070         pointer->hpos += dx;
    1071         pointer->vpos += dy;
     1120        pointer->pos.x += dx;
     1121        pointer->pos.y += dy;
    10721122        fibril_mutex_unlock(&pointer_list_mtx);
    1073         comp_damage(old_hpos, old_vpos, cursor_width, cursor_height);
    1074         comp_damage(old_hpos + dx, old_vpos + dy, cursor_width, cursor_height);
     1123        comp_damage(old_pos.x, old_pos.y, cursor_width, cursor_height);
     1124        comp_damage(old_pos.x + dx, old_pos.y + dy, cursor_width, cursor_height);
    10751125
    10761126        fibril_mutex_lock(&window_list_mtx);
     
    10841134                        sysarg_t width, height;
    10851135                        surface_get_resolution(top->surface, &width, &height);
    1086                         within_client = comp_coord_to_client(pointer->hpos, pointer->vpos,
     1136                        within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    10871137                            top->transform, width, height, &point_x, &point_y);
    10881138                        fibril_mutex_unlock(&window_list_mtx);
     
    11031153                } else {
    11041154                        /* Pointer is grabbed by top-level window action. */
    1105                         pointer->accum_dx += dx;
    1106                         pointer->accum_dy += dy;
     1155                        pointer->accum.x += dx;
     1156                        pointer->accum.y += dy;
    11071157#if ANIMATE_WINDOW_TRANSFORMS == 1
    11081158                        sysarg_t x, y, width, height;
     
    11181168        }
    11191169
    1120         async_answer_0(iid, EOK);
    1121 }
    1122 
    1123 static void comp_mouse_button(pointer_t *pointer, ipc_callid_t iid, ipc_call_t *icall)
    1124 {
    1125         sysarg_t btn_num = IPC_GET_ARG1(*icall);
    1126         bool pressed = (bool) IPC_GET_ARG2(*icall);
    1127 
    1128         if (pressed) {
    1129                 pointer->btn_hpos = pointer->hpos;
    1130                 pointer->btn_vpos = pointer->vpos;
    1131                 pointer->btn_num = btn_num;
     1170        return EOK;
     1171}
     1172
     1173static int comp_mouse_button(input_t *input, int bnum, int bpress)
     1174{
     1175        pointer_t *pointer = input_pointer(input);
     1176
     1177        if (bpress) {
     1178                pointer->btn_pos = pointer->pos;
     1179                pointer->btn_num = bnum;
    11321180                pointer->pressed = true;
    11331181
     
    11371185                if (!win || !win->surface) {
    11381186                        fibril_mutex_unlock(&window_list_mtx);
    1139                         async_answer_0(iid, EOK);
    1140                         return;
     1187                        return EOK;
    11411188                }
    11421189                sysarg_t x, y, width, height;
    11431190                surface_get_resolution(win->surface, &width, &height);
    1144                 bool within_client = comp_coord_to_client(pointer->hpos, pointer->vpos,
     1191                bool within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    11451192                    win->transform, width, height, &x, &y);
    11461193                fibril_mutex_unlock(&window_list_mtx);
     
    11541201                                event->data.pos.pos_id = pointer->id;
    11551202                                event->data.pos.type = POS_PRESS;
    1156                                 event->data.pos.btn_num = btn_num;
     1203                                event->data.pos.btn_num = bnum;
    11571204                                event->data.pos.hpos = x;
    11581205                                event->data.pos.vpos = y;
    11591206                                comp_post_event(event);
    11601207                        } else {
    1161                                 async_answer_0(iid, ENOMEM);
    1162                                 return;
    1163                         }
    1164                 }
    1165         } else if (pointer->pressed && pointer->btn_num == btn_num) {
     1208                                return ENOMEM;
     1209                        }
     1210                }
     1211        } else if (pointer->pressed && pointer->btn_num == (unsigned)bnum) {
    11661212                pointer->pressed = false;
    11671213
     
    11781224                        if (win->surface) {
    11791225                                surface_get_resolution(win->surface, &width, &height);
    1180                                 within_client = comp_coord_to_client(pointer->hpos, pointer->vpos,
     1226                                within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    11811227                                    win->transform, width, height, &point_x, &point_y);
    11821228                        }
     
    11911237                        pointer->grab_flags = GF_EMPTY;
    11921238                        fibril_mutex_unlock(&window_list_mtx);
    1193                         async_answer_0(iid, EOK);
    1194                         return;
     1239                        return EOK;
    11951240                }
    11961241
     
    12571302                                event->data.pos.pos_id = pointer->id;
    12581303                                event->data.pos.type = POS_RELEASE;
    1259                                 event->data.pos.btn_num = btn_num;
     1304                                event->data.pos.btn_num = bnum;
    12601305                                event->data.pos.hpos = point_x;
    12611306                                event->data.pos.vpos = point_y;
     
    12631308                        pointer->grab_flags = GF_EMPTY;
    12641309                       
    1265                 } else if (within_client && (pointer->grab_flags == GF_EMPTY) && (btn_num == 1)) {
     1310                } else if (within_client && (pointer->grab_flags == GF_EMPTY) && (bnum == 1)) {
    12661311
    12671312                        /* Bring the window to the foreground. */
     
    12861331        }
    12871332
    1288         async_answer_0(iid, EOK);
    1289 }
    1290 
    1291 static void comp_key_press(ipc_callid_t iid, ipc_call_t *icall)
    1292 {
    1293         kbd_event_type_t type = IPC_GET_ARG1(*icall);
    1294         keycode_t key = IPC_GET_ARG2(*icall);
    1295         keymod_t mods = IPC_GET_ARG3(*icall);
    1296         wchar_t c = IPC_GET_ARG4(*icall);
    1297 
     1333        return EOK;
     1334}
     1335
     1336static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
     1337    keymod_t mods, wchar_t c)
     1338{
    12981339        bool win_transform = (mods & KM_ALT) && (
    12991340            key == KC_W || key == KC_S || key == KC_A || key == KC_D ||
     
    13781419                        if (event == NULL) {
    13791420                                fibril_mutex_unlock(&window_list_mtx);
    1380                                 async_answer_0(iid, ENOMEM);
    1381                                 return;
     1421                                return ENOMEM;
    13821422                        }
    13831423
     
    14481488        } else if (win_close) {
    14491489                window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    1450                 if (event == NULL) {
    1451                         async_answer_0(iid, ENOMEM);
    1452                         return;
    1453                 }
     1490                if (event == NULL)
     1491                        return ENOMEM;
    14541492
    14551493                link_initialize(&event->link);
     
    15021540                        switch (key) {
    15031541                        case KC_I:
    1504                                 vp->hpos += 0;
    1505                                 vp->vpos += -20;
     1542                                vp->pos.x += 0;
     1543                                vp->pos.y += -20;
    15061544                                break;
    15071545                        case KC_K:
    1508                                 vp->hpos += 0;
    1509                                 vp->vpos += 20;
     1546                                vp->pos.x += 0;
     1547                                vp->pos.y += 20;
    15101548                                break;
    15111549                        case KC_J:
    1512                                 vp->hpos += -20;
    1513                                 vp->vpos += 0;
     1550                                vp->pos.x += -20;
     1551                                vp->pos.y += 0;
    15141552                                break;
    15151553                        case KC_L:
    1516                                 vp->hpos += 20;
    1517                                 vp->vpos += 0;
     1554                                vp->pos.x += 20;
     1555                                vp->pos.y += 0;
    15181556                                break;
    15191557                        default:
    1520                                 vp->hpos += 0;
    1521                                 vp->vpos += 0;
     1558                                vp->pos.x += 0;
     1559                                vp->pos.y += 0;
    15221560                                break;
    15231561                        }
    15241562                       
    1525                         sysarg_t x = vp->hpos;
    1526                         sysarg_t y = vp->vpos;
     1563                        sysarg_t x = vp->pos.x;
     1564                        sysarg_t y = vp->pos.y;
    15271565                        sysarg_t width, height;
    15281566                        surface_get_resolution(vp->surface, &width, &height);
     
    15941632        } else {
    15951633                window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    1596                 if (event == NULL) {
    1597                         async_answer_0(iid, ENOMEM);
    1598                         return;
    1599                 }
     1634                if (event == NULL)
     1635                        return ENOMEM;
    16001636
    16011637                link_initialize(&event->link);
     
    16091645        }
    16101646
    1611         async_answer_0(iid, EOK);
    1612 }
    1613 
    1614 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    1615 {
     1647        return EOK;
     1648}
     1649
     1650static int input_connect(const char *svc)
     1651{
     1652        async_sess_t *sess;
     1653        service_id_t dsid;
     1654
     1655        int rc = loc_service_get_id(svc, &dsid, 0);
     1656        if (rc != EOK) {
     1657                printf("%s: Input service %s not found\n", NAME, svc);
     1658                return rc;
     1659        }
     1660
     1661        sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
     1662        if (sess == NULL) {
     1663                printf("%s: Unable to connect to input service %s\n", NAME,
     1664                    svc);
     1665                return EIO;
     1666        }
     1667
    16161668        fibril_mutex_lock(&pointer_list_mtx);
    16171669        pointer_t *pointer = pointer_create();
     
    16221674        fibril_mutex_unlock(&pointer_list_mtx);
    16231675
    1624         /* Ignore parameters, the connection is already opened. */
    1625         while (true) {
    1626                 ipc_call_t call;
    1627                 ipc_callid_t callid = async_get_call(&call);
    1628 
    1629                 if (!IPC_GET_IMETHOD(call)) {
    1630                         fibril_mutex_lock(&pointer_list_mtx);
    1631                         if (pointer != NULL) {
    1632                                 list_remove(&pointer->link);
    1633                                 pointer_destroy(pointer);
    1634                         }
    1635                         fibril_mutex_unlock(&pointer_list_mtx);
    1636                         async_hangup(input_sess);
    1637                         return;
    1638                 }
    1639 
    1640                 switch (IPC_GET_IMETHOD(call)) {
    1641                 case INPUT_EVENT_KEY:
    1642                         comp_key_press(callid, &call);
    1643                         break;
    1644                 case INPUT_EVENT_MOVE:
    1645                         comp_mouse_move(pointer, callid, &call);
    1646                         break;
    1647                 case INPUT_EVENT_BUTTON:
    1648                         comp_mouse_button(pointer, callid, &call);
    1649                         break;
    1650                 default:
    1651                         async_answer_0(callid, EINVAL);
    1652                 }
    1653         }
    1654 }
    1655 
    1656 static async_sess_t *input_connect(const char *svc)
    1657 {
    1658         async_sess_t *sess;
    1659         service_id_t dsid;
    1660 
    1661         int rc = loc_service_get_id(svc, &dsid, 0);
    1662         if (rc == EOK) {
    1663                 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
    1664                 if (sess == NULL) {
    1665                         printf("%s: Unable to connect to input service %s\n", NAME, svc);
    1666                         return NULL;
    1667                 }
    1668         } else
    1669                 return NULL;
    1670 
    1671         async_exch_t *exch = async_exchange_begin(sess);
    1672         rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
    1673         async_exchange_end(exch);
    1674 
     1676        if (pointer == NULL) {
     1677                printf("%s: Cannot create pointer.\n", NAME);
     1678                async_hangup(sess);
     1679                return ENOMEM;
     1680        }
     1681
     1682        rc = input_open(sess, &input_ev_ops, pointer, &input);
    16751683        if (rc != EOK) {
    16761684                async_hangup(sess);
    1677                 printf("%s: Unable to create callback connection to service %s (%s)\n",
     1685                printf("%s: Unable to communicate with service %s (%s)\n",
    16781686                    NAME, svc, str_error(rc));
    1679                 return NULL;
    1680         }
    1681 
    1682         return sess;
     1687                return rc;
     1688        }
     1689
     1690        return EOK;
     1691}
     1692
     1693static void input_disconnect(void)
     1694{
     1695        pointer_t *pointer = input->user;
     1696        input_close(input);
     1697        pointer_destroy(pointer);
    16831698}
    16841699
     
    17331748
    17341749        /* Establish input bidirectional connection. */
    1735         input_sess = input_connect(input_svc);
    1736         if (input_sess == NULL) {
    1737                 return -1;
    1738         }
     1750        rc = input_connect(input_svc);
     1751        if (rc != EOK)
     1752                return rc;
    17391753
    17401754        /* Create viewports and connect them to visualizers. */
     
    17421756        rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
    17431757        if (rc != EOK) {
    1744                 async_hangup(input_sess);
     1758                input_disconnect();
    17451759                return -1;
    17461760        }
     
    17501764        rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
    17511765        if (rc != EOK || svcs_cnt == 0) {
    1752                 async_hangup(input_sess);
     1766                input_disconnect();
    17531767                return -1;
    17541768        }
     
    17661780       
    17671781        if (list_empty(&viewport_list)) {
    1768                 async_hangup(input_sess);
     1782                input_disconnect();
    17691783                return -1;
    17701784        }
Note: See TracChangeset for help on using the changeset viewer.