@@ -5,7 +5,7 @@ use std::cell::Cell;
5
5
6
6
use wasm_bindgen:: prelude:: * ;
7
7
8
- use super :: { is_mobile , AppRunner , WebRunner } ;
8
+ use super :: { AppRunner , WebRunner } ;
9
9
10
10
pub struct TextAgent {
11
11
input : web_sys:: HtmlInputElement ,
@@ -22,12 +22,17 @@ impl TextAgent {
22
22
. create_element ( "input" ) ?
23
23
. dyn_into :: < web_sys:: HtmlInputElement > ( ) ?;
24
24
input. set_type ( "text" ) ;
25
+ input. set_autofocus ( true ) ;
26
+ input. set_attribute ( "autocapitalize" , "off" ) ?;
25
27
26
28
// append it to `<body>` and hide it outside of the viewport
27
29
let style = input. style ( ) ;
28
- style. set_property ( "opacity" , "0" ) ?;
30
+ style. set_property ( "background-color" , "transparent" ) ?;
31
+ style. set_property ( "border" , "none" ) ?;
32
+ style. set_property ( "outline" , "none" ) ?;
29
33
style. set_property ( "width" , "1px" ) ?;
30
34
style. set_property ( "height" , "1px" ) ?;
35
+ style. set_property ( "caret-color" , "transparent" ) ?;
31
36
style. set_property ( "position" , "absolute" ) ?;
32
37
style. set_property ( "top" , "0" ) ?;
33
38
style. set_property ( "left" , "0" ) ?;
@@ -39,6 +44,12 @@ impl TextAgent {
39
44
let input = input. clone ( ) ;
40
45
move |event : web_sys:: InputEvent , runner : & mut AppRunner | {
41
46
let text = input. value ( ) ;
47
+ // Fix android virtual keyboard Gboard
48
+ // This removes the virtual keyboard's suggestion.
49
+ if !event. is_composing ( ) {
50
+ input. blur ( ) . ok ( ) ;
51
+ input. focus ( ) . ok ( ) ;
52
+ }
42
53
// if `is_composing` is true, then user is using IME, for example: emoji, pinyin, kanji, hangul, etc.
43
54
// In that case, the browser emits both `input` and `compositionupdate` events,
44
55
// and we need to ignore the `input` event.
@@ -103,14 +114,8 @@ impl TextAgent {
103
114
& self ,
104
115
ime : Option < egui:: output:: IMEOutput > ,
105
116
canvas : & web_sys:: HtmlCanvasElement ,
117
+ zoom_factor : f32 ,
106
118
) -> Result < ( ) , JsValue > {
107
- // Mobile keyboards don't follow the text input it's writing to,
108
- // instead typically being fixed in place on the bottom of the screen,
109
- // so don't bother moving the text agent on mobile.
110
- if is_mobile ( ) {
111
- return Ok ( ( ) ) ;
112
- }
113
-
114
119
// Don't move the text agent unless the position actually changed:
115
120
if self . prev_ime_output . get ( ) == ime {
116
121
return Ok ( ( ) ) ;
@@ -119,14 +124,24 @@ impl TextAgent {
119
124
120
125
let Some ( ime) = ime else { return Ok ( ( ) ) } ;
121
126
122
- let canvas_rect = super :: canvas_content_rect ( canvas) ;
127
+ let mut canvas_rect = super :: canvas_content_rect ( canvas) ;
128
+ // Fix for safari with virtual keyboard flapping position
129
+ if is_mobile_safari ( ) {
130
+ canvas_rect. min . y = canvas. offset_top ( ) as f32 ;
131
+ }
123
132
let cursor_rect = ime. cursor_rect . translate ( canvas_rect. min . to_vec2 ( ) ) ;
124
133
125
134
let style = self . input . style ( ) ;
126
135
127
136
// This is where the IME input will point to:
128
- style. set_property ( "left" , & format ! ( "{}px" , cursor_rect. center( ) . x) ) ?;
129
- style. set_property ( "top" , & format ! ( "{}px" , cursor_rect. center( ) . y) ) ?;
137
+ style. set_property (
138
+ "left" ,
139
+ & format ! ( "{}px" , cursor_rect. center( ) . x * zoom_factor) ,
140
+ ) ?;
141
+ style. set_property (
142
+ "top" ,
143
+ & format ! ( "{}px" , cursor_rect. center( ) . y * zoom_factor) ,
144
+ ) ?;
130
145
131
146
Ok ( ( ) )
132
147
}
@@ -173,3 +188,16 @@ impl Drop for TextAgent {
173
188
self . input . remove ( ) ;
174
189
}
175
190
}
191
+
192
+ /// Returns `true` if the app is likely running on a mobile device on navigator Safari.
193
+ fn is_mobile_safari ( ) -> bool {
194
+ ( || {
195
+ let user_agent = web_sys:: window ( ) ?. navigator ( ) . user_agent ( ) . ok ( ) ?;
196
+ let is_ios = user_agent. contains ( "iPhone" )
197
+ || user_agent. contains ( "iPad" )
198
+ || user_agent. contains ( "iPod" ) ;
199
+ let is_safari = user_agent. contains ( "Safari" ) ;
200
+ Some ( is_ios && is_safari)
201
+ } ) ( )
202
+ . unwrap_or ( false )
203
+ }
0 commit comments