File Coverage

blib/lib/Gtk2/Ex/WidgetBits.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # Copyright 2007, 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             package Gtk2::Ex::WidgetBits;
19 1     1   855 use 5.008;
  1         3  
  1         39  
20 1     1   6 use strict;
  1         2  
  1         33  
21 1     1   6 use warnings;
  1         2  
  1         39  
22 1     1   5 use Carp;
  1         1  
  1         76  
23 1     1   747 use Gtk2;
  0            
  0            
24              
25             # uncomment this to run the ### lines
26             #use Smart::Comments;
27              
28             our $VERSION = 48;
29              
30             # get_root_position() might be done as
31             #
32             # my $toplevel = $widget->get_toplevel;
33             # my $window = $toplevel->window || return; # if unrealized
34             # return $widget->translate_coordinates ($toplevel,
35             # $window->get_position);
36             #
37             # if it can be assumed the toplevel widget of a hierarchy has its window a
38             # child of the root window (after possible window manager frame). Or
39             # alternately just get_toplevel() could eliminate the 'no-window' test if it
40             # can be assumed the toplevel is a windowed widget. All of which is of
41             # course true of GtkWindow, and probably ends up right for GtkPlug too, but
42             # could a custom toplevel widget do something tricky?
43             #
44             sub get_root_position {
45             my ($widget) = @_;
46             my $window = $widget->window || return; # if unrealized
47             require Gtk2::Ex::GdkBits;
48             my ($x, $y) = Gtk2::Ex::GdkBits::window_get_root_position ($window);
49             if ($widget->flags & 'no-window') {
50             my $alloc = $widget->allocation;
51             $x += $alloc->x;
52             $y += $alloc->y;
53             }
54             return ($x, $y);
55             }
56             sub warp_pointer {
57             my ($widget, $x, $y) = @_;
58             my ($origin_x, $origin_y) = get_root_position ($widget)
59             or croak "Cannot warp on unrealized $widget";
60             my $screen = $widget->get_screen;
61             my $display = $widget->get_display;
62             $display->warp_pointer ($screen, $origin_x + $x, $origin_y + $y);
63             }
64              
65             sub xy_root_to_widget {
66             my ($widget, $root_x, $root_y) = @_;
67             ### _xy_root_to_widget(): "$widget", $root_x, $root_y
68             my ($x, $y) = Gtk2::Ex::WidgetBits::get_root_position ($widget);
69             if (! defined $x) {
70             ### widget unrealized
71             return;
72             } else {
73             return ($root_x - $x, $root_y - $y);
74             }
75             }
76              
77             #------------------------------------------------------------------------------
78              
79             sub xy_distance_mm {
80             my ($widget, $x1, $y1, $x2, $y2) = @_;
81             my ($xmm, $ymm) = pixel_size_mm ($widget)
82             or return undef;
83             return _hypot ($xmm * ($x1 - $x2),
84             $ymm * ($y1 - $y2));
85             }
86              
87             sub pixel_aspect_ratio {
88             my ($widget) = @_;
89             my ($xmm, $ymm) = pixel_size_mm ($widget)
90             or return undef;
91             return ($xmm / $ymm);
92             }
93              
94             if (Gtk2::Gdk::Screen->can('get_width')) {
95             eval "\n#line ".(__LINE__+1)." \"".__FILE__."\"\n" . <<'HERE' or die;
96             ### using widget->screen
97              
98             sub pixel_size_mm {
99             my ($widget) = @_;
100              
101             # gtk_widget_get_screen() returns the default screen if the widget is not
102             # yet in a toplevel, so test gtk_widget_has_screen() first. Often just
103             # that default screen would be good enough, but best not to be sloppy with
104             # that sort of thing if potentially multi-display.
105             #
106             $widget->has_screen
107             or return; # no values
108             my $screen = $widget->get_screen;
109             return ($screen->get_width_mm / $screen->get_width,
110             $screen->get_height_mm / $screen->get_height);
111              
112             # Pointless in Gtk 2.14, the monitor sizes are always -1.
113             # Xinerama 1.1 doesn't give monitor sizes in millimetres, only pixel areas.
114             #
115             # For a multi-monitor screen an individual monitor size is used if
116             # available. Currently the calculation only looks at a single monitor
117             # containing or nearest to the widget, using C. No
118             # attempt is made to tell if the line x1,y1 to x2,y2 crosses multiple
119             # monitors.
120             #
121             # # xinerama new in Gtk 2.14 (2008) and Gtk2-Perl 1.191 (Aug 2008)
122             # if (my $func = $screen->can('get_monitor_at_window')) {
123             # # no position on the screen until realized
124             # if (my $win = $widget->window) {
125             # my $mnum = $func->($screen, $win);
126             # my $rect = $screen->get_monitor_geometry ($mnum);
127             # my $width_mm = $screen->get_monitor_width_mm ($mnum);
128             # my $height_mm = $screen->get_monitor_height_mm ($mnum);
129             # # sizes -1 if not known
130             # if ($width_mm != -1 && $height_mm != -1) {
131             # return ($width_mm / $rect->width,
132             # $height_mm / $rect->height);
133             # }
134             # }
135             # }
136             }
137             1
138             HERE
139              
140             } else {
141             eval "\n#line ".(__LINE__+1)." \"".__FILE__."\"\n" . <<'HERE' or die;
142             ### using Gtk 2.0.x single-screen size
143              
144             # Gtk 2.0.x single-screen sizes
145             sub pixel_size_mm {
146             return (Gtk2::Gdk->screen_width_mm / Gtk2::Gdk->screen_width,
147             Gtk2::Gdk->screen_height_mm / Gtk2::Gdk->screen_height);
148             }
149             1
150             HERE
151             }
152              
153             #------------------------------------------------------------------------------
154             # generic
155              
156             # cf Math::Libm hypot()
157             sub _hypot {
158             my ($x, $y) = @_;
159             return sqrt ($x ** 2 + $y ** 2);
160             }
161              
162             1;
163             __END__