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

Changeset c4a53280 in mainline


Ignore:
Timestamp:
2022-12-01T14:39:56Z (2 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
795c6f7
Parents:
68d68e9
git-author:
Jiri Svoboda <jiri@…> (2022-11-30 18:39:42)
git-committer:
Jiri Svoboda <jiri@…> (2022-12-01 14:39:56)
Message:

Optimize redrawing of window buttons

We cache the button pich inside wndlist_t. We only repaint the entire
window list if the pitch changes. Otherwise we just (un)paint the
affected buttons.

Location:
uspace/app/taskbar
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/taskbar/test/wndlist.c

    r68d68e9 rc4a53280  
    407407}
    408408
     409/** Test wndlist_last() */
     410PCUT_TEST(last)
     411{
     412        errno_t rc;
     413        ui_t *ui = NULL;
     414        ui_wnd_params_t params;
     415        ui_window_t *window = NULL;
     416        ui_fixed_t *fixed = NULL;
     417        wndlist_t *wndlist;
     418        wndlist_entry_t *entry;
     419
     420        rc = ui_create_disp(NULL, &ui);
     421        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     422
     423        ui_wnd_params_init(&params);
     424        params.caption = "Hello";
     425
     426        rc = ui_window_create(ui, &params, &window);
     427        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     428        PCUT_ASSERT_NOT_NULL(window);
     429
     430        rc = ui_fixed_create(&fixed);
     431        ui_window_add(window, ui_fixed_ctl(fixed));
     432
     433        rc = wndlist_create(window, fixed, &wndlist);
     434        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     435
     436        rc = wndlist_append(wndlist, 1, "Foo", true);
     437        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     438
     439        rc = wndlist_append(wndlist, 2, "Bar", true);
     440        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     441
     442        entry = wndlist_last(wndlist);
     443        PCUT_ASSERT_NOT_NULL(entry);
     444        PCUT_ASSERT_INT_EQUALS(2, entry->wnd_id);
     445
     446        wndlist_destroy(wndlist);
     447
     448        ui_window_destroy(window);
     449        ui_destroy(ui);
     450}
     451
    409452/** Test wndlist_count() */
    410453PCUT_TEST(count)
  • uspace/app/taskbar/types/wndlist.h

    r68d68e9 rc4a53280  
    5757        /** Window button */
    5858        ui_pbutton_t *button;
     59        /** Window button rectangle */
     60        gfx_rect_t rect;
    5961} wndlist_entry_t;
    6062
     
    7678        list_t entries;
    7779
     80        /** Current button pitch */
     81        gfx_coord_t pitch;
     82
    7883        /** Window management service */
    7984        wndmgt_t *wndmgt;
  • uspace/app/taskbar/wndlist.c

    r68d68e9 rc4a53280  
    3434
    3535#include <gfx/coord.h>
     36#include <gfx/render.h>
    3637#include <stdbool.h>
    3738#include <stddef.h>
     
    9192    wndlist_t **rwndlist)
    9293{
     94        ui_resource_t *res = ui_window_get_res(window);
    9395        wndlist_t *wndlist = NULL;
    9496        errno_t rc;
     
    103105        wndlist->fixed = fixed;
    104106        list_initialize(&wndlist->entries);
     107
     108        if (ui_resource_is_textmode(res))
     109                wndlist->pitch = wndlist_button_pitch_max_text;
     110        else
     111                wndlist->pitch = wndlist_button_pitch_max;
     112
    105113        *rwndlist = wndlist;
    106114        return EOK;
     
    223231        entry->visible = false;
    224232
    225         /*
    226          * Update rectangles for all entries, including @a entry, adding
    227          * it to the layout, if applicable.
    228          */
    229         e = wndlist_first(wndlist);
    230         while (e != NULL) {
    231                 wndlist_set_entry_rect(wndlist, e);
    232                 e = wndlist_next(e);
    233         }
    234 
    235233        /* Set button callbacks */
    236234        ui_pbutton_set_cb(entry->button, &wndlist_button_cb, (void *)entry);
    237235
    238         if (paint)
    239                 return wndlist_repaint(wndlist);
     236        if (wndlist_update_pitch(wndlist)) {
     237                /*
     238                 * Update rectangles for all entries, including @a entry, adding
     239                 * it to the layout, if applicable.
     240                 */
     241                e = wndlist_first(wndlist);
     242                while (e != NULL) {
     243                        wndlist_set_entry_rect(wndlist, e);
     244                        e = wndlist_next(e);
     245                }
     246
     247                if (paint)
     248                        return wndlist_repaint(wndlist);
     249        } else {
     250                wndlist_set_entry_rect(wndlist, entry);
     251                if (paint)
     252                        return ui_pbutton_paint(entry->button);
     253        }
    240254
    241255        return EOK;
     
    260274{
    261275        wndlist_entry_t *e;
     276        wndlist_entry_t *next;
     277        wndlist_entry_t *last;
     278        errno_t rc = EOK;
     279
    262280        assert(entry->wndlist == wndlist);
     281        next = wndlist_next(entry);
     282
     283        /* Remember last entry */
     284        last = wndlist_last(wndlist);
    263285
    264286        if (entry->visible)
    265287                ui_fixed_remove(wndlist->fixed, ui_pbutton_ctl(entry->button));
     288        list_remove(&entry->lentries);
     289
     290        if (wndlist_update_pitch(wndlist)) {
     291                /*
     292                 * Update rectangles for all entries.
     293                 */
     294                e = wndlist_first(wndlist);
     295                while (e != NULL) {
     296                        wndlist_set_entry_rect(wndlist, e);
     297                        e = wndlist_next(e);
     298                }
     299
     300                if (paint)
     301                        rc = wndlist_repaint(wndlist);
     302        } else {
     303                /* Unpaint the last entry */
     304                if (paint)
     305                        rc = wndlist_unpaint_entry(last);
     306
     307                /*
     308                 * Update rectangles for entries to the right
     309                 */
     310
     311                e = NULL;
     312                while (next != NULL) {
     313                        e = next;
     314
     315                        wndlist_set_entry_rect(wndlist, e);
     316                        if (paint) {
     317                                rc = ui_pbutton_paint(e->button);
     318                                if (rc != EOK)
     319                                        return rc;
     320                        }
     321
     322                        next = wndlist_next(e);
     323                }
     324        }
     325
    266326        ui_pbutton_destroy(entry->button);
    267         list_remove(&entry->lentries);
    268327        free(entry);
    269 
    270         /* Update positions of the all entries */
    271         e = wndlist_first(wndlist);
    272         while (e != NULL) {
    273                 wndlist_set_entry_rect(wndlist, e);
    274                 e = wndlist_next(e);
    275         }
    276 
    277         if (!paint)
    278                 return EOK;
    279 
    280         return wndlist_repaint(wndlist);
    281 }
    282 
    283 /** Update window list entry.
    284  *
    285  * @param wndlist Window list
    286  * @param entry Window list entry
    287  * @return @c EOK on success or an error code
    288  */
    289 errno_t wndlist_update(wndlist_t *wndlist, wndlist_entry_t *entry,
    290     const char *caption)
    291 {
    292         errno_t rc;
    293         assert(entry->wndlist == wndlist);
    294 
    295         rc = ui_pbutton_set_caption(entry->button, caption);
    296         if (rc != EOK)
    297                 return rc;
    298 
    299         rc = ui_pbutton_paint(entry->button);
    300         if (rc != EOK)
    301                 return rc;
    302 
    303         return wndlist_repaint(wndlist);
    304 }
    305 
    306 /** Compute and set window list entry rectangle.
    307  *
    308  * Compute rectangle for window list entry and set it.
    309  *
    310  * @param wndlist Window list
    311  * @param entry Window list entry
    312  */
    313 void wndlist_set_entry_rect(wndlist_t *wndlist, wndlist_entry_t *entry)
    314 {
    315         wndlist_entry_t *e;
    316         gfx_rect_t rect;
     328        return rc;
     329}
     330
     331/** Update button pitch.
     332 *
     333 * Recalculatebutton pitch @c wndlist->pitch based on current number
     334 * of buttons.
     335 *
     336 * @param wndlist Window list
     337 * @return @c true iff pitch changed
     338 */
     339bool wndlist_update_pitch(wndlist_t *wndlist)
     340{
    317341        ui_resource_t *res;
     342        size_t nbuttons;
    318343        gfx_coord_t pitch;
    319344        gfx_coord_t pitch_max;
    320345        gfx_coord_t pitch_min;
    321346        gfx_coord_t pad;
    322         size_t idx;
    323         size_t nbuttons;
    324 
    325         /* Determine entry index */
    326         idx = 0;
    327         e = wndlist_first(wndlist);
    328         while (e != entry) {
    329                 assert(e != NULL);
    330                 e = wndlist_next(e);
    331                 ++idx;
    332         }
    333347
    334348        res = ui_window_get_res(wndlist->window);
     
    346360        /* Compute pitch that fits all buttons perfectly */
    347361        nbuttons = wndlist_count(wndlist);
    348         pitch = (wndlist->rect.p1.x - wndlist->rect.p0.x + pad) / nbuttons;
     362        if (nbuttons > 0)
     363                pitch = (wndlist->rect.p1.x - wndlist->rect.p0.x + pad) / nbuttons;
     364        else
     365                pitch = pitch_min;
     366
    349367        if (pitch < pitch_min)
    350368                pitch = pitch_min;
    351369        if (pitch > pitch_max)
    352370                pitch = pitch_max;
     371
     372        /* Did the pitch change? */
     373        if (pitch == wndlist->pitch)
     374                return false;
     375
     376        wndlist->pitch = pitch;
     377        return true;
     378}
     379
     380/** Update window list entry.
     381 *
     382 * @param wndlist Window list
     383 * @param entry Window list entry
     384 * @return @c EOK on success or an error code
     385 */
     386errno_t wndlist_update(wndlist_t *wndlist, wndlist_entry_t *entry,
     387    const char *caption)
     388{
     389        errno_t rc;
     390        assert(entry->wndlist == wndlist);
     391
     392        rc = ui_pbutton_set_caption(entry->button, caption);
     393        if (rc != EOK)
     394                return rc;
     395
     396        rc = ui_pbutton_paint(entry->button);
     397        if (rc != EOK)
     398                return rc;
     399
     400        return wndlist_repaint(wndlist);
     401}
     402
     403/** Compute and set window list entry rectangle.
     404 *
     405 * Compute rectangle for window list entry and set it.
     406 *
     407 * @param wndlist Window list
     408 * @param entry Window list entry
     409 */
     410void wndlist_set_entry_rect(wndlist_t *wndlist, wndlist_entry_t *entry)
     411{
     412        wndlist_entry_t *e;
     413        gfx_rect_t rect;
     414        ui_resource_t *res;
     415        gfx_coord_t pitch;
     416        gfx_coord_t pad;
     417        size_t idx;
     418
     419        /* Determine entry index */
     420        idx = 0;
     421        e = wndlist_first(wndlist);
     422        while (e != entry) {
     423                assert(e != NULL);
     424                e = wndlist_next(e);
     425                ++idx;
     426        }
     427
     428        res = ui_window_get_res(wndlist->window);
     429
     430        if (ui_resource_is_textmode(res)) {
     431                pad = wndlist_button_pad_text;
     432        } else {
     433                pad = wndlist_button_pad;
     434        }
     435
     436        pitch = wndlist->pitch;
    353437
    354438        rect.p0.x = wndlist->rect.p0.x + pitch * idx;
     
    375459
    376460        ui_pbutton_set_rect(entry->button, &rect);
     461        entry->rect = rect;
     462}
     463
     464/** Compute and set window list entry rectangle.
     465 *
     466 * Compute rectangle for window list entry and set it.
     467 *
     468 * @param entry Window list entry
     469 * @return EOK on success or an error code
     470 */
     471errno_t wndlist_unpaint_entry(wndlist_entry_t *entry)
     472{
     473        errno_t rc;
     474        gfx_context_t *gc;
     475        ui_resource_t *res;
     476        gfx_color_t *color;
     477
     478        gc = ui_window_get_gc(entry->wndlist->window);
     479        res = ui_window_get_res(entry->wndlist->window);
     480        color = ui_resource_get_wnd_face_color(res);
     481
     482        rc = gfx_set_color(gc, color);
     483        if (rc != EOK)
     484                return rc;
     485
     486        rc = gfx_fill_rect(gc, &entry->rect);
     487        if (rc != EOK)
     488                return rc;
     489
     490        return EOK;
    377491}
    378492
     
    485599}
    486600
     601/** Get last window list entry.
     602 *
     603 * @param wndlist Window list
     604 * @return Last entry or @c NULL if the list is empty
     605 */
     606wndlist_entry_t *wndlist_last(wndlist_t *wndlist)
     607{
     608        link_t *link;
     609
     610        link = list_last(&wndlist->entries);
     611        if (link == NULL)
     612                return NULL;
     613
     614        return list_get_instance(link, wndlist_entry_t, lentries);
     615}
     616
    487617/** Get next window list entry.
    488618 *
  • uspace/app/taskbar/wndlist.h

    r68d68e9 rc4a53280  
    5252extern errno_t wndlist_append(wndlist_t *, sysarg_t, const char *, bool);
    5353extern errno_t wndlist_remove(wndlist_t *, wndlist_entry_t *, bool);
     54extern bool wndlist_update_pitch(wndlist_t *);
    5455extern errno_t wndlist_update(wndlist_t *, wndlist_entry_t *, const char *);
    5556extern void wndlist_set_entry_rect(wndlist_t *, wndlist_entry_t *);
    5657extern wndlist_entry_t *wndlist_entry_by_id(wndlist_t *, sysarg_t);
    5758extern wndlist_entry_t *wndlist_first(wndlist_t *);
     59extern wndlist_entry_t *wndlist_last(wndlist_t *);
    5860extern wndlist_entry_t *wndlist_next(wndlist_entry_t *);
    5961extern size_t wndlist_count(wndlist_t *);
    6062extern errno_t wndlist_repaint(wndlist_t *);
     63extern errno_t wndlist_unpaint_entry(wndlist_entry_t *);
    6164
    6265#endif
Note: See TracChangeset for help on using the changeset viewer.