diff options
-rw-r--r-- | include/views/SkOSWindow_Win.h | 47 | ||||
-rw-r--r-- | src/views/win/SkOSWindow_win.cpp | 145 | ||||
-rw-r--r-- | src/views/win/skia_win.cpp | 72 | ||||
-rw-r--r-- | tools/VisualBench.cpp | 2 |
4 files changed, 207 insertions, 59 deletions
diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h index fe65459f4d..7a0cb7c0fd 100644 --- a/include/views/SkOSWindow_Win.h +++ b/include/views/SkOSWindow_Win.h @@ -11,6 +11,8 @@ #define SkOSWindow_Win_DEFINED #include "SkWindow.h" +#include "../../src/core/SkFunction.h" +#include "../../src/core/SkTHash.h" #if SK_ANGLE #include "EGL/egl.h" @@ -18,12 +20,13 @@ class SkOSWindow : public SkWindow { public: - SkOSWindow(void* hwnd); - virtual ~SkOSWindow(); + struct WindowInit { + TCHAR* fClass; + HINSTANCE fInstance; + }; - void* getHWND() const { return fHWND; } - void setSize(int width, int height); - void updateSize(); + SkOSWindow(const void* winInit); + virtual ~SkOSWindow(); static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); @@ -49,6 +52,24 @@ public: SK_WM_SkTimerID = 0xFFFF // just need a non-zero value }; + void setFullscreen(bool) override; + void setVsync(bool) override; + void closeWindow() override; + + static SkOSWindow* GetOSWindowForHWND(void* hwnd) { + SkOSWindow** win = gHwndToOSWindowMap.find(hwnd); + if (!win) { + return NULL; + } + return *win; + } + + // Iterates SkFunction over all the SkOSWindows and their corresponding HWNDs. + // The void* argument to the SkFunction is a HWND. + static void ForAllWindows(const SkFunction<void(void*, SkOSWindow**)>& f) { + gHwndToOSWindowMap.foreach(f); + } + protected: virtual bool quitOnDeactivate() { return true; } @@ -60,6 +81,9 @@ protected: virtual void onSetTitle(const char title[]); private: + static SkTHashMap<void*, SkOSWindow*> gHwndToOSWindowMap; + + WindowInit fWinInit; void* fHWND; void doPaint(void* ctx); @@ -74,10 +98,23 @@ private: #endif // SK_ANGLE #endif // SK_SUPPORT_GPU + bool fFullscreen; + struct SavedWindowState { + bool fZoomed; + LONG fStyle; + LONG fExStyle; + RECT fRect; + LONG fScreenWidth; + LONG fScreenHeight; + LONG fScreenBits; + void* fHWND; + } fSavedWindowState; + HMENU fMBar; SkBackEndTypes fAttached; + void updateSize(); #if SK_SUPPORT_GPU bool attachGL(int msaaSampleCount, AttachmentInfo* info); void detachGL(); diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp index 91ff17ed65..a0288d973c 100644 --- a/src/views/win/SkOSWindow_win.cpp +++ b/src/views/win/SkOSWindow_win.cpp @@ -32,18 +32,21 @@ #endif -static SkOSWindow* gCurrOSWin; -static HWND gEventTarget; - #define WM_EVENT_CALLBACK (WM_USER+0) -void post_skwinevent() +void post_skwinevent(HWND hwnd) { - PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0); + PostMessage(hwnd, WM_EVENT_CALLBACK, 0, 0); } -SkOSWindow::SkOSWindow(void* hWnd) { - fHWND = hWnd; +SkTHashMap<void*, SkOSWindow*> SkOSWindow::gHwndToOSWindowMap; + +SkOSWindow::SkOSWindow(const void* winInit) { + fWinInit = *(const WindowInit*)winInit; + + fHWND = CreateWindow(fWinInit.fClass, NULL, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, fWinInit.fInstance, NULL); + gHwndToOSWindowMap.set(fHWND, this); #if SK_SUPPORT_GPU #if SK_ANGLE fDisplay = EGL_NO_DISPLAY; @@ -53,10 +56,11 @@ SkOSWindow::SkOSWindow(void* hWnd) { fHGLRC = NULL; #endif fAttached = kNone_BackEndType; - gEventTarget = (HWND)hWnd; + fFullscreen = false; } SkOSWindow::~SkOSWindow() { + this->setFullscreen(false); #if SK_SUPPORT_GPU if (fHGLRC) { wglDeleteContext((HGLRC)fHGLRC); @@ -78,6 +82,8 @@ SkOSWindow::~SkOSWindow() { } #endif // SK_ANGLE #endif // SK_SUPPORT_GPU + gHwndToOSWindowMap.remove(fHWND); + DestroyWindow((HWND)fHWND); } static SkKey winToskKey(WPARAM vk) { @@ -159,7 +165,7 @@ bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_EVENT_CALLBACK: if (SkEvent::ProcessEvent()) { - post_skwinevent(); + post_skwinevent(hWnd); } return true; } @@ -208,14 +214,12 @@ void SkOSWindow::doPaint(void* ctx) { } } -#if 0 void SkOSWindow::updateSize() { RECT r; - GetWindowRect((HWND)this->getHWND(), &r); + GetWindowRect((HWND)fHWND, &r); this->resize(r.right - r.left, r.bottom - r.top); } -#endif void SkOSWindow::onHandleInval(const SkIRect& r) { RECT rect; @@ -290,8 +294,9 @@ static SkKey raw2key(uint32_t raw) void SkEvent::SignalNonEmptyQueue() { - post_skwinevent(); - //SkDebugf("signal nonempty\n"); + SkOSWindow::ForAllWindows([](void* hWND, SkOSWindow**) { + post_skwinevent((HWND)hWND); + }); } static UINT_PTR gTimer; @@ -367,7 +372,6 @@ void SkOSWindow::detachGL() { } void SkOSWindow::presentGL() { - glFlush(); HDC dc = GetDC((HWND)fHWND); SwapBuffers(dc); ReleaseDC((HWND)fHWND, dc); @@ -609,4 +613,115 @@ void SkOSWindow::present() { } } +void SkOSWindow::setFullscreen(bool fullscreen) { + if (fullscreen == fFullscreen) { + return; + } + if (fHGLRC) { + this->detachGL(); + } + // This is hacked together from various sources on the web. It can certainly be improved and be + // made more robust. + if (fullscreen) { + // Save current window/resolution information. + fSavedWindowState.fZoomed = SkToBool(IsZoomed((HWND)fHWND)); + if (fSavedWindowState.fZoomed) { + SendMessage((HWND)fHWND, WM_SYSCOMMAND, SC_RESTORE, 0); + } + fSavedWindowState.fStyle = GetWindowLong((HWND)fHWND, GWL_STYLE); + fSavedWindowState.fExStyle = GetWindowLong((HWND)fHWND, GWL_EXSTYLE); + GetWindowRect((HWND)fHWND, &fSavedWindowState.fRect); + DEVMODE dmScreenSettings; // Device Mode + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared + dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dmScreenSettings); + fSavedWindowState.fScreenWidth = dmScreenSettings.dmPelsWidth; + fSavedWindowState.fScreenHeight = dmScreenSettings.dmPelsHeight; + fSavedWindowState.fScreenBits = dmScreenSettings.dmBitsPerPel; + fSavedWindowState.fHWND = fHWND; + } + + if (fullscreen) { + // Try different sizes to find an allowed setting? Use ChangeDisplaySettingsEx? + static const int kWidth = 1280; + static const int kHeight = 1024; + DEVMODE dmScreenSettings; + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = kWidth; + dmScreenSettings.dmPelsHeight = kHeight; + dmScreenSettings.dmBitsPerPel = 32; + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { + return; + } + RECT WindowRect; + WindowRect.left = 0; + WindowRect.right = kWidth; + WindowRect.top = 0; + WindowRect.bottom = kHeight; + ShowCursor(FALSE); + AdjustWindowRectEx(&WindowRect, WS_POPUP, FALSE, WS_EX_APPWINDOW); + HWND fsHWND = CreateWindowEx( + WS_EX_APPWINDOW, + fWinInit.fClass, + NULL, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, + 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, + NULL, + NULL, + fWinInit.fInstance, + NULL + ); + if (!fsHWND) { + return; + } + // Hide the old window and set the entry in the global mapping for this SkOSWindow to the + // new HWND. + ShowWindow((HWND)fHWND, SW_HIDE); + gHwndToOSWindowMap.remove(fHWND); + fHWND = fsHWND; + gHwndToOSWindowMap.set(fHWND, this); + this->updateSize(); + } else { + DEVMODE dmScreenSettings; + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = fSavedWindowState.fScreenWidth; + dmScreenSettings.dmPelsHeight = fSavedWindowState.fScreenHeight; + dmScreenSettings.dmBitsPerPel = fSavedWindowState.fScreenBits; + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { + return; + } + gHwndToOSWindowMap.remove(fHWND); + DestroyWindow((HWND)fHWND); + fHWND = fSavedWindowState.fHWND; + gHwndToOSWindowMap.set(fHWND, this); + ShowWindow((HWND)fHWND, SW_SHOW); + SetWindowLong((HWND)fHWND, GWL_STYLE, fSavedWindowState.fStyle); + SetWindowLong((HWND)fHWND, GWL_EXSTYLE, fSavedWindowState.fExStyle); + + int width = fSavedWindowState.fRect.right - fSavedWindowState.fRect.left; + int height = fSavedWindowState.fRect.right - fSavedWindowState.fRect.left; + SetWindowPos((HWND)fHWND, NULL, fSavedWindowState.fRect.left, fSavedWindowState.fRect.top, + width, height, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + if (fSavedWindowState.fZoomed) { + SendMessage((HWND)fHWND, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + } + this->updateSize(); + } + fFullscreen = fullscreen; +} + +void SkOSWindow::setVsync(bool enable) { + SkWGLExtensions wgl; + wgl.swapInterval(enable ? 1 : 0); +} + +void SkOSWindow::closeWindow() { + this->setFullscreen(false); + DestroyWindow((HWND)fHWND); +} #endif diff --git a/src/views/win/skia_win.cpp b/src/views/win/skia_win.cpp index e2f0fdaf94..859bb6f63c 100644 --- a/src/views/win/skia_win.cpp +++ b/src/views/win/skia_win.cpp @@ -13,9 +13,8 @@ #define MAX_LOADSTRING 100 // Global Variables: -HINSTANCE hInst; // current instance -TCHAR szTitle[] = _T("SampleApp"); // The title bar text -TCHAR szWindowClass[] = _T("SAMPLEAPP"); // the main window class name +HINSTANCE gHInst; // current instance +TCHAR gSZWindowClass[] = _T("SkiaApp"); // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); @@ -24,9 +23,9 @@ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, - int nCmdShow) + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); @@ -77,16 +76,16 @@ ATOM MyRegisterClass(HINSTANCE hInstance) wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = NULL; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = NULL; wcex.hCursor = NULL; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = NULL; - wcex.lpszClassName = szWindowClass; + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = gSZWindowClass; wcex.hIconSm = NULL; return RegisterClassEx(&wcex); @@ -95,8 +94,6 @@ ATOM MyRegisterClass(HINSTANCE hInstance) #include "SkOSWindow_Win.h" extern SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv); -static SkOSWindow* gSkWind; - char* tchar_to_utf8(const TCHAR* str) { #ifdef _UNICODE int size = WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), NULL, 0, NULL, NULL); @@ -125,16 +122,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, LPTSTR lpCmdLine) { application_init(); - hInst = hInstance; // Store instance handle in our global variable - - HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); - - if (!hWnd) - { - return FALSE; - } - + gHInst = hInstance; // Store instance handle in our global variable char* argv[4096]; int argc = 0; TCHAR exename[1024], *next; @@ -148,12 +136,18 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, LPTSTR lpCmdLine) arg = _tcstok_s(NULL, _T(" "), &next); } - gSkWind = create_sk_window(hWnd, argc, argv); + SkOSWindow::WindowInit winInit; + winInit.fInstance = gHInst; + winInit.fClass = gSZWindowClass; + + create_sk_window(&winInit, argc, argv); for (int i = 0; i < argc; ++i) { sk_free(argv[i]); } - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); + SkOSWindow::ForAllWindows([nCmdShow](void* hWnd, SkOSWindow**){ + ShowWindow((HWND)hWnd, nCmdShow); + UpdateWindow((HWND)hWnd); } + ); return TRUE; } @@ -171,16 +165,18 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, LPTSTR lpCmdLine) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { - case WM_COMMAND: - return DefWindowProc(hWnd, message, wParam, lParam); - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - if (gSkWind->wndProc(hWnd, message, wParam, lParam)) { - return 0; - } else { + case WM_COMMAND: return DefWindowProc(hWnd, message, wParam, lParam); + case WM_DESTROY: + PostQuitMessage(0); + break; + default: { + SkOSWindow* window = SkOSWindow::GetOSWindowForHWND(hWnd); + if (window && window->wndProc(hWnd, message, wParam, lParam)) { + return 0; + } else { + return DefWindowProc(hWnd, message, wParam, lParam); + } } } return 0; diff --git a/tools/VisualBench.cpp b/tools/VisualBench.cpp index c0343d715f..5cd1ebd57a 100644 --- a/tools/VisualBench.cpp +++ b/tools/VisualBench.cpp @@ -101,13 +101,13 @@ bool VisualBench::setupBackend() { this->setVisibleP(true); this->setClipToBounds(false); + this->setFullscreen(true); if (!this->attach(kNativeGL_BackEndType, FLAGS_msaa, &fAttachmentInfo)) { SkDebugf("Not possible to create backend.\n"); INHERITED::detach(); return false; } - this->setFullscreen(true); this->setVsync(false); this->resetContext(); return true; |