File Coverage

blib/lib/Test/Weaken/Gtk2.pm
Criterion Covered Total %
statement 32 82 39.0
branch 6 36 16.6
condition 1 18 5.5
subroutine 11 15 73.3
pod 8 8 100.0
total 58 159 36.4


line stmt bran cond sub pod time code
1             # Copyright 2008, 2009, 2010, 2011, 2012 Kevin Ryde
2              
3             # This file is part of Gtk2-Ex-WidgetBits.
4             #
5             # Gtk2-Ex-WidgetBits is free software; you can redistribute it and/or
6             # modify it under the terms of the GNU General Public License as published
7             # by the Free Software Foundation; either version 3, or (at your option) any
8             # later version.
9             #
10             # Gtk2-Ex-WidgetBits is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13             # Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Gtk2-Ex-WidgetBits. If not, see .
17              
18              
19             package Test::Weaken::Gtk2;
20 5     5   16192 use 5.006; # for "our" (which Test::Weaken itself uses)
  5         21  
  5         268  
21 5     5   33 use strict;
  5         12  
  5         191  
22 5     5   29 use warnings;
  5         11  
  5         203  
23 5     5   29 use Scalar::Util 'refaddr';
  5         7  
  5         533  
24              
25             # uncomment this to run the ### lines
26             #use Smart::Comments;
27              
28 5     5   27 use Exporter;
  5         85  
  5         7340  
