Merge lp:~unity-team/unity/unity.text-entry-im into lp:unity

Proposed by Brandon Schaefer
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 2011
Proposed branch: lp:~unity-team/unity/unity.text-entry-im
Merge into: lp:unity
Diff against target: 377 lines (+27/-251)
3 files modified
plugins/unityshell/src/DashController.cpp (+2/-0)
plugins/unityshell/src/IMTextEntry.cpp (+24/-221)
plugins/unityshell/src/IMTextEntry.h (+1/-30)
To merge this branch: bzr merge lp:~unity-team/unity/unity.text-entry-im
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Needs Fixing
Tim Penhey (community) Approve
Jay Taoko (community) Approve
Thomi Richards (community) Approve
Review via email: mp+94305@code.launchpad.net

Commit message

IMTextEntry now only handles copy/cut and pasting, everything else is in nux::TextEntry

To post a comment you must log in.
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

I've had a look through this, and it looks good to me.

review: Approve
Revision history for this message
Jay Taoko (jaytaoko) wrote :

Approved!

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/333/console reported an error when processing this lp:~unity-team/unity/unity.text-entry-im branch.
Not merging it.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

-- checking for modules 'compiz;nux-2.0>=2.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;gnome-desktop-3.0;gdu;ibus-1.0;unity>=4.99.0'
-- package 'ibus-1.0' not found

Hmm I thought "libibus-1.0-dev" had been added to unity

Revision history for this message
Tim Penhey (thumper) wrote :

Changes look good, lets try it.

