| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" | 5 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" |
| 6 | 6 |
| 7 #include <X11/extensions/shape.h> | 7 #include <X11/extensions/shape.h> |
| 8 #include <X11/extensions/XInput2.h> | 8 #include <X11/extensions/XInput2.h> |
| 9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
| 10 #include <X11/Xregion.h> | 10 #include <X11/Xregion.h> |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 //////////////////////////////////////////////////////////////////////////////// | 180 //////////////////////////////////////////////////////////////////////////////// |
| 181 // DesktopWindowTreeHostX11, public: | 181 // DesktopWindowTreeHostX11, public: |
| 182 | 182 |
| 183 DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( | 183 DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( |
| 184 internal::NativeWidgetDelegate* native_widget_delegate, | 184 internal::NativeWidgetDelegate* native_widget_delegate, |
| 185 DesktopNativeWidgetAura* desktop_native_widget_aura) | 185 DesktopNativeWidgetAura* desktop_native_widget_aura) |
| 186 : xdisplay_(gfx::GetXDisplay()), | 186 : xdisplay_(gfx::GetXDisplay()), |
| 187 xwindow_(0), | 187 xwindow_(0), |
| 188 x_root_window_(DefaultRootWindow(xdisplay_)), | 188 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 189 atom_cache_(xdisplay_, kAtomsToCache), | 189 atom_cache_(xdisplay_, kAtomsToCache), |
| 190 window_mapped_(false), | 190 window_mapped_in_server_(false), |
| 191 wait_for_unmap_(false), | 191 window_mapped_in_client_(false), |
| 192 is_fullscreen_(false), | 192 is_fullscreen_(false), |
| 193 is_always_on_top_(false), | 193 is_always_on_top_(false), |
| 194 use_native_frame_(false), | 194 use_native_frame_(false), |
| 195 should_maximize_after_map_(false), | 195 should_maximize_after_map_(false), |
| 196 use_argb_visual_(false), | 196 use_argb_visual_(false), |
| 197 drag_drop_client_(NULL), | 197 drag_drop_client_(NULL), |
| 198 native_widget_delegate_(native_widget_delegate), | 198 native_widget_delegate_(native_widget_delegate), |
| 199 desktop_native_widget_aura_(desktop_native_widget_aura), | 199 desktop_native_widget_aura_(desktop_native_widget_aura), |
| 200 content_window_(NULL), | 200 content_window_(NULL), |
| 201 window_parent_(NULL), | 201 window_parent_(NULL), |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 | 586 |
| 587 void DesktopWindowTreeHostX11::ShowMaximizedWithBounds( | 587 void DesktopWindowTreeHostX11::ShowMaximizedWithBounds( |
| 588 const gfx::Rect& restored_bounds) { | 588 const gfx::Rect& restored_bounds) { |
| 589 ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED); | 589 ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED); |
| 590 // Enforce |restored_bounds_in_pixels_| since calling Maximize() could have | 590 // Enforce |restored_bounds_in_pixels_| since calling Maximize() could have |
| 591 // reset it. | 591 // reset it. |
| 592 restored_bounds_in_pixels_ = ToPixelRect(restored_bounds); | 592 restored_bounds_in_pixels_ = ToPixelRect(restored_bounds); |
| 593 } | 593 } |
| 594 | 594 |
| 595 bool DesktopWindowTreeHostX11::IsVisible() const { | 595 bool DesktopWindowTreeHostX11::IsVisible() const { |
| 596 return window_mapped_ && !wait_for_unmap_; | 596 return window_mapped_in_client_; |
| 597 } | 597 } |
| 598 | 598 |
| 599 void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) { | 599 void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) { |
| 600 gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(requested_size)).size(); | 600 gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(requested_size)).size(); |
| 601 size_in_pixels = AdjustSize(size_in_pixels); | 601 size_in_pixels = AdjustSize(size_in_pixels); |
| 602 bool size_changed = bounds_in_pixels_.size() != size_in_pixels; | 602 bool size_changed = bounds_in_pixels_.size() != size_in_pixels; |
| 603 XResizeWindow(xdisplay_, xwindow_, size_in_pixels.width(), | 603 XResizeWindow(xdisplay_, xwindow_, size_in_pixels.width(), |
| 604 size_in_pixels.height()); | 604 size_in_pixels.height()); |
| 605 bounds_in_pixels_.set_size(size_in_pixels); | 605 bounds_in_pixels_.set_size(size_in_pixels); |
| 606 if (size_changed) { | 606 if (size_changed) { |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 824 } | 824 } |
| 825 | 825 |
| 826 bool DesktopWindowTreeHostX11::IsActive() const { | 826 bool DesktopWindowTreeHostX11::IsActive() const { |
| 827 // Focus and stacking order are independent in X11. Since we cannot guarantee | 827 // Focus and stacking order are independent in X11. Since we cannot guarantee |
| 828 // a window is topmost iff it has focus, just use the focus state to determine | 828 // a window is topmost iff it has focus, just use the focus state to determine |
| 829 // if a window is active. Note that Activate() and Deactivate() change the | 829 // if a window is active. Note that Activate() and Deactivate() change the |
| 830 // stacking order in addition to changing the focus state. | 830 // stacking order in addition to changing the focus state. |
| 831 bool is_active = | 831 bool is_active = |
| 832 (has_window_focus_ || has_pointer_focus_) && !ignore_keyboard_input_; | 832 (has_window_focus_ || has_pointer_focus_) && !ignore_keyboard_input_; |
| 833 | 833 |
| 834 // is_active => window_mapped_ | 834 // is_active => window_mapped_in_server_ |
| 835 // !window_mapped_ => !is_active | 835 // !window_mapped_in_server_ => !is_active |
| 836 DCHECK(!is_active || window_mapped_); | 836 DCHECK(!is_active || window_mapped_in_server_); |
| 837 | 837 |
| 838 // |has_window_focus_| and |has_pointer_focus_| are mutually exclusive. | 838 // |has_window_focus_| and |has_pointer_focus_| are mutually exclusive. |
| 839 DCHECK(!has_window_focus_ || !has_pointer_focus_); | 839 DCHECK(!has_window_focus_ || !has_pointer_focus_); |
| 840 | 840 |
| 841 return is_active; | 841 return is_active; |
| 842 } | 842 } |
| 843 | 843 |
| 844 void DesktopWindowTreeHostX11::Maximize() { | 844 void DesktopWindowTreeHostX11::Maximize() { |
| 845 if (HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN")) { | 845 if (HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN")) { |
| 846 // Unfullscreen the window if it is fullscreen. | 846 // Unfullscreen the window if it is fullscreen. |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1217 } | 1217 } |
| 1218 | 1218 |
| 1219 void DesktopWindowTreeHostX11::ShowImpl() { | 1219 void DesktopWindowTreeHostX11::ShowImpl() { |
| 1220 ShowWindowWithState(ui::SHOW_STATE_NORMAL); | 1220 ShowWindowWithState(ui::SHOW_STATE_NORMAL); |
| 1221 native_widget_delegate_->OnNativeWidgetVisibilityChanged(true); | 1221 native_widget_delegate_->OnNativeWidgetVisibilityChanged(true); |
| 1222 } | 1222 } |
| 1223 | 1223 |
| 1224 void DesktopWindowTreeHostX11::HideImpl() { | 1224 void DesktopWindowTreeHostX11::HideImpl() { |
| 1225 if (IsVisible()) { | 1225 if (IsVisible()) { |
| 1226 XWithdrawWindow(xdisplay_, xwindow_, 0); | 1226 XWithdrawWindow(xdisplay_, xwindow_, 0); |
| 1227 wait_for_unmap_ = true; | 1227 window_mapped_in_client_ = false; |
| 1228 } | 1228 } |
| 1229 native_widget_delegate_->OnNativeWidgetVisibilityChanged(false); | 1229 native_widget_delegate_->OnNativeWidgetVisibilityChanged(false); |
| 1230 } | 1230 } |
| 1231 | 1231 |
| 1232 gfx::Rect DesktopWindowTreeHostX11::GetBoundsInPixels() const { | 1232 gfx::Rect DesktopWindowTreeHostX11::GetBoundsInPixels() const { |
| 1233 return bounds_in_pixels_; | 1233 return bounds_in_pixels_; |
| 1234 } | 1234 } |
| 1235 | 1235 |
| 1236 void DesktopWindowTreeHostX11::SetBoundsInPixels( | 1236 void DesktopWindowTreeHostX11::SetBoundsInPixels( |
| 1237 const gfx::Rect& requested_bounds_in_pixel) { | 1237 const gfx::Rect& requested_bounds_in_pixel) { |
| 1238 gfx::Rect bounds_in_pixels(requested_bounds_in_pixel.origin(), | 1238 gfx::Rect bounds_in_pixels(requested_bounds_in_pixel.origin(), |
| 1239 AdjustSize(requested_bounds_in_pixel.size())); | 1239 AdjustSize(requested_bounds_in_pixel.size())); |
| 1240 bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin(); | 1240 bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin(); |
| 1241 bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size(); | 1241 bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size(); |
| 1242 XWindowChanges changes = {0}; | 1242 XWindowChanges changes = {0}; |
| 1243 unsigned value_mask = 0; | 1243 unsigned value_mask = 0; |
| 1244 | 1244 |
| 1245 delayed_resize_task_.Cancel(); | |
| 1246 | 1245 |
| 1247 if (size_changed) { | 1246 if (size_changed) { |
| 1247 // Only cancel the delayed resize task if we're already about to call |
| 1248 // OnHostResized in this function. |
| 1249 delayed_resize_task_.Cancel(); |
| 1250 |
| 1248 // Update the minimum and maximum sizes in case they have changed. | 1251 // Update the minimum and maximum sizes in case they have changed. |
| 1249 UpdateMinAndMaxSize(); | 1252 UpdateMinAndMaxSize(); |
| 1250 | 1253 |
| 1251 if (bounds_in_pixels.width() < min_size_in_pixels_.width() || | 1254 if (bounds_in_pixels.width() < min_size_in_pixels_.width() || |
| 1252 bounds_in_pixels.height() < min_size_in_pixels_.height() || | 1255 bounds_in_pixels.height() < min_size_in_pixels_.height() || |
| 1253 (!max_size_in_pixels_.IsEmpty() && | 1256 (!max_size_in_pixels_.IsEmpty() && |
| 1254 (bounds_in_pixels.width() > max_size_in_pixels_.width() || | 1257 (bounds_in_pixels.width() > max_size_in_pixels_.width() || |
| 1255 bounds_in_pixels.height() > max_size_in_pixels_.height()))) { | 1258 bounds_in_pixels.height() > max_size_in_pixels_.height()))) { |
| 1256 gfx::Size size_in_pixels = bounds_in_pixels.size(); | 1259 gfx::Size size_in_pixels = bounds_in_pixels.size(); |
| 1257 if (!max_size_in_pixels_.IsEmpty()) | 1260 if (!max_size_in_pixels_.IsEmpty()) |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 insets.size() == 4) { | 1660 insets.size() == 4) { |
| 1658 // |insets| are returned in the order: [left, right, top, bottom]. | 1661 // |insets| are returned in the order: [left, right, top, bottom]. |
| 1659 native_window_frame_borders_in_pixels_ = | 1662 native_window_frame_borders_in_pixels_ = |
| 1660 gfx::Insets(insets[2], insets[0], insets[3], insets[1]); | 1663 gfx::Insets(insets[2], insets[0], insets[3], insets[1]); |
| 1661 } else { | 1664 } else { |
| 1662 native_window_frame_borders_in_pixels_ = gfx::Insets(); | 1665 native_window_frame_borders_in_pixels_ = gfx::Insets(); |
| 1663 } | 1666 } |
| 1664 } | 1667 } |
| 1665 | 1668 |
| 1666 void DesktopWindowTreeHostX11::UpdateMinAndMaxSize() { | 1669 void DesktopWindowTreeHostX11::UpdateMinAndMaxSize() { |
| 1667 if (!IsVisible()) | |
| 1668 return; | |
| 1669 | |
| 1670 gfx::Size minimum_in_pixels = | 1670 gfx::Size minimum_in_pixels = |
| 1671 ToPixelRect(gfx::Rect(native_widget_delegate_->GetMinimumSize())).size(); | 1671 ToPixelRect(gfx::Rect(native_widget_delegate_->GetMinimumSize())).size(); |
| 1672 gfx::Size maximum_in_pixels = | 1672 gfx::Size maximum_in_pixels = |
| 1673 ToPixelRect(gfx::Rect(native_widget_delegate_->GetMaximumSize())).size(); | 1673 ToPixelRect(gfx::Rect(native_widget_delegate_->GetMaximumSize())).size(); |
| 1674 if (min_size_in_pixels_ == minimum_in_pixels && | 1674 if (min_size_in_pixels_ == minimum_in_pixels && |
| 1675 max_size_in_pixels_ == maximum_in_pixels) | 1675 max_size_in_pixels_ == maximum_in_pixels) |
| 1676 return; | 1676 return; |
| 1677 | 1677 |
| 1678 min_size_in_pixels_ = minimum_in_pixels; | 1678 min_size_in_pixels_ = minimum_in_pixels; |
| 1679 max_size_in_pixels_ = maximum_in_pixels; | 1679 max_size_in_pixels_ = maximum_in_pixels; |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1930 if (show_state == ui::SHOW_STATE_INACTIVE || wm_user_time_ms != 0) { | 1930 if (show_state == ui::SHOW_STATE_INACTIVE || wm_user_time_ms != 0) { |
| 1931 XChangeProperty( | 1931 XChangeProperty( |
| 1932 xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_USER_TIME"), | 1932 xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_USER_TIME"), |
| 1933 XA_CARDINAL, 32, PropModeReplace, | 1933 XA_CARDINAL, 32, PropModeReplace, |
| 1934 reinterpret_cast<const unsigned char*>(&wm_user_time_ms), 1); | 1934 reinterpret_cast<const unsigned char*>(&wm_user_time_ms), 1); |
| 1935 } | 1935 } |
| 1936 | 1936 |
| 1937 ui::X11EventSource* event_source = ui::X11EventSource::GetInstance(); | 1937 ui::X11EventSource* event_source = ui::X11EventSource::GetInstance(); |
| 1938 DCHECK(event_source); | 1938 DCHECK(event_source); |
| 1939 | 1939 |
| 1940 if (wait_for_unmap_) { | 1940 UpdateMinAndMaxSize(); |
| 1941 // Block until our window is unmapped. This avoids a race condition when | |
| 1942 // remapping an unmapped window. | |
| 1943 event_source->BlockUntilWindowUnmapped(xwindow_); | |
| 1944 DCHECK(!wait_for_unmap_); | |
| 1945 } | |
| 1946 | 1941 |
| 1947 XMapWindow(xdisplay_, xwindow_); | 1942 XMapWindow(xdisplay_, xwindow_); |
| 1948 | 1943 window_mapped_in_client_ = true; |
| 1949 // We now block until our window is mapped. Some X11 APIs will crash and | |
| 1950 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is | |
| 1951 // asynchronous. | |
| 1952 event_source->BlockUntilWindowMapped(xwindow_); | |
| 1953 } | 1944 } |
| 1954 | 1945 |
| 1955 void DesktopWindowTreeHostX11::SetWindowTransparency() { | 1946 void DesktopWindowTreeHostX11::SetWindowTransparency() { |
| 1956 compositor()->SetHostHasTransparentBackground(use_argb_visual_); | 1947 compositor()->SetHostHasTransparentBackground(use_argb_visual_); |
| 1957 window()->SetTransparent(use_argb_visual_); | 1948 window()->SetTransparent(use_argb_visual_); |
| 1958 content_window_->SetTransparent(use_argb_visual_); | 1949 content_window_->SetTransparent(use_argb_visual_); |
| 1959 } | 1950 } |
| 1960 | 1951 |
| 1961 void DesktopWindowTreeHostX11::Relayout() { | 1952 void DesktopWindowTreeHostX11::Relayout() { |
| 1962 Widget* widget = native_widget_delegate_->AsWidget(); | 1953 Widget* widget = native_widget_delegate_->AsWidget(); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 default: | 2156 default: |
| 2166 NOTREACHED(); | 2157 NOTREACHED(); |
| 2167 } | 2158 } |
| 2168 | 2159 |
| 2169 // If we coalesced an event we need to free its cookie. | 2160 // If we coalesced an event we need to free its cookie. |
| 2170 if (num_coalesced > 0) | 2161 if (num_coalesced > 0) |
| 2171 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); | 2162 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); |
| 2172 break; | 2163 break; |
| 2173 } | 2164 } |
| 2174 case MapNotify: { | 2165 case MapNotify: { |
| 2175 window_mapped_ = true; | 2166 window_mapped_in_server_ = true; |
| 2176 | 2167 |
| 2177 for (DesktopWindowTreeHostObserverX11& observer : observer_list_) | 2168 for (DesktopWindowTreeHostObserverX11& observer : observer_list_) |
| 2178 observer.OnWindowMapped(xwindow_); | 2169 observer.OnWindowMapped(xwindow_); |
| 2179 | 2170 |
| 2180 UpdateMinAndMaxSize(); | |
| 2181 | |
| 2182 // Some WMs only respect maximize hints after the window has been mapped. | 2171 // Some WMs only respect maximize hints after the window has been mapped. |
| 2183 // Check whether we need to re-do a maximization. | 2172 // Check whether we need to re-do a maximization. |
| 2184 if (should_maximize_after_map_) { | 2173 if (should_maximize_after_map_) { |
| 2185 Maximize(); | 2174 Maximize(); |
| 2186 should_maximize_after_map_ = false; | 2175 should_maximize_after_map_ = false; |
| 2187 } | 2176 } |
| 2188 | 2177 |
| 2189 break; | 2178 break; |
| 2190 } | 2179 } |
| 2191 case UnmapNotify: { | 2180 case UnmapNotify: { |
| 2192 window_mapped_ = false; | 2181 window_mapped_in_server_ = false; |
| 2193 wait_for_unmap_ = false; | |
| 2194 has_pointer_ = false; | 2182 has_pointer_ = false; |
| 2195 has_pointer_grab_ = false; | 2183 has_pointer_grab_ = false; |
| 2196 has_pointer_focus_ = false; | 2184 has_pointer_focus_ = false; |
| 2197 has_window_focus_ = false; | 2185 has_window_focus_ = false; |
| 2198 for (DesktopWindowTreeHostObserverX11& observer : observer_list_) | 2186 for (DesktopWindowTreeHostObserverX11& observer : observer_list_) |
| 2199 observer.OnWindowUnmapped(xwindow_); | 2187 observer.OnWindowUnmapped(xwindow_); |
| 2200 break; | 2188 break; |
| 2201 } | 2189 } |
| 2202 case ClientMessage: { | 2190 case ClientMessage: { |
| 2203 Atom message_type = xev->xclient.message_type; | 2191 Atom message_type = xev->xclient.message_type; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2365 | 2353 |
| 2366 // static | 2354 // static |
| 2367 DesktopWindowTreeHost* DesktopWindowTreeHost::Create( | 2355 DesktopWindowTreeHost* DesktopWindowTreeHost::Create( |
| 2368 internal::NativeWidgetDelegate* native_widget_delegate, | 2356 internal::NativeWidgetDelegate* native_widget_delegate, |
| 2369 DesktopNativeWidgetAura* desktop_native_widget_aura) { | 2357 DesktopNativeWidgetAura* desktop_native_widget_aura) { |
| 2370 return new DesktopWindowTreeHostX11(native_widget_delegate, | 2358 return new DesktopWindowTreeHostX11(native_widget_delegate, |
| 2371 desktop_native_widget_aura); | 2359 desktop_native_widget_aura); |
| 2372 } | 2360 } |
| 2373 | 2361 |
| 2374 } // namespace views | 2362 } // namespace views |
| OLD | NEW |