src/video/wincommon/SDL_syswm.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #define WIN32_LEAN_AND_MEAN
    25 #include <windows.h>
    26 
    27 #include "SDL_version.h"
    28 #include "SDL_video.h"
    29 #include "SDL_loadso.h"
    30 #include "SDL_syswm.h"
    31 #include "../SDL_pixels_c.h"
    32 #include "../SDL_cursor_c.h"
    33 #include "SDL_syswm_c.h"
    34 #include "SDL_wingl_c.h"
    35 
    36 
    37 #ifdef _WIN32_WCE
    38 #define DISABLE_ICON_SUPPORT
    39 #endif
    40 
    41 /* The screen icon -- needs to be freed on SDL_VideoQuit() */
    42 HICON screen_icn = NULL;
    43 
    44 #ifdef _WIN32_WCE
    45 
    46 BOOL(WINAPI * CoreCatchInput) (int flag) = NULL;
    47 int input_catched = 0;
    48 HINSTANCE coredll = NULL;
    49 
    50 // the same API call that gx.dll does to catch the input
    51 void
    52 LoadInputCatchFunc()
    53 {
    54     coredll = SDL_LoadObject("coredll.dll");
    55     if (coredll) {
    56         CoreCatchInput =
    57             (int (WINAPI *) (int)) GetProcAddress(coredll,
    58                                                   (const unsigned short *)
    59                                                   1453);
    60     }
    61 }
    62 
    63 #endif
    64 
    65 
    66 /* Win32 icon mask semantics are different from those of SDL:
    67      SDL applies the mask to the icon and copies result to desktop.
    68      Win32 applies the mask to the desktop and XORs the icon on.
    69    This means that the SDL mask needs to be applied to the icon and
    70    then inverted and passed to Win32.
    71 */
    72 void
    73 WIN_SetWMIcon(_THIS, SDL_Surface * icon, Uint8 * mask)
    74 {
    75 #ifdef DISABLE_ICON_SUPPORT
    76     return;
    77 #else
    78     SDL_Palette *pal_256;
    79     SDL_Surface *icon_256;
    80     Uint8 *pdata, *pwin32;
    81     Uint8 *mdata, *mwin32, m = 0;
    82     int icon_len;
    83     int icon_plen;
    84     int icon_mlen;
    85     int icon_pitch;
    86     int mask_pitch;
    87     SDL_Rect bounds;
    88     int i, skip;
    89     int row, col;
    90     struct /* quasi-BMP format */ Win32Icon
    91     {
    92         Uint32 biSize;
    93         Sint32 biWidth;
    94         Sint32 biHeight;
    95         Uint16 biPlanes;
    96         Uint16 biBitCount;
    97         Uint32 biCompression;
    98         Uint32 biSizeImage;
    99         Sint32 biXPelsPerMeter;
   100         Sint32 biYPelsPerMeter;
   101         Uint32 biClrUsed;
   102         Uint32 biClrImportant;
   103         struct                  /* RGBQUAD -- note it's BGR ordered */
   104         {
   105             Uint8 rgbBlue;
   106             Uint8 rgbGreen;
   107             Uint8 rgbRed;
   108             Uint8 rgbReserved;
   109         } biColors[256];
   110         /* Pixels:
   111            Uint8 pixels[]
   112          */
   113         /* Mask:
   114            Uint8 mask[]
   115          */
   116     } *icon_win32;
   117 
   118     /* Allocate the win32 bmp icon and set everything to zero */
   119     icon_pitch = ((icon->w + 3) & ~3);
   120     mask_pitch = ((icon->w + 7) / 8);
   121     icon_plen = icon->h * icon_pitch;
   122     icon_mlen = icon->h * mask_pitch;
   123     icon_len = sizeof(*icon_win32) + icon_plen + icon_mlen;
   124     icon_win32 = (struct Win32Icon *) SDL_stack_alloc(Uint8, icon_len);
   125     if (icon_win32 == NULL) {
   126         return;
   127     }
   128     SDL_memset(icon_win32, 0, icon_len);
   129 
   130     /* Set the basic BMP parameters */
   131     icon_win32->biSize = sizeof(*icon_win32) - sizeof(icon_win32->biColors);
   132     icon_win32->biWidth = icon->w;
   133     icon_win32->biHeight = icon->h * 2;
   134     icon_win32->biPlanes = 1;
   135     icon_win32->biBitCount = 8;
   136     icon_win32->biSizeImage = icon_plen + icon_mlen;
   137 
   138     /* Allocate a standard 256 color icon surface */
   139     icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
   140                                     icon_win32->biBitCount, 0, 0, 0, 0);
   141     if (icon_256 == NULL) {
   142         SDL_stack_free(icon_win32);
   143         return;
   144     }
   145     pal_256 = icon_256->format->palette;
   146     if (icon->format->palette &&
   147         (icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)) {
   148         Uint8 black;
   149         SDL_memcpy(pal_256->colors, icon->format->palette->colors,
   150                    pal_256->ncolors * sizeof(SDL_Color));
   151         /* Make sure that 0 is black! */
   152         black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00);
   153         pal_256->colors[black] = pal_256->colors[0];
   154         pal_256->colors[0].r = 0x00;
   155         pal_256->colors[0].g = 0x00;
   156         pal_256->colors[0].b = 0x00;
   157     } else {
   158         SDL_DitherColors(pal_256->colors, icon_256->format->BitsPerPixel);
   159     }
   160 
   161     /* Now copy color data to the icon BMP */
   162     for (i = 0; i < (1 << icon_win32->biBitCount); ++i) {
   163         icon_win32->biColors[i].rgbRed = pal_256->colors[i].r;
   164         icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g;
   165         icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b;
   166     }
   167 
   168     /* Convert icon to a standard surface format.  This may not always
   169        be necessary, as Windows supports a variety of BMP formats, but
   170        it greatly simplifies our code.
   171      */
   172     bounds.x = 0;
   173     bounds.y = 0;
   174     bounds.w = icon->w;
   175     bounds.h = icon->h;
   176     if (SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0) {
   177         SDL_stack_free(icon_win32);
   178         SDL_FreeSurface(icon_256);
   179         return;
   180     }
   181 
   182     /* Copy pixels upside-down to icon BMP, masked with the icon mask */
   183     if (SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch)) {
   184         SDL_stack_free(icon_win32);
   185         SDL_FreeSurface(icon_256);
   186         SDL_SetError("Warning: Unexpected icon_256 characteristics");
   187         return;
   188     }
   189     pdata = (Uint8 *) icon_256->pixels;
   190     mdata = mask;
   191     pwin32 =
   192         (Uint8 *) icon_win32 + sizeof(*icon_win32) + icon_plen - icon_pitch;
   193     skip = icon_pitch - icon->w;
   194     for (row = 0; row < icon->h; ++row) {
   195         for (col = 0; col < icon->w; ++col) {
   196             if ((col % 8) == 0) {
   197                 m = *mdata++;
   198             }
   199             if ((m & 0x80) != 0x00) {
   200                 *pwin32 = *pdata;
   201             }
   202             m <<= 1;
   203             ++pdata;
   204             ++pwin32;
   205         }
   206         pdata += skip;
   207         pwin32 += skip;
   208         pwin32 -= 2 * icon_pitch;
   209     }
   210     SDL_FreeSurface(icon_256);
   211 
   212     /* Copy mask inverted and upside-down to icon BMP */
   213     mdata = mask;
   214     mwin32 = (Uint8 *) icon_win32
   215         + sizeof(*icon_win32) + icon_plen + icon_mlen - mask_pitch;
   216     for (row = 0; row < icon->h; ++row) {
   217         for (col = 0; col < mask_pitch; ++col) {
   218             *mwin32++ = ~*mdata++;
   219         }
   220         mwin32 -= 2 * mask_pitch;
   221     }
   222 
   223     /* Finally, create the icon handle and set the window icon */
   224     screen_icn = CreateIconFromResourceEx((Uint8 *) icon_win32, icon_len,
   225                                           TRUE, 0x00030000, icon->w, icon->h,
   226                                           LR_DEFAULTCOLOR);
   227     if (screen_icn == NULL) {
   228         SDL_SetError("Couldn't create Win32 icon handle");
   229     } else {
   230         SetClassLongPtr(SDL_Window, GCLP_HICON, (LONG_PTR) screen_icn);
   231     }
   232     SDL_stack_free(icon_win32);
   233 #endif /* DISABLE_ICON_SUPPORT */
   234 }
   235 
   236 void
   237 WIN_SetWMCaption(_THIS, const char *title, const char *icon)
   238 {
   239 #ifdef _WIN32_WCE
   240     /* WinCE uses the UNICODE version */
   241     LPWSTR lpszW = SDL_iconv_utf8_ucs2((char *) title);
   242     SetWindowText(SDL_Window, lpszW);
   243     SDL_free(lpszW);
   244 #else
   245     char *lpsz = SDL_iconv_utf8_latin1((char *) title);
   246     SetWindowText(SDL_Window, lpsz);
   247     SDL_free(lpsz);
   248 #endif
   249 }
   250 
   251 int
   252 WIN_IconifyWindow(_THIS)
   253 {
   254     ShowWindow(SDL_Window, SW_MINIMIZE);
   255     return (1);
   256 }
   257 
   258 SDL_GrabMode
   259 WIN_GrabInput(_THIS, SDL_GrabMode mode)
   260 {
   261     if (mode == SDL_GRAB_OFF) {
   262         ClipCursor(NULL);
   263         if (!(SDL_cursorstate & CURSOR_VISIBLE)) {
   264             /*      RJR: March 28, 2000
   265                must be leaving relative mode, move mouse from
   266                center of window to where it belongs ... */
   267             POINT pt;
   268             int x, y;
   269             SDL_GetMouseState(&x, &y);
   270             pt.x = x;
   271             pt.y = y;
   272             ClientToScreen(SDL_Window, &pt);
   273             SetCursorPos(pt.x, pt.y);
   274         }
   275 #ifdef _WIN32_WCE
   276         if (input_catched) {
   277             if (!CoreCatchInput)
   278                 LoadInputCatchFunc();
   279 
   280             if (CoreCatchInput)
   281                 CoreCatchInput(0);
   282         }
   283 #endif
   284     } else {
   285         ClipCursor(&SDL_bounds);
   286         if (!(SDL_cursorstate & CURSOR_VISIBLE)) {
   287             /*      RJR: March 28, 2000
   288                must be entering relative mode, get ready by
   289                moving mouse to      center of window ... */
   290             POINT pt;
   291             pt.x = (SDL_VideoSurface->w / 2);
   292             pt.y = (SDL_VideoSurface->h / 2);
   293             ClientToScreen(SDL_Window, &pt);
   294             SetCursorPos(pt.x, pt.y);
   295         }
   296 #ifdef _WIN32_WCE
   297         if (!input_catched) {
   298             if (!CoreCatchInput)
   299                 LoadInputCatchFunc();
   300 
   301             if (CoreCatchInput)
   302                 CoreCatchInput(1);
   303         }
   304 #endif
   305     }
   306     return (mode);
   307 }
   308 
   309 /* If 'info' is the right version, this function fills it and returns 1.
   310    Otherwise, in case of a version mismatch, it returns -1.
   311 */
   312 int
   313 WIN_GetWMInfo(_THIS, SDL_SysWMinfo * info)
   314 {
   315     if (info->version.major <= SDL_MAJOR_VERSION) {
   316         info->window = SDL_Window;
   317         if (SDL_VERSIONNUM(info->version.major,
   318                            info->version.minor,
   319                            info->version.patch) >= SDL_VERSIONNUM(1, 2, 5)) {
   320 #if SDL_VIDEO_OPENGL
   321             info->hglrc = GL_hrc;
   322 #else
   323             info->hglrc = NULL;
   324 #endif
   325         }
   326         return (1);
   327     } else {
   328         SDL_SetError("Application not compiled with SDL %d.%d\n",
   329                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   330         return (-1);
   331     }
   332 }
   333 
   334 /* vi: set ts=4 sw=4 expandtab: */