diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-24 00:35:12 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-24 00:35:12 +0000 |
commit | 6bcd5f36cd94649887eff0c87df4f4496001984a (patch) | |
tree | 28de74fe181e53fec448173bb1445062a30ec1e2 | |
parent | 0704a97d5caa9b7d90d2d9ed39b3db91557a3cb0 (diff) | |
download | chromium_src-6bcd5f36cd94649887eff0c87df4f4496001984a.zip chromium_src-6bcd5f36cd94649887eff0c87df4f4496001984a.tar.gz chromium_src-6bcd5f36cd94649887eff0c87df4f4496001984a.tar.bz2 |
The bug is "screen.width/availWidth returns different value with FireFox in Linux dual monitor environment", FireFox uses Xinerama to get screen width/height information. If we cannot use Xinerama, return the same width/height info as before.
BUG=28560
TEST=1, Prepare dual monitor Linux system which can use Xinerama. 2, Launch browser and run javascript "document.write("screen.witdh = " + screen.width + "<br>");". 3, Make sure the width is in single monitor width size.
Patch by Takano.Naoki@gmail.com.
Original Review: http://codereview.chromium.org/6714036/
Review URL: http://codereview.chromium.org/6725024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79226 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/renderer_host/render_message_filter_gtk.cc | 115 |
1 files changed, 89 insertions, 26 deletions
diff --git a/content/browser/renderer_host/render_message_filter_gtk.cc b/content/browser/renderer_host/render_message_filter_gtk.cc index 8d91b57..163285a 100644 --- a/content/browser/renderer_host/render_message_filter_gtk.cc +++ b/content/browser/renderer_host/render_message_filter_gtk.cc @@ -2,35 +2,45 @@ // 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 "chrome/common/render_messages.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" +// 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. +#include <X11/extensions/Xinerama.h> + using WebKit::WebScreenInfo; using WebKit::WebScreenInfoFactory; -// We get null window_ids passed into the two functions below; please see -// http://crbug.com/9060 for more details. +namespace { -void RenderMessageFilter::DoOnGetScreenInfo(gfx::NativeViewId view, - IPC::Message* reply_msg) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11)); - Display* display = ui::GetSecondaryDisplay(); - int screen = ui::GetDefaultScreen(display); - WebScreenInfo results = WebScreenInfoFactory::screenInfo(display, screen); - ViewHostMsg_GetScreenInfo::WriteReplyParams(reply_msg, results); - Send(reply_msg); +// 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); } -void RenderMessageFilter::DoOnGetWindowRect(gfx::NativeViewId view, - IPC::Message* reply_msg) { +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. @@ -46,23 +56,77 @@ void RenderMessageFilter::DoOnGetWindowRect(gfx::NativeViewId view, rect = gfx::Rect(x, y, width, height); } } - - ViewHostMsg_GetWindowRect::WriteReplyParams(reply_msg, rect); - Send(reply_msg); + return rect; } -// Return the top-level parent of the given window. Called on the -// BACKGROUND_X11 thread. -static XID GetTopLevelWindow(XID window) { - bool parent_is_root; - XID parent_window; +} // namespace - if (!ui::GetWindowParent(&parent_window, &parent_is_root, window)) - return 0; - if (parent_is_root) - return window; +// We get null window_ids passed into the two functions below; please see +// http://crbug.com/9060 for more details. - return GetTopLevelWindow(parent_window); +void RenderMessageFilter::DoOnGetScreenInfo(gfx::NativeViewId view, + IPC::Message* reply_msg) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::BACKGROUND_X11)); + Display* display = ui::GetSecondaryDisplay(); + + WebScreenInfo results = WebScreenInfoFactory::screenInfo(display, + ui::GetDefaultScreen(display)); + + // 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); + } + } + + ViewHostMsg_GetScreenInfo::WriteReplyParams(reply_msg, results); + Send(reply_msg); +} + +void RenderMessageFilter::DoOnGetWindowRect(gfx::NativeViewId view, + IPC::Message* reply_msg) { + ViewHostMsg_GetWindowRect::WriteReplyParams(reply_msg, + GetWindowRectFromView(view)); + Send(reply_msg); } void RenderMessageFilter::DoOnGetRootWindowRect(gfx::NativeViewId view, @@ -116,4 +180,3 @@ void RenderMessageFilter::OnGetRootWindowRect(gfx::NativeViewId view, NewRunnableMethod( this, &RenderMessageFilter::DoOnGetRootWindowRect, view, reply_msg)); } - |