src/video/directfb/SDL_DirectFB_WM.c
author Sam Lantinga
Mon, 16 Aug 2010 09:04:55 -0700
changeset 4636 b196d2758026
parent 4568 25b9cd8bdc30
child 5199 164f20ba08eb
permissions -rw-r--r--
Couriersud to Sam

Hi Sam,

20100815_1.diff contains updates for the directfb driver:

- more documentation, mainly on software OpenGL in README.directfb
- Revised error handling leading to leaner code
- Improved/fixed OpenGL handling of multiple contexts.
- Made the built-in simple window manager handle OpenGL windows.
- Rewrote pixelformat mapping - this was quite ugly before.

Well, all software GL, but working :-)
couriersud@3023
     1
/*
couriersud@3023
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 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
slouken@4636
    30
#include "../../events/SDL_windowevents_c.h"
slouken@4636
    31
couriersud@3023
    32
#define COLOR_EXPAND(col) col.r, col.g, col.b, col.a
couriersud@3023
    33
couriersud@3023
    34
static DFB_Theme theme_std = {
couriersud@3023
    35
    4, 4, 8, 8,
couriersud@3023
    36
    {255, 200, 200, 200},
couriersud@3023
    37
    24,
couriersud@3023
    38
    {255, 0, 0, 255},
couriersud@3023
    39
    16,
couriersud@3023
    40
    {255, 255, 255, 255},
couriersud@3023
    41
    "/usr/share/fonts/truetype/freefont/FreeSans.ttf",
couriersud@3023
    42
    {255, 255, 0, 0},
couriersud@3023
    43
    {255, 255, 255, 0},
couriersud@3023
    44
};
couriersud@3023
    45
couriersud@3023
    46
static DFB_Theme theme_none = {
couriersud@3023
    47
    0, 0, 0, 0,
couriersud@3023
    48
    {0, 0, 0, 0},
couriersud@3023
    49
    0,
couriersud@3023
    50
    {0, 0, 0, 0},
couriersud@3023
    51
    0,
couriersud@3023
    52
    {0, 0, 0, 0},
couriersud@3023
    53
    NULL
couriersud@3023
    54
};
couriersud@3023
    55
couriersud@3023
    56
static void
slouken@4636
    57
DrawTriangle(IDirectFBSurface * s, int down, int x, int y, int w)
couriersud@3023
    58
{
couriersud@3023
    59
    int x1, x2, x3;
couriersud@3023
    60
    int y1, y2, y3;
couriersud@3023
    61
couriersud@3023
    62
    if (down) {
couriersud@3023
    63
        x1 = x + w / 2;
couriersud@3023
    64
        x2 = x;
couriersud@3023
    65
        x3 = x + w;
couriersud@3023
    66
        y1 = y + w;
couriersud@3023
    67
        y2 = y;
couriersud@3023
    68
        y3 = y;
couriersud@3023
    69
    } else {
couriersud@3023
    70
        x1 = x + w / 2;
couriersud@3023
    71
        x2 = x;
couriersud@3023
    72
        x3 = x + w;
couriersud@3023
    73
        y1 = y;
couriersud@3023
    74
        y2 = y + w;
couriersud@3023
    75
        y3 = y + w;
couriersud@3023
    76
    }
couriersud@3023
    77
    s->FillTriangle(s, x1, y1, x2, y2, x3, y3);
couriersud@3023
    78
}
couriersud@3023
    79
couriersud@3023
    80
static void
slouken@4636
    81
LoadFont(_THIS, SDL_Window * window)
slouken@4636
    82
{
slouken@4636
    83
    SDL_DFB_DEVICEDATA(_this);
slouken@4636
    84
    SDL_DFB_WINDOWDATA(window);
slouken@4636
    85
slouken@4636
    86
	if (windata->font != NULL) {
slouken@4636
    87
		SDL_DFB_RELEASE(windata->font);
slouken@4636
    88
	    windata->font = NULL;
slouken@4636
    89
	    SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font));
slouken@4636
    90
	}
slouken@4636
    91
	
slouken@4636
    92
	if (windata->theme.font != NULL)
slouken@4636
    93
	{
slouken@4636
    94
        DFBFontDescription fdesc;
slouken@4636
    95
slouken@4636
    96
		SDL_zero(fdesc);
slouken@4636
    97
	    fdesc.flags = DFDESC_HEIGHT;
slouken@4636
    98
	    fdesc.height = windata->theme.font_size;
slouken@4636
    99
	    SDL_DFB_CHECK(devdata->
slouken@4636
   100
	                  dfb->CreateFont(devdata->dfb, windata->theme.font,
slouken@4636
   101
	                                  &fdesc, &windata->font));
slouken@4636
   102
	    SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, windata->font));
slouken@4636
   103
	}
slouken@4636
   104
}
slouken@4636
   105
slouken@4636
   106
static void
slouken@4636
   107
DrawCraption(_THIS, IDirectFBSurface * s, int x, int y, char *text)
couriersud@3023
   108
{
couriersud@3023
   109
    DFBSurfaceTextFlags flags;
couriersud@3023
   110
couriersud@3023
   111
    flags = DSTF_CENTER | DSTF_TOP;
couriersud@3023
   112
couriersud@3023
   113
    s->DrawString(s, text, -1, x, y, flags);
couriersud@3023
   114
}
couriersud@3023
   115
couriersud@3023
   116
void
slouken@4636
   117
DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window)
couriersud@3023
   118
{
couriersud@3023
   119
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   120
    IDirectFBSurface *s = windata->window_surface;
couriersud@3023
   121
    DFB_Theme *t = &windata->theme;
couriersud@3023
   122
    int i;
couriersud@3023
   123
    int d = (t->caption_size - t->font_size) / 2;
couriersud@3023
   124
    int x, y, w;
couriersud@3023
   125
couriersud@3023
   126
couriersud@3023
   127
    if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN))
couriersud@3023
   128
        return;
couriersud@3023
   129
slouken@4636
   130
	LoadFont(_this, window);
couriersud@3023
   131
    //s->SetDrawingFlags(s, DSDRAW_BLEND);
couriersud@3023
   132
    s->SetColor(s, COLOR_EXPAND(t->frame_color));
couriersud@3023
   133
    /* top */
