00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "winGraphicsWindow.h"
00016 #include "config_windisplay.h"
00017 #include "winGraphicsPipe.h"
00018
00019 #include "graphicsPipe.h"
00020 #include "keyboardButton.h"
00021 #include "mouseButton.h"
00022 #include "clockObject.h"
00023 #include "config_util.h"
00024 #include "throw_event.h"
00025 #include "nativeWindowHandle.h"
00026
00027 #include <tchar.h>
00028
00029
00030
00031 TypeHandle WinGraphicsWindow::_type_handle;
00032 TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle;
00033
00034 WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
00035 WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
00036
00037 WinGraphicsWindow *WinGraphicsWindow::_cursor_window = NULL;
00038 bool WinGraphicsWindow::_cursor_hidden = false;
00039
00040
00041
00042
00043 bool WinGraphicsWindow::_got_saved_params = false;
00044 int WinGraphicsWindow::_saved_mouse_trails;
00045 BOOL WinGraphicsWindow::_saved_cursor_shadow;
00046 BOOL WinGraphicsWindow::_saved_mouse_vanish;
00047
00048 WinGraphicsWindow::IconFilenames WinGraphicsWindow::_icon_filenames;
00049 WinGraphicsWindow::IconFilenames WinGraphicsWindow::_cursor_filenames;
00050
00051 WinGraphicsWindow::WindowClasses WinGraphicsWindow::_window_classes;
00052 int WinGraphicsWindow::_window_class_index = 0;
00053
00054 static const char * const errorbox_title = "Panda3D Error";
00055
00056
00057
00058
00059
00060
00061
00062
00063 typedef WINUSERAPI UINT (WINAPI *tGetRawInputDeviceList)
00064 (OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PUINT puiNumDevices, IN UINT cbSize);
00065 typedef WINUSERAPI UINT(WINAPI *tGetRawInputData)
00066 (IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize, IN UINT cbSizeHeader);
00067 typedef WINUSERAPI UINT(WINAPI *tGetRawInputDeviceInfoA)
00068 (IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize);
00069 typedef WINUSERAPI BOOL (WINAPI *tRegisterRawInputDevices)
00070 (IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
00071
00072 static tGetRawInputDeviceList pGetRawInputDeviceList;
00073 static tGetRawInputData pGetRawInputData;
00074 static tGetRawInputDeviceInfoA pGetRawInputDeviceInfoA;
00075 static tRegisterRawInputDevices pRegisterRawInputDevices;
00076
00077
00078
00079
00080
00081
00082 WinGraphicsWindow::
00083 WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
00084 const string &name,
00085 const FrameBufferProperties &fb_prop,
00086 const WindowProperties &win_prop,
00087 int flags,
00088 GraphicsStateGuardian *gsg,
00089 GraphicsOutput *host) :
00090 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00091 {
00092 initialize_input_devices();
00093 _hWnd = (HWND)0;
00094 _ime_open = false;
00095 _ime_active = false;
00096 _tracking_mouse_leaving = false;
00097 _maximized = false;
00098 _cursor = 0;
00099 _lost_keypresses = false;
00100 _lshift_down = false;
00101 _rshift_down = false;
00102 _lcontrol_down = false;
00103 _rcontrol_down = false;
00104 _lalt_down = false;
00105 _ralt_down = false;
00106 _hparent = NULL;
00107 #ifdef HAVE_WIN_TOUCHINPUT
00108 _numTouches = 0;
00109 #endif
00110 }
00111
00112
00113
00114
00115
00116
00117 WinGraphicsWindow::
00118 ~WinGraphicsWindow() {
00119 if (_window_handle != (WindowHandle *)NULL) {
00120 DCAST(WinWindowHandle, _window_handle)->clear_window();
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 bool WinGraphicsWindow::
00135 move_pointer(int device, int x, int y) {
00136
00137
00138
00139 _ime_active = false;
00140
00141
00142
00143 if (device == 0) {
00144
00145 if (!_properties.get_foreground() )
00146
00147 {
00148
00149
00150 return false;
00151 }
00152
00153 RECT view_rect;
00154 get_client_rect_screen(_hWnd, &view_rect);
00155
00156 SetCursorPos(view_rect.left + x, view_rect.top + y);
00157 _input_devices[0].set_pointer_in_window(x, y);
00158 return true;
00159 } else {
00160
00161 if ((device < 1)||(device >= (int)_input_devices.size())) {
00162 return false;
00163 }
00164 _input_devices[device].set_pointer_in_window(x, y);
00165 return true;
00166 }
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 void WinGraphicsWindow::
00176 close_ime() {
00177
00178 if (!_ime_open)
00179 return;
00180
00181 HIMC hIMC = ImmGetContext(_hWnd);
00182 if (hIMC != 0) {
00183 if (!ImmSetOpenStatus(hIMC, false)) {
00184 windisplay_cat.debug() << "ImmSetOpenStatus failed\n";
00185 }
00186 ImmReleaseContext(_hWnd, hIMC);
00187 }
00188 _ime_open = false;
00189
00190 windisplay_cat.debug() << "success: closed ime window\n";
00191 return;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 void WinGraphicsWindow::
00209 begin_flip() {
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void WinGraphicsWindow::
00223 process_events() {
00224 GraphicsWindow::process_events();
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 MSG msg;
00243
00244
00245
00246
00247 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
00248 process_1_event();
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 void WinGraphicsWindow::
00272 set_properties_now(WindowProperties &properties) {
00273 GraphicsWindow::set_properties_now(properties);
00274 if (!properties.is_any_specified()) {
00275
00276 return;
00277 }
00278
00279 if (properties.has_title()) {
00280 string title = properties.get_title();
00281 _properties.set_title(title);
00282 TextEncoder encoder;
00283 wstring title_w = encoder.decode_text(title);
00284 SetWindowTextW(_hWnd, title_w.c_str());
00285 properties.clear_title();
00286 }
00287
00288 if (properties.has_cursor_hidden()) {
00289 bool hide_cursor = properties.get_cursor_hidden();
00290 _properties.set_cursor_hidden(hide_cursor);
00291 if (_cursor_window == this) {
00292 hide_or_show_cursor(hide_cursor);
00293 }
00294
00295 properties.clear_cursor_hidden();
00296 }
00297
00298 if (properties.has_cursor_filename()) {
00299 Filename filename = properties.get_cursor_filename();
00300 _properties.set_cursor_filename(filename);
00301
00302 _cursor = get_cursor(filename);
00303 if (_cursor == 0) {
00304 _cursor = LoadCursor(NULL, IDC_ARROW);
00305 }
00306
00307 if (_cursor_window == this) {
00308 SetCursor(_cursor);
00309 }
00310
00311 properties.clear_cursor_filename();
00312 }
00313
00314 if (properties.has_z_order()) {
00315 WindowProperties::ZOrder last_z_order = _properties.get_z_order();
00316 _properties.set_z_order(properties.get_z_order());
00317 adjust_z_order(last_z_order, properties.get_z_order());
00318
00319 properties.clear_z_order();
00320 }
00321
00322 if (properties.has_foreground() && properties.get_foreground()) {
00323 if (!SetActiveWindow(_hWnd)) {
00324 windisplay_cat.warning()
00325 << "SetForegroundWindow() failed!\n";
00326 } else {
00327 _properties.set_foreground(true);
00328 }
00329
00330 properties.clear_foreground();
00331 }
00332
00333 if (properties.has_minimized()) {
00334 if (_properties.get_minimized() != properties.get_minimized()) {
00335 if (properties.get_minimized()) {
00336 ShowWindow(_hWnd, SW_MINIMIZE);
00337 } else {
00338 ShowWindow(_hWnd, SW_RESTORE);
00339 }
00340 _properties.set_minimized(properties.get_minimized());
00341 _properties.set_foreground(!properties.get_minimized());
00342 }
00343 properties.clear_minimized();
00344 }
00345
00346 if (properties.has_fullscreen()) {
00347 if (properties.get_fullscreen() && !is_fullscreen()) {
00348 if (do_fullscreen_switch()){
00349 _properties.set_fullscreen(true);
00350 properties.clear_fullscreen();
00351 } else {
00352 windisplay_cat.warning()
00353 << "Switching to fullscreen mode failed!\n";
00354 }
00355 } else if (!properties.get_fullscreen() && is_fullscreen()){
00356 if (do_windowed_switch()){
00357 _properties.set_fullscreen(false);
00358 properties.clear_fullscreen();
00359 } else {
00360 windisplay_cat.warning()
00361 << "Switching to windowed mode failed!\n";
00362 }
00363 }
00364 }
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 void WinGraphicsWindow::
00375 trigger_flip() {
00376 GraphicsWindow::trigger_flip();
00377
00378 if (!get_unexposed_draw()) {
00379
00380
00381
00382 InvalidateRect(_hWnd, NULL, FALSE);
00383 _got_expose_event = false;
00384
00385 if (windisplay_cat.is_spam()) {
00386 windisplay_cat.spam()
00387 << "InvalidateRect: " << this << "\n";
00388 }
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397
00398 void WinGraphicsWindow::
00399 close_window() {
00400 set_cursor_out_of_window();
00401 DestroyWindow(_hWnd);
00402
00403 if (is_fullscreen()) {
00404
00405 do_fullscreen_disable();
00406 }
00407
00408
00409 _window_handles.erase(_hWnd);
00410 _hWnd = (HWND)0;
00411
00412 GraphicsWindow::close_window();
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422 bool WinGraphicsWindow::
00423 open_window() {
00424 if (_properties.has_cursor_filename()) {
00425 _cursor = get_cursor(_properties.get_cursor_filename());
00426 }
00427 if (_cursor == 0) {
00428 _cursor = LoadCursor(NULL, IDC_ARROW);
00429 }
00430 bool want_foreground = (!_properties.has_foreground() || _properties.get_foreground());
00431 bool want_minimized = (_properties.has_minimized() && _properties.get_minimized()) && !want_foreground;
00432
00433 HWND old_foreground_window = GetForegroundWindow();
00434
00435
00436
00437
00438
00439 _creating_window = this;
00440 bool opened = open_graphic_window(is_fullscreen());
00441 _creating_window = (WinGraphicsWindow *)NULL;
00442
00443 if (!opened) {
00444 return false;
00445 }
00446
00447
00448
00449 _window_handles.insert(WindowHandles::value_type(_hWnd, this));
00450
00451
00452 SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0,
00453 SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
00454
00455
00456 if (want_minimized) {
00457 ShowWindow(_hWnd, SW_MINIMIZE);
00458 ShowWindow(_hWnd, SW_MINIMIZE);
00459 } else {
00460 ShowWindow(_hWnd, SW_SHOWNORMAL);
00461 ShowWindow(_hWnd, SW_SHOWNORMAL);
00462 }
00463
00464 HWND new_foreground_window = _hWnd;
00465 if (!want_foreground) {
00466
00467
00468 new_foreground_window = old_foreground_window;
00469 }
00470
00471 if (!SetActiveWindow(new_foreground_window)) {
00472 windisplay_cat.warning()
00473 << "SetActiveWindow() failed!\n";
00474 }
00475
00476
00477
00478
00479 if (!SetForegroundWindow(new_foreground_window)) {
00480 windisplay_cat.warning()
00481 << "SetForegroundWindow() failed!\n";
00482 }
00483
00484
00485 _ime_open = false;
00486 _ime_active = false;
00487 HIMC hIMC = ImmGetContext(_hWnd);
00488 if (hIMC != 0) {
00489 _ime_open = (ImmGetOpenStatus(hIMC) != 0);
00490 ImmReleaseContext(_hWnd, hIMC);
00491 }
00492
00493
00494 if ((pRegisterRawInputDevices)&&(_input_devices.size() > 1)) {
00495 RAWINPUTDEVICE Rid;
00496 Rid.usUsagePage = 0x01;
00497 Rid.usUsage = 0x02;
00498 Rid.dwFlags = 0;
00499 Rid.hwndTarget = _hWnd;
00500 pRegisterRawInputDevices(&Rid, 1, sizeof (Rid));
00501 }
00502
00503
00504 _window_handle = NativeWindowHandle::make_win(_hWnd);
00505
00506
00507 _window_handle = new WinWindowHandle(this, *_window_handle);
00508
00509
00510 if (_parent_window_handle != (WindowHandle *)NULL) {
00511 _parent_window_handle->attach_child(_window_handle);
00512 }
00513
00514
00515 set_focus();
00516
00517
00518 #ifdef HAVE_WIN_TOUCHINPUT
00519 RegisterTouchWindow(_hWnd, 0);
00520 #endif
00521
00522 return true;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 void WinGraphicsWindow::
00536 initialize_input_devices() {
00537 UINT nInputDevices;
00538 PRAWINPUTDEVICELIST pRawInputDeviceList;
00539
00540 nassertv(_input_devices.size() == 0);
00541
00542
00543 memset(_input_device_handle, 0, sizeof(_input_device_handle));
00544 GraphicsWindowInputDevice device =
00545 GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
00546 add_input_device(device);
00547
00548
00549 if (pRegisterRawInputDevices==0) {
00550 HMODULE user32 = LoadLibrary("user32.dll");
00551 if (user32) {
00552 pRegisterRawInputDevices = (tRegisterRawInputDevices)GetProcAddress(user32,"RegisterRawInputDevices");
00553 pGetRawInputDeviceList = (tGetRawInputDeviceList) GetProcAddress(user32,"GetRawInputDeviceList");
00554 pGetRawInputDeviceInfoA = (tGetRawInputDeviceInfoA) GetProcAddress(user32,"GetRawInputDeviceInfoA");
00555 pGetRawInputData = (tGetRawInputData) GetProcAddress(user32,"GetRawInputData");
00556 }
00557 }
00558
00559 if (pRegisterRawInputDevices==0) return;
00560 if (pGetRawInputDeviceList==0) return;
00561 if (pGetRawInputDeviceInfoA==0) return;
00562 if (pGetRawInputData==0) return;
00563
00564
00565 if (pGetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0)
00566 return;
00567
00568
00569 pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(sizeof(RAWINPUTDEVICELIST) * nInputDevices);
00570 if (pRawInputDeviceList==0) return;
00571
00572
00573 if (pGetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1)
00574 return;
00575
00576
00577 for (int i = 0; i < (int)nInputDevices; i++) {
00578 if (pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE) {
00579
00580 UINT nSize;
00581 if (pGetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)0, &nSize) != 0)
00582 return;
00583 char *psName = (char*)alloca(sizeof(TCHAR) * nSize);
00584 if (psName == 0) return;
00585 if (pGetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0)
00586 return;
00587
00588
00589 if (strncmp(psName,"\\??\\Root#RDP_MOU#0000#",22)!=0) {
00590 if (_input_devices.size() < 32) {
00591 if (strncmp(psName,"\\??\\",4)==0) psName += 4;
00592 char *pound1 = strchr(psName,'#');
00593 char *pound2 = pound1 ? strchr(pound1+1,'#') : 0;
00594 char *pound3 = pound2 ? strchr(pound2+1,'#') : 0;
00595 if (pound3) *pound3 = 0;
00596 for (char *p = psName; *p; p++) {
00597 if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
00598 *p = '_';
00599 }
00600 }
00601 if (pound2) *pound2 = '.';
00602 _input_device_handle[_input_devices.size()] = pRawInputDeviceList[i].hDevice;
00603 GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_only(this, psName);
00604 device.set_pointer_in_window(0,0);
00605 add_input_device(device);
00606 }
00607 }
00608 }
00609 }
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 void WinGraphicsWindow::
00622 fullscreen_minimized(WindowProperties &) {
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 void WinGraphicsWindow::
00635 fullscreen_restored(WindowProperties &) {
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 bool WinGraphicsWindow::
00648 do_reshape_request(int x_origin, int y_origin, bool has_origin,
00649 int x_size, int y_size) {
00650 if (windisplay_cat.is_debug()) {
00651 windisplay_cat.debug()
00652 << "Got reshape request (" << x_origin << ", " << y_origin
00653 << ", " << has_origin << ", " << x_size << ", " << y_size << ")\n";
00654 }
00655 if (!is_fullscreen()) {
00656 if (has_origin) {
00657
00658 if (x_origin == -2) {
00659 x_origin = 0.5 * (_pipe->get_display_width() - x_size);
00660 }
00661 if (y_origin == -2) {
00662 y_origin = 0.5 * (_pipe->get_display_height() - y_size);
00663 }
00664 _properties.set_origin(x_origin, y_origin);
00665
00666 if (x_origin == -1 && y_origin == -1) {
00667 x_origin = 0;
00668 y_origin = 0;
00669 has_origin = false;
00670 }
00671 }
00672
00673
00674
00675 RECT view_rect;
00676 SetRect(&view_rect, x_origin, y_origin,
00677 x_origin + x_size, y_origin + y_size);
00678 WINDOWINFO wi;
00679 GetWindowInfo(_hWnd, &wi);
00680 AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle);
00681
00682 UINT flags = SWP_NOZORDER | SWP_NOSENDCHANGING;
00683
00684 if (has_origin) {
00685 x_origin = view_rect.left;
00686 y_origin = view_rect.top;
00687 } else {
00688 x_origin = CW_USEDEFAULT;
00689 y_origin = CW_USEDEFAULT;
00690 flags |= SWP_NOMOVE;
00691 }
00692
00693 SetWindowPos(_hWnd, NULL, x_origin, y_origin,
00694 view_rect.right - view_rect.left,
00695 view_rect.bottom - view_rect.top,
00696 flags);
00697
00698 handle_reshape();
00699 return true;
00700 }
00701
00702
00703 return do_fullscreen_resize(x_size, y_size);
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713 void WinGraphicsWindow::
00714 handle_reshape() {
00715 RECT view_rect;
00716 if (!GetClientRect(_hWnd, &view_rect)) {
00717
00718
00719
00720 if (windisplay_cat.is_debug()) {
00721 windisplay_cat.debug()
00722 << "GetClientRect() failed in handle_reshape. Ignoring.\n";
00723 }
00724 return;
00725 }
00726
00727
00728
00729 if (view_rect.left == 0 && view_rect.right == 0 &&
00730 view_rect.bottom == 0 && view_rect.top == 0) {
00731 if (windisplay_cat.is_debug()) {
00732 windisplay_cat.debug()
00733 << "GetClientRect() returned all zeroes in handle_reshape. Ignoring.\n";
00734 }
00735 return;
00736 }
00737
00738 bool result = ClientToScreen(_hWnd, (POINT*)&view_rect.left);
00739 if (result) {
00740 result = ClientToScreen(_hWnd, (POINT*)&view_rect.right);
00741 }
00742
00743 if (!result) {
00744 if (windisplay_cat.is_debug()) {
00745 windisplay_cat.debug()
00746 << "ClientToScreen() failed in handle_reshape. Ignoring.\n";
00747 }
00748 return;
00749 }
00750
00751 WindowProperties properties;
00752 properties.set_size((view_rect.right - view_rect.left),
00753 (view_rect.bottom - view_rect.top));
00754
00755
00756 properties.set_origin(view_rect.left, view_rect.top);
00757
00758 if (windisplay_cat.is_spam()) {
00759 windisplay_cat.spam()
00760 << "reshape to origin: (" << properties.get_x_origin() << ","
00761 << properties.get_y_origin() << "), size: (" << properties.get_x_size()
00762 << "," << properties.get_y_size() << ")\n";
00763 }
00764
00765 adjust_z_order();
00766 system_changed_properties(properties);
00767 }
00768
00769
00770
00771
00772
00773
00774
00775 bool WinGraphicsWindow::
00776 do_fullscreen_resize(int x_size, int y_size) {
00777 HWND hDesktopWindow = GetDesktopWindow();
00778 HDC scrnDC = GetDC(hDesktopWindow);
00779 DWORD dwFullScreenBitDepth = GetDeviceCaps(scrnDC, BITSPIXEL);
00780 ReleaseDC(hDesktopWindow, scrnDC);
00781
00782
00783
00784
00785
00786
00787
00788 DEVMODE dm;
00789 if (!find_acceptable_display_mode(x_size, y_size,
00790 dwFullScreenBitDepth, dm)) {
00791 windisplay_cat.error()
00792 << "window resize(" << x_size << ", " << y_size
00793 << ") failed, no compatible fullscreen display mode found!\n";
00794 return false;
00795 }
00796
00797
00798 SetWindowPos(_hWnd, NULL, 0,0, x_size, y_size,
00799 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
00800 int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
00801
00802 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
00803 windisplay_cat.error()
00804 << "resize ChangeDisplaySettings failed (error code: "
00805 << chg_result << ") for specified res: "
00806 << dm.dmPelsWidth << " x " << dm.dmPelsHeight
00807 << " x " << dm.dmBitsPerPel << ", "
00808 << dm.dmDisplayFrequency << " Hz\n";
00809 return false;
00810 }
00811
00812 _fullscreen_display_mode = dm;
00813
00814 windisplay_cat.info()
00815 << "Resized fullscreen window to " << x_size << ", " << y_size
00816 << " bitdepth " << dwFullScreenBitDepth << ", "
00817 << dm.dmDisplayFrequency << "Hz\n";
00818
00819 _properties.set_size(x_size, y_size);
00820 set_size_and_recalc(x_size, y_size);
00821
00822 return true;
00823 }
00824
00825
00826
00827
00828
00829
00830
00831 bool WinGraphicsWindow::
00832 do_fullscreen_switch() {
00833 if (!do_fullscreen_enable()) {
00834
00835 return false;
00836 }
00837
00838 DWORD window_style = make_style(true);
00839 SetWindowLong(_hWnd, GWL_STYLE, window_style);
00840
00841 WINDOW_METRICS metrics;
00842 bool has_origin;
00843 if (!calculate_metrics(true, window_style, metrics, has_origin)){
00844 return false;
00845 }
00846
00847 SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, metrics.width, metrics.height,
00848 SWP_FRAMECHANGED | SWP_SHOWWINDOW);
00849 return true;
00850 }
00851
00852
00853
00854
00855
00856
00857
00858 bool WinGraphicsWindow::
00859 do_windowed_switch() {
00860 do_fullscreen_disable();
00861 DWORD window_style = make_style(false);
00862 SetWindowLong(_hWnd, GWL_STYLE, window_style);
00863
00864 WINDOW_METRICS metrics;
00865 bool has_origin;
00866
00867 if (!calculate_metrics(false, window_style, metrics, has_origin)){
00868 return false;
00869 }
00870
00871
00872
00873
00874
00875 SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0,
00876 metrics.width, metrics.height,
00877 SWP_FRAMECHANGED | SWP_SHOWWINDOW);
00878
00879 return true;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889 void WinGraphicsWindow::
00890 reconsider_fullscreen_size(DWORD &, DWORD &, DWORD &) {
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 void WinGraphicsWindow::
00904 support_overlay_window(bool) {
00905 }
00906
00907
00908
00909
00910
00911
00912
00913 DWORD WinGraphicsWindow::
00914 make_style(bool fullscreen) {
00915
00916
00917
00918
00919
00920
00921
00922
00923 DWORD window_style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
00924
00925 if (fullscreen){
00926 window_style |= WS_SYSMENU;
00927 } else if (!_properties.get_undecorated()) {
00928 window_style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
00929
00930 if (!_properties.get_fixed_size()) {
00931 window_style |= (WS_SIZEBOX | WS_MAXIMIZEBOX);
00932 } else {
00933 window_style |= WS_BORDER;
00934 }
00935 }
00936 return window_style;
00937 }
00938
00939
00940
00941
00942
00943
00944
00945 bool WinGraphicsWindow::
00946 calculate_metrics(bool fullscreen, DWORD window_style, WINDOW_METRICS &metrics,
00947 bool &has_origin) {
00948 metrics.x = 0;
00949 metrics.y = 0;
00950 has_origin = _properties.has_origin();
00951 if (!fullscreen && has_origin) {
00952 metrics.x = _properties.get_x_origin();
00953 metrics.y = _properties.get_y_origin();
00954
00955
00956 if (metrics.x == -2) {
00957 metrics.x = 0.5 * (_pipe->get_display_width() - _properties.get_x_size());
00958 }
00959 if (metrics.y == -2) {
00960 metrics.y = 0.5 * (_pipe->get_display_height() - _properties.get_y_size());
00961 }
00962 _properties.set_origin(metrics.x, metrics.y);
00963
00964 if (metrics.x == -1 && metrics.y == -1) {
00965 metrics.x = 0;
00966 metrics.y = 0;
00967 has_origin = false;
00968 }
00969 }
00970
00971 metrics.width = _properties.get_x_size();
00972 metrics.height = _properties.get_y_size();
00973
00974 if (!fullscreen){
00975 RECT win_rect;
00976 SetRect(&win_rect, metrics.x, metrics.y,
00977 metrics.x + metrics.width, metrics.y + metrics.height);
00978
00979
00980 if (!AdjustWindowRect(&win_rect, window_style, FALSE)) {
00981 windisplay_cat.error()
00982 << "AdjustWindowRect failed!" << endl;
00983 return false;
00984 }
00985
00986 if (has_origin) {
00987 metrics.x = win_rect.left;
00988 metrics.y = win_rect.top;
00989 } else {
00990 metrics.x = CW_USEDEFAULT;
00991 metrics.y = CW_USEDEFAULT;
00992 }
00993 metrics.width = win_rect.right - win_rect.left;
00994 metrics.height = win_rect.bottom - win_rect.top;
00995 }
00996
00997 return true;
00998 }
00999
01000
01001
01002
01003
01004
01005 bool WinGraphicsWindow::
01006 open_graphic_window(bool fullscreen) {
01007 DWORD window_style = make_style(fullscreen);
01008
01009 wstring title;
01010 if (_properties.has_title()) {
01011 TextEncoder encoder;
01012 title = encoder.decode_text(_properties.get_title());
01013 }
01014
01015 if (!_properties.has_size()) {
01016
01017 _properties.set_size(640, 480);
01018 }
01019
01020 WINDOW_METRICS metrics;
01021 bool has_origin;
01022 if (!calculate_metrics(fullscreen, window_style, metrics, has_origin)){
01023 return false;
01024 }
01025
01026 const WindowClass &wclass = register_window_class(_properties);
01027 HINSTANCE hinstance = GetModuleHandle(NULL);
01028
01029 _hparent = NULL;
01030
01031 if (!fullscreen){
01032 WindowHandle *window_handle = _properties.get_parent_window();
01033 if (window_handle != NULL) {
01034 windisplay_cat.info()
01035 << "Got parent_window " << *window_handle << "\n";
01036 WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
01037 if (os_handle != NULL) {
01038 windisplay_cat.info()
01039 << "os_handle type " << os_handle->get_type() << "\n";
01040
01041 if (os_handle->is_of_type(NativeWindowHandle::WinHandle::get_class_type())) {
01042 NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle);
01043 _hparent = win_handle->get_handle();
01044 } else if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
01045 NativeWindowHandle::IntHandle *int_handle = DCAST(NativeWindowHandle::IntHandle, os_handle);
01046 _hparent = (HWND)int_handle->get_handle();
01047 }
01048 }
01049 }
01050 _parent_window_handle = window_handle;
01051 } else {
01052 _parent_window_handle = NULL;
01053 }
01054
01055 if (!_hparent) {
01056 _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(), window_style,
01057 metrics.x, metrics.y,
01058 metrics.width,
01059 metrics.height,
01060 NULL, NULL, hinstance, 0);
01061 } else {
01062 int x_origin = 0;
01063 int y_origin = 0;
01064
01065 if (!fullscreen && has_origin) {
01066 x_origin = _properties.get_x_origin();
01067 y_origin = _properties.get_y_origin();
01068 }
01069
01070 _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(),
01071 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,
01072 x_origin, y_origin,
01073 _properties.get_x_size(), _properties.get_y_size(),
01074 _hparent, NULL, hinstance, 0);
01075
01076 if (_hWnd) {
01077
01078
01079
01080
01081
01082
01083
01084 WindowProperties properties;
01085 properties.set_foreground(true);
01086 system_changed_properties(properties);
01087 }
01088 }
01089
01090 if (!_hWnd) {
01091 windisplay_cat.error()
01092 << "CreateWindow() failed!" << endl;
01093 show_error_message();
01094 return false;
01095 }
01096
01097
01098
01099
01100
01101 if (fullscreen){
01102 if (!do_fullscreen_enable()){
01103 return false;
01104 }
01105 }
01106
01107 return true;
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117 bool WinGraphicsWindow::
01118 do_fullscreen_enable() {
01119
01120 HWND hDesktopWindow = GetDesktopWindow();
01121 HDC scrnDC = GetDC(hDesktopWindow);
01122 DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
01123
01124
01125
01126 ReleaseDC(hDesktopWindow, scrnDC);
01127
01128 DWORD dwWidth = _properties.get_x_size();
01129 DWORD dwHeight = _properties.get_y_size();
01130 DWORD dwFullScreenBitDepth = cur_bitdepth;
01131
01132 DEVMODE dm;
01133 reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth);
01134 if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth, dm)) {
01135 windisplay_cat.error()
01136 << "Videocard has no supported display resolutions at specified res ("
01137 << dwWidth << " x " << dwHeight << " x " << dwFullScreenBitDepth <<")\n";
01138 return false;
01139 }
01140
01141 dm.dmPelsWidth = dwWidth;
01142 dm.dmPelsHeight = dwHeight;
01143 dm.dmBitsPerPel = dwFullScreenBitDepth;
01144 int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
01145
01146 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
01147 windisplay_cat.error()
01148 << "ChangeDisplaySettings failed (error code: "
01149 << chg_result << ") for specified res: "
01150 << dm.dmPelsWidth << " x " << dm.dmPelsHeight
01151 << " x " << dm.dmBitsPerPel << ", "
01152 << dm.dmDisplayFrequency << " Hz\n";
01153 return false;
01154 }
01155
01156 _fullscreen_display_mode = dm;
01157
01158 _properties.set_origin(0, 0);
01159 _properties.set_size(dwWidth, dwHeight);
01160
01161 return true;
01162
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172 bool WinGraphicsWindow::
01173 do_fullscreen_disable() {
01174 int chg_result = ChangeDisplaySettings(NULL, 0x0);
01175 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
01176 windisplay_cat.warning()
01177 << "ChangeDisplaySettings failed to restore Windowed mode\n";
01178 return false;
01179 }
01180 return true;
01181 }
01182
01183
01184
01185
01186
01187
01188
01189 void WinGraphicsWindow::
01190 adjust_z_order() {
01191 WindowProperties::ZOrder z_order = _properties.get_z_order();
01192 adjust_z_order(z_order, z_order);
01193 }
01194
01195
01196
01197
01198
01199
01200
01201 void WinGraphicsWindow::
01202 adjust_z_order(WindowProperties::ZOrder last_z_order,
01203 WindowProperties::ZOrder this_z_order) {
01204 HWND order;
01205 bool do_change = false;
01206
01207 switch (this_z_order) {
01208 case WindowProperties::Z_bottom:
01209 order = HWND_BOTTOM;
01210 do_change = true;
01211 break;
01212
01213 case WindowProperties::Z_normal:
01214 if ((last_z_order != WindowProperties::Z_normal) &&
01215
01216
01217 (last_z_order != WindowProperties::Z_bottom ||
01218 _properties.get_foreground())
01219
01220
01221
01222 ) {
01223 order = HWND_TOP;
01224 do_change = true;
01225 }
01226 break;
01227
01228 case WindowProperties::Z_top:
01229 order = HWND_TOPMOST;
01230 do_change = true;
01231 break;
01232 }
01233 if (do_change) {
01234 BOOL result = SetWindowPos(_hWnd, order, 0,0,0,0,
01235 SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
01236 if (!result) {
01237 windisplay_cat.warning()
01238 << "SetWindowPos failed.\n";
01239 }
01240 }
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 void WinGraphicsWindow::
01252 track_mouse_leaving(HWND hwnd) {
01253
01254
01255
01256
01257 WinGraphicsPipe *winpipe;
01258 DCAST_INTO_V(winpipe, _pipe);
01259
01260 if (winpipe->_pfnTrackMouseEvent != NULL) {
01261 TRACKMOUSEEVENT tme = {
01262 sizeof(TRACKMOUSEEVENT),
01263 TME_LEAVE,
01264 hwnd,
01265 0
01266 };
01267
01268
01269 BOOL bSucceeded = winpipe->_pfnTrackMouseEvent(&tme);
01270
01271 if ((!bSucceeded) && windisplay_cat.is_debug()) {
01272 windisplay_cat.debug()
01273 << "TrackMouseEvent failed!, LastError=" << GetLastError() << endl;
01274 }
01275
01276 _tracking_mouse_leaving = true;
01277 }
01278 }
01279
01280
01281
01282
01283
01284
01285
01286 void WinGraphicsWindow::
01287 set_focus() {
01288 if (SetFocus(_hWnd) == NULL && GetLastError() != 0) {
01289
01290
01291
01292
01293
01294 if (_parent_window_handle != NULL && _window_handle != NULL) {
01295 _parent_window_handle->request_keyboard_focus(_window_handle);
01296 } else {
01297
01298 windisplay_cat.error()
01299 << "SetFocus failed: " << GetLastError() << "\n";
01300 }
01301 }
01302 }
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 void WinGraphicsWindow::
01315 receive_windows_message(unsigned int msg, int wparam, int lparam) {
01316
01317
01318
01319
01320
01321 window_proc(_hWnd, msg, wparam, lparam);
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331 LONG WinGraphicsWindow::
01332 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
01333 if (windisplay_cat.is_spam()) {
01334 windisplay_cat.spam()
01335 << ClockObject::get_global_clock()->get_real_time()
01336 << " window_proc(" << (void *)this << ", " << hwnd << ", "
01337 << msg << ", " << wparam << ", " << lparam << ")\n";
01338 }
01339 WindowProperties properties;
01340 int button = -1;
01341
01342 switch (msg) {
01343 case WM_MOUSEMOVE:
01344 if (!_tracking_mouse_leaving) {
01345
01346 track_mouse_leaving(hwnd);
01347 }
01348 set_cursor_in_window();
01349 if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))))
01350 return 0;
01351 break;
01352
01353 case WM_INPUT:
01354 handle_raw_input((HRAWINPUT)lparam);
01355 break;
01356
01357 case WM_MOUSELEAVE:
01358 _tracking_mouse_leaving = false;
01359 handle_mouse_exit();
01360 set_cursor_out_of_window();
01361 break;
01362
01363 case WM_CREATE:
01364 {
01365 track_mouse_leaving(hwnd);
01366 ClearToBlack(hwnd, _properties);
01367
01368 POINT cpos;
01369 GetCursorPos(&cpos);
01370 ScreenToClient(hwnd, &cpos);
01371 RECT clientRect;
01372 GetClientRect(hwnd, &clientRect);
01373 if (PtInRect(&clientRect,cpos)) {
01374 set_cursor_in_window();
01375 } else {
01376 set_cursor_out_of_window();
01377 }
01378 }
01379 break;
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404 case WM_CLOSE:
01405
01406
01407 {
01408 string close_request_event = get_close_request_event();
01409 if (!close_request_event.empty()) {
01410
01411
01412 throw_event(close_request_event);
01413 return 0;
01414
01415 } else {
01416
01417
01418 close_window();
01419 properties.set_open(false);
01420 system_changed_properties(properties);
01421
01422
01423 }
01424 }
01425 break;
01426
01427 case WM_CHILDACTIVATE:
01428 if (windisplay_cat.is_debug()) {
01429 windisplay_cat.debug()
01430 << "WM_CHILDACTIVATE: " << hwnd << "\n";
01431 }
01432 break;
01433
01434 case WM_ACTIVATE:
01435 if (windisplay_cat.is_debug()) {
01436 windisplay_cat.debug()
01437 << "WM_ACTIVATE: " << hwnd << ", " << wparam << ", " << lparam << "\n";
01438 }
01439 properties.set_minimized((wparam & 0xffff0000) != 0);
01440 if ((wparam & 0xffff) != WA_INACTIVE)
01441 {
01442 properties.set_foreground(true);
01443 if (is_fullscreen())
01444 {
01445
01446
01447 int chg_result =
01448 ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN);
01449 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
01450 const DEVMODE &dm = _fullscreen_display_mode;
01451 windisplay_cat.error()
01452 << "restore ChangeDisplaySettings failed (error code: "
01453 << chg_result << ") for specified res: "
01454 << dm.dmPelsWidth << " x " << dm.dmPelsHeight
01455 << " x " << dm.dmBitsPerPel << ", "
01456 << dm.dmDisplayFrequency << " Hz\n";
01457 }
01458
01459 GdiFlush();
01460 SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
01461 fullscreen_restored(properties);
01462 }
01463 }
01464 else
01465 {
01466 properties.set_foreground(false);
01467 if (is_fullscreen())
01468 {
01469
01470
01471 properties.set_minimized(true);
01472
01473
01474
01475
01476 ShowWindow(_hWnd, SW_MINIMIZE);
01477 GdiFlush();
01478 do_fullscreen_disable();
01479 fullscreen_minimized(properties);
01480 }
01481 }
01482
01483 adjust_z_order();
01484 system_changed_properties(properties);
01485 break;
01486
01487 case WM_SIZE:
01488 if (windisplay_cat.is_debug()) {
01489 windisplay_cat.debug()
01490 << "WM_SIZE: " << hwnd << ", " << wparam << "\n";
01491 }
01492
01493
01494 if (wparam == SIZE_MAXIMIZED) {
01495 _maximized = true;
01496 handle_reshape();
01497
01498 } else if (wparam == SIZE_RESTORED && _maximized) {
01499
01500
01501
01502
01503
01504 _maximized = false;
01505 handle_reshape();
01506 }
01507 break;
01508
01509 case WM_EXITSIZEMOVE:
01510 handle_reshape();
01511 break;
01512
01513 case WM_WINDOWPOSCHANGED:
01514 adjust_z_order();
01515 break;
01516
01517 case WM_PAINT:
01518
01519
01520
01521 if (GetUpdateRect(_hWnd, NULL, false)) {
01522 if (windisplay_cat.is_spam()) {
01523 windisplay_cat.spam()
01524 << "Got update regions: " << this << "\n";
01525 }
01526 _got_expose_event = true;
01527 }
01528 break;
01529
01530 case WM_LBUTTONDOWN:
01531 if (_lost_keypresses) {
01532 resend_lost_keypresses();
01533 }
01534 SetCapture(hwnd);
01535 _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
01536 _input_devices[0].button_down(MouseButton::button(0), get_message_time());
01537
01538
01539 set_focus();
01540 return 0;
01541
01542 case WM_MBUTTONDOWN:
01543 if (_lost_keypresses) {
01544 resend_lost_keypresses();
01545 }
01546 SetCapture(hwnd);
01547 _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
01548 _input_devices[0].button_down(MouseButton::button(1), get_message_time());
01549
01550 set_focus();
01551 return 0;
01552
01553 case WM_RBUTTONDOWN:
01554 if (_lost_keypresses) {
01555 resend_lost_keypresses();
01556 }
01557 SetCapture(hwnd);
01558 _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
01559 _input_devices[0].button_down(MouseButton::button(2), get_message_time());
01560
01561 set_focus();
01562 return 0;
01563
01564 case WM_XBUTTONDOWN:
01565 {
01566 if (_lost_keypresses) {
01567 resend_lost_keypresses();
01568 }
01569 SetCapture(hwnd);
01570 int whichButton = GET_XBUTTON_WPARAM(wparam);
01571 _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
01572 if (whichButton == XBUTTON1) {
01573 _input_devices[0].button_down(MouseButton::button(3), get_message_time());
01574 } else if (whichButton == XBUTTON2) {
01575 _input_devices[0].button_down(MouseButton::button(4), get_message_time());
01576 }
01577 }
01578 return 0;
01579
01580 case WM_LBUTTONUP:
01581 if (_lost_keypresses) {
01582 resend_lost_keypresses();
01583 }
01584 ReleaseCapture();
01585 _input_devices[0].button_up(MouseButton::button(0), get_message_time());
01586 return 0;
01587
01588 case WM_MBUTTONUP:
01589 if (_lost_keypresses) {
01590 resend_lost_keypresses();
01591 }
01592 ReleaseCapture();
01593 _input_devices[0].button_up(MouseButton::button(1), get_message_time());
01594 return 0;
01595
01596 case WM_RBUTTONUP:
01597 if (_lost_keypresses) {
01598 resend_lost_keypresses();
01599 }
01600 ReleaseCapture();
01601 _input_devices[0].button_up(MouseButton::button(2), get_message_time());
01602 return 0;
01603
01604 case WM_XBUTTONUP:
01605 {
01606 if (_lost_keypresses) {
01607 resend_lost_keypresses();
01608 }
01609 ReleaseCapture();
01610 int whichButton = GET_XBUTTON_WPARAM(wparam);
01611 if (whichButton == XBUTTON1) {
01612 _input_devices[0].button_up(MouseButton::button(3), get_message_time());
01613 } else if (whichButton == XBUTTON2) {
01614 _input_devices[0].button_up(MouseButton::button(4), get_message_time());
01615 }
01616 }
01617 return 0;
01618
01619 case WM_MOUSEWHEEL:
01620 {
01621 int delta = GET_WHEEL_DELTA_WPARAM(wparam);
01622
01623 POINT point;
01624 GetCursorPos(&point);
01625 ScreenToClient(hwnd, &point);
01626 double time = get_message_time();
01627
01628 if (delta >= 0) {
01629 while (delta > 0) {
01630 handle_keypress(MouseButton::wheel_up(), point.x, point.y, time);
01631 handle_keyrelease(MouseButton::wheel_up(), time);
01632 delta -= WHEEL_DELTA;
01633 }
01634 } else {
01635 while (delta < 0) {
01636 handle_keypress(MouseButton::wheel_down(), point.x, point.y, time);
01637 handle_keyrelease(MouseButton::wheel_down(), time);
01638 delta += WHEEL_DELTA;
01639 }
01640 }
01641 return 0;
01642 }
01643 break;
01644
01645
01646 case WM_IME_SETCONTEXT:
01647 if (!ime_hide)
01648 break;
01649
01650 windisplay_cat.debug() << "hwnd = " << hwnd << " and GetFocus = " << GetFocus() << endl;
01651 _ime_hWnd = ImmGetDefaultIMEWnd(hwnd);
01652 if (::SendMessage(_ime_hWnd, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0))
01653
01654 windisplay_cat.debug() << "SendMessage failed for " << _ime_hWnd << endl;
01655 else
01656 windisplay_cat.debug() << "SendMessage Succeeded for " << _ime_hWnd << endl;
01657
01658 windisplay_cat.debug() << "wparam is " << wparam << ", lparam is " << lparam << endl;
01659 lparam &= ~ISC_SHOWUIALL;
01660 if (ImmIsUIMessage(_ime_hWnd, msg, wparam, lparam))
01661 windisplay_cat.debug() << "wparam is " << wparam << ", lparam is " << lparam << endl;
01662
01663 break;
01664
01665
01666 case WM_IME_NOTIFY:
01667 if (wparam == IMN_SETOPENSTATUS) {
01668 HIMC hIMC = ImmGetContext(hwnd);
01669 nassertr(hIMC != 0, 0);
01670 _ime_open = (ImmGetOpenStatus(hIMC) != 0);
01671 if (!_ime_open) {
01672 _ime_active = false;
01673 }
01674 if (ime_hide) {
01675
01676 COMPOSITIONFORM comf;
01677 CANDIDATEFORM canf;
01678 ImmGetCompositionWindow(hIMC, &comf);
01679 ImmGetCandidateWindow(hIMC, 0, &canf);
01680 windisplay_cat.debug() <<
01681 "comf style " << comf.dwStyle <<
01682 " comf point: x" << comf.ptCurrentPos.x << ",y " << comf.ptCurrentPos.y <<
01683 " comf rect: l " << comf.rcArea.left << ",t " << comf.rcArea.top << ",r " <<
01684 comf.rcArea.right << ",b " << comf.rcArea.bottom << endl;
01685 windisplay_cat.debug() <<
01686 "canf style " << canf.dwStyle <<
01687 " canf point: x" << canf.ptCurrentPos.x << ",y " << canf.ptCurrentPos.y <<
01688 " canf rect: l " << canf.rcArea.left << ",t " << canf.rcArea.top << ",r " <<
01689 canf.rcArea.right << ",b " << canf.rcArea.bottom << endl;
01690 comf.dwStyle = CFS_POINT;
01691 comf.ptCurrentPos.x = 2000;
01692 comf.ptCurrentPos.y = 2000;
01693
01694 canf.dwStyle = CFS_EXCLUDE;
01695 canf.dwIndex = 0;
01696 canf.ptCurrentPos.x = 0;
01697 canf.ptCurrentPos.y = 0;
01698 canf.rcArea.left = 0;
01699 canf.rcArea.top = 0;
01700 canf.rcArea.right = 640;
01701 canf.rcArea.bottom = 480;
01702
01703 #if 0
01704 comf.rcArea.left = 200;
01705 comf.rcArea.top = 200;
01706 comf.rcArea.right = 0;
01707 comf.rcArea.bottom = 0;
01708 #endif
01709
01710 if (ImmSetCompositionWindow(hIMC, &comf))
01711 windisplay_cat.debug() << "set composition form: success\n";
01712 for (int i=0; i<3; ++i) {
01713 if (ImmSetCandidateWindow(hIMC, &canf))
01714 windisplay_cat.debug() << "set candidate form: success\n";
01715 canf.dwIndex++;
01716 }
01717 }
01718
01719 ImmReleaseContext(hwnd, hIMC);
01720 }
01721 break;
01722
01723 case WM_IME_STARTCOMPOSITION:
01724 support_overlay_window(true);
01725 _ime_active = true;
01726 break;
01727
01728 case WM_IME_ENDCOMPOSITION:
01729 support_overlay_window(false);
01730 _ime_active = false;
01731
01732 if (ime_aware) {
01733 wstring ws;
01734 _input_devices[0].candidate(ws, 0, 0, 0);
01735 }
01736
01737 break;
01738
01739 case WM_IME_COMPOSITION:
01740 if (ime_aware) {
01741
01742
01743
01744
01745
01746
01747 if (!_ime_active) {
01748 return 0;
01749 }
01750
01751 HIMC hIMC = ImmGetContext(hwnd);
01752 nassertr(hIMC != 0, 0);
01753
01754 DWORD result_size = 0;
01755 static const int ime_buffer_size = 256;
01756 static const int ime_buffer_size_bytes = ime_buffer_size / sizeof(wchar_t);
01757 wchar_t ime_buffer[ime_buffer_size];
01758 size_t cursor_pos, delta_start;
01759
01760 if (lparam & GCS_RESULTSTR) {
01761 result_size = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
01762 ime_buffer, ime_buffer_size_bytes);
01763 size_t num_chars = result_size / sizeof(wchar_t);
01764 for (size_t i = 0; i < num_chars; ++i) {
01765 _input_devices[0].keystroke(ime_buffer[i]);
01766 }
01767 }
01768
01769 if (lparam & GCS_COMPSTR) {
01770 result_size = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0);
01771 cursor_pos = result_size & 0xffff;
01772
01773 result_size = ImmGetCompositionStringW(hIMC, GCS_DELTASTART, NULL, 0);
01774 delta_start = result_size & 0xffff;
01775 result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, ime_buffer, ime_buffer_size);
01776 size_t num_chars = result_size / sizeof(wchar_t);
01777
01778 _input_devices[0].candidate(wstring(ime_buffer, num_chars),
01779 min(cursor_pos, delta_start),
01780 max(cursor_pos, delta_start),
01781 cursor_pos);
01782 }
01783 ImmReleaseContext(hwnd, hIMC);
01784 }
01785 break;
01786
01787 case WM_CHAR:
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 if (!_ime_open) {
01800 _input_devices[0].keystroke(wparam);
01801 }
01802 break;
01803
01804 case WM_SYSKEYDOWN:
01805 if (_lost_keypresses) {
01806 resend_lost_keypresses();
01807 }
01808 if (windisplay_cat.is_debug()) {
01809 windisplay_cat.debug()
01810 << "syskeydown: " << wparam << " (" << lookup_key(wparam) << ")\n";
01811 }
01812 {
01813
01814
01815
01816 POINT point;
01817 GetCursorPos(&point);
01818 ScreenToClient(hwnd, &point);
01819 handle_keypress(lookup_key(wparam), point.x, point.y,
01820 get_message_time());
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 if (wparam == VK_MENU) {
01831 if ((GetKeyState(VK_LMENU) & 0x8000) != 0 && ! _lalt_down) {
01832 handle_keypress(KeyboardButton::lalt(), point.x, point.y,
01833 get_message_time());
01834 _lalt_down = true;
01835 }
01836 if ((GetKeyState(VK_RMENU) & 0x8000) != 0 && ! _ralt_down) {
01837 handle_keypress(KeyboardButton::ralt(), point.x, point.y,
01838 get_message_time());
01839 _ralt_down = true;
01840 }
01841 }
01842 if (wparam == VK_F10) {
01843
01844
01845 return 0;
01846 }
01847 }
01848 break;
01849
01850 case WM_SYSCOMMAND:
01851 if (wparam == SC_KEYMENU) {
01852
01853
01854
01855
01856
01857
01858
01859
01860 return 0;
01861 }
01862 break;
01863
01864 case WM_KEYDOWN:
01865 if (_lost_keypresses) {
01866 resend_lost_keypresses();
01867 }
01868 if (windisplay_cat.is_debug()) {
01869 windisplay_cat.debug()
01870 << "keydown: " << wparam << " (" << lookup_key(wparam) << ")\n";
01871 }
01872
01873
01874
01875
01876 if ((lparam & 0x40000000) == 0) {
01877 POINT point;
01878 GetCursorPos(&point);
01879 ScreenToClient(hwnd, &point);
01880 handle_keypress(lookup_key(wparam), point.x, point.y,
01881 get_message_time());
01882
01883
01884
01885
01886
01887 if (wparam == VK_SHIFT) {
01888 if ((GetKeyState(VK_LSHIFT) & 0x8000) != 0 && ! _lshift_down) {
01889 handle_keypress(KeyboardButton::lshift(), point.x, point.y,
01890 get_message_time());
01891 _lshift_down = true;
01892 }
01893 if ((GetKeyState(VK_RSHIFT) & 0x8000) != 0 && ! _rshift_down) {
01894 handle_keypress(KeyboardButton::rshift(), point.x, point.y,
01895 get_message_time());
01896 _rshift_down = true;
01897 }
01898 } else if(wparam == VK_CONTROL) {
01899 if ((GetKeyState(VK_LCONTROL) & 0x8000) != 0 && ! _lcontrol_down) {
01900 handle_keypress(KeyboardButton::lcontrol(), point.x, point.y,
01901 get_message_time());
01902 _lcontrol_down = true;
01903 }
01904 if ((GetKeyState(VK_RCONTROL) & 0x8000) != 0 && ! _rcontrol_down) {
01905 handle_keypress(KeyboardButton::rcontrol(), point.x, point.y,
01906 get_message_time());
01907 _rcontrol_down = true;
01908 }
01909 }
01910
01911
01912
01913 if ((wparam=='V') && (GetKeyState(VK_CONTROL) < 0) &&
01914 !_input_devices.empty()) {
01915 HGLOBAL hglb;
01916 char *lptstr;
01917
01918 if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
01919
01920
01921 hglb = GetClipboardData(CF_TEXT);
01922 if (hglb!=NULL) {
01923 lptstr = (char *) GlobalLock(hglb);
01924 if (lptstr != NULL) {
01925 char *pChar;
01926 for (pChar=lptstr; *pChar!=NULL; pChar++) {
01927 _input_devices[0].keystroke((uchar)*pChar);
01928 }
01929 GlobalUnlock(hglb);
01930 }
01931 }
01932 CloseClipboard();
01933 }
01934 }
01935 } else {
01936
01937
01938 POINT point;
01939 GetCursorPos(&point);
01940 ScreenToClient(hwnd, &point);
01941 handle_keypress(lookup_key(wparam), point.x, point.y,
01942 get_message_time());
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 if (wparam == VK_SHIFT) {
01957 if (((GetKeyState(VK_LSHIFT) & 0x8000) != 0) && ! _lshift_down ) {
01958 handle_keypress(KeyboardButton::lshift(), point.x, point.y,
01959 get_message_time());
01960 _lshift_down = true;
01961 } else if (((GetKeyState(VK_RSHIFT) & 0x8000) != 0) && ! _rshift_down ) {
01962 handle_keypress(KeyboardButton::rshift(), point.x, point.y,
01963 get_message_time());
01964 _rshift_down = true;
01965 } else {
01966 if ((GetKeyState(VK_LSHIFT) & 0x8000) != 0) {
01967 handle_keypress(KeyboardButton::lshift(), point.x, point.y,
01968 get_message_time());
01969 }
01970 if ((GetKeyState(VK_RSHIFT) & 0x8000) != 0) {
01971 handle_keypress(KeyboardButton::rshift(), point.x, point.y,
01972 get_message_time());
01973 }
01974 }
01975 } else if(wparam == VK_CONTROL) {
01976 if (((GetKeyState(VK_LCONTROL) & 0x8000) != 0) && ! _lcontrol_down ) {
01977 handle_keypress(KeyboardButton::lcontrol(), point.x, point.y,
01978 get_message_time());
01979 _lcontrol_down = true;
01980 } else if (((GetKeyState(VK_RCONTROL) & 0x8000) != 0) && ! _rcontrol_down ) {
01981 handle_keypress(KeyboardButton::rcontrol(), point.x, point.y,
01982 get_message_time());
01983 _rcontrol_down = true;
01984 } else {
01985 if ((GetKeyState(VK_LCONTROL) & 0x8000) != 0) {
01986 handle_keypress(KeyboardButton::lcontrol(), point.x, point.y,
01987 get_message_time());
01988 }
01989 if ((GetKeyState(VK_RCONTROL) & 0x8000) != 0) {
01990 handle_keypress(KeyboardButton::rcontrol(), point.x, point.y,
01991 get_message_time());
01992 }
01993 }
01994 }
01995 }
01996 break;
01997
01998 case WM_SYSKEYUP:
01999 case WM_KEYUP:
02000 if (_lost_keypresses) {
02001 resend_lost_keypresses();
02002 }
02003 if (windisplay_cat.is_debug()) {
02004 windisplay_cat.debug()
02005 << "keyup: " << wparam << " (" << lookup_key(wparam) << ")\n";
02006 }
02007 handle_keyrelease(lookup_key(wparam), get_message_time());
02008
02009
02010
02011
02012
02013 if (wparam == VK_SHIFT) {
02014 if ((GetKeyState(VK_LSHIFT) & 0x8000) == 0 && _lshift_down) {
02015 handle_keyrelease(KeyboardButton::lshift(), get_message_time());
02016 _lshift_down = false;
02017 }
02018 if ((GetKeyState(VK_RSHIFT) & 0x8000) == 0 && _rshift_down) {
02019 handle_keyrelease(KeyboardButton::rshift(), get_message_time());
02020 _rshift_down = false;
02021 }
02022 } else if(wparam == VK_CONTROL) {
02023 if ((GetKeyState(VK_LCONTROL) & 0x8000) == 0 && _lcontrol_down) {
02024 handle_keyrelease(KeyboardButton::lcontrol(), get_message_time());
02025 _lcontrol_down = false;
02026 }
02027 if ((GetKeyState(VK_RCONTROL) & 0x8000) == 0 && _rcontrol_down) {
02028 handle_keyrelease(KeyboardButton::rcontrol(), get_message_time());
02029 _rcontrol_down = false;
02030 }
02031 } else if(wparam == VK_MENU) {
02032 if ((GetKeyState(VK_LMENU) & 0x8000) == 0 && _lalt_down) {
02033 handle_keyrelease(KeyboardButton::lalt(), get_message_time());
02034 _lalt_down = false;
02035 }
02036 if ((GetKeyState(VK_RMENU) & 0x8000) == 0 && _ralt_down) {
02037 handle_keyrelease(KeyboardButton::ralt(), get_message_time());
02038 _ralt_down = false;
02039 }
02040 }
02041 break;
02042
02043 case WM_KILLFOCUS:
02044 if (windisplay_cat.is_debug()) {
02045 windisplay_cat.debug()
02046 << "killfocus\n";
02047 }
02048
02049 _input_devices[0].focus_lost(get_message_time());
02050 properties.set_foreground(false);
02051 system_changed_properties(properties);
02052 break;
02053
02054 case WM_SETFOCUS:
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075 if (windisplay_cat.is_debug()) {
02076 windisplay_cat.debug()
02077 << "setfocus\n";
02078 }
02079
02080 if (_lost_keypresses) {
02081 resend_lost_keypresses();
02082 }
02083
02084 properties.set_foreground(true);
02085 system_changed_properties(properties);
02086 break;
02087
02088 case PM_ACTIVE:
02089 if (windisplay_cat.is_debug()) {
02090 windisplay_cat.debug()
02091 << "PM_ACTIVE\n";
02092 }
02093 properties.set_foreground(true);
02094 system_changed_properties(properties);
02095 break;
02096
02097 case PM_INACTIVE:
02098 if (windisplay_cat.is_debug()) {
02099 windisplay_cat.debug()
02100 << "PM_INACTIVE\n";
02101 }
02102 properties.set_foreground(false);
02103 system_changed_properties(properties);
02104 break;
02105
02106 #ifdef HAVE_WIN_TOUCHINPUT
02107 case WM_TOUCH:
02108 _numTouches = LOWORD(wparam);
02109 if(_numTouches > MAX_TOUCHES)
02110 _numTouches = MAX_TOUCHES;
02111 GetTouchInputInfo((HTOUCHINPUT)lparam, _numTouches, _touches, sizeof(TOUCHINPUT));
02112 CloseTouchInputHandle((HTOUCHINPUT)lparam);
02113 break;
02114 #endif
02115 }
02116
02117
02118 for ( WinProcClasses::iterator it=_window_proc_classes.begin() ; it != _window_proc_classes.end(); it++ ){
02119 (*it)->wnd_proc(this, hwnd, msg, wparam, lparam);
02120 }
02121
02122 return DefWindowProcW(hwnd, msg, wparam, lparam);
02123 }
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133 LONG WINAPI WinGraphicsWindow::
02134 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
02135
02136 WindowHandles::const_iterator wi;
02137 wi = _window_handles.find(hwnd);
02138 if (wi != _window_handles.end()) {
02139
02140 return (*wi).second->window_proc(hwnd, msg, wparam, lparam);
02141 }
02142
02143
02144 if (_creating_window != (WinGraphicsWindow *)NULL) {
02145 return _creating_window->window_proc(hwnd, msg, wparam, lparam);
02146 }
02147
02148
02149
02150 return DefWindowProcW(hwnd, msg, wparam, lparam);
02151 }
02152
02153
02154
02155
02156
02157
02158 void WinGraphicsWindow::
02159 process_1_event() {
02160 MSG msg;
02161
02162 if (!GetMessage(&msg, NULL, 0, 0)) {
02163
02164
02165 exit(msg.wParam);
02166 }
02167
02168
02169 TranslateMessage(&msg);
02170
02171 DispatchMessage(&msg);
02172 }
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 void WinGraphicsWindow::
02184 resend_lost_keypresses() {
02185 nassertv(_lost_keypresses);
02186
02187
02188
02189
02190 _lost_keypresses = false;
02191 }
02192
02193
02194
02195
02196
02197
02198
02199
02200 void WinGraphicsWindow::
02201 update_cursor_window(WinGraphicsWindow *to_window) {
02202 bool hide_cursor = false;
02203 if (to_window == (WinGraphicsWindow *)NULL) {
02204
02205
02206 if (_got_saved_params) {
02207 SystemParametersInfo(SPI_SETMOUSETRAILS, NULL,
02208 (PVOID)_saved_mouse_trails, NULL);
02209 SystemParametersInfo(SPI_SETCURSORSHADOW, NULL,
02210 (PVOID)_saved_cursor_shadow, NULL);
02211 SystemParametersInfo(SPI_SETMOUSEVANISH, NULL,
02212 (PVOID)_saved_mouse_vanish, NULL);
02213 _got_saved_params = false;
02214 }
02215
02216 } else {
02217 const WindowProperties &to_props = to_window->get_properties();
02218 hide_cursor = to_props.get_cursor_hidden();
02219
02220
02221
02222
02223
02224
02225
02226 if (!_got_saved_params) {
02227 SystemParametersInfo(SPI_GETMOUSETRAILS, NULL,
02228 &_saved_mouse_trails, NULL);
02229 SystemParametersInfo(SPI_GETCURSORSHADOW, NULL,
02230 &_saved_cursor_shadow, NULL);
02231 SystemParametersInfo(SPI_GETMOUSEVANISH, NULL,
02232 &_saved_mouse_vanish, NULL);
02233 _got_saved_params = true;
02234
02235 SystemParametersInfo(SPI_SETMOUSETRAILS, NULL, (PVOID)0, NULL);
02236 SystemParametersInfo(SPI_SETCURSORSHADOW, NULL, (PVOID)false, NULL);
02237 SystemParametersInfo(SPI_SETMOUSEVANISH, NULL, (PVOID)false, NULL);
02238 }
02239
02240 SetCursor(to_window->_cursor);
02241 }
02242
02243 hide_or_show_cursor(hide_cursor);
02244
02245 _cursor_window = to_window;
02246 }
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256 void WinGraphicsWindow::
02257 hide_or_show_cursor(bool hide_cursor) {
02258 if (hide_cursor) {
02259 if (!_cursor_hidden) {
02260 ShowCursor(false);
02261 _cursor_hidden = true;
02262 }
02263 } else {
02264 if (_cursor_hidden) {
02265 ShowCursor(true);
02266 _cursor_hidden = false;
02267 }
02268 }
02269 }
02270
02271
02272 #define MIN_REFRESH_RATE 60
02273
02274 #define ACCEPTABLE_REFRESH_RATE(RATE) ((RATE >= MIN_REFRESH_RATE) || (RATE==0) || (RATE==1))
02275
02276
02277
02278
02279
02280
02281
02282
02283 bool WinGraphicsWindow::
02284 find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp,
02285 DEVMODE &dm) {
02286 int modenum = 0;
02287
02288 while (1) {
02289 ZeroMemory(&dm, sizeof(dm));
02290 dm.dmSize = sizeof(dm);
02291
02292 if (!EnumDisplaySettings(NULL, modenum, &dm)) {
02293 break;
02294 }
02295
02296 if ((dm.dmPelsWidth == dwWidth) && (dm.dmPelsHeight == dwHeight) &&
02297 (dm.dmBitsPerPel == bpp)) {
02298 return true;
02299 }
02300 modenum++;
02301 }
02302
02303 return false;
02304 }
02305
02306
02307
02308
02309
02310
02311
02312
02313 void WinGraphicsWindow::
02314 show_error_message(DWORD message_id) {
02315 LPTSTR message_buffer;
02316
02317 if (message_id == 0) {
02318 message_id = GetLastError();
02319 }
02320
02321 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
02322 NULL, message_id,
02323 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
02324 (LPTSTR)&message_buffer,
02325 1024, NULL);
02326 MessageBox(GetDesktopWindow(), message_buffer, _T(errorbox_title), MB_OK);
02327 windisplay_cat.fatal() << "System error msg: " << message_buffer << endl;
02328 LocalFree(message_buffer);
02329 }
02330
02331
02332
02333
02334
02335
02336 void WinGraphicsWindow::
02337 handle_keypress(ButtonHandle key, int x, int y, double time) {
02338 _input_devices[0].set_pointer_in_window(x, y);
02339 if (key != ButtonHandle::none()) {
02340 _input_devices[0].button_down(key, time);
02341 }
02342 }
02343
02344
02345
02346
02347
02348
02349
02350
02351 void WinGraphicsWindow::
02352 handle_keyresume(ButtonHandle key, double time) {
02353 if (key != ButtonHandle::none()) {
02354 _input_devices[0].button_resume_down(key, time);
02355 }
02356 }
02357
02358
02359
02360
02361
02362
02363 void WinGraphicsWindow::
02364 handle_keyrelease(ButtonHandle key, double time) {
02365 if (key != ButtonHandle::none()) {
02366 _input_devices[0].button_up(key, time);
02367 }
02368 }
02369
02370
02371
02372
02373
02374
02375
02376 ButtonHandle WinGraphicsWindow::
02377 lookup_key(WPARAM wparam) const {
02378
02379
02380 if (!_ime_active) {
02381 switch(wparam) {
02382 case VK_BACK: return KeyboardButton::backspace();
02383 case VK_DELETE: return KeyboardButton::del();
02384 case VK_ESCAPE: return KeyboardButton::escape();
02385 case VK_SPACE: return KeyboardButton::space();
02386 case VK_UP: return KeyboardButton::up();
02387 case VK_DOWN: return KeyboardButton::down();
02388 case VK_LEFT: return KeyboardButton::left();
02389 case VK_RIGHT: return KeyboardButton::right();
02390 }
02391 }
02392
02393
02394
02395 switch(wparam) {
02396 case VK_TAB: return KeyboardButton::tab();
02397 case VK_PRIOR: return KeyboardButton::page_up();
02398 case VK_NEXT: return KeyboardButton::page_down();
02399 case VK_HOME: return KeyboardButton::home();
02400 case VK_END: return KeyboardButton::end();
02401 case VK_F1: return KeyboardButton::f1();
02402 case VK_F2: return KeyboardButton::f2();
02403 case VK_F3: return KeyboardButton::f3();
02404 case VK_F4: return KeyboardButton::f4();
02405 case VK_F5: return KeyboardButton::f5();
02406 case VK_F6: return KeyboardButton::f6();
02407 case VK_F7: return KeyboardButton::f7();
02408 case VK_F8: return KeyboardButton::f8();
02409 case VK_F9: return KeyboardButton::f9();
02410 case VK_F10: return KeyboardButton::f10();
02411 case VK_F11: return KeyboardButton::f11();
02412 case VK_F12: return KeyboardButton::f12();
02413 case VK_INSERT: return KeyboardButton::insert();
02414 case VK_CAPITAL: return KeyboardButton::caps_lock();
02415 case VK_NUMLOCK: return KeyboardButton::num_lock();
02416 case VK_SCROLL: return KeyboardButton::scroll_lock();
02417 case VK_PAUSE: return KeyboardButton::pause();
02418 case VK_SNAPSHOT: return KeyboardButton::print_screen();
02419
02420 case VK_SHIFT: return KeyboardButton::shift();
02421 case VK_LSHIFT: return KeyboardButton::lshift();
02422 case VK_RSHIFT: return KeyboardButton::rshift();
02423
02424 case VK_CONTROL: return KeyboardButton::control();
02425 case VK_LCONTROL: return KeyboardButton::lcontrol();
02426 case VK_RCONTROL: return KeyboardButton::rcontrol();
02427
02428 case VK_MENU: return KeyboardButton::alt();
02429 case VK_LMENU: return KeyboardButton::lalt();
02430 case VK_RMENU: return KeyboardButton::ralt();
02431
02432 default:
02433 int key = MapVirtualKey(wparam, 2);
02434 if (isascii(key) && key != 0) {
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448 return KeyboardButton::ascii_key(tolower(key));
02449 }
02450 break;
02451 }
02452 return ButtonHandle::none();
02453 }
02454
02455
02456
02457
02458
02459
02460 void WinGraphicsWindow::
02461 handle_raw_input(HRAWINPUT hraw) {
02462 LPBYTE lpb;
02463 UINT dwSize;
02464
02465 if (hraw == 0) {
02466 return;
02467 }
02468 if (pGetRawInputData(hraw, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)) == -1) {
02469 return;
02470 }
02471
02472 lpb = (LPBYTE)alloca(sizeof(LPBYTE) * dwSize);
02473 if (lpb == NULL) {
02474 return;
02475 }
02476
02477 if (pGetRawInputData(hraw, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) {
02478 return;
02479 }
02480
02481 RAWINPUT *raw = (RAWINPUT *)lpb;
02482 if (raw->header.hDevice == 0) {
02483 return;
02484 }
02485
02486 for (int i = 1; i < (int)(_input_devices.size()); ++i) {
02487 if (_input_device_handle[i] == raw->header.hDevice) {
02488 int adjx = raw->data.mouse.lLastX;
02489 int adjy = raw->data.mouse.lLastY;
02490
02491 if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
02492 _input_devices[i].set_pointer_in_window(adjx, adjy);
02493 } else {
02494 int oldx = _input_devices[i].get_raw_pointer().get_x();
02495 int oldy = _input_devices[i].get_raw_pointer().get_y();
02496 _input_devices[i].set_pointer_in_window(oldx + adjx, oldy + adjy);
02497 }
02498
02499 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) {
02500 _input_devices[i].button_down(MouseButton::button(0), get_message_time());
02501 }
02502 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) {
02503 _input_devices[i].button_up(MouseButton::button(0), get_message_time());
02504 }
02505 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) {
02506 _input_devices[i].button_down(MouseButton::button(2), get_message_time());
02507 }
02508 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) {
02509 _input_devices[i].button_up(MouseButton::button(2), get_message_time());
02510 }
02511 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) {
02512 _input_devices[i].button_down(MouseButton::button(1), get_message_time());
02513 }
02514 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) {
02515 _input_devices[i].button_up(MouseButton::button(1), get_message_time());
02516 }
02517 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) {
02518 _input_devices[i].button_down(MouseButton::button(3), get_message_time());
02519 }
02520 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) {
02521 _input_devices[i].button_up(MouseButton::button(3), get_message_time());
02522 }
02523 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) {
02524 _input_devices[i].button_down(MouseButton::button(4), get_message_time());
02525 }
02526 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) {
02527 _input_devices[i].button_up(MouseButton::button(4), get_message_time());
02528 }
02529 }
02530 }
02531 }
02532
02533
02534
02535
02536
02537
02538 bool WinGraphicsWindow::
02539 handle_mouse_motion(int x, int y) {
02540 _input_devices[0].set_pointer_in_window(x, y);
02541 return false;
02542 }
02543
02544
02545
02546
02547
02548
02549 void WinGraphicsWindow::
02550 handle_mouse_exit() {
02551
02552 _input_devices[0].set_pointer_out_of_window();
02553 }
02554
02555
02556
02557
02558
02559
02560
02561
02562 HICON WinGraphicsWindow::
02563 get_icon(const Filename &filename) {
02564
02565 IconFilenames::iterator fi = _icon_filenames.find(filename);
02566 if (fi != _icon_filenames.end()) {
02567 return (HICON)((*fi).second);
02568 }
02569
02570
02571
02572
02573
02574
02575 Filename resolved = filename;
02576 if (!resolved.resolve_filename(get_model_path())) {
02577
02578 if (resolved.is_fully_qualified() && resolved.exists()) {
02579
02580
02581 } else {
02582 windisplay_cat.warning()
02583 << "Could not find icon filename " << filename << "\n";
02584 return 0;
02585 }
02586 }
02587 fi = _icon_filenames.find(resolved);
02588 if (fi != _icon_filenames.end()) {
02589 _icon_filenames[filename] = (*fi).second;
02590 return (HICON)((*fi).second);
02591 }
02592
02593 Filename os = resolved.to_os_specific();
02594
02595 HANDLE h = LoadImage(NULL, os.c_str(),
02596 IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
02597 if (h == 0) {
02598 windisplay_cat.warning()
02599 << "windows icon filename '" << os << "' could not be loaded!!\n";
02600 }
02601
02602 _icon_filenames[filename] = h;
02603 _icon_filenames[resolved] = h;
02604 return (HICON)h;
02605 }
02606
02607
02608
02609
02610
02611
02612
02613
02614 HCURSOR WinGraphicsWindow::
02615 get_cursor(const Filename &filename) {
02616
02617 if (filename.empty()) {
02618 return 0;
02619 }
02620
02621
02622 IconFilenames::iterator fi = _cursor_filenames.find(filename);
02623 if (fi != _cursor_filenames.end()) {
02624 return (HCURSOR)((*fi).second);
02625 }
02626
02627
02628
02629
02630
02631
02632 Filename resolved = filename;
02633 if (!resolved.resolve_filename(get_model_path())) {
02634
02635 windisplay_cat.warning()
02636 << "Could not find cursor filename " << filename << "\n";
02637 return 0;
02638 }
02639 fi = _cursor_filenames.find(resolved);
02640 if (fi != _cursor_filenames.end()) {
02641 _cursor_filenames[filename] = (*fi).second;
02642 return (HCURSOR)((*fi).second);
02643 }
02644
02645 Filename os = resolved.to_os_specific();
02646
02647 HANDLE h = LoadImage(NULL, os.c_str(),
02648 IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
02649 if (h == 0) {
02650 windisplay_cat.warning()
02651 << "windows cursor filename '" << os << "' could not be loaded!!\n";
02652 show_error_message();
02653 }
02654
02655 _cursor_filenames[filename] = h;
02656 _cursor_filenames[resolved] = h;
02657 return (HCURSOR)h;
02658 }
02659
02660 static HCURSOR get_cursor(const Filename &filename);
02661
02662
02663
02664
02665
02666
02667
02668
02669 const WinGraphicsWindow::WindowClass &WinGraphicsWindow::
02670 register_window_class(const WindowProperties &props) {
02671 WindowClass wcreg(props);
02672 wostringstream wclass_name;
02673 wclass_name << L"WinGraphicsWindow" << _window_class_index;
02674 wcreg._name = wclass_name.str();
02675
02676 pair<WindowClasses::iterator, bool> found = _window_classes.insert(wcreg);
02677 const WindowClass &wclass = (*found.first);
02678
02679 if (!found.second) {
02680
02681 return wclass;
02682 }
02683
02684
02685 _window_class_index++;
02686
02687 WNDCLASSW wc;
02688
02689 HINSTANCE instance = GetModuleHandle(NULL);
02690
02691
02692 ZeroMemory(&wc, sizeof(wc));
02693 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
02694 wc.lpfnWndProc = (WNDPROC)static_window_proc;
02695 wc.hInstance = instance;
02696
02697 wc.hIcon = wclass._icon;
02698
02699 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
02700 wc.lpszMenuName = NULL;
02701 wc.lpszClassName = wclass._name.c_str();
02702
02703 if (!RegisterClassW(&wc)) {
02704 windisplay_cat.error()
02705 << "could not register window class " << wclass._name << "!" << endl;
02706 return wclass;
02707 }
02708
02709 return wclass;
02710 }
02711
02712
02713
02714
02715
02716
02717 WinGraphicsWindow::WinWindowHandle::
02718 WinWindowHandle(WinGraphicsWindow *window, const WindowHandle ©) :
02719 WindowHandle(copy),
02720 _window(window)
02721 {
02722 }
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732 void WinGraphicsWindow::WinWindowHandle::
02733 clear_window() {
02734 _window = NULL;
02735 }
02736
02737
02738
02739
02740
02741
02742
02743 void WinGraphicsWindow::WinWindowHandle::
02744 receive_windows_message(unsigned int msg, int wparam, int lparam) {
02745 if (_window != NULL) {
02746 _window->receive_windows_message(msg, wparam, lparam);
02747 }
02748 }
02749
02750
02751
02752 void PrintErrorMessage(DWORD msgID) {
02753 LPTSTR pMessageBuffer;
02754
02755 if (msgID==PRINT_LAST_ERROR)
02756 msgID=GetLastError();
02757
02758 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
02759 NULL,msgID,
02760 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
02761 (LPTSTR) &pMessageBuffer,
02762 1024, NULL);
02763 MessageBox(GetDesktopWindow(),pMessageBuffer,_T(errorbox_title),MB_OK);
02764 windisplay_cat.fatal() << "System error msg: " << pMessageBuffer << endl;
02765 LocalFree( pMessageBuffer );
02766 }
02767
02768 void
02769 ClearToBlack(HWND hWnd, const WindowProperties &props) {
02770 if (!props.has_origin()) {
02771 if (windisplay_cat.is_debug()) {
02772 windisplay_cat.debug()
02773 << "Skipping ClearToBlack, no origin specified yet.\n";
02774 }
02775 return;
02776 }
02777
02778 if (windisplay_cat.is_debug()) {
02779 windisplay_cat.debug()
02780 << "ClearToBlack(" << hWnd << ", " << props << ")\n";
02781 }
02782
02783 HDC hDC=GetDC(hWnd);
02784 RECT clrRect = {
02785 props.get_x_origin(), props.get_y_origin(),
02786 props.get_x_origin() + props.get_x_size(),
02787 props.get_y_origin() + props.get_y_size()
02788 };
02789 FillRect(hDC,&clrRect,(HBRUSH)GetStockObject(BLACK_BRUSH));
02790 ReleaseDC(hWnd,hDC);
02791 GdiFlush();
02792 }
02793
02794
02795
02796
02797
02798
02799
02800 void get_client_rect_screen(HWND hwnd, RECT *view_rect) {
02801 GetClientRect(hwnd, view_rect);
02802
02803 POINT ul, lr;
02804 ul.x = view_rect->left;
02805 ul.y = view_rect->top;
02806 lr.x = view_rect->right;
02807 lr.y = view_rect->bottom;
02808
02809 ClientToScreen(hwnd, &ul);
02810 ClientToScreen(hwnd, &lr);
02811
02812 view_rect->left = ul.x;
02813 view_rect->top = ul.y;
02814 view_rect->right = lr.x;
02815 view_rect->bottom = lr.y;
02816 }
02817
02818
02819
02820
02821
02822
02823
02824
02825 void WinGraphicsWindow::add_window_proc( const GraphicsWindowProc* wnd_proc ){
02826 nassertv(wnd_proc != NULL);
02827 _window_proc_classes.insert( (GraphicsWindowProc*)wnd_proc );
02828 }
02829
02830
02831
02832
02833
02834
02835
02836 void WinGraphicsWindow::remove_window_proc( const GraphicsWindowProc* wnd_proc ){
02837 nassertv(wnd_proc != NULL);
02838 _window_proc_classes.erase( (GraphicsWindowProc*)wnd_proc );
02839 }
02840
02841
02842
02843
02844
02845
02846
02847 void WinGraphicsWindow::clear_window_procs(){
02848 _window_proc_classes.clear();
02849 }
02850
02851
02852
02853
02854
02855
02856
02857 bool WinGraphicsWindow::supports_window_procs() const{
02858 return true;
02859 }
02860
02861
02862
02863
02864
02865
02866
02867 bool WinGraphicsWindow::
02868 is_touch_event(GraphicsWindowProcCallbackData* callbackData){
02869 #ifdef HAVE_WIN_TOUCHINPUT
02870 return callbackData->get_msg() == WM_TOUCH;
02871 #else
02872 return false;
02873 #endif
02874 }
02875
02876
02877
02878
02879
02880
02881
02882 int WinGraphicsWindow::
02883 get_num_touches(){
02884 #ifdef HAVE_WIN_TOUCHINPUT
02885 return _numTouches;
02886 #else
02887 return 0;
02888 #endif
02889 }
02890
02891
02892
02893
02894
02895
02896
02897 TouchInfo WinGraphicsWindow::
02898 get_touch_info(int index){
02899 #ifdef HAVE_WIN_TOUCHINPUT
02900 TOUCHINPUT ti = _touches[index];
02901 POINT point;
02902 point.x = TOUCH_COORD_TO_PIXEL(ti.x);
02903 point.y = TOUCH_COORD_TO_PIXEL(ti.y);
02904 ScreenToClient(_hWnd, &point);
02905
02906 TouchInfo ret = TouchInfo();
02907 ret.set_x(point.x);
02908 ret.set_y(point.y);
02909 ret.set_id(ti.dwID);
02910 ret.set_flags(ti.dwFlags);
02911 return ret;
02912 #else
02913 return TouchInfo();
02914 #endif
02915 }