diff src/video/SDL_cursor.c @ 1670:eef792d31de8 SDL-1.3

Work in progress. :)
author Sam Lantinga <slouken@libsdl.org>
date Wed, 07 Jun 2006 16:10:28 +0000
parents 4da1ee79c9af
children
line wrap: on
line diff
--- a/src/video/SDL_cursor.c	Mon May 29 05:08:33 2006 +0000
+++ b/src/video/SDL_cursor.c	Wed Jun 07 16:10:28 2006 +0000
@@ -23,22 +23,17 @@
 
 /* General cursor handling code for SDL */
 
-#include "SDL_mutex.h"
 #include "SDL_video.h"
 #include "SDL_mouse.h"
-#include "SDL_blit.h"
 #include "SDL_sysvideo.h"
 #include "SDL_cursor_c.h"
-#include "SDL_pixels_c.h"
 #include "default_cursor.h"
-#include "../events/SDL_sysevents.h"
-#include "../events/SDL_events_c.h"
 
 /* These are static for our cursor handling code */
+/* FIXME: Add support for multiple simultaneous cursors */
 volatile int SDL_cursorstate = CURSOR_VISIBLE;
 SDL_Cursor *SDL_cursor = NULL;
 static SDL_Cursor *SDL_defcursor = NULL;
-SDL_mutex *SDL_cursorlock = NULL;
 
 /* Public functions */
 void
@@ -58,13 +53,10 @@
             SDL_FreeCursor(cursor);
         }
     }
-    if (SDL_cursorlock != NULL) {
-        SDL_DestroyMutex(SDL_cursorlock);
-        SDL_cursorlock = NULL;
-    }
 }
+
 int
-SDL_CursorInit(Uint32 multithreaded)
+SDL_CursorInit(void)
 {
     /* We don't have mouse focus, and the cursor isn't drawn yet */
 #ifndef IPOD
@@ -79,43 +71,15 @@
         SDL_SetCursor(SDL_defcursor);
     }
 
-    /* Create a lock if necessary */
-    if (multithreaded) {
-        SDL_cursorlock = SDL_CreateMutex();
-    }
-
     /* That's it! */
     return (0);
 }
 
-/* Multi-thread support for cursors */
-#ifndef SDL_LockCursor
-void
-SDL_LockCursor(void)
-{
-    if (SDL_cursorlock) {
-        SDL_mutexP(SDL_cursorlock);
-    }
-}
-#endif
-#ifndef SDL_UnlockCursor
-void
-SDL_UnlockCursor(void)
-{
-    if (SDL_cursorlock) {
-        SDL_mutexV(SDL_cursorlock);
-    }
-}
-#endif
-
-/* Software cursor drawing support */
 SDL_Cursor *
 SDL_CreateCursor(Uint8 * data, Uint8 * mask,
                  int w, int h, int hot_x, int hot_y)
 {
     SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    int savelen;
-    int i;
     SDL_Cursor *cursor;
 
     /* Make sure the width is a multiple of 8 */
@@ -127,41 +91,10 @@
         return (NULL);
     }
 
-    /* Allocate memory for the cursor */
-    cursor = (SDL_Cursor *) SDL_malloc(sizeof *cursor);
-    if (cursor == NULL) {
-        SDL_OutOfMemory();
-        return (NULL);
-    }
-    savelen = (w * 4) * h;
-    cursor->area.x = 0;
-    cursor->area.y = 0;
-    cursor->area.w = w;
-    cursor->area.h = h;
-    cursor->hot_x = hot_x;
-    cursor->hot_y = hot_y;
-    cursor->data = (Uint8 *) SDL_malloc((w / 8) * h * 2);
-    cursor->mask = cursor->data + ((w / 8) * h);
-    cursor->save[0] = (Uint8 *) SDL_malloc(savelen * 2);
-    cursor->save[1] = cursor->save[0] + savelen;
-    cursor->wm_cursor = NULL;
-    if (!cursor->data || !cursor->save[0]) {
-        SDL_FreeCursor(cursor);
-        SDL_OutOfMemory();
-        return (NULL);
-    }
-    for (i = ((w / 8) * h) - 1; i >= 0; --i) {
-        cursor->data[i] = data[i];
-        cursor->mask[i] = mask[i] | data[i];
-    }
-    SDL_memset(cursor->save[0], 0, savelen * 2);
-
-    /* If the window manager gives us a good cursor, we're done! */
     if (_this->CreateWMCursor) {
-        cursor->wm_cursor = _this->CreateWMCursor(_this, data, mask,
-                                                  w, h, hot_x, hot_y);
+        cursor = _this->CreateWMCursor(_this, data, mask, w, h, hot_x, hot_y);
     } else {
-        cursor->wm_cursor = NULL;
+        cursor = NULL;
     }
     return (cursor);
 }
