diff options
author | tony@chromium.org <tony@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-31 22:29:54 +0000 |
---|---|---|
committer | tony@chromium.org <tony@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-31 22:29:54 +0000 |
commit | b7b678f549e7a622615e6488d8e36fe998f85aec (patch) | |
tree | f1b9c196f11d0d6f365b02f03f39a74b73838a0f | |
parent | fde205d647c882dc36d2753d0b3e4ac342a89b19 (diff) | |
download | chromium_src-b7b678f549e7a622615e6488d8e36fe998f85aec.zip chromium_src-b7b678f549e7a622615e6488d8e36fe998f85aec.tar.gz chromium_src-b7b678f549e7a622615e6488d8e36fe998f85aec.tar.bz2 |
Remove the use of the X11 background thread and instead handle sync
render messages on the UI thread.
This avoids a lot of complexity by allowing us to use gdk methods to
get window and screen information and fixes issue 80096.
Also remove the unrealize lock since we're only operating on the UI
thread.
There will be follow up patches to:
- Remove the X11 background thread.
- Update GtkNativeViewManager to be non-thread safe and remove all the locking
since it appears to only be used on the UI thread now.
- Remove functions in x11_util.* that are no longer used.
BUG=80096
TEST=See test case in issue 80096. Make sure that the custom frame
is disabled.
Review URL: http://codereview.chromium.org/7085009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87381 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 23 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter.h | 19 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter_gtk.cc | 150 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host.cc | 7 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host.h | 7 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_gtk.cc | 86 | ||||
-rw-r--r-- | content/content_browser.gypi | 1 | ||||
-rw-r--r-- | ui/gfx/gtk_native_view_id_manager.cc | 17 | ||||
-rw-r--r-- | ui/gfx/gtk_native_view_id_manager.h | 12 |
9 files changed, 133 insertions, 189 deletions
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 9b0d75e..dd3f0cd 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -304,13 +304,6 @@ RenderMessageFilter::~RenderMessageFilter() { void RenderMessageFilter::OverrideThreadForMessage(const IPC::Message& message, BrowserThread::ID* thread) { switch (message.type()) { -#if defined(USE_X11) - case ViewHostMsg_GetScreenInfo::ID: - case ViewHostMsg_GetWindowRect::ID: - case ViewHostMsg_GetRootWindowRect::ID: - *thread = BrowserThread::BACKGROUND_X11; - break; -#endif // Can't load plugins on IO thread. case ViewHostMsg_GetPlugins::ID: // The PluginService::GetPluginInfo may need to load the plugins. Don't do @@ -327,15 +320,16 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, bool* message_was_ok) { bool handled = true; IPC_BEGIN_MESSAGE_MAP_EX(RenderMessageFilter, message, *message_was_ok) - // On Linux we need to dispatch these messages to the UI2 thread - // because we cannot make X calls from the IO thread. Mac - // doesn't have windowed plug-ins so we handle the messages in - // the UI thread. On Windows, we intercept the messages and - // handle them directly. -#if !defined(OS_MACOSX) +#if defined(OS_WIN) + // On Windows, we handle these on the IO thread to avoid a deadlock with + // plugins. On non-Windows systems, we need to handle them on the UI + // thread. IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnGetScreenInfo) IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnGetWindowRect) IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnGetRootWindowRect) + + // This hack is Windows-specific. + IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont) #endif IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID) @@ -351,9 +345,6 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont) #endif -#if defined(OS_WIN) // This hack is Windows-specific. - IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont) -#endif IPC_MESSAGE_HANDLER(ViewHostMsg_GetPlugins, OnGetPlugins) IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginInfo, OnGetPluginInfo) IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index f9d183d..08741b6 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -135,19 +135,20 @@ class RenderMessageFilter : public BrowserMessageFilter { uint32* font_id); #endif -#if defined(OS_WIN) // This hack is Windows-specific. - // Cache fonts for the renderer. See RenderMessageFilter::OnPreCacheFont - // implementation for more details. - void OnPreCacheFont(LOGFONT font); -#endif - -#if !defined(OS_MACOSX) - // Not handled in the IO thread on Mac. +#if defined(OS_WIN) + // On Windows, we handle these on the IO thread to avoid a deadlock with + // plugins. On non-Windows systems, we need to handle them on the UI thread. void OnGetScreenInfo(gfx::NativeViewId window, WebKit::WebScreenInfo* results); void OnGetWindowRect(gfx::NativeViewId window, gfx::Rect* rect); void OnGetRootWindowRect(gfx::NativeViewId window, gfx::Rect* rect); + + // This hack is Windows-specific. + // Cache fonts for the renderer. See RenderMessageFilter::OnPreCacheFont + // implementation for more details. + void OnPreCacheFont(LOGFONT font); #endif + void OnGetPlugins(bool refresh, std::vector<webkit::npapi::WebPluginInfo>* plugins); void OnGetPluginInfo(int routing_id, @@ -173,7 +174,7 @@ class RenderMessageFilter : public BrowserMessageFilter { void OnCheckNotificationPermission(const GURL& source_url, int* permission_level); -// Used to ask the browser to allocate a block of shared memory for the + // Used to ask the browser to allocate a block of shared memory for the // renderer to send back data in, since shared memory can't be created // in the renderer on POSIX due to the sandbox. void OnAllocateSharedMemoryBuffer(uint32 buffer_size, diff --git a/content/browser/renderer_host/render_message_filter_gtk.cc b/content/browser/renderer_host/render_message_filter_gtk.cc deleted file mode 100644 index 4612734..0000000 --- a/content/browser/renderer_host/render_message_filter_gtk.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <dlfcn.h> - -#include "content/browser/renderer_host/render_message_filter.h" - -#include "content/browser/browser_thread.h" -#include "content/common/view_messages.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/x11/WebScreenInfoFactory.h" -#include "ui/base/clipboard/clipboard.h" -#include "ui/base/x/x11_util.h" -#include "ui/gfx/gtk_native_view_id_manager.h" - -#if !defined(OS_CHROMEOS) -// We want to obey the alphabetical order for including header files, but -// #define macros in X11 header files affect chrome header files -// (e.g. Success), so include Xinerama.h here. We don't include Xinerama.h on -// Chrome OS since the X server for Chrome OS does not support the extension. -#include <X11/extensions/Xinerama.h> -#endif // OS_CHROMEOS - -using WebKit::WebScreenInfo; -using WebKit::WebScreenInfoFactory; - -namespace { - -// Return the top-level parent of the given window. Called on the -// BACKGROUND_X11 thread. -XID GetTopLevelWindow(XID window) { - bool parent_is_root; - XID parent_window; - - if (!ui::GetWindowParent(&parent_window, &parent_is_root, window)) - return 0; - if (parent_is_root) - return window; - - return GetTopLevelWindow(parent_window); -} - -gfx::Rect GetWindowRectFromView(gfx::NativeViewId view) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11)); - // This is called to get the x, y offset (in screen coordinates) of the given - // view and its width and height. - gfx::Rect rect; - XID window; - - base::AutoLock lock(GtkNativeViewManager::GetInstance()->unrealize_lock()); - if (GtkNativeViewManager::GetInstance()->GetXIDForId(&window, view)) { - if (window) { - int x, y; - unsigned width, height; - if (ui::GetWindowGeometry(&x, &y, &width, &height, window)) - rect = gfx::Rect(x, y, width, height); - } - } - return rect; -} - -} // namespace - -// We get null window_ids passed into the two functions below; please see -// http://crbug.com/9060 for more details. -void RenderMessageFilter::OnGetScreenInfo(gfx::NativeViewId view, - WebKit::WebScreenInfo* results) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11)); - Display* display = ui::GetSecondaryDisplay(); - - *results = WebScreenInfoFactory::screenInfo(display, - ui::GetDefaultScreen(display)); - -#if !defined(OS_CHROMEOS) - // First check if we can use Xinerama. - XineramaScreenInfo* screen_info = NULL; - int screen_num = 0; - void* xinerama_lib = dlopen("libXinerama.so.1", RTLD_LAZY); - if (xinerama_lib) { - // Prototypes for Xinerama functions. - typedef Bool (*XineramaIsActiveFunction)(Display* display); - typedef XineramaScreenInfo* - (*XineramaQueryScreensFunction)(Display* display, int* num); - - XineramaIsActiveFunction is_active = (XineramaIsActiveFunction) - dlsym(xinerama_lib, "XineramaIsActive"); - - XineramaQueryScreensFunction query_screens = (XineramaQueryScreensFunction) - dlsym(xinerama_lib, "XineramaQueryScreens"); - - // Get the number of screens via Xinerama - if (is_active && query_screens && is_active(display)) - screen_info = query_screens(display, &screen_num); - - if (screen_info) { - // We can use Xinerama information. Calculate the intersect rect size - // between window rect and screen rect, and choose the biggest size. - gfx::Rect rect = GetWindowRectFromView(view); - int max_intersect_index = 0; - for (int i = 0, max_intersect_size = 0; i < screen_num; ++i) { - gfx::Rect screen_rect(screen_info[i].x_org, screen_info[i].y_org, - screen_info[i].width, screen_info[i].height); - gfx::Rect intersect_rect = screen_rect.Intersect(rect); - int intersect_size = intersect_rect.width() * intersect_rect.height(); - if (intersect_size > max_intersect_size) { - max_intersect_size = intersect_size; - max_intersect_index = i; - } - } - XineramaScreenInfo& target_screen = screen_info[max_intersect_index]; - results->rect = WebKit::WebRect(target_screen.x_org, - target_screen.y_org, - target_screen.width, - target_screen.height); - results->availableRect = results->rect; - - XFree(screen_info); - } - } -#endif // OS_CHROMEOS -} - -void RenderMessageFilter::OnGetWindowRect(gfx::NativeViewId view, - gfx::Rect* rect) { - *rect = GetWindowRectFromView(view); -} - -void RenderMessageFilter::OnGetRootWindowRect(gfx::NativeViewId view, - gfx::Rect* rect) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11)); - // This is called to get the screen coordinates and size of the browser - // window itself. - *rect = gfx::Rect(); - XID window; - - base::AutoLock lock(GtkNativeViewManager::GetInstance()->unrealize_lock()); - if (GtkNativeViewManager::GetInstance()->GetXIDForId(&window, view)) { - if (window) { - const XID toplevel = GetTopLevelWindow(window); - if (toplevel) { - int x, y; - unsigned width, height; - if (ui::GetWindowGeometry(&x, &y, &width, &height, toplevel)) - *rect = gfx::Rect(x, y, width, height); - } - } - } -} diff --git a/content/browser/renderer_host/render_widget_host.cc b/content/browser/renderer_host/render_widget_host.cc index 30ad1b0..670e50f 100644 --- a/content/browser/renderer_host/render_widget_host.cc +++ b/content/browser/renderer_host/render_widget_host.cc @@ -170,10 +170,12 @@ bool RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) { OnMsgImeCancelComposition) IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing, OnMsgDidActivateAcceleratedCompositing) -#if defined(OS_MACOSX) +#if defined(OS_POSIX) IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnMsgGetScreenInfo) IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnMsgGetWindowRect) IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnMsgGetRootWindowRect) +#endif +#if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(ViewHostMsg_PluginFocusChanged, OnMsgPluginFocusChanged) IPC_MESSAGE_HANDLER(ViewHostMsg_StartPluginIme, @@ -188,7 +190,8 @@ bool RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) { OnAcceleratedSurfaceSetTransportDIB) IPC_MESSAGE_HANDLER(ViewHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) -#elif defined(TOOLKIT_USES_GTK) +#endif +#if defined(TOOLKIT_USES_GTK) IPC_MESSAGE_HANDLER(ViewHostMsg_CreatePluginContainer, OnMsgCreatePluginContainer) IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyPluginContainer, diff --git a/content/browser/renderer_host/render_widget_host.h b/content/browser/renderer_host/render_widget_host.h index a275b58..e610958 100644 --- a/content/browser/renderer_host/render_widget_host.h +++ b/content/browser/renderer_host/render_widget_host.h @@ -460,11 +460,13 @@ class RenderWidgetHost : public IPC::Channel::Listener, void OnMsgDidActivateAcceleratedCompositing(bool activated); -#if defined(OS_MACOSX) +#if defined(OS_POSIX) void OnMsgGetScreenInfo(gfx::NativeViewId view, WebKit::WebScreenInfo* results); void OnMsgGetWindowRect(gfx::NativeViewId window_id, gfx::Rect* results); void OnMsgGetRootWindowRect(gfx::NativeViewId window_id, gfx::Rect* results); +#endif +#if defined(OS_MACOSX) void OnMsgPluginFocusChanged(bool focused, int plugin_id); void OnMsgStartPluginIme(); void OnAllocateFakePluginWindowHandle(bool opaque, @@ -481,7 +483,8 @@ class RenderWidgetHost : public IPC::Channel::Listener, TransportDIB::Handle transport_dib); void OnAcceleratedSurfaceBuffersSwapped(gfx::PluginWindowHandle window, uint64 surface_id); -#elif defined(OS_POSIX) +#endif +#if defined(TOOLKIT_USES_GTK) void OnMsgCreatePluginContainer(gfx::PluginWindowHandle id); void OnMsgDestroyPluginContainer(gfx::PluginWindowHandle id); #endif diff --git a/content/browser/renderer_host/render_widget_host_gtk.cc b/content/browser/renderer_host/render_widget_host_gtk.cc index e378edf..b7dd333 100644 --- a/content/browser/renderer_host/render_widget_host_gtk.cc +++ b/content/browser/renderer_host/render_widget_host_gtk.cc @@ -4,7 +4,93 @@ #include "content/browser/renderer_host/render_widget_host.h" +#include <gdk/gdkx.h> +#include <gtk/gtk.h> + +#include "base/synchronization/lock.h" #include "content/browser/renderer_host/render_widget_host_view.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/x11/WebScreenInfoFactory.h" +#include "ui/gfx/gtk_native_view_id_manager.h" +#include "ui/gfx/rect.h" + +using WebKit::WebScreenInfo; +using WebKit::WebScreenInfoFactory; + +// We get a null |view| passed into this function please see +// http://crbug.com/9060 for more details. +void RenderWidgetHost::OnMsgGetScreenInfo(gfx::NativeViewId view, + WebScreenInfo* results) { + GtkWidget* widget = NULL; + GdkWindow* gdk_window = NULL; + if (GtkNativeViewManager::GetInstance()->GetNativeViewForId( + &widget, view) && widget) { + gdk_window = widget->window; + } else { + GdkDisplay* display = gdk_display_get_default(); + gdk_window = gdk_display_get_window_at_pointer(display, NULL, NULL); + } + if (!gdk_window) + return; + GdkScreen* screen = gdk_drawable_get_screen(gdk_window); + *results = WebScreenInfoFactory::screenInfo( + gdk_x11_drawable_get_xdisplay(gdk_window), + gdk_x11_screen_get_screen_number(screen)); + + // TODO(tony): We should move this code into WebScreenInfoFactory. + int monitor_number = gdk_screen_get_monitor_at_window(screen, gdk_window); + GdkRectangle monitor_rect; + gdk_screen_get_monitor_geometry(screen, monitor_number, &monitor_rect); + results->rect = WebKit::WebRect(monitor_rect.x, monitor_rect.y, + monitor_rect.width, monitor_rect.height); + // TODO(tony): Should we query _NET_WORKAREA to get the workarea? + results->availableRect = results->rect; +} + +// We get null window_ids passed into this function please see +// http://crbug.com/9060 for more details. +void RenderWidgetHost::OnMsgGetWindowRect(gfx::NativeViewId window_id, + gfx::Rect* results) { + GtkWidget* widget = NULL; + if (!GtkNativeViewManager::GetInstance()->GetNativeViewForId( + &widget, window_id) || !widget) { + return; + } + GdkWindow* gdk_window = widget->window; + if (!gdk_window) + return; + GdkRectangle window_rect; + gdk_window_get_origin(gdk_window, &window_rect.x, &window_rect.y); + gdk_drawable_get_size(gdk_window, &window_rect.width, &window_rect.height); + *results = window_rect; +} + +// We get null window_ids passed into this function please see +// http://crbug.com/9060 for more details. +void RenderWidgetHost::OnMsgGetRootWindowRect(gfx::NativeViewId window_id, + gfx::Rect* results) { + GtkWidget* widget = NULL; + if (!GtkNativeViewManager::GetInstance()->GetNativeViewForId( + &widget, window_id) || !widget) { + return; + } + GtkWidget* toplevel = gtk_widget_get_toplevel(widget); + if (!toplevel) + return; + + GdkRectangle frame_extents; + GdkWindow* gdk_window = toplevel->window; + if (!gdk_window) + return; + gdk_window_get_frame_extents(gdk_window, &frame_extents); + int width = 0; + int height = 0; + gdk_drawable_get_size(gdk_window, &width, &height); + // Although we return a rect, this is actually two pairs of data: The + // position of the top left corner of the window and the size of the window + // not including the window decorations. + *results = gfx::Rect(frame_extents.x, frame_extents.y, width, height); +} void RenderWidgetHost::OnMsgCreatePluginContainer(gfx::PluginWindowHandle id) { // TODO(piman): view_ can only be NULL with delayed view creation in diff --git a/content/content_browser.gypi b/content/content_browser.gypi index bfc92d0..8da029e 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -238,7 +238,6 @@ 'browser/renderer_host/redirect_to_file_resource_handler.h', 'browser/renderer_host/render_message_filter.cc', 'browser/renderer_host/render_message_filter.h', - 'browser/renderer_host/render_message_filter_gtk.cc', 'browser/renderer_host/render_message_filter_win.cc', 'browser/renderer_host/render_process_host.cc', 'browser/renderer_host/render_process_host.h', diff --git a/ui/gfx/gtk_native_view_id_manager.cc b/ui/gfx/gtk_native_view_id_manager.cc index d2a3699..14105f8 100644 --- a/ui/gfx/gtk_native_view_id_manager.cc +++ b/ui/gfx/gtk_native_view_id_manager.cc @@ -86,7 +86,7 @@ bool GtkNativeViewManager::GetXIDForId(XID* output, gfx::NativeViewId id) { base::AutoLock locked(lock_); std::map<gfx::NativeViewId, NativeViewInfo>::const_iterator i = - id_to_info_.find(id); + id_to_info_.find(id); if (i == id_to_info_.end()) return false; @@ -95,6 +95,20 @@ bool GtkNativeViewManager::GetXIDForId(XID* output, gfx::NativeViewId id) { return true; } +bool GtkNativeViewManager::GetNativeViewForId(gfx::NativeView* output, + gfx::NativeViewId id) { + base::AutoLock locked(lock_); + + std::map<gfx::NativeViewId, NativeViewInfo>::const_iterator i = + id_to_info_.find(id); + + if (i == id_to_info_.end()) + return false; + + *output = i->second.widget; + return true; +} + bool GtkNativeViewManager::GetPermanentXIDForId(XID* output, gfx::NativeViewId id) { base::AutoLock locked(lock_); @@ -197,7 +211,6 @@ void GtkNativeViewManager::OnRealize(gfx::NativeView widget) { } void GtkNativeViewManager::OnUnrealize(gfx::NativeView widget) { - base::AutoLock unrealize_locked(unrealize_lock_); base::AutoLock locked(lock_); const gfx::NativeViewId id = GetWidgetId(widget); diff --git a/ui/gfx/gtk_native_view_id_manager.h b/ui/gfx/gtk_native_view_id_manager.h index 6ea16a2..6b544ff 100644 --- a/ui/gfx/gtk_native_view_id_manager.h +++ b/ui/gfx/gtk_native_view_id_manager.h @@ -61,6 +61,11 @@ class GtkNativeViewManager { // |*xid| is set to 0. bool GetXIDForId(XID* xid, gfx::NativeViewId id); + // May be called from the UI thread: + // + // Same as GetXIDForId except it returns the NativeView (GtkWidget*). + bool GetNativeViewForId(gfx::NativeView* xid, gfx::NativeViewId id); + // Must be called from the UI thread because we may need the associated // widget to create a window. // @@ -90,8 +95,6 @@ class GtkNativeViewManager { void OnUnrealize(gfx::NativeView widget); void OnDestroy(gfx::NativeView widget); - base::Lock& unrealize_lock() { return unrealize_lock_; } - private: // This object is a singleton: GtkNativeViewManager(); @@ -107,11 +110,6 @@ class GtkNativeViewManager { gfx::NativeViewId GetWidgetId(gfx::NativeView id); - // This lock can be used to block GTK from unrealizing windows. This is needed - // when the BACKGROUND_X11 thread is using a window obtained via GetXIDForId, - // and can't allow the X11 resource to be deleted. - base::Lock unrealize_lock_; - // protects native_view_to_id_ and id_to_info_ base::Lock lock_; |