diff options
author | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-15 00:20:18 +0000 |
---|---|---|
committer | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-15 00:20:18 +0000 |
commit | 488b420457ae3b003ba2cd9e9dd12fc4067833ec (patch) | |
tree | 0f70baea04a2a50ab27203a4b01a2a0d249e1851 /ui | |
parent | f3fa076c5af0d1f384fa298bced8fddcac912a6e (diff) | |
download | chromium_src-488b420457ae3b003ba2cd9e9dd12fc4067833ec.zip chromium_src-488b420457ae3b003ba2cd9e9dd12fc4067833ec.tar.gz chromium_src-488b420457ae3b003ba2cd9e9dd12fc4067833ec.tar.bz2 |
[Aura] Support always-on-top top level window.
BUG=97256,102582
TEST=AlwaysOnTop related tests in ShellTest should pass.
Review URL: http://codereview.chromium.org/8387043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109990 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura/client/aura_constants.cc | 11 | ||||
-rw-r--r-- | ui/aura/client/aura_constants.h | 11 | ||||
-rw-r--r-- | ui/aura/desktop_host_linux.cc | 3 | ||||
-rw-r--r-- | ui/aura/test/aura_test_base.cc | 8 | ||||
-rw-r--r-- | ui/aura/test/aura_test_base.h | 4 | ||||
-rw-r--r-- | ui/aura_shell/always_on_top_controller.cc | 80 | ||||
-rw-r--r-- | ui/aura_shell/always_on_top_controller.h | 54 | ||||
-rw-r--r-- | ui/aura_shell/aura_shell.gyp | 5 | ||||
-rw-r--r-- | ui/aura_shell/shell.cc | 8 | ||||
-rw-r--r-- | ui/aura_shell/shell_unittest.cc | 107 | ||||
-rw-r--r-- | ui/aura_shell/stacking_controller.cc | 10 | ||||
-rw-r--r-- | ui/aura_shell/stacking_controller.h | 8 | ||||
-rw-r--r-- | ui/aura_shell/stacking_controller_unittest.cc | 6 | ||||
-rw-r--r-- | ui/aura_shell/test/aura_shell_test_base.cc | 36 | ||||
-rw-r--r-- | ui/aura_shell/test/aura_shell_test_base.h | 31 | ||||
-rw-r--r-- | ui/base/x/x11_util.cc | 22 | ||||
-rw-r--r-- | ui/base/x/x11_util.h | 4 |
17 files changed, 385 insertions, 23 deletions
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc index fb6aa65..cae03d6 100644 --- a/ui/aura/client/aura_constants.cc +++ b/ui/aura/client/aura_constants.cc @@ -6,10 +6,9 @@ namespace aura { -const char* kRestoreBoundsKey = "RestoreBoundsKey"; +const char kAlwaysOnTopKey[] = "AlwaysOnTop"; +const char kRestoreBoundsKey[] = "RestoreBoundsKey"; +const char kShowStateKey[] = "ShowStateKey"; +const char kTooltipTextKey[] = "TooltipTextKey"; -const char* kShowStateKey = "ShowStateKey"; - -const char* kTooltipTextKey = "TooltipTextKey"; - -} +} // namespace aura diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h index 1c7def54..c206563 100644 --- a/ui/aura/client/aura_constants.h +++ b/ui/aura/client/aura_constants.h @@ -11,17 +11,20 @@ namespace aura { // Window property keys that are shared between aura_shell and chrome/views. +// A property key to store always-on-top flag. The type of the value is boolean. +AURA_EXPORT extern const char kAlwaysOnTopKey[]; + // A property key to store the restore bounds for a window. The type // of the value is |gfx::Rect*|. -AURA_EXPORT extern const char* kRestoreBoundsKey; +AURA_EXPORT extern const char kRestoreBoundsKey[]; // A property key to store ui::WindowShowState for a window. // See ui/base/ui_base_types.h for its definition. -AURA_EXPORT extern const char* kShowStateKey; +AURA_EXPORT extern const char kShowStateKey[]; // A property key to store tooltip text for a window. The type of the value -// is |std::string*|. -AURA_EXPORT extern const char* kTooltipTextKey; +// is |string16*|. +AURA_EXPORT extern const char kTooltipTextKey[]; } // namespace aura diff --git a/ui/aura/desktop_host_linux.cc b/ui/aura/desktop_host_linux.cc index 17cacb8..e20b1c57 100644 --- a/ui/aura/desktop_host_linux.cc +++ b/ui/aura/desktop_host_linux.cc @@ -289,6 +289,9 @@ DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) DesktopHostLinux::~DesktopHostLinux() { XDestroyWindow(xdisplay_, xwindow_); + + // Clears XCursorCache. + ui::GetXCursor(ui::kCursorClearXCursorCache); } base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( diff --git a/ui/aura/test/aura_test_base.cc b/ui/aura/test/aura_test_base.cc index 8d7a7bc..185ae6a 100644 --- a/ui/aura/test/aura_test_base.cc +++ b/ui/aura/test/aura_test_base.cc @@ -38,8 +38,7 @@ AuraTestBase::~AuraTestBase() { // Flush the message loop because we have pending release tasks // and these tasks if un-executed would upset Valgrind. - message_loop_.RunAllPendingWithDispatcher( - Desktop::GetInstance()->GetDispatcher()); + RunAllPendingInMessageLoop(); // Ensure that we don't use the previously-allocated static Desktop object // later -- on Linux, it holds a reference to our message loop's X connection. @@ -61,5 +60,10 @@ void AuraTestBase::TearDown() { testing::Test::TearDown(); } +void AuraTestBase::RunAllPendingInMessageLoop() { + message_loop_.RunAllPendingWithDispatcher( + Desktop::GetInstance()->GetDispatcher()); +} + } // namespace test } // namespace aura diff --git a/ui/aura/test/aura_test_base.h b/ui/aura/test/aura_test_base.h index bea5a75..8986a2f 100644 --- a/ui/aura/test/aura_test_base.h +++ b/ui/aura/test/aura_test_base.h @@ -28,6 +28,10 @@ class AuraTestBase : public testing::Test { virtual void SetUp() OVERRIDE; virtual void TearDown() OVERRIDE; + protected: + // Flushes message loop. + void RunAllPendingInMessageLoop(); + private: MessageLoopForUI message_loop_; bool setup_called_; diff --git a/ui/aura_shell/always_on_top_controller.cc b/ui/aura_shell/always_on_top_controller.cc new file mode 100644 index 0000000..177deb3 --- /dev/null +++ b/ui/aura_shell/always_on_top_controller.cc @@ -0,0 +1,80 @@ +// 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 "ui/aura_shell/always_on_top_controller.h" + +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/window.h" +#include "ui/aura/window_types.h" + +namespace aura_shell { +namespace internal { + +AlwaysOnTopController::AlwaysOnTopController() + : default_container_(NULL), + always_on_top_container_(NULL) { +} + +AlwaysOnTopController::~AlwaysOnTopController() { + if (default_container_) + default_container_->RemoveObserver(this); + if (always_on_top_container_) + always_on_top_container_->RemoveObserver(this); +} + +void AlwaysOnTopController::SetContainers(aura::Window* default_container, + aura::Window* always_on_top_container) { + // Both containers should have no children. + DCHECK(default_container->children().empty()); + DCHECK(always_on_top_container->children().empty()); + + // We are not handling any containers yet. + DCHECK(default_container_ == NULL && always_on_top_container_ == NULL); + + default_container_ = default_container; + default_container_->AddObserver(this); + + always_on_top_container_ = always_on_top_container; + always_on_top_container_->AddObserver(this); +} + +aura::Window* AlwaysOnTopController::GetContainer(aura::Window* window) const { + DCHECK(default_container_ && always_on_top_container_); + return !window->GetProperty(aura::kAlwaysOnTopKey) ? default_container_ : + always_on_top_container_; +} + +void AlwaysOnTopController::OnWindowAdded(aura::Window* child) { + // Observe direct child of the containers. + if (child->parent() == default_container_ || + child->parent() == always_on_top_container_) { + child->AddObserver(this); + } +} + +void AlwaysOnTopController::OnWillRemoveWindow(aura::Window* child) { + child->RemoveObserver(this); +} + +void AlwaysOnTopController::OnPropertyChanged(aura::Window* window, + const char* name, + void* old) { + if (name == aura::kAlwaysOnTopKey) { + DCHECK(window->type() == aura::WINDOW_TYPE_NORMAL || + window->type() == aura::WINDOW_TYPE_POPUP); + aura::Window* container = GetContainer(window); + if (window->parent() != container) + container->AddChild(window); + } +} + +void AlwaysOnTopController::OnWindowDestroyed(aura::Window* window) { + if (window == default_container_) + default_container_ = NULL; + if (window == always_on_top_container_) + always_on_top_container_ = NULL; +} + +} // namespace internal +} // namespace aura_shell diff --git a/ui/aura_shell/always_on_top_controller.h b/ui/aura_shell/always_on_top_controller.h new file mode 100644 index 0000000..e0690b3 --- /dev/null +++ b/ui/aura_shell/always_on_top_controller.h @@ -0,0 +1,54 @@ +// 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. + +#ifndef UI_AURA_SHELL_ALWAYS_ON_TOP_CONTROLLER_H_ +#define UI_AURA_SHELL_ALWAYS_ON_TOP_CONTROLLER_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/window_observer.h" + +namespace aura { +class Window; +} + +namespace aura_shell { +namespace internal { + +// AlwaysOnTopController puts window into proper containers based on its +// 'AlwaysOnTop' property. That is, putting a window to |default_container_| +// if its "AlwaysOnTop" property is false. Otherwise, put it in +// |always_on_top_container_|. +class AlwaysOnTopController : public aura::WindowObserver { + public: + AlwaysOnTopController(); + virtual ~AlwaysOnTopController(); + + // Sets the two top level window containers. + void SetContainers(aura::Window* default_container, + aura::Window* always_on_top_container); + + // Gets container for given |window| based on its "AlwaysOnTop" property. + aura::Window* GetContainer(aura::Window* window) const; + + private: + // Overridden from aura::WindowObserver: + virtual void OnWindowAdded(aura::Window* child) OVERRIDE; + virtual void OnWillRemoveWindow(aura::Window* child) OVERRIDE; + virtual void OnPropertyChanged(aura::Window* window, + const char* name, + void* old) OVERRIDE; + virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; + + aura::Window* default_container_; + aura::Window* always_on_top_container_; + + DISALLOW_COPY_AND_ASSIGN(AlwaysOnTopController); +}; + +} // namepsace aura_shell +} // namepsace internal + +#endif // UI_AURA_SHELL_ALWAYS_ON_TOP_CONTROLLER_H_ diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp index 9a9fb01..240f49b 100644 --- a/ui/aura_shell/aura_shell.gyp +++ b/ui/aura_shell/aura_shell.gyp @@ -33,6 +33,8 @@ ], 'sources': [ # All .cc, .h under views, except unittests + 'always_on_top_controller.cc', + 'always_on_top_controller.h', 'default_container_event_filter.cc', 'default_container_event_filter.h', 'default_container_layout_manager.cc', @@ -121,9 +123,12 @@ 'launcher/view_model_unittest.cc', 'launcher/view_model_utils_unittest.cc', 'run_all_unittests.cc', + 'shell_unittest.cc', 'stacking_controller_unittest.cc', 'test_suite.cc', 'test_suite.h', + 'test/aura_shell_test_base.cc', + 'test/aura_shell_test_base.h', 'toplevel_layout_manager_unittest.cc', 'toplevel_window_event_filter_unittest.cc', 'workspace_controller_unittest.cc', diff --git a/ui/aura_shell/shell.cc b/ui/aura_shell/shell.cc index c16b63c..dc40423 100644 --- a/ui/aura_shell/shell.cc +++ b/ui/aura_shell/shell.cc @@ -92,6 +92,9 @@ Shell::Shell(ShellDelegate* delegate) } Shell::~Shell() { + DCHECK(instance_ == this); + instance_ = NULL; + // Make sure we delete WorkspaceController before launcher is // deleted as it has a reference to launcher model. workspace_controller_.reset(); @@ -130,6 +133,11 @@ void Shell::Init() { (*i)->Show(); } + internal::StackingController* stacking_controller = + static_cast<internal::StackingController*>( + desktop_window->stacking_client()); + stacking_controller->Init(); + internal::DesktopLayoutManager* desktop_layout = new internal::DesktopLayoutManager(desktop_window); desktop_window->SetLayoutManager(desktop_layout); diff --git a/ui/aura_shell/shell_unittest.cc b/ui/aura_shell/shell_unittest.cc new file mode 100644 index 0000000..a9a18e2 --- /dev/null +++ b/ui/aura_shell/shell_unittest.cc @@ -0,0 +1,107 @@ +// 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 "ui/aura/test/aura_test_base.h" +#include "ui/aura/window.h" +#include "ui/aura_shell/shell.h" +#include "ui/aura_shell/shell_window_ids.h" +#include "ui/aura_shell/test/aura_shell_test_base.h" +#include "views/widget/widget.h" + +namespace aura_shell { +namespace test { + +namespace { + +views::Widget* CreateTestWindow(const views::Widget::InitParams& params) { + views::Widget* widget = new views::Widget; + widget->Init(params); + return widget; +} + +aura::Window* GetDefaultContainer() { + return Shell::GetInstance()->GetContainer( + aura_shell::internal::kShellWindowId_DefaultContainer); +} + +aura::Window* GetAlwaysOnTopContainer() { + return Shell::GetInstance()->GetContainer( + aura_shell::internal::kShellWindowId_AlwaysOnTopContainer); +} + +void TestCreateWindow(views::Widget::InitParams::Type type, + bool always_on_top, + aura::Window* expected_container) { + views::Widget::InitParams widget_params(type); + widget_params.keep_on_top = always_on_top; + + views::Widget* widget = CreateTestWindow(widget_params); + widget->Show(); + + EXPECT_EQ(expected_container, widget->GetNativeWindow()->parent()) << + "TestCreateWindow: type=" << type << ", always_on_top=" << always_on_top; + + widget->Close(); +} + +} // namespace + +class ShellTest : public AuraShellTestBase { + public: + ShellTest() {} + virtual ~ShellTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(ShellTest); +}; + +TEST_F(ShellTest, CreateWindow) { + // Normal window should be created in default container. + TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW, + false, // always_on_top + GetDefaultContainer()); + TestCreateWindow(views::Widget::InitParams::TYPE_POPUP, + false, // always_on_top + GetDefaultContainer()); + + // Always-on-top window and popup are created in always-on-top container. + TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW, + true, // always_on_top + GetAlwaysOnTopContainer()); + TestCreateWindow(views::Widget::InitParams::TYPE_POPUP, + true, // always_on_top + GetAlwaysOnTopContainer()); +} + +TEST_F(ShellTest, ChangeAlwaysOnTop) { + views::Widget::InitParams widget_params( + views::Widget::InitParams::TYPE_WINDOW); + + // Creates a normal window + views::Widget* widget = CreateTestWindow(widget_params); + widget->Show(); + + // It should be in default container. + EXPECT_EQ(GetDefaultContainer(), widget->GetNativeWindow()->parent()); + + // Flip always-on-top flag. + widget->SetAlwaysOnTop(true); + // And it should in always on top container now. + EXPECT_EQ(GetAlwaysOnTopContainer(), widget->GetNativeWindow()->parent()); + + // Flip always-on-top flag. + widget->SetAlwaysOnTop(false); + // It should go back to default container. + EXPECT_EQ(GetDefaultContainer(), widget->GetNativeWindow()->parent()); + + // Set the same always-on-top flag again. + widget->SetAlwaysOnTop(false); + // Should have no effect and we are still in the default container. + EXPECT_EQ(GetDefaultContainer(), widget->GetNativeWindow()->parent()); + + widget->Close(); +} + +} // namespace test +} // namespace aura_shell diff --git a/ui/aura_shell/stacking_controller.cc b/ui/aura_shell/stacking_controller.cc index 2fb3ec6..3a913c3 100644 --- a/ui/aura_shell/stacking_controller.cc +++ b/ui/aura_shell/stacking_controller.cc @@ -6,6 +6,7 @@ #include "ui/aura/desktop.h" #include "ui/aura/window.h" +#include "ui/aura_shell/always_on_top_controller.h" #include "ui/aura_shell/shell.h" #include "ui/aura_shell/shell_window_ids.h" @@ -35,6 +36,13 @@ StackingController::StackingController() { StackingController::~StackingController() { } +void StackingController::Init() { + always_on_top_controller_.reset(new internal::AlwaysOnTopController); + always_on_top_controller_->SetContainers( + GetContainer(internal::kShellWindowId_DefaultContainer), + GetContainer(internal::kShellWindowId_AlwaysOnTopContainer)); +} + // static aura::Window* StackingController::GetActivatableWindow(aura::Window* window) { aura::Window* parent = window->parent(); @@ -60,7 +68,7 @@ void StackingController::AddChildToDefaultParent(aura::Window* window) { switch (window->type()) { case aura::WINDOW_TYPE_NORMAL: case aura::WINDOW_TYPE_POPUP: - parent = GetContainer(internal::kShellWindowId_DefaultContainer); + parent = always_on_top_controller_->GetContainer(window); break; case aura::WINDOW_TYPE_MENU: case aura::WINDOW_TYPE_TOOLTIP: diff --git a/ui/aura_shell/stacking_controller.h b/ui/aura_shell/stacking_controller.h index 2091f1f..20bb5fe 100644 --- a/ui/aura_shell/stacking_controller.h +++ b/ui/aura_shell/stacking_controller.h @@ -8,16 +8,22 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "ui/aura/client/stacking_client.h" namespace aura_shell { namespace internal { +class AlwaysOnTopController; + class StackingController : public aura::StackingClient { public: StackingController(); virtual ~StackingController(); + // Initializes this controller. + void Init(); + // Returns true if |window| exists within a container that supports // activation. static aura::Window* GetActivatableWindow(aura::Window* window); @@ -29,6 +35,8 @@ class StackingController : public aura::StackingClient { aura::Window* ignore) const OVERRIDE; private: + scoped_ptr<internal::AlwaysOnTopController> always_on_top_controller_; + DISALLOW_COPY_AND_ASSIGN(StackingController); }; diff --git a/ui/aura_shell/stacking_controller_unittest.cc b/ui/aura_shell/stacking_controller_unittest.cc index 500c24f..cf4fdc7 100644 --- a/ui/aura_shell/stacking_controller_unittest.cc +++ b/ui/aura_shell/stacking_controller_unittest.cc @@ -5,18 +5,16 @@ #include "ui/aura_shell/stacking_controller.h" #include "ui/aura/desktop.h" -#include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/test/test_window_delegate.h" -#include "ui/aura_shell/shell.h" +#include "ui/aura_shell/test/aura_shell_test_base.h" namespace aura_shell { namespace test { -typedef aura::test::AuraTestBase StackingControllerTest; +typedef aura_shell::test::AuraShellTestBase StackingControllerTest; TEST_F(StackingControllerTest, GetTopmostWindowToActivate) { - Shell::CreateInstance(NULL); aura::test::ActivateWindowDelegate activate; aura::test::ActivateWindowDelegate non_activate(false); diff --git a/ui/aura_shell/test/aura_shell_test_base.cc b/ui/aura_shell/test/aura_shell_test_base.cc new file mode 100644 index 0000000..fe121f2 --- /dev/null +++ b/ui/aura_shell/test/aura_shell_test_base.cc @@ -0,0 +1,36 @@ +// 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 "ui/aura_shell/test/aura_shell_test_base.h" + +#include "ui/aura_shell/shell.h" + +namespace aura_shell { +namespace test { + +AuraShellTestBase::AuraShellTestBase() { +} + +AuraShellTestBase::~AuraShellTestBase() { +} + +void AuraShellTestBase::SetUp() { + aura::test::AuraTestBase::SetUp(); + + // Creates Shell and hook with Desktop. + aura_shell::Shell::CreateInstance(NULL); +} + +void AuraShellTestBase::TearDown() { + // Flush the message loop to finish pending release tasks. + RunAllPendingInMessageLoop(); + + // Tear down the shell. + aura_shell::Shell::DeleteInstanceForTesting(); + + aura::test::AuraTestBase::TearDown(); +} + +} // namespace test +} // namespace aura_shell diff --git a/ui/aura_shell/test/aura_shell_test_base.h b/ui/aura_shell/test/aura_shell_test_base.h new file mode 100644 index 0000000..c08c556 --- /dev/null +++ b/ui/aura_shell/test/aura_shell_test_base.h @@ -0,0 +1,31 @@ +// 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. + +#ifndef UI_AURA_SHELL_TEST_AURA_SHELL_TEST_BASE_H_ +#define UI_AURA_SHELL_TEST_AURA_SHELL_TEST_BASE_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "ui/aura/test/aura_test_base.h" + +namespace aura_shell { +namespace test { + +class AuraShellTestBase : public aura::test::AuraTestBase { + public: + AuraShellTestBase(); + virtual ~AuraShellTestBase(); + + // testing::Test: + virtual void SetUp() OVERRIDE; + virtual void TearDown() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(AuraShellTestBase); +}; + +} // namespace test +} // namespace aura_shell + +#endif // UI_AURA_SHELL_TEST_AURA_SHELL_TEST_BASE_H_ diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc index dada148..aa11de8 100644 --- a/ui/base/x/x11_util.cc +++ b/ui/base/x/x11_util.cc @@ -114,12 +114,7 @@ class XCursorCache { public: XCursorCache() {} ~XCursorCache() { - Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); - for (std::map<int, Cursor>::iterator it = - cache_.begin(); it != cache_.end(); ++it) { - XFreeCursor(display, it->second); - } - cache_.clear(); + Clear(); } Cursor GetCursor(int cursor_shape) { @@ -134,6 +129,15 @@ class XCursorCache { return it.first->second; } + void Clear() { + Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); + for (std::map<int, Cursor>::iterator it = + cache_.begin(); it != cache_.end(); ++it) { + XFreeCursor(display, it->second); + } + cache_.clear(); + } + private: // Maps X11 font cursor shapes to Cursor IDs. std::map<int, Cursor> cache_; @@ -218,6 +222,12 @@ int GetDefaultScreen(Display* display) { Cursor GetXCursor(int cursor_shape) { CR_DEFINE_STATIC_LOCAL(XCursorCache, cache, ()); + + if (cursor_shape == kCursorClearXCursorCache) { + cache.Clear(); + return 0; + } + return cache.GetCursor(cursor_shape); } diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h index f9e979c..888e76a 100644 --- a/ui/base/x/x11_util.h +++ b/ui/base/x/x11_util.h @@ -68,6 +68,10 @@ UI_EXPORT bool QueryRenderSupport(Display* dpy); // Return the default screen number for the display int GetDefaultScreen(Display* display); +// TODO(xiyuan): Fix the stale XCursorCache problem per http://crbug.com/102759. +// A special cursor that makes GetXCursor below to clear its XCursorCache. +const int kCursorClearXCursorCache = -1; + // Returns an X11 Cursor, sharable across the process. // |cursor_shape| is an X font cursor shape, see XCreateFontCursor(). UI_EXPORT Cursor GetXCursor(int cursor_shape); |