After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 592405 - Enhance GtkTextView to support fine-grained control of its behaviors to user actions.
Enhance GtkTextView to support fine-grained control of its behaviors to user ...
Status: RESOLVED OBSOLETE
Product: gtk+
Classification: Platform
Component: Widget: GtkTextView
unspecified
Other All
: Normal enhancement
: ---
Assigned To: gtk-bugs
gtk-bugs
: 615660 (view as bug list)
Depends on:
Blocks: 163251
 
 
Reported: 2009-08-20 05:19 UTC by James Su
Modified: 2018-02-10 03:24 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
new signals v1 (11.22 KB, patch)
2010-02-11 00:16 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
new signals v2 (11.80 KB, patch)
2010-02-11 14:05 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
new signals v3 (8.73 KB, patch)
2010-02-12 18:09 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
new signals v4 (10.71 KB, patch)
2010-02-12 19:25 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
new signals v5 (11.38 KB, patch)
2010-02-12 23:17 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review

Description James Su 2009-08-20 05:19:43 UTC
Right now GtkTextView provides several signals and virtual functions to help customer controls its behaviors. For example, "backspace" signal can be intercepted to adjust the behavior of GtkTextView when user presses Backspace key.

But such facilities provided by GtkTextView are far from enough. For exapmle, some applications may want to adjust the behavior of GtkTextView when user presses Enter and Tab key. GtkSourceView is a very good example for it. For now, application must intercept "key-press-event" to achieve such goal, but it causes many problems, mainly related to im context and key bindings. You may refer to GtkSourceView's source code, especially the gtk_source_view_key_press_event() function, to see how tricky it is.

I think Mac OSX's NSTextView would be very good example in this area, which provides much more action messages to help customize its behavior, see:
http://developer.apple.com/documentation/Cocoa/Conceptual/TextEditing/TextEditing.html
http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html

For example, NSTextView supports following action messages that can be intercepted by customer:

    * – cancelOperation:
    * – capitalizeWord:
    * – centerSelectionInVisibleArea:
    * – changeCaseOfLetter:
    * – complete:
    * – deleteBackward:
    * – deleteBackwardByDecomposingPreviousCharacter:
    * – deleteForward:
    * – deleteToBeginningOfLine:
    * – deleteToBeginningOfParagraph:
    * – deleteToEndOfLine:
    * – deleteToEndOfParagraph:
    * – deleteToMark:
    * – deleteWordBackward:
    * – deleteWordForward:
    * – indent:
    * – insertBacktab:
    * – insertContainerBreak:
    * – insertLineBreak:
    * – insertNewline:
    * – insertNewlineIgnoringFieldEditor:
    * – insertParagraphSeparator:
    * – insertTab:
    * – insertTabIgnoringFieldEditor:
    * – insertText:
    * – lowercaseWord:
    * – moveBackward:
    * – moveBackwardAndModifySelection:
    * – moveDown:
    * – moveDownAndModifySelection:
    * – moveForward:
    * – moveForwardAndModifySelection:
    * – moveLeft:
    * – moveLeftAndModifySelection:
    * – moveRight:
    * – moveRightAndModifySelection:
    * – moveToBeginningOfDocument:
    * – moveToBeginningOfLine:
    * – moveToBeginningOfParagraph:
    * – moveToEndOfDocument:
    * – moveToEndOfLine:
    * – moveToEndOfParagraph:
    * – moveUp:
    * – moveUpAndModifySelection:
    * – moveWordBackward:
    * – moveWordBackwardAndModifySelection:
    * – moveWordForward:
    * – moveWordForwardAndModifySelection:
    * – moveWordLeft:
    * – moveWordRight:
    * – moveWordRightAndModifySelection:
    * – moveWordLeftAndModifySelection:
    * – pageDown:
    * – pageUp:
    * – scrollLineDown:
    * – scrollLineUp:
    * – scrollPageDown:
    * – scrollPageUp:
    * – selectAll:
    * – selectLine:
    * – selectParagraph:
    * – selectToMark:
    * – selectWord:
    * – setMark:
    * – showContextHelp:
    * – swapWithMark:
    * – transpose:
    * – transposeWords:
    * – uppercaseWord:
    * – yank:

For exapmle, one can intercept insertTab message to change the behavior of Tab key press without interfering with key event handler and input method.

So my proposal is to add similar action signals to GtkTextView (at least some of them) to make it much easier to control GtkTextView's behavior.

IMHO, following action signals would be very useful:
"insert-tab" (default binding is Tab key)
"insert-back-tab" (default binding is shift-Tab key)
"insert-new-line" (default binding is Enter key)
"insert-line-break" (default binding is ctrl-Enter key)
"cancel-operation" (default binding is Escape key)

With these action signals, applications like GtkSourceView would not need to access GtkTextView's im_context anymore and the code would be simplified.
Comment 1 Ignacio Casal Quinteiro (nacho) 2010-02-11 00:16:05 UTC
Created attachment 153494 [details] [review]
new signals v1

This patch isn't finished:

1) the methods names sucks a bit
2) Also the enums names, the thing here is that in text view all makes the same. ie. control+return makes the same as return, shit+tab it makes the same as tab.
3) The doc needs to be completed.
Comment 2 Matthias Clasen 2010-02-11 03:46:22 UTC
Hmm, looking at the gtksourceview code, I don't actually see the use of C-Enter.
And if we are just looking at Tab/S-Tab/Enter/S-Enter, I think I prefer the

"insert-tab"
"insert-back-tab"
"insert-new-line"
"insert-line-break"

approach.
Comment 3 Ignacio Casal Quinteiro (nacho) 2010-02-11 14:05:27 UTC
Created attachment 153529 [details] [review]
new signals v2

Ok, added the 4 signals. insert-new-line and insert-line-back uses the same handler, and insert-tab and insert-back-tab uses also the same same. Hope this is ok.
Comment 4 Christian Dywan 2010-02-12 15:31:15 UTC
(In reply to comment #3)
> Created an attachment (id=153529) [details] [review]
> new signals v2

+/**
+ * gtk_text_buffer_insert_new_line:
+ * @buffer: a #GtkTextBuffer
+ * @iter: a position in @buffer
+ * @interactive: whether the deletion is caused by user interaction
+ * @default_editable: whether the buffer is editable by default
+ * 
+ * Performs the appropriate action as if the user hit the enter
+ * key with the cursor at the position specified by @iter.
+ * 
+ * Because the buffer is modified, all outstanding iterators become
+ * invalid after calling this function; however, the @iter will be
+ * re-initialized to point to the location where text was deleted.
+ *
+ * Since: 2.20
+ **/

Look like convenience functions to me. Are those commonly used in applications?

+  /**
+   * GtkTextView::insert-back-tab:
+   * @text_view: the object which received the signal
+   *
+   * The ::insert-back-tab signal is a 
+   * <link linkend="keybinding-signals">keybinding signal</link> 
+   * which gets emitted when the user asks for it.
+   *
+   * The default bindings for this signal is
+   * GDK_ISO_Left_Tab.
+   */
+  signals[INSERT_BACK_TAB] =
+    g_signal_new (I_("insert-back-tab"),
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GtkTextViewClass, insert_back_tab),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);

There is no explanation what insert-back-tab does, or how it is different from insert-tab and it looks like the implementation is indentical. What's the use case?

All signals are missing Since tags.
Comment 5 Ignacio Casal Quinteiro (nacho) 2010-02-12 16:12:03 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > Created an attachment (id=153529) [details] [review] [details] [review]
> > new signals v2
> 
> +/**
> + * gtk_text_buffer_insert_new_line:
> + * @buffer: a #GtkTextBuffer
> + * @iter: a position in @buffer
> + * @interactive: whether the deletion is caused by user interaction
> + * @default_editable: whether the buffer is editable by default
> + * 
> + * Performs the appropriate action as if the user hit the enter
> + * key with the cursor at the position specified by @iter.
> + * 
> + * Because the buffer is modified, all outstanding iterators become
> + * invalid after calling this function; however, the @iter will be
> + * re-initialized to point to the location where text was deleted.
> + *
> + * Since: 2.20
> + **/
> 
> Look like convenience functions to me. Are those commonly used in applications?
Well, I just followed the case of the backspace, they could be removed easily though, mclasen told me that they were ok.

> 
> +  /**
> +   * GtkTextView::insert-back-tab:
> +   * @text_view: the object which received the signal
> +   *
> +   * The ::insert-back-tab signal is a 
> +   * <link linkend="keybinding-signals">keybinding signal</link> 
> +   * which gets emitted when the user asks for it.
> +   *
> +   * The default bindings for this signal is
> +   * GDK_ISO_Left_Tab.
> +   */
> +  signals[INSERT_BACK_TAB] =
> +    g_signal_new (I_("insert-back-tab"),
> +          G_OBJECT_CLASS_TYPE (gobject_class),
> +          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
> +          G_STRUCT_OFFSET (GtkTextViewClass, insert_back_tab),
> +          NULL, NULL,
> +          _gtk_marshal_VOID__VOID,
> +          G_TYPE_NONE, 0);
> 
> There is no explanation what insert-back-tab does, or how it is different from
> insert-tab and it looks like the implementation is indentical. What's the use
> case?
About this, right now textview manages that cases in the same way that's why they use the same handler. Also the reason for this is because we need to listen to this signals in gtksourceview. So to get rid to the call of textview->im_context we need this.

