Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/views/widget/widget_mac_utils.h" | |
| 6 | |
| 7 #import <objc/runtime.h> | |
| 8 | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/mac/foundation_util.h" | |
| 12 #include "ui/views/cocoa/bridged_content_view.h" | |
| 13 #include "ui/views/controls/native/native_view_host.h" | |
| 14 #include "ui/views/widget/widget.h" | |
| 15 | |
| 16 namespace views { | |
| 17 namespace { | |
| 18 | |
| 19 using HostedViews = std::vector<std::pair<const views::View*, NSView*>>; | |
| 20 | |
| 21 struct EqualToView { | |
| 22 EqualToView(const views::View* view) : view_(view) {} | |
| 23 bool operator()(const HostedViews::value_type& v) const { | |
| 24 return v.first == view_; | |
| 25 } | |
| 26 | |
| 27 private: | |
| 28 const views::View* view_; | |
| 29 }; | |
| 30 | |
| 31 struct EqualToNSView { | |
| 32 EqualToNSView(NSView* native_view) : native_view_(native_view) {} | |
| 33 bool operator()(const HostedViews::value_type& v) const { | |
| 34 return v.second == native_view_; | |
| 35 } | |
| 36 | |
| 37 private: | |
| 38 NSView* native_view_; | |
| 39 }; | |
| 40 | |
| 41 HostedViews GetViewsWithAssociatedNativeViews(const Widget* widget) { | |
| 42 HostedViews result; | |
| 43 const auto* subviews = [widget->GetNativeView() subviews]; | |
| 44 for (NSView* child in subviews) { | |
| 45 NSValue* value = objc_getAssociatedObject(child, &kAssociatedViewHostKey); | |
| 46 if (value) | |
| 47 result.emplace_back(static_cast<const views::View*>(value.pointerValue), | |
| 48 child); | |
| 49 } | |
| 50 return result; | |
| 51 } | |
| 52 | |
| 53 HostedViews::iterator SortViewsList(const views::View* view, | |
| 54 HostedViews::iterator begin, | |
| 55 HostedViews::iterator end) { | |
| 56 auto it = std::find_if(begin, end, EqualToView(view)); | |
| 57 if (it != end) { | |
| 58 std::swap(*begin, *it); | |
| 59 ++begin; | |
| 60 } | |
| 61 for (int i = 0; i < view->child_count(); ++i) | |
| 62 begin = SortViewsList(view->child_at(i), begin, end); | |
| 63 return begin; | |
| 64 } | |
| 65 | |
| 66 NSComparisonResult SubviewSorter(id lhs, id rhs, void* hosts_as_void) { | |
| 67 DCHECK_NE(lhs, rhs); | |
| 68 | |
| 69 const HostedViews* hosts = static_cast<const HostedViews*>(hosts_as_void); | |
| 70 auto left_it = std::find_if(hosts->begin(), hosts->end(), EqualToNSView(lhs)); | |
|
tapted
2016/03/15 22:54:53
This call is O(n) so it makes the sorting algorith
kirr
2016/03/16 09:16:34
I used vector of pairs as one container for all (a
kirr
2016/03/16 21:43:45
Done.
| |
| 71 auto right_it = | |
| 72 std::find_if(hosts->begin(), hosts->end(), EqualToNSView(rhs)); | |
| 73 bool left_found = left_it != hosts->end(); | |
| 74 bool right_found = right_it != hosts->end(); | |
| 75 | |
| 76 // Sort unassociated views below associated views. | |
| 77 if (left_found != right_found) { | |
|
tapted
2016/03/15 22:54:53
nit: doesn't need curlies
kirr
2016/03/16 21:43:45
Done.
| |
| 78 return left_found ? NSOrderedDescending : NSOrderedAscending; | |
| 79 } | |
| 80 | |
| 81 if (left_found) | |
|
tapted
2016/03/15 22:54:53
nit: needs curlies
kirr
2016/03/16 21:43:45
Done.
| |
| 82 return std::distance(hosts->begin(), left_it) < | |
| 83 std::distance(hosts->begin(), right_it) | |
| 84 ? NSOrderedAscending | |
| 85 : NSOrderedDescending; | |
| 86 | |
| 87 // If both are unassociated, consider that order is not important | |
| 88 return NSOrderedSame; | |
| 89 } | |
| 90 | |
| 91 } // namespace | |
| 92 | |
| 93 int kAssociatedViewHostKey; | |
| 94 | |
| 95 void AttachNSViewRelatedToHost(NSView* native_view, NativeViewHost* host) { | |
|
tapted
2016/03/15 22:54:53
I don't think this function is necessary.
Aura ob
kirr
2016/03/16 21:43:45
Done.
| |
| 96 Widget* new_parent = host->GetWidget(); | |
| 97 HostedViews hosts = GetViewsWithAssociatedNativeViews(new_parent); | |
| 98 hosts.emplace_back(host, native_view); | |
| 99 SortViewsList(new_parent->GetRootView(), hosts.begin(), hosts.end()); | |
| 100 | |
| 101 BridgedContentView* new_superview = | |
| 102 base::mac::ObjCCastStrict<BridgedContentView>( | |
| 103 new_parent->GetNativeView()); | |
| 104 DCHECK(new_superview); | |
| 105 | |
| 106 auto it = std::find_if(hosts.begin(), hosts.end(), EqualToView(host)); | |
| 107 if (it == hosts.end() || (it + 1) == hosts.end()) { | |
| 108 [new_superview addSubview:native_view]; | |
| 109 } else { | |
| 110 NSView* view_above = (it + 1)->second; | |
| 111 [new_superview addSubview:native_view | |
| 112 positioned:NSWindowBelow | |
| 113 relativeTo:view_above]; | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 void ReorderChildNSViews(Widget* widget) { | |
| 118 HostedViews hosts = GetViewsWithAssociatedNativeViews(widget); | |
| 119 HostedViews sorted_hosts = hosts; | |
| 120 SortViewsList(widget->GetRootView(), sorted_hosts.begin(), | |
| 121 sorted_hosts.end()); | |
| 122 | |
| 123 if (hosts != sorted_hosts) | |
|
tapted
2016/03/15 22:54:53
nit: need curlies
(policy is if the body is multi
kirr
2016/03/16 21:43:45
Done. Thanks.
| |
| 124 [widget->GetNativeView() sortSubviewsUsingFunction:&SubviewSorter | |
|
tapted
2016/03/15 22:54:53
If we are worried about using this function in par
kirr
2016/03/16 21:43:45
Seems like it's better not worry about it until we
| |
| 125 context:&sorted_hosts]; | |
| 126 } | |
| 127 | |
| 128 } // namespace views | |
| OLD | NEW |