29             our @ISA = ('Exporter');
30             our @EXPORT_OK = qw(contents_container
31             contents_submenu
32             contents_cell_renderers
33             destructor_destroy
34             destructor_destroy_and_iterate
35             ignore_default_display);
36              
37             our $VERSION = 48;
38              
39             sub contents_container {
40 1     1 1 8 my ($ref) = @_;
41 1         12 require Scalar::Util;
42 1 50 33     9 if (Scalar::Util::blessed($ref)
43             && $ref->isa('Gtk2::Container')) {
44 0         0 return $ref->get_children;
45             } else {
46 1         3 return ();
47             }
48             }
49              
50             sub contents_submenu {
51 1     1 1 6 my ($ref) = @_;
52 1         4 require Scalar::Util;
53 1 50       6 if (Scalar::Util::blessed($ref)) {
54 0         0 my $menu;
55 0 0       0 if ($ref->isa('Gtk2::MenuItem')) {
    0          
56 0         0 $menu = $ref->get_submenu;
57             } elsif ($ref->isa('Gtk2::MenuToolButton')) {
58 0         0 $menu = $ref->get_menu;
59             }
60 0 0       0 if (defined $menu) {
61 0         0 return $menu;
62             }
63             }
64 1         3 return ();
65             }
66              
67             sub contents_cell_renderers {
68 1     1 1 5 my ($ref) = @_;
69              
70 1         5 require Scalar::Util;
71 1 50       8 Scalar::Util::blessed($ref) || return;
72 0         0 my $method;
73 0 0 0     0 if ($ref->isa('Gtk2::CellLayout')
    0 0        
74             && $ref->can('get_cells')) { # new in Gtk 2.12
75 0         0 $method = 'get_cells';
76              
77             } elsif ($ref->isa('Gtk2::TreeViewColumn') || $ref->isa('Gtk2::CellView')) {
78             # gtk_cell_view_get_cell_renderers() or
79             # gtk_tree_view_column_get_cell_renderers() pre-dating the interface
80             # style
81 0         0 $method = 'get_cell_renderers';
82              
83             } else {
84 0         0 return;
85             }
86              
87             # as of Gtk 2.20.1 GtkCellView tries to set the data into the cells
88             # returned by either the get_cells interface or
89             # gtk_cell_view_get_cell_renderers(). If there's no display_row set then
90             # it throws a g_log. Suppress that in case we're looking for leaks in an
91             # empty CellView or without a display_row.
92             #
93 0         0 my @cells;
94             {
95 0         0 my $old_warn = $SIG{__WARN__};
  0         0  
96             local $SIG{__WARN__} = sub {
97 0     0   0 my ($str) = @_;
98 0 0       0 if (index ($str, 'Gtk-CRITICAL **: gtk_cell_view_set_cell_data: assertion') >= 0) {
99             ### Suppressed gtk_cell_view_set_cell_data() assertion failure
100 0         0 return;
101             }
102 0 0       0 if ($old_warn) {
103 0         0 $old_warn->(@_);
104             } else {
105 0         0 warn @_;
106             }
107 0         0 };
108 0         0 @cells = $ref->$method;
109             }
110              
111             # Gtk2-Perl 1.221 returns a one-element list of undef if no cells.
112             # Prefer to return an empty list for that case.
113 0 0 0     0 if (@cells == 1 && ! defined $cells[0]) {
114 0         0 @cells = ();
115             }
116 0         0 return @cells;
117             }
118              
119             #------------------------------------------------------------------------------
120             sub destructor_destroy {
121 0     0 1 0 my ($ref) = @_;
122 0 0       0 if (ref($ref) eq 'ARRAY') {
123 0         0 $ref = $ref->[0];
124             }
125 0         0 $ref->destroy;
126             }
127              
128             sub destructor_destroy_and_iterate {
129 0     0 1 0 my ($ref) = @_;
130 0         0 destructor_destroy ($ref);
131 0         0 _main_iterations();
132             }
133              
134             # Gtk 2.16 can go into a hard loop on events_pending() / main_iteration_do()
135             # if dbus is not running, or something like that. In any case limiting the
136             # iterations is good for test safety.
137             #
138             # FIXME: Not sure how aggressive to be on hitting the maximum count. If
139             # testing can likely continue then a diagnostic is enough, but maybe a
140             # count-out means something too broken to continue.
141             #
142             # The iterations count actually run is cute to see to check what has gone
143             # through the main loop. Would it be worth giving that always, or under an
144             # option, or something?
145             #
146             sub _main_iterations {
147 0     0   0 require Test::More;
148 0         0 my $count = 0;
149             ### _main_iterations() ...
150 0         0 while (Gtk2->events_pending) {
151 0         0 $count++;
152 0         0 Gtk2->main_iteration_do (0);
153              
154 0 0       0 if ($count >= 1000) {
155             ### _main_iterations() count exceeded: $count
156 0         0 eval {
157 0         0 Test::More::diag ("main_iterations(): oops, bailed out after $count events/iterations");
158             };
159 0         0 return;
160             }
161             }
162             ### _main_iterations() events/iterations: $count
163             }
164              
165             #------------------------------------------------------------------------------
166             sub ignore_default_display {
167 2     2 1 198 my ($ref) = @_;
168              
169             # Gtk2 loaded, and Gtk 2.2 up
170 2 50       31 Gtk2::Gdk::Display->can('get_default') || return 0;
171              
172 0   0     0 my $default_display = Gtk2::Gdk::Display->get_default
173             || return 0; # undef until Gtk2 inited
174              
175 0         0 return (refaddr($ref) == refaddr($default_display));
176             }
177              
178             sub ignore_default_screen {
179 1     1 1 218 my ($ref) = @_;
180              
181             # Gtk2 loaded, and Gtk 2.2 up
182 1 50       21 Gtk2::Gdk::Screen->can('get_default') || return 0;
183              
184 0   0     0 my $default_screen = Gtk2::Gdk::Screen->get_default
185             || return 0; # undef until Gtk2 inited
186              
187 0         0 return (refaddr($ref) == refaddr($default_screen));
188             }
189              
190             sub ignore_default_root_window {
191 1     1 1 436 my ($ref) = @_;
192              
193             # must have Gtk2 loaded
194 1 50       22 Gtk2::Gdk->can('get_default_root_window') or return 0;
195              
196             # in Gtk 2.2 up must have default screen from Gtk2->init_check() otherwise
197             # Gtk2::Gdk->get_default_root_window() gives a g_log() warning
198 0 0         if (Gtk2::Gdk::Screen->can('get_default')) {
199 0 0         Gtk2::Gdk::Screen->get_default || return 0;
200             }
201              
202             # in Gtk 2.0 get NULL from gdk_get_default_root_window() if no
203             # Gtk2->init_check() yet
204 0   0       my $default_root_window = Gtk2::Gdk->get_default_root_window
205             || return 0;
206              
207 0           return (refaddr($ref) == refaddr($default_root_window));
208             }
209              
210              
211             #------------------------------------------------------------------------------
212             1;
213             __END__