Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 6301a24f in mainline


Ignore:
Timestamp:
2020-06-05T20:20:06Z (4 weeks ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
8aef01c
Parents:
d70e7b7b
Message:

Window previews need to be drawn as part of ds_display_paint

Location:
uspace
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/gfx/include/gfx/coord.h

    rd70e7b7b r6301a24f  
    5454extern void gfx_rect_dims(gfx_rect_t *, gfx_coord2_t *);
    5555extern bool gfx_rect_is_empty(gfx_rect_t *);
     56extern bool gfx_rect_is_incident(gfx_rect_t *, gfx_rect_t *);
    5657extern bool gfx_pix_inside_rect(gfx_coord2_t *, gfx_rect_t *);
    5758
  • uspace/lib/gfx/src/coord.c

    rd70e7b7b r6301a24f  
    3737#include <macros.h>
    3838#include <stdbool.h>
     39#include <stddef.h>
    3940
    4041/** Add two vectors.
     
    192193 * If the two rectangles do not intersect, the result will be an empty
    193194 * rectangle (check with gfx_rect_is_empty()). The resulting rectangle
    194  * is always sorted.
     195 * is always sorted. If @a clip is NULL, no clipping is performed.
    195196 *
    196197 * @param rect Source rectangle
    197  * @param clip Clipping rectangle
     198 * @param clip Clipping rectangle or @c NULL
    198199 * @param dest Place to store clipped rectangle
    199200 */
     
    201202{
    202203        gfx_rect_t srect, sclip;
     204
     205        if (clip == NULL) {
     206                *dest = *rect;
     207                return;
     208        }
    203209
    204210        gfx_rect_points_sort(rect, &srect);
     
    235241}
    236242
     243/** Determine if two rectangles share any pixels
     244 *
     245 * @param a First rectangle
     246 * @param b Second rectangle
     247 * @return @c true iff rectangles share any pixels
     248 */
     249bool gfx_rect_is_incident(gfx_rect_t *a, gfx_rect_t *b)
     250{
     251        gfx_rect_t r;
     252
     253        gfx_rect_clip(a, b, &r);
     254        return !gfx_rect_is_empty(&r);
     255}
     256
    237257/** Get rectangle dimensions.
    238258 *
  • uspace/lib/gfx/test/coord.c

    rd70e7b7b r6301a24f  
    560560}
    561561
     562/** Clip rectangle with no clipping rectangle */
     563PCUT_TEST(rect_clip_rect_noclip)
     564{
     565        gfx_rect_t rect;
     566        gfx_rect_t dest;
     567
     568        rect.p0.x = 1;
     569        rect.p0.y = 2;
     570        rect.p1.x = 3;
     571        rect.p1.y = 4;
     572
     573        gfx_rect_clip(&rect, NULL, &dest);
     574        PCUT_ASSERT_INT_EQUALS(rect.p0.x, dest.p0.x);
     575        PCUT_ASSERT_INT_EQUALS(rect.p0.y, dest.p0.y);
     576        PCUT_ASSERT_INT_EQUALS(rect.p1.x, dest.p1.x);
     577        PCUT_ASSERT_INT_EQUALS(rect.p1.y, dest.p1.y);
     578}
     579
    562580/** Sort span points that are already sorted should produde indentical points */
    563581PCUT_TEST(rect_points_sort_sorted)
     
    638656}
    639657
    640 /** gfx_rect_is_empty for staright non-empty rectangle returns false */
     658/** gfx_rect_is_empty for straight non-empty rectangle returns false */
    641659PCUT_TEST(rect_is_empty_neg)
    642660{
     
    662680}
    663681
     682/** gfx_rect_is_incident for neighboring rectangles returns false */
     683PCUT_TEST(rect_is_incident_neighbor)
     684{
     685        gfx_rect_t a;
     686        gfx_rect_t b;
     687
     688        a.p0.x = 1;
     689        a.p0.y = 2;
     690        a.p1.x = 3;
     691        a.p1.y = 4;
     692
     693        b.p0.x = 3;
     694        b.p0.y = 2;
     695        b.p1.x = 5;
     696        b.p1.y = 6;
     697
     698        PCUT_ASSERT_FALSE(gfx_rect_is_incident(&a, &b));
     699}
     700
     701/** gfx_rect_is_incident for a inside b returns true */
     702PCUT_TEST(rect_is_incident_a_inside_b)
     703{
     704        gfx_rect_t a;
     705        gfx_rect_t b;
     706
     707        a.p0.x = 2;
     708        a.p0.y = 3;
     709        a.p1.x = 4;
     710        a.p1.y = 5;
     711
     712        b.p0.x = 1;
     713        b.p0.y = 2;
     714        b.p1.x = 5;
     715        b.p1.y = 6;
     716
     717        PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
     718}
     719
     720/** gfx_rect_is_incident for b inside a returns true */
     721PCUT_TEST(rect_is_incident_b_inside_a)
     722{
     723        gfx_rect_t a;
     724        gfx_rect_t b;
     725
     726        a.p0.x = 1;
     727        a.p0.y = 2;
     728        a.p1.x = 5;
     729        a.p1.y = 6;
     730
     731        b.p0.x = 2;
     732        b.p0.y = 3;
     733        b.p1.x = 4;
     734        b.p1.y = 5;
     735
     736        PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
     737}
     738
     739/** gfx_rect_is_incident for a and b sharing corner returns true */
     740PCUT_TEST(rect_is_incident_corner)
     741{
     742        gfx_rect_t a;
     743        gfx_rect_t b;
     744
     745        a.p0.x = 1;
     746        a.p0.y = 2;
     747        a.p1.x = 3;
     748        a.p1.y = 4;
     749
     750        b.p0.x = 2;
     751        b.p0.y = 3;
     752        b.p1.x = 4;
     753        b.p1.y = 5;
     754
     755        PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
     756}
     757
     758/** gfx_rect_is_incident for a == b returns true */
     759PCUT_TEST(rect_is_incident_same)
     760{
     761        gfx_rect_t a;
     762        gfx_rect_t b;
     763
     764        a.p0.x = 1;
     765        a.p0.y = 2;
     766        a.p1.x = 3;
     767        a.p1.y = 4;
     768
     769        b.p0.x = 1;
     770        b.p0.y = 2;
     771        b.p1.x = 3;
     772        b.p1.y = 4;
     773
     774        PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
     775}
     776
    664777/** gfx_pix_inside_rect for  */
    665778PCUT_TEST(pix_inside_rect)
  • uspace/srv/hid/display/display.c

    rd70e7b7b r6301a24f  
    570570        }
    571571
     572        /* Paint window previews for windows being resized or moved */
     573        wnd = ds_display_last_window(disp);
     574        while (wnd != NULL) {
     575                rc = ds_window_paint_preview(wnd, rect);
     576                if (rc != EOK)
     577                        return rc;
     578
     579                wnd = ds_display_prev_window(wnd);
     580        }
     581
     582        /* Paint pointers */
    572583        seat = ds_display_first_seat(disp);
    573584        while (seat != NULL) {
  • uspace/srv/hid/display/seat.c

    rd70e7b7b r6301a24f  
    251251{
    252252        gfx_rect_t new_rect;
    253         gfx_rect_t isect;
    254253        gfx_rect_t envelope;
    255254        errno_t rc;
     
    257256        ds_seat_get_pointer_rect(seat, &new_rect);
    258257
    259         gfx_rect_clip(old_rect, &new_rect, &isect);
    260         if (gfx_rect_is_empty(&isect)) {
     258        if (gfx_rect_is_incident(old_rect, &new_rect)) {
    261259                /* Rectangles do not intersect. Repaint them separately. */
    262260                rc = ds_display_paint(seat->display, &new_rect);
  • uspace/srv/hid/display/window.c

    rd70e7b7b r6301a24f  
    5050
    5151static void ds_window_update_cb(void *, gfx_rect_t *);
     52static void ds_window_get_preview_rect(ds_window_t *, gfx_rect_t *);
    5253
    5354/** Create window.
     
    205206}
    206207
    207 /** Start moving a window by mouse drag.
    208  *
    209  * @param wnd Window
    210  * @param pos Position where mouse button was pressed
    211  */
    212 static void ds_window_start_move(ds_window_t *wnd, gfx_coord2_t *pos)
    213 {
     208/** Get the preview rectangle for a window.
     209 *
     210 * Get the preview rectangle if the window is being resized or moved.
     211 * If the window is not being resized or moved, return an empty rectangle.
     212 *
     213 * @param wnd Window
     214 * @param rect Place to store preview rectangle
     215 */
     216static void ds_window_get_preview_rect(ds_window_t *wnd, gfx_rect_t *rect)
     217{
     218        switch (wnd->state) {
     219        case dsw_idle:
     220                break;
     221        case dsw_moving:
     222                gfx_rect_translate(&wnd->preview_pos, &wnd->rect, rect);
     223                return;
     224        case dsw_resizing:
     225                gfx_rect_translate(&wnd->dpos, &wnd->preview_rect, rect);
     226                return;
     227        }
     228
     229        rect->p0.x = 0;
     230        rect->p0.y = 0;
     231        rect->p1.x = 0;
     232        rect->p1.y = 0;
     233}
     234
     235/** Paint window preview if the window is being moved or resized.
     236 *
     237 * If the window is not being resized or moved, take no action and return
     238 * success.
     239 *
     240 * @param wnd Window for which to paint preview
     241 * @param rect Clipping rectangle
     242 * @return EOK on success or an error code
     243 */
     244errno_t ds_window_paint_preview(ds_window_t *wnd, gfx_rect_t *rect)
     245{
     246        errno_t rc;
    214247        gfx_color_t *color;
     248        gfx_rect_t prect;
     249        gfx_rect_t drect;
    215250        gfx_context_t *gc;
    216         gfx_rect_t drect;
    217         errno_t rc;
    218 
    219         log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
    220             (int) pos->x, (int) pos->y);
    221 
    222         if (wnd->state != dsw_idle)
    223                 return;
    224 
    225         wnd->orig_pos = *pos;
    226         wnd->state = dsw_moving;
    227         wnd->preview_pos = wnd->dpos;
     251
     252        log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint_preview");
     253
     254        /*
     255         * Get preview rectangle. If the window is not being resized/moved,
     256         * we should get an empty rectangle.
     257         */
     258        ds_window_get_preview_rect(wnd, &prect);
     259        if (gfx_rect_is_empty(&prect)) {
     260                /* There is nothing to paint */
     261                return EOK;
     262        }
     263
     264        /* Clip rendering to the clipping rectangle */
     265        gfx_rect_clip(&prect, rect, &drect);
    228266
    229267        rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
    230268        if (rc != EOK)
    231                 return;
    232 
    233         gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
     269                return rc;
    234270
    235271        gc = ds_display_get_gc(wnd->display); // XXX
     
    240276
    241277        gfx_color_delete(color);
     278        return EOK;
     279}
     280
     281/** Repaint window preview when resizing or moving.
     282 *
     283 * Repaint the window preview wich was previously at rectangle @a old_rect.
     284 * The current preview rectangle is determined from window state. If
     285 * the window did not previously have a preview, @a old_rect should point
     286 * to an empty rectangle or be NULL. When window has finished
     287 * moving or resizing, the preview will be cleared.
     288 *
     289 * @param wnd Window for which to paint preview
     290 * @param rect Clipping rectangle
     291 * @return EOK on success or an error code
     292 */
     293static errno_t ds_window_repaint_preview(ds_window_t *wnd, gfx_rect_t *old_rect)
     294{
     295        errno_t rc;
     296        gfx_rect_t prect;
     297        gfx_rect_t envelope;
     298        bool oldr;
     299        bool newr;
     300
     301        log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_repaint_preview");
     302
     303        /*
     304         * Get current preview rectangle. If the window is not being resized/moved,
     305         * we should get an empty rectangle.
     306         */
     307        ds_window_get_preview_rect(wnd, &prect);
     308
     309        oldr = (old_rect != NULL) && !gfx_rect_is_empty(old_rect);
     310        newr = !gfx_rect_is_empty(&prect);
     311
     312        if (oldr && newr && gfx_rect_is_incident(old_rect, &prect)) {
     313                /*
     314                 * As an optimization, repaint both rectangles in a single
     315                 * operation.
     316                 */
     317
     318                gfx_rect_envelope(old_rect, &prect, &envelope);
     319
     320                rc = ds_display_paint(wnd->display, &envelope);
     321                if (rc != EOK)
     322                        return rc;
     323        } else {
     324                /* Repaint each rectangle separately */
     325                if (oldr) {
     326                        rc = ds_display_paint(wnd->display, old_rect);
     327                        if (rc != EOK)
     328                                return rc;
     329                }
     330
     331                if (newr) {
     332                        rc = ds_display_paint(wnd->display, &prect);
     333                        if (rc != EOK)
     334                                return rc;
     335                }
     336        }
     337
     338        return EOK;
     339}
     340
     341/** Start moving a window by mouse drag.
     342 *
     343 * @param wnd Window
     344 * @param pos Position where mouse button was pressed
     345 */
     346static void ds_window_start_move(ds_window_t *wnd, gfx_coord2_t *pos)
     347{
     348        log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
     349            (int) pos->x, (int) pos->y);
     350
     351        if (wnd->state != dsw_idle)
     352                return;
     353
     354        wnd->orig_pos = *pos;
     355        wnd->state = dsw_moving;
     356        wnd->preview_pos = wnd->dpos;
     357
     358        (void) ds_window_repaint_preview(wnd, NULL);
    242359}
    243360
     
    251368        gfx_coord2_t dmove;
    252369        gfx_coord2_t nwpos;
     370        gfx_rect_t old_rect;
    253371
    254372        log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
     
    258376
    259377        gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
    260 
    261378        gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
     379
     380        ds_window_get_preview_rect(wnd, &old_rect);
     381
    262382        wnd->dpos = nwpos;
    263383        wnd->state = dsw_idle;
     
    275395        gfx_coord2_t dmove;
    276396        gfx_coord2_t nwpos;
    277         gfx_rect_t drect;
    278         gfx_color_t *color;
    279         gfx_context_t *gc;
    280         errno_t rc;
     397        gfx_rect_t old_rect;
    281398
    282399        log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
     
    285402        assert(wnd->state == dsw_moving);
    286403
    287         gfx_rect_translate(&wnd->preview_pos, &wnd->rect, &drect);
    288         ds_display_paint(wnd->display, &drect);
    289 
    290404        gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
    291 
    292405        gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
     406
     407        ds_window_get_preview_rect(wnd, &old_rect);
    293408        wnd->preview_pos = nwpos;
    294409
    295         gfx_rect_translate(&nwpos, &wnd->rect, &drect);
    296 
    297         rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
    298         if (rc != EOK)
    299                 return;
    300 
    301         gc = ds_display_get_gc(wnd->display); // XXX
    302         if (gc != NULL) {
    303                 gfx_set_color(gc, color);
    304                 gfx_fill_rect(gc, &drect);
    305         }
    306 
    307         gfx_color_delete(color);
     410        (void) ds_window_repaint_preview(wnd, &old_rect);
    308411}
    309412
     
    335438        ctype = display_cursor_from_wrsz(rsztype);
    336439        ds_seat_set_wm_cursor(seat, wnd->display->cursor[ctype]);
     440
     441        (void) ds_window_repaint_preview(wnd, NULL);
    337442}
    338443
     
    352457
    353458        assert(wnd->state == dsw_resizing);
    354 
    355         (void) ds_display_paint(wnd->display, NULL);
    356 
    357459        gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
    358460
     
    366468        seat = ds_display_first_seat(wnd->display);
    367469        ds_seat_set_wm_cursor(seat, NULL);
     470
     471        (void) ds_display_paint(wnd->display, NULL);
    368472}
    369473
     
    377481        gfx_coord2_t dresize;
    378482        gfx_rect_t nrect;
    379         gfx_rect_t drect;
    380         gfx_color_t *color;
    381         gfx_context_t *gc;
    382         errno_t rc;
     483        gfx_rect_t old_rect;
    383484
    384485        log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
     
    387488        assert(wnd->state == dsw_resizing);
    388489
    389         gfx_rect_translate(&wnd->dpos, &wnd->preview_rect, &drect);
    390         (void) ds_display_paint(wnd->display, &drect);
    391 
    392490        gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
    393 
    394491        ds_window_calc_resize(wnd, &dresize, &nrect);
    395         gfx_rect_translate(&wnd->dpos, &nrect, &drect);
     492
     493        ds_window_get_preview_rect(wnd, &old_rect);
    396494        wnd->preview_rect = nrect;
    397 
    398         rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
    399         if (rc != EOK)
    400                 return;
    401 
    402         gc = ds_display_get_gc(wnd->display); // XXX
    403         if (gc != NULL) {
    404                 gfx_set_color(gc, color);
    405                 gfx_fill_rect(gc, &drect);
    406         }
    407 
    408         gfx_color_delete(color);
     495        (void) ds_window_repaint_preview(wnd, &old_rect);
    409496}
    410497
  • uspace/srv/hid/display/window.h

    rd70e7b7b r6301a24f  
    5656extern gfx_context_t *ds_window_get_ctx(ds_window_t *);
    5757extern errno_t ds_window_paint(ds_window_t *, gfx_rect_t *);
     58errno_t ds_window_paint_preview(ds_window_t *, gfx_rect_t *);
    5859extern errno_t ds_window_post_kbd_event(ds_window_t *, kbd_event_t *);
    5960extern errno_t ds_window_post_pos_event(ds_window_t *, pos_event_t *);
Note: See TracChangeset for help on using the changeset viewer.