couriersud@3023
   134
    for (i = 0; i < t->top_size; i++)
couriersud@3023
   135
        s->DrawLine(s, 0, i, windata->size.w, i);
couriersud@3023
   136
    /* bottom */
couriersud@3023
   137
    for (i = windata->size.h - t->bottom_size; i < windata->size.h; i++)
couriersud@3023
   138
        s->DrawLine(s, 0, i, windata->size.w, i);
couriersud@3023
   139
    /* left */
couriersud@3023
   140
    for (i = 0; i < t->left_size; i++)
couriersud@3023
   141
        s->DrawLine(s, i, 0, i, windata->size.h);
couriersud@3023
   142
    /* right */
couriersud@3023
   143
    for (i = windata->size.w - t->right_size; i < windata->size.w; i++)
couriersud@3023
   144
        s->DrawLine(s, i, 0, i, windata->size.h);
couriersud@3023
   145
    /* Caption */
couriersud@3023
   146
    s->SetColor(s, COLOR_EXPAND(t->caption_color));
couriersud@3023
   147
    s->FillRectangle(s, t->left_size, t->top_size, windata->client.w,
couriersud@3023
   148
                     t->caption_size);
couriersud@3023
   149
    /* Close Button */
couriersud@3023
   150
    w = t->caption_size;
couriersud@3023
   151
    x = windata->size.w - t->right_size - w + d;
couriersud@3023
   152
    y = t->top_size + d;
couriersud@3023
   153
    s->SetColor(s, COLOR_EXPAND(t->close_color));
slouken@4636
   154
    DrawTriangle(s, 1, x, y, w - 2 * d);
couriersud@3023
   155
    /* Max Button */
couriersud@3023
   156
    s->SetColor(s, COLOR_EXPAND(t->max_color));
slouken@4636
   157
    DrawTriangle(s, window->flags & SDL_WINDOW_MAXIMIZED ? 1 : 0, x - w,
couriersud@3023
   158
               y, w - 2 * d);
couriersud@3023
   159
couriersud@3023
   160
    /* Caption */
couriersud@3023
   161
    if (window->title) {
slouken@4636
   162
	    s->SetColor(s, COLOR_EXPAND(t->font_color));
slouken@4636
   163
        DrawCraption(_this, s, (x - w) / 2, t->top_size + d, window->title);
couriersud@3023
   164
    }
couriersud@3023
   165
    /* Icon */
