SOLVED - sortof [was Re: "mark_set" callback fires 3 or 4 times when using arrow keys/mouse in textview?}

2015-12-28 Thread David C. Rankin

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

2015-12-28 Thread Franco Broi
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

2015-12-28 Thread Tristan Van Berkom
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

2015-12-28 Thread Franco Broi
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