After some offline discussion, I decided to experiment with g_idle_add_full() since that function seems to work for other people. Unfortunately, it doesn't in my case. The width of the first column is still 0 and bad behavior is reproducible: column[0](0) = 0 -> 0 cell[0] = min->102, natural->102, text->98 column[1](66) = 98 -> 164 cell[0] = min->20, natural->20 cell[1] = min->16, natural->16 cell[2] = min->35, natural->35 column[2](36) = 164 -> 200 cell[0] = min->16, natural->16 x = 138.000000, y = 274.000000 Looking at the code for g_main_context_invoke_full() and g_idle_add_full(), as expected, the portion of g_main_context_invoke_full() that deals with the idle source is virtually identical to g_idle_add_full(). So, the issue is somewhere deeper. Are there any GLib or Gtk+ developers on this list that can offer any help? On Tue, Jan 8, 2019 at 4:35 PM Lex Trotman <elextr@xxxxxxxxx> wrote: > > "calling gtk functions from a thread would be possible only through > g_idle_add()." thats my understanding from > https://developer.gnome.org/gdk3/stable/gdk3-Threads.html and thats > what our app does. It never seems to be a performance problem, the > main thread continuously chews its way through the idle queue. > > Cheers > Lex > > On Wed, 9 Jan 2019 at 10:17, Mitko Haralanov <voidtrance@xxxxxxxxx> wrote: > > > > I havent looked at the actual code but I am willing to bet that the "idle source" is just using g_idle_add(). If so, g_main_context_invoke_full() is essentially the same. > > > > If not the case, calling gtk functions from a thread would be possible only through g_idle_add(). I would think that if that were the case, it would have been mentioned in the docs. > > > > Thank you, > > Mitko > > > > On Tue, Jan 8, 2019, 16:11 Lex Trotman <elextr@xxxxxxxxx wrote: > >> > >> Hi Mitko, > >> > >> Same problem, from g_main_context_invoke() "In any other case, an idle > >> source is created to call function and that source is attached to > >> context (presumably to be run in another thread)." > >> > >> Cheers > >> Lex > >> > >> On Wed, 9 Jan 2019 at 09:55, Mitko Haralanov <voidtrance@xxxxxxxxx> wrote: > >> > > >> > Hi Lex, > >> > > >> > That is for the "notify" callback, which only deals with free/release > >> > of the "data" pointer. The "function" callback is different and should > >> > be called from the context default thread (as the documentation > >> > describes.) > >> > > >> > Thank you, > >> > Mitko > >> > > >> > On Tue, Jan 8, 2019 at 3:44 PM Lex Trotman <elextr@xxxxxxxxx> wrote: > >> > > > >> > > Mito, > >> > > > >> > > It seems to me that since the g_main_context_invoke_full() docs say > >> > > "notify should not assume that it is called from any particular > >> > > thread" that notify cannot call GTK functions since GTK is not thread > >> > > safe. > >> > > > >> > > Cheers > >> > > Lex > >> > > > >> > > PS I'm not on gtk-list and am not gonna join for one line, feel free to forward > >> > > > >> > > On Wed, 9 Jan 2019 at 04:03, Mitko Haralanov via gtk-list > >> > > <gtk-list@xxxxxxxxx> wrote: > >> > > > > >> > > > Thanks for the reply. > >> > > > > >> > > > When calling g_main_context_invoke_full(), I am using NULL as the > >> > > > context pointer. According to the documentation of > >> > > > g_main_context_invoke(): > >> > > > > >> > > > "If context is NULL then the global default main context — as > >> > > > returned by g_main_context_default() — is used." > >> > > > > >> > > > So, the code should be using the correct context. > >> > > > > >> > > > One of the main reasons why I am not using g_idle_add() is the timing > >> > > > of the callback. I don't want to defer the processing of the callback > >> > > > to the "idle" time since this is signal handling related. Another > >> > > > advantage of g_main_context_invoke[_full]() is that it will check the > >> > > > "context" of the caller and, if possible, will call the callback > >> > > > directly: > >> > > > > >> > > > "If context is owned by the current thread, function is called > >> > > > directly. Otherwise, if context is the thread-default main context of > >> > > > the current thread and g_main_context_acquire() > >> > > > succeeds, then function is called and g_main_context_release() > >> > > > is called afterwards. > >> > > > In any other case, an idle source is created to call function > >> > > > and that source is attached to context (presumably to be run in > >> > > > another thread). The idle source is attached with > >> > > > G_PRIORITY_DEFAULT priority. If you want a different priority, > >> > > > use g_main_context_invoke_full()." > >> > > > > >> > > > Your suggested implementation is basically the GLib's async queues. > >> > > > Or, may be, a custom event source. However, it seems that > >> > > > g_main_context_invoke_full() should be doing exactly that. With all > >> > > > due respect, I also don't see how it would solve the issue. If the > >> > > > current implementation has an problem with locking/race conditions, > >> > > > would your suggested implementation suffer from the same issue since > >> > > > it's using the same or similar mechanism for calling the callback? > >> > > > > >> > > > Thank you, > >> > > > > >> > > > Mitko > >> > > > > >> > > > > >> > > > On Mon, Jan 7, 2019 at 3:54 PM ente <ente@xxxxxxx> wrote: > >> > > > > > >> > > > > Hi, > >> > > > > > >> > > > > > >> > > > > I am not sure with my answer. Treat it as unreliable. > >> > > > > > >> > > > > There seems to be a difference between g_idle_add > >> > > > > and g_main_context_invoke_full. While the documentation of idle_add > >> > > > > says: > >> > > > > "Adds a function to be called [...] to the default main loop." (i.e. > >> > > > > main thread / the only gtk-thread) g_main_context_invoke_full does not > >> > > > > mention the main loop - although it mentions a "context" which I have > >> > > > > no experience with and which may be related to the main loop. So maybe > >> > > > > you must retrieve the correct context using g_main_context_default or > >> > > > > g_main_context_acquire. Keep in mind: glib is thread safe, gtk is not. > >> > > > > g_main_context_invoke_full may support glib multi threading while > >> > > > > g_idle_add clearly sends your function call to the gtk thread. > >> > > > > > >> > > > > The effect you are describing makes sense to me. The effects you > >> > > > > observe sound very much like race conditions in the treeview event > >> > > > > handler. > >> > > > > > >> > > > > Why aren't you using g_idle_add in the first place? In my experience > >> > > > > this works like a charm. Be careful with one thing tho: The main loop > >> > > > > has a "todo-list". Each time you call "g_idle_add" it adds an item to > >> > > > > that todo-list and schedules a call to your function. If your function > >> > > > > doesn't return false, it won't even be taken down from the todo-list. > >> > > > > Each click event ends on that todo-list. Each column resize adds > >> > > > > multiple items to that todo-list (depending on your column resize > >> > > > > policy and the number of rows). As soon as you add more items to that > >> > > > > list, your UI becomes unresponsive. It seems advisable to build your > >> > > > > own shadow todo-list for the update process, i.e.: > >> > > > > * setup a function "update_progress" > >> > > > > * on the first threaded update event, call idle_add for the function > >> > > > > and put the new progress and the row number in your own data structure > >> > > > > * while the function is still "planned in for idle_add", just add new > >> > > > > events to your own data structure > >> > > > > * process 1 to 10 (maybe some more) events on each of the calls > >> > > > > * the function returns true as long as there is still some events in > >> > > > > your own list; it returns false otherwise > >> > > > > * apply mutex checks on your data structure (not sure if i should > >> > > > > mention, I am sure you had this in your mind already) > >> > > > > > >> > > > > Each time you update a progress bar in your treeview, several (at least > >> > > > > one) events are added to the gtk-todo list (repaint!, re-order? and > >> > > > > maybe some more). Doing multiple progress events at once may lower the > >> > > > > amount of events, gtk has to process (a re-order affects all rows - > >> > > > > doing an update on multiple rows does not change anything here). > >> > > > > > >> > > > > That's my 5 cents. I hope it helped a bit. > >> > > > > > >> > > > > > >> > > > > regards, > >> > > > > > >> > > > > > >> > > > > ente > >> > > > > > >> > > > > > >> > > > > On Mon, 2019-01-07 at 08:28 -0800, Mitko Haralanov via gtk-list wrote: > >> > > > > > Anyone have any ideas? I still can't figure out why the column sizes > >> > > > > > go to > >> > > > > > 0. > >> > > > > > > >> > > > > > Thank you. > >> > > > > > > >> > > > > > On Tue, Dec 18, 2018, 13:40 Mitko Haralanov < > >> > > > > > voidtrance@xxxxxxxxx > >> > > > > > wrote: > >> > > > > > > >> > > > > > > This is Gtk3: > >> > > > > > > gtk3-3.22.26-2.fc27.x86_64 > >> > > > > > > > >> > > > > > > On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list < > >> > > > > > > gtk-list@xxxxxxxxx > >> > > > > > > > wrote: > >> > > > > > > > >> > > > > > > > Is it Gtk2 or Gtk3, which version exactly? > >> > > > > > > > > >> > > > > > > > > >> > > > > > > > Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk- > >> > > > > > > > list < > >> > > > > > > > gtk-list@xxxxxxxxx > >> > > > > > > > > ha scritto: > >> > > > > > > > > >> > > > > > > > > I mistakenly replied only to Luca!! Forwarding to the list. > >> > > > > > > > > > >> > > > > > > > > (Sorry, Luca, my bad) > >> > > > > > > > > - Mitko > >> > > > > > > > > > >> > > > > > > > > ---------- Forwarded message --------- > >> > > > > > > > > From: Mitko Haralanov < > >> > > > > > > > > voidtrance@xxxxxxxxx > >> > > > > > > > > > > >> > > > > > > > > Date: Tue, Dec 18, 2018 at 9:37 AM > >> > > > > > > > > Subject: Re: Emitting signals from threads > >> > > > > > > > > To: Luca Bacci < > >> > > > > > > > > luca.bacci982@xxxxxxxxx > >> > > > > > > > > > > >> > > > > > > > > > >> > > > > > > > > > >> > > > > > > > > I found something that is different between the two cases - > >> > > > > > > > > button click > >> > > > > > > > > with signals and without. > >> > > > > > > > > > >> > > > > > > > > Using the code from the link that Luca posted, I decided to > >> > > > > > > > > print the > >> > > > > > > > > size of each column when a button press is received. As it > >> > > > > > > > > turns out, the > >> > > > > > > > > width of the columns is different in the two cases: > >> > > > > > > > > > >> > > > > > > > > Without thread signals: > >> > > > > > > > > column[0](193) = 0 -> 193 > >> > > > > > > > > cell[0] = min->109, natural->109 > >> > > > > > > > > column[1](66) = 193 -> 259 > >> > > > > > > > > cell[0] = min->20, natural->20 > >> > > > > > > > > cell[1] = min->16, natural->16 > >> > > > > > > > > cell[2] = min->35, natural->35 > >> > > > > > > > > column[2](36) = 259 -> 295 > >> > > > > > > > > cell[0] = min->16, natural->16 > >> > > > > > > > > x = 105.872116, y = 259.547516 > >> > > > > > > > > > >> > > > > > > > > (x and y are the coordinates of the button press event) > >> > > > > > > > > > >> > > > > > > > > With thread signals: > >> > > > > > > > > column[0](0) = 0 -> 0 > >> > > > > > > > > cell[0] = min->135, natural->135 > >> > > > > > > > > column[1](66) = 0 -> 66 > >> > > > > > > > > cell[0] = min->20, natural->20 > >> > > > > > > > > cell[1] = min->16, natural->16 > >> > > > > > > > > cell[2] = min->35, natural->35 > >> > > > > > > > > column[2](36) = 66 -> 102 > >> > > > > > > > > cell[0] = min->16, natural->16 > >> > > > > > > > > x = 113.528488, y = 158.563782 > >> > > > > > > > > > >> > > > > > > > > As you can see, the width of the first column is 0 when the > >> > > > > > > > > signals are > >> > > > > > > > > being emitted. As expected, if I were to click very close to > >> > > > > > > > > the left > >> > > > > > > > > border of the widget, the edit dialog does not get triggered as > >> > > > > > > > > the x > >> > > > > > > > > coordinate falls within column 1: > >> > > > > > > > > > >> > > > > > > > > column[0](0) = 0 -> 0 > >> > > > > > > > > cell[0] = min->135, natural->135 > >> > > > > > > > > column[1](66) = 0 -> 66 > >> > > > > > > > > cell[0] = min->20, natural->20 > >> > > > > > > > > cell[1] = min->16, natural->16 > >> > > > > > > > > cell[2] = min->35, natural->35 > >> > > > > > > > > column[2](36) = 66 -> 102 > >> > > > > > > > > cell[0] = min->16, natural->16 > >> > > > > > > > > x = 21.247330, y = 181.310333 > >> > > > > > > > > > >> > > > > > > > > I could use the cell renderer width if the column width is 0 > >> > > > > > > > > but that > >> > > > > > > > > seems unreliable since the cell renderer width is not the same > >> > > > > > > > > as the > >> > > > > > > > > column and it's also not static. > >> > > > > > > > > > >> > > > > > > > > On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov < > >> > > > > > > > > voidtrance@xxxxxxxxx > >> > > > > > > > > > > >> > > > > > > > > wrote: > >> > > > > > > > > > >> > > > > > > > > > I am not posting the complete function because there is a lot > >> > > > > > > > > > of > >> > > > > > > > > > irrelevant code. I am also not interested in the specific > >> > > > > > > > > > cell renderer but > >> > > > > > > > > > rather the row on which the click occurred. > >> > > > > > > > > > > >> > > > > > > > > > tatic gboolean on_button_press_event(GtkWidget *widget, > >> > > > > > > > > > GdkEvent *event, > >> > > > > > > > > > gpointer data) > >> > > > > > > > > > { > >> > > > > > > > > > GtkTreeView *treeview = GTK_TREE_VIEW(widget); > >> > > > > > > > > > GdkEventButton *button = (GdkEventButton *)event; > >> > > > > > > > > > GtkTreeModel *model; > >> > > > > > > > > > GtkTreePath *path; > >> > > > > > > > > > GtkTreeIter iter; > >> > > > > > > > > > GtkTreeViewColumn *column; > >> > > > > > > > > > GtkScopeProjectEditDialog *dialog; > >> > > > > > > > > > GtkScopeProjectEditData *pdata, fill; > >> > > > > > > > > > GtkScopeProject *project; > >> > > > > > > > > > guint response, index; > >> > > > > > > > > > gboolean ret = FALSE; > >> > > > > > > > > > > >> > > > > > > > > > if (button->type != GDK_BUTTON_PRESS || > >> > > > > > > > > > !gtk_tree_view_get_path_at_pos(treeview, button->x, > >> > > > > > > > > > button->y, > >> > > > > > > > > > &path, &column, NULL, NULL)) > >> > > > > > > > > > return FALSE; > >> > > > > > > > > > > >> > > > > > > > > > index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column), > >> > > > > > > > > > "index")); > >> > > > > > > > > > if (index != TREEVIEW_COLUMN_EDIT) > >> > > > > > > > > > goto done; > >> > > > > > > > > > model = gtk_tree_view_get_model(treeview); > >> > > > > > > > > > if (!gtk_tree_model_get_iter(model, &iter, path)) > >> > > > > > > > > > goto done; > >> > > > > > > > > > gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ, > >> > > > > > > > > > &project, -1); > >> > > > > > > > > > ... > >> > > > > > > > > > > >> > > > > > > > > > The issue is that the column which is returned by > >> > > > > > > > > > gtk_tree_view_get_path_at_pos() is different depending on > >> > > > > > > > > > whether thread > >> > > > > > > > > > signals are being emitted vs not. I have verified that the > >> > > > > > > > > > button press > >> > > > > > > > > > coordinates are the same (button->x and button->y have the > >> > > > > > > > > > same values in > >> > > > > > > > > > both cases). > >> > > > > > > > > > > >> > > > > > > > > > > >> > > > > > > > > > On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci < > >> > > > > > > > > > luca.bacci982@xxxxxxxxx > >> > > > > > > > > > > > >> > > > > > > > > > wrote: > >> > > > > > > > > > > >> > > > > > > > > > > Hi Mitko! Can you post here the code for the button-press > >> > > > > > > > > > > event > >> > > > > > > > > > > handler? > >> > > > > > > > > > > It should more or less follow the code here: > >> > > > > > > > > > > http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html > >> > > > > > > > > > > > >> > > > > > > > > > > > >> > > > > > > > > > > Luca > >> > > > > > > > > > > > >> > > > > > > > > > > Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov > >> > > > > > > > > > > via gtk-list < > >> > > > > > > > > > > gtk-list@xxxxxxxxx > >> > > > > > > > > > > > ha scritto: > >> > > > > > > > > > > > >> > > > > > > > > > > > Hi, > >> > > > > > > > > > > > > >> > > > > > > > > > > > In my application, I want to be able to update a treeview > >> > > > > > > > > > > > from a > >> > > > > > > > > > > > separate thread. Each treeview row was a column that is a > >> > > > > > > > > > > > progress bar. The > >> > > > > > > > > > > > progress to be displayed is generated by a separate > >> > > > > > > > > > > > thread as to not block > >> > > > > > > > > > > > the UI. > >> > > > > > > > > > > > > >> > > > > > > > > > > > Since GTK is not thread-safe, the way the application is > >> > > > > > > > > > > > written is > >> > > > > > > > > > > > that the thread, when it needs to emit a signal, will > >> > > > > > > > > > > > prepare the signal > >> > > > > > > > > > > > data and then call g_main_context_invoke_full(NULL, cb, > >> > > > > > > > > > > > data, ...) in order > >> > > > > > > > > > > > to be able to call g_singal_emit() in the global default > >> > > > > > > > > > > > context thread. > >> > > > > > > > > > > > The signal handler updates the tree model, which in turn > >> > > > > > > > > > > > updates the tree > >> > > > > > > > > > > > view. > >> > > > > > > > > > > > > >> > > > > > > > > > > > For the most part this works with one big, ugly exception > >> > > > > > > > > > > > - the same > >> > > > > > > > > > > > treeview has a column, which is supposed to open the > >> > > > > > > > > > > > item's Edit dialog > >> > > > > > > > > > > > when clicked. So, naturally, I have a button-press > >> > > > > > > > > > > > handler connected to the > >> > > > > > > > > > > > treeview, which launches the Edit dialog when the button > >> > > > > > > > > > > > press occurs in > >> > > > > > > > > > > > the correct column. > >> > > > > > > > > > > > > >> > > > > > > > > > > > However, when an update is running and the thread is > >> > > > > > > > > > > > continuously > >> > > > > > > > > > > > emitting signals, clicking on *any* column of *any* of > >> > > > > > > > > > > > the other items > >> > > > > > > > > > > > opens the Edit dialog. The treeview behaves as if the > >> > > > > > > > > > > > items in it have only > >> > > > > > > > > > > > one column. > >> > > > > > > > > > > > > >> > > > > > > > > > > > Every example or document that I have seen in relation to > >> > > > > > > > > > > > signals > >> > > > > > > > > > > > from threads says to emit the signal from a g_idle_add() > >> > > > > > > > > > > > handler. However, > >> > > > > > > > > > > > g_main_context_invoke_full(NULL, ...) should be the same > >> > > > > > > > > > > > as calling > >> > > > > > > > > > > > g_idle_add(). > >> > > > > > > > > > > > > >> > > > > > > > > > > > Can someone shed some light into what might be happening? > >> > > > > > > > > > > > > >> > > > > > > > > > > > Thank you. > >> > > > > > > > > > > > > >> > > > > > > > > > > > > >> > > > > > > > > > > > _______________________________________________ > >> > > > > > > > > > > > gtk-list mailing list > >> > > > > > > > > > > > gtk-list@xxxxxxxxx > >> > > > > > > > > > > > > >> > > > > > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list > >> > > > > > > > > > > > > >> > > > > > > > > > > > > >> > > > > > > > > > > > >> > > > > > > > > > > _______________________________________________ > >> > > > > > > > > > >> > > > > > > > > gtk-list mailing list > >> > > > > > > > > gtk-list@xxxxxxxxx > >> > > > > > > > > > >> > > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list > >> > > > > > > > > > >> > > > > > > > > > >> > > > > > > > > >> > > > > > > > _______________________________________________ > >> > > > > > > > gtk-list mailing list > >> > > > > > > > gtk-list@xxxxxxxxx > >> > > > > > > > > >> > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list > >> > > > > > > > > >> > > > > > > > > >> > > > > > > >> > > > > > _______________________________________________ > >> > > > > > gtk-list mailing list > >> > > > > > gtk-list@xxxxxxxxx > >> > > > > > > >> > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list > >> > > > > > > >> > > > > > >> > > > > > >> > > > > > >> > > > _______________________________________________ > >> > > > gtk-list mailing list > >> > > > gtk-list@xxxxxxxxx > >> > > > https://mail.gnome.org/mailman/listinfo/gtk-list _______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx https://mail.gnome.org/mailman/listinfo/gtk-list