Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gtk_widget_add_tick_callback() and gtk_main_iteration()

Tags:

c++

gtk

gtk3

gtkmm3

I have two GTK windows

  1. Normal (main) window that runs animation, draws stuff in callback registered by gtk_widget_add_tick_callback().

  2. At some point secondary window is created that runs modal loop:

    void show_modal() 
    {
       GtkWindow* gw = gtkwindow(this);
    
       if( parent() )
         gtk_window_set_transient_for(gw, gtkwindow( parent() ));
    
    
       gtk_widget_show(GTK_WIDGET(gw));
       gtk_window_set_modal(gw,TRUE);
       gtk_window_set_keep_above(gw,TRUE);
       this->update_window_state(gool::WINDOW_SHOWN);
    
       while( this->is_valid_window() )
       {
          if(this->_window_state == WINDOW_HIDDEN) break;
          if(this->_window_state == WINDOW_STATE_NA) break;
          gtk_main_iteration(); // gtk_main_iteration_do(true);
       }
    }
    

Problem: Animation in main window works fine until show_modal() is invoked. It appears as gtk_main_iteration(); blocks ticks added by gtk_widget_add_tick_callback() function. As soon as I close secondary window and so while() {gtk_main_iteration();} loop exits then animations in main window start running again.

Any idea of how to make "animation friendly" modal loops in GTK?

UPDATE: it appears as gtk_main_iteration(); blocks not only ticks but any updates of any windows other than "current" - they are simply frozen. What is the reasoning of such GTK behavior?

UPDATE #2:

gtk_dialog_run(); behaves exactly as gtk_main_iteration(); - locks any updates on any window in process other than active window.

like image 725
c-smile Avatar asked Mar 08 '17 19:03

c-smile


Video Answer


1 Answers

It seems to be by definition: link

gboolean gtk_main_iteration (void); Runs a single iteration of the mainloop. If no events are waiting to be processed GTK+ will block until the next event is noticed. If you don’t want to block look at gtk_main_iteration_do() or check if any events are pending with gtk_events_pending() first.

The explanation suggests to use gtk_main_iteration_do(FALSE) if you don't want blocking:

gboolean gtk_main_iteration_do (gboolean blocking); Runs a single iteration of the mainloop. If no events are available either return or block depending on the value of blocking: TRUE if you want GTK+ to block if no events are pending

As for gtk_dialog_run: it also blocks by design link

gint gtk_dialog_run (GtkDialog *dialog); Blocks in a recursive main loop until the dialog either emits the “response” signal, or is destroyed.[...]

I read about people solving this using multiple threads: handle the GUI in the main thread and do background work in another one. There's an article about it here that might be useful.

like image 68
JHBonarius Avatar answered Oct 10 '22 07:10

JHBonarius