1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_ 6 #define CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/strings/string16.h" 13 #include "third_party/npapi/bindings/npapi.h" 14 #include "ui/gfx/rect.h" 15 16 namespace content { 17 18 class PluginInstance; 19 20 // A class that emulates an IME for windowless plug-ins. A windowless plug-in 21 // does not have a window. Therefore, we cannot attach an IME to a windowless 22 // plug-in. To allow such windowless plug-ins to use IMEs without any changes to 23 // them, this class receives the IME data from a browser and patches IMM32 24 // functions to return the IME data when a windowless plug-in calls IMM32 25 // functions. I would not Flash retrieves pointers to IMM32 functions with 26 // GetProcAddress(), this class also needs a hook to GetProcAddress() to 27 // dispatch IMM32 function calls from a plug-in to this class as listed in the 28 // following snippet. 29 // 30 // FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name) { 31 // FARPROC* proc = WebPluginIMEWin::GetProcAddress(name); 32 // if (proc) 33 // return proc; 34 // return ::GetProcAddress(module, name); 35 // } 36 // ... 37 // app::win::IATPatchFunction get_proc_address; 38 // get_proc_address.Patch( 39 // GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress", 40 // GetProcAddressPatch); 41 // 42 // After we successfuly dispatch IMM32 calls from a plug-in to this class, we 43 // need to update its IME data so the class can return it to the plug-in through 44 // its IMM32 calls. To update the IME data, we call CompositionUpdated() or 45 // CompositionCompleted() BEFORE sending an IMM32 Window message to the plugin 46 // with a SendEvents() call as listed in the following snippet. (Plug-ins call 47 // IMM32 functions when it receives IMM32 window messages. We need to update the 48 // IME data of this class before sending IMM32 messages so the plug-ins can get 49 // the latest data.) 50 // 51 // WebPluginIMEWin ime; 52 // ... 53 // base::string16 text = "composing"; 54 // std::vector<int> clauses; 55 // clauses.push_back(0); 56 // clauses.push_back(text.length()); 57 // std::vector<int> target; 58 // ime.CompositionUpdated(text, clauses, target, text.length()); 59 // ime.SendEvents(instance()); 60 // 61 // base::string16 result = "result"; 62 // ime.CompositionCompleted(result); 63 // ime.SendEvents(instance()); 64 // 65 // This class also provides GetStatus() so we can retrieve the IME status 66 // changed by a plug-in with IMM32 functions. This function is mainly used for 67 // retrieving the position of a caret. 68 // 69 class WebPluginIMEWin { 70 public: 71 // A simple class that allows a plug-in to access a WebPluginIMEWin instance 72 // only in a scope. 73 class ScopedLock { 74 public: 75 explicit ScopedLock(WebPluginIMEWin* instance) : instance_(instance) { 76 if (instance_) 77 instance_->Lock(); 78 } 79 ~ScopedLock() { 80 if (instance_) 81 instance_->Unlock(); 82 } 83 84 private: 85 WebPluginIMEWin* instance_; 86 }; 87 88 WebPluginIMEWin(); 89 ~WebPluginIMEWin(); 90 91 // Sends raw IME events sent from a browser to this IME emulator and updates 92 // the list of Windows events to be sent to a plug-in. A raw IME event is 93 // mapped to two or more Windows events and it is not so trivial to send these 94 // Windows events to a plug-in. This function inserts Windows events in the 95 // order expected by a plug-in. 96 void CompositionUpdated(const base::string16& text, 97 std::vector<int> clauses, 98 std::vector<int> target, 99 int cursor_position); 100 void CompositionCompleted(const base::string16& text); 101 102 // Send all the events added in Update() to a plug-in. 103 bool SendEvents(PluginInstance* instance); 104 105 // Retrieves the status of this IME emulator. 106 bool GetStatus(int* input_type, gfx::Rect* caret_rect); 107 108 // Returns the pointers to IMM32-emulation functions implemented by this 109 // class. This function is used for over-writing the ones returned from 110 // GetProcAddress() calls of Win32 API. 111 static FARPROC GetProcAddress(const char* name); 112 113 private: 114 // Allow (or disallow) the patch functions to use this WebPluginIMEWin 115 // instance through our patch functions. Our patch functions need a static 116 // member variable |instance_| to access a WebPluginIMEWIn instance. We lock 117 // this static variable to prevent two or more plug-ins from accessing a 118 // WebPluginIMEWin instance. 119 void Lock(); 120 void Unlock(); 121 122 // Retrieve the instance of this class. 123 static WebPluginIMEWin* GetInstance(HIMC context); 124 125 // IMM32 patch functions implemented by this class. 126 static BOOL WINAPI ImmAssociateContextEx(HWND window, 127 HIMC context, 128 DWORD flags); 129 static LONG WINAPI ImmGetCompositionStringW(HIMC context, 130 DWORD index, 131 LPVOID dst_data, 132 DWORD dst_size); 133 static HIMC WINAPI ImmGetContext(HWND window); 134 static BOOL WINAPI ImmReleaseContext(HWND window, HIMC context); 135 static BOOL WINAPI ImmSetCandidateWindow(HIMC context, 136 CANDIDATEFORM* candidate); 137 static BOOL WINAPI ImmSetOpenStatus(HIMC context, BOOL open); 138 139 // a list of NPEvents to be sent to a plug-in. 140 std::vector<NPEvent> events_; 141 142 // The return value for GCS_COMPSTR. 143 base::string16 composition_text_; 144 145 // The return value for GCS_RESULTSTR. 146 base::string16 result_text_; 147 148 // The return value for GCS_COMPATTR. 149 std::string composition_attributes_; 150 151 // The return value for GCS_COMPCLAUSE. 152 std::vector<uint32> composition_clauses_; 153 154 // The return value for GCS_RESULTCLAUSE. 155 uint32 result_clauses_[2]; 156 157 // The return value for GCS_CURSORPOS. 158 int cursor_position_; 159 160 // The return value for GCS_DELTASTART. 161 int delta_start_; 162 163 // Whether we are composing text. This variable is used for sending a 164 // WM_IME_STARTCOMPOSITION message when we start composing IME text. 165 bool composing_text_; 166 167 // Whether a plug-in supports IME messages. When a plug-in cannot handle 168 // IME messages, we need to send the IME text with WM_CHAR messages as Windows 169 // does. 170 bool support_ime_messages_; 171 172 // The IME status received from a plug-in. 173 bool status_updated_; 174 int input_type_; 175 gfx::Rect caret_rect_; 176 177 // The pointer to the WebPluginIMEWin instance used by patch functions. 178 static WebPluginIMEWin* instance_; 179 }; 180 181 } // namespace content 182 183 #endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_ 184