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