zhangqd / chromiumembedded

Automatically exported from code.google.com/p/chromiumembedded
0 stars 1 forks source link

combobox drop down menu is displaced #1208

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
* What steps will reproduce the problem?

1. Load any webpage with an html form combobox element into cefclient or 
cefsimple.
2. Move the cefclient/cefsimple window.
3. Activate the combobox dropdown menu.

What is the expected output?

* The combobox dropdown menu should appear under the combobox.

What do you see instead?  The combobox menu appears underneath where the 
combobox would be located if the CEF browser window had not been moved in step 
2.

* What version of the product are you using?

CEF 3.1750.1619_windows32
Compiled with visual studio 2012.
CEF_ENABLE_SANDBOX=0.

* In what operating system?

Windows 7 professional SP1

Original issue reported on code.google.com by ryan.g...@gmail.com on 18 Feb 2014 at 12:46

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by magreenb...@gmail.com on 18 Feb 2014 at 7:53

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I created a fix for this with jQuery. I still need to add styling to look 
exactly like the built-in version. 
https://github.com/norbertkeresztes/cef-dropdown-fix

Original comment by norbertk...@gmail.com on 30 Mar 2014 at 10:41

GoogleCodeExporter commented 9 years ago
Issue 1250 has been merged into this issue.

Original comment by magreenb...@gmail.com on 10 Apr 2014 at 3:49

GoogleCodeExporter commented 9 years ago
Issue 1269 has been merged into this issue.

Original comment by magreenb...@gmail.com on 6 May 2014 at 3:19

GoogleCodeExporter commented 9 years ago
simply but not beautiful workaround is add wm_move to cefclient with this code:

    case WM_MOVE:
        if (g_handler.get() && g_handler->GetBrowser()) {
            // Pass focus to the browser window
                        CefWindowHandle hwnd =
                    g_handler->GetBrowser()->GetHost()->GetWindowHandle();
                    RECT rect;
                    GetClientRect(hWnd, &rect);
                    HDWP hdwp = BeginDeferWindowPos(1);
                    hdwp = DeferWindowPos(hdwp, hwnd, NULL,
                        rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top+1,
                        SWP_NOZORDER);
                    EndDeferWindowPos(hdwp);

                                        HDWP hdwp2 = BeginDeferWindowPos(1);
                    hdwp2 = DeferWindowPos(hdwp2, hwnd, NULL,
                        rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
                        SWP_NOZORDER);
                    EndDeferWindowPos(hdwp2);

        }
        return TRUE;

Original comment by gchiocc...@gmail.com on 7 May 2014 at 11:31

GoogleCodeExporter commented 9 years ago
I've changed previous fix, as it results in non smooth moving of window

// Fix for dropdown moving - Callback for EnumChildWindows 
BOOL CALLBACK EnumWndProc(HWND hWnd, LPARAM lParam)
{
    PostMessage(hWnd, WM_KILLFOCUS, NULL, NULL);
    return TRUE;
}

... and in main window message processing...

case WM_MOVE:
    if (g_handler.get() && g_handler->GetBrowser()) {
        CefWindowHandle hwnd =  g_handler->GetBrowser()->GetHost()->GetWindowHandle();
        if (hwnd) EnumChildWindows(hwnd, EnumWndProc, NULL);
    }
    return TRUE;

Original comment by dgr...@gmail.com on 23 Jun 2014 at 11:40

GoogleCodeExporter commented 9 years ago
Is this change on master?

Original comment by shimiml4 on 30 Jun 2014 at 9:31

GoogleCodeExporter commented 9 years ago
Yes, I just confirmed it is still present.

I used the following . . . 
cefbuilds.com Windows 32bit 2014-06-26 CEF 3.2043.1750
MS visual studio 2013

Original comment by ryan.g...@gmail.com on 30 Jun 2014 at 11:24

GoogleCodeExporter commented 9 years ago
After investigating that problem, it looks like we somehow have to call 
RenderWidgetHostImpl::SendScreenRects() after moving window. Renderer send 
message ViewHostMsg_ShowWidget for showing HTMLSelect element, with wrong 
coordinates because it doesn't know that window has been moved. 
I've temporarily solved this problem by creating method in CefBrowserHost in 
which I call SendScreenRects(), and then call this method from WM_MOVE handler 
in main window.

