cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_DirectFB_WM.c (12839B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#if SDL_VIDEO_DRIVER_DIRECTFB
     24
     25#include "SDL_DirectFB_video.h"
     26#include "SDL_DirectFB_window.h"
     27
     28#include "../../events/SDL_windowevents_c.h"
     29
     30#define COLOR_EXPAND(col) col.r, col.g, col.b, col.a
     31
     32static DFB_Theme theme_std = {
     33    4, 4, 8, 8,
     34    {255, 200, 200, 200},
     35    24,
     36    {255, 0, 0, 255},
     37    16,
     38    {255, 255, 255, 255},
     39    "/usr/share/fonts/truetype/freefont/FreeSans.ttf",
     40    {255, 255, 0, 0},
     41    {255, 255, 255, 0},
     42};
     43
     44static DFB_Theme theme_none = {
     45    0, 0, 0, 0,
     46    {0, 0, 0, 0},
     47    0,
     48    {0, 0, 0, 0},
     49    0,
     50    {0, 0, 0, 0},
     51    NULL
     52};
     53
     54static void
     55DrawTriangle(IDirectFBSurface * s, int down, int x, int y, int w)
     56{
     57    int x1, x2, x3;
     58    int y1, y2, y3;
     59
     60    if (down) {
     61        x1 = x + w / 2;
     62        x2 = x;
     63        x3 = x + w;
     64        y1 = y + w;
     65        y2 = y;
     66        y3 = y;
     67    } else {
     68        x1 = x + w / 2;
     69        x2 = x;
     70        x3 = x + w;
     71        y1 = y;
     72        y2 = y + w;
     73        y3 = y + w;
     74    }
     75    s->FillTriangle(s, x1, y1, x2, y2, x3, y3);
     76}
     77
     78static void
     79LoadFont(_THIS, SDL_Window * window)
     80{
     81    SDL_DFB_DEVICEDATA(_this);
     82    SDL_DFB_WINDOWDATA(window);
     83
     84    if (windata->font != NULL) {
     85        SDL_DFB_RELEASE(windata->font);
     86        windata->font = NULL;
     87        SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font));
     88    }
     89
     90    if (windata->theme.font != NULL)
     91    {
     92        DFBFontDescription fdesc;
     93
     94        SDL_zero(fdesc);
     95        fdesc.flags = DFDESC_HEIGHT;
     96        fdesc.height = windata->theme.font_size;
     97        SDL_DFB_CHECK(devdata->
     98                      dfb->CreateFont(devdata->dfb, windata->theme.font,
     99                                      &fdesc, &windata->font));
    100        SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font));
    101    }
    102}
    103
    104static void
    105DrawCraption(_THIS, IDirectFBSurface * s, int x, int y, char *text)
    106{
    107    DFBSurfaceTextFlags flags;
    108
    109    flags = DSTF_CENTER | DSTF_TOP;
    110
    111    s->DrawString(s, text, -1, x, y, flags);
    112}
    113
    114void
    115DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window)
    116{
    117    SDL_DFB_WINDOWDATA(window);
    118    IDirectFBSurface *s = windata->window_surface;
    119    DFB_Theme *t = &windata->theme;
    120    int i;
    121    int d = (t->caption_size - t->font_size) / 2;
    122    int x, y, w;
    123
    124
    125    if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN))
    126        return;
    127
    128    SDL_DFB_CHECK(s->SetSrcBlendFunction(s, DSBF_ONE));
    129    SDL_DFB_CHECK(s->SetDstBlendFunction(s, DSBF_ZERO));
    130    SDL_DFB_CHECK(s->SetDrawingFlags(s, DSDRAW_NOFX));
    131    SDL_DFB_CHECK(s->SetBlittingFlags(s, DSBLIT_NOFX));
    132
    133    LoadFont(_this, window);
    134    /* s->SetDrawingFlags(s, DSDRAW_BLEND); */
    135    s->SetColor(s, COLOR_EXPAND(t->frame_color));
    136    /* top */
    137    for (i = 0; i < t->top_size; i++)
    138        s->DrawLine(s, 0, i, windata->size.w, i);
    139    /* bottom */
    140    for (i = windata->size.h - t->bottom_size; i < windata->size.h; i++)
    141        s->DrawLine(s, 0, i, windata->size.w, i);
    142    /* left */
    143    for (i = 0; i < t->left_size; i++)
    144        s->DrawLine(s, i, 0, i, windata->size.h);
    145    /* right */
    146    for (i = windata->size.w - t->right_size; i < windata->size.w; i++)
    147        s->DrawLine(s, i, 0, i, windata->size.h);
    148    /* Caption */
    149    s->SetColor(s, COLOR_EXPAND(t->caption_color));
    150    s->FillRectangle(s, t->left_size, t->top_size, windata->client.w,
    151                     t->caption_size);
    152    /* Close Button */
    153    w = t->caption_size;
    154    x = windata->size.w - t->right_size - w + d;
    155    y = t->top_size + d;
    156    s->SetColor(s, COLOR_EXPAND(t->close_color));
    157    DrawTriangle(s, 1, x, y, w - 2 * d);
    158    /* Max Button */
    159    s->SetColor(s, COLOR_EXPAND(t->max_color));
    160    DrawTriangle(s, window->flags & SDL_WINDOW_MAXIMIZED ? 1 : 0, x - w,
    161               y, w - 2 * d);
    162
    163    /* Caption */
    164    if (window->title) {
    165        s->SetColor(s, COLOR_EXPAND(t->font_color));
    166        DrawCraption(_this, s, (x - w) / 2, t->top_size + d, window->title);
    167    }
    168    /* Icon */
    169    if (windata->icon) {
    170        DFBRectangle dr;
    171
    172        dr.x = t->left_size + d;
    173        dr.y = t->top_size + d;
    174        dr.w = w - 2 * d;
    175        dr.h = w - 2 * d;
    176        s->SetBlittingFlags(s, DSBLIT_BLEND_ALPHACHANNEL);
    177
    178        s->StretchBlit(s, windata->icon, NULL, &dr);
    179    }
    180    windata->wm_needs_redraw = 0;
    181}
    182
    183DFBResult
    184DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch)
    185{
    186    SDL_DFB_WINDOWDATA(window);
    187    IDirectFBWindow *dfbwin = windata->dfbwin;
    188
    189    SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, cw, ch));
    190    dfbwin->GetSize(dfbwin, cw, ch);
    191    *cw -= windata->theme.left_size + windata->theme.right_size;
    192    *ch -=
    193        windata->theme.top_size + windata->theme.caption_size +
    194        windata->theme.bottom_size;
    195    return DFB_OK;
    196}
    197
    198void
    199DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h)
    200{
    201    SDL_DFB_WINDOWDATA(window);
    202
    203    if (!windata->is_managed)
    204        windata->theme = theme_none;
    205    else if (flags & SDL_WINDOW_BORDERLESS)
    206        /* desc.caps |= DWCAPS_NODECORATION;) */
    207        windata->theme = theme_none;
    208    else if (flags & SDL_WINDOW_FULLSCREEN) {
    209        windata->theme = theme_none;
    210    } else if (flags & SDL_WINDOW_MAXIMIZED) {
    211        windata->theme = theme_std;
    212        windata->theme.left_size = 0;
    213        windata->theme.right_size = 0;
    214        windata->theme.top_size = 0;
    215        windata->theme.bottom_size = 0;
    216    } else {
    217        windata->theme = theme_std;
    218    }
    219
    220    windata->client.x = windata->theme.left_size;
    221    windata->client.y = windata->theme.top_size + windata->theme.caption_size;
    222    windata->client.w = w;
    223    windata->client.h = h;
    224    windata->size.w =
    225        w + windata->theme.left_size + windata->theme.right_size;
    226    windata->size.h =
    227        h + windata->theme.top_size +
    228        windata->theme.caption_size + windata->theme.bottom_size;
    229}
    230
    231
    232enum
    233{
    234    WM_POS_NONE = 0x00,
    235    WM_POS_CAPTION = 0x01,
    236    WM_POS_CLOSE = 0x02,
    237    WM_POS_MAX = 0x04,
    238    WM_POS_LEFT = 0x08,
    239    WM_POS_RIGHT = 0x10,
    240    WM_POS_TOP = 0x20,
    241    WM_POS_BOTTOM = 0x40,
    242};
    243
    244static int
    245WMIsClient(DFB_WindowData * p, int x, int y)
    246{
    247    x -= p->client.x;
    248    y -= p->client.y;
    249    if (x < 0 || y < 0)
    250        return 0;
    251    if (x >= p->client.w || y >= p->client.h)
    252        return 0;
    253    return 1;
    254}
    255
    256static int
    257WMPos(DFB_WindowData * p, int x, int y)
    258{
    259    int pos = WM_POS_NONE;
    260
    261    if (!WMIsClient(p, x, y)) {
    262        if (y < p->theme.top_size) {
    263            pos |= WM_POS_TOP;
    264        } else if (y < p->client.y) {
    265            if (x <
    266                p->size.w - p->theme.right_size - 2 * p->theme.caption_size) {
    267                pos |= WM_POS_CAPTION;
    268            } else if (x <
    269                       p->size.w - p->theme.right_size -
    270                       p->theme.caption_size) {
    271                pos |= WM_POS_MAX;
    272            } else {
    273                pos |= WM_POS_CLOSE;
    274            }
    275        } else if (y >= p->size.h - p->theme.bottom_size) {
    276            pos |= WM_POS_BOTTOM;
    277        }
    278        if (x < p->theme.left_size) {
    279            pos |= WM_POS_LEFT;
    280        } else if (x >= p->size.w - p->theme.right_size) {
    281            pos |= WM_POS_RIGHT;
    282        }
    283    }
    284    return pos;
    285}
    286
    287int
    288DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
    289{
    290    SDL_DFB_DEVICEDATA(_this);
    291    SDL_DFB_WINDOWDATA(window);
    292    DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
    293    IDirectFBWindow *dfbwin = windata->dfbwin;
    294    DFBWindowOptions wopts;
    295
    296    if (!windata->is_managed)
    297        return 0;
    298
    299    SDL_DFB_CHECK(dfbwin->GetOptions(dfbwin, &wopts));
    300
    301    switch (evt->type) {
    302    case DWET_BUTTONDOWN:
    303        if (evt->buttons & DIBM_LEFT) {
    304            int pos = WMPos(windata, evt->x, evt->y);
    305            switch (pos) {
    306            case WM_POS_NONE:
    307                return 0;
    308            case WM_POS_CLOSE:
    309                windata->wm_grab = WM_POS_NONE;
    310                SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0,
    311                                    0);
    312                return 1;
    313            case WM_POS_MAX:
    314                windata->wm_grab = WM_POS_NONE;
    315                if (window->flags & SDL_WINDOW_MAXIMIZED) {
    316                    SDL_RestoreWindow(window);
    317                } else {
    318                    SDL_MaximizeWindow(window);
    319                }
    320                return 1;
    321            case WM_POS_CAPTION:
    322                if (!(wopts & DWOP_KEEP_STACKING)) {
    323                    DirectFB_RaiseWindow(_this, window);
    324                }
    325                if (window->flags & SDL_WINDOW_MAXIMIZED)
    326                    return 1;
    327                /* fall through */
    328            default:
    329                windata->wm_grab = pos;
    330                if (gwindata != NULL)
    331                    SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
    332                SDL_DFB_CHECK(dfbwin->GrabPointer(dfbwin));
    333                windata->wm_lastx = evt->cx;
    334                windata->wm_lasty = evt->cy;
    335            }
    336        }
    337        return 1;
    338    case DWET_BUTTONUP:
    339        if (!windata->wm_grab)
    340            return 0;
    341        if (!(evt->buttons & DIBM_LEFT)) {
    342            if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
    343                int dx = evt->cx - windata->wm_lastx;
    344                int dy = evt->cy - windata->wm_lasty;
    345
    346                if (!(wopts & DWOP_KEEP_SIZE)) {
    347                    int cw, ch;
    348                    if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
    349                        dx = 0;
    350                    else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
    351                        dy = 0;
    352                    SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch));
    353
    354                    /* necessary to trigger an event - ugly */
    355                    SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL));
    356                    SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx + 1, ch + dy));
    357                    SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL));
    358
    359                    SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
    360                }
    361            }
    362            SDL_DFB_CHECK(dfbwin->UngrabPointer(dfbwin));
    363            if (gwindata != NULL)
    364                SDL_DFB_CHECK(gwindata->dfbwin->GrabPointer(gwindata->dfbwin));
    365            windata->wm_grab = WM_POS_NONE;
    366            return 1;
    367        }
    368        break;
    369    case DWET_MOTION:
    370        if (!windata->wm_grab)
    371            return 0;
    372        if (evt->buttons & DIBM_LEFT) {
    373            int dx = evt->cx - windata->wm_lastx;
    374            int dy = evt->cy - windata->wm_lasty;
    375
    376            if (windata->wm_grab & WM_POS_CAPTION) {
    377                if (!(wopts & DWOP_KEEP_POSITION))
    378                    SDL_DFB_CHECK(dfbwin->Move(dfbwin, dx, dy));
    379            }
    380            if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
    381                if (!(wopts & DWOP_KEEP_SIZE)) {
    382                    int cw, ch;
    383
    384                    /* Make sure all events are disabled for this operation ! */
    385                    SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL));
    386
    387                    if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
    388                        dx = 0;
    389                    else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
    390                        dy = 0;
    391
    392                    SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch));
    393                    SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
    394
    395                    SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL));
    396                }
    397            }
    398            windata->wm_lastx = evt->cx;
    399            windata->wm_lasty = evt->cy;
    400            return 1;
    401        }
    402        break;
    403    case DWET_KEYDOWN:
    404        break;
    405    case DWET_KEYUP:
    406        break;
    407    default:
    408        ;
    409    }
    410    return 0;
    411}
    412
    413#endif /* SDL_VIDEO_DRIVER_DIRECTFB */