> 
> All signals are missing Since tags.
Sorry about the since.
Comment 6 Christian Dywan 2010-02-12 16:58:21 UTC
(In reply to comment #5)
> (In reply to comment #4)
> > (In reply to comment #3)
> > > Created an attachment (id=153529) [details] [review] [details] [review] [details] [review]
> > > new signals v2
> > + * gtk_text_buffer_insert_new_line:
> > [...]
> > Look like convenience functions to me. Are those commonly used in applications?
> Well, I just followed the case of the backspace, they could be removed easily
> though, mclasen told me that they were ok.

gtk_text_buffer_backspace is more complex and requires knowledge of text buffer internals. By comparison, gtk_text_buffer_insert_new_line is a no-brainer. That's why I asked where it's needed outside of GTK+.

> > +  /**
> > +   * GtkTextView::insert-back-tab:
> > +   * @text_view: the object which received the signal
> > [...]
> > There is no explanation what insert-back-tab does, or how it is different from
> > insert-tab and it looks like the implementation is indentical. What's the use
> > case?
> About this, right now textview manages that cases in the same way that's why
> they use the same handler. Also the reason for this is because we need to
> listen to this signals in gtksourceview. So to get rid to the call of
> textview->im_context we need this.

I think you should just mention what it can be used for. And if insert-back-tab is handled differently from insert-tab, give an example.
Comment 7 Matthias Clasen 2010-02-12 17:05:40 UTC
> gtk_text_buffer_backspace is more complex and requires knowledge of text buffer
> internals. By comparison, gtk_text_buffer_insert_new_line is a no-brainer.
> That's why I asked where it's needed outside of GTK+.

I guess Christian is right, we can actually do fine without introducing this new api.


> I think you should just mention what it can be used for. And if insert-back-tab
> is handled differently from insert-tab, give an example.

While an example would be appreciated, I will point out that back-tab actually is a keycap on your tab key. The original meaning was pretty clearly to move back to the previous tab position (while tab will move forward to the next tab position. But that is in navigation, not insertion.
Comment 8 Ignacio Casal Quinteiro (nacho) 2010-02-12 18:09:27 UTC
Created attachment 153654 [details] [review]
new signals v3

Removed the buffer api, added the since and a comment for the back tab that I'm not sure about it.
Comment 9 Matthias Clasen 2010-02-12 18:29:50 UTC
Looks good to me now, but it is missing the part where you take out the hardcoded handling of Tab and Enter in the key-press handler, no ?
Comment 10 Ignacio Casal Quinteiro (nacho) 2010-02-12 19:25:52 UTC
Created attachment 153656 [details] [review]
new signals v4

I think now it should be, but see that with this patch we only manage control+(Kinds of return) and Return keys, this can be a regression as we also manage right now shift and control+shift.
Comment 11 Ignacio Casal Quinteiro (nacho) 2010-02-12 23:17:42 UTC
Created attachment 153673 [details] [review]
new signals v5

Same as previous one but as discussed in irc with shift and control+shift.
Comment 12 Ignacio Casal Quinteiro (nacho) 2010-02-14 14:09:17 UTC
We were discussing about this and this approach will not work for us because we would have to override the signals and we would endup without beeing able to reset or filter the im_context so we could go with:
 * emit the signal from the key-press event after reset the im_context instead of bind the keys.
 * another approach would be gtk_text_view_filter_keypress that proxies im_context filter keypress. Though not sure if we would need also a gtk_text_view_reset_im_context as in gedit-view we override one of the textview signals.

Any thoughts about this?
Comment 13 Xavier Claessens 2010-05-03 09:54:24 UTC
For empathy, we need a way to intercept ENTER keypress to send the IM message instead of adding newline. How is that working with the proposed signals?

1) I connet "insert-new-line" signal on the GtkTextView object.
2) in the callback, I use g_signal_stop_emission_by_name() to make sure the default implementation is not called and the newline is not inserted. 

If that's correct, I guess I also need a way to set the "need_im_reset" flag GtkTextView has. But that's bug #163251 I think.
Comment 14 Xavier Claessens 2010-05-03 09:55:59 UTC
*** Bug 615660 has been marked as a duplicate of this bug. ***
Comment 15 Matthias Clasen 2018-02-10 03:24:36 UTC
We're moving to gitlab! As part of this move, we are closing bugs that haven't seen activity in more than 5 years. If this issue is still imporant to you and
still relevant with GTK+ 3.22 or master, please consider creating a gitlab issue
for it.