src/video/win32/SDL_win32window.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 06 Jul 2006 07:17:11 +0000
branchSDL-1.3
changeset 1724 6c63fc2bd986
parent 1722 5daa04d862f1
child 1732 fd65f12b6de6
permissions -rw-r--r--
Proof of concept done - Win32 GDI implementation mostly complete.
     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 #include "../SDL_sysvideo.h"
    25 
    26 #include "SDL_win32video.h"
    27 
    28 /* This is included after SDL_win32video.h, which includes windows.h */
    29 #include "SDL_syswm.h"
    30 
    31 
    32 static int
    33 SetupWindowData(SDL_Window * window, HWND hwnd, BOOL created)
    34 {
    35     SDL_WindowData *data;
    36 
    37     /* Allocate the window data */
    38     data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
    39     if (!data) {
    40         SDL_OutOfMemory();
    41         return -1;
    42     }
    43     data->windowID = window->id;
    44     data->hwnd = hwnd;
    45     data->created = created;
    46     data->mouse_pressed = SDL_FALSE;
    47     data->videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata;
    48 
    49     /* Associate the data with the window */
    50     if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
    51         SDL_free(data);
    52         WIN_SetError("SetProp() failed");
    53         return -1;
    54     }
    55 
    56     /* Set up the window proc function */
    57     data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
    58     if (data->wndproc == NULL) {
    59         data->wndproc = DefWindowProc;
    60     } else {
    61         SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
    62     }
    63 
    64     /* Fill in the SDL window with the window data */
    65     {
    66         POINT point;
    67         point.x = 0;
    68         point.y = 0;
    69         if (ClientToScreen(hwnd, &point)) {
    70             window->x = point.x;
    71             window->y = point.y;
    72         }
    73     }
    74     {
    75         RECT rect;
    76         if (GetClientRect(hwnd, &rect)) {
    77             window->w = rect.right;
    78             window->h = rect.bottom;
    79         }
    80     }
    81     {
    82         DWORD style = GetWindowLong(hwnd, GWL_STYLE);
    83         if (style & WS_VISIBLE) {
    84             window->flags |= SDL_WINDOW_SHOWN;
    85         } else {
    86             window->flags &= ~SDL_WINDOW_SHOWN;
    87         }
    88         if (style & (WS_BORDER | WS_THICKFRAME)) {
    89             window->flags &= ~SDL_WINDOW_BORDERLESS;
    90         } else {
    91             window->flags |= SDL_WINDOW_BORDERLESS;
    92         }
    93         if (style & WS_THICKFRAME) {
    94             window->flags |= SDL_WINDOW_RESIZABLE;
    95         } else {
    96             window->flags &= ~SDL_WINDOW_RESIZABLE;
    97         }
    98         if (style & WS_MAXIMIZE) {
    99             window->flags |= SDL_WINDOW_MAXIMIZED;
   100         } else {
   101             window->flags &= ~SDL_WINDOW_MAXIMIZED;
   102         }
   103         if (style & WS_MINIMIZE) {
   104             window->flags |= SDL_WINDOW_MINIMIZED;
   105         } else {
   106             window->flags &= ~SDL_WINDOW_MINIMIZED;
   107         }
   108     }
   109 
   110     /* All done! */
   111     window->driverdata = data;
   112     return 0;
   113 }
   114 
   115 int
   116 WIN_CreateWindow(_THIS, SDL_Window * window)
   117 {
   118     HWND hwnd;
   119     LPTSTR title = NULL;
   120     HWND top;
   121     RECT rect;
   122     DWORD style = 0;
   123     int x, y;
   124     int w, h;
   125 
   126     if (window->title) {
   127         title = WIN_UTF8ToString(window->title);
   128     } else {
   129         title = NULL;
   130     }
   131 
   132     if (window->flags & SDL_WINDOW_SHOWN) {
   133         style |= WS_VISIBLE;
   134     }
   135     if ((window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS))) {
   136         style |= WS_POPUP;
   137     } else {
   138         style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
   139     }
   140     if (window->flags & SDL_WINDOW_RESIZABLE) {
   141         style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
   142     }
   143     if (window->flags & SDL_WINDOW_MAXIMIZED) {
   144         style |= WS_MAXIMIZE;
   145     }
   146     if (window->flags & SDL_WINDOW_MINIMIZED) {
   147         style |= WS_MINIMIZE;
   148     }
   149 
   150     /* Figure out what the window area will be */
   151     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   152         top = HWND_TOPMOST;
   153     } else {
   154         top = HWND_NOTOPMOST;
   155     }
   156     rect.left = 0;
   157     rect.top = 0;
   158     rect.right = window->w;
   159     rect.bottom = window->h;
   160     AdjustWindowRectEx(&rect, style, FALSE, 0);
   161     w = (rect.right - rect.left);
   162     h = (rect.bottom - rect.top);
   163 
   164     if ((window->flags & SDL_WINDOW_FULLSCREEN) ||
   165         window->x == SDL_WINDOWPOS_CENTERED) {
   166         x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
   167     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   168         x = CW_USEDEFAULT;
   169     } else {
   170         x = window->x + rect.left;
   171     }
   172     if ((window->flags & SDL_WINDOW_FULLSCREEN) ||
   173         window->y == SDL_WINDOWPOS_CENTERED) {
   174         y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
   175     } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
   176         y = CW_USEDEFAULT;
   177     } else {
   178         y = window->y + rect.top;
   179     }
   180 
   181     hwnd = CreateWindow(SDL_Appname,
   182                         title ? title : TEXT(""),
   183                         style, x, y, w, h, NULL, NULL, SDL_Instance, NULL);
   184     WIN_PumpEvents(_this);
   185 
   186     if (title) {
   187         SDL_free(title);
   188     }
   189 
   190     if (!hwnd) {
   191         WIN_SetError("Couldn't create window");
   192         return -1;
   193     }
   194 
   195     if (SetupWindowData(window, hwnd, TRUE) < 0) {
   196         DestroyWindow(hwnd);
   197         return -1;
   198     }
   199     return 0;
   200 }
   201 
   202 int
   203 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   204 {
   205     HWND hwnd = (HWND) data;
   206     LPTSTR title;
   207     int titleLen;
   208 
   209     /* Query the title from the existing window */
   210     titleLen = GetWindowTextLength(hwnd);
   211     title = SDL_stack_alloc(TCHAR, titleLen + 1);
   212     if (title) {
   213         titleLen = GetWindowText(hwnd, title, titleLen);
   214     } else {
   215         titleLen = 0;
   216     }
   217     if (titleLen > 0) {
   218         window->title = WIN_StringToUTF8(title);
   219     }
   220     if (title) {
   221         SDL_stack_free(title);
   222     }
   223 
   224     if (SetupWindowData(window, hwnd, FALSE) < 0) {
   225         return -1;
   226     }
   227     return 0;
   228 }
   229 
   230 void
   231 WIN_SetWindowTitle(_THIS, SDL_Window * window)
   232 {
   233     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   234     LPTSTR title;
   235 
   236     if (window->title) {
   237         title = WIN_UTF8ToString(window->title);
   238     } else {
   239         title = NULL;
   240     }
   241     SetWindowText(hwnd, title ? title : TEXT(""));
   242     if (title) {
   243         SDL_free(title);
   244     }
   245 }
   246 
   247 void
   248 WIN_SetWindowPosition(_THIS, SDL_Window * window)
   249 {
   250     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   251     RECT rect;
   252     DWORD style;
   253     HWND top;
   254     int x, y;
   255     int w, h;
   256 
   257     /* Figure out what the window area will be */
   258     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   259         top = HWND_TOPMOST;
   260     } else {
   261         top = HWND_NOTOPMOST;
   262     }
   263     style = GetWindowLong(hwnd, GWL_STYLE);
   264     rect.left = 0;
   265     rect.top = 0;
   266     rect.right = window->w;
   267     rect.bottom = window->h;
   268     AdjustWindowRectEx(&rect, style,
   269                        (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
   270                                                            NULL), 0);
   271     w = (rect.right - rect.left);
   272     h = (rect.bottom - rect.top);
   273 
   274     if ((window->flags & SDL_WINDOW_FULLSCREEN) ||
   275         window->x == SDL_WINDOWPOS_CENTERED) {
   276         x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
   277         window->x = x - rect.left;
   278     } else {
   279         x = window->x + rect.left;
   280     }
   281     if ((window->flags & SDL_WINDOW_FULLSCREEN) ||
   282         window->y == SDL_WINDOWPOS_CENTERED) {
   283         y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
   284         window->y = y - rect.top;
   285     } else {
   286         y = window->y + rect.top;
   287     }
   288     SetWindowPos(hwnd, top, x, y, h, w, (SWP_NOCOPYBITS | SWP_NOSIZE));
   289 }
   290 
   291 void
   292 WIN_SetWindowSize(_THIS, SDL_Window * window)
   293 {
   294     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   295     RECT rect;
   296     DWORD style;
   297     HWND top;
   298     int w, h;
   299 
   300     /* Figure out what the window area will be */
   301     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   302         top = HWND_TOPMOST;
   303     } else {
   304         top = HWND_NOTOPMOST;
   305     }
   306     style = GetWindowLong(hwnd, GWL_STYLE);
   307     rect.left = 0;
   308     rect.top = 0;
   309     rect.right = window->w;
   310     rect.bottom = window->h;
   311     AdjustWindowRectEx(&rect, style,
   312                        (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
   313                                                            NULL), 0);
   314     w = (rect.right - rect.left);
   315     h = (rect.bottom - rect.top);
   316 
   317     SetWindowPos(hwnd, top, 0, 0, h, w, (SWP_NOCOPYBITS | SWP_NOMOVE));
   318 }
   319 
   320 void
   321 WIN_ShowWindow(_THIS, SDL_Window * window)
   322 {
   323     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   324 
   325     ShowWindow(hwnd, SW_SHOW);
   326 }
   327 
   328 void
   329 WIN_HideWindow(_THIS, SDL_Window * window)
   330 {
   331     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   332 
   333     ShowWindow(hwnd, SW_HIDE);
   334 }
   335 
   336 void
   337 WIN_RaiseWindow(_THIS, SDL_Window * window)
   338 {
   339     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   340     HWND top;
   341 
   342     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   343         top = HWND_TOPMOST;
   344     } else {
   345         top = HWND_NOTOPMOST;
   346     }
   347     SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
   348 }
   349 
   350 void
   351 WIN_MaximizeWindow(_THIS, SDL_Window * window)
   352 {
   353     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   354 
   355     ShowWindow(hwnd, SW_MAXIMIZE);
   356 }
   357 
   358 void
   359 WIN_MinimizeWindow(_THIS, SDL_Window * window)
   360 {
   361     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   362 
   363     ShowWindow(hwnd, SW_MINIMIZE);
   364 }
   365 
   366 void
   367 WIN_RestoreWindow(_THIS, SDL_Window * window)
   368 {
   369     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   370 
   371     ShowWindow(hwnd, SW_RESTORE);
   372 }
   373 
   374 void
   375 WIN_SetWindowGrab(_THIS, SDL_Window * window)
   376 {
   377     /* FIXME! */
   378 }
   379 
   380 void
   381 WIN_DestroyWindow(_THIS, SDL_Window * window)
   382 {
   383     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   384 
   385     if (data) {
   386         if (data->created) {
   387             DestroyWindow(data->hwnd);
   388         }
   389         SDL_free(data);
   390     }
   391 }
   392 
   393 SDL_bool
   394 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   395 {
   396     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   397     if (info->version.major <= SDL_MAJOR_VERSION) {
   398         info->window = hwnd;
   399         /* FIXME! */
   400         info->hglrc = NULL;
   401         return SDL_TRUE;
   402     } else {
   403         SDL_SetError("Application not compiled with SDL %d.%d\n",
   404                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   405         return SDL_FALSE;
   406     }
   407 }
   408 
   409 /* vi: set ts=4 sw=4 expandtab: */