Ignore:
Timestamp:
2012-11-24T17:49:48Z (11 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c8e2ac5
Parents:
ba733e83
Message:

Resolved Ticket #484 (Window movement is invisible). Fast enough to be used in Qemu/non-KVM.

File:
1 edited

Legend:

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

    rba733e83 r563573b  
    9090typedef struct {
    9191        link_t link;
    92         sysarg_t id;
    93         uint8_t state;
    94         desktop_point_t pos;
    95         sysarg_t btn_num;
    96         desktop_point_t btn_pos;
    97         desktop_vector_t accum;
    98         sysarg_t grab_flags;
    99         bool pressed;
    100         cursor_t cursor;
    101 } pointer_t;
    102 
    103 static sysarg_t pointer_id = 0;
    104 static FIBRIL_MUTEX_INITIALIZE(pointer_list_mtx);
    105 static LIST_INITIALIZE(pointer_list);
    106 
    107 typedef struct {
    108         link_t link;
    10992        service_id_t in_dsid;
    11093        service_id_t out_dsid;
     
    129112typedef struct {
    130113        link_t link;
     114        sysarg_t id;
     115        uint8_t state;
     116        desktop_point_t pos;
     117        sysarg_t btn_num;
     118        desktop_point_t btn_pos;
     119        desktop_vector_t accum;
     120        sysarg_t grab_flags;
     121        bool pressed;
     122        cursor_t cursor;
     123        window_t ghost;
     124        desktop_vector_t accum_ghost;
     125} pointer_t;
     126
     127static sysarg_t pointer_id = 0;
     128static FIBRIL_MUTEX_INITIALIZE(pointer_list_mtx);
     129static LIST_INITIALIZE(pointer_list);
     130
     131typedef struct {
     132        link_t link;
    131133        service_id_t dsid;
    132134        vslmode_t mode;
     
    181183        cursor_init(&p->cursor, CURSOR_DECODER_EMBEDDED, NULL);
    182184
     185        /* Ghost window for transformation animation. */
     186        transform_identity(&p->ghost.transform);
     187        transform_translate(&p->ghost.transform, coord_origin, coord_origin);
     188        p->ghost.dx = coord_origin;
     189        p->ghost.dy = coord_origin;
     190        p->ghost.fx = 1;
     191        p->ghost.fy = 1;
     192        p->ghost.angle = 0;
     193        p->ghost.opacity = 255;
     194        p->ghost.surface = NULL;
     195        p->accum_ghost.x = 0;
     196        p->accum_ghost.y = 0;
     197
    183198        return p;
    184199}
     
    271286                sysarg_t y[4];
    272287                comp_coord_from_client(x_in, y_in, win_trans, &x[0], &y[0]);
    273                 comp_coord_from_client(x_in + w_in - 1, y_in, win_trans, &x[1], &y[1]);
    274                 comp_coord_from_client(x_in + w_in - 1, y_in + h_in - 1, win_trans, &x[2], &y[2]);
    275                 comp_coord_from_client(x_in, y_in + h_in - 1, win_trans, &x[3], &y[3]);
     288                comp_coord_from_client(x_in + w_in, y_in, win_trans, &x[1], &y[1]);
     289                comp_coord_from_client(x_in + w_in, y_in + h_in, win_trans, &x[2], &y[2]);
     290                comp_coord_from_client(x_in, y_in + h_in, win_trans, &x[3], &y[3]);
    276291                (*x_out) = x[0];
    277292                (*y_out) = y[0];
     
    373388                        list_foreach(pointer_list, link) {
    374389
     390                                pointer_t *ptr = list_get_instance(link, pointer_t, link);
     391                                if (ptr->ghost.surface) {
     392
     393                                        sysarg_t x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost;
     394                                        sysarg_t x_dmg_ghost, y_dmg_ghost, w_dmg_ghost, h_dmg_ghost;
     395                                        surface_get_resolution(ptr->ghost.surface, &w_bnd_ghost, &h_bnd_ghost);
     396                                        comp_coord_bounding_rect(0, 0, w_bnd_ghost, h_bnd_ghost, ptr->ghost.transform,
     397                                            &x_bnd_ghost, &y_bnd_ghost, &w_bnd_ghost, &h_bnd_ghost);
     398                                        bool isec_ghost = rectangle_intersect(
     399                                            x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
     400                                            x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost,
     401                                            &x_dmg_ghost, &y_dmg_ghost, &w_dmg_ghost, &h_dmg_ghost);
     402
     403                                        if (isec_ghost) {
     404                                                /* FIXME: Ghost is currently drawn based on the bounding
     405                                                 * rectangle of the window, which is sufficient as long
     406                                                 * as the windows can be rotated only by 90 degrees.
     407                                                 * For ghost to be compatible with arbitrary-angle
     408                                                 * rotation, it should be drawn as four lines adjusted
     409                                                 * by the transformation matrix. That would however
     410                                                 * require to equip libdraw with line drawing functionality. */
     411
     412                                                transform_t transform = ptr->ghost.transform;
     413                                                double_point_t pos;
     414                                                pos.x = vp->pos.x;
     415                                                pos.y = vp->pos.y;
     416                                                transform_translate(&transform, -pos.x, -pos.y);
     417
     418                                                pixel_t ghost_color;
     419
     420                                                if (y_bnd_ghost == y_dmg_ghost) {
     421                                                        for (sysarg_t x = x_dmg_ghost - vp->pos.x;
     422                                                                    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
     423                                                                ghost_color = surface_get_pixel(vp->surface,
     424                                                                    x, y_dmg_ghost - vp->pos.y);
     425                                                                surface_put_pixel(vp->surface,
     426                                                                    x, y_dmg_ghost - vp->pos.y, INVERT(ghost_color));
     427                                                        }
     428                                                }
     429
     430                                                if (y_bnd_ghost + h_bnd_ghost == y_dmg_ghost + h_dmg_ghost) {
     431                                                        for (sysarg_t x = x_dmg_ghost - vp->pos.x;
     432                                                                    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
     433                                                                ghost_color = surface_get_pixel(vp->surface,
     434                                                                    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1);
     435                                                                surface_put_pixel(vp->surface,
     436                                                                    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1, INVERT(ghost_color));
     437                                                        }
     438                                                }
     439
     440                                                if (x_bnd_ghost == x_dmg_ghost) {
     441                                                        for (sysarg_t y = y_dmg_ghost - vp->pos.y;
     442                                                                    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
     443                                                                ghost_color = surface_get_pixel(vp->surface,
     444                                                                    x_dmg_ghost - vp->pos.x, y);
     445                                                                surface_put_pixel(vp->surface,
     446                                                                    x_dmg_ghost - vp->pos.x, y, INVERT(ghost_color));
     447                                                        }
     448                                                }
     449
     450                                                if (x_bnd_ghost + w_bnd_ghost == x_dmg_ghost + w_dmg_ghost) {
     451                                                        for (sysarg_t y = y_dmg_ghost - vp->pos.y;
     452                                                                    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
     453                                                                ghost_color = surface_get_pixel(vp->surface,
     454                                                                    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y);
     455                                                                surface_put_pixel(vp->surface,
     456                                                                    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y, INVERT(ghost_color));
     457                                                        }
     458                                                }
     459                                        }
     460
     461                                }
     462                        }
     463
     464                        list_foreach(pointer_list, link) {
     465
    375466                                /* Determine what part of the pointer intersects with the
    376467                                 * updated area of the current viewport. */
     
    409500                                        surface_add_damaged_region(vp->surface, x_vp, y_vp, w_dmg_ptr, h_dmg_ptr);
    410501                                }
     502
    411503                        }
    412504                }
     
    10071099
    10081100static void comp_window_animate(pointer_t *pointer, window_t *win,
    1009      sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
     1101    sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
    10101102{
    10111103        /* window_list_mtx locked by caller */
     
    10841176            dmg_x, dmg_y, dmg_width, dmg_height);
    10851177}
     1178
     1179#if ANIMATE_WINDOW_TRANSFORMS == 0
     1180static void comp_ghost_animate(pointer_t *pointer,
     1181    desktop_rect_t *rect1, desktop_rect_t *rect2, desktop_rect_t *rect3, desktop_rect_t *rect4)
     1182{
     1183        int dx = pointer->accum_ghost.x;
     1184        int dy = pointer->accum_ghost.y;
     1185        pointer->accum_ghost.x = 0;
     1186        pointer->accum_ghost.y = 0;
     1187
     1188        bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
     1189        bool scale = (pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_SCALE_Y);
     1190        bool resize = (pointer->grab_flags & GF_RESIZE_X) || (pointer->grab_flags & GF_RESIZE_Y);
     1191
     1192        sysarg_t width, height;
     1193        surface_get_resolution(pointer->ghost.surface, &width, &height);
     1194
     1195        if (move) {
     1196                double cx = 0;
     1197                double cy = 0;
     1198                if (pointer->grab_flags & GF_MOVE_X) {
     1199                        cx = 1;
     1200                }
     1201                if (pointer->grab_flags & GF_MOVE_Y) {
     1202                        cy = 1;
     1203                }
     1204
     1205                if (scale || resize) {
     1206                        transform_t rotate;
     1207                        transform_identity(&rotate);
     1208                        transform_rotate(&rotate, pointer->ghost.angle);
     1209                        transform_apply_linear(&rotate, &cx, &cy);
     1210                }
     1211
     1212                cx = (cx < 0) ? (-1 * cx) : cx;
     1213                cy = (cy < 0) ? (-1 * cy) : cy;
     1214
     1215                pointer->ghost.dx += (cx * dx);
     1216                pointer->ghost.dy += (cy * dy);
     1217        }
     1218
     1219        if (scale || resize) {
     1220                double _dx = dx;
     1221                double _dy = dy;
     1222                transform_t unrotate;
     1223                transform_identity(&unrotate);
     1224                transform_rotate(&unrotate, -pointer->ghost.angle);
     1225                transform_apply_linear(&unrotate, &_dx, &_dy);
     1226                _dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
     1227                _dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
     1228
     1229                if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
     1230                        double fx = 1.0 + (_dx / (width * pointer->ghost.fx));
     1231                        pointer->ghost.fx *= fx;
     1232                }
     1233
     1234                if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
     1235                        double fy = 1.0 + (_dy / (height * pointer->ghost.fy));
     1236                        pointer->ghost.fy *= fy;
     1237                }
     1238        }
     1239
     1240        sysarg_t x1, y1, width1, height1;
     1241        sysarg_t x2, y2, width2, height2;
     1242        comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
     1243            &x1, &y1, &width1, &height1);
     1244        comp_recalc_transform(&pointer->ghost);
     1245        comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
     1246            &x2, &y2, &width2, &height2);
     1247
     1248        sysarg_t x_u, y_u, w_u, h_u;
     1249        rectangle_union(x1, y1, width1, height1, x2, y2, width2, height2,
     1250            &x_u, &y_u, &w_u, &h_u);
     1251
     1252        sysarg_t x_i, y_i, w_i, h_i;
     1253        rectangle_intersect(x1, y1, width1, height1, x2, y2, width2, height2,
     1254            &x_i, &y_i, &w_i, &h_i);
     1255
     1256        if (w_i == 0 || h_i == 0) {
     1257                rect1->x = x_u; rect2->x = 0; rect3->x = 0; rect4->x = 0;
     1258                rect1->y = y_u; rect2->y = 0; rect3->y = 0; rect4->y = 0;
     1259                rect1->w = w_u; rect2->w = 0; rect3->w = 0; rect4->w = 0;
     1260                rect1->h = h_u; rect2->h = 0; rect3->h = 0; rect4->h = 0;
     1261        } else {
     1262                rect1->x = x_u;
     1263                rect1->y = y_u;
     1264                rect1->w = x_i - x_u + 1;
     1265                rect1->h = h_u;
     1266
     1267                rect2->x = x_u;
     1268                rect2->y = y_u;
     1269                rect2->w = w_u;
     1270                rect2->h = y_i - y_u + 1;
     1271
     1272                rect3->x = x_i + w_i - 1;
     1273                rect3->y = y_u;
     1274                rect3->w = w_u - w_i - x_i + x_u + 1;
     1275                rect3->h = h_u;
     1276               
     1277                rect4->x = x_u;
     1278                rect4->y = y_i + h_i - 1;
     1279                rect4->w = w_u;
     1280                rect4->h = h_u - h_i - y_i + y_u + 1;
     1281        }
     1282}
     1283#endif
    10861284
    10871285static int comp_abs_move(input_t *input, unsigned x , unsigned y,
     
    11681366                        pointer->accum.x += dx;
    11691367                        pointer->accum.y += dy;
     1368                        pointer->accum_ghost.x += dx;
     1369                        pointer->accum_ghost.y += dy;
     1370#if ANIMATE_WINDOW_TRANSFORMS == 0
     1371                        if (pointer->ghost.surface == NULL) {
     1372                                pointer->ghost.surface = top->surface;
     1373                                pointer->ghost.dx = top->dx;
     1374                                pointer->ghost.dy = top->dy;
     1375                                pointer->ghost.fx = top->fx;
     1376                                pointer->ghost.fy = top->fy;
     1377                                pointer->ghost.angle = top->angle;
     1378                                pointer->ghost.transform = top->transform;
     1379                        }
     1380                        desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
     1381                        comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
     1382#endif
    11701383#if ANIMATE_WINDOW_TRANSFORMS == 1
    11711384                        sysarg_t x, y, width, height;
     
    11731386#endif
    11741387                        fibril_mutex_unlock(&window_list_mtx);
     1388#if ANIMATE_WINDOW_TRANSFORMS == 0
     1389                        comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
     1390                        comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
     1391                        comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
     1392                        comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
     1393#endif
    11751394#if ANIMATE_WINDOW_TRANSFORMS == 1
    11761395                        comp_damage(x, y, width, height);
     
    12191438        sysarg_t dmg_width = 0;
    12201439        sysarg_t dmg_height = 0;
     1440       
     1441#if ANIMATE_WINDOW_TRANSFORMS == 0
     1442        desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
     1443#endif
    12211444
    12221445        if (bpress) {
     
    12511474                pointer->pressed = false;
    12521475
     1476#if ANIMATE_WINDOW_TRANSFORMS == 0
    12531477                sysarg_t pre_x = 0;
    12541478                sysarg_t pre_y = 0;
     
    12561480                sysarg_t pre_height = 0;
    12571481
    1258 #if ANIMATE_WINDOW_TRANSFORMS == 0
    12591482                if (pointer->grab_flags != GF_EMPTY) {
     1483                        if (pointer->ghost.surface) {
     1484                                comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
     1485                                pointer->ghost.surface = NULL;
     1486                        }
    12601487                        comp_window_animate(pointer, top, &pre_x, &pre_y, &pre_width, &pre_height);
    12611488                        dmg_x = pre_x;
     
    13211548
    13221549        fibril_mutex_unlock(&window_list_mtx);
     1550
     1551#if ANIMATE_WINDOW_TRANSFORMS == 0
     1552                comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
     1553                comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
     1554                comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
     1555                comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
     1556#endif
    13231557
    13241558        if (dmg_width > 0 && dmg_height > 0) {
     
    17051939{
    17061940        /* Coordinates of the central pixel. */
    1707         coord_origin = UINT32_MAX / 2;
     1941        coord_origin = UINT32_MAX / 4;
    17081942       
    17091943        /* Color of the viewport background. Must be opaque. */
Note: See TracChangeset for help on using the changeset viewer.