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

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

Issue 268673017: Fix X11TopmostWindowFinder (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 70
71 // Constants that are part of EWMH. 71 // Constants that are part of EWMH.
72 const int k_NET_WM_STATE_ADD = 1; 72 const int k_NET_WM_STATE_ADD = 1;
73 const int k_NET_WM_STATE_REMOVE = 0; 73 const int k_NET_WM_STATE_REMOVE = 0;
74 74
75 const char* kAtomsToCache[] = { 75 const char* kAtomsToCache[] = {
76 "UTF8_STRING", 76 "UTF8_STRING",
77 "WM_DELETE_WINDOW", 77 "WM_DELETE_WINDOW",
78 "WM_PROTOCOLS", 78 "WM_PROTOCOLS",
79 "WM_S0", 79 "WM_S0",
80 "_NET_FRAME_EXTENTS",
80 "_NET_WM_CM_S0", 81 "_NET_WM_CM_S0",
81 "_NET_WM_ICON", 82 "_NET_WM_ICON",
82 "_NET_WM_NAME", 83 "_NET_WM_NAME",
83 "_NET_WM_PID", 84 "_NET_WM_PID",
84 "_NET_WM_PING", 85 "_NET_WM_PING",
85 "_NET_WM_STATE", 86 "_NET_WM_STATE",
86 "_NET_WM_STATE_ABOVE", 87 "_NET_WM_STATE_ABOVE",
87 "_NET_WM_STATE_FULLSCREEN", 88 "_NET_WM_STATE_FULLSCREEN",
88 "_NET_WM_STATE_HIDDEN", 89 "_NET_WM_STATE_HIDDEN",
89 "_NET_WM_STATE_MAXIMIZED_HORZ", 90 "_NET_WM_STATE_MAXIMIZED_HORZ",
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 is_fullscreen_(false), 135 is_fullscreen_(false),
135 is_always_on_top_(false), 136 is_always_on_top_(false),
136 use_native_frame_(false), 137 use_native_frame_(false),
137 use_argb_visual_(false), 138 use_argb_visual_(false),
138 drag_drop_client_(NULL), 139 drag_drop_client_(NULL),
139 current_cursor_(ui::kCursorNull), 140 current_cursor_(ui::kCursorNull),
140 native_widget_delegate_(native_widget_delegate), 141 native_widget_delegate_(native_widget_delegate),
141 desktop_native_widget_aura_(desktop_native_widget_aura), 142 desktop_native_widget_aura_(desktop_native_widget_aura),
142 content_window_(NULL), 143 content_window_(NULL),
143 window_parent_(NULL), 144 window_parent_(NULL),
144 custom_window_shape_(NULL), 145 window_shape_(NULL),
146 custom_window_shape_(false),
145 urgency_hint_set_(false) { 147 urgency_hint_set_(false) {
146 } 148 }
147 149
148 DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { 150 DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
149 window()->ClearProperty(kHostForRootWindow); 151 window()->ClearProperty(kHostForRootWindow);
150 aura::client::SetWindowMoveClient(window(), NULL); 152 aura::client::SetWindowMoveClient(window(), NULL);
151 desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this); 153 desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
152 if (custom_window_shape_) 154 if (window_shape_)
153 XDestroyRegion(custom_window_shape_); 155 XDestroyRegion(window_shape_);
154 DestroyDispatcher(); 156 DestroyDispatcher();
155 } 157 }
156 158
157 // static 159 // static
158 aura::Window* DesktopWindowTreeHostX11::GetContentWindowForXID(XID xid) { 160 aura::Window* DesktopWindowTreeHostX11::GetContentWindowForXID(XID xid) {
159 aura::WindowTreeHost* host = 161 aura::WindowTreeHost* host =
160 aura::WindowTreeHost::GetForAcceleratedWidget(xid); 162 aura::WindowTreeHost::GetForAcceleratedWidget(xid);
161 return host ? host->window()->GetProperty(kViewsWindowForRootWindow) : NULL; 163 return host ? host->window()->GetProperty(kViewsWindowForRootWindow) : NULL;
162 } 164 }
163 165
(...skipping 11 matching lines...) Expand all
175 open_windows().end(), 177 open_windows().end(),
176 windows.begin(), 178 windows.begin(),
177 GetContentWindowForXID); 179 GetContentWindowForXID);
178 return windows; 180 return windows;
179 } 181 }
180 182
181 gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const { 183 gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const {
182 return bounds_; 184 return bounds_;
183 } 185 }
184 186
187 gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowOuterBounds() const {
188 gfx::Rect outer_bounds(bounds_);
189 outer_bounds.Inset(-native_window_frame_borders_);
190 return outer_bounds;
191 }
192
193 ::Region DesktopWindowTreeHostX11::GetWindowShape() const {
194 return window_shape_;
195 }
196
185 void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged( 197 void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged(
186 bool active) { 198 bool active) {
187 if (active) { 199 if (active) {
188 FlashFrame(false); 200 FlashFrame(false);
189 OnHostActivated(); 201 OnHostActivated();
190 open_windows().remove(xwindow_); 202 open_windows().remove(xwindow_);
191 open_windows().insert(open_windows().begin(), xwindow_); 203 open_windows().insert(open_windows().begin(), xwindow_);
192 } 204 }
193 205
194 desktop_native_widget_aura_->HandleActivationChanged(active); 206 desktop_native_widget_aura_->HandleActivationChanged(active);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 338
327 desktop_native_widget_aura_->OnHostClosed(); 339 desktop_native_widget_aura_->OnHostClosed();
328 } 340 }
329 341
330 aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() { 342 aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() {
331 return this; 343 return this;
332 } 344 }
333 345
334 void DesktopWindowTreeHostX11::ShowWindowWithState( 346 void DesktopWindowTreeHostX11::ShowWindowWithState(
335 ui::WindowShowState show_state) { 347 ui::WindowShowState show_state) {
336 if (!window_mapped_) 348 if (!window_mapped_) {
337 MapWindow(show_state); 349 MapWindow(show_state);
pkotwicz 2014/05/09 21:11:08 I added a call to ResetWindowRegion() here. This o
350 ResetWindowRegion();
351 }
338 352
339 if (show_state == ui::SHOW_STATE_NORMAL || 353 if (show_state == ui::SHOW_STATE_NORMAL ||
340 show_state == ui::SHOW_STATE_MAXIMIZED) { 354 show_state == ui::SHOW_STATE_MAXIMIZED) {
341 // Note: XFCE ignores a maximize hint given before mapping the window. 355 // Note: XFCE ignores a maximize hint given before mapping the window.
342 if (show_state == ui::SHOW_STATE_MAXIMIZED) 356 if (show_state == ui::SHOW_STATE_MAXIMIZED)
343 Maximize(); 357 Maximize();
344 Activate(); 358 Activate();
345 } 359 }
346 360
347 native_widget_delegate_->AsWidget()->SetInitialFocus(show_state); 361 native_widget_delegate_->AsWidget()->SetInitialFocus(show_state);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 if (!XGetGeometry(xdisplay_, x_root_window_, &root, &x, &y, 472 if (!XGetGeometry(xdisplay_, x_root_window_, &root, &x, &y,
459 &width, &height, &border_width, &depth)) { 473 &width, &height, &border_width, &depth)) {
460 NOTIMPLEMENTED(); 474 NOTIMPLEMENTED();
461 return gfx::Rect(0, 0, 10, 10); 475 return gfx::Rect(0, 0, 10, 10);
462 } 476 }
463 477
464 return gfx::Rect(x, y, width, height); 478 return gfx::Rect(x, y, width, height);
465 } 479 }
466 480
467 void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) { 481 void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) {
468 if (custom_window_shape_) 482 if (window_shape_)
469 XDestroyRegion(custom_window_shape_); 483 XDestroyRegion(window_shape_);
470 custom_window_shape_ = gfx::CreateRegionFromSkRegion(*native_region); 484 custom_window_shape_ = true;
485 window_shape_ = gfx::CreateRegionFromSkRegion(*native_region);
471 ResetWindowRegion(); 486 ResetWindowRegion();
472 delete native_region; 487 delete native_region;
473 } 488 }
474 489
475 void DesktopWindowTreeHostX11::Activate() { 490 void DesktopWindowTreeHostX11::Activate() {
476 if (!window_mapped_) 491 if (!window_mapped_)
477 return; 492 return;
478 493
479 X11DesktopHandler::get()->ActivateWindow(xwindow_); 494 X11DesktopHandler::get()->ActivateWindow(xwindow_);
480 } 495 }
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 CreateCompositor(GetAcceleratedWidget()); 1124 CreateCompositor(GetAcceleratedWidget());
1110 } 1125 }
1111 1126
1112 bool DesktopWindowTreeHostX11::IsWindowManagerPresent() { 1127 bool DesktopWindowTreeHostX11::IsWindowManagerPresent() {
1113 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 1128 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
1114 // of WM_Sn selections (where n is a screen number). 1129 // of WM_Sn selections (where n is a screen number).
1115 return XGetSelectionOwner( 1130 return XGetSelectionOwner(
1116 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; 1131 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
1117 } 1132 }
1118 1133
1134 void DesktopWindowTreeHostX11::OnWMStateUpdated() {
1135 std::vector< ::Atom> atom_list;
1136 if (!ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list))
1137 return;
1138
1139 window_properties_.clear();
1140 std::copy(atom_list.begin(), atom_list.end(),
1141 inserter(window_properties_, window_properties_.begin()));
1142
1143 if (!restored_bounds_.IsEmpty() && !IsMaximized()) {
1144 // If we have restored bounds, but WM_STATE no longer claims to be
1145 // maximized, we should clear our restored bounds.
1146 restored_bounds_ = gfx::Rect();
1147 } else if (IsMaximized() && restored_bounds_.IsEmpty()) {
1148 // The request that we become maximized originated from a different process.
1149 // |bounds_| already contains our maximized bounds. Do a best effort attempt
1150 // to get restored bounds by setting it to our previously set bounds (and if
1151 // we get this wrong, we aren't any worse off since we'd otherwise be
1152 // returning our maximized bounds).
1153 restored_bounds_ = previous_bounds_;
1154 }
1155
1156 is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN");
1157 is_always_on_top_ = HasWMSpecProperty("_NET_WM_STATE_ABOVE");
1158
1159 // Now that we have different window properties, we may need to relayout the
1160 // window. (The windows code doesn't need this because their window change is
1161 // synchronous.)
1162 //
1163 // TODO(erg): While this does work, there's a quick flash showing the
1164 // tabstrip/toolbar/etc. when going into fullscreen mode before hiding those
1165 // parts of the UI because we receive the sizing event from the window
1166 // manager before we receive the event that changes the fullscreen state.
1167 // Unsure what to do about that.
1168 Widget* widget = native_widget_delegate_->AsWidget();
1169 NonClientView* non_client_view = widget->non_client_view();
1170 // non_client_view may be NULL, especially during creation.
1171 if (non_client_view) {
1172 non_client_view->client_view()->InvalidateLayout();
1173 non_client_view->InvalidateLayout();
1174 }
1175 widget->GetRootView()->Layout();
1176 // Refresh the window's border, which may need to be updated if we have
1177 // changed the window's maximization state.
1178 ResetWindowRegion();
1179 }
1180
1181 void DesktopWindowTreeHostX11::OnFrameExtentsUpdated() {
1182 std::vector<int> insets;
1183 if (ui::GetIntArrayProperty(xwindow_, "_NET_FRAME_EXTENTS", &insets) &&
1184 insets.size() == 4) {
1185 // |insets| are returned in the order: [left, right, top, bottom].
1186 native_window_frame_borders_ = gfx::Insets(
1187 insets[2],
1188 insets[0],
1189 insets[3],
1190 insets[1]);
1191 } else {
1192 native_window_frame_borders_ = gfx::Insets();
1193 }
1194 }
1195
1119 void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled, 1196 void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled,
1120 ::Atom state1, 1197 ::Atom state1,
1121 ::Atom state2) { 1198 ::Atom state2) {
1122 XEvent xclient; 1199 XEvent xclient;
1123 memset(&xclient, 0, sizeof(xclient)); 1200 memset(&xclient, 0, sizeof(xclient));
1124 xclient.type = ClientMessage; 1201 xclient.type = ClientMessage;
1125 xclient.xclient.window = xwindow_; 1202 xclient.xclient.window = xwindow_;
1126 xclient.xclient.message_type = atom_cache_.GetAtom("_NET_WM_STATE"); 1203 xclient.xclient.message_type = atom_cache_.GetAtom("_NET_WM_STATE");
1127 xclient.xclient.format = 32; 1204 xclient.xclient.format = 32;
1128 xclient.xclient.data.l[0] = 1205 xclient.xclient.data.l[0] =
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 g_current_capture->SendEventToProcessor(event); 1279 g_current_capture->SendEventToProcessor(event);
1203 } else { 1280 } else {
1204 SendEventToProcessor(event); 1281 SendEventToProcessor(event);
1205 } 1282 }
1206 } 1283 }
1207 1284
1208 void DesktopWindowTreeHostX11::ResetWindowRegion() { 1285 void DesktopWindowTreeHostX11::ResetWindowRegion() {
1209 // If a custom window shape was supplied then apply it. 1286 // If a custom window shape was supplied then apply it.
1210 if (custom_window_shape_) { 1287 if (custom_window_shape_) {
1211 XShapeCombineRegion( 1288 XShapeCombineRegion(
1212 xdisplay_, xwindow_, ShapeBounding, 0, 0, custom_window_shape_, false); 1289 xdisplay_, xwindow_, ShapeBounding, 0, 0, window_shape_, false);
1213 return; 1290 return;
1214 } 1291 }
1215 1292
1293 if (window_shape_)
1294 XDestroyRegion(window_shape_);
1295 window_shape_ = NULL;
1296
1216 if (!IsMaximized()) { 1297 if (!IsMaximized()) {
1217 gfx::Path window_mask; 1298 gfx::Path window_mask;
1218 views::Widget* widget = native_widget_delegate_->AsWidget(); 1299 views::Widget* widget = native_widget_delegate_->AsWidget();
1219 if (widget->non_client_view()) { 1300 if (widget->non_client_view()) {
1220 // Some frame views define a custom (non-rectangular) window mask. If 1301 // Some frame views define a custom (non-rectangular) window mask. If
1221 // so, use it to define the window shape. If not, fall through. 1302 // so, use it to define the window shape. If not, fall through.
1222 widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask); 1303 widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask);
1223 if (window_mask.countPoints() > 0) { 1304 if (window_mask.countPoints() > 0) {
1224 Region region = gfx::CreateRegionFromSkPath(window_mask); 1305 window_shape_ = gfx::CreateRegionFromSkPath(window_mask);
1225 XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 1306 XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding,
1226 0, 0, region, false); 1307 0, 0, window_shape_, false);
1227 XDestroyRegion(region);
1228 return; 1308 return;
1229 } 1309 }
1230 } 1310 }
1231 } 1311 }
1232 1312
1233 // If we didn't set the shape for any reason, reset the shaping information. 1313 // If we didn't set the shape for any reason, reset the shaping information.
1234 // How this is done depends on the border style, due to quirks and bugs in 1314 // How this is done depends on the border style, due to quirks and bugs in
1235 // various window managers. 1315 // various window managers.
1236 if (ShouldUseNativeFrame()) { 1316 if (ShouldUseNativeFrame()) {
1237 // If the window has system borders, the mask must be set to null (not a 1317 // If the window has system borders, the mask must be set to null (not a
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 } else { 1680 } else {
1601 break; 1681 break;
1602 } 1682 }
1603 } 1683 }
1604 1684
1605 ui::MouseEvent mouseev(xev); 1685 ui::MouseEvent mouseev(xev);
1606 DispatchMouseEvent(&mouseev); 1686 DispatchMouseEvent(&mouseev);
1607 break; 1687 break;
1608 } 1688 }
1609 case PropertyNotify: { 1689 case PropertyNotify: {
1610 // Get our new window property state if the WM has told us its changed. 1690 ::Atom changed_atom = xev->xproperty.atom;
1611 ::Atom state = atom_cache_.GetAtom("_NET_WM_STATE"); 1691 if (changed_atom == atom_cache_.GetAtom("_NET_WM_STATE"))
1612 1692 OnWMStateUpdated();
1613 std::vector< ::Atom> atom_list; 1693 else if (changed_atom == atom_cache_.GetAtom("_NET_FRAME_EXTENTS"))
1614 if (xev->xproperty.atom == state && 1694 OnFrameExtentsUpdated();
1615 ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list)) {
1616 window_properties_.clear();
1617 std::copy(atom_list.begin(), atom_list.end(),
1618 inserter(window_properties_, window_properties_.begin()));
1619
1620 if (!restored_bounds_.IsEmpty() && !IsMaximized()) {
1621 // If we have restored bounds, but WM_STATE no longer claims to be
1622 // maximized, we should clear our restored bounds.
1623 restored_bounds_ = gfx::Rect();
1624 } else if (IsMaximized() && restored_bounds_.IsEmpty()) {
1625 // The request that we become maximized originated from a different
1626 // process. |bounds_| already contains our maximized bounds. Do a
1627 // best effort attempt to get restored bounds by setting it to our
1628 // previously set bounds (and if we get this wrong, we aren't any
1629 // worse off since we'd otherwise be returning our maximized bounds).
1630 restored_bounds_ = previous_bounds_;
1631 }
1632
1633 is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN");
1634 is_always_on_top_ = HasWMSpecProperty("_NET_WM_STATE_ABOVE");
1635
1636 // Now that we have different window properties, we may need to
1637 // relayout the window. (The windows code doesn't need this because
1638 // their window change is synchronous.)
1639 //
1640 // TODO(erg): While this does work, there's a quick flash showing the
1641 // tabstrip/toolbar/etc. when going into fullscreen mode before hiding
1642 // those parts of the UI because we receive the sizing event from the
1643 // window manager before we receive the event that changes the
1644 // fullscreen state. Unsure what to do about that.
1645 Widget* widget = native_widget_delegate_->AsWidget();
1646 NonClientView* non_client_view = widget->non_client_view();
1647 // non_client_view may be NULL, especially during creation.
1648 if (non_client_view) {
1649 non_client_view->client_view()->InvalidateLayout();
1650 non_client_view->InvalidateLayout();
1651 }
1652 widget->GetRootView()->Layout();
1653 // Refresh the window's border, which may need to be updated if we have
1654 // changed the window's maximization state.
1655 ResetWindowRegion();
1656 }
1657 break; 1695 break;
1658 } 1696 }
1659 case SelectionNotify: { 1697 case SelectionNotify: {
1660 drag_drop_client_->OnSelectionNotify(xev->xselection); 1698 drag_drop_client_->OnSelectionNotify(xev->xselection);
1661 break; 1699 break;
1662 } 1700 }
1663 } 1701 }
1664 return ui::POST_DISPATCH_STOP_PROPAGATION; 1702 return ui::POST_DISPATCH_STOP_PROPAGATION;
1665 } 1703 }
1666 1704
(...skipping 14 matching lines...) Expand all
1681 if (linux_ui) { 1719 if (linux_ui) {
1682 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window); 1720 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window);
1683 if (native_theme) 1721 if (native_theme)
1684 return native_theme; 1722 return native_theme;
1685 } 1723 }
1686 1724
1687 return ui::NativeTheme::instance(); 1725 return ui::NativeTheme::instance();
1688 } 1726 }
1689 1727
1690 } // namespace views 1728 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698