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