src/video/directfb/SDL_DirectFB_mouse.c
author Sam Lantinga
Fri, 27 Jan 2017 21:23:27 -0800
changeset 10861 71d8f9afb690
parent 10737 3406a0f8b041
child 10998 cedca11e9b61
permissions -rw-r--r--
Fixed bug 3569 - GL_UpdateViewport leaves PROJECTION matrix selected

Tom Seddon

GL_ActivateRenderer may call GL_UpdateViewport, which leaves the GL_PROJECTION matrix selected. But after GL_ResetState, the GL_MODELVIEW matrix is selected, suggesting that's the intended default state.

It seems at least like these should be consistent. Presumably GL_UpdateViewport should be doing a glMatrixMode(GL_MODELVIEW) before it finishes.
slouken@2226
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@2226
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@2226
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@2226
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@2226
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@5199
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_DIRECTFB
slouken@6044
    24
slouken@5488
    25
#include "SDL_assert.h"
slouken@2226
    26
slouken@2226
    27
#include "SDL_DirectFB_video.h"
slouken@5488
    28
#include "SDL_DirectFB_mouse.h"
slouken@5488
    29
#include "SDL_DirectFB_modes.h"
slouken@5488
    30
#include "SDL_DirectFB_window.h"
slouken@2226
    31
slouken@2226
    32
#include "../SDL_sysvideo.h"
slouken@2226
    33
#include "../../events/SDL_mouse_c.h"
slouken@2226
    34
slouken@5488
    35
static SDL_Cursor *DirectFB_CreateDefaultCursor(void);
couriersud@3023
    36
static SDL_Cursor *DirectFB_CreateCursor(SDL_Surface * surface,
couriersud@3023
    37
                                         int hot_x, int hot_y);
slouken@2226
    38
static int DirectFB_ShowCursor(SDL_Cursor * cursor);
slouken@2226
    39
static void DirectFB_MoveCursor(SDL_Cursor * cursor);
slouken@2226
    40
static void DirectFB_FreeCursor(SDL_Cursor * cursor);
slouken@5488
    41
static void DirectFB_WarpMouse(SDL_Window * window, int x, int y);
slouken@5488
    42
static void DirectFB_FreeMouse(SDL_Mouse * mouse);
slouken@5488
    43
slouken@5488
    44
static const char *arrow[] = {
slouken@5488
    45
    /* pixels */
slouken@5488
    46
    "X                               ",
slouken@5488
    47
    "XX                              ",
slouken@5488
    48
    "X.X                             ",
slouken@5488
    49
    "X..X                            ",
slouken@5488
    50
    "X...X                           ",
slouken@5488
    51
    "X....X                          ",
slouken@5488
    52
    "X.....X                         ",
slouken@5488
    53
    "X......X                        ",
slouken@5488
    54
    "X.......X                       ",
slouken@5488
    55
    "X........X                      ",
slouken@5488
    56
    "X.....XXXXX                     ",
slouken@5488
    57
    "X..X..X                         ",
slouken@5488
    58
    "X.X X..X                        ",
slouken@5488
    59
    "XX  X..X                        ",
slouken@5488
    60
    "X    X..X                       ",
slouken@5488
    61
    "     X..X                       ",
slouken@5488
    62
    "      X..X                      ",
slouken@5488
    63
    "      X..X                      ",
slouken@5488
    64
    "       XX                       ",
slouken@5488
    65
    "                                ",
slouken@5488
    66
    "                                ",
slouken@5488
    67
    "                                ",
slouken@5488
    68
    "                                ",
slouken@5488
    69
    "                                ",
slouken@5488
    70
    "                                ",
slouken@5488
    71
    "                                ",
slouken@5488
    72
    "                                ",
slouken@5488
    73
    "                                ",
slouken@5488
    74
    "                                ",
slouken@5488
    75
    "                                ",
slouken@5488
    76
    "                                ",
slouken@5488
    77
    "                                ",
slouken@5488
    78
};
slouken@5488
    79
slouken@5488
    80
static SDL_Cursor *
slouken@5488
    81
