Gtk2-Ex-Xor

 view release on metacpan or  search on metacpan

lib/Gtk2/Ex/Xor.pm  view on Meta::CPAN

*Goo::Canvas::Gtk2_Ex_Xor_background_from_style
  = \&Gtk2::Entry::Gtk2_Ex_Xor_background_from_style;

# For Gtk2::Bin subclasses such as Gtk2::EventBox, look at the child's
# background if there's a child and if it's a no-window widget, since that
# child is what will be xored over.
#
# Perhaps this should be only some of the Bin classes, like Gtk2::Window,
# Gtk2::EventBox and Gtk2::Alignment.
{
  package Gtk2::Bin;
  sub Gtk2_Ex_Xor_background {
    my ($widget) = @_;
    # same override as above ...
    if (exists $widget->{'Gtk2_Ex_Xor_background'}) {
      return $widget->{'Gtk2_Ex_Xor_background'};
    }
    if (my $child = $widget->get_child) {
      if ($child->flags & 'no-window') {
        return $child->Gtk2_Ex_Xor_background;
      }
    }
    return $widget->SUPER::Gtk2_Ex_Xor_background;
  }
}


#------------------------------------------------------------------------------
# window choice hacks

# normal "->window" for most widgets
*Gtk2::Widget::Gtk2_Ex_Xor_window = \&Gtk2::Widget::window;

# for Gtk2::Layout must draw into its "bin_window"
*Gtk2::Layout::Gtk2_Ex_Xor_window = \&Gtk2::Layout::bin_window;

sub Gtk2::TextView::Gtk2_Ex_Xor_window {
  my ($textview) = @_;
  return $textview->get_window ('text');
}

# GtkEntry has a window and then within that a subwindow just 4 pixels
# smaller in height.  The latter is what it draws on.
#
# The following code as per Gtk2::Ex::WidgetCursor.  Since the subwindow
# isn't a documented feature check that it does, in fact, exist.
#
# The alternative would be "include inferiors" on the xor gc's.  But that'd
# probably cause problems on windowed widget children, since expose events
# in them wouldn't be seen by the parent's expose to redraw the
# crosshair/lasso/etc.
#
sub Gtk2::Entry::Gtk2_Ex_Xor_window {
  my ($widget) = @_;
  my $win = $widget->window || return undef; # if unrealized
  return ($win->get_children)[0] # first child
    || $win;
}

# GooCanvas draws on a subwindow too, also undocumented it seems
# (there's a tmp_window too, but that's only an overlay suppressing some
# expose events or something at selected times)
*Goo::Canvas::Gtk2_Ex_Xor_window = \&Gtk2::Entry::Gtk2_Ex_Xor_window;

1;
__END__

=for stopwords add-ons natively bg xoring multi-window subwindow subwindows SyncCall Ryde Gtk2-Ex-Xor

=head1 NAME

Gtk2::Ex::Xor -- shared support for drawing with XOR

=head1 DESCRIPTION

This is support code shared by C<Gtk2::Ex::CrossHair> and
C<Gtk2::Ex::Lasso>.

Both those add-ons draw using an "xor" onto the pixels in a widget (hence
the dist name), using a value that flips between the widget background and
the cross or lasso line colour.  Drawing like this is fast and portable,
though doing it as an add-on can potentially clash with what the widget does
natively.

=over 4

=item *

A single dominant background colour is assumed.  Often shades of grey or
similar will end up with a contrasting line but there's no guarantee of
that.

=item *

The background colour is taken from the widget C<Gtk2::Style> "bg" for
normal widgets, or from "base" for text widgets C<Gtk2::Entry> and
C<Gtk2::TextView>.  C<Goo::Canvas> is recognised as using "base" too.

=item *

Expose events are watched and xoring redone, though it assumes the widget
will redraw only the exposed region, as opposed to a full window redraw.
Clipping in a redraw is usually what you want, especially if the display
might not have the X double-buffering extension.

=item *

For multi-window widgets it's necessary to figure out which subwindow is the
one to draw on.  The xoring recognises the "bin" window of C<Gtk2::Layout>
(which includes C<Gnome2::Canvas>), the "text" subwindow of
C<Gtk2::TextView>, and the secret subwindows of C<Gtk2::Entry> and
C<Goo::Canvas>.

=item *

The SyncCall mechanism is used to protect against flooding the server with
more drawing than it can keep up with.  Each motion event would only result
in a few drawing requests, but it's still easy to overload the server if it
sends a lot of motions or if it's not very fast at drawing wide lines.  The
effect of SyncCall is to delay further drawing until hearing back from the
server that the previous has completed.



( run in 2.149 seconds using v1.01-cache-2.11-cpan-7fcb06a456a )