… | |
… | |
6 | |
6 | |
7 | use Mozilla::Plugin; |
7 | use Mozilla::Plugin; |
8 | |
8 | |
9 | =head1 DESCRIPTION |
9 | =head1 DESCRIPTION |
10 | |
10 | |
|
|
11 | sorry... |
|
|
12 | |
11 | =over 4 |
13 | =over 4 |
12 | |
14 | |
13 | =cut |
15 | =cut |
14 | |
16 | |
15 | package Mozilla::Plugin; |
17 | package Mozilla::Plugin; |
16 | |
18 | |
17 | use base Exporter; |
19 | use base Exporter; |
|
|
20 | use Storable; |
18 | #use XSLoader; |
21 | #use XSLoader; |
19 | |
22 | |
20 | $VERSION = 0.12; |
23 | $VERSION = 0.01; |
21 | @EXPORT = qw(); |
24 | @EXPORT = qw(); |
22 | |
25 | |
23 | warn "in module [@ARGV]";#d# |
|
|
24 | |
|
|
25 | #XSLoader::load __PACKAGE__, $VERSION; |
26 | #XSLoader::load __PACKAGE__, $VERSION; |
26 | use Data::Dumper; |
27 | use Data::Dumper;#d# |
27 | |
28 | |
28 | my $data; |
29 | my $data; |
|
|
30 | |
|
|
31 | sub BIAS() { -2000000000 } # ugliest hack ever seen |
29 | |
32 | |
30 | sub snd_cmd($) { |
33 | sub snd_cmd($) { |
31 | $data = pack "NN", 0, ord($_[0]); |
34 | $data = pack "NN", 0, ord($_[0]); |
32 | } |
35 | } |
33 | |
36 | |
|
|
37 | sub snd_ptr($) { |
|
|
38 | $data .= $_[0]; |
|
|
39 | } |
|
|
40 | |
|
|
41 | sub snd_u32($) { |
|
|
42 | $data .= pack "N", $_[0]; |
|
|
43 | } |
|
|
44 | |
34 | sub snd_i32($) { |
45 | sub snd_i32($) { |
35 | $data .= pack "N", $_[0]; |
46 | $data .= pack "N", $_[0] - BIAS; |
36 | } |
47 | } |
37 | |
48 | |
38 | sub snd_blk($) { |
49 | sub snd_blk($) { |
39 | $data .= pack "NA*", length($_[0]), $_[0]; |
50 | $data .= pack "NA*", length($_[0]), $_[0]; |
40 | } |
51 | } |
41 | |
52 | |
42 | sub snd_snd($) { |
53 | sub snd_snd() { |
43 | substr ($data, 0, 4) = pack "N", length $data; |
54 | substr ($data, 0, 4) = pack "N", length $data; |
44 | length($data) == syswrite $_[0], $data; |
55 | length ($data) == syswrite FD, $data; |
45 | } |
56 | } |
46 | |
57 | |
|
|
58 | sub snd_dyn($) { |
|
|
59 | length ($_[0]) == syswrite FD, $_[0]; |
|
|
60 | } |
|
|
61 | |
47 | sub rcv_cmd { |
62 | sub rcv_cmd() { |
48 | my $buf; |
63 | my $buf; |
49 | 4 == sysread $_[0], $buf, 4 or exit; |
64 | 4 == sysread FD, $buf, 4 or exit; |
50 | my $len = unpack "N", $buf; |
65 | my $len = unpack "N", $buf; |
51 | $len -= 4; |
66 | $len -= 4; |
52 | $len == sysread $_[0], $buf, $len or die; |
67 | $len == sysread FD, $buf, $len or die; |
53 | |
68 | |
54 | $data = substr $buf, 4; |
69 | $data = substr $buf, 4; |
55 | |
70 | |
56 | substr $buf, 3, 1; |
71 | substr $buf, 3, 1; |
57 | } |
72 | } |
58 | |
73 | |
|
|
74 | sub rcv_ptr() { |
|
|
75 | my $ptr = substr $data, 0, 8; |
|
|
76 | $data = substr $data, 8; |
|
|
77 | $ptr; |
|
|
78 | } |
|
|
79 | |
|
|
80 | sub rcv_u32() { |
|
|
81 | my $u32 = unpack "N", $data; |
|
|
82 | $data = substr $data, 4; |
|
|
83 | $u32; |
|
|
84 | } |
|
|
85 | |
59 | sub rcv_i32() { |
86 | sub rcv_i32() { |
60 | my $i32 = unpack "N", $data; |
87 | my $i32 = BIAS + unpack "N", $data; |
61 | $data = substr $data, 4; |
88 | $data = substr $data, 4; |
62 | $i32; |
89 | $i32; |
63 | } |
90 | } |
64 | |
91 | |
65 | sub rcv_blk() { |
92 | sub rcv_blk() { |
… | |
… | |
67 | my $str = substr $data, 4, $len; |
94 | my $str = substr $data, 4, $len; |
68 | $data = substr $data, 4 + $len; |
95 | $data = substr $data, 4 + $len; |
69 | $str; |
96 | $str; |
70 | } |
97 | } |
71 | |
98 | |
72 | sub handle_cmd { |
99 | =item my $fh = server_fh |
|
|
100 | |
|
|
101 | The design of this module is event-based. When the plug-in starts (there |
|
|
102 | is always just one interpreter) it spawns one perl interpreter which |
|
|
103 | will immediately go into a even loop. If you want to use your own event |
|
|
104 | loop (e.g. using the Gtk or Event modules) you need to register a file |
|
|
105 | input handler on the filehandle returned by C<server_fh> that calls |
|
|
106 | C<server_event> whenever there is input pending on C<server_fh>. This will |
|
|
107 | ensure proper operation of the plug-in. |
|
|
108 | |
|
|
109 | =item server_event |
|
|
110 | |
|
|
111 | Call this function whenever there is data available on the C<server_fh>. This function |
|
|
112 | might not return. |
|
|
113 | |
|
|
114 | Due to this design (flaw?), sharing of different toolkits using this |
|
|
115 | plug-in is difficult at best. Spawning a new perl interpreter for every |
|
|
116 | plug-in is also not very viable, so in the future one might be able to |
|
|
117 | specify a group on the embed statement (i.e. EMBED GROUP="gtk+"). |
|
|
118 | |
|
|
119 | =cut |
|
|
120 | |
|
|
121 | sub server_fh() { *FD } |
|
|
122 | |
|
|
123 | sub server_event() { |
73 | my $cmd = rcv_cmd *FD1; |
124 | my $cmd = rcv_cmd; |
|
|
125 | |
|
|
126 | warn "cmd<$cmd>\n";#d# |
74 | |
127 | |
75 | if ($cmd eq "I") { |
128 | if ($cmd eq "I") { |
76 | rcv_i32 == 1 or die "protocol version mismatch\n"; |
129 | rcv_u32 == 1 or die "protocol version mismatch\n"; |
77 | ($IFACE, $OSNAME, $OSVERS) = (rcv_blk, rcv_blk, rcv_blk); |
130 | ($IFACE, $OSNAME, $OSVERS) = (rcv_blk, rcv_blk, rcv_blk); |
78 | warn " ($IFACE, $OSNAME, $OSVERS) \n";#d# |
131 | |
79 | } elsif ($cmd eq "+") { |
132 | } elsif ($cmd eq "+") { |
80 | my ($objid, $type, $mode, $save, $argc) |
133 | my ($objid, $type, $mode, $save, $argc) |
81 | = (rcv_i32, rcv_blk, rcv_i32, rcv_blk, rcv_i32); |
134 | = (rcv_ptr, rcv_blk, rcv_u32, rcv_blk, rcv_u32); |
82 | my %args; |
135 | my %args; |
83 | $args{rcv_blk} = rcv_blk while $argc--; |
136 | while ($argc--) { |
|
|
137 | my ($argn, $argv) = (rcv_blk, rcv_blk); |
|
|
138 | $args{$argn} = $argv; |
|
|
139 | } |
84 | |
140 | |
|
|
141 | warn "new obj $objid\n";#d# |
85 | $_OBJ{$objid} = new Mozilla::Plugin |
142 | $_OBJ{$objid} = new Mozilla::Plugin |
|
|
143 | objid => $objid, |
86 | type => $type, |
144 | type => $type, |
87 | mode => $mode, |
145 | mode => $mode, |
88 | save => $save, |
146 | save => $save, |
89 | args => \%args; |
147 | args => \%args; |
90 | |
148 | |
91 | } elsif ($cmd eq "-") { |
149 | } elsif ($cmd eq "-") { |
92 | my $objid = rcv_i32; |
150 | my $objid = rcv_ptr; |
93 | my $save = |
151 | my $save = (delete $_OBJ{$objid})->save; |
94 | $_OBJ{$objid}->save |
152 | snd_cmd "-"; |
|
|
153 | snd_u32 length $save; |
|
|
154 | snd_snd and snd_dyn $save; |
|
|
155 | |
|
|
156 | } elsif ($cmd eq "W") { |
|
|
157 | my $objid = rcv_ptr; |
|
|
158 | my %args = ( |
|
|
159 | window => rcv_ptr, |
|
|
160 | x => rcv_i32, |
|
|
161 | y => rcv_i32, |
|
|
162 | w => rcv_i32, |
|
|
163 | h => rcv_i32, |
|
|
164 | ); |
|
|
165 | if ($IFACE eq "UNIX") { |
|
|
166 | $args{window} = unpack "xxxxN", $args{window}; |
|
|
167 | $args{ws_type} = rcv_i32; |
|
|
168 | $args{ws_depth} = rcv_u32; |
|
|
169 | } |
|
|
170 | |
|
|
171 | $_OBJ{$objid}->set_window(\%args); |
|
|
172 | |
95 | } else { |
173 | } else { |
96 | die "unknown command '$cmd' received"; |
174 | die "unknown command '$cmd' received"; |
97 | } |
175 | } |
98 | } |
176 | } |
99 | |
177 | |
100 | sub mainloop { |
178 | sub mainloop { |
101 | handle_cmd while 1; |
179 | server_event while 1; |
102 | } |
180 | } |
103 | |
181 | |
104 | sub _main { |
182 | sub init { |
105 | $LIBDIR = shift @ARGV; |
183 | my $self = shift; |
|
|
184 | |
106 | $IN_MOZILLA = 1; |
185 | $IN_MOZILLA = 1; |
107 | (shift @ARGV) =~ /^(\d+),(\d+)$/ or die "init arg error"; |
186 | |
108 | my ($fd1, $fd2) = ($1, $2); |
|
|
109 | open FD1, "+<&=$fd1"; binmode FD1; |
187 | open FD, "+<&=$_[0]"; binmode $FD; |
110 | open FD2, "+<&=$fd2"; binmode FD2; |
|
|
111 | |
188 | |
|
|
189 | warn "init: ".Dumper(@_); |
|
|
190 | |
112 | mainloop; |
191 | $self->mainloop; |
113 | |
|
|
114 | close FD2; |
|
|
115 | close FD1; |
|
|
116 | } |
192 | } |
117 | |
193 | |
118 | sub new { |
194 | sub new { |
|
|
195 | my $class = shift; |
|
|
196 | my $self = bless { @_ }, $class; |
|
|
197 | $self->{save} = $self->{save} ne "" |
|
|
198 | ? Storable::thaw $self->{save} |
|
|
199 | : {}; |
119 | warn "new: ".Dumper(\@_); |
200 | warn "new: ".Dumper($self); |
|
|
201 | $self; |
120 | } |
202 | } |
121 | |
203 | |
122 | sub set_window { |
204 | sub set_window { |
|
|
205 | my $self = shift; |
|
|
206 | my $new = shift; |
|
|
207 | if ($self->{window}) { |
|
|
208 | if ($self->{window}{window} ne $new->{window}) { |
|
|
209 | $self->window_delete($self->{window}); |
|
|
210 | } else { |
|
|
211 | $self->window_resize($new->{window}, $new->{w}, $new->{h}); |
|
|
212 | } |
|
|
213 | $self->{window} = $new; |
|
|
214 | } else { |
|
|
215 | $self->{window} = $new; |
|
|
216 | $self->window_new($new->{window}, $new->{w}, $new->{h}); |
|
|
217 | } |
123 | warn "set_window: ".Dumper(\@_); |
218 | warn "set_window: ".Dumper($self); |
124 | } |
219 | } |
|
|
220 | |
|
|
221 | sub window_new {} |
|
|
222 | sub window_resize {} |
|
|
223 | sub window_delete {} |
125 | |
224 | |
126 | sub save { |
225 | sub save { |
127 | warn "save: ".Dumper(\@_); |
226 | $_[0]->{save}{test} = ['t1',5,7]; |
128 | "[save]"; |
227 | Storable::nfreeze $_[0]->{save}; |
129 | } |
228 | } |
130 | |
229 | |
131 | sub DESTROY { |
230 | sub DESTROY { |
132 | warn "DESTROY"; |
231 | warn "DESTROY"; |
133 | } |
232 | } |