view release on metacpan or search on metacpan
- new email
Version 15, November 2010
- fix signal warnings for target widget destroyed when unrealized
Version 14, November 2010
- an actual Glib::Object so can make from Gtk2::Builder
- cleanup realize handler on destroy (harmless but unsightly)
Version 13, September 2010
- fix some realize-during-busy commented out for debugging
Version 12, September 2010
- test manifest only as an author test
Version 11, August 2010
- tests allow for perl 5.8.3 overload.pm on widget somehow not working
Version 10, June 2010
- use refaddr() just in case a widget overloads numizing
Version 4, June 2008
- fix for unrealized Gtk2::Entry
Version 3, June 2008
- let test suite cope with single-display gdk backends, as
reported by Jamie Lahowetz
Version 2, May 2008
- use GtkButton private subwindow
- notice new toplevels during busy
Version 1, April 2008
- the first version
Changes
COPYING
debian/changelog
debian/compat
debian/control
debian/copyright
debian/rules
debian/source/format
debian/watch
devel/busy-two.pl
devel/busydestroy.pl
devel/busynew.pl
devel/combo.pl
devel/entry.pl
devel/GNUmakefile
devel/invisible-blank.c
devel/invisible.pl
devel/linkbutton.pl
devel/loading.pl
devel/no-window.pl
devel/overload.pl
devel/run.pl
devel/set-cursor.pl
devel/spinner.pl
devel/unbusy-idle.pl
examples/builder-add.pl
examples/builder.pl
examples/cursortype.pl
examples/heart.pl
examples/misc.pl
examples/priority.pl
examples/timebusy.pl
inc/my_pod2html
lib/Gtk2/Ex/WidgetCursor.pm
Makefile.PL
MANIFEST This list of files
MANIFEST.SKIP
README
SIGNATURE
t/busy-first.t
t/MyTestHelpers.pm
t/overload.t
t/test-weaken.t
t/WidgetCursor.t
xt/0-file-is-part-of.t
xt/0-META-read.t
xt/0-no-debug-left-on.t
xt/0-Test-ConsistentVersion.t
xt/0-Test-DistManifest.t
xt/0-Test-Pod.t
General Public License for more details.
You should have received a copy of the GNU General Public License along
with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
Gtk2::Ex::WidgetCursor helps you manage what mouse pointer cursor is
used in a widget's window. You can setup for a base cursor, then
something special cursor during a drag, and perhaps a "watch" for a
busy state on top of one or both of those.
A global "busy" mechanism is included, as a convenient way to display
a wristwatch in all windows while away number crunching.
The only prerequisite is Gtk2-Perl. The WidgetCursor home page is
http://user42.tuxfamily.org/gtk2-ex-widgetcursor/index.html
SHA256 6de0ac3ffe5f917fc41416c5ea0d3516f90c8319731baca73c55d3ac5e3f2acf Makefile.PL
SHA256 7f6763e6c048d6fa4f4b2ec5d02d0bb08f04e412030e240505256ef2e41f80b9 README
SHA256 c8f4e875810765cc6c965b3a40b2c1bbcda19807b1f44f4a7fc7df1747e19176 debian/changelog
SHA256 2e6d31a5983a91251bfae5aefa1c0a19d8ba3cf601d0e8a706b4cfa9661a6b8a debian/compat
SHA256 73779bd11b3a8f8b234ce7c8601b7d9e767ed78c104ce6e7f47628bdaf1e11c4 debian/control
SHA256 137c63cfddb8f7d3528a792468c763496e1996b24e61006122421b3c4b635c26 debian/copyright
SHA256 aab6f8697fd597d373e9c7529eff229dfd983fca5958d6216e450358079f1943 debian/rules
SHA256 5717e7c840171019a4eeab5b79a7f894a4986eaff93d04ec5b12c9a189f594bf debian/source/format
SHA256 f1cc6c1f1c313003a83de637f05f2d59b2f8bd7f19b7a27c002148c9dcb7c2e1 debian/watch
SHA256 01d26429e305f1e52f5dc016325d4dc1d697dc3d99997ec23569d4e5d5bea49f devel/GNUmakefile
SHA256 ba5546355e1e78c1cda8fb035bc908fc85977f0993cadc0a56f962cdc45d828a devel/busy-two.pl
SHA256 745b4760521d7fb043e2a473a7e214711e4b7804f64607525cd61a9f8cc6ed2c devel/busydestroy.pl
SHA256 97c05a83f7bc7f0c7419b585de8be34760828f187a21f05a0ce36040ed25d791 devel/busynew.pl
SHA256 ac7163658e33ee22b90d8ef7894848a313781c41ac9a97aa0d2f1b08d175dc9f devel/combo.pl
SHA256 55e51513152aa5843a9150f3126d1b0d8f653b9b5d64fae16e0266bef2978475 devel/entry.pl
SHA256 4f70ed551a096c820c810d600dd8d0829a5e81585053403d06901590aba89f98 devel/invisible-blank.c
SHA256 b738ce59757cb946958205e9c2256adaa7834e12d92dbc3daa5fe6e4a538a48e devel/invisible.pl
SHA256 0a6fe337f184f7d588244835baa203f6fb74093b4f1636804f38a57aa10e9b22 devel/linkbutton.pl
SHA256 b7a3fa7f8e5e28ff7f7d5a0603d23c141cedf830b794f1c45e66abac8265f82e devel/loading.pl
SHA256 f6fe94943233596430f3a40b99955a6158469c347586e4c5203ca4279879d5b9 devel/no-window.pl
SHA256 bf705da54aea9bb995ab53f7779568056a4f8319d0901dfbf0feea9ffb9edec8 devel/overload.pl
SHA256 20435d1d513fb357ef5bbe518c1a80cf95d314e3ca20f187e131ca7f1801ec33 devel/run.pl
SHA256 5ac46c09a9b30995cf136b93e36ef7c5fd4d9e9b43c92b072a3ef7b1ca58c967 devel/set-cursor.pl
SHA256 36f006fb633c24992365d5904350371c911db3a2de8bb71481ef1476c26622e5 devel/spinner.pl
SHA256 4fa5a5d8ea745f63bfcfe8183dcb6a5a1df5c3882122c16440aa053da06439b8 devel/unbusy-idle.pl
SHA256 9d2112549514565d1cfc169ff64ad3e186ab9f624497b609878b571e6980ddd4 examples/builder-add.pl
SHA256 25deb56fd3d95c74206469e41df3d10c4f2ef56e9e5d673ecab142d50b9c30be examples/builder.pl
SHA256 a0ca81975172e8de7853f56dccbaf8026c65c9e5b70bfcac6a4e1ad785ff314b examples/cursortype.pl
SHA256 fe5af376c1936c2e31e7f3e31b383a23c1755270453043b5f80ed8ba2ca930ed examples/heart.pl
SHA256 bb3241e9e5ae3ff0fb5da75173a7d000cdda444648eef0d4eae2027c0d179b70 examples/misc.pl
SHA256 7c43513dc16e29d2ea2aced931672b5c169e031149b9a7eeff6e58729a7a3697 examples/priority.pl
SHA256 77a02b07175ec52819a827c760a577834034af1f4b78f7735f37538d17f8aa72 examples/timebusy.pl
SHA256 28bec8fe29b497164cfeac7aa1707d8ed81874bb08ccda5b7a490b0869f4a3ca inc/my_pod2html
SHA256 f691964f756e6256512ca4328f9256906c1cece200d3430d1be8d9658e6bd3bb lib/Gtk2/Ex/WidgetCursor.pm
SHA256 91cd2bba3e246abf05c342ed549ed6d902e8a77a43b6c9c4e092e4c918732ac0 t/MyTestHelpers.pm
SHA256 3f665cc2fd0ce7c1aa48a82ce29bd7b80025314b23d61280d6640b430a5987dd t/WidgetCursor.t
SHA256 937a89c7b2bfbd73b9fdd0d0bb047377547dd3c34da0e79f29bbca9eacd25bfc t/busy-first.t
SHA256 0a6353296350d6acb2bbfa199e9ab4971a985cee37786da31c7b9028bcafd421 t/overload.t
SHA256 c980e0a574f31863065bef04b9640a5783f53eb646ed9404d35458360da2c313 t/test-weaken.t
SHA256 ef75312e02ddcfed7095de7eecebc6b7b863d56acd9b64142737ab7a5edb57e3 xt/0-META-read.t
SHA256 f03d4741c4e6dd385c7bafa06118082bad4809a64e28a094635324ef8ab4f3e5 xt/0-Test-ConsistentVersion.t
SHA256 be42622f3841d04240cb1284e6b30e1af81cb0fcb56d29e853c70af656653488 xt/0-Test-DistManifest.t
SHA256 48b441e0c335e93946d913897e342662387788833229c5ba5fac57f0ff3d567c xt/0-Test-Pod.t
SHA256 2e1e1d896a226aeb190cdcfbe83969f634c1be3e7344302e023915e3f7150732 xt/0-Test-Synopsis.t
SHA256 d33b48c1986680cd934565250bd9e3879674dfe6aad69b1717ed76354a29ff44 xt/0-Test-YAML-Meta.t
SHA256 75a73148514fad2715873d1e02a6fa8e3b9cc43f7aff97aaffac9721c086a319 xt/0-file-is-part-of.t
SHA256 6bdbe1a3a52562b120ddac9fab256ef581e65f5b189422c0ccdb968915b6269c xt/0-no-debug-left-on.t
debian/control view on Meta::CPAN
Homepage: http://user42.tuxfamily.org/gtk2-ex-widgetcursor/index.html
Bugs: mailto:user42_kevin@yahoo.com.au
Package: libgtk2-ex-widgetcursor-perl
Architecture: all
Depends: perl (>= 5.8), libglib-perl, libglib-ex-objectbits-perl (>= 1), libgtk2-perl, ${perl:Depends}, ${misc:Depends}
Description: Mouse pointer cursor in widgets
Gtk2::Ex::WidgetCursor manages the mouse pointer cursor displayed in
the window of a widget. It helps widget or application actions
cooperate with what is normally a write-only resource on the window.
A global busy is included for easy display of a wristwatch in all
application windows while number crunching.
debian/rules view on Meta::CPAN
# sed -i \
# -e 's:F<examples:F</usr/share/doc/libgtk2-ex-widgetcursor-perl/examples:g' \
# -e 's:An F</usr:A F</usr:g' \
# debian/libgtk2-ex-widgetcursor-perl/usr/share/perl5/Gtk2/Ex/WidgetCursor.pm
#
# sed -i \
# -e 's:[\\]fIexamples:\\fI/usr/share/doc/libgtk2-ex-widgetcursor-perl/examples:g' \
# -e 's:An [\\]fI/usr:A \\fI/usr:g' \
# debian/libgtk2-ex-widgetcursor-perl/usr/share/man/man3/Gtk2::Ex::WidgetCursor.3pm
# =for me -- examples/timebusy.pl becomes /usr/share/doc/... in the deb
# =for me -- becomes /usr/share/doc/... in the deb
# =for me -- becomes /usr/share/doc/... in the deb
devel/busy-two.pl view on Meta::CPAN
# Gtk2-Ex-WidgetCursor is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# The Busy/Open now has the new window noticed, the same as the way
# Busy/Open/Rebusy had to be done in WidgetCursor version 1.
#
use strict;
use warnings;
use Gtk2 '-init';
use Gtk2::Ex::WidgetCursor;
use FindBin;
my $progname = $FindBin::Script;
devel/busy-two.pl view on Meta::CPAN
my $t2 = Gtk2::Window->new ('toplevel');
$t2->set_name ("my_toplevel_2");
$t2->signal_connect (destroy => sub {
print "$progname: quit\n";
Gtk2->main_quit;
});
{
my $button = Gtk2::Button->new_with_label ("Busy");
$button->signal_connect (clicked => sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
$toplevel->get_display->flush;
sleep (2);
});
$vbox->pack_start ($button, 1,1,0);
}
$toplevel->show_all;
$t2->show_all;
Gtk2->main;
exit 0;
devel/busydestroy.pl view on Meta::CPAN
print "$progname: main_quit\n";
Gtk2->main_quit;
});
my $vbox = Gtk2::VBox->new;
$toplevel->add ($vbox);
{
my $button = Gtk2::Button->new_with_label ("Busy and Exit");
$button->signal_connect (clicked => sub {
print "$progname: busy and exit\n";
Gtk2::Ex::WidgetCursor->busy;
$toplevel->destroy;
Gtk2->main_quit;
});
$vbox->pack_start ($button, 1,1,0);
}
package Foo;
use strict;
use warnings;
sub new {
my ($class) = @_;
my $self = bless {}, $class;
$self->{'circular'} = $self;
return $self;
}
sub DESTROY {
print "$progname: Foo destroy\n";
Gtk2::Ex::WidgetCursor->unbusy;
}
package main;
my $foo = Foo->new;
$toplevel->show_all;
Gtk2->main;
print "$progname: main returned, now exit\n";
exit 0;
devel/busynew.pl view on Meta::CPAN
# Gtk2-Ex-WidgetCursor is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# The Busy/Open now has the new window noticed, the same as the way
# Busy/Open/Rebusy had to be done in WidgetCursor version 1.
#
use strict;
use warnings;
use Gtk2 '-init';
use Gtk2::Ex::WidgetCursor;
use FindBin;
my $progname = $FindBin::Script;
devel/busynew.pl view on Meta::CPAN
my $toplevel = Gtk2::Window->new ('toplevel');
$toplevel->set_size_request (75, 75);
$toplevel->show_all;
});
$vbox->pack_start ($button, 1,1,0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy and Open");
$button->signal_connect (clicked => sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
my $toplevel = Gtk2::Window->new ('toplevel');
$toplevel->set_size_request (100, 100);
print "$progname: show $toplevel\n";
$toplevel->show_all;
print "$progname: sleep\n";
sleep (2);
print "$progname: flush\n";
$toplevel->get_display->flush;
print "$progname: sleep\n";
sleep (2);
});
$vbox->pack_start ($button, 1,1,0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy / Open / Re-Busy");
$button->signal_connect (clicked => sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
my $toplevel = Gtk2::Window->new ('toplevel');
$toplevel->set_size_request (100, 100);
print "$progname: show $toplevel\n";
$toplevel->show_all;
print "$progname: re-busy\n";
Gtk2::Ex::WidgetCursor->busy;
print "$progname: sleep now\n";
sleep (4);
});
$vbox->pack_start ($button, 1,1,0);
}
$toplevel->show_all;
Gtk2->main;
exit 0;
devel/combo.pl view on Meta::CPAN
#
# Gtk2-Ex-WidgetCursor is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# Some experimenting with Gtk2::Combo. The main thing to do is press "busy
# shortly" and then quickly open the combo popup to see the watch cursor is
# put on there.
use strict;
use warnings;
use Gtk2 '-init';
use Gtk2::Ex::WidgetCursor;
my $toplevel = Gtk2::Window->new ('toplevel');
devel/combo.pl view on Meta::CPAN
Gtk2->main_quit;
});
my $vbox = Gtk2::VBox->new;
$toplevel->add ($vbox);
my $button = Gtk2::Button->new_with_label ("Busy Shortly");
$button->signal_connect
(clicked => sub {
Glib::Timeout->add (1000, sub {
print "combo.pl: busy\n";
Gtk2::Ex::WidgetCursor->busy;
sleep (4);
return 0; # stop timer
});
});
$vbox->pack_start ($button, 1,1,0);
my $combo = Gtk2::Combo->new;
$vbox->pack_start ($combo, 1,1,0);
$combo->set_popdown_strings ('One', 'Two', 'Three', 'Four');
devel/entry.pl view on Meta::CPAN
print "$progname: set umbrella ",$check->get_active,"\n";
$wc->active ($check->get_active);
});
$vbox->pack_start ($check, 1,1,0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy Shortly");
$button->signal_connect
(clicked => sub {
Glib::Timeout->add (1000, sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
sleep (4);
return 0; # stop timer
});
});
$vbox->pack_start ($button, 1,1,0);
}
$toplevel->show_all;
{
devel/linkbutton.pl view on Meta::CPAN
$wc->active ($check->get_active);
});
$vbox->pack_start ($check, 1,1,0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy Shortly");
$button->signal_connect
(clicked => sub {
Glib::Timeout->add (1000, sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
sleep (4);
return 0; # stop timer
});
});
$vbox->pack_start ($button, 1,1,0);
}
$toplevel->show_all;
print "LinkButton sibling windows ",
devel/run.pl view on Meta::CPAN
$button->signal_connect (clicked => sub {
print "$progname: umbrella\n";
$base->cursor('umbrella');
$base->active (1);
});
$vbox->pack_start ($button, 0, 0, 0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy");
$button->signal_connect (clicked => sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
sleep (3);
});
$vbox->pack_start ($button, 0, 0, 0);
}
{
my $wc = Gtk2::Ex::WidgetCursor->new (widget => $area,
cursor => 'heart');
print "$progname: heart $wc\n";
my $id;
sub heart_on {
devel/run.pl view on Meta::CPAN
? Gtk2::Gdk::Cursor->new('gobbler') : undef);
});
$vbox->pack_start ($button, 0, 0, 0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy Shortly");
$button->signal_connect
(clicked => sub {
Glib::Timeout->add (1000, sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
sleep (3);
return 0; # stop timer
});
});
$vbox->pack_start ($button, 0, 0, 0);
}
{
my $button = Gtk2::Button->new_with_label ("Pointer Grab");
$button->signal_connect
(clicked => sub {
devel/spinner.pl view on Meta::CPAN
print "$progname: set umbrella ",$check->get_active,"\n";
$wc->active ($check->get_active);
});
$vbox->pack_start ($check, 1,1,0);
}
{
my $button = Gtk2::Button->new_with_label ("Busy Shortly");
$button->signal_connect
(clicked => sub {
Glib::Timeout->add (1000, sub {
print "$progname: busy\n";
Gtk2::Ex::WidgetCursor->busy;
sleep (4);
return 0; # stop timer
});
});
$vbox->pack_start ($button, 1,1,0);
}
$toplevel->show_all;
print "$progname: Spin _widget_sibling_windows() ",
devel/unbusy-idle.pl view on Meta::CPAN
#
# Gtk2-Ex-WidgetCursor is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# The Gtk2::Ex::WidgetCursor->busy() turns off after the high idle stops
# itself.
use strict;
use warnings;
use Gtk2 '-init';
use Gtk2::Ex::WidgetCursor;
my $toplevel = Gtk2::Window->new('toplevel');
$toplevel->signal_connect (destroy => sub { Gtk2->main_quit; });
devel/unbusy-idle.pl view on Meta::CPAN
my $low_count = 0;
sub low_idle {
print "low idle\n";
sleep(2);
return (++$low_count <= 4); # continue until 4
}
Glib::Idle->add (\&high_idle, undef, Glib::G_PRIORITY_DEFAULT_IDLE - 1000);
Glib::Idle->add (\&low_idle, undef, Glib::G_PRIORITY_DEFAULT_IDLE + 1000);
my $wc = Gtk2::Ex::WidgetCursor->busy;
$toplevel->show_all;
$toplevel->get_display->flush;
Gtk2->main;
exit 0;
examples/misc.pl view on Meta::CPAN
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# This is a miscellaneous contrivance showing three WidgetCursors variously
# acting. There's a base cursor starting undef or settable to a boat or
# umbrella, then a "heart" on and off under a timer, and a button drag
# cursor. A button for the Gtk2::Ex::WidgetCursor->busy mechanism shows how
# it trumps them all (in this case for a 3 second sleep()).
#
# There's no priority level settings, we instead use the rule that the
# newest created has precedence (among equal priorities). This means the
# heart trumps the base, and the button drag cursor which is created
# on-demand is the newest of all three when it exists.
use strict;
use warnings;
examples/misc.pl view on Meta::CPAN
$heart_timer_id = undef;
$heart_cursor->active (0);
}
});
sub heart_beat {
$heart_cursor->active (! $heart_cursor->active);
return 1; # Glib::SOURCE_CONTINUE, continue timer
}
my $busy_button = Gtk2::Button->new_with_label ("Busy");
$busy_button->signal_connect (clicked => sub {
Gtk2::Ex::WidgetCursor->busy;
sleep (3);
});
$vbox->pack_start ($busy_button, 0,0,0);
$toplevel->show_all;
Gtk2->main;
exit 0;
examples/timebusy.pl view on Meta::CPAN
#
# Gtk2-Ex-WidgetCursor is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# If you want to have a "busy" indication across a Glib::Timeout or a
# Glib::IO socket then you just make a WidgetCursor and turn it on and off
# when starting or finishing. The code here does that across some timer
# steps.
#
# You don't have to create the WidgetCursor immediately, you could do that
# when actually starting (the start() function here). And of course the
# cursor could be just on an affected widget (or widgets) not the whole
# toplevel.
#
# If your job holds working state for the calculation in a hash or object or
lib/Gtk2/Ex/WidgetCursor.pm view on Meta::CPAN
#------------------------------------------------------------------------------
# Cribs on widgets using gdk_window_set_cursor directly:
#
# GtkAboutDialog [not handled]
# Puts "email" and "link" tags on text in the credits GtkTextView and
# then does set_cursor on entering or leaving those.
#
# GtkCombo [ok mostly, with a hack]
# Does a single set_cursor for a 'top-left-arrow' on a GtkEventBox in
# its popup when realized. We dig that out for include_children,
# primarily so a busy() shows the watch on the popup window if it
# happens to be open. Of course GtkCombo is one of the ever-lengthening
# parade of working and well-defined widgets which Gtk says you're not
# meant to use any more.
#
# GtkCurve [not handled]
# Multiple set_cursor calls according to mode and motion. A rarely used
# widget so ignore it for now.
#
# GtkEntry [ok, with a hack]
# An Entry uses a private GdkWindow subwindow 4 pixels smaller than the
lib/Gtk2/Ex/WidgetCursor.pm view on Meta::CPAN
# the latter when done. Getting the subwindow is fast since Gtk
# maintains the list of children for gdk_window_get_children() itself
# (as opposed to the way plain Xlib queries the server).
#
# The Entry can be made to restore the insertion cursor by toggling
# 'sensitive'. Hard to know which is worse: toggling sensitive
# needlessly, or forcibly setting the cursor back. The latter is needed
# for the SpinButton subclass below, so it's easier to do that.
#
# GtkFileChooser [probably ok]
# Sets a GDK_CURSOR_WATCH temporarily when busy. That probably kills
# any WidgetCursor setting, but probably GtkFileChooser isn't something
# you'll manipulate externally.
#
# GtkLabel [not handled]
# Puts GDK_XTERM on a private selection window when sensitive and
# selectable text, or something. This misses out on include_children
# for now.
#
# GtkLinkButton [not very good]
# A GtkButton subclass which does 'hand' set_cursor on its windowed
lib/Gtk2/Ex/WidgetCursor.pm view on Meta::CPAN
# the hand on the parent, so that gets the right effect. But any
# WidgetCursor setting on the parent is lost when LinkButton turns off
# its hand under a leave-event. Might have to make a hack connecting to
# leave-event and re-applying the parent window.
#
# GtkPaned [not handled]
# Puts a cursor on its GdkWindow handle when sensitive. Not covered by
# include_children for now.
#
# GtkRecentChooser [probably ok]
# A GDK_WATCH when busy, similar to GtkFileChooser above. Hopefully ok
# most of the time with no special attention.
#
# GtkSpinButton [imperfect]
# Subclass of GtkEntry, but adds a "panel" window of arrows. In Gtk
# 2.12 it was overlaid on the normal Entry widget window, ie. the main
# outer one. In Gtk 2.14 it's a child of that outer window.
#
# For 2.12 it can be dug out by looking for sibling windows with events
# directed to the widget. Then it's a case of operating on three
# windows: the Entry main, the Entry 4-pixel smaller subwindow and the
lib/Gtk2/Ex/WidgetCursor.pm view on Meta::CPAN
&& ($parent = $widget->get_parent) # might not have a parent
&& $parent->get_name eq 'gtk-combo-popup-window');
}
#------------------------------------------------------------------------------
# Could think about documenting this idle level to the world, maybe like the
# following, but would it be any use?
#
# =item C<$Gtk2::Ex::WidgetCursor::busy_idle_priority>
#
# The priority level of the (C<< Glib::Idle->add >>) handler installed by
# C<busy>. This is C<G_PRIORITY_DEFAULT_IDLE - 10> by default, which is
# designed to stay busy through Gtk resizing and redrawing at around
# C<G_PRIORITY_HIGH_IDLE>, but end the busy before ordinary "default idle"
# tasks.
#
# You can change this depending what things you set running at what idle
# levels and where you consider the application no longer busy for user
# purposes. But note changing this variable only affects future C<busy>
# calls, not any currently active one.
#
use constant BUSY_IDLE_PRIORITY => Glib::G_PRIORITY_DEFAULT_IDLE - 10;
my $busy_wc;
my $busy_id;
my $realize_id;
sub busy {
my ($class) = @_;
my @widgets = Gtk2::Window->list_toplevels;
### busy on toplevels: join(' ',@widgets)
if ($busy_wc) {
$busy_wc->add_widgets (@widgets);
} else {
### new busy with class: $class
$busy_wc = $class->new (widgets => \@widgets,
cursor => 'watch',
include_children => 1,
priority => 1000,
active => 1);
}
_flush_mapped_widgets (@widgets);
# This is a hack to persuade Gtk2-Perl 1.160 and 1.181 to finish loading
# Gtk2::Widget. Without this if no Gtk2::Widget has ever been created the
# signal_add_emission_hook() fails. 1.160 needs the combination of isa()
# and find_property(). 1.181 is ok with find_property() alone. Either
# way these can be removed when ready to depend on 1.200 and up.
Gtk2::Widget->isa ('Gtk2::Widget');
Gtk2::Widget->find_property ('name');
$realize_id ||= Gtk2::Widget->signal_add_emission_hook
(realize => \&_do_busy_realize_emission);
$busy_id ||= Glib::Idle->add
(\&_busy_idle_handler, undef, BUSY_IDLE_PRIORITY);
}
# While busy notice extra toplevels which have been realized.
# The cursor setting is applied at the realize so it's there ready for when
# the map is done.
sub _do_busy_realize_emission {
my ($invocation_hint, $param_list) = @_;
my ($widget) = @$param_list;
### WidgetCursor _do_busy_realize_emission(): "$widget"
if ($widget->isa ('Gtk2::Window')) {
$busy_wc->add_widgets (Gtk2::Window->list_toplevels);
### _do_busy_realize_emission() flush
$widget->get_display->flush;
}
return 1; # stay connected
}
# Call unbusy() through $busy_wc to allow for possible subclassing.
# Using unbusy does a flush, which is often unnecessary but will ensure that
# if there's lower priority idles still to run then our cursors go out
# before the time they take.
#
sub _busy_idle_handler {
### _busy_idle_handler finished
$busy_id = undef;
if ($busy_wc) { $busy_wc->unbusy; }
return 0; # Glib::SOURCE_REMOVE, one run only
}
sub unbusy {
# my ($class_or_self) = @_;
### WidgetCursor unbusy()
# Some freaky stuff can happen during perl "global destruction" with
# classes being destroyed and disconecting emission hooks on their own,
# provoking warnings from code like the following that does a cleanup
# itself. Fairly confident that doesn't apply to Gtk2::Widget because
# that class probably, hopefully, maybe, never gets destroyed, or at least
# not until well after any Perl code might get a chance to call unbusy().
#
if ($realize_id) {
Gtk2::Widget->signal_remove_emission_hook (realize => $realize_id);
undef $realize_id;
}
if ($busy_id) {
Glib::Source->remove ($busy_id);
$busy_id = undef;
}
if ($busy_wc) {
my @widgets = $busy_wc->widgets;
$busy_wc = undef;
# flush to show new cursors immediately, per busy() below
_flush_mapped_widgets (@widgets);
}
}
# flush the Gtk2::Gdk::Display's of all the given widgets, if they're mapped
# (with the idea being if they're unmapped then there's nothing to see so no
# need to flush)
#
sub _flush_mapped_widgets {
my @widget_list = @_;
lib/Gtk2/Ex/WidgetCursor.pm view on Meta::CPAN
=for test_synopsis my ($mywidget)
=head1 SYNOPSIS
use Gtk2::Ex::WidgetCursor;
my $wc = Gtk2::Ex::WidgetCursor->new (widget => $mywidget,
cursor => 'fleur',
active => 1);
# show wristwatch everywhere while number crunching
Gtk2::Ex::WidgetCursor->busy;
# bonus invisible cursor creator
my $cursor = Gtk2::Ex::WidgetCursor->invisible_cursor;
=head1 OBJECT HIERARCHY
C<Gtk2::Ex::WidgetCursor> is a subclass of C<Glib::Object>.
Glib::Object
Gtk2::Ex::WidgetCursor
=head1 DESCRIPTION
WidgetCursor manages the mouse pointer cursor shown in widget windows as per
C<Gtk2::Gdk::Window> C<set_cursor>. A "busy" mechanism can display a
wristwatch in all windows when the whole application is blocked.
With the plain window C<set_cursor>, it's difficult for widget add-ons or
independent parts of an application to cooperate with what should be shown
at different times or in different modes.
A C<Gtk2::Ex::WidgetCursor> object represents a desired cursor in one or
more widgets. When "active" and when it's the newest or highest priority
then the specified cursor is set onto those widget window(s). If the
WidgetCursor object is later made inactive or destroyed then the next
remaining highest WidgetCursor takes effect, etc.
The idea is to have say a base WidgetCursor for an overall mode, then
something else temporarily while dragging, and perhaps a wristwatch "busy"
indication overriding one or both those (like the global "busy" mechanism
below).
See the F<examples> directory in the sources for some variously contrived
sample programs.
=head1 WIDGETCURSOR OBJECTS
=head2 Construction
=over
lib/Gtk2/Ex/WidgetCursor.pm view on Meta::CPAN
Whether to apply the cursor to child widgets of the given widgets too.
Normally the cursor in a child widget overrides its parents (as
C<set_cursor> does at the window level). But with C<include-children>, a
setting in a parent applies to the children too, with priority+newest
applied as usual.
=back
=head1 APPLICATION BUSY
The C<busy> mechanism sets a "watch" cursor on all windows to tell the user
the program is doing CPU-intensive work and might not run the main loop to
draw or interact for a while.
If your busy state isn't CPU-intensive, but instead perhaps a Glib timer or
an I/O watch on a socket, then this is not what you want, it'll turn off too
soon. (Instead simply make a C<WidgetCursor> with a C<"watch"> and turn it
on or off at your start and end points. See F<examples/timebusy.pl> for
that sort of thing.)
=over 4
=item C<< Gtk2::Ex::WidgetCursor->busy () >>
Show the C<"watch"> cursor (a little wristwatch) in all the application's
widget windows (toplevels, dialogs, popups, etc). An idle handler
(C<< Glib::Idle->add >>) removes the watch automatically upon returning to
the main loop.
The X queue is flushed to set the cursor immediately, so the program can go
straight into its work. For example
Gtk2::Ex::WidgetCursor->busy;
foreach my $i (1 .. 1_000_000) {
# do much number crunching
}
If you create new windows within a C<busy> then they too get the busy cursor
(or they're supposed to, something fishy in Gtk 2.20 and maybe 2.18 has
broken it). You can even go busy before creating any windows at all. But
note WidgetCursor doesn't do any extra X flush for new creations; if you
want them to show immediately then you must flush in the usual way.
C<busy> uses a C<WidgetCursor> object as described above and so cooperates
with application uses of that. Priority level 1000 is set to be above other
cursor settings.
=item C<< Gtk2::Ex::WidgetCursor->unbusy () >>
Explicitly remove the watch cursor setup by C<busy> above. The X request
queue is flushed to ensure any cursor change appears immediately. If
C<busy> is not active then do nothing.
It's unlikely you'll need C<unbusy>, because if your program hasn't yet
reached the idle handler in the main loop then it's probably still busy!
But perhaps if most of your work is done then you could unbusy while the
remainder is finishing up.
=back
=head1 INVISIBLE CURSOR
The following invisible cursor is used by WidgetCursor for the
C<"invisible"> cursor and is made available for general use.
=over 4
t/busy-first.t view on Meta::CPAN
#
# Gtk2-Ex-WidgetCursor is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-WidgetCursor. If not, see <http://www.gnu.org/licenses/>.
# specific test of go busy when no widgets, exercising a workaround for
# Gtk2-Perl 1.181
use strict;
use warnings;
use Gtk2::Ex::WidgetCursor;
use Test::More tests => 1;
use lib 't';
use MyTestHelpers;
BEGIN { MyTestHelpers::nowarnings() }
SKIP: {
require Gtk2;
Gtk2->disable_setlocale; # leave LC_NUMERIC alone for version nums
if (! Gtk2->init_check) { skip 'due to no DISPLAY available', 1; }
Gtk2::Ex::WidgetCursor->busy;
ok (1);
}
exit 0;
t/overload.t view on Meta::CPAN
my $toplevel = Gtk2::Window->new;
$toplevel->add ($widget);
$toplevel->show_all;
MyTestHelpers::main_iterations();
my $wobj = Gtk2::Ex::WidgetCursor->new (widgets => [$toplevel,$widget],
active => 1,
include_children => 1,
cursor => 'invisible');
Gtk2::Ex::WidgetCursor->busy;
$toplevel->destroy;
ok (1);
exit 0;