Ignore:
File:
1 edited

Legend:

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

    rd17a4a9 r82edef2  
    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}
     
    192207}
    193208
    194 static window_t *window_create()
     209static window_t *window_create(sysarg_t x_offset, sysarg_t y_offset)
    195210{
    196211        window_t *win = (window_t *) malloc(sizeof(window_t));
     
    202217        prodcons_initialize(&win->queue);
    203218        transform_identity(&win->transform);
    204         transform_translate(&win->transform, coord_origin, coord_origin);
    205         win->dx = coord_origin;
    206         win->dy = coord_origin;
     219        transform_translate(&win->transform,
     220            coord_origin + x_offset, coord_origin + y_offset);
     221        win->dx = coord_origin + x_offset;
     222        win->dy = coord_origin + y_offset;
    207223        win->fx = 1;
    208224        win->fy = 1;
     
    267283    sysarg_t *x_out, sysarg_t *y_out, sysarg_t *w_out, sysarg_t *h_out)
    268284{
    269         sysarg_t x[4];
    270         sysarg_t y[4];
    271         comp_coord_from_client(x_in, y_in, win_trans, &x[0], &y[0]);
    272         comp_coord_from_client(x_in + w_in, y_in, win_trans, &x[1], &y[1]);
    273         comp_coord_from_client(x_in + w_in, y_in + h_in, win_trans, &x[2], &y[2]);
    274         comp_coord_from_client(x_in, y_in + h_in, win_trans, &x[3], &y[3]);
    275         (*x_out) = x[0];
    276         (*y_out) = y[0];
    277         (*w_out) = x[0];
    278         (*h_out) = y[0];
    279         for (int i = 1; i < 4; ++i) {
    280                 (*x_out) = (x[i] < (*x_out)) ? x[i] : (*x_out);
    281                 (*y_out) = (y[i] < (*y_out)) ? y[i] : (*y_out);
    282                 (*w_out) = (x[i] > (*w_out)) ? x[i] : (*w_out);
    283                 (*h_out) = (y[i] > (*h_out)) ? y[i] : (*h_out);
    284         }
    285         (*w_out) -= (*x_out);
    286         (*h_out) -= (*y_out);
     285        if (w_in > 0 && h_in > 0) {
     286                sysarg_t x[4];
     287                sysarg_t y[4];
     288                comp_coord_from_client(x_in, y_in, win_trans, &x[0], &y[0]);
     289                comp_coord_from_client(x_in + w_in - 1, y_in, win_trans, &x[1], &y[1]);
     290                comp_coord_from_client(x_in + w_in - 1, y_in + h_in - 1, win_trans, &x[2], &y[2]);
     291                comp_coord_from_client(x_in, y_in + h_in - 1, win_trans, &x[3], &y[3]);
     292                (*x_out) = x[0];
     293                (*y_out) = y[0];
     294                (*w_out) = x[0];
     295                (*h_out) = y[0];
     296                for (int i = 1; i < 4; ++i) {
     297                        (*x_out) = (x[i] < (*x_out)) ? x[i] : (*x_out);
     298                        (*y_out) = (y[i] < (*y_out)) ? y[i] : (*y_out);
     299                        (*w_out) = (x[i] > (*w_out)) ? x[i] : (*w_out);
     300                        (*h_out) = (y[i] > (*h_out)) ? y[i] : (*h_out);
     301                }
     302                (*w_out) = (*w_out) - (*x_out) + 1;
     303                (*h_out) = (*h_out) - (*y_out) + 1;
     304        } else {
     305                (*w_out) = 0;
     306                (*h_out) = 0;
     307        }
    287308}
    288309
     
    309330                        /* Paint background color. */
    310331                        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) {
    312                                         surface_put_pixel(vp->surface, x, y, bg_color);
     332                                pixel_t *dst = pixelmap_pixel_at(
     333                                    surface_pixmap_access(vp->surface), x_dmg_vp - vp->pos.x, y);
     334                                sysarg_t count = w_dmg_vp;
     335                                while (count-- != 0) {
     336                                        *dst++ = bg_color;
    313337                                }
    314338                        }
     339                        surface_add_damaged_region(vp->surface,
     340                            x_dmg_vp - vp->pos.x, y_dmg_vp - vp->pos.y, w_dmg_vp, h_dmg_vp);
    315341
    316342                        transform_t transform;
     
    363389                        list_foreach(pointer_list, link) {
    364390
     391                                pointer_t *ptr = list_get_instance(link, pointer_t, link);
     392                                if (ptr->ghost.surface) {
     393
     394                                        sysarg_t x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost;
     395                                        sysarg_t x_dmg_ghost, y_dmg_ghost, w_dmg_ghost, h_dmg_ghost;
     396                                        surface_get_resolution(ptr->ghost.surface, &w_bnd_ghost, &h_bnd_ghost);
     397                                        comp_coord_bounding_rect(0, 0, w_bnd_ghost, h_bnd_ghost, ptr->ghost.transform,
     398                                            &x_bnd_ghost, &y_bnd_ghost, &w_bnd_ghost, &h_bnd_ghost);
     399                                        bool isec_ghost = rectangle_intersect(
     400                                            x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
     401                                            x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost,
     402                                            &x_dmg_ghost, &y_dmg_ghost, &w_dmg_ghost, &h_dmg_ghost);
     403
     404                                        if (isec_ghost) {
     405                                                /* FIXME: Ghost is currently drawn based on the bounding
     406                                                 * rectangle of the window, which is sufficient as long
     407                                                 * as the windows can be rotated only by 90 degrees.
     408                                                 * For ghost to be compatible with arbitrary-angle
     409                                                 * rotation, it should be drawn as four lines adjusted
     410                                                 * by the transformation matrix. That would however
     411                                                 * require to equip libdraw with line drawing functionality. */
     412
     413                                                transform_t transform = ptr->ghost.transform;
     414                                                double_point_t pos;
     415                                                pos.x = vp->pos.x;
     416                                                pos.y = vp->pos.y;
     417                                                transform_translate(&transform, -pos.x, -pos.y);
     418
     419                                                pixel_t ghost_color;
     420
     421                                                if (y_bnd_ghost == y_dmg_ghost) {
     422                                                        for (sysarg_t x = x_dmg_ghost - vp->pos.x;
     423                                                                    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
     424                                                                ghost_color = surface_get_pixel(vp->surface,
     425                                                                    x, y_dmg_ghost - vp->pos.y);
     426                                                                surface_put_pixel(vp->surface,
     427                                                                    x, y_dmg_ghost - vp->pos.y, INVERT(ghost_color));
     428                                                        }
     429                                                }
     430
     431                                                if (y_bnd_ghost + h_bnd_ghost == y_dmg_ghost + h_dmg_ghost) {
     432                                                        for (sysarg_t x = x_dmg_ghost - vp->pos.x;
     433                                                                    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
     434                                                                ghost_color = surface_get_pixel(vp->surface,
     435                                                                    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1);
     436                                                                surface_put_pixel(vp->surface,
     437                                                                    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1, INVERT(ghost_color));
     438                                                        }
     439                                                }
     440
     441                                                if (x_bnd_ghost == x_dmg_ghost) {
     442                                                        for (sysarg_t y = y_dmg_ghost - vp->pos.y;
     443                                                                    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
     444                                                                ghost_color = surface_get_pixel(vp->surface,
     445                                                                    x_dmg_ghost - vp->pos.x, y);
     446                                                                surface_put_pixel(vp->surface,
     447                                                                    x_dmg_ghost - vp->pos.x, y, INVERT(ghost_color));
     448                                                        }
     449                                                }
     450
     451                                                if (x_bnd_ghost + w_bnd_ghost == x_dmg_ghost + w_dmg_ghost) {
     452                                                        for (sysarg_t y = y_dmg_ghost - vp->pos.y;
     453                                                                    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
     454                                                                ghost_color = surface_get_pixel(vp->surface,
     455                                                                    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y);
     456                                                                surface_put_pixel(vp->surface,
     457                                                                    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y, INVERT(ghost_color));
     458                                                        }
     459                                                }
     460                                        }
     461
     462                                }
     463                        }
     464
     465                        list_foreach(pointer_list, link) {
     466
    365467                                /* Determine what part of the pointer intersects with the
    366468                                 * updated area of the current viewport. */
     
    376478                                if (isec_ptr) {
    377479                                        /* Pointer is currently painted directly by copying pixels.
    378                                          * However, it is possible to draw the painter similarly
     480                                         * However, it is possible to draw the pointer similarly
    379481                                         * as window by using drawctx_transfer. It would allow
    380482                                         * more sophisticated control over drawing, but would also
    381483                                         * cost more regarding the performance. */
    382484
    383                                         pixel_t pix = 0;
    384485                                        sysarg_t x_vp = x_dmg_ptr - vp->pos.x;
    385486                                        sysarg_t y_vp = y_dmg_ptr - vp->pos.y;
     
    388489
    389490                                        for (sysarg_t y = 0; y < h_dmg_ptr; ++y) {
    390                                                 for (sysarg_t x = 0; x < w_dmg_ptr; ++x) {
    391                                                         pix = surface_get_pixel(sf_ptr, x_ptr + x, y_ptr + y);
    392                                                         if (ALPHA(pix) == 255) {
    393                                                                 surface_put_pixel(vp->surface, x_vp + x, y_vp + y, pix);
    394                                                         }
     491                                                pixel_t *src = pixelmap_pixel_at(
     492                                                    surface_pixmap_access(sf_ptr), x_ptr, y_ptr + y);
     493                                                pixel_t *dst = pixelmap_pixel_at(
     494                                                    surface_pixmap_access(vp->surface), x_vp, y_vp + y);
     495                                                sysarg_t count = w_dmg_ptr;
     496                                                while (count-- != 0) {
     497                                                        *dst = (*src & 0xff000000) ? *src : *dst;
     498                                                        ++dst; ++src;
    395499                                                }
    396500                                        }
     501                                        surface_add_damaged_region(vp->surface, x_vp, y_vp, w_dmg_ptr, h_dmg_ptr);
    397502                                }
     503
    398504                        }
    399505                }
     
    450556        } else {
    451557                fibril_mutex_lock(&window_list_mtx);
    452                 comp_coord_bounding_rect(x, y, width, height,
     558                comp_coord_bounding_rect(x - 1, y - 1, width + 2, height + 2,
    453559                    win->transform, &x, &y, &width, &height);
    454560                fibril_mutex_unlock(&window_list_mtx);
     
    468574                pointer_t *pointer = list_get_instance(link, pointer_t, link);
    469575                if (pointer->id == pos_id) {
    470                         pointer->grab_flags = grab_flags;
     576                        pointer->grab_flags = pointer->pressed ? grab_flags : GF_EMPTY;
    471577                        // TODO change pointer->state according to grab_flags
    472578                        break;
     
    541647}
    542648
     649static void comp_post_event_win(window_event_t *event, window_t *target)
     650{
     651        fibril_mutex_lock(&window_list_mtx);
     652        window_t *window = NULL;
     653        list_foreach(window_list, link) {
     654                window = list_get_instance(link, window_t, link);
     655                if (window == target) {
     656                        prodcons_produce(&window->queue, &event->link);
     657                }
     658        }
     659        if (!window) {
     660                free(event);
     661        }
     662        fibril_mutex_unlock(&window_list_mtx);
     663}
     664
     665static void comp_post_event_top(window_event_t *event)
     666{
     667        fibril_mutex_lock(&window_list_mtx);
     668        window_t *win = (window_t *) list_first(&window_list);
     669        if (win) {
     670                prodcons_produce(&win->queue, &event->link);
     671        } else {
     672                free(event);
     673        }
     674        fibril_mutex_unlock(&window_list_mtx);
     675}
     676
    543677static void comp_window_close(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
    544678{
     
    546680        fibril_mutex_lock(&window_list_mtx);
    547681        list_remove(&win->link);
     682        window_t *win_focus = (window_t *) list_first(&window_list);
     683        window_event_t *event_focus = (window_event_t *) malloc(sizeof(window_event_t));
     684        if (event_focus) {
     685                link_initialize(&event_focus->link);
     686                event_focus->type = ET_WINDOW_FOCUS;
     687        }
    548688        fibril_mutex_unlock(&window_list_mtx);
     689
     690        if (event_focus && win_focus) {
     691                comp_post_event_win(event_focus, win_focus);
     692        }
    549693
    550694        /* Calculate damage. */
     
    601745                        fibril_mutex_lock(&window_list_mtx);
    602746
    603                         window_t *win = window_create();
     747                        window_t *win = window_create(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    604748                        if (!win) {
    605749                                async_answer_2(callid, ENOMEM, 0, 0);
     
    630774                        }
    631775
     776                        window_t *win_unfocus = (window_t *) list_first(&window_list);
    632777                        list_prepend(&win->link, &window_list);
     778
     779                        window_event_t *event_unfocus = (window_event_t *) malloc(sizeof(window_event_t));
     780                        if (event_unfocus) {
     781                                link_initialize(&event_unfocus->link);
     782                                event_unfocus->type = ET_WINDOW_UNFOCUS;
     783                        }
    633784                       
    634785                        async_answer_2(callid, EOK, win->in_dsid, win->out_dsid);
    635786                        fibril_mutex_unlock(&window_list_mtx);
     787                       
     788                        if (event_unfocus && win_unfocus) {
     789                                comp_post_event_win(event_unfocus, win_unfocus);
     790                        }
     791
    636792                        return;
    637793                } else {
     
    9531109}
    9541110
    955 static void comp_post_event(window_event_t *event)
    956 {
    957         fibril_mutex_lock(&window_list_mtx);
    958         window_t *win = (window_t *) list_first(&window_list);
    959         if (win) {
    960                 prodcons_produce(&win->queue, &event->link);
    961         } else {
    962                 free(event);
    963         }
    964         fibril_mutex_unlock(&window_list_mtx);
    965 }
    966 
    9671111static void comp_recalc_transform(window_t *win)
    9681112{
     
    9731117        transform_t scale;
    9741118        transform_identity(&scale);
    975         transform_scale(&scale, win->fx, win->fy);
     1119        if (win->fx != 1 || win->fy != 1) {
     1120                transform_scale(&scale, win->fx, win->fy);
     1121        }
    9761122
    9771123        transform_t rotate;
    9781124        transform_identity(&rotate);
    979         transform_rotate(&rotate, win->angle);
     1125        if (win->angle != 0) {
     1126                transform_rotate(&rotate, win->angle);
     1127        }
    9801128
    9811129        transform_t transform;
     
    9941142
    9951143static void comp_window_animate(pointer_t *pointer, window_t *win,
    996      sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
     1144    sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
    9971145{
    9981146        /* window_list_mtx locked by caller */
     1147        /* pointer_list_mtx locked by caller */
    9991148
    10001149        int dx = pointer->accum.x;
     
    10201169                }
    10211170
    1022                 if (scale || resize) {
     1171                if ((scale || resize) && (win->angle != 0)) {
    10231172                        transform_t rotate;
    10241173                        transform_identity(&rotate);
     
    10371186                double _dx = dx;
    10381187                double _dy = dy;
    1039                 transform_t unrotate;
    1040                 transform_identity(&unrotate);
    1041                 transform_rotate(&unrotate, -win->angle);
    1042                 transform_apply_linear(&unrotate, &_dx, &_dy);
     1188                if (win->angle != 0) {
     1189                        transform_t unrotate;
     1190                        transform_identity(&unrotate);
     1191                        transform_rotate(&unrotate, -win->angle);
     1192                        transform_apply_linear(&unrotate, &_dx, &_dy);
     1193                }
    10431194                _dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
    10441195                _dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
    10451196
    10461197                if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
    1047                         double fx = 1.0 + (_dx / (width * win->fx));
     1198                        double fx = 1.0 + (_dx / ((width - 1) * win->fx));
    10481199                        if (fx > 0) {
     1200#if ANIMATE_WINDOW_TRANSFORMS == 0
     1201                                if (scale) win->fx *= fx;
     1202#endif
     1203#if ANIMATE_WINDOW_TRANSFORMS == 1
    10491204                                win->fx *= fx;
     1205#endif
    10501206                                scale_back_x *= fx;
    10511207                        }
     
    10531209
    10541210                if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
    1055                         double fy = 1.0 + (_dy / (height * win->fy));
     1211                        double fy = 1.0 + (_dy / ((height - 1) * win->fy));
    10561212                        if (fy > 0) {
     1213#if ANIMATE_WINDOW_TRANSFORMS == 0
     1214                                if (scale) win->fy *= fy;
     1215#endif
     1216#if ANIMATE_WINDOW_TRANSFORMS == 1
    10571217                                win->fy *= fy;
     1218#endif
    10581219                                scale_back_y *= fy;
    10591220                        }
     
    10711232            dmg_x, dmg_y, dmg_width, dmg_height);
    10721233}
     1234
     1235#if ANIMATE_WINDOW_TRANSFORMS == 0
     1236static void comp_ghost_animate(pointer_t *pointer,
     1237    desktop_rect_t *rect1, desktop_rect_t *rect2, desktop_rect_t *rect3, desktop_rect_t *rect4)
     1238{
     1239        /* window_list_mtx locked by caller */
     1240        /* pointer_list_mtx locked by caller */
     1241
     1242        int dx = pointer->accum_ghost.x;
     1243        int dy = pointer->accum_ghost.y;
     1244        pointer->accum_ghost.x = 0;
     1245        pointer->accum_ghost.y = 0;
     1246
     1247        bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
     1248        bool scale = (pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_SCALE_Y);
     1249        bool resize = (pointer->grab_flags & GF_RESIZE_X) || (pointer->grab_flags & GF_RESIZE_Y);
     1250
     1251        sysarg_t width, height;
     1252        surface_get_resolution(pointer->ghost.surface, &width, &height);
     1253
     1254        if (move) {
     1255                double cx = 0;
     1256                double cy = 0;
     1257                if (pointer->grab_flags & GF_MOVE_X) {
     1258                        cx = 1;
     1259                }
     1260                if (pointer->grab_flags & GF_MOVE_Y) {
     1261                        cy = 1;
     1262                }
     1263
     1264                if (scale || resize) {
     1265                        transform_t rotate;
     1266                        transform_identity(&rotate);
     1267                        transform_rotate(&rotate, pointer->ghost.angle);
     1268                        transform_apply_linear(&rotate, &cx, &cy);
     1269                }
     1270
     1271                cx = (cx < 0) ? (-1 * cx) : cx;
     1272                cy = (cy < 0) ? (-1 * cy) : cy;
     1273
     1274                pointer->ghost.dx += (cx * dx);
     1275                pointer->ghost.dy += (cy * dy);
     1276        }
     1277
     1278        if (scale || resize) {
     1279                double _dx = dx;
     1280                double _dy = dy;
     1281                transform_t unrotate;
     1282                transform_identity(&unrotate);
     1283                transform_rotate(&unrotate, -pointer->ghost.angle);
     1284                transform_apply_linear(&unrotate, &_dx, &_dy);
     1285                _dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
     1286                _dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
     1287
     1288                if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
     1289                        double fx = 1.0 + (_dx / ((width - 1) * pointer->ghost.fx));
     1290                        pointer->ghost.fx *= fx;
     1291                }
     1292
     1293                if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
     1294                        double fy = 1.0 + (_dy / ((height - 1) * pointer->ghost.fy));
     1295                        pointer->ghost.fy *= fy;
     1296                }
     1297        }
     1298
     1299        sysarg_t x1, y1, width1, height1;
     1300        sysarg_t x2, y2, width2, height2;
     1301        comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
     1302            &x1, &y1, &width1, &height1);
     1303        comp_recalc_transform(&pointer->ghost);
     1304        comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
     1305            &x2, &y2, &width2, &height2);
     1306
     1307        sysarg_t x_u, y_u, w_u, h_u;
     1308        rectangle_union(x1, y1, width1, height1, x2, y2, width2, height2,
     1309            &x_u, &y_u, &w_u, &h_u);
     1310
     1311        sysarg_t x_i, y_i, w_i, h_i;
     1312        rectangle_intersect(x1, y1, width1, height1, x2, y2, width2, height2,
     1313            &x_i, &y_i, &w_i, &h_i);
     1314
     1315        if (w_i == 0 || h_i == 0) {
     1316                rect1->x = x_u; rect2->x = 0; rect3->x = 0; rect4->x = 0;
     1317                rect1->y = y_u; rect2->y = 0; rect3->y = 0; rect4->y = 0;
     1318                rect1->w = w_u; rect2->w = 0; rect3->w = 0; rect4->w = 0;
     1319                rect1->h = h_u; rect2->h = 0; rect3->h = 0; rect4->h = 0;
     1320        } else {
     1321                rect1->x = x_u;
     1322                rect1->y = y_u;
     1323                rect1->w = x_i - x_u + 1;
     1324                rect1->h = h_u;
     1325
     1326                rect2->x = x_u;
     1327                rect2->y = y_u;
     1328                rect2->w = w_u;
     1329                rect2->h = y_i - y_u + 1;
     1330
     1331                rect3->x = x_i + w_i - 1;
     1332                rect3->y = y_u;
     1333                rect3->w = w_u - w_i - x_i + x_u + 1;
     1334                rect3->h = h_u;
     1335               
     1336                rect4->x = x_u;
     1337                rect4->y = y_i + h_i - 1;
     1338                rect4->w = w_u;
     1339                rect4->h = h_u - h_i - y_i + y_u + 1;
     1340        }
     1341}
     1342#endif
    10731343
    10741344static int comp_abs_move(input_t *input, unsigned x , unsigned y,
     
    11251395
    11261396        fibril_mutex_lock(&window_list_mtx);
     1397        fibril_mutex_lock(&pointer_list_mtx);
    11271398        window_t *top = (window_t *) list_first(&window_list);
    11281399        if (top && top->surface) {
     
    11361407                        within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    11371408                            top->transform, width, height, &point_x, &point_y);
    1138                         fibril_mutex_unlock(&window_list_mtx);
    1139 
     1409
     1410                        window_event_t *event = NULL;
    11401411                        if (within_client) {
    1141                                 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     1412                                event = (window_event_t *) malloc(sizeof(window_event_t));
    11421413                                if (event) {
    11431414                                        link_initialize(&event->link);
     
    11481419                                        event->data.pos.hpos = point_x;
    11491420                                        event->data.pos.vpos = point_y;
    1150                                         comp_post_event(event);
    11511421                                }
    11521422                        }
     1423
     1424                        fibril_mutex_unlock(&pointer_list_mtx);
     1425                        fibril_mutex_unlock(&window_list_mtx);
     1426
     1427                        if (event) {
     1428                                comp_post_event_top(event);
     1429                        }
     1430
    11531431                } else {
    11541432                        /* Pointer is grabbed by top-level window action. */
    11551433                        pointer->accum.x += dx;
    11561434                        pointer->accum.y += dy;
     1435                        pointer->accum_ghost.x += dx;
     1436                        pointer->accum_ghost.y += dy;
     1437#if ANIMATE_WINDOW_TRANSFORMS == 0
     1438                        if (pointer->ghost.surface == NULL) {
     1439                                pointer->ghost.surface = top->surface;
     1440                                pointer->ghost.dx = top->dx;
     1441                                pointer->ghost.dy = top->dy;
     1442                                pointer->ghost.fx = top->fx;
     1443                                pointer->ghost.fy = top->fy;
     1444                                pointer->ghost.angle = top->angle;
     1445                                pointer->ghost.transform = top->transform;
     1446                        }
     1447                        desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
     1448                        comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
     1449#endif
    11571450#if ANIMATE_WINDOW_TRANSFORMS == 1
    11581451                        sysarg_t x, y, width, height;
    11591452                        comp_window_animate(pointer, top, &x, &y, &width, &height);
    11601453#endif
     1454                        fibril_mutex_unlock(&pointer_list_mtx);
    11611455                        fibril_mutex_unlock(&window_list_mtx);
     1456#if ANIMATE_WINDOW_TRANSFORMS == 0
     1457                        comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
     1458                        comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
     1459                        comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
     1460                        comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
     1461#endif
    11621462#if ANIMATE_WINDOW_TRANSFORMS == 1
    11631463                        comp_damage(x, y, width, height);
     
    11651465                }
    11661466        } else {
     1467                fibril_mutex_unlock(&pointer_list_mtx);
    11671468                fibril_mutex_unlock(&window_list_mtx);
    11681469        }
     
    11741475{
    11751476        pointer_t *pointer = input_pointer(input);
     1477
     1478        fibril_mutex_lock(&window_list_mtx);
     1479        fibril_mutex_lock(&pointer_list_mtx);
     1480        window_t *win = NULL;
     1481        sysarg_t point_x = 0;
     1482        sysarg_t point_y = 0;
     1483        sysarg_t width, height;
     1484        bool within_client = false;
     1485
     1486        /* Determine the window which the mouse click belongs to. */
     1487        list_foreach(window_list, link) {
     1488                win = list_get_instance(link, window_t, link);
     1489                if (win->surface) {
     1490                        surface_get_resolution(win->surface, &width, &height);
     1491                        within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
     1492                            win->transform, width, height, &point_x, &point_y);
     1493                }
     1494                if (within_client) {
     1495                        break;
     1496                }
     1497        }
     1498
     1499        /* Check whether the window is top-level window. */
     1500        window_t *top = (window_t *) list_first(&window_list);
     1501        if (!win || !top) {
     1502                fibril_mutex_unlock(&pointer_list_mtx);
     1503                fibril_mutex_unlock(&window_list_mtx);
     1504                return EOK;
     1505        }
     1506
     1507        window_event_t *event_top = NULL;
     1508        window_event_t *event_unfocus = NULL;
     1509        window_t *win_unfocus = NULL;
     1510        sysarg_t dmg_x, dmg_y;
     1511        sysarg_t dmg_width = 0;
     1512        sysarg_t dmg_height = 0;
     1513       
     1514#if ANIMATE_WINDOW_TRANSFORMS == 0
     1515        desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
     1516#endif
    11761517
    11771518        if (bpress) {
     
    11801521                pointer->pressed = true;
    11811522
    1182                 /* Check whether mouse press belongs to the top-level window. */
    1183                 fibril_mutex_lock(&window_list_mtx);
    1184                 window_t *win = (window_t *) list_first(&window_list);
    1185                 if (!win || !win->surface) {
    1186                         fibril_mutex_unlock(&window_list_mtx);
    1187                         return EOK;
    1188                 }
    1189                 sysarg_t x, y, width, height;
    1190                 surface_get_resolution(win->surface, &width, &height);
    1191                 bool within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    1192                     win->transform, width, height, &x, &y);
    1193                 fibril_mutex_unlock(&window_list_mtx);
    1194 
    1195                 /* Send mouse press to the top-level window. */
     1523                /* Bring the window to the foreground. */
     1524                if ((win != top) && within_client) {
     1525                        win_unfocus = (window_t *) list_first(&window_list);
     1526                        list_remove(&win->link);
     1527                        list_prepend(&win->link, &window_list);
     1528                        event_unfocus = (window_event_t *) malloc(sizeof(window_event_t));
     1529                        if (event_unfocus) {
     1530                                link_initialize(&event_unfocus->link);
     1531                                event_unfocus->type = ET_WINDOW_UNFOCUS;
     1532                        }
     1533                        comp_coord_bounding_rect(0, 0, width, height, win->transform,
     1534                            &dmg_x, &dmg_y, &dmg_width, &dmg_height);
     1535                }
     1536
     1537                /* Notify top-level window about mouse press. */
    11961538                if (within_client) {
    1197                         window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
    1198                         if (event) {
    1199                                 link_initialize(&event->link);
    1200                                 event->type = ET_POSITION_EVENT;
    1201                                 event->data.pos.pos_id = pointer->id;
    1202                                 event->data.pos.type = POS_PRESS;
    1203                                 event->data.pos.btn_num = bnum;
    1204                                 event->data.pos.hpos = x;
    1205                                 event->data.pos.vpos = y;
    1206                                 comp_post_event(event);
    1207                         } else {
    1208                                 return ENOMEM;
    1209                         }
    1210                 }
     1539                        event_top = (window_event_t *) malloc(sizeof(window_event_t));
     1540                        if (event_top) {
     1541                                link_initialize(&event_top->link);
     1542                                event_top->type = ET_POSITION_EVENT;
     1543                                event_top->data.pos.pos_id = pointer->id;
     1544                                event_top->data.pos.type = POS_PRESS;
     1545                                event_top->data.pos.btn_num = bnum;
     1546                                event_top->data.pos.hpos = point_x;
     1547                                event_top->data.pos.vpos = point_y;
     1548                        }
     1549                        pointer->grab_flags = GF_EMPTY;
     1550                }
     1551
    12111552        } else if (pointer->pressed && pointer->btn_num == (unsigned)bnum) {
    12121553                pointer->pressed = false;
    12131554
    1214                 fibril_mutex_lock(&window_list_mtx);
    1215                 window_t *win = NULL;
    1216                 sysarg_t point_x = 0;
    1217                 sysarg_t point_y = 0;
    1218                 sysarg_t width, height;
    1219                 bool within_client = false;
    1220 
    1221                 /* Determine the window which the mouse release belongs to. */
    1222                 list_foreach(window_list, link) {
    1223                         win = list_get_instance(link, window_t, link);
    1224                         if (win->surface) {
    1225                                 surface_get_resolution(win->surface, &width, &height);
    1226                                 within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    1227                                     win->transform, width, height, &point_x, &point_y);
    1228                         }
    1229                         if (within_client) {
    1230                                 break;
    1231                         }
    1232                 }
    1233 
    1234                 /* Check whether the window is top-level window. */
    1235                 window_t *top = (window_t *) list_first(&window_list);
    1236                 if (!win || !top) {
    1237                         pointer->grab_flags = GF_EMPTY;
    1238                         fibril_mutex_unlock(&window_list_mtx);
    1239                         return EOK;
    1240                 }
    1241 
    1242                 window_event_t *event = NULL;
    1243                 sysarg_t dmg_x, dmg_y;
    1244                 sysarg_t dmg_width = 0;
    1245                 sysarg_t dmg_height = 0;
    1246 
     1555#if ANIMATE_WINDOW_TRANSFORMS == 0
    12471556                sysarg_t pre_x = 0;
    12481557                sysarg_t pre_y = 0;
     
    12501559                sysarg_t pre_height = 0;
    12511560
    1252 #if ANIMATE_WINDOW_TRANSFORMS == 0
    12531561                if (pointer->grab_flags != GF_EMPTY) {
     1562                        if (pointer->ghost.surface) {
     1563                                comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
     1564                                pointer->ghost.surface = NULL;
     1565                        }
    12541566                        comp_window_animate(pointer, top, &pre_x, &pre_y, &pre_width, &pre_height);
    12551567                        dmg_x = pre_x;
     
    12631575
    12641576                        surface_get_resolution(top->surface, &width, &height);
     1577#if ANIMATE_WINDOW_TRANSFORMS == 1
    12651578                        top->fx *= (1.0 / scale_back_x);
    12661579                        top->fy *= (1.0 / scale_back_y);
    12671580                        comp_recalc_transform(top);
     1581#endif
    12681582
    12691583                        /* Commit proper resize action. */
    1270                         event = (window_event_t *) malloc(sizeof(window_event_t));
    1271                         if (event) {
    1272                                 link_initialize(&event->link);
    1273                                 event->type = ET_WINDOW_RESIZE;
     1584                        event_top = (window_event_t *) malloc(sizeof(window_event_t));
     1585                        if (event_top) {
     1586                                link_initialize(&event_top->link);
     1587                                event_top->type = ET_WINDOW_RESIZE;
    12741588
    12751589                                int dx = (int) (((double) width) * (scale_back_x - 1.0));
     
    12771591
    12781592                                if (pointer->grab_flags & GF_RESIZE_X) {
    1279                                         event->data.rsz.width =
     1593                                        event_top->data.rsz.width =
    12801594                                                ((((int) width) + dx) >= 0) ? (width + dx) : 0;
    12811595                                } else {
    1282                                         event->data.rsz.width = width;
     1596                                        event_top->data.rsz.width = width;
    12831597                                }
    12841598
    12851599                                if (pointer->grab_flags & GF_RESIZE_Y) {
    1286                                         event->data.rsz.height =
     1600                                        event_top->data.rsz.height =
    12871601                                                ((((int) height) + dy) >= 0) ? (height + dy) : 0;
    12881602                                } else {
    1289                                         event->data.rsz.height = height;
     1603                                        event_top->data.rsz.height = height;
    12901604                                }
    12911605                        }
     
    12961610                       
    12971611                        /* Notify top-level window about mouse release. */
    1298                         event = (window_event_t *) malloc(sizeof(window_event_t));
    1299                         if (event) {
    1300                                 link_initialize(&event->link);
    1301                                 event->type = ET_POSITION_EVENT;
    1302                                 event->data.pos.pos_id = pointer->id;
    1303                                 event->data.pos.type = POS_RELEASE;
    1304                                 event->data.pos.btn_num = bnum;
    1305                                 event->data.pos.hpos = point_x;
    1306                                 event->data.pos.vpos = point_y;
     1612                        event_top = (window_event_t *) malloc(sizeof(window_event_t));
     1613                        if (event_top) {
     1614                                link_initialize(&event_top->link);
     1615                                event_top->type = ET_POSITION_EVENT;
     1616                                event_top->data.pos.pos_id = pointer->id;
     1617                                event_top->data.pos.type = POS_RELEASE;
     1618                                event_top->data.pos.btn_num = bnum;
     1619                                event_top->data.pos.hpos = point_x;
     1620                                event_top->data.pos.vpos = point_y;
    13071621                        }
    13081622                        pointer->grab_flags = GF_EMPTY;
    1309                        
    1310                 } else if (within_client && (pointer->grab_flags == GF_EMPTY) && (bnum == 1)) {
    1311 
    1312                         /* Bring the window to the foreground. */
    1313                         list_remove(&win->link);
    1314                         list_prepend(&win->link, &window_list);
    1315                         comp_coord_bounding_rect(0, 0, width, height, win->transform,
    1316                             &dmg_x, &dmg_y, &dmg_width, &dmg_height);
    13171623                       
    13181624                } else {
     
    13201626                }
    13211627
    1322                 fibril_mutex_unlock(&window_list_mtx);
    1323 
    1324                 if (dmg_width > 0 && dmg_height > 0) {
    1325                         comp_damage(dmg_x, dmg_y, dmg_width, dmg_height);
    1326                 }
    1327 
    1328                 if (event) {
    1329                         comp_post_event(event);
    1330                 }
     1628        }
     1629
     1630        fibril_mutex_unlock(&pointer_list_mtx);
     1631        fibril_mutex_unlock(&window_list_mtx);
     1632
     1633#if ANIMATE_WINDOW_TRANSFORMS == 0
     1634                comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
     1635                comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
     1636                comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
     1637                comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
     1638#endif
     1639
     1640        if (dmg_width > 0 && dmg_height > 0) {
     1641                comp_damage(dmg_x, dmg_y, dmg_width, dmg_height);
     1642        }
     1643
     1644        if (event_unfocus && win_unfocus) {
     1645                comp_post_event_win(event_unfocus, win_unfocus);
     1646        }
     1647
     1648        if (event_top) {
     1649                comp_post_event_top(event_top);
    13311650        }
    13321651
     
    14521771
    14531772                        fibril_mutex_unlock(&window_list_mtx);
    1454                         comp_post_event(event);
     1773                        comp_post_event_top(event);
    14551774                } else {
    14561775                        fibril_mutex_unlock(&window_list_mtx);
     
    14941813                event->type = ET_WINDOW_CLOSE;
    14951814
    1496                 comp_post_event(event);
     1815                comp_post_event_top(event);
    14971816        } else if (win_switch) {
    14981817                fibril_mutex_lock(&window_list_mtx);
     
    15021821                        list_append(&win1->link, &window_list);
    15031822                        window_t *win2 = (window_t *) list_first(&window_list);
     1823
     1824                        window_event_t *event1 = (window_event_t *) malloc(sizeof(window_event_t));
     1825                        if (event1) {
     1826                                link_initialize(&event1->link);
     1827                                event1->type = ET_WINDOW_UNFOCUS;
     1828                        }
     1829
     1830                        window_event_t *event2 = (window_event_t *) malloc(sizeof(window_event_t));
     1831                        if (event2) {
     1832                                link_initialize(&event2->link);
     1833                                event2->type = ET_WINDOW_FOCUS;
     1834                        }
    15041835
    15051836                        sysarg_t x1 = 0;
     
    15301861
    15311862                        fibril_mutex_unlock(&window_list_mtx);
     1863
     1864                        if (event1 && win1) {
     1865                                comp_post_event_win(event1, win1);
     1866                        }
     1867
     1868                        if (event2 && win2) {
     1869                                comp_post_event_win(event2, win2);
     1870                        }
     1871
    15321872                        comp_damage(x, y, width, height);
    15331873                } else {
     
    16001940                fibril_mutex_lock(&window_list_mtx);
    16011941
    1602                 window_t *red_win = window_create();
     1942                window_t *red_win = window_create(0, 0);
    16031943                red_win->surface = surface_create(250, 150, NULL, 0);
    16041944                pixel_t red_pix = PIXEL(255, 240, 0, 0);
     
    16101950                list_prepend(&red_win->link, &window_list);
    16111951
    1612                 window_t *blue_win = window_create();
     1952                window_t *blue_win = window_create(0, 0);
    16131953                blue_win->surface = surface_create(200, 100, NULL, 0);
    16141954                pixel_t blue_pix = PIXEL(255, 0, 0, 240);
     
    16201960                list_prepend(&blue_win->link, &window_list);
    16211961
    1622                 window_t *helenos_win = window_create();
     1962                window_t *helenos_win = window_create(0, 0);
    16231963                helenos_win->surface = decode_tga((void *) helenos_tga, helenos_tga_size, 0);
    16241964                list_prepend(&helenos_win->link, &window_list);
    16251965
    1626                 window_t *nameic_win = window_create();
     1966                window_t *nameic_win = window_create(0, 0);
    16271967                nameic_win->surface = decode_tga((void *) nameic_tga, nameic_tga_size, 0);
    16281968                list_prepend(&nameic_win->link, &window_list);
     
    16421982                event->data.kbd.c = c;
    16431983
    1644                 comp_post_event(event);
     1984                comp_post_event_top(event);
    16451985        }
    16461986
     
    16932033static void input_disconnect(void)
    16942034{
    1695         pointer_t *pointer = input->user;
     2035        pointer_t *pointer = input->user;
    16962036        input_close(input);
    16972037        pointer_destroy(pointer);
     
    17062046{
    17072047        /* Coordinates of the central pixel. */
    1708         coord_origin = UINT32_MAX / 2;
     2048        coord_origin = UINT32_MAX / 4;
    17092049       
    17102050        /* Color of the viewport background. Must be opaque. */
Note: See TracChangeset for help on using the changeset viewer.