@@ -180,56 +113,22 @@
         return;
     }
 
-    /* Prevent the event thread from moving the mouse */
-    SDL_LockCursor();
-
     /* Set the new cursor */
     if (cursor && (cursor != SDL_cursor)) {
-        /* Erase the current mouse position */
-        if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
-            SDL_EraseCursor(SDL_VideoSurface);
-        } else if (_this->MoveWMCursor) {
-            /* If the video driver is moving the cursor directly,
-               it needs to hide the old cursor before (possibly)
-               showing the new one.  (But don't erase NULL cursor)
-             */
-            if (SDL_cursor) {
-                _this->ShowWMCursor(_this, NULL);
-            }
-        }
         SDL_cursor = cursor;
     }
 
     /* Draw the new mouse cursor */
     if (SDL_cursor && (SDL_cursorstate & CURSOR_VISIBLE)) {
-        /* Use window manager cursor if possible */
-        if (SDL_cursor->wm_cursor &&
-            _this->ShowWMCursor(_this, SDL_cursor->wm_cursor)) {
-            SDL_cursorstate &= ~CURSOR_USINGSW;
-        } else {
-            SDL_cursorstate |= CURSOR_USINGSW;
-            if (_this->ShowWMCursor) {
-                _this->ShowWMCursor(_this, NULL);
-            }
-            {
-                int x, y;
-                SDL_GetMouseState(&x, &y);
-                SDL_cursor->area.x = (x - SDL_cursor->hot_x);
-                SDL_cursor->area.y = (y - SDL_cursor->hot_y);
-            }
-            SDL_DrawCursor(SDL_VideoSurface);
+        if (_this->ShowWMCursor) {
+            _this->ShowWMCursor(_this, SDL_cursor);
         }
     } else {
         /* Erase window manager mouse (cursor not visible) */
-        if (SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW)) {
-            SDL_EraseCursor(SDL_VideoSurface);
-        } else {
-            if (_this) {
-                _this->ShowWMCursor(_this, NULL);
-            }
+        if (_this->ShowWMCursor) {
+            _this->ShowWMCursor(_this, NULL);
         }
     }
-    SDL_UnlockCursor();
 }
 
 SDL_Cursor *
@@ -248,16 +147,9 @@
         if (cursor != SDL_defcursor) {
             SDL_VideoDevice *_this = SDL_GetVideoDevice();
 
-            if (cursor->data) {
-                SDL_free(cursor->data);
+            if (_this && _this->FreeWMCursor) {
+                _this->FreeWMCursor(_this, cursor);
             }
-            if (cursor->save[0]) {
-                SDL_free(cursor->save[0]);
-            }
-            if (_this && cursor->wm_cursor) {
-                _this->FreeWMCursor(_this, cursor->wm_cursor);
-            }
-            SDL_free(cursor);
         }
     }
 }
