29#define WM_DPICHANGED 0x02E0
33#define WM_TOUCH 0x0240
37#define WM_MOUSEHWHEEL 0x020E
42#define TOUCH_COORD_TO_PIXEL(l) ((l) / 100)
47DECLARE_HANDLE(HTOUCHINPUT);
51TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle;
53WinGraphicsWindow::WindowHandles WinGraphicsWindow::_window_handles;
57bool WinGraphicsWindow::_cursor_hidden =
false;
59RECT WinGraphicsWindow::_mouse_unconfined_cliprect;
64bool WinGraphicsWindow::_got_saved_params =
false;
65int WinGraphicsWindow::_saved_mouse_trails;
66BOOL WinGraphicsWindow::_saved_cursor_shadow;
67BOOL WinGraphicsWindow::_saved_mouse_vanish;
73int WinGraphicsWindow::_window_class_index = 0;
75static const char *
const errorbox_title =
"Panda3D Error";
79typedef BOOL (WINAPI *PFN_REGISTERTOUCHWINDOW)(IN HWND hWnd, IN ULONG ulFlags);
80typedef BOOL (WINAPI *PFN_GETTOUCHINPUTINFO)(IN HTOUCHINPUT hTouchInput, IN UINT cInputs, OUT PTOUCHINPUT pInputs, IN
int cbSize);
81typedef BOOL (WINAPI *PFN_CLOSETOUCHINPUTHANDLE)(IN HTOUCHINPUT hTouchInput);
83static PFN_REGISTERTOUCHWINDOW pRegisterTouchWindow = 0;
84static PFN_GETTOUCHINPUTINFO pGetTouchInputInfo = 0;
85static PFN_CLOSETOUCHINPUTHANDLE pCloseTouchInputHandle = 0;
92 const std::string &name,
98 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
100 initialize_input_devices();
104 _tracking_mouse_leaving =
false;
106 _lost_keypresses =
false;
107 _lshift_down =
false;
108 _rshift_down =
false;
109 _lcontrol_down =
false;
110 _rcontrol_down =
false;
121~WinGraphicsWindow() {
122 if (_window_handle !=
nullptr) {
123 DCAST(WinWindowHandle, _window_handle)->clear_window();
135 nassertr(device >= 0 && device < (
int)_input_devices.size(),
MouseData());
141 if (device == 0 && result._in_window && GetCursorPos(&cpos) && ScreenToClient(_hWnd, &cpos)) {
143 result._xpos = cpos.x;
144 result._ypos = cpos.y;
170 if (!_properties.get_foreground() )
181 SetCursorPos(view_rect.left + x, view_rect.top + y);
186 if ((device < 1)||(device >= (
int)_input_devices.size())) {
204 HIMC hIMC = ImmGetContext(_hWnd);
206 if (!ImmSetOpenStatus(hIMC,
false)) {
207 windisplay_cat.debug() <<
"ImmSetOpenStatus failed\n";
209 ImmReleaseContext(_hWnd, hIMC);
213 windisplay_cat.debug() <<
"success: closed ime window\n";
261 if (!disable_message_loop) {
264 while (PeekMessage(&msg,
nullptr, 0, 0, PM_NOREMOVE)) {
288 if (do_windowed_switch()) {
289 _properties.set_fullscreen(
false);
291 windisplay_cat.warning()
292 <<
"Switching to windowed mode failed!\n";
302 x_size = _properties.get_x_size();
303 y_size = _properties.get_y_size();
305 if (do_fullscreen_switch(x_size, y_size)) {
306 _properties.set_fullscreen(
true);
309 windisplay_cat.warning()
310 <<
"Switching to fullscreen mode failed!\n";
335 if (_parent_window_handle ==
nullptr) {
336 LPoint2i top_left = _properties.get_origin();
337 LPoint2i bottom_right = top_left + _properties.get_size();
339 DWORD window_style = make_style(_properties);
340 SetWindowLong(_hWnd, GWL_STYLE, window_style);
344 SetRect(&view_rect, top_left[0], top_left[1],
345 bottom_right[0], bottom_right[1]);
347 GetWindowInfo(_hWnd, &wi);
348 AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle);
351 SetWindowPos(_hWnd, HWND_NOTOPMOST, view_rect.left, view_rect.top,
352 view_rect.right - view_rect.left,
353 view_rect.bottom - view_rect.top,
354 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED |
355 SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
360 std::string title = properties.
get_title();
361 _properties.set_title(title);
364 SetWindowTextW(_hWnd, title_w.c_str());
371 ::SendMessage(_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon);
372 ::SendMessage(_hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon);
381 _properties.set_cursor_hidden(hide_cursor);
382 if (_cursor_window ==
this) {
383 hide_or_show_cursor(hide_cursor);
391 _properties.set_cursor_filename(filename);
393 _cursor = get_cursor(filename);
395 _cursor = LoadCursor(
nullptr, IDC_ARROW);
398 if (_cursor_window ==
this) {
406 WindowProperties::ZOrder last_z_order = _properties.get_z_order();
408 adjust_z_order(last_z_order, properties.
get_z_order());
414 if (!SetActiveWindow(_hWnd)) {
415 windisplay_cat.warning()
416 <<
"SetForegroundWindow() failed!\n";
418 _properties.set_foreground(
true);
425 if (_properties.get_minimized() != properties.
get_minimized()) {
427 ShowWindow(_hWnd, SW_MINIMIZE);
429 ShowWindow(_hWnd, SW_RESTORE);
439 if (do_fullscreen_switch()){
440 _properties.set_fullscreen(
true);
443 windisplay_cat.warning()
444 <<
"Switching to fullscreen mode failed!\n";
449 if (properties.has_mouse_mode()) {
450 if (properties.
get_mouse_mode() != _properties.get_mouse_mode()) {
452 case WindowProperties::M_absolute:
453 case WindowProperties::M_relative:
455 if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
457 windisplay_cat.info() <<
"Unconfining cursor from window\n";
459 _properties.set_mouse_mode(WindowProperties::M_absolute);
462 case WindowProperties::M_confined:
465 if (GetForegroundWindow() != _hWnd || confine_cursor()) {
466 _properties.set_mouse_mode(WindowProperties::M_confined);
480void WinGraphicsWindow::
482 GraphicsWindow::trigger_flip();
488 InvalidateRect(_hWnd,
nullptr, FALSE);
489 _got_expose_event =
false;
491 if (windisplay_cat.is_spam()) {
492 windisplay_cat.spam()
493 <<
"InvalidateRect: " <<
this <<
"\n";
501void WinGraphicsWindow::
503 set_cursor_out_of_window();
504 DestroyWindow(_hWnd);
506 if (_properties.has_mouse_mode() &&
507 _properties.get_mouse_mode() == WindowProperties::M_confined) {
513 do_fullscreen_disable();
517 _window_handles.erase(_hWnd);
520 GraphicsWindow::close_window();
527bool WinGraphicsWindow::
529 if (_properties.has_cursor_filename()) {
530 _cursor = get_cursor(_properties.get_cursor_filename());
533 _cursor = LoadCursor(
nullptr, IDC_ARROW);
535 bool want_foreground = (!_properties.has_foreground() || _properties.get_foreground());
536 bool want_minimized = (_properties.has_minimized() && _properties.get_minimized()) && !want_foreground;
538 HWND old_foreground_window = GetForegroundWindow();
543 _creating_window =
this;
544 bool opened = open_graphic_window();
545 _creating_window =
nullptr;
553 _window_handles.insert(WindowHandles::value_type(_hWnd,
this));
556 SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0,
557 SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
560 if (want_minimized) {
561 ShowWindow(_hWnd, SW_MINIMIZE);
562 ShowWindow(_hWnd, SW_MINIMIZE);
564 ShowWindow(_hWnd, SW_SHOWNORMAL);
565 ShowWindow(_hWnd, SW_SHOWNORMAL);
568 HWND new_foreground_window = _hWnd;
569 if (!want_foreground) {
572 new_foreground_window = old_foreground_window;
575 if (!SetActiveWindow(new_foreground_window)) {
576 windisplay_cat.warning()
577 <<
"SetActiveWindow() failed!\n";
583 if (!SetForegroundWindow(new_foreground_window)) {
584 windisplay_cat.warning()
585 <<
"SetForegroundWindow() failed!\n";
591 HIMC hIMC = ImmGetContext(_hWnd);
593 _ime_open = (ImmGetOpenStatus(hIMC) != 0);
594 ImmReleaseContext(_hWnd, hIMC);
598 if (_input_devices.size() > 1) {
600 Rid.usUsagePage = 0x01;
603 Rid.hwndTarget = _hWnd;
604 RegisterRawInputDevices(&Rid, 1,
sizeof (Rid));
608 _window_handle = NativeWindowHandle::make_win(_hWnd);
611 _window_handle =
new WinWindowHandle(
this, *_window_handle);
614 if (_parent_window_handle !=
nullptr) {
615 _parent_window_handle->attach_child(_window_handle);
622 static bool initialized =
false;
625 HMODULE user32 = GetModuleHandleA(
"user32.dll");
628 pRegisterTouchWindow = (PFN_REGISTERTOUCHWINDOW)GetProcAddress(user32,
"RegisterTouchWindow");
629 pGetTouchInputInfo = (PFN_GETTOUCHINPUTINFO)GetProcAddress(user32,
"GetTouchInputInfo");
630 pCloseTouchInputHandle = (PFN_CLOSETOUCHINPUTHANDLE)GetProcAddress(user32,
"CloseTouchInputHandle");
635 if (pRegisterTouchWindow !=
nullptr) {
636 pRegisterTouchWindow(_hWnd, 0);
648void WinGraphicsWindow::
649initialize_input_devices() {
651 PRAWINPUTDEVICELIST pRawInputDeviceList;
653 nassertv(_input_devices.size() == 0);
656 memset(_input_device_handle, 0,
sizeof(_input_device_handle));
658 GraphicsWindowInputDevice::pointer_and_keyboard(
this,
"keyboard_mouse");
659 add_input_device(device);
663 if ((
int)GetRawInputDeviceList(
nullptr, &nInputDevices,
sizeof(RAWINPUTDEVICELIST)) != 0) {
668 pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(
sizeof(RAWINPUTDEVICELIST) * nInputDevices);
669 if (pRawInputDeviceList ==
nullptr) {
674 if ((
int)GetRawInputDeviceList(pRawInputDeviceList, &nInputDevices,
sizeof(RAWINPUTDEVICELIST)) == -1) {
679 for (
int i = 0; i < (int)nInputDevices; i++) {
680 if (pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE) {
683 if ((
int)GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)
nullptr, &nSize) != 0) {
686 char *psName = (
char*)alloca(
sizeof(TCHAR) * nSize);
687 if (psName ==
nullptr)
continue;
688 if ((
int)GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0) {
693 if (strncmp(psName,
"\\??\\Root#RDP_MOU#0000#",22)!=0) {
694 if (_input_devices.size() < 32) {
695 if (strncmp(psName,
"\\??\\",4)==0) psName += 4;
696 char *pound1 = strchr(psName,
'#');
697 char *pound2 = pound1 ? strchr(pound1+1,
'#') : 0;
698 char *pound3 = pound2 ? strchr(pound2+1,
'#') : 0;
699 if (pound3) *pound3 = 0;
700 for (
char *p = psName; *p; p++) {
705 if (pound2) *pound2 =
'.';
706 _input_device_handle[_input_devices.size()] = pRawInputDeviceList[i].hDevice;
709 device->set_pointer_in_window(0, 0);
710 add_input_device(device);
723void WinGraphicsWindow::
733void WinGraphicsWindow::
743bool WinGraphicsWindow::
744do_reshape_request(
int x_origin,
int y_origin,
bool has_origin,
745 int x_size,
int y_size) {
746 if (windisplay_cat.is_debug()) {
747 windisplay_cat.debug()
748 <<
"Got reshape request (" << x_origin <<
", " << y_origin
749 <<
", " << has_origin <<
", " << x_size <<
", " << y_size <<
")\n";
754 if (x_origin == -2) {
755 x_origin = 0.5 * (_pipe->get_display_width() - x_size);
757 if (y_origin == -2) {
758 y_origin = 0.5 * (_pipe->get_display_height() - y_size);
760 _properties.set_origin(x_origin, y_origin);
762 if (x_origin == -1 && y_origin == -1) {
772 SetRect(&view_rect, x_origin, y_origin,
773 x_origin + x_size, y_origin + y_size);
775 GetWindowInfo(_hWnd, &wi);
776 AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle);
778 UINT flags = SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE;
781 x_origin = view_rect.left;
782 y_origin = view_rect.top;
784 x_origin = CW_USEDEFAULT;
785 y_origin = CW_USEDEFAULT;
789 SetWindowPos(_hWnd,
nullptr, x_origin, y_origin,
790 view_rect.right - view_rect.left,
791 view_rect.bottom - view_rect.top,
799 return do_fullscreen_resize(x_size, y_size);
806void WinGraphicsWindow::
809 if (!GetClientRect(_hWnd, &view_rect)) {
812 if (windisplay_cat.is_debug()) {
813 windisplay_cat.debug()
814 <<
"GetClientRect() failed in handle_reshape. Ignoring.\n";
821 if (view_rect.left == 0 && view_rect.right == 0 &&
822 view_rect.bottom == 0 && view_rect.top == 0) {
823 if (windisplay_cat.is_debug()) {
824 windisplay_cat.debug()
825 <<
"GetClientRect() returned all zeroes in handle_reshape. Ignoring.\n";
830 bool result = (FALSE != ClientToScreen(_hWnd, (POINT*)&view_rect.left));
832 result = (FALSE != ClientToScreen(_hWnd, (POINT*)&view_rect.right));
836 if (windisplay_cat.is_debug()) {
837 windisplay_cat.debug()
838 <<
"ClientToScreen() failed in handle_reshape. Ignoring.\n";
848 if (_properties.has_mouse_mode() &&
849 _properties.get_mouse_mode() == WindowProperties::M_confined &&
850 _hWnd == GetForegroundWindow()) {
853 if (GetCursorPos(&cpos) && PtInRect(&view_rect, cpos)) {
854 windisplay_cat.info()
855 <<
"ClipCursor() to " << view_rect.left <<
"," << view_rect.top
856 <<
" to " << view_rect.right <<
"," << view_rect.bottom << endl;
858 if (!ClipCursor(&view_rect)) {
859 windisplay_cat.warning()
860 <<
"Failed to re-confine cursor to window.\n";
866 properties.
set_size((view_rect.right - view_rect.left),
867 (view_rect.bottom - view_rect.top));
870 properties.
set_origin(view_rect.left, view_rect.top);
872 if (windisplay_cat.is_debug()) {
873 windisplay_cat.debug()
874 <<
"reshape to origin: (" << properties.
get_x_origin() <<
","
880 system_changed_properties(properties);
886bool WinGraphicsWindow::
887do_fullscreen_resize(
int x_size,
int y_size) {
888 HWND hDesktopWindow = GetDesktopWindow();
889 HDC scrnDC = GetDC(hDesktopWindow);
890 DWORD dwFullScreenBitDepth = GetDeviceCaps(scrnDC, BITSPIXEL);
891 ReleaseDC(hDesktopWindow, scrnDC);
899 if (!find_acceptable_display_mode(x_size, y_size,
900 dwFullScreenBitDepth, dm)) {
901 windisplay_cat.error()
902 <<
"window resize(" << x_size <<
", " << y_size
903 <<
") failed, no compatible fullscreen display mode found!\n";
908 SetWindowPos(_hWnd,
nullptr, 0,0, x_size, y_size,
909 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
910 int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
912 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
913 windisplay_cat.error()
914 <<
"resize ChangeDisplaySettings failed (error code: "
915 << chg_result <<
") for specified res: "
916 << dm.dmPelsWidth <<
" x " << dm.dmPelsHeight
917 <<
" x " << dm.dmBitsPerPel <<
", "
918 << dm.dmDisplayFrequency <<
" Hz\n";
922 _fullscreen_display_mode = dm;
924 windisplay_cat.info()
925 <<
"Resized fullscreen window to " << x_size <<
", " << y_size
926 <<
" bitdepth " << dwFullScreenBitDepth <<
", "
927 << dm.dmDisplayFrequency <<
"Hz\n";
929 _properties.set_size(x_size, y_size);
938bool WinGraphicsWindow::
939do_fullscreen_switch(
int x_size,
int y_size) {
940 if (!do_fullscreen_enable(x_size, y_size)) {
946 props.set_fullscreen(
true);
947 DWORD window_style = make_style(props);
948 SetWindowLong(_hWnd, GWL_STYLE, window_style);
950 SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, x_size, y_size,
951 SWP_FRAMECHANGED | SWP_SHOWWINDOW);
960bool WinGraphicsWindow::
961do_fullscreen_switch() {
962 return do_fullscreen_switch(_properties.get_x_size(), _properties.get_y_size());
968bool WinGraphicsWindow::
969do_windowed_switch() {
970 do_fullscreen_disable();
973 props.set_fullscreen(
false);
974 DWORD window_style = make_style(props);
975 SetWindowLong(_hWnd, GWL_STYLE, window_style);
977 WINDOW_METRICS metrics;
980 if (!calculate_metrics(
false, window_style, metrics, has_origin)){
988 SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0,
989 metrics.width, metrics.height,
990 SWP_FRAMECHANGED | SWP_SHOWWINDOW);
993 if (_properties.has_mouse_mode() &&
994 _properties.get_mouse_mode() == WindowProperties::M_confined) {
1005void WinGraphicsWindow::
1006reconsider_fullscreen_size(DWORD &, DWORD &, DWORD &) {
1015void WinGraphicsWindow::
1016support_overlay_window(
bool) {
1022DWORD WinGraphicsWindow::
1031 DWORD window_style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
1034 window_style |= WS_POPUP | WS_SYSMENU;
1036 else if (_parent_window_handle) {
1037 window_style |= WS_CHILD;
1040 window_style |= WS_POPUP;
1043 window_style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
1046 window_style |= (WS_SIZEBOX | WS_MAXIMIZEBOX);
1048 window_style |= WS_BORDER;
1052 return window_style;
1059bool WinGraphicsWindow::
1060calculate_metrics(
bool fullscreen, DWORD window_style, WINDOW_METRICS &metrics,
1064 has_origin = _properties.has_origin();
1065 if (!fullscreen && has_origin) {
1066 metrics.x = _properties.get_x_origin();
1067 metrics.y = _properties.get_y_origin();
1070 if (metrics.x == -2) {
1071 metrics.x = 0.5 * (_pipe->get_display_width() - _properties.get_x_size());
1073 if (metrics.y == -2) {
1074 metrics.y = 0.5 * (_pipe->get_display_height() - _properties.get_y_size());
1076 _properties.set_origin(metrics.x, metrics.y);
1078 if (metrics.x == -1 && metrics.y == -1) {
1085 metrics.width = _properties.get_x_size();
1086 metrics.height = _properties.get_y_size();
1090 SetRect(&win_rect, metrics.x, metrics.y,
1091 metrics.x + metrics.width, metrics.y + metrics.height);
1094 if (!AdjustWindowRect(&win_rect, window_style, FALSE)) {
1095 windisplay_cat.error()
1096 <<
"AdjustWindowRect failed!" << endl;
1101 metrics.x = win_rect.left;
1102 metrics.y = win_rect.top;
1104 metrics.x = CW_USEDEFAULT;
1105 metrics.y = CW_USEDEFAULT;
1107 metrics.width = win_rect.right - win_rect.left;
1108 metrics.height = win_rect.bottom - win_rect.top;
1117bool WinGraphicsWindow::
1118open_graphic_window() {
1119 DWORD window_style = make_style(_properties);
1122 if (_properties.has_title()) {
1124 title = encoder.
decode_text(_properties.get_title());
1127 if (!_properties.has_size()) {
1129 _properties.set_size(640, 480);
1132 WINDOW_METRICS metrics;
1134 if (!calculate_metrics(fullscreen, window_style, metrics, has_origin)){
1138 const WindowClass &wclass = register_window_class(_properties);
1139 HINSTANCE hinstance = GetModuleHandle(
nullptr);
1144 WindowHandle *window_handle = _properties.get_parent_window();
1145 if (window_handle !=
nullptr) {
1146 windisplay_cat.info()
1147 <<
"Got parent_window " << *window_handle <<
"\n";
1149 if (os_handle !=
nullptr) {
1150 windisplay_cat.info()
1151 <<
"os_handle type " << os_handle->get_type() <<
"\n";
1153 if (os_handle->
is_of_type(NativeWindowHandle::WinHandle::get_class_type())) {
1154 NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle);
1155 _hparent = win_handle->get_handle();
1156 }
else if (os_handle->
is_of_type(NativeWindowHandle::IntHandle::get_class_type())) {
1158 _hparent = (HWND)int_handle->get_handle();
1162 _parent_window_handle = window_handle;
1164 _parent_window_handle =
nullptr;
1168 _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(), window_style,
1169 metrics.x, metrics.y,
1172 nullptr,
nullptr, hinstance, 0);
1177 if (!fullscreen && has_origin) {
1178 x_origin = _properties.get_x_origin();
1179 y_origin = _properties.get_y_origin();
1182 _hWnd = CreateWindowW(wclass._name.c_str(), title.c_str(),
1183 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,
1185 _properties.get_x_size(), _properties.get_y_size(),
1186 _hparent,
nullptr, hinstance, 0);
1199 system_changed_properties(properties);
1204 windisplay_cat.error()
1205 <<
"CreateWindow() failed!" << endl;
1206 show_error_message();
1215 if (!do_fullscreen_enable()) {
1227bool WinGraphicsWindow::
1228do_fullscreen_enable(
int x_size,
int y_size) {
1230 HWND hDesktopWindow = GetDesktopWindow();
1231 HDC scrnDC = GetDC(hDesktopWindow);
1232 DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL);
1236 ReleaseDC(hDesktopWindow, scrnDC);
1238 DWORD dwWidth = x_size;
1239 DWORD dwHeight = y_size;
1240 DWORD dwFullScreenBitDepth = cur_bitdepth;
1243 reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth);
1244 if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth, dm)) {
1245 windisplay_cat.error()
1246 <<
"Videocard has no supported display resolutions at specified res ("
1247 << dwWidth <<
" x " << dwHeight <<
" x " << dwFullScreenBitDepth <<
")\n";
1251 dm.dmPelsWidth = dwWidth;
1252 dm.dmPelsHeight = dwHeight;
1253 dm.dmBitsPerPel = dwFullScreenBitDepth;
1254 int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
1256 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
1257 windisplay_cat.error()
1258 <<
"ChangeDisplaySettings failed (error code: "
1259 << chg_result <<
") for specified res: "
1260 << dm.dmPelsWidth <<
" x " << dm.dmPelsHeight
1261 <<
" x " << dm.dmBitsPerPel <<
", "
1262 << dm.dmDisplayFrequency <<
" Hz\n";
1266 _fullscreen_display_mode = dm;
1274bool WinGraphicsWindow::
1275do_fullscreen_enable() {
1276 return do_fullscreen_enable(_properties.get_x_size(), _properties.get_y_size());
1283bool WinGraphicsWindow::
1284do_fullscreen_disable() {
1285 int chg_result = ChangeDisplaySettings(
nullptr, 0x0);
1286 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
1287 windisplay_cat.warning()
1288 <<
"ChangeDisplaySettings failed to restore Windowed mode\n";
1297void WinGraphicsWindow::
1299 WindowProperties::ZOrder z_order = _properties.get_z_order();
1300 adjust_z_order(z_order, z_order);
1306void WinGraphicsWindow::
1307adjust_z_order(WindowProperties::ZOrder last_z_order,
1308 WindowProperties::ZOrder this_z_order) {
1310 bool do_change =
false;
1312 switch (this_z_order) {
1313 case WindowProperties::Z_bottom:
1314 order = HWND_BOTTOM;
1318 case WindowProperties::Z_normal:
1319 if ((last_z_order != WindowProperties::Z_normal) &&
1321 (last_z_order != WindowProperties::Z_bottom ||
1322 _properties.get_foreground())
1327 order = HWND_NOTOPMOST;
1332 case WindowProperties::Z_top:
1333 order = HWND_TOPMOST;
1338 BOOL result = SetWindowPos(_hWnd, order, 0,0,0,0,
1339 SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
1341 windisplay_cat.warning()
1342 <<
"SetWindowPos failed.\n";
1352void WinGraphicsWindow::
1353track_mouse_leaving(HWND hwnd) {
1355 DCAST_INTO_V(winpipe, _pipe);
1357 TRACKMOUSEEVENT tme = {
1358 sizeof(TRACKMOUSEEVENT),
1365 BOOL bSucceeded = TrackMouseEvent(&tme);
1367 if (!bSucceeded && windisplay_cat.is_debug()) {
1368 windisplay_cat.debug()
1369 <<
"TrackMouseEvent failed!, LastError=" << GetLastError() << endl;
1372 _tracking_mouse_leaving =
true;
1378bool WinGraphicsWindow::
1383 windisplay_cat.info()
1384 <<
"ClipCursor() to " << clip.left <<
"," << clip.top <<
" to "
1385 << clip.right <<
"," << clip.bottom << endl;
1387 if (!ClipCursor(&clip)) {
1388 windisplay_cat.warning()
1389 <<
"Failed to confine cursor to window.\n";
1400void WinGraphicsWindow::
1402 if (SetFocus(_hWnd) ==
nullptr && GetLastError() != 0) {
1408 if (_parent_window_handle !=
nullptr && _window_handle !=
nullptr) {
1409 _parent_window_handle->request_keyboard_focus(_window_handle);
1412 windisplay_cat.error()
1413 <<
"SetFocus failed: " << GetLastError() <<
"\n";
1439window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
1440 if (windisplay_cat.is_spam()) {
1441 windisplay_cat.spam()
1443 <<
" window_proc(" << (
void *)
this <<
", " << hwnd <<
", "
1444 << msg <<
", " << wparam <<
", " << lparam <<
")\n";
1450 if (!_tracking_mouse_leaving) {
1452 track_mouse_leaving(hwnd);
1454 set_cursor_in_window();
1455 if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))))
1460 handle_raw_input((HRAWINPUT)lparam);
1464 _tracking_mouse_leaving =
false;
1465 handle_mouse_exit();
1466 set_cursor_out_of_window();
1471 track_mouse_leaving(hwnd);
1472 ClearToBlack(hwnd, _properties);
1475 GetCursorPos(&cpos);
1476 ScreenToClient(hwnd, &cpos);
1478 GetClientRect(hwnd, &clientRect);
1479 if (PtInRect(&clientRect,cpos)) {
1480 set_cursor_in_window();
1482 set_cursor_out_of_window();
1515 if (!close_request_event.empty()) {
1518 throw_event(close_request_event);
1526 system_changed_properties(properties);
1533 case WM_CHILDACTIVATE:
1534 if (windisplay_cat.is_debug()) {
1535 windisplay_cat.debug()
1536 <<
"WM_CHILDACTIVATE: " << hwnd <<
"\n";
1541 if (windisplay_cat.is_debug()) {
1542 windisplay_cat.debug()
1543 <<
"WM_ACTIVATE: " << hwnd <<
", " << wparam <<
", " << lparam <<
"\n";
1546 if ((wparam & 0xffff) != WA_INACTIVE)
1554 ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN);
1555 if (chg_result != DISP_CHANGE_SUCCESSFUL) {
1556 const DEVMODE &dm = _fullscreen_display_mode;
1557 windisplay_cat.error()
1558 <<
"restore ChangeDisplaySettings failed (error code: "
1559 << chg_result <<
") for specified res: "
1560 << dm.dmPelsWidth <<
" x " << dm.dmPelsHeight
1561 <<
" x " << dm.dmBitsPerPel <<
", "
1562 << dm.dmDisplayFrequency <<
" Hz\n";
1566 SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
1567 fullscreen_restored(properties);
1571 if (_properties.has_mouse_mode() &&
1572 _properties.get_mouse_mode() == WindowProperties::M_confined) {
1573 if (!confine_cursor()) {
1590 ShowWindow(_hWnd, SW_MINIMIZE);
1592 do_fullscreen_disable();
1593 fullscreen_minimized(properties);
1598 system_changed_properties(properties);
1604 if (windisplay_cat.is_debug()) {
1605 windisplay_cat.debug()
1606 <<
"WM_SIZE: " << hwnd <<
", " << wparam <<
"\n";
1610 case WM_EXITSIZEMOVE:
1611 if (windisplay_cat.is_debug()) {
1612 windisplay_cat.debug()
1613 <<
"WM_EXITSIZEMOVE: " << hwnd <<
", " << wparam <<
"\n";
1617 if (_properties.has_mouse_mode() &&
1618 _properties.get_mouse_mode() == WindowProperties::M_confined) {
1623 case WM_WINDOWPOSCHANGED:
1624 if (windisplay_cat.is_debug()) {
1625 windisplay_cat.debug()
1626 <<
"WM_WINDOWPOSCHANGED: " << hwnd <<
", " << wparam <<
"\n";
1628 if (_hWnd !=
nullptr) {
1638 if (GetUpdateRect(_hWnd,
nullptr,
false)) {
1639 if (windisplay_cat.is_spam()) {
1640 windisplay_cat.spam()
1641 <<
"Got update regions: " <<
this <<
"\n";
1643 _got_expose_event =
true;
1647 case WM_LBUTTONDOWN:
1648 if (_lost_keypresses) {
1649 resend_lost_keypresses();
1659 case WM_MBUTTONDOWN:
1660 if (_lost_keypresses) {
1661 resend_lost_keypresses();
1670 case WM_RBUTTONDOWN:
1671 if (_lost_keypresses) {
1672 resend_lost_keypresses();
1681 case WM_XBUTTONDOWN:
1683 if (_lost_keypresses) {
1684 resend_lost_keypresses();
1687 int whichButton = GET_XBUTTON_WPARAM(wparam);
1689 if (whichButton == XBUTTON1) {
1691 }
else if (whichButton == XBUTTON2) {
1698 if (_lost_keypresses) {
1699 resend_lost_keypresses();
1708 if (_lost_keypresses) {
1709 resend_lost_keypresses();
1718 if (_lost_keypresses) {
1719 resend_lost_keypresses();
1729 if (_lost_keypresses) {
1730 resend_lost_keypresses();
1735 int whichButton = GET_XBUTTON_WPARAM(wparam);
1736 if (whichButton == XBUTTON1) {
1738 }
else if (whichButton == XBUTTON2) {
1746 int delta = GET_WHEEL_DELTA_WPARAM(wparam);
1749 GetCursorPos(&point);
1750 ScreenToClient(hwnd, &point);
1751 double time = get_message_time();
1757 delta -= WHEEL_DELTA;
1763 delta += WHEEL_DELTA;
1770 case WM_MOUSEHWHEEL:
1772 int delta = GET_WHEEL_DELTA_WPARAM(wparam);
1775 GetCursorPos(&point);
1776 ScreenToClient(hwnd, &point);
1777 double time = get_message_time();
1783 delta -= WHEEL_DELTA;
1789 delta += WHEEL_DELTA;
1796 case WM_IME_SETCONTEXT:
1800 windisplay_cat.debug() <<
"hwnd = " << hwnd <<
" and GetFocus = " << GetFocus() << endl;
1801 _ime_hWnd = ImmGetDefaultIMEWnd(hwnd);
1802 if (::SendMessage(_ime_hWnd, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0))
1804 windisplay_cat.debug() <<
"SendMessage failed for " << _ime_hWnd << endl;
1806 windisplay_cat.debug() <<
"SendMessage Succeeded for " << _ime_hWnd << endl;
1808 windisplay_cat.debug() <<
"wparam is " << wparam <<
", lparam is " << lparam << endl;
1809 lparam &= ~ISC_SHOWUIALL;
1810 if (ImmIsUIMessage(_ime_hWnd, msg, wparam, lparam))
1811 windisplay_cat.debug() <<
"wparam is " << wparam <<
", lparam is " << lparam << endl;
1817 if (wparam == IMN_SETOPENSTATUS) {
1818 HIMC hIMC = ImmGetContext(hwnd);
1819 nassertr(hIMC != 0, 0);
1820 _ime_open = (ImmGetOpenStatus(hIMC) != 0);
1822 _ime_active =
false;
1826 COMPOSITIONFORM comf;
1828 ImmGetCompositionWindow(hIMC, &comf);
1829 ImmGetCandidateWindow(hIMC, 0, &canf);
1830 windisplay_cat.debug() <<
1831 "comf style " << comf.dwStyle <<
1832 " comf point: x" << comf.ptCurrentPos.x <<
",y " << comf.ptCurrentPos.y <<
1833 " comf rect: l " << comf.rcArea.left <<
",t " << comf.rcArea.top <<
",r " <<
1834 comf.rcArea.right <<
",b " << comf.rcArea.bottom << endl;
1835 windisplay_cat.debug() <<
1836 "canf style " << canf.dwStyle <<
1837 " canf point: x" << canf.ptCurrentPos.x <<
",y " << canf.ptCurrentPos.y <<
1838 " canf rect: l " << canf.rcArea.left <<
",t " << canf.rcArea.top <<
",r " <<
1839 canf.rcArea.right <<
",b " << canf.rcArea.bottom << endl;
1840 comf.dwStyle = CFS_POINT;
1841 comf.ptCurrentPos.x = 2000;
1842 comf.ptCurrentPos.y = 2000;
1844 canf.dwStyle = CFS_EXCLUDE;
1846 canf.ptCurrentPos.x = 0;
1847 canf.ptCurrentPos.y = 0;
1848 canf.rcArea.left = 0;
1849 canf.rcArea.top = 0;
1850 canf.rcArea.right = 640;
1851 canf.rcArea.bottom = 480;
1854 comf.rcArea.left = 200;
1855 comf.rcArea.top = 200;
1856 comf.rcArea.right = 0;
1857 comf.rcArea.bottom = 0;
1860 if (ImmSetCompositionWindow(hIMC, &comf))
1861 windisplay_cat.debug() <<
"set composition form: success\n";
1862 for (
int i=0; i<3; ++i) {
1863 if (ImmSetCandidateWindow(hIMC, &canf))
1864 windisplay_cat.debug() <<
"set candidate form: success\n";
1869 ImmReleaseContext(hwnd, hIMC);
1873 case WM_IME_STARTCOMPOSITION:
1874 support_overlay_window(
true);
1878 case WM_IME_ENDCOMPOSITION:
1879 support_overlay_window(
false);
1880 _ime_active =
false;
1889 case WM_IME_COMPOSITION:
1901 HIMC hIMC = ImmGetContext(hwnd);
1902 nassertr(hIMC != 0, 0);
1904 DWORD result_size = 0;
1905 static const int ime_buffer_size = 256;
1906 static const int ime_buffer_size_bytes = ime_buffer_size /
sizeof(wchar_t);
1907 wchar_t ime_buffer[ime_buffer_size];
1908 size_t cursor_pos, delta_start;
1910 if (lparam & GCS_RESULTSTR) {
1911 result_size = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
1912 ime_buffer, ime_buffer_size_bytes);
1913 size_t num_chars = result_size /
sizeof(wchar_t);
1914 for (
size_t i = 0; i < num_chars; ++i) {
1919 if (lparam & GCS_COMPSTR) {
1920 result_size = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS,
nullptr, 0);
1921 cursor_pos = result_size & 0xffff;
1923 result_size = ImmGetCompositionStringW(hIMC, GCS_DELTASTART,
nullptr, 0);
1924 delta_start = result_size & 0xffff;
1925 result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, ime_buffer, ime_buffer_size);
1926 size_t num_chars = result_size /
sizeof(wchar_t);
1928 _input->
candidate(wstring(ime_buffer, num_chars),
1929 std::min(cursor_pos, delta_start),
1930 std::max(cursor_pos, delta_start),
1933 ImmReleaseContext(hwnd, hIMC);
1954 if (_lost_keypresses) {
1955 resend_lost_keypresses();
1957 if (windisplay_cat.is_debug()) {
1958 windisplay_cat.debug()
1959 <<
"syskeydown: " << wparam <<
" (" << lookup_key(wparam) <<
")\n";
1965 GetCursorPos(&point);
1966 ScreenToClient(hwnd, &point);
1967 handle_keypress(lookup_key(wparam), point.x, point.y,
1968 get_message_time());
1970 if ((lparam & 0x40000000) == 0) {
1971 handle_raw_keypress(lookup_raw_key(lparam), get_message_time());
1982 if (wparam == VK_MENU) {
1983 if ((GetKeyState(VK_LMENU) & 0x8000) != 0 && ! _lalt_down) {
1984 handle_keypress(KeyboardButton::lalt(), point.x, point.y,
1985 get_message_time());
1988 if ((GetKeyState(VK_RMENU) & 0x8000) != 0 && ! _ralt_down) {
1989 handle_keypress(KeyboardButton::ralt(), point.x, point.y,
1990 get_message_time());
1994 if (wparam == VK_F10) {
2003 if (wparam == SC_KEYMENU) {
2015 if (_lost_keypresses) {
2016 resend_lost_keypresses();
2018 if (windisplay_cat.is_debug()) {
2019 windisplay_cat.debug()
2020 <<
"keydown: " << wparam <<
" (" << lookup_key(wparam) <<
")\n";
2025 if ((lparam & 0x40000000) == 0) {
2027 GetCursorPos(&point);
2028 ScreenToClient(hwnd, &point);
2029 handle_keypress(lookup_key(wparam), point.x, point.y,
2030 get_message_time());
2031 handle_raw_keypress(lookup_raw_key(lparam), get_message_time());
2037 if (wparam == VK_SHIFT) {
2038 if ((GetKeyState(VK_LSHIFT) & 0x8000) != 0 && ! _lshift_down) {
2039 handle_keypress(KeyboardButton::lshift(), point.x, point.y,
2040 get_message_time());
2041 _lshift_down =
true;
2043 if ((GetKeyState(VK_RSHIFT) & 0x8000) != 0 && ! _rshift_down) {
2044 handle_keypress(KeyboardButton::rshift(), point.x, point.y,
2045 get_message_time());
2046 _rshift_down =
true;
2048 }
else if(wparam == VK_CONTROL) {
2049 if ((GetKeyState(VK_LCONTROL) & 0x8000) != 0 && ! _lcontrol_down) {
2050 handle_keypress(KeyboardButton::lcontrol(), point.x, point.y,
2051 get_message_time());
2052 _lcontrol_down =
true;
2054 if ((GetKeyState(VK_RCONTROL) & 0x8000) != 0 && ! _rcontrol_down) {
2055 handle_keypress(KeyboardButton::rcontrol(), point.x, point.y,
2056 get_message_time());
2057 _rcontrol_down =
true;
2063 if ((wparam==
'V') && (GetKeyState(VK_CONTROL) < 0) &&
2064 !_input_devices.empty() && paste_emit_keystrokes) {
2068 if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(
nullptr)) {
2070 hglb = GetClipboardData(CF_TEXT);
2071 if (hglb!=
nullptr) {
2072 lptstr = (
char *) GlobalLock(hglb);
2073 if (lptstr !=
nullptr) {
2075 for (pChar = lptstr; *pChar; pChar++) {
2088 GetCursorPos(&point);
2089 ScreenToClient(hwnd, &point);
2090 handle_keypress(lookup_key(wparam), point.x, point.y,
2091 get_message_time());
2104 if (wparam == VK_SHIFT) {
2105 if (((GetKeyState(VK_LSHIFT) & 0x8000) != 0) && ! _lshift_down ) {
2106 handle_keypress(KeyboardButton::lshift(), point.x, point.y,
2107 get_message_time());
2108 _lshift_down =
true;
2109 }
else if (((GetKeyState(VK_RSHIFT) & 0x8000) != 0) && ! _rshift_down ) {
2110 handle_keypress(KeyboardButton::rshift(), point.x, point.y,
2111 get_message_time());
2112 _rshift_down =
true;
2114 if ((GetKeyState(VK_LSHIFT) & 0x8000) != 0) {
2115 handle_keypress(KeyboardButton::lshift(), point.x, point.y,
2116 get_message_time());
2118 if ((GetKeyState(VK_RSHIFT) & 0x8000) != 0) {
2119 handle_keypress(KeyboardButton::rshift(), point.x, point.y,
2120 get_message_time());
2123 }
else if(wparam == VK_CONTROL) {
2124 if (((GetKeyState(VK_LCONTROL) & 0x8000) != 0) && ! _lcontrol_down ) {
2125 handle_keypress(KeyboardButton::lcontrol(), point.x, point.y,
2126 get_message_time());
2127 _lcontrol_down =
true;
2128 }
else if (((GetKeyState(VK_RCONTROL) & 0x8000) != 0) && ! _rcontrol_down ) {
2129 handle_keypress(KeyboardButton::rcontrol(), point.x, point.y,
2130 get_message_time());
2131 _rcontrol_down =
true;
2133 if ((GetKeyState(VK_LCONTROL) & 0x8000) != 0) {
2134 handle_keypress(KeyboardButton::lcontrol(), point.x, point.y,
2135 get_message_time());
2137 if ((GetKeyState(VK_RCONTROL) & 0x8000) != 0) {
2138 handle_keypress(KeyboardButton::rcontrol(), point.x, point.y,
2139 get_message_time());
2148 if (_lost_keypresses) {
2149 resend_lost_keypresses();
2151 if (windisplay_cat.is_debug()) {
2152 windisplay_cat.debug()
2153 <<
"keyup: " << wparam <<
" (" << lookup_key(wparam) <<
")\n";
2155 handle_keyrelease(lookup_key(wparam), get_message_time());
2156 handle_raw_keyrelease(lookup_raw_key(lparam), get_message_time());
2161 if (wparam == VK_SHIFT) {
2162 if ((GetKeyState(VK_LSHIFT) & 0x8000) == 0 && _lshift_down) {
2163 handle_keyrelease(KeyboardButton::lshift(), get_message_time());
2164 _lshift_down =
false;
2166 if ((GetKeyState(VK_RSHIFT) & 0x8000) == 0 && _rshift_down) {
2167 handle_keyrelease(KeyboardButton::rshift(), get_message_time());
2168 _rshift_down =
false;
2170 }
else if(wparam == VK_CONTROL) {
2171 if ((GetKeyState(VK_LCONTROL) & 0x8000) == 0 && _lcontrol_down) {
2172 handle_keyrelease(KeyboardButton::lcontrol(), get_message_time());
2173 _lcontrol_down =
false;
2175 if ((GetKeyState(VK_RCONTROL) & 0x8000) == 0 && _rcontrol_down) {
2176 handle_keyrelease(KeyboardButton::rcontrol(), get_message_time());
2177 _rcontrol_down =
false;
2179 }
else if(wparam == VK_MENU) {
2180 if ((GetKeyState(VK_LMENU) & 0x8000) == 0 && _lalt_down) {
2181 handle_keyrelease(KeyboardButton::lalt(), get_message_time());
2184 if ((GetKeyState(VK_RMENU) & 0x8000) == 0 && _ralt_down) {
2185 handle_keyrelease(KeyboardButton::ralt(), get_message_time());
2192 if (windisplay_cat.is_debug()) {
2193 windisplay_cat.debug()
2199 system_changed_properties(properties);
2221 if (windisplay_cat.is_debug()) {
2222 windisplay_cat.debug()
2226 if (_lost_keypresses) {
2227 resend_lost_keypresses();
2231 system_changed_properties(properties);
2235 if (windisplay_cat.is_debug()) {
2236 windisplay_cat.debug()
2240 system_changed_properties(properties);
2244 if (windisplay_cat.is_debug()) {
2245 windisplay_cat.debug()
2249 system_changed_properties(properties);
2255 if (windisplay_cat.is_debug()) {
2256 windisplay_cat.debug() <<
"DPI changed to " << LOWORD(wparam);
2258 if (LOWORD(wparam) != HIWORD(wparam)) {
2259 windisplay_cat.debug(
false) <<
"x" << HIWORD(wparam) <<
"\n";
2261 windisplay_cat.debug(
false) <<
"\n";
2266 if (!_properties.get_fixed_size() && dpi_window_resize) {
2267 RECT &rect = *(LPRECT)lparam;
2268 SetWindowPos(_hWnd, HWND_TOP, rect.left, rect.top,
2269 rect.right - rect.left, rect.bottom - rect.top,
2270 SWP_NOZORDER | SWP_NOACTIVATE);
2275 _num_touches = LOWORD(wparam);
2276 if (_num_touches > MAX_TOUCHES) {
2277 _num_touches = MAX_TOUCHES;
2279 if (pGetTouchInputInfo != 0) {
2280 pGetTouchInputInfo((HTOUCHINPUT)lparam, _num_touches, _touches,
sizeof(TOUCHINPUT));
2281 pCloseTouchInputHandle((HTOUCHINPUT)lparam);
2287 for ( WinProcClasses::iterator it=_window_proc_classes.begin() ; it != _window_proc_classes.end(); it++ ){
2288 (*it)->wnd_proc(
this, hwnd, msg, wparam, lparam);
2291 return DefWindowProcW(hwnd, msg, wparam, lparam);
2302 WindowHandles::const_iterator wi;
2303 wi = _window_handles.find(hwnd);
2304 if (wi != _window_handles.end()) {
2306 return (*wi).second->window_proc(hwnd, msg, wparam, lparam);
2310 if (_creating_window !=
nullptr) {
2311 return _creating_window->
window_proc(hwnd, msg, wparam, lparam);
2316 return DefWindowProcW(hwnd, msg, wparam, lparam);
2322void WinGraphicsWindow::
2326 if (!GetMessage(&msg,
nullptr, 0, 0)) {
2333 TranslateMessage(&msg);
2335 DispatchMessage(&msg);
2343void WinGraphicsWindow::
2344resend_lost_keypresses() {
2345 nassertv(_lost_keypresses);
2350 _lost_keypresses =
false;
2357void WinGraphicsWindow::
2359 bool hide_cursor =
false;
2360 if (to_window ==
nullptr) {
2363 if (_got_saved_params) {
2364 SystemParametersInfo(SPI_SETMOUSETRAILS, _saved_mouse_trails,
2366 SystemParametersInfo(SPI_SETCURSORSHADOW, 0,
2367 _saved_cursor_shadow ? (PVOID)1 : nullptr, 0);
2368 SystemParametersInfo(SPI_SETMOUSEVANISH, 0,
2369 _saved_mouse_vanish ? (PVOID)1 : nullptr, 0);
2370 _got_saved_params =
false;
2382 if (!_got_saved_params) {
2383 SystemParametersInfo(SPI_GETMOUSETRAILS, 0,
2384 &_saved_mouse_trails, 0);
2385 SystemParametersInfo(SPI_GETCURSORSHADOW, 0,
2386 &_saved_cursor_shadow, 0);
2387 SystemParametersInfo(SPI_GETMOUSEVANISH, 0,
2388 &_saved_mouse_vanish, 0);
2389 _got_saved_params =
true;
2391 SystemParametersInfo(SPI_SETMOUSETRAILS, 0, (PVOID)0, 0);
2392 SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)
false, 0);
2393 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, (PVOID)
false, 0);
2396 SetCursor(to_window->_cursor);
2399 hide_or_show_cursor(hide_cursor);
2401 _cursor_window = to_window;
2409void WinGraphicsWindow::
2410hide_or_show_cursor(
bool hide_cursor) {
2412 if (!_cursor_hidden) {
2414 _cursor_hidden =
true;
2417 if (_cursor_hidden) {
2419 _cursor_hidden =
false;
2425#define MIN_REFRESH_RATE 60
2428#define ACCEPTABLE_REFRESH_RATE(RATE) ((RATE >= MIN_REFRESH_RATE) || (RATE==0) || (RATE==1))
2434bool WinGraphicsWindow::
2435find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp,
2440 ZeroMemory(&cur_dm,
sizeof(cur_dm));
2441 cur_dm.dmSize =
sizeof(cur_dm);
2442 EnumDisplaySettings(
nullptr, ENUM_CURRENT_SETTINGS, &cur_dm);
2445 int saved_modenum = -1;
2448 ZeroMemory(&dm,
sizeof(dm));
2449 dm.dmSize =
sizeof(dm);
2451 if (!EnumDisplaySettings(
nullptr, modenum, &dm)) {
2455 if ((dm.dmPelsWidth == dwWidth) && (dm.dmPelsHeight == dwHeight) &&
2456 (dm.dmBitsPerPel == bpp)) {
2459 if (dm.dmDisplayFrequency == cur_dm.dmDisplayFrequency) {
2461 }
else if (saved_modenum == -1) {
2462 saved_modenum = modenum;
2470 if (saved_modenum != -1) {
2471 ZeroMemory(&dm,
sizeof(dm));
2472 dm.dmSize =
sizeof(dm);
2474 if (EnumDisplaySettings(
nullptr, saved_modenum, &dm)) {
2486void WinGraphicsWindow::
2487show_error_message(DWORD message_id) {
2488 LPTSTR message_buffer;
2490 if (message_id == 0) {
2491 message_id = GetLastError();
2494 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
2495 nullptr, message_id,
2496 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2497 (LPTSTR)&message_buffer,
2499 MessageBox(GetDesktopWindow(), message_buffer, _T(errorbox_title), MB_OK);
2500 windisplay_cat.fatal() <<
"System error msg: " << message_buffer << endl;
2501 LocalFree(message_buffer);
2507void WinGraphicsWindow::
2508handle_keypress(
ButtonHandle key,
int x,
int y,
double time) {
2510 if (key != ButtonHandle::none()) {
2519void WinGraphicsWindow::
2521 if (key != ButtonHandle::none()) {
2529void WinGraphicsWindow::
2531 if (key != ButtonHandle::none()) {
2539void WinGraphicsWindow::
2541 if (key != ButtonHandle::none()) {
2549void WinGraphicsWindow::
2551 if (key != ButtonHandle::none()) {
2561lookup_key(WPARAM wparam)
const {
2566 case VK_BACK:
return KeyboardButton::backspace();
2567 case VK_DELETE:
return KeyboardButton::del();
2568 case VK_ESCAPE:
return KeyboardButton::escape();
2569 case VK_SPACE:
return KeyboardButton::space();
2570 case VK_UP:
return KeyboardButton::up();
2571 case VK_DOWN:
return KeyboardButton::down();
2572 case VK_LEFT:
return KeyboardButton::left();
2573 case VK_RIGHT:
return KeyboardButton::right();
2580 case VK_TAB:
return KeyboardButton::tab();
2581 case VK_PRIOR:
return KeyboardButton::page_up();
2582 case VK_NEXT:
return KeyboardButton::page_down();
2583 case VK_HOME:
return KeyboardButton::home();
2584 case VK_END:
return KeyboardButton::end();
2585 case VK_F1:
return KeyboardButton::f1();
2586 case VK_F2:
return KeyboardButton::f2();
2587 case VK_F3:
return KeyboardButton::f3();
2588 case VK_F4:
return KeyboardButton::f4();
2589 case VK_F5:
return KeyboardButton::f5();
2590 case VK_F6:
return KeyboardButton::f6();
2591 case VK_F7:
return KeyboardButton::f7();
2592 case VK_F8:
return KeyboardButton::f8();
2593 case VK_F9:
return KeyboardButton::f9();
2594 case VK_F10:
return KeyboardButton::f10();
2595 case VK_F11:
return KeyboardButton::f11();
2596 case VK_F12:
return KeyboardButton::f12();
2597 case VK_INSERT:
return KeyboardButton::insert();
2598 case VK_CAPITAL:
return KeyboardButton::caps_lock();
2599 case VK_NUMLOCK:
return KeyboardButton::num_lock();
2600 case VK_SCROLL:
return KeyboardButton::scroll_lock();
2601 case VK_PAUSE:
return KeyboardButton::pause();
2602 case VK_SNAPSHOT:
return KeyboardButton::print_screen();
2604 case VK_SHIFT:
return KeyboardButton::shift();
2605 case VK_LSHIFT:
return KeyboardButton::lshift();
2606 case VK_RSHIFT:
return KeyboardButton::rshift();
2608 case VK_CONTROL:
return KeyboardButton::control();
2609 case VK_LCONTROL:
return KeyboardButton::lcontrol();
2610 case VK_RCONTROL:
return KeyboardButton::rcontrol();
2612 case VK_MENU:
return KeyboardButton::alt();
2613 case VK_LMENU:
return KeyboardButton::lalt();
2614 case VK_RMENU:
return KeyboardButton::ralt();
2616 case VK_LWIN:
return KeyboardButton::lmeta();
2617 case VK_RWIN:
return KeyboardButton::rmeta();
2618 case VK_APPS:
return KeyboardButton::menu();
2621 int key = MapVirtualKey(wparam, 2);
2622 if (isascii(key) && key != 0) {
2637 return ButtonHandle::none();
2645lookup_raw_key(LPARAM lparam)
const {
2646 unsigned char vsc = (lparam & 0xff0000) >> 16;
2648 if (lparam & 0x1000000) {
2651 case 28:
return KeyboardButton::enter();
2652 case 29:
return KeyboardButton::rcontrol();
2654 case 55:
return KeyboardButton::print_screen();
2655 case 56:
return KeyboardButton::ralt();
2656 case 69:
return KeyboardButton::num_lock();
2657 case 71:
return KeyboardButton::home();
2658 case 72:
return KeyboardButton::up();
2659 case 73:
return KeyboardButton::page_up();
2660 case 75:
return KeyboardButton::left();
2661 case 77:
return KeyboardButton::right();
2662 case 79:
return KeyboardButton::end();
2663 case 80:
return KeyboardButton::down();
2664 case 81:
return KeyboardButton::page_down();
2665 case 82:
return KeyboardButton::insert();
2666 case 83:
return KeyboardButton::del();
2667 case 91:
return KeyboardButton::lmeta();
2668 case 92:
return KeyboardButton::rmeta();
2669 case 93:
return KeyboardButton::menu();
2675 ButtonHandle::none(),
2676 KeyboardButton::escape(),
2689 KeyboardButton::backspace(),
2690 KeyboardButton::tab(),
2703 KeyboardButton::enter(),
2704 KeyboardButton::lcontrol(),
2717 KeyboardButton::lshift(),
2729 KeyboardButton::rshift(),
2731 KeyboardButton::lalt(),
2732 KeyboardButton::space(),
2733 KeyboardButton::caps_lock(),
2734 KeyboardButton::f1(),
2735 KeyboardButton::f2(),
2736 KeyboardButton::f3(),
2737 KeyboardButton::f4(),
2738 KeyboardButton::f5(),
2739 KeyboardButton::f6(),
2740 KeyboardButton::f7(),
2741 KeyboardButton::f8(),
2742 KeyboardButton::f9(),
2743 KeyboardButton::f10(),
2744 KeyboardButton::pause(),
2745 KeyboardButton::scroll_lock(),
2760 return raw_map[vsc];
2766 case 87:
return KeyboardButton::f11();
2767 case 88:
return KeyboardButton::f12();
2768 default:
return ButtonHandle::none();
2780get_keyboard_map()
const {
2785 unsigned short ex_vsc[] = {0x56, 0x57, 0x58,
2786 0x011c, 0x011d, 0x0135, 0x0137, 0x0138, 0x0145, 0x0147, 0x0148, 0x0149, 0x014b, 0x014d, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x015b, 0x015c, 0x015d};
2788 for (
int k = 1; k < 84 +
sizeof(ex_vsc) /
sizeof(
short); ++k) {
2790 vsc = ex_vsc[k - 84];
2795 UINT lparam = vsc << 16;
2797 if (raw_button == ButtonHandle::none()) {
2803 button = KeyboardButton::pause();
2805 }
else if (vsc >= 0x47 && vsc <= 0x53) {
2807 button = raw_button;
2819 UINT vk = MapVirtualKeyA(vsc, MAPVK_VSC_TO_VK_EX);
2820 button = lookup_key(vk);
2826 int len = GetKeyNameTextW(lparam, text, 256);
2838void WinGraphicsWindow::
2839handle_raw_input(HRAWINPUT hraw) {
2846 if (GetRawInputData(hraw, RID_INPUT,
nullptr, &dwSize,
sizeof(RAWINPUTHEADER)) == -1) {
2850 lpb = (LPBYTE)alloca(
sizeof(LPBYTE) * dwSize);
2851 if (lpb ==
nullptr) {
2855 if (GetRawInputData(hraw, RID_INPUT, lpb, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize) {
2859 RAWINPUT *raw = (RAWINPUT *)lpb;
2860 if (raw->header.hDevice == 0) {
2864 for (
size_t i = 1; i < _input_devices.size(); ++i) {
2865 if (_input_device_handle[i] == raw->header.hDevice) {
2869 int adjx = raw->data.mouse.lLastX;
2870 int adjy = raw->data.mouse.lLastY;
2872 if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
2873 input->set_pointer_in_window(adjx, adjy);
2875 input->pointer_moved(adjx, adjy);
2878 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) {
2881 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) {
2884 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) {
2887 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) {
2890 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) {
2893 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) {
2896 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) {
2899 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) {
2902 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) {
2905 if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) {
2915bool WinGraphicsWindow::
2916handle_mouse_motion(
int x,
int y) {
2924void WinGraphicsWindow::
2925handle_mouse_exit() {
2934HICON WinGraphicsWindow::
2935get_icon(
const Filename &filename) {
2937 IconFilenames::iterator fi = _icon_filenames.find(filename);
2938 if (fi != _icon_filenames.end()) {
2939 return (HICON)((*fi).second);
2953 windisplay_cat.warning()
2954 <<
"Could not find icon filename " << filename <<
"\n";
2958 fi = _icon_filenames.find(resolved);
2959 if (fi != _icon_filenames.end()) {
2960 _icon_filenames[filename] = (*fi).second;
2961 return (HICON)((*fi).second);
2966 HANDLE h = LoadImage(
nullptr, os.c_str(),
2967 IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
2969 windisplay_cat.warning()
2970 <<
"windows icon filename '" << os <<
"' could not be loaded!!\n";
2973 _icon_filenames[filename] = h;
2974 _icon_filenames[resolved] = h;
2982HCURSOR WinGraphicsWindow::
2983get_cursor(
const Filename &filename) {
2985 if (filename.empty()) {
2990 IconFilenames::iterator fi = _cursor_filenames.find(filename);
2991 if (fi != _cursor_filenames.end()) {
2992 return (HCURSOR)((*fi).second);
3002 windisplay_cat.warning()
3003 <<
"Could not find cursor filename " << filename <<
"\n";
3006 fi = _cursor_filenames.find(resolved);
3007 if (fi != _cursor_filenames.end()) {
3008 _cursor_filenames[filename] = (*fi).second;
3009 return (HCURSOR)((*fi).second);
3014 HANDLE h = LoadImage(
nullptr, os.c_str(),
3015 IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
3017 windisplay_cat.warning()
3018 <<
"windows cursor filename '" << os <<
"' could not be loaded!!\n";
3019 show_error_message();
3022 _cursor_filenames[filename] = h;
3023 _cursor_filenames[resolved] = h;
3027static HCURSOR get_cursor(
const Filename &filename);
3033const WinGraphicsWindow::WindowClass &WinGraphicsWindow::
3035 WindowClass wcreg(props);
3036 std::wostringstream wclass_name;
3037 wclass_name << L
"WinGraphicsWindow" << _window_class_index;
3038 wcreg._name = wclass_name.str();
3040 std::pair<WindowClasses::iterator, bool> found = _window_classes.insert(wcreg);
3041 const WindowClass &wclass = (*found.first);
3043 if (!found.second) {
3049 _window_class_index++;
3053 HINSTANCE instance = GetModuleHandle(
nullptr);
3056 ZeroMemory(&wc,
sizeof(wc));
3057 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
3059 wc.hInstance = instance;
3061 wc.hIcon = wclass._icon;
3063 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
3064 wc.lpszMenuName =
nullptr;
3065 wc.lpszClassName = wclass._name.c_str();
3067 if (!RegisterClassW(&wc)) {
3068 windisplay_cat.error()
3069 <<
"could not register window class " << wclass._name <<
"!" << endl;
3079WinGraphicsWindow::WinWindowHandle::
3091void WinGraphicsWindow::WinWindowHandle::
3100void WinGraphicsWindow::WinWindowHandle::
3101receive_windows_message(
unsigned int msg,
int wparam,
int lparam) {
3102 if (_window !=
nullptr) {
3109void PrintErrorMessage(DWORD msgID) {
3110 LPTSTR pMessageBuffer;
3112 if (msgID==PRINT_LAST_ERROR)
3113 msgID=GetLastError();
3115 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
3117 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
3118 (LPTSTR) &pMessageBuffer,
3120 MessageBox(GetDesktopWindow(),pMessageBuffer,_T(errorbox_title),MB_OK);
3121 windisplay_cat.fatal() <<
"System error msg: " << pMessageBuffer << endl;
3122 LocalFree( pMessageBuffer );
3128 if (windisplay_cat.is_debug()) {
3129 windisplay_cat.debug()
3130 <<
"Skipping ClearToBlack, no origin specified yet.\n";
3135 if (windisplay_cat.is_debug()) {
3136 windisplay_cat.debug()
3137 <<
"ClearToBlack(" << hWnd <<
", " << props <<
")\n";
3140 HDC hDC=GetDC(hWnd);
3146 FillRect(hDC,&clrRect,(HBRUSH)GetStockObject(BLACK_BRUSH));
3147 ReleaseDC(hWnd,hDC);
3156 GetClientRect(hwnd, view_rect);
3159 ul.x = view_rect->left;
3160 ul.y = view_rect->top;
3161 lr.x = view_rect->right;
3162 lr.y = view_rect->bottom;
3164 ClientToScreen(hwnd, &ul);
3165 ClientToScreen(hwnd, &lr);
3167 view_rect->left = ul.x;
3168 view_rect->top = ul.y;
3169 view_rect->right = lr.x;
3170 view_rect->bottom = lr.y;
3179 nassertv(wnd_proc !=
nullptr);
3188 nassertv(wnd_proc !=
nullptr);
3197 _window_proc_classes.clear();
3214 return callbackData->get_msg() == WM_TOUCH;
3223 return _num_touches;
3232 nassertr(index >= 0 && index < MAX_TOUCHES,
TouchInfo());
3234 TOUCHINPUT ti = _touches[index];
3236 point.x = TOUCH_COORD_TO_PIXEL(ti.x);
3237 point.y = TOUCH_COORD_TO_PIXEL(ti.y);
3238 ScreenToClient(_hWnd, &point);
3243 ret.set_id(ti.dwID);
3244 ret.set_flags(ti.dwFlags);
get_real_time
Returns the actual number of seconds elapsed since the ClockObject was created, or since it was last ...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
The name of a file, such as a texture file or an Egg file.
bool is_fully_qualified() const
Returns true if the filename is fully qualified, e.g.
bool resolve_filename(const DSearchPath &searchpath, const std::string &default_extension=std::string())
Searches the given search path for the filename.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
bool exists() const
Returns true if the filename exists on the physical disk, false otherwise.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
void set_size_and_recalc(int x, int y)
Changes the x_size and y_size, then recalculates structures that depend on size.
An object to create GraphicsOutputs that share a particular 3-D API.
Encapsulates all the communication with a particular instance of a given rendering backend.
This specialization on CallbackData is passed when the callback is initiated from from an implementat...
Defines an interface for storing platform-specific window processor methods.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
get_unexposed_draw
See set_unexposed_draw().
get_properties
Returns the current properties of the window.
bool is_fullscreen() const
Returns true if the window has been opened as a fullscreen window, false otherwise.
get_close_request_event
Returns the name of the event set via set_close_request_event().
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
Similar to MutexHolder, but for a light mutex.
This class can be used to convert text between multiple representations, e.g.
std::wstring decode_text(const std::string &text) const
Returns the given wstring decoded to a single-byte string, via the current encoding system.
get_text
Returns the current text, as encoded via the current encoding system.
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
Stores information for a single touch event.
TypeHandle is the identifier used to differentiate C++ class types.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This is an abstract base class for wglGraphicsPipe and wdxGraphicsPipe; that is, those graphics pipes...
An abstract base class for glGraphicsWindow and dxGraphicsWindow (and, in general,...
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
void receive_windows_message(unsigned int msg, int wparam, int lparam)
This is called to receive a keyboard event generated by proxy by another window in a parent process.
virtual bool is_touch_event(GraphicsWindowProcCallbackData *callbackData)
Returns whether the specified event msg is a touch message.
virtual MouseData get_pointer(int device) const
Returns the MouseData associated with the nth input device's pointer.
virtual bool move_pointer(int device, int x, int y)
Forces the pointer to the indicated position within the window, if possible.
virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
This is the nonstatic window_proc function.
virtual int get_num_touches()
Returns the current number of touches on this window.
virtual bool supports_window_procs() const
Returns whether this window supports adding of windows proc handlers.
virtual void begin_flip()
This function will be called within the draw thread after end_frame() has been called on all windows,...
virtual void close_ime()
Forces the ime window to close, if any.
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
This is attached to the window class for all WinGraphicsWindow windows; it is called to handle window...
virtual void remove_window_proc(const GraphicsWindowProc *wnd_proc_object)
Removes the specified Windows proc event handler.
virtual TouchInfo get_touch_info(int index)
Returns the TouchInfo object describing the specified touch.
virtual void clear_window_procs()
Removes all Windows proc event handlers.
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
virtual void add_window_proc(const GraphicsWindowProc *wnd_proc_object)
Adds the specified Windows proc event handler to be called whenever a Windows event occurs.
This object represents a window on the desktop, not necessarily a Panda window.
get_os_handle
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
clear_cursor_filename
Removes the cursor_filename specification from the properties.
has_cursor_filename
Returns true if set_cursor_filename() has been specified.
get_title
Returns the window's title.
get_undecorated
Returns true if the window has no border.
clear_cursor_hidden
Removes the cursor_hidden specification from the properties.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
set_mouse_mode
Specifies the mode in which the window is to operate its mouse pointer.
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
int get_y_origin() const
Returns the y coordinate of the window's top-left corner, not including decorations.
has_undecorated
Returns true if set_undecorated() has been specified.
clear_z_order
Removes the z_order specification from the properties.
get_minimized
Returns true if the window is minimized.
clear_mouse_mode
Removes the mouse_mode specification from the properties.
has_fullscreen
Returns true if set_fullscreen() has been specified.
has_size
Returns true if the window size has been specified, false otherwise.
clear_title
Removes the title specification from the properties.
has_minimized
Returns true if set_minimized() has been specified.
set_size
Specifies the requested size of the window, in pixels.
get_foreground
Returns true if the window is in the foreground.
has_fixed_size
Returns true if set_fixed_size() has been specified.
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
clear_fixed_size
Removes the fixed_size specification from the properties.
clear_fullscreen
Removes the fullscreen specification from the properties.
set_foreground
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
clear_size
Removes the size specification from the properties.
set_open
Specifies whether the window should be open.
get_z_order
Returns the window's z_order.
get_icon_filename
Returns the icon filename associated with the window.
get_fullscreen
Returns true if the window is in fullscreen mode.
has_title
Returns true if the window title has been specified, false otherwise.
get_mouse_mode
See set_mouse_mode().
has_origin
Returns true if the window origin has been specified, false otherwise.
has_foreground
Returns true if set_foreground() has been specified.
clear_foreground
Removes the foreground specification from the properties.
get_cursor_filename
Returns the icon filename associated with the mouse cursor.
clear_undecorated
Removes the undecorated specification from the properties.
get_cursor_hidden
Returns true if the mouse cursor is invisible.
clear_minimized
Removes the minimized specification from the properties.
has_cursor_hidden
Returns true if set_cursor_hidden() has been specified.
set_minimized
Specifies whether the window should be created minimized (true), or normal (false).
clear_icon_filename
Removes the icon_filename specification from the properties.
has_z_order
Returns true if the window z_order has been specified, false otherwise.
get_fixed_size
Returns true if the window cannot be resized by the user, false otherwise.
int get_x_origin() const
Returns the x coordinate of the window's top-left corner, not including decorations.
set_origin
Specifies the origin on the screen (in pixels, relative to the top-left corner) at which the window s...
has_icon_filename
Returns true if set_icon_filename() has been specified.
This is our own Panda specialization on the default STL map.
This is our own Panda specialization on the default STL set.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BEGIN_PUBLISH typedef PointerData MouseData
Deprecated alias for PointerData.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EXPCL_PANDAWIN void get_client_rect_screen(HWND hwnd, RECT *view_rect)
Fills view_rect with the coordinates of the client area of the indicated window, converted to screen ...