1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Main window creation and management.
12 *
13 * By Stefan Schimanski.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include "allegro.h"
20 #include "allegro/internal/aintern.h"
21 #include "allegro/platform/aintwin.h"
22 #include "wddraw.h"
23
24 #ifndef SCAN_DEPEND
25 #include <string.h>
26 #include <process.h>
27 #include <time.h>
28 #endif
29
30 #ifndef ALLEGRO_WINDOWS
31 #error something is wrong with the makefile
32 #endif
33
34 #define PREFIX_I "al-wwnd INFO: "
35 #define PREFIX_W "al-wwnd WARNING: "
36 #define PREFIX_E "al-wwnd ERROR: "
37
38
39 /* general */
40 static HWND allegro_wnd = NULL;
41 char wnd_title[WND_TITLE_SIZE]; /* ASCII string */
42 int wnd_x = 0;
43 int wnd_y = 0;
44 int wnd_width = 0;
45 int wnd_height = 0;
46 int wnd_sysmenu = FALSE;
47
48 static int last_wnd_x = -1;
49 static int last_wnd_y = -1;
50
51 static int window_is_initialized = FALSE;
52
53 /* graphics */
54 WIN_GFX_DRIVER *win_gfx_driver;
55 CRITICAL_SECTION gfx_crit_sect;
56 int gfx_crit_sect_nesting = 0;
57
58 /* close button user hook */
59 void (*user_close_proc)(void) = NULL;
60
61 /* window thread internals */
62 #define ALLEGRO_WND_CLASS "AllegroWindow"
63 static HWND user_wnd = NULL;
64 static WNDPROC user_wnd_proc = NULL;
65 static HANDLE wnd_thread = NULL;
66 static HWND (*wnd_create_proc)(WNDPROC) = NULL;
67 static int old_style = 0;
68
69 static int (*wnd_msg_pre_proc)(HWND, UINT, WPARAM, LPARAM, int *) = NULL;
70
71 /* custom window msgs */
72 #define SWITCH_TIMER 1
73 static UINT msg_call_proc = 0;
74 static UINT msg_suicide = 0;
75
76 /* window modules management */
77 struct WINDOW_MODULES {
78 int keyboard;
79 int mouse;
80 int joystick;
81 int joy_type;
82 int sound;
83 int digi_card;
84 int midi_card;
85 int sound_input;
86 int digi_input_card;
87 int midi_input_card;
88 };
89
90 /* Used in adjust_window(). */
91 #ifndef CCHILDREN_TITLEBAR
92 #define CCHILDREN_TITLEBAR 5
93 typedef struct {
94 DWORD cbSize;
95 RECT rcTitleBar;
96 DWORD rgstate[CCHILDREN_TITLEBAR + 1];
97 } TITLEBARINFO, *PTITLEBARINFO, *LPTITLEBARINFO;
98 #endif /* ifndef CCHILDREN_TITLEBAR */
99
100
101
102 /* init_window_modules:
103 * Initialises the modules that are specified by the WM argument.
104 */
init_window_modules(struct WINDOW_MODULES * wm)105 static int init_window_modules(struct WINDOW_MODULES *wm)
106 {
107 if (wm->keyboard)
108 install_keyboard();
109
110 if (wm->mouse)
111 install_mouse();
112
113 if (wm->joystick)
114 install_joystick(wm->joy_type);
115
116 if (wm->sound)
117 install_sound(wm->digi_card, wm->midi_card, NULL);
118
119 if (wm->sound_input)
120 install_sound_input(wm->digi_input_card, wm->midi_input_card);
121
122 return 0;
123 }
124
125
126
127 /* exit_window_modules:
128 * Removes the modules that depend upon the main window:
129 * - keyboard (DirectInput),
130 * - mouse (DirectInput),
131 * - joystick (DirectInput),
132 * - sound (DirectSound),
133 * - sound input (DirectSoundCapture).
134 * If WM is not NULL, record which modules are really removed.
135 */
exit_window_modules(struct WINDOW_MODULES * wm)136 static void exit_window_modules(struct WINDOW_MODULES *wm)
137 {
138 if (wm)
139 memset(wm, 0, sizeof(*wm));
140
141 if (_keyboard_installed) {
142 if (wm)
143 wm->keyboard = TRUE;
144
145 remove_keyboard();
146 }
147
148 if (_mouse_installed) {
149 if (wm)
150 wm->mouse = TRUE;
151
152 remove_mouse();
153 }
154
155 if (_joystick_installed) {
156 if (wm) {
157 wm->joystick = TRUE;
158 wm->joy_type = _joy_type;
159 }
160
161 remove_joystick();
162 }
163
164 if (_sound_installed) {
165 if (wm) {
166 wm->sound = TRUE;
167 wm->digi_card = digi_card;
168 wm->midi_card = midi_card;
169 }
170
171 remove_sound();
172 }
173
174 if (_sound_input_installed) {
175 if (wm) {
176 wm->sound_input = TRUE;
177 wm->digi_input_card = digi_input_card;
178 wm->midi_input_card = midi_input_card;
179 }
180
181 remove_sound_input();
182 }
183 }
184
185
186
187 /* wnd_call_proc:
188 * Instructs the window thread to call the specified procedure and
189 * waits until the procedure has returned.
190 */
wnd_call_proc(int (* proc)(void))191 int wnd_call_proc(int (*proc) (void))
192 {
193 return SendMessage(allegro_wnd, msg_call_proc, (WPARAM)proc, (LPARAM)0);
194 }
195
196
197
198 /* wnd_schedule_proc:
199 * Instructs the window thread to call the specified procedure but
200 * doesn't wait until the procedure has returned.
201 */
wnd_schedule_proc(int (* proc)(void))202 void wnd_schedule_proc(int (*proc) (void))
203 {
204 PostMessage(allegro_wnd, msg_call_proc, (WPARAM)proc, (LPARAM)0);
205 }
206
207
208
209 /* directx_wnd_proc:
210 * Window procedure for the Allegro window class.
211 */
directx_wnd_proc(HWND wnd,UINT message,WPARAM wparam,LPARAM lparam)212 static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
213 {
214 PAINTSTRUCT ps;
215
216 if (message == msg_call_proc)
217 return ( ( LRESULT(*)( void ) )wparam ) ( );
218
219 if (message == msg_suicide) {
220 DestroyWindow(wnd);
221 return 0;
222 }
223
224 /* Call user callback if available */
225 if (wnd_msg_pre_proc){
226 int retval = 0;
227 if (wnd_msg_pre_proc(wnd, message, wparam, lparam, &retval) == 0)
228 return (LRESULT)retval;
229 }
230
231 /* See get_reverse_mapping() in wkeybd.c to see what this is for. */
232 if (FALSE && (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)) {
233 static char name[256];
234 TCHAR str[256];
235 WCHAR wstr[256];
236
237 GetKeyNameText(lparam, str, sizeof str);
238 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr);
239 uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name);
240 _TRACE(PREFIX_I" key[%s] = 0x%08lx;\n", name, lparam & 0x1ff0000);
241 }
242
243 switch (message) {
244
245 case WM_CREATE:
246 if (!user_wnd_proc)
247 allegro_wnd = wnd;
248 break;
249
250 case WM_DESTROY:
251 if (user_wnd_proc) {
252 exit_window_modules(NULL);
253 _win_reset_switch_mode();
254 }
255 else {
256 PostQuitMessage(0);
257 }
258
259 allegro_wnd = NULL;
260 break;
261
262 case WM_SETCURSOR:
263 if (!user_wnd_proc || _mouse_installed) {
264 mouse_set_syscursor();
265 return 1; /* not TRUE */
266 }
267 break;
268
269 case WM_ACTIVATE:
270 if (LOWORD(wparam) == WA_INACTIVE) {
271 _win_switch_out();
272 }
273 else {
274 /* Ignore the WM_ACTIVATE event if the window is minimized. */
275 if (HIWORD(wparam))
276 break;
277
278 if (gfx_driver && !gfx_driver->windowed) {
279 /* 1.2s delay to let Windows complete the switch in fullscreen mode */
280 SetTimer(allegro_wnd, SWITCH_TIMER, 1200, NULL);
281 }
282 else {
283 /* no delay in windowed mode */
284 _win_switch_in();
285 }
286 }
287 break;
288
289 case WM_TIMER:
290 if (wparam == SWITCH_TIMER) {
291 KillTimer(allegro_wnd, SWITCH_TIMER);
292 _win_switch_in();
293 return 0;
294 }
295 break;
296
297 case WM_ENTERSIZEMOVE:
298 if (win_gfx_driver && win_gfx_driver->enter_sysmode)
299 win_gfx_driver->enter_sysmode();
300 break;
301
302 case WM_EXITSIZEMOVE:
303 if (win_gfx_driver && win_gfx_driver->exit_sysmode)
304 win_gfx_driver->exit_sysmode();
305 break;
306
307 case WM_MOVE:
308 if (GetActiveWindow() == allegro_wnd) {
309 if (!IsIconic(allegro_wnd)) {
310 wnd_x = (short) LOWORD(lparam);
311 wnd_y = (short) HIWORD(lparam);
312
313 if (win_gfx_driver && win_gfx_driver->move)
314 win_gfx_driver->move(wnd_x, wnd_y, wnd_width, wnd_height);
315 }
316 else if (win_gfx_driver && win_gfx_driver->iconify) {
317 win_gfx_driver->iconify();
318 }
319 }
320 break;
321
322 case WM_SIZE:
323 wnd_width = LOWORD(lparam);
324 wnd_height = HIWORD(lparam);
325 break;
326
327 case WM_PAINT:
328 if (!user_wnd_proc || win_gfx_driver) {
329 BeginPaint(wnd, &ps);
330 if (win_gfx_driver && win_gfx_driver->paint)
331 win_gfx_driver->paint(&ps.rcPaint);
332 EndPaint(wnd, &ps);
333 return 0;
334 }
335 break;
336
337 case WM_KEYDOWN:
338 case WM_KEYUP:
339 case WM_SYSKEYDOWN:
340 case WM_SYSKEYUP:
341 /* Disable the default message-based key handler
342 * in order to prevent conflicts on NT kernels.
343 */
344 if (!user_wnd_proc || _keyboard_installed)
345 return 0;
346 break;
347
348 case WM_SYSCOMMAND:
349 if (wparam == SC_MONITORPOWER || wparam == SC_SCREENSAVE) {
350 if (_screensaver_policy == ALWAYS_DISABLED
351 || (_screensaver_policy == FULLSCREEN_DISABLED
352 && gfx_driver && !gfx_driver->windowed))
353 return 0;
354 }
355 break;
356
357 case WM_INITMENUPOPUP:
358 wnd_sysmenu = TRUE;
359 mouse_set_sysmenu(TRUE);
360
361 if (win_gfx_driver && win_gfx_driver->enter_sysmode)
362 win_gfx_driver->enter_sysmode();
363 break;
364
365 case WM_MENUSELECT:
366 if ((HIWORD(wparam) == 0xFFFF) && (!lparam)) {
367 wnd_sysmenu = FALSE;
368 mouse_set_sysmenu(FALSE);
369
370 if (win_gfx_driver && win_gfx_driver->exit_sysmode)
371 win_gfx_driver->exit_sysmode();
372 }
373 break;
374
375 case WM_MENUCHAR :
376 return (MNC_CLOSE<<16)|(wparam&0xffff);
377
378 case WM_CLOSE:
379 if (!user_wnd_proc) {
380 if (user_close_proc)
381 (*user_close_proc)();
382 return 0;
383 }
384 break;
385
386 case WM_QUERYNEWPALETTE:
387 case WM_PALETTECHANGED:
388 if ((HWND)wparam != wnd && gfx_directx_primary_surface) {
389 IDirectDrawSurface2_SetPalette(gfx_directx_primary_surface->id, ddpalette);
390 InvalidateRect(wnd, NULL, 1);
391 return 1;
392 }
393 break;
394 }
395
396 /* pass message to default window proc */
397 if (user_wnd_proc)
398 return CallWindowProc(user_wnd_proc, wnd, message, wparam, lparam);
399 else
400 return DefWindowProc(wnd, message, wparam, lparam);
401 }
402
403
404
405 /* create_directx_window:
406 * Creates the Allegro window.
407 */
create_directx_window(void)408 static HWND create_directx_window(void)
409 {
410 static int first = 1;
411 WNDCLASS wnd_class;
412 char fname[1024];
413 HWND wnd;
414
415 if (first) {
416 /* setup the window class */
417 wnd_class.style = CS_HREDRAW | CS_VREDRAW;
418 wnd_class.lpfnWndProc = directx_wnd_proc;
419 wnd_class.cbClsExtra = 0;
420 wnd_class.cbWndExtra = 0;
421 wnd_class.hInstance = allegro_inst;
422 wnd_class.hIcon = LoadIcon(allegro_inst, "allegro_icon");
423 if (!wnd_class.hIcon)
424 wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
425 wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
426 wnd_class.hbrBackground = NULL;
427 wnd_class.lpszMenuName = NULL;
428 wnd_class.lpszClassName = ALLEGRO_WND_CLASS;
429
430 RegisterClass(&wnd_class);
431
432 /* what are we called? */
433 get_executable_name(fname, sizeof(fname));
434 ustrlwr(fname);
435
436 usetc(get_extension(fname), 0);
437 if (ugetat(fname, -1) == '.')
438 usetat(fname, -1, 0);
439
440 do_uconvert(get_filename(fname), U_CURRENT, wnd_title, U_ASCII, WND_TITLE_SIZE);
441
442 first = 0;
443 }
444
445 /* create the window now */
446 wnd = CreateWindowEx(WS_EX_APPWINDOW, ALLEGRO_WND_CLASS, wnd_title,
447 WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
448 -100, -100, 0, 0,
449 NULL, NULL, allegro_inst, NULL);
450 if (!wnd) {
451 _TRACE(PREFIX_E "CreateWindowEx() failed (%s)\n", win_err_str(GetLastError()));
452 return NULL;
453 }
454
455 SetSystemPaletteUse(GetDC(wnd), SYSPAL_NOSTATIC256);
456 ShowWindow(wnd, SW_SHOWNORMAL);
457 SetForegroundWindow(wnd);
458 UpdateWindow(wnd);
459
460 return wnd;
461 }
462
463
464
465 /* wnd_thread_proc:
466 * Thread function that handles the messages of the directx window.
467 */
wnd_thread_proc(HANDLE setup_event)468 static void wnd_thread_proc(HANDLE setup_event)
469 {
470 DWORD result;
471 MSG msg;
472
473 _win_thread_init();
474 _TRACE(PREFIX_I "window thread starts\n");
475
476 /* setup window */
477 if (wnd_create_proc)
478 allegro_wnd = wnd_create_proc(directx_wnd_proc);
479 else
480 allegro_wnd = create_directx_window();
481
482 if (!allegro_wnd)
483 goto End;
484
485 /* now the thread it running successfully, let's acknowledge */
486 SetEvent(setup_event);
487
488 /* message loop */
489 while (TRUE) {
490 result = MsgWaitForMultipleObjects(_win_input_events, _win_input_event_id, FALSE, INFINITE, QS_ALLINPUT);
491 if ((result >= WAIT_OBJECT_0) && (result < (int)(WAIT_OBJECT_0 + _win_input_events))) {
492 /* one of the registered events is in signaled state */
493 (*_win_input_event_handler[result - WAIT_OBJECT_0])();
494 }
495 else if (result == WAIT_OBJECT_0 + _win_input_events) {
496 /* messages are waiting in the queue */
497 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
498 if (GetMessage(&msg, NULL, 0, 0)) {
499 DispatchMessage(&msg);
500 }
501 else {
502 goto End;
503 }
504 }
505 }
506 }
507
508 End:
509 _TRACE(PREFIX_I "window thread exits\n");
510 _win_thread_exit();
511 }
512
513
514
515 /* init_directx_window:
516 * If the user called win_set_window, the user window will be hooked to receive
517 * messages from Allegro. Otherwise a thread is created to own the new window.
518 */
init_directx_window(void)519 int init_directx_window(void)
520 {
521 union {
522 POINT p;
523 RECT r;
524 } win_rect;
525 HANDLE events[2];
526 long result;
527
528 /* setup globals */
529 msg_call_proc = RegisterWindowMessage("Allegro call proc");
530 msg_suicide = RegisterWindowMessage("Allegro window suicide");
531
532 /* initialize gfx critical section */
533 InitializeCriticalSection(&gfx_crit_sect);
534
535 if (user_wnd) {
536 /* initializes input module and requests dedicated thread */
537 _win_input_init(TRUE);
538
539 /* hook the user window */
540 user_wnd_proc = (WNDPROC) SetWindowLongPtr(user_wnd, GWLP_WNDPROC, (LONG_PTR)directx_wnd_proc);
541 if (!user_wnd_proc)
542 return -1;
543
544 allegro_wnd = user_wnd;
545
546 /* retrieve the window dimensions */
547 GetWindowRect(allegro_wnd, &win_rect.r);
548 ClientToScreen(allegro_wnd, &win_rect.p);
549 ClientToScreen(allegro_wnd, &win_rect.p + 1);
550 wnd_x = win_rect.r.left;
551 wnd_y = win_rect.r.top;
552 wnd_width = win_rect.r.right - win_rect.r.left;
553 wnd_height = win_rect.r.bottom - win_rect.r.top;
554 }
555 else {
556 /* initializes input module without dedicated thread */
557 _win_input_init(FALSE);
558
559 /* create window thread */
560 events[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* acknowledges that thread is up */
561 events[1] = (HANDLE) _beginthread(wnd_thread_proc, 0, events[0]);
562 result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
563
564 CloseHandle(events[0]);
565
566 switch (result) {
567 case WAIT_OBJECT_0: /* window was created successfully */
568 wnd_thread = events[1];
569 SetThreadPriority(wnd_thread, THREAD_PRIORITY_ABOVE_NORMAL);
570 break;
571
572 default: /* thread failed to create window */
573 return -1;
574 }
575 }
576
577 /* save window style */
578 old_style = GetWindowLong(allegro_wnd, GWL_STYLE);
579
580 return 0;
581 }
582
583
584
585 /* exit_directx_window:
586 * If a user window was hooked, the old window proc is set. Otherwise
587 * the window thread is destroyed.
588 */
exit_directx_window(void)589 void exit_directx_window(void)
590 {
591 if (user_wnd) {
592 /* restore old window proc */
593 SetWindowLongPtr(user_wnd, GWLP_WNDPROC, (LONG_PTR)user_wnd_proc);
594 user_wnd_proc = NULL;
595 user_wnd = NULL;
596 allegro_wnd = NULL;
597 }
598 else {
599 /* Destroy the window: we cannot directly use DestroyWindow() because
600 * we are not running in the same thread as that of the window.
601 */
602 PostMessage(allegro_wnd, msg_suicide, 0, 0);
603
604 /* wait until the window thread ends */
605 WaitForSingleObject(wnd_thread, INFINITE);
606 wnd_thread = NULL;
607 }
608
609 DeleteCriticalSection(&gfx_crit_sect);
610
611 _win_input_exit();
612
613 window_is_initialized = FALSE;
614 }
615
616
617
618 /* restore_window_style:
619 * Restores the previous style of the window.
620 */
restore_window_style(void)621 void restore_window_style(void)
622 {
623 SetWindowLong(allegro_wnd, GWL_STYLE, old_style);
624 SetWindowPos(allegro_wnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
625 }
626
627
628
629 /* adjust_window:
630 * Moves and resizes the window if we have full control over it.
631 */
adjust_window(int w,int h)632 int adjust_window(int w, int h)
633 {
634 RECT working_area, win_size;
635 TITLEBARINFO tb_info;
636 HMODULE user32_handle;
637 typedef BOOL (WINAPI *func)(HWND, PTITLEBARINFO);
638 func get_title_bar_info = NULL;
639 int tb_height = 0;
640 static int last_w=-1, last_h=-1;
641
642 if (!user_wnd) {
643 SystemParametersInfo(SPI_GETWORKAREA, 0, &working_area, 0);
644
645 if ((last_w == -1) && (last_h == -1)) {
646 /* first window placement: try to center it */
647 last_wnd_x = (working_area.left + working_area.right - w)/2;
648 last_wnd_y = (working_area.top + working_area.bottom - h)/2;
649 }
650 else {
651 /* try to get the height of the window's title bar */
652 user32_handle = GetModuleHandle("user32");
653 if (user32_handle) {
654 get_title_bar_info
655 = (func)GetProcAddress(user32_handle, "GetTitleBarInfo");
656 if (get_title_bar_info) {
657 tb_info.cbSize = sizeof(TITLEBARINFO);
658 if (get_title_bar_info(allegro_wnd, &tb_info))
659 tb_height
660 = tb_info.rcTitleBar.bottom - tb_info.rcTitleBar.top;
661 }
662 }
663 if (!user32_handle || !get_title_bar_info)
664 tb_height = GetSystemMetrics(SM_CYSIZE);
665
666 /* try to center the window relative to its last position */
667 last_wnd_x += (last_w - w)/2;
668 last_wnd_y += (last_h - h)/2;
669
670 if (last_wnd_x + w >= working_area.right)
671 last_wnd_x = working_area.right - w;
672 if (last_wnd_y + h >= working_area.bottom)
673 last_wnd_y = working_area.bottom - h;
674 if (last_wnd_x < working_area.left)
675 last_wnd_x = working_area.left;
676 if (last_wnd_y - tb_height < working_area.top)
677 last_wnd_y = working_area.top + tb_height;
678 }
679
680 #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH
681 last_wnd_x &= 0xfffffffc;
682 #endif
683
684 win_size.left = last_wnd_x;
685 win_size.top = last_wnd_y;
686 win_size.right = last_wnd_x+w;
687 win_size.bottom = last_wnd_y+h;
688
689 last_w = w;
690 last_h = h;
691
692 /* retrieve the size of the decorated window */
693 AdjustWindowRect(&win_size, GetWindowLong(allegro_wnd, GWL_STYLE), FALSE);
694
695 /* display the window */
696 MoveWindow(allegro_wnd, win_size.left, win_size.top,
697 win_size.right - win_size.left, win_size.bottom - win_size.top, TRUE);
698
699 /* check that the actual window size is the one requested */
700 GetClientRect(allegro_wnd, &win_size);
701 if (((win_size.right - win_size.left) != w) || ((win_size.bottom - win_size.top) != h))
702 return -1;
703
704 wnd_x = last_wnd_x;
705 wnd_y = last_wnd_y;
706 wnd_width = w;
707 wnd_height = h;
708 }
709
710 return 0;
711 }
712
713
714
715 /* save_window_pos:
716 * Stores the position of the current window before closing it so that
717 * it can be used as the initial position for the next window.
718 */
save_window_pos(void)719 void save_window_pos(void)
720 {
721 last_wnd_x = wnd_x;
722 last_wnd_y = wnd_y;
723 }
724
725
726
727 /* win_set_window:
728 * Selects an user-defined window for Allegro or
729 * the built-in window if NULL is passed.
730 */
win_set_window(HWND wnd)731 void win_set_window(HWND wnd)
732 {
733 static int (*saved_scbc)(void (*proc)(void)) = NULL;
734 struct WINDOW_MODULES wm;
735
736 if (window_is_initialized || !wnd) {
737 exit_window_modules(&wm);
738 exit_directx_window();
739 }
740
741 user_wnd = wnd;
742
743 /* The user retains full control over the close button if he registers
744 a user-defined window. */
745 if (user_wnd) {
746 if (!saved_scbc)
747 saved_scbc = system_directx.set_close_button_callback;
748
749 system_directx.set_close_button_callback = NULL;
750 }
751 else {
752 if (saved_scbc)
753 system_directx.set_close_button_callback = saved_scbc;
754 }
755
756 if (window_is_initialized || !wnd) {
757 init_directx_window();
758 init_window_modules(&wm);
759 }
760
761 window_is_initialized = TRUE;
762 }
763
764
765
766 /* win_get_window:
767 * Returns the Allegro window handle.
768 */
win_get_window(void)769 HWND win_get_window(void)
770 {
771 return allegro_wnd;
772 }
773
774
win_set_msg_pre_proc(int (* proc)(HWND,UINT,WPARAM,LPARAM,int *))775 void win_set_msg_pre_proc(int (*proc)(HWND, UINT, WPARAM, LPARAM, int *))
776 {
777 wnd_msg_pre_proc = proc;
778 }
779
780
781 /* win_set_wnd_create_proc:
782 * Sets a custom window creation proc.
783 */
win_set_wnd_create_proc(HWND (* proc)(WNDPROC))784 void win_set_wnd_create_proc(HWND (*proc)(WNDPROC))
785 {
786 wnd_create_proc = proc;
787 }
788
789
790
791 /* win_grab_input:
792 * Grabs the input devices.
793 */
win_grab_input(void)794 void win_grab_input(void)
795 {
796 wnd_schedule_proc(key_dinput_acquire);
797 wnd_schedule_proc(mouse_dinput_grab);
798 wnd_schedule_proc(joystick_dinput_acquire);
799 }
800