DirectFB_CreateDefaultCursor(void)
slouken@5488
    82
{
slouken@5488
    83
    SDL_VideoDevice *dev = SDL_GetVideoDevice();
slouken@5488
    84
slouken@5488
    85
    SDL_DFB_DEVICEDATA(dev);
slouken@5488
    86
    DFB_CursorData *curdata;
slouken@5488
    87
    DFBResult ret;
slouken@5488
    88
    DFBSurfaceDescription dsc;
slouken@5488
    89
    SDL_Cursor *cursor;
slouken@5488
    90
    Uint32 *dest;
slouken@5488
    91
    Uint32 *p;
slouken@5488
    92
    int pitch, i, j;
slouken@5488
    93
slouken@5488
    94
    SDL_DFB_ALLOC_CLEAR( cursor, sizeof(*cursor));
slouken@5488
    95
    SDL_DFB_ALLOC_CLEAR(curdata, sizeof(*curdata));
slouken@5488
    96
slouken@5488
    97
    dsc.flags =
slouken@5488
    98
        DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
slouken@5488
    99
    dsc.caps = DSCAPS_VIDEOONLY;
slouken@5488
   100
    dsc.width = 32;
slouken@5488
   101
    dsc.height = 32;
slouken@5488
   102
    dsc.pixelformat = DSPF_ARGB;
slouken@5488
   103
slouken@5488
   104
    SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
slouken@5488
   105
                                                 &curdata->surf));
slouken@5488
   106
    curdata->hotx = 0;
slouken@5488
   107
    curdata->hoty = 0;
slouken@5488
   108
    cursor->driverdata = curdata;
slouken@5488
   109
slouken@5488
   110
    SDL_DFB_CHECKERR(curdata->surf->Lock(curdata->surf, DSLF_WRITE,
slouken@5488
   111
                                         (void *) &dest, &pitch));
slouken@5488
   112
slouken@5488
   113
    /* Relies on the fact that this is only called with ARGB surface. */
slouken@5488
   114
    for (i = 0; i < 32; i++)
slouken@5488
   115
    {
slouken@5488
   116
        for (j = 0; j < 32; j++)
slouken@5488
   117
        {
slouken@7191
   118
            switch (arrow[i][j])
slouken@7191
   119
            {
slouken@7191
   120
            case ' ': dest[j] = 0x00000000; break;
slouken@7191
   121
            case '.': dest[j] = 0xffffffff; break;
slouken@7191
   122
            case 'X': dest[j] = 0xff000000; break;
slouken@7191
   123
            }
slouken@5488
   124
        }
slouken@5488
   125
        dest += (pitch >> 2);
slouken@5488
   126
    }
slouken@5488
   127
slouken@5488
   128
    curdata->surf->Unlock(curdata->surf);
slouken@5488
   129
    return cursor;
slouken@5488
   130
  error:
slouken@5488
   131
    return NULL;
slouken@5488
   132
}
slouken@5488
   133
slouken@5488
   134
/* Create a cursor from a surface */
slouken@5488
   135
static SDL_Cursor *
slouken@5488
   136
DirectFB_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
slouken@5488
   137
{
slouken@5488
   138
    SDL_VideoDevice *dev = SDL_GetVideoDevice();
slouken@5488
   139
slouken@5488
   140
    SDL_DFB_DEVICEDATA(dev);
slouken@5488
   141
    DFB_CursorData *curdata;
slouken@5488
   142
    DFBResult ret;
slouken@5488
   143
    DFBSurfaceDescription dsc;
slouken@5488
   144
    SDL_Cursor *cursor;
slouken@5488
   145
    Uint32 *dest;
slouken@5488
   146
    Uint32 *p;
slouken@5488
   147
    int pitch, i;
slouken@5488
   148
slouken@5488
   149
    SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
slouken@5488
   150
    SDL_assert(surface->pitch == surface->w * 4);
slouken@5488
   151
slouken@5488
   152
    SDL_DFB_ALLOC_CLEAR( cursor, sizeof(*cursor));
slouken@5488
   153
    SDL_DFB_ALLOC_CLEAR(curdata, sizeof(*curdata));
slouken@5488
   154
slouken@5488
   155
    dsc.flags =
slouken@5488
   156
        DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
slouken@5488
   157
    dsc.caps = DSCAPS_VIDEOONLY;
slouken@5488
   158
    dsc.width = surface->w;
slouken@5488
   159
    dsc.height = surface->h;
slouken@5488
   160
    dsc.pixelformat = DSPF_ARGB;
slouken@5488
   161
slouken@5488
   162
    SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
slouken@5488
   163
                                                 &curdata->surf));
