Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / platform / graphics / win / FullScreenController.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28
29 #if ENABLE(FULLSCREEN_API)
30
31 #include "FullScreenController.h"
32
33 #include "Element.h"
34 #include "FullScreenControllerClient.h"
35 #include "IntRect.h"
36 #include "MediaPlayerPrivateFullscreenWindow.h"
37 #include "Timer.h"
38 #include "WebCoreInstanceHandle.h"
39 #include <wtf/RefPtr.h>
40
41 using namespace WebCore;
42
43 static const int kFullScreenAnimationDuration = 500; // milliseconds 
44
45 class FullScreenController::Private : public MediaPlayerPrivateFullscreenClient  {
46 public:
47     Private(FullScreenController* controller, FullScreenControllerClient* client) 
48         : m_controller(controller)
49         , m_client(client)
50         , m_originalHost(0)
51         , m_isFullScreen(false)
52         , m_isEnteringFullScreen(false)
53         , m_isExitingFullScreen(false)
54     {
55     }
56     virtual ~Private() = default;
57
58     virtual LRESULT fullscreenClientWndProc(HWND, UINT, WPARAM, LPARAM);
59     
60     FullScreenController* m_controller;
61     FullScreenControllerClient* m_client;
62     std::unique_ptr<MediaPlayerPrivateFullscreenWindow> m_fullScreenWindow;
63     std::unique_ptr<MediaPlayerPrivateFullscreenWindow> m_backgroundWindow;
64     IntRect m_fullScreenFrame;
65     IntRect m_originalFrame;
66     HWND m_originalHost;
67     bool m_isFullScreen;
68     bool m_isEnteringFullScreen;
69     bool m_isExitingFullScreen;
70 };
71
72 LRESULT FullScreenController::Private::fullscreenClientWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
73 {
74     LRESULT lResult = 0;
75
76     switch (msg) {
77     case WM_MOVE:
78         m_fullScreenFrame.setX(LOWORD(lParam));
79         m_fullScreenFrame.setY(HIWORD(lParam));
80         break;
81     case WM_SIZE:
82         m_fullScreenFrame.setWidth(LOWORD(lParam));
83         m_fullScreenFrame.setHeight(HIWORD(lParam));
84         if (m_client->fullScreenClientWindow())
85             ::SetWindowPos(m_client->fullScreenClientWindow(), 0, 0, 0, m_fullScreenFrame.width(), m_fullScreenFrame.height(), SWP_NOREPOSITION  | SWP_NOMOVE);
86         break;
87     case WM_ACTIVATE:
88         // Because m_fullScreenWindow is a topmost window, we need to exit full screen explicitly when it's deactivated.
89         if (!wParam && m_fullScreenWindow && (hwnd == m_fullScreenWindow->hwnd()))
90             m_controller->exitFullScreen();
91         break;
92     case WM_KEYDOWN:
93         if (wParam == VK_ESCAPE) {
94             m_controller->exitFullScreen();
95             break;
96         }
97         FALLTHROUGH;
98     default:
99         lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
100     }
101
102     return lResult;
103 }
104
105 FullScreenController::FullScreenController(FullScreenControllerClient* client)
106     : m_private(std::make_unique<Private>(this, client))
107 {
108     ASSERT_ARG(client, client);
109 }
110
111 FullScreenController::~FullScreenController() = default;
112
113 bool FullScreenController::isFullScreen() const
114 {
115     return m_private->m_isFullScreen;
116 }
117
118 void FullScreenController::enterFullScreen()
119 {
120     if (m_private->m_isFullScreen || m_private->m_isEnteringFullScreen)
121         return;
122     m_private->m_isFullScreen = true;
123     m_private->m_isEnteringFullScreen = true;
124
125     m_private->m_client->fullScreenClientSaveScrollPosition();
126
127     m_private->m_originalHost = m_private->m_client->fullScreenClientParentWindow();
128     RECT originalFrame = {0, 0, 0, 0};
129     ::GetClientRect(m_private->m_client->fullScreenClientWindow(), &originalFrame);
130     ::MapWindowPoints(m_private->m_client->fullScreenClientWindow(), m_private->m_originalHost, reinterpret_cast<LPPOINT>(&originalFrame), 2);
131     m_private->m_originalFrame = originalFrame;
132
133     ASSERT(!m_private->m_backgroundWindow);
134     m_private->m_backgroundWindow = std::make_unique<MediaPlayerPrivateFullscreenWindow>(m_private.get());
135     m_private->m_backgroundWindow->createWindow(0);
136     ::AnimateWindow(m_private->m_backgroundWindow->hwnd(), kFullScreenAnimationDuration, AW_BLEND | AW_ACTIVATE);
137
138     m_private->m_client->fullScreenClientWillEnterFullScreen();
139     ASSERT(!m_private->m_fullScreenWindow);
140     m_private->m_fullScreenWindow = std::make_unique<MediaPlayerPrivateFullscreenWindow>(m_private.get());
141     ASSERT(m_private->m_fullScreenWindow);
142     m_private->m_fullScreenWindow->createWindow(0);
143
144     m_private->m_client->fullScreenClientSetParentWindow(m_private->m_fullScreenWindow->hwnd());
145
146     IntRect viewFrame(IntPoint(), m_private->m_fullScreenFrame.size());
147     ::SetWindowPos(m_private->m_fullScreenWindow->hwnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
148     ::SetWindowPos(m_private->m_client->fullScreenClientWindow(), HWND_TOP, 0, 0, viewFrame.width(), viewFrame.height(), SWP_NOACTIVATE);
149
150     m_private->m_client->fullScreenClientDidEnterFullScreen();
151     m_private->m_client->fullScreenClientForceRepaint();
152 }
153
154 void FullScreenController::enterFullScreenRepaintCompleted()
155 {
156     if (!m_private->m_isEnteringFullScreen)
157         return;
158     m_private->m_isEnteringFullScreen = false;
159
160     // Normally, when the background fullscreen window is animated in, the Windows taskbar will be hidden, but this doesn't always work for some reason.
161     // Setting the real fullscreen window to be a topmost window will force the taskbar to be hidden when we call AnimateWindow() below if it wasn't before.
162     ::SetWindowPos(m_private->m_fullScreenWindow->hwnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
163     ::AnimateWindow(m_private->m_fullScreenWindow->hwnd(), kFullScreenAnimationDuration, AW_BLEND | AW_ACTIVATE);
164 }
165
166 void FullScreenController::exitFullScreen()
167 {
168     if (!m_private->m_isFullScreen || m_private->m_isExitingFullScreen)
169         return;
170     m_private->m_isFullScreen = false;
171     m_private->m_isExitingFullScreen = true;
172
173     ::AnimateWindow(m_private->m_fullScreenWindow->hwnd(), kFullScreenAnimationDuration, AW_HIDE | AW_BLEND);
174
175     m_private->m_client->fullScreenClientWillExitFullScreen();
176     m_private->m_client->fullScreenClientSetParentWindow(m_private->m_originalHost);
177     m_private->m_fullScreenWindow = nullptr;
178
179     ::SetWindowPos(m_private->m_client->fullScreenClientWindow(), 0, m_private->m_originalFrame.x(), m_private->m_originalFrame.y(), m_private->m_originalFrame.width(), m_private->m_originalFrame.height(), SWP_NOACTIVATE | SWP_NOZORDER);
180
181     m_private->m_client->fullScreenClientRestoreScrollPosition();
182     m_private->m_client->fullScreenClientDidExitFullScreen();
183     m_private->m_client->fullScreenClientForceRepaint();
184 }
185
186 void FullScreenController::exitFullScreenRepaintCompleted()
187 {
188     if (!m_private->m_isExitingFullScreen)
189         return;
190     m_private->m_isExitingFullScreen = false;
191
192     ASSERT(m_private->m_backgroundWindow);
193     ::AnimateWindow(m_private->m_backgroundWindow->hwnd(), kFullScreenAnimationDuration, AW_HIDE | AW_BLEND);
194     m_private->m_backgroundWindow = nullptr;
195 }
196
197 void FullScreenController::repaintCompleted()
198 {
199     if (m_private->m_isEnteringFullScreen)
200         enterFullScreenRepaintCompleted();
201     else if (m_private->m_isExitingFullScreen)
202         exitFullScreenRepaintCompleted();
203 }
204
205 void FullScreenController::close()
206 {
207     if (!m_private->m_isFullScreen)
208         return;
209     m_private->m_isFullScreen = false;
210
211     m_private->m_client->fullScreenClientWillExitFullScreen();
212     m_private->m_client->fullScreenClientSetParentWindow(m_private->m_originalHost);
213     m_private->m_fullScreenWindow = nullptr;
214
215     m_private->m_client->fullScreenClientDidExitFullScreen();
216     ::SetWindowPos(m_private->m_client->fullScreenClientWindow(), 0, m_private->m_originalFrame.x(), m_private->m_originalFrame.y(), m_private->m_originalFrame.width(), m_private->m_originalFrame.height(), SWP_NOACTIVATE | SWP_NOZORDER);
217     ::RedrawWindow(m_private->m_client->fullScreenClientWindow(), 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN);
218     m_private->m_backgroundWindow = nullptr;
219 }
220 #endif