review: Approve
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :
review: Needs Fixing
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Sorry, I must have missed that while deleting everything! Here is the fix again:
https://code.launchpad.net/~brandontschaefer/unity/unity.fix-middle-paste-reg/+merge/94441

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/DashController.cpp'
2--- plugins/unityshell/src/DashController.cpp 2012-02-15 10:54:48 +0000
3+++ plugins/unityshell/src/DashController.cpp 2012-02-23 10:16:31 +0000
4@@ -278,6 +278,8 @@
5 window_->EnableInputWindow(false, "Dash", true, false);
6 visible_ = false;
7
8+ nux::GetWindowCompositor().SetKeyFocusArea(NULL,nux::KEY_NAV_NONE);
9+
10 if (restore)
11 PluginAdapter::Default ()->restoreInputFocus ();
12
13
14=== modified file 'plugins/unityshell/src/IMTextEntry.cpp'
15--- plugins/unityshell/src/IMTextEntry.cpp 2012-02-23 08:55:35 +0000
16+++ plugins/unityshell/src/IMTextEntry.cpp 2012-02-23 10:16:31 +0000
17@@ -21,7 +21,6 @@
18
19 #include "IMTextEntry.h"
20
21-#include <boost/lexical_cast.hpp>
22 #include <NuxCore/Logger.h>
23 #include <UnityCore/GLibWrapper.h>
24
25@@ -36,127 +35,20 @@
26 NUX_IMPLEMENT_OBJECT_TYPE(IMTextEntry);
27
28 IMTextEntry::IMTextEntry()
29- : TextEntry("", "", 80085)
30- , preedit_string("")
31- , im_enabled(false)
32- , im_active(false)
33- , focused_(false)
34-{
35- g_setenv("IBUS_ENABLE_SYNC_MODE", "1", TRUE);
36- CheckIMEnabled();
37- im_enabled ? SetupMultiIM() : SetupSimpleIM();
38-
39- key_nav_focus_change.connect([&](nux::Area* area, bool focus, nux::KeyNavDirection dir)
40- {
41- focus ? OnFocusIn() : OnFocusOut();
42- });
43- mouse_up.connect(sigc::mem_fun(this, &IMTextEntry::OnMouseButtonUp));
44-}
45-
46-void IMTextEntry::CheckIMEnabled()
47-{
48- const char* module = g_getenv("GTK_IM_MODULE");
49- if (module &&
50- g_strcmp0(module, "") &&
51- g_strcmp0(module, "gtk-im-context-simple"))
52- im_enabled = true;
53-
54- LOG_DEBUG(logger) << "Input method support is "
55- << (im_enabled ? "enabled" : "disabled");
56-}
57-
58-void IMTextEntry::SetupSimpleIM()
59-{
60- im_context_ = gtk_im_context_simple_new();
61-
62- sig_manager_.Add(new Signal<void, GtkIMContext*, char*>(im_context_, "commit", sigc::mem_fun(this, &IMTextEntry::OnCommit)));
63- sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-changed", sigc::mem_fun(this, &IMTextEntry::OnPreeditChanged)));
64- sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-start", sigc::mem_fun(this, &IMTextEntry::OnPreeditStart)));
65- sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-end", sigc::mem_fun(this, &IMTextEntry::OnPreeditEnd)));
66-}
67-
68-void IMTextEntry::SetupMultiIM()
69-{
70- im_context_ = gtk_im_multicontext_new();
71-
72- sig_manager_.Add(new Signal<void, GtkIMContext*, char*>(im_context_, "commit", sigc::mem_fun(this, &IMTextEntry::OnCommit)));
73- sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-changed", sigc::mem_fun(this, &IMTextEntry::OnPreeditChanged)));
74- sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-start", sigc::mem_fun(this, &IMTextEntry::OnPreeditStart)));
75- sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-end", sigc::mem_fun(this, &IMTextEntry::OnPreeditEnd)));
76+ : TextEntry("", NUX_TRACKER_LOCATION)
77+{
78 }
79
80 bool IMTextEntry::InspectKeyEvent(unsigned int event_type,
81 unsigned int keysym,
82 const char* character)
83 {
84- bool propagate_event = !(TryHandleEvent(event_type, keysym, character));
85-
86- LOG_DEBUG(logger) << "Input method "
87- << (im_enabled ? gtk_im_multicontext_get_context_id(glib::object_cast<GtkIMMulticontext>(im_context_)) : "simple")
88- << " "
89- << (propagate_event ? "did not handle " : "handled ")
90- << "event ("
91- << (event_type == NUX_KEYDOWN ? "press" : "release")
92- << ") ";
93-
94- if (propagate_event)
95- propagate_event = !TryHandleSpecial(event_type, keysym, character);
96-
97- if (propagate_event)
98- {
99- text_input_mode_ = event_type == NUX_KEYDOWN;
100- propagate_event = TextEntry::InspectKeyEvent(event_type, keysym, character);
101- text_input_mode_ = false;
102-
103- UpdateCursorLocation();
104- }
105- return propagate_event;
106-}
107-
108-bool IMTextEntry::TryHandleEvent(unsigned int eventType,
109- unsigned int keysym,
110- const char* character)
111-{
112- nux::Event event = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent();
113-
114- CheckValidClientWindow(event.x11_window);
115-
116- GdkEventKey ev;
117- KeyEventToGdkEventKey(event, ev);
118-
119- return gtk_im_context_filter_keypress(im_context_, &ev);
120-}
121-
122-inline void IMTextEntry::CheckValidClientWindow(Window window)
123-{
124- if (!client_window_)
125- {
126- client_window_ = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), window);
127- gtk_im_context_set_client_window(im_context_, client_window_);
128-
129- if (focused_)
130- {
131- gtk_im_context_focus_in(im_context_);
132- }
133- }
134-}
135-
136-void IMTextEntry::KeyEventToGdkEventKey(Event& event, GdkEventKey& gdk_event)
137-{
138- gdk_event.type = event.type == nux::NUX_KEYDOWN ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
139- gdk_event.window = client_window_;
140- gdk_event.send_event = FALSE;
141- gdk_event.time = event.x11_timestamp;
142- gdk_event.state = event.x11_key_state;
143- gdk_event.keyval = event.x11_keysym;
144-
145- gchar* txt = const_cast<gchar*>(event.GetText());
146- gdk_event.length = strlen(txt);
147- gdk_event.string = txt;
148-
149- gdk_event.hardware_keycode = event.x11_keycode;
150- gdk_event.group = 0;
151- gdk_event.is_modifier = 0;
152+ bool need_to_filter_event = TryHandleSpecial(event_type, keysym, character);
153+
154+ if (need_to_filter_event)
155+ need_to_filter_event = TextEntry::InspectKeyEvent(event_type, keysym, character);
156+
157+ return need_to_filter_event;
158 }
159
160 bool IMTextEntry::TryHandleSpecial(unsigned int eventType, unsigned int keysym, const char* character)
161@@ -166,13 +58,14 @@
162 bool shift = (event.GetKeyState() & NUX_STATE_SHIFT);
163 bool ctrl = (event.GetKeyState() & NUX_STATE_CTRL);
164
165+ /* If there is preedit, handle the event else where, but we
166+ want to be able to copy/paste while ibus is active */
167+ if (!preedit_.empty())
168+ return true;
169+
170 if (eventType != NUX_KEYDOWN)
171 return false;
172
173- /* If IM is active, de-activate Copy & Paste */
174- if (im_active)
175- return true;
176-
177 if (((keyval == NUX_VK_x) && ctrl && !shift) ||
178 ((keyval == NUX_VK_DELETE) && shift && !ctrl))
179 {
180@@ -194,15 +87,16 @@
181 }
182 else
183 {
184- return false;
185+ return true;
186 }
187- return true;
188+ return false;
189 }
190
191 void IMTextEntry::Cut()
192 {
193 Copy();
194 DeleteSelection();
195+ QueueRefresh (true, true);
196 }
197
198 void IMTextEntry::Copy()
199@@ -221,122 +115,31 @@
200 GdkAtom origin = primary ? GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD;
201 glib::Object<GtkClipboard> clip(gtk_clipboard_get_for_display(gdk_display_get_default(),
202 origin));
203+
204 auto callback = [](GtkClipboard* clip, const char* text, gpointer user_data)
205 {
206 IMTextEntry* self = static_cast<IMTextEntry*>(user_data);
207 if (text)
208- self->InsertTextAt(self->cursor_, std::string(text));
209+ self->InsertText(std::string(text));
210 };
211
212 gtk_clipboard_request_text(clip, callback, this);
213 }
214
215-void IMTextEntry::InsertTextAt(unsigned int position, std::string const& text)
216+void IMTextEntry::InsertText(std::string const& text)
217 {
218 DeleteSelection();
219
220 if (!text.empty())
221 {
222 std::string new_text(GetText());
223- new_text.insert(position, text);
224+ new_text.insert(cursor_, text);
225
226- int cursor = position;
227+ int cursor = cursor_;
228 SetText(new_text.c_str());
229 SetCursor(cursor + text.length());
230- UpdateCursorLocation();
231- }
232-}
233-
234-void IMTextEntry::OnCommit(GtkIMContext* context, char* str)
235-{
236- LOG_DEBUG(logger) << "Commit: " << str;
237- DeleteSelection();
238-
239- if (str)
240- {
241- InsertTextAt(cursor_, std::string(str));
242- }
243-}
244-
245-void IMTextEntry::OnPreeditChanged(GtkIMContext* context)
246-{
247- glib::String preedit;
248- int cursor_pos = -1;
249-
250- gtk_im_context_get_preedit_string(context, &preedit, &preedit_attrs_, &cursor_pos);
251-
252- LOG_DEBUG(logger) << "Preedit changed: " << preedit;
253-
254- preedit_ = preedit.Str();
255-
256- if (!preedit.Str().empty()) {
257- preedit_cursor_ = preedit.Str().length();
258- QueueRefresh(true, true);
259+ QueueRefresh (true, true);
260 text_changed.emit(this);
261- UpdateCursorLocation();
262- }
263-}
264-
265-void IMTextEntry::OnPreeditStart(GtkIMContext* context)
266-{
267- im_active = true;
268-
269- LOG_DEBUG(logger) << "Preedit start";
270-}
271-
272-void IMTextEntry::OnPreeditEnd(GtkIMContext* context)
273-{
274- im_active = false;
275- ResetPreedit();
276- gtk_im_context_reset(im_context_);
277-
278- QueueRefresh(true, true);
279- text_changed.emit(this);
280-
281- LOG_DEBUG(logger) << "Preedit ended";
282-}
283-
284-void IMTextEntry::OnFocusIn()
285-{
286- focused_ = true;
287- gtk_im_context_focus_in(im_context_);
288- gtk_im_context_reset(im_context_);
289- UpdateCursorLocation();
290-}
291-
292-void IMTextEntry::OnFocusOut()
293-{
294- focused_ = false;
295- gtk_im_context_focus_out(im_context_);
296-}
297-
298-void IMTextEntry::UpdateCursorLocation()
299-{
300- nux::Rect strong, weak;
301- GetCursorRects(&strong, &weak);
302- nux::Geometry geo = GetGeometry();
303-
304- GdkRectangle area = { strong.x + geo.x, strong.y + geo.y, strong.width, strong.height };
305- gtk_im_context_set_cursor_location(im_context_, &area);
306-}
307-
308-void IMTextEntry::OnMouseButtonUp(int x, int y, unsigned long bflags, unsigned long kflags)
309-{
310- int button = nux::GetEventButton(bflags);
311-
312- if (im_enabled && button == 3)
313- {
314- GtkWidget* menu = gtk_menu_new();
315- gtk_im_multicontext_append_menuitems(glib::object_cast<GtkIMMulticontext>(im_context_),
316- GTK_MENU_SHELL(menu));
317- gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, GDK_CURRENT_TIME);
318- }
319- else if (button == 2)
320- {
321- SetCursor(XYToTextIndex(x, y));
322- UpdateCursorLocation();
323- Paste(true);
324- }
325-}
326-
327+ }
328+}
329 }
330
331=== modified file 'plugins/unityshell/src/IMTextEntry.h'
332--- plugins/unityshell/src/IMTextEntry.h 2012-02-13 09:49:45 +0000
333+++ plugins/unityshell/src/IMTextEntry.h 2012-02-23 10:16:31 +0000
334@@ -40,42 +40,13 @@
335 public:
336 IMTextEntry();
337
338- nux::Property<std::string> preedit_string;
339- nux::Property<bool> im_enabled;
340- nux::Property<bool> im_active;
341-
342 private:
343- void CheckIMEnabled();
344- void SetupSimpleIM();
345- void SetupMultiIM();
346-
347 bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character);
348- bool TryHandleEvent(unsigned int eventType, unsigned int keysym, const char* character);
349- void KeyEventToGdkEventKey(Event& event, GdkEventKey& gdk_event);
350- inline void CheckValidClientWindow(Window window);
351 bool TryHandleSpecial(unsigned int eventType, unsigned int keysym, const char* character);
352- void InsertTextAt(unsigned int position, std::string const& text);
353+ void InsertText(std::string const& text);
354 void Cut();
355 void Copy();
356 void Paste(bool primary = false);
357-
358- void OnCommit(GtkIMContext* context, char* str);
359- void OnPreeditChanged(GtkIMContext* context);
360- void OnPreeditStart(GtkIMContext* context);
361- void OnPreeditEnd(GtkIMContext* context);
362-
363- void OnFocusIn();
364- void OnFocusOut();
365-
366- void UpdateCursorLocation();
367-
368- void OnMouseButtonUp(int x, int y, unsigned long bflags, unsigned long kflags);
369-
370- private:
371- glib::SignalManager sig_manager_;
372- glib::Object<GtkIMContext> im_context_;
373- glib::Object<GdkWindow> client_window_;
374- bool focused_;
375 };
376
377 }