slouken@5488
   164
    curdata->hotx = hot_x;
slouken@5488
   165
    curdata->hoty = hot_y;
slouken@5488
   166
    cursor->driverdata = curdata;
slouken@5488
   167
slouken@5488
   168
    SDL_DFB_CHECKERR(curdata->surf->Lock(curdata->surf, DSLF_WRITE,
slouken@5488
   169
                                         (void *) &dest, &pitch));
slouken@5488
   170
slouken@5488
   171
    p = surface->pixels;
slouken@5488
   172
    for (i = 0; i < surface->h; i++)
slouken@5488
   173
        memcpy((char *) dest + i * pitch,
slouken@5488
   174
               (char *) p + i * surface->pitch, 4 * surface->w);
slouken@5488
   175
slouken@5488
   176
    curdata->surf->Unlock(curdata->surf);
slouken@5488
   177
    return cursor;
slouken@5488
   178
  error:
slouken@5488
   179
    return NULL;
slouken@5488
   180
}
slouken@5488
   181
slouken@5488
   182
/* Show the specified cursor, or hide if cursor is NULL */
slouken@5488
   183
static int
slouken@5488
   184
DirectFB_ShowCursor(SDL_Cursor * cursor)
slouken@5488
   185
{
slouken@5488
   186
    SDL_DFB_CURSORDATA(cursor);
slouken@5488
   187
    DFBResult ret;
slouken@5488
   188
    SDL_Window *window;
slouken@5488
   189
slouken@5488
   190
    window = SDL_GetFocusWindow();
slouken@5488
   191
    if (!window)
slouken@5488
   192
        return -1;
slouken@5488
   193
    else {
slouken@5488
   194
        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5488
   195
slouken@5488
   196
        if (display) {
slouken@5488
   197
            DFB_DisplayData *dispdata =
slouken@5488
   198
                (DFB_DisplayData *) display->driverdata;
slouken@5488
   199
            DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
slouken@5488
   200
slouken@5488
   201
            if (cursor)
slouken@5488
   202
                SDL_DFB_CHECKERR(windata->dfbwin->
slouken@5488
   203
                                 SetCursorShape(windata->dfbwin,
slouken@5488
   204
                                                curdata->surf, curdata->hotx,
slouken@5488
   205
                                                curdata->hoty));
slouken@5488
   206
slouken@5488
   207
            SDL_DFB_CHECKERR(dispdata->layer->
slouken@5488
   208
                             SetCooperativeLevel(dispdata->layer,
slouken@5488
   209
                                                 DLSCL_ADMINISTRATIVE));
slouken@5488
   210
            SDL_DFB_CHECKERR(dispdata->layer->
slouken@5488
   211
                             SetCursorOpacity(dispdata->layer,
slouken@5488
   212
                                              cursor ? 0xC0 : 0x00));
slouken@5488
   213
            SDL_DFB_CHECKERR(dispdata->layer->
slouken@5488
   214
                             SetCooperativeLevel(dispdata->layer,
slouken@5488
   215
                                                 DLSCL_SHARED));
slouken@5488
   216
        }
slouken@5488
   217
    }
slouken@5488
   218
slouken@5488
   219
    return 0;
slouken@5488
   220
  error:
slouken@5488
   221
    return -1;
slouken@5488
   222
}
slouken@5488
   223
slouken@5488
   224
/* Free a window manager cursor */
slouken@5488
   225
static void
slouken@5488
   226
DirectFB_FreeCursor(SDL_Cursor * cursor)
slouken@5488
   227
{
slouken@5488
   228
    SDL_DFB_CURSORDATA(cursor);
slouken@5488
   229
slouken@5488
   230
    SDL_DFB_RELEASE(curdata->surf);
slouken@5488
   231
    SDL_DFB_FREE(cursor->driverdata);
slouken@5488
   232
    SDL_DFB_FREE(cursor);
slouken@5488
   233
}
slouken@5488
   234
slouken@5488
   235
/* Warp the mouse to (x,y) */
slouken@5488
   236
static void
slouken@5488
   237
