Changeset 8965860c in mainline for uspace/lib/ui/src/scrollbar.c


Ignore:
Timestamp:
2022-03-23T18:35:16Z (2 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7ca7215
Parents:
d4ea1f6
Message:

Clickmatic

A class that periodically generates when held, after initial delay.
This is quite similar to the typematic feature found in PC keyboards.
We use it to automatically scroll when scrollbar button or through
is held.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/src/scrollbar.c

    rd4ea1f6 r8965860c  
    5353 * button on the up/down through generates page up / page down events.
    5454 *
    55  * TODO: Up/down buttons/throughs should be equipped with an autorepeat
    56  * mechanism: after an initial delay, start repeating at a preset rate.
     55 * Pressing and holding down mouse button on up / down button or up / down
     56 * through will auto-scroll (using clickmatic).
    5757 */
    5858
     
    6565#include <stdlib.h>
    6666#include <str.h>
     67#include <ui/clickmatic.h>
    6768#include <ui/control.h>
    6869#include <ui/paint.h>
    6970#include <ui/pbutton.h>
    7071#include <ui/scrollbar.h>
     72#include <ui/ui.h>
     73#include <ui/window.h>
     74#include "../private/pbutton.h"
    7175#include "../private/resource.h"
    7276#include "../private/scrollbar.h"
     
    9296
    9397static void ui_scrollbar_up_btn_down(ui_pbutton_t *, void *);
     98static void ui_scrollbar_up_btn_up(ui_pbutton_t *, void *);
    9499static void ui_scrollbar_down_btn_down(ui_pbutton_t *, void *);
     100static void ui_scrollbar_down_btn_up(ui_pbutton_t *, void *);
    95101static void ui_scrollbar_ctl_destroy(void *);
    96102static errno_t ui_scrollbar_ctl_paint(void *);
    97103static ui_evclaim_t ui_scrollbar_ctl_pos_event(void *, pos_event_t *);
    98104
    99 ui_pbutton_cb_t ui_scrollbar_up_btn_cb = {
    100         .down = ui_scrollbar_up_btn_down
     105static ui_pbutton_cb_t ui_scrollbar_up_btn_cb = {
     106        .down = ui_scrollbar_up_btn_down,
     107        .up = ui_scrollbar_up_btn_up
    101108};
    102109
    103 ui_pbutton_cb_t ui_scrollbar_down_btn_cb = {
    104         .down = ui_scrollbar_down_btn_down
     110static ui_pbutton_cb_t ui_scrollbar_down_btn_cb = {
     111        .down = ui_scrollbar_down_btn_down,
     112        .up = ui_scrollbar_down_btn_up
    105113};
    106114
    107115/** Scrollbar control ops */
    108 ui_control_ops_t ui_scrollbar_ops = {
     116static ui_control_ops_t ui_scrollbar_ops = {
    109117        .destroy = ui_scrollbar_ctl_destroy,
    110118        .paint = ui_scrollbar_ctl_paint,
     
    112120};
    113121
     122static void ui_scrollbar_cm_up(ui_clickmatic_t *, void *);
     123static void ui_scrollbar_cm_down(ui_clickmatic_t *, void *);
     124static void ui_scrollbar_cm_page_up(ui_clickmatic_t *, void *);
     125static void ui_scrollbar_cm_page_down(ui_clickmatic_t *, void *);
     126
     127/** Scrollbar clickmatic up callbacks */
     128ui_clickmatic_cb_t ui_scrollbar_clickmatic_up_cb = {
     129        .clicked = ui_scrollbar_cm_up
     130};
     131
     132/** Scrollbar clickmatic down callbacks */
     133ui_clickmatic_cb_t ui_scrollbar_clickmatic_down_cb = {
     134        .clicked = ui_scrollbar_cm_down
     135};
     136
     137/** Scrollbar clickmatic page up callbacks */
     138ui_clickmatic_cb_t ui_scrollbar_clickmatic_page_up_cb = {
     139        .clicked = ui_scrollbar_cm_page_up
     140};
     141
     142/** Scrollbar clickmatic page down callbacks */
     143ui_clickmatic_cb_t ui_scrollbar_clickmatic_page_down_cb = {
     144        .clicked = ui_scrollbar_cm_page_down
     145};
     146
    114147/** Create new scrollbar.
    115148 *
    116  * @param resource UI resource
     149 * @param ui UI
     150 * @param window Window containing scrollbar
    117151 * @param rscrollbar Place to store pointer to new scrollbar
    118152 * @return EOK on success, ENOMEM if out of memory
    119153 */
    120 errno_t ui_scrollbar_create(ui_resource_t *resource,
     154errno_t ui_scrollbar_create(ui_t *ui, ui_window_t *window,
    121155    ui_scrollbar_t **rscrollbar)
    122156{
    123157        ui_scrollbar_t *scrollbar;
     158        ui_resource_t *resource;
    124159        errno_t rc;
     160
     161        resource = ui_window_get_res(window);
    125162
    126163        scrollbar = calloc(1, sizeof(ui_scrollbar_t));
     
    155192            ui_scrollbar_def_thumb_len;
    156193
    157         scrollbar->res = resource;
     194        scrollbar->ui = ui;
     195        scrollbar->window = window;
    158196        *rscrollbar = scrollbar;
    159197        return EOK;
     
    283321    gfx_rect_t *rect, gfx_rect_t *inside)
    284322{
    285         return ui_paint_bevel(scrollbar->res->gc, rect,
    286             scrollbar->res->btn_highlight_color,
    287             scrollbar->res->btn_shadow_color, ui_scrollbar_thumb_bevel_width, inside);
    288 }
    289 
    290 /** Determine scrollbar thumb rectagle.
    291  *
    292  * @param scrollbar Scrollbar
    293  */
    294 static void ui_scrollbar_thumb_rect(ui_scrollbar_t *scrollbar, gfx_rect_t *rect)
    295 {
    296         ui_scrollbar_geom_t geom;
    297 
    298         ui_scrollbar_get_geom(scrollbar, &geom);
    299         *rect = geom.thumb_rect;
     323        ui_resource_t *resource = ui_window_get_res(scrollbar->window);
     324
     325        return ui_paint_bevel(resource->gc, rect,
     326            resource->btn_highlight_color,
     327            resource->btn_shadow_color, ui_scrollbar_thumb_bevel_width, inside);
    300328}
    301329
     
    310338gfx_coord_t ui_scrollbar_through_length(ui_scrollbar_t *scrollbar)
    311339{
     340        ui_resource_t *resource;
    312341        gfx_coord2_t dims;
    313342        gfx_coord_t w;
    314343
     344        resource = ui_window_get_res(scrollbar->window);
     345
    315346        gfx_rect_dims(&scrollbar->rect, &dims);
    316         w = scrollbar->res->textmode ? ui_scrollbar_btn_len_text :
     347        w = resource->textmode ? ui_scrollbar_btn_len_text :
    317348            ui_scrollbar_btn_len;
    318349        return dims.x - 2 * w;
     
    339370void ui_scrollbar_set_thumb_length(ui_scrollbar_t *scrollbar, gfx_coord_t len)
    340371{
     372        ui_resource_t *resource;
    341373        gfx_coord_t min_len;
    342374        gfx_coord_t max_len;
    343375
    344         min_len = scrollbar->res->textmode ?
     376        resource = ui_window_get_res(scrollbar->window);
     377
     378        min_len = resource->textmode ?
    345379            ui_scrollbar_min_thumb_len_text :
    346380            ui_scrollbar_min_thumb_len;
     
    353387
    354388        if (len != scrollbar->thumb_len) {
    355                 (void) ui_scrollbar_thumb_clear(scrollbar);
    356389                scrollbar->thumb_len = len;
    357390                (void) ui_scrollbar_paint(scrollbar);
     
    387420
    388421        if (pos != scrollbar->pos) {
    389                 (void) ui_scrollbar_thumb_clear(scrollbar);
    390422                scrollbar->pos = pos;
    391423                (void) ui_scrollbar_paint(scrollbar);
     424                ui_scrollbar_throughs_update(scrollbar,
     425                    &scrollbar->last_curs_pos);
    392426                ui_scrollbar_moved(scrollbar, pos);
    393427        }
     
    401435errno_t ui_scrollbar_paint_gfx(ui_scrollbar_t *scrollbar)
    402436{
     437        ui_resource_t *resource;
    403438        ui_scrollbar_geom_t geom;
    404439        gfx_rect_t brect;
     
    406441        errno_t rc;
    407442
     443        resource = ui_window_get_res(scrollbar->window);
     444
    408445        ui_scrollbar_get_geom(scrollbar, &geom);
    409446
    410447        /* Paint scrollbar frame */
    411448
    412         rc = ui_paint_inset_frame(scrollbar->res, &scrollbar->rect, NULL);
     449        rc = ui_paint_inset_frame(resource, &scrollbar->rect, NULL);
    413450        if (rc != EOK)
    414451                goto error;
    415452
    416453        /* Paint scrollbar up through */
    417         rc = gfx_set_color(scrollbar->res->gc,
    418             scrollbar->up_through_held ?
    419             scrollbar->res->sbar_act_through_color :
    420             scrollbar->res->sbar_through_color);
    421         if (rc != EOK)
    422                 goto error;
    423 
    424         rc = gfx_fill_rect(scrollbar->res->gc, &geom.up_through_rect);
     454        rc = gfx_set_color(resource->gc,
     455            scrollbar->up_through_held && scrollbar->up_through_inside ?
     456            resource->sbar_act_through_color :
     457            resource->sbar_through_color);
     458        if (rc != EOK)
     459                goto error;
     460
     461        rc = gfx_fill_rect(resource->gc, &geom.up_through_rect);
    425462        if (rc != EOK)
    426463                goto error;
     
    428465        /* Paint scrollbar down through */
    429466
    430         rc = gfx_set_color(scrollbar->res->gc,
    431             scrollbar->down_through_held ?
    432             scrollbar->res->sbar_act_through_color :
    433             scrollbar->res->sbar_through_color);
    434         if (rc != EOK)
    435                 goto error;
    436 
    437         rc = gfx_fill_rect(scrollbar->res->gc, &geom.down_through_rect);
     467        rc = gfx_set_color(resource->gc,
     468            scrollbar->down_through_held && scrollbar->down_through_inside ?
     469            resource->sbar_act_through_color :
     470            resource->sbar_through_color);
     471        if (rc != EOK)
     472                goto error;
     473
     474        rc = gfx_fill_rect(resource->gc, &geom.down_through_rect);
    438475        if (rc != EOK)
    439476                goto error;
     
    441478        /* Paint scrollbar thumb */
    442479
    443         rc = ui_scrollbar_paint_thumb_frame(scrollbar->res, &geom.thumb_rect,
     480        rc = ui_scrollbar_paint_thumb_frame(resource, &geom.thumb_rect,
    444481            ui_scrollbar_thumb_frame_thickness, &brect);
    445482        if (rc != EOK)
     
    450487                goto error;
    451488
    452         rc = gfx_set_color(scrollbar->res->gc, scrollbar->res->btn_face_color);
    453         if (rc != EOK)
    454                 goto error;
    455 
    456         rc = gfx_fill_rect(scrollbar->res->gc, &irect);
     489        rc = gfx_set_color(resource->gc, resource->btn_face_color);
     490        if (rc != EOK)
     491                goto error;
     492
     493        rc = gfx_fill_rect(resource->gc, &irect);
    457494        if (rc != EOK)
    458495                goto error;
     
    466503                goto error;
    467504
    468         rc = gfx_update(scrollbar->res->gc);
     505        rc = gfx_update(resource->gc);
    469506        if (rc != EOK)
    470507                goto error;
     
    482519errno_t ui_scrollbar_paint_text(ui_scrollbar_t *scrollbar)
    483520{
     521        ui_resource_t *resource;
    484522        gfx_coord2_t pos;
    485523        gfx_text_fmt_t fmt;
     
    490528        errno_t rc;
    491529
     530        resource = ui_window_get_res(scrollbar->window);
     531
    492532        /* Paint scrollbar through */
    493533
     
    496536
    497537        gfx_text_fmt_init(&fmt);
    498         fmt.font = scrollbar->res->font;
    499         fmt.color = scrollbar->res->sbar_through_color;
     538        fmt.font = resource->font;
     539        fmt.color = resource->sbar_through_color;
    500540        fmt.halign = gfx_halign_left;
    501541        fmt.valign = gfx_valign_top;
     
    552592                goto error;
    553593
    554         rc = gfx_update(scrollbar->res->gc);
     594        rc = gfx_update(resource->gc);
    555595        if (rc != EOK)
    556596                goto error;
     
    568608errno_t ui_scrollbar_paint(ui_scrollbar_t *scrollbar)
    569609{
    570         if (scrollbar->res->textmode)
     610        ui_resource_t *resource = ui_window_get_res(scrollbar->window);
     611
     612        if (resource->textmode)
    571613                return ui_scrollbar_paint_text(scrollbar);
    572614        else
     
    581623void ui_scrollbar_get_geom(ui_scrollbar_t *scrollbar, ui_scrollbar_geom_t *geom)
    582624{
     625        ui_resource_t *resource;
    583626        gfx_coord_t btn_len;
    584627        gfx_rect_t orect;
    585628        gfx_rect_t irect;
    586629
    587         if (scrollbar->res->textmode) {
     630        resource = ui_window_get_res(scrollbar->window);
     631
     632        if (resource->textmode) {
    588633                btn_len = ui_scrollbar_btn_len_text;
    589634        } else {
     
    591636        }
    592637
    593         if (scrollbar->res->textmode) {
     638        if (resource->textmode) {
    594639                irect = scrollbar->rect;
    595640                orect = scrollbar->rect;
    596641        } else {
    597                 ui_paint_get_inset_frame_inside(scrollbar->res,
     642                ui_paint_get_inset_frame_inside(resource,
    598643                    &scrollbar->rect, &irect);
    599                 ui_paint_get_bevel_inside(scrollbar->res->gc,
     644                ui_paint_get_bevel_inside(resource->gc,
    600645                    &scrollbar->rect, 1, &orect);
    601646        }
     
    636681}
    637682
    638 /** Clear scrollbar thumb.
    639  *
    640  * @param scrollbar Scrollbar
    641  * @return EOK on success or an error code
    642  */
    643 errno_t ui_scrollbar_thumb_clear(ui_scrollbar_t *scrollbar)
    644 {
    645         gfx_rect_t rect;
    646         errno_t rc;
    647 
    648         /* No need to clear thumb in text mode */
    649         if (scrollbar->res->textmode)
    650                 return EOK;
    651 
    652         ui_scrollbar_thumb_rect(scrollbar, &rect);
    653 
    654         rc = gfx_set_color(scrollbar->res->gc, scrollbar->res->wnd_face_color);
    655         if (rc != EOK)
    656                 goto error;
    657 
    658         rc = gfx_fill_rect(scrollbar->res->gc, &rect);
    659         if (rc != EOK)
    660                 goto error;
    661 
    662         return EOK;
    663 error:
    664         return rc;
    665 }
    666 
    667683/** Press down scrollbar thumb.
    668684 *
     
    688704void ui_scrollbar_up_through_press(ui_scrollbar_t *scrollbar)
    689705{
    690         if (scrollbar->up_through_held)
    691                 return;
     706        ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
    692707
    693708        scrollbar->up_through_held = true;
    694         (void) ui_scrollbar_paint(scrollbar);
    695 
    696         ui_scrollbar_page_up(scrollbar);
     709        scrollbar->up_through_inside = true;
     710
     711        ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_page_up_cb,
     712            (void *) scrollbar);
     713        ui_clickmatic_press(clickmatic);
    697714}
    698715
     
    703720void ui_scrollbar_down_through_press(ui_scrollbar_t *scrollbar)
    704721{
    705         if (scrollbar->down_through_held)
    706                 return;
     722        ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
    707723
    708724        scrollbar->down_through_held = true;
    709         (void) ui_scrollbar_paint(scrollbar);
    710 
    711         ui_scrollbar_page_down(scrollbar);
     725        scrollbar->down_through_inside = true;
     726
     727        ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_page_down_cb,
     728            (void *) scrollbar);
     729        ui_clickmatic_press(clickmatic);
    712730}
    713731
     
    719737void ui_scrollbar_release(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
    720738{
     739        ui_clickmatic_t *clickmatic;
     740
    721741        if (scrollbar->thumb_held) {
    722742                ui_scrollbar_update(scrollbar, pos);
     
    725745
    726746        if (scrollbar->up_through_held || scrollbar->down_through_held) {
     747                clickmatic = ui_get_clickmatic(scrollbar->ui);
     748                ui_clickmatic_release(clickmatic);
     749                ui_clickmatic_set_cb(clickmatic, NULL, NULL);
     750
    727751                scrollbar->up_through_held = false;
    728752                scrollbar->down_through_held = false;
     
    731755}
    732756
     757/** Update state of scrollbar throuhgs.
     758 *
     759 * Update state of scrollbar throughs after mouse cursor or thumb has moved.
     760 *
     761 * @param scrollbar Scrollbar
     762 * @param pos Mouse cursor position
     763 */
     764void ui_scrollbar_throughs_update(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
     765{
     766        ui_scrollbar_geom_t geom;
     767        bool inside_up;
     768        bool inside_down;
     769
     770        ui_scrollbar_get_geom(scrollbar, &geom);
     771
     772        inside_up = gfx_pix_inside_rect(pos, &geom.up_through_rect);
     773        inside_down = gfx_pix_inside_rect(pos, &geom.down_through_rect);
     774
     775        if (inside_up && !scrollbar->up_through_inside) {
     776                scrollbar->up_through_inside = true;
     777                (void) ui_scrollbar_paint(scrollbar);
     778        } else if (!inside_up && scrollbar->up_through_inside) {
     779                scrollbar->up_through_inside = false;
     780                (void) ui_scrollbar_paint(scrollbar);
     781        }
     782
     783        if (inside_down && !scrollbar->down_through_inside) {
     784                scrollbar->down_through_inside = true;
     785                (void) ui_scrollbar_paint(scrollbar);
     786        } else if (!inside_down && scrollbar->down_through_inside) {
     787                scrollbar->down_through_inside = false;
     788                (void) ui_scrollbar_paint(scrollbar);
     789        }
     790}
     791
    733792/** Pointer moved.
    734793 *
     
    744803                ui_scrollbar_set_pos(scrollbar, spos);
    745804        }
     805
     806        ui_scrollbar_throughs_update(scrollbar, pos);
    746807}
    747808
     
    845906        case POS_UPDATE:
    846907                ui_scrollbar_update(scrollbar, &pos);
     908                scrollbar->last_curs_pos = pos;
    847909                break;
    848910        case POS_DCLICK:
     
    861923{
    862924        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
    863 
    864         ui_scrollbar_up(scrollbar);
     925        ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
     926
     927        ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_up_cb,
     928            (void *) scrollbar);
     929        ui_clickmatic_press(clickmatic);
     930}
     931
     932/** Scrollbar up button released.
     933 *
     934 * @param pbutton Up button
     935 * @param arg Argument (ui_scrollbar_t *)
     936 */
     937static void ui_scrollbar_up_btn_up(ui_pbutton_t *pbutton, void *arg)
     938{
     939        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
     940        ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
     941
     942        ui_clickmatic_release(clickmatic);
     943        ui_clickmatic_set_cb(clickmatic, NULL, NULL);
    865944}
    866945
     
    873952{
    874953        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
    875 
    876         ui_scrollbar_down(scrollbar);
     954        ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
     955
     956        ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_down_cb,
     957            (void *) scrollbar);
     958        ui_clickmatic_press(clickmatic);
     959}
     960
     961/** Scrollbar down button released.
     962 *
     963 * @param pbutton Down button
     964 * @param arg Argument (ui_scrollbar_t *)
     965 */
     966static void ui_scrollbar_down_btn_up(ui_pbutton_t *pbutton, void *arg)
     967{
     968        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
     969        ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
     970
     971        ui_clickmatic_release(clickmatic);
     972        ui_clickmatic_set_cb(clickmatic, NULL, NULL);
    877973}
    878974
     
    9081004ui_evclaim_t ui_scrollbar_ctl_pos_event(void *arg, pos_event_t *event)
    9091005{
    910         ui_scrollbar_t *scrollbar = (ui_scrollbar_t *) arg;
     1006        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
    9111007
    9121008        return ui_scrollbar_pos_event(scrollbar, event);
    9131009}
    9141010
     1011/** Scrollbar clickmatic up button click event.
     1012 *
     1013 * @param clickmatic Clickmatic
     1014 * @param arg Argument (ui_scrollbar_t *)
     1015 */
     1016static void ui_scrollbar_cm_up(ui_clickmatic_t *clickmatic, void *arg)
     1017{
     1018        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
     1019
     1020        if (scrollbar->up_btn->inside)
     1021                ui_scrollbar_up(scrollbar);
     1022}
     1023
     1024/** Scrollbar clickmatic down button click event.
     1025 *
     1026 * @param clickmatic Clickmatic
     1027 * @param arg Argument (ui_scrollbar_t *)
     1028 */
     1029static void ui_scrollbar_cm_down(ui_clickmatic_t *clickmatic, void *arg)
     1030{
     1031        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
     1032
     1033        if (scrollbar->down_btn->inside)
     1034                ui_scrollbar_down(scrollbar);
     1035}
     1036
     1037/** Scrollbar clickmatic up through click event.
     1038 *
     1039 * @param clickmatic Clickmatic
     1040 * @param arg Argument (ui_scrollbar_t *)
     1041 */
     1042static void ui_scrollbar_cm_page_up(ui_clickmatic_t *clickmatic, void *arg)
     1043{
     1044        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
     1045
     1046        if (scrollbar->up_through_inside)
     1047                ui_scrollbar_page_up(scrollbar);
     1048}
     1049
     1050/** Scrollbar clickmatic down through click event.
     1051 *
     1052 * @param clickmatic Clickmatic
     1053 * @param arg Argument (ui_scrollbar_t *)
     1054 */
     1055static void ui_scrollbar_cm_page_down(ui_clickmatic_t *clickmatic, void *arg)
     1056{
     1057        ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
     1058
     1059        if (scrollbar->down_through_inside)
     1060                ui_scrollbar_page_down(scrollbar);
     1061}
     1062
    9151063/** @}
    9161064 */
Note: See TracChangeset for help on using the changeset viewer.