couriersud@3023
   166
    if (windata->icon) {
couriersud@3023
   167
        DFBRectangle dr;
couriersud@3023
   168
couriersud@3023
   169
        dr.x = t->left_size + d;
couriersud@3023
   170
        dr.y = t->top_size + d;
couriersud@3023
   171
        dr.w = w - 2 * d;
couriersud@3023
   172
        dr.h = w - 2 * d;
couriersud@3023
   173
        s->SetBlittingFlags(s, DSBLIT_BLEND_ALPHACHANNEL);
couriersud@3023
   174
couriersud@3023
   175
        s->StretchBlit(s, windata->icon, NULL, &dr);
couriersud@3023
   176
    }
couriersud@3023
   177
    windata->wm_needs_redraw = 0;
couriersud@3023
   178
}
couriersud@3023
   179
couriersud@3023
   180
DFBResult
couriersud@3023
   181
DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch)
couriersud@3023
   182
{
couriersud@3023
   183
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   184
slouken@4636
   185
    SDL_DFB_CHECK(windata->window->GetSize(windata->window, cw, ch));
couriersud@3023
   186
    *cw -= windata->theme.left_size + windata->theme.right_size;
couriersud@3023
   187
    *ch -=
couriersud@3023
   188
        windata->theme.top_size + windata->theme.caption_size +
couriersud@3023
   189
        windata->theme.bottom_size;
slouken@4636
   190
    return DFB_OK;
couriersud@3023
   191
}
couriersud@3023
   192
couriersud@3023
   193
void
slouken@4636
   194
DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h)
couriersud@3023
   195
{
couriersud@3023
   196
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   197
couriersud@3023
   198
    if (!windata->is_managed)
couriersud@3023
   199
        windata->theme = theme_none;
slouken@4636
   200
    else if (flags & SDL_WINDOW_FULLSCREEN) {
couriersud@3023
   201
        windata->theme = theme_none;
slouken@4636
   202
    } else if (flags & SDL_WINDOW_MAXIMIZED) {
couriersud@3023
   203
        windata->theme = theme_std;
couriersud@3023
   204
        windata->theme.left_size = 0;
couriersud@3023
   205
        windata->theme.right_size = 0;
couriersud@3023
   206
        windata->theme.top_size = 0;
couriersud@3023
   207
        windata->theme.bottom_size = 0;
couriersud@3023
   208
    } else {
couriersud@3023
   209
        windata->theme = theme_std;
couriersud@3023
   210
    }
couriersud@3023
   211
couriersud@3023
   212
    windata->client.x = windata->theme.left_size;
couriersud@3023
   213
    windata->client.y = windata->theme.top_size + windata->theme.caption_size;
slouken@4636
   214
    windata->client.w = w;
slouken@4636
   215
    windata->client.h = h;
couriersud@3023
   216
    windata->size.w =
slouken@4636
   217
        w + windata->theme.left_size + windata->theme.right_size;
couriersud@3023
   218
    windata->size.h =
slouken@4636
   219
        h + windata->theme.top_size +
couriersud@3023
   220
        windata->theme.caption_size + windata->theme.bottom_size;
couriersud@3023
   221
}
couriersud@3023
   222
couriersud@3023
   223
void
couriersud@3023
   224
DirectFB_WM_MaximizeWindow(_THIS, SDL_Window * window)
couriersud@3023
   225
{
couriersud@3023
   226
    SDL_DFB_WINDOWDATA(window);
slouken@3685
   227
    SDL_VideoDisplay *display = window->display;
couriersud@3023
   228
slouken@4636
   229
    SDL_DFB_CHECK(windata->window->GetPosition(windata->window,
slouken@4636
   230
                                 &windata->restore.x, &windata->restore.y));
slouken@4636
   231
    SDL_DFB_CHECK(windata->window->GetSize(windata->window, &windata->restore.w,
slouken@4636
   232
                             &windata->restore.h));
couriersud@3023
   233
slouken@4636
   234
    DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
couriersud@3023
   235
slouken@4636
   236
    SDL_DFB_CHECK(windata->window->MoveTo(windata->window, 0, 0));
slouken@4636
   237
    SDL_DFB_CHECK(windata->window->Resize(windata->window,
slouken@4636
   238
                            display->current_mode.w, display->current_mode.h));
couriersud@3023
   239
}
couriersud@3023
   240
couriersud@3023
   241
void
couriersud@3023
   242
