Skip to content

Commit b23a657

Browse files
dfaureogoffart
authored andcommitted
Hide Android selection handles when scrolled out of view
In a LineEdit with a long text, when dragging the selection to the point where the anchor scrolls out of view in the other direection, it used to keep being visible, outside the LineEdit. This commit fixes that by passing the clip rect to the java code that positions the selection handles.
1 parent 92ebe92 commit b23a657

File tree

4 files changed

+43
-13
lines changed

4 files changed

+43
-13
lines changed

internal/backends/android-activity/java/SlintAndroidJavaHelper.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,18 +243,31 @@ public void setCursorPos(int left_x, int left_y, int right_x, int right_y, int c
243243
mCursorHandle.setPosition(left_x, left_y);
244244
handleHeight = mCursorHandle.getHeight();
245245
} else if (num_handles == 2) {
246-
if (mLeftHandle == null) {
247-
mLeftHandle = new InputHandle(this, android.R.attr.textSelectHandleLeft);
246+
if (left_x != -1) {
247+
if (mLeftHandle == null) {
248+
mLeftHandle = new InputHandle(this, android.R.attr.textSelectHandleLeft);
249+
}
250+
mLeftHandle.setPosition(left_x, left_y);
251+
handleHeight = mLeftHandle.getHeight();
252+
} else {
253+
if (mLeftHandle != null) {
254+
mLeftHandle.hide();
255+
}
248256
}
249-
if (mRightHandle == null) {
250-
mRightHandle = new InputHandle(this, android.R.attr.textSelectHandleRight);
257+
if (right_x != -1) {
258+
if (mRightHandle == null) {
259+
mRightHandle = new InputHandle(this, android.R.attr.textSelectHandleRight);
260+
}
261+
mRightHandle.setPosition(right_x, right_y);
262+
handleHeight = mRightHandle.getHeight();
263+
} else {
264+
if (mRightHandle != null) {
265+
mRightHandle.hide();
266+
}
251267
}
252268
if (mCursorHandle != null) {
253269
mCursorHandle.hide();
254270
}
255-
mLeftHandle.setPosition(left_x, left_y);
256-
mRightHandle.setPosition(right_x, right_y);
257-
handleHeight = mLeftHandle.getHeight();
258271
showActionMenu();
259272
} else {
260273
if (mCursorHandle != null) {

internal/backends/android-activity/javahelper.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,22 @@ impl JavaHelper {
194194
};
195195
env.delete_local_ref(class_it)?;
196196

197-
let cur_origin = data.cursor_rect_origin.to_physical(scale_factor);
197+
let cur_origin = data.cursor_rect_origin.to_physical(scale_factor); // i32
198198
let anchor_origin = data.anchor_point.to_physical(scale_factor);
199199
let cur_size = data.cursor_rect_size.to_physical(scale_factor);
200200

201+
let cur_visible = data.clip_rect.map_or(true, |r| {
202+
r.contains(i_slint_core::lengths::logical_point_from_api(data.cursor_rect_origin))
203+
});
204+
let anchor_visible = data.clip_rect.map_or(true, |r| {
205+
r.contains(i_slint_core::lengths::logical_point_from_api(data.anchor_point))
206+
});
207+
201208
// Add 2*cur_size.width to the y position to be a bit under the cursor
202209
let cursor_height = cur_size.height as i32 + 2 * cur_size.width as i32;
203-
let cur_x = cur_origin.x + cur_size.width as i32 / 2;
210+
let cur_x = if cur_visible { cur_origin.x + cur_size.width as i32 / 2 } else { -1 };
204211
let cur_y = cur_origin.y + cursor_height;
205-
let anchor_x = anchor_origin.x;
212+
let anchor_x = if anchor_visible { anchor_origin.x } else { -1 };
206213
let anchor_y = anchor_origin.y + 2 * cur_size.width as i32;
207214

208215
env.call_method(

internal/core/items/text.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,15 +1505,22 @@ impl TextInput {
15051505
let cursor_relative =
15061506
self.cursor_rect_for_byte_offset(cursor_position, window_adapter, self_rc);
15071507
let geometry = self_rc.geometry();
1508-
let origin = self_rc.map_to_window(geometry.origin).to_vector();
1508+
let origin = self_rc.map_to_window(geometry.origin);
1509+
let origin_vector = origin.to_vector();
15091510
let cursor_rect_origin =
1510-
crate::api::LogicalPosition::from_euclid(cursor_relative.origin + origin);
1511+
crate::api::LogicalPosition::from_euclid(cursor_relative.origin + origin_vector);
15111512
let cursor_rect_size = crate::api::LogicalSize::from_euclid(cursor_relative.size);
15121513
let anchor_point = crate::api::LogicalPosition::from_euclid(
15131514
self.cursor_rect_for_byte_offset(anchor_position, window_adapter, self_rc).origin
1514-
+ origin
1515+
+ origin_vector
15151516
+ cursor_relative.size,
15161517
);
1518+
let maybe_parent =
1519+
self_rc.parent_item(crate::item_tree::ParentItemTraversalMode::StopAtPopups);
1520+
let clip_rect = maybe_parent.map(|parent| {
1521+
let geom = parent.geometry();
1522+
LogicalRect::new(parent.map_to_window(geom.origin), geom.size)
1523+
});
15171524

15181525
InputMethodProperties {
15191526
text,
@@ -1525,6 +1532,7 @@ impl TextInput {
15251532
cursor_rect_size,
15261533
anchor_point,
15271534
input_type: self.input_type(),
1535+
clip_rect,
15281536
}
15291537
}
15301538

internal/core/window.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ pub struct InputMethodProperties {
293293
pub anchor_point: LogicalPosition,
294294
/// The type of input for the text edit.
295295
pub input_type: InputType,
296+
/// The clip rect in window coordinates
297+
pub clip_rect: Option<LogicalRect>,
296298
}
297299

298300
/// This struct describes layout constraints of a resizable element, such as a window.

0 commit comments

Comments
 (0)