Merge lp:~3v1n0/unity/middle-click-paste-in-dash into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Mirco Müller
Approved revision: no longer in the source branch.
Merged at revision: 1870
Proposed branch: lp:~3v1n0/unity/middle-click-paste-in-dash
Merge into: lp:unity
Diff against target: 218 lines (+59/-33)
3 files modified
manual-tests/Dash.txt (+15/-0)
plugins/unityshell/src/IMTextEntry.cpp (+39/-29)
plugins/unityshell/src/IMTextEntry.h (+5/-4)
To merge this branch: bzr merge lp:~3v1n0/unity/middle-click-paste-in-dash
Reviewer Review Type Date Requested Status
Mirco Müller (community) Approve
Andrea Azzarone (community) Approve
Review via email: mp+87311@code.launchpad.net

Description of the change

Add support to middle-click pasting on the dash search bar.

When the XA_PRIMARY clipboard has some content, that is pasted by middle click over the dash search bar.
This is for consistency with the rest of the system.

I've also added the proper glib::Object support to the class.

To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote :

Middle-click pasting doesn't work. Only Ctrl-V allows me to paste into the dash's search-bar.

review: Needs Fixing
Revision history for this message
Andrea Azzarone (azzar1) wrote :

150 + if (!im_enabled)
151 + return;

This if is no longer needed.

review: Needs Fixing
Revision history for this message
Andrea Azzarone (azzar1) wrote :

Just to be clear you should do either:

if (button == 3 and im_enabled)
{
}
else if (button == 2)
or

if (!im_enabled and button != 2)
  return;

if (button == 3)
{
}
else if (button == 2)
{
}

...

I'd prefer the former.

Revision history for this message
Andrea Azzarone (azzar1) :
review: Approve
Revision history for this message
Andrea Azzarone (azzar1) wrote :

+1

Revision history for this message
Mirco Müller (macslow) wrote :

