00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "wcrGraphicsWindow.h"
00020 #include "wcrGraphicsPipe.h"
00021 #include "config_wcrdisplay.h"
00022 #include <keyboardButton.h>
00023 #include <mouseButton.h>
00024 #include "crGraphicsStateGuardian.h"
00025 #include <errno.h>
00026 #include <time.h>
00027 #include <mmsystem.h>
00028 #include <tchar.h>
00029 #include <map>
00030 #include <throw_event.h>
00031
00032 #include <string.h>
00033 #include "../wgldisplay/Win32Defs.h"
00034
00035
00036
00037 #ifdef DO_PSTATS
00038 #include <pStatTimer.h>
00039 #endif
00040
00041 #define WCR_WCREXT_PROTOTYPES
00042 #include "wcrext.h"
00043
00044
00045
00046
00047 TypeHandle wcrGraphicsWindow::_type_handle;
00048
00049 static bool wc_registered = false;
00050
00051 #define MOUSE_ENTERED 0
00052 #define MOUSE_EXITED 1
00053
00054 #define FONT_BITMAP_OGLDISPLAYLISTNUM 1000 // an arbitrary ID #
00055
00056 #define LAST_ERROR 0
00057 #define ERRORBOX_TITLE "Panda3D Error"
00058 #define WCR_WINDOWCLASSNAME "wcrDisplay"
00059
00060 #define PAUSED_TIMER_ID 7 // completely arbitrary choice
00061
00062 typedef map<HWND,wcrGraphicsWindow *> HWND_PANDAWIN_MAP;
00063
00064 HWND_PANDAWIN_MAP hwnd_pandawin_map;
00065 wcrGraphicsWindow *global_wcrwinptr=NULL;
00066
00067 typedef enum {Software, MCD, ICD} OGLDriverType;
00068 static char *OGLDrvStrings[3] = {"Software","MCD","ICD"};
00069
00070 LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam,LPARAM lparam);
00071
00072
00073
00074 #define NUM_MODIFIER_KEYS 16
00075 unsigned int hardcoded_modifier_buttons[NUM_MODIFIER_KEYS]={VK_SHIFT,VK_MENU,VK_CONTROL,VK_SPACE,VK_TAB,
00076 VK_UP,VK_DOWN,VK_LEFT,VK_RIGHT,VK_PRIOR,VK_NEXT,VK_HOME,VK_END,
00077 VK_INSERT,VK_DELETE,VK_ESCAPE};
00078
00079
00080 #define MIN_REFRESH_RATE 60
00081
00082 #define ACCEPTABLE_REFRESH_RATE(RATE) ((RATE >= MIN_REFRESH_RATE) || (RATE==0) || (RATE==1))
00083
00084 void PrintErrorMessage(DWORD msgID) {
00085 LPTSTR pMessageBuffer;
00086
00087 if (msgID==LAST_ERROR)
00088 msgID=GetLastError();
00089
00090 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00091 NULL,msgID,
00092 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00093 (LPTSTR) &pMessageBuffer,
00094 1024, NULL);
00095 MessageBox(GetDesktopWindow(),pMessageBuffer,_T(ERRORBOX_TITLE),MB_OK);
00096 wcrdisplay_cat.fatal() << "System error msg: " << pMessageBuffer << endl;
00097 LocalFree(pMessageBuffer);
00098 }
00099
00100
00101 void wcrGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
00102
00103 _exiting_window = true;
00104
00105
00106
00107
00108 if (!bAtExitFnCalled) {
00109
00110 #if 0 //[ TODO:skyler
00111 if ((_hdc!=NULL)&&(_context!=NULL)) {
00112
00113
00114 HGLRC current_context = GetCurrentContext();
00115
00116 HDC current_dc = NULL;
00117
00118 if ((current_context != _context) || (current_dc != _hdc)) {
00119 if (!chromium.MakeCurrent(_hdc, 0, _context)) {
00120 PrintErrorMessage(LAST_ERROR);
00121 }
00122 }
00123 report_errors();
00124 }
00125 #endif //]
00126
00127 if (gl_show_fps_meter)
00128 chromium.DeleteLists(FONT_BITMAP_OGLDISPLAYLISTNUM, 128);
00129
00130 report_errors();
00131
00132
00133 release_gsg();
00134
00135 report_errors();
00136
00137
00138 #if 0 //[ TODO:skyler
00139 HGLRC curcxt=GetCurrentContext();
00140 if (curcxt!=NULL)
00141 unmake_current();
00142
00143 if (_context!=NULL) {
00144 chromium.DeleteContext(_context);
00145 _context = NULL;
00146 }
00147 #endif //]
00148 }
00149
00150 if (_hdc!=NULL) {
00151 ReleaseDC(_mwindow,_hdc);
00152 _hdc = NULL;
00153 }
00154
00155 if ((_hOldForegroundWindow!=NULL) && (_mwindow==GetForegroundWindow())) {
00156 SetForegroundWindow(_hOldForegroundWindow);
00157 }
00158
00159 if (_mwindow!=NULL) {
00160 if (_bLoadedCustomCursor && _hMouseCursor!=NULL)
00161 DestroyCursor(_hMouseCursor);
00162
00163 DestroyWindow(_mwindow);
00164 hwnd_pandawin_map.erase(_mwindow);
00165 _mwindow = NULL;
00166 }
00167
00168 if (_pCurrent_display_settings!=NULL) {
00169 delete _pCurrent_display_settings;
00170 _pCurrent_display_settings = NULL;
00171 }
00172
00173 if (_props._fullscreen) {
00174
00175 ChangeDisplaySettings(NULL,0x0);
00176 }
00177 }
00178
00179 void wcrGraphicsWindow::do_close_window() {
00180 GraphicsWindow::do_close_window();
00181 DestroyMe(false);
00182 }
00183
00184
00185
00186
00187
00188
00189 wcrGraphicsWindow::~wcrGraphicsWindow() {
00190 close_window();
00191 }
00192
00193 void DestroyAllWindows(bool bAtExitFnCalled) {
00194
00195 while(!hwnd_pandawin_map.empty()) {
00196
00197 HWND_PANDAWIN_MAP::iterator pwin = hwnd_pandawin_map.begin();
00198 if ((*pwin).second != NULL)
00199 (*pwin).second->DestroyMe(bAtExitFnCalled);
00200 }
00201 }
00202
00203 void AtExitFn() {
00204 #ifdef _DEBUG
00205 wcrdisplay_cat.spam() << "AtExitFn called\n";
00206 #endif
00207 DestroyAllWindows(true);
00208 }
00209
00210 bool find_acceptable_display_mode(DWORD dwWidth,DWORD dwHeight,DWORD bpp,DEVMODE &dm) {
00211 int modenum=0;
00212
00213
00214 while(1) {
00215 ZeroMemory(&dm, sizeof(dm));
00216 dm.dmSize = sizeof(dm);
00217
00218 if (!EnumDisplaySettings(NULL,modenum,&dm))
00219 break;
00220
00221 if ((dm.dmPelsWidth==dwWidth) && (dm.dmPelsHeight==dwHeight) &&
00222 (dm.dmBitsPerPel==bpp) && ACCEPTABLE_REFRESH_RATE(dm.dmDisplayFrequency)) {
00223 return true;
00224 }
00225 modenum++;
00226 }
00227
00228 return false;
00229 }
00230
00231
00232
00233
00234
00235
00236 void wcrGraphicsWindow::config() {
00237 #if 1 //[
00238 int spu_ids[] = { 0, 1 };
00239 char *spu_names[] = { "readback", "pack" };
00240
00241 SPU *spu;
00242 spu = crSPULoadChain(sizeof(spu_names)/sizeof(spu_names[0]), spu_ids,
00243 spu_names, NULL, NULL);
00244 if (!spu) {
00245 cerr << "!spu" << endl;
00246 exit(0);
00247 }
00248 chromium=spu->dispatch_table;
00249 cerr << "CRGraphicsStateGuardian chromium:" << (void*)&chromium <<
00250 " spu:" << (void*)spu << " dispatch:" << (void*)&(spu->dispatch_table) << "\n\n\n\n\n\n" << endl;
00251
00252 #endif //]
00253
00254 GraphicsWindow::config();
00255
00256 HINSTANCE hinstance = GetModuleHandle(NULL);
00257 HWND hDesktopWindow = GetDesktopWindow();
00258
00259 global_wcrwinptr = this;
00260
00261 _exiting_window = false;
00262 _return_control_to_app = false;
00263 _bIsLowVidMemCard = false;
00264 _active_minimized_fullscreen = false;
00265 _PandaPausedTimer = NULL;
00266 _mouse_input_enabled = false;
00267 _mouse_motion_enabled = false;
00268 _mouse_passive_motion_enabled = false;
00269 _mouse_entry_enabled = false;
00270 _context = NULL;
00271 _hdc = NULL;
00272 _window_inactive = false;
00273 _pCurrent_display_settings = NULL;
00274 _mwindow = NULL;
00275 _gsg = NULL;
00276 ZeroMemory(&_pixelformat,sizeof(_pixelformat));
00277 _hOldForegroundWindow=GetForegroundWindow();
00278
00279 WNDCLASS wc;
00280
00281
00282 ZeroMemory(&wc, sizeof(WNDCLASS));
00283 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00284 wc.lpfnWndProc = (WNDPROC) static_window_proc;
00285 wc.hInstance = hinstance;
00286
00287 string windows_icon_filename = get_icon_filename_2().to_os_specific();
00288 string windows_mono_cursor_filename = get_mono_cursor_filename_2().to_os_specific();
00289
00290 if (!windows_icon_filename.empty()) {
00291
00292
00293
00294
00295 wc.hIcon = (HICON) LoadImage(NULL, windows_icon_filename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
00296
00297 if (wc.hIcon==NULL) {
00298 wcrdisplay_cat.warning() << "windows icon filename '" << windows_icon_filename << "' not found!!\n";
00299 }
00300 } else {
00301 wc.hIcon = NULL;
00302 }
00303
00304 _bLoadedCustomCursor = false;
00305 if (!windows_mono_cursor_filename.empty()) {
00306
00307
00308
00309 DWORD load_flags = LR_LOADFROMFILE;
00310
00311 if (_props._fullscreen) {
00312
00313
00314 load_flags |= LR_CREATEDIBSECTION;
00315 }
00316
00317
00318 _hMouseCursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags);
00319
00320 if (_hMouseCursor==NULL) {
00321 wcrdisplay_cat.warning() << "windows cursor filename '" << windows_mono_cursor_filename << "' not found!!\n";
00322 }
00323 _bLoadedCustomCursor = true;
00324 } else {
00325 _hMouseCursor = LoadCursor(NULL, IDC_ARROW);
00326 }
00327
00328 if (!wc_registered) {
00329
00330 wc.hCursor = _hMouseCursor;
00331 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
00332 wc.lpszMenuName = NULL;
00333 wc.lpszClassName = WCR_WINDOWCLASSNAME;
00334
00335 if (!RegisterClass(&wc)) {
00336 wcrdisplay_cat.error() << "could not register window class!" << endl;
00337 }
00338 wc_registered = true;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 DWORD window_style = WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
00348
00349
00350 if (_props._fullscreen) {
00351 DWORD dwWidth = _props._xsize;
00352 DWORD dwHeight = _props._ysize;
00353
00354 HDC scrnDC=GetDC(hDesktopWindow);
00355 DWORD drvr_ver=GetDeviceCaps(scrnDC,DRIVERVERSION);
00356 DWORD cur_bitdepth=GetDeviceCaps(scrnDC,BITSPIXEL);
00357 DWORD cur_scrnwidth=GetDeviceCaps(scrnDC,HORZRES);
00358 DWORD cur_scrnheight=GetDeviceCaps(scrnDC,VERTRES);
00359 ReleaseDC(hDesktopWindow,scrnDC);
00360
00361 DWORD dwFullScreenBitDepth=cur_bitdepth;
00362
00363 DEVMODE dm;
00364 if (!find_acceptable_display_mode(dwWidth,dwHeight,dwFullScreenBitDepth,dm)) {
00365 wcrdisplay_cat.fatal() << "Videocard has no supported display resolutions at specified res (" << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<")\n";
00366 exit(1);
00367 }
00368
00369
00370
00371 _mwindow = CreateWindow(WCR_WINDOWCLASSNAME, _props._title.c_str(),
00372 window_style,0,0,dwWidth,dwHeight,hDesktopWindow, NULL, hinstance, 0);
00373
00374
00375 SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
00376
00377 ShowWindow(_mwindow, SW_SHOWNORMAL);
00378 ShowWindow(_mwindow, SW_SHOWNORMAL);
00379
00380 int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
00381
00382 if (chg_result!=DISP_CHANGE_SUCCESSFUL) {
00383 wcrdisplay_cat.fatal() << "ChangeDisplaySettings failed (error code: " << chg_result <<") for specified res (" << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<"), " << dm.dmDisplayFrequency << "Hz\n";
00384 exit(1);
00385 }
00386
00387 _pCurrent_display_settings = new(DEVMODE);
00388 memcpy(_pCurrent_display_settings,&dm,sizeof(DEVMODE));
00389
00390 _props._xorg = 0;
00391 _props._yorg = 0;
00392 _props._xsize = dwWidth;
00393 _props._ysize = dwHeight;
00394
00395 if (wcrdisplay_cat.is_debug())
00396 wcrdisplay_cat.debug() << "set fullscreen mode at res (" << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<"), " << dm.dmDisplayFrequency << "Hz\n";
00397 } else {
00398
00399 RECT win_rect;
00400 SetRect(&win_rect, _props._xorg, _props._yorg, _props._xorg + _props._xsize,
00401 _props._yorg + _props._ysize);
00402
00403 if (_props._border) {
00404 window_style |= WS_OVERLAPPEDWINDOW;
00405 }
00406
00407 BOOL bRes = AdjustWindowRect(&win_rect, window_style, FALSE);
00408
00409 if (!bRes) {
00410 wcrdisplay_cat.fatal() << "AdjustWindowRect failed!" << endl;
00411 exit(1);
00412 }
00413
00414
00415 if (win_rect.left < 0) {
00416 win_rect.right += abs(win_rect.left); win_rect.left = 0;
00417 }
00418 if (win_rect.top < 0) {
00419 win_rect.bottom += abs(win_rect.top); win_rect.top = 0;
00420 }
00421
00422 _mwindow = CreateWindow(WCR_WINDOWCLASSNAME, _props._title.c_str(),
00423 window_style, win_rect.left, win_rect.top, win_rect.right-win_rect.left,
00424 win_rect.bottom-win_rect.top,
00425 NULL, NULL, hinstance, 0);
00426 }
00427
00428 if (!_mwindow) {
00429 wcrdisplay_cat.fatal() << "CreateWindow() failed!" << endl;
00430 PrintErrorMessage(LAST_ERROR);
00431 exit(1);
00432 }
00433
00434
00435 _ime_open = false;
00436 HIMC hIMC = ImmGetContext(_mwindow);
00437 if (hIMC != 0) {
00438 _ime_open = (ImmGetOpenStatus(hIMC) != 0);
00439 ImmReleaseContext(_mwindow, hIMC);
00440 }
00441
00442 hwnd_pandawin_map[_mwindow] = this;
00443 global_wcrwinptr = NULL;
00444
00445
00446 SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
00447
00448 _hdc = GetDC(_mwindow);
00449
00450
00451
00452 int pfnum=choose_visual();
00453
00454 if (gl_forced_pixfmt!=0) {
00455 if (wcrdisplay_cat.is_debug())
00456 wcrdisplay_cat.debug() << "overriding pixfmt choice algorithm (" << pfnum << ") with gl-force-pixfmt("<<gl_forced_pixfmt<< ")\n";
00457 pfnum=gl_forced_pixfmt;
00458 }
00459
00460
00461 if (wcrdisplay_cat.is_debug())
00462 wcrdisplay_cat.debug() << "config() - picking pixfmt #"<< pfnum <<endl;
00463
00464 if (!SetPixelFormat(_hdc, pfnum, &_pixelformat)) {
00465 wcrdisplay_cat.fatal()
00466 << "config() - SetPixelFormat("<< pfnum << ") failed after window create" << endl;
00467 exit(1);
00468 }
00469
00470
00471 setup_colormap();
00472
00473 _context = chromium.CreateContext(_hdc, CR_RGB_BIT | CR_DOUBLE_BIT);
00474 if (!_context) {
00475 wcrdisplay_cat.fatal()
00476 << "config() - failed to create Win32 rendering context" << endl;
00477 exit(1);
00478 }
00479
00480
00481 ShowWindow(_mwindow, SW_SHOWNORMAL);
00482 ShowWindow(_mwindow, SW_SHOWNORMAL);
00483
00484
00485 enable_mouse_input(true);
00486 enable_mouse_motion(true);
00487 enable_mouse_passive_motion(true);
00488
00489
00490 GraphicsWindowInputDevice device =
00491 GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
00492 _input_devices.push_back(device);
00493
00494
00495
00496
00497 make_current();
00498 make_gsg();
00499
00500 check_for_color_cursor_support();
00501
00502
00503
00504 string tmpstr((char*)chromium.GetString(GL_EXTENSIONS));
00505
00506 _extensions_str = tmpstr;
00507
00508 PFNWCRGETEXTENSIONSSTRINGEXTPROC wcrGetExtensionsStringEXT = NULL;
00509 PFNWCRGETEXTENSIONSSTRINGARBPROC wcrGetExtensionsStringARB = NULL;
00510
00511 #if 0 //[
00512 if (!support_wiregl) {
00513 wcrGetExtensionsStringARB = (PFNWCRGETEXTENSIONSSTRINGARBPROC)chromium.GetProcAddress("wcrGetExtensionsStringARB");
00514 wcrGetExtensionsStringEXT = (PFNWCRGETEXTENSIONSSTRINGEXTPROC)chromium.GetProcAddress("wcrGetExtensionsStringEXT");
00515 }
00516 #endif //]
00517
00518 if (wcrGetExtensionsStringARB!=NULL) {
00519 _extensions_str += " ";
00520
00521 const char *ARBextensions = wcrGetExtensionsStringARB(NULL);
00522 _extensions_str.append(ARBextensions);
00523 }
00524
00525 if (wcrGetExtensionsStringEXT!=NULL) {
00526
00527 _extensions_str += " ";
00528 const char *EXTextensions = wcrGetExtensionsStringEXT();
00529 _extensions_str.append(EXTextensions);
00530 }
00531
00532 if (wcrdisplay_cat.is_spam())
00533 wcrdisplay_cat.spam() << "GL extensions: " << _extensions_str << endl;
00534
00535 #if 0 //[
00536 if (gl_sync_video) {
00537
00538
00539 if (_extensions_str.find("WCR_EXT_swap_control")!=_extensions_str.npos) {
00540 PFNWCRSWAPINTERVALEXTPROC wcrSwapIntervalEXT;
00541 wcrSwapIntervalEXT = (PFNWCRSWAPINTERVALEXTPROC) chromium.GetProcAddress("wcrSwapIntervalEXT");
00542 if (wcrSwapIntervalEXT!=NULL)
00543 wcrSwapIntervalEXT(1);
00544
00545 if (wcrdisplay_cat.is_spam())
00546 wcrdisplay_cat.spam() << "setting swapbuffer interval to 1/refresh\n";
00547 }
00548 }
00549 #endif //]
00550
00551 if (gl_show_fps_meter) {
00552
00553 _start_time = timeGetTime();
00554 _current_fps = 0.0;
00555 _start_frame_count = _cur_frame_count = 0;
00556
00557
00558
00559
00560
00561
00562
00563 }
00564
00565 if (wcrdisplay_cat.is_info()) {
00566 const char *vendStr=(const char *) chromium.GetString(GL_VENDOR);
00567 const char *rendStr=(const char *) chromium.GetString(GL_RENDERER);
00568 const char *versStr=(const char *) chromium.GetString(GL_VERSION);
00569
00570
00571
00572 if (vendStr!=NULL) {
00573 wcrdisplay_cat.info()
00574 << "GL_VENDOR: " << vendStr
00575 << " GL_RENDERER: " << ((rendStr==NULL) ? "" : rendStr)
00576 << " GL_VERSION: " << ((versStr==NULL) ? "" : versStr) << endl;
00577 } else {
00578 wcrdisplay_cat.info() << "chromium.GetString(GL_VENDOR) returns NULL!\n";
00579 }
00580 }
00581 }
00582
00583 void wcrGraphicsWindow::
00584 check_for_color_cursor_support() {
00585
00586
00587
00588
00589
00590
00591
00592 string windows_color_cursor_filename = get_color_cursor_filename_2().to_os_specific();
00593 if (windows_color_cursor_filename.empty())
00594 return;
00595
00596 bool bSupportsColorCursor=false;
00597 const GLubyte *vendorname=chromium.GetString(GL_VENDOR);
00598 if (vendorname==NULL) {
00599 return;
00600 }
00601 char vendorstr[500];
00602 strncpy(vendorstr,(const char *)vendorname,sizeof(vendorstr));
00603 _strlwr(vendorstr);
00604 if (strstr(vendorstr,"nvidia")!=NULL)
00605 bSupportsColorCursor=true;
00606
00607
00608
00609
00610 if (bSupportsColorCursor) {
00611
00612
00613
00614 DWORD load_flags = LR_LOADFROMFILE;
00615
00616 if (_props._fullscreen) {
00617
00618
00619 load_flags |= LR_CREATEDIBSECTION;
00620
00621
00622
00623 }
00624
00625
00626 HCURSOR hNewMouseCursor = (HCURSOR) LoadImage(NULL, windows_color_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags);
00627
00628 if (hNewMouseCursor==NULL) {
00629 wcrdisplay_cat.warning() << "windows color cursor filename '" << windows_color_cursor_filename << "' not found!!\n";
00630 return;
00631 }
00632
00633 SetClassLongPtr(_mwindow, GCLP_HCURSOR, (LONG_PTR) hNewMouseCursor);
00634 SetCursor(hNewMouseCursor);
00635
00636 if (_bLoadedCustomCursor)
00637 DestroyCursor(_hMouseCursor);
00638 _hMouseCursor = hNewMouseCursor;
00639
00640 if (wcrdisplay_cat.is_spam())
00641 wcrdisplay_cat.spam() << "loaded color cursor\n";
00642 }
00643 }
00644
00645
00646
00647
00648
00649
00650 wcrGraphicsWindow::
00651 wcrGraphicsWindow(GraphicsPipe* pipe) : GraphicsWindow(pipe) {
00652 config();
00653 }
00654
00655
00656
00657
00658
00659
00660 wcrGraphicsWindow::
00661 wcrGraphicsWindow(GraphicsPipe* pipe, const
00662 GraphicsWindow::Properties& props) : GraphicsWindow(pipe, props) {
00663 config();
00664 }
00665
00666 #ifdef _DEBUG
00667 void PrintPFD(PIXELFORMATDESCRIPTOR *pfd,char *msg) {
00668
00669 OGLDriverType drvtype;
00670 if ((pfd->dwFlags & PFD_GENERIC_ACCELERATED) && (pfd->dwFlags & PFD_GENERIC_FORMAT))
00671 drvtype=MCD;
00672 else if (!(pfd->dwFlags & PFD_GENERIC_ACCELERATED) && !(pfd->dwFlags & PFD_GENERIC_FORMAT))
00673 drvtype=ICD;
00674 else {
00675 drvtype=Software;
00676 }
00677
00678 #define PrintFlag(FLG) ((pfd->dwFlags & PFD_##FLG) ? (" PFD_" #FLG "|") : "")
00679 wcrdisplay_cat.spam() << "================================\n";
00680
00681 wcrdisplay_cat.spam() << msg << ", " << OGLDrvStrings[drvtype] << " driver\n"
00682 << "PFD flags: 0x" << (void*)pfd->dwFlags << " (" <<
00683 PrintFlag(GENERIC_ACCELERATED) <<
00684 PrintFlag(GENERIC_FORMAT) <<
00685 PrintFlag(DOUBLEBUFFER) <<
00686 PrintFlag(SUPPORT_OPENGL) <<
00687 PrintFlag(SUPPORT_GDI) <<
00688 PrintFlag(STEREO) <<
00689 PrintFlag(DRAW_TO_WINDOW) <<
00690 PrintFlag(DRAW_TO_BITMAP) <<
00691 PrintFlag(SWAP_EXCHANGE) <<
00692 PrintFlag(SWAP_COPY) <<
00693 PrintFlag(SWAP_LAYER_BUFFERS) <<
00694 PrintFlag(NEED_PALETTE) <<
00695 PrintFlag(NEED_SYSTEM_PALETTE) <<
00696 PrintFlag(SUPPORT_DIRECTDRAW) << ")\n"
00697 << "PFD iPixelType: " << ((pfd->iPixelType==PFD_TYPE_RGBA) ? "PFD_TYPE_RGBA":"PFD_TYPE_COLORINDEX") << endl
00698 << "PFD cColorBits: " << (DWORD)pfd->cColorBits << " R: " << (DWORD)pfd->cRedBits <<" G: " << (DWORD)pfd->cGreenBits <<" B: " << (DWORD)pfd->cBlueBits << endl
00699 << "PFD cAlphaBits: " << (DWORD)pfd->cAlphaBits << " DepthBits: " << (DWORD)pfd->cDepthBits <<" StencilBits: " << (DWORD)pfd->cStencilBits <<" AccumBits: " << (DWORD)pfd->cAccumBits << endl;
00700 }
00701 #endif
00702
00703
00704
00705
00706
00707
00708 int wcrGraphicsWindow::choose_visual() {
00709
00710 int mask = _props._mask;
00711 int want_depth_bits = _props._want_depth_bits;
00712 int want_color_bits = _props._want_color_bits;
00713 OGLDriverType drvtype;
00714
00715 if (mask & W_MULTISAMPLE) {
00716 wcrdisplay_cat.info()
00717 << "config() - multisample not supported"<< endl;
00718 mask &= ~W_MULTISAMPLE;
00719 }
00720 wcrdisplay_cat.info()
00721 << "mask =0x" << (void*) mask
00722 << endl;
00723
00724 PIXELFORMATDESCRIPTOR pfd;
00725 ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
00726 pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
00727 pfd.nVersion=1;
00728
00729
00730
00731
00732
00733
00734 int MaxPixFmtNum=DescribePixelFormat(_hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00735 int cur_bpp=GetDeviceCaps(_hdc,BITSPIXEL);
00736 int pfnum;
00737
00738 #ifdef _DEBUG
00739 if (wcrdisplay_cat.is_debug()) {
00740 for(pfnum=1;pfnum<=MaxPixFmtNum;pfnum++) {
00741 DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00742
00743 if ((pfd.dwFlags & PFD_GENERIC_ACCELERATED) && (pfd.dwFlags & PFD_GENERIC_FORMAT))
00744 drvtype=MCD;
00745 else if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) && !(pfd.dwFlags & PFD_GENERIC_FORMAT))
00746 drvtype=ICD;
00747 else {
00748 drvtype=Software;
00749 continue;
00750 }
00751
00752
00753 char msg[200];
00754 sprintf(msg,"GL PixelFormat[%d]",pfnum);
00755 PrintPFD(&pfd,msg);
00756 }
00757 }
00758 #endif
00759
00760 for(pfnum=1;pfnum<=MaxPixFmtNum;pfnum++) {
00761 DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00762
00763
00764 if ((pfd.dwFlags & PFD_GENERIC_FORMAT) != 0) {
00765 drvtype = Software;
00766 continue;
00767 }
00768 else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED)
00769 drvtype = MCD;
00770 else
00771 drvtype = ICD;
00772
00773 #if MY_OLD_ALGORITHM
00774 if ((pfd.dwFlags & PFD_GENERIC_ACCELERATED) && (pfd.dwFlags & PFD_GENERIC_FORMAT))
00775 drvtype=MCD;
00776 else if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) && !(pfd.dwFlags & PFD_GENERIC_FORMAT))
00777 drvtype=ICD;
00778 else {
00779 drvtype=Software;
00780 continue;
00781 }
00782 #endif
00783
00784 if (wcrdisplay_cat.is_debug())
00785 wcrdisplay_cat->debug() << "----------------" << endl;
00786
00787 if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) && !(mask & W_INDEX))
00788 continue;
00789
00790 DWORD dwReqFlags=(PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
00791
00792 if (wcrdisplay_cat.is_debug()) {
00793 if (mask & W_ALPHA)
00794 wcrdisplay_cat->debug() << "want alpha, pfd says '"
00795 << (int)(pfd.cAlphaBits) << "'" << endl;
00796 if (mask & W_DEPTH)
00797 wcrdisplay_cat->debug() << "want depth, pfd says '"
00798 << (int)(pfd.cDepthBits) << "'" << endl;
00799 if (mask & W_STENCIL)
00800 wcrdisplay_cat->debug() << "want stencil, pfd says '"
00801 << (int)(pfd.cStencilBits) << "'" << endl;
00802 wcrdisplay_cat->debug() << "final flag check "
00803 << (int)(pfd.dwFlags & dwReqFlags) << " =? "
00804 << (int)dwReqFlags << endl;
00805 wcrdisplay_cat->debug() << "pfd bits = " << (int)(pfd.cColorBits)
00806 << endl;
00807 wcrdisplay_cat->debug() << "cur_bpp = " << cur_bpp << endl;
00808 }
00809
00810 if (mask & W_DOUBLE)
00811 dwReqFlags|= PFD_DOUBLEBUFFER;
00812 if ((mask & W_ALPHA) && (pfd.cAlphaBits==0))
00813 continue;
00814 if ((mask & W_DEPTH) && (pfd.cDepthBits==0))
00815 continue;
00816 if ((mask & W_STENCIL) && (pfd.cStencilBits==0))
00817 continue;
00818
00819 if ((pfd.dwFlags & dwReqFlags)!=dwReqFlags)
00820 continue;
00821
00822
00823
00824
00825 if ((pfd.cColorBits!=cur_bpp) && (!((cur_bpp==16) && (pfd.cColorBits==15)))
00826 && (!((cur_bpp==32) && (pfd.cColorBits==24))))
00827 continue;
00828
00829
00830
00831
00832 break;
00833 }
00834
00835 if (pfnum>MaxPixFmtNum) {
00836 wcrdisplay_cat.error() << "ERROR: couldn't find HW-accelerated OpenGL pixfmt appropriate for this desktop!!\n";
00837 wcrdisplay_cat.error() << "make sure OpenGL driver is installed, and try reducing the screen size\n";
00838 if (cur_bpp>16)
00839 wcrdisplay_cat.error() << "or reducing the desktop screen pixeldepth\n";
00840 exit(1);
00841 }
00842
00843 #ifdef _DEBUG
00844 char msg[200];
00845 sprintf(msg,"Selected GL PixelFormat is #%d",pfnum);
00846 PrintPFD(&pfd,msg);
00847 #endif
00848
00849 memcpy(&_pixelformat,&pfd,sizeof(PIXELFORMATDESCRIPTOR));
00850
00851 return pfnum;
00852 }
00853
00854
00855
00856
00857
00858
00859 void wcrGraphicsWindow::setup_colormap() {
00860
00861 PIXELFORMATDESCRIPTOR pfd;
00862 LOGPALETTE *logical;
00863 int n;
00864
00865
00866 memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
00867 DescribePixelFormat(_hdc, GetPixelFormat(_hdc),
00868 sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00869
00870 if (!(pfd.dwFlags & PFD_NEED_PALETTE ||
00871 pfd.iPixelType == PFD_TYPE_COLORINDEX))
00872 return;
00873
00874 n = 1 << pfd.cColorBits;
00875
00876
00877
00878 logical = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
00879 sizeof(PALETTEENTRY) * n);
00880 memset(logical, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * n);
00881
00882
00883 logical->palVersion = 0x300;
00884 logical->palNumEntries = n;
00885
00886
00887 GetSystemPaletteEntries(_hdc, 0, 256, &logical->palPalEntry[0]);
00888
00889 if (pfd.iPixelType == PFD_TYPE_RGBA) {
00890 int redMask = (1 << pfd.cRedBits) - 1;
00891 int greenMask = (1 << pfd.cGreenBits) - 1;
00892 int blueMask = (1 << pfd.cBlueBits) - 1;
00893 int i;
00894
00895
00896 for (i = 0; i < n; ++i) {
00897 logical->palPalEntry[i].peRed =
00898 (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
00899 logical->palPalEntry[i].peGreen =
00900 (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
00901 logical->palPalEntry[i].peBlue =
00902 (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
00903 logical->palPalEntry[i].peFlags = 0;
00904 }
00905 }
00906
00907 _colormap = CreatePalette(logical);
00908 free(logical);
00909
00910 SelectPalette(_hdc, _colormap, FALSE);
00911 RealizePalette(_hdc);
00912 }
00913
00914
00915
00916
00917
00918
00919 void wcrGraphicsWindow::end_frame() {
00920 if (gl_show_fps_meter) {
00921 DO_PSTATS_STUFF(PStatTimer timer(_show_fps_pcollector);)
00922 DWORD now = timeGetTime();
00923
00924 float time_delta = (now - _start_time) * 0.001f;
00925
00926 if (time_delta > gl_fps_meter_update_interval) {
00927
00928
00929
00930 DWORD num_frames = _cur_frame_count - _start_frame_count;
00931
00932 _current_fps = num_frames / time_delta;
00933 _start_time = now;
00934 _start_frame_count = _cur_frame_count;
00935 }
00936
00937 char fps_msg[15];
00938 sprintf(fps_msg, "%.02f fps", _current_fps);
00939
00940
00941
00942
00943
00944
00945 chromium.Color3f(0.0f,1.0f,1.0f);
00946
00947 GLboolean tex_was_on = chromium.IsEnabled(GL_TEXTURE_2D);
00948
00949 if (tex_was_on)
00950 chromium.Disable(GL_TEXTURE_2D);
00951
00952 chromium.MatrixMode(GL_MODELVIEW);
00953 chromium.PushMatrix();
00954 chromium.LoadIdentity();
00955 chromium.MatrixMode(GL_PROJECTION);
00956 chromium.PushMatrix();
00957 chromium.LoadIdentity();
00958
00959 chromium.Ortho(0.0f,_props._xsize,
00960 0.0f,_props._ysize,
00961 -1.0f,1.0f);
00962
00963 chromium.RasterPos2f(_props._xsize-70,_props._ysize-20);
00964
00965
00966 chromium.ListBase(FONT_BITMAP_OGLDISPLAYLISTNUM);
00967
00968
00969
00970 chromium.CallLists(strlen(fps_msg), GL_UNSIGNED_BYTE, fps_msg);
00971
00972 chromium.PopMatrix();
00973 chromium.MatrixMode(GL_MODELVIEW);
00974 chromium.PopMatrix();
00975
00976 if (tex_was_on)
00977 chromium.Enable(GL_TEXTURE_2D);
00978
00979 _cur_frame_count++;
00980 }
00981
00982 {
00983 DO_PSTATS_STUFF(PStatTimer timer(_swap_pcollector);)
00984 if (_is_synced)
00985 chromium.Finish();
00986 else {
00987 chromium.SwapBuffers();
00988 }
00989 }
00990 GraphicsWindow::end_frame();
00991 }
00992
00993
00994
00995
00996
00997
00998 void wcrGraphicsWindow::swap() {
00999 if (_is_synced)
01000 chromium.SwapBuffers();
01001 }
01002
01003 bool wcrGraphicsWindow::resize(unsigned int xsize,unsigned int ysize) {
01004 if (!_props._fullscreen) {
01005
01006 SetWindowPos(_mwindow, NULL, 0,0, xsize,ysize, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
01007 } else {
01008 DWORD dwWidth = xsize;
01009 DWORD dwHeight = ysize;
01010
01011 HWND hDesktopWindow = GetDesktopWindow();
01012 HDC scrnDC=GetDC(hDesktopWindow);
01013 DWORD dwFullScreenBitDepth=GetDeviceCaps(scrnDC,BITSPIXEL);
01014 ReleaseDC(hDesktopWindow,scrnDC);
01015
01016
01017
01018
01019
01020
01021 DEVMODE dm;
01022 if (!find_acceptable_display_mode(dwWidth,dwHeight,dwFullScreenBitDepth,dm)) {
01023 wcrdisplay_cat.fatal() << "window resize(" << xsize << "," << ysize << ") failed, no compatible fullscreen display mode found!\n";
01024 return false;
01025 }
01026
01027
01028 SetWindowPos(_mwindow, NULL, 0,0, xsize, ysize, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
01029
01030 int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
01031
01032 if (chg_result!=DISP_CHANGE_SUCCESSFUL) {
01033 wcrdisplay_cat.fatal() << "resize ChangeDisplaySettings failed (error code: " << chg_result <<") for specified res (" << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<"), " << dm.dmDisplayFrequency << "Hz\n";
01034 exit(1);
01035 }
01036
01037
01038 assert(_pCurrent_display_settings!=NULL);
01039 memcpy(_pCurrent_display_settings,&dm,sizeof(DEVMODE));
01040 }
01041 return true;
01042 }
01043
01044 unsigned int wcrGraphicsWindow::
01045 verify_window_sizes(unsigned int numsizes,unsigned int *dimen) {
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058 if (!_props._fullscreen || (numsizes==0)) {
01059 return numsizes;
01060 }
01061
01062 assert(dimen!=NULL);
01063
01064 HWND hDesktopWindow = GetDesktopWindow();
01065 HDC scrnDC=GetDC(hDesktopWindow);
01066 DWORD dwFullScreenBitDepth=GetDeviceCaps(scrnDC,BITSPIXEL);
01067 ReleaseDC(hDesktopWindow,scrnDC);
01068
01069
01070
01071
01072 DEVMODE dm;
01073 uint modenum=0;
01074 uint goodmodes=0;
01075 unsigned int *cur_dim_pair=dimen;
01076 for(;modenum<numsizes;modenum++,cur_dim_pair+=2) {
01077 bool bIsGoodmode;
01078 DWORD dwWidth=cur_dim_pair[0];
01079 DWORD dwHeight=cur_dim_pair[1];
01080
01081 if ((dwWidth==0)||(dwHeight==0)) {
01082 bIsGoodmode=false;
01083 } else {
01084 if (_bIsLowVidMemCard) {
01085 bIsGoodmode=((float)(dwWidth*(float)dwHeight)<=(float)(640*480));
01086 } else {
01087 bIsGoodmode = find_acceptable_display_mode(dwWidth,dwHeight,dwFullScreenBitDepth,dm);
01088 }
01089 }
01090
01091 if (bIsGoodmode) {
01092 goodmodes++;
01093 } else {
01094
01095 cur_dim_pair[0]=0;
01096 cur_dim_pair[1]=0;
01097 }
01098 }
01099
01100 return goodmodes;
01101 }
01102
01103
01104
01105
01106
01107
01108 void wcrGraphicsWindow::handle_reshape() {
01109 RECT view_rect;
01110 GetClientRect(_mwindow, &view_rect);
01111 ClientToScreen(_mwindow, (POINT*)&view_rect.left);
01112 ClientToScreen(_mwindow, (POINT*)&view_rect.right);
01113
01114
01115 resized((view_rect.right - view_rect.left),(view_rect.bottom - view_rect.top));
01116
01117 _props._xorg = view_rect.left;
01118 _props._yorg = view_rect.top;
01119
01120 if (wcrdisplay_cat.is_spam()) {
01121 wcrdisplay_cat.spam() << "reshape to origin: (" << _props._xorg << "," << _props._yorg << "), size: (" << _props._xsize << "," << _props._ysize << ")\n";
01122 }
01123 }
01124
01125
01126
01127
01128
01129
01130 void wcrGraphicsWindow::handle_mouse_motion(int x, int y) {
01131 _input_devices[0].set_pointer_in_window(x, y);
01132 }
01133
01134
01135
01136
01137
01138
01139 void wcrGraphicsWindow::handle_mouse_entry(int state) {
01140 if (state == MOUSE_EXITED) {
01141 _input_devices[0].set_pointer_out_of_window();
01142 }
01143 }
01144
01145
01146
01147
01148
01149
01150 void wcrGraphicsWindow::
01151 handle_keypress(ButtonHandle key, int x, int y) {
01152 _input_devices[0].set_pointer_in_window(x, y);
01153 if (key != ButtonHandle::none()) {
01154 _input_devices[0].button_down(key);
01155 }
01156 }
01157
01158
01159
01160
01161
01162
01163 void wcrGraphicsWindow::
01164 handle_keyrelease(ButtonHandle key) {
01165 if (key != ButtonHandle::none()) {
01166 _input_devices[0].button_up(key);
01167 }
01168 }
01169
01170 void INLINE process_1_event() {
01171 MSG msg;
01172
01173 if (!GetMessage(&msg, NULL, 0, 0)) {
01174
01175 DestroyAllWindows(false);
01176 exit(msg.wParam);
01177 }
01178
01179
01180 TranslateMessage(&msg);
01181
01182 DispatchMessage(&msg);
01183 }
01184
01185 void INLINE wcrGraphicsWindow::process_events() {
01186 if (_window_inactive) {
01187
01188
01189
01190 while(_window_inactive && (!_return_control_to_app)) {
01191 process_1_event();
01192 }
01193 _return_control_to_app = false;
01194
01195 } else {
01196 MSG msg;
01197
01198
01199 while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
01200 process_1_event();
01201 }
01202 }
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 bool wcrGraphicsWindow::
01216 supports_update() const {
01217 return true;
01218 }
01219
01220
01221
01222
01223
01224
01225 void wcrGraphicsWindow::update() {
01226 #ifdef DO_PSTATS
01227 _show_code_pcollector.stop();
01228
01229 if (!_window_inactive) {
01230 PStatClient::main_tick();
01231 }
01232 #endif
01233
01234 process_events();
01235
01236 if (_window_inactive) {
01237
01238 if (_idle_callback)
01239 call_idle_callback();
01240 return;
01241 }
01242
01243 call_draw_callback(true);
01244
01245 if (_idle_callback)
01246 call_idle_callback();
01247
01248 #ifdef DO_PSTATS
01249 _show_code_pcollector.start();
01250 #endif
01251 }
01252
01253
01254
01255
01256
01257
01258 void wcrGraphicsWindow::enable_mouse_input(bool val) {
01259 _mouse_input_enabled = val;
01260 }
01261
01262
01263
01264
01265
01266
01267 void wcrGraphicsWindow::enable_mouse_motion(bool val) {
01268 _mouse_motion_enabled = val;
01269 }
01270
01271
01272
01273
01274
01275
01276 void wcrGraphicsWindow::enable_mouse_passive_motion(bool val) {
01277 _mouse_passive_motion_enabled = val;
01278 }
01279
01280
01281
01282
01283
01284
01285 void wcrGraphicsWindow::make_current() {
01286
01287 chromium.MakeCurrent(0, 0, _context);
01288 #if 0 //[
01289 if ((_hdc==NULL)||(_context==NULL)||(_window_inactive)) {
01290 return;
01291 }
01292
01293 DO_PSTATS_STUFF(PStatTimer timer(_make_current_pcollector);)
01294
01295
01296 GLint current_context = 0;
01297
01298 HDC current_dc = NULL;
01299
01300 if ((current_context != (int)_context) || (current_dc != _hdc)) {
01301 #if 1 //[
01302 chromium.MakeCurrent(_hdc, 0, _context);
01303 #else //][
01304 if (!chromium.MakeCurrent(_hdc, 0, _context)) {
01305 PrintErrorMessage(LAST_ERROR);
01306 }
01307 #endif //]
01308 }
01309 #endif //]
01310
01311 report_errors();
01312 }
01313
01314
01315
01316
01317
01318
01319 void wcrGraphicsWindow::unmake_current() {
01320 report_errors();
01321
01322 #if 1 //[
01323 chromium.MakeCurrent(0, 0, 0);
01324 #else //][
01325 if (!chromium.MakeCurrent(NULL, NULL, 0)) {
01326 PrintErrorMessage(LAST_ERROR);
01327 }
01328 #endif //]
01329 }
01330
01331 int wcrGraphicsWindow::get_depth_bitwidth() {
01332 return _pixelformat.cDepthBits;
01333 }
01334
01335
01336
01337
01338
01339
01340
01341 TypeHandle wcrGraphicsWindow::
01342 get_gsg_type() const {
01343 return CRGraphicsStateGuardian::get_class_type();
01344 }
01345
01346 GraphicsWindow *wcrGraphicsWindow::
01347 make_wcrGraphicsWindow(const FactoryParams ¶ms) {
01348 GraphicsWindow::WindowPipe *pipe_param;
01349 if (!get_param_into(pipe_param, params)) {
01350 wcrdisplay_cat.error()
01351 << "No pipe specified for window creation!" << endl;
01352 return NULL;
01353 }
01354
01355 GraphicsPipe *pipe = pipe_param->get_pipe();
01356
01357 GraphicsWindow::WindowProps *props_param;
01358 if (!get_param_into(props_param, params)) {
01359 return new wcrGraphicsWindow(pipe);
01360 } else {
01361 return new wcrGraphicsWindow(pipe, props_param->get_properties());
01362 }
01363 }
01364
01365 TypeHandle wcrGraphicsWindow::get_class_type() {
01366 return _type_handle;
01367 }
01368
01369 void wcrGraphicsWindow::init_type() {
01370 GraphicsWindow::init_type();
01371 register_type(_type_handle, "wcrGraphicsWindow",
01372 GraphicsWindow::get_class_type());
01373 }
01374
01375 TypeHandle wcrGraphicsWindow::get_type() const {
01376 return get_class_type();
01377 }
01378
01379
01380
01381
01382
01383
01384 LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
01385 HWND_PANDAWIN_MAP::iterator pwin;
01386 pwin=hwnd_pandawin_map.find(hwnd);
01387
01388 if (pwin!=hwnd_pandawin_map.end()) {
01389 wcrGraphicsWindow *wcrwinptr=(*pwin).second;
01390 return wcrwinptr->window_proc(hwnd, msg, wparam, lparam);
01391 } else if (global_wcrwinptr!=NULL){
01392
01393 return global_wcrwinptr->window_proc(hwnd, msg, wparam, lparam);
01394 } else {
01395
01396 return DefWindowProc(hwnd, msg, wparam, lparam);
01397 }
01398 }
01399
01400 void wcrGraphicsWindow::deactivate_window() {
01401
01402
01403
01404 if ((!_props._fullscreen) || _exiting_window || _window_inactive || _active_minimized_fullscreen) {
01405 #ifdef _DEBUG
01406 if (wcrdisplay_cat.is_spam())
01407 wcrdisplay_cat.spam() << "deactivate_window called, but ignored in current mode" << endl;
01408 #endif
01409 return;
01410 }
01411
01412 throw_event("PandaPaused");
01413
01414 if (!bResponsive_minimized_fullscreen_window) {
01415 if (wcrdisplay_cat.is_spam())
01416 wcrdisplay_cat.spam() << "WCR window deactivated, releasing gl context and waiting...\n";
01417
01418 _window_inactive = true;
01419 unmake_current();
01420 } else {
01421 _active_minimized_fullscreen = true;
01422 assert(_props._fullscreen);
01423
01424 if (wcrdisplay_cat.is_spam())
01425 wcrdisplay_cat.spam() << "WCR window minimized from fullscreen mode, remaining active...\n";
01426 }
01427
01428
01429
01430 WINDOWPLACEMENT wndpl;
01431 wndpl.length=sizeof(WINDOWPLACEMENT);
01432
01433 if (!GetWindowPlacement(_mwindow,&wndpl)) {
01434 wcrdisplay_cat.error() << "GetWindowPlacement failed!\n";
01435 return;
01436 }
01437
01438 if ((wndpl.showCmd!=SW_MINIMIZE)&&(wndpl.showCmd!=SW_SHOWMINIMIZED)) {
01439 ShowWindow(_mwindow, SW_MINIMIZE);
01440 }
01441
01442
01443 ChangeDisplaySettings(NULL,0x0);
01444
01445 if (!bResponsive_minimized_fullscreen_window) {
01446 _PandaPausedTimer = SetTimer(_mwindow,PAUSED_TIMER_ID,1500,NULL);
01447 if (_PandaPausedTimer!=PAUSED_TIMER_ID) {
01448 wcrdisplay_cat.error() << "Error in SetTimer!\n";
01449 }
01450 }
01451
01452 if (_props._fullscreen) {
01453 throw_event("PandaRestarted");
01454 }
01455 }
01456
01457 void wcrGraphicsWindow::reactivate_window() {
01458 if (_window_inactive) {
01459 if (wcrdisplay_cat.is_spam())
01460 wcrdisplay_cat.spam() << "WCR window re-activated...\n";
01461
01462 _window_inactive = false;
01463
01464 if (_PandaPausedTimer!=NULL) {
01465 KillTimer(_mwindow,_PandaPausedTimer);
01466 _PandaPausedTimer = NULL;
01467 }
01468
01469
01470 SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
01471
01472 ChangeDisplaySettings(_pCurrent_display_settings,CDS_FULLSCREEN);
01473
01474 GdiFlush();
01475 make_current();
01476 } else if (_active_minimized_fullscreen) {
01477 if (wcrdisplay_cat.is_spam())
01478 wcrdisplay_cat.spam() << "redisplaying minimized fullscrn active WCR window...\n";
01479
01480
01481 SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
01482
01483 ChangeDisplaySettings(_pCurrent_display_settings,CDS_FULLSCREEN);
01484
01485 GdiFlush();
01486 make_current();
01487 _active_minimized_fullscreen = false;
01488 }
01489 }
01490
01491
01492
01493
01494
01495
01496 LONG WINAPI wcrGraphicsWindow::
01497 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
01498 int button = -1;
01499 int x, y;
01500
01501 switch (msg) {
01502 case WM_CREATE:
01503 break;
01504
01505 case WM_CLOSE:
01506 close_window();
01507
01508
01509
01510
01511
01512
01513
01514
01515 if (hwnd_pandawin_map.size()==0) {
01516 exit(0);
01517 }
01518 break;
01519
01520 case WM_MOVE:
01521
01522
01523
01524 break;
01525
01526
01527 case WM_ACTIVATEAPP: {
01528 #ifdef _DEBUG
01529 wcrdisplay_cat.spam() << "WM_ACTIVATEAPP(" << (bool)(wparam!=0) <<") received\n";
01530 #endif
01531
01532 if (!wparam) {
01533 deactivate_window();
01534 return 0;
01535 }
01536 break;
01537 }
01538
01539 case WM_EXITSIZEMOVE:
01540 #ifdef _DEBUG
01541 wcrdisplay_cat.spam() << "WM_EXITSIZEMOVE received" << endl;
01542 #endif
01543
01544 reactivate_window();
01545 handle_reshape();
01546 break;
01547
01548 case WM_ENTERSIZEMOVE:
01549 break;
01550
01551 case WM_SIZE: {
01552 DWORD width,height;
01553
01554 width = LOWORD(lparam); height = HIWORD(lparam);
01555 #ifdef _DEBUG
01556 {
01557 wcrdisplay_cat.spam() << "WM_SIZE received with width:" << width << " height: " << height << " flags: " <<
01558 ((wparam == SIZE_MAXHIDE)? "SIZE_MAXHIDE " : "") << ((wparam == SIZE_MAXSHOW)? "SIZE_MAXSHOW " : "") <<
01559 ((wparam == SIZE_MINIMIZED)? "SIZE_MINIMIZED " : "") << ((wparam == SIZE_RESTORED)? "SIZE_RESTORED " : "") <<
01560 ((wparam == SIZE_MAXIMIZED)? "SIZE_MAXIMIZED " : "") << endl;
01561 }
01562 #endif
01563 if (_mwindow==NULL)
01564 break;
01565
01566 if ((wparam==SIZE_MAXIMIZED) || (wparam==SIZE_RESTORED)) {
01567 reactivate_window();
01568
01569
01570 handle_reshape();
01571 }
01572 break;
01573 }
01574
01575 case WM_PAINT: {
01576 PAINTSTRUCT ps;
01577 BeginPaint(hwnd, &ps);
01578
01579 EndPaint(hwnd, &ps);
01580 return 0;
01581 }
01582
01583 case WM_IME_NOTIFY:
01584 if (wparam == IMN_SETOPENSTATUS) {
01585 HIMC hIMC = ImmGetContext(hwnd);
01586 nassertr(hIMC != 0, 0);
01587 _ime_open = (ImmGetOpenStatus(hIMC) != 0);
01588 ImmReleaseContext(hwnd, hIMC);
01589 }
01590 break;
01591
01592 case WM_IME_COMPOSITION:
01593 if (lparam & GCS_RESULTSTR) {
01594 HIMC hIMC = ImmGetContext(hwnd);
01595 nassertr(hIMC != 0, 0);
01596
01597 static const int max_ime_result = 128;
01598 static char ime_result[max_ime_result];
01599
01600 DWORD result_size =
01601 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
01602 ime_result, max_ime_result);
01603 ImmReleaseContext(hwnd, hIMC);
01604
01605
01606 wchar_t *ime_wchar_result = (wchar_t *)ime_result;
01607 for (DWORD i = 0; i < result_size / 2; i++) {
01608 _input_devices[0].keystroke(ime_wchar_result[i]);
01609 }
01610 }
01611 break;
01612
01613 case WM_CHAR:
01614
01615
01616
01617
01618
01619 if (!_ime_open && !_input_devices.empty()) {
01620 _input_devices[0].keystroke(wparam);
01621 }
01622 break;
01623
01624 case WM_SYSKEYDOWN:
01625
01626
01627
01628 if (wparam == VK_F10) {
01629 return 0;
01630 }
01631 break;
01632
01633 case WM_KEYDOWN: {
01634 POINT point;
01635
01636 GetCursorPos(&point);
01637 ScreenToClient(hwnd, &point);
01638
01639 #ifdef NDEBUG
01640 handle_keypress(lookup_key(wparam), point.x, point.y);
01641 #else
01642
01643 if (!((wparam=='V') && (GetKeyState(VK_CONTROL) < 0))) {
01644 handle_keypress(lookup_key(wparam), point.x, point.y);
01645 } else {
01646 HGLOBAL hglb;
01647 char *lptstr;
01648
01649 if (!IsClipboardFormatAvailable(CF_TEXT))
01650 return 0;
01651
01652 if (!OpenClipboard(NULL))
01653 return 0;
01654
01655 hglb = GetClipboardData(CF_TEXT);
01656 if (hglb!=NULL) {
01657 lptstr = (char *) GlobalLock(hglb);
01658 if (lptstr != NULL) {
01659 char *pChar;
01660 for(pChar=lptstr;*pChar!=NULL;pChar++) {
01661 handle_keypress(KeyboardButton::ascii_key((uchar)*pChar), point.x, point.y);
01662 }
01663 GlobalUnlock(hglb);
01664 }
01665 }
01666 CloseClipboard();
01667 }
01668 #endif
01669 break;
01670 }
01671
01672 case WM_SYSKEYUP:
01673 case WM_KEYUP:
01674 handle_keyrelease(lookup_key(wparam));
01675 break;
01676
01677 case WM_LBUTTONDOWN:
01678 button = 0;
01679 case WM_MBUTTONDOWN:
01680 if (button < 0)
01681 button = 1;
01682
01683 case WM_RBUTTONDOWN:
01684 if (button < 0)
01685 button = 2;
01686 SetCapture(hwnd);
01687
01688
01689 #define SET_MOUSE_COORD(iVal,VAL) { \
01690 iVal = VAL; \
01691 if (iVal & 0x8000) \
01692 iVal -= 0x10000; \
01693 }
01694
01695 SET_MOUSE_COORD(x,LOWORD(lparam));
01696 SET_MOUSE_COORD(y,HIWORD(lparam));
01697
01698
01699 handle_keypress(MouseButton::button(button), x, y);
01700 break;
01701 case WM_LBUTTONUP:
01702 button = 0;
01703 case WM_MBUTTONUP:
01704 if (button < 0)
01705 button = 1;
01706 case WM_RBUTTONUP:
01707 if (button < 0)
01708 button = 2;
01709 ReleaseCapture();
01710 #if 0
01711 SET_MOUSE_COORD(x,LOWORD(lparam));
01712 SET_MOUSE_COORD(y,HIWORD(lparam));
01713
01714 #endif
01715 handle_keyrelease(MouseButton::button(button));
01716 break;
01717
01718 case WM_MOUSEMOVE:
01719 SET_MOUSE_COORD(x,LOWORD(lparam));
01720 SET_MOUSE_COORD(y,HIWORD(lparam));
01721
01722 if (mouse_motion_enabled() &&
01723 (wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) {
01724
01725 handle_mouse_motion(x, y);
01726 } else if (mouse_passive_motion_enabled() &&
01727 ((wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)) {
01728
01729 handle_mouse_motion(x, y);
01730 }
01731 break;
01732
01733 case WM_SETFOCUS: {
01734
01735
01736 if (_mouse_entry_enabled) {
01737 make_current();
01738 handle_mouse_entry(MOUSE_ENTERED);
01739 }
01740
01741 POINT point;
01742 GetCursorPos(&point);
01743 ScreenToClient(hwnd, &point);
01744
01745
01746
01747
01748
01749
01750 int i;
01751 for(i=0;i<NUM_MODIFIER_KEYS;i++) {
01752 if (GetKeyState(hardcoded_modifier_buttons[i]) < 0)
01753 handle_keypress(lookup_key(hardcoded_modifier_buttons[i]),point.x,point.y);
01754 }
01755 return 0;
01756 }
01757
01758 case WM_KILLFOCUS: {
01759 if (_mouse_entry_enabled)
01760 handle_mouse_entry(MOUSE_EXITED);
01761
01762 int i;
01763 for(i=0;i<NUM_MODIFIER_KEYS;i++) {
01764 if (GetKeyState(hardcoded_modifier_buttons[i]) < 0)
01765 handle_keyrelease(lookup_key(hardcoded_modifier_buttons[i]));
01766 }
01767
01768 return 0;
01769 }
01770 break;
01771
01772 case WM_TIMER:
01773 if ((wparam==_PandaPausedTimer) && _window_inactive) {
01774
01775 _return_control_to_app = true;
01776
01777
01778
01779 }
01780
01781 break;
01782 }
01783
01784 return DefWindowProc(hwnd, msg, wparam, lparam);
01785 }
01786
01787
01788
01789
01790
01791
01792 ButtonHandle wcrGraphicsWindow::
01793 lookup_key(WPARAM wparam) const {
01794 switch(wparam) {
01795 case VK_BACK: return KeyboardButton::backspace();
01796 case VK_TAB: return KeyboardButton::tab();
01797 case VK_ESCAPE: return KeyboardButton::escape();
01798 case VK_SPACE: return KeyboardButton::space();
01799 case VK_UP: return KeyboardButton::up();
01800 case VK_DOWN: return KeyboardButton::down();
01801 case VK_LEFT: return KeyboardButton::left();
01802 case VK_RIGHT: return KeyboardButton::right();
01803 case VK_PRIOR: return KeyboardButton::page_up();
01804 case VK_NEXT: return KeyboardButton::page_down();
01805 case VK_HOME: return KeyboardButton::home();
01806 case VK_END: return KeyboardButton::end();
01807 case VK_F1: return KeyboardButton::f1();
01808 case VK_F2: return KeyboardButton::f2();
01809 case VK_F3: return KeyboardButton::f3();
01810 case VK_F4: return KeyboardButton::f4();
01811 case VK_F5: return KeyboardButton::f5();
01812 case VK_F6: return KeyboardButton::f6();
01813 case VK_F7: return KeyboardButton::f7();
01814 case VK_F8: return KeyboardButton::f8();
01815 case VK_F9: return KeyboardButton::f9();
01816 case VK_F10: return KeyboardButton::f10();
01817 case VK_F11: return KeyboardButton::f11();
01818 case VK_F12: return KeyboardButton::f12();
01819 case VK_INSERT: return KeyboardButton::insert();
01820 case VK_DELETE: return KeyboardButton::del();
01821 case VK_CAPITAL: return KeyboardButton::caps_lock();
01822 case VK_NUMLOCK: return KeyboardButton::num_lock();
01823 case VK_SCROLL: return KeyboardButton::scroll_lock();
01824 case VK_SNAPSHOT: return KeyboardButton::print_screen();
01825
01826 case VK_SHIFT:
01827 case VK_LSHIFT:
01828 case VK_RSHIFT:
01829 return KeyboardButton::shift();
01830
01831 case VK_CONTROL:
01832 case VK_LCONTROL:
01833 case VK_RCONTROL:
01834 return KeyboardButton::control();
01835
01836 case VK_MENU:
01837 case VK_LMENU:
01838 case VK_RMENU:
01839 return KeyboardButton::alt();
01840
01841 default:
01842 int key = MapVirtualKey(wparam, 2);
01843 if (isascii(key) && key != 0) {
01844 bool bCapsLockDown=((GetKeyState(VK_CAPITAL) & 0x1)!=0);
01845 bool bShiftUp = (GetKeyState(VK_SHIFT) >= 0);
01846 if (bShiftUp) {
01847 if (bCapsLockDown)
01848 key = toupper(key);
01849 else key = tolower(key);
01850 } else {
01851 switch(key) {
01852
01853 case '1': key = '!'; break;
01854 case '2': key = '@'; break;
01855 case '3': key = '#'; break;
01856 case '4': key = '$'; break;
01857 case '5': key = '%'; break;
01858 case '6': key = '^'; break;
01859 case '7': key = '&'; break;
01860 case '8': key = '*'; break;
01861 case '9': key = '('; break;
01862 case '0': key = ')'; break;
01863 case '-': key = '_'; break;
01864 case '=': key = '+'; break;
01865 case ',': key = '<'; break;
01866 case '.': key = '>'; break;
01867 case '/': key = '?'; break;
01868 case ';': key = ':'; break;
01869 case '\'': key = '"'; break;
01870 case '[': key = '{'; break;
01871 case ']': key = '}'; break;
01872 case '\\': key = '|'; break;
01873 case '`': key = '~'; break;
01874 default:
01875 if (bCapsLockDown)
01876 key = tolower(key);
01877 else key = toupper(key);
01878 }
01879 }
01880 return KeyboardButton::ascii_key((uchar)key);
01881 }
01882 break;
01883 }
01884 return ButtonHandle::none();
01885 }
01886
01887