DirectFB_WarpMouse(SDL_Window * window, int x, int y)
slouken@5488
   238
{
slouken@5488
   239
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5488
   240
    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
slouken@5488
   241
    DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
slouken@5488
   242
    DFBResult ret;
slouken@5488
   243
    int cx, cy;
slouken@5488
   244
slouken@5488
   245
    SDL_DFB_CHECKERR(windata->dfbwin->GetPosition(windata->dfbwin, &cx, &cy));
slouken@5488
   246
    SDL_DFB_CHECKERR(dispdata->layer->WarpCursor(dispdata->layer,
slouken@5488
   247
                                                 cx + x + windata->client.x,
slouken@5488
   248
                                                 cy + y + windata->client.y));
slouken@5488
   249
slouken@5488
   250
  error:
slouken@5488
   251
    return;
slouken@5488
   252
}
slouken@5488
   253
slouken@5488
   254
#if USE_MULTI_API
slouken@5488
   255
slouken@3685
   256
static void DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window,
slouken@2226
   257
                               int x, int y);
slouken@2226
   258
slouken@2860
   259
static int id_mask;
slouken@2860
   260
slouken@2860
   261
static DFBEnumerationResult
couriersud@3023
   262
EnumMice(DFBInputDeviceID device_id, DFBInputDeviceDescription desc,
couriersud@3023
   263
         void *callbackdata)
slouken@2860
   264
{
slouken@2860
   265
    DFB_DeviceData *devdata = callbackdata;
slouken@2860
   266
slouken@2860
   267
    if ((desc.type & DIDTF_MOUSE) && (device_id & id_mask)) {
slouken@2860
   268
        SDL_Mouse mouse;
slouken@2860
   269
slouken@2860
   270
        SDL_zero(mouse);
slouken@2940
   271
        mouse.id = device_id;
slouken@2860
   272
        mouse.CreateCursor = DirectFB_CreateCursor;
slouken@2860
   273
        mouse.ShowCursor = DirectFB_ShowCursor;
slouken@2860
   274
        mouse.MoveCursor = DirectFB_MoveCursor;
slouken@2860
   275
        mouse.FreeCursor = DirectFB_FreeCursor;
slouken@2860
   276
        mouse.WarpMouse = DirectFB_WarpMouse;
slouken@2860
   277
        mouse.FreeMouse = DirectFB_FreeMouse;
slouken@2860
   278
        mouse.cursor_shown = 1;
slouken@2860
   279
slouken@2940
   280
        SDL_AddMouse(&mouse, desc.name, 0, 0, 1);
slouken@2940
   281
        devdata->mouse_id[devdata->num_mice++] = device_id;
slouken@2860
   282
    }
slouken@2860
   283
    return DFENUM_OK;
slouken@2860
   284
}
slouken@2860
   285
slouken@2226
   286
void
slouken@2226
   287
DirectFB_InitMouse(_THIS)
slouken@2226
   288
{
slouken@2226
   289
    SDL_DFB_DEVICEDATA(_this);
slouken@2860
   290
slouken@2860
   291
    devdata->num_mice = 0;
slouken@2998
   292
    if (devdata->use_linux_input) {
slouken@2860
   293
        /* try non-core devices first */
slouken@2860
   294
        id_mask = 0xF0;
slouken@2860
   295
        devdata->dfb->EnumInputDevices(devdata->dfb, EnumMice, devdata);
slouken@2860
   296
        if (devdata->num_mice == 0) {
slouken@2860
   297
            /* try core devices */
slouken@2860
   298
            id_mask = 0x0F;
slouken@2860
   299
            devdata->dfb->EnumInputDevices(devdata->dfb, EnumMice, devdata);
slouken@2860
   300
        }
slouken@2860
   301
    }
slouken@2860
   302
    if (devdata->num_mice == 0) {
slouken@2860
   303
        SDL_Mouse mouse;
slouken@2226
   304
slouken@2860
   305
        SDL_zero(mouse);
slouken@2860
   306
        mouse.CreateCursor = DirectFB_CreateCursor;
slouken@2860
   307
        mouse.ShowCursor = DirectFB_ShowCursor;
slouken@2860
   308
        mouse.MoveCursor = DirectFB_MoveCursor;
slouken@2860
   309
        mouse.FreeCursor = DirectFB_FreeCursor;
slouken@2860
   310
        mouse.WarpMouse = DirectFB_WarpMouse;
slouken@2860
   311
        mouse.FreeMouse = DirectFB_FreeMouse;
slouken@2860
   312
        mouse.cursor_shown = 1;
slouken@2860
   313
slouken@2940
   314
        SDL_AddMouse(&mouse, "Mouse", 0, 0, 1);
slouken@2860
   315
        devdata->num_mice = 1;
slouken@2860
   316
    }
slouken@2226
   317
}
slouken@2226
   318
