Commit 5978af5e authored by derat@chromium.org's avatar derat@chromium.org

aura: Try to make Linux host resize code more reliable.

There's no guarantee that we'll get the host window size that
we ask for.  This adjusts WindowTest.Transform to not ask for
a specific size, and instead just use the size it's been
given.

I also fixed a race in DesktopHostLinux::Show() when running
under X window managers that don't take the _WM_S0 selection.
We now wait for notification that the host window has been
mapped before trying to focus it.

I moved the logic for choosing to create a fullscreen host
window out of DesktopHostLinux and into the browser.

Finally, I changed DesktopHostLinux::SetSize() (called by
Desktop::SetHostSize()) update the internal size and notify
the desktop immediately.

BUG=100979,100894
TEST=tests pass on ion3; fullscreen window is created on chrome os

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106989 0039d316-1c4b-4281-b951-d872f2087c98
parent 2b89cb91
......@@ -143,6 +143,7 @@
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/system/runtime_environment.h"
#include "chrome/browser/chromeos/system_key_event_listener.h"
#include "chrome/browser/chromeos/user_cros_settings_provider.h"
#include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
......@@ -1347,6 +1348,11 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunInternal() {
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kViewsDesktop);
#endif
#if defined(USE_AURA) && defined(OS_CHROMEOS)
if (chromeos::system::runtime_environment::IsRunningOnChromeOS())
aura::Desktop::set_use_fullscreen_host_window(true);
#endif
// Always add the --block-reading-third-party-cookies flag, if not already
// set. We'll leave this on for a bit to determine if we Break The Web for
// Canary users.
......
......@@ -41,11 +41,9 @@ static const int kDefaultHostWindowHeight = 1024;
} // namespace
// static
Desktop* Desktop::instance_ = NULL;
// static
ui::Compositor*(*Desktop::compositor_factory_)() = NULL;
bool Desktop::use_fullscreen_host_window_ = false;
Desktop::Desktop()
: Window(NULL),
......@@ -411,26 +409,29 @@ bool Desktop::IsFocusedWindow(const Window* window) const {
void Desktop::Init() {
Window::Init();
SetBounds(gfx::Rect(gfx::Point(), host_->GetSize()));
SetBounds(gfx::Rect(host_->GetSize()));
Show();
compositor()->SetRootLayer(layer());
}
gfx::Rect Desktop::GetInitialHostWindowBounds() const {
gfx::Rect bounds(kDefaultHostWindowX, kDefaultHostWindowY,
kDefaultHostWindowWidth, kDefaultHostWindowHeight);
const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kAuraHostWindowSize);
int width = 0, height = 0;
vector<string> parts;
base::SplitString(size_str, 'x', &parts);
if (parts.size() != 2 ||
!base::StringToInt(parts[0], &width) ||
!base::StringToInt(parts[1], &height) ||
width <= 0 || height <= 0) {
width = kDefaultHostWindowWidth;
height = kDefaultHostWindowHeight;
int parsed_width = 0, parsed_height = 0;
if (parts.size() == 2 &&
base::StringToInt(parts[0], &parsed_width) && parsed_width > 0 &&
base::StringToInt(parts[1], &parsed_height) && parsed_height > 0) {
bounds.set_size(gfx::Size(parsed_width, parsed_height));
} else if (use_fullscreen_host_window_) {
bounds = gfx::Rect(DesktopHost::GetNativeDisplaySize());
}
return gfx::Rect(kDefaultHostWindowX, kDefaultHostWindowY, width, height);
return bounds;
}
} // namespace aura
......@@ -56,6 +56,10 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate,
return compositor_factory_;
}
static void set_use_fullscreen_host_window(bool use_fullscreen) {
use_fullscreen_host_window_ = use_fullscreen;
}
ui::Compositor* compositor() { return compositor_.get(); }
gfx::Point last_mouse_location() const { return last_mouse_location_; }
DesktopDelegate* delegate() { return delegate_.get(); }
......@@ -167,12 +171,17 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate,
static Desktop* instance_;
// Used to schedule painting.
base::WeakPtrFactory<Desktop> schedule_paint_factory_;
// Factory used to create Compositors. Settable by tests.
static ui::Compositor*(*compositor_factory_)();
// If set before the Desktop is created, the host window will cover the entire
// screen. Note that this can still be overridden via the
// switches::kAuraHostWindowSize flag.
static bool use_fullscreen_host_window_;
// Used to schedule painting.
base::WeakPtrFactory<Desktop> schedule_paint_factory_;
Window* active_window_;
// Last location seen in a mouse event.
......
......@@ -29,6 +29,10 @@ class DesktopHost : public MessageLoop::Dispatcher {
// Creates a new DesktopHost. The caller owns the returned value.
static DesktopHost* Create(const gfx::Rect& bounds);
// Returns the actual size of the display.
// (gfx::Screen only reports on the virtual desktop exposed by Aura.)
static gfx::Size GetNativeDisplaySize();
// Sets the Desktop this DesktopHost is hosting. DesktopHost does not own the
// Desktop.
virtual void SetDesktop(Desktop* desktop) = 0;
......
......@@ -198,7 +198,9 @@ class DesktopHostLinux : public DesktopHost {
virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
virtual gfx::Point QueryMouseLocation() OVERRIDE;
// Returns true if there's an X window manager present.
// Returns true if there's an X window manager present... in most cases. Some
// window managers (notably, ion3) don't implement enough of ICCCM for us to
// detect that they're there.
bool IsWindowManagerPresent();
Desktop* desktop_;
......@@ -211,33 +213,20 @@ class DesktopHostLinux : public DesktopHost {
gfx::NativeCursor current_cursor_;
// The size of |xwindow_|.
gfx::Rect bounds_;
// True while we requested configure, but haven't recieved configure event
// yet.
bool expect_configure_event_;
gfx::Size size_;
DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux);
};
DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds)
: desktop_(NULL),
xdisplay_(NULL),
xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
xwindow_(0),
current_cursor_(aura::kCursorNull),
bounds_(bounds) {
// This assumes that the message-pump creates and owns the display.
xdisplay_ = base::MessagePumpX::GetDefaultXDisplay();
// Ingore the requested bounds and just cover the whole screen if there's no
// X window manager present.
if (!IsWindowManagerPresent())
bounds_.SetRect(
0, 0, DisplayWidth(xdisplay_, 0), DisplayHeight(xdisplay_, 0));
size_(bounds.size()) {
xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_),
bounds_.x(), bounds_.y(),
bounds_.width(), bounds_.height(),
bounds.x(), bounds.y(),
bounds.width(), bounds.height(),
0, 0, 0);
long event_mask = ButtonPressMask | ButtonReleaseMask |
......@@ -282,28 +271,6 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
handled = desktop_->DispatchMouseEvent(&mouseev);
break;
}
case MotionNotify: {
// Discard all but the most recent motion event that targets the same
// window with unchanged state.
XEvent last_event;
while (XPending(xev->xany.display)) {
XEvent next_event;
XPeekEvent(xev->xany.display, &next_event);
if (next_event.type == MotionNotify &&
next_event.xmotion.window == xev->xmotion.window &&
next_event.xmotion.subwindow == xev->xmotion.subwindow &&
next_event.xmotion.state == xev->xmotion.state) {
XNextEvent(xev->xany.display, &last_event);
xev = &last_event;
} else {
break;
}
}
MouseEvent mouseev(xev);
handled = desktop_->DispatchMouseEvent(&mouseev);
break;
}
case ConfigureNotify: {
DCHECK_EQ(xdisplay_, xev->xconfigure.display);
DCHECK_EQ(xwindow_, xev->xconfigure.window);
......@@ -313,15 +280,13 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
// from within aura (e.g. the X window manager can change the size). Make
// sure the desktop size is maintained properly.
gfx::Size size(xev->xconfigure.width, xev->xconfigure.height);
if (bounds_.size() != size || expect_configure_event_) {
expect_configure_event_ = false;
bounds_.set_size(size);
if (size_ != size) {
size_ = size;
desktop_->OnHostResized(size);
}
handled = true;
break;
}
case GenericEvent: {
ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
if (!factory->ShouldProcessXI2Event(xev))
......@@ -367,6 +332,37 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
// If we coalesced an event we need to free its cookie.
if (num_coalesced > 0)
XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
break;
}
case MapNotify: {
// If there's no window manager running, we need to assign the X input
// focus to our host window.
if (!IsWindowManagerPresent())
XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
handled = true;
break;
}
case MotionNotify: {
// Discard all but the most recent motion event that targets the same
// window with unchanged state.
XEvent last_event;
while (XPending(xev->xany.display)) {
XEvent next_event;
XPeekEvent(xev->xany.display, &next_event);
if (next_event.type == MotionNotify &&
next_event.xmotion.window == xev->xmotion.window &&
next_event.xmotion.subwindow == xev->xmotion.subwindow &&
next_event.xmotion.state == xev->xmotion.state) {
XNextEvent(xev->xany.display, &last_event);
xev = &last_event;
} else {
break;
}
}
MouseEvent mouseev(xev);
handled = desktop_->DispatchMouseEvent(&mouseev);
break;
}
}
return handled ? EVENT_PROCESSED : EVENT_IGNORED;
......@@ -382,27 +378,25 @@ gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() {
void DesktopHostLinux::Show() {
XMapWindow(xdisplay_, xwindow_);
// If there's no window manager running, we need to assign the X input focus
// to our host window. (If there's no window manager running, it should also
// be safe to assume that the host window will have been mapped by the time
// that our SetInputFocus request is received.)
if (!IsWindowManagerPresent())
XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
XFlush(xdisplay_);
}
gfx::Size DesktopHostLinux::GetSize() const {
return bounds_.size();
return size_;
}
void DesktopHostLinux::SetSize(const gfx::Size& size) {
if (bounds_.size() == size)
if (size == size_)
return;
expect_configure_event_ = true;
bounds_.set_size(size);
XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
// Assume that the resize will go through as requested, which should be the
// case if we're running without a window manager. If there's a window
// manager, it can modify or ignore the request, but (per ICCCM) we'll get a
// (possibly synthetic) ConfigureNotify about the actual size and correct
// |size_| later.
size_ = size;
desktop_->OnHostResized(size);
}
void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) {
......@@ -428,8 +422,8 @@ gfx::Point DesktopHostLinux::QueryMouseLocation() {
&root_x_return, &root_y_return,
&win_x_return, &win_y_return,
&mask_return);
return gfx::Point(max(0, min(bounds_.width(), win_x_return)),
max(0, min(bounds_.height(), win_y_return)));
return gfx::Point(max(0, min(size_.width(), win_x_return)),
max(0, min(size_.height(), win_y_return)));
}
bool DesktopHostLinux::IsWindowManagerPresent() {
......@@ -446,4 +440,10 @@ DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
return new DesktopHostLinux(bounds);
}
// static
gfx::Size DesktopHost::GetNativeDisplaySize() {
::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
}
} // namespace aura
......@@ -106,6 +106,12 @@ DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
return new DesktopHostWin(bounds);
}
// static
gfx::Size DesktopHost::GetNativeDisplaySize() {
return gfx::Size(GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN));
}
DesktopHostWin::DesktopHostWin(const gfx::Rect& bounds) : desktop_(NULL) {
Init(NULL, bounds);
SetWindowText(hwnd(), L"aura::Desktop!");
......
......@@ -969,11 +969,8 @@ TEST_F(WindowTest, IsOrContainsFullscreenWindow) {
// Tests transformation on the desktop.
TEST_F(WindowTest, Transform) {
Desktop* desktop = Desktop::GetInstance();
gfx::Size size(200, 300);
desktop->SetHostSize(size);
desktop->ShowDesktop();
EXPECT_EQ(gfx::Rect(size), gfx::Rect(desktop->GetHostSize()));
gfx::Size size = desktop->GetHostSize();
EXPECT_EQ(gfx::Rect(size),
gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point()));
......@@ -984,26 +981,35 @@ TEST_F(WindowTest, Transform) {
desktop->SetTransform(transform);
// The size should be the transformed size.
EXPECT_EQ(gfx::Rect(0, 0, 300, 200), gfx::Rect(desktop->GetHostSize()));
EXPECT_EQ(gfx::Rect(0, 0, 300, 200), desktop->bounds());
EXPECT_EQ(gfx::Rect(0, 0, 300, 200),
gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point()));
gfx::Size transformed_size(size.height(), size.width());
EXPECT_EQ(transformed_size.ToString(), desktop->GetHostSize().ToString());
EXPECT_EQ(gfx::Rect(transformed_size).ToString(),
desktop->bounds().ToString());
EXPECT_EQ(gfx::Rect(transformed_size).ToString(),
gfx::Screen::GetMonitorAreaNearestPoint(gfx::Point()).ToString());
ActivateWindowDelegate d1;
scoped_ptr<Window> w1(
CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(0, 10, 50, 50), NULL));
w1->Show();
gfx::Point miss_point(5, 5);
transform.TransformPoint(miss_point);
MouseEvent mouseev1(ui::ET_MOUSE_PRESSED,
gfx::Point(195, 5), ui::EF_LEFT_BUTTON_DOWN);
miss_point,
ui::EF_LEFT_BUTTON_DOWN);
desktop->DispatchMouseEvent(&mouseev1);
EXPECT_FALSE(w1->GetFocusManager()->GetFocusedWindow());
MouseEvent mouseup(ui::ET_MOUSE_RELEASED,
gfx::Point(195, 5), ui::EF_LEFT_BUTTON_DOWN);
miss_point,
ui::EF_LEFT_BUTTON_DOWN);
desktop->DispatchMouseEvent(&mouseup);
gfx::Point hit_point(5, 15);
transform.TransformPoint(hit_point);
MouseEvent mouseev2(ui::ET_MOUSE_PRESSED,
gfx::Point(185, 5), ui::EF_LEFT_BUTTON_DOWN);
hit_point,
ui::EF_LEFT_BUTTON_DOWN);
desktop->DispatchMouseEvent(&mouseev2);
EXPECT_EQ(w1.get(), desktop->active_window());
EXPECT_EQ(w1.get(), w1->GetFocusManager()->GetFocusedWindow());
......
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