src/video/directfb/SDL_DirectFB_WM.c
author Couriersud
Sun, 11 Jan 2009 23:49:23 +0000
changeset 3023 d72a0dd80e8b
child 3040 62d4992e5a92
permissions -rw-r--r--
DirectFB cleanups & simple window manager

- use SDL_getenv, not getenv ...
- no more support for 0.9.25 - not even mentioned any longer on directfb.org
- fix fullscreen issues
- add a simple window manager unless the directfb team comes up with a working wm.

The driver has support for a very, very basic window manager you may
want to use when runnning with "wm=default". Use

export SDL_DIRECTFB_WM=1

to enable basic window borders including icon support. In order to have the window title rendered,
you need to have the following font installed:

/usr/share/fonts/truetype/freefont/FreeSans.ttf
couriersud@3023
     1
/*
couriersud@3023
     2
    SDL - Simple DirectMedia Layer
couriersud@3023
     3
    Copyright (C) 1997-2009 Sam Lantinga
couriersud@3023
     4
couriersud@3023
     5
    This library is free software; you can redistribute it and/or
couriersud@3023
     6
    modify it under the terms of the GNU Lesser General Public
couriersud@3023
     7
    License as published by the Free Software Foundation; either
couriersud@3023
     8
    version 2.1 of the License, or (at your option) any later version.
couriersud@3023
     9
couriersud@3023
    10
    This library is distributed in the hope that it will be useful,
couriersud@3023
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
couriersud@3023
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
couriersud@3023
    13
    Lesser General Public License for more details.
couriersud@3023
    14
couriersud@3023
    15
    You should have received a copy of the GNU Lesser General Public
couriersud@3023
    16
    License along with this library; if not, write to the Free Software
couriersud@3023
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
couriersud@3023
    18
couriersud@3023
    19
    Sam Lantinga
couriersud@3023
    20
    slouken@libsdl.org
couriersud@3023
    21
*/
couriersud@3023
    22
#include "SDL_config.h"
couriersud@3023
    23
couriersud@3023
    24
//#include "SDL_syswm.h"
couriersud@3023
    25
//#include "../SDL_sysvideo.h"
couriersud@3023
    26
//#include "../../events/SDL_keyboard_c.h"
couriersud@3023
    27
couriersud@3023
    28
#include "SDL_DirectFB_video.h"
couriersud@3023
    29
couriersud@3023
    30
#define COLOR_EXPAND(col) col.r, col.g, col.b, col.a
couriersud@3023
    31
couriersud@3023
    32
static DFB_Theme theme_std = {
couriersud@3023
    33
    4, 4, 8, 8,
couriersud@3023
    34
    {255, 200, 200, 200},
couriersud@3023
    35
    24,
couriersud@3023
    36
    {255, 0, 0, 255},
couriersud@3023
    37
    16,
couriersud@3023
    38
    {255, 255, 255, 255},
couriersud@3023
    39
    "/usr/share/fonts/truetype/freefont/FreeSans.ttf",
couriersud@3023
    40
    {255, 255, 0, 0},
couriersud@3023
    41
    {255, 255, 255, 0},
couriersud@3023
    42
};
couriersud@3023
    43
couriersud@3023
    44
static DFB_Theme theme_none = {
couriersud@3023
    45
    0, 0, 0, 0,
couriersud@3023
    46
    {0, 0, 0, 0},
couriersud@3023
    47
    0,
couriersud@3023
    48
    {0, 0, 0, 0},
couriersud@3023
    49
    0,
couriersud@3023
    50
    {0, 0, 0, 0},
couriersud@3023
    51
    NULL
couriersud@3023
    52
};
couriersud@3023
    53
couriersud@3023
    54
static void
couriersud@3023
    55
DrTriangle(IDirectFBSurface * s, int down, int x, int y, int w)
couriersud@3023
    56
{
couriersud@3023
    57
    int x1, x2, x3;
couriersud@3023
    58
    int y1, y2, y3;
couriersud@3023
    59
couriersud@3023
    60
    if (down) {
couriersud@3023
    61
        x1 = x + w / 2;
couriersud@3023
    62
        x2 = x;
couriersud@3023
    63
        x3 = x + w;
couriersud@3023
    64
        y1 = y + w;
couriersud@3023
    65
        y2 = y;
couriersud@3023
    66
        y3 = y;
couriersud@3023
    67
    } else {
couriersud@3023
    68
        x1 = x + w / 2;
couriersud@3023
    69
        x2 = x;
couriersud@3023
    70
        x3 = x + w;
couriersud@3023
    71
        y1 = y;
couriersud@3023
    72
        y2 = y + w;
couriersud@3023
    73
        y3 = y + w;
couriersud@3023
    74
    }
couriersud@3023
    75
    s->FillTriangle(s, x1, y1, x2, y2, x3, y3);
couriersud@3023
    76
}
couriersud@3023
    77
couriersud@3023
    78
static void
couriersud@3023
    79
DrCaption(IDirectFBSurface * s, int x, int y, char *text)
couriersud@3023
    80
{
couriersud@3023
    81
    DFBSurfaceTextFlags flags;
couriersud@3023
    82
couriersud@3023
    83
    flags = DSTF_CENTER | DSTF_TOP;
couriersud@3023
    84
couriersud@3023
    85
    s->DrawString(s, text, -1, x, y, flags);
couriersud@3023
    86
}
couriersud@3023
    87
couriersud@3023
    88
void
couriersud@3023
    89
DirectFB_WM_RedrawLayout(SDL_Window * window)
couriersud@3023
    90
{
couriersud@3023
    91
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
    92
    IDirectFBSurface *s = windata->window_surface;
couriersud@3023
    93
    DFB_Theme *t = &windata->theme;
couriersud@3023
    94
    int i;
couriersud@3023
    95
    int d = (t->caption_size - t->font_size) / 2;
couriersud@3023
    96
    int x, y, w;
couriersud@3023
    97
couriersud@3023
    98
couriersud@3023
    99
    if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN))
couriersud@3023
   100
        return;
couriersud@3023
   101
couriersud@3023
   102
    //s->SetDrawingFlags(s, DSDRAW_BLEND);
couriersud@3023
   103
    s->SetColor(s, COLOR_EXPAND(t->frame_color));
couriersud@3023
   104
    /* top */
couriersud@3023
   105
    for (i = 0; i < t->top_size; i++)
couriersud@3023
   106
        s->DrawLine(s, 0, i, windata->size.w, i);
couriersud@3023
   107
    /* bottom */
couriersud@3023
   108
    for (i = windata->size.h - t->bottom_size; i < windata->size.h; i++)
couriersud@3023
   109
        s->DrawLine(s, 0, i, windata->size.w, i);
couriersud@3023
   110
    /* left */
couriersud@3023
   111
    for (i = 0; i < t->left_size; i++)
couriersud@3023
   112
        s->DrawLine(s, i, 0, i, windata->size.h);
couriersud@3023
   113
    /* right */
couriersud@3023
   114
    for (i = windata->size.w - t->right_size; i < windata->size.w; i++)
couriersud@3023
   115
        s->DrawLine(s, i, 0, i, windata->size.h);
couriersud@3023
   116
    /* Caption */
couriersud@3023
   117
    s->SetColor(s, COLOR_EXPAND(t->caption_color));
couriersud@3023
   118
    s->FillRectangle(s, t->left_size, t->top_size, windata->client.w,
couriersud@3023
   119
                     t->caption_size);
couriersud@3023
   120
    /* Close Button */
couriersud@3023
   121
    w = t->caption_size;
couriersud@3023
   122
    x = windata->size.w - t->right_size - w + d;
couriersud@3023
   123
    y = t->top_size + d;
couriersud@3023
   124
    s->SetColor(s, COLOR_EXPAND(t->close_color));
couriersud@3023
   125
    DrTriangle(s, 1, x, y, w - 2 * d);
couriersud@3023
   126
    /* Max Button */
couriersud@3023
   127
    s->SetColor(s, COLOR_EXPAND(t->max_color));
couriersud@3023
   128
    DrTriangle(s, window->flags & SDL_WINDOW_MAXIMIZED ? 1 : 0, x - w,
couriersud@3023
   129
               y, w - 2 * d);
couriersud@3023
   130
couriersud@3023
   131
    /* Caption */
couriersud@3023
   132
    if (window->title) {
couriersud@3023
   133
        s->SetColor(s, COLOR_EXPAND(t->font_color));
couriersud@3023
   134
        DrCaption(s, (x - w) / 2, t->top_size + d, window->title);
couriersud@3023
   135
    }
couriersud@3023
   136
    /* Icon */
couriersud@3023
   137
    if (windata->icon) {
couriersud@3023
   138
        DFBRectangle dr;
couriersud@3023
   139
couriersud@3023
   140
        dr.x = t->left_size + d;
couriersud@3023
   141
        dr.y = t->top_size + d;
couriersud@3023
   142
        dr.w = w - 2 * d;
couriersud@3023
   143
        dr.h = w - 2 * d;
couriersud@3023
   144
        s->SetBlittingFlags(s, DSBLIT_BLEND_ALPHACHANNEL);
couriersud@3023
   145
couriersud@3023
   146
        s->StretchBlit(s, windata->icon, NULL, &dr);
couriersud@3023
   147
    }
couriersud@3023
   148
    windata->wm_needs_redraw = 0;
couriersud@3023
   149
}
couriersud@3023
   150
couriersud@3023
   151
DFBResult
couriersud@3023
   152
DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch)
couriersud@3023
   153
{
couriersud@3023
   154
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   155
    DFBResult ret;
couriersud@3023
   156
couriersud@3023
   157
    ret = windata->window->GetSize(windata->window, cw, ch);
couriersud@3023
   158
    *cw -= windata->theme.left_size + windata->theme.right_size;
couriersud@3023
   159
    *ch -=
couriersud@3023
   160
        windata->theme.top_size + windata->theme.caption_size +
couriersud@3023
   161
        windata->theme.bottom_size;
couriersud@3023
   162
    return ret;
couriersud@3023
   163
}
couriersud@3023
   164
couriersud@3023
   165
void
couriersud@3023
   166
DirectFB_WM_AdjustWindowLayout(SDL_Window * window)
couriersud@3023
   167
{
couriersud@3023
   168
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   169
couriersud@3023
   170
    if (!windata->is_managed)
couriersud@3023
   171
        windata->theme = theme_none;
couriersud@3023
   172
    else if (window->flags & SDL_WINDOW_FULLSCREEN) {
couriersud@3023
   173
        windata->theme = theme_none;
couriersud@3023
   174
    } else if (window->flags & SDL_WINDOW_MAXIMIZED) {
couriersud@3023
   175
        windata->theme = theme_std;
couriersud@3023
   176
        windata->theme.left_size = 0;
couriersud@3023
   177
        windata->theme.right_size = 0;
couriersud@3023
   178
        windata->theme.top_size = 0;
couriersud@3023
   179
        windata->theme.bottom_size = 0;
couriersud@3023
   180
    } else {
couriersud@3023
   181
        windata->theme = theme_std;
couriersud@3023
   182
    }
couriersud@3023
   183
couriersud@3023
   184
    windata->client.x = windata->theme.left_size;
couriersud@3023
   185
    windata->client.y = windata->theme.top_size + windata->theme.caption_size;
couriersud@3023
   186
    windata->client.w = window->w;
couriersud@3023
   187
    windata->client.h = window->h;
couriersud@3023
   188
    windata->size.w =
couriersud@3023
   189
        window->w + windata->theme.left_size + windata->theme.right_size;
couriersud@3023
   190
    windata->size.h =
couriersud@3023
   191
        window->h + windata->theme.top_size +
couriersud@3023
   192
        windata->theme.caption_size + windata->theme.bottom_size;
couriersud@3023
   193
}
couriersud@3023
   194
couriersud@3023
   195
void
couriersud@3023
   196