slouken@2226
   319
void
slouken@2226
   320
DirectFB_QuitMouse(_THIS)
slouken@2226
   321
{
slouken@2226
   322
    SDL_DFB_DEVICEDATA(_this);
slouken@2226
   323
slouken@2998
   324
    if (devdata->use_linux_input) {
slouken@2860
   325
        SDL_MouseQuit();
slouken@2860
   326
    } else {
slouken@2860
   327
        SDL_DelMouse(0);
slouken@2860
   328
    }
slouken@2226
   329
}
slouken@2226
   330
slouken@2226
   331
slouken@2226
   332
/* This is called when a mouse motion event occurs */
slouken@2226
   333
static void
slouken@2226
   334
DirectFB_MoveCursor(SDL_Cursor * cursor)
slouken@2226
   335
{
slouken@2737
   336
slouken@2226
   337
}
slouken@2226
   338
slouken@2226
   339
/* Warp the mouse to (x,y) */
slouken@2226
   340
static void
slouken@3685
   341
DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window, int x, int y)
slouken@2226
   342
{
slouken@5246
   343
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@2226
   344
    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
slouken@2226
   345
    DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
slouken@2226
   346
    DFBResult ret;
slouken@2226
   347
    int cx, cy;
slouken@2226
   348
slouken@5199
   349
    SDL_DFB_CHECKERR(windata->dfbwin->GetPosition(windata->dfbwin, &cx, &cy));
couriersud@3023
   350
    SDL_DFB_CHECKERR(dispdata->layer->WarpCursor(dispdata->layer,
couriersud@3023
   351
                                                 cx + x + windata->client.x,
couriersud@3023
   352
                                                 cy + y + windata->client.y));
slouken@2226
   353
slouken@2226
   354
  error:
slouken@2226
   355
    return;
slouken@2226
   356
}
slouken@2226
   357
slouken@2226
   358
/* Free the mouse when it's time */
slouken@2226
   359
static void
slouken@2226
   360
DirectFB_FreeMouse(SDL_Mouse * mouse)
slouken@2226
   361
{
slouken@2737
   362
    /* nothing yet */
slouken@2226
   363
}
slouken@2226
   364
slouken@4568
   365
#else /* USE_MULTI_API */
slouken@4568
   366
slouken@4568
   367
void
slouken@4568
   368
DirectFB_InitMouse(_THIS)
slouken@4568
   369
{
slouken@4568
   370
    SDL_DFB_DEVICEDATA(_this);
slouken@4568
   371
slouken@5488
   372
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5488
   373
slouken@5488
   374
    mouse->CreateCursor = DirectFB_CreateCursor;
slouken@5488
   375
    mouse->ShowCursor = DirectFB_ShowCursor;
slouken@5488
   376
    mouse->WarpMouse = DirectFB_WarpMouse;
slouken@5488
   377
    mouse->FreeCursor = DirectFB_FreeCursor;
slouken@5488
   378
slouken@5490
   379
    SDL_SetDefaultCursor(DirectFB_CreateDefaultCursor());
slouken@5488
   380
slouken@4568
   381
    devdata->num_mice = 1;
slouken@4568
   382
}
slouken@4568
   383
slouken@4568
   384
void
slouken@4568
   385
DirectFB_QuitMouse(_THIS)
slouken@4568
   386
{
slouken@4568
   387
}
slouken@4568
   388
slouken@4568
   389
slouken@4568
   390
#endif
slouken@4568
   391
slouken@6044
   392
#endif /* SDL_VIDEO_DRIVER_DIRECTFB */
slouken@6044
   393
slouken@2226
   394
/* vi: set ts=4 sw=4 expandtab: */