Compare commits

...

4 Commits

Author SHA1 Message Date
Nik Pavlov 0a627230ac views: Fix overlay bounds outside of window (fixes #3457) 2024-10-15 18:28:13 +00:00
Marshall Greenblatt f94ac23e52 wrapper: Add missing algorithm include (fixes #3804) 2024-10-15 14:05:14 -04:00
Nik Pavlov 745a4d6e3b ceftests: Simplify ViewsWindowTest.WindowAccelerator test (see #3188)
Remove the CefWindowDelegate::OnKeyEvent check as that method
is not currently triggered with the Chrome runtime (see #3797).
2024-10-15 18:01:11 +00:00
Nik Pavlov 29ef97d6b5 mac: views: Always initialize CommandDispatcher (see #3188)
ChromeCommandDispatcherDelegate forwards accelerator events to
the FocusManager through NativeWidgetMacNSWindowHost::
HandleAccelerator. Always initialize it so that accelerators also
work in a CefWindow without a BrowserView.
2024-10-15 17:58:23 +00:00
5 changed files with 20 additions and 69 deletions

View File

@ -52,6 +52,7 @@ class CefNativeWidgetMac : public views::NativeWidgetMac {
bool IsCefWindowInitialized() const; bool IsCefWindowInitialized() const;
raw_ptr<BrowserView, AcrossTasksDanglingUntriaged> browser_view_ = nullptr; raw_ptr<BrowserView, AcrossTasksDanglingUntriaged> browser_view_ = nullptr;
bool initialized_ = false;
}; };
#endif // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_ #endif // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_

View File

@ -138,7 +138,12 @@ void CefNativeWidgetMac::OnWindowFullscreenTransitionComplete() {
} }
void CefNativeWidgetMac::OnWindowInitialized() { void CefNativeWidgetMac::OnWindowInitialized() {
if (!browser_view_) { // This connects the native widget with the command dispatcher so accelerators
// work even if a browser_view_ is not created later.
// The initialized_ check is necessary because the method can be called twice:
// 1. From NativeWidgetMac::InitNativeWidget
// 2. From ChromeBrowserFrame::Init
if (initialized_) {
return; return;
} }
@ -146,10 +151,12 @@ void CefNativeWidgetMac::OnWindowInitialized() {
if (auto* bridge = GetInProcessNSWindowBridge()) { if (auto* bridge = GetInProcessNSWindowBridge()) {
bridge->SetCommandDispatcher([[ChromeCommandDispatcherDelegate alloc] init], bridge->SetCommandDispatcher([[ChromeCommandDispatcherDelegate alloc] init],
[[BrowserWindowCommandHandler alloc] init]); [[BrowserWindowCommandHandler alloc] init]);
} else { initialized_ = true;
} else if (browser_view_) {
if (auto* host = GetHostForBrowser(browser_view_->browser())) { if (auto* host = GetHostForBrowser(browser_view_->browser())) {
host->GetAppShim()->CreateCommandDispatcherForWidget( host->GetAppShim()->CreateCommandDispatcherForWidget(
GetNSWindowHost()->bridged_native_widget_id()); GetNSWindowHost()->bridged_native_widget_id());
initialized_ = true;
} }
} }
} }

View File

@ -280,18 +280,17 @@ void CefOverlayViewHost::SetOverlayBounds(const gfx::Rect& bounds) {
return; return;
} }
gfx::Rect new_bounds = bounds; // Empty bounds are not allowed.
if (bounds.IsEmpty()) {
// Keep the result inside the widget.
new_bounds.Intersect(window_view_->bounds());
if (new_bounds == bounds_) {
return; return;
} }
bounds_changing_ = true; bounds_changing_ = true;
bounds_ = bounds;
// Keep the result inside the widget.
bounds_.Intersect(window_view_->bounds());
bounds_ = new_bounds;
if (view_->size() != bounds_.size()) { if (view_->size() != bounds_.size()) {
view_->SetSize(bounds_.size()); view_->SetSize(bounds_.size());
} }

View File

@ -4,6 +4,7 @@
#include "include/wrapper/cef_message_router.h" #include "include/wrapper/cef_message_router.h"
#include <algorithm>
#include <limits> #include <limits>
#include <map> #include <map>
#include <set> #include <set>

View File

@ -522,68 +522,21 @@ void WindowIconFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
TestWindowDelegate::RunTest(event, std::move(config)); TestWindowDelegate::RunTest(event, std::move(config));
} }
const int kChar = 'A'; constexpr int kChar = 'A';
const int kCloseWindowId = 2; constexpr int kCloseWindowId = 2;
bool got_accelerator; bool got_accelerator;
int got_key_event_alt_count;
bool got_key_event_char;
void TriggerAccelerator(CefRefPtr<CefWindow> window) { void TriggerAccelerator(CefRefPtr<CefWindow> window) {
window->SendKeyPress(kChar, EVENTFLAG_ALT_DOWN); window->SendKeyPress(kChar, EVENTFLAG_ALT_DOWN);
} }
bool OnKeyEvent(CefRefPtr<CefWindow> window, const CefKeyEvent& event) {
if (event.type != KEYEVENT_RAWKEYDOWN) {
return false;
}
if (event.windows_key_code == VK_MENU) {
// First we get the ALT key press in all cases.
EXPECT_FALSE(got_key_event_char);
if (got_key_event_alt_count == 0) {
EXPECT_FALSE(got_accelerator);
} else {
EXPECT_TRUE(got_accelerator);
}
EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
got_key_event_alt_count++;
} else if (event.windows_key_code == kChar) {
// Then we get the char key press with the ALT modifier if the accelerator
// isn't registered.
EXPECT_TRUE(got_accelerator);
EXPECT_EQ(got_key_event_alt_count, 2);
EXPECT_FALSE(got_key_event_char);
EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
got_key_event_char = true;
// Call this method just to make sure it doesn't crash.
window->RemoveAllAccelerators();
// End the test by closing the Window.
window->Close();
return true;
}
return false;
}
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) { bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
EXPECT_FALSE(got_accelerator); EXPECT_FALSE(got_accelerator);
EXPECT_EQ(got_key_event_alt_count, 1);
EXPECT_FALSE(got_key_event_char);
EXPECT_EQ(kCloseWindowId, command_id); EXPECT_EQ(kCloseWindowId, command_id);
got_accelerator = true; got_accelerator = true;
// Remove the accelerator. window->Close();
window->RemoveAccelerator(kCloseWindowId);
// Now send the event without the accelerator registered. Should result in a
// call to OnKeyEvent.
TriggerAccelerator(window);
return true; return true;
} }
@ -598,25 +551,15 @@ void RunWindowAccelerator(CefRefPtr<CefWindow> window) {
void VerifyWindowAccelerator(CefRefPtr<CefWindow> window) { void VerifyWindowAccelerator(CefRefPtr<CefWindow> window) {
EXPECT_TRUE(got_accelerator); EXPECT_TRUE(got_accelerator);
EXPECT_EQ(got_key_event_alt_count, 2);
EXPECT_TRUE(got_key_event_char);
} }
// Expected order of events:
// 1. OnKeyEvent for ALT key press.
// 2. OnAccelerator for ALT+Char key press (with accelerator registered).
// 3. OnKeyEvent for ALT key press.
// 4. OnKeyEvent for ALT+Char key press (without accelerator registered).
void WindowAcceleratorImpl(CefRefPtr<CefWaitableEvent> event) { void WindowAcceleratorImpl(CefRefPtr<CefWaitableEvent> event) {
got_accelerator = false; got_accelerator = false;
got_key_event_alt_count = 0;
got_key_event_char = false;
auto config = std::make_unique<TestWindowDelegate::Config>(); auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowAccelerator); config->on_window_created = base::BindOnce(RunWindowAccelerator);
config->on_window_destroyed = base::BindOnce(VerifyWindowAccelerator); config->on_window_destroyed = base::BindOnce(VerifyWindowAccelerator);
config->on_accelerator = base::BindRepeating(OnAccelerator); config->on_accelerator = base::BindRepeating(OnAccelerator);
config->on_key_event = base::BindRepeating(OnKeyEvent);
config->close_window = false; config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config)); TestWindowDelegate::RunTest(event, std::move(config));
} }