OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/base/x/selection_requestor.h" | 5 #include "ui/base/x/selection_requestor.h" |
6 | 6 |
7 #include "base/message_pump_aurax11.h" | 7 #include "base/message_pump_aurax11.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "ui/base/x/selection_utils.h" | 9 #include "ui/base/x/selection_utils.h" |
| 10 #include "ui/base/x/x11_util.h" |
10 | 11 |
11 namespace ui { | 12 namespace ui { |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 const char kChromeSelection[] = "CHROME_SELECTION"; | 16 const char kChromeSelection[] = "CHROME_SELECTION"; |
16 | 17 |
17 const char* kAtomsToCache[] = { | 18 const char* kAtomsToCache[] = { |
18 kChromeSelection, | 19 kChromeSelection, |
19 NULL | 20 NULL |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 current_target_ = target; | 61 current_target_ = target; |
61 in_nested_loop_ = true; | 62 in_nested_loop_ = true; |
62 quit_closure_ = run_loop.QuitClosure(); | 63 quit_closure_ = run_loop.QuitClosure(); |
63 run_loop.Run(); | 64 run_loop.Run(); |
64 in_nested_loop_ = false; | 65 in_nested_loop_ = false; |
65 current_target_ = None; | 66 current_target_ = None; |
66 | 67 |
67 if (returned_property_ != property_to_set) | 68 if (returned_property_ != property_to_set) |
68 return false; | 69 return false; |
69 | 70 |
70 // Retrieve the data from our window. | 71 return ui::GetRawBytesOfProperty(x_window_, returned_property_, |
71 unsigned long nitems = 0; | 72 out_data, out_data_bytes, out_data_items, |
72 unsigned long nbytes = 0; | 73 out_type); |
73 Atom prop_type = None; | |
74 int prop_format = 0; | |
75 unsigned char* property_data = NULL; | |
76 if (XGetWindowProperty(x_display_, | |
77 x_window_, | |
78 returned_property_, | |
79 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False, | |
80 AnyPropertyType, &prop_type, &prop_format, | |
81 &nitems, &nbytes, &property_data) != Success) { | |
82 return false; | |
83 } | |
84 | |
85 if (prop_type == None) | |
86 return false; | |
87 | |
88 if (out_data) | |
89 *out_data = property_data; | |
90 | |
91 if (out_data_bytes) { | |
92 // So even though we should theoretically have nbytes (and we can't | |
93 // pass NULL there), we need to manually calculate the byte length here | |
94 // because nbytes always returns zero. | |
95 switch (prop_format) { | |
96 case 8: | |
97 *out_data_bytes = nitems; | |
98 break; | |
99 case 16: | |
100 *out_data_bytes = sizeof(short) * nitems; | |
101 break; | |
102 case 32: | |
103 *out_data_bytes = sizeof(long) * nitems; | |
104 break; | |
105 default: | |
106 NOTREACHED(); | |
107 break; | |
108 } | |
109 } | |
110 | |
111 if (out_data_items) | |
112 *out_data_items = nitems; | |
113 | |
114 if (out_type) | |
115 *out_type = prop_type; | |
116 | |
117 return true; | |
118 } | 74 } |
119 | 75 |
120 scoped_ptr<SelectionData> SelectionRequestor::RequestAndWaitForTypes( | 76 scoped_ptr<SelectionData> SelectionRequestor::RequestAndWaitForTypes( |
121 const std::vector< ::Atom>& types) { | 77 const std::vector< ::Atom>& types) { |
122 for (std::vector< ::Atom>::const_iterator it = types.begin(); | 78 for (std::vector< ::Atom>::const_iterator it = types.begin(); |
123 it != types.end(); ++it) { | 79 it != types.end(); ++it) { |
124 unsigned char* data = NULL; | 80 unsigned char* data = NULL; |
125 size_t data_bytes = 0; | 81 size_t data_bytes = 0; |
126 ::Atom type = None; | 82 ::Atom type = None; |
127 if (PerformBlockingConvertSelection(*it, | 83 if (PerformBlockingConvertSelection(*it, |
128 &data, | 84 &data, |
129 &data_bytes, | 85 &data_bytes, |
130 NULL, | 86 NULL, |
131 &type) && | 87 &type) && |
132 type == *it) { | 88 type == *it) { |
133 scoped_ptr<SelectionData> data_out(new SelectionData(x_display_)); | 89 scoped_ptr<SelectionData> data_out(new SelectionData); |
134 data_out->Set(type, (char*)data, data_bytes, true); | 90 data_out->Set(type, (char*)data, data_bytes, true); |
135 return data_out.Pass(); | 91 return data_out.Pass(); |
136 } | 92 } |
137 } | 93 } |
138 | 94 |
139 return scoped_ptr<SelectionData>(); | 95 return scoped_ptr<SelectionData>(); |
140 } | 96 } |
141 | 97 |
142 void SelectionRequestor::OnSelectionNotify(const XSelectionEvent& event) { | 98 void SelectionRequestor::OnSelectionNotify(const XSelectionEvent& event) { |
143 if (!in_nested_loop_) { | 99 if (!in_nested_loop_) { |
144 // This shouldn't happen; we're not waiting on the X server for data, but | 100 // This shouldn't happen; we're not waiting on the X server for data, but |
145 // any client can send any message... | 101 // any client can send any message... |
146 return; | 102 return; |
147 } | 103 } |
148 | 104 |
149 if (selection_name_ == event.selection && | 105 if (selection_name_ == event.selection && |
150 current_target_ == event.target) { | 106 current_target_ == event.target) { |
151 returned_property_ = event.property; | 107 returned_property_ = event.property; |
152 } else { | 108 } else { |
153 // I am assuming that if some other client sent us a message after we've | 109 // I am assuming that if some other client sent us a message after we've |
154 // asked for data, but it's malformed, we should just treat as if they sent | 110 // asked for data, but it's malformed, we should just treat as if they sent |
155 // us an error message. | 111 // us an error message. |
156 returned_property_ = None; | 112 returned_property_ = None; |
157 } | 113 } |
158 | 114 |
159 quit_closure_.Run(); | 115 quit_closure_.Run(); |
160 } | 116 } |
161 | 117 |
162 } // namespace ui | 118 } // namespace ui |
OLD | NEW |