Changeset e1c6d5df in mainline


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)
Location:
uspace
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/vdemo/vdemo.c

    rff98ce8 re1c6d5df  
    110110{
    111111        if (argc >= 2) {
    112                 window_t *main_window = window_open(argv[1], true, true, "vdemo");
     112                window_t *main_window = window_open(argv[1], true, true, "vdemo", 0, 0);
    113113                if (!main_window) {
    114114                        printf("Cannot open main window.\n");
  • uspace/app/vlaunch/vlaunch.c

    rff98ce8 re1c6d5df  
    9898       
    9999        winreg = argv[1];
    100         window_t *main_window = window_open(argv[1], true, true, "vlaunch");
     100        window_t *main_window = window_open(argv[1], true, true, "vlaunch", 0, 0);
    101101        if (!main_window) {
    102102                printf("Cannot open main window.\n");
  • uspace/app/vterm/vterm.c

    rff98ce8 re1c6d5df  
    4949        }
    5050       
    51         window_t *main_window = window_open(argv[1], true, true, "vterm");
     51        window_t *main_window = window_open(argv[1], true, true, "vterm", 0, 0);
    5252        if (!main_window) {
    5353                printf("%s: Cannot open main window.\n", NAME);
  • uspace/drv/fb/kfb/port.c

    rff98ce8 re1c6d5df  
    163163                /* Faster damage routine ignoring offsets. */
    164164                for (sysarg_t y = y0; y < height + y0; ++y) {
     165                        pixel_t *pixel = pixelmap_pixel_at(map, x0, y);
    165166                        for (sysarg_t x = x0; x < width + x0; ++x) {
    166                                 kfb.pixel2visual(kfb.addr + FB_POS(x, y),
    167                                     *pixelmap_pixel_at(map, x, y));
     167                                kfb.pixel2visual(kfb.addr + FB_POS(x, y), *pixel++);
    168168                        }
    169169                }
  • uspace/lib/c/generic/io/window.c

    rff98ce8 re1c6d5df  
    4040#include <stdio.h>
    4141
    42 int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out)
     42int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out,
     43    sysarg_t x_offset, sysarg_t y_offset)
    4344{
    4445        async_exch_t *exch = async_exchange_begin(sess);
    45         int ret = async_req_0_2(exch, WINDOW_REGISTER, in, out);
     46        int ret = async_req_2_2(exch, WINDOW_REGISTER, x_offset, y_offset, in, out);
    4647        async_exchange_end(exch);
    4748
  • uspace/lib/c/include/io/pixel.h

    rff98ce8 re1c6d5df  
    4242        ((channel) >> (8 - (bits)))
    4343
     44#define INVERT(pixel) ((pixel) ^ 0x00ffffff)
     45
    4446#define ALPHA(pixel)  ((pixel) >> 24)
    4547#define RED(pixel)    (((pixel) & 0x00ff0000) >> 16)
  • uspace/lib/c/include/io/pixelmap.h

    rff98ce8 re1c6d5df  
    5252    sysarg_t y)
    5353{
    54         size_t offset = y * pixelmap->width + x;
    55         pixel_t *pixel = pixelmap->data + offset;
    56         return pixel;
     54        if (x < pixelmap->width && y < pixelmap->height) {
     55                size_t offset = y * pixelmap->width + x;
     56                pixel_t *pixel = pixelmap->data + offset;
     57                return pixel;
     58        } else {
     59                return NULL;
     60        }
    5761}
    5862
  • uspace/lib/c/include/io/window.h

    rff98ce8 re1c6d5df  
    7171        ET_POSITION_EVENT,
    7272        ET_SIGNAL_EVENT,
     73        ET_WINDOW_FOCUS,
     74        ET_WINDOW_UNFOCUS,
    7375        ET_WINDOW_RESIZE,
    7476        ET_WINDOW_REFRESH,
     
    100102} window_grab_flags_t;
    101103
    102 extern int win_register(async_sess_t *, service_id_t *, service_id_t *);
     104extern int win_register(async_sess_t *, service_id_t *, service_id_t *, sysarg_t, sysarg_t);
    103105
    104106extern int win_get_event(async_sess_t *, window_event_t *);
  • uspace/lib/draw/drawctx.c

    rff98ce8 re1c6d5df  
    129129        }
    130130
    131         bool clipped = false;
    132         bool masked = false;
    133 
    134         for (sysarg_t _y = y; _y < y + height; ++_y) {
    135                 for (sysarg_t _x = x; _x < x + width; ++_x) {
    136                         if (context->shall_clip) {
    137                                 clipped = _x < context->clip_x && _x >= context->clip_width
    138                                     && _y < context->clip_y && _y >= context->clip_height;
    139                         }
    140                        
    141                         if (context->mask) {
    142                                 pixel_t p = surface_get_pixel(context->mask, _x, _y);
    143                                 masked = p > 0 ? false : true;
    144                         }
    145 
    146                         if (!clipped && !masked) {
    147                                 pixel_t p_src = source_determine_pixel(context->source, _x, _y);
    148                                 pixel_t p_dst = surface_get_pixel(context->surface, _x, _y);
    149                                 pixel_t p_res = context->compose(p_src, p_dst);
    150                                 surface_put_pixel(context->surface, _x, _y, p_res);
     131        bool transfer_fast = source_is_fast(context->source)
     132            && (context->shall_clip == false)
     133            && (context->mask == NULL)
     134            && (context->compose == compose_src || context->compose == compose_over);
     135
     136        if (transfer_fast) {
     137
     138                for (sysarg_t _y = y; _y < y + height; ++_y) {
     139                        pixel_t *src = source_direct_access(context->source, x, _y);
     140                        pixel_t *dst = pixelmap_pixel_at(surface_pixmap_access(context->surface), x, _y);
     141                        if (src && dst) {
     142                                sysarg_t count = width;
     143                                while (count-- != 0) {
     144                                        *dst++ = *src++;
     145                                }
    151146                        }
    152147                }
     148                surface_add_damaged_region(context->surface, x, y, width, height);
     149
     150        } else {
     151
     152                bool clipped = false;
     153                bool masked = false;
     154                for (sysarg_t _y = y; _y < y + height; ++_y) {
     155                        for (sysarg_t _x = x; _x < x + width; ++_x) {
     156                                if (context->shall_clip) {
     157                                        clipped = _x < context->clip_x && _x >= context->clip_width
     158                                            && _y < context->clip_y && _y >= context->clip_height;
     159                                }
     160
     161                                if (context->mask) {
     162                                        pixel_t p = surface_get_pixel(context->mask, _x, _y);
     163                                        masked = p > 0 ? false : true;
     164                                }
     165
     166                                if (!clipped && !masked) {
     167                                        pixel_t p_src = source_determine_pixel(context->source, _x, _y);
     168                                        pixel_t p_dst = surface_get_pixel(context->surface, _x, _y);
     169                                        pixel_t p_res = context->compose(p_src, p_dst);
     170                                        surface_put_pixel(context->surface, _x, _y, p_res);
     171                                }
     172                        }
     173                }
     174
    153175        }
    154176}
  • uspace/lib/draw/source.c

    rff98ce8 re1c6d5df  
    9090}
    9191
     92bool source_is_fast(source_t *source)
     93{
     94        return (source->mask == NULL)
     95            && (source->alpha == (pixel_t) PIXEL(255, 0, 0, 0))
     96            && (source->texture != NULL)
     97            && (source->texture_tile == false)
     98            && transform_is_fast(&source->transform);
     99}
     100
     101pixel_t *source_direct_access(source_t *source, double x, double y)
     102{
     103        assert(source_is_fast(source));
     104
     105        long _x = (long) (x + source->transform.m[0][2]);
     106        long _y = (long) (y + source->transform.m[1][2]);
     107
     108        return pixelmap_pixel_at(
     109            surface_pixmap_access(source->texture), (sysarg_t) _x, (sysarg_t) _y);
     110}
     111
    92112pixel_t source_determine_pixel(source_t *source, double x, double y)
    93113{
  • uspace/lib/draw/source.h

    rff98ce8 re1c6d5df  
    7171extern void source_set_mask(source_t *, surface_t *, bool);
    7272
     73extern bool source_is_fast(source_t *);
     74extern pixel_t *source_direct_access(source_t *, double, double);
    7375extern pixel_t source_determine_pixel(source_t *, double, double);
    7476
  • uspace/lib/draw/surface.c

    rff98ce8 re1c6d5df  
    143143}
    144144
     145void surface_add_damaged_region(surface_t *surface, surface_coord_t x, surface_coord_t y,
     146    surface_coord_t width, surface_coord_t height)
     147{
     148        surface->dirty_x_lo = surface->dirty_x_lo > x ? x : surface->dirty_x_lo;
     149        surface->dirty_y_lo = surface->dirty_y_lo > y ? y : surface->dirty_y_lo;
     150
     151        surface_coord_t x_hi = x + width - 1;
     152        surface_coord_t y_hi = y + height - 1;
     153
     154        surface->dirty_x_hi = surface->dirty_x_hi < x_hi ? x_hi : surface->dirty_x_hi;
     155        surface->dirty_y_hi = surface->dirty_y_hi < y_hi ? y_hi : surface->dirty_y_hi;
     156}
     157
    145158void surface_reset_damaged_region(surface_t *surface)
    146159{
     
    158171        surface->dirty_y_hi = surface->dirty_y_hi < y ? y : surface->dirty_y_hi;
    159172
    160         if (x < surface->pixmap.width && y < surface->pixmap.height) {
    161                 pixelmap_put_pixel(&surface->pixmap, x, y, pixel);
    162         }
     173        pixelmap_put_pixel(&surface->pixmap, x, y, pixel);
    163174}
    164175
    165176pixel_t surface_get_pixel(surface_t *surface, surface_coord_t x, surface_coord_t y)
    166177{
    167         if (x < surface->pixmap.width && y < surface->pixmap.height) {
    168                 return pixelmap_get_pixel(&surface->pixmap, x, y);
    169         } else {
    170                 return 0;
    171         }
     178        return pixelmap_get_pixel(&surface->pixmap, x, y);
    172179}
    173180
  • uspace/lib/draw/surface.h

    rff98ce8 re1c6d5df  
    6161extern void surface_get_damaged_region(surface_t *, surface_coord_t *, surface_coord_t *,
    6262    surface_coord_t *, surface_coord_t *);
     63extern void surface_add_damaged_region(surface_t *, surface_coord_t , surface_coord_t ,
     64    surface_coord_t , surface_coord_t );
    6365extern void surface_reset_damaged_region(surface_t *);
    6466
  • uspace/lib/gui/terminal.c

    rff98ce8 re1c6d5df  
    196196        uint16_t glyph = fb_font_glyph(field->ch);
    197197       
    198         // FIXME: This font drawing routine is shamelessly
    199         //        suboptimal. It should be optimized for
    200         //        aligned memory transfers, etc.
    201        
    202198        for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
    203                 for (unsigned int x = 0; x < FONT_WIDTH; x++) {
    204                         pixel_t pixel =
    205                             (fb_font[glyph][y] & (1 << (7 - x))) ? fgcolor : bgcolor;
    206                         surface_put_pixel(surface, bx + x, by + y, pixel);
     199                pixel_t *dst = pixelmap_pixel_at(
     200                    surface_pixmap_access(surface), bx, by + y);
     201                pixel_t *dst_max = pixelmap_pixel_at(
     202                    surface_pixmap_access(surface), bx + FONT_WIDTH - 1, by + y);
     203                if (!dst || !dst_max) continue;
     204                int count = FONT_WIDTH;
     205                while (count-- != 0) {
     206                        *dst++ = (fb_font[glyph][y] & (1 << count)) ? fgcolor : bgcolor;
    207207                }
    208208        }
     209        surface_add_damaged_region(surface, bx, by, FONT_WIDTH, FONT_SCANLINES);
    209210}
    210211
  • uspace/lib/gui/window.c

    rff98ce8 re1c6d5df  
    6666
    6767static pixel_t border_color = PIXEL(255, 0, 0, 0);
    68 static pixel_t header_bgcolor = PIXEL(255, 25, 25, 112);
    69 static pixel_t header_fgcolor = PIXEL(255, 255, 255, 255);
     68static pixel_t header_bg_focus_color = PIXEL(255, 25, 25, 112);
     69static pixel_t header_fg_focus_color = PIXEL(255, 255, 255, 255);
     70static pixel_t header_bg_unfocus_color = PIXEL(255, 70, 130, 180);
     71static pixel_t header_fg_unfocus_color = PIXEL(255, 255, 255, 255);
    7072
    7173static void paint_internal(widget_t *w)
     
    9496            w->vpos + w->height - border_thickness, w->width, border_thickness);
    9597
    96         source_set_color(&source, header_bgcolor);
     98        source_set_color(&source,
     99            w->window->is_focused ? header_bg_focus_color : header_bg_unfocus_color);
    97100        drawctx_transfer(&drawctx,
    98101            w->hpos + border_thickness, w->vpos + border_thickness,
     
    106109        char cls_pict[] = "x";
    107110        font_get_box(&font, cls_pict, &cls_width, &cls_height);
    108         source_set_color(&source, header_fgcolor);
     111        source_set_color(&source,
     112            w->window->is_focused ? header_fg_focus_color : header_fg_unfocus_color);
    109113        sysarg_t cls_x = ((close_width - cls_width) / 2) + w->hpos + w->width -
    110114            border_thickness - close_width;
     
    447451                        break;
    448452                case ET_POSITION_EVENT:
     453                        if (!win->is_focused) {
     454                                win->is_focused = true;
     455                                handle_refresh(win);
     456                        }
    449457                        deliver_position_event(win, event->data.pos);
    450458                        break;
     
    454462                case ET_WINDOW_RESIZE:
    455463                        handle_resize(win, event->data.rsz.width, event->data.rsz.height);
     464                        break;
     465                case ET_WINDOW_FOCUS:
     466                        if (!win->is_focused) {
     467                                win->is_focused = true;
     468                                handle_refresh(win);
     469                        }
     470                        break;
     471                case ET_WINDOW_UNFOCUS:
     472                        if (win->is_focused) {
     473                                win->is_focused = false;
     474                                handle_refresh(win);
     475                        }
    456476                        break;
    457477                case ET_WINDOW_REFRESH:
     
    514534}
    515535
    516 window_t *window_open(char *winreg, bool is_main, bool is_decorated, const char *caption)
     536window_t *window_open(char *winreg, bool is_main, bool is_decorated,
     537    const char *caption, sysarg_t x_offset, sysarg_t y_offset)
    517538{
    518539        int rc;
     
    525546        win->is_main = is_main;
    526547        win->is_decorated = is_decorated;
     548        win->is_focused = true;
    527549        prodcons_initialize(&win->events);
    528550        fibril_mutex_initialize(&win->guard);
     
    557579        service_id_t out_dsid;
    558580       
    559         rc = win_register(reg_sess, &in_dsid, &out_dsid);
     581        rc = win_register(reg_sess, &in_dsid, &out_dsid, x_offset, y_offset);
    560582        async_hangup(reg_sess);
    561583        if (rc != EOK) {
  • uspace/lib/gui/window.h

    rff98ce8 re1c6d5df  
    5050        bool is_main; /**< True for the main window of the application. */
    5151        bool is_decorated; /**< True if the window decorations should be rendered. */
     52        bool is_focused; /**< True for the top level window of the desktop. */
    5253        char *caption; /**< Text title of the window header. */
    5354        async_sess_t *isess; /**< Input events from compositor. */
     
    6566 * If the window is declared as main, its closure causes termination of the
    6667 * whole application. Note that opened window does not have any surface yet. */
    67 extern window_t *window_open(char *, bool, bool, const char *);
     68extern window_t *window_open(char *, bool, bool, const char *, sysarg_t, sysarg_t);
    6869
    6970/**
  • uspace/lib/softrend/filter.c

    rff98ce8 re1c6d5df  
    4444                _x %= pixmap->width;
    4545                _y %= pixmap->height;
    46         } else if (_x < 0 || _x >= (long) pixmap->width || _y < 0 || _y >= (long) pixmap->height) {
    47                 return 0;
    4846        }
    4947
  • uspace/lib/softrend/transform.c

    rff98ce8 re1c6d5df  
    136136}
    137137
     138bool transform_is_fast(transform_t *t)
     139{
     140        return (t->m[0][0] == 1) && (t->m[0][1] == 0)
     141            && (t->m[1][0] == 0) && (t->m[1][1] == 1)
     142            && ((t->m[0][2] - ((long) t->m[0][2])) == 0.0)
     143            && ((t->m[1][2] - ((long) t->m[1][2])) == 0.0);
     144}
     145
    138146void transform_apply_linear(const transform_t *t, double *x, double *y)
    139147{
  • uspace/lib/softrend/transform.h

    rff98ce8 re1c6d5df  
    3737#define SOFTREND_TRANSFORM_H_
    3838
     39#include <bool.h>
     40
    3941#ifndef PI
    4042#define PI 3.141592653589793
     
    5355extern void transform_rotate(transform_t *, double);
    5456
     57extern bool transform_is_fast(transform_t *);
     58
    5559extern void transform_apply_linear(const transform_t *, double *, double *);
    5660extern void transform_apply_affine(const transform_t *, double *, double *);
  • 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. */
  • uspace/srv/hid/compositor/compositor.h

    rff98ce8 re1c6d5df  
    4343typedef desktop_point_t desktop_vector_t;
    4444
     45typedef struct {
     46        desktop_coord_t x;
     47        desktop_coord_t y;
     48        desktop_coord_t w;
     49        desktop_coord_t h;
     50} desktop_rect_t;
     51
    4552/* TODO remove? */
    4653typedef struct {
Note: See TracChangeset for help on using the changeset viewer.