/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using static Interop.InputMethod; namespace Tizen.Uix.InputMethod { /// /// Enumeration of the key codes. /// If keycode & 0xff000000 == 0x01000000 then this key code is directly encoded 24-bit UCS character.The UCS value is keycode & 0x00ffffff. /// Defines the list of keys supported by the system.Note that certain keys may not be available on all devices. /// public enum KeyCode { /// /// The backspace key /// BackSpace = 0xFF08, /// /// The tab key /// Tab = 0xFF09, /// /// The linefeed key /// Linefeed = 0xFF0A, /// /// The clear key /// Clear = 0xFF0B, /// /// The return key /// Return = 0xFF0D, /// /// The pause key /// Pause = 0xFF13, /// /// The scroll lock key /// ScrollLock = 0xFF14, /// /// The sys req key /// SysReq = 0xFF15, /// /// The escape key /// Escape = 0xFF1B, /// /// The delete key /// Delete = 0xFFFF, /* Cursor control & motion */ /// /// The home key /// Home = 0xFF50, /// /// The left directional key /// Left = 0xFF51, /// /// The up directional key /// Up = 0xFF52, /// /// The right directional key /// Right = 0xFF53, /// /// The down directional key /// Down = 0xFF54, /// /// The prior, previous key /// Prior = 0xFF55, /// /// The page up key /// Page_Up = 0xFF55, /// /// The next key /// Next = 0xFF56, /// /// The page down key /// Page_Down = 0xFF56, /// /// The end key /// End = 0xFF57, /// /// The begin key /// Begin = 0xFF58, /* Misc Functions */ /// /// The select key /// Select = 0xFF60, /// /// The print key /// Print = 0xFF61, /// /// The execute, run, do key /// Execute = 0xFF62, /// /// The insert key /// Insert = 0xFF63, /// /// The undo key /// Undo = 0xFF65, /// /// The redo key /// Redo = 0xFF66, /// /// The menu key /// Menu = 0xFF67, /// /// The find key /// Find = 0xFF68, /// /// The cancel, stop, abort, exit key /// Cancel = 0xFF69, /// /// The help key /// Help = 0xFF6A, /// /// The break key /// Break = 0xFF6B, /// /// The character set switch key /// Mode_switch = 0xFF7E, /// /// The num lock key /// Num_Lock = 0xFF7F, /* Keypad */ /// /// The Numpad space key /// KPSpace = 0xFF80, /// /// The Numpad tab key /// KPTab = 0xFF89, /// /// The Numpad enter key /// KPEnter = 0xFF8D, /// /// The Numpad function 1 key /// KPF1 = 0xFF91, /// /// The Numpad function 2 key /// KPF2 = 0xFF92, /// /// The Numpad function 3 key /// KPF3 = 0xFF93, /// /// The Numpad function 4 key /// KPF4 = 0xFF94, /// /// The Numpad home key /// KPHome = 0xFF95, /// /// The Numpad left key /// KPLeft = 0xFF96, /// /// The Numpad up key /// KPUp = 0xFF97, /// /// The Numpad right key /// KPRight = 0xFF98, /// /// The Numpad down key /// KPDown = 0xFF99, /// /// The Numpad prior, previous key /// KPPrior = 0xFF9A, /// /// The Numpad page up key /// KPPage_Up = 0xFF9A, /// /// The Numpad next key /// KPNext = 0xFF9B, /// /// The Numpad page down key /// KPPage_Down = 0xFF9B, /// /// The Numpad end key /// KPEnd = 0xFF9C, /// /// The Numpad begin key /// KPBegin = 0xFF9D, /// /// The Numpad insert key /// KPInsert = 0xFF9E, /// /// The Numpad delete key /// KPDelete = 0xFF9F, /// /// The Numpad equal key /// KPEqual = 0xFFBD, /// /// The Numpad multiply key /// KPMultiply = 0xFFAA, /// /// The Numpad add key /// KPAdd = 0xFFAB, /// /// The Numpad separator key /// KPSeparator = 0xFFAC, /// /// The Numpad subtract key /// KPSubtract = 0xFFAD, /// /// The Numpad decimal key /// KPDecimal = 0xFFAE, /// /// The Numpad divide key /// KPDivide = 0xFFAF, /// /// The Numpad 0 key /// KP0 = 0xFFB0, /// /// The Numpad 1 key /// KP1 = 0xFFB1, /// /// The Numpad 2 key /// KP2 = 0xFFB2, /// /// The Numpad 3 key /// KP3 = 0xFFB3, /// /// The Numpad 4 key /// KP4 = 0xFFB4, /// /// The Numpad 5 key /// KP5 = 0xFFB5, /// /// The Numpad 6 key /// KP6 = 0xFFB6, /// /// The Numpad 7 key /// KP7 = 0xFFB7, /// /// The Numpad 8 key /// KP8 = 0xFFB8, /// /// The Numpad 9 key /// KP9 = 0xFFB9, /* Auxilliary Functions */ /// /// The function 1 key /// F1 = 0xFFBE, /// /// The function 2 key /// F2 = 0xFFBF, /// /// The function 3 key /// F3 = 0xFFC0, /// /// The function 4 key /// F4 = 0xFFC1, /// /// The function 5 key /// F5 = 0xFFC2, /// /// The function 6 key /// F6 = 0xFFC3, /// /// The function 7 key /// F7 = 0xFFC4, /// /// The function 8 key /// F8 = 0xFFC5, /// /// The function 9 key /// F9 = 0xFFC6, /// /// The function 10 key /// F10 = 0xFFC7, /// /// The function 11 key /// F11 = 0xFFC8, /// /// The function 12 key /// F12 = 0xFFC9, /// /// The function 13 key /// F13 = 0xFFCA, /// /// The function 14 key /// F14 = 0xFFCB, /// /// The function 15 key /// F15 = 0xFFCC, /// /// The function 16 key /// F16 = 0xFFCD, /// /// The function 17 key /// F17 = 0xFFCE, /// /// The function 18 key /// F18 = 0xFFCF, /// /// The function 19 key /// F19 = 0xFFD0, /// /// The function 20 key /// F20 = 0xFFD1, /// /// The function 21 key /// F21 = 0xFFD2, /// /// The function 22 key /// F22 = 0xFFD3, /// /// The function 23 key /// F23 = 0xFFD4, /// /// The function 24 key /// F24 = 0xFFD5, /// /// The function 25 key /// F25 = 0xFFD6, /// /// The function 26 key /// F26 = 0xFFD7, /// /// The function 27 key /// F27 = 0xFFD8, /// /// The function 28 key /// F28 = 0xFFD9, /// /// The function 29 key /// F29 = 0xFFDA, /// /// The function 30 key /// F30 = 0xFFDB, /// /// The function 31 key /// F31 = 0xFFDC, /// /// The function 32 key /// F32 = 0xFFDD, /// /// The function 33 key /// F33 = 0xFFDE, /// /// The function 34 key /// F34 = 0xFFDF, /// /// The function 35 key /// F35 = 0xFFE0, /* Modifier keys */ /// /// The left shift key /// ShiftL = 0xFFE1, /// /// The right shift key /// ShiftR = 0xFFE2, /// /// The left control key /// ControlL = 0xFFE3, /// /// The right control key /// ControlR = 0xFFE4, /// /// The caps lock key /// CapsLock = 0xFFE5, /// /// The shift lock key /// ShiftLock = 0xFFE6, /// /// The left meta key /// MetaL = 0xFFE7, /// /// The right meta key /// MetaR = 0xFFE8, /// /// The left alt key /// AltL = 0xFFE9, /// /// The right alt key /// AltR = 0xFFEA, /// /// The left super key /// SuperL = 0xFFEB, /// /// The right super key /// SuperR = 0xFFEC, /// /// The left hyper key /// HyperL = 0xFFED, /// /// The right hyper key /// HyperR = 0xFFEE, /* Latin 1 */ /// /// The space key /// Space = 0x020, /// /// The exclamation key /// Exclam = 0x021, /// /// The quotedbl key /// Quotedbl = 0x022, /// /// The number sign key /// NumberSign = 0x023, /// /// The dollar key /// Dollar = 0x024, /// /// The percent key /// Percent = 0x025, /// /// The ampersand key /// Ampersand = 0x026, /// /// The apostrophe key /// Apostrophe = 0x027, /// /// The parenleft key /// Parenleft = 0x028, /// /// The parenright key /// Parenright = 0x029, /// /// The asterisk key /// Asterisk = 0x02a, /// /// The plus key /// Plus = 0x02b, /// /// The comma key /// Comma = 0x02c, /// /// The minus key /// Minus = 0x02d, /// /// The period key /// Period = 0x02e, /// /// The slash key /// Slash = 0x02f, /// /// The 0 key /// Keypad0 = 0x030, /// /// The 1 key /// Keypad1 = 0x031, /// /// The 2 key /// Keypad2 = 0x032, /// /// The 3 key /// Keypad3 = 0x033, /// /// The 4 key /// Keypad4 = 0x034, /// /// The 5 key /// Keypad5 = 0x035, /// /// The 6 key /// Keypad6 = 0x036, /// /// The 7 key /// Keypad7 = 0x037, /// /// The 8 key /// Keypad8 = 0x038, /// /// The 9 key /// Keypad9 = 0x039, /// /// The colon key /// Colon = 0x03a, /// /// The semicolon key /// Semicolon = 0x03b, /// /// The less key /// Less = 0x03c, /// /// The equal key /// Equal = 0x03d, /// /// The greater key /// Greater = 0x03e, /// /// The question key /// Question = 0x03f, /// /// The at key /// At = 0x040, /// /// The A key /// KeypadA = 0x041, /// /// The B key /// KeypadB = 0x042, /// /// The C key /// KeypadC = 0x043, /// /// The D key /// KeypadD = 0x044, /// /// The E key /// KeypadE = 0x045, /// /// The F key /// KeypadF = 0x046, /// /// The G key /// KeypadG = 0x047, /// /// The H key /// KeypadH = 0x048, /// /// The I key /// KeypadI = 0x049, /// /// The J key /// KeypadJ = 0x04a, /// /// The K key /// KeypadK = 0x04b, /// /// The L key /// KeypadL = 0x04c, /// /// The M key /// KeypadM = 0x04d, /// /// The N key /// KeypadN = 0x04e, /// /// The O key /// KeypadO = 0x04f, /// /// The P key /// KeypadP = 0x050, /// /// The Q key /// KeypadQ = 0x051, /// /// The R key /// KeypadR = 0x052, /// /// The S key /// KeypadS = 0x053, /// /// The T key /// KeypadT = 0x054, /// /// The U key /// KeypadU = 0x055, /// /// The V key /// KeypadV = 0x056, /// /// The W key /// KeypadW = 0x057, /// /// The X key /// KeypadX = 0x058, /// /// The Y key /// KeypadY = 0x059, /// /// The Z key /// KeypadZ = 0x05a, /// /// The left bracket key /// BracketLeft = 0x05b, /// /// The backslash key /// Backslash = 0x05c, /// /// The right bracket key /// BracketRight = 0x05d, /// /// The circumflex key /// AsciiCircum = 0x05e, /// /// The underscore key /// Underscore = 0x05f, /// /// The grave key /// Grave = 0x060, /// /// The a key /// Keypada = 0x061, /// /// The b key /// Keypadb = 0x062, /// /// The c key /// Keypadc = 0x063, /// /// The d key /// Keypadd = 0x064, /// /// The e key /// Keypade = 0x065, /// /// The f key /// Keypadf = 0x066, /// /// The g key /// Keypadg = 0x067, /// /// The h key /// Keypadh = 0x068, /// /// The i key /// Keypadi = 0x069, /// /// The j key /// Keypadj = 0x06a, /// /// The k key /// Keypadk = 0x06b, /// /// The l key /// Keypadl = 0x06c, /// /// The m key /// Keypadm = 0x06d, /// /// The n key /// Keypadn = 0x06e, /// /// The o key /// Keypado = 0x06f, /// /// The p key /// Keypadp = 0x070, /// /// The q key /// Keypadq = 0x071, /// /// The r key /// Keypadr = 0x072, /// /// The s key /// Keypads = 0x073, /// /// The t key /// Keypadt = 0x074, /// /// The u key /// Keypadu = 0x075, /// /// The v key /// Keypadv = 0x076, /// /// The w key /// Keypadw = 0x077, /// /// The x key /// Keypadx = 0x078, /// /// The y key /// Keypady = 0x079, /// /// The z key /// Keypadz = 0x07a, /// /// The left brace key /// BraceLeft = 0x07b, /// /// The bar key /// Bar = 0x07c, /// /// The right brace key /// BraceRight = 0x07d, /// /// The tilde key /// AsciiTilde = 0x07e, }; /// /// Enumeration of the key masks. /// The key masks indicate which modifier keys is pressed down during the keyboard hit.The special MASK_RELEASED indicates the key release event. /// public enum KeyMask { /// /// Key press event without modifier key /// Pressed = 0, /// /// The Shift key is pressed down /// Shift = (1 << 0), /// /// The CapsLock key is pressed down /// CapsLock = (1 << 1), /// /// The Control key is pressed down /// Control = (1 << 2), /// /// The Alt key is pressed down /// Alt = (1 << 3), /// /// The Meta key is pressed down /// Meta = (1 << 4), /// /// The Win (between Control and Alt) is pressed down /// Win = (1 << 5), /// /// The Hyper key is pressed down /// Hyper = (1 << 6), /// /// The NumLock key is pressed down /// NumLock = (1 << 7), /// /// Key release event /// Released = (1 << 15), } /// /// This class contains api's related to IME(Input method editor) /// public static class InputMethodEditor { private static Object thisLock = new Object(); private static ImeCallbackStructGCHandle _imeCallbackStructGCHandle = new ImeCallbackStructGCHandle(); private static event EventHandler _focusIn; private static ImeFocusedInCb _imeFocusedInDelegate; private static event EventHandler _focusOut; private static ImeFocusedOutCb _imeFocusedOutDelegate; private static event EventHandler _surroundingTextUpdated; private static ImeSurroundingTextUpdatedCb _imeSurroundingTextUpdatedDelegate; private static event EventHandler _inputContextReset; private static ImeInputContextResetCb _imeInputContextResetDelegate; private static event EventHandler _cursorPositionUpdated; private static ImeCursorPositionUpdatedCb _imeCursorPositionUpdatedDelegate; private static event EventHandler _langaugeSet; private static ImeLanguageSetCb _imeLanguageSetDelegate; private static event EventHandler _imDataSet; private static ImeImdataSetCb _imeDataSetDelegate; private static event EventHandler _layoutSet; private static ImeLayoutSetCb _imeLayoutSetDelegate; private static event EventHandler _returnKeyTypeSet; private static ImeReturnKeySetCb _imeReturnKeySetDelegate; private static event EventHandler _returnKeyStateSet; private static ImeReturnKeyStateSetCb _imeReturnKeyStateSetDelegate; private static ImeProcessKeyEventCb _imeProcessKeyDelegate; private static event EventHandler _displayLanguageChanged; private static ImeDisplayLanguageChangedCb _imeDisplayLanguageChangedDelegate; private static event EventHandler _rotationDegreeChanged; private static ImeRotationChangedCb _imeRotationChangedDelegate; private static event EventHandler _accessibilityStateChanged; private static ImeAccessibilityStateChangedCb _imeAccessibilityStateChangedDelegate; private static ImeLanguageRequestedCb _imeLanguageRequestedDelegate; private static OutAction _languageRequestedDelegate; private static BoolAction _processKeyDelagate; private static ImeImdataRequestedCb _imeImDataRequestedDelegate; private static OutArrayAction _imDataRequestedDelegate; private static ImeGeometryRequestedCb _imeGeometryRequestedDelegate; private static OutAction _geometryRequestedDelegate; private static Action _userCreate; private static Action _userTerminate; private static Action _userShow; private static Action _userHide; private static ImeCreateCb _create = (IntPtr userData) => { Log.Info(LogTag, "In Create Delegate"); _userCreate?.Invoke(); }; private static ImeTerminateCb _terminate = (IntPtr userData) => { Log.Info(LogTag, "In terminate Delegate"); _userTerminate?.Invoke(); _imeCallbackStructGCHandle.Dispose(); }; private static ImeShowCb _show = (int contextId, IntPtr context, IntPtr userData) => { Log.Info(LogTag, "In Show Delegate"); _userShow?.Invoke(new ContextId(contextId), new InputMethodContext(context)); }; private static ImeHideCb _hide = (int contextId, IntPtr userData) => { Log.Info(LogTag, "In Hide Delegate"); _userHide?.Invoke(new ContextId(contextId)); }; /// /// Structure representing ContextId /// public struct ContextId : IEquatable { internal ContextId(int id) { Id = id; } internal int Id { get; private set; } public bool Equals(ContextId other) { return this.Id == other.Id; } } /// /// rectangle representing the position and size of UI Control /// public struct Rect { /// /// The x position in screen /// public int x; /// /// The y position in screen /// public int y; /// /// The window width /// public int w; /// /// The window height /// public int h; } /// /// An Action with 1 out parameter /// /// Generic Type /// The out parameter public delegate void OutAction(out T a); /// /// An Action with an array out parameter /// /// Generic Type /// The out parameter 1 public delegate void OutArrayAction(out T[] a); /// /// An Action with 3 Input Parameter returning a bool /// /// Generic Type for Parameter 1 /// Generic Type for Parameter 2 /// Generic Type for Parameter 3 /// The Input Parameter 1 /// The Input Parameter 2 /// The Input Parameter 3 /// public delegate bool BoolAction(T a, T1 b, T2 c); /// /// Called when an associated text input UI control has focus. /// public static event EventHandler FocusedIn { add { lock (thisLock) { _imeFocusedInDelegate = (int contextId, IntPtr userData) => { FocusedInEventArgs args = new FocusedInEventArgs(contextId); _focusIn?.Invoke(null, args); }; ErrorCode error = ImeEventSetFocusedInCb(_imeFocusedInDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add FocusedIn Failed with error " + error); } else { _focusIn += value; } } } remove { lock (thisLock) { _focusIn -= value; } } } /// /// Called when an associated text input UI control loses focus. /// public static event EventHandler FocusedOut { add { lock (thisLock) { _imeFocusedOutDelegate = (int contextId, IntPtr userData) => { FocusedOutEventArgs args = new FocusedOutEventArgs(contextId); _focusOut?.Invoke(null, args); }; ErrorCode error = ImeEventSetFocusedOutCb(_imeFocusedOutDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add FocusedOut Failed with error " + error); } else { _focusOut += value; } } } remove { lock (thisLock) { _focusOut -= value; } } } /// /// Called when an associated text input UI control responds to a request with the surrounding text. /// public static event EventHandler SurroundingTextUpdated { add { lock (thisLock) { _imeSurroundingTextUpdatedDelegate = (int contextId, IntPtr text, int cursorPos, IntPtr userData) => { SurroundingTextUpdatedEventArgs args = new SurroundingTextUpdatedEventArgs(contextId, Marshal.PtrToStringAnsi(text), cursorPos); _surroundingTextUpdated?.Invoke(null, args); }; ErrorCode error = ImeEventSetSurroundingTextUpdatedCb(_imeSurroundingTextUpdatedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add SurroundingTextUpdated Failed with error " + error); } else { _surroundingTextUpdated += value; } } } remove { lock (thisLock) { _surroundingTextUpdated -= value; } } } /// /// Called to reset the input context of an associated text input UI control. /// public static event EventHandler InputContextReset { add { lock (thisLock) { _imeInputContextResetDelegate = (IntPtr userData) => { _inputContextReset?.Invoke(null, EventArgs.Empty); }; ErrorCode error = ImeEventSetInputContextResetCb(_imeInputContextResetDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add InputContextReset Failed with error " + error); } else { _inputContextReset += value; } } } remove { lock (thisLock) { _inputContextReset -= value; } } } /// /// Called when the position of the cursor in an associated text input UI control changes. /// public static event EventHandler CursorPositionUpdated { add { lock (thisLock) { _imeCursorPositionUpdatedDelegate = (int cursorPos, IntPtr userData) => { CursorPositionUpdatedEventArgs args = new CursorPositionUpdatedEventArgs(cursorPos); _cursorPositionUpdated?.Invoke(null, args); }; ErrorCode error = ImeEventSetCursorPositionUpdatedCb(_imeCursorPositionUpdatedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add CursorPositionUpdated Failed with error " + error); } else { _cursorPositionUpdated += value; } } } remove { lock (thisLock) { _cursorPositionUpdated -= value; } } } /// /// Called to set the preferred language to the input panel. /// It will be only called when the client application changes the edit field's language attribute after the input panel is shown. /// public static event EventHandler LanguageSet { add { lock (thisLock) { _imeLanguageSetDelegate = (InputPanelLanguage language, IntPtr userData) => { LanguageSetEventArgs args = new LanguageSetEventArgs(language); _langaugeSet?.Invoke(null, args); }; ErrorCode error = ImeEventSetLanguageSetCb(_imeLanguageSetDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add LanguageSet Failed with error " + error); } else { _langaugeSet += value; } } } remove { lock (thisLock) { _langaugeSet -= value; } } } /// /// Called to set the application specific data to deliver to the input panel. /// public static event EventHandler DataSet { add { lock (thisLock) { _imeDataSetDelegate = (IntPtr data, uint dataLength, IntPtr userData) => { byte[] destination = new byte[dataLength]; Marshal.Copy(data, destination, 0, (int)dataLength); SetDataEventArgs args = new SetDataEventArgs(destination, dataLength); _imDataSet?.Invoke(null, args); }; ErrorCode error = ImeEventSetImdataSetCb(_imeDataSetDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add DataSet Failed with error " + error); } else { _imDataSet += value; } } } remove { lock (thisLock) { _imDataSet -= value; } } } /// /// Called when an associated text input UI control requests the input panel to set its layout. /// It will be only called when the client application changes the edit field's layout attribute after the input panel is shown. /// public static event EventHandler LayoutSet { add { lock (thisLock) { _imeLayoutSetDelegate = (InputPanelLayout layout, IntPtr userData) => { LayoutSetEventArgs args = new LayoutSetEventArgs(layout); _layoutSet?.Invoke(null, args); }; ErrorCode error = ImeEventSetLayoutSetCb(_imeLayoutSetDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add LayoutSet Failed with error " + error); } else { _layoutSet += value; } } } remove { lock (thisLock) { _layoutSet -= value; } } } /// /// Called when an associated text input UI control requests the input panel to set the Return key label. /// The input panel can show text or image on the Return button according to the Return key action. /// public static event EventHandler ReturnKeySet { add { lock (thisLock) { _imeReturnKeySetDelegate = (InputPanelReturnKey type, IntPtr userData) => { ReturnKeySetEventArgs args = new ReturnKeySetEventArgs(type); _returnKeyTypeSet?.Invoke(null, args); }; ErrorCode error = ImeEventSetReturnKeySetCb(_imeReturnKeySetDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add ReturnKeySet Failed with error " + error); } else { _returnKeyTypeSet += value; } } } remove { lock (thisLock) { _returnKeyTypeSet -= value; } } } /// /// Called when an associated text input UI control requests the input panel to enable or disable the Return key state. /// public static event EventHandler ReturnKeyStateSet { add { lock (thisLock) { _imeReturnKeyStateSetDelegate = (bool state, IntPtr userData) => { ReturnKeyStateSetEventArgs args = new ReturnKeyStateSetEventArgs(state); _returnKeyStateSet?.Invoke(null, args); }; ErrorCode error = ImeEventSetReturnKeyStateSetCb(_imeReturnKeyStateSetDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add ReturnKeyStateSet Failed with error " + error); } else { _returnKeyStateSet += value; } } } remove { lock (thisLock) { _returnKeyStateSet -= value; } } } /// /// Called when the system display Language is changed. /// public static event EventHandler DisplayLanguageChanged { add { lock (thisLock) { _imeDisplayLanguageChangedDelegate = (IntPtr language, IntPtr userData) => { DisplayLanguageChangedEventArgs args = new DisplayLanguageChangedEventArgs(Marshal.PtrToStringAnsi(language)); _displayLanguageChanged?.Invoke(null, args); }; ErrorCode error = ImeEventSetDisplayLanguageChangedCb(_imeDisplayLanguageChangedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add DisplayLanguageChanged Failed with error " + error); } else { _displayLanguageChanged += value; } } } remove { lock (thisLock) { _displayLanguageChanged -= value; } } } /// /// Called when the device is rotated. /// public static event EventHandler RotationChanged { add { lock (thisLock) { _imeRotationChangedDelegate = (int degree, IntPtr userData) => { RotationChangedEventArgs args = new RotationChangedEventArgs(degree); _rotationDegreeChanged?.Invoke(null, args); }; ErrorCode error = ImeEventSetRotationChangedCb(_imeRotationChangedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add RotationChanged Failed with error " + error); } else { _rotationDegreeChanged += value; } } } remove { lock (thisLock) { _rotationDegreeChanged -= value; } } } /// /// Called when Accessibility in Settings application is on or off. /// public static event EventHandler AccessibilityStateChanged { add { lock (thisLock) { _imeAccessibilityStateChangedDelegate = (bool state, IntPtr userData) => { AccessibilityStateChangedEventArgs args = new AccessibilityStateChangedEventArgs(state); _accessibilityStateChanged?.Invoke(null, args); }; ErrorCode error = ImeEventSetAccessibilityStateChangedCb(_imeAccessibilityStateChangedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add AccessibilityStateChanged Failed with error " + error); } else { _accessibilityStateChanged += value; } } } remove { lock (thisLock) { _accessibilityStateChanged -= value; } } } /// /// Sets the languageRequested Action /// /// /// Called when an associated text input UI control requests the language from the input panel, requesting for language code. /// public static void SetLanguageRequestedCallback(OutAction languageRequested) { _imeLanguageRequestedDelegate = (IntPtr userData, out IntPtr langCode) => { string langauage; _languageRequestedDelegate(out langauage); char[] languageArray = langauage.ToCharArray(); langCode = new IntPtr(); Marshal.Copy(languageArray, 0, langCode, languageArray.Length); }; ErrorCode error = ImeEventSetLanguageRequestedCallbackCb(_imeLanguageRequestedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add SetLanguageRequestedCallback Failed with error " + error); } _languageRequestedDelegate = languageRequested; } /// /// Sets the processKey Action /// If the key event is from the external device, DeviceInfo will have its name, class and subclass information. /// /// /// The Action is alled when the key event is received from the external devices or SendKey function. /// This Event processes the key event before an associated text input UI control does. /// public static void SetProcessKeyCallback(BoolAction processKey) { _imeProcessKeyDelegate = (KeyCode keyCode, KeyMask keyMask, IntPtr devInfo, IntPtr userData) => { return _processKeyDelagate(keyCode, keyMask, new InputMethodDeviceInformation(devInfo)); }; ErrorCode error = ImeEventSetProcessKeyEventCb(_imeProcessKeyDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add ProcessKey Failed with error " + error); } _processKeyDelagate = processKey; } /// /// Sets the imDataRequested Action /// /// /// Called when an associated text input UI control requests the application specific data from the input panel, requesting for data array and it's length. /// public static void SetDataRequestedCallback(OutArrayAction imDataRequested) { _imeImDataRequestedDelegate = (IntPtr userData, out IntPtr data, out uint dataLength) => { byte[] dataArr; _imDataRequestedDelegate(out dataArr); data = new IntPtr(); Marshal.Copy(dataArr, 0, data, dataArr.Length); dataLength = (uint)dataArr.Length; }; ErrorCode error = ImeEventSetImdataRequestedCb(_imeImDataRequestedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add SetDataRequestedCallback Failed with error " + error); } _imDataRequestedDelegate = imDataRequested; } /// /// Sets the GeometryRequested Action /// /// /// Called when an associated text input UI control requests the position and size from the input panel, requesting for x,y,w,h values. /// public static void SetGeometryRequestedCallback(OutAction geometryRequested) { _imeGeometryRequestedDelegate = (IntPtr userData, out int x, out int y, out int w, out int h) => { Rect rect = new Rect(); _geometryRequestedDelegate(out rect); x = rect.x; y = rect.y; w = rect.w; h = rect.h; }; ErrorCode error = ImeEventSetGeometryRequestedCallbackCb(_imeGeometryRequestedDelegate, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Add SetGeometryRequestedCallback Failed with error " + error); } _geometryRequestedDelegate = geometryRequested; } /// /// Runs the main loop of IME application. /// This function starts to run IME application's main loop. /// /// /// http://tizen.org/privilege/ime /// /// /// This API is a blocking call, as it starts the main loop of the application. /// /// This is called to initialize IME application before the main loop starts up /// This is called when IME application is terminated /// /// This is called when IME application is shown /// It provides the Context Inofrmation and the Context Id /// /// /// This is called when IME application is hidden /// It provides the Context Id /// /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) Operation failed /// public static void Run(Action create, Action terminate, Action show, Action hide) { _userCreate = create; _userTerminate = terminate; _userShow = show; _userHide = hide; _imeCallbackStructGCHandle._imeCallbackStruct.create = _create; _imeCallbackStructGCHandle._imeCallbackStruct.terminate = _terminate; _imeCallbackStructGCHandle._imeCallbackStruct.hide = _hide; _imeCallbackStructGCHandle._imeCallbackStruct.show = _show; ErrorCode error = ImeRun(ref _imeCallbackStructGCHandle._imeCallbackStruct, IntPtr.Zero); if (error != ErrorCode.None) { Log.Error(LogTag, "Run Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Sends a key event to the associated text input UI control. /// /// /// This function sends key down or up event with key mask to the client application. If forwardKey is true, this key event goes to the edit filed directly. /// And if forwardKey is false, the ProcessKey event receives the key event before the edit field. /// /// /// http://tizen.org/privilege/ime /// /// The key code to be sent /// The modifier key mask /// The flag to send the key event directly to the edit field /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// public static void SendKeyEvent(KeyCode keyCode, KeyMask keyMask, bool forwardKey = false) { ErrorCode error = ImeSendKeyEvent(keyCode, keyMask, forwardKey); if (error != ErrorCode.None) { Log.Error(LogTag, "SendEvent Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Sends the text to the associated text input UI control. /// /// /// http://tizen.org/privilege/ime /// /// The string to be committed /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// public static void CommitString(string str) { ErrorCode error = ImeCommitString(str); if (error != ErrorCode.None) { Log.Error(LogTag, "CommitString Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Requests to show preedit string. /// /// /// http://tizen.org/privilege/ime /// /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// public static void ShowPreEditString() { ErrorCode error = ImeShowPreeditString(); if (error != ErrorCode.None) { Log.Error(LogTag, "ShowPreEditString Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Requests to hide preedit string. /// /// /// http://tizen.org/privilege/ime /// /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// public static void HidePreEditString() { ErrorCode error = ImeHidePreeditString(); if (error != ErrorCode.None) { Log.Error(LogTag, "HidePreEditString Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Updates a new preedit string. /// /// /// http://tizen.org/privilege/ime /// /// The string to be updated in preedit /// /// The list which has ime_preedit_attribute lists, strings can be composed of multiple string attributes: underline, highlight color and reversal color. /// The attrs list can be empty if no attributes to set /// /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// 3) Invalid Parameter /// public static void UpdatePreEditString(string str, IEnumerable attrs) { IntPtr einaList = IntPtr.Zero; List attributeHandleList = new List(); foreach (PreEditAttribute attribute in attrs) { ImePreEditAttributeStruct imePreEditAttribute = new ImePreEditAttributeStruct(); imePreEditAttribute.start = attribute.Start; imePreEditAttribute.length = attribute.Length; imePreEditAttribute.type = (int)attribute.Type; imePreEditAttribute.value = attribute.Value; GCHandle attributeHandle = GCHandle.Alloc(imePreEditAttribute, GCHandleType.Pinned); attributeHandleList.Add(attributeHandle); einaList = Interop.EinaList.EinaListAppend(einaList, attributeHandle.AddrOfPinnedObject()); } ErrorCode error = ImeUpdatePreeditString(str, einaList); foreach (GCHandle handle in attributeHandleList) { handle.Free(); } if (error != ErrorCode.None) { Log.Error(LogTag, "UpdatePreEditString Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Requests the surrounding text from the position of the cursor, asynchronously. /// /// /// http://tizen.org/privilege/ime /// /// The maximum length of string to be retrieved before the cursor, -1 means unlimited /// The maximum length of string to be retrieved after the cursor, -1 means unlimited /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// /// /// The requested surrounding text can be received using the SurroundingTextUpdated Event, only if it is set. /// public static void RequestSurroundingText(int maxLenBefore, int maxLenAfter) { ErrorCode error = ImeRequestSurroundingText(maxLenBefore, maxLenAfter); if (error != ErrorCode.None) { Log.Error(LogTag, "RequestSurroundingText Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Requests to delete surrounding text. /// /// /// http://tizen.org/privilege/ime /// /// The offset value from the cursor position /// The length of the text to delete /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// 3) Invalid Parameter /// public static void DeleteSurroundingText(int offset, int len) { ErrorCode error = ImeDeleteSurroundingText(offset, len); if (error != ErrorCode.None) { Log.Error(LogTag, "DeleteSurroundingText Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// Gets the surrounding text from the position of the cursor, synchronously. /// /// /// http://tizen.org/privilege/ime /// /// The maximum length of string to be retrieved before the cursor, -1 means unlimited /// The maximum length of string to be retrieved after the cursor, -1 means unlimited /// The surrounding text /// The cursor position /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// 3) Invalid Parameter /// 4) Failed to obtain text due to out of memory /// public static void GetSurroundingText(int maxLenBefore, int maxLenAfter, out string text, out int cursorPosition) { IntPtr txt; ErrorCode error = ImeGetSurroundingText(maxLenBefore, maxLenAfter, out txt, out cursorPosition); if (error != ErrorCode.None) { Log.Error(LogTag, "GetSurroundingText Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } text = Marshal.PtrToStringAnsi(txt); } /// /// Requests to set selection. /// /// /// http://tizen.org/privilege/ime /// /// The start cursor position in text (in characters not bytes) /// The end cursor position in text (in characters not bytes) /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// 3) Invalid Parameter /// public static void SetSelection(int start, int end) { ErrorCode error = ImeSetSelection(start, end); if (error != ErrorCode.None) { Log.Error(LogTag, "SetSelection Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// This API returns the input panel main window. /// /// /// http://tizen.org/privilege/ime /// /// The input panel main window object on success, otherwise null /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) IME main loop isn't started yet /// 3) Operation Failed /// public static EditorWindow GetMainWindow() { EditorWindow._handle = ImeGetMainWindow(); EditorWindow obj = new EditorWindow(); ErrorCode error = (ErrorCode)Tizen.Internals.Errors.ErrorFacts.GetLastResult(); if (error != ErrorCode.None) { Log.Error(LogTag, "GetMainWindow Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } return obj; } /// /// This API requests the InputMethodEditor to initialize /// /// /// http://tizen.org/privilege/ime /// /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) Operation Failed /// public static void Create() { ErrorCode error = ImeInitialize(); Log.Info(LogTag, "ImeInitialize result : " + error); if (error != ErrorCode.None) { Log.Error(LogTag, "ImeInitialize Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } error = ImePrepare(); Log.Info(LogTag, "ImePrepare result : " + error); if (error != ErrorCode.None) { Log.Error(LogTag, "ImePrepare Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } /// /// This API requests the InputMethodEditor to finalize /// /// /// http://tizen.org/privilege/ime /// /// /// This can occur due to the following reasons: /// 1) The application does not have the privilege to call this function /// 2) Operation Failed /// public static void Destroy() { ErrorCode error = ImeFinalize(); Log.Info(LogTag, "ImeFinalize result : " + error); if (error != ErrorCode.None) { Log.Error(LogTag, "ImeFinalize Failed with error " + error); throw InputMethodExceptionFactory.CreateException(error); } } } }