DirectFB_WM_RestoreWindow(_THIS, SDL_Window * window)
couriersud@3023
   243
{
couriersud@3023
   244
    SDL_DFB_WINDOWDATA(window);
couriersud@3023
   245
slouken@4636
   246
    DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED), 
slouken@4636
   247
    	windata->restore.w, windata->restore.h);
couriersud@3023
   248
slouken@4636
   249
    SDL_DFB_CHECK(windata->window->Resize(windata->window, windata->restore.w,
slouken@4636
   250
                            windata->restore.h));
slouken@4636
   251
    SDL_DFB_CHECK(windata->window->MoveTo(windata->window, windata->restore.x,
slouken@4636
   252
                            windata->restore.y));
couriersud@3023
   253
}
couriersud@3023
   254
couriersud@3023
   255
enum
couriersud@3023
   256
{
couriersud@3023
   257
    WM_POS_NONE = 0x00,
couriersud@3023
   258
    WM_POS_CAPTION = 0x01,
couriersud@3023
   259
    WM_POS_CLOSE = 0x02,
couriersud@3023
   260
    WM_POS_MAX = 0x04,
couriersud@3023
   261
    WM_POS_LEFT = 0x08,
couriersud@3023
   262
    WM_POS_RIGHT = 0x10,
couriersud@3023
   263
    WM_POS_TOP = 0x20,
couriersud@3023
   264
    WM_POS_BOTTOM = 0x40,
couriersud@3023
   265
};
couriersud@3023
   266
couriersud@3023
   267
static int
couriersud@3023
   268
WMIsClient(DFB_WindowData * p, int x, int y)
couriersud@3023
   269
{
couriersud@3023
   270
    x -= p->client.x;
couriersud@3023
   271
    y -= p->client.y;
couriersud@3023
   272
    if (x < 0 || y < 0)
couriersud@3023
   273
        return 0;
couriersud@3023
   274
    if (x >= p->client.w || y >= p->client.h)
couriersud@3023
   275
        return 0;
couriersud@3023
   276
    return 1;
couriersud@3023
   277
}
couriersud@3023
   278
couriersud@3023
   279
static int
couriersud@3023
   280
WMPos(DFB_WindowData * p, int x, int y)
couriersud@3023
   281
{
couriersud@3023
   282
    int pos = WM_POS_NONE;
couriersud@3023
   283
couriersud@3023
   284
    if (!WMIsClient(p, x, y)) {
couriersud@3023
   285
        if (y < p->theme.top_size) {
couriersud@3023
   286
            pos |= WM_POS_TOP;
couriersud@3023
   287
        } else if (y < p->client.y) {
couriersud@3023
   288
            if (x <
couriersud@3023
   289
                p->size.w - p->theme.right_size - 2 * p->theme.caption_size) {
couriersud@3023
   290
                pos |= WM_POS_CAPTION;
couriersud@3023
   291
            } else if (x <
couriersud@3023
   292
                       p->size.w - p->theme.right_size -
couriersud@3023
   293
                       p->theme.caption_size) {
couriersud@3023
   294
                pos |= WM_POS_MAX;
couriersud@3023
   295
            } else {
couriersud@3023
   296
                pos |= WM_POS_CLOSE;
couriersud@3023
   297
            }
couriersud@3023
   298
        } else if (y >= p->size.h - p->theme.bottom_size) {
couriersud@3023
   299
            pos |= WM_POS_BOTTOM;
couriersud@3023
   300
        }
couriersud@3023
   301
        if (x < p->theme.left_size) {
couriersud@3023
   302
            pos |= WM_POS_LEFT;
couriersud@3023
   303
        } else if (x >= p->size.w - p->theme.right_size) {
couriersud@3023
   304
            pos |= WM_POS_RIGHT;
couriersud@3023
   305
        }
couriersud@3023
   306
    }
couriersud@3023
   307
    return pos;
couriersud@3023
   308
}
couriersud@3023
   309
couriersud@3023
   310
static int wm_grab;
couriersud@3023
   311
static int wm_lastx;
couriersud@3023
   312
static int wm_lasty;
couriersud@3023
   313
couriersud@3023
   314
int
slouken@3040
   315
DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
couriersud@3023
   316
{
slouken@4636
   317
    SDL_DFB_DEVICEDATA(_this);
couriersud@3023
   318
    SDL_DFB_WINDOWDATA(window);
slouken@4636
   319
	DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
couriersud@3023
   320
couriersud@3023
   321
    if (!windata->is_managed)
couriersud@3023
   322
        return 0;
couriersud@3023
   323
couriersud@3023
   324
    switch (evt->type) {
couriersud@3023
   325
    case DWET_BUTTONDOWN:
couriersud@3023
   326
        if (evt->buttons & DIBM_LEFT) {
couriersud@3023
   327
            int pos = WMPos(windata, evt->x, evt->y);
couriersud@3023
   328
            switch (pos) {
couriersud@3023
   329
            case WM_POS_NONE:
couriersud@3023
   330
                return 0;
couriersud@3023
   331
            case WM_POS_CLOSE:
slouken@4636
   332
		        wm_grab = WM_POS_NONE;
slouken@4568
   333
                SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0,
slouken@3040
   334
                                    0);
couriersud@3023
   335
                return 1;
couriersud@3023
   336
            case WM_POS_MAX:
slouken@4636
   337
		        wm_grab = WM_POS_NONE;
couriersud@3023
   338
                if (window->flags & SDL_WINDOW_MAXIMIZED) {
slouken@4636
   339
                	SDL_RestoreWindow(window);
couriersud@3023
   340
                } else {
slouken@4636
   341
                    SDL_MaximizeWindow(window);
couriersud@3023
   342
                }
couriersud@3023
   343
                return 1;
slouken@4636
   344
            case WM_POS_CAPTION:
slouken@4636
   345
                DirectFB_RaiseWindow(_this, window);
slouken@4636
   346
                /* fall through */
couriersud@3023
   347
            default:
couriersud@3023
   348
                wm_grab = pos;
slouken@4636
   349
                if (gwindata != NULL)
slouken@4636
   350
	                SDL_DFB_CHECK(gwindata->window->UngrabPointer(gwindata->window));
slouken@4636
   351
                SDL_DFB_CHECK(windata->window->GrabPointer(windata->window));
couriersud@3023
   352
                wm_lastx = evt->cx;
couriersud@3023
   353
                wm_lasty = evt->cy;
couriersud@3023
   354
            }
couriersud@3023
   355
        }
couriersud@3023
   356
        return 1;
couriersud@3023
   357
    case DWET_BUTTONUP:
couriersud@3023
   358
        break;
couriersud@3023
   359
    case DWET_MOTION:
couriersud@3023
   360
        if (!wm_grab)
couriersud@3023
   361
            return 0;
couriersud@3023
   362
        if (evt->buttons & DIBM_LEFT) {
couriersud@3023
   363
            int dx = evt->cx - wm_lastx;
couriersud@3023
   364
            int dy = evt->cy - wm_lasty;
couriersud@3023
   365
            int cw, ch;
couriersud@3023
   366
couriersud@3023
   367
            if (wm_grab & WM_POS_CAPTION)
slouken@4636
   368
                SDL_DFB_CHECK(windata->window->Move(windata->window, dx, dy));
slouken@4636
   369
	        if (wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
slouken@4636
   370
	            if ((wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
slouken@4636
   371
	            	dx = 0;
slouken@4636
   372
	            else if ((wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
slouken@4636
   373
	            	dy = 0;
slouken@4636
   374
                SDL_DFB_CHECK(windata->window->GetSize(windata->window, &cw, &ch));
slouken@4636
   375
                SDL_DFB_CHECK(windata->window->Resize(windata->window, cw + dx, ch + dy));
couriersud@3023
   376
            }
couriersud@3023
   377
            wm_lastx = evt->cx;
couriersud@3023
   378
            wm_lasty = evt->cy;
couriersud@3023
   379
            return 1;
couriersud@3023
   380
        }
slouken@4636
   381
        SDL_DFB_CHECK(windata->window->UngrabPointer(windata->window));
slouken@4636
   382
        if (gwindata != NULL)
slouken@4636
   383
            SDL_DFB_CHECK(gwindata->window->GrabPointer(gwindata->window));
couriersud@3023
   384
        wm_grab = WM_POS_NONE;
couriersud@3023
   385
        break;
couriersud@3023
   386
    case DWET_KEYDOWN:
couriersud@3023
   387
        break;
couriersud@3023
   388
    case DWET_KEYUP:
couriersud@3023
   389
        break;
couriersud@3023
   390
    default:
couriersud@3023
   391
        ;
couriersud@3023
   392
    }
couriersud@3023
   393
    return 0;
couriersud@3023
   394
}