SOLVED - sortof [was Re: "mark_set" callback fires 3 or 4 times when using arrow keys/mouse in textview?}
On 12/22/2015 05:13 PM, David C. Rankin wrote: How can I limit the the execution of the 'on_mark_set' callback to a single call regardless of whether there is data being entered or if cursor is being moved with the arrow-keys or mouse? Any help will be greatly appreciated. OK, I have a solution that is probably not as elegant as desired. Delving into the "mark_set" signal and multiple firing of the callback opened a small can of worms regarding a number of considerations associated with GtkTextMark and GtkTextIter relationships. The problem can be summarized as follows: (1) the proper callback prototype to handle the "mark_set" signal is: void on_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, context *app) (2) there are multiple text marks at each iter location. (3) when responding to the "mark_set" signal, the 'mark' passed to the callback can be any of the marks at the "iter" location which are passed in "no particular order" and are passed differently depending on whether normal text is being entered, arrow-keys are pressed, or whether the mouse is clicked to reposition to "insert" cursor mark. (4) This prevents a simple comparison between the "mark" parameter and gtk_text_buffer_get_insert (buffer) alone from being used to determine whether to respond to a "mark_set" signal or not. The short version of a solution to prevent responding to multiple "mark_set" signals is as follows. (the callback is still fired, but you can test between 'current' and 'new' line:col locations responding only when the values differ) void on_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, context *app) { gint line, col; line = gtk_text_iter_get_line (iter); col = gtk_text_iter_get_line_offset (iter); if (line == app->line && col == app->col) return; app->line = line; app->col = col; g_print (" line: %3d col: %d\n", app->line + 1, app->col + 1); if (buffer) {} if (mark) {} } Now for the rest of the story... I am normally reasonably adept at finding this type of information myself in the documentation or via the web without having to ask, but in this case there simply isn't much in the way of details on how, what or in what order "mark_set" callback parameters are passed each time the callback is fired. I'll leave what I found here to save the next person a bit of time. Each time the "mark_set" signal is generated, there can be multiple marks at any given iter *location*. In the case of normal input (e.g. 'a', 'b', etc...) the mark passed to the on_mark_set() callback is not necessarily the "insert" mark, but is apparently simply the last of the marks present at that iter *location*. (In each case below an anonymous mark is passed as a result of normal text input) The list of marks at any given iter position can be found by the GSList of marks returned by gtk_text_iter_get_marks (iter). (*note:* the marks in the list returned are in *no particular* order -- which is probably the basis for this whole issue to begin with. See: https://developer.gnome.org/gtk2/stable/GtkTextIter.html#gtk-text-iter-get-marks) For example, you can examine the marks with the following debug code: void on_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, context *app) { gint line, col; #ifdef DEBUG g_print (" mark: %p - gtbgi (buffer): %p mark->name: %s\n", mark, gtk_text_buffer_get_insert (buffer), gtk_text_mark_get_name (mark)); GSList *marks = gtk_text_iter_get_marks (iter); GSList *p = marks; gint i = 0; while (p) { const gchar *name = gtk_text_mark_get_name (GTK_TEXT_MARK(p->data)); g_print ("mark[%d] : %p : %s\n", i++, GTK_TEXT_MARK(p->data), name); p = p->next; } g_slist_free (marks); #endif line = gtk_text_iter_get_line (iter); col = gtk_text_iter_get_line_offset (iter); if (line == app->line && col == app->col) return; app->line = line; app->col = col; #ifdef DEBUG g_print (" line: %3d col: %d\n\n", app->line + 1, app->col + 1); #endif if (mark) {} } Compiling and then using the same (enter 'abc', then Left-Arrow, then *mouse-click* at the end) fires the on_mark_set() callback for each 'abc' entered: $ ./bin/text_mcve_dbg mark: 0x2458880 - gtbgi (buffer): 0x237d600 mark->name: (null) mark[0] : 0x237d600 : insert mark[1] : 0x237d620 : selection_bound mark[2] : 0x237d7a0 : gtk_drag_target mark[3] : 0x2458880 : (null) line: 1 col: 2 mark: 0x24792c0 - gtbgi (buffer): 0x237d600 mark->name: (null) mark[0] : 0x237d600 : insert mark[1] : 0x237d620 : selection_bound mark[2] : 0x237d7a0 : gtk_drag_target
gtk_widget_grab_focus sets scrollbar adjustments to 0
Hi I have a drawingarea inside a scrolled window for which I'd like to grab the focus so the user can use keyboard inputs but I want to do it without changing the scrolled window position. What I'm finding is the gtk_widget_grab_focus call on the drawable results in the scrolled window adjustments being set to zero. This is the traceback: #4 0x00386a02a3af in g_signal_emit () at /lib64/libgobject-2.0.so.0 #5 0x7757686a in gtk_adjustment_value_changed () at /lib64/libgtk-3.so.0 #6 0x775d22c8 in gtk_container_real_set_focus_child () at /lib64/libgtk-3.so.0 #7 0x00386a01301b in g_cclosure_marshal_VOID__OBJECTv () at /lib64/libgobject-2.0.so.0 #8 0x00386a00ff64 in _g_closure_invoke_va () at /lib64/libgobject-2.0.so.0 #9 0x00386a029b60 in g_signal_emit_valist () at /lib64/libgobject-2.0.so.0 #10 0x00386a02a3af in g_signal_emit () at /lib64/libgobject-2.0.so.0 #11 0x777b2138 in gtk_widget_real_grab_focus () at /lib64/libgtk-3.so.0 #12 0x00386a00ff64 in _g_closure_invoke_va () at /lib64/libgobject-2.0.so.0 #13 0x00386a029b60 in g_signal_emit_valist () at /lib64/libgobject-2.0.so.0 #14 0x00386a02a3af in g_signal_emit () at /lib64/libgobject-2.0.so.0 #15 0x777b09da in gtk_widget_grab_focus () at /lib64/libgtk-3.so.0 I can see the code in gtk_container_real_set_focus_child calling gtk_adjustment_clamp_page but don't understand why and I don't see any way to stop it from doing it. My workaround for the moment is to get the adjustment values before the grab and set them again after but this is seems a bit of a hack. Cheers, ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: gtk_widget_grab_focus sets scrollbar adjustments to 0
On Mon, 2015-12-28 at 18:01 +0800, Franco Broi wrote: > Hi > > I have a drawingarea inside a scrolled window for which I'd like to > grab > the focus so the user can use keyboard inputs but I want to do it > without changing the scrolled window position. What I'm finding is > the > gtk_widget_grab_focus call on the drawable results in the scrolled > window adjustments being set to zero. > [...] > I can see the code in gtk_container_real_set_focus_child calling > gtk_adjustment_clamp_page but don't understand why and I don't see > any > way to stop it from doing it. [...] Hi, the reasoning is that usually focus is not given to the direct child of a scrolled window, but to another grandchild. This usually makes sense so that when using keynav and tabbing from widget to widget inside a scrolled area, the scrolled window will automatically adjust itself to reveal the new button/entry/widget which may otherwise be hidden (so the user doesnt end up having to manually move the scrollbars to see what widget is focused). For your case, you should be able to opt out by simply clearing the focus adjustments with the gtk_container_set_focus_[v/h]adjustment() APIs. Cheers, -Tristan ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: gtk_widget_grab_focus sets scrollbar adjustments to 0
On Mon, 2015-12-28 at 19:26 +0900, Tristan Van Berkom wrote: > On Mon, 2015-12-28 at 18:01 +0800, Franco Broi wrote: > > Hi > > > > I have a drawingarea inside a scrolled window for which I'd like to > > grab > > the focus so the user can use keyboard inputs but I want to do it > > without changing the scrolled window position. What I'm finding is > > the > > gtk_widget_grab_focus call on the drawable results in the scrolled > > window adjustments being set to zero. > > > [...] > > > I can see the code in gtk_container_real_set_focus_child calling > > gtk_adjustment_clamp_page but don't understand why and I don't see > > any > > way to stop it from doing it. > [...] > > Hi, >the reasoning is that usually focus is not given to the direct child > of a scrolled window, but to another grandchild. > > This usually makes sense so that when using keynav and tabbing from > widget to widget inside a scrolled area, the scrolled window will > automatically adjust itself to reveal the new button/entry/widget which > may otherwise be hidden (so the user doesnt end up having to manually > move the scrollbars to see what widget is focused). > > For your case, you should be able to opt out by simply clearing the > focus adjustments with the gtk_container_set_focus_[v/h]adjustment() > APIs. Thanks for the quick reply Tristan. Had me flummoxed for a while until I worked out that it is the adjustments of the scrolledwindow's child that need to be cleared - the viewport?? gtk_container_set_focus_vadjustment(GTK_CONTAINER(gtk_bin_get_child(GTK_BIN(sw))), NULL); Cheers, ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list