1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/gfx/screen.h"
10 #include "base/logging.h"
11 #include "ui/gfx/display.h"
15 bool GetScreenWorkArea(gfx::Rect
* out_rect
) {
17 guchar
* raw_data
= NULL
;
19 ok
= gdk_property_get(gdk_get_default_root_window(), // a gdk window
20 gdk_atom_intern("_NET_WORKAREA", FALSE
), // property
21 gdk_atom_intern("CARDINAL", FALSE
), // property type
22 0, // byte offset into property
23 0xff, // property length to retrieve
24 false, // delete property after retrieval?
25 NULL
, // returned property type
26 NULL
, // returned data format
27 &data_len
, // returned data len
28 &raw_data
); // returned data
32 // We expect to get four longs back: x, y, width, height.
33 if (data_len
< static_cast<gint
>(4 * sizeof(glong
))) {
39 glong
* data
= reinterpret_cast<glong
*>(raw_data
);
43 gint height
= data
[3];
46 out_rect
->SetRect(x
, y
, width
, height
);
50 gfx::Rect
NativePrimaryMonitorBounds() {
51 GdkScreen
* screen
= gdk_screen_get_default();
53 gdk_screen_get_monitor_geometry(screen
, 0, &rect
);
54 return gfx::Rect(rect
);
57 gfx::Rect
GetMonitorAreaNearestWindow(gfx::NativeView view
) {
58 GdkScreen
* screen
= gdk_screen_get_default();
60 if (view
&& GTK_IS_WINDOW(view
)) {
61 GtkWidget
* top_level
= gtk_widget_get_toplevel(view
);
62 DCHECK(GTK_IS_WINDOW(top_level
));
63 GtkWindow
* window
= GTK_WINDOW(top_level
);
64 screen
= gtk_window_get_screen(window
);
65 monitor_num
= gdk_screen_get_monitor_at_window(
67 gtk_widget_get_window(top_level
));
70 gdk_screen_get_monitor_geometry(screen
, monitor_num
, &bounds
);
71 return gfx::Rect(bounds
);
74 class ScreenGtk
: public gfx::Screen
{
79 virtual ~ScreenGtk() {
82 virtual bool IsDIPEnabled() OVERRIDE
{
86 virtual gfx::Point
GetCursorScreenPoint() OVERRIDE
{
88 gdk_display_get_pointer(gdk_display_get_default(), NULL
, &x
, &y
, NULL
);
89 return gfx::Point(x
, y
);
92 // Returns the window under the cursor.
93 virtual gfx::NativeWindow
GetWindowAtCursorScreenPoint() OVERRIDE
{
94 GdkWindow
* window
= gdk_window_at_pointer(NULL
, NULL
);
99 gdk_window_get_user_data(window
, &data
);
100 GtkWidget
* widget
= reinterpret_cast<GtkWidget
*>(data
);
103 widget
= gtk_widget_get_toplevel(widget
);
104 return GTK_IS_WINDOW(widget
) ? GTK_WINDOW(widget
) : NULL
;
107 // Returns the number of displays.
108 // Mirrored displays are excluded; this method is intended to return the
109 // number of distinct, usable displays.
110 virtual int GetNumDisplays() OVERRIDE
{
111 // This query is kinda bogus for Linux -- do we want number of X screens?
112 // The number of monitors Xinerama has? We'll just use whatever GDK uses.
113 GdkScreen
* screen
= gdk_screen_get_default();
114 return gdk_screen_get_n_monitors(screen
);
117 // Returns the display nearest the specified window.
118 virtual gfx::Display
GetDisplayNearestWindow(
119 gfx::NativeView view
) const OVERRIDE
{
120 gfx::Rect bounds
= GetMonitorAreaNearestWindow(view
);
121 // Do not use the _NET_WORKAREA here, this is supposed to be an area on a
122 // specific monitor, and _NET_WORKAREA is a hint from the WM that
123 // generally spans across all monitors. This would make the work area
124 // larger than the monitor.
125 // TODO(danakj) This is a work-around as there is no standard way to get
126 // this area, but it is a rect that we should be computing. The standard
127 // means to compute this rect would be to watch all windows with
128 // _NET_WM_STRUT(_PARTIAL) hints, and subtract their space from the
129 // physical area of the display to construct a work area.
130 // TODO(oshima): Implement ID and Observer.
131 return gfx::Display(0, bounds
);
134 // Returns the the display nearest the specified point.
135 virtual gfx::Display
GetDisplayNearestPoint(
136 const gfx::Point
& point
) const OVERRIDE
{
137 GdkScreen
* screen
= gdk_screen_get_default();
138 gint monitor
= gdk_screen_get_monitor_at_point(
139 screen
, point
.x(), point
.y());
141 gdk_screen_get_monitor_geometry(screen
, monitor
, &bounds
);
142 // TODO(oshima): Implement ID and Observer.
143 return gfx::Display(0, gfx::Rect(bounds
));
146 // Returns the display that most closely intersects the provided bounds.
147 virtual gfx::Display
GetDisplayMatching(
148 const gfx::Rect
& match_rect
) const OVERRIDE
{
149 // TODO(thestig) Implement multi-monitor support.
150 return GetPrimaryDisplay();
153 // Returns the primary display.
154 virtual gfx::Display
GetPrimaryDisplay() const OVERRIDE
{
155 gfx::Rect bounds
= NativePrimaryMonitorBounds();
156 // TODO(oshima): Implement ID and Observer.
157 gfx::Display
display(0, bounds
);
159 if (GetScreenWorkArea(&rect
)) {
160 display
.set_work_area(gfx::IntersectRects(rect
, bounds
));
162 // Return the best we've got.
163 display
.set_work_area(bounds
);
168 virtual void AddObserver(gfx::DisplayObserver
* observer
) OVERRIDE
{
169 // TODO(oshima): crbug.com/122863.
172 virtual void RemoveObserver(gfx::DisplayObserver
* observer
) OVERRIDE
{
173 // TODO(oshima): crbug.com/122863.
177 DISALLOW_COPY_AND_ASSIGN(ScreenGtk
);
184 Screen
* CreateNativeScreen() {
185 return new ScreenGtk
;