workaround problems when calling gtk things from ruby threads by deferring the calls...
authorgc <gc>
Sun, 3 Jul 2005 17:40:48 +0000 (17:40 +0000)
committergc <gc>
Sun, 3 Jul 2005 17:40:48 +0000 (17:40 +0000)
bin/booh

index c05210a8b09441edef2253773ac8f85f9313e82d..0a5ca76790676a0eda48c1fbc84f06cfe0404adf 100755 (executable)
--- a/bin/booh
+++ b/bin/booh
@@ -21,6 +21,7 @@
 
 require 'getoptlong'
 require 'tempfile'
+require 'thread'
 
 require 'gtk2'
 require 'booh/gtkadds'
@@ -147,22 +148,22 @@ def set_mousecursor(what, *widget)
     $current_cursor = what
 end
 def set_mousecursor_wait(*widget)
-    set_mousecursor(Gdk::Cursor::WATCH, *widget)
+    gtk_thread_protect { set_mousecursor(Gdk::Cursor::WATCH, *widget) }
     if Thread.current == Thread.main
         Gtk.main_iteration while Gtk.events_pending?
     end
 end
 def set_mousecursor_normal(*widget)
-    set_mousecursor(Gdk::Cursor::LEFT_PTR, *widget)
+    gtk_thread_protect { set_mousecursor(Gdk::Cursor::LEFT_PTR, *widget) }
 end
 def push_mousecursor_wait(*widget)
     if $current_cursor != Gdk::Cursor::WATCH
         $save_cursor = $current_cursor
-        set_mousecursor_wait(*widget)
+        gtk_thread_protect { set_mousecursor_wait(*widget) }
     end
 end
 def pop_mousecursor(*widget)
-    set_mousecursor($save_cursor || Gdk::Cursor::LEFT_PTR, *widget)
+    gtk_thread_protect { set_mousecursor($save_cursor || Gdk::Cursor::LEFT_PTR, *widget) }
 end
 
 def current_dest_dir
@@ -572,7 +573,7 @@ def gen_real_thumbnail(type, origfile, destfile, xmldir, size, img, infotype)
     Thread.new {
         push_mousecursor_wait
         gen_real_thumbnail_core(type, origfile, destfile, xmldir, size, infotype)
-        img.set(destfile)
+        gtk_thread_protect { img.set(destfile) }
         $modified_pixbufs[destfile] = { :orig => img.pixbuf, :pixbuf => img.pixbuf, :angle_to_orig => 0 }
         if entry2type(origfile) == 'video'
             #- cleanup temp for videos
@@ -1230,32 +1231,32 @@ def backend_wait_message(parent, msg, infopipe_path, mode)
                     elements += sizes
                 end
                 element_counter = 0
-                pb1_1.fraction = 0
+                gtk_thread_protect { pb1_1.fraction = 0 }
                 if mode != 'one dir scan'
                     newtext = utf8(full_src_dir_to_rel($1))
                     newtext = '/' if newtext == ''
-                    pb1_2.text = newtext
+                    gtk_thread_protect { pb1_2.text = newtext }
                     directories_counter += 1
-                    pb1_2.fraction = directories_counter / directories
+                    gtk_thread_protect { pb1_2.fraction = directories_counter / directories }
                 end
             elsif line =~ /^processing element$/
                 element_counter += 1
-                pb1_1.fraction = element_counter / elements
+                gtk_thread_protect { pb1_1.fraction = element_counter / elements }
             elsif line =~ /^processing size$/
                 element_counter += 1
-                pb1_1.fraction = element_counter / elements
+                gtk_thread_protect { pb1_1.fraction = element_counter / elements }
             elsif line =~ /^finished processing sizes$/
-                pb1_1.fraction = 1
+                gtk_thread_protect { pb1_1.fraction = 1 }
             elsif line =~ /^creating index.html$/
-                pb1_2.text = utf8(_("finished"))
-                pb1_1.fraction = pb1_2.fraction = 1
+                gtk_thread_protect { pb1_2.text = utf8(_("finished")) }
+                gtk_thread_protect { pb1_1.fraction = pb1_2.fraction = 1 }
                 directories_counter = 0
             elsif line =~ /^index.html: (.+)/
                 newtext = utf8(full_src_dir_to_rel($1))
                 newtext = '/' if newtext == ''
-                pb2.text = newtext
+                gtk_thread_protect { pb2.text = newtext }
                 directories_counter += 1
-                pb2.fraction = directories_counter / directories
+                gtk_thread_protect { pb2.fraction = directories_counter / directories }
             end
         end
     }
@@ -1286,19 +1287,19 @@ def call_backend(cmd, waitmsg, mode, params)
         msg 2, cmd
         if pid = fork
             id, exitstatus = Process.waitpid2(pid)
-            w8.destroy
+            gtk_thread_protect { w8.destroy }
             if exitstatus == 0
                 if params[:successmsg]
-                    show_popup($main_window, params[:successmsg])
+                    gtk_thread_protect { show_popup($main_window, params[:successmsg]) }
                 end
                 if params[:closure_after]
-                    params[:closure_after].call
+                    gtk_thread_protect(&params[:closure_after])
                 end
             elsif exitstatus == 15
                 #- say nothing, user aborted
             else
                 if params[:failuremsg]
-                    show_popup($main_window, params[:failuremsg])
+                    gtk_thread_protect { show_popup($main_window, params[:failuremsg]) }
                 end
             end
         else
@@ -1968,7 +1969,7 @@ def new_album
             if File.directory?(from_utf8(src_nb_calculated_for)) && src_nb_calculated_for != '/'
                 if File.readable?(from_utf8(src_nb_calculated_for))
                     src_nb_thread = Thread.new {
-                        src_nb.set_markup(utf8(_("<span size='small'><i>processing...</i></span>")))
+                        gtk_thread_protect { src_nb.set_markup(utf8(_("<span size='small'><i>processing...</i></span>"))) }
                         total = { 'image' => 0, 'video' => 0, nil => 0 }
                         `find '#{from_utf8(src_nb_calculated_for)}' -type d`.each { |dir|
                             if File.basename(dir) =~ /^\./
@@ -1982,7 +1983,7 @@ def new_album
                                 end
                             end
                         }
-                        src_nb.set_markup(utf8(_("<span size='small'><i>%s images and %s videos</i></span>") % [ total['image'], total['video'] ]))
+                        gtk_thread_protect { src_nb.set_markup(utf8(_("<span size='small'><i>%s images and %s videos</i></span>") % [ total['image'], total['video'] ])) }
                         src_nb_thread = nil
                     }
                 else
@@ -2660,6 +2661,16 @@ French: Guillaume Cottenceau") % $VERSION), { :centered => true, :pos_centered =
     return [ mb, tb ]
 end
 
+def gtk_thread_protect(&proc)
+    if Thread.current == Thread.main
+        proc.call
+    else
+        $protect_gtk_pending_calls.synchronize {
+            $gtk_pending_calls << proc
+        }
+    end
+end
+
 def create_main_window
 
     mb, tb = create_menu_and_toolbar
@@ -2749,6 +2760,15 @@ def create_main_window
         false
     }
 
+    $protect_gtk_pending_calls = Mutex.new
+    $gtk_pending_calls = []
+    Gtk.timeout_add(100) {
+        $protect_gtk_pending_calls.synchronize {
+            $gtk_pending_calls.each { |c| c.call }
+            $gtk_pending_calls = []
+        }
+    }
+
     $statusbar.push(0, utf8(_("Ready.")))
     $main_window.show_all
 end