Original comment by egor.iva...@gmail.com on 28 Aug 2014 at 7:06

GoogleCodeExporter commented 9 years ago
The workaround that I found working, upon improving on one of the previous 
fixes, is to redraw the window on WM_EXITSIZEMOVE event, like this:

case WM_EXITSIZEMOVE:
    if (g_handler.get() && g_handler->GetBrowser()) {
        // Pass focus to the browser window
        CefWindowHandle hwnd =
            g_handler->GetBrowser()->GetHost()->GetWindowHandle();
        RECT rect;
        GetClientRect(hWnd, &rect);
        HDWP hdwp = BeginDeferWindowPos(1);
        hdwp = DeferWindowPos(hdwp, hwnd, NULL,
            rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1,
            SWP_NOZORDER);
        EndDeferWindowPos(hdwp);

        HDWP hdwp2 = BeginDeferWindowPos(1);
        hdwp2 = DeferWindowPos(hdwp2, hwnd, NULL,
            rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
            SWP_NOZORDER);
        EndDeferWindowPos(hdwp2);

    }
    return TRUE;

This is the same code as the previous fix, but it only occurs once, and doesn't 
introduce the problem of non-smooth window moving.

Original comment by slobodan...@gmail.com on 7 Sep 2014 at 9:35

GoogleCodeExporter commented 9 years ago
That is a great workaround. Anyone thought of one for Linux?

Original comment by jcmay...@gmail.com on 18 Sep 2014 at 11:33

GoogleCodeExporter commented 9 years ago
Okay, I may have a workaround for Linux. I'll test it some more and post it 
tomorrow morning.

Original comment by jcmay...@gmail.com on 19 Sep 2014 at 12:01

GoogleCodeExporter commented 9 years ago
The linux fix is pretty much the same as what slobodan did for Windows. When 
the main window is moved/sized, you fake a quick size operation to force the 
required updates.

My handler for the "size-allocate" signal is basically exactly like the one in 
CefClient
void VboxSizeAllocated(GtkWidget* /*widget*/,
                       GtkAllocation* allocation,
                       void* /*data*/) {
  if (g_cef_client) {
    CefRefPtr<CefBrowser> browser = g_cef_client->cef_main_browser();
    if (browser && !browser->GetHost()->IsWindowRenderingDisabled()) {
      // Size the browser window to match the GTK widget.
      ::Display* xdisplay = cef_get_xdisplay();
      ::Window xwindow = browser->GetHost()->GetWindowHandle();
      XWindowChanges changes = {0};
      changes.width = allocation->width;
      changes.height = allocation->height - g_toolbar_height;
      XConfigureWindow(xdisplay, xwindow, CWHeight | CWWidth, &changes);
    }
  }
}

To force the resize after a move add a signal handler for "configure-event" as 
follows

g_signal_connect(g_main_window, "configure-event", G_CALLBACK(OnWindowResize), 
0);

This handler will be called after every main window move or size operation. It 
is only called once when the operation ends.

In your handler fake two calls to VboxSizeAllocated() as follows
boolean OnWindowResize(GtkWindow* window, GdkEventConfigure* event,
                        gpointer data) {
  if (event) {
    // Force a slight resize to fix dropdown placement issue.
    GtkAllocation temp;
    temp.width = event->width;
    temp.height = event->height + 1;
    VboxSizeAllocated(NULL, &temp, NULL);
    temp.height = event->height;
    VboxSizeAllocated(NULL, &temp, NULL);
  }
}

Original comment by jmay...@google.com on 19 Sep 2014 at 5:53

GoogleCodeExporter commented 9 years ago
Here is my version of the workaround in comment #11.  It improves on #11 by 
closing any open select elements when you begin moving the window and only uses 
one deferred window position sequence.