Finally works now for me too.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'manual-tests/Dash.txt'
2--- manual-tests/Dash.txt 2011-12-18 19:38:55 +0000
3+++ manual-tests/Dash.txt 2012-01-05 15:07:25 +0000
4@@ -36,3 +36,18 @@
5 The dropped icon should not have the keyboard focus and should not remain
6 enlightened.
7
8+Dash SearchBar middle-click
9+---------------------------
10+This test shows how the middle click over the dash search bar should work
11+(see lp:842462)
12+
13+#. Open a text editor, and write some dummy text
14+#. Select some text part of the written dummy text with mouse
15+#. Press Super or Alt+F2 to open the Dash
16+#. Move the mouse over the dash search bar
17+#. Press middle click to paste the content of your primary clipboard
18+
19+Outcome
20+ The text previously selected is pasted on the search bar at mouse pointer
21+ position, if the operation is repeated the text is inserted where
22+ the mouse pointer is.
23
24=== modified file 'plugins/unityshell/src/IMTextEntry.cpp'
25--- plugins/unityshell/src/IMTextEntry.cpp 2011-12-10 06:41:53 +0000
26+++ plugins/unityshell/src/IMTextEntry.cpp 2012-01-05 15:07:25 +0000
27@@ -42,8 +42,6 @@
28 , preedit_string("")
29 , im_enabled(false)
30 , im_active(false)
31- , im_context_(0)
32- , client_window_(0)
33 , focused_(false)
34 {
35 g_setenv("IBUS_ENABLE_SYNC_MODE", "1", TRUE);
36@@ -53,14 +51,6 @@
37 mouse_up.connect(sigc::mem_fun(this, &IMTextEntry::OnMouseButtonUp));
38 }
39
40-IMTextEntry::~IMTextEntry()
41-{
42- if (im_context_)
43- g_object_unref(im_context_);
44- if (client_window_)
45- g_object_unref(client_window_);
46-}
47-
48 void IMTextEntry::CheckIMEnabled()
49 {
50 const char* module = g_getenv("GTK_IM_MODULE");
51@@ -76,7 +66,7 @@
52 void IMTextEntry::SetupSimpleIM()
53 {
54 im_context_ = gtk_im_context_simple_new();
55-
56+
57 sig_manager_.Add(new Signal<void, GtkIMContext*, char*>(im_context_, "commit", sigc::mem_fun(this, &IMTextEntry::OnCommit)));
58 sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-changed", sigc::mem_fun(this, &IMTextEntry::OnPreeditChanged)));
59 sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-start", sigc::mem_fun(this, &IMTextEntry::OnPreeditStart)));
60@@ -86,7 +76,7 @@
61 void IMTextEntry::SetupMultiIM()
62 {
63 im_context_ = gtk_im_multicontext_new();
64-
65+
66 sig_manager_.Add(new Signal<void, GtkIMContext*, char*>(im_context_, "commit", sigc::mem_fun(this, &IMTextEntry::OnCommit)));
67 sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-changed", sigc::mem_fun(this, &IMTextEntry::OnPreeditChanged)));
68 sig_manager_.Add(new Signal<void, GtkIMContext*>(im_context_, "preedit-start", sigc::mem_fun(this, &IMTextEntry::OnPreeditStart)));
69@@ -100,7 +90,7 @@
70 bool propagate_event = !(TryHandleEvent(event_type, keysym, character));
71
72 LOG_DEBUG(logger) << "Input method "
73- << (im_enabled ? gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(im_context_)) : "simple")
74+ << (im_enabled ? gtk_im_multicontext_get_context_id(glib::object_cast<GtkIMMulticontext>(im_context_)) : "simple")
75 << " "
76 << (propagate_event ? "did not handle " : "handled ")
77 << "event ("
78@@ -224,19 +214,37 @@
79 }
80 }
81
82-void IMTextEntry::Paste()
83+void IMTextEntry::Paste(bool primary)
84 {
85- GtkClipboard* clip = gtk_clipboard_get_for_display(gdk_display_get_default(),
86- GDK_SELECTION_CLIPBOARD);
87+ GdkAtom origin = primary ? GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD;
88+ glib::Object<GtkClipboard> clip(gtk_clipboard_get_for_display(gdk_display_get_default(),
89+ origin));
90 auto callback = [](GtkClipboard* clip, const char* text, gpointer user_data)
91 {
92 IMTextEntry* self = static_cast<IMTextEntry*>(user_data);
93- self->OnCommit (self->im_context_, const_cast<char*>(text));
94+ if (text)
95+ self->InsertTextAt(self->cursor_, std::string(text));
96 };
97
98 gtk_clipboard_request_text(clip, callback, this);
99 }
100
101+void IMTextEntry::InsertTextAt(unsigned int position, std::string const& text)
102+{
103+ DeleteSelection();
104+
105+ if (!text.empty())
106+ {
107+ std::string new_text(GetText());
108+ new_text.insert(position, text);
109+
110+ int cursor = position;
111+ SetText(new_text.c_str());
112+ SetCursor(cursor + text.length());
113+ UpdateCursorLocation();
114+ }
115+}
116+
117 void IMTextEntry::OnCommit(GtkIMContext* context, char* str)
118 {
119 LOG_DEBUG(logger) << "Commit: " << str;
120@@ -244,13 +252,7 @@
121
122 if (str)
123 {
124- std::string new_text = GetText();
125- new_text.insert(cursor_, str);
126-
127- int cursor = cursor_;
128- SetText(new_text.c_str());
129- SetCursor(cursor + strlen(str));
130- UpdateCursorLocation();
131+ InsertTextAt(cursor_, std::string(str));
132 }
133 }
134
135@@ -265,7 +267,7 @@
136
137 preedit_ = preedit.Str();
138
139- if (strlen(preedit.Str().c_str())) {
140+ if (!preedit.Str().empty()) {
141 preedit_cursor_ = preedit.Str().length();
142 QueueRefresh(true, true);
143 sigTextChanged.emit(this);
144@@ -311,20 +313,28 @@
145 nux::Rect strong, weak;
146 GetCursorRects(&strong, &weak);
147 nux::Geometry geo = GetGeometry();
148-
149+
150 GdkRectangle area = { strong.x + geo.x, strong.y + geo.y, strong.width, strong.height };
151 gtk_im_context_set_cursor_location(im_context_, &area);
152 }
153
154 void IMTextEntry::OnMouseButtonUp(int x, int y, unsigned long bflags, unsigned long kflags)
155 {
156- if (nux::GetEventButton(bflags) == 3 && im_enabled)
157+ int button = nux::GetEventButton(bflags);
158+
159+ if (im_enabled && button == 3)
160 {
161 GtkWidget* menu = gtk_menu_new();
162- gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(im_context_),
163- GTK_MENU_SHELL(menu));
164+ gtk_im_multicontext_append_menuitems(glib::object_cast<GtkIMMulticontext>(im_context_),
165+ GTK_MENU_SHELL(menu));
166 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, GDK_CURRENT_TIME);
167 }
168+ else if (button == 2)
169+ {
170+ SetCursor(XYToTextIndex(x, y));
171+ UpdateCursorLocation();
172+ Paste(true);
173+ }
174 }
175
176 }
177
178=== modified file 'plugins/unityshell/src/IMTextEntry.h'
179--- plugins/unityshell/src/IMTextEntry.h 2011-09-29 08:16:37 +0000
180+++ plugins/unityshell/src/IMTextEntry.h 2012-01-05 15:07:25 +0000
181@@ -26,6 +26,7 @@
182 #include <Nux/Nux.h>
183 #include <Nux/TextEntry.h>
184 #include <UnityCore/GLibSignal.h>
185+#include <UnityCore/GLibWrapper.h>
186
187 namespace unity
188 {
189@@ -40,7 +41,6 @@
190 NUX_DECLARE_OBJECT_TYPE(IMTextEntry, nux::TextEntry);
191 public:
192 IMTextEntry();
193- ~IMTextEntry();
194
195 nux::Property<std::string> preedit_string;
196 nux::Property<bool> im_enabled;
197@@ -56,9 +56,10 @@
198 void KeyEventToGdkEventKey(Event& event, GdkEventKey& gdk_event);
199 inline void CheckValidClientWindow(Window window);
200 bool TryHandleSpecial(unsigned int eventType, unsigned int keysym, const char* character);
201+ void InsertTextAt(unsigned int position, std::string const& text);
202 void Cut();
203 void Copy();
204- void Paste();
205+ void Paste(bool primary = false);
206
207 void OnCommit(GtkIMContext* context, char* str);
208 void OnPreeditChanged(GtkIMContext* context);
209@@ -73,8 +74,8 @@
210
211 private:
212 glib::SignalManager sig_manager_;
213- GtkIMContext* im_context_;
214- GdkWindow* client_window_;
215+ glib::Object<GtkIMContext> im_context_;
216+ glib::Object<GdkWindow> client_window_;
217 bool focused_;
218 };
219