Chromium Code Reviews| Index: ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| index b1f5ac609277d6e65bb2aabf592f78de3e38ca09..65a20798919a5c50fc45e68c23d9b16becf9dd70 100644 |
| --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| @@ -77,6 +77,7 @@ const char* kAtomsToCache[] = { |
| "WM_DELETE_WINDOW", |
| "WM_PROTOCOLS", |
| "WM_S0", |
| + "_NET_FRAME_EXTENTS", |
| "_NET_WM_CM_S0", |
| "_NET_WM_ICON", |
| "_NET_WM_NAME", |
| @@ -141,7 +142,8 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( |
| desktop_native_widget_aura_(desktop_native_widget_aura), |
| content_window_(NULL), |
| window_parent_(NULL), |
| - custom_window_shape_(NULL), |
| + window_shape_(NULL), |
| + custom_window_shape_(false), |
| urgency_hint_set_(false) { |
| } |
| @@ -149,8 +151,8 @@ DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { |
| window()->ClearProperty(kHostForRootWindow); |
| aura::client::SetWindowMoveClient(window(), NULL); |
| desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this); |
| - if (custom_window_shape_) |
| - XDestroyRegion(custom_window_shape_); |
| + if (window_shape_) |
| + XDestroyRegion(window_shape_); |
| DestroyDispatcher(); |
| } |
| @@ -182,6 +184,16 @@ gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const { |
| return bounds_; |
| } |
| +gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowOuterBounds() const { |
| + gfx::Rect outer_bounds(bounds_); |
| + outer_bounds.Inset(-native_window_frame_borders_); |
| + return outer_bounds; |
| +} |
| + |
| +::Region DesktopWindowTreeHostX11::GetWindowShape() const { |
| + return window_shape_; |
| +} |
| + |
| void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged( |
| bool active) { |
| if (active) { |
| @@ -465,9 +477,10 @@ gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const { |
| } |
| void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) { |
| - if (custom_window_shape_) |
| - XDestroyRegion(custom_window_shape_); |
| - custom_window_shape_ = gfx::CreateRegionFromSkRegion(*native_region); |
| + if (window_shape_) |
| + XDestroyRegion(window_shape_); |
| + custom_window_shape_ = true; |
| + window_shape_ = gfx::CreateRegionFromSkRegion(*native_region); |
| ResetWindowRegion(); |
| delete native_region; |
| } |
| @@ -1118,6 +1131,66 @@ bool DesktopWindowTreeHostX11::IsWindowManagerPresent() { |
| xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
| } |
| +void DesktopWindowTreeHostX11::OnWMStateUpdated() { |
| + std::vector< ::Atom> atom_list; |
| + if (ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list)) { |
|
sadrul
2014/05/08 18:53:29
Early out instead if this is false?
|
| + window_properties_.clear(); |
| + std::copy(atom_list.begin(), atom_list.end(), |
| + inserter(window_properties_, window_properties_.begin())); |
| + |
| + if (!restored_bounds_.IsEmpty() && !IsMaximized()) { |
| + // If we have restored bounds, but WM_STATE no longer claims to be |
| + // maximized, we should clear our restored bounds. |
| + restored_bounds_ = gfx::Rect(); |
| + } else if (IsMaximized() && restored_bounds_.IsEmpty()) { |
| + // The request that we become maximized originated from a different |
| + // process. |bounds_| already contains our maximized bounds. Do a |
| + // best effort attempt to get restored bounds by setting it to our |
| + // previously set bounds (and if we get this wrong, we aren't any |
| + // worse off since we'd otherwise be returning our maximized bounds). |
| + restored_bounds_ = previous_bounds_; |
| + } |
| + |
| + is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN"); |
| + is_always_on_top_ = HasWMSpecProperty("_NET_WM_STATE_ABOVE"); |
| + |
| + // Now that we have different window properties, we may need to |
| + // relayout the window. (The windows code doesn't need this because |
| + // their window change is synchronous.) |
| + // |
| + // TODO(erg): While this does work, there's a quick flash showing the |
| + // tabstrip/toolbar/etc. when going into fullscreen mode before hiding |
| + // those parts of the UI because we receive the sizing event from the |
| + // window manager before we receive the event that changes the |
| + // fullscreen state. Unsure what to do about that. |
| + Widget* widget = native_widget_delegate_->AsWidget(); |
| + NonClientView* non_client_view = widget->non_client_view(); |
| + // non_client_view may be NULL, especially during creation. |
| + if (non_client_view) { |
| + non_client_view->client_view()->InvalidateLayout(); |
| + non_client_view->InvalidateLayout(); |
| + } |
| + widget->GetRootView()->Layout(); |
| + // Refresh the window's border, which may need to be updated if we have |
| + // changed the window's maximization state. |
| + ResetWindowRegion(); |
| + } |
| +} |
| + |
| +void DesktopWindowTreeHostX11::OnFrameExtentsUpdated() { |
| + std::vector<int> insets; |
| + if (ui::GetIntArrayProperty(xwindow_, "_NET_FRAME_EXTENTS", &insets) && |
|
sadrul
2014/05/08 18:53:29
Add a comment about the ordering in _NET_FRAME_EXT
|
| + insets.size() == 4) { |
| + native_window_frame_borders_ = gfx::Insets( |
| + insets[2], |
| + insets[0], |
| + insets[3], |
| + insets[1]); |
| + } else { |
| + native_window_frame_borders_ = gfx::Insets(); |
| + } |
| +} |
| + |
| void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled, |
| ::Atom state1, |
| ::Atom state2) { |
| @@ -1211,10 +1284,14 @@ void DesktopWindowTreeHostX11::ResetWindowRegion() { |
| // If a custom window shape was supplied then apply it. |
| if (custom_window_shape_) { |
| XShapeCombineRegion( |
| - xdisplay_, xwindow_, ShapeBounding, 0, 0, custom_window_shape_, false); |
| + xdisplay_, xwindow_, ShapeBounding, 0, 0, window_shape_, false); |
| return; |
| } |
| + if (window_shape_) |
| + XDestroyRegion(window_shape_); |
| + window_shape_ = NULL; |
| + |
| if (!IsMaximized()) { |
| gfx::Path window_mask; |
| views::Widget* widget = native_widget_delegate_->AsWidget(); |
| @@ -1223,10 +1300,9 @@ void DesktopWindowTreeHostX11::ResetWindowRegion() { |
| // so, use it to define the window shape. If not, fall through. |
| widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask); |
| if (window_mask.countPoints() > 0) { |
| - Region region = gfx::CreateRegionFromSkPath(window_mask); |
| + window_shape_ = gfx::CreateRegionFromSkPath(window_mask); |
| XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, |
| - 0, 0, region, false); |
| - XDestroyRegion(region); |
| + 0, 0, window_shape_, false); |
|
sadrul
2014/05/08 18:53:29
Interesting. Can there be a test for this case?
|
| return; |
| } |
| } |
| @@ -1609,53 +1685,11 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent( |
| break; |
| } |
| case PropertyNotify: { |
| - // Get our new window property state if the WM has told us its changed. |
| - ::Atom state = atom_cache_.GetAtom("_NET_WM_STATE"); |
| - |
| - std::vector< ::Atom> atom_list; |
| - if (xev->xproperty.atom == state && |
| - ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list)) { |
| - window_properties_.clear(); |
| - std::copy(atom_list.begin(), atom_list.end(), |
| - inserter(window_properties_, window_properties_.begin())); |
| - |
| - if (!restored_bounds_.IsEmpty() && !IsMaximized()) { |
| - // If we have restored bounds, but WM_STATE no longer claims to be |
| - // maximized, we should clear our restored bounds. |
| - restored_bounds_ = gfx::Rect(); |
| - } else if (IsMaximized() && restored_bounds_.IsEmpty()) { |
| - // The request that we become maximized originated from a different |
| - // process. |bounds_| already contains our maximized bounds. Do a |
| - // best effort attempt to get restored bounds by setting it to our |
| - // previously set bounds (and if we get this wrong, we aren't any |
| - // worse off since we'd otherwise be returning our maximized bounds). |
| - restored_bounds_ = previous_bounds_; |
| - } |
| - |
| - is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN"); |
| - is_always_on_top_ = HasWMSpecProperty("_NET_WM_STATE_ABOVE"); |
| - |
| - // Now that we have different window properties, we may need to |
| - // relayout the window. (The windows code doesn't need this because |
| - // their window change is synchronous.) |
| - // |
| - // TODO(erg): While this does work, there's a quick flash showing the |
| - // tabstrip/toolbar/etc. when going into fullscreen mode before hiding |
| - // those parts of the UI because we receive the sizing event from the |
| - // window manager before we receive the event that changes the |
| - // fullscreen state. Unsure what to do about that. |
| - Widget* widget = native_widget_delegate_->AsWidget(); |
| - NonClientView* non_client_view = widget->non_client_view(); |
| - // non_client_view may be NULL, especially during creation. |
| - if (non_client_view) { |
| - non_client_view->client_view()->InvalidateLayout(); |
| - non_client_view->InvalidateLayout(); |
| - } |
| - widget->GetRootView()->Layout(); |
| - // Refresh the window's border, which may need to be updated if we have |
| - // changed the window's maximization state. |
| - ResetWindowRegion(); |
| - } |
| + ::Atom changed_atom = xev->xproperty.atom; |
| + if (changed_atom == atom_cache_.GetAtom("_NET_WM_STATE")) |
| + OnWMStateUpdated(); |
| + else if (changed_atom == atom_cache_.GetAtom("_NET_FRAME_EXTENTS")) |
| + OnFrameExtentsUpdated(); |
| break; |
| } |
| case SelectionNotify: { |