Chromium Code Reviews| 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/events/gestures/gesture_sequence.h" | 5 #include "ui/events/gestures/gesture_sequence.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 | 122 |
| 123 GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY = | 123 GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY = |
| 124 G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_STATIONARY, TSI_ALWAYS), | 124 G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_STATIONARY, TSI_ALWAYS), |
| 125 | 125 |
| 126 GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED = | 126 GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED = |
| 127 G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_CANCELLED, TSI_ALWAYS), | 127 G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_CANCELLED, TSI_ALWAYS), |
| 128 | 128 |
| 129 GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED = | 129 GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED = |
| 130 G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 1, TS_PRESSED, TSI_NOT_PROCESSED), | 130 G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 1, TS_PRESSED, TSI_NOT_PROCESSED), |
| 131 | 131 |
| 132 GST_SYNTHETIC_CLICK_ABORTED_FIRST_RELEASED = | |
| 133 G(GS_SYNTHETIC_CLICK_ABORTED, 0, TS_RELEASED, TSI_ALWAYS), | |
| 134 | |
| 135 GST_SYNTHETIC_CLICK_ABORTED_SECOND_PRESSED = | |
| 136 G(GS_SYNTHETIC_CLICK_ABORTED, 1, TS_PRESSED, TSI_NOT_PROCESSED), | |
| 137 | |
| 132 GST_SCROLL_FIRST_RELEASED = | 138 GST_SCROLL_FIRST_RELEASED = |
| 133 G(GS_SCROLL, 0, TS_RELEASED, TSI_ALWAYS), | 139 G(GS_SCROLL, 0, TS_RELEASED, TSI_ALWAYS), |
| 134 | 140 |
| 135 // Once scroll has started, process all touch-move events. | 141 // Once scroll has started, process all touch-move events. |
| 136 GST_SCROLL_FIRST_MOVED = | 142 GST_SCROLL_FIRST_MOVED = |
| 137 G(GS_SCROLL, 0, TS_MOVED, TSI_ALWAYS), | 143 G(GS_SCROLL, 0, TS_MOVED, TSI_ALWAYS), |
| 138 | 144 |
| 139 GST_SCROLL_FIRST_CANCELLED = | 145 GST_SCROLL_FIRST_CANCELLED = |
| 140 G(GS_SCROLL, 0, TS_CANCELLED, TSI_ALWAYS), | 146 G(GS_SCROLL, 0, TS_CANCELLED, TSI_ALWAYS), |
| 141 | 147 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED: | 341 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED: |
| 336 case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: | 342 case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: |
| 337 case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: | 343 case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: |
| 338 case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: | 344 case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: |
| 339 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED: | 345 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED: |
| 340 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED: | 346 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED: |
| 341 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED: | 347 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED: |
| 342 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY: | 348 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY: |
| 343 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED: | 349 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED: |
| 344 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED: | 350 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED: |
| 351 case GST_SYNTHETIC_CLICK_ABORTED_FIRST_RELEASED: | |
| 352 case GST_SYNTHETIC_CLICK_ABORTED_SECOND_PRESSED: | |
| 345 case GST_SCROLL_FIRST_RELEASED: | 353 case GST_SCROLL_FIRST_RELEASED: |
| 346 case GST_SCROLL_FIRST_MOVED: | 354 case GST_SCROLL_FIRST_MOVED: |
| 347 case GST_SCROLL_FIRST_CANCELLED: | 355 case GST_SCROLL_FIRST_CANCELLED: |
| 348 case GST_SCROLL_SECOND_PRESSED: | 356 case GST_SCROLL_SECOND_PRESSED: |
| 349 case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED: | 357 case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED: |
| 350 case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED_HANDLED: | 358 case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED_HANDLED: |
| 351 case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED: | 359 case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED: |
| 352 case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED_HANDLED: | 360 case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED_HANDLED: |
| 353 case GST_PENDING_TWO_FINGER_TAP_FIRST_MOVED: | 361 case GST_PENDING_TWO_FINGER_TAP_FIRST_MOVED: |
| 354 case GST_PENDING_TWO_FINGER_TAP_SECOND_MOVED: | 362 case GST_PENDING_TWO_FINGER_TAP_SECOND_MOVED: |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 550 | 558 |
| 551 switch (signature) { | 559 switch (signature) { |
| 552 case GST_INVALID: | 560 case GST_INVALID: |
| 553 break; | 561 break; |
| 554 | 562 |
| 555 case GST_NO_GESTURE_FIRST_PRESSED: | 563 case GST_NO_GESTURE_FIRST_PRESSED: |
| 556 TouchDown(event, point, gestures.get()); | 564 TouchDown(event, point, gestures.get()); |
| 557 set_state(GS_PENDING_SYNTHETIC_CLICK); | 565 set_state(GS_PENDING_SYNTHETIC_CLICK); |
| 558 break; | 566 break; |
| 559 case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED: | 567 case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED: |
| 568 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED: | |
| 560 if (Click(event, point, gestures.get())) | 569 if (Click(event, point, gestures.get())) |
| 561 point.UpdateForTap(); | 570 point.UpdateForTap(); |
| 562 else | 571 else |
| 563 PrependTapCancelGestureEvent(point, gestures.get()); | 572 PrependTapCancelGestureEvent(point, gestures.get()); |
| 564 set_state(GS_NO_GESTURE); | 573 set_state(GS_NO_GESTURE); |
| 565 break; | 574 break; |
| 566 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED: | 575 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED: |
| 567 case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: | 576 case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: |
| 568 if (ScrollStart(event, point, gestures.get())) { | 577 if (ScrollStart(event, point, gestures.get())) { |
| 569 PrependTapCancelGestureEvent(point, gestures.get()); | 578 PrependTapCancelGestureEvent(point, gestures.get()); |
| 570 set_state(GS_SCROLL); | 579 set_state(GS_SCROLL); |
| 571 if (ScrollUpdate(event, point, gestures.get())) | 580 if (ScrollUpdate(event, point, gestures.get())) |
| 572 point.UpdateForScroll(); | 581 point.UpdateForScroll(); |
| 573 } | 582 } |
| 574 break; | 583 break; |
| 584 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED: | |
| 575 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED: | 585 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED: |
| 576 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY: | 586 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY: |
| 577 // No scrolling allowed, so nothing happens. | |
| 578 break; | |
| 579 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED: | |
| 580 if (point.IsInScrollWindow(event)) { | 587 if (point.IsInScrollWindow(event)) { |
| 581 PrependTapCancelGestureEvent(point, gestures.get()); | 588 PrependTapCancelGestureEvent(point, gestures.get()); |
| 589 set_state(GS_SYNTHETIC_CLICK_ABORTED); | |
| 590 } else { | |
| 582 set_state(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL); | 591 set_state(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL); |
| 583 } | 592 } |
| 584 break; | 593 break; |
| 585 case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED_HANDLED: | 594 case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED_HANDLED: |
| 586 case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: | 595 case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: |
| 596 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED: | |
| 597 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED: | |
| 587 PrependTapCancelGestureEvent(point, gestures.get()); | 598 PrependTapCancelGestureEvent(point, gestures.get()); |
| 588 set_state(GS_NO_GESTURE); | 599 set_state(GS_NO_GESTURE); |
| 589 break; | 600 break; |
| 590 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED: | 601 case GST_SYNTHETIC_CLICK_ABORTED_FIRST_RELEASED: |
| 591 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED: | |
| 592 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED: | |
| 593 set_state(GS_NO_GESTURE); | 602 set_state(GS_NO_GESTURE); |
| 594 break; | 603 break; |
| 595 case GST_SCROLL_FIRST_MOVED: | 604 case GST_SCROLL_FIRST_MOVED: |
| 596 if (scroll_type_ == ST_VERTICAL || | 605 if (scroll_type_ == ST_VERTICAL || |
| 597 scroll_type_ == ST_HORIZONTAL) | 606 scroll_type_ == ST_HORIZONTAL) |
| 598 BreakRailScroll(event, point, gestures.get()); | 607 BreakRailScroll(event, point, gestures.get()); |
| 599 if (ScrollUpdate(event, point, gestures.get())) | 608 if (ScrollUpdate(event, point, gestures.get())) |
| 600 point.UpdateForScroll(); | 609 point.UpdateForScroll(); |
| 601 break; | 610 break; |
| 602 case GST_SCROLL_FIRST_RELEASED: | 611 case GST_SCROLL_FIRST_RELEASED: |
| 603 case GST_SCROLL_FIRST_CANCELLED: | 612 case GST_SCROLL_FIRST_CANCELLED: |
| 604 ScrollEnd(event, point, gestures.get()); | 613 ScrollEnd(event, point, gestures.get()); |
| 605 set_state(GS_NO_GESTURE); | 614 set_state(GS_NO_GESTURE); |
| 606 break; | 615 break; |
| 607 case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: | 616 case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: |
| 617 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED: | |
| 608 PrependTapCancelGestureEvent(point, gestures.get()); | 618 PrependTapCancelGestureEvent(point, gestures.get()); |
| 609 TwoFingerTapOrPinch(event, point, gestures.get()); | 619 TwoFingerTapOrPinch(event, point, gestures.get()); |
| 610 break; | 620 break; |
| 611 case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED: | 621 case GST_SYNTHETIC_CLICK_ABORTED_SECOND_PRESSED: |
| 612 TwoFingerTapOrPinch(event, point, gestures.get()); | 622 TwoFingerTapOrPinch(event, point, gestures.get()); |
| 613 break; | 623 break; |
| 614 case GST_SCROLL_SECOND_PRESSED: | 624 case GST_SCROLL_SECOND_PRESSED: |
| 615 PinchStart(event, point, gestures.get()); | 625 PinchStart(event, point, gestures.get()); |
| 616 set_state(GS_PINCH); | 626 set_state(GS_PINCH); |
| 617 break; | 627 break; |
| 618 case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED: | 628 case GST_PENDING_TWO_FINGER_TAP_FIRST_RELEASED: |
| 619 case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED: | 629 case GST_PENDING_TWO_FINGER_TAP_SECOND_RELEASED: |
| 620 TwoFingerTouchReleased(event, point, gestures.get()); | 630 TwoFingerTouchReleased(event, point, gestures.get()); |
| 621 set_state(GS_SCROLL); | 631 set_state(GS_SCROLL); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 744 | 754 |
| 745 if (event.type() == ui::ET_TOUCH_RELEASED || | 755 if (event.type() == ui::ET_TOUCH_RELEASED || |
| 746 event.type() == ui::ET_TOUCH_CANCELLED) | 756 event.type() == ui::ET_TOUCH_CANCELLED) |
| 747 AppendEndGestureEvent(point, gestures.get()); | 757 AppendEndGestureEvent(point, gestures.get()); |
| 748 | 758 |
| 749 if (state_ != last_state) | 759 if (state_ != last_state) |
| 750 DVLOG(4) << "Gesture Sequence" | 760 DVLOG(4) << "Gesture Sequence" |
| 751 << " State: " << state_ | 761 << " State: " << state_ |
| 752 << " touch id: " << event.touch_id(); | 762 << " touch id: " << event.touch_id(); |
| 753 | 763 |
| 754 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) { | 764 // If the state has changed from one in which a long/show press is possible to |
| 765 // one in which they are not possible, cancel the timers. | |
| 766 if (last_state != state_ && | |
| 767 state_ != GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL && | |
|
sadrul
2014/01/17 17:11:35
Can this be somewhat like this:
if (last_state
tdresser
2014/01/17 19:48:42
We don't even need the "last_state != state" check
| |
| 768 (last_state == GS_PENDING_SYNTHETIC_CLICK || | |
| 769 last_state == GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL)) { | |
| 755 GetLongPressTimer()->Stop(); | 770 GetLongPressTimer()->Stop(); |
| 756 GetShowPressTimer()->Stop(); | 771 GetShowPressTimer()->Stop(); |
| 757 } | 772 } |
| 758 | 773 |
| 759 // The set of point_ids must be contiguous and include 0. | 774 // The set of point_ids must be contiguous and include 0. |
| 760 // When a touch point is released, all points with ids greater than the | 775 // When a touch point is released, all points with ids greater than the |
| 761 // released point must have their ids decremented, or the set of point_ids | 776 // released point must have their ids decremented, or the set of point_ids |
| 762 // could end up with gaps. | 777 // could end up with gaps. |
| 763 if (event.type() == ui::ET_TOUCH_RELEASED || | 778 if (event.type() == ui::ET_TOUCH_RELEASED || |
| 764 event.type() == ui::ET_TOUCH_CANCELLED) { | 779 event.type() == ui::ET_TOUCH_CANCELLED) { |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1095 rect.height()), | 1110 rect.height()), |
| 1096 point->enclosing_rectangle().CenterPoint(), | 1111 point->enclosing_rectangle().CenterPoint(), |
| 1097 flags_, | 1112 flags_, |
| 1098 base::Time::FromDoubleT(point->last_touch_time()), | 1113 base::Time::FromDoubleT(point->last_touch_time()), |
| 1099 1 << point->touch_id())); | 1114 1 << point->touch_id())); |
| 1100 } | 1115 } |
| 1101 | 1116 |
| 1102 bool GestureSequence::Click(const TouchEvent& event, | 1117 bool GestureSequence::Click(const TouchEvent& event, |
| 1103 const GesturePoint& point, | 1118 const GesturePoint& point, |
| 1104 Gestures* gestures) { | 1119 Gestures* gestures) { |
| 1105 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 1120 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || |
| 1121 state_ == GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL); | |
| 1106 if (point.IsInClickWindow(event)) { | 1122 if (point.IsInClickWindow(event)) { |
| 1107 int tap_count = 1; | 1123 int tap_count = 1; |
| 1108 if (point.IsInTripleClickWindow(event)) | 1124 if (point.IsInTripleClickWindow(event)) |
| 1109 tap_count = 3; | 1125 tap_count = 3; |
| 1110 else if (point.IsInDoubleClickWindow(event)) | 1126 else if (point.IsInDoubleClickWindow(event)) |
| 1111 tap_count = 2; | 1127 tap_count = 2; |
| 1112 if (tap_count == 1 && GetShowPressTimer()->IsRunning()) { | 1128 if (tap_count == 1 && GetShowPressTimer()->IsRunning()) { |
| 1113 GetShowPressTimer()->Stop(); | 1129 GetShowPressTimer()->Stop(); |
| 1114 AppendShowPressGestureEvent(); | 1130 AppendShowPressGestureEvent(); |
| 1115 } | 1131 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1180 &GestureSequence::AppendShowPressGestureEvent); | 1196 &GestureSequence::AppendShowPressGestureEvent); |
| 1181 | 1197 |
| 1182 return true; | 1198 return true; |
| 1183 } | 1199 } |
| 1184 | 1200 |
| 1185 bool GestureSequence::TwoFingerTouchDown(const TouchEvent& event, | 1201 bool GestureSequence::TwoFingerTouchDown(const TouchEvent& event, |
| 1186 const GesturePoint& point, | 1202 const GesturePoint& point, |
| 1187 Gestures* gestures) { | 1203 Gestures* gestures) { |
| 1188 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || | 1204 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || |
| 1189 state_ == GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL || | 1205 state_ == GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL || |
| 1206 state_ == GS_SYNTHETIC_CLICK_ABORTED || | |
| 1190 state_ == GS_SCROLL); | 1207 state_ == GS_SCROLL); |
| 1191 | 1208 |
| 1192 if (state_ == GS_SCROLL) { | 1209 if (state_ == GS_SCROLL) { |
| 1193 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 1210 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, |
| 1194 0.f, 0.f); | 1211 0.f, 0.f); |
| 1195 } | 1212 } |
| 1196 second_touch_time_ = event.time_stamp(); | 1213 second_touch_time_ = event.time_stamp(); |
| 1197 return true; | 1214 return true; |
| 1198 } | 1215 } |
| 1199 | 1216 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1440 // Since a timer is running, there should be a non-NULL point. | 1457 // Since a timer is running, there should be a non-NULL point. |
| 1441 const GesturePoint* point = GetPointByPointId(0); | 1458 const GesturePoint* point = GetPointByPointId(0); |
| 1442 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), | 1459 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), |
| 1443 event.location())) { | 1460 event.location())) { |
| 1444 GetLongPressTimer()->Stop(); | 1461 GetLongPressTimer()->Stop(); |
| 1445 GetShowPressTimer()->Stop(); | 1462 GetShowPressTimer()->Stop(); |
| 1446 } | 1463 } |
| 1447 } | 1464 } |
| 1448 | 1465 |
| 1449 } // namespace ui | 1466 } // namespace ui |
| OLD | NEW |