Fix Win32Window::resize breaking angle_tests.

We were messing up the client rect on resize, which caused the
ReadPixels checks to mess up around the window edges. Disabling
the window styles on the test windows masked this bug. Fix this
by using a style-less child window inside the parent window.
This gives us access to window styles for the samples project,
along with the ability to use tiny 1x1 windows for testing.

BUG=angle:730

Change-Id: Ic6dd931df7b4e32fbbcacbb004d3bbc49917f658
Reviewed-on: https://chromium-review.googlesource.com/217024
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/tests/angle_tests/ANGLETest.cpp b/tests/angle_tests/ANGLETest.cpp
index 0e1c3e2..1bed5e7 100644
--- a/tests/angle_tests/ANGLETest.cpp
+++ b/tests/angle_tests/ANGLETest.cpp
@@ -22,6 +22,8 @@
 void ANGLETest::TearDown()
 {
     swapBuffers();
+    mOSWindow->messageLoop();
+
     if (!destroyEGLContext())
     {
         FAIL() << "egl context destruction failed.";
diff --git a/util/OSWindow.h b/util/OSWindow.h
index f83514f..7d25a1e 100644
--- a/util/OSWindow.h
+++ b/util/OSWindow.h
@@ -31,7 +31,7 @@
     virtual void messageLoop() = 0;
 
     bool popEvent(Event *event);
-    void pushEvent(Event event);
+    virtual void pushEvent(Event event);
 
     virtual void setMousePosition(int x, int y) = 0;
     virtual bool resize(int width, int height) = 0;
diff --git a/util/win32/Win32Window.cpp b/util/win32/Win32Window.cpp
index 2b492ea..ec5a0c0 100644
--- a/util/win32/Win32Window.cpp
+++ b/util/win32/Win32Window.cpp
@@ -362,8 +362,8 @@
 }
 
 Win32Window::Win32Window()
-    : mClassName(),
-      mNativeWindow(0),
+    : mNativeWindow(0),
+      mParentWindow(0),
       mNativeDisplay(0)
 {
 }
@@ -377,36 +377,55 @@
 {
     destroy();
 
-    mClassName = name;
+    mParentClassName = name;
+    mChildClassName = name + "Child";
 
-    WNDCLASSEXA windowClass = { 0 };
-    windowClass.cbSize = sizeof(WNDCLASSEXA);
-    windowClass.style = CS_OWNDC;
-    windowClass.lpfnWndProc = WndProc;
-    windowClass.cbClsExtra = 0;
-    windowClass.cbWndExtra = 0;
-    windowClass.hInstance = GetModuleHandle(NULL);
-    windowClass.hIcon = NULL;
-    windowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
-    windowClass.hbrBackground = 0;
-    windowClass.lpszMenuName = NULL;
-    windowClass.lpszClassName = mClassName.c_str();
-    if (!RegisterClassExA(&windowClass))
+    WNDCLASSEXA parentWindowClass = { 0 };
+    parentWindowClass.cbSize = sizeof(WNDCLASSEXA);
+    parentWindowClass.style = 0;
+    parentWindowClass.lpfnWndProc = WndProc;
+    parentWindowClass.cbClsExtra = 0;
+    parentWindowClass.cbWndExtra = 0;
+    parentWindowClass.hInstance = GetModuleHandle(NULL);
+    parentWindowClass.hIcon = NULL;
+    parentWindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
+    parentWindowClass.hbrBackground = 0;
+    parentWindowClass.lpszMenuName = NULL;
+    parentWindowClass.lpszClassName = mParentClassName.c_str();
+    if (!RegisterClassExA(&parentWindowClass))
     {
         return false;
     }
 
-    DWORD style = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_SYSMENU;
-    DWORD extendedStyle = WS_EX_APPWINDOW;
+    WNDCLASSEXA childWindowClass = { 0 };
+    childWindowClass.cbSize = sizeof(WNDCLASSEXA);
+    childWindowClass.style = CS_OWNDC;
+    childWindowClass.lpfnWndProc = WndProc;
+    childWindowClass.cbClsExtra = 0;
+    childWindowClass.cbWndExtra = 0;
+    childWindowClass.hInstance = GetModuleHandle(NULL);
+    childWindowClass.hIcon = NULL;
+    childWindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
+    childWindowClass.hbrBackground = 0;
+    childWindowClass.lpszMenuName = NULL;
+    childWindowClass.lpszClassName = mChildClassName.c_str();
+    if (!RegisterClassExA(&childWindowClass))
+    {
+        return false;
+    }
+
+    DWORD parentStyle = WS_VISIBLE | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
+    DWORD parentExtendedStyle = WS_EX_APPWINDOW;
 
     RECT sizeRect = { 0, 0, width, height };
-    AdjustWindowRectEx(&sizeRect, style, false, extendedStyle);
+    AdjustWindowRectEx(&sizeRect, parentStyle, FALSE, parentExtendedStyle);
 
-    mNativeWindow = CreateWindowExA(extendedStyle, mClassName.c_str(), name.c_str(), style, CW_USEDEFAULT, CW_USEDEFAULT,
+    mParentWindow = CreateWindowExA(parentExtendedStyle, mParentClassName.c_str(), name.c_str(), parentStyle, CW_USEDEFAULT, CW_USEDEFAULT,
                                     sizeRect.right - sizeRect.left, sizeRect.bottom - sizeRect.top, NULL, NULL,
                                     GetModuleHandle(NULL), this);
 
-    ShowWindow(mNativeWindow, SW_SHOW);
+    mNativeWindow = CreateWindowExA(0, mChildClassName.c_str(), name.c_str(), WS_VISIBLE | WS_CHILD, 0, 0, width, height,
+                                    mParentWindow, NULL, GetModuleHandle(NULL), this);
 
     mNativeDisplay = GetDC(mNativeWindow);
     if (!mNativeDisplay)
@@ -432,7 +451,14 @@
         mNativeWindow = 0;
     }
 
-    UnregisterClassA(mClassName.c_str(), NULL);
+    if (mParentWindow)
+    {
+        DestroyWindow(mParentWindow);
+        mParentWindow = 0;
+    }
+
+    UnregisterClassA(mParentClassName.c_str(), NULL);
+    UnregisterClassA(mChildClassName.c_str(), NULL);
 }
 
 EGLNativeWindowType Win32Window::getNativeWindow() const
@@ -475,24 +501,54 @@
 
 bool Win32Window::resize(int width, int height)
 {
+    if (width == mWidth && height == mHeight)
+    {
+        return true;
+    }
+
     RECT windowRect;
-    if (!GetWindowRect(mNativeWindow, &windowRect))
+    if (!GetWindowRect(mParentWindow, &windowRect))
     {
         return false;
     }
 
-    if (!MoveWindow(mNativeWindow, windowRect.left, windowRect.top, width, height, FALSE))
+    RECT clientRect;
+    if (!GetClientRect(mParentWindow, &clientRect))
     {
         return false;
     }
 
-    mWidth = width;
-    mHeight = height;
+    LONG diffX = (windowRect.right - windowRect.left) - clientRect.right;
+    LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom;
+    if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY, FALSE))
+    {
+        return false;
+    }
+
+    if (!MoveWindow(mNativeWindow, 0, 0, width, height, FALSE))
+    {
+        return false;
+    }
 
     return true;
 }
 
 bool Win32Window::setVisible(bool isVisible)
 {
-    return (ShowWindow(mNativeWindow, isVisible ? SW_SHOW : SW_HIDE) == TRUE);
+    int flag = (isVisible ? SW_SHOW : SW_HIDE);
+
+    return (ShowWindow(mNativeWindow, flag) == TRUE) &&
+           (ShowWindow(mParentWindow, flag) == TRUE);
+}
+
+void Win32Window::pushEvent(Event event)
+{
+    OSWindow::pushEvent(event);
+
+    switch (event.Type)
+    {
+      case Event::EVENT_RESIZED:
+        MoveWindow(mNativeWindow, 0, 0, mWidth, mHeight, FALSE);
+        break;
+    }
 }
diff --git a/util/win32/Win32Window.h b/util/win32/Win32Window.h
index 2429f33..7510f60 100644
--- a/util/win32/Win32Window.h
+++ b/util/win32/Win32Window.h
@@ -25,17 +25,18 @@
 
     void messageLoop();
 
-    bool popEvent(Event *event);
-    void pushEvent(Event event);
+    virtual void pushEvent(Event event);
 
     void setMousePosition(int x, int y);
     bool resize(int width, int height);
     bool setVisible(bool isVisible);
 
   private:
-    std::string mClassName;
+    std::string mParentClassName;
+    std::string mChildClassName;
 
     EGLNativeWindowType mNativeWindow;
+    EGLNativeWindowType mParentWindow;
     EGLNativeDisplayType mNativeDisplay;
 };