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

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

Powered by Google App Engine
This is Rietveld 408576698