@@ -269,13 +161,11 @@
 
     showing = (SDL_cursorstate & CURSOR_VISIBLE);
     if (toggle >= 0) {
-        SDL_LockCursor();
         if (toggle) {
             SDL_cursorstate |= CURSOR_VISIBLE;
         } else {
             SDL_cursorstate &= ~CURSOR_VISIBLE;
         }
-        SDL_UnlockCursor();
         if ((SDL_cursorstate & CURSOR_VISIBLE) != showing) {
             SDL_VideoDevice *_this = SDL_GetVideoDevice();
 
@@ -291,509 +181,23 @@
 }
 
 void
-SDL_WarpMouse(Uint16 x, Uint16 y)
+SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
 {
     SDL_VideoDevice *_this = SDL_GetVideoDevice();
 
-    if (!_this || !SDL_PublicSurface) {
-        SDL_SetError("A video mode must be set before warping mouse");
+    /* FIXME: This should specify the target window */
+    if (!_this || !SDL_CurrentDisplay.num_windows) {
+        SDL_SetError("A window must be created before warping mouse");
         return;
     }
 
-    /* If we have an offset video mode, offset the mouse coordinates */
-    if (SDL_VideoSurface->pitch == 0) {
-        x += SDL_VideoSurface->offset /
-            SDL_VideoSurface->format->BytesPerPixel;
-        y += SDL_VideoSurface->offset;
-    } else {
-        x += (SDL_VideoSurface->offset % SDL_VideoSurface->pitch) /
-            SDL_VideoSurface->format->BytesPerPixel;
-        y += (SDL_VideoSurface->offset / SDL_VideoSurface->pitch);
+    if (!windowID) {
+        windowID = SDL_CurrentWindow;
     }
 
     /* This generates a mouse motion event */
     if (_this->WarpWMCursor) {
-        _this->WarpWMCursor(_this, x, y);
-    } else {
-        SDL_PrivateMouseMotion(0, 0, x, y);
-    }
-}
-
-void
-SDL_MoveCursor(int x, int y)
-{
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-
-    /* Erase and update the current mouse position */
-    if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
-        /* Erase and redraw mouse cursor in new position */
-        SDL_LockCursor();
-        SDL_EraseCursor(SDL_VideoSurface);
-        SDL_cursor->area.x = (x - SDL_cursor->hot_x);
-        SDL_cursor->area.y = (y - SDL_cursor->hot_y);
-        SDL_DrawCursor(SDL_VideoSurface);
-        SDL_UnlockCursor();
-    } else if (_this->MoveWMCursor) {
-        _this->MoveWMCursor(_this, x, y);
-    }
-}
-
-/* Keep track of the current cursor colors */
-static int palette_changed = 1;
-static Uint8 pixels8[2];
-
-void
-SDL_CursorPaletteChanged(void)
-{
-    palette_changed = 1;
-}
-
-void
-SDL_MouseRect(SDL_Rect * area)
-{
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    int clip_diff;
-
-    *area = SDL_cursor->area;
-    if (area->x < 0) {
-        area->w += area->x;
-        area->x = 0;
-    }
-    if (area->y < 0) {
-        area->h += area->y;
-        area->y = 0;
-    }
-    clip_diff = (area->x + area->w) - SDL_VideoSurface->w;
-    if (clip_diff > 0) {
-        area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
-    }
-    clip_diff = (area->y + area->h) - SDL_VideoSurface->h;
-    if (clip_diff > 0) {
-        area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
-    }
-}
-
-static void
-SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
-{
-    const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
-    int i, w, h;
-    Uint8 *data, datab;
-    Uint8 *mask, maskb;
-
-    data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
-    mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
-    switch (screen->format->BytesPerPixel) {
-
-    case 1:
-        {
-            Uint8 *dst;
-            int dstskip;
-
-            if (palette_changed) {
-                pixels8[0] =
-                    (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
-                pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
-                palette_changed = 0;
-            }
-            dst = (Uint8 *) screen->pixels +
-                (SDL_cursor->area.y + area->y) * screen->pitch +
-                SDL_cursor->area.x;
-            dstskip = screen->pitch - area->w;
-
-            for (h = area->h; h; h--) {
-                for (w = area->w / 8; w; w--) {
-                    maskb = *mask++;
-                    datab = *data++;
-                    for (i = 0; i < 8; ++i) {
-                        if (maskb & 0x80) {
-                            *dst = pixels8[datab >> 7];
-                        }
-                        maskb <<= 1;
-                        datab <<= 1;
-                        dst++;
-                    }
-                }
-                dst += dstskip;
-            }
-        }
-        break;
-
-    case 2:
-        {
-            Uint16 *dst;
-            int dstskip;
-
-            dst = (Uint16 *) screen->pixels +
-                (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
-                SDL_cursor->area.x;
-            dstskip = (screen->pitch / 2) - area->w;
-
-            for (h = area->h; h; h--) {
-                for (w = area->w / 8; w; w--) {
-                    maskb = *mask++;
-                    datab = *data++;
-                    for (i = 0; i < 8; ++i) {
-                        if (maskb & 0x80) {
-                            *dst = (Uint16) pixels[datab >> 7];
-                        }
-                        maskb <<= 1;
-                        datab <<= 1;
-                        dst++;
-                    }
-                }
-                dst += dstskip;
-            }
-        }
-        break;
-
-    case 3:
-        {
-            Uint8 *dst;
-            int dstskip;
-
-            dst = (Uint8 *) screen->pixels +
-                (SDL_cursor->area.y + area->y) * screen->pitch +
-                SDL_cursor->area.x * 3;
-            dstskip = screen->pitch - area->w * 3;
-
-            for (h = area->h; h; h--) {
-                for (w = area->w / 8; w; w--) {
-                    maskb = *mask++;
-                    datab = *data++;
-                    for (i = 0; i < 8; ++i) {
-                        if (maskb & 0x80) {
-                            SDL_memset(dst, pixels[datab >> 7], 3);
-                        }
-                        maskb <<= 1;
-                        datab <<= 1;
-                        dst += 3;
-                    }
-                }
-                dst += dstskip;
-            }
-        }
-        break;
-
-    case 4:
-        {
-            Uint32 *dst;
-            int dstskip;
-
-            dst = (Uint32 *) screen->pixels +
-                (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
-                SDL_cursor->area.x;
-            dstskip = (screen->pitch / 4) - area->w;
-
-            for (h = area->h; h; h--) {
-                for (w = area->w / 8; w; w--) {
-                    maskb = *mask++;
-                    datab = *data++;
-                    for (i = 0; i < 8; ++i) {
-                        if (maskb & 0x80) {
-                            *dst = pixels[datab >> 7];
-                        }
-                        maskb <<= 1;
-                        datab <<= 1;
-                        dst++;
-                    }
-                }
-                dst += dstskip;
-            }
-        }
-        break;
-    }
-}
-
-static void
-SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
-{
-    const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
-    int h;
-    int x, minx, maxx;
-    Uint8 *data, datab = 0;
-    Uint8 *mask, maskb = 0;
-    Uint8 *dst;
-    int dstbpp, dstskip;
-
-    data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
-    mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
-    dstbpp = screen->format->BytesPerPixel;
-    dst = (Uint8 *) screen->pixels +
-        (SDL_cursor->area.y + area->y) * screen->pitch +
-        SDL_cursor->area.x * dstbpp;
-    dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
-
-    minx = area->x;
-    maxx = area->x + area->w;
-    if (screen->format->BytesPerPixel == 1) {
-        if (palette_changed) {
-            pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
-            pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
-            palette_changed = 0;
-        }
-        for (h = area->h; h; h--) {
-            for (x = 0; x < SDL_cursor->area.w; ++x) {
-                if ((x % 8) == 0) {
-                    maskb = *mask++;
-                    datab = *data++;
-                }
-                if ((x >= minx) && (x < maxx)) {
-                    if (maskb & 0x80) {
-                        SDL_memset(dst, pixels8[datab >> 7], dstbpp);
-                    }
-                }
-                maskb <<= 1;
-                datab <<= 1;
-                dst += dstbpp;
-            }
-            dst += dstskip;
-        }
-    } else {
-        for (h = area->h; h; h--) {
-            for (x = 0; x < SDL_cursor->area.w; ++x) {
-                if ((x % 8) == 0) {
-                    maskb = *mask++;
-                    datab = *data++;
-                }
-                if ((x >= minx) && (x < maxx)) {
-                    if (maskb & 0x80) {
-                        SDL_memset(dst, pixels[datab >> 7], dstbpp);
-                    }
-                }
-                maskb <<= 1;
-                datab <<= 1;
-                dst += dstbpp;
-            }
-            dst += dstskip;
-        }
-    }
-}
-
-/* This handles the ugly work of converting the saved cursor background from
-   the pixel format of the shadow surface to that of the video surface.
-   This is only necessary when blitting from a shadow surface of a different
-   pixel format than the video surface, and using a software rendered cursor.
-*/
-static void
-SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
-{
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    SDL_BlitInfo info;
-    SDL_loblit RunBlit;
-
-    /* Make sure we can steal the blit mapping */
-    if (screen->map->dst != SDL_VideoSurface) {
-        return;
-    }
-
-    /* Set up the blit information */
-    info.s_pixels = SDL_cursor->save[1];
-    info.s_width = w;
-    info.s_height = h;
-    info.s_skip = 0;
-    info.d_pixels = SDL_cursor->save[0];
-    info.d_width = w;
-    info.d_height = h;
-    info.d_skip = 0;
-    info.aux_data = screen->map->sw_data->aux_data;
-    info.src = screen->format;
-    info.table = screen->map->table;
-    info.dst = SDL_VideoSurface->format;
-    RunBlit = screen->map->sw_data->blit;
-
-    /* Run the actual software blit */
-    RunBlit(&info);
-}
-
-void
-SDL_DrawCursorNoLock(SDL_Surface * screen)
-{
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    SDL_Rect area;
-
-    /* Get the mouse rectangle, clipped to the screen */
-    SDL_MouseRect(&area);
-    if ((area.w == 0) || (area.h == 0)) {
-        return;
-    }
-
-    /* Copy mouse background */
-    {
-        int w, h, screenbpp;
-        Uint8 *src, *dst;
-
-        /* Set up the copy pointers */
-        screenbpp = screen->format->BytesPerPixel;
-        if ((screen == SDL_VideoSurface) ||
-            FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) {
-            dst = SDL_cursor->save[0];
-        } else {
-            dst = SDL_cursor->save[1];
-        }
-        src = (Uint8 *) screen->pixels + area.y * screen->pitch +
-            area.x * screenbpp;
-
-        /* Perform the copy */
-        w = area.w * screenbpp;
-        h = area.h;
-        while (h--) {
-            SDL_memcpy(dst, src, w);
-            dst += w;
-            src += screen->pitch;
-        }
-    }
-
-    /* Draw the mouse cursor */
-    area.x -= SDL_cursor->area.x;
-    area.y -= SDL_cursor->area.y;
-    if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
-        SDL_DrawCursorFast(screen, &area);
-    } else {
-        SDL_DrawCursorSlow(screen, &area);
-    }
-}
-
-void
-SDL_DrawCursor(SDL_Surface * screen)
-{
-    /* Lock the screen if necessary */
-    if (screen == NULL) {
-        return;
-    }
-    if (SDL_MUSTLOCK(screen)) {
-        if (SDL_LockSurface(screen) < 0) {
-            return;
-        }
-    }
-
-    SDL_DrawCursorNoLock(screen);
-
-    /* Unlock the screen and update if necessary */
-    if (SDL_MUSTLOCK(screen)) {
-        SDL_UnlockSurface(screen);
-    }
-    if ((screen->flags & SDL_SCREEN_SURFACE) &&
-        !(screen->flags & SDL_HWSURFACE)) {
-        SDL_VideoDevice *_this = SDL_GetVideoDevice();
-        SDL_Window *window;
-        SDL_Rect area;
-
-        window = SDL_GetWindowFromSurface(screen);
-        if (!window) {
-            return;
-        }
-
-        SDL_MouseRect(&area);
-
-        if (_this->UpdateWindowSurface) {
-            _this->UpdateWindowSurface(_this, window, 1, &area);
-        }
-    }
-}
-
-void
-SDL_EraseCursorNoLock(SDL_Surface * screen)
-{
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    SDL_Window *window;
-    SDL_Rect area;
-
-    /* Get the window associated with the surface */
-    window = SDL_GetWindowFromSurface(screen);
-    if (!window || !window->surface) {
-        return;
-    }
-
-    /* Get the mouse rectangle, clipped to the screen */
-    SDL_MouseRect(&area);
-    if ((area.w == 0) || (area.h == 0)) {
-        return;
-    }
-
-    /* Copy mouse background */
-    {
-        int w, h, screenbpp;
-        Uint8 *src, *dst;
-
-        /* Set up the copy pointers */
-        screenbpp = screen->format->BytesPerPixel;
-        if ((screen->flags & SDL_SCREEN_SURFACE) ||
-            FORMAT_EQUAL(screen->format, window->surface->format)) {
-            src = SDL_cursor->save[0];
-        } else {
-            src = SDL_cursor->save[1];
-        }
-        dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
-            area.x * screenbpp;
-
-        /* Perform the copy */
-        w = area.w * screenbpp;
-        h = area.h;
-        while (h--) {
-            SDL_memcpy(dst, src, w);
-            src += w;
-            dst += screen->pitch;
-        }
-
-        /* Perform pixel conversion on cursor background */
-        if (src > SDL_cursor->save[1]) {
-            SDL_ConvertCursorSave(screen, area.w, area.h);
-        }
-    }
-}
-
-void
-SDL_EraseCursor(SDL_Surface * screen)
-{
-    /* Lock the screen if necessary */
-    if (screen == NULL) {
-        return;
-    }
-    if (SDL_MUSTLOCK(screen)) {
-        if (SDL_LockSurface(screen) < 0) {
-            return;
-        }
-    }
-
-    SDL_EraseCursorNoLock(screen);
-
-    /* Unlock the screen and update if necessary */
-    if (SDL_MUSTLOCK(screen)) {
-        SDL_UnlockSurface(screen);
-    }
-    if ((screen->flags & SDL_SCREEN_SURFACE) &&
-        !(screen->flags & SDL_HWSURFACE)) {
-        SDL_VideoDevice *_this = SDL_GetVideoDevice();
-        SDL_Window *window;
-        SDL_Rect area;
-
-        window = SDL_GetWindowFromSurface(screen);
-        if (!window) {
-            return;
-        }
-
-        SDL_MouseRect(&area);
-
-        if (_this->UpdateWindowSurface) {
-            _this->UpdateWindowSurface(_this, window, 1, &area);
-        }
-    }
-}
-
-/* Reset the cursor on video mode change
-   FIXME:  Keep track of all cursors, and reset them all.
- */
-void
-SDL_ResetCursor(void)
-{
-    int savelen;
-
-    if (SDL_cursor) {
-        savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
-        SDL_cursor->area.x = 0;
-        SDL_cursor->area.y = 0;
-        SDL_memset(SDL_cursor->save[0], 0, savelen);
+        _this->WarpWMCursor(_this, windowID, x, y);
     }
 }