Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc

Issue 2630773002: Avoid blocking while mapping an X11 window (Closed)
Patch Set: Address feedback Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698