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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |