1 |
package mouse; # $Id: mouse.pm 267529 2010-04-13 13:48:09Z pzanoni $ |
2 |
|
3 |
#use diagnostics; |
4 |
#use strict; |
5 |
|
6 |
#-###################################################################################### |
7 |
#- misc imports |
8 |
#-###################################################################################### |
9 |
use common; |
10 |
use modules; |
11 |
use detect_devices; |
12 |
use run_program; |
13 |
use devices; |
14 |
use modules; |
15 |
use any; |
16 |
use log; |
17 |
|
18 |
sub _all_mice() { |
19 |
arch() =~ /^sparc/ ? |
20 |
( |
21 |
'sunmouse' => |
22 |
[ [ 'sunmouse' ], |
23 |
[ [ 3, 'sun', 'sun', N_("Sun - Mouse") ] |
24 |
] ] |
25 |
) : |
26 |
( |
27 |
'PS/2' => |
28 |
[ [ 'psaux' ], |
29 |
[ [ 2, 'ps/2', 'PS/2', N_("Standard") ], |
30 |
[ 5, 'ps/2', 'MouseManPlusPS/2', N_("Logitech MouseMan+") ], |
31 |
[ 5, 'imps2', 'IMPS/2', N_("Generic PS2 Wheel Mouse") ], |
32 |
[ 5, 'ps/2', 'GlidePointPS/2', N_("GlidePoint") ], |
33 |
[ 5, 'imps2', 'auto', N_("Automatic") ], |
34 |
'', |
35 |
[ 5, 'ps/2', 'ThinkingMousePS/2', N_("Kensington Thinking Mouse") ], |
36 |
[ 5, 'netmouse', 'NetMousePS/2', N_("Genius NetMouse") ], |
37 |
[ 5, 'netmouse', 'NetScrollPS/2', N_("Genius NetScroll") ], |
38 |
[ 7, 'ps/2', 'ExplorerPS/2', N_("Microsoft Explorer") ], |
39 |
] ], |
40 |
|
41 |
'USB' => |
42 |
[ [ 'input/mice' ], |
43 |
[ [ 1, 'ps/2', 'ExplorerPS/2', N_("1 button") ], |
44 |
[ 2, 'ps/2', 'ExplorerPS/2', N_("Generic 2 Button Mouse") ], |
45 |
[ 3, 'ps/2', 'ExplorerPS/2', N_("Generic") ], |
46 |
[ 3, 'ps/2', 'ExplorerPS/2', N_("Generic 3 Button Mouse with Wheel emulation"), 'wheel' ], |
47 |
[ 5, 'ps/2', 'ExplorerPS/2', N_("Wheel") ], |
48 |
[ 7, 'ps/2', 'ExplorerPS/2', N_("Microsoft Explorer") ], |
49 |
] ], |
50 |
|
51 |
N_("serial") => |
52 |
[ [ map { "ttyS$_" } 0..3 ], |
53 |
[ [ 2, 'Microsoft', 'Microsoft', N_("Generic 2 Button Mouse") ], |
54 |
[ 3, 'Microsoft', 'Microsoft', N_("Generic 3 Button Mouse") ], |
55 |
[ 3, 'Microsoft', 'Microsoft', N_("Generic 3 Button Mouse with Wheel emulation"), 'wheel' ], |
56 |
[ 5, 'ms3', 'IntelliMouse', N_("Microsoft IntelliMouse") ], |
57 |
[ 3, 'MouseMan', 'MouseMan', N_("Logitech MouseMan") ], |
58 |
[ 3, 'MouseMan', 'MouseMan', N_("Logitech MouseMan with Wheel emulation"), 'wheel' ], |
59 |
[ 2, 'MouseSystems', 'MouseSystems', N_("Mouse Systems") ], |
60 |
'', |
61 |
[ 3, 'logim', 'MouseMan', N_("Logitech CC Series") ], |
62 |
[ 3, 'logim', 'MouseMan', N_("Logitech CC Series with Wheel emulation"), 'wheel' ], |
63 |
[ 5, 'pnp', 'IntelliMouse', N_("Logitech MouseMan+/FirstMouse+") ], |
64 |
[ 5, 'ms3', 'IntelliMouse', N_("Genius NetMouse") ], |
65 |
[ 2, 'MMSeries', 'MMSeries', N_("MM Series") ], |
66 |
[ 2, 'MMHitTab', 'MMHittab', N_("MM HitTablet") ], |
67 |
[ 3, 'Logitech', 'Logitech', N_("Logitech Mouse (serial, old C7 type)") ], |
68 |
[ 3, 'Logitech', 'Logitech', N_("Logitech Mouse (serial, old C7 type) with Wheel emulation"), 'wheel' ], |
69 |
[ 3, 'Microsoft', 'ThinkingMouse', N_("Kensington Thinking Mouse") ], |
70 |
[ 3, 'Microsoft', 'ThinkingMouse', N_("Kensington Thinking Mouse with Wheel emulation"), 'wheel' ], |
71 |
] ], |
72 |
|
73 |
N_("busmouse") => |
74 |
[ [ arch() eq 'ppc' ? 'adbmouse' : ('atibm', 'inportbm', 'logibm') ], |
75 |
[ if_(arch() eq 'ppc', [ 1, 'Busmouse', 'BusMouse', N_("1 button") ]), |
76 |
[ 2, 'Busmouse', 'BusMouse', N_("2 buttons") ], |
77 |
[ 3, 'Busmouse', 'BusMouse', N_("3 buttons") ], |
78 |
[ 3, 'Busmouse', 'BusMouse', N_("3 buttons with Wheel emulation"), 'wheel' ], |
79 |
] ], |
80 |
|
81 |
N_("Universal") => |
82 |
[ [ 'input/mice' ], |
83 |
[ [ 7, 'ps/2', 'ExplorerPS/2', N_("Any PS/2 & USB mice") ], |
84 |
[ 7, 'ps/2', 'ExplorerPS/2', N_("Force evdev") ], #- evdev is magically handled in mouse::select() |
85 |
if_(detect_devices::is_xbox(), [ 5, 'ps/2', 'IMPS/2', N_("Microsoft Xbox Controller S") ]), |
86 |
if_(detect_devices::is_virtualbox(), [ 7, 'ps/2', 'vboxmouse', N_("VirtualBox mouse") ]), |
87 |
if_(detect_devices::is_vmware(), [ 7, 'ps/2', 'vmmouse', N_("VMware mouse") ]), |
88 |
] ], |
89 |
|
90 |
N_("none") => |
91 |
[ [ 'none' ], |
92 |
[ [ 0, 'none', 'Microsoft', N_("No mouse") ], |
93 |
] ], |
94 |
); |
95 |
} |
96 |
|
97 |
#- Logitech MX700 |
98 |
#- |
99 |
#- I: Bus=0003 Vendor=046d Product=c506 Version=1600 |
100 |
#- N: Name="Logitech USB Receiver" |
101 |
#- P: Phys=usb-0000:00:11.3-2/input0 |
102 |
#- S: Sysfs=/class/input/input5 |
103 |
#- H: Handlers=mouse2 ts2 event3 |
104 |
#- B: EV=7 |
105 |
#- B: KEY=ffff0000 0 0 0 0 0 0 0 0 |
106 |
#- B: REL=103 |
107 |
#- |
108 |
#- T: Bus=05 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 4 Spd=1.5 MxCh= 0 |
109 |
#- D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 |
110 |
#- P: Vendor=046d ProdID=c506 Rev=16.00 |
111 |
#- S: Manufacturer=Logitech |
112 |
#- S: Product=USB Receiver |
113 |
#- C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 50mA |
114 |
#- I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid |
115 |
#- E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=10ms |
116 |
|
117 |
|
118 |
my %mouse_btn_keymap = ( |
119 |
0 => "NONE", |
120 |
67 => "F9", |
121 |
68 => "F10", |
122 |
87 => "F11", |
123 |
88 => "F12", |
124 |
85 => "F13", |
125 |
89 => "F14", |
126 |
90 => "F15", |
127 |
56 => "L-Option/Alt", |
128 |
125 => "L-Command (Apple)", |
129 |
98 => "Num: /", |
130 |
55 => "Num: *", |
131 |
117 => "Num: =", |
132 |
96 => "Enter", |
133 |
); |
134 |
sub _ppc_one_button_keys() { keys %mouse_btn_keymap } |
135 |
sub _ppc_one_button_key2text { $mouse_btn_keymap{$_[0]} } |
136 |
|
137 |
my @mouses_fields = qw(nbuttons MOUSETYPE Protocol name EmulateWheel); |
138 |
|
139 |
sub _raw2mouse { |
140 |
my ($type, $raw) = @_; |
141 |
$raw or return; |
142 |
|
143 |
my %l; @l{@mouses_fields} = @$raw; |
144 |
+{ %l, type => $type, if_($l{nbuttons} < 3, Emulate3Buttons => 1) }; |
145 |
} |
146 |
|
147 |
sub fullname2mouse { |
148 |
my ($fname, %opts) = @_; |
149 |
my ($type, @l) = split '\|', $fname; |
150 |
my $name = pop @l; #- ensure we get rid of "[Other]" |
151 |
my %mice = _all_mice(); |
152 |
|
153 |
if (my @devices = @{$mice{$type}[0]}) { |
154 |
member($opts{device}, @devices) or delete $opts{device}; |
155 |
$opts{device} ||= $devices[0]; |
156 |
} |
157 |
foreach (@{$mice{$type}[1]}) { |
158 |
my $l = _raw2mouse($type, $_); |
159 |
$name eq $l->{name} and return { %$l, %opts }; |
160 |
} |
161 |
die "$fname not found ($type, $name)"; |
162 |
} |
163 |
|
164 |
sub read() { |
165 |
my %mouse = getVarsFromSh "$::prefix/etc/sysconfig/mouse"; |
166 |
eval { fullname2mouse($mouse{FULLNAME}, device => $mouse{device}) } || \%mouse; |
167 |
} |
168 |
|
169 |
sub write { |
170 |
my ($do_pkgs, $mouse) = @_; |
171 |
|
172 |
setVarsInSh("$::prefix/etc/sysconfig/mouse", { |
173 |
device => $mouse->{device}, |
174 |
MOUSETYPE => $mouse->{MOUSETYPE}, |
175 |
FULLNAME => qq($mouse->{type}|$mouse->{name}), |
176 |
}); |
177 |
|
178 |
various_xfree_conf($do_pkgs, $mouse); |
179 |
|
180 |
if (arch() =~ /ppc/) { |
181 |
my $s = join('', |
182 |
"dev.mac_hid.mouse_button_emulation = " . to_bool($mouse->{button2_key} || $mouse->{button3_key}) . "\n", |
183 |
if_($mouse->{button2_key}, "dev.mac_hid.mouse_button2_keycode = $mouse->{button2_key}\n"), |
184 |
if_($mouse->{button3_key}, "dev.mac_hid.mouse_button3_keycode = $mouse->{button3_key}\n"), |
185 |
); |
186 |
substInFile { |
187 |
$_ = '' if /^\Qdev.mac_hid.mouse_button/; |
188 |
$_ .= $s if eof; |
189 |
} "$::prefix/etc/sysctl.conf"; |
190 |
} |
191 |
} |
192 |
|
193 |
sub _input_entry_to_device_by_id { |
194 |
my ($input) = @_; |
195 |
|
196 |
my $ID_SERIAL = chomp_(run_program::get_stdout('usb_id', $input->{sysfs_path})); |
197 |
$ID_SERIAL =~ s/[^\w#+\-.:=@_]/_/g; #- udev do a further cleanup, eg: "Wacom_Co.,Ltd._MTE-450" => "Wacom_Co._Ltd._MTE-450". cf ALLOWED_CHARS udev.h |
198 |
my $sysfs_device = "input/by-id/usb-$ID_SERIAL-event-mouse"; #- from /etc/udev/rules.d/60-persistent-input.rules |
199 |
if ($::isInstall || -e "/dev/$sysfs_device") { |
200 |
$sysfs_device; |
201 |
} else { |
202 |
log::l("$sysfs_device missing"); |
203 |
(); |
204 |
} |
205 |
} |
206 |
|
207 |
sub _probe_usb_wacom_devices() { |
208 |
detect_devices::hasWacom() or return; |
209 |
|
210 |
eval { modules::load("wacom", "evdev") }; |
211 |
|
212 |
map { _input_entry_to_device_by_id($_) } detect_devices::usbWacom(); |
213 |
} |
214 |
|
215 |
sub _detect_serial() { |
216 |
my ($t, $mouse, @wacom); |
217 |
|
218 |
#- Whouah! probing all devices from ttyS0 to ttyS3 once a time! |
219 |
detect_devices::probeSerialDevices(); |
220 |
|
221 |
#- check new probing methods keep everything used here intact! |
222 |
foreach (0..3) { |
223 |
$t = detect_devices::probeSerial("/dev/ttyS$_") or next; |
224 |
if ($t->{CLASS} eq 'MOUSE') { |
225 |
$t->{MFG} ||= $t->{MANUFACTURER}; |
226 |
|
227 |
my $name = 'Generic 2 Button Mouse'; |
228 |
$name = 'Microsoft IntelliMouse' if $t->{MFG} eq 'MSH' && $t->{MODEL} eq '0001'; |
229 |
$name = 'Logitech MouseMan' if $t->{MFG} eq 'LGI' && $t->{MODEL} =~ /^80/; |
230 |
$name = 'Genius NetMouse' if $t->{MFG} eq 'KYE' && $t->{MODEL} eq '0003'; |
231 |
|
232 |
$mouse ||= fullname2mouse("serial|$name", device => "ttyS$_"); |
233 |
last; |
234 |
} elsif ($t->{CLASS} eq "PEN" || $t->{MANUFACTURER} eq "WAC") { |
235 |
push @wacom, "ttyS$_"; |
236 |
} |
237 |
} |
238 |
$mouse, @wacom; |
239 |
} |
240 |
|
241 |
sub _mice2evdev { |
242 |
my (@mice) = @_; |
243 |
|
244 |
[ map { |
245 |
#- we always use HWheelRelativeAxisButtons for evdev, it tells mice with no horizontal wheel to skip those buttons |
246 |
#- that way we ensure 6 & 7 is always horizontal wheel |
247 |
#- (cf patch skip-HWheelRelativeAxisButtons-even-if-unused in x11-driver-input-evdev) |
248 |
{ device => "/dev/$_", HWheelRelativeAxisButtons => "7 6" }; |
249 |
} map { _input_entry_to_device_by_id($_) } @mice ]; |
250 |
} |
251 |
|
252 |
sub _detect_evdev_mice { |
253 |
my (@mice) = @_; |
254 |
|
255 |
foreach (@mice) { |
256 |
my @l = $_->{usb} && $_->{usb}{driver} =~ /^Mouse:(.*)/ ? split('\|', $1) : (); |
257 |
foreach my $opt (@l) { |
258 |
if ($opt eq 'evdev') { |
259 |
$_->{want_evdev} = 1; |
260 |
} |
261 |
} |
262 |
if ($_->{HWHEEL}) { |
263 |
$_->{want_evdev} = 1; |
264 |
} |
265 |
} |
266 |
|
267 |
my @evdev_mice = grep { $_->{want_evdev} } @mice; |
268 |
|
269 |
log::l("configuring mice for evdev (" . join(' ', map { "$_->{vendor}:$_->{product}" } @evdev_mice) . ")") if @evdev_mice; |
270 |
|
271 |
{ evdev_mice_all => _mice2evdev(@mice), |
272 |
if_(@evdev_mice, evdev_mice => _mice2evdev(@evdev_mice)) }; |
273 |
} |
274 |
|
275 |
sub detect { |
276 |
my ($modules_conf) = @_; |
277 |
|
278 |
# let more USB tablets and touchscreens magically work at install time |
279 |
# through /dev/input/mice multiplexing: |
280 |
detect_devices::probe_category('input/tablet'); |
281 |
detect_devices::probe_category('input/touchscreen'); |
282 |
|
283 |
my @wacom = _probe_usb_wacom_devices(); |
284 |
|
285 |
$modules_conf->get_probeall("usb-interface") and eval { modules::load('usbhid') }; |
286 |
if (detect_devices::is_virtualbox()) { |
287 |
fullname2mouse("Universal|VirtualBox mouse"); |
288 |
} elsif (detect_devices::is_vmware()) { |
289 |
fullname2mouse("Universal|VMware mouse"); |
290 |
} elsif (my @mice = grep { $_->{Handlers}{mouse} } detect_devices::getInputDevices_and_usb()) { |
291 |
my @synaptics = map { |
292 |
{ ALPS => $_->{ALPS} }; |
293 |
} grep { $_->{Synaptics} || $_->{ALPS} } @mice; |
294 |
|
295 |
my $evdev_opts = _detect_evdev_mice(@mice); |
296 |
|
297 |
my $fullname = detect_devices::is_xbox() ? |
298 |
'Universal|Microsoft Xbox Controller S' : |
299 |
arch() eq "ppc" ? |
300 |
'USB|1 button' : |
301 |
'Universal|Any PS/2 & USB mice'; |
302 |
|
303 |
fullname2mouse($fullname, wacom => \@wacom, |
304 |
synaptics => $synaptics[0], |
305 |
if_($evdev_opts, %$evdev_opts)); |
306 |
} elsif (arch() eq 'ppc') { |
307 |
# No need to search for an ADB mouse. If I did, the PPC kernel would |
308 |
# find one whether or not I had one installed! So.. default to it. |
309 |
fullname2mouse("busmouse|1 button"); |
310 |
} elsif (arch() =~ /^sparc/) { |
311 |
fullname2mouse("sunmouse|Sun - Mouse"); |
312 |
} else { |
313 |
#- probe serial device to make sure a wacom has been detected. |
314 |
eval { modules::load("serial") }; |
315 |
my ($serial_mouse, @serial_wacom) = _detect_serial(); |
316 |
push @wacom, @serial_wacom; |
317 |
if ($serial_mouse) { |
318 |
{ wacom => \@wacom, %$serial_mouse }; |
319 |
} elsif (@wacom) { |
320 |
#- in case only a wacom has been found, assume an inexistant mouse (necessary). |
321 |
fullname2mouse('none|No mouse', wacom => \@wacom); |
322 |
} else { |
323 |
fullname2mouse('Universal|Any PS/2 & USB mice', unsafe => 1); |
324 |
} |
325 |
} |
326 |
} |
327 |
|
328 |
sub load_modules { |
329 |
my ($mouse) = @_; |
330 |
my @l; |
331 |
push @l, qw(hid mousedev usbmouse) if $mouse->{type} =~ /USB/; |
332 |
push @l, qw(serial) if $mouse->{type} =~ /serial/ || any { /ttyS/ } @{$mouse->{wacom}}; |
333 |
push @l, qw(wacom evdev) if any { /event/ } @{$mouse->{wacom}}; |
334 |
push @l, qw(evdev) if $mouse->{synaptics} || $mouse->{evdev_mice}; |
335 |
|
336 |
eval { modules::load(@l) }; |
337 |
} |
338 |
|
339 |
sub set_xfree_conf { |
340 |
my ($mouse, $xfree_conf, $b_keep_auxmouse_unchanged) = @_; |
341 |
|
342 |
my @mice = map { |
343 |
{ |
344 |
(member($_->{Protocol}, qw(vboxmouse vmmouse)) ? "Driver" : "Protocol") => $_->{Protocol}, |
345 |
Device => devices::make($_->{device}), |
346 |
if_($_->{Emulate3Buttons} || $_->{EmulateWheel}, Emulate3Buttons => undef, Emulate3Timeout => 50), |
347 |
if_($_->{EmulateWheel}, EmulateWheel => undef, EmulateWheelButton => 2), |
348 |
}; |
349 |
} $mouse; |
350 |
|
351 |
if ($mouse->{evdev_mice}) { |
352 |
push @mice, @{$mouse->{evdev_mice}}; |
353 |
} elsif (!$mouse->{synaptics} && $b_keep_auxmouse_unchanged) { |
354 |
my (undef, @l) = $xfree_conf->get_mice; |
355 |
push @mice, @l; |
356 |
} |
357 |
|
358 |
$xfree_conf->set_mice(@mice); |
359 |
|
360 |
if (my @wacoms = @{$mouse->{wacom} || []}) { |
361 |
$xfree_conf->set_wacoms(map { { Device => "/dev/$_", USB => to_bool(m|input/by-path/event|) } } @wacoms); |
362 |
} |
363 |
} |
364 |
|
365 |
sub various_xfree_conf { |
366 |
my ($do_pkgs, $mouse) = @_; |
367 |
|
368 |
-e "/usr/bin/X" or return; |
369 |
|
370 |
#- we don't need this anymore. Remove it for upgrades |
371 |
unlink("$::prefix/etc/X11/xinit.d/mouse_buttons"); |
372 |
{ |
373 |
my $f = "$::prefix/etc/X11/xinit.d/xpad"; |
374 |
if ($mouse->{name} !~ /^Microsoft Xbox Controller/) { |
375 |
unlink($f); |
376 |
} else { |
377 |
output_with_perm($f, 0755, "xset m 1/8 1\n"); |
378 |
} |
379 |
} |
380 |
|
381 |
require Xconfig::card; |
382 |
my $inputdrvpath = Xconfig::card::modules_dir() . '/input'; |
383 |
my $pkgs = [ |
384 |
if_($mouse->{synaptics}, ['x11-driver-input-synaptics', "$inputdrvpath/synaptics_drv.so"]), |
385 |
if_($mouse->{evdev_mice}, ['x11-driver-input-evdev', "$inputdrvpath/evdev_drv.so"]), |
386 |
if_($mouse->{Protocol} eq 'vboxmouse', ['x11-driver-input-vboxmouse', "$inputdrvpath/vboxmouse_drv.so"]), |
387 |
if_(@{$mouse->{wacom}}, ['x11-driver-input-wacom', "$inputdrvpath/wacom_drv.so"]), |
388 |
if_($mouse->{name} =~ /VMware/i, ['x11-driver-input-vmmouse', "$inputdrvpath/vmmouse_drv.so"]), |
389 |
]; |
390 |
$do_pkgs->ensure_files_are_installed($pkgs, 1); |
391 |
|
392 |
} |
393 |
|
394 |
#- write_conf : write the mouse infos into the Xconfig files. |
395 |
#- input : |
396 |
#- $mouse : the hashtable containing the informations |
397 |
#- $mouse input |
398 |
#- $mouse->{nbuttons} : number of buttons : integer |
399 |
#- $mouse->{device} : device of the mouse : string : ex 'psaux' |
400 |
#- $mouse->{Protocol} : type of the mouse for X : string (eg 'PS/2') |
401 |
#- $mouse->{type} : type (generic ?) of the mouse : string : ex 'PS/2' |
402 |
#- $mouse->{name} : name of the mouse : string : ex 'Standard' |
403 |
#- $mouse->{MOUSETYPE} : type of the mouse : string : ex "ps/2" |
404 |
sub write_conf { |
405 |
my ($do_pkgs, $modules_conf, $mouse, $b_keep_auxmouse_unchanged) = @_; |
406 |
|
407 |
&write($do_pkgs, $mouse); |
408 |
$modules_conf->write if $mouse->{device} eq "input/mice" && !$::testing; |
409 |
|
410 |
eval { |
411 |
require Xconfig::xfree; |
412 |
my $xfree_conf = Xconfig::xfree->read; |
413 |
set_xfree_conf($mouse, $xfree_conf, $b_keep_auxmouse_unchanged); |
414 |
$xfree_conf->write; |
415 |
}; |
416 |
} |
417 |
|
418 |
sub _xmouse2xId { |
419 |
#- xmousetypes must be sorted as found in /usr/include/X11/extensions/xf86misc.h |
420 |
#- so that first mean "0", etc |
421 |
my @xmousetypes = ( |
422 |
"Microsoft", |
423 |
"MouseSystems", |
424 |
"MMSeries", |
425 |
"Logitech", |
426 |
"BusMouse", #MouseMan, |
427 |
"Logitech", |
428 |
"PS/2", |
429 |
"MMHittab", |
430 |
"GlidePoint", |
431 |
"IntelliMouse", |
432 |
"ThinkingMouse", |
433 |
"IMPS/2", |
434 |
"ThinkingMousePS/2", |
435 |
"MouseManPlusPS/2", |
436 |
"GlidePointPS/2", |
437 |
"NetMousePS/2", |
438 |
"NetScrollPS/2", |
439 |
"SysMouse", |
440 |
"Auto", |
441 |
"AceCad", |
442 |
"ExplorerPS/2", |
443 |
"USB", |
444 |
); |
445 |
my ($id) = @_; |
446 |
$id = 'BusMouse' if $id eq 'MouseMan'; |
447 |
$id = 'IMPS/2' if $id eq 'ExplorerPS/2' && $::isInstall; |
448 |
eval { find_index { $_ eq $id } @xmousetypes } || 0; |
449 |
} |
450 |
|
451 |
sub change_mouse_live { |
452 |
my ($mouse, $old) = @_; |
453 |
|
454 |
my $xId = _xmouse2xId($mouse->{Protocol}); |
455 |
$old->{device} ne $mouse->{device} || $xId != _xmouse2xId($old->{Protocol}) or return; |
456 |
|
457 |
log::l("telling X server to use another mouse ($mouse->{Protocol}, $xId)"); |
458 |
eval { modules::load('serial') } if $mouse->{device} =~ /ttyS/; |
459 |
|
460 |
if (!$::testing) { |
461 |
devices::make($mouse->{device}); |
462 |
symlinkf($mouse->{device}, "/dev/mouse"); |
463 |
eval { |
464 |
require xf86misc::main; |
465 |
xf86misc::main::setMouseLive($ENV{DISPLAY}, $xId, $mouse->{Emulate3Buttons}); |
466 |
}; |
467 |
} |
468 |
1; |
469 |
} |
470 |
|
471 |
sub test_mouse_install { |
472 |
my ($mouse, $x_protocol_changed) = @_; |
473 |
require ugtk2; |
474 |
ugtk2->import(qw(:wrappers :create)); |
475 |
my $w = ugtk2->new(N("Testing the mouse"), disallow_big_help => 1); |
476 |
my $darea = Gtk2::DrawingArea->new; |
477 |
$darea->set_events([ 'button_press_mask', 'button_release_mask' ]); #$darea must be unrealized. |
478 |
gtkadd($w->{window}, |
479 |
gtkpack(my $vbox_grab = Gtk2::VBox->new(0, 0), |
480 |
$darea, |
481 |
gtkset_sensitive(create_okcancel($w, undef, '', 'edge'), 1) |
482 |
), |
483 |
); |
484 |
test_mouse($mouse, $darea, $x_protocol_changed); |
485 |
$w->sync; # HACK |
486 |
Gtk2::Gdk->pointer_grab($vbox_grab->window, 1, 'pointer_motion_mask', $vbox_grab->window, undef, 0); |
487 |
my $r = $w->main; |
488 |
Gtk2::Gdk->pointer_ungrab(0); |
489 |
$r; |
490 |
} |
491 |
|
492 |
sub _fullnames() { |
493 |
map_each { |
494 |
my $type = $::a; |
495 |
grep { $_ } map { |
496 |
if ($_) { |
497 |
my $l = _raw2mouse($type, $_); |
498 |
"$type|$l->{name}"; |
499 |
} else { |
500 |
$type .= "|[" . N("Other") . "]"; |
501 |
''; |
502 |
} |
503 |
} @{$::b->[1]}; |
504 |
} _all_mice(); |
505 |
} |
506 |
|
507 |
sub select { |
508 |
my ($in, $mouse) = @_; |
509 |
|
510 |
my $prev = my $fullname = $mouse->{type} . '|' . $mouse->{name}; |
511 |
|
512 |
$in->ask_from_({ messages => N("Please choose your type of mouse."), |
513 |
title => N("Mouse choice"), |
514 |
interactive_help_id => 'selectMouse', |
515 |
if_($mouse->{unsafe}, cancel => ''), |
516 |
}, |
517 |
[ { list => [ _fullnames() ], separator => '|', val => \$fullname, |
518 |
format => sub { join('|', map { translate($_) } split('\|', $_[0])) } } ]) or return; |
519 |
|
520 |
if ($fullname ne $prev) { |
521 |
my $mouse_ = fullname2mouse($fullname, device => $mouse->{device}); |
522 |
if ($fullname =~ /evdev/) { |
523 |
$mouse_->{evdev_mice} = $mouse_->{evdev_mice_all} = $mouse->{evdev_mice_all}; |
524 |
} |
525 |
%$mouse = %$mouse_; |
526 |
} |
527 |
|
528 |
if ($mouse->{nbuttons} < 3 && $::isStandalone) { |
529 |
$mouse->{Emulate3Buttons} = $in->ask_yesorno('', N("Emulate third button?"), 1); |
530 |
} |
531 |
|
532 |
if ($mouse->{type} eq 'serial') { |
533 |
$in->ask_from_({ title => N("Mouse Port"), |
534 |
messages => N("Please choose which serial port your mouse is connected to."), |
535 |
interactive_help_id => 'selectSerialPort', |
536 |
}, [ { list => [ detect_devices::serialPorts() ], format => \&detect_devices::serialPort2text, val => \$mouse->{device} } ]) or return &select; |
537 |
} |
538 |
|
539 |
if (arch() =~ /ppc/ && $mouse->{nbuttons} == 1) { |
540 |
#- set a sane default F11/F12 |
541 |
$mouse->{button2_key} = 87; |
542 |
$mouse->{button3_key} = 88; |
543 |
$in->ask_from('', N("Buttons emulation"), |
544 |
[ |
545 |
{ label => N("Button 2 Emulation"), val => \$mouse->{button2_key}, list => [ _ppc_one_button_keys() ], format => \&_ppc_one_button_key2text }, |
546 |
{ label => N("Button 3 Emulation"), val => \$mouse->{button3_key}, list => [ _ppc_one_button_keys() ], format => \&_ppc_one_button_key2text }, |
547 |
]) or return; |
548 |
} |
549 |
1; |
550 |
} |
551 |
|
552 |
sub test_mouse { |
553 |
my ($mouse, $darea, $b_x_protocol_changed) = @_; |
554 |
|
555 |
require ugtk2; |
556 |
ugtk2->import(qw(:wrappers)); |
557 |
my $suffix = $mouse->{nbuttons} <= 2 ? '2b' : $mouse->{nbuttons} == 3 ? '3b' : '3b+'; |
558 |
my %offsets = (mouse_2b_right => [ 93, 0 ], mouse_3b_right => [ 117, 0 ], |
559 |
mouse_2b_middle => [ 82, 80 ], mouse_3b_middle => [ 68, 0 ], 'mouse_3b+_middle' => [ 85, 67 ]); |
560 |
my %image_files = ( |
561 |
mouse => "mouse_$suffix", |
562 |
left => 'mouse_' . ($suffix eq '3b+' ? '3b' : $suffix) . '_left', |
563 |
right => 'mouse_' . ($suffix eq '3b+' ? '3b' : $suffix) . '_right', |
564 |
if_($mouse->{nbuttons} > 2, middle => 'mouse_' . $suffix . '_middle'), |
565 |
up => 'arrow_up', |
566 |
down => 'arrow_down'); |
567 |
my %images = map { $_ => ugtk2::gtkcreate_pixbuf("$image_files{$_}.png") } keys %image_files; |
568 |
my $width = $images{mouse}->get_width; |
569 |
my $height = round_up($images{mouse}->get_height, 6); |
570 |
|
571 |
my $draw_text = sub { |
572 |
my ($t, $y) = @_; |
573 |
my $layout = $darea->create_pango_layout($t); |
574 |
my ($w) = $layout->get_pixel_size; |
575 |
$darea->window->draw_layout($darea->style->black_gc, |
576 |
($darea->allocation->width-$w)/2, |
577 |
($darea->allocation->height-$height)/2 + $y, |
578 |
$layout); |
579 |
}; |
580 |
my $draw_pixbuf = sub { |
581 |
my ($p, $x, $y, $w, $h) = @_; |
582 |
$w = $p->get_width; |
583 |
$h = $p->get_height; |
584 |
$p->render_to_drawable($darea->window, $darea->style->bg_gc('normal'), 0, 0, |
585 |
($darea->allocation->width-$width)/2 + $x, ($darea->allocation->height-$height)/2 + $y, |
586 |
$w, $h, 'none', 0, 0); |
587 |
}; |
588 |
my $draw_by_name = sub { |
589 |
my ($name) = @_; |
590 |
my $file = $image_files{$name}; |
591 |
my ($x, $y) = @{$offsets{$file} || [ 0, 0 ]}; |
592 |
$draw_pixbuf->($images{$name}, $x, $y); |
593 |
}; |
594 |
my $drawarea = sub { |
595 |
$draw_by_name->('mouse'); |
596 |
if ($::isInstall || 1) { |
597 |
$draw_text->(N("Please test the mouse"), 200); |
598 |
if ($b_x_protocol_changed && $mouse->{nbuttons} > 3 && $mouse->{device} eq 'psaux' && member($mouse->{Protocol}, 'IMPS/2', 'ExplorerPS/2')) { |
599 |
$draw_text->(N("To activate the mouse,"), 240); |
600 |
$draw_text->(N("MOVE YOUR WHEEL!"), 260); |
601 |
} |
602 |
} |
603 |
}; |
604 |
|
605 |
my $timeout; |
606 |
my $paintButton = sub { |
607 |
my ($nb) = @_; |
608 |
$timeout or $drawarea->(); |
609 |
if ($nb == 0) { |
610 |
$draw_by_name->('left'); |
611 |
} elsif ($nb == 2) { |
612 |
$draw_by_name->('right'); |
613 |
} elsif ($nb == 1) { |
614 |
if ($mouse->{nbuttons} >= 3) { |
615 |
$draw_by_name->('middle'); |
616 |
} else { |
617 |
my ($x, $y) = @{$offsets{mouse_2b_middle}}; |
618 |
$darea->window->draw_arc($darea->style->black_gc, |
619 |
1, ($darea->allocation->width-$width)/2 + $x, ($darea->allocation->height-$height)/2 + $y, 20, 25, |
620 |
0, 360 * 64); |
621 |
} |
622 |
} elsif ($mouse->{nbuttons} > 3) { |
623 |
my ($x, $y) = @{$offsets{$image_files{middle}}}; |
624 |
if ($nb == 3) { |
625 |
$draw_pixbuf->($images{up}, $x+6, $y-10); |
626 |
} elsif ($nb == 4) { |
627 |
$draw_pixbuf->($images{down}, $x+6, $y + $images{middle}->get_height + 2); |
628 |
} |
629 |
$draw_by_name->('middle'); |
630 |
$timeout and Glib::Source->remove($timeout); |
631 |
$timeout = Glib::Timeout->add(100, sub { $drawarea->(); $timeout = 0; 0 }); |
632 |
} |
633 |
}; |
634 |
|
635 |
$darea->signal_connect(button_press_event => sub { $paintButton->($_[1]->button - 1) }); |
636 |
$darea->signal_connect(scroll_event => sub { $paintButton->($_[1]->direction eq 'up' ? 3 : 4) }); |
637 |
$darea->signal_connect(button_release_event => $drawarea); |
638 |
$darea->signal_connect(expose_event => $drawarea); |
639 |
$darea->set_size_request($width, $height); |
640 |
} |
641 |
|
642 |
|
643 |
=begin |
644 |
|
645 |
=head1 NAME |
646 |
|
647 |
mouse - Perl functions to handle mice |
648 |
|
649 |
=head1 SYNOPSYS |
650 |
|
651 |
require modules; |
652 |
require mouse; |
653 |
mouse::detect(modules::any_conf->read); |
654 |
|
655 |
=head1 DESCRIPTION |
656 |
|
657 |
C<mouse> is a perl module used by mousedrake to detect and configure the mouse. |
658 |
|
659 |
=head1 COPYRIGHT |
660 |
|
661 |
Copyright (C) 2000-2006 Mandriva <tvignaud@mandriva.com> |
662 |
|
663 |
This program is free software; you can redistribute it and/or modify |
664 |
it under the terms of the GNU General Public License as published by |
665 |
the Free Software Foundation; either version 2, or (at your option) |
666 |
any later version. |
667 |
|
668 |
This program is distributed in the hope that it will be useful, |
669 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
670 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
671 |
GNU General Public License for more details. |
672 |
|
673 |
You should have received a copy of the GNU General Public License |
674 |
along with this program; if not, write to the Free Software |
675 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
676 |
|
677 |
=cut |