Ignore:
Timestamp:
2012-11-29T07:44:58Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3194d83
Parents:
ff98ce8 (diff), 82edef2 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~petr-koupy/helenos/gui-optim.

The main improvements are:

  • significantly faster rendering (making qemu/non-KVM usable) if user limits himself just to window movement and resizing (i.e. avoiding rotation, scaling and transparency)
  • preview of the result of window transformation is depicted by a "ghost" frame following the mouse pointer
  • changing of window focus feels more natural and intuitive (mouse click handler behaves more like in mainstream operating systems, window titles changes color to reflect whether they have focus or not)
File:
1 edited

Legend:

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

    rff98ce8 re1c6d5df  
    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.