SDL  2.0
SDL_windowswindow.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_WINDOWS
24 
25 #include "../../core/windows/SDL_windows.h"
26 
27 #include "SDL_assert.h"
28 #include "../SDL_sysvideo.h"
29 #include "../SDL_pixels_c.h"
30 #include "../../events/SDL_keyboard_c.h"
31 #include "../../events/SDL_mouse_c.h"
32 
33 #include "SDL_windowsvideo.h"
34 #include "SDL_windowswindow.h"
35 #include "SDL_hints.h"
36 
37 /* Dropfile support */
38 #include <shellapi.h>
39 
40 /* This is included after SDL_windowsvideo.h, which includes windows.h */
41 #include "SDL_syswm.h"
42 
43 /* Windows CE compatibility */
44 #ifndef SWP_NOCOPYBITS
45 #define SWP_NOCOPYBITS 0
46 #endif
47 
48 /* Fake window to help with DirectInput events. */
49 HWND SDL_HelperWindow = NULL;
50 static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
51 static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
52 static ATOM SDL_HelperWindowClass = 0;
53 
54 #define STYLE_BASIC (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
55 #define STYLE_FULLSCREEN (WS_POPUP)
56 #define STYLE_BORDERLESS (WS_POPUP)
57 #define STYLE_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
58 #define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
59 #define STYLE_MASK (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
60 
61 static DWORD
62 GetWindowStyle(SDL_Window * window)
63 {
64  DWORD style = 0;
65 
66  if (window->flags & SDL_WINDOW_FULLSCREEN) {
67  style |= STYLE_FULLSCREEN;
68  } else {
69  if (window->flags & SDL_WINDOW_BORDERLESS) {
70  style |= STYLE_BORDERLESS;
71  } else {
72  style |= STYLE_NORMAL;
73  }
74 
75  /* You can have a borderless resizable window */
76  if (window->flags & SDL_WINDOW_RESIZABLE) {
77  style |= STYLE_RESIZABLE;
78  }
79  }
80  return style;
81 }
82 
83 static void
84 WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
85 {
86  RECT rect;
87 
88  rect.left = 0;
89  rect.top = 0;
90  rect.right = (use_current ? window->w : window->windowed.w);
91  rect.bottom = (use_current ? window->h : window->windowed.h);
92  AdjustWindowRectEx(&rect, style, menu, 0);
93 
94  *x = (use_current ? window->x : window->windowed.x) + rect.left;
95  *y = (use_current ? window->y : window->windowed.y) + rect.top;
96  *width = (rect.right - rect.left);
97  *height = (rect.bottom - rect.top);
98 }
99 
100 static void
101 WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current)
102 {
104  HWND hwnd = data->hwnd;
105  DWORD style;
106  BOOL menu;
107 
108  style = GetWindowLong(hwnd, GWL_STYLE);
109  menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
110  WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
111 }
112 
113 static void
114 WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
115 {
116  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
117  HWND hwnd = data->hwnd;
118  HWND top;
119  int x, y;
120  int w, h;
121 
122  /* Figure out what the window area will be */
124  top = HWND_TOPMOST;
125  } else {
126  top = HWND_NOTOPMOST;
127  }
128 
129  WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
130 
131  data->expected_resize = SDL_TRUE;
132  SetWindowPos(hwnd, top, x, y, w, h, flags);
133  data->expected_resize = SDL_FALSE;
134 }
135 
136 static int
137 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
138 {
139  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
140  SDL_WindowData *data;
141 
142  /* Allocate the window data */
143  data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
144  if (!data) {
145  return SDL_OutOfMemory();
146  }
147  data->window = window;
148  data->hwnd = hwnd;
149  data->parent = parent;
150  data->hdc = GetDC(hwnd);
151  data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
152  data->created = created;
153  data->mouse_button_flags = 0;
154  data->videodata = videodata;
155  data->initializing = SDL_TRUE;
156 
157  window->driverdata = data;
158 
159  /* Associate the data with the window */
160  if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
161  ReleaseDC(hwnd, data->hdc);
162  SDL_free(data);
163  return WIN_SetError("SetProp() failed");
164  }
165 
166  /* Set up the window proc function */
167 #ifdef GWLP_WNDPROC
168  data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
169  if (data->wndproc == WIN_WindowProc) {
170  data->wndproc = NULL;
171  } else {
172  SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
173  }
174 #else
175  data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
176  if (data->wndproc == WIN_WindowProc) {
177  data->wndproc = NULL;
178  } else {
179  SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
180  }
181 #endif
182 
183  /* Fill in the SDL window with the window data */
184  {
185  RECT rect;
186  if (GetClientRect(hwnd, &rect)) {
187  int w = rect.right;
188  int h = rect.bottom;
189  if ((window->w && window->w != w) || (window->h && window->h != h)) {
190  /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */
191  int x, y;
192  int w, h;
193 
194  /* Figure out what the window area will be */
195  WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
196  SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
197  } else {
198  window->w = w;
199  window->h = h;
200  }
201  }
202  }
203  {
204  POINT point;
205  point.x = 0;
206  point.y = 0;
207  if (ClientToScreen(hwnd, &point)) {
208  window->x = point.x;
209  window->y = point.y;
210  }
211  }
212  {
213  DWORD style = GetWindowLong(hwnd, GWL_STYLE);
214  if (style & WS_VISIBLE) {
215  window->flags |= SDL_WINDOW_SHOWN;
216  } else {
217  window->flags &= ~SDL_WINDOW_SHOWN;
218  }
219  if (style & (WS_BORDER | WS_THICKFRAME)) {
220  window->flags &= ~SDL_WINDOW_BORDERLESS;
221  } else {
222  window->flags |= SDL_WINDOW_BORDERLESS;
223  }
224  if (style & WS_THICKFRAME) {
225  window->flags |= SDL_WINDOW_RESIZABLE;
226  } else {
227  window->flags &= ~SDL_WINDOW_RESIZABLE;
228  }
229 #ifdef WS_MAXIMIZE
230  if (style & WS_MAXIMIZE) {
231  window->flags |= SDL_WINDOW_MAXIMIZED;
232  } else
233 #endif
234  {
235  window->flags &= ~SDL_WINDOW_MAXIMIZED;
236  }
237 #ifdef WS_MINIMIZE
238  if (style & WS_MINIMIZE) {
239  window->flags |= SDL_WINDOW_MINIMIZED;
240  } else
241 #endif
242  {
243  window->flags &= ~SDL_WINDOW_MINIMIZED;
244  }
245  }
246  if (GetFocus() == hwnd) {
247  window->flags |= SDL_WINDOW_INPUT_FOCUS;
249 
250  if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
251  RECT rect;
252  GetClientRect(hwnd, &rect);
253  ClientToScreen(hwnd, (LPPOINT) & rect);
254  ClientToScreen(hwnd, (LPPOINT) & rect + 1);
255  ClipCursor(&rect);
256  }
257  }
258 
259  /* Enable multi-touch */
260  if (videodata->RegisterTouchWindow) {
261  videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
262  }
263 
264  /* Enable dropping files */
265  DragAcceptFiles(hwnd, TRUE);
266 
267  data->initializing = SDL_FALSE;
268 
269  /* All done! */
270  return 0;
271 }
272 
273 
274 
275 int
277 {
278  HWND hwnd, parent = NULL;
279  DWORD style = STYLE_BASIC;
280  int x, y;
281  int w, h;
282 
283  if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
284  parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
285  }
286 
287  style |= GetWindowStyle(window);
288 
289  /* Figure out what the window area will be */
290  WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_TRUE);
291 
292  hwnd =
293  CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
294  SDL_Instance, NULL);
295  if (!hwnd) {
296  return WIN_SetError("Couldn't create window");
297  }
298 
300 
301  if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) {
302  DestroyWindow(hwnd);
303  if (parent) {
304  DestroyWindow(parent);
305  }
306  return -1;
307  }
308 
309  if (!(window->flags & SDL_WINDOW_OPENGL)) {
310  return 0;
311  }
312 
313  /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
314 #if SDL_VIDEO_OPENGL_ES2
317  && (!_this->gl_data || WIN_GL_UseEGL(_this))
318 #endif /* SDL_VIDEO_OPENGL_WGL */
319  ) {
320 #if SDL_VIDEO_OPENGL_EGL
321  if (WIN_GLES_SetupWindow(_this, window) < 0) {
322  WIN_DestroyWindow(_this, window);
323  return -1;
324  }
325  return 0;
326 #else
327  return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
328 #endif /* SDL_VIDEO_OPENGL_EGL */
329  }
330 #endif /* SDL_VIDEO_OPENGL_ES2 */
331 
332 #if SDL_VIDEO_OPENGL_WGL
333  if (WIN_GL_SetupWindow(_this, window) < 0) {
334  WIN_DestroyWindow(_this, window);
335  return -1;
336  }
337 #else
338  return SDL_SetError("Could not create GL window (WGL support not configured)");
339 #endif
340 
341  return 0;
342 }
343 
344 int
345 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
346 {
347  HWND hwnd = (HWND) data;
348  LPTSTR title;
349  int titleLen;
350 
351  /* Query the title from the existing window */
352  titleLen = GetWindowTextLength(hwnd);
353  title = SDL_stack_alloc(TCHAR, titleLen + 1);
354  if (title) {
355  titleLen = GetWindowText(hwnd, title, titleLen);
356  } else {
357  titleLen = 0;
358  }
359  if (titleLen > 0) {
360  window->title = WIN_StringToUTF8(title);
361  }
362  if (title) {
363  SDL_stack_free(title);
364  }
365 
366  if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
367  return -1;
368  }
369 
370 #if SDL_VIDEO_OPENGL_WGL
371  {
373  if (hint) {
374  /* This hint is a pointer (in string form) of the address of
375  the window to share a pixel format with
376  */
377  SDL_Window *otherWindow = NULL;
378  SDL_sscanf(hint, "%p", (void**)&otherWindow);
379 
380  /* Do some error checking on the pointer */
381  if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
382  {
383  /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
384  if (otherWindow->flags & SDL_WINDOW_OPENGL)
385  {
386  window->flags |= SDL_WINDOW_OPENGL;
387  if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
388  return -1;
389  }
390  }
391  }
392  }
393  }
394 #endif
395  return 0;
396 }
397 
398 void
400 {
401  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
402  LPTSTR title = WIN_UTF8ToString(window->title);
403  SetWindowText(hwnd, title);
404  SDL_free(title);
405 }
406 
407 void
409 {
410  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
411  HICON hicon = NULL;
412  BYTE *icon_bmp;
413  int icon_len, y;
414  SDL_RWops *dst;
415 
416  /* Create temporary bitmap buffer */
417  icon_len = 40 + icon->h * icon->w * sizeof(Uint32);
418  icon_bmp = SDL_stack_alloc(BYTE, icon_len);
419  dst = SDL_RWFromMem(icon_bmp, icon_len);
420  if (!dst) {
421  SDL_stack_free(icon_bmp);
422  return;
423  }
424 
425  /* Write the BITMAPINFO header */
426  SDL_WriteLE32(dst, 40);
427  SDL_WriteLE32(dst, icon->w);
428  SDL_WriteLE32(dst, icon->h * 2);
429  SDL_WriteLE16(dst, 1);
430  SDL_WriteLE16(dst, 32);
431  SDL_WriteLE32(dst, BI_RGB);
432  SDL_WriteLE32(dst, icon->h * icon->w * sizeof(Uint32));
433  SDL_WriteLE32(dst, 0);
434  SDL_WriteLE32(dst, 0);
435  SDL_WriteLE32(dst, 0);
436  SDL_WriteLE32(dst, 0);
437 
438  /* Write the pixels upside down into the bitmap buffer */
440  y = icon->h;
441  while (y--) {
442  Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
443  SDL_RWwrite(dst, src, icon->w * sizeof(Uint32), 1);
444  }
445 
446  hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
447 
448  SDL_RWclose(dst);
449  SDL_stack_free(icon_bmp);
450 
451  /* Set the icon for the window */
452  SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
453 
454  /* Set the icon in the task manager (should we do this?) */
455  SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
456 }
457 
458 void
460 {
461  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
462 }
463 
464 void
466 {
467  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
468 }
469 
470 void
472 {
473  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
474  ShowWindow(hwnd, SW_SHOW);
475 }
476 
477 void
479 {
480  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
481  ShowWindow(hwnd, SW_HIDE);
482 }
483 
484 void
486 {
487  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
488  SetForegroundWindow(hwnd);
489 }
490 
491 void
493 {
494  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
495  HWND hwnd = data->hwnd;
496  data->expected_resize = SDL_TRUE;
497  ShowWindow(hwnd, SW_MAXIMIZE);
498  data->expected_resize = SDL_FALSE;
499 }
500 
501 void
503 {
504  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
505  ShowWindow(hwnd, SW_MINIMIZE);
506 }
507 
508 void
509 WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
510 {
511  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
512  HWND hwnd = data->hwnd;
513  DWORD style;
514 
515  style = GetWindowLong(hwnd, GWL_STYLE);
516  style &= ~STYLE_MASK;
517  style |= GetWindowStyle(window);
518 
519  data->in_border_change = SDL_TRUE;
520  SetWindowLong(hwnd, GWL_STYLE, style);
521  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
522  data->in_border_change = SDL_FALSE;
523 }
524 
525 void
526 WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
527 {
528  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
529  HWND hwnd = data->hwnd;
530  DWORD style;
531 
532  style = GetWindowLong(hwnd, GWL_STYLE);
533  style &= ~STYLE_MASK;
534  style |= GetWindowStyle(window);
535 
536  SetWindowLong(hwnd, GWL_STYLE, style);
537 }
538 
539 void
541 {
542  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
543  HWND hwnd = data->hwnd;
544  data->expected_resize = SDL_TRUE;
545  ShowWindow(hwnd, SW_RESTORE);
546  data->expected_resize = SDL_FALSE;
547 }
548 
549 void
550 WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
551 {
552  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
553  HWND hwnd = data->hwnd;
554  SDL_Rect bounds;
555  DWORD style;
556  HWND top;
557  int x, y;
558  int w, h;
559 
561  top = HWND_TOPMOST;
562  } else {
563  top = HWND_NOTOPMOST;
564  }
565 
566  style = GetWindowLong(hwnd, GWL_STYLE);
567  style &= ~STYLE_MASK;
568  style |= GetWindowStyle(window);
569 
570  WIN_GetDisplayBounds(_this, display, &bounds);
571 
572  if (fullscreen) {
573  x = bounds.x;
574  y = bounds.y;
575  w = bounds.w;
576  h = bounds.h;
577 
578  /* Unset the maximized flag. This fixes
579  https://bugzilla.libsdl.org/show_bug.cgi?id=3215
580  */
581  if (style & WS_MAXIMIZE) {
583  style &= ~WS_MAXIMIZE;
584  }
585  } else {
586  /* Restore window-maximization state, as applicable.
587  Special care is taken to *not* do this if and when we're
588  alt-tab'ing away (to some other window; as indicated by
589  in_window_deactivation), otherwise
590  https://bugzilla.libsdl.org/show_bug.cgi?id=3215 can reproduce!
591  */
593  style |= WS_MAXIMIZE;
595  }
596 
597  WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_FALSE);
598  }
599  SetWindowLong(hwnd, GWL_STYLE, style);
600  data->expected_resize = SDL_TRUE;
601  SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
602  data->expected_resize = SDL_FALSE;
603 }
604 
605 int
606 WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
607 {
608  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
609  SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
610  HDC hdc;
611  BOOL succeeded = FALSE;
612 
613  hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
614  if (hdc) {
615  succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
616  if (!succeeded) {
617  WIN_SetError("SetDeviceGammaRamp()");
618  }
619  DeleteDC(hdc);
620  }
621  return succeeded ? 0 : -1;
622 }
623 
624 int
626 {
627  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
628  SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
629  HDC hdc;
630  BOOL succeeded = FALSE;
631 
632  hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
633  if (hdc) {
634  succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
635  if (!succeeded) {
636  WIN_SetError("GetDeviceGammaRamp()");
637  }
638  DeleteDC(hdc);
639  }
640  return succeeded ? 0 : -1;
641 }
642 
643 void
644 WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
645 {
646  WIN_UpdateClipCursor(window);
647 
648  if (window->flags & SDL_WINDOW_FULLSCREEN) {
649  UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
650 
651  if (!(window->flags & SDL_WINDOW_SHOWN)) {
652  flags |= SWP_NOACTIVATE;
653  }
654  WIN_SetWindowPositionInternal(_this, window, flags);
655  }
656 }
657 
658 void
660 {
661  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
662 
663  if (data) {
664  ReleaseDC(data->hwnd, data->hdc);
665  RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
666  if (data->created) {
667  DestroyWindow(data->hwnd);
668  if (data->parent) {
669  DestroyWindow(data->parent);
670  }
671  } else {
672  /* Restore any original event handler... */
673  if (data->wndproc != NULL) {
674 #ifdef GWLP_WNDPROC
675  SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
676  (LONG_PTR) data->wndproc);
677 #else
678  SetWindowLong(data->hwnd, GWL_WNDPROC,
679  (LONG_PTR) data->wndproc);
680 #endif
681  }
682  }
683  SDL_free(data);
684  }
685  window->driverdata = NULL;
686 }
687 
688 SDL_bool
690 {
691  const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
692  if (info->version.major <= SDL_MAJOR_VERSION) {
693  int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
694 
696  info->info.win.window = data->hwnd;
697 
698  if (versionnum >= SDL_VERSIONNUM(2, 0, 4)) {
699  info->info.win.hdc = data->hdc;
700  }
701 
702  if (versionnum >= SDL_VERSIONNUM(2, 0, 5)) {
703  info->info.win.hinstance = data->hinstance;
704  }
705 
706  return SDL_TRUE;
707  } else {
708  SDL_SetError("Application not compiled with SDL %d.%d",
710  return SDL_FALSE;
711  }
712 }
713 
714 
715 /*
716  * Creates a HelperWindow used for DirectInput events.
717  */
718 int
719 SDL_HelperWindowCreate(void)
720 {
721  HINSTANCE hInstance = GetModuleHandle(NULL);
722  WNDCLASS wce;
723 
724  /* Make sure window isn't created twice. */
725  if (SDL_HelperWindow != NULL) {
726  return 0;
727  }
728 
729  /* Create the class. */
730  SDL_zero(wce);
731  wce.lpfnWndProc = DefWindowProc;
732  wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
733  wce.hInstance = hInstance;
734 
735  /* Register the class. */
736  SDL_HelperWindowClass = RegisterClass(&wce);
737  if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
738  return WIN_SetError("Unable to create Helper Window Class");
739  }
740 
741  /* Create the window. */
742  SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
743  SDL_HelperWindowName,
744  WS_OVERLAPPED, CW_USEDEFAULT,
745  CW_USEDEFAULT, CW_USEDEFAULT,
746  CW_USEDEFAULT, HWND_MESSAGE, NULL,
747  hInstance, NULL);
748  if (SDL_HelperWindow == NULL) {
749  UnregisterClass(SDL_HelperWindowClassName, hInstance);
750  return WIN_SetError("Unable to create Helper Window");
751  }
752 
753  return 0;
754 }
755 
756 
757 /*
758  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
759  */
760 void
761 SDL_HelperWindowDestroy(void)
762 {
763  HINSTANCE hInstance = GetModuleHandle(NULL);
764 
765  /* Destroy the window. */
766  if (SDL_HelperWindow != NULL) {
767  if (DestroyWindow(SDL_HelperWindow) == 0) {
768  WIN_SetError("Unable to destroy Helper Window");
769  return;
770  }
771  SDL_HelperWindow = NULL;
772  }
773 
774  /* Unregister the class. */
775  if (SDL_HelperWindowClass != 0) {
776  if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
777  WIN_SetError("Unable to destroy Helper Window Class");
778  return;
779  }
780  SDL_HelperWindowClass = 0;
781  }
782 }
783 
784 void WIN_OnWindowEnter(_THIS, SDL_Window * window)
785 {
786  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
787 
788  if (!data || !data->hwnd) {
789  /* The window wasn't fully initialized */
790  return;
791  }
792 
793  if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
794  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
795  }
796 
797 #ifdef WM_MOUSELEAVE
798  {
799  TRACKMOUSEEVENT trackMouseEvent;
800 
801  trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
802  trackMouseEvent.dwFlags = TME_LEAVE;
803  trackMouseEvent.hwndTrack = data->hwnd;
804 
805  TrackMouseEvent(&trackMouseEvent);
806  }
807 #endif /* WM_MOUSELEAVE */
808 }
809 
810 void
812 {
813  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
814  SDL_Mouse *mouse = SDL_GetMouse();
815 
816  if (data->focus_click_pending) {
817  return;
818  }
819 
820  if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
821  (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
822  if (mouse->relative_mode && !mouse->relative_mode_warp) {
823  LONG cx, cy;
824  RECT rect;
825  GetWindowRect(data->hwnd, &rect);
826 
827  cx = (rect.left + rect.right) / 2;
828  cy = (rect.top + rect.bottom) / 2;
829 
830  /* Make an absurdly small clip rect */
831  rect.left = cx - 1;
832  rect.right = cx + 1;
833  rect.top = cy - 1;
834  rect.bottom = cy + 1;
835 
836  ClipCursor(&rect);
837  } else {
838  RECT rect;
839  if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
840  ClientToScreen(data->hwnd, (LPPOINT) & rect);
841  ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
842  ClipCursor(&rect);
843  }
844  }
845  } else {
846  ClipCursor(NULL);
847  }
848 }
849 
850 int
852 {
853  return 0; /* just succeed, the real work is done elsewhere. */
854 }
855 
856 int
857 WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
858 {
859  const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
860  const HWND hwnd = data->hwnd;
861  const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
862 
863  SDL_assert(style != 0);
864 
865  if (opacity == 1.0f) {
866  /* want it fully opaque, just mark it unlayered if necessary. */
867  if (style & WS_EX_LAYERED) {
868  if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
869  return WIN_SetError("SetWindowLong()");
870  }
871  }
872  } else {
873  const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
874  /* want it transparent, mark it layered if necessary. */
875  if ((style & WS_EX_LAYERED) == 0) {
876  if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
877  return WIN_SetError("SetWindowLong()");
878  }
879  }
880 
881  if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
882  return WIN_SetError("SetLayeredWindowAttributes()");
883  }
884  }
885 
886  return 0;
887 }
888 
889 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
890 
891 /* vi: set ts=4 sw=4 expandtab: */
#define BI_RGB
Definition: SDL_bmp.c:45
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
HINSTANCE SDL_Instance
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:110
void WIN_SetWindowSize(_THIS, SDL_Window *window)
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
GLenum GLenum dst
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
void WIN_RaiseWindow(_THIS, SDL_Window *window)
const void * magic
Definition: SDL_sysvideo.h:75
SDL_Rect rect
Definition: testrelative.c:27
int WIN_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
void WIN_DestroyWindow(_THIS, SDL_Window *window)
GLfloat GLfloat GLfloat GLfloat h
SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
void WIN_MaximizeWindow(_THIS, SDL_Window *window)
#define SDL_GetHint
SDL_version version
Definition: SDL_syswm.h:196
SDL_bool expected_resize
Uint8 major
Definition: SDL_version.h:53
#define SDL_WriteLE16
LPTSTR SDL_Appname
GLfloat f
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:197
SDL_Window * window
uint32_t Uint32
Definition: SDL_stdinc.h:181
GLenum src
GLdouble GLdouble GLdouble GLdouble top
SDL_Rect windowed
Definition: SDL_sysvideo.h:87
void WIN_OnWindowEnter(_THIS, SDL_Window *window)
GLfloat GLfloat GLfloat alpha
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:378
void WIN_SetWindowPosition(_THIS, SDL_Window *window)
int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
int WIN_CreateWindow(_THIS, SDL_Window *window)
struct SDL_VideoDevice::@33 gl_config
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_bool windowed_mode_was_maximized
TCHAR DeviceName[32]
SDL_bool in_border_change
void * SDL_calloc(size_t nmemb, size_t size)
int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
void WIN_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
void * pixels
Definition: SDL_surface.h:75
void WIN_MinimizeWindow(_THIS, SDL_Window *window)
#define _THIS
struct SDL_VideoData * videodata
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
#define SDL_VERSIONNUM(X, Y, Z)
Definition: SDL_version.h:94
int WIN_SetWindowOpacity(_THIS, SDL_Window *window, float opacity)
void SDL_free(void *mem)
#define TRUE
Definition: edid-parse.c:33
void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
void WIN_ShowWindow(_THIS, SDL_Window *window)
GLubyte GLubyte GLubyte GLubyte w
#define SDL_RWFromMem
void WIN_UpdateClipCursor(SDL_Window *window)
Uint8 minor
Definition: SDL_version.h:54
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
#define SDL_zero(x)
Definition: SDL_stdinc.h:385
#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT
A variable that is the address of another SDL_Window* (as a hex string formatted with "%p")...
Definition: SDL_hints.h:546
#define SDL_sscanf
char * title
Definition: SDL_sysvideo.h:77
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h:66
#define SDL_VIDEO_OPENGL_WGL
#define TWF_FINETOUCH
#define TWF_WANTPALM
int w
Definition: SDL_rect.h:67
void WIN_RestoreWindow(_THIS, SDL_Window *window)
GLenum GLenum GLsizei const GLuint GLboolean enabled
#define SDL_assert(condition)
Definition: SDL_assert.h:169
int WIN_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
Window window
Definition: SDL_syswm.h:218
SDL_bool SDL_ShouldAllowTopmost(void)
Definition: SDL_video.c:3888
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
int WIN_SetError(const char *prefix)
#define SDL_SetError
void WIN_SetWindowTitle(_THIS, SDL_Window *window)
GLbitfield flags
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
void WIN_PumpEvents(_THIS)
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1073
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
void WIN_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
int h
Definition: SDL_rect.h:67
The type used to identify a window.
Definition: SDL_sysvideo.h:73
void WIN_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
#define SDL_WriteLE32
uint16_t Uint16
Definition: SDL_stdinc.h:169
SDL_bool in_window_deactivation
union SDL_SysWMinfo::@18 info
void WIN_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
void * driverdata
Definition: SDL_sysvideo.h:111
int WIN_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
void WIN_HideWindow(_THIS, SDL_Window *window)
#define FALSE
Definition: edid-parse.c:34
Uint32 flags
Definition: SDL_sysvideo.h:83
int y
Definition: SDL_rect.h:66
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
Uint8 patch
Definition: SDL_version.h:55