1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "renderer/window_util.h"
31
32 #include "base/coordinates.h"
33
34 namespace mozc {
35 namespace renderer {
36 namespace {
GetWindowRectForMainWindowFromPreeditRectHorizontal(const Point & target_point,const Rect & preedit_rect,const Size & window_size,const Point & zero_point_offset,const Rect & working_area)37 Rect GetWindowRectForMainWindowFromPreeditRectHorizontal(
38 const Point &target_point, const Rect &preedit_rect,
39 const Size &window_size, const Point &zero_point_offset,
40 const Rect &working_area) {
41 Rect window_rect(target_point, window_size);
42 window_rect.origin.x -= zero_point_offset.x;
43 window_rect.origin.y -= zero_point_offset.y;
44
45 // If monitor_rect has erroneous value, it returns window_rect.
46 if (working_area.Height() == 0 || working_area.Width() == 0) {
47 return window_rect;
48 }
49
50 // If the working area below the preedit does not have enough vertical space
51 // to display the candidate window, put the candidate window above
52 // the preedit.
53 if (working_area.Bottom() < window_rect.Bottom()) {
54 window_rect.origin.y -= (window_rect.Height() + preedit_rect.Height());
55 // We add zero_point_offset.y twice to keep the same distance
56 // above the preedit_rect.
57 window_rect.origin.y += zero_point_offset.y * 2;
58 }
59
60 if (working_area.Bottom() < window_rect.Bottom()) {
61 window_rect.origin.y -= (window_rect.Bottom() - working_area.Bottom());
62 }
63
64 if (window_rect.Top() < working_area.Top()) {
65 window_rect.origin.y += (working_area.Top() - window_rect.Top());
66 }
67
68 if (working_area.Right() < window_rect.Right()) {
69 window_rect.origin.x -= (window_rect.Right() - working_area.Right());
70 }
71
72 if (window_rect.Left() < working_area.Left()) {
73 window_rect.origin.x += (working_area.Left() - window_rect.Left());
74 }
75
76 return window_rect;
77 }
78
GetWindowRectForMainWindowFromPreeditRectVertical(const Point & target_point,const Rect & preedit_rect,const Size & window_size,const Point & zero_point_offset,const Rect & working_area)79 Rect GetWindowRectForMainWindowFromPreeditRectVertical(
80 const Point &target_point, const Rect &preedit_rect,
81 const Size &window_size, const Point &zero_point_offset,
82 const Rect &working_area) {
83 Rect window_rect(target_point, window_size);
84
85 // Currently |zero_point_offset| is ignored because the candidate renderer
86 // has not supported vertical writing.
87
88 // Since |target_point| is pointing the upper-left of the preedit, move the
89 // candidate window to the right side of the preedit.
90 window_rect.origin.x += preedit_rect.Width();
91
92 // If monitor_rect has erroneous value, it returns window_rect.
93 if (working_area.Height() == 0 || working_area.Width() == 0) {
94 return window_rect;
95 }
96
97 if (working_area.Right() < window_rect.Right()) {
98 window_rect.origin.x -= (window_rect.Width() + preedit_rect.Width());
99 }
100
101 if (working_area.Right() < window_rect.Right()) {
102 window_rect.origin.x -= (window_rect.Right() - working_area.Right());
103 }
104
105 if (window_rect.Left() < working_area.Left()) {
106 window_rect.origin.x += (working_area.Left() - window_rect.Left());
107 }
108
109 if (working_area.Bottom() < window_rect.Bottom()) {
110 window_rect.origin.y -= (window_rect.Bottom() - working_area.Bottom());
111 }
112
113 if (window_rect.Top() < working_area.Top()) {
114 window_rect.origin.y += (working_area.Top() - window_rect.Top());
115 }
116
117 return window_rect;
118 }
119 } // namespace
120
GetWindowRectForMainWindowFromPreeditRect(const Rect & preedit_rect,const Size & window_size,const Point & zero_point_offset,const Rect & working_area)121 Rect WindowUtil::GetWindowRectForMainWindowFromPreeditRect(
122 const Rect &preedit_rect, const Size &window_size,
123 const Point &zero_point_offset, const Rect &working_area) {
124 const Point preedit_bottom_left(preedit_rect.Left(), preedit_rect.Bottom());
125
126 return GetWindowRectForMainWindowFromPreeditRectHorizontal(
127 preedit_bottom_left, preedit_rect, window_size, zero_point_offset,
128 working_area);
129 }
130
GetWindowRectForMainWindowFromTargetPoint(const Point & target_point,const Size & window_size,const Point & zero_point_offset,const Rect & working_area)131 Rect WindowUtil::GetWindowRectForMainWindowFromTargetPoint(
132 const Point &target_point, const Size &window_size,
133 const Point &zero_point_offset, const Rect &working_area) {
134 Rect window_rect(target_point, window_size);
135 window_rect.origin.x -= zero_point_offset.x;
136 window_rect.origin.y -= zero_point_offset.y;
137
138 // If monitor_rect has erroneous value, it returns window_rect.
139 if (working_area.Height() == 0 || working_area.Width() == 0) {
140 return window_rect;
141 }
142
143 if (working_area.Bottom() < window_rect.Bottom()) {
144 window_rect.origin.y -= (window_rect.Bottom() - working_area.Bottom());
145 }
146
147 if (window_rect.Top() < working_area.Top()) {
148 window_rect.origin.y += (working_area.Top() - window_rect.Top());
149 }
150
151 if (working_area.Right() < window_rect.Right()) {
152 window_rect.origin.x -= (window_rect.Right() - working_area.Right());
153 }
154
155 if (window_rect.Left() < working_area.Left()) {
156 window_rect.origin.x += (working_area.Left() - window_rect.Left());
157 }
158
159 return window_rect;
160 }
161
GetWindowRectForMainWindowFromTargetPointAndPreedit(const Point & target_point,const Rect & preedit_rect,const Size & window_size,const Point & zero_point_offset,const Rect & working_area,bool vertical)162 Rect WindowUtil::GetWindowRectForMainWindowFromTargetPointAndPreedit(
163 const Point &target_point, const Rect &preedit_rect,
164 const Size &window_size, const Point &zero_point_offset,
165 const Rect &working_area, bool vertical) {
166 if (vertical) {
167 return GetWindowRectForMainWindowFromPreeditRectVertical(
168 target_point, preedit_rect, window_size, zero_point_offset,
169 working_area);
170 }
171
172 return GetWindowRectForMainWindowFromPreeditRectHorizontal(
173 target_point, preedit_rect, window_size, zero_point_offset,
174 working_area);
175 }
176
GetWindowRectForCascadingWindow(const Rect & selected_row,const Size & window_size,const Point & zero_point_offset,const Rect & working_area)177 Rect WindowUtil::GetWindowRectForCascadingWindow(
178 const Rect &selected_row, const Size &window_size,
179 const Point &zero_point_offset, const Rect &working_area) {
180 const Point row_top_right(selected_row.Right(), selected_row.Top());
181
182 Rect window_rect(row_top_right, window_size);
183 window_rect.origin.x -= zero_point_offset.x;
184 window_rect.origin.y -= zero_point_offset.y;
185
186 if (working_area.Height() == 0 || working_area.Width() == 0) {
187 return window_rect;
188 }
189
190 // If the working area right to the specified candidate window does not have
191 // enough horizontal space to display the cascading window,
192 // put the cascading window left to the candidate window.
193 if (working_area.Right() < window_rect.Right()) {
194 window_rect.origin.x -= (window_rect.Width() + selected_row.Width());
195 // We add zero_point_offset.x twice to keep the same distance
196 // left of the selected_row.
197 window_rect.origin.x += zero_point_offset.x * 2;
198 }
199
200 if (working_area.Bottom() < window_rect.Bottom()) {
201 window_rect.origin.y -= (window_rect.Bottom() - working_area.Bottom());
202 }
203
204 if (window_rect.Top() < working_area.Top()) {
205 window_rect.origin.y += (working_area.Top() - window_rect.Top());
206 }
207
208 if (window_rect.Left() < working_area.Left()) {
209 window_rect.origin.x += (working_area.Left() - window_rect.Left());
210 }
211
212 return window_rect;
213 }
214
GetWindowRectForInfolistWindow(const Size & window_size,const Rect & candidate_rect,const Rect & working_area)215 Rect WindowUtil::GetWindowRectForInfolistWindow(
216 const Size &window_size, const Rect &candidate_rect,
217 const Rect &working_area) {
218 Point infolist_pos;
219
220 if (working_area.Height() == 0 || working_area.Width() == 0) {
221 infolist_pos.x = candidate_rect.Left() + candidate_rect.Width();
222 infolist_pos.y = candidate_rect.Top();
223 return Rect(infolist_pos, window_size);
224 }
225 if (candidate_rect.Left() + candidate_rect.Width() + window_size.width >
226 working_area.Right()) {
227 infolist_pos.x = candidate_rect.Left() - window_size.width;
228 } else {
229 infolist_pos.x = candidate_rect.Left() + candidate_rect.Width();
230 }
231 if (candidate_rect.Top() + window_size.height > working_area.Bottom()) {
232 infolist_pos.y = working_area.Bottom() - window_size.height;
233 } else {
234 infolist_pos.y = candidate_rect.Top();
235 }
236 return Rect(infolist_pos, window_size);
237 }
238 } // namespace renderer
239 } // namespace mozc
240