Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Busy Windows Using Gtk2

by aecooper (Acolyte)
on Jan 25, 2008 at 10:44 UTC ( [id://664263]=perlquestion: print w/replies, xml ) Need Help??

aecooper has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I'm writing a GTK2 Perl application and I am trying to write a routine that will make a window busy, i.e. display the busy cursor and stop all input events (keyboard and mouse clicks, but not move movement) from going to the window).

This is using Perl version 5.8.5 on WhiteBox 4 respin 1 (clone of RHAS4U3).

I include the following:

use strict; use Glib qw(FALSE TRUE); use Gnome2; use Gnome2::VFS -init; use Gtk2 -init; set_locale Gtk2; init Gtk2; use Gtk2::GladeXML; use Gtk2::Helper; use Gtk2::Pango; use Gtk2::SourceView; use IPC::Open3; use Monotone::AutomateStdio; use POSIX qw(:errno_h :sys_wait_h); use POSIX qw(strftime);
I use the following routine to update the display when inside a callback that is busy doing some processing:
sub gtk2_update() { return if (Gtk2->main_level() == 0); while (Gtk2->events_pending()) { Gtk2->main_iteration(); } }
and the following to make a window busy/unbusy:
sub make_busy($$) { my($instance, $busy) = @_; # Create and store the cursors if we haven't done so already. if (! exists($instance->{busy_cursor})) { $instance->{normal_cursor} = Gtk2::Gdk::Cursor->new("left-ptr"); $instance->{busy_cursor} = Gtk2::Gdk::Cursor->new("watch"); } # Do it. Make the application bar grab the input when the window is # busy, that way we gobble up keyboard and mouse events that could # muck up the application state. if ($busy) { $instance->{window}->window()-> set_cursor($instance->{busy_cursor}); Gtk2->grab_add($instance->{appbar}); } else { $instance->{window}->window()-> set_cursor($instance->{normal_cursor}); Gtk2->grab_remove($instance->{appbar}); } }
This sort of works. However if the mouse cursor is moved to a widget whilst the window is busy, then the window is made unbusy, the user has to move the cursor away from the widget and then back again before it will respond to a button click (I suspect because the movement was lost along with everything else).

I have tried to interrupt the flow of events by writing my own main event loop but that didn't work very well. I'm sure there is an easy answer as it is a common thing to want to do but I can't find anything on this. Any ideas?

MTIA,

Tony.

Replies are listed 'Best First'.
Re: Busy Windows Using Gtk2
by zentara (Archbishop) on Jan 25, 2008 at 16:04 UTC
    In Gtk2 it can get complicated, dealing with all the signals. Tk is so much easier with ->Busy and ->Unbusy. Without a working snippet to play with, I can only offer you 2 snippets which show some of the complexities. The Perl/Gtk2 maillist may be a better source of answers for this. Otherwise show a chopped down working snippet to demonstrate your problem.

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Busy Windows Using Gtk2
by Anonymous Monk on Jan 28, 2008 at 04:48 UTC
    The sanctioned trick from gtk+ itself is $window->set_sensitive (FALSE);to "gray out" the window and stop responding to input. Setting the cursor as you did is a nice touch. :-) However, if you want to provide a "cancel" button, don't simply desensitize the toplevel window, or the cancel button will be unusable, too! Just desensitize the relevant containers.

    Note that when you set_sensitive(TRUE) again after the work is finished, the same problem exists as you see -- the user has to move the mouse away from the current widget or the current widget might not respond to clicks. This happens simply because the window doesn't realize that the pointer is in his area, because he didn't get a pointer-enter event. This even happens in C programs.

Re: Busy Windows Using Gtk2
by aecooper (Acolyte) on May 16, 2009 at 18:11 UTC
    Many thanks for your replies. I didn't like the idea of desensitizing the whole window as that is very big change to the display and possibly only for a short duration of time.

    In the end I got the an event loop mechanism working that simply filtered out offending user input events, allowing for `stop' style buttons to be pressed. This module also handles context sensitive help, busy cursor handling and window recycling. I will probably put this on CPAN at some point. The event loop is only used when the app is busy, otherwise the default action takes place which avoids the unnecessary c to perl marshalling. It works really well now.

    Many thanks for your help.

    Tony.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://664263]
Approved by bingos
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2024-04-25 14:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found