Commit 8581ac38 authored by tfarina@chromium.org's avatar tfarina@chromium.org

Extract MonitorInfoProvider from WindowSizer.

And move the functionality into gfx::Screen.

BUG=101507
R=ben@chromium.org

Review URL: http://codereview.chromium.org/8549008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113531 0039d316-1c4b-4281-b951-d872f2087c98
parent a62479b9
......@@ -12,7 +12,6 @@
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_service.h"
#include "ui/gfx/rect.h"
......
......@@ -11,13 +11,13 @@
#include "chrome/browser/notifications/balloon_host.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
namespace {
......@@ -465,9 +465,7 @@ bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() {
#if defined(OS_MACOSX)
gfx::Rect new_work_area = GetMacWorkArea();
#else
scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
WindowSizer::CreateDefaultMonitorInfoProvider());
gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea();
gfx::Rect new_work_area = gfx::Screen::GetPrimaryMonitorWorkArea();
#endif
if (!work_area_.Equals(new_work_area)) {
work_area_.SetRect(new_work_area.x(), new_work_area.y(),
......
......@@ -10,7 +10,6 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
......@@ -21,6 +20,7 @@
#include "net/test/test_server.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/screen.h"
namespace {
......@@ -62,9 +62,7 @@ class PDFBrowserTest : public InProcessBrowserTest,
// to a smaller window and then expanding leads to slight anti-aliasing
// differences of the text and the pixel comparison fails.
gfx::Rect bounds(gfx::Rect(0, 0, kBrowserWidth, kBrowserHeight));
scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_info(
WindowSizer::CreateDefaultMonitorInfoProvider());
gfx::Rect screen_bounds = monitor_info->GetPrimaryMonitorBounds();
gfx::Rect screen_bounds = gfx::Screen::GetPrimaryMonitorBounds();
ASSERT_GT(screen_bounds.width(), kBrowserWidth);
ASSERT_GT(screen_bounds.height(), kBrowserHeight);
browser()->window()->SetBounds(bounds);
......
......@@ -41,8 +41,8 @@
#include "chrome/browser/ui/find_bar/find_tab_helper.h"
#include "chrome/browser/ui/gtk/about_chrome_dialog.h"
#include "chrome/browser/ui/gtk/accelerators_gtk.h"
#include "chrome/browser/ui/gtk/avatar_menu_button_gtk.h"
#include "chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h"
#include "chrome/browser/ui/gtk/avatar_menu_button_gtk.h"
#include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h"
#include "chrome/browser/ui/gtk/browser_titlebar.h"
#include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
......@@ -72,7 +72,6 @@
#include "chrome/browser/ui/page_info_bubble.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/task_manager_dialog.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
......@@ -82,8 +81,8 @@
#include "content/browser/renderer_host/render_widget_host_view.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_service.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
......@@ -97,6 +96,7 @@
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/cairo_cached_surface.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/skia_utils_gtk.h"
namespace {
......@@ -1960,10 +1960,8 @@ void BrowserWindowGtk::SaveWindowPosition() {
window_preferences->SetInteger("bottom", restored_bounds_.bottom());
window_preferences->SetBoolean("maximized", IsMaximized());
scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_info_provider(
WindowSizer::CreateDefaultMonitorInfoProvider());
gfx::Rect work_area(
monitor_info_provider->GetMonitorWorkAreaMatching(restored_bounds_));
gfx::Screen::GetMonitorWorkAreaMatching(restored_bounds_));
window_preferences->SetInteger("work_area_left", work_area.x());
window_preferences->SetInteger("work_area_top", work_area.y());
window_preferences->SetInteger("work_area_right", work_area.right());
......
......@@ -12,10 +12,10 @@
#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
#include "chrome/browser/ui/panels/panel_overflow_strip.h"
#include "chrome/browser/ui/panels/panel_strip.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "ui/gfx/screen.h"
namespace {
const int kOverflowStripThickness = 24;
......@@ -51,14 +51,12 @@ PanelManager::~PanelManager() {
}
void PanelManager::OnDisplayChanged() {
scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
WindowSizer::CreateDefaultMonitorInfoProvider());
#if defined(OS_MACOSX)
// On OSX, panels should be dropped all the way to the bottom edge of the
// screen (and overlap Dock).
gfx::Rect work_area = info_provider->GetPrimaryMonitorBounds();
gfx::Rect work_area = gfx::Screen::GetPrimaryMonitorBounds();
#else
gfx::Rect work_area = info_provider->GetPrimaryMonitorWorkArea();
gfx::Rect work_area = gfx::Screen::GetPrimaryMonitorWorkArea();
#endif
SetWorkArea(work_area);
}
......
......@@ -13,10 +13,10 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/views/accessibility_event_router_views.h"
#include "chrome/browser/ui/views/event_utils.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/common/pref_names.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/widget.h"
......@@ -69,10 +69,7 @@ void ChromeViewsDelegate::SaveWindowPlacement(const views::Widget* window,
window_preferences->SetBoolean("maximized",
show_state == ui::SHOW_STATE_MAXIMIZED);
scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_info_provider(
WindowSizer::CreateDefaultMonitorInfoProvider());
gfx::Rect work_area(
monitor_info_provider->GetMonitorWorkAreaMatching(bounds));
gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaMatching(bounds));
window_preferences->SetInteger("work_area_left", work_area.x());
window_preferences->SetInteger("work_area_top", work_area.y());
window_preferences->SetInteger("work_area_right", work_area.right());
......
......@@ -14,7 +14,6 @@
#include "chrome/browser/ui/toolbar/toolbar_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/browser/tab_contents/tab_contents.h"
......@@ -31,6 +30,7 @@
#include "ui/gfx/font.h"
#include "ui/gfx/path.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/views_delegate.h"
......
......@@ -4,6 +4,7 @@
#include "chrome/browser/ui/window_sizer.h"
#include "base/compiler_specific.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
......@@ -11,6 +12,27 @@
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/pref_names.h"
#include "ui/gfx/screen.h"
// Minimum height of the visible part of a window.
const int kMinVisibleHeight = 30;
// Minimum width of the visible part of a window.
const int kMinVisibleWidth = 30;
class DefaultMonitorInfoProvider : public MonitorInfoProvider {
public:
// Overridden from MonitorInfoProvider:
virtual gfx::Rect GetPrimaryMonitorWorkArea() const OVERRIDE {
return gfx::Screen::GetPrimaryMonitorWorkArea();
}
virtual gfx::Rect GetPrimaryMonitorBounds() const OVERRIDE {
return gfx::Screen::GetPrimaryMonitorBounds();
}
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const OVERRIDE {
return gfx::Screen::GetMonitorWorkAreaMatching(match_rect);
}
};
///////////////////////////////////////////////////////////////////////////////
// An implementation of WindowSizer::StateProvider that gets the last active
......@@ -102,6 +124,11 @@ class DefaultStateProvider : public WindowSizer::StateProvider {
///////////////////////////////////////////////////////////////////////////////
// WindowSizer, public:
WindowSizer::WindowSizer(StateProvider* state_provider)
: state_provider_(state_provider),
monitor_info_provider_(new DefaultMonitorInfoProvider) {
}
WindowSizer::WindowSizer(StateProvider* state_provider,
MonitorInfoProvider* monitor_info_provider)
: state_provider_(state_provider),
......@@ -116,8 +143,7 @@ void WindowSizer::GetBrowserWindowBounds(const std::string& app_name,
const gfx::Rect& specified_bounds,
const Browser* browser,
gfx::Rect* window_bounds) {
const WindowSizer sizer(new DefaultStateProvider(app_name, browser),
CreateDefaultMonitorInfoProvider());
const WindowSizer sizer(new DefaultStateProvider(app_name, browser));
sizer.DetermineWindowBounds(specified_bounds, window_bounds);
}
......@@ -196,40 +222,6 @@ void WindowSizer::GetDefaultWindowBounds(gfx::Rect* default_bounds) const {
default_width, default_height);
}
bool WindowSizer::PositionIsOffscreen(int position, Edge edge) const {
DCHECK(monitor_info_provider_.get());
size_t monitor_count = monitor_info_provider_->GetMonitorCount();
for (size_t i = 0; i < monitor_count; ++i) {
gfx::Rect work_area = monitor_info_provider_->GetWorkAreaAt(i);
switch (edge) {
case TOP:
if (position >= work_area.y())
return false;
break;
case LEFT:
if (position >= work_area.x())
return false;
break;
case BOTTOM:
if (position <= work_area.bottom())
return false;
break;
case RIGHT:
if (position <= work_area.right())
return false;
break;
}
}
return true;
}
namespace {
// Minimum height of the visible part of a window.
static const int kMinVisibleHeight = 30;
// Minimum width of the visible part of a window.
static const int kMinVisibleWidth = 30;
}
void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining(
const gfx::Rect& other_bounds,
const gfx::Rect& saved_work_area,
......
......@@ -6,14 +6,30 @@
#define CHROME_BROWSER_UI_WINDOW_SIZER_H_
#pragma once
#include <vector>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/rect.h"
class Browser;
// An interface implemented by an object that can retrieve information about
// the monitors on the system.
class MonitorInfoProvider {
public:
virtual ~MonitorInfoProvider() {}
// Returns the bounds of the work area of the primary monitor.
virtual gfx::Rect GetPrimaryMonitorWorkArea() const = 0;
// Returns the bounds of the primary monitor.
virtual gfx::Rect GetPrimaryMonitorBounds() const = 0;
// Returns the bounds of the work area of the monitor that most closely
// intersects the provided bounds.
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
// WindowSizer
//
......@@ -27,55 +43,18 @@ class Browser;
//
class WindowSizer {
public:
class MonitorInfoProvider;
class StateProvider;
// The WindowSizer assumes ownership of these objects.
// WindowSizer owns |state_provider| and will create a default
// MonitorInfoProvider using the physical screen.
explicit WindowSizer(StateProvider* state_provider);
// WindowSizer owns |state_provider| and |monitor_info_provider|.
// It will use the supplied monitor info provider. Used only for testing.
WindowSizer(StateProvider* state_provider,
MonitorInfoProvider* monitor_info_provider);
virtual ~WindowSizer();
// Static factory methods to create default MonitorInfoProvider
// instances. The returned object is owned by the caller.
static MonitorInfoProvider* CreateDefaultMonitorInfoProvider();
// An interface implemented by an object that can retrieve information about
// the monitors on the system.
class MonitorInfoProvider {
public:
MonitorInfoProvider() {}
virtual ~MonitorInfoProvider() {}
// Returns the bounds of the work area of the primary monitor.
virtual gfx::Rect GetPrimaryMonitorWorkArea() const = 0;
// Returns the bounds of the primary monitor.
virtual gfx::Rect GetPrimaryMonitorBounds() const = 0;
// Returns the bounds of the work area of the monitor that most closely
// intersects the provided bounds.
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const = 0;
// Ensures number and coordinates of work areas are up-to-date. You must
// call this before calling either of the below functions, as work areas can
// change while the program is running.
virtual void UpdateWorkAreas() = 0;
// Returns the number of monitors on the system.
size_t GetMonitorCount() const {
return work_areas_.size();
}
// Returns the bounds of the work area of the monitor at the specified
// index.
gfx::Rect GetWorkAreaAt(size_t index) const {
return work_areas_[index];
}
protected:
std::vector<gfx::Rect> work_areas_;
};
virtual ~WindowSizer();
// An interface implemented by an object that can retrieve state from either a
// persistent store or an existing window.
......@@ -140,10 +119,6 @@ class WindowSizer {
// size based on monitor size, etc.
void GetDefaultWindowBounds(gfx::Rect* default_bounds) const;
// Returns true if the specified position is "offscreen" for the given edge,
// meaning that it's outside all work areas in the direction of that edge.
bool PositionIsOffscreen(int position, Edge edge) const;
// Adjusts |bounds| to be visible onscreen, biased toward the work area of the
// monitor containing |other_bounds|. Despite the name, this doesn't
// guarantee the bounds are fully contained within this monitor's work rect;
......
......@@ -4,47 +4,10 @@
#include "chrome/browser/ui/window_sizer.h"
#include "base/compiler_specific.h"
#include "ui/gfx/screen.h"
// This doesn't matter for aura, which has different tiling.
// static
const int WindowSizer::kWindowTilePixels = 10;
// An implementation of WindowSizer::MonitorInfoProvider. This assumes a single
// monitor, which is currently the case.
class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
public:
DefaultMonitorInfoProvider() {}
virtual gfx::Rect GetPrimaryMonitorWorkArea() const OVERRIDE {
return gfx::Screen::GetMonitorWorkAreaNearestPoint(gfx::Point());
}
virtual gfx::Rect GetPrimaryMonitorBounds() const OVERRIDE {
return gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point());
}
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const OVERRIDE {
return gfx::Screen::GetMonitorWorkAreaNearestPoint(gfx::Point());
}
virtual void UpdateWorkAreas() OVERRIDE {
work_areas_.clear();
work_areas_.push_back(GetPrimaryMonitorBounds());
}
private:
DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
};
// static
WindowSizer::MonitorInfoProvider*
WindowSizer::CreateDefaultMonitorInfoProvider() {
return new DefaultMonitorInfoProvider();
}
// static
gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
// TODO(oshima):This is used to control panel/popups, and this may not be
......
......@@ -10,6 +10,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "ui/gfx/screen.h"
// Used to pad the default new window size. On Windows, this is also used for
// positioning new windows (each window is offset from the previous one).
......@@ -17,93 +18,9 @@
// size.
const int WindowSizer::kWindowTilePixels = 10;
// An implementation of WindowSizer::MonitorInfoProvider that gets the actual
// monitor information from X via GDK.
class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
public:
DefaultMonitorInfoProvider() { }
virtual gfx::Rect GetPrimaryMonitorWorkArea() const {
gfx::Rect rect;
if (GetScreenWorkArea(&rect))
return rect.Intersect(GetPrimaryMonitorBounds());
// Return the best we've got.
return GetPrimaryMonitorBounds();
}
virtual gfx::Rect GetPrimaryMonitorBounds() const {
GdkScreen* screen = gdk_screen_get_default();
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, 0, &rect);
return gfx::Rect(rect);
}
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const {
// TODO(thestig) Implement multi-monitor support.
return GetPrimaryMonitorWorkArea();
}
void UpdateWorkAreas() {
// TODO(thestig) Implement multi-monitor support.
work_areas_.clear();
work_areas_.push_back(GetPrimaryMonitorBounds());
}
private:
// Get the available screen space as a gfx::Rect, or return false if
// if it's unavailable (i.e. the window manager doesn't support
// retrieving this).
// TODO(thestig) Use _NET_CURRENT_DESKTOP here as well?
bool GetScreenWorkArea(gfx::Rect* out_rect) const {
gboolean ok;
guchar* raw_data = NULL;
gint data_len = 0;
ok = gdk_property_get(gdk_get_default_root_window(), // a gdk window
gdk_atom_intern("_NET_WORKAREA", FALSE), // property
gdk_atom_intern("CARDINAL", FALSE), // property type
0, // byte offset into property
0xff, // property length to retrieve
false, // delete property after retrieval?
NULL, // returned property type
NULL, // returned data format
&data_len, // returned data len
&raw_data); // returned data
if (!ok)
return false;
// We expect to get four longs back: x, y, width, height.
if (data_len < static_cast<gint>(4 * sizeof(glong))) {
NOTREACHED();
g_free(raw_data);
return false;
}
glong* data = reinterpret_cast<glong*>(raw_data);
gint x = data[0];
gint y = data[1];
gint width = data[2];
gint height = data[3];
g_free(raw_data);
out_rect->SetRect(x, y, width, height);
return true;
}
DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
};
// static
WindowSizer::MonitorInfoProvider*
WindowSizer::CreateDefaultMonitorInfoProvider() {
return new DefaultMonitorInfoProvider();
}
// static
gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
scoped_ptr<MonitorInfoProvider> provider(CreateDefaultMonitorInfoProvider());
gfx::Rect monitor_bounds = provider->GetPrimaryMonitorWorkArea();
gfx::Rect monitor_bounds = gfx::Screen::GetPrimaryMonitorWorkArea();
gfx::Point corner(monitor_bounds.x(), monitor_bounds.y());
if (Browser* browser = BrowserList::GetLastActive()) {
GtkWindow* window =
......
......@@ -2,113 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/window_sizer.h"
#import <Cocoa/Cocoa.h>
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/window_sizer.h"
// How much horizontal and vertical offset there is between newly
// opened windows.
const int WindowSizer::kWindowTilePixels = 22;
namespace {
class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
public:
DefaultMonitorInfoProvider() { }
// Overridden from WindowSizer::MonitorInfoProvider:
virtual gfx::Rect GetPrimaryMonitorWorkArea() const {
// Primary monitor is defined as the monitor with the menubar,
// which is always at index 0.
NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
NSRect frame = [primary frame];
NSRect visible_frame = [primary visibleFrame];
// Convert coordinate systems.
gfx::Rect rect = gfx::Rect(NSRectToCGRect(visible_frame));
rect.set_y(frame.size.height -
visible_frame.origin.y - visible_frame.size.height);
return rect;
}
virtual gfx::Rect GetPrimaryMonitorBounds() const {
// Primary monitor is defined as the monitor with the menubar,
// which is always at index 0.
NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
return gfx::Rect(NSRectToCGRect([primary frame]));
}
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const {
NSScreen* match_screen = GetMatchingScreen(match_rect);
return ConvertCoordinateSystem([match_screen visibleFrame]);
}
virtual void UpdateWorkAreas();
private:
// Returns a pointer to the screen that most closely matches the
// given |match_rect|. This function currently returns the screen
// that contains the largest amount of |match_rect| by area.
NSScreen* GetMatchingScreen(const gfx::Rect& match_rect) const {
// Default to the monitor with the current keyboard focus, in case
// |match_rect| is not on any screen at all.
NSScreen* max_screen = [NSScreen mainScreen];
int max_area = 0;
for (NSScreen* screen in [NSScreen screens]) {
gfx::Rect monitor_area = ConvertCoordinateSystem([screen frame]);
gfx::Rect intersection = monitor_area.Intersect(match_rect);
int area = intersection.width() * intersection.height();
if (area > max_area) {
max_area = area;
max_screen = screen;
}
}
return max_screen;
}
// The lower left corner of screen 0 is always at (0, 0). The
// cross-platform code expects the origin to be in the upper left,
// so we have to translate |ns_rect| to the new coordinate
// system.
gfx::Rect ConvertCoordinateSystem(NSRect ns_rect) const;
DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
};
void DefaultMonitorInfoProvider::UpdateWorkAreas() {
work_areas_.clear();
for (NSScreen* screen in [NSScreen screens]) {
gfx::Rect rect = ConvertCoordinateSystem([screen visibleFrame]);
work_areas_.push_back(rect);
}
}
gfx::Rect DefaultMonitorInfoProvider::ConvertCoordinateSystem(
NSRect ns_rect) const {
// Primary monitor is defined as the monitor with the menubar,
// which is always at index 0.
NSScreen* primary_screen = [[NSScreen screens] objectAtIndex:0];
float primary_screen_height = [primary_screen frame].size.height;
gfx::Rect rect(NSRectToCGRect(ns_rect));
rect.set_y(primary_screen_height - rect.y() - rect.height());
return rect;
}
} // namespace
// static
WindowSizer::MonitorInfoProvider*
WindowSizer::CreateDefaultMonitorInfoProvider() {
return new DefaultMonitorInfoProvider();
}
// static
gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
NSRect work_area = [[NSScreen mainScreen] visibleFrame];
......
......@@ -43,7 +43,7 @@ static int kWindowTilePixels = WindowSizer::kWindowTilePixels;
// Testing implementation of WindowSizer::MonitorInfoProvider that we can use
// to fake various monitor layouts and sizes.
class TestMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
class TestMonitorInfoProvider : public MonitorInfoProvider {
public:
TestMonitorInfoProvider() {}
virtual ~TestMonitorInfoProvider() {}
......@@ -68,8 +68,6 @@ class TestMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
return work_areas_[GetMonitorIndexMatchingBounds(match_rect)];
}
virtual void UpdateWorkAreas() OVERRIDE {}
private:
size_t GetMonitorIndexMatchingBounds(const gfx::Rect& match_rect) const {
int max_area = 0;
......@@ -88,6 +86,7 @@ class TestMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
}
std::vector<gfx::Rect> monitor_bounds_;
std::vector<gfx::Rect> work_areas_;
DISALLOW_COPY_AND_ASSIGN(TestMonitorInfoProvider);
};
......
......@@ -12,66 +12,6 @@
// opened windows.
const int WindowSizer::kWindowTilePixels = 10;
// An implementation of WindowSizer::MonitorInfoProvider that gets the actual
// monitor information from Windows.
class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
public:
DefaultMonitorInfoProvider() { }
// Overridden from WindowSizer::MonitorInfoProvider:
virtual gfx::Rect GetPrimaryMonitorWorkArea() const {
return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
MONITOR_DEFAULTTOPRIMARY)).rcWork);
}
virtual gfx::Rect GetPrimaryMonitorBounds() const {
return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
MONITOR_DEFAULTTOPRIMARY)).rcMonitor);
}
virtual gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect) const {
RECT other_bounds_rect = match_rect.ToRECT();
MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
&other_bounds_rect, MONITOR_DEFAULTTONEAREST));
return gfx::Rect(monitor_info.rcWork);
}
void UpdateWorkAreas() {
work_areas_.clear();
EnumDisplayMonitors(NULL, NULL,
&DefaultMonitorInfoProvider::MonitorEnumProc,
reinterpret_cast<LPARAM>(&work_areas_));
}
private:
// A callback for EnumDisplayMonitors that records the work area of the
// current monitor in the enumeration.
static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor,
HDC monitor_dc,
LPRECT monitor_rect,
LPARAM data) {
reinterpret_cast<std::vector<gfx::Rect>*>(data)->push_back(
gfx::Rect(GetMonitorInfoForMonitor(monitor).rcWork));
return TRUE;
}
static MONITORINFO GetMonitorInfoForMonitor(HMONITOR monitor) {
MONITORINFO monitor_info = { 0 };
monitor_info.cbSize = sizeof(monitor_info);
GetMonitorInfo(monitor, &monitor_info);
return monitor_info;
}
DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
};
// static
WindowSizer::MonitorInfoProvider*
WindowSizer::CreateDefaultMonitorInfoProvider() {
return new DefaultMonitorInfoProvider();
}
// static
gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
RECT area;
......
......@@ -43,6 +43,17 @@ class UI_EXPORT Screen {
// the monitor nearest the specified point.
static gfx::Rect GetMonitorAreaNearestPoint(const gfx::Point& point);
// Returns the bounds of the work area of the primary monitor.
static gfx::Rect GetPrimaryMonitorWorkArea();
// Returns the bounds of the primary monitor.
static gfx::Rect GetPrimaryMonitorBounds();
// Returns the bounds of the work area of the monitor that most closely
// intersects the provided bounds.
static gfx::Rect GetMonitorWorkAreaMatching(
const gfx::Rect& match_rect);
// Returns the window under the cursor.
static gfx::NativeWindow GetWindowAtCursorScreenPoint();
......
......@@ -47,6 +47,21 @@ gfx::Rect Screen::GetMonitorAreaNearestPoint(const gfx::Point& point) {
return instance_->GetMonitorAreaNearestPointImpl(point);
}
// static
gfx::Rect Screen::GetPrimaryMonitorWorkArea() {
return instance_->GetMonitorWorkAreaNearestPoint(gfx::Point());
}
// static
gfx::Rect Screen::GetPrimaryMonitorBounds() {
return instance_->GetMonitorAreaNearestPoint(gfx::Point());
}
// static
gfx::Rect Screen::GetMonitorWorkAreaMatching(const gfx::Rect& match_rect) {
return instance_->GetMonitorWorkAreaNearestPoint(gfx::Point());
}
// static
gfx::NativeWindow Screen::GetWindowAtCursorScreenPoint() {
return instance_->GetWindowAtCursorScreenPointImpl();
......
......@@ -9,6 +9,45 @@
#include "base/logging.h"
namespace {
bool GetScreenWorkArea(gfx::Rect* out_rect) {
gboolean ok;
guchar* raw_data = NULL;
gint data_len = 0;
ok = gdk_property_get(gdk_get_default_root_window(), // a gdk window
gdk_atom_intern("_NET_WORKAREA", FALSE), // property
gdk_atom_intern("CARDINAL", FALSE), // property type
0, // byte offset into property
0xff, // property length to retrieve
false, // delete property after retrieval?
NULL, // returned property type
NULL, // returned data format
&data_len, // returned data len
&raw_data); // returned data
if (!ok)
return false;
// We expect to get four longs back: x, y, width, height.
if (data_len < static_cast<gint>(4 * sizeof(glong))) {
NOTREACHED();
g_free(raw_data);
return false;
}
glong* data = reinterpret_cast<glong*>(raw_data);
gint x = data[0];
gint y = data[1];
gint width = data[2];
gint height = data[3];
g_free(raw_data);
out_rect->SetRect(x, y, width, height);
return true;
}
} // namespace
namespace gfx {
// static
......@@ -63,6 +102,30 @@ gfx::Rect Screen::GetMonitorAreaNearestPoint(const gfx::Point& point) {
return gfx::Rect(bounds);
}
// static
gfx::Rect Screen::GetPrimaryMonitorWorkArea() {
gfx::Rect rect;
if (GetScreenWorkArea(&rect))
return rect.Intersect(GetPrimaryMonitorBounds());
// Return the best we've got.
return GetPrimaryMonitorBounds();
}
// static
gfx::Rect Screen::GetPrimaryMonitorBounds() {
GdkScreen* screen = gdk_screen_get_default();
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, 0, &rect);
return gfx::Rect(rect);
}
// static
gfx::Rect Screen::GetMonitorWorkAreaMatching(const gfx::Rect& match_rect) {
// TODO(thestig) Implement multi-monitor support.
return GetPrimaryMonitorWorkArea();
}
// static
gfx::NativeWindow Screen::GetWindowAtCursorScreenPoint() {
GdkWindow* window = gdk_window_at_pointer(NULL, NULL);
......
......@@ -7,6 +7,39 @@
#import <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
namespace {
gfx::Rect ConvertCoordinateSystem(NSRect ns_rect) {
// Primary monitor is defined as the monitor with the menubar,
// which is always at index 0.
NSScreen* primary_screen = [[NSScreen screens] objectAtIndex:0];
float primary_screen_height = [primary_screen frame].size.height;
gfx::Rect rect(NSRectToCGRect(ns_rect));
rect.set_y(primary_screen_height - rect.y() - rect.height());
return rect;
}
NSScreen* GetMatchingScreen(const gfx::Rect& match_rect) {
// Default to the monitor with the current keyboard focus, in case
// |match_rect| is not on any screen at all.
NSScreen* max_screen = [NSScreen mainScreen];
int max_area = 0;
for (NSScreen* screen in [NSScreen screens]) {
gfx::Rect monitor_area = ConvertCoordinateSystem([screen frame]);
gfx::Rect intersection = monitor_area.Intersect(match_rect);
int area = intersection.width() * intersection.height();
if (area > max_area) {
max_area = area;
max_screen = screen;
}
}
return max_screen;
}
} // namespace
namespace gfx {
// static
......@@ -18,6 +51,35 @@ gfx::Point Screen::GetCursorScreenPoint() {
return gfx::Point(mouseLocation.x, mouseLocation.y);
}
// static
gfx::Rect Screen::GetPrimaryMonitorWorkArea() {
// Primary monitor is defined as the monitor with the menubar,
// which is always at index 0.
NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
NSRect frame = [primary frame];
NSRect visible_frame = [primary visibleFrame];
// Convert coordinate systems.
gfx::Rect rect = gfx::Rect(NSRectToCGRect(visible_frame));
rect.set_y(frame.size.height - visible_frame.origin.y -
visible_frame.size.height);
return rect;
}
// static
gfx::Rect Screen::GetPrimaryMonitorBounds() {
// Primary monitor is defined as the monitor with the menubar,
// which is always at index 0.
NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
return gfx::Rect(NSRectToCGRect([primary frame]));
}
// static
gfx::Rect Screen::GetMonitorWorkAreaMatching(const gfx::Rect& match_rect) {
NSScreen* match_screen = GetMatchingScreen(match_rect);
return ConvertCoordinateSystem([match_screen visibleFrame]);
}
// static
gfx::Size Screen::GetPrimaryMonitorSize() {
CGDirectDisplayID main_display = CGMainDisplayID();
......
......@@ -6,6 +6,17 @@
#include <windows.h>
namespace {
MONITORINFO GetMonitorInfoForMonitor(HMONITOR monitor) {
MONITORINFO monitor_info = { 0 };
monitor_info.cbSize = sizeof(monitor_info);
GetMonitorInfo(monitor, &monitor_info);
return monitor_info;
}
} // namespace
namespace gfx {
// static
......@@ -54,6 +65,26 @@ gfx::Rect Screen::GetMonitorAreaNearestPoint(const gfx::Point& point) {
return GetMonitorAreaOrWorkAreaNearestPoint(point, false);
}
// static
gfx::Rect Screen::GetPrimaryMonitorWorkArea() {
return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
MONITOR_DEFAULTTOPRIMARY)).rcWork);
}
// static
gfx::Rect Screen::GetPrimaryMonitorBounds() {
return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
MONITOR_DEFAULTTOPRIMARY)).rcMonitor);
}
// static
gfx::Rect Screen::GetMonitorWorkAreaMatching(const gfx::Rect& match_rect) {
RECT other_bounds_rect = match_rect.ToRECT();
MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
&other_bounds_rect, MONITOR_DEFAULTTONEAREST));
return gfx::Rect(monitor_info.rcWork);
}
// static
gfx::NativeWindow Screen::GetWindowAtCursorScreenPoint() {
POINT location;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment