Ignore:
File:
1 edited

Legend:

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

    rec50d65e rb979ffb  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    171171 * @param window Window
    172172 * @param drect Display rectangle
     173 * @param wrect Window rectangle
     174 * @param prect Parent rectangle for popup placement or @c NULL
     175 * @param placement Window placement
    173176 * @param params Window parameters
    174177 * @param pos Place to store position of top-left corner
    175178 */
    176179static void ui_window_place(ui_window_t *window, gfx_rect_t *drect,
    177     ui_wnd_params_t *params, gfx_coord2_t *pos)
     180    gfx_rect_t *wrect, gfx_rect_t *prect, ui_wnd_placement_t placement,
     181    gfx_coord2_t *pos)
    178182{
    179183        gfx_coord2_t dims;
     
    181185        gfx_rect_t below_rect;
    182186
    183         assert(params->placement != ui_wnd_place_default ||
     187        assert(placement != ui_wnd_place_default ||
    184188            ui_is_fullscreen(window->ui));
    185189
     
    187191        pos->y = 0;
    188192
    189         switch (params->placement) {
     193        switch (placement) {
    190194        case ui_wnd_place_default:
    191                 assert(ui_is_fullscreen(window->ui));
     195        case ui_wnd_place_center:
     196                assert(placement != ui_wnd_place_default ||
     197                    ui_is_fullscreen(window->ui));
    192198                /* Center window */
    193                 gfx_rect_dims(&params->rect, &dims);
     199                gfx_rect_dims(wrect, &dims);
    194200                pos->x = (drect->p0.x + drect->p1.x) / 2 - dims.x / 2;
    195201                pos->y = (drect->p0.y + drect->p1.y) / 2 - dims.y / 2;
     
    197203        case ui_wnd_place_top_left:
    198204        case ui_wnd_place_full_screen:
    199                 pos->x = drect->p0.x - params->rect.p0.x;
    200                 pos->y = drect->p0.y - params->rect.p0.y;
     205                pos->x = drect->p0.x - wrect->p0.x;
     206                pos->y = drect->p0.y - wrect->p0.y;
    201207                break;
    202208        case ui_wnd_place_top_right:
    203                 pos->x = drect->p1.x - params->rect.p1.x;
    204                 pos->y = drect->p0.y - params->rect.p0.y;
     209                pos->x = drect->p1.x - wrect->p1.x;
     210                pos->y = drect->p0.y - wrect->p0.y;
    205211                break;
    206212        case ui_wnd_place_bottom_left:
    207                 pos->x = drect->p0.x - params->rect.p0.x;
    208                 pos->y = drect->p1.y - params->rect.p1.y;
     213                pos->x = drect->p0.x - wrect->p0.x;
     214                pos->y = drect->p1.y - wrect->p1.y;
    209215                break;
    210216        case ui_wnd_place_bottom_right:
    211                 pos->x = drect->p1.x - params->rect.p1.x;
    212                 pos->y = drect->p1.y - params->rect.p1.y;
     217                pos->x = drect->p1.x - wrect->p1.x;
     218                pos->y = drect->p1.y - wrect->p1.y;
    213219                break;
    214220        case ui_wnd_place_popup:
    215221                /* Compute rectangle when placed below */
    216                 below_pos.x = params->prect.p0.x;
    217                 below_pos.y = params->prect.p1.y;
    218                 gfx_rect_translate(&below_pos, &params->rect, &below_rect);
     222                below_pos.x = prect->p0.x;
     223                below_pos.y = prect->p1.y;
     224                gfx_rect_translate(&below_pos, wrect, &below_rect);
    219225
    220226                /* Does below_rect fit within the display? */
    221227                if (gfx_rect_is_inside(&below_rect, drect)) {
    222228                        /* Place popup window below parent rectangle */
    223                         pos->x = params->prect.p0.x - params->rect.p0.x;
    224                         pos->y = params->prect.p1.y - params->rect.p0.y;
     229                        pos->x = prect->p0.x - wrect->p0.x;
     230                        pos->y = prect->p1.y - wrect->p0.y;
    225231                } else {
    226232                        /* Place popup window above parent rectangle */
    227                         pos->x = params->prect.p0.x;
    228                         pos->y = params->prect.p0.y -
    229                             (params->rect.p1.y - params->rect.p0.y);
     233                        pos->x = prect->p0.x;
     234                        pos->y = prect->p0.y -
     235                            (wrect->p1.y - wrect->p0.y);
    230236                }
    231237                break;
    232238        }
     239}
     240
     241static void ui_window_set_dpos(ui_window_t *window, gfx_coord2_t *dpos)
     242{
     243        window->dpos = *dpos;
     244        if (window->xgc != NULL)
     245                xlate_gc_set_off(window->xgc, &window->dpos);
    233246}
    234247
     
    332345        mem_gc_t *memgc = NULL;
    333346        xlate_gc_t *xgc = NULL;
     347        gfx_coord2_t dpos;
    334348        errno_t rc;
    335349
     
    343357        dparams.rect = params->rect;
    344358        dparams.caption = params->caption;
    345         /* Only allow making the window larger */
    346         gfx_rect_dims(&params->rect, &dparams.min_size);
     359        dparams.min_size = params->min_size;
    347360
    348361        /*
     
    358371        if ((params->flags & ui_wndf_popup) != 0)
    359372                dparams.flags |= wndf_popup;
     373        if ((params->flags & ui_wndf_nofocus) != 0)
     374                dparams.flags |= wndf_nofocus;
    360375        if ((params->flags & ui_wndf_topmost) != 0)
    361376                dparams.flags |= wndf_topmost;
     
    381396                if (params->placement != ui_wnd_place_default) {
    382397                        /* Set initial display window position */
    383                         ui_window_place(window, &info.rect, params,
    384                             &dparams.pos);
     398                        ui_window_place(window, &info.rect, &params->rect,
     399                            &params->prect, params->placement, &dparams.pos);
    385400
    386401                        dparams.flags |= wndf_setpos;
     
    474489#endif
    475490        if (ui->display == NULL) {
    476                 ui_window_place(window, &ui->rect, params, &window->dpos);
    477 
    478                 if (window->xgc != NULL)
    479                         xlate_gc_set_off(window->xgc, &window->dpos);
     491                ui_window_place(window, &ui->rect, &params->rect, &params->prect,
     492                    params->placement, &dpos);
     493                ui_window_set_dpos(window, &dpos);
    480494        }
    481495
     
    535549}
    536550
     551/** Update window placement after screen resize (only in fullscreen UI).
     552 *
     553 * @param window UI window
     554 */
     555void ui_window_update_placement(ui_window_t *window)
     556{
     557        if (window->placement == ui_wnd_place_full_screen ||
     558            (window->flags & uiwf_maximized) != 0) {
     559                /* Update size of fullscreen or maximized window. */
     560                (void)ui_window_resize(window, &window->ui->rect);
     561                ui_window_send_resize(window);
     562        }
     563}
     564
    537565/** Destroy window.
    538566 *
     
    569597        /* Need to repaint if windows are emulated */
    570598        if (ui_is_fullscreen(ui)) {
    571                 ui_paint(ui);
     599                (void)ui_paint(ui);
    572600                /* Send focus event to newly active window */
    573601                nwindow = ui_window_get_active(ui);
     
    612640        window->control = NULL;
    613641        control->elemp = NULL;
     642}
     643
     644/** Get first (lowermost) window (only valid in fullscreen mode).
     645 *
     646 * @param ui User interface
     647 * @return First window
     648 */
     649ui_window_t *ui_window_first(ui_t *ui)
     650{
     651        link_t *link;
     652
     653        link = list_first(&ui->windows);
     654        if (link == NULL)
     655                return NULL;
     656
     657        return list_get_instance(link, ui_window_t, lwindows);
     658}
     659
     660/** Get next window (only valid in fullscreen mode).
     661 *
     662 * @param cur Current window
     663 * @return First window
     664 */
     665ui_window_t *ui_window_next(ui_window_t *cur)
     666{
     667        link_t *link;
     668
     669        link = list_next(&cur->lwindows, &cur->ui->windows);
     670        if (link == NULL)
     671                return NULL;
     672
     673        return list_get_instance(link, ui_window_t, lwindows);
    614674}
    615675
     
    650710        gfx_bitmap_alloc_t app_alloc;
    651711        gfx_bitmap_alloc_t win_alloc;
     712        gfx_coord2_t dpos;
    652713        errno_t rc;
    653714
     
    725786                        break;
    726787                }
     788        } else {
     789                /* fullscreen mode or unit tests */
     790                switch (scop) {
     791                case ui_wsc_resize:
     792                        break;
     793                case ui_wsc_maximize:
     794                        window->normal_dpos = window->dpos;
     795                        dpos.x = 0;
     796                        dpos.y = 0;
     797                        ui_window_set_dpos(window, &dpos);
     798                        break;
     799                case ui_wsc_unmaximize:
     800                        ui_window_set_dpos(window, &window->normal_dpos);
     801                        break;
     802                }
    727803        }
    728804
     
    732808                /* Window is resized, now we can map the window bitmap again */
    733809                gfx_bitmap_params_init(&win_params);
    734                 win_params.flags |= bmpf_direct_output;
     810                if (window->ui->display != NULL)
     811                        win_params.flags |= bmpf_direct_output;
    735812                win_params.rect = nrect;
    736813
     
    761838                gfx_bitmap_destroy(window->app_bmp);
    762839                window->app_bmp = app_bmp;
     840        }
     841
     842        switch (scop) {
     843        case ui_wsc_resize:
     844                break;
     845        case ui_wsc_maximize:
     846                window->flags |= uiwf_maximized;
     847                break;
     848        case ui_wsc_unmaximize:
     849                window->flags &= ~uiwf_maximized;
     850                break;
    763851        }
    764852
     
    784872errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
    785873{
    786         return ui_window_size_change(window, rect, ui_wsc_resize);
     874        errno_t rc;
     875
     876        rc = ui_window_size_change(window, rect, ui_wsc_resize);
     877        if (rc != EOK)
     878                return rc;
     879
     880        /* Need to repaint UI if windows are emulated */
     881        if (ui_is_fullscreen(window->ui))
     882                (void)ui_paint(window->ui);
     883
     884        return EOK;
    787885}
    788886
     
    9751073        ui_t *ui = window->ui;
    9761074
    977         ui_lock(ui);
     1075        fibril_mutex_lock(&ui->lock);
    9781076        ui_window_send_close(window);
    979         ui_unlock(ui);
     1077        fibril_mutex_unlock(&ui->lock);
    9801078}
    9811079
     
    9861084        ui_t *ui = window->ui;
    9871085
    988         ui_lock(ui);
     1086        fibril_mutex_lock(&ui->lock);
    9891087        (void)nfocus;
    9901088
     
    9951093
    9961094        ui_window_send_focus(window, nfocus);
    997         ui_unlock(ui);
     1095        fibril_mutex_unlock(&ui->lock);
    9981096}
    9991097
     
    10041102        ui_t *ui = window->ui;
    10051103
    1006         ui_lock(ui);
     1104        fibril_mutex_lock(&ui->lock);
    10071105        ui_window_send_kbd(window, kbd_event);
    1008         ui_unlock(ui);
     1106        fibril_mutex_unlock(&ui->lock);
    10091107}
    10101108
     
    10201118                return;
    10211119
    1022         ui_lock(ui);
     1120        fibril_mutex_lock(&ui->lock);
    10231121
    10241122        claim = ui_wdecor_pos_event(window->wdecor, event);
    10251123        if (claim == ui_claimed) {
    1026                 ui_unlock(ui);
     1124                fibril_mutex_unlock(&ui->lock);
    10271125                return;
    10281126        }
    10291127
    10301128        ui_window_send_pos(window, event);
    1031         ui_unlock(ui);
     1129        fibril_mutex_unlock(&ui->lock);
    10321130}
    10331131
     
    10451143                return;
    10461144
    1047         ui_lock(ui);
     1145        fibril_mutex_lock(&ui->lock);
    10481146        (void) ui_window_resize(window, rect);
    1049         (void) ui_window_paint(window);
    1050         ui_unlock(ui);
     1147        ui_window_send_resize(window);
     1148        fibril_mutex_unlock(&ui->lock);
    10511149}
    10521150
     
    10571155        ui_t *ui = window->ui;
    10581156
    1059         ui_lock(ui);
     1157        fibril_mutex_lock(&ui->lock);
    10601158
    10611159        if (window->wdecor != NULL && nfocus == 0) {
     
    10651163
    10661164        ui_window_send_unfocus(window, nfocus);
    1067         ui_unlock(ui);
     1165        fibril_mutex_unlock(&ui->lock);
    10681166}
    10691167
     
    12951393void ui_window_send_minimize(ui_window_t *window)
    12961394{
    1297         if (window->cb != NULL && window->cb->maximize != NULL)
     1395        if (window->cb != NULL && window->cb->minimize != NULL)
    12981396                window->cb->minimize(window, window->arg);
    12991397        else
     
    13931491        else
    13941492                return ui_window_def_unfocus(window, nfocus);
     1493}
     1494
     1495/** Send window resize event.
     1496 *
     1497 * @param window Window
     1498 */
     1499void ui_window_send_resize(ui_window_t *window)
     1500{
     1501        if (window->cb != NULL && window->cb->resize != NULL)
     1502                window->cb->resize(window, window->arg);
     1503        else
     1504                return ui_window_def_resize(window);
    13951505}
    13961506
     
    14741584
    14751585        window->normal_rect = old_rect;
    1476         (void) ui_window_paint(window);
     1586        ui_window_send_resize(window);
     1587
     1588        /* Need to repaint UI if windows are emulated */
     1589        if (ui_is_fullscreen(window->ui))
     1590                (void)ui_paint(window->ui);
     1591
    14771592        return EOK;
    14781593}
     
    14991614        }
    15001615
    1501         (void) ui_window_paint(window);
     1616        ui_window_send_resize(window);
     1617
     1618        /* Need to repaint UI if windows are emulated */
     1619        if (ui_is_fullscreen(window->ui))
     1620                (void)ui_paint(window->ui);
     1621
    15021622        return EOK;
    15031623}
     
    15731693        if (window->control != NULL)
    15741694                ui_control_unfocus(window->control, nfocus);
     1695}
     1696
     1697/** Default window resize routine.
     1698 *
     1699 * @param window Window
     1700 * @return EOK on success or an error code
     1701 */
     1702void ui_window_def_resize(ui_window_t *window)
     1703{
     1704        ui_window_paint(window);
    15751705}
    15761706
Note: See TracChangeset for help on using the changeset viewer.