case WM_ENTERSIZEMOVE:
case WM_EXITSIZEMOVE:
  if (g_handler.get() && g_handler->GetBrowser()) {
    // Pass focus to the browser window
    CefWindowHandle hwnd =
        g_handler->GetBrowser()->GetHost()->GetWindowHandle();
    RECT rect;
    GetClientRect(hWnd, &rect);

    HDWP hdwp = BeginDeferWindowPos(1);
    hdwp = DeferWindowPos(hdwp, hwnd, NULL,
                          rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1,
                          SWP_NOZORDER);
    hdwp = DeferWindowPos(hdwp, hwnd, NULL,
                          rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
                          SWP_NOZORDER);
    EndDeferWindowPos(hdwp);

  }
  return TRUE;

Original comment by ryan.g...@gmail.com on 26 Sep 2014 at 3:43

GoogleCodeExporter commented 9 years ago
Great, thanks :)

Original comment by slobodan...@gmail.com on 26 Sep 2014 at 4:07

GoogleCodeExporter commented 9 years ago
Related comments: http://magpcss.org/ceforum/viewtopic.php?f=6&t=11503#p22484

Original comment by magreenb...@gmail.com on 14 Oct 2014 at 2:28

GoogleCodeExporter commented 9 years ago
The RenderWidgetHostImpl::SendScreenRects() method needs to be called when the 
window is moved or resized. In Chrome (revision d075289) on Windows the call 
stacks are as follows:

WM_MOVING message:
>   chrome.dll!content::RenderWidgetHostImpl::SendScreenRects() Line 370    C++
    chrome.dll!content::WebContentsViewAura::WindowObserver::SendScreenRects() Line 683 C++
    chrome.dll!content::WebContentsViewAura::WindowObserver::OnHostMoved(const aura::WindowTreeHost * host, const gfx::Point & new_origin) Line 677 C++
    chrome.dll!aura::WindowTreeHost::OnHostMoved(const gfx::Point & new_location) Line 231  C++
    chrome.dll!views::DesktopWindowTreeHostWin::HandleMove() Line 796   C++
    chrome.dll!views::HWNDMessageHandler::OnMoving(unsigned int param, const tagRECT * new_bounds) Line 1586    C++
    chrome.dll!views::HWNDMessageHandler::_ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) Line 390  C++
    chrome.dll!views::HWNDMessageHandler::OnWndProc(unsigned int message, unsigned int w_param, long l_param) Line 924  C++

WM_WINDOWPOSCHANGED message:
    chrome.dll!content::RenderWidgetHostImpl::SendScreenRects() Line 370    C++
    chrome.dll!content::WebContentsViewAura::WindowObserver::SendScreenRects() Line 683 C++
    chrome.dll!content::WebContentsViewAura::WindowObserver::OnWindowBoundsChanged(aura::Window * window, const gfx::Rect & old_bounds, const gfx::Rect & new_bounds) Line 623  C++
    chrome.dll!aura::Window::OnWindowBoundsChanged(const gfx::Rect & old_bounds) Line 1350  C++
    chrome.dll!base::internal::RunnableAdapter<void (__thiscall aura::Window::*)(gfx::Rect const &)>::Run(aura::Window * object, const gfx::Rect & a1) Line 190 C++
    chrome.dll!base::internal::InvokeHelper<0,void,base::internal::RunnableAdapter<void (__thiscall aura::Window::*)(gfx::Rect const &)>,void __cdecl(aura::Window *,gfx::Rect const &)>::MakeItSo(base::internal::RunnableAdapter<void (__thiscall aura::Window::*)(gfx::Rect const &)> runnable, aura::Window * a1, const gfx::Rect & a2) Line 899    C++
    chrome.dll!base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall aura::Window::*)(gfx::Rect const &)>,void __cdecl(aura::Window *,gfx::Rect const &),void __cdecl(base::internal::UnretainedWrapper<aura::Window>,gfx::Rect)>,void __cdecl(aura::Window *,gfx::Rect const &)>::Run(base::internal::BindStateBase * base) Line 1253   C++
    chrome.dll!base::Callback<void __cdecl(void)>::Run() Line 401   C++
    chrome.dll!ui::Layer::SetBoundsFromAnimation(const gfx::Rect & bounds) Line 833 C++
    chrome.dll!ui::LayerAnimator::SetBounds(const gfx::Rect & value) Line 102   C++
    chrome.dll!ui::Layer::SetBounds(const gfx::Rect & bounds) Line 245  C++
    chrome.dll!aura::Window::SetBoundsInternal(const gfx::Rect & new_bounds) Line 915   C++
    chrome.dll!aura::Window::SetBounds(const gfx::Rect & new_bounds) Line 449   C++
    chrome.dll!views::DesktopNativeWidgetAura::OnHostResized(const aura::WindowTreeHost * host) Line 1174   C++
    chrome.dll!aura::WindowTreeHost::OnHostResized(const gfx::Size & new_size) Line 244 C++
    chrome.dll!views::DesktopWindowTreeHostWin::HandleClientSizeChanged(const gfx::Size & new_size) Line 815    C++