DirectFB_WM_MaximizeWindow(_THIS, SDL_Window * window)
couriersud@3023
   197
{
couriersud@3023
   198
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   199
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
couriersud@3023
   200
couriersud@3023
   201
    windata->window->GetPosition(windata->window,
couriersud@3023
   202
                                     &windata->restore.x,
couriersud@3023
   203
                                     &windata->restore.y);
couriersud@3023
   204
    windata->window->GetSize(windata->window, &windata->restore.w,
couriersud@3023
   205
                                 &windata->restore.h);
couriersud@3023
   206
couriersud@3023
   207
    /* Do this already here */
couriersud@3023
   208
    window->flags |= SDL_WINDOW_MAXIMIZED;
couriersud@3023
   209
    DirectFB_WM_AdjustWindowLayout(window);
couriersud@3023
   210
couriersud@3023
   211
    windata->window->MoveTo(windata->window, 0, 0);
couriersud@3023
   212
    windata->window->Resize(windata->window,
couriersud@3023
   213
                            display->current_mode.w,
couriersud@3023
   214
                            display->current_mode.h);
couriersud@3023
   215
    SDL_SendWindowEvent(windata->sdl_id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
couriersud@3023
   216
}
couriersud@3023
   217
couriersud@3023
   218
void
couriersud@3023
   219
DirectFB_WM_RestoreWindow(_THIS, SDL_Window * window)
couriersud@3023
   220
{
couriersud@3023
   221
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   222
couriersud@3023
   223
    /* Do this already here */
couriersud@3023
   224
    //window->flags &= ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED);
couriersud@3023
   225
couriersud@3023
   226
    DirectFB_WM_AdjustWindowLayout(window);
couriersud@3023
   227
    windata->window->MoveTo(windata->window, windata->restore.x,
couriersud@3023
   228
                            windata->restore.y);
couriersud@3023
   229
    windata->window->Resize(windata->window, windata->restore.w,
couriersud@3023
   230
                            windata->restore.h);
couriersud@3023
   231
    SDL_SendWindowEvent(windata->sdl_id, SDL_WINDOWEVENT_RESTORED, 0, 0);
couriersud@3023
   232
}
couriersud@3023
   233
couriersud@3023
   234
enum
couriersud@3023
   235
{
couriersud@3023
   236
    WM_POS_NONE = 0x00,
couriersud@3023
   237
    WM_POS_CAPTION = 0x01,
couriersud@3023
   238
    WM_POS_CLOSE = 0x02,
couriersud@3023
   239
    WM_POS_MAX = 0x04,
couriersud@3023
   240
    WM_POS_LEFT = 0x08,
couriersud@3023
   241
    WM_POS_RIGHT = 0x10,
couriersud@3023
   242
    WM_POS_TOP = 0x20,
couriersud@3023
   243
    WM_POS_BOTTOM = 0x40,
couriersud@3023
   244
};
couriersud@3023
   245
couriersud@3023
   246
static int
couriersud@3023
   247
WMIsClient(DFB_WindowData * p, int x, int y)
couriersud@3023
   248
{
couriersud@3023
   249
    x -= p->client.x;
couriersud@3023
   250
    y -= p->client.y;
couriersud@3023
   251
    if (x < 0 || y < 0)
couriersud@3023
   252
        return 0;
couriersud@3023
   253
    if (x >= p->client.w || y >= p->client.h)
couriersud@3023
   254
        return 0;
couriersud@3023
   255
    return 1;
couriersud@3023
   256
}
couriersud@3023
   257
couriersud@3023
   258
static int
couriersud@3023
   259
WMPos(DFB_WindowData * p, int x, int y)
couriersud@3023
   260
{
couriersud@3023
   261
    int pos = WM_POS_NONE;
couriersud@3023
   262
couriersud@3023
   263
    if (!WMIsClient(p, x, y)) {
couriersud@3023
   264
        if (y < p->theme.top_size) {
couriersud@3023
   265
            pos |= WM_POS_TOP;
couriersud@3023
   266
        } else if (y < p->client.y) {
couriersud@3023
   267
            if (x <
couriersud@3023
   268
                p->size.w - p->theme.right_size - 2 * p->theme.caption_size) {
couriersud@3023
   269
                pos |= WM_POS_CAPTION;
couriersud@3023
   270
            } else if (x <
couriersud@3023
   271
                       p->size.w - p->theme.right_size -
couriersud@3023
   272
                       p->theme.caption_size) {
couriersud@3023
   273
                pos |= WM_POS_MAX;
couriersud@3023
   274
            } else {
couriersud@3023
   275
                pos |= WM_POS_CLOSE;
couriersud@3023
   276
            }
couriersud@3023
   277
        } else if (y >= p->size.h - p->theme.bottom_size) {
couriersud@3023
   278
            pos |= WM_POS_BOTTOM;
couriersud@3023
   279
        }
couriersud@3023
   280
        if (x < p->theme.left_size) {
couriersud@3023
   281
            pos |= WM_POS_LEFT;
couriersud@3023
   282
        } else if (x >= p->size.w - p->theme.right_size) {
couriersud@3023
   283
            pos |= WM_POS_RIGHT;
couriersud@3023
   284
        }
couriersud@3023
   285
    }
couriersud@3023
   286
    return pos;
couriersud@3023
   287
}
couriersud@3023
   288
couriersud@3023
   289
static int wm_grab;
couriersud@3023
   290
static int wm_lastx;
couriersud@3023
   291
static int wm_lasty;
couriersud@3023
   292
couriersud@3023
   293
int
couriersud@3023
   294
DirectFB_WM_ProcessEvent(_THIS, SDL_Window *window, DFBWindowEvent * evt)
couriersud@3023
   295
{
couriersud@3023
   296
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   297
couriersud@3023
   298
    if (!windata->is_managed)
couriersud@3023
   299
        return 0;
couriersud@3023
   300
couriersud@3023
   301
    switch (evt->type) {
couriersud@3023
   302
    case DWET_BUTTONDOWN:
couriersud@3023
   303
        if (evt->buttons & DIBM_LEFT) {
couriersud@3023
   304
            int pos = WMPos(windata, evt->x, evt->y);
couriersud@3023
   305
            switch (pos) {
couriersud@3023
   306
            case WM_POS_NONE:
couriersud@3023
   307
                return 0;
couriersud@3023
   308
            case WM_POS_CLOSE:
couriersud@3023
   309
                SDL_SendWindowEvent(windata->sdl_id, SDL_WINDOWEVENT_CLOSE, 0, 0);
couriersud@3023
   310
                return 1;
couriersud@3023
   311
            case WM_POS_MAX:
couriersud@3023
   312
                if (window->flags & SDL_WINDOW_MAXIMIZED) {
couriersud@3023
   313
                    DirectFB_WM_RestoreWindow(_this, window);
couriersud@3023
   314
                } else {
couriersud@3023
   315
                	DirectFB_WM_MaximizeWindow(_this, window);
couriersud@3023
   316
                }
couriersud@3023
   317
                return 1;
couriersud@3023
   318
            default:
couriersud@3023
   319
                wm_grab = pos;
couriersud@3023
   320
                windata->window->GrabPointer(windata->window);
couriersud@3023
   321
                wm_lastx = evt->cx;
couriersud@3023
   322
                wm_lasty = evt->cy;
couriersud@3023
   323
            }
couriersud@3023
   324
        }
couriersud@3023
   325
        return 1;
couriersud@3023
   326
    case DWET_BUTTONUP:
couriersud@3023
   327
        break;
couriersud@3023
   328
    case DWET_MOTION:
couriersud@3023
   329
        if (!wm_grab)
couriersud@3023
   330
            return 0;
couriersud@3023
   331
        if (evt->buttons & DIBM_LEFT) {
couriersud@3023
   332
            int dx = evt->cx - wm_lastx;
couriersud@3023
   333
            int dy = evt->cy - wm_lasty;
couriersud@3023
   334
            int cw, ch;
couriersud@3023
   335
couriersud@3023
   336
            if (wm_grab & WM_POS_CAPTION)
couriersud@3023
   337
                windata->window->Move(windata->window, dx, dy);
couriersud@3023
   338
            if (wm_grab & WM_POS_RIGHT) {
couriersud@3023
   339
                windata->window->GetSize(windata->window, &cw, &ch);
couriersud@3023
   340
                windata->window->Resize(windata->window, cw + dx, ch);
couriersud@3023
   341
            }
couriersud@3023
   342
            if (wm_grab & WM_POS_BOTTOM) {
couriersud@3023
   343
                windata->window->GetSize(windata->window, &cw, &ch);
couriersud@3023
   344
                windata->window->Resize(windata->window, cw, ch + dy);
couriersud@3023
   345
            }
couriersud@3023
   346
            wm_lastx = evt->cx;
couriersud@3023
   347
            wm_lasty = evt->cy;
couriersud@3023
   348
            return 1;
couriersud@3023
   349
        }
couriersud@3023
   350
        windata->window->UngrabPointer(windata->window);
couriersud@3023
   351
        wm_grab = WM_POS_NONE;
couriersud@3023
   352
        break;
couriersud@3023
   353
    case DWET_KEYDOWN:
couriersud@3023
   354
        break;
couriersud@3023
   355
    case DWET_KEYUP:
couriersud@3023
   356
        break;
couriersud@3023
   357
    default:
couriersud@3023
   358
        ;
couriersud@3023
   359
    }
couriersud@3023
   360
    return 0;
couriersud@3023
   361
}