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:
Isaac Devine
2018-02-28 17:47:36 +13:00
committed by Marshall Greenblatt
parent fbc59483b9
commit 5969b2bbb8
19 changed files with 85 additions and 9 deletions

View File

@@ -78,8 +78,8 @@ bool CefBrowserPlatformDelegateNativeLinux::CreateHostWindow() {
// Add a reference that will be released in BrowserDestroyed().
browser_->AddRef();
CefWindowDelegateView* delegate_view =
new CefWindowDelegateView(GetBackgroundColor());
CefWindowDelegateView* delegate_view = new CefWindowDelegateView(
GetBackgroundColor(), window_x11_->TopLevelAlwaysOnTop());
delegate_view->Init(window_info_.window, browser_->web_contents(),
gfx::Rect(gfx::Point(), rect.size()));

View File

@@ -189,8 +189,15 @@ bool CefBrowserPlatformDelegateNativeWin::CreateHostWindow() {
point =
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 =
new CefWindowDelegateView(GetBackgroundColor());
new CefWindowDelegateView(GetBackgroundColor(), always_on_top);
delegate_view->Init(window_info_.window, browser_->web_contents(),
gfx::Rect(0, 0, point.x(), point.y()));

View File

@@ -12,8 +12,11 @@
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
CefWindowDelegateView::CefWindowDelegateView(SkColor background_color)
: background_color_(background_color), web_view_(NULL) {}
CefWindowDelegateView::CefWindowDelegateView(SkColor background_color,
bool always_on_top)
: background_color_(background_color),
web_view_(NULL),
always_on_top_(always_on_top) {}
void CefWindowDelegateView::Init(gfx::AcceleratedWidget parent_widget,
content::WebContents* web_contents,
@@ -44,6 +47,8 @@ void CefWindowDelegateView::Init(gfx::AcceleratedWidget parent_widget,
// CefBrowserHostImpl::PlatformSetFocus.
params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
params.keep_on_top = always_on_top_;
// Results in a call to InitContent().
widget->Init(params);

View File

@@ -20,7 +20,7 @@ class WebView;
// will be deleted automatically when the associated root window is destroyed.
class CefWindowDelegateView : public views::WidgetDelegateView {
public:
explicit CefWindowDelegateView(SkColor background_color);
CefWindowDelegateView(SkColor background_color, bool always_on_top);
// Create the Widget and associated root window.
void Init(gfx::AcceleratedWidget parent_widget,
@@ -43,6 +43,7 @@ class CefWindowDelegateView : public views::WidgetDelegateView {
private:
SkColor background_color_;
views::WebView* web_view_;
bool always_on_top_;
DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView);
};

View File

@@ -396,3 +396,34 @@ void CefWindowX11::ContinueFocus() {
browser_->SetFocus(true);
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;
}

View File

@@ -52,6 +52,8 @@ class CefWindowX11 : public ui::PlatformEventDispatcher {
::Window xwindow() const { return xwindow_; }
gfx::Rect bounds() const { return bounds_; }
bool TopLevelAlwaysOnTop() const;
private:
void ContinueFocus();