diff --git a/panda/src/pnmtext/freetypeFace.I b/panda/src/pnmtext/freetypeFace.I index c2fd271562..bc09446ebc 100644 --- a/panda/src/pnmtext/freetypeFace.I +++ b/panda/src/pnmtext/freetypeFace.I @@ -13,7 +13,7 @@ //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// -// Function: TextFont::get_face +// Function: FreetypeFace::get_face // Access: Published // Description: Retrieves the internal freetype face. //////////////////////////////////////////////////////////////////// @@ -23,11 +23,14 @@ get_face() { } //////////////////////////////////////////////////////////////////// -// Function: TextFont::set_face +// Function: FreetypeFace::set_face // Access: Published // Description: Sets the internal freetype face. //////////////////////////////////////////////////////////////////// INLINE void FreetypeFace:: set_face(FT_Face face) { + if (_face != NULL){ + FT_Done_Face(_face); + } _face = face; } diff --git a/panda/src/pnmtext/freetypeFont.cxx b/panda/src/pnmtext/freetypeFont.cxx index 565819f289..ba0b7d77c4 100644 --- a/panda/src/pnmtext/freetypeFont.cxx +++ b/panda/src/pnmtext/freetypeFont.cxx @@ -42,7 +42,7 @@ FreetypeFont:: FreetypeFont() { _font_loaded = false; - _face = new FreetypeFace(); + _face = NULL; _point_size = text_point_size; _requested_pixels_per_unit = text_pixels_per_unit; @@ -91,6 +91,7 @@ load_font(const Filename &font_filename, int face_index) { (const FT_Byte *)_raw_font_data.data(), _raw_font_data.length(), face_index, &face); + _face = new FreetypeFace(); _face->set_face(face); } @@ -135,6 +136,7 @@ load_font(const char *font_data, int data_length, int face_index) { error = FT_New_Memory_Face(_ft_library, (const FT_Byte *)font_data, data_length, face_index, &face); + _face = new FreetypeFace(); _face->set_face(face); if (error == FT_Err_Unknown_File_Format) { diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 8a2b867eb9..ab9596b835 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -379,12 +379,7 @@ open_window() { // even before it gives us a handle. Warning: this is not thread // safe! _creating_window = this; - bool opened; - if (is_fullscreen()) { - opened = open_fullscreen_window(); - } else { - opened = open_regular_window(); - } + bool opened = open_graphic_window(is_fullscreen()); _creating_window = (WinGraphicsWindow *)NULL; if (!opened) { @@ -737,96 +732,12 @@ support_overlay_window(bool) { } //////////////////////////////////////////////////////////////////// -// Function: WinGraphicsWindow::open_fullscreen_window +// Function: WinGraphicsWindow::open_graphic_window // Access: Private -// Description: Creates a fullscreen-style window. +// Description: Creates a regular or fullscreen window. //////////////////////////////////////////////////////////////////// bool WinGraphicsWindow:: -open_fullscreen_window() -{ - // from MSDN: - // An OpenGL window has its own pixel format. Because of this, only - // device contexts retrieved for the client area of an OpenGL - // window are allowed to draw into the window. As a result, an - // OpenGL window should be created with the WS_CLIPCHILDREN and - // WS_CLIPSIBLINGS styles. Additionally, the window class attribute - // should not include the CS_PARENTDC style. - DWORD window_style = - WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - - if (!_properties.has_size()) { - // Just pick a stupid default size if one isn't specified. - _properties.set_size(640, 480); - } - - // No parent window for a fullscreen window. - _parent_window_handle = NULL; - - HWND hDesktopWindow = GetDesktopWindow(); - HDC scrnDC = GetDC(hDesktopWindow); - DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL); - // DWORD drvr_ver = GetDeviceCaps(scrnDC, DRIVERVERSION); - // DWORD cur_scrnwidth = GetDeviceCaps(scrnDC, HORZRES); - // DWORD cur_scrnheight = GetDeviceCaps(scrnDC, VERTRES); - ReleaseDC(hDesktopWindow, scrnDC); - - DWORD dwWidth = _properties.get_x_size(); - DWORD dwHeight = _properties.get_y_size(); - DWORD dwFullScreenBitDepth = cur_bitdepth; - - reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth); - if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth, - _fullscreen_display_mode)) { - windisplay_cat.error() - << "Videocard has no supported display resolutions at specified res (" - << dwWidth << " x " << dwHeight << " x " << dwFullScreenBitDepth <<")\n"; - return false; - } - - string title; - if (_properties.has_title()) { - title = _properties.get_title(); - } - - // I'd prefer to CreateWindow after DisplayChange in case it messes - // up GL somehow, but I need the window's black background to cover - // up the desktop during the mode change - const WindowClass &wclass = register_window_class(_properties); - HINSTANCE hinstance = GetModuleHandle(NULL); - - _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style, - 0, 0, dwWidth, dwHeight, - hDesktopWindow, NULL, hinstance, 0); - if (!_hWnd) { - windisplay_cat.error() - << "CreateWindow() failed!" << endl; - show_error_message(); - return false; - } - - int chg_result = ChangeDisplaySettings(&_fullscreen_display_mode, - CDS_FULLSCREEN); - if (chg_result != DISP_CHANGE_SUCCESSFUL) { - windisplay_cat.error() - << "ChangeDisplaySettings failed (error code: " - << chg_result << ") for specified res (" << dwWidth - << " x " << dwHeight << " x " << dwFullScreenBitDepth - << "), " << _fullscreen_display_mode.dmDisplayFrequency << "Hz\n"; - return false; - } - - _properties.set_origin(0, 0); - _properties.set_size(dwWidth, dwHeight); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: WinGraphicsWindow::open_regular_window -// Access: Private -// Description: Creates a non-fullscreen window, on the desktop. -//////////////////////////////////////////////////////////////////// -bool WinGraphicsWindow:: -open_regular_window() { +open_graphic_window(bool fullscreen) { // from MSDN: // An OpenGL window has its own pixel format. Because of this, only // device contexts retrieved for the client area of an OpenGL @@ -837,7 +748,9 @@ open_regular_window() { DWORD window_style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - if (!_properties.get_undecorated()) { + if (fullscreen){ + window_style |= WS_SYSMENU; + } else if (!_properties.get_undecorated()) { window_style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); if (!_properties.get_fixed_size()) { @@ -846,44 +759,52 @@ open_regular_window() { window_style |= WS_BORDER; } } - - int x_origin = 0; - int y_origin = 0; - if (_properties.has_origin()) { - x_origin = _properties.get_x_origin(); - y_origin = _properties.get_y_origin(); - } - - int x_size = 100; - int y_size = 100; - if (_properties.has_size()) { - x_size = _properties.get_x_size(); - y_size = _properties.get_y_size(); - } - - RECT win_rect; - SetRect(&win_rect, x_origin, y_origin, - x_origin + x_size, y_origin + y_size); - // compute window size based on desired client area size - if (!AdjustWindowRect(&win_rect, window_style, FALSE)) { - windisplay_cat.error() - << "AdjustWindowRect failed!" << endl; - return false; - } - string title; if (_properties.has_title()) { title = _properties.get_title(); } - if (_properties.has_origin()) { - x_origin = win_rect.left; - y_origin = win_rect.top; + if (!_properties.has_size()) { + //Just pick a conservative default size if one isn't specified. + _properties.set_size(640, 480); + } - } else { - x_origin = CW_USEDEFAULT; - y_origin = CW_USEDEFAULT; + int x_origin = 0; + int y_origin = 0; + if (!fullscreen && _properties.has_origin()) { + x_origin = _properties.get_x_origin(); + y_origin = _properties.get_y_origin(); + } + + int x_size = _properties.get_x_size(); + int y_size = _properties.get_y_size(); + + int clientAreaWidth = x_size; + int clientAreaHeight = y_size; + + if (!fullscreen){ + RECT win_rect; + SetRect(&win_rect, x_origin, y_origin, + x_origin + x_size, y_origin + y_size); + + // compute window size based on desired client area size + if (!AdjustWindowRect(&win_rect, window_style, FALSE)) { + windisplay_cat.error() + << "AdjustWindowRect failed!" << endl; + return false; + } + + if (_properties.has_origin()) { + x_origin = win_rect.left; + y_origin = win_rect.top; + + } else { + x_origin = CW_USEDEFAULT; + y_origin = CW_USEDEFAULT; + } + clientAreaWidth = win_rect.right - win_rect.left; + clientAreaHeight = win_rect.bottom - win_rect.top; } const WindowClass &wclass = register_window_class(_properties); @@ -891,38 +812,41 @@ open_regular_window() { _hparent = NULL; - WindowHandle *window_handle = _properties.get_parent_window(); - if (window_handle != NULL) { - windisplay_cat.info() - << "Got parent_window " << *window_handle << "\n"; - WindowHandle::OSHandle *os_handle = window_handle->get_os_handle(); - if (os_handle != NULL) { + if (!fullscreen){ + WindowHandle *window_handle = _properties.get_parent_window(); + if (window_handle != NULL) { windisplay_cat.info() - << "os_handle type " << os_handle->get_type() << "\n"; - - if (os_handle->is_of_type(NativeWindowHandle::WinHandle::get_class_type())) { - NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle); - _hparent = win_handle->get_handle(); - } else if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) { - NativeWindowHandle::IntHandle *int_handle = DCAST(NativeWindowHandle::IntHandle, os_handle); - _hparent = (HWND)int_handle->get_handle(); + << "Got parent_window " << *window_handle << "\n"; + WindowHandle::OSHandle *os_handle = window_handle->get_os_handle(); + if (os_handle != NULL) { + windisplay_cat.info() + << "os_handle type " << os_handle->get_type() << "\n"; + + if (os_handle->is_of_type(NativeWindowHandle::WinHandle::get_class_type())) { + NativeWindowHandle::WinHandle *win_handle = DCAST(NativeWindowHandle::WinHandle, os_handle); + _hparent = win_handle->get_handle(); + } else if (os_handle->is_of_type(NativeWindowHandle::IntHandle::get_class_type())) { + NativeWindowHandle::IntHandle *int_handle = DCAST(NativeWindowHandle::IntHandle, os_handle); + _hparent = (HWND)int_handle->get_handle(); + } } } + _parent_window_handle = window_handle; + } else { + _parent_window_handle = NULL; } - _parent_window_handle = window_handle; - if (!_hparent) { + if (!_hparent) { // This can be a regular window or a fullscreen window _hWnd = CreateWindow(wclass._name.c_str(), title.c_str(), window_style, x_origin, y_origin, - win_rect.right - win_rect.left, - win_rect.bottom - win_rect.top, + clientAreaWidth, + clientAreaHeight, NULL, NULL, hinstance, 0); - - } else { + } else { // This is a regular window with a parent x_origin = 0; y_origin = 0; - if (_properties.has_origin()) { + if (!fullscreen && _properties.has_origin()) { x_origin = _properties.get_x_origin(); y_origin = _properties.get_y_origin(); } @@ -954,6 +878,51 @@ open_regular_window() { return false; } + // I'd prefer to CreateWindow after DisplayChange in case it messes + // up GL somehow, but I need the window's black background to cover + // up the desktop during the mode change. + + if (fullscreen){ + HWND hDesktopWindow = GetDesktopWindow(); + HDC scrnDC = GetDC(hDesktopWindow); + DWORD cur_bitdepth = GetDeviceCaps(scrnDC, BITSPIXEL); + // DWORD drvr_ver = GetDeviceCaps(scrnDC, DRIVERVERSION); + // DWORD cur_scrnwidth = GetDeviceCaps(scrnDC, HORZRES); + // DWORD cur_scrnheight = GetDeviceCaps(scrnDC, VERTRES); + ReleaseDC(hDesktopWindow, scrnDC); + + DWORD dwWidth = _properties.get_x_size(); + DWORD dwHeight = _properties.get_y_size(); + DWORD dwFullScreenBitDepth = cur_bitdepth; + + DEVMODE dm; + reconsider_fullscreen_size(dwWidth, dwHeight, dwFullScreenBitDepth); + if (!find_acceptable_display_mode(dwWidth, dwHeight, dwFullScreenBitDepth, dm)) { + windisplay_cat.error() + << "Videocard has no supported display resolutions at specified res (" + << dwWidth << " x " << dwHeight << " x " << dwFullScreenBitDepth <<")\n"; + return false; + } + + dm.dmPelsWidth = dwWidth; + dm.dmPelsHeight = dwHeight; + dm.dmBitsPerPel = dwFullScreenBitDepth; + int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); + + if (chg_result != DISP_CHANGE_SUCCESSFUL) { + windisplay_cat.error() + << "ChangeDisplaySettings failed (error code: " + << chg_result << ") for specified res (" << dwWidth + << " x " << dwHeight << " x " << dwFullScreenBitDepth + << "), " << _fullscreen_display_mode.dmDisplayFrequency << "Hz\n"; + return false; + } + + _properties.set_origin(0, 0); + _properties.set_size(dwWidth, dwHeight); + + } + return true; } @@ -2165,7 +2134,21 @@ find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp, if ((dm.dmPelsWidth == dwWidth) && (dm.dmPelsHeight == dwHeight) && (dm.dmBitsPerPel == bpp)) { - return true; + cout << "[FS FOUND] " << dwWidth << "x" << dwHeight << "@" << bpp << endl; + // We want to modify the current DEVMODE rather than using a fresh one in order + // to work around a Windows 7 bug. + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)){ + dm.dmPelsWidth = dwWidth; + dm.dmPelsHeight = dwHeight; + dm.dmBitsPerPel = bpp; + return true; + } else { + windisplay_cat.error() + << "Couldn't retrieve active device mode.\n"; + return false; + } } modenum++; } diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 9afbf71aac..684fbcd3a0 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -89,8 +89,7 @@ protected: virtual void support_overlay_window(bool flag); private: - bool open_fullscreen_window(); - bool open_regular_window(); + bool open_graphic_window(bool fullscreen); void adjust_z_order(); void adjust_z_order(WindowProperties::ZOrder last_z_order, WindowProperties::ZOrder this_z_order);