From 672d86d86c743f7da38f4e1d0d4d1a7af61002e5 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 07:30:10 -0700 Subject: [PATCH 01/15] Start stubbing out IMEManager --- src/Model/IMEManager.re | 4 ++++ src/Model/Oni_Model.re | 1 + 2 files changed, 5 insertions(+) create mode 100644 src/Model/IMEManager.re diff --git a/src/Model/IMEManager.re b/src/Model/IMEManager.re new file mode 100644 index 0000000000..e06823807c --- /dev/null +++ b/src/Model/IMEManager.re @@ -0,0 +1,4 @@ + +let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = (_state) => { + None; +} diff --git a/src/Model/Oni_Model.re b/src/Model/Oni_Model.re index f3984a51ba..72284b4123 100644 --- a/src/Model/Oni_Model.re +++ b/src/Model/Oni_Model.re @@ -17,6 +17,7 @@ module EditorVisibleRanges = EditorVisibleRanges; module Focus = Focus; module FocusManager = FocusManager; module GlobalCommands = GlobalCommands; +module IMEManager = IMEManager; module Lifecycle = Lifecycle; module Quickmenu = Quickmenu; module FilterJob = FilterJob; From 4a34f585754c73edc0f034ed05881299b40e3635 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 07:53:21 -0700 Subject: [PATCH 02/15] Wire up IME model --- src/Feature/Input/Feature_Input.re | 32 +++++++++++++++++++------ src/Feature/Input/Feature_Input.rei | 2 +- src/Feature/Input/IME.re | 37 +++++++++++++++++++++++++++++ src/Model/IMEManager.re | 16 +++++++++++-- src/Store/StoreThread.re | 4 +++- 5 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 src/Feature/Input/IME.re diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index 2f8d940cda..2eaf424dcf 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -198,6 +198,7 @@ type command = [@deriving show] type msg = | Command(command) + | IME(IME.msg) | KeybindingsUpdated([@opaque] list(Schema.resolvedKeybinding)) | KeybindingsReloaded({ bindings: [@opaque] list(Schema.resolvedKeybinding), @@ -227,6 +228,7 @@ type model = { // such that we can provide a unique id for the timer to flush on timeout. inputTick: int, keybindingLoader: KeybindingsLoader.t, + ime: IME.t, }; type uniqueId = InputStateMachine.uniqueId; @@ -280,6 +282,8 @@ let initial = (~loader, keybindings) => { keyDisplayer: None, inputTick: 0, keybindingLoader: loader, + + ime: IME.initial, }; }; @@ -561,6 +565,12 @@ let update = (msg, model) => { {...model, keyDisplayer: Some(KeyDisplayer.initial)}, Nothing, ) + + | IME(imeMsg) => ( + {...model, ime: IME.update(imeMsg, model.ime)}, + Nothing + ) + | VimMap(mapping) => // When parsing Vim-style mappings, don't require a shift key. // In other words - characters like 'J' should resolve to 'Shift+j' @@ -692,8 +702,9 @@ module Commands = { let sub = ( + ~imeBoundingArea as _, ~config, - {keyDisplayer, inputTick, inputStateMachine, keybindingLoader, _}, + {keyDisplayer, inputTick, inputStateMachine, keybindingLoader, ime, _}, ) => { let keyDisplayerSub = switch (keyDisplayer) { @@ -702,6 +713,8 @@ let sub = KeyDisplayer.sub(kd) |> Isolinear.Sub.map(msg => KeyDisplayer(msg)) }; + let imeSub = IME.sub(ime); + let timeoutSub = switch (Configuration.timeout.get(config)) { | NoTimeout => Isolinear.Sub.none @@ -724,7 +737,7 @@ let sub = KeybindingsReloaded({bindings, errors}) }); - [keyDisplayerSub, timeoutSub, loaderSub] |> Isolinear.Sub.batch; + [keyDisplayerSub, imeSub, timeoutSub, loaderSub] |> Isolinear.Sub.batch; }; module ContextKeys = { @@ -761,11 +774,16 @@ module View = { module Overlay = { let make = (~input, ~uiFont, ~bottom, ~right, ()) => { - switch (input.keyDisplayer) { - | None => React.empty - | Some(keyDisplayer) => - - }; + let keyDisplayerView = + switch (input.keyDisplayer) { + | None => React.empty + | Some(keyDisplayer) => + + }; + + let imeView = ; + + [keyDisplayerView, imeView] |> React.listToElement; }; }; diff --git a/src/Feature/Input/Feature_Input.rei b/src/Feature/Input/Feature_Input.rei index cb2b8323e9..512461e0f9 100644 --- a/src/Feature/Input/Feature_Input.rei +++ b/src/Feature/Input/Feature_Input.rei @@ -161,7 +161,7 @@ let update: (msg, model) => (model, outmsg); // SUBSCRIPTION -let sub: (~config: Config.resolver, model) => Isolinear.Sub.t(msg); +let sub: (~imeBoundingArea: option(Revery.Math.BoundingBox2d.t), ~config: Config.resolver, model) => Isolinear.Sub.t(msg); // CONTRIBUTIONS diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re new file mode 100644 index 0000000000..13cdba368a --- /dev/null +++ b/src/Feature/Input/IME.re @@ -0,0 +1,37 @@ +module BoundingBox2d = Revery.Math.BoundingBox2d; + +type t = {currentRect: option(BoundingBox2d.t)}; + +let initial = { + // currentRect: None + currentRect: Some(BoundingBox2d.create(10., 10., 50., 50.)), +}; + +[@deriving show] +type msg = unit; + +let update = (msg, model) => model; + +let sub = _ime => Isolinear.Sub.none; + +module View = { + open Revery; + open Revery.UI; + let make = (~ime, ()) => { + switch (ime.currentRect) { + | None => React.empty + | Some(bbox) => + let (x, y, w, h) = BoundingBox2d.getBounds(bbox); + int_of_float), + left(x |> int_of_float), + width(w |> int_of_float), + height(h |> int_of_float), + backgroundColor(Revery.Colors.red), + ] + />; + }; + }; +}; diff --git a/src/Model/IMEManager.re b/src/Model/IMEManager.re index e06823807c..f4d4376125 100644 --- a/src/Model/IMEManager.re +++ b/src/Model/IMEManager.re @@ -1,4 +1,16 @@ -let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = (_state) => { - None; +let rect = (x, y, width, height) => { + Revery.Math.BoundingBox2d.create( + x |> float, + y |> float, + width |> float, + height |> float) } + +let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = (state) => { + switch (FocusManager.current(state)) { + | Editor => Some(rect(50, 50, 75, 75)) + + | _ => Some(rect(100, 100, 100, 100)) + }; +}; diff --git a/src/Store/StoreThread.re b/src/Store/StoreThread.re index 2f71a17562..be8370bb03 100644 --- a/src/Store/StoreThread.re +++ b/src/Store/StoreThread.re @@ -404,9 +404,11 @@ let start = ) |> Isolinear.Sub.batch; + let imeBoundingArea = Oni_Model.IMEManager.textArea(state); + let inputSubscription = state.input - |> Feature_Input.sub(~config) + |> Feature_Input.sub(~imeBoundingArea, ~config) |> Isolinear.Sub.map(msg => Model.Actions.Input(msg)); let notificationSub = From 4a23ec88c603a187b6c624ab6ce7fa5904b21ca1 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 08:09:01 -0700 Subject: [PATCH 03/15] More IME hacking --- src/Core/IME.re | 27 ++++++++++++++++++++++ src/Core/Oni_Core.re | 1 + src/Feature/Input/Feature_Input.re | 11 +++++---- src/Feature/Input/IME.re | 31 ++++++++++++++++++++++--- src/Model/IMEManager.re | 37 +++++++++++++++++++----------- src/Model/Oni_Model.re | 1 - src/Store/StoreThread.re | 2 +- 7 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 src/Core/IME.re diff --git a/src/Core/IME.re b/src/Core/IME.re new file mode 100644 index 0000000000..8edb6438fc --- /dev/null +++ b/src/Core/IME.re @@ -0,0 +1,27 @@ +let rect = (x, y, width, height) => { + Revery.Math.BoundingBox2d.create( + x |> float, + y |> float, + width |> float, + height |> float, + ); +}; + +module MutableState = { + let current = ref(None); +}; + +let reset = () => MutableState.current := None; + +let set = maybeBbox => MutableState.current := Some(bbox); + +let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = + state => { + ignore(state); + MutableStae.current^; + // switch (FocusManager.current(state)) { + // | Editor => Some(rect(50, 50, 75, 75)) + // | Extensions => None + // | _ => Some(rect(100, 100, 100, 100)) + // }; + }; diff --git a/src/Core/Oni_Core.re b/src/Core/Oni_Core.re index e95c7671db..0ff4622229 100644 --- a/src/Core/Oni_Core.re +++ b/src/Core/Oni_Core.re @@ -30,6 +30,7 @@ module FontLigatures = FontLigatures; module FontSmoothing = FontSmoothing; module FontMeasurementCache = FontMeasurementCache; module Glob = Glob; +module IME = IME; module IconTheme = IconTheme; module Indentation = Indentation; module IndentationConverter = IndentationConverter; diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index 2eaf424dcf..872601927f 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -567,9 +567,9 @@ let update = (msg, model) => { ) | IME(imeMsg) => ( - {...model, ime: IME.update(imeMsg, model.ime)}, - Nothing - ) + {...model, ime: IME.update(imeMsg, model.ime)}, + Nothing, + ) | VimMap(mapping) => // When parsing Vim-style mappings, don't require a shift key. @@ -702,7 +702,7 @@ module Commands = { let sub = ( - ~imeBoundingArea as _, + ~imeBoundingArea, ~config, {keyDisplayer, inputTick, inputStateMachine, keybindingLoader, ime, _}, ) => { @@ -713,7 +713,8 @@ let sub = KeyDisplayer.sub(kd) |> Isolinear.Sub.map(msg => KeyDisplayer(msg)) }; - let imeSub = IME.sub(ime); + let imeSub = + IME.sub(~imeBoundingArea, ime) |> Isolinear.Sub.map(msg => IME(msg)); let timeoutSub = switch (Configuration.timeout.get(config)) { diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 13cdba368a..5ffb81a593 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -1,3 +1,6 @@ +open Oni_Core; +open Utility; + module BoundingBox2d = Revery.Math.BoundingBox2d; type t = {currentRect: option(BoundingBox2d.t)}; @@ -8,11 +11,33 @@ let initial = { }; [@deriving show] -type msg = unit; +type msg = + | StopTextInput + | TextInputAvailable([@opaque] BoundingBox2d.t); -let update = (msg, model) => model; +let update = (msg, model) => + switch (msg) { + | StopTextInput => {currentRect: None} + | TextInputAvailable(bbox) => {currentRect: Some(bbox)} + }; -let sub = _ime => Isolinear.Sub.none; +let sub = (~imeBoundingArea, ime) => { + switch (imeBoundingArea) { + | None => + SubEx.value(~uniqueId="Feature_Input.IME.noTextInput", StopTextInput) + | Some(bbox) => + let (x, y, width, height) = BoundingBox2d.getBounds(bbox); + let uniqueId = + Printf.sprintf( + "Feature_Input.IME.textInputChanged-%f-%f-%f-%f", + x, + y, + width, + height, + ); + SubEx.value(~uniqueId, TextInputAvailable(bbox)); + }; +}; module View = { open Revery; diff --git a/src/Model/IMEManager.re b/src/Model/IMEManager.re index f4d4376125..8edb6438fc 100644 --- a/src/Model/IMEManager.re +++ b/src/Model/IMEManager.re @@ -1,16 +1,27 @@ - let rect = (x, y, width, height) => { - Revery.Math.BoundingBox2d.create( - x |> float, - y |> float, - width |> float, - height |> float) -} - -let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = (state) => { - switch (FocusManager.current(state)) { - | Editor => Some(rect(50, 50, 75, 75)) + Revery.Math.BoundingBox2d.create( + x |> float, + y |> float, + width |> float, + height |> float, + ); +}; - | _ => Some(rect(100, 100, 100, 100)) - }; +module MutableState = { + let current = ref(None); }; + +let reset = () => MutableState.current := None; + +let set = maybeBbox => MutableState.current := Some(bbox); + +let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = + state => { + ignore(state); + MutableStae.current^; + // switch (FocusManager.current(state)) { + // | Editor => Some(rect(50, 50, 75, 75)) + // | Extensions => None + // | _ => Some(rect(100, 100, 100, 100)) + // }; + }; diff --git a/src/Model/Oni_Model.re b/src/Model/Oni_Model.re index 72284b4123..f3984a51ba 100644 --- a/src/Model/Oni_Model.re +++ b/src/Model/Oni_Model.re @@ -17,7 +17,6 @@ module EditorVisibleRanges = EditorVisibleRanges; module Focus = Focus; module FocusManager = FocusManager; module GlobalCommands = GlobalCommands; -module IMEManager = IMEManager; module Lifecycle = Lifecycle; module Quickmenu = Quickmenu; module FilterJob = FilterJob; diff --git a/src/Store/StoreThread.re b/src/Store/StoreThread.re index be8370bb03..dc17451ec5 100644 --- a/src/Store/StoreThread.re +++ b/src/Store/StoreThread.re @@ -404,7 +404,7 @@ let start = ) |> Isolinear.Sub.batch; - let imeBoundingArea = Oni_Model.IMEManager.textArea(state); + let imeBoundingArea = IME.textArea(); let inputSubscription = state.input From 9b7cdca37d92764d52ab0f5193c66c40b2c92cb9 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 08:17:53 -0700 Subject: [PATCH 04/15] Alternate approach --- src/Components/InputText/View.re | 9 ++++++++- src/Core/IME.re | 14 +++++++------- src/Feature/Input/Feature_Input.re | 2 ++ src/Model/IMEManager.re | 27 --------------------------- src/Store/StoreThread.re | 2 +- 5 files changed, 18 insertions(+), 36 deletions(-) delete mode 100644 src/Model/IMEManager.re diff --git a/src/Components/InputText/View.re b/src/Components/InputText/View.re index 0a14eca1cf..15d6345d6d 100644 --- a/src/Components/InputText/View.re +++ b/src/Components/InputText/View.re @@ -165,6 +165,7 @@ let%component make = (), ) => { let%hook textRef = Hooks.ref(None); + let%hook textBoundingBox = Hooks.ref(None); let%hook scrollOffset = Hooks.ref(0); let%hook () = @@ -344,9 +345,15 @@ let%component make = fontSize />; + switch (textBoundingBox^) { + | Some(bbox) when isFocused => Oni_Core.IME.set(Some(bbox)) + | _ => () + }; + + style={Styles.box(~shadowOpacity, ~theme, ~focused=model.isFocused)} + onBoundingBoxChanged={bbox => {textBoundingBox := Some(bbox)}}> diff --git a/src/Core/IME.re b/src/Core/IME.re index 8edb6438fc..15d6d8a462 100644 --- a/src/Core/IME.re +++ b/src/Core/IME.re @@ -1,3 +1,4 @@ +module BoundingBox2d = Revery.Math.BoundingBox2d; let rect = (x, y, width, height) => { Revery.Math.BoundingBox2d.create( x |> float, @@ -8,20 +9,19 @@ let rect = (x, y, width, height) => { }; module MutableState = { - let current = ref(None); + let current: ref(option(BoundingBox2d.t)) = ref(None); }; let reset = () => MutableState.current := None; -let set = maybeBbox => MutableState.current := Some(bbox); +let set = maybeBbox => MutableState.current := maybeBbox; -let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = - state => { - ignore(state); - MutableStae.current^; +let textArea = _state => { + MutableState.current // switch (FocusManager.current(state)) { // | Editor => Some(rect(50, 50, 75, 75)) // | Extensions => None // | _ => Some(rect(100, 100, 100, 100)) + ^; // }; - }; +}; diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index 872601927f..d8164548c5 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -1,5 +1,7 @@ +module InnerIME = IME; open Oni_Core; open Utility; +module IME = InnerIME; module Log = (val Log.withNamespace("Oni2.Feature.Input")); module KeybindingsLoader = KeybindingsLoader; diff --git a/src/Model/IMEManager.re b/src/Model/IMEManager.re deleted file mode 100644 index 8edb6438fc..0000000000 --- a/src/Model/IMEManager.re +++ /dev/null @@ -1,27 +0,0 @@ -let rect = (x, y, width, height) => { - Revery.Math.BoundingBox2d.create( - x |> float, - y |> float, - width |> float, - height |> float, - ); -}; - -module MutableState = { - let current = ref(None); -}; - -let reset = () => MutableState.current := None; - -let set = maybeBbox => MutableState.current := Some(bbox); - -let textArea: State.t => option(Revery.Math.BoundingBox2d.t) = - state => { - ignore(state); - MutableStae.current^; - // switch (FocusManager.current(state)) { - // | Editor => Some(rect(50, 50, 75, 75)) - // | Extensions => None - // | _ => Some(rect(100, 100, 100, 100)) - // }; - }; diff --git a/src/Store/StoreThread.re b/src/Store/StoreThread.re index dc17451ec5..e85d5774a4 100644 --- a/src/Store/StoreThread.re +++ b/src/Store/StoreThread.re @@ -404,7 +404,7 @@ let start = ) |> Isolinear.Sub.batch; - let imeBoundingArea = IME.textArea(); + let imeBoundingArea = Oni_Core.IME.textArea(); let inputSubscription = state.input From c59425a469fec6c220468254e6cba63a3d8128d1 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 08:21:53 -0700 Subject: [PATCH 05/15] Set up IME positioning --- src/Components/InputText/View.re | 4 +++- src/Feature/Input/IME.re | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Components/InputText/View.re b/src/Components/InputText/View.re index 15d6345d6d..6a97ae4470 100644 --- a/src/Components/InputText/View.re +++ b/src/Components/InputText/View.re @@ -346,7 +346,9 @@ let%component make = />; switch (textBoundingBox^) { - | Some(bbox) when isFocused => Oni_Core.IME.set(Some(bbox)) + | Some(bbox) when isFocused => + prerr_endline("BBOX: " ++ Revery.Math.BoundingBox2d.toString(bbox)); + Oni_Core.IME.set(Some(bbox)); | _ => () }; diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 5ffb81a593..2b46341a46 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -52,8 +52,8 @@ module View = { position(`Absolute), top(y |> int_of_float), left(x |> int_of_float), - width(w |> int_of_float), - height(h |> int_of_float), + width(w -. x |> int_of_float), + height(h -. y |> int_of_float), backgroundColor(Revery.Colors.red), ] />; From c0da1095156c86b2f1a0f3f6d8a99c772149d473 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 08:55:18 -0700 Subject: [PATCH 06/15] More tweaks --- src/Feature/Input/IME.re | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 2b46341a46..ed69d26586 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -35,6 +35,9 @@ let sub = (~imeBoundingArea, ime) => { width, height, ); + // HACK: + + Sdl2.TextInput.setInputRect(50, 50, 50, 50); SubEx.value(~uniqueId, TextInputAvailable(bbox)); }; }; From 6e14b53dd2866e2e29d0b5a57db6415927f7f07e Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 09:19:02 -0700 Subject: [PATCH 07/15] Wire up IME position for editor --- src/Feature/Editor/EditorSurface.re | 18 ++++++++++++++++++ src/Feature/Input/IME.re | 2 +- src/Service/IME/Service_IME.re | 13 +++++++++++++ src/Service/IME/Service_IME.rei | 19 +++++++++++++++++++ src/Service/IME/dune | 6 ++++++ src/bin_editor/Oni2_editor.re | 6 +++++- 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/Service/IME/Service_IME.re create mode 100644 src/Service/IME/Service_IME.rei create mode 100644 src/Service/IME/dune diff --git a/src/Feature/Editor/EditorSurface.re b/src/Feature/Editor/EditorSurface.re index fdb42af92f..cca4d34191 100644 --- a/src/Feature/Editor/EditorSurface.re +++ b/src/Feature/Editor/EditorSurface.re @@ -217,6 +217,8 @@ let%component make = let cursorPosition = Editor.getPrimaryCursor(editor); + + let layout = Editor.getLayout(editor); let matchingPairCheckPosition = @@ -271,6 +273,22 @@ let%component make = diffMarkers />; + let (pixelPosition: PixelPosition.t, _) = Editor.bufferCharacterPositionToPixel( + ~position=cursorPosition, + editor + ); + let left = Editor.pixelX(editor) +. pixelPosition.x +. gutterWidth; + let top = Editor.pixelY(editor) +. pixelPosition.y; + if (isActiveSplit && Vim.Mode.isInsert(mode)) { + + Oni_Core.IME.set(Some(Revery.Math.BoundingBox2d.create( + left, + top, + left+.20., + top+.25., + ))); + } + let hoverPopup = { let maybeHover = Feature_LanguageSupport.Hover.Popup.make( diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index ed69d26586..c4455ecfee 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -57,7 +57,7 @@ module View = { left(x |> int_of_float), width(w -. x |> int_of_float), height(h -. y |> int_of_float), - backgroundColor(Revery.Colors.red), + backgroundColor(Revery.Color.rgba(1.0, 0., 0., 0.5)), ] />; }; diff --git a/src/Service/IME/Service_IME.re b/src/Service/IME/Service_IME.re new file mode 100644 index 0000000000..2f052da876 --- /dev/null +++ b/src/Service/IME/Service_IME.re @@ -0,0 +1,13 @@ +open Revery; +open Oni_Core; + +module Sub = { + type edit = { + text: string, + start: int, + length: int, + }; + + let ime = + (~window as _, ~compositionStart, ~compositionEdit, ~compositionEnd) => Isolinear.Sub.none; +}; diff --git a/src/Service/IME/Service_IME.rei b/src/Service/IME/Service_IME.rei new file mode 100644 index 0000000000..41b2ce58f4 --- /dev/null +++ b/src/Service/IME/Service_IME.rei @@ -0,0 +1,19 @@ +open Revery; +open Oni_Core; + +module Sub: { + type edit = { + text: string, + start: int, + length: int, + }; + + let ime: + ( + ~window: Window.t, + ~compositionStart: 'msg, + ~compositionEdit: edit => 'msg, + ~compositionEnd: 'msg + ) => + Isolinear.Sub.t('msg); +}; diff --git a/src/Service/IME/dune b/src/Service/IME/dune new file mode 100644 index 0000000000..dd1e0f0253 --- /dev/null +++ b/src/Service/IME/dune @@ -0,0 +1,6 @@ +(library + (name Service_IME) + (public_name Oni2.service.ime) + (libraries Oni2.editor-core-types Oni2.core Revery isolinear base) + (preprocess + (pps ppx_let ppx_deriving.show))) diff --git a/src/bin_editor/Oni2_editor.re b/src/bin_editor/Oni2_editor.re index dc561a64d7..1a5d6c8840 100644 --- a/src/bin_editor/Oni2_editor.re +++ b/src/bin_editor/Oni2_editor.re @@ -391,7 +391,11 @@ switch (eff) { let update = UI.start( - ~onBeforeRender=() => Feature_Sneak.View.reset(), + ~onBeforeRender={ + () => { + Feature_Sneak.View.reset(); + Oni_Core.IME.reset(); + }}, window, , ); From bf103a1e50246753be6fb1aae1d0cf356295ef27 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 11:23:29 -0700 Subject: [PATCH 08/15] Wire up Service_IME effect --- src/Feature/Editor/EditorSurface.re | 22 +++++++---------- src/Feature/Input/Feature_Input.re | 35 +++++++++++++++------------- src/Feature/Input/Feature_Input.rei | 33 +++++++++++++++----------- src/Feature/Input/IME.re | 11 +++++---- src/Feature/Input/dune | 4 ++-- src/Feature/Terminal/TerminalView.re | 16 ++++++++++++- src/Service/IME/Service_IME.re | 17 ++++++++++++++ src/Service/IME/Service_IME.rei | 4 ++++ src/Store/Features.re | 2 ++ src/bin_editor/Oni2_editor.re | 10 ++++---- 10 files changed, 99 insertions(+), 55 deletions(-) diff --git a/src/Feature/Editor/EditorSurface.re b/src/Feature/Editor/EditorSurface.re index cca4d34191..69625ddbae 100644 --- a/src/Feature/Editor/EditorSurface.re +++ b/src/Feature/Editor/EditorSurface.re @@ -217,8 +217,6 @@ let%component make = let cursorPosition = Editor.getPrimaryCursor(editor); - - let layout = Editor.getLayout(editor); let matchingPairCheckPosition = @@ -273,21 +271,17 @@ let%component make = diffMarkers />; - let (pixelPosition: PixelPosition.t, _) = Editor.bufferCharacterPositionToPixel( - ~position=cursorPosition, - editor - ); + let (pixelPosition: PixelPosition.t, _) = + Editor.bufferCharacterPositionToPixel(~position=cursorPosition, editor); let left = Editor.pixelX(editor) +. pixelPosition.x +. gutterWidth; let top = Editor.pixelY(editor) +. pixelPosition.y; if (isActiveSplit && Vim.Mode.isInsert(mode)) { - - Oni_Core.IME.set(Some(Revery.Math.BoundingBox2d.create( - left, - top, - left+.20., - top+.25., - ))); - } + Oni_Core.IME.set( + Some( + Revery.Math.BoundingBox2d.create(left, top, left +. 20., top +. 25.), + ), + ); + }; let hoverPopup = { let maybeHover = diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index d8164548c5..88a4d3bf32 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -170,18 +170,6 @@ module Configuration = { // MSG -type outmsg = - | Nothing - | DebugInputShown - | ErrorNotifications(list(string)) - | MapParseError({ - fromKeys: string, - toKeys: string, - error: string, - }) - | OpenFile(FpExp.t(FpExp.absolute)) - | TimedOut; - type execute = InputStateMachine.execute = | NamedCommand({ @@ -214,6 +202,19 @@ type msg = | KeyDisplayer([@opaque] KeyDisplayer.msg) | Timeout; +type outmsg = + | Nothing + | DebugInputShown + | Effect(Isolinear.Effect.t(msg)) + | ErrorNotifications(list(string)) + | MapParseError({ + fromKeys: string, + toKeys: string, + error: string, + }) + | OpenFile(FpExp.t(FpExp.absolute)) + | TimedOut; + module Msg = { let keybindingsUpdated = keybindings => KeybindingsUpdated(keybindings); let vimMap = mapping => VimMap(mapping); @@ -568,10 +569,12 @@ let update = (msg, model) => { Nothing, ) - | IME(imeMsg) => ( - {...model, ime: IME.update(imeMsg, model.ime)}, - Nothing, - ) + | IME(imeMsg) => + let (ime', imeEffect) = IME.update(imeMsg, model.ime); + ( + {...model, ime: ime'}, + Effect(imeEffect |> Isolinear.Effect.map(msg => IME(msg))), + ); | VimMap(mapping) => // When parsing Vim-style mappings, don't require a shift key. diff --git a/src/Feature/Input/Feature_Input.rei b/src/Feature/Input/Feature_Input.rei index 512461e0f9..d2b0983f77 100644 --- a/src/Feature/Input/Feature_Input.rei +++ b/src/Feature/Input/Feature_Input.rei @@ -4,18 +4,6 @@ open EditorInput; // TODO: Move to Service_Input module ReveryKeyConverter = ReveryKeyConverter; -type outmsg = - | Nothing - | DebugInputShown - | ErrorNotifications(list(string)) - | MapParseError({ - fromKeys: string, - toKeys: string, - error: string, - }) - | OpenFile(FpExp.t(FpExp.absolute)) - | TimedOut; - [@deriving show] type command; @@ -73,6 +61,19 @@ module KeybindingsLoader: { [@deriving show] type msg; +type outmsg = + | Nothing + | DebugInputShown + | Effect(Isolinear.Effect.t(msg)) + | ErrorNotifications(list(string)) + | MapParseError({ + fromKeys: string, + toKeys: string, + error: string, + }) + | OpenFile(FpExp.t(FpExp.absolute)) + | TimedOut; + module Msg: { let keybindingsUpdated: list(Schema.resolvedKeybinding) => msg; let vimMap: Vim.Mapping.t => msg; @@ -161,7 +162,13 @@ let update: (msg, model) => (model, outmsg); // SUBSCRIPTION -let sub: (~imeBoundingArea: option(Revery.Math.BoundingBox2d.t), ~config: Config.resolver, model) => Isolinear.Sub.t(msg); +let sub: + ( + ~imeBoundingArea: option(Revery.Math.BoundingBox2d.t), + ~config: Config.resolver, + model + ) => + Isolinear.Sub.t(msg); // CONTRIBUTIONS diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index c4455ecfee..1a9d2380f1 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -15,10 +15,15 @@ type msg = | StopTextInput | TextInputAvailable([@opaque] BoundingBox2d.t); +type outmsg = Isolinear.Effect.t(msg); + let update = (msg, model) => switch (msg) { - | StopTextInput => {currentRect: None} - | TextInputAvailable(bbox) => {currentRect: Some(bbox)} + | StopTextInput => ({currentRect: None}, Isolinear.Effect.none) + | TextInputAvailable(bbox) => ( + {currentRect: Some(bbox)}, + Service_IME.Effects.setIMEPosition(bbox), + ) }; let sub = (~imeBoundingArea, ime) => { @@ -35,9 +40,7 @@ let sub = (~imeBoundingArea, ime) => { width, height, ); - // HACK: - Sdl2.TextInput.setInputRect(50, 50, 50, 50); SubEx.value(~uniqueId, TextInputAvailable(bbox)); }; }; diff --git a/src/Feature/Input/dune b/src/Feature/Input/dune index 61b4f758d0..0dbb3d4b85 100644 --- a/src/Feature/Input/dune +++ b/src/Feature/Input/dune @@ -2,7 +2,7 @@ (name Feature_Input) (public_name Oni2.feature.input) (inline_tests) - (libraries Oni2.core Oni2.feature.commands Oni2.service.time EditorInput - Revery isolinear base Oni2.KeyboardLayout) + (libraries Oni2.core Oni2.feature.commands Oni2.service.ime + Oni2.service.time EditorInput Revery isolinear base Oni2.KeyboardLayout) (preprocess (pps brisk-reconciler.ppx ppx_let ppx_deriving.show ppx_inline_test))) diff --git a/src/Feature/Terminal/TerminalView.re b/src/Feature/Terminal/TerminalView.re index a309f58dbc..daef221e3d 100644 --- a/src/Feature/Terminal/TerminalView.re +++ b/src/Feature/Terminal/TerminalView.re @@ -48,6 +48,8 @@ module Terminal = { let%hook lastDimensions = Hooks.ref(None); + let%hook lastBoundingBox = Hooks.ref(None); + // When the terminal id changes, we need to make sure we're dispatching the resized // event, too. The ideal fix would be to have this component 'keyed' on the `terminal.id` // but since we don't have the concept of a key prop, this `If` handler will be triggered @@ -67,6 +69,15 @@ module Terminal = { let Service_Font.{fontSize, smoothing, _} = font; + let onBoundingBoxChanged = bbox => { + lastBoundingBox := Some(bbox); + }; + + switch (lastBoundingBox^) { + | Some(bbox) when isActive => Oni_Core.IME.set(Some(bbox)) + | _ => () + }; + let onDimensionsChanged = ( {height, width, _}: Revery.UI.NodeEvents.DimensionsChangedEventParams.t, @@ -104,7 +115,10 @@ module Terminal = { screen, ); }; - + element ; }; diff --git a/src/Service/IME/Service_IME.re b/src/Service/IME/Service_IME.re index 2f052da876..c763543988 100644 --- a/src/Service/IME/Service_IME.re +++ b/src/Service/IME/Service_IME.re @@ -1,6 +1,23 @@ open Revery; open Oni_Core; +module BoundingBox2d = Revery.Math.BoundingBox2d; + +module Effects = { + let setIMEPosition: BoundingBox2d.t => Isolinear.Effect.t(_) = + bbox => { + Isolinear.Effect.create(~name="Service_IME.Effects.setImePosition", () => { + let (x0, y0, x1, y1) = BoundingBox2d.getBounds(bbox); + Sdl2.TextInput.setInputRect( + x0 |> int_of_float, + y0 |> int_of_float, + x1 -. x0 |> int_of_float, + y1 -. y0 |> int_of_float, + ); + }); + }; +}; + module Sub = { type edit = { text: string, diff --git a/src/Service/IME/Service_IME.rei b/src/Service/IME/Service_IME.rei index 41b2ce58f4..d93101c9d5 100644 --- a/src/Service/IME/Service_IME.rei +++ b/src/Service/IME/Service_IME.rei @@ -1,6 +1,10 @@ open Revery; open Oni_Core; +module Effects: { + let setIMEPosition: Math.BoundingBox2d.t => Isolinear.Effect.t(_); +}; + module Sub: { type edit = { text: string, diff --git a/src/Store/Features.re b/src/Store/Features.re index 497d21ce45..ab4e359c7d 100644 --- a/src/Store/Features.re +++ b/src/Store/Features.re @@ -654,6 +654,8 @@ let update = | Nothing => Isolinear.Effect.none | DebugInputShown => Internal.openFileEffect("oni://DebugInput") + | Effect(eff) => eff |> Isolinear.Effect.map(msg => Input(msg)) + | ErrorNotifications(errorMessages) => errorMessages |> List.map(msg => Internal.notificationEffect(~kind=Error, msg)) diff --git a/src/bin_editor/Oni2_editor.re b/src/bin_editor/Oni2_editor.re index 1a5d6c8840..1e25252460 100644 --- a/src/bin_editor/Oni2_editor.re +++ b/src/bin_editor/Oni2_editor.re @@ -391,11 +391,11 @@ switch (eff) { let update = UI.start( - ~onBeforeRender={ - () => { - Feature_Sneak.View.reset(); - Oni_Core.IME.reset(); - }}, + ~onBeforeRender= + () => { + Feature_Sneak.View.reset(); + Oni_Core.IME.reset(); + }, window, , ); From 4b2b385b246922491cdad60ffd0d57bb4794bd28 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 11:55:06 -0700 Subject: [PATCH 09/15] Add configuration setting to gate rendering --- src/Feature/Input/Feature_Input.re | 16 +++++++++++++++- src/Feature/Input/Feature_Input.rei | 2 ++ src/Feature/Input/IME.re | 16 +++++++++++----- src/Store/Features.re | 4 ++++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index 88a4d3bf32..354838482f 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -166,6 +166,10 @@ module Configuration = { CustomDecoders.timeout, ~default=Timeout(Revery.Time.seconds(1)), ); + + module Debug = { + let showIMEFocus = setting("debug.ime.showFocus", bool, ~default=false); + }; }; // MSG @@ -234,6 +238,15 @@ type model = { ime: IME.t, }; +let configurationChanged = (~config, model: model) => { + ...model, + ime: + IME.setDebugView( + ~enabled=Configuration.Debug.showIMEFocus.get(config), + model.ime, + ), +}; + type uniqueId = InputStateMachine.uniqueId; let incrementTick = ({inputTick, _} as model) => { @@ -762,7 +775,8 @@ module Contributions = { openDefaultKeybindingsFile, ]; - let configuration = Configuration.[leaderKey.spec, timeout.spec]; + let configuration = + Configuration.[Debug.showIMEFocus.spec, leaderKey.spec, timeout.spec]; let contextKeys = model => { WhenExpr.ContextKeys.( diff --git a/src/Feature/Input/Feature_Input.rei b/src/Feature/Input/Feature_Input.rei index d2b0983f77..5aa9af4b95 100644 --- a/src/Feature/Input/Feature_Input.rei +++ b/src/Feature/Input/Feature_Input.rei @@ -156,6 +156,8 @@ let disable: model => model; let notifyFileSaved: (FpExp.t(FpExp.absolute), model) => model; +let configurationChanged: (~config: Config.resolver, model) => model; + // UPDATE let update: (msg, model) => (model, outmsg); diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 1a9d2380f1..4149425118 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -3,11 +3,15 @@ open Utility; module BoundingBox2d = Revery.Math.BoundingBox2d; -type t = {currentRect: option(BoundingBox2d.t)}; +type t = { + currentRect: option(BoundingBox2d.t), + showDebugFocus: bool, +}; let initial = { // currentRect: None currentRect: Some(BoundingBox2d.create(10., 10., 50., 50.)), + showDebugFocus: false, }; [@deriving show] @@ -17,11 +21,13 @@ type msg = type outmsg = Isolinear.Effect.t(msg); +let setDebugView = (~enabled, model) => {...model, showDebugFocus: enabled}; + let update = (msg, model) => switch (msg) { - | StopTextInput => ({currentRect: None}, Isolinear.Effect.none) + | StopTextInput => ({...model, currentRect: None}, Isolinear.Effect.none) | TextInputAvailable(bbox) => ( - {currentRect: Some(bbox)}, + {...model, currentRect: Some(bbox)}, Service_IME.Effects.setIMEPosition(bbox), ) }; @@ -50,8 +56,7 @@ module View = { open Revery.UI; let make = (~ime, ()) => { switch (ime.currentRect) { - | None => React.empty - | Some(bbox) => + | Some(bbox) when ime.showDebugFocus => let (x, y, w, h) = BoundingBox2d.getBounds(bbox); ; + | _ => React.empty }; }; }; diff --git a/src/Store/Features.re b/src/Store/Features.re index ab4e359c7d..24504609cc 100644 --- a/src/Store/Features.re +++ b/src/Store/Features.re @@ -219,6 +219,9 @@ module Internal = { state.buffers |> Feature_Buffers.configurationChanged(~config=resolver); + let input = + state.input |> Feature_Input.configurationChanged(~config=resolver); + let languageSupport = state.languageSupport |> Feature_LanguageSupport.configurationChanged(~config=resolver); @@ -255,6 +258,7 @@ module Internal = { buffers, colorTheme, fileExplorer, + input, languageSupport, sideBar, layout, From c33b64bd41873b9b1dd358f994b344819b7d3e04 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 14 May 2021 12:40:45 -0700 Subject: [PATCH 10/15] Test text edit event --- src/Components/InputText/View.re | 4 +--- src/Store/InputStoreConnector.re | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Components/InputText/View.re b/src/Components/InputText/View.re index 6a97ae4470..15d6345d6d 100644 --- a/src/Components/InputText/View.re +++ b/src/Components/InputText/View.re @@ -346,9 +346,7 @@ let%component make = />; switch (textBoundingBox^) { - | Some(bbox) when isFocused => - prerr_endline("BBOX: " ++ Revery.Math.BoundingBox2d.toString(bbox)); - Oni_Core.IME.set(Some(bbox)); + | Some(bbox) when isFocused => Oni_Core.IME.set(Some(bbox)) | _ => () }; diff --git a/src/Store/InputStoreConnector.re b/src/Store/InputStoreConnector.re index 1bcf2acfc4..4220eccb3d 100644 --- a/src/Store/InputStoreConnector.re +++ b/src/Store/InputStoreConnector.re @@ -289,9 +289,19 @@ let start = (window: option(Revery.Window.t), runEffects) => { window, event => { let time = Revery.Time.now(); + prerr_endline("Text input: " ++ event.text); dispatch(Actions.TextInput(event.text, time)); }, ); + + let _: unit => unit = + Revery.Window.onCompositionEdit(window, event => { + prerr_endline( + "Composition text: " ++ event.text, + // let time = Revery.Time.now(); + // dispatch(Actions.TextInput(event.text, time)); + ) + }); (); }; From 8d12fe4faf6fd1aba26d68a1dc062f5feda9d1c3 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Mon, 17 May 2021 12:30:48 -0700 Subject: [PATCH 11/15] More IME tweaks --- src/Components/InputText/Model.re | 1 + src/Feature/Input/Feature_Input.re | 7 +++++ src/Feature/Input/Feature_Input.rei | 5 ++++ src/Feature/Input/IME.re | 16 +++++++++-- src/Model/Actions.re | 6 +++++ src/Store/InputStoreConnector.re | 41 ++++++++++++++++++++++------- 6 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/Components/InputText/Model.re b/src/Components/InputText/Model.re index 270a6a4797..2123ced73a 100644 --- a/src/Components/InputText/Model.re +++ b/src/Components/InputText/Model.re @@ -206,6 +206,7 @@ module Internal = { }; let handleInput = (~text, ~selection: Selection.t, key) => { + prerr_endline("Handle input: " ++ key); switch (key, Selection.isCollapsed(selection)) { // Arrow keys | ("", true) => ( diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index 354838482f..908d329032 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -313,6 +313,13 @@ type effect = }) | RemapRecursionLimitHit; +let imeEdit = (~candidateText, ~length, ~start, model) => { + ...model, + ime: IME.setCandidateText(~candidateText, ~length, ~start, model.ime), +}; + +let isImeActive = ({ime, _}) => IME.isActive(ime); + let keyDown = ( ~config, diff --git a/src/Feature/Input/Feature_Input.rei b/src/Feature/Input/Feature_Input.rei index 5aa9af4b95..caab8e3b53 100644 --- a/src/Feature/Input/Feature_Input.rei +++ b/src/Feature/Input/Feature_Input.rei @@ -117,6 +117,11 @@ let timeout: let text: (~text: string, ~time: Revery.Time.t, model) => (model, list(effect)); +let imeEdit: + (~candidateText: string, ~length: int, ~start: int, model) => model; + +let isImeActive: model => bool; + let candidates: (~config: Config.resolver, ~context: WhenExpr.ContextKeys.t, model) => list((EditorInput.Matcher.t, execute)); diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 4149425118..de77126a9f 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -6,12 +6,14 @@ module BoundingBox2d = Revery.Math.BoundingBox2d; type t = { currentRect: option(BoundingBox2d.t), showDebugFocus: bool, + candidateText: string, }; let initial = { // currentRect: None currentRect: Some(BoundingBox2d.create(10., 10., 50., 50.)), showDebugFocus: false, + candidateText: "", }; [@deriving show] @@ -23,6 +25,15 @@ type outmsg = Isolinear.Effect.t(msg); let setDebugView = (~enabled, model) => {...model, showDebugFocus: enabled}; +let setCandidateText = (~candidateText, ~length as _, ~start as _, model) => { + ...model, + candidateText, +}; + +let isActive = model => { + model.candidateText != ""; +}; + let update = (msg, model) => switch (msg) { | StopTextInput => ({...model, currentRect: None}, Isolinear.Effect.none) @@ -66,8 +77,9 @@ module View = { width(w -. x |> int_of_float), height(h -. y |> int_of_float), backgroundColor(Revery.Color.rgba(1.0, 0., 0., 0.5)), - ] - />; + ]> + + ; | _ => React.empty }; }; diff --git a/src/Model/Actions.re b/src/Model/Actions.re index 604342a0fc..c15595080a 100644 --- a/src/Model/Actions.re +++ b/src/Model/Actions.re @@ -41,6 +41,12 @@ type t = scancode: int, time: [@opaque] Revery.Time.t, }) + // Action when there is a composition edit change + | TextEdit({ + start: int, + length: int, + compositionText: string, + }) | TextInput(string, [@opaque] Revery.Time.t) | KeyUp({ scancode: int, diff --git a/src/Store/InputStoreConnector.re b/src/Store/InputStoreConnector.re index 4220eccb3d..a0fb0086dd 100644 --- a/src/Store/InputStoreConnector.re +++ b/src/Store/InputStoreConnector.re @@ -219,6 +219,18 @@ let start = (window: option(Revery.Window.t), runEffects) => { updateFromInput(newState, actions); }; + let handleTextEdit = (~compositionText, ~start, ~length, state: State.t) => { + let input' = + Feature_Input.imeEdit( + ~candidateText=compositionText, + ~length, + ~start, + state.input, + ); + + ({...state, input: input'}, Isolinear.Effect.none); + }; + let handleKeyUp = (~scancode, state: State.t) => { let context = Model.ContextKeys.all(state); @@ -237,15 +249,20 @@ let start = (window: option(Revery.Window.t), runEffects) => { // TODO: This should be moved to a Feature_Keybindings project let updater = (state: State.t, action: Actions.t) => { switch (action) { - | KeyDown({key, scancode, time}) => + | KeyDown({key, scancode, time}) + when !Feature_Input.isImeActive(state.input) => handleKeyPress(~scancode, state, time, key) - | KeyUp({scancode, _}) => handleKeyUp(~scancode, state) + | KeyUp({scancode, _}) when !Feature_Input.isImeActive(state.input) => + handleKeyUp(~scancode, state) | KeyTimeout => handleTimeout(state) | TextInput(text, time) => handleTextInput(state, time, text) + | TextEdit({compositionText, start, length}) => + handleTextEdit(~compositionText, ~start, ~length, state) + | Pasted({rawText, isMultiLine, lines}) => ( state, pasteEffect(~rawText, ~isMultiLine, ~lines, state), @@ -295,13 +312,19 @@ let start = (window: option(Revery.Window.t), runEffects) => { ); let _: unit => unit = - Revery.Window.onCompositionEdit(window, event => { - prerr_endline( - "Composition text: " ++ event.text, - // let time = Revery.Time.now(); - // dispatch(Actions.TextInput(event.text, time)); - ) - }); + Revery.Window.onCompositionEdit( + window, + event => { + prerr_endline("Text edit: " ++ event.text); + dispatch( + Actions.TextEdit({ + start: event.start, + length: event.length, + compositionText: event.text, + }), + ); + }, + ); (); }; From f6b5aa3b4df891cb09f5b4b6e39ad1a599a7c727 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 1 Jun 2021 14:41:29 -0700 Subject: [PATCH 12/15] Formatting --- src/Service/IME/Service_IME.re | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Service/IME/Service_IME.re b/src/Service/IME/Service_IME.re index 7ced34bb64..9d5c7e47ec 100644 --- a/src/Service/IME/Service_IME.re +++ b/src/Service/IME/Service_IME.re @@ -26,5 +26,10 @@ module Sub = { }; let ime = - (~window as _, ~compositionStart as _, ~compositionEdit as _, ~compositionEnd as _) => Isolinear.Sub.none; + ( + ~window as _, + ~compositionStart as _, + ~compositionEdit as _, + ~compositionEnd as _, + ) => Isolinear.Sub.none; }; From 60e66f22478bf0479214dcd16afd1e484d13632c Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 1 Jun 2021 14:54:07 -0700 Subject: [PATCH 13/15] Close IME when text input action goes through --- src/Feature/Input/Feature_Input.re | 1 + src/Feature/Input/IME.re | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/Feature/Input/Feature_Input.re b/src/Feature/Input/Feature_Input.re index 908d329032..80fe90d7bf 100644 --- a/src/Feature/Input/Feature_Input.re +++ b/src/Feature/Input/Feature_Input.re @@ -393,6 +393,7 @@ let text = (~text, ~time, {inputStateMachine, keyDisplayer, _} as model) => { ...model, inputStateMachine: inputStateMachine', keyDisplayer: keyDisplayer', + ime: IME.clear(model.ime), } |> incrementTick, effects, diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index e1bc0d5987..3457334c30 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -34,6 +34,11 @@ let isActive = model => { model.candidateText != ""; }; +let clear = (model) => { + ...model, + candidateText: "" +}; + let update = (msg, model) => switch (msg) { | StopTextInput => ({...model, currentRect: None}, Isolinear.Effect.none) From 8874229641ceef9ce138423c7ab3d0b38068ce29 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 1 Jun 2021 15:15:49 -0700 Subject: [PATCH 14/15] Underline candidate text --- src/Feature/Input/IME.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 3457334c30..4bd0bdfa9a 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -83,7 +83,7 @@ module View = { height(h -. y |> int_of_float), backgroundColor(Revery.Color.rgba(1.0, 0., 0., 0.5)), ]> - + ; | _ => React.empty }; From c6f93e24d93a36d61537ea1d5de7aa921a7fec95 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 14 Jul 2021 16:28:48 -0700 Subject: [PATCH 15/15] Merge master --- src/Feature/Input/IME.re | 5 +---- src/Feature/Terminal/TerminalView.re | 16 +++++----------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/Feature/Input/IME.re b/src/Feature/Input/IME.re index 4bd0bdfa9a..03bdefcc9c 100644 --- a/src/Feature/Input/IME.re +++ b/src/Feature/Input/IME.re @@ -34,10 +34,7 @@ let isActive = model => { model.candidateText != ""; }; -let clear = (model) => { - ...model, - candidateText: "" -}; +let clear = model => {...model, candidateText: ""}; let update = (msg, model) => switch (msg) { diff --git a/src/Feature/Terminal/TerminalView.re b/src/Feature/Terminal/TerminalView.re index 39105bd706..ae65940c3e 100644 --- a/src/Feature/Terminal/TerminalView.re +++ b/src/Feature/Terminal/TerminalView.re @@ -73,16 +73,6 @@ module Terminal = { | _ => () }; - let lineHeightSize = - Oni_Core.LineHeight.calculate(~measuredFontHeight=fontSize, lineHeight); - let terminalFont = - EditorTerminal.Font.make( - ~smoothing, - ~size=fontSize, - ~lineHeight=lineHeightSize, - resolvedFont, - ); - let onDimensionsChanged = ( {height, width, _}: Revery.UI.NodeEvents.DimensionsChangedEventParams.t, @@ -149,7 +139,11 @@ module Terminal = { />; let elems = [element, scrollBar] |> React.listToElement; - + elems ; };