Fullscreen and Fullscreen YouTube video fixes

This commit is contained in:
2026-05-14 19:52:38 +12:00
parent 6fac7e320b
commit 406d73c10f
6 changed files with 142 additions and 7 deletions
+36 -2
View File
@@ -211,6 +211,12 @@ void NebulaController::OnBrowserClosing(nebula::cef::BrowserRole role, CefRefPtr
menu_popup_browser_ = nullptr; menu_popup_browser_ = nullptr;
menu_popup_client_ = nullptr; menu_popup_client_ = nullptr;
} else { } else {
if (content_fullscreen_) {
const auto* active_tab = tabs_.ActiveTab();
if (active_tab && active_tab->browser && active_tab->browser->IsSame(browser)) {
SetContentFullscreen(false);
}
}
tabs_.ClearBrowser(browser); tabs_.ClearBrowser(browser);
} }
MaybeFinishShutdown(); MaybeFinishShutdown();
@@ -308,6 +314,15 @@ void NebulaController::OnContentFaviconChanged(CefRefPtr<CefBrowser> browser, co
tabs_.UpdateFavicon(browser, urls); tabs_.UpdateFavicon(browser, urls);
} }
void NebulaController::OnContentFullscreenChanged(CefRefPtr<CefBrowser> browser, bool fullscreen) {
const auto* active_tab = tabs_.ActiveTab();
if (!active_tab || !active_tab->browser || !active_tab->browser->IsSame(browser)) {
return;
}
SetContentFullscreen(fullscreen);
}
void NebulaController::OnPopupRequested(CefRefPtr<CefBrowser> browser, const std::string& target_url) { void NebulaController::OnPopupRequested(CefRefPtr<CefBrowser> browser, const std::string& target_url) {
if (!tabs_.OwnsBrowser(browser)) { if (!tabs_.OwnsBrowser(browser)) {
return; return;
@@ -445,7 +460,7 @@ void NebulaController::CreateMenuPopupBrowser() {
} }
void NebulaController::PositionMenuPopup() { void NebulaController::PositionMenuPopup() {
if (!window_ || !window_->hwnd() || !menu_popup_browser_) { if (content_fullscreen_ || !window_ || !window_->hwnd() || !menu_popup_browser_) {
return; return;
} }
@@ -493,19 +508,38 @@ void NebulaController::FreshReload() {
tabs_.LoadURL(WithCacheBuster(tab->url)); tabs_.LoadURL(WithCacheBuster(tab->url));
} }
void NebulaController::SetContentFullscreen(bool fullscreen) {
if (content_fullscreen_ == fullscreen) {
return;
}
content_fullscreen_ = fullscreen;
if (fullscreen) {
CloseMenuPopup();
}
SetBrowserVisible(chrome_browser_, !fullscreen);
if (window_) {
window_->SetFullscreen(fullscreen);
}
ResizeBrowsers();
}
void NebulaController::ResizeBrowsers() { void NebulaController::ResizeBrowsers() {
if (!window_) { if (!window_) {
return; return;
} }
const auto layout = window_->CurrentLayout(); const auto layout = window_->CurrentLayout(!content_fullscreen_);
if (chrome_browser_) { if (chrome_browser_) {
window_->ResizeChild(chrome_browser_->GetHost()->GetWindowHandle(), layout.chrome); window_->ResizeChild(chrome_browser_->GetHost()->GetWindowHandle(), layout.chrome);
} }
if (const auto* tab = tabs_.ActiveTab(); tab && tab->browser) { if (const auto* tab = tabs_.ActiveTab(); tab && tab->browser) {
window_->ResizeChild(tab->browser->GetHost()->GetWindowHandle(), layout.content); window_->ResizeChild(tab->browser->GetHost()->GetWindowHandle(), layout.content);
} }
if (!content_fullscreen_) {
PositionMenuPopup(); PositionMenuPopup();
}
} }
void NebulaController::SendChromeState(const nebula::browser::NebulaTab& tab) { void NebulaController::SendChromeState(const nebula::browser::NebulaTab& tab) {
+3
View File
@@ -34,6 +34,7 @@ public:
void OnContentLoadingStateChanged(CefRefPtr<CefBrowser> browser, bool is_loading) override; void OnContentLoadingStateChanged(CefRefPtr<CefBrowser> browser, bool is_loading) override;
void OnContentLoadProgressChanged(CefRefPtr<CefBrowser> browser, double progress) override; void OnContentLoadProgressChanged(CefRefPtr<CefBrowser> browser, double progress) override;
void OnContentFaviconChanged(CefRefPtr<CefBrowser> browser, const std::vector<std::string>& urls) override; void OnContentFaviconChanged(CefRefPtr<CefBrowser> browser, const std::vector<std::string>& urls) override;
void OnContentFullscreenChanged(CefRefPtr<CefBrowser> browser, bool fullscreen) override;
void OnPopupRequested(CefRefPtr<CefBrowser> browser, const std::string& target_url) override; void OnPopupRequested(CefRefPtr<CefBrowser> browser, const std::string& target_url) override;
bool ShouldBypassInsecureWarning(CefRefPtr<CefBrowser> browser, const std::string& target_url) override; bool ShouldBypassInsecureWarning(CefRefPtr<CefBrowser> browser, const std::string& target_url) override;
@@ -50,6 +51,7 @@ private:
void ToggleDevTools(); void ToggleDevTools();
void AdjustZoom(double delta); void AdjustZoom(double delta);
void FreshReload(); void FreshReload();
void SetContentFullscreen(bool fullscreen);
void ResizeBrowsers(); void ResizeBrowsers();
void SendChromeState(const nebula::browser::NebulaTab& tab); void SendChromeState(const nebula::browser::NebulaTab& tab);
void MaybeFinishShutdown(); void MaybeFinishShutdown();
@@ -59,6 +61,7 @@ private:
int show_command_ = SW_SHOWDEFAULT; int show_command_ = SW_SHOWDEFAULT;
bool closing_ = false; bool closing_ = false;
bool chrome_ready_ = false; bool chrome_ready_ = false;
bool content_fullscreen_ = false;
std::unique_ptr<nebula::window::NebulaWindow> window_; std::unique_ptr<nebula::window::NebulaWindow> window_;
nebula::browser::TabManager tabs_; nebula::browser::TabManager tabs_;
+7
View File
@@ -89,6 +89,13 @@ void NebulaBrowserClient::OnFaviconURLChange(CefRefPtr<CefBrowser> browser,
} }
} }
void NebulaBrowserClient::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen) {
CEF_REQUIRE_UI_THREAD();
if (role_ == BrowserRole::Content && delegate_) {
delegate_->OnContentFullscreenChanged(browser, fullscreen);
}
}
bool NebulaBrowserClient::OnPreKeyEvent(CefRefPtr<CefBrowser> browser, bool NebulaBrowserClient::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event, const CefKeyEvent& event,
CefEventHandle os_event, CefEventHandle os_event,
+2
View File
@@ -30,6 +30,7 @@ public:
virtual void OnContentLoadingStateChanged(CefRefPtr<CefBrowser> browser, bool is_loading) = 0; virtual void OnContentLoadingStateChanged(CefRefPtr<CefBrowser> browser, bool is_loading) = 0;
virtual void OnContentLoadProgressChanged(CefRefPtr<CefBrowser> browser, double progress) = 0; virtual void OnContentLoadProgressChanged(CefRefPtr<CefBrowser> browser, double progress) = 0;
virtual void OnContentFaviconChanged(CefRefPtr<CefBrowser> browser, const std::vector<std::string>& urls) = 0; virtual void OnContentFaviconChanged(CefRefPtr<CefBrowser> browser, const std::vector<std::string>& urls) = 0;
virtual void OnContentFullscreenChanged(CefRefPtr<CefBrowser> browser, bool fullscreen) = 0;
virtual void OnPopupRequested(CefRefPtr<CefBrowser> browser, const std::string& target_url) = 0; virtual void OnPopupRequested(CefRefPtr<CefBrowser> browser, const std::string& target_url) = 0;
virtual bool ShouldBypassInsecureWarning(CefRefPtr<CefBrowser> browser, const std::string& target_url) = 0; virtual bool ShouldBypassInsecureWarning(CefRefPtr<CefBrowser> browser, const std::string& target_url) = 0;
}; };
@@ -63,6 +64,7 @@ public:
const CefString& title) override; const CefString& title) override;
void OnFaviconURLChange(CefRefPtr<CefBrowser> browser, void OnFaviconURLChange(CefRefPtr<CefBrowser> browser,
const std::vector<CefString>& icon_urls) override; const std::vector<CefString>& icon_urls) override;
void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen) override;
bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser, bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event, const CefKeyEvent& event,
+87 -3
View File
@@ -23,6 +23,30 @@ RECT GetWorkArea() {
return work_area; return work_area;
} }
RECT GetMonitorWorkArea(HWND hwnd) {
MONITORINFO monitor_info = {};
monitor_info.cbSize = sizeof(monitor_info);
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor && GetMonitorInfoW(monitor, &monitor_info)) {
return monitor_info.rcWork;
}
return GetWorkArea();
}
RECT GetMonitorArea(HWND hwnd) {
MONITORINFO monitor_info = {};
monitor_info.cbSize = sizeof(monitor_info);
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor && GetMonitorInfoW(monitor, &monitor_info)) {
return monitor_info.rcMonitor;
}
return GetWorkArea();
}
bool IsResizeHit(LRESULT hit) { bool IsResizeHit(LRESULT hit) {
return hit == HTLEFT || hit == HTRIGHT || hit == HTTOP || hit == HTBOTTOM || return hit == HTLEFT || hit == HTRIGHT || hit == HTTOP || hit == HTBOTTOM ||
hit == HTTOPLEFT || hit == HTTOPRIGHT || hit == HTBOTTOMLEFT || hit == HTBOTTOMRIGHT; hit == HTTOPLEFT || hit == HTTOPRIGHT || hit == HTBOTTOMLEFT || hit == HTBOTTOMRIGHT;
@@ -125,14 +149,16 @@ bool NebulaWindow::Create(HINSTANCE instance, int show_command) {
return true; return true;
} }
BrowserLayout NebulaWindow::CurrentLayout() const { BrowserLayout NebulaWindow::CurrentLayout(bool show_chrome) const {
RECT client = {}; RECT client = {};
if (hwnd_) { if (hwnd_) {
GetClientRect(hwnd_, &client); GetClientRect(hwnd_, &client);
} }
BrowserLayout layout; BrowserLayout layout;
layout.chrome = {0, 0, client.right, std::min<LONG>(ScaleForDpi(chrome_height_dip_), client.bottom)}; layout.chrome = show_chrome
? RECT{0, 0, client.right, std::min<LONG>(ScaleForDpi(chrome_height_dip_), client.bottom)}
: RECT{0, 0, 0, 0};
layout.content = {0, layout.chrome.bottom, client.right, client.bottom}; layout.content = {0, layout.chrome.bottom, client.right, client.bottom};
return layout; return layout;
} }
@@ -160,13 +186,55 @@ void NebulaWindow::Minimize() {
} }
void NebulaWindow::ToggleMaximize() { void NebulaWindow::ToggleMaximize() {
if (!hwnd_) { if (!hwnd_ || fullscreen_) {
return; return;
} }
ShowWindow(hwnd_, IsZoomed(hwnd_) ? SW_RESTORE : SW_MAXIMIZE); ShowWindow(hwnd_, IsZoomed(hwnd_) ? SW_RESTORE : SW_MAXIMIZE);
} }
void NebulaWindow::SetFullscreen(bool fullscreen) {
if (!hwnd_ || fullscreen_ == fullscreen) {
return;
}
if (fullscreen) {
restore_style_ = GetWindowLongPtrW(hwnd_, GWL_STYLE);
restore_ex_style_ = GetWindowLongPtrW(hwnd_, GWL_EXSTYLE);
restore_placement_.length = sizeof(restore_placement_);
GetWindowPlacement(hwnd_, &restore_placement_);
fullscreen_ = true;
const RECT monitor = GetMonitorArea(hwnd_);
SetWindowLongPtrW(hwnd_, GWL_STYLE, restore_style_ & ~(WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
SetWindowLongPtrW(hwnd_, GWL_EXSTYLE, restore_ex_style_);
SetWindowPos(
hwnd_,
HWND_TOPMOST,
monitor.left,
monitor.top,
monitor.right - monitor.left,
monitor.bottom - monitor.top,
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
} else {
fullscreen_ = false;
SetWindowLongPtrW(hwnd_, GWL_STYLE, restore_style_);
SetWindowLongPtrW(hwnd_, GWL_EXSTYLE, restore_ex_style_);
SetWindowPlacement(hwnd_, &restore_placement_);
SetWindowPos(
hwnd_,
HWND_NOTOPMOST,
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
ApplyWindowFrameStyle(hwnd_);
}
NotifyResize();
}
void NebulaWindow::Close() { void NebulaWindow::Close() {
if (hwnd_) { if (hwnd_) {
SendMessageW(hwnd_, WM_CLOSE, 0, 0); SendMessageW(hwnd_, WM_CLOSE, 0, 0);
@@ -335,6 +403,18 @@ LRESULT NebulaWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) {
return 0; return 0;
} }
case WM_GETMINMAXINFO: {
const RECT work_area = GetMonitorWorkArea(hwnd_);
const RECT monitor_area = GetMonitorArea(hwnd_);
auto* minmax = reinterpret_cast<MINMAXINFO*>(lparam);
minmax->ptMaxPosition.x = work_area.left - monitor_area.left;
minmax->ptMaxPosition.y = work_area.top - monitor_area.top;
minmax->ptMaxSize.x = work_area.right - work_area.left;
minmax->ptMaxSize.y = work_area.bottom - work_area.top;
return 0;
}
case WM_CLOSE: case WM_CLOSE:
if (delegate_) { if (delegate_) {
delegate_->OnWindowCloseRequested(); delegate_->OnWindowCloseRequested();
@@ -409,6 +489,10 @@ LRESULT NebulaWindow::HitTestPoint(POINT point) const {
RECT window = {}; RECT window = {};
GetWindowRect(hwnd_, &window); GetWindowRect(hwnd_, &window);
if (fullscreen_ || IsZoomed(hwnd_)) {
return HTCLIENT;
}
const int resize_border = ScaleForDpi(resize_border_dip_); const int resize_border = ScaleForDpi(resize_border_dip_);
const bool left = point.x >= window.left && point.x < window.left + resize_border; const bool left = point.x >= window.left && point.x < window.left + resize_border;
const bool right = point.x < window.right && point.x >= window.right - resize_border; const bool right = point.x < window.right && point.x >= window.right - resize_border;
+6 -1
View File
@@ -26,11 +26,12 @@ public:
bool Create(HINSTANCE instance, int show_command); bool Create(HINSTANCE instance, int show_command);
HWND hwnd() const { return hwnd_; } HWND hwnd() const { return hwnd_; }
BrowserLayout CurrentLayout() const; BrowserLayout CurrentLayout(bool show_chrome = true) const;
void ResizeChild(HWND child, const RECT& rect) const; void ResizeChild(HWND child, const RECT& rect) const;
void Minimize(); void Minimize();
void ToggleMaximize(); void ToggleMaximize();
void SetFullscreen(bool fullscreen);
void Close(); void Close();
void BeginDrag(); void BeginDrag();
void SetTitle(const std::wstring& title); void SetTitle(const std::wstring& title);
@@ -53,6 +54,10 @@ private:
WindowDelegate* delegate_ = nullptr; WindowDelegate* delegate_ = nullptr;
HINSTANCE instance_ = nullptr; HINSTANCE instance_ = nullptr;
HWND hwnd_ = nullptr; HWND hwnd_ = nullptr;
bool fullscreen_ = false;
LONG_PTR restore_style_ = 0;
LONG_PTR restore_ex_style_ = 0;
WINDOWPLACEMENT restore_placement_ = {sizeof(WINDOWPLACEMENT)};
UINT dpi_ = 96; UINT dpi_ = 96;
int resize_border_dip_ = 8; int resize_border_dip_ = 8;
int chrome_height_dip_ = 104; int chrome_height_dip_ = 104;