>   chrome.dll!views::HWNDMessageHandler::ClientAreaSizeChanged() Line 1083 C++
    chrome.dll!views::HWNDMessageHandler::OnWindowPosChanged(tagWINDOWPOS * window_pos) Line 2307   C++
    chrome.dll!views::HWNDMessageHandler::_ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) Line 403  C++
    chrome.dll!views::HWNDMessageHandler::OnWndProc(unsigned int message, unsigned int w_param, long l_param) Line 924  C++

Original comment by magreenb...@gmail.com on 28 Oct 2014 at 3:40

GoogleCodeExporter commented 9 years ago
@#18: The WM_WINDOWPOSCHANGED message currently works as expected in CEF. To 
fix this issue it will be necessary to also forward the WM_MOVE message to 
DesktopWindowTreeHostWin.

Original comment by magreenb...@gmail.com on 28 Oct 2014 at 3:56

GoogleCodeExporter commented 9 years ago
Just a heads up that I think this issue affects all platforms.

Original comment by jcmay...@gmail.com on 28 Oct 2014 at 4:14

GoogleCodeExporter commented 9 years ago
Issue 1360 has been merged into this issue.

Original comment by magreenb...@gmail.com on 28 Oct 2014 at 4:50

GoogleCodeExporter commented 9 years ago
Issue 590 has been merged into this issue.

Original comment by magreenb...@gmail.com on 28 Oct 2014 at 4:50

GoogleCodeExporter commented 9 years ago
To dismiss select popups on window move/resize Aura uses 
RenderWidgetHostViewAura::EventFilterForPopupExit which is triggered when the 
non-client area of the window is clicked. For CEF the popup is already 
dismissed on window resize but we need to explicitly dismiss it on window move.

Original comment by magreenb...@gmail.com on 28 Oct 2014 at 5:28

GoogleCodeExporter commented 9 years ago
@#23: Dismissal of the popup in Chrome (revision d075289) on Windows by 
clicking in the non-client area:

1. Browser process:

>   chrome.dll!content::RenderWidgetHostImpl::Shutdown() Line 426   C++
    chrome.dll!content::RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(ui::LocatedEvent * event) Line 391   C++
    chrome.dll!content::RenderWidgetHostViewAura::EventFilterForPopupExit::OnMouseEvent(ui::MouseEvent * event) Line 362    C++
    chrome.dll!ui::EventHandler::OnEvent(ui::Event * event) Line 29 C++

2. Renderer process:

>   chrome_child.dll!blink::PopupContainer::hide() Line 354 C++
    chrome_child.dll!blink::WebPopupMenuImpl::close() Line 171  C++
    chrome_child.dll!content::RenderWidget::Close() Line 1449   C++

Dismissal of the popup by resizing the browser in CEF, renderer process:

>   libcef.dll!blink::WebViewImpl::hideSelectPopup() Line 1547  C++
    libcef.dll!blink::WebViewImpl::hidePopups() Line 3749   C++
    libcef.dll!content::RenderViewImpl::OnResize(const ViewMsg_Resize_Params & params) Line 3253    C++

Original comment by magreenb...@gmail.com on 28 Oct 2014 at 5:40

GoogleCodeExporter commented 9 years ago
Trunk revision 1901 and 2171 branch revision 1902 add a new 
CefBrowserHost::NotifyMoveOrResizeStarted() method that, when called from 
client applications on Windows and Linux, fix positioning of select popups and 
dismissal on window move/resize. This problem does not reproduce on OS X so 
there's no need to call the new method on that platform.

Original comment by magreenb...@gmail.com on 29 Oct 2014 at 6:16

GoogleCodeExporter commented 9 years ago
Any chance of having this patched down to the 2062 release branch? We aren't 
able to go to 2171 due yet due to some issues we have yet to track down.

Original comment by jcmay...@gmail.com on 29 Oct 2014 at 9:12

GoogleCodeExporter commented 9 years ago
@#26: Can you test and attach a patch for 2062 branch? Thanks.

Original comment by magreenb...@gmail.com on 31 Oct 2014 at 6:52

GoogleCodeExporter commented 9 years ago
Will do.

Original comment by jcmay...@gmail.com on 31 Oct 2014 at 7:02

GoogleCodeExporter commented 9 years ago
I'm manually incorporating the changes for this but am not quite sure what to 
do with the patch file mod. There appears to be some git commit ids in there 
that I'm not sure about

see 
https://code.google.com/p/chromiumembedded/source/diff?spec=svn1902&r=1902&forma
t=side&path=/branches/2171/cef3/patch/patches/views_widget_180.patch

line 60: "index 9831992..23a00a9 100644"

Is there a process I need to follow to make the required changes to this file?

Original comment by jcmay...@gmail.com on 4 Nov 2014 at 9:09

GoogleCodeExporter commented 9 years ago
@#29: You should change DesktopWindowTreeHostX11::GetBounds manually in your 
2062 branch checkout (with the previous patch already applied) and then run 
`python src/cef/tools/patch_updater.py --resave` to re-save the 
views_widget_180.patch file including your changes.

Original comment by magreenb...@gmail.com on 7 Nov 2014 at 6:25

GoogleCodeExporter commented 9 years ago
Is anyone else still seeing this issue if CEF is a child of another window on 
Windows? In my case, it appears the WM_MOVE and WM_MOVING are never being sent 
to CEF.

Original comment by Hylinn.T...@gmail.com on 15 Dec 2014 at 6:14

GoogleCodeExporter commented 9 years ago
After migrating to branch 2171, this issue is not resolved for us.

Original comment by jke...@connectwise.com on 15 Dec 2014 at 6:42

GoogleCodeExporter commented 9 years ago
I just tried 2171 r1949 and the issue is resolved for me on Windows. My app 
does get the WM_MOVE and WM_MOVING messages in its message proc.

Original comment by jcmay...@gmail.com on 15 Dec 2014 at 6:51

GoogleCodeExporter commented 9 years ago
@#31,32: You need to implement WM_MOVE/WM_MOVING in your top-level window and 
call CefBrowserHost::NotifyMoveOrResizeStarted(). See the example in cefclient.

Original comment by magreenb...@gmail.com on 15 Dec 2014 at 6:54

GoogleCodeExporter commented 9 years ago
@#34: Gotcha. My issue arises because, in my case, CEF is wrapped in an ActiveX 
control which is in turn wrapped by a custom WPF control. I don't have access 
to change the handling of WM_MOVE/WM_MOVING on those components so I can't tell 
them to call CefBrowserHost::NotifyMoveOrResizeStarted().

Original comment by Hylinn.T...@gmail.com on 15 Dec 2014 at 11:03

GoogleCodeExporter commented 9 years ago
I would think whoever is controlling CEF, sounds like your activeX control, 
needs to call NotifyMoveOrResize(started). Your activeX control must get some 
notification or callback when the control is resized. That would be the place 
to call this method.

Original comment by jcmay...@gmail.com on 15 Dec 2014 at 11:18

GoogleCodeExporter commented 9 years ago
Issue 1537 has been merged into this issue.

Original comment by magreenb...@gmail.com on 9 Mar 2015 at 9:55