mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-02 20:26:59 +01:00
Windows: Fix hidden dropdowns when the window is topmost (issue #1468)
Also add a --always-on-top flag to cefclient to allow easier testing of this behavior on Windows and Linux.
This commit is contained in:
parent
1928572b52
commit
c64898f9fc
@ -81,8 +81,8 @@ bool CefBrowserPlatformDelegateNativeLinux::CreateHostWindow() {
|
|||||||
// Add a reference that will be released in BrowserDestroyed().
|
// Add a reference that will be released in BrowserDestroyed().
|
||||||
browser_->AddRef();
|
browser_->AddRef();
|
||||||
|
|
||||||
CefWindowDelegateView* delegate_view =
|
CefWindowDelegateView* delegate_view = new CefWindowDelegateView(
|
||||||
new CefWindowDelegateView(GetBackgroundColor());
|
GetBackgroundColor(), window_x11_->TopLevelAlwaysOnTop());
|
||||||
delegate_view->Init(window_info_.window, browser_->web_contents(),
|
delegate_view->Init(window_info_.window, browser_->web_contents(),
|
||||||
gfx::Rect(gfx::Point(), rect.size()));
|
gfx::Rect(gfx::Point(), rect.size()));
|
||||||
|
|
||||||
|
@ -194,8 +194,15 @@ bool CefBrowserPlatformDelegateNativeWin::CreateHostWindow() {
|
|||||||
point =
|
point =
|
||||||
gfx::ToFlooredPoint(gfx::ScalePoint(gfx::PointF(point), 1.0f / scale));
|
gfx::ToFlooredPoint(gfx::ScalePoint(gfx::PointF(point), 1.0f / scale));
|
||||||
|
|
||||||
|
// Stay on top if top-most window hosting the web view is topmost.
|
||||||
|
HWND top_level_window = GetAncestor(window_info_.window, GA_ROOT);
|
||||||
|
DWORD top_level_window_ex_styles =
|
||||||
|
GetWindowLongPtr(top_level_window, GWL_EXSTYLE);
|
||||||
|
bool always_on_top =
|
||||||
|
(top_level_window_ex_styles & WS_EX_TOPMOST) == WS_EX_TOPMOST;
|
||||||
|
|
||||||
CefWindowDelegateView* delegate_view =
|
CefWindowDelegateView* delegate_view =
|
||||||
new CefWindowDelegateView(GetBackgroundColor());
|
new CefWindowDelegateView(GetBackgroundColor(), always_on_top);
|
||||||
delegate_view->Init(window_info_.window, browser_->web_contents(),
|
delegate_view->Init(window_info_.window, browser_->web_contents(),
|
||||||
gfx::Rect(0, 0, point.x(), point.y()));
|
gfx::Rect(0, 0, point.x(), point.y()));
|
||||||
|
|
||||||
|
@ -12,8 +12,11 @@
|
|||||||
#include "ui/views/layout/fill_layout.h"
|
#include "ui/views/layout/fill_layout.h"
|
||||||
#include "ui/views/widget/widget.h"
|
#include "ui/views/widget/widget.h"
|
||||||
|
|
||||||
CefWindowDelegateView::CefWindowDelegateView(SkColor background_color)
|
CefWindowDelegateView::CefWindowDelegateView(SkColor background_color,
|
||||||
: background_color_(background_color), web_view_(NULL) {}
|
bool always_on_top)
|
||||||
|
: background_color_(background_color),
|
||||||
|
web_view_(NULL),
|
||||||
|
always_on_top_(always_on_top) {}
|
||||||
|
|
||||||
void CefWindowDelegateView::Init(gfx::AcceleratedWidget parent_widget,
|
void CefWindowDelegateView::Init(gfx::AcceleratedWidget parent_widget,
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
@ -44,6 +47,8 @@ void CefWindowDelegateView::Init(gfx::AcceleratedWidget parent_widget,
|
|||||||
// CefBrowserHostImpl::PlatformSetFocus.
|
// CefBrowserHostImpl::PlatformSetFocus.
|
||||||
params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
|
params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
|
||||||
|
|
||||||
|
params.keep_on_top = always_on_top_;
|
||||||
|
|
||||||
// Results in a call to InitContent().
|
// Results in a call to InitContent().
|
||||||
widget->Init(params);
|
widget->Init(params);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class WebView;
|
|||||||
// will be deleted automatically when the associated root window is destroyed.
|
// will be deleted automatically when the associated root window is destroyed.
|
||||||
class CefWindowDelegateView : public views::WidgetDelegateView {
|
class CefWindowDelegateView : public views::WidgetDelegateView {
|
||||||
public:
|
public:
|
||||||
explicit CefWindowDelegateView(SkColor background_color);
|
CefWindowDelegateView(SkColor background_color, bool always_on_top);
|
||||||
|
|
||||||
// Create the Widget and associated root window.
|
// Create the Widget and associated root window.
|
||||||
void Init(gfx::AcceleratedWidget parent_widget,
|
void Init(gfx::AcceleratedWidget parent_widget,
|
||||||
@ -43,6 +43,7 @@ class CefWindowDelegateView : public views::WidgetDelegateView {
|
|||||||
private:
|
private:
|
||||||
SkColor background_color_;
|
SkColor background_color_;
|
||||||
views::WebView* web_view_;
|
views::WebView* web_view_;
|
||||||
|
bool always_on_top_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView);
|
DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView);
|
||||||
};
|
};
|
||||||
|
@ -396,3 +396,34 @@ void CefWindowX11::ContinueFocus() {
|
|||||||
browser_->SetFocus(true);
|
browser_->SetFocus(true);
|
||||||
focus_pending_ = false;
|
focus_pending_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CefWindowX11::TopLevelAlwaysOnTop() const {
|
||||||
|
::Window toplevel_window = FindToplevelParent(xdisplay_, xwindow_);
|
||||||
|
|
||||||
|
Atom state_atom = gfx::GetAtom("_NET_WM_STATE");
|
||||||
|
Atom state_keep_above = gfx::GetAtom("_NET_WM_STATE_KEEP_ABOVE");
|
||||||
|
Atom* states;
|
||||||
|
|
||||||
|
Atom actual_type;
|
||||||
|
int actual_format;
|
||||||
|
unsigned long num_items;
|
||||||
|
unsigned long bytes_after;
|
||||||
|
|
||||||
|
XGetWindowProperty(xdisplay_, toplevel_window, state_atom, 0, 1024,
|
||||||
|
x11::False, XA_ATOM, &actual_type, &actual_format,
|
||||||
|
&num_items, &bytes_after,
|
||||||
|
reinterpret_cast<unsigned char**>(&states));
|
||||||
|
|
||||||
|
bool always_on_top = false;
|
||||||
|
|
||||||
|
for (unsigned long i = 0; i < num_items; ++i) {
|
||||||
|
if (states[i] == state_keep_above) {
|
||||||
|
always_on_top = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(states);
|
||||||
|
|
||||||
|
return always_on_top;
|
||||||
|
}
|
||||||
|
@ -52,6 +52,8 @@ class CefWindowX11 : public ui::PlatformEventDispatcher {
|
|||||||
::Window xwindow() const { return xwindow_; }
|
::Window xwindow() const { return xwindow_; }
|
||||||
gfx::Rect bounds() const { return bounds_; }
|
gfx::Rect bounds() const { return bounds_; }
|
||||||
|
|
||||||
|
bool TopLevelAlwaysOnTop() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ContinueFocus();
|
void ContinueFocus();
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ namespace client {
|
|||||||
struct RootWindowConfig {
|
struct RootWindowConfig {
|
||||||
RootWindowConfig();
|
RootWindowConfig();
|
||||||
|
|
||||||
|
// If true the window will always display above other windows.
|
||||||
|
bool always_on_top;
|
||||||
|
|
||||||
// If true the window will show controls.
|
// If true the window will show controls.
|
||||||
bool with_controls;
|
bool with_controls;
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ void MaximizeWindow(GtkWindow* window) {
|
|||||||
|
|
||||||
RootWindowGtk::RootWindowGtk()
|
RootWindowGtk::RootWindowGtk()
|
||||||
: with_controls_(false),
|
: with_controls_(false),
|
||||||
|
always_on_top_(false),
|
||||||
with_osr_(false),
|
with_osr_(false),
|
||||||
with_extension_(false),
|
with_extension_(false),
|
||||||
is_popup_(false),
|
is_popup_(false),
|
||||||
@ -84,6 +85,7 @@ void RootWindowGtk::Init(RootWindow::Delegate* delegate,
|
|||||||
|
|
||||||
delegate_ = delegate;
|
delegate_ = delegate;
|
||||||
with_controls_ = config.with_controls;
|
with_controls_ = config.with_controls;
|
||||||
|
always_on_top_ = config.always_on_top;
|
||||||
with_osr_ = config.with_osr;
|
with_osr_ = config.with_osr;
|
||||||
with_extension_ = config.with_extension;
|
with_extension_ = config.with_extension;
|
||||||
start_rect_ = config.bounds;
|
start_rect_ = config.bounds;
|
||||||
@ -275,6 +277,10 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
CHECK(window_);
|
CHECK(window_);
|
||||||
|
|
||||||
|
if (always_on_top_) {
|
||||||
|
gtk_window_set_keep_above(GTK_WINDOW(window_), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_window_set_default_size(GTK_WINDOW(window_), width, height);
|
gtk_window_set_default_size(GTK_WINDOW(window_), width, height);
|
||||||
g_signal_connect(G_OBJECT(window_), "focus-in-event",
|
g_signal_connect(G_OBJECT(window_), "focus-in-event",
|
||||||
G_CALLBACK(&RootWindowGtk::WindowFocusIn), this);
|
G_CALLBACK(&RootWindowGtk::WindowFocusIn), this);
|
||||||
|
@ -125,6 +125,7 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
// After initialization all members are only accessed on the main thread.
|
// After initialization all members are only accessed on the main thread.
|
||||||
// Members set during initialization.
|
// Members set during initialization.
|
||||||
bool with_controls_;
|
bool with_controls_;
|
||||||
|
bool always_on_top_;
|
||||||
bool with_osr_;
|
bool with_osr_;
|
||||||
bool with_extension_;
|
bool with_extension_;
|
||||||
bool is_popup_;
|
bool is_popup_;
|
||||||
|
@ -21,6 +21,7 @@ static const char* kDefaultImageCache[] = {"menu_icon", "window_icon"};
|
|||||||
|
|
||||||
RootWindowViews::RootWindowViews()
|
RootWindowViews::RootWindowViews()
|
||||||
: with_controls_(false),
|
: with_controls_(false),
|
||||||
|
always_on_top_(false),
|
||||||
with_extension_(false),
|
with_extension_(false),
|
||||||
initially_hidden_(false),
|
initially_hidden_(false),
|
||||||
is_popup_(false),
|
is_popup_(false),
|
||||||
@ -42,6 +43,7 @@ void RootWindowViews::Init(RootWindow::Delegate* delegate,
|
|||||||
|
|
||||||
delegate_ = delegate;
|
delegate_ = delegate;
|
||||||
with_controls_ = config.with_controls;
|
with_controls_ = config.with_controls;
|
||||||
|
always_on_top_ = config.always_on_top;
|
||||||
with_extension_ = config.with_extension;
|
with_extension_ = config.with_extension;
|
||||||
initially_hidden_ = config.initially_hidden;
|
initially_hidden_ = config.initially_hidden;
|
||||||
if (initially_hidden_ && !config.source_bounds.IsEmpty()) {
|
if (initially_hidden_ && !config.source_bounds.IsEmpty()) {
|
||||||
@ -239,6 +241,7 @@ void RootWindowViews::OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) {
|
|||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
DCHECK(!window_);
|
DCHECK(!window_);
|
||||||
window_ = window;
|
window_ = window;
|
||||||
|
window_->SetAlwaysOnTop(always_on_top_);
|
||||||
|
|
||||||
if (!pending_extensions_.empty()) {
|
if (!pending_extensions_.empty()) {
|
||||||
window_->OnExtensionsChanged(pending_extensions_);
|
window_->OnExtensionsChanged(pending_extensions_);
|
||||||
|
@ -104,6 +104,7 @@ class RootWindowViews : public RootWindow,
|
|||||||
// unless otherwise indicated.
|
// unless otherwise indicated.
|
||||||
// Members set during initialization.
|
// Members set during initialization.
|
||||||
bool with_controls_;
|
bool with_controls_;
|
||||||
|
bool always_on_top_;
|
||||||
bool with_extension_;
|
bool with_extension_;
|
||||||
bool initially_hidden_;
|
bool initially_hidden_;
|
||||||
CefRefPtr<CefWindow> parent_window_;
|
CefRefPtr<CefWindow> parent_window_;
|
||||||
|
@ -103,6 +103,7 @@ int GetURLBarHeight(HWND hwnd) {
|
|||||||
|
|
||||||
RootWindowWin::RootWindowWin()
|
RootWindowWin::RootWindowWin()
|
||||||
: with_controls_(false),
|
: with_controls_(false),
|
||||||
|
always_on_top_(false),
|
||||||
with_osr_(false),
|
with_osr_(false),
|
||||||
with_extension_(false),
|
with_extension_(false),
|
||||||
is_popup_(false),
|
is_popup_(false),
|
||||||
@ -152,6 +153,7 @@ void RootWindowWin::Init(RootWindow::Delegate* delegate,
|
|||||||
|
|
||||||
delegate_ = delegate;
|
delegate_ = delegate;
|
||||||
with_controls_ = config.with_controls;
|
with_controls_ = config.with_controls;
|
||||||
|
always_on_top_ = config.always_on_top;
|
||||||
with_osr_ = config.with_osr;
|
with_osr_ = config.with_osr;
|
||||||
with_extension_ = config.with_extension;
|
with_extension_ = config.with_extension;
|
||||||
|
|
||||||
@ -333,6 +335,7 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
CHECK(find_message_id_);
|
CHECK(find_message_id_);
|
||||||
|
|
||||||
const DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
|
const DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
|
||||||
|
const DWORD dwExStyle = always_on_top_ ? WS_EX_TOPMOST : 0;
|
||||||
|
|
||||||
int x, y, width, height;
|
int x, y, width, height;
|
||||||
if (::IsRectEmpty(&start_rect_)) {
|
if (::IsRectEmpty(&start_rect_)) {
|
||||||
@ -341,7 +344,7 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
} else {
|
} else {
|
||||||
// Adjust the window size to account for window frame and controls.
|
// Adjust the window size to account for window frame and controls.
|
||||||
RECT window_rect = start_rect_;
|
RECT window_rect = start_rect_;
|
||||||
::AdjustWindowRectEx(&window_rect, dwStyle, with_controls_, 0);
|
::AdjustWindowRectEx(&window_rect, dwStyle, with_controls_, dwExStyle);
|
||||||
|
|
||||||
x = start_rect_.left;
|
x = start_rect_.left;
|
||||||
y = start_rect_.top;
|
y = start_rect_.top;
|
||||||
@ -352,8 +355,8 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
browser_settings_ = settings;
|
browser_settings_ = settings;
|
||||||
|
|
||||||
// Create the main window initially hidden.
|
// Create the main window initially hidden.
|
||||||
CreateWindow(window_class.c_str(), window_title.c_str(), dwStyle, x, y, width,
|
CreateWindowEx(dwExStyle, window_class.c_str(), window_title.c_str(), dwStyle,
|
||||||
height, NULL, NULL, hInstance, this);
|
x, y, width, height, NULL, NULL, hInstance, this);
|
||||||
CHECK(hwnd_);
|
CHECK(hwnd_);
|
||||||
|
|
||||||
if (!called_enable_non_client_dpi_scaling_ && IsProcessPerMonitorDpiAware()) {
|
if (!called_enable_non_client_dpi_scaling_ && IsProcessPerMonitorDpiAware()) {
|
||||||
|
@ -112,6 +112,7 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
// After initialization all members are only accessed on the main thread.
|
// After initialization all members are only accessed on the main thread.
|
||||||
// Members set during initialization.
|
// Members set during initialization.
|
||||||
bool with_controls_;
|
bool with_controls_;
|
||||||
|
bool always_on_top_;
|
||||||
bool with_osr_;
|
bool with_osr_;
|
||||||
bool with_extension_;
|
bool with_extension_;
|
||||||
bool is_popup_;
|
bool is_popup_;
|
||||||
|
@ -222,6 +222,13 @@ void ViewsWindow::SetFullscreen(bool fullscreen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewsWindow::SetAlwaysOnTop(bool on_top) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
if (window_) {
|
||||||
|
window_->SetAlwaysOnTop(on_top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ViewsWindow::SetLoadingState(bool isLoading,
|
void ViewsWindow::SetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) {
|
bool canGoForward) {
|
||||||
|
@ -112,6 +112,7 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
|||||||
void SetTitle(const std::string& title);
|
void SetTitle(const std::string& title);
|
||||||
void SetFavicon(CefRefPtr<CefImage> image);
|
void SetFavicon(CefRefPtr<CefImage> image);
|
||||||
void SetFullscreen(bool fullscreen);
|
void SetFullscreen(bool fullscreen);
|
||||||
|
void SetAlwaysOnTop(bool on_top);
|
||||||
void SetLoadingState(bool isLoading, bool canGoBack, bool canGoForward);
|
void SetLoadingState(bool isLoading, bool canGoBack, bool canGoForward);
|
||||||
void SetDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
void SetDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
||||||
void TakeFocus(bool next);
|
void TakeFocus(bool next);
|
||||||
|
@ -130,6 +130,7 @@ int RunMain(int argc, char* argv[]) {
|
|||||||
test_runner::RegisterSchemeHandlers();
|
test_runner::RegisterSchemeHandlers();
|
||||||
|
|
||||||
RootWindowConfig window_config;
|
RootWindowConfig window_config;
|
||||||
|
window_config.always_on_top = command_line->HasSwitch(switches::kAlwaysOnTop);
|
||||||
window_config.with_controls =
|
window_config.with_controls =
|
||||||
!command_line->HasSwitch(switches::kHideControls);
|
!command_line->HasSwitch(switches::kHideControls);
|
||||||
window_config.with_osr = settings.windowless_rendering_enabled ? true : false;
|
window_config.with_osr = settings.windowless_rendering_enabled ? true : false;
|
||||||
|
@ -95,6 +95,7 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
|
|||||||
test_runner::RegisterSchemeHandlers();
|
test_runner::RegisterSchemeHandlers();
|
||||||
|
|
||||||
RootWindowConfig window_config;
|
RootWindowConfig window_config;
|
||||||
|
window_config.always_on_top = command_line->HasSwitch(switches::kAlwaysOnTop);
|
||||||
window_config.with_controls =
|
window_config.with_controls =
|
||||||
!command_line->HasSwitch(switches::kHideControls);
|
!command_line->HasSwitch(switches::kHideControls);
|
||||||
window_config.with_osr = settings.windowless_rendering_enabled ? true : false;
|
window_config.with_osr = settings.windowless_rendering_enabled ? true : false;
|
||||||
|
@ -37,6 +37,7 @@ const char kFilterURL[] = "filter-url";
|
|||||||
const char kUseViews[] = "use-views";
|
const char kUseViews[] = "use-views";
|
||||||
const char kHideFrame[] = "hide-frame";
|
const char kHideFrame[] = "hide-frame";
|
||||||
const char kHideControls[] = "hide-controls";
|
const char kHideControls[] = "hide-controls";
|
||||||
|
const char kAlwaysOnTop[] = "always-on-top";
|
||||||
const char kHideTopMenu[] = "hide-top-menu";
|
const char kHideTopMenu[] = "hide-top-menu";
|
||||||
const char kWidevineCdmPath[] = "widevine-cdm-path";
|
const char kWidevineCdmPath[] = "widevine-cdm-path";
|
||||||
const char kSslClientCertificate[] = "ssl-client-certificate";
|
const char kSslClientCertificate[] = "ssl-client-certificate";
|
||||||
|
@ -31,6 +31,7 @@ extern const char kFilterURL[];
|
|||||||
extern const char kUseViews[];
|
extern const char kUseViews[];
|
||||||
extern const char kHideFrame[];
|
extern const char kHideFrame[];
|
||||||
extern const char kHideControls[];
|
extern const char kHideControls[];
|
||||||
|
extern const char kAlwaysOnTop[];
|
||||||
extern const char kHideTopMenu[];
|
extern const char kHideTopMenu[];
|
||||||
extern const char kWidevineCdmPath[];
|
extern const char kWidevineCdmPath[];
|
||||||
extern const char kSslClientCertificate[];
|
extern const char kSslClientCertificate[];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user