1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector> 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <X11/extensions/shape.h> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <X11/Xlib.h> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Get rid of X11 macros which conflict with gtest. 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#undef Bool 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#undef None 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/aura/window.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/aura/window_tree_host.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/base/hit_test.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/base/x/x11_util.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/platform/x11/x11_event_source.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/path.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/point.h" 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/rect.h" 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/x/x11_atom_cache.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/test/views_test_base.h" 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/views/test/x11_property_change_waiter.h" 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h" 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/window/non_client_view.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace views { 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Blocks till the window state hint, |hint|, is set or unset. 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class WMStateWaiter : public X11PropertyChangeWaiter { 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WMStateWaiter(XID window, 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* hint, 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool wait_till_set) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : X11PropertyChangeWaiter(window, "_NET_WM_STATE"), 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) hint_(hint), 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) wait_till_set_(wait_till_set) { 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* kAtomsToCache[] = { 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) hint, 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NULL 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) atom_cache_.reset(new ui::X11AtomCache(gfx::GetXDisplay(), kAtomsToCache)); 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~WMStateWaiter() { 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // X11PropertyChangeWaiter: 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) OVERRIDE { 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<Atom> hints; 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints)) { 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<Atom>::iterator it = std::find( 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) hints.begin(), 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) hints.end(), 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) atom_cache_->GetAtom(hint_)); 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool hint_set = (it != hints.end()); 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return hint_set != wait_till_set_; 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<ui::X11AtomCache> atom_cache_; 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The name of the hint to wait to get set or unset. 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* hint_; 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Whether we are waiting for |hint| to be set or unset. 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool wait_till_set_; 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(WMStateWaiter); 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// A NonClientFrameView with a window mask with the bottom right corner cut out. 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ShapedNonClientFrameView : public NonClientFrameView { 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit ShapedNonClientFrameView() { 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~ShapedNonClientFrameView() { 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // NonClientFrameView: 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual gfx::Rect GetBoundsForClientView() const OVERRIDE { 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return bounds(); 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual gfx::Rect GetWindowBoundsForClientBounds( 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const gfx::Rect& client_bounds) const OVERRIDE { 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return client_bounds; 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE { 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return HTNOWHERE; 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void GetWindowMask(const gfx::Size& size, 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Path* window_mask) OVERRIDE { 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int right = size.width(); 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int bottom = size.height(); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->moveTo(0, 0); 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->lineTo(0, bottom); 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->lineTo(right, bottom); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->lineTo(right, 10); 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->lineTo(right - 10, 10); 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->lineTo(right - 10, 0); 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window_mask->close(); 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void ResetWindowControls() OVERRIDE { 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void UpdateWindowIcon() OVERRIDE { 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void UpdateWindowTitle() OVERRIDE { 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void SizeConstraintsChanged() OVERRIDE { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ShapedNonClientFrameView); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ShapedWidgetDelegate : public WidgetDelegateView { 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ShapedWidgetDelegate() { 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~ShapedWidgetDelegate() { 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // WidgetDelegateView: 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual NonClientFrameView* CreateNonClientFrameView( 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Widget* widget) OVERRIDE { 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return new ShapedNonClientFrameView; 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ShapedWidgetDelegate); 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Creates a widget of size 100x100. 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<Widget> CreateWidget(WidgetDelegate* delegate) { 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Widget> widget(new Widget); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Widget::InitParams params(Widget::InitParams::TYPE_WINDOW); 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.delegate = delegate; 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.remove_standard_frame = true; 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.native_widget = new DesktopNativeWidgetAura(widget.get()); 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.bounds = gfx::Rect(100, 100, 100, 100); 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget->Init(params); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return widget.Pass(); 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns the list of rectangles which describe |xid|'s bounding region via the 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// X shape extension. 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<gfx::Rect> GetShapeRects(XID xid) { 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int dummy; 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int shape_rects_size; 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XRectangle* shape_rects = XShapeGetRectangles(gfx::GetXDisplay(), 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) xid, 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ShapeBounding, 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &shape_rects_size, 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &dummy); 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<gfx::Rect> shape_vector; 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < shape_rects_size; ++i) { 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_vector.push_back(gfx::Rect( 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_rects[i].x, 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_rects[i].y, 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_rects[i].width, 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_rects[i].height)); 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XFree(shape_rects); 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return shape_vector; 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true if one of |rects| contains point (x,y). 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ShapeRectContainsPoint(const std::vector<gfx::Rect>& shape_rects, 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int x, 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int y) { 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Point point(x, y); 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < shape_rects.size(); ++i) { 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shape_rects[i].Contains(point)) 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class DesktopWindowTreeHostX11Test : public ViewsTestBase { 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DesktopWindowTreeHostX11Test() { 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~DesktopWindowTreeHostX11Test() { 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void SetUp() OVERRIDE { 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ViewsTestBase::SetUp(); 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Make X11 synchronous for our display connection. This does not force the 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // window manager to behave synchronously. 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XSynchronize(gfx::GetXDisplay(), True); 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void TearDown() OVERRIDE { 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XSynchronize(gfx::GetXDisplay(), False); 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ViewsTestBase::TearDown(); 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11Test); 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Tests that the shape is properly set on the x window. 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(DesktopWindowTreeHostX11Test, Shape) { 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!ui::IsShapeExtensionAvailable()) 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // 1) Test setting the window shape via the NonClientFrameView. This technique 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // is used to get rounded corners on Chrome windows when not using the native 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // window frame. 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Widget> widget1 = CreateWidget(new ShapedWidgetDelegate()); 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget1->Show(); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui::X11EventSource::GetInstance()->DispatchXEvents(); 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<gfx::Rect> shape_rects = GetShapeRects(xid1); 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(shape_rects.empty()); 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The widget was supposed to be 100x100, but the WM might have ignored this 23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // suggestion. 23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int widget_width = widget1->GetWindowBoundsInScreen().width(); 23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, widget_width - 15, 5)); 23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, widget_width - 5, 5)); 23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, widget_width - 5, 15)); 24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, widget_width + 5, 15)); 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Changing widget's size should update the shape. 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget1->SetBounds(gfx::Rect(100, 100, 200, 200)); 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui::X11EventSource::GetInstance()->DispatchXEvents(); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (widget1->GetWindowBoundsInScreen().width() == 200) { 24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) shape_rects = GetShapeRects(xid1); 24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_FALSE(shape_rects.empty()); 24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 85, 5)); 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 5)); 25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 185, 5)); 25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 195, 5)); 25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 195, 15)); 25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 205, 15)); 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (ui::WmSupportsHint(ui::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"))) { 25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The shape should be changed to a rectangle which fills the entire screen 25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // when |widget1| is maximized. 26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) { 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WMStateWaiter waiter(xid1, "_NET_WM_STATE_MAXIMIZED_VERT", true); 26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) widget1->Maximize(); 26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) waiter.Wait(); 26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // xvfb does not support Xrandr so we cannot check the maximized window's 26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // bounds. 26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) gfx::Rect maximized_bounds; 26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ui::GetWindowRect(xid1, &maximized_bounds); 27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) shape_rects = GetShapeRects(xid1); 27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_FALSE(shape_rects.empty()); 27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) maximized_bounds.width() - 1, 27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5)); 27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) maximized_bounds.width() - 1, 27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15)); 27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // 2) Test setting the window shape via Widget::SetShape(). 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Path shape2; 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.moveTo(10, 0); 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.lineTo(10, 10); 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.lineTo(0, 10); 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.lineTo(0, 100); 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.lineTo(100, 100); 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.lineTo(100, 0); 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape2.close(); 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Widget> widget2(CreateWidget(NULL)); 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget2->Show(); 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget2->SetShape(shape2.CreateNativeRegion()); 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui::X11EventSource::GetInstance()->DispatchXEvents(); 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) XID xid2 = widget2->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_rects = GetShapeRects(xid2); 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(shape_rects.empty()); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 5, 5)); 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 15, 5)); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 15)); 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 105, 15)); 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Changing the widget's size should not affect the shape. 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget2->SetBounds(gfx::Rect(100, 100, 200, 200)); 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shape_rects = GetShapeRects(xid2); 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_FALSE(shape_rects.empty()); 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 5, 5)); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 15, 5)); 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 15)); 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 105, 15)); 3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Setting the shape to NULL resets the shape back to the entire 3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // window bounds. 3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) widget2->SetShape(NULL); 3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) shape_rects = GetShapeRects(xid2); 3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ASSERT_FALSE(shape_rects.empty()); 3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 5, 5)); 3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 15, 5)); 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 15)); 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 105, 15)); 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 500, 500)); 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Test that the widget ignores changes in fullscreen state initiated by the 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// window manager (e.g. via a window manager accelerator key). 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(DesktopWindowTreeHostX11Test, WindowManagerTogglesFullscreen) { 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ui::WmSupportsHint(ui::GetAtom("_NET_WM_STATE_FULLSCREEN"))) 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<Widget> widget = CreateWidget(new ShapedWidgetDelegate()); 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) XID xid = widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) widget->Show(); 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ui::X11EventSource::GetInstance()->DispatchXEvents(); 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::Rect initial_bounds = widget->GetWindowBoundsInScreen(); 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WMStateWaiter waiter(xid, "_NET_WM_STATE_FULLSCREEN", true); 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) widget->SetFullscreen(true); 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) waiter.Wait(); 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(widget->IsFullscreen()); 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Emulate the window manager exiting fullscreen via a window manager 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // accelerator key. It should not affect the widget's fullscreen state. 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* kAtomsToCache[] = { 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "_NET_WM_STATE", 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "_NET_WM_STATE_FULLSCREEN", 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NULL 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Display* display = gfx::GetXDisplay(); 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ui::X11AtomCache atom_cache(display, kAtomsToCache); 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) XEvent xclient; 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) memset(&xclient, 0, sizeof(xclient)); 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.type = ClientMessage; 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.window = xid; 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.message_type = atom_cache.GetAtom("_NET_WM_STATE"); 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.format = 32; 361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.data.l[0] = 0; 362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.data.l[1] = atom_cache.GetAtom("_NET_WM_STATE_FULLSCREEN"); 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.data.l[2] = 0; 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.data.l[3] = 1; 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) xclient.xclient.data.l[4] = 0; 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) XSendEvent(display, DefaultRootWindow(display), False, 367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SubstructureRedirectMask | SubstructureNotifyMask, 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &xclient); 369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WMStateWaiter waiter(xid, "_NET_WM_STATE_FULLSCREEN", false); 371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) waiter.Wait(); 372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_TRUE(widget->IsFullscreen()); 374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Calling Widget::SetFullscreen(false) should clear the widget's fullscreen 376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // state and clean things up. 377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) widget->SetFullscreen(false); 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_FALSE(widget->IsFullscreen()); 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(initial_bounds.ToString(), 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) widget->GetWindowBoundsInScreen().ToString()); 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Tests that the minimization information is propagated to the content window. 3846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)TEST_F(DesktopWindowTreeHostX11Test, ToggleMinimizePropogateToContentWindow) { 3856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) Widget widget; 3866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); 3876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 3886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) params.native_widget = new DesktopNativeWidgetAura(&widget); 3896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) widget.Init(params); 3906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) widget.Show(); 3916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ui::X11EventSource::GetInstance()->DispatchXEvents(); 3926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 3936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) XID xid = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(); 3946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) Display* display = gfx::GetXDisplay(); 3956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 3966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Minimize by sending _NET_WM_STATE_HIDDEN 3976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) { 3986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const char* kAtomsToCache[] = { 3996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) "_NET_WM_STATE", 4006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) "_NET_WM_STATE_HIDDEN", 4016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) NULL 4026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) }; 4036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ui::X11AtomCache atom_cache(display, kAtomsToCache); 4056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector< ::Atom> atom_list; 4076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) atom_list.push_back(atom_cache.GetAtom("_NET_WM_STATE_HIDDEN")); 4086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ui::SetAtomArrayProperty(xid, "_NET_WM_STATE", "ATOM", atom_list); 4096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) XEvent xevent; 4116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) memset(&xevent, 0, sizeof(xevent)); 4126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.type = PropertyNotify; 4136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.type = PropertyNotify; 4146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.send_event = 1; 4156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.display = display; 4166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.window = xid; 4176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.atom = atom_cache.GetAtom("_NET_WM_STATE"); 4186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.state = 0; 4196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) XSendEvent(display, DefaultRootWindow(display), False, 4206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) SubstructureRedirectMask | SubstructureNotifyMask, 4216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) &xevent); 4226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) WMStateWaiter waiter(xid, "_NET_WM_STATE_HIDDEN", true); 4246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) waiter.Wait(); 4256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 4266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_FALSE(widget.GetNativeWindow()->IsVisible()); 4276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Show from minimized by sending _NET_WM_STATE_FOCUSED 4296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) { 4306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const char* kAtomsToCache[] = { 4316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) "_NET_WM_STATE", 4326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) "_NET_WM_STATE_FOCUSED", 4336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) NULL 4346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) }; 4356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ui::X11AtomCache atom_cache(display, kAtomsToCache); 4376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector< ::Atom> atom_list; 4396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) atom_list.push_back(atom_cache.GetAtom("_NET_WM_STATE_FOCUSED")); 4406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ui::SetAtomArrayProperty(xid, "_NET_WM_STATE", "ATOM", atom_list); 4416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) XEvent xevent; 4436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) memset(&xevent, 0, sizeof(xevent)); 4446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.type = PropertyNotify; 4456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.type = PropertyNotify; 4466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.send_event = 1; 4476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.display = display; 4486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.window = xid; 4496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.atom = atom_cache.GetAtom("_NET_WM_STATE"); 4506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) xevent.xproperty.state = 0; 4516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) XSendEvent(display, DefaultRootWindow(display), False, 4526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) SubstructureRedirectMask | SubstructureNotifyMask, 4536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) &xevent); 4546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) WMStateWaiter waiter(xid, "_NET_WM_STATE_FOCUSED", true); 4566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) waiter.Wait(); 4576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 4586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_TRUE(widget.GetNativeWindow()->IsVisible()); 4596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 4606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace views 462