Ignore:
File:
1 edited

Legend:

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

    rd17a4a9 rb8f1a349  
    3434
    3535#include <sys/types.h>
    36 #include <bool.h>
     36#include <stdbool.h>
    3737#include <errno.h>
    3838#include <str_error.h>
     
    8787static sysarg_t coord_origin;
    8888static pixel_t bg_color;
    89 
    90 typedef struct {
    91         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);
    10689
    10790typedef struct {
     
    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;
     
    250266}
    251267
    252 static void comp_coord_from_client(sysarg_t x_in, sysarg_t y_in, transform_t win_trans,
     268static void comp_coord_from_client(double x_in, double y_in, transform_t win_trans,
    253269    sysarg_t *x_out, sysarg_t *y_out)
    254270{
     
    263279}
    264280
    265 static void comp_coord_bounding_rect(sysarg_t x_in, sysarg_t y_in,
    266     sysarg_t w_in, sysarg_t h_in, transform_t win_trans,
     281static void comp_coord_bounding_rect(double x_in, double y_in,
     282    double w_in, double h_in, transform_t win_trans,
    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                (*x_out) = 0;
     306                (*y_out) = 0;
     307                (*w_out) = 0;
     308                (*h_out) = 0;
     309        }
    287310}
    288311
     
    309332                        /* Paint background color. */
    310333                        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);
     334                                pixel_t *dst = pixelmap_pixel_at(
     335                                    surface_pixmap_access(vp->surface), x_dmg_vp - vp->pos.x, y);
     336                                sysarg_t count = w_dmg_vp;
     337                                while (count-- != 0) {
     338                                        *dst++ = bg_color;
    313339                                }
    314340                        }
     341                        surface_add_damaged_region(vp->surface,
     342                            x_dmg_vp - vp->pos.x, y_dmg_vp - vp->pos.y, w_dmg_vp, h_dmg_vp);
    315343
    316344                        transform_t transform;
     
    363391                        list_foreach(pointer_list, link) {
    364392
     393                                pointer_t *ptr = list_get_instance(link, pointer_t, link);
     394                                if (ptr->ghost.surface) {
     395
     396                                        sysarg_t x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost;
     397                                        sysarg_t x_dmg_ghost, y_dmg_ghost, w_dmg_ghost, h_dmg_ghost;
     398                                        surface_get_resolution(ptr->ghost.surface, &w_bnd_ghost, &h_bnd_ghost);
     399                                        comp_coord_bounding_rect(0, 0, w_bnd_ghost, h_bnd_ghost, ptr->ghost.transform,
     400                                            &x_bnd_ghost, &y_bnd_ghost, &w_bnd_ghost, &h_bnd_ghost);
     401                                        bool isec_ghost = rectangle_intersect(
     402                                            x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
     403                                            x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost,
     404                                            &x_dmg_ghost, &y_dmg_ghost, &w_dmg_ghost, &h_dmg_ghost);
     405
     406                                        if (isec_ghost) {
     407                                                /* FIXME: Ghost is currently drawn based on the bounding
     408                                                 * rectangle of the window, which is sufficient as long
     409                                                 * as the windows can be rotated only by 90 degrees.
     410                                                 * For ghost to be compatible with arbitrary-angle
     411                                                 * rotation, it should be drawn as four lines adjusted
     412                                                 * by the transformation matrix. That would however
     413                                                 * require to equip libdraw with line drawing functionality. */
     414
     415                                                transform_t transform = ptr->ghost.transform;
     416                                                double_point_t pos;
     417                                                pos.x = vp->pos.x;
     418                                                pos.y = vp->pos.y;
     419                                                transform_translate(&transform, -pos.x, -pos.y);
     420
     421                                                pixel_t ghost_color;
     422
     423                                                if (y_bnd_ghost == y_dmg_ghost) {
     424                                                        for (sysarg_t x = x_dmg_ghost - vp->pos.x;
     425                                                                    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
     426                                                                ghost_color = surface_get_pixel(vp->surface,
     427                                                                    x, y_dmg_ghost - vp->pos.y);
     428                                                                surface_put_pixel(vp->surface,
     429                                                                    x, y_dmg_ghost - vp->pos.y, INVERT(ghost_color));
     430                                                        }
     431                                                }
     432
     433                                                if (y_bnd_ghost + h_bnd_ghost == y_dmg_ghost + h_dmg_ghost) {
     434                                                        for (sysarg_t x = x_dmg_ghost - vp->pos.x;
     435                                                                    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
     436                                                                ghost_color = surface_get_pixel(vp->surface,
     437                                                                    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1);
     438                                                                surface_put_pixel(vp->surface,
     439                                                                    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1, INVERT(ghost_color));
     440                                                        }
     441                                                }
     442
     443                                                if (x_bnd_ghost == x_dmg_ghost) {
     444                                                        for (sysarg_t y = y_dmg_ghost - vp->pos.y;
     445                                                                    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
     446                                                                ghost_color = surface_get_pixel(vp->surface,
     447                                                                    x_dmg_ghost - vp->pos.x, y);
     448                                                                surface_put_pixel(vp->surface,
     449                                                                    x_dmg_ghost - vp->pos.x, y, INVERT(ghost_color));
     450                                                        }
     451                                                }
     452
     453                                                if (x_bnd_ghost + w_bnd_ghost == x_dmg_ghost + w_dmg_ghost) {
     454                                                        for (sysarg_t y = y_dmg_ghost - vp->pos.y;
     455                                                                    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
     456                                                                ghost_color = surface_get_pixel(vp->surface,
     457                                                                    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y);
     458                                                                surface_put_pixel(vp->surface,
     459                                                                    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y, INVERT(ghost_color));
     460                                                        }
     461                                                }
     462                                        }
     463
     464                                }
     465                        }
     466
     467                        list_foreach(pointer_list, link) {
     468
    365469                                /* Determine what part of the pointer intersects with the
    366470                                 * updated area of the current viewport. */
     
    376480                                if (isec_ptr) {
    377481                                        /* Pointer is currently painted directly by copying pixels.
    378                                          * However, it is possible to draw the painter similarly
     482                                         * However, it is possible to draw the pointer similarly
    379483                                         * as window by using drawctx_transfer. It would allow
    380484                                         * more sophisticated control over drawing, but would also
    381485                                         * cost more regarding the performance. */
    382486
    383                                         pixel_t pix = 0;
    384487                                        sysarg_t x_vp = x_dmg_ptr - vp->pos.x;
    385488                                        sysarg_t y_vp = y_dmg_ptr - vp->pos.y;
     
    388491
    389492                                        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                                                         }
     493                                                pixel_t *src = pixelmap_pixel_at(
     494                                                    surface_pixmap_access(sf_ptr), x_ptr, y_ptr + y);
     495                                                pixel_t *dst = pixelmap_pixel_at(
     496                                                    surface_pixmap_access(vp->surface), x_vp, y_vp + y);
     497                                                sysarg_t count = w_dmg_ptr;
     498                                                while (count-- != 0) {
     499                                                        *dst = (*src & 0xff000000) ? *src : *dst;
     500                                                        ++dst; ++src;
    395501                                                }
    396502                                        }
     503                                        surface_add_damaged_region(vp->surface, x_vp, y_vp, w_dmg_ptr, h_dmg_ptr);
    397504                                }
     505
    398506                        }
    399507                }
     
    441549static void comp_window_damage(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
    442550{
    443         sysarg_t x = IPC_GET_ARG1(*icall);
    444         sysarg_t y = IPC_GET_ARG2(*icall);
    445         sysarg_t width = IPC_GET_ARG3(*icall);
    446         sysarg_t height = IPC_GET_ARG4(*icall);
     551        double x = IPC_GET_ARG1(*icall);
     552        double y = IPC_GET_ARG2(*icall);
     553        double width = IPC_GET_ARG3(*icall);
     554        double height = IPC_GET_ARG4(*icall);
    447555
    448556        if (width == 0 || height == 0) {
     
    450558        } else {
    451559                fibril_mutex_lock(&window_list_mtx);
    452                 comp_coord_bounding_rect(x, y, width, height,
    453                     win->transform, &x, &y, &width, &height);
     560                sysarg_t x_dmg_glob, y_dmg_glob, w_dmg_glob, h_dmg_glob;
     561                comp_coord_bounding_rect(x - 1, y - 1, width + 2, height + 2,
     562                    win->transform, &x_dmg_glob, &y_dmg_glob, &w_dmg_glob, &h_dmg_glob);
    454563                fibril_mutex_unlock(&window_list_mtx);
    455                 comp_damage(x, y, width, height);
     564                comp_damage(x_dmg_glob, y_dmg_glob, w_dmg_glob, h_dmg_glob);
    456565        }
    457566
     
    468577                pointer_t *pointer = list_get_instance(link, pointer_t, link);
    469578                if (pointer->id == pos_id) {
    470                         pointer->grab_flags = grab_flags;
     579                        pointer->grab_flags = pointer->pressed ? grab_flags : GF_EMPTY;
    471580                        // TODO change pointer->state according to grab_flags
    472581                        break;
     
    541650}
    542651
     652static void comp_post_event_win(window_event_t *event, window_t *target)
     653{
     654        fibril_mutex_lock(&window_list_mtx);
     655        window_t *window = NULL;
     656        list_foreach(window_list, link) {
     657                window = list_get_instance(link, window_t, link);
     658                if (window == target) {
     659                        prodcons_produce(&window->queue, &event->link);
     660                }
     661        }
     662        if (!window) {
     663                free(event);
     664        }
     665        fibril_mutex_unlock(&window_list_mtx);
     666}
     667
     668static void comp_post_event_top(window_event_t *event)
     669{
     670        fibril_mutex_lock(&window_list_mtx);
     671        window_t *win = (window_t *) list_first(&window_list);
     672        if (win) {
     673                prodcons_produce(&win->queue, &event->link);
     674        } else {
     675                free(event);
     676        }
     677        fibril_mutex_unlock(&window_list_mtx);
     678}
     679
    543680static void comp_window_close(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
    544681{
     
    546683        fibril_mutex_lock(&window_list_mtx);
    547684        list_remove(&win->link);
     685        window_t *win_focus = (window_t *) list_first(&window_list);
     686        window_event_t *event_focus = (window_event_t *) malloc(sizeof(window_event_t));
     687        if (event_focus) {
     688                link_initialize(&event_focus->link);
     689                event_focus->type = ET_WINDOW_FOCUS;
     690        }
    548691        fibril_mutex_unlock(&window_list_mtx);
     692
     693        if (event_focus && win_focus) {
     694                comp_post_event_win(event_focus, win_focus);
     695        }
    549696
    550697        /* Calculate damage. */
     
    601748                        fibril_mutex_lock(&window_list_mtx);
    602749
    603                         window_t *win = window_create();
     750                        window_t *win = window_create(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    604751                        if (!win) {
    605752                                async_answer_2(callid, ENOMEM, 0, 0);
     
    630777                        }
    631778
     779                        window_t *win_unfocus = (window_t *) list_first(&window_list);
    632780                        list_prepend(&win->link, &window_list);
     781
     782                        window_event_t *event_unfocus = (window_event_t *) malloc(sizeof(window_event_t));
     783                        if (event_unfocus) {
     784                                link_initialize(&event_unfocus->link);
     785                                event_unfocus->type = ET_WINDOW_UNFOCUS;
     786                        }
    633787                       
    634788                        async_answer_2(callid, EOK, win->in_dsid, win->out_dsid);
    635789                        fibril_mutex_unlock(&window_list_mtx);
     790                       
     791                        if (event_unfocus && win_unfocus) {
     792                                comp_post_event_win(event_unfocus, win_unfocus);
     793                        }
     794
    636795                        return;
    637796                } else {
     
    9531112}
    9541113
    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 
    9671114static void comp_recalc_transform(window_t *win)
    9681115{
     
    9731120        transform_t scale;
    9741121        transform_identity(&scale);
    975         transform_scale(&scale, win->fx, win->fy);
     1122        if (win->fx != 1 || win->fy != 1) {
     1123                transform_scale(&scale, win->fx, win->fy);
     1124        }
    9761125
    9771126        transform_t rotate;
    9781127        transform_identity(&rotate);
    979         transform_rotate(&rotate, win->angle);
     1128        if (win->angle != 0) {
     1129                transform_rotate(&rotate, win->angle);
     1130        }
    9801131
    9811132        transform_t transform;
     
    9941145
    9951146static 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)
     1147    sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
    9971148{
    9981149        /* window_list_mtx locked by caller */
     1150        /* pointer_list_mtx locked by caller */
    9991151
    10001152        int dx = pointer->accum.x;
     
    10201172                }
    10211173
    1022                 if (scale || resize) {
     1174                if ((scale || resize) && (win->angle != 0)) {
    10231175                        transform_t rotate;
    10241176                        transform_identity(&rotate);
     
    10371189                double _dx = dx;
    10381190                double _dy = dy;
    1039                 transform_t unrotate;
    1040                 transform_identity(&unrotate);
    1041                 transform_rotate(&unrotate, -win->angle);
    1042                 transform_apply_linear(&unrotate, &_dx, &_dy);
     1191                if (win->angle != 0) {
     1192                        transform_t unrotate;
     1193                        transform_identity(&unrotate);
     1194                        transform_rotate(&unrotate, -win->angle);
     1195                        transform_apply_linear(&unrotate, &_dx, &_dy);
     1196                }
    10431197                _dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
    10441198                _dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
    10451199
    10461200                if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
    1047                         double fx = 1.0 + (_dx / (width * win->fx));
     1201                        double fx = 1.0 + (_dx / ((width - 1) * win->fx));
    10481202                        if (fx > 0) {
     1203#if ANIMATE_WINDOW_TRANSFORMS == 0
     1204                                if (scale) win->fx *= fx;
     1205#endif
     1206#if ANIMATE_WINDOW_TRANSFORMS == 1
    10491207                                win->fx *= fx;
     1208#endif
    10501209                                scale_back_x *= fx;
    10511210                        }
     
    10531212
    10541213                if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
    1055                         double fy = 1.0 + (_dy / (height * win->fy));
     1214                        double fy = 1.0 + (_dy / ((height - 1) * win->fy));
    10561215                        if (fy > 0) {
     1216#if ANIMATE_WINDOW_TRANSFORMS == 0
     1217                                if (scale) win->fy *= fy;
     1218#endif
     1219#if ANIMATE_WINDOW_TRANSFORMS == 1
    10571220                                win->fy *= fy;
     1221#endif
    10581222                                scale_back_y *= fy;
    10591223                        }
     
    10711235            dmg_x, dmg_y, dmg_width, dmg_height);
    10721236}
     1237
     1238#if ANIMATE_WINDOW_TRANSFORMS == 0
     1239static void comp_ghost_animate(pointer_t *pointer,
     1240    desktop_rect_t *rect1, desktop_rect_t *rect2, desktop_rect_t *rect3, desktop_rect_t *rect4)
     1241{
     1242        /* window_list_mtx locked by caller */
     1243        /* pointer_list_mtx locked by caller */
     1244
     1245        int dx = pointer->accum_ghost.x;
     1246        int dy = pointer->accum_ghost.y;
     1247        pointer->accum_ghost.x = 0;
     1248        pointer->accum_ghost.y = 0;
     1249
     1250        bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
     1251        bool scale = (pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_SCALE_Y);
     1252        bool resize = (pointer->grab_flags & GF_RESIZE_X) || (pointer->grab_flags & GF_RESIZE_Y);
     1253
     1254        sysarg_t width, height;
     1255        surface_get_resolution(pointer->ghost.surface, &width, &height);
     1256
     1257        if (move) {
     1258                double cx = 0;
     1259                double cy = 0;
     1260                if (pointer->grab_flags & GF_MOVE_X) {
     1261                        cx = 1;
     1262                }
     1263                if (pointer->grab_flags & GF_MOVE_Y) {
     1264                        cy = 1;
     1265                }
     1266
     1267                if (scale || resize) {
     1268                        transform_t rotate;
     1269                        transform_identity(&rotate);
     1270                        transform_rotate(&rotate, pointer->ghost.angle);
     1271                        transform_apply_linear(&rotate, &cx, &cy);
     1272                }
     1273
     1274                cx = (cx < 0) ? (-1 * cx) : cx;
     1275                cy = (cy < 0) ? (-1 * cy) : cy;
     1276
     1277                pointer->ghost.dx += (cx * dx);
     1278                pointer->ghost.dy += (cy * dy);
     1279        }
     1280
     1281        if (scale || resize) {
     1282                double _dx = dx;
     1283                double _dy = dy;
     1284                transform_t unrotate;
     1285                transform_identity(&unrotate);
     1286                transform_rotate(&unrotate, -pointer->ghost.angle);
     1287                transform_apply_linear(&unrotate, &_dx, &_dy);
     1288                _dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
     1289                _dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
     1290
     1291                if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
     1292                        double fx = 1.0 + (_dx / ((width - 1) * pointer->ghost.fx));
     1293                        pointer->ghost.fx *= fx;
     1294                }
     1295
     1296                if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
     1297                        double fy = 1.0 + (_dy / ((height - 1) * pointer->ghost.fy));
     1298                        pointer->ghost.fy *= fy;
     1299                }
     1300        }
     1301
     1302        sysarg_t x1, y1, width1, height1;
     1303        sysarg_t x2, y2, width2, height2;
     1304        comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
     1305            &x1, &y1, &width1, &height1);
     1306        comp_recalc_transform(&pointer->ghost);
     1307        comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
     1308            &x2, &y2, &width2, &height2);
     1309
     1310        sysarg_t x_u, y_u, w_u, h_u;
     1311        rectangle_union(x1, y1, width1, height1, x2, y2, width2, height2,
     1312            &x_u, &y_u, &w_u, &h_u);
     1313
     1314        sysarg_t x_i, y_i, w_i, h_i;
     1315        rectangle_intersect(x1, y1, width1, height1, x2, y2, width2, height2,
     1316            &x_i, &y_i, &w_i, &h_i);
     1317
     1318        if (w_i == 0 || h_i == 0) {
     1319                rect1->x = x_u; rect2->x = 0; rect3->x = 0; rect4->x = 0;
     1320                rect1->y = y_u; rect2->y = 0; rect3->y = 0; rect4->y = 0;
     1321                rect1->w = w_u; rect2->w = 0; rect3->w = 0; rect4->w = 0;
     1322                rect1->h = h_u; rect2->h = 0; rect3->h = 0; rect4->h = 0;
     1323        } else {
     1324                rect1->x = x_u;
     1325                rect1->y = y_u;
     1326                rect1->w = x_i - x_u + 1;
     1327                rect1->h = h_u;
     1328
     1329                rect2->x = x_u;
     1330                rect2->y = y_u;
     1331                rect2->w = w_u;
     1332                rect2->h = y_i - y_u + 1;
     1333
     1334                rect3->x = x_i + w_i - 1;
     1335                rect3->y = y_u;
     1336                rect3->w = w_u - w_i - x_i + x_u + 1;
     1337                rect3->h = h_u;
     1338               
     1339                rect4->x = x_u;
     1340                rect4->y = y_i + h_i - 1;
     1341                rect4->w = w_u;
     1342                rect4->h = h_u - h_i - y_i + y_u + 1;
     1343        }
     1344}
     1345#endif
    10731346
    10741347static int comp_abs_move(input_t *input, unsigned x , unsigned y,
     
    11251398
    11261399        fibril_mutex_lock(&window_list_mtx);
     1400        fibril_mutex_lock(&pointer_list_mtx);
    11271401        window_t *top = (window_t *) list_first(&window_list);
    11281402        if (top && top->surface) {
     
    11361410                        within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
    11371411                            top->transform, width, height, &point_x, &point_y);
    1138                         fibril_mutex_unlock(&window_list_mtx);
    1139 
     1412
     1413                        window_event_t *event = NULL;
    11401414                        if (within_client) {
    1141                                 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     1415                                event = (window_event_t *) malloc(sizeof(window_event_t));
    11421416                                if (event) {
    11431417                                        link_initialize(&event->link);
     
    11481422                                        event->data.pos.hpos = point_x;
    11491423                                        event->data.pos.vpos = point_y;
    1150                                         comp_post_event(event);
    11511424                                }
    11521425                        }
     1426
     1427                        fibril_mutex_unlock(&pointer_list_mtx);
     1428                        fibril_mutex_unlock(&window_list_mtx);
     1429
     1430                        if (event) {
     1431                                comp_post_event_top(event);
     1432                        }
     1433
    11531434                } else {
    11541435                        /* Pointer is grabbed by top-level window action. */
    11551436                        pointer->accum.x += dx;
    11561437                        pointer->accum.y += dy;
     1438                        pointer->accum_ghost.x += dx;
     1439                        pointer->accum_ghost.y += dy;
     1440#if ANIMATE_WINDOW_TRANSFORMS == 0
     1441                        if (pointer->ghost.surface == NULL) {
     1442                                pointer->ghost.surface = top->surface;
     1443                                pointer->ghost.dx = top->dx;
     1444                                pointer->ghost.dy = top->dy;
     1445                                pointer->ghost.fx = top->fx;
     1446                                pointer->ghost.fy = top->fy;
     1447                                pointer->ghost.angle = top->angle;
     1448                                pointer->ghost.transform = top->transform;
     1449                        }
     1450                        desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
     1451                        comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
     1452#endif
    11571453#if ANIMATE_WINDOW_TRANSFORMS == 1
    11581454                        sysarg_t x, y, width, height;
    11591455                        comp_window_animate(pointer, top, &x, &y, &width, &height);
    11601456#endif
     1457                        fibril_mutex_unlock(&pointer_list_mtx);
    11611458                        fibril_mutex_unlock(&window_list_mtx);
     1459#if ANIMATE_WINDOW_TRANSFORMS == 0
     1460                        comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
     1461                        comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
     1462                        comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
     1463                        comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
     1464#endif
    11621465#if ANIMATE_WINDOW_TRANSFORMS == 1
    11631466                        comp_damage(x, y, width, height);
     
    11651468                }
    11661469        } else {
     1470                fibril_mutex_unlock(&pointer_list_mtx);
    11671471                fibril_mutex_unlock(&window_list_mtx);
    11681472        }
     
    11741478{
    11751479        pointer_t *pointer = input_pointer(input);
     1480
     1481        fibril_mutex_lock(&window_list_mtx);
     1482        fibril_mutex_lock(&pointer_list_mtx);
     1483        window_t *win = NULL;
     1484        sysarg_t point_x = 0;
     1485        sysarg_t point_y = 0;
     1486        sysarg_t width, height;
     1487        bool within_client = false;
     1488
     1489        /* Determine the window which the mouse click belongs to. */
     1490        list_foreach(window_list, link) {
     1491                win = list_get_instance(link, window_t, link);
     1492                if (win->surface) {
     1493                        surface_get_resolution(win->surface, &width, &height);
     1494                        within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
     1495                            win->transform, width, height, &point_x, &point_y);
     1496                }
     1497                if (within_client) {
     1498                        break;
     1499                }
     1500        }
     1501
     1502        /* Check whether the window is top-level window. */
     1503        window_t *top = (window_t *) list_first(&window_list);
     1504        if (!win || !top) {
     1505                fibril_mutex_unlock(&pointer_list_mtx);
     1506                fibril_mutex_unlock(&window_list_mtx);
     1507                return EOK;
     1508        }
     1509
     1510        window_event_t *event_top = NULL;
     1511        window_event_t *event_unfocus = NULL;
     1512        window_t *win_unfocus = NULL;
     1513        sysarg_t dmg_x, dmg_y;
     1514        sysarg_t dmg_width = 0;
     1515        sysarg_t dmg_height = 0;
     1516       
     1517#if ANIMATE_WINDOW_TRANSFORMS == 0
     1518        desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
     1519#endif
    11761520
    11771521        if (bpress) {
     
    11801524                pointer->pressed = true;
    11811525
    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. */
     1526                /* Bring the window to the foreground. */
     1527                if ((win != top) && within_client) {
     1528                        win_unfocus = (window_t *) list_first(&window_list);
     1529                        list_remove(&win->link);
     1530                        list_prepend(&win->link, &window_list);
     1531                        event_unfocus = (window_event_t *) malloc(sizeof(window_event_t));
     1532                        if (event_unfocus) {
     1533                                link_initialize(&event_unfocus->link);
     1534                                event_unfocus->type = ET_WINDOW_UNFOCUS;
     1535                        }
     1536                        comp_coord_bounding_rect(0, 0, width, height, win->transform,
     1537                            &dmg_x, &dmg_y, &dmg_width, &dmg_height);
     1538                }
     1539
     1540                /* Notify top-level window about mouse press. */
    11961541                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                 }
     1542                        event_top = (window_event_t *) malloc(sizeof(window_event_t));
     1543                        if (event_top) {
     1544                                link_initialize(&event_top->link);
     1545                                event_top->type = ET_POSITION_EVENT;
     1546                                event_top->data.pos.pos_id = pointer->id;
     1547                                event_top->data.pos.type = POS_PRESS;
     1548                                event_top->data.pos.btn_num = bnum;
     1549                                event_top->data.pos.hpos = point_x;
     1550                                event_top->data.pos.vpos = point_y;
     1551                        }
     1552                        pointer->grab_flags = GF_EMPTY;
     1553                }
     1554
    12111555        } else if (pointer->pressed && pointer->btn_num == (unsigned)bnum) {
    12121556                pointer->pressed = false;
    12131557
    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 
     1558#if ANIMATE_WINDOW_TRANSFORMS == 0
    12471559                sysarg_t pre_x = 0;
    12481560                sysarg_t pre_y = 0;
     
    12501562                sysarg_t pre_height = 0;
    12511563
    1252 #if ANIMATE_WINDOW_TRANSFORMS == 0
    12531564                if (pointer->grab_flags != GF_EMPTY) {
     1565                        if (pointer->ghost.surface) {
     1566                                comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
     1567                                pointer->ghost.surface = NULL;
     1568                        }
    12541569                        comp_window_animate(pointer, top, &pre_x, &pre_y, &pre_width, &pre_height);
    12551570                        dmg_x = pre_x;
     
    12631578
    12641579                        surface_get_resolution(top->surface, &width, &height);
     1580#if ANIMATE_WINDOW_TRANSFORMS == 1
    12651581                        top->fx *= (1.0 / scale_back_x);
    12661582                        top->fy *= (1.0 / scale_back_y);
    12671583                        comp_recalc_transform(top);
     1584#endif
    12681585
    12691586                        /* 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;
     1587                        event_top = (window_event_t *) malloc(sizeof(window_event_t));
     1588                        if (event_top) {
     1589                                link_initialize(&event_top->link);
     1590                                event_top->type = ET_WINDOW_RESIZE;
    12741591
    12751592                                int dx = (int) (((double) width) * (scale_back_x - 1.0));
     
    12771594
    12781595                                if (pointer->grab_flags & GF_RESIZE_X) {
    1279                                         event->data.rsz.width =
     1596                                        event_top->data.rsz.width =
    12801597                                                ((((int) width) + dx) >= 0) ? (width + dx) : 0;
    12811598                                } else {
    1282                                         event->data.rsz.width = width;
     1599                                        event_top->data.rsz.width = width;
    12831600                                }
    12841601
    12851602                                if (pointer->grab_flags & GF_RESIZE_Y) {
    1286                                         event->data.rsz.height =
     1603                                        event_top->data.rsz.height =
    12871604                                                ((((int) height) + dy) >= 0) ? (height + dy) : 0;
    12881605                                } else {
    1289                                         event->data.rsz.height = height;
     1606                                        event_top->data.rsz.height = height;
    12901607                                }
    12911608                        }
     
    12961613                       
    12971614                        /* 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;
     1615                        event_top = (window_event_t *) malloc(sizeof(window_event_t));
     1616                        if (event_top) {
     1617                                link_initialize(&event_top->link);
     1618                                event_top->type = ET_POSITION_EVENT;
     1619                                event_top->data.pos.pos_id = pointer->id;
     1620                                event_top->data.pos.type = POS_RELEASE;
     1621                                event_top->data.pos.btn_num = bnum;
     1622                                event_top->data.pos.hpos = point_x;
     1623                                event_top->data.pos.vpos = point_y;
    13071624                        }
    13081625                        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);
    13171626                       
    13181627                } else {
     
    13201629                }
    13211630
    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                 }
     1631        }
     1632
     1633        fibril_mutex_unlock(&pointer_list_mtx);
     1634        fibril_mutex_unlock(&window_list_mtx);
     1635
     1636#if ANIMATE_WINDOW_TRANSFORMS == 0
     1637                comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
     1638                comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
     1639                comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
     1640                comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
     1641#endif
     1642
     1643        if (dmg_width > 0 && dmg_height > 0) {
     1644                comp_damage(dmg_x, dmg_y, dmg_width, dmg_height);
     1645        }
     1646
     1647        if (event_unfocus && win_unfocus) {
     1648                comp_post_event_win(event_unfocus, win_unfocus);
     1649        }
     1650
     1651        if (event_top) {
     1652                comp_post_event_top(event_top);
    13311653        }
    13321654
     
    14521774
    14531775                        fibril_mutex_unlock(&window_list_mtx);
    1454                         comp_post_event(event);
     1776                        comp_post_event_top(event);
    14551777                } else {
    14561778                        fibril_mutex_unlock(&window_list_mtx);
     
    14941816                event->type = ET_WINDOW_CLOSE;
    14951817
    1496                 comp_post_event(event);
     1818                comp_post_event_top(event);
    14971819        } else if (win_switch) {
    14981820                fibril_mutex_lock(&window_list_mtx);
     
    15021824                        list_append(&win1->link, &window_list);
    15031825                        window_t *win2 = (window_t *) list_first(&window_list);
     1826
     1827                        window_event_t *event1 = (window_event_t *) malloc(sizeof(window_event_t));
     1828                        if (event1) {
     1829                                link_initialize(&event1->link);
     1830                                event1->type = ET_WINDOW_UNFOCUS;
     1831                        }
     1832
     1833                        window_event_t *event2 = (window_event_t *) malloc(sizeof(window_event_t));
     1834                        if (event2) {
     1835                                link_initialize(&event2->link);
     1836                                event2->type = ET_WINDOW_FOCUS;
     1837                        }
    15041838
    15051839                        sysarg_t x1 = 0;
     
    15301864
    15311865                        fibril_mutex_unlock(&window_list_mtx);
     1866
     1867                        if (event1 && win1) {
     1868                                comp_post_event_win(event1, win1);
     1869                        }
     1870
     1871                        if (event2 && win2) {
     1872                                comp_post_event_win(event2, win2);
     1873                        }
     1874
    15321875                        comp_damage(x, y, width, height);
    15331876                } else {
     
    16001943                fibril_mutex_lock(&window_list_mtx);
    16011944
    1602                 window_t *red_win = window_create();
     1945                window_t *red_win = window_create(0, 0);
    16031946                red_win->surface = surface_create(250, 150, NULL, 0);
    16041947                pixel_t red_pix = PIXEL(255, 240, 0, 0);
     
    16101953                list_prepend(&red_win->link, &window_list);
    16111954
    1612                 window_t *blue_win = window_create();
     1955                window_t *blue_win = window_create(0, 0);
    16131956                blue_win->surface = surface_create(200, 100, NULL, 0);
    16141957                pixel_t blue_pix = PIXEL(255, 0, 0, 240);
     
    16191962                }
    16201963                list_prepend(&blue_win->link, &window_list);
    1621 
    1622                 window_t *helenos_win = window_create();
    1623                 helenos_win->surface = decode_tga((void *) helenos_tga, helenos_tga_size, 0);
    1624                 list_prepend(&helenos_win->link, &window_list);
    1625 
    1626                 window_t *nameic_win = window_create();
     1964               
     1965                window_t *nameic_win = window_create(0, 0);
    16271966                nameic_win->surface = decode_tga((void *) nameic_tga, nameic_tga_size, 0);
    16281967                list_prepend(&nameic_win->link, &window_list);
     
    16421981                event->data.kbd.c = c;
    16431982
    1644                 comp_post_event(event);
     1983                comp_post_event_top(event);
    16451984        }
    16461985
     
    16932032static void input_disconnect(void)
    16942033{
    1695         pointer_t *pointer = input->user;
     2034        pointer_t *pointer = input->user;
    16962035        input_close(input);
    16972036        pointer_destroy(pointer);
     
    17062045{
    17072046        /* Coordinates of the central pixel. */
    1708         coord_origin = UINT32_MAX / 2;
     2047        coord_origin = UINT32_MAX / 4;
    17092048       
    17102049        /* Color of the viewport background. Must be opaque. */
Note: See TracChangeset for help on using the changeset viewer.