From 5fd2d25f56ee44f0a4f93eee0fb161879404241d Mon Sep 17 00:00:00 2001 From: Pascal Rigaux Date: Wed, 25 Apr 2007 12:26:16 +0000 Subject: re-sync after the big svn loss --- lib/Xconfig/card.pm | 310 ++++++++++++------------------ lib/Xconfig/main.pm | 83 ++++---- lib/Xconfig/monitor.pm | 36 +++- lib/Xconfig/parse.pm | 57 +++--- lib/Xconfig/plugins.pm | 232 ++++++++++++++++++++++ lib/Xconfig/proprietary.pm | 70 ++++++- lib/Xconfig/resolution_and_depth.pm | 65 +++++-- lib/Xconfig/various.pm | 226 +++++++++++++++++++--- lib/Xconfig/xfree.pm | 207 ++++++++++++-------- lib/keyboard.pm | 139 ++++++++------ lib/mouse.pm | 371 ++++++++++++++++++++---------------- lib/xf86misc/.cvsignore | 5 - lib/xf86misc/Makefile | 2 +- 13 files changed, 1176 insertions(+), 627 deletions(-) create mode 100644 lib/Xconfig/plugins.pm delete mode 100644 lib/xf86misc/.cvsignore (limited to 'lib') diff --git a/lib/Xconfig/card.pm b/lib/Xconfig/card.pm index 686957d..ea5df29 100644 --- a/lib/Xconfig/card.pm +++ b/lib/Xconfig/card.pm @@ -3,11 +3,17 @@ package Xconfig::card; # $Id$ use diagnostics; use strict; +use lib '/usr/lib/libDrakX'; use detect_devices; +use Xconfig::xfree; use modules; use common; +use interactive; use log; +my $lib = arch() =~ /x86_64/ ? "lib64" : "lib"; + +sub modules_dir() { "/usr/$lib/xorg/modules" } my %VideoRams = ( 256 => N_("256 kB"), @@ -21,12 +27,10 @@ my %VideoRams = ( 65536 => N_("64 MB or more"), ); -my $lib = arch() =~ /x86_64/ ? "lib64" : "lib"; - my @xfree4_Drivers = ((arch() =~ /^sparc/ ? qw(sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx) : - qw(apm ark chips cirrus cyrix glide i128 i740 i810 imstt - mga neomagic newport nv rendition r128 radeon vesa - s3 s3virge savage siliconmotion sis tdfx tga trident tseng vmware)), + qw(amd apm ark ast chips cirrus cyrix glide i128 i740 i810 imstt + mga nsc neomagic newport nv rendition openchrome vesa via + s3 s3virge savage siliconmotion sis sisusb tdfx tga trident tseng vmware)), qw(ati glint vga fbdev)); sub from_raw_X { @@ -36,7 +40,11 @@ sub from_raw_X { my $card = { use_DRI_GLX => eval { any { /dri/ } $raw_X->get_modules }, + DRI_GLX_SPECIAL => first($raw_X->get_ModulePaths), %$device, + if_($device->{Driver} eq 'nvidia', + DriverVersion => + readlink("$::prefix/etc/alternatives/gl_conf") =~ m!nvidia(.*)/! ? $1 : '97xx'), }; add_to_card__using_Cards($card, $card->{BoardName}); $card; @@ -56,6 +64,12 @@ sub to_raw_X { if (arch() =~ /ppc/ && ($_->{Driver} eq 'r128' || $_->{Driver} eq 'radeon')) { $_->{UseFBDev} = 1; } + if ($_->{Driver} eq 'i810') { + $_->{Options}{May_Need_ForceBIOS} = '1'; + } + if (member($_->{Driver}, qw(i810 ati))) { + $_->{Options}{XaaNoOffscreenPixmaps} = '1'; + } } $raw_X->set_devices(@cards); @@ -63,19 +77,21 @@ sub to_raw_X { $raw_X->get_ServerLayout->{Xinerama} = { commented => !$card->{Xinerama}, Option => 1 } if defined $card->{Xinerama}; - # cleanup previous special nvidia libglx - $raw_X->remove_load_module($_) foreach @{$card->{REMOVE_GLX} || []}; + # cleanup deprecated previous special nvidia explicit libglx + $raw_X->remove_load_module(modules_dir() . "$_/libglx.so") foreach '/extensions/nvidia', '/extensions/nvidia_legacy', '/extensions'; + # remove ModulePath that we added + $raw_X->remove_ModulePath(modules_dir() . "/extensions/$_") foreach 'nvidia97xx', 'nvidia96xx', 'nvidia71xx'; + $raw_X->remove_ModulePath(modules_dir()); + # then may re-add some if ($card->{DRI_GLX_SPECIAL}) { - $raw_X->remove_load_module('glx'); # this doesn't duplicate the above glx line - # This loads the NVIDIA GLX extension module. - # IT IS IMPORTANT TO KEEP NAME AS FULL PATH TO libglx.so ELSE - # IT WILL LOAD XFree86 glx module and the server will crash. - $raw_X->add_load_module($card->{DRI_GLX_SPECIAL}); - } else { - $raw_X->set_load_module('glx', $card->{Driver} ne 'fbdev'); #- glx for everyone, except proprietary nvidia and fbdev - $raw_X->set_load_module('dri', $card->{use_DRI_GLX}); + $raw_X->add_ModulePath($card->{DRI_GLX_SPECIAL}); } + #- if we have some special ModulePath, ensure the last one is the standard ModulePath + $raw_X->add_ModulePath(modules_dir()) if $raw_X->get_ModulePaths; + + $raw_X->set_load_module('glx', $card->{Driver} ne 'fbdev'); #- glx for everyone, except fbdev + $raw_X->set_load_module('dri', $card->{use_DRI_GLX}); #- dri when needed, except proprietary nvidia $raw_X->remove_Section('DRI'); @@ -96,14 +112,18 @@ sub probe() { VendorName => $l[0], BoardName => $l[1], BusID => "PCI:$_->{pci_bus}:$_->{pci_device}:$_->{pci_function}", }; - if ($_->{driver} =~ /Card:(.*)/) { $card->{BoardName} = $1; add_to_card__using_Cards($card, $1) } - elsif ($_->{driver} =~ /Driver:(.*)/) { $card->{Driver} = $1 } - else { internal_error() } - + if (my ($card_name) = $_->{driver} =~ /Card:(.*)/) { + $card->{BoardName} = $card_name; + add_to_card__using_Cards($card, $card_name); + } elsif ($_->{driver} =~ /Driver:(.*)/) { + $card->{Driver} = $1; + } else { + internal_error(); + } $card; } @c; - if (@cards >= 2 && $cards[0]{card_name} eq $cards[1]{card_name} && $cards[0]{card_name} eq 'Intel 830') { + if (@cards >= 2 && $cards[0]{card_name} eq $cards[1]{card_name} && $cards[0]{card_name} eq 'Intel 830 - 965') { shift @cards; } #- take a default on sparc if nothing has been found. @@ -178,20 +198,19 @@ sub card_config__not_listed { add_to_card__using_Cards($card, $s); } else { $card->{Driver} = $s; + $card->{DRI_GLX} = 0; } $card->{manually_chosen} = 1; 1; } sub multi_head_choose { - my ($in, $auto, @cards) = @_; + my ($in, $_auto, @cards) = @_; my @choices = multi_head_choices('', @cards); my $tc = $choices[0]; - if ($auto) { - @choices == 1 or return; - } else { + if (@choices > 1) { $tc = $in->ask_from_listf(N("Multi-head configuration"), N("Your system supports multiple head configuration. What do you want to do?"), sub { $_[0]{text} }, \@choices) or return; @@ -223,12 +242,12 @@ sub configure_auto_install { }; } - my ($glx_choice) = xfree_and_glx_choices($card); - log::explanations("Using $glx_choice->{text}"); - $glx_choice->{code}(); + install_server($card, $options, $do_pkgs) or return; + $card = choose_Driver2_or_not($card, undef); + + Xconfig::various::various_auto_install($raw_X, $card, $old_X); set_glx_restrictions($card); - install_server($card, $options, $do_pkgs); if ($card->{needVideoRam} && !$card->{VideoRam}) { $card->{VideoRam} = $options->{VideoRam_probed} || 4096; log::explanations("argh, I need to know VideoRam! Taking " . ($options->{probed_VideoRam} ? "the probed" : "a default") . " value: VideoRam = $card->{VideoRam}"); @@ -246,38 +265,30 @@ sub configure { if (!$cards[0]{Driver}) { if ($options->{allowFB}) { $cards[0]{Driver} = 'fbdev'; - } elsif ($auto) { - log::explanations("Xconfig::card: auto failed (unknown card and no allowFB)"); - return 0; } } - if (!$auto) { + if (!$auto || !$cards[0]{Driver}) { card_config__not_listed: card_config__not_listed($in, $cards[0], $options) or return; } my $card = multi_head_choose($in, $auto, @cards) or return; - xfree_and_glx_choose($in, $card, $auto) or return; + install_server($card, $options, $do_pkgs) or goto card_config__not_listed; + + $card = choose_Driver2_or_not($card, $in); + + Xconfig::various::various($in, $raw_X, $card, $options, $auto); + set_glx_restrictions($card); - eval { install_server($card, $options, $do_pkgs) }; - if ($@) { - $in->ask_warn('', N("Can not install Xorg package: %s", $@)); - goto card_config__not_listed; - } - if ($card->{needVideoRam} && !$card->{VideoRam}) { - if ($auto) { - log::explanations("Xconfig::card: auto failed (needVideoRam)"); - return; - } $card->{VideoRam} = (find { $_ <= $options->{VideoRam_probed} } reverse ikeys %VideoRams) || 4096; $in->ask_from('', N("Select the memory size of your graphics card"), [ { val => \$card->{VideoRam}, type => 'list', list => [ ikeys %VideoRams ], format => sub { translate($VideoRams{$_[0]}) }, - not_edit => !$::expert } ]) or return; + not_edit => 0 } ]) or return; } to_raw_X($card, $raw_X); @@ -287,97 +298,80 @@ sub configure { sub install_server { my ($card, $options, $do_pkgs) = @_; - my $prog = "$::prefix/usr/X11R6/bin/Xorg"; - my @packages; - push @packages, 'xorg-x11-server' if ! -x $prog; - - #- additional packages to install according available card. - #- add XFree86-libs-DRI here if using DRI (future split of XFree86 TODO) - if ($card->{use_DRI_GLX}) { - push @packages, 'Glide_V5' if $card->{card_name} eq 'Voodoo5 (generic)'; - push @packages, 'Glide_V3-DRI' if member($card->{card_name}, 'Voodoo3 (generic)', 'Voodoo Banshee (generic)'); - push @packages, 'xorg-x11-glide-module' if $card->{card_name} =~ /Voodoo/; - } + my @must_have = "x11-driver-video-$card->{Driver}"; if ($options->{freedriver}) { delete $card->{Driver2}; } - my %nvidia_packages = ( - #- using NVIDIA Legacy driver for old NVIDIA cards (TNT, TNT2, Vanta, Quadro, Quadro2, GeForce and GeForce2): - legacy => [ qw(nvidia_legacy-kernel nvidia_legacy) ], - #- using current NVIDIA driver for recent NVIDIA cards (Geforce/Quadro 3/4/FX/6x00/NVS): - new => [ qw(nvidia-kernel nvidia) ], - ); - - my %proprietary_Driver2 = ( - nvidia => $nvidia_packages{ $card->{NVIDIA_LEGACY} ? 'legacy' : 'new' }, - fglrx => [ 'ati-kernel', 'ati' ], #- using ATI fglrx driver (Radeon, Fire GL cards only). - ); - if (my $rpms_needed = $proprietary_Driver2{$card->{Driver2}}) { - if (my $proprietary_packages = $do_pkgs->check_kernel_module_packages($rpms_needed->[0], $rpms_needed->[1])) { - push @packages, @$proprietary_packages; - # prevent having both nvidia & nvidia_legacy driver installed due to incompatibility: - if ($card->{Driver2} eq 'nvidia') { - $do_pkgs->remove($_) foreach @{$do_pkgs->check_kernel_module_packages(@{$nvidia_packages{ $card->{NVIDIA_LEGACY} ? 'new' : 'legacy' }})}; - } - } - } - - $do_pkgs->install(@packages) if @packages; - -x $prog or die "server not available (should be in $prog)"; - - my $modules_dir = "/usr/X11R6/$lib/modules"; - my $new_nvidia_libglx = "$modules_dir/extensions/nvidia/libglx.so"; - my $old_nvidia_libglx = "$modules_dir/extensions/libglx.so"; - #- make sure everything is correct at this point, packages have really been installed - #- and driver and GLX extension is present. - if ($card->{Driver2} eq 'nvidia' && - (-e "$::prefix$modules_dir/drivers/nvidia_drv.o" || -e "$::prefix$modules_dir/drivers/nvidia_drv.so")) { - #- when there is extensions/libglx.a, it means extensions/libglx.so is not xorg's libglx, so it may be nvidia's - #- new nvidia packages have libglx.so in extensions/nvidia instead of simply extensions/ - my $libglx_a = -e "$::prefix$modules_dir/extensions/libglx.a"; - my $libglx = find { -l "$::prefix$_" } $new_nvidia_libglx, if_($libglx_a, $old_nvidia_libglx); - if ($libglx) { - log::explanations("Using specific NVIDIA driver and GLX extensions"); - $card->{Driver} = 'nvidia'; - $card->{DRI_GLX_SPECIAL} = $libglx; - } - } - if ($card->{Driver2} eq 'fglrx' && - -e "$::prefix$modules_dir/dri/fglrx_dri.so" && - (-e "$::prefix$modules_dir/drivers/fglrx_drv.o" || -e "$::prefix$modules_dir/drivers/fglrx_drv.so")) { - log::explanations("Using specific ATI fglrx and DRI drivers"); - $card->{Driver} = 'fglrx'; + if ($card->{Driver2}) { + require Xconfig::proprietary; + push @packages, Xconfig::proprietary::pkgs_for_Driver2($card, $do_pkgs); } - $card->{REMOVE_GLX} = [ $old_nvidia_libglx, $new_nvidia_libglx ]; - libgl_config($card); + $do_pkgs->ensure_are_installed([ @must_have, @packages ], 1) or + @must_have == listlength($do_pkgs->are_installed(@must_have)) + or return; if ($card->{need_MATROX_HAL}) { require Xconfig::proprietary; Xconfig::proprietary::install_matrox_hal($::prefix); } + 1; } -sub xfree_and_glx_choose { - my ($in, $card, $auto) = @_; - - my @choices = xfree_and_glx_choices($card); - - my $tc = - $auto ? $choices[0] : - $in->ask_from_listf_raw({ title => N("Xorg configuration"), - messages => formatAlaTeX(join("\n\n\n", (grep { $_ } map { $_->{more_messages} } @choices), - N("Which configuration of Xorg do you want to have?"))), - interactive_help_id => 'configureX_xfree_and_glx', - }, - sub { $_[0]{text} }, \@choices) or return; - log::explanations("Using $tc->{text}"); - $tc->{code}(); - set_glx_restrictions($card); - 1; +sub choose_Driver2_or_not { + my ($card, $o_in) = @_; + + my $card2; + if ($card->{Driver2}) { + require Xconfig::proprietary; + $card2 = Xconfig::proprietary::may_use_Driver2($card); + } + + if ($card2) { + !$o_in || $o_in->ask_yesorno('', formatAlaTeX(N("There is a proprietary driver available for your video card which may support additional features. +Do you wish to use it?")), 1) and $card = $card2; + } + + libgl_config_and_more($card); + $card; +} + +#- configures which libGL.so.1 to use, using update-alternatives +#- it also configures nvidia_drv.so (using a slave alternative, cf "update-alternatives --display gl_conf") +sub libgl_config_and_more { + my ($card) = @_; + + if ($card->{Driver} eq 'nvidia') { + $card->{DriverVersion} or internal_error("DriverVersion should be set for driver nvidia!"); + } + + #- ensure old deprecated conf files are not there anymore + unlink("/etc/ld.so.conf.d/$_.conf") foreach 'nvidia', 'nvidia_legacy', 'ati'; + + my $wanted = $card->{Driver} eq 'fglrx' ? "/etc/ld.so.conf.d/GL/ati.conf" : + $card->{Driver} eq 'nvidia' ? "/etc/nvidia$card->{DriverVersion}/ld.so.conf" : + '/etc/ld.so.conf.d/GL/' . (arch() =~ /64/ ? 'lib64' : 'lib') . 'mesagl1.conf'; + my $link = "$::prefix/etc/alternatives/gl_conf"; + if (readlink($link) ne $wanted) { + -e "$::prefix$wanted" or log::l("ERROR: $wanted does not exist, linking $link to it anyway"); + common::symlinkf_update_alternatives('gl_conf', $wanted); + if ($::isStandalone) { + log::explanations("ldconfig will be run because the GL library was " . ($wanted ? 'enabled' : 'disabled')); + system("/sbin/ldconfig"); + } + } + if ($card->{Driver} eq 'fglrx') { + log::l("workaround buggy fglrx driver: make dm restart xserver (#29550)"); + eval { common::update_gnomekderc_no_create("$::prefix/etc/kde/kdm/kdmrc", 'X-:0-Core' => ( + TerminateServer => "true", + )) }; + eval { update_gnomekderc("$::prefix/etc/X11/gdm/custom.conf", daemon => ( + AlwaysRestartServer => "true", + )) }; + } } sub multi_head_choices { @@ -415,36 +409,6 @@ sub multi_head_choices { @choices; } -#- Xorg version available, it would be better to parse available package and get version from it. -sub xorg_version() { '6.9' } - -sub xfree_and_glx_choices { - my ($card) = @_; - - my @choices = if_($card->{Driver}, { text => N("Xorg %s", xorg_version()), code => sub {} }); - - #- no GLX with Xinerama - return @choices if $card->{Xinerama}; - - #- ask the expert or any user on second pass user to enable or not hardware acceleration support. - if ($card->{DRI_GLX}) { - unshift @choices, { text => N("Xorg %s with 3D hardware acceleration", xorg_version()), - code => sub { $card->{use_DRI_GLX} = 1 }, - more_messages => N("Your card can have 3D hardware acceleration support with Xorg %s.", xorg_version()), - }; - } - - #- an expert user may want to try to use an EXPERIMENTAL 3D acceleration. - if ($card->{DRI_GLX_EXPERIMENTAL} && $::expert) { - push @choices, { text => N("Xorg %s with EXPERIMENTAL 3D hardware acceleration", xorg_version()), - code => sub { $card->{use_DRI_GLX} = 1 }, - more_messages => N("Your card can have 3D hardware acceleration support with Xorg %s, -NOTE THIS IS EXPERIMENTAL SUPPORT AND MAY FREEZE YOUR COMPUTER.", xorg_version()), - }; - } - @choices; -} - sub set_glx_restrictions { my ($card) = @_; @@ -453,52 +417,14 @@ sub set_glx_restrictions { if ($card->{use_DRI_GLX}) { $card->{needVideoRam} = 1 if $card->{description} =~ /Matrox.* G[245][05]0/; ($card->{needVideoRam}, $card->{VideoRam}) = (1, 16384) - if member($card->{card_name}, 'Intel 810', 'Intel 815'); + if $card->{card_name} eq 'Intel 810 / 815'; #- hack for ATI Rage 128 card using a bttv or peripheral with PCI bus mastering exchange #- AND using DRI at the same time. - if (member($card->{card_name}, 'ATI Rage 128', 'ATI Rage 128 TVout', 'ATI Rage 128 Mobility')) { - $card->{Options}{UseCCEFor2D} = bool2text(modules::probe_category('multimedia/tv')); + if ($card->{card_name} eq 'ATI Rage 128 TV-out') { + $card->{Options}{UseCCEFor2D} = bool2text(detect_devices::probe_category('multimedia/tv')); } } - - #- check for Matrox G200 PCI cards, disable AGP in such cases, causes black screen else. - if (member($card->{card_name}, 'Matrox Millennium 200', 'Matrox Millennium 200', 'Matrox Mystique') && $card->{description} !~ /AGP/) { - log::explanations("disabling AGP mode for Matrox card, as it seems to be a PCI card"); - log::explanations("this is only used for XFree 3.3.6, see /etc/X11/glx.conf"); - substInFile { s/^\s*#*\s*mga_dma\s*=\s*\d+\s*$/mga_dma = 0\n/ } "$::prefix/etc/X11/glx.conf"; - } -} - -sub libgl_config { - my ($card) = @_; - - my $dir = "$::prefix/etc/ld.so.conf.d"; - my $comment = '# commented-by-DrakX '; - - my %driver_to_libgl_config = ( - nvidia => $card->{NVIDIA_LEGACY} ? 'nvidia_legacy.conf' : 'nvidia.conf', - nvidia_other => !$card->{NVIDIA_LEGACY} ? 'nvidia_legacy.conf' : 'nvidia.conf', - fglrx => 'ati.conf', - ); - my $need_to_run_ldconfig; - my $wanted = $driver_to_libgl_config{$card->{Driver}}; - foreach my $file (values %driver_to_libgl_config) { - substInFile { - my ($commented, $s) = /^(\Q$comment\E)?(.*)/; - if ($file eq $wanted) { - $_ = "$s\n"; - $need_to_run_ldconfig ||= $commented; - } else { - $_ = "$comment$s\n"; - $need_to_run_ldconfig ||= !$commented; - } - } "$dir/$file" if -e "$dir/$file"; - } - if ($::isStandalone && $need_to_run_ldconfig) { - log::explanations("ldconfig will be run because the GL library was " . ($wanted ? 'enabled' : 'disabled')); - system("/sbin/ldconfig"); - } } sub add_to_card__using_Cards { @@ -550,8 +476,6 @@ sub readCardsDB { BAD_FB_RESTORE => sub { $card->{BAD_FB_RESTORE} = 1 }, FB_TVOUT => sub { $card->{FB_TVOUT} = 1 }, UNSUPPORTED => sub { delete $card->{Driver} }, - NVIDIA_LEGACY => sub { $card->{NVIDIA_LEGACY} = 1 }, - COMMENT => sub {}, }; diff --git a/lib/Xconfig/main.pm b/lib/Xconfig/main.pm index bdb4cbf..37a02c3 100644 --- a/lib/Xconfig/main.pm +++ b/lib/Xconfig/main.pm @@ -5,6 +5,7 @@ use strict; use Xconfig::monitor; use Xconfig::card; +use Xconfig::plugins; use Xconfig::resolution_and_depth; use Xconfig::various; use Xconfig::screen; @@ -34,7 +35,11 @@ sub configure_resolution { card => Xconfig::card::from_raw_X($raw_X), monitors => [ $raw_X->get_monitors ], }; - $X->{resolution} = Xconfig::resolution_and_depth::configure($in, $raw_X, $X->{card}, $X->{monitors}) or return; + if (my $rc = Xconfig::various::handle_May_Need_ForceBIOS($in, $raw_X)) { + return $rc; + } + + $X->{resolutions} = Xconfig::resolution_and_depth::configure($in, $raw_X, $X->{card}, $X->{monitors}) or return; if ($raw_X->prepare_write ne $before) { &write($raw_X, $X); } else { @@ -50,12 +55,10 @@ sub configure_everything_auto_install { $options->{VideoRam_probed} = $X->{monitors}[0]{VideoRam_probed}; $X->{card} = Xconfig::card::configure_auto_install($raw_X, $do_pkgs, $old_X, $options) or return; Xconfig::screen::configure($raw_X) or return; - $X->{resolution} = Xconfig::resolution_and_depth::configure_auto_install($raw_X, $X->{card}, $X->{monitors}, $old_X); + $X->{resolutions} = Xconfig::resolution_and_depth::configure_auto_install($raw_X, $X->{card}, $X->{monitors}, $old_X); my $action = &write($raw_X, $X); - Xconfig::various::runlevel(exists $old_X->{xdm} && !$old_X->{xdm} ? 3 : 5); - $action; } @@ -69,15 +72,13 @@ sub configure_everything { $ok &&= $X->{card} = Xconfig::card::configure($in, $raw_X, $do_pkgs, $auto, $options); $ok &&= $X->{monitors} = Xconfig::monitor::configure($in, $raw_X, int($raw_X->get_devices), $probed_info, $auto); $ok &&= Xconfig::screen::configure($raw_X); - $ok &&= $X->{resolution} = Xconfig::resolution_and_depth::configure($in, $raw_X, $X->{card}, $X->{monitors}, $auto); + $ok &&= $X->{resolutions} = Xconfig::resolution_and_depth::configure($in, $raw_X, $X->{card}, $X->{monitors}, $auto); $ok &&= Xconfig::test::test($in, $raw_X, $X->{card}, '', 'skip_badcard') if !$auto; if (!$ok) { return if $auto; ($ok) = configure_chooser_raw($in, $raw_X, $do_pkgs, $options, $X, 1); } - $X->{various} ||= Xconfig::various::various($in, $X->{card}, $options, $auto); - may_write($in, $raw_X, $X, $ok); } @@ -89,7 +90,7 @@ sub configure_chooser_raw { my $update_texts = sub { $texts{card} = $X->{card} && $X->{card}{BoardName} || N("Custom"); $texts{monitors} = $X->{monitors} && $X->{monitors}[0]{ModelName} || N("Custom"); - $texts{resolution} = Xconfig::resolution_and_depth::to_string($X->{resolution}); + $texts{resolutions} = Xconfig::resolution_and_depth::to_string($X->{resolutions}[0]); $texts{$_} =~ s/(.{20}).*/$1.../ foreach keys %texts; #- ensure not too long }; @@ -97,7 +98,7 @@ sub configure_chooser_raw { my $may_set; my $prompt_for_resolution = sub { - $may_set->('resolution', Xconfig::resolution_and_depth::configure($in, $raw_X, $X->{card}, $X->{monitors})); + $may_set->('resolutions', Xconfig::resolution_and_depth::configure($in, $raw_X, $X->{card}, $X->{monitors})); }; $may_set = sub { my ($field, $val) = @_; @@ -108,15 +109,13 @@ sub configure_chooser_raw { $update_texts->(); if (member($field, 'card', 'monitors')) { - my ($default_resolution) = Xconfig::resolution_and_depth::choices($raw_X, $X->{resolution}, $X->{card}, $X->{monitors}); - if (find { $default_resolution->{$_} ne $X->{resolution}{$_} } 'X', 'Y', 'Depth') { + my ($default_resolution, @other_resolutions) = Xconfig::resolution_and_depth::choices($raw_X, $X->{resolutions}[0], $X->{card}, $X->{monitors}); + if (Xconfig::resolution_and_depth::to_string($default_resolution) ne + Xconfig::resolution_and_depth::to_string($X->{resolutions}[0])) { $prompt_for_resolution->(); } else { - if ($default_resolution->{bios} && !$X->{resolution}{bios}) { - $may_set->('resolution', $default_resolution); - } Xconfig::screen::configure($raw_X); - $raw_X->set_resolution($X->{resolution}) if $X->{resolution}; + $may_set->('resolutions', Xconfig::resolution_and_depth::set_resolution($raw_X, $default_resolution, @other_resolutions)); } } } @@ -124,6 +123,7 @@ sub configure_chooser_raw { my $ok; $in->ask_from_({ interactive_help_id => 'configureX_chooser', + title => N("Graphic Card & Monitor Configuration"), if_($::isStandalone, ok => N("Quit")) }, [ { label => N("Graphic Card"), val => \$texts{card}, clicked => sub { @@ -132,7 +132,7 @@ sub configure_chooser_raw { { label => N("Monitor"), val => \$texts{monitors}, clicked => sub { $may_set->('monitors', Xconfig::monitor::configure($in, $raw_X, int($raw_X->get_devices))); } }, - { label => N("Resolution"), val => \$texts{resolution}, disabled => sub { !$X->{card} || !$X->{monitors} }, + { label => N("Resolution"), val => \$texts{resolutions}, disabled => sub { !$X->{card} || !$X->{monitors} }, clicked => $prompt_for_resolution }, if_(Xconfig::card::check_bad_card($X->{card}) || $::isStandalone, { val => N("Test"), disabled => sub { !$X->{card} || !$X->{monitors} }, @@ -141,9 +141,14 @@ sub configure_chooser_raw { } }, ), { val => N("Options"), clicked => sub { - Xconfig::various::various($in, $X->{card}, $options); - $X->{various} = 'done'; + Xconfig::various::various($in, $raw_X, $X->{card}, $options, 0, 'read_existing'); + Xconfig::card::to_raw_X($X->{card}, $raw_X); } }, + if_(Xconfig::plugins::list(), + { val => N("Plugins"), clicked => sub { + Xconfig::plugins::choose($in, $raw_X); + } }, + ), ]); $ok, $b_modified; } @@ -154,7 +159,7 @@ sub configure_chooser { my $X = { card => scalar eval { Xconfig::card::from_raw_X($raw_X) }, monitors => [ $raw_X->get_monitors ], - resolution => scalar eval { $raw_X->get_resolution }, + resolutions => [ eval { $raw_X->get_resolutions } ], }; my $before = $raw_X->prepare_write; my ($ok) = configure_chooser_raw($in, $raw_X, $do_pkgs, $options, $X); @@ -171,20 +176,21 @@ sub configure_everything_or_configure_chooser { my $raw_X = eval { Xconfig::xfree->read }; my $err = $@ && formatError($@); - $err ||= check_valid($raw_X) if $raw_X && @$raw_X; #- that's ok if config is empty + $err ||= check_valid($raw_X) if $raw_X; #- that's ok if config is empty if ($err) { log::l("ERROR: bad X config file (error: $err)"); $options->{ignore_bad_conf} or $in->ask_okcancel('', N("Your Xorg configuration file is broken, we will ignore it.")) or return; - $raw_X = []; + undef $raw_X; } my $rc = 'ok'; - if (is_empty_array_ref($raw_X)) { + if (!$raw_X) { $raw_X = Xconfig::default::configure($in->do_pkgs, $o_keyboard, $o_mouse); $rc = configure_everything($in, $raw_X, $in->do_pkgs, $auto, $options); } elsif (!$auto) { - $rc = configure_chooser($in, $raw_X, $in->do_pkgs, $options); + $rc = Xconfig::various::handle_May_Need_ForceBIOS($in, $raw_X); + $rc ||= configure_chooser($in, $raw_X, $in->do_pkgs, $options); } $rc && $raw_X, $rc; } @@ -206,9 +212,9 @@ sub write { export_to_install_X($X) if $::isInstall; $raw_X->write; Xconfig::various::check_XF86Config_symlink(); - symlinkf "../../usr/X11R6/bin/Xorg", "$::prefix/etc/X11/X"; - if ($X->{resolution}{bios}) { - Xconfig::various::setupFB($X->{resolution}{bios}); + symlinkf "../../usr/bin/Xorg", "$::prefix/etc/X11/X"; + if ($X->{resolutions}[0]{bios}) { + Xconfig::various::setupFB($X->{resolutions}[0]{bios}); 'need_reboot'; } else { 'need_restart'; @@ -219,9 +225,9 @@ sub write { sub export_to_install_X { my ($X) = @_; - $::o->{X}{resolution_wanted} = $X->{resolution}{X}; - $::o->{X}{default_depth} = $X->{resolution}{Depth}; - $::o->{X}{bios_vga_mode} = $X->{resolution}{bios}; + $::o->{X}{resolution_wanted} = $X->{resolutions}[0]{X} . 'x' . $X->{resolutions}[0]{Y}; + $::o->{X}{default_depth} = $X->{resolutions}[0]{Depth}; + $::o->{X}{bios_vga_mode} = $X->{resolutions}[0]{bios}; $::o->{X}{monitors} = $X->{monitors} if $X->{monitors}[0]{manually_chosen} && $X->{monitors}[0]{vendor} ne "Plug'n Play"; $::o->{X}{card} = $X->{card} if $X->{card}{manually_chosen}; $::o->{X}{Xinerama} = 1 if $X->{card}{Xinerama}; @@ -240,23 +246,4 @@ sub check_valid { ''; } -#- most usefull XFree86-4.0.1 server options. Default values is the first ones. -our @options_serverflags = ( - 'DontZap' => [ "Off", "On" ], - 'DontZoom' => [ "Off", "On" ], - 'DisableVidModeExtension' => [ "Off", "On" ], - 'AllowNonLocalXvidtune' => [ "Off", "On" ], - 'DisableModInDev' => [ "Off", "On" ], - 'AllowNonLocalModInDev' => [ "Off", "On" ], - 'AllowMouseOpenFail' => [ "False", "True" ], - 'VTSysReq' => [ "Off", "On" ], - 'BlankTime' => [ "10", "5", "3", "15", "30" ], - 'StandByTime' => [ "20", "10", "6", "30", "60" ], - 'SuspendTime' => [ "30", "15", "9", "45", "90" ], - 'OffTime' => [ "40", "20", "12", "60", "120" ], - 'Pixmap' => [ "32", "24" ], - 'PC98' => [ "auto-detected", "False", "True" ], - 'NoPM' => [ "False", "True" ], -); - 1; diff --git a/lib/Xconfig/monitor.pm b/lib/Xconfig/monitor.pm index ba5360b..d376f15 100644 --- a/lib/Xconfig/monitor.pm +++ b/lib/Xconfig/monitor.pm @@ -85,8 +85,7 @@ sub choose { my ($in, $monitor, $head_nb, $card_Driver, $b_auto) = @_; my $ok = is_valid($monitor); - if ($b_auto) { - log::l("Xconfig::monitor: auto failed") if !$ok; + if ($b_auto && $ok) { return $ok; } @@ -181,10 +180,35 @@ sub probe { probe_DDC() || probe_DMI() || probe_using_X($o_card_Driver); } +#- some EDID are much too strict: +#- the HorizSync range is too small to allow smaller resolutions +sub adjust_HorizSync_from_edid { + my ($monitor) = @_; + + my ($hmin, $hmax) = $monitor->{HorizSync} =~ /(\d+)-(\d+)/ or return; + if ($hmin > 45) { + log::l("replacing HorizSync $hmin-$hmax with 31.5-$hmax (allow 800x600)"); + $monitor->{HorizSync} = "31.5-$hmax"; + } +} +#- the VertRefresh range is too weird +sub adjust_VertRefresh_from_edid { + my ($monitor) = @_; + + my ($vmin, $vmax) = $monitor->{VertRefresh} =~ /(\d+)-(\d+)/ or return; + if ($vmin > 60) { + log::l("replacing VertRefresh $vmin-$vmax with 60-$vmax"); + $monitor->{VertRefresh} = "60-$vmax"; + } +} + sub probe_DDC() { my ($edid, $vbe) = any::monitor_full_edid() or return; my $monitor = eval($edid); + adjust_HorizSync_from_edid($monitor); + adjust_VertRefresh_from_edid($monitor); + if ($vbe =~ /Memory: (\d+)k/) { $monitor->{VideoRam_probed} = $1; } @@ -200,7 +224,10 @@ sub probe_DDC() { { val => $_->{ModeLine}, pre_comment => $_->{ModeLine_comment} . "\n" }; } - if (@$detailed_timings == 1) { + if (@$detailed_timings == 1 && $_->{horizontal_active} >= 1024) { + #- we don't use detailed_timing when it is 640x480 or 800x600, + #- since 14" CRTs often give this even when they handle 1024x768 correctly (and desktop is no good in poor resolutions) + #- should we care about {has_preferred_timing} ? $monitor->{preferred_resolution} = { X => $_->{horizontal_active}, Y => $_->{vertical_active} }; } @@ -210,6 +237,7 @@ sub probe_DDC() { $monitor->{VendorName} = "Plug'n Play"; $monitor->{ModelName} = $monitor->{monitor_name}; $monitor->{ModelName} =~ s/"/''/g; + $monitor->{ModelName} =~ s/[\0-\x20]/ /g; } configure_automatic($monitor) or return; $monitor; @@ -241,7 +269,7 @@ sub generic_flat_panel { { VendorName => 'Generic', ModelName => "Flat Panel $resolution", - HorizSync => '31.5-100', VertRefresh => '60', + HorizSync => '31.5-' . ($X > 1920 ? '100' : '90'), VertRefresh => '60', preferred_resolution => { X => $X, Y => $Y }, }; } diff --git a/lib/Xconfig/parse.pm b/lib/Xconfig/parse.pm index 71062a0..e7e97f4 100644 --- a/lib/Xconfig/parse.pm +++ b/lib/Xconfig/parse.pm @@ -8,35 +8,35 @@ use common; sub read_XF86Config { my ($file) = @_; - my $raw_X = raw_from_file($file); - from_raw(@$raw_X); - $raw_X; + my $raw = _rraw_from_file($file); + _from_rraw(@$raw); + $raw; } sub prepare_write_XF86Config { - my ($raw_X) = @_; - map { raw_to_string(before_to_string({ %$_ }, 0)) } @$raw_X; + my ($raw) = @_; + map { _raw_to_string(_before_to_string({ %$_ }, 0)) } @$raw; } sub write_XF86Config { - my ($raw_X, $file) = @_; - my @blocks = prepare_write_XF86Config($raw_X); + my ($raw, $file) = @_; + my @blocks = prepare_write_XF86Config($raw); @blocks ? output($file, @blocks) : unlink $file; } sub read_XF86Config_from_string { my ($s) = @_; - my $raw_X = raw_from_file('-', [ split "\n", $s ]); - from_raw(@$raw_X); - $raw_X; + my $raw = _rraw_from_file('-', [ split "\n", $s ]); + _from_rraw(@$raw); + $raw; } #-############################################################################### #- raw reading/saving #-############################################################################### -sub raw_from_file { #- internal +sub _rraw_from_file { my ($file, $o_lines) = @_; - my $raw_X = []; + my $rraw = []; my $lines = $o_lines || [ cat_($file) ]; my $line; @@ -68,7 +68,7 @@ sub raw_from_file { #- internal if (/^Section\s+"(.*)"/i) { die "$file:$line: missing EndSection\n" if @objs; my $e = { name => $1, l => [], kind => 'Section' }; - push @$raw_X, $e; + push @$rraw, $e; unshift @objs, $e; $obj = ''; $attach_comment->('pre'); } elsif (/^Subsection\s+"(.*)"/i) { @@ -110,21 +110,26 @@ sub raw_from_file { #- internal push @{$objs[0]{l}}, $obj; } } - $raw_X; + $rraw; } -sub raw_to_string { +sub _simple_val_to_string { + my ($name, $e) = @_; + my $key = $e->{Option} ? qq(Option "$name") : $name; + my $val = defined $e->{val} ? ($e->{Option} && $e->{val} !~ /^"/ ? qq( "$e->{val}") : qq( $e->{val})) : ''; + ($e->{commented} ? '#' : '') . $key . $val; +} + +sub _raw_to_string { my ($e, $b_want_spacing) = @_; my $s = do { if ($e->{l}) { - my $inside = join('', map_index { raw_to_string($_, $::i) } @{$e->{l}}); + my $inside = join('', map_index { _raw_to_string($_, $::i) } @{$e->{l}}); $inside .= $e->{post_comment} || ''; $inside =~ s/^/ /mg; qq(\n$e->{kind} "$e->{name}"\n) . $inside . "End$e->{kind}"; } else { - ($e->{commented} ? '#' : '') . - ($e->{Option} ? qq(Option "$e->{name}") : $e->{name}) . - (defined $e->{val} ? ($e->{Option} && $e->{val} !~ /^"/ ? qq( "$e->{val}") : qq( $e->{val})) : ''); + _simple_val_to_string($e->{name}, $e); } }; ($e->{pre_comment} ? ($b_want_spacing ? "\n" : '') . $e->{pre_comment} : '') . $s . ($e->{comment_on_line} || '') . "\n" . (!$e->{l} && $e->{post_comment} || ''); @@ -147,16 +152,16 @@ my %kind_names = ( WacomEraser => [ qw(Port) ], #-/ ServerLayout => [ qw(Identifier) ], ); -my @want_string = qw(Identifier DeviceName VendorName ModelName BoardName Driver Device Chipset Monitor Protocol XkbModel XkbLayout XkbOptions XkbCompat Load BusID); +my @want_string = qw(Identifier DeviceName VendorName ModelName BoardName Driver Device Chipset Monitor Protocol XkbModel XkbLayout XkbOptions XkbCompat Load ModulePath BusID); %kind_names = map_each { lc $::a => [ map { lc } @$::b ] } %kind_names; @want_string = map { lc } @want_string; -sub from_raw { - sub from_raw__rec { +sub _from_rraw { + sub _from_rraw__rec { my ($current, $e) = @_; if ($e->{l}) { - from_raw($e); + _from_rraw($e); push @{$current->{l}{$e->{name}}}, $e; } else { if (member(lc $e->{name}, @want_string)) { @@ -178,13 +183,13 @@ sub from_raw { foreach my $e (@_) { ($e->{l}, my $l) = ({}, $e->{l}); - from_raw__rec($e, $_) foreach @$l; + _from_rraw__rec($e, $_) foreach @$l; delete $e->{kind}; } } -sub before_to_string { +sub _before_to_string { my ($e, $depth) = @_; if ($e->{l}) { @@ -195,7 +200,7 @@ sub before_to_string { $e->{l} = [ map { my $name = $_; map { - before_to_string({ name => $name, %$_ }, $depth+1); + _before_to_string({ name => $name, %$_ }, $depth+1); } deref_array($e->{l}{$name}); } @sorted ]; } elsif (member(lc $e->{name}, @want_string)) { diff --git a/lib/Xconfig/plugins.pm b/lib/Xconfig/plugins.pm new file mode 100644 index 0000000..620c2fe --- /dev/null +++ b/lib/Xconfig/plugins.pm @@ -0,0 +1,232 @@ +package Xconfig::plugins; # $Id: plugins.pm 110085 2007-01-18 08:45:14Z pixel $ + +use diagnostics; +use strict; + +use Xconfig::parse; +use Xconfig::xfree; +use common; + +my $dir = '/usr/share/libDrakX/x11-plugins'; + +sub list() { + glob_("$dir/*.pl"); +} + +sub _load { + my ($plugin_pl_file) = @_; + my $plugin = eval cat_($plugin_pl_file); + $@ and die "bad $plugin_pl_file. error: $@\n"; + + #- ensure only one line + $plugin->{summary} =~ s/\n/ /g; + + eval { $plugin->{raw} = Xconfig::parse::read_XF86Config_from_string($plugin->{conf}) }; + $@ and die "bad $plugin_pl_file conf. error: $@\n"; + + $plugin; +} + +my $mark = '# Using plugin'; +sub parse_active_plugin { + my ($raw_X) = @_; + + $raw_X->{plugins} and internal_error("parse_active_plugin must be done before doing anything with plugins"); + + my $first = $raw_X->{raw}[0]; + if (my @l = $first->{pre_comment} =~ /^\Q$mark\E (.*)/gm) { + $raw_X->{plugins} = [ map { { active => 1, summary => $_ } } @l ]; + } +} +sub _mark_active_in_header { + my ($raw_X, $summary) = @_; + my $first = $raw_X->{raw}[0]; + $first->{pre_comment} =~ s/\n/\n$mark $summary\n/; +} +sub _remove_active_in_header { + my ($raw_X, $summary) = @_; + my $first = $raw_X->{raw}[0]; + $first->{pre_comment} =~ s/\Q$mark $summary\E\n//; +} + +sub load { + my ($raw_X, $plugin_pl_file) = @_; + + my $plugin = eval { _load($plugin_pl_file) }; + $@ and log::l("bad plugin $plugin_pl_file: $@"), return; + + if (my $existing = find { $_->{summary} eq $plugin->{summary} } @{$raw_X->{plugins}}) { + put_in_hash($existing, $plugin); + $existing->{updated} = 1; + } else { + push @{$raw_X->{plugins}}, $plugin; + } +} + +sub val { &Xconfig::xfree::val } + +sub apply_plugin { + my ($raw_X, $plugin) = @_; + + if ($plugin->{active}) { + $plugin->{updated} or return; + + #- removing before re-applying again + remove_plugin($raw_X, $plugin); + } + + log::l("applying plugin $plugin->{summary}"); + + foreach my $e (@{$plugin->{raw}}) { + _mark_lines_with_name($plugin->{summary}, $e); + + if (my @sections = _select_sections_to_modify($raw_X, $e)) { + #- modifying existing sections + #- if there is more than one, modify all of them! + _merge_in_section($_, $e->{l}) foreach @sections; + } else { + #- adding the section + $raw_X->add_Section($e->{name}, $e->{l}); + } + } + + _mark_active_in_header($raw_X, $plugin->{summary}); + $plugin->{active} = 1; +} + +sub _select_sections_to_modify { + my ($raw_X, $e) = @_; + + my @sections = $raw_X->get_Sections($e->{name}) or return; + + if ($e->{l}{Identifier}) { + if (my @l = grep { val($_->{Identifier}) eq $e->{l}{Identifier}{val} } @sections) { + #- only modifying the section(s) matching the Driver (useful for InputDevice) + delete $e->{l}{Identifier}; #- do not tag-with-comment this line used only to select the section + @l; + } else { + #- if no matching section, we will create it + (); + } + } elsif ($e->{l}{Driver}) { + if (my @l = grep { val($_->{Driver}) eq $e->{l}{Driver}{val} } @sections) { + #- only modifying the section(s) matching the Driver (useful for InputDevice) + delete $e->{l}{Driver}; #- do not tag-with-comment this line used only to select the section + @l; + } else { + #- hum, modifying existing sections, is that good? :-/ + @sections; + } + } else { + #- modifying existing sections + @sections; + } +} + +sub _merge_in_section { + my ($h, $h_to_add) = @_; + + foreach my $name (keys %$h_to_add) { + if (exists $h->{$name}) { + my $pre_comment = join('', map { "#HIDDEN $_->{val}\n" } deref_array($h->{$name})); + my ($first, @other) = deref_array($h_to_add->{$name}); + $first = { pre_comment => $pre_comment, %$first }; + + $h->{$name} = ref($h->{$name}) eq 'ARRAY' ? [ $first, @other ] : $first; + } else { + $h->{$name} = $h_to_add->{$name}; + } + } +} + +sub _mark_lines_with_name { + my ($summary, $e) = @_; + if ($e->{l}) { + _mark_lines_with_name($summary, $_) foreach map { deref_array($_) } values %{$e->{l}}; + } else { + $e->{comment_on_line} = " # $summary"; + } +} + +sub remove_plugin { + my ($raw_X, $plugin) = @_; + + $plugin->{active} or return; + + log::l("removing plugin $plugin->{summary}"); + + @{$raw_X->{raw}} = map { + _remove_plugin($plugin->{summary}, $_); + } @{$raw_X->{raw}}; + + _remove_active_in_header($raw_X, $plugin->{summary}); + $plugin->{active} = 0; +} + +sub _remove_plugin { + my ($summary, $e) = @_; + if ($e->{l}) { + my $removed; + foreach my $k (keys %{$e->{l}}) { + my $v = $e->{l}{$k}; + my @v = map { _remove_plugin($summary, $_) } deref_array($v); + if (@v) { + if (ref($v) eq 'ARRAY') { + @$v = @v; + } else { + $e->{l}{$k} = $v[0]; + } + } else { + $removed = 1; + delete $e->{l}{$k}; + } + } + if_(!$removed || %{$e->{l}}, $e); + } elsif ($e->{comment_on_line} eq " # $summary") { + if (my @hidden = $e->{pre_comment} =~ /^#HIDDEN (.*)/gm) { + delete $e->{comment_on_line}; + delete $e->{pre_comment}; + map { { %$e, val => $_ } } @hidden; + } else { + (); + } + } else { + $e; + } +} + +sub apply_or_remove_plugin { + my ($raw_X, $plugin, $apply) = @_; + + if ($apply) { + apply_plugin($raw_X, $plugin); + } else { + remove_plugin($raw_X, $plugin); + } +} + +sub choose { + my ($in, $raw_X) = @_; + + parse_active_plugin($raw_X) if !$raw_X->{plugins}; + + load($raw_X, $_) foreach list(); + + my $plugins = $raw_X->{plugins}; + $_->{want_active} = $_->{active} foreach @$plugins; + + $in->ask_from_({}, + [ { title => 1, label => N("Choose plugins") }, + map { + { type => 'bool', val => \$_->{want_active}, text => $_->{summary} }, + { val => formatAlaTeX($_->{description}) }; + } @$plugins ]) or return; + + foreach (@$plugins) { + apply_or_remove_plugin($raw_X, $_, $_->{want_active}) + if $_->{want_active} != $_->{active}; + } + + 1; +} +1; diff --git a/lib/Xconfig/proprietary.pm b/lib/Xconfig/proprietary.pm index ed196de..3fae5f9 100644 --- a/lib/Xconfig/proprietary.pm +++ b/lib/Xconfig/proprietary.pm @@ -4,7 +4,9 @@ use diagnostics; use strict; use common; +use Xconfig::card; +my $lib = arch() =~ /x86_64/ ? "lib64" : "lib"; sub install_matrox_hal { my ($prefix) = @_; @@ -12,7 +14,7 @@ sub install_matrox_hal { my $tar = "mgadrivers-2.0.tgz"; my $dir_in_tar = "mgadrivers"; - my $dest_dir = "$prefix/usr/X11R6/lib/modules/drivers"; + my $dest_dir = "$prefix/usr/lib/xorg/modules/drivers"; #- already installed return if -e "$dest_dir/mga_hal_drv.o" || $::testing; @@ -31,5 +33,71 @@ sub install_matrox_hal { rm_rf("$tmpdir/$dir_in_tar"); } +sub pkg_name_for_Driver2 { + my ($card) = @_; + $card->{Driver2} eq 'fglrx' ? 'ati' : + $card->{Driver2} =~ /^nvidia/ ? $card->{Driver2} : ''; +} + +sub pkgs_for_Driver2 { + my ($card, $do_pkgs) = @_; + + my $pkg = pkg_name_for_Driver2($card); + + $pkg && $do_pkgs->is_available($pkg) or return; + + my $module_pkgs = $do_pkgs->check_kernel_module_packages($pkg) or + log::l("$pkg available, but no kernel module package (for installed kernels, and no dkms)"), return; + + ($pkg, @$module_pkgs); +} + +sub may_use_Driver2 { + my ($card) = @_; + + my $modules_dir = Xconfig::card::modules_dir(); + #- make sure everything is correct at this point, packages have really been installed + #- and driver and GLX extension is present. + + my $check_drv = sub { + my ($drv, $o_subdir) = @_; + my @l = (if_($o_subdir, "$modules_dir/drivers/$o_subdir/$drv.so"), + "$modules_dir/drivers/$drv.so", + "$modules_dir/drivers/$drv.o"); + my $has = find { -e "$::prefix$_" } @l; + $has or log::l("proprietary $drv driver missing, defaulting to free software driver (we searched for: @l)"); + $has; + }; + + my $card2 = { + %$card, + $card->{Driver2} =~ /^nvidia(.*)/ ? + (Driver => 'nvidia', DriverVersion => $1) : + (Driver => $card->{Driver2}), + }; + + if ($card2->{Driver} eq 'nvidia') { + $check_drv->('nvidia_drv', "nvidia$card2->{DriverVersion}") or return; + + my $libglx_path = Xconfig::card::modules_dir() . "/extensions/nvidia$card2->{DriverVersion}"; + -e "$::prefix$libglx_path/libglx.so" or log::l("special NVIDIA libglx missing, defaulting to free software driver"), return; + + log::explanations("Using specific NVIDIA driver and GLX extensions"); + $card2->{DRI_GLX_SPECIAL} = $libglx_path; + $card2->{Options}{IgnoreEDID} = 1 if $card2->{DriverVersion} ne '97xx'; + $card2; + } elsif ($card2->{Driver} eq 'fglrx') { + $check_drv->('fglrx_drv') or return; + -e "$::prefix$modules_dir/dri/fglrx_dri.so" || -e "$::prefix/usr/$lib/dri/fglrx_dri.so" or + log::l("proprietary fglrx_dri.so missing, defaulting to free software driver"), return; + + log::explanations("Using specific ATI fglrx and DRI drivers"); + $card2->{DRI_GLX} = 1; + $card2; + } else { + undef; + } +} + 1; diff --git a/lib/Xconfig/resolution_and_depth.pm b/lib/Xconfig/resolution_and_depth.pm index 2942664..2564980 100644 --- a/lib/Xconfig/resolution_and_depth.pm +++ b/lib/Xconfig/resolution_and_depth.pm @@ -34,7 +34,8 @@ my @bios_vga_modes = ( sub from_bios { my ($bios) = @_; - find { $_->{bios} == $bios } @bios_vga_modes; + my $bios_int = $bios =~ /^0x(.*)/ ? hex($1) : $bios; + find { $_->{bios} == $bios_int } @bios_vga_modes; } sub bios_vga_modes() { @bios_vga_modes } @@ -82,7 +83,7 @@ sub allowed { my @depths; if ($card->{Driver} eq 'fglrx') { @depths = 24; - } elsif ($card->{BoardName} eq 'RIVA128') { + } elsif ($card->{BoardName} eq 'NVIDIA RIVA 128') { @depths = qw(8 15 24); } elsif ($card->{use_DRI_GLX}) { $prefered_depth = 16; @@ -146,6 +147,8 @@ sub choices { #- sort it, so we can take the first one when we want the "best" @resolutions = sort { $b->{X} <=> $a->{X} || $b->{Y} <=> $a->{Y} || $b->{Depth} <=> $a->{Depth} } @resolutions; + $_->{ratio} ||= resolution2ratio($_) foreach @resolutions; + if ($resolution_wanted->{X} && !$resolution_wanted->{Y}) { #- assuming ratio 4/3 $resolution_wanted->{Y} = round($resolution_wanted->{X} * 3 / 4); @@ -203,9 +206,7 @@ sub configure { } else { $default_resolution = choose($in, $default_resolution, @resolutions) or return; } - set_resolution($raw_X, $default_resolution); - - $default_resolution; + set_resolution($raw_X, $default_resolution, @resolutions); } sub configure_auto_install { @@ -216,18 +217,25 @@ sub configure_auto_install { { X => $X, Y => $Y, Depth => $old_X->{default_depth} }; }; - my ($default_resolution) = choices($raw_X, $resolution_wanted, $card, $monitors); + my ($default_resolution, @resolutions) = choices($raw_X, $resolution_wanted, $card, $monitors); $default_resolution or die "you selected an unusable depth"; - set_resolution($raw_X, $default_resolution); - - $default_resolution; + set_resolution($raw_X, $default_resolution, @resolutions); } sub set_resolution { - my ($raw_X, $resolution) = @_; - $raw_X->set_resolution($resolution); + my ($raw_X, $resolution, @other) = @_; + + my $ratio = resolution2ratio($resolution, 'non-strict'); + @other = uniq_ { $_->{X} . 'x' . $_->{Y} } @other; + @other = grep { $_->{X} < $resolution->{X} } @other; + @other = filter_on_ratio($ratio, @other); + my $resolutions = [ $resolution, @other ]; + + $raw_X->set_resolutions($resolutions); set_default_background($resolution); + set_915resolution($resolution) if is_915resolution_configured(); + $resolutions; } sub set_default_background { my ($resolution) = @_; @@ -251,6 +259,21 @@ sub set_default_background { symlinkf $l[0][0], "$dir/default.png"; } +sub is_915resolution_configured() { + my $f = "$::prefix/etc/sysconfig/915resolution"; + -e $f && { getVarsFromSh($f) }->{XRESO}; +} +sub set_915resolution { + my ($resolution) = @_; + + my $f = "$::prefix/etc/sysconfig/915resolution"; + setVarsInSh($f, { + MODE => 'best', + XRESO => $resolution->{X}, + YRESO => $resolution->{Y}, + }); + run_program::rooted($::prefix, 'service', '915resolution', 'start'); +} sub resolution2ratio { my ($resolution, $b_non_strict) = @_; @@ -258,22 +281,22 @@ sub resolution2ratio { $res eq '1280x1024' && $b_non_strict ? '4/3' : $Xconfig::xfree::resolution2ratio{$res}; } +sub filter_on_ratio { + my ($ratio, @l) = @_; + grep { + !$ratio + || $_->{ratio} eq $ratio + || $ratio eq '4/3' && "$_->{X}x$_->{Y}" eq '1280x1024'; + } @l; +} + sub choose_gtk { my ($in, $card, $default_resolution, @resolutions) = @_; - $_->{ratio} ||= resolution2ratio($_) foreach @resolutions; - my $chosen_Depth = $default_resolution->{Depth}; my $chosen_res = { X => $default_resolution->{X} || 1024, Y => $default_resolution->{Y} }; my $chosen_ratio = resolution2ratio($chosen_res, 'non-strict') || '4/3'; - my $filter_on_ratio = sub { - grep { - !$chosen_ratio - || $_->{ratio} eq $chosen_ratio - || $chosen_ratio eq '4/3' && "$_->{X}x$_->{Y}" eq '1280x1024'; - } @_; - }; my $filter_on_Depth = sub { grep { $_->{Depth} == $chosen_Depth } @_; }; @@ -305,7 +328,7 @@ sub choose_gtk { my $proposed_resolutions = []; my $set_proposed_resolutions = sub { my ($suggested_res) = @_; - @matching_ratio = $filter_on_ratio->(@resolutions); + @matching_ratio = filter_on_ratio($chosen_ratio, @resolutions); gtkval_modify(\$proposed_resolutions, [ (reverse uniq_ { $res2text->($_) } @matching_ratio), if_($chosen_ratio, { text => N_("Other") }), diff --git a/lib/Xconfig/various.pm b/lib/Xconfig/various.pm index c38205f..dc74fce 100644 --- a/lib/Xconfig/various.pm +++ b/lib/Xconfig/various.pm @@ -18,21 +18,18 @@ sub to_string { sub info { my ($raw_X, $card) = @_; my $info; - my $xf_ver = Xconfig::card::xorg_version(); - my $title = $card->{use_DRI_GLX} ? N("Xorg %s with 3D hardware acceleration", $xf_ver) : - N("Xorg %s", $xf_ver); my $keyboard = eval { $raw_X->get_keyboard } || {}; my @monitors = eval { $raw_X->get_monitors }; my $device = eval { $raw_X->get_device } || {}; my $mouse = eval { first($raw_X->get_mice) } || {}; + $info .= N("3D hardware acceleration: %s\n", translate(bool2yesno($card->{use_DRI_GLX}))); $info .= N("Keyboard layout: %s\n", $keyboard->{XkbLayout}); $info .= N("Mouse type: %s\n", $mouse->{Protocol}); - $info .= N("Mouse device: %s\n", $mouse->{Device}) if $::expert; foreach my $monitor (@monitors) { $info .= N("Monitor: %s\n", $monitor->{ModelName}); - $info .= N("Monitor HorizSync: %s\n", $monitor->{HorizSync}) if $::expert; - $info .= N("Monitor VertRefresh: %s\n", $monitor->{VertRefresh}) if $::expert; + $info .= N("Monitor HorizSync: %s\n", $monitor->{HorizSync}); + $info .= N("Monitor VertRefresh: %s\n", $monitor->{VertRefresh}); } $info .= N("Graphics card: %s\n", $device->{VendorName} . ' ' . $device->{BoardName}); $info .= N("Graphics memory: %s kB\n", $device->{VideoRam}) if $device->{VideoRam}; @@ -41,17 +38,155 @@ sub info { $info .= N("Resolution: %s\n", join('x', @$resolution{'X', 'Y'})); } $info .= N("Xorg driver: %s\n", $device->{Driver}) if $device->{Driver}; - "$title\n\n$info"; + $info; +} + +sub default { + my ($card, $various) = @_; + + my $isLaptop = detect_devices::isLaptop(); + + add2hash_($various, { + isLaptop => $isLaptop, + xdm => 1, + Composite => !($card->{Driver} eq 'fglrx' || $card->{Driver} eq 'nvidia' && $card->{DriverVersion} eq '71xx'), + if_($card->{Driver} eq 'nvidia', RenderAccel => $card->{DriverVersion} eq '97xx', Clone => 0), + if_($card->{Driver} eq 'savage', HWCursor => 1), + if_($card->{Driver} eq 'i810' && $isLaptop, Clone => 0), + if_($card->{Driver} eq 'ati' && $isLaptop, Clone => 1, BIOSHotkeys => 0), + if_(exists $card->{DRI_GLX}, use_DRI_GLX => $card->{DRI_GLX} && !$card->{Xinerama}), + if_(member($card->{Driver}, qw(i128 ati sis trident via savage)), EXA => 0), #- list taken from http://wiki.x.org/wiki/ExaStatus + }); } sub various { - my ($in, $card, $options, $b_auto) = @_; + my ($in, $raw_X, $card, $options, $b_auto, $b_read_existing) = @_; tvout($in, $card, $options) if !$b_auto; - choose_xdm($in, $b_auto); + + my $use_DRI_GLX = member('dri', $raw_X->get_modules); + + my $various = { + if_($::isStandalone, xdm => runlevel() == 5), + if_($b_read_existing, + Composite => ($raw_X->get_Section('Extensions') || {})->{Composite}, + if_(($card->{Options}{MonitorLayout} || [])->[0] eq '"NONE,CRT+LFP"' || + ($card->{Options}{TwinViewOrientation} || [])->[0] eq '"Clone"', + Clone => 1), + if_(($card->{Options}{MonitorLayout} || [])->[0] eq '"LVDS,NONE"', + Clone => 0), + if_($card->{Options}{BIOSHotkeys}, + BIOSHotkeys => 1), + if_($card->{Options}{AccelMethod}, + EXA => ($card->{Options}{AccelMethod} || [])->[0] eq '"EXA"'), + if_($card->{Driver} eq 'nvidia', + RenderAccel => !$card->{Options}{RenderAccel}, + ), + HWCursor => !$card->{Options}{SWCursor}, + if_($card->{DRI_GLX} || $use_DRI_GLX, use_DRI_GLX => $use_DRI_GLX), + ), + }; + default($card, $various); + + if (!$b_auto) { + choose($in, $various) or return; + } + + config($raw_X, $card, $various) && $various; +} + +sub various_auto_install { + my ($raw_X, $card, $old_X) = @_; + + my $various = { %$old_X }; + default($card, $various); + config($raw_X, $card, $various); 1; } +sub config { + my ($raw_X, $card, $various) = @_; + + if ($various->{Composite}) { + my $raw = $raw_X->get_Section('Extensions') || $raw_X->add_Section('Extensions', {}); + $raw->{Composite} = { 'Option' => 1 }; + if ($card->{Driver} eq 'nvidia') { + $card->{Options}{AddARGBGLXVisuals} = undef; + } + } else { + if (my $raw = $raw_X->get_Section('Extensions')) { + delete $raw->{Composite}; + %$raw or $raw_X->remove_Section('Extensions'); + } + if ($card->{Driver} eq 'nvidia') { + delete $card->{Options}{AddARGBGLXVisuals}; + } + } + if (exists $various->{use_DRI_GLX}) { + $card->{use_DRI_GLX} = $various->{use_DRI_GLX}; + } + + if (exists $various->{RenderAccel}) { + if ($various->{RenderAccel}) { + delete $card->{Options}{RenderAccel}; + } else { + $card->{Options}{RenderAccel} = 'false'; + } + } + + if (exists $various->{HWCursor}) { + if ($various->{HWCursor}) { + delete $card->{Options}{SWCursor}; + } else { + $card->{Options}{SWCursor} = undef; + } + } + + if (exists $various->{BIOSHotkeys}) { + if ($various->{BIOSHotkeys}) { + $card->{Options}{BIOSHotkeys} = undef; + } else { + delete $card->{Options}{BIOSHotkeys}; + } + } + + if (exists $various->{EXA}) { + if ($various->{EXA}) { + $card->{Options}{AccelMethod} = 'EXA'; + } else { + delete $card->{Options}{AccelMethod}; + } + } + + if (exists $various->{Clone}) { + if ($card->{Driver} eq 'nvidia') { + if ($various->{Clone}) { + $card->{Options}{TwinView} = undef; + $card->{Options}{TwinViewOrientation} = 'Clone'; + } else { + delete $card->{Options}{TwinView}; + delete $card->{Options}{TwinViewOrientation}; + } + } elsif ($card->{Driver} eq 'i810') { + if ($various->{Clone}) { + $card->{Options}{MonitorLayout} = 'NONE,CRT+LFP'; + } else { + delete $card->{Options}{MonitorLayout}; + } + } elsif ($card->{Driver} eq 'ati') { + if ($various->{Clone}) { + #- the default is Clone + delete $card->{Options}{MonitorLayout}; + } else { + #- forcing no display on CRT + $card->{Options}{MonitorLayout} = 'LVDS,NONE'; + } + } + } + + Xconfig::various::runlevel($various->{xdm} ? 5 : 3); +} + sub runlevel { my ($o_runlevel) = @_; my $f = "$::prefix/etc/inittab"; @@ -63,20 +198,39 @@ sub runlevel { } } -sub choose_xdm { - my ($in, $b_auto) = @_; - my $xdm = $::isStandalone ? runlevel() == 5 : 1; +sub choose { + my ($in, $various) = @_; + + $in->ask_from_({ title => N("Xorg configuration") }, [ + { label => N("Graphic card options"), title => 1 }, + exists $various->{use_DRI_GLX} ? + { text => N("3D hardware acceleration"), + type => 'bool', val => \$various->{use_DRI_GLX} } : (), + { text => N("Enable Translucency (Composite extension)"), + type => 'bool', val => \$various->{Composite} }, + exists $various->{HWCursor} ? + { text => N("Use hardware accelerated mouse pointer"), + type => 'bool', val => \$various->{HWCursor} } : (), + exists $various->{RenderAccel} ? + { text => N("Enable RENDER Acceleration (this may cause bugs displaying text)"), + type => 'bool', val => \$various->{RenderAccel} } : (), + exists $various->{Clone} ? + { text => $various->{isLaptop} ? + N("Enable duplicate display on the external monitor") : + N("Enable duplicate display on the second display"), + type => 'bool', val => \$various->{Clone} } : (), + exists $various->{BIOSHotkeys} ? + { text => N("Enable BIOS hotkey for external monitor switching"), + type => 'bool', val => \$various->{BIOSHotkeys} } : (), + exists $various->{EXA} ? + { text => N("Use EXA instead of XAA (better performance for Render and Composite)"), + type => 'bool', val => \$various->{EXA} } : (), + { label => N("Graphical interface at startup"), title => 1 }, + { text => N("Automatically start the graphical interface (Xorg) upon booting"), + type => 'bool', val => \$various->{xdm} }, + ]) or return; - if (!$b_auto) { - $xdm = $in->ask_yesorno_({ - title => N("Graphical interface at startup"), - messages => -N("I can setup your computer to automatically start the graphical interface (Xorg) upon booting. -Would you like Xorg to start when you reboot?"), - interactive_help_id => 'configureXxdm', - }, $xdm); - } - runlevel($xdm ? 5 : 3); + 1; } sub tvout { @@ -171,8 +325,36 @@ sub setupFB { $_->{vga} = $bios_vga_mode if $_->{vga}; #- replace existing vga= with } + bootloader::update_splash($bootloader); bootloader::action($bootloader, 'write', $all_hds); bootloader::action($bootloader, 'when_config_changed'); } +sub handle_May_Need_ForceBIOS { + my ($in, $raw_X) = @_; + + Xconfig::resolution_and_depth::is_915resolution_configured and return; + + any { $_->{Options}{May_Need_ForceBIOS} } $raw_X->get_devices or return; + + my $log = cat_('/var/log/Xorg.0.log'); + $log =~ /Option "May_Need_ForceBIOS" is not used/ or return; + + + my @builtin_modes = $log =~ /\*Built-in mode "(\d+x\d+)"/g; + my $resolution = $raw_X->get_resolution; + !member("$resolution->{X}x$resolution->{Y}", @builtin_modes) or return; + + $in->ask_yesorno('', formatAlaTeX(N("The display resolution being used may not be correct. + +If your desktop appears to stretch beyond the edges of the display, +installing %s may help fix the problem. Install it now?", '915resolution')), 1) or return; + + $in->do_pkgs->ensure_binary_is_installed('915resolution', '915resolution', 1) or return; + + Xconfig::resolution_and_depth::set_915resolution($resolution); + + 'need_restart'; +} + 1; diff --git a/lib/Xconfig/xfree.pm b/lib/Xconfig/xfree.pm index 5cba3ee..1e5eaaa 100644 --- a/lib/Xconfig/xfree.pm +++ b/lib/Xconfig/xfree.pm @@ -1,5 +1,7 @@ package Xconfig::xfree; # $Id$ +my ($Revision) = '$Revision$' =~ /(\d+)/; + use diagnostics; use strict; @@ -8,8 +10,8 @@ use Xconfig::parse; #- mostly internal only sub new { - my ($class, $val) = @_; - bless $val, $class; + my ($class, $raw) = @_; + @$raw && bless { raw => $raw }, $class; } sub _conf_files() { @@ -22,11 +24,14 @@ sub _conf_files() { sub read_and_prepare_write { my ($class) = @_; my $file = find { -f $_ } _conf_files(); - my $raw_X = $class->new(Xconfig::parse::read_XF86Config($file)); + my $raw_X = $class->new(Xconfig::parse::read_XF86Config($file)) or return; my $before = $raw_X->prepare_write; - if (my ($Keyboard) = $raw_X->get_InputDevices('Keyboard')) { - $Keyboard->{Driver}{val} = 'keyboard'; + if (my ($keyboard) = $raw_X->get_InputDevices('keyboard')) { + $keyboard->{Driver}{val} = 'kbd'; + } + if (my ($keyboard) = $raw_X->get_InputDevices('Keyboard')) { + $keyboard->{Driver}{val} = 'kbd'; } #- ugly hack to fix empty ModeLine lines, XFdrake seems to generate some, but where??? @@ -56,35 +61,60 @@ sub write { #- keep it for old programs still using this name symlink basename($file), "$::prefix/etc/X11/XF86Config"; } - Xconfig::parse::write_XF86Config($raw_X, $file); + set_Revision($raw_X); + Xconfig::parse::write_XF86Config($raw_X->{raw}, $file); } sub prepare_write { my ($raw_X) = @_; - join('', Xconfig::parse::prepare_write_XF86Config($raw_X)); + set_Revision($raw_X); + join('', Xconfig::parse::prepare_write_XF86Config($raw_X->{raw})); } sub empty_config { my ($class) = @_; $class->new(Xconfig::parse::read_XF86Config_from_string(our $default_header)); } +my $mark = '# File generated by XFdrake'; +sub get_Revision { + my ($raw_X) = @_; + my $first = $raw_X->{raw}[0]; + $first->{pre_comment} =~ /^\Q$mark\E \(rev (\d+)\)/ && $1; +} +sub set_Revision { + my ($raw_X) = @_; + my $first = $raw_X->{raw}[0]; + my $first_comment = $first->{pre_comment}; + + my $was_there = $first_comment =~ s/^\Q$mark\E.*\n//; + $first->{pre_comment} = "$mark (rev $Revision)\n" . ($was_there ? '' : "\n") . $first_comment; +} + ################################################################################ # keyboard ##################################################################### ################################################################################ my @keyboard_fields = qw(XkbLayout XkbModel XkbDisable XkbOptions XkbCompat); sub get_keyboard { my ($raw_X) = @_; - my $raw_kbd = first(map { $raw_X->get_InputDevices($_) } 'keyboard', 'kbd') or die "no keyboard section"; + my $raw_kbd = _raw_get_keyboard($raw_X) or die "no keyboard section"; raw_export_section($raw_kbd, \@keyboard_fields); } sub set_keyboard { my ($raw_X, $kbd) = @_; - my $raw_kbd = first(map { $raw_X->get_InputDevices($_) } 'keyboard', 'kbd') || _new_keyboard_section($raw_X); + my $raw_kbd = _raw_get_keyboard($raw_X) || _new_keyboard_section($raw_X); raw_import_section($raw_kbd, $kbd); _set_Option('keyboard', $raw_kbd, keys %$kbd); } +sub _raw_get_keyboard { + my ($raw_X) = @_; + first($raw_X->get_Sections('InputDevice', sub { + my ($entry) = @_; + my $Driver = val($entry->{Driver}); + $Driver eq 'kbd' || $Driver eq 'evdev' && val($entry->{XkbLayout}); + })); +} sub _new_keyboard_section { my ($raw_X) = @_; - my $raw_kbd = { Identifier => { val => 'Keyboard1' }, Driver => { val => 'keyboard' } }; + my $raw_kbd = { Identifier => { val => 'Keyboard1' }, Driver => { val => 'kbd' } }; $raw_X->add_Section('InputDevice', $raw_kbd); my $layout = get_ServerLayout($raw_X)->{InputDevice} ||= []; @@ -97,38 +127,44 @@ sub _new_keyboard_section { ################################################################################ # mouse ######################################################################## ################################################################################ -#- example: { Protocol => 'IMPS/2', Device => '/dev/psaux', Emulate3Buttons => undef, Emulate3Timeout => 50, ZAxisMapping => [ '4 5', '6 7' ] } -my @mouse_fields = qw(Protocol Device ZAxisMapping Emulate3Buttons Emulate3Timeout); #-); +#- example mouse: { Protocol => 'IMPS/2', Device => '/dev/psaux', Emulate3Buttons => undef, Emulate3Timeout => 50, ZAxisMapping => [ '4 5', '6 7' ] } +#- example evdev: { vendor => '0x045e', product => '0x008c' } +my @mouse_fields = qw(Protocol Device ZAxisMapping Emulate3Buttons Emulate3Timeout vendor product); #-); sub get_mice { my ($raw_X) = @_; - my @raw_mice = $raw_X->get_InputDevices('mouse'); + my @raw_mice = $raw_X->get_Sections('InputDevice', \&_is_mouse); map { raw_export_section($_, \@mouse_fields) } @raw_mice; } sub set_mice { my ($raw_X, @mice) = @_; - my @raw_mice = _new_mouse_sections($raw_X, int @mice); + my @raw_mice = _new_mouse_sections($raw_X, map { $_->{Protocol} ? 'mouse' : 'evdev' } @mice); mapn { my ($raw_mouse, $mouse) = @_; raw_import_section($raw_mouse, $mouse); _set_Option('mouse', $raw_mouse, keys %$mouse); } \@raw_mice, \@mice; } +sub _is_mouse { + my ($entry) = @_; + my $Driver = val($entry->{Driver}); + $Driver eq 'mouse' || $Driver eq 'evdev' && !val($entry->{XkbLayout}); +} sub _new_mouse_sections { - my ($raw_X, $nb_new) = @_; - $raw_X->remove_InputDevices('mouse'); + my ($raw_X, @Drivers) = @_; + $raw_X->remove_Section('InputDevice', \&_is_mouse); my $layout = get_ServerLayout($raw_X)->{InputDevice} ||= []; @$layout = grep { $_->{val} !~ /^"Mouse/ } @$layout; - $nb_new or return; + @Drivers or return; - my @l = map { - my $h = { Identifier => { val => "Mouse$_" }, Driver => { val => 'mouse' } }; + my @l = map_index { + my $h = { Identifier => { val => 'Mouse' . ($::i + 1) }, Driver => { val => $_ } }; $raw_X->add_Section('InputDevice', $h); - } (1 .. $nb_new); + } @Drivers; push @$layout, { val => qq("Mouse1" "CorePointer") }; - push @$layout, { val => qq("Mouse$_" "SendCoreEvents") } foreach 2 .. $nb_new; + push @$layout, { val => qq("Mouse$_" "SendCoreEvents") } foreach 2 .. @Drivers; @l; } @@ -138,31 +174,41 @@ sub _new_mouse_sections { # resolution ################################################################### ################################################################################ sub get_resolution { + my ($raw_X, $o_Screen) = @_; + first(get_resolutions($raw_X, $o_Screen)); +} +sub get_resolutions { my ($raw_X, $o_Screen) = @_; my $Screen = $o_Screen || $raw_X->get_default_screen or return {}; my $depth = val($Screen->{DefaultColorDepth} || $Screen->{DefaultDepth}); my $Display = find { !$depth || val($_->{l}{Depth}) eq $depth } @{$Screen->{Display} || []} or return {}; - $Display->{l}{Virtual} && val($Display->{l}{Virtual}) =~ /(\d+)\s+(\d+)/ or - val($Display->{l}{Modes}) =~ /(\d+)x(\d+)/ or return {}; - { X => $1, Y => $2, Depth => val($Display->{l}{Depth}) }; + my $s = val($Display->{l}{Virtual} || $Display->{l}{Modes}); + my @l; + while ($s =~ /(\d+)(x|\s+)(\d+)/g) { + push @l, { X => $1, Y => $3, Depth => val($Display->{l}{Depth}) }; + } + @l; } -sub set_resolution { - my ($raw_X, $resolution, $o_Screen_) = @_; +sub set_resolutions { + my ($raw_X, $resolutions, $o_Screen) = @_; - foreach my $Screen ($o_Screen_ ? $o_Screen_ : $raw_X->get_Sections('Screen')) { + foreach my $Screen ($o_Screen ? $o_Screen : $raw_X->get_Sections('Screen')) { $Screen ||= $raw_X->get_default_screen or internal_error('no screen'); - my $Mode_name = (any { $_->{l}{Modes} } @{$Screen->{Display} || []}) ? 'Modes' : 'Virtual'; - my $Mode = sprintf($Mode_name eq 'Modes' ? '"%dx%d"' : '%d %d', @$resolution{'X', 'Y'}); + #- if the existing config is using Virtual, keep Virtual, otherwise default to Modes + my $Mode_name = (any { $_->{l}{Virtual} } @{$Screen->{Display} || []}) ? 'Virtual' : 'Modes'; + + my @l = $Mode_name eq 'Modes' ? @$resolutions : first(@$resolutions); + my @Modes = map { sprintf($Mode_name eq 'Modes' ? '"%dx%d"' : '%d %d', @$_{'X', 'Y'}) } @l; delete $Screen->{DefaultDepth}; - $Screen->{DefaultColorDepth} = { val => $resolution->{Depth} eq '32' ? 24 : $resolution->{Depth} }; + $Screen->{DefaultColorDepth} = { val => $resolutions->[0]{Depth} eq '32' ? 24 : $resolutions->[0]{Depth} }; $Screen->{Display} = [ map { - { l => { Depth => { val => $_ }, $Mode_name => { val => $Mode } } }; + { l => { Depth => { val => $_ }, $Mode_name => { val => join(' ', @Modes) } } }; } 8, 15, 16, 24 ]; } - add_gtf_ModeLines($raw_X, $resolution); + add_gtf_ModeLines($raw_X, $resolutions); } @@ -250,7 +296,6 @@ sub set_synaptics { @$layout = grep { $_->{val} !~ /^"SynapticsMouse/ } @$layout; @synaptics or return; - add_load_module($raw_X, "synaptics"); each_index { my $synaptics_mouse = $_; @@ -261,9 +306,7 @@ sub set_synaptics { Driver => { val => "synaptics" }, }; my %opts = ( - Device => $synaptics_mouse->{Device}, - Protocol => $synaptics_mouse->{Protocol}, - $synaptics_mouse->{ALPS} ? ( + if_($synaptics_mouse->{ALPS}, #- from /usr/share/doc/synaptics-0.14.0/README.alps #- and http://qa.mandrakesoft.com/show_bug.cgi?id=14512 LeftEdge => 120, @@ -272,9 +315,7 @@ sub set_synaptics { BottomEdge => 650, FingerLow => 14, FingerHigh => 15, - MaxTapTime => 180, MaxTapMove => 110, - EmulateMidButtonTime => 75, VertScrollDelta => 20, HorizScrollDelta => 20, MinSpeed => '0.8', @@ -284,24 +325,9 @@ sub set_synaptics { EdgeMotionMaxSpeed => 200, UpDownScrolling => 1, CircularScrolling => 1, - CircScrollDelta => '0.1', CircScrollTrigger => 2, UpDownScrolling => 0, - ) : ( - #- from /usr/share/doc/synaptics-0.14.0/INSTALL - LeftEdge => 1700, - RightEdge => 5300, - TopEdge => 1700, - BottomEdge => 4200, - FingerLow => 25, - FingerHigh => 30, - MaxTapTime => 180, - MaxTapMove => 220, - VertScrollDelta => 100, - MinSpeed => '0.09', - MaxSpeed => '0.18', - AccelFactor => '0.0015', - ), + ), #- use default driver options for non-ALPS SHMConfig => "on", ); while (my ($k, $v) = each %opts) { @@ -356,21 +382,24 @@ sub default_ModeLine() { } sub add_gtf_ModeLines { - my ($raw_X, $resolution) = @_; + my ($raw_X, $resolutions) = @_; my $banner = 'modeline generated by gtf(1) [handled by XFdrake]'; - my $res = $resolution->{X} . 'x' . $resolution->{Y}; + my $res = $resolutions->[0]{X} . 'x' . $resolutions->[0]{Y}; my @to_add; if ($res ne '1280x1024' && ($res eq '1400x1050' || $res eq '1152x864' || $Xconfig::xfree::resolution2ratio{$res} ne '4/3')) { - @to_add = map { + @to_add = map { + my $resolution = $_; + map { my $s = run_program::rooted_get_stdout($::prefix, 'gtf', $resolution->{X}, $resolution->{Y}, $_); if (my ($name, $val) = $s =~ /ModeLine\s*"(.*)"(.*)/i) { chomp $val; $name =~ s/\.00//; #- nicer that way { val => qq("${name}"$val), pre_comment => "# $banner\n" }; } else { () } - } reverse(sort_numbers(@Xconfig::xfree::vfreqs)); + } reverse(sort_numbers(@Xconfig::xfree::vfreqs)); + } @$resolutions; } $raw_X->set_monitors(map { @@ -465,6 +494,28 @@ sub set_load_module { } +################################################################################ +# ModulePath ################################################################### +################################################################################ +sub get_ModulePaths { + my ($raw_X) = @_; + my $raw_Files = $raw_X->get_Section('Files') or return; + my $Files = raw_export_section($raw_Files, ['ModulePath']); + @{$Files->{ModulePath} || []}; +} +sub add_ModulePath { + my ($raw_X, $ModulePath) = @_; + my $raw_Files = $raw_X->get_Section('Files') || $raw_X->add_Section('Files', {}); + + push @{$raw_Files->{ModulePath}}, { val => $ModulePath } if !member($ModulePath, $raw_X->get_ModulePaths); +} +sub remove_ModulePath { + my ($raw_X, $ModulePath) = @_; + my $raw_Files = $raw_X->get_Section('Files') or return; + my @l = grep { $_->{val} ne $ModulePath && $_->{val} ne "$ModulePath/" } @{$raw_Files->{ModulePath}}; + $raw_Files->{ModulePath} = \@l; +} + #-############################################################################## #- helpers #-############################################################################## @@ -483,7 +534,7 @@ sub get_InputDevices { } sub remove_InputDevices { my ($raw_X, $Driver) = @_; - $raw_X->remove_Section('InputDevice', sub { val($_[0]{Driver}) ne $Driver }); + $raw_X->remove_Section('InputDevice', sub { val($_[0]{Driver}) eq $Driver }); } sub get_ServerLayout { @@ -524,23 +575,25 @@ sub add_Section { my %order = map_index { { lc($_) => $::i } } @suggested_ordering; my $e = { name => $Section, l => $h }; my $added; - @$raw_X = map { + my $raw = $raw_X->{raw}; + @$raw = map { if ($order{lc $_->{name}} > $order{lc $Section} && !$added) { $added = 1; ($e, $_); } else { $_ } - } @$raw_X; - push @$raw_X, $e if !$added; + } @$raw; + push @$raw, $e if !$added; $h; } sub remove_Section { my ($raw_X, $Section, $o_when) = @_; - @$raw_X = grep { $_->{name} ne $Section || $o_when && $o_when->($_->{l}) } @$raw_X; + my $raw = $raw_X->{raw}; + @$raw = grep { $_->{name} ne $Section || $o_when && !$o_when->($_->{l}) } @$raw; $raw_X; } sub get_Sections { my ($raw_X, $Section, $o_when) = @_; - map { if_(lc($_->{name}) eq lc($Section) && (!$o_when || $o_when->($_->{l})), $_->{l}) } @$raw_X; + map { if_(lc($_->{name}) eq lc($Section) && (!$o_when || $o_when->($_->{l})), $_->{l}) } @{$raw_X->{raw}}; } sub get_Section { my ($raw_X, $Section, $o_when) = @_; @@ -564,7 +617,7 @@ sub val { sub ModeLine_from_string { my ($s) = @_; my $raw_X_for_ModeLine = Xconfig::parse::read_XF86Config_from_string($s); - get_Section($raw_X_for_ModeLine, 'Monitor')->{ModeLine}; + get_Section(Xconfig::xfree->new($raw_X_for_ModeLine), 'Monitor')->{ModeLine}; } @@ -591,7 +644,7 @@ our %ratio2resolutions = ( # 1.25 '5/4' => [ qw(640x512 720x576 1280x1024 1800x1440) ], - # SXGA=1280x1024 QSXGA=2560x2048 + # SXGA=1280x1024 QSXGA=2560x2048, HSXGA=5120x4096 # 1.33 '4/3' => [ @@ -599,21 +652,24 @@ our %ratio2resolutions = ( 1024x768 1152x864 1280x960 1400x1050 1600x1200 1920x1440 2048x1536), # 768x576 1792x1344 1856x1392 # DBLSCAN: 400x300 416x312 512x384 576x432 700x525 896x672 928x696 960x720 - ], # VGA=640x480, SVGA=800x600, XGA=1024x768, SXGA+=1400x1050, UXGA=1600x1200, QXGA=2048x1536 QSXGA+=2800x2100, QUXGA=3200x2400 + ], # VGA=640x480, SVGA=800x600, XGA=1024x768, SXGA+=1400x1050, + # UXGA=1600x1200, QXGA=2048x1536 QSXGA+=2800x2100, QUXGA=3200x2400, + # HUXGA=6400x4800 # 1.5 '3/2' => [ qw(360x240 720x480 1152x768) ], # 576x384 (DBLSCAN of 1152x768) # 1.6 - '16/10' => [ qw(1280x800 1440x900 1600x1000 1680x1050 1920x1200) ], # 320x200 640x400 960x600 2560x1600 - # WSXGA+=1680x1050, WUXGA=1920x1200, WQUXGA=3840x2400 + '16/10' => [ qw(1280x800 1440x900 1600x1000 1680x1050 1920x1200 2560x1600) ], # 320x200 640x400 960x600 3840x2400 + # WSXGA+=1680x1050, WUXGA=1920x1200, WQXGA=2560x1600, WQUXGA=3840x2400, WHUXGA=7680x4800 # 1.67 '15/9' => [ qw(1280x768) ], # 800x480 # WXGA=1280x768 or ??? (should be 1366x768) # 1.78 - '16/9' => [ qw(1280x720 1600x900 1920x1080) ], # 960x540 1024x576 + '16/9' => [ qw(1280x720 1600x900 1920x1080) ], # 960x540 1024x576 1360x765 + # UHDTV=7680x4320 # now more weird things @@ -628,7 +684,8 @@ our %ratio2resolutions = ( # '17/12' => [ qw(544x384) ] , # 1.56 - # '25/16' => [ qw(1600x1024) ], # WSXGA, (DBLSCAN 800x512) + # '25/16' => [ qw(1600x1024 3200x2048 6400x4096) ], # (DBLSCAN 800x512) + # WSXGA=1600x1024, WQSXGA=3200x2048, WHSXGA=6400x4096 # 1.707 # '128/75' => [ qw(1024x600) ], @@ -677,18 +734,16 @@ foreach my $ratio (keys %ratio2resolutions) { } our $default_header = <<'END'; -# File generated by XFdrake. - # ********************************************************************** # Refer to the xorg.conf man page for details about the format of # this file. # ********************************************************************** Section "Files" - # Multiple FontPath entries are allowed (they are concatenated together) - # By default, Mandrake 6.0 and later now use a font server independent of - # the X server to render fonts. + # font server independent of the X server to render fonts. FontPath "unix/:-1" + # minimal fonts to allow X to run without xfs + FontPath "/usr/share/fonts/misc:unscaled" EndSection Section "ServerFlags" diff --git a/lib/keyboard.pm b/lib/keyboard.pm index 5885754..e724b55 100644 --- a/lib/keyboard.pm +++ b/lib/keyboard.pm @@ -25,32 +25,36 @@ our %lang2keyboard = ( 'af' => 'us_intl', 'am' => 'us:90', - 'ar' => 'ar:90', + 'ar' => 'ara:90', 'as' => 'ben:90 ben2:80 us_intl:5', 'az' => 'az:90 tr_q:10 us_intl:5', 'az_IR' => 'ir:90', 'be' => 'by:90 ru:50 ru_yawerty:40', -# 'ber' => 'tifinagh:80 tifinagh_p:70', - 'ber' => 'tifinagh_p:90', + 'ber' => 'tifinagh:80 tifinagh_p:70', 'bg' => 'bg_phonetic:60 bg:50', 'bn' => 'ben:90 ben2:80 dev:20 us_intl:5', - 'bo' => 'dz', + 'bo' => 'bt', 'br' => 'fr:90', 'bs' => 'bs:90', 'ca' => 'es:90 fr:15', + 'ca@valencian' => 'es', 'chr' => 'chr:80 us:60 us_intl:60', 'cs' => 'cz_qwerty:70 cz:50', - 'cy' => 'uk:90', + 'cy' => 'gb:90', 'da' => 'dk:90', 'de' => 'de_nodeadkeys:70 de:50 be:50 ch_de:50', - 'dz' => 'dz', + 'dz' => 'bt', 'el' => 'gr:90', - 'en' => 'us:89 us_intl:50 qc:50 uk:50', -'en_IE' => 'ie:80 uk:70 dvorak_gb:10', -'en_US' => 'us:90 us_intl:50 dvorak:10', -'en_GB' => 'uk:89 us:60 us_intl:50 dvorak_gb:10', + 'en' => 'us:89 us3:80 us_intl:50 qc:50 gb:50 dvorak:10', +'en_AU' => 'us:80 us3:70 us_intl:50 gb:40 dvorak:10 dvorak_gb:5', +'en_CA' => 'us:80 us3:70 us_intl:50 qc:50 gb:40 dvorak:10', +'en_GB' => 'gb:89 us:60 us_intl:50 dvorak_gb:10', +'en_IE' => 'ie:80 gb:70 dvorak_gb:10', +'en_NG' => 'ng:80 us:60', +'en_NZ' => 'us:80 us3:70 us_intl:50 gb:40 dvorak:10 dvorak_gb:5', +'en_US' => 'us:90 us3:80 us_intl:50 dvorak:10', 'eo' => 'us_intl:89 dvorak_eo:30 dvorak:10', - 'es' => 'es:85 la:80 us_intl:50', + 'es' => 'es:85 lat:80 us_intl:50', 'et' => 'ee:90', 'eu' => 'es:90 fr:15', 'fa' => 'ir:90', @@ -58,12 +62,13 @@ our %lang2keyboard = 'fo' => 'fo:80 is:70 dk:60', 'fr' => 'fr:89 qc:85 be:85 ch_fr:70 dvorak_fr:20', 'fur' => 'it:90', - 'ga' => 'ie:80 uk:70 dvorak_gb:10', - 'gd' => 'uk:80 ie:70 dvorak_gb:10', + 'ga' => 'ie:80 gb:70 dvorak_gb:10', + 'gd' => 'gb:80 ie:70 dvorak_gb:10', 'gl' => 'es:90', - 'gn' => 'la:85 es:80 us_intl:50', + 'gn' => 'lat:85 es:80 us_intl:50', 'gu' => 'guj:90', - 'gv' => 'uk:80 ie:70', + 'gv' => 'gb:80 ie:70', + 'ha' => 'ng', 'he' => 'il:90 il_phonetic:10', 'hi' => 'dev:90', 'hr' => 'hr:90 si:50', @@ -71,28 +76,29 @@ our %lang2keyboard = 'hy' => 'am:90 am_old:10 am_phonetic:5', 'ia' => 'us:90 us_intl:20', 'id' => 'us:90 us_intl:20', + 'ig' => 'ng', 'is' => 'is:90', 'it' => 'it:90 ch_fr:50 ch_de:50', - 'iu' => 'iu:90', - 'ja' => 'jp:90 us:50 us_intl:20', + 'iu' => 'iku:90', + 'ja' => 'jp:90', 'ka' => 'ge_la:90 ge_ru:50', 'kl' => 'dk:80 us_intl:30', 'kn' => 'kan:90', 'ko' => 'kr:90 us:60', 'ku' => 'tr_q:90 tr_f:30', -'ku_IQ' => 'ku:90', - 'kw' => 'uk:80 ie:70', - 'ky' => 'ky:90 ru_yawerty:40', +'ku_IQ' => 'kur:90', + 'kw' => 'gb:80 ie:70', + 'ky' => 'kg:90 ru_yawerty:40', 'lb' => 'ch_fr:89 be:85 us_intl:70 fr:60 dvorak_fr:20', 'li' => 'us_intl:80 be:70 nl:10 us:5', 'lo' => 'lao:90', 'lt' => 'lt:80 lt_new:70 lt_b:60 lt_p:50', 'ltg' => 'lv:90 lt:40 lt_new:30 lt_b:20 lt_p:10 ee:5', 'lv' => 'lv:90 lt:40 lt_new:30 lt_b:20 lt_p:10 ee:5', - 'mi' => 'mao:90 uk:30 us_intl:20', + 'mi' => 'mao:90 gb:30 us_intl:20', 'mk' => 'mk:90', 'ml' => 'mal:90', - 'mn' => 'mng:90 ru:20 ru_yawerty:5', + 'mn' => 'mn:90 ru:20 ru_yawerty:5', 'mr' => 'dev:90', 'ms' => 'us:90 us_intl:20', 'mt' => 'mt:90 mt_us:35 us_intl:10', @@ -108,20 +114,21 @@ our %lang2keyboard = 'pa' => 'gur:90', 'ph' => 'us:90 us_intl:20', 'pl' => 'pl:90 pl2:60 dvorak_pl:10', - 'pp' => 'br:80 la:20 pt:10 us_intl:30', - 'ps' => 'ps:80 sd:60', -'pt_BR' => 'br:90 la:20 pt:10 us_intl:30', + 'pp' => 'br:80 lat:20 pt:10 us_intl:30', + 'ps' => 'pus:80 snd:60', +'pt_BR' => 'br:90 lat:20 pt:10 us_intl:30', 'pt' => 'pt:90', 'ro' => 'ro2:80 ro:40 us_intl:10', 'ru' => 'ru:85 ru_yawerty:80 ua:50', 'sc' => 'it:90', - 'sd' => 'sd:80 ar:20', - 'se' => 'sapmi:70 sapmi_sefi:50', + 'sd' => 'snd:80 ara:20', + 'se' => 'smi:70 smi_sefi:50', 'sh' => 'yu:80', + 'si' => 'sin', 'sk' => 'sk_qwerty:80 sk:70', 'sl' => 'si:90 hr:50', 'sq' => 'al:90', - 'sr' => 'sr:80', + 'sr' => 'srp:80', 'ss' => 'us_intl', 'st' => 'us_intl', 'sv' => 'se:90 fi:30 dvorak_se:10', @@ -129,12 +136,12 @@ our %lang2keyboard = 'te' => 'tel:90', 'tg' => 'tj:90 ru_yawerty:40', 'th' => 'th:80 th_pat:50 th_tis:60', - 'tk' => 'tk:80 tr_q:50 tr_f:40', + 'tk' => 'tm:80 tr_q:50 tr_f:40', 'tl' => 'us:90 us_intl:20', 'tr' => 'tr_q:90 tr_f:30', 'tt' => 'ru:50 ru_yawerty:40', 'uk' => 'ua:90 ru:50 ru_yawerty:40', - 'ur' => 'ur:80 sd:60 ar:20', + 'ur' => 'urd:80 snd:60 ara:20', 'uz' => 'uz:80 ru_yawerty:40', 'uz\@Cyrl' => 'uz:80 ru_yawerty:40', 'uz\@Latn' => 'us:80 uz:80', @@ -143,6 +150,7 @@ our %lang2keyboard = 'wa' => 'be:90 fr:5', 'xh' => 'us_intl', 'yi' => 'il_phonetic:90 il:10 us_intl:10', + 'yo' => 'ng', 'zh_CN' => 'us:90', 'zh_TW' => 'us:90', 'zu' => 'us_intl', @@ -155,37 +163,41 @@ our %lang2keyboard = # with different layouts printed on the keys. my @usb2keyboard = ( - qw(SKIP ar_SKIP be ca_SKIP qc cz dk fi fr de gr il hu us_intl it jp), + qw(SKIP ara_SKIP be ca_SKIP qc cz dk fi fr de gr il hu us_intl it jp), #- 0x10 - qw(kr la nl no ir pl pt ru sk es se ch_de ch_de ch_de tw_SKIP tr_q), + qw(kr lat nl no ir pl pt ru sk es se ch_fr ch_de ch_de tw_SKIP tr_q), #- 0x20 - qw(uk us_SKIP yu tr_f), + qw(gb us_SKIP yu tr_f), #- higher codes not attribued as of 2002-02 ); #- key = extension for Xmodmap file, [0] = description of the keyboard, #- [1] = name for loadkeys, [2] = name for XKB, [3] = "1" if it is #- a multigroup layout (eg: one with latin/non-latin letters) +#- +#- note: there seems to be a limit of 4 stackable xkb layouts my %keyboards = ( arch() =~ /^sparc/ ? ( +#- do we still support those? all but "se" and "us" have dissapeared from +#- symbols/sun/ directory in Xorg package. "cz" => [ N_("_: keyboard\nCzech (QWERTZ)"), "sunt5-cz-us", "cz", 0 ], "de" => [ N_("_: keyboard\nGerman"), "sunt5-de-latin1", "de", 0 ], "dvorak" => [ N_("_: keyboard\nDvorak"), "sundvorak", "dvorak",0 ], "es" => [ N_("_: keyboard\nSpanish"), "sunt5-es", "es", 0 ], "fi" => [ N_("_: keyboard\nFinnish"), "sunt5-fi-latin1", "fi", 0 ], "fr" => [ N_("_: keyboard\nFrench"), "sunt5-fr-latin1", "fr", 0 ], + "gb" => [ N_("UK keyboard"), "sunt5-uk", "gb", 0 ], "no" => [ N_("_: keyboard\nNorwegian"), "sunt4-no-latin1", "no", 0 ], "pl" => [ N_("_: keyboard\nPolish"), "sun-pl-altgraph", "pl", 0 ], "ru" => [ N_("_: keyboard\nRussian"), "sunt5-ru", "ru", 1 ], "se" => [ N_("_: keyboard\nSwedish"), "sunt5-fi-latin1", "se", 0 ], - "uk" => [ N_("UK keyboard"), "sunt5-uk", "gb", 0 ], - "us" => [ N_("US keyboard"), "sunkeymap", "us", 0 ], + "us" => [ N_("US keyboard"), "sunkeymap", "us", 0 ], ) : ( "al" => [ N_("_: keyboard\nAlbanian"), "al", "al", 0 ], "am_old" => [ N_("_: keyboard\nArmenian (old)"), "am_old", "am(old)", 1 ], "am" => [ N_("_: keyboard\nArmenian (typewriter)"), "am-armscii8", "am", 1 ], "am_phonetic" => [ N_("_: keyboard\nArmenian (phonetic)"), "am_phonetic", "am(phonetic)",1 ], - "ar" => [ N_("_: keyboard\nArabic"), "us", "ara(digits)", 1 ], + "ara" => [ N_("_: keyboard\nArabic"), "us", "ara(digits)", 1 ], "az" => [ N_("_: keyboard\nAzerbaidjani (latin)"), "az", "az", 0 ], "be" => [ N_("_: keyboard\nBelgian"), "be2-latin1", "be", 0 ], "ben" => [ N_("_: keyboard\nBengali (Inscript-layout)"), "us", "in(ben)", 1 ], @@ -193,7 +205,8 @@ arch() =~ /^sparc/ ? ( "bg_phonetic" => [ N_("_: keyboard\nBulgarian (phonetic)"), "bg", "bg(phonetic)", 1 ], "bg" => [ N_("_: keyboard\nBulgarian (BDS)"), "bg_bds", "bg", 1 ], "br" => [ N_("_: keyboard\nBrazilian (ABNT-2)"), "br-abnt2", "br", 0 ], - "bs" => [ N_("_: keyboard\nBosnian"), "croat", "ba", 0 ], + "bs" => [ N_("_: keyboard\nBosnian"), "croat", "ba", 0 ], + "bt" => [ N_("_: keyboard\nDzongkha/Tibetan"), "us", "bt", 1 ], "by" => [ N_("_: keyboard\nBelarusian"), "by-cp1251", "by", 1 ], "ch_de" => [ N_("_: keyboard\nSwiss (German layout)"), "sg-latin1", "ch(de)", 0 ], "ch_fr" => [ N_("_: keyboard\nSwiss (French layout)"), "fr_CH-latin1", "ch(fr)", 0 ], @@ -212,12 +225,12 @@ arch() =~ /^sparc/ ? ( "dvorak_no" => [ N_("_: keyboard\nDvorak (Norwegian)"), "no-dvorak", "no(dvorak)", 0 ], "dvorak_pl" => [ N_("_: keyboard\nDvorak (Polish)"), "pl-dvorak", "pl(dvorak)", 0 ], "dvorak_se" => [ N_("_: keyboard\nDvorak (Swedish)"), "se-dvorak", "se(dvorak)", 0 ], - "dz" => [ N_("_: keyboard\nDzongkha/Tibetan"), "us", "bt", 1 ], "ee" => [ N_("_: keyboard\nEstonian"), "ee-latin9", "ee", 0 ], "es" => [ N_("_: keyboard\nSpanish"), "es-latin1", "es", 0 ], "fi" => [ N_("_: keyboard\nFinnish"), "fi-latin1", "fi", 0 ], "fo" => [ N_("_: keyboard\nFaroese"), "is-latin1", "fo", 0 ], "fr" => [ N_("_: keyboard\nFrench"), "fr-latin1", "fr", 0 ], + "gb" => [ N_("UK keyboard"), "uk-latin1", "gb", 0 ], "ge_ru" => [N_("_: keyboard\nGeorgian (\"Russian\" layout)"), "ge_ru-georgian_academy", "ge(ru)",1], "ge_la" => [N_("_: keyboard\nGeorgian (\"Latin\" layout)"), "ge_la-georgian_academy", "ge(la)",1], "gr" => [ N_("_: keyboard\nGreek"), "gr-8859_7", "gr(extended)", 1 ], @@ -227,26 +240,26 @@ arch() =~ /^sparc/ ? ( "hr" => [ N_("_: keyboard\nCroatian"), "croat", "hr", 0 ], "hu" => [ N_("_: keyboard\nHungarian"), "hu-latin2", "hu", 0 ], "ie" => [ N_("_: keyboard\nIrish"), "uk-latin1", "ie", 0 ], + "iku" => [ N_("_: keyboard\nInuktitut"), "us", "ca(ike)", 1 ], "il" => [ N_("_: keyboard\nIsraeli"), "il-8859_8", "il", 1 ], "il_phonetic" => [ N_("_: keyboard\nIsraeli (phonetic)"), "hebrew", "il(phonetic)", 1 ], "ir" => [ N_("_: keyboard\nIranian"), "ir-isiri_3342", "ir", 1 ], "is" => [ N_("_: keyboard\nIcelandic"), "is-latin1", "is", 0 ], "it" => [ N_("_: keyboard\nItalian"), "it-latin1", "it", 0 ], - "iu" => [ N_("_: keyboard\nInuktitut"), "us", "ca(ike)", 1 ], # Japanese keyboard is dual latin/kana; but telling it here shows a # message to choose the switching key that is misleading, as input methods # are not automatically enabled when typing in kana - "jp" => [ N_("_: keyboard\nJapanese 106 keys"), "jp106", "us,jp", 0 ], - "kan" => [ N_("_: keyboard\nKannada"), "us", "in(kan)", 1 ], + "jp" => [ N_("_: keyboard\nJapanese 106 keys"), "jp106", "jp", 0 ], + "kan" => [ N_("_: keyboard\nKannada"), "us", "in(kan)", 1 ], + "kg" => [ N_("_: keyboard\nKyrgyz"), "ky", "kg(direct)", 1 ], # There is no XKB korean file yet; but using xmodmap one disables # some functionality; "us" used for XKB until this is fixed "kr" => [ N_("_: keyboard\nKorean"), "us", "us", 1 ], # TODO: console map - "ku" => [ N_("_: keyboard\nKurdish (arabic script)"), "us", "ku", 1 ], - "ky" => [ N_("_: keyboard\nKyrgyz"), "ky", "ky", 1 ], - "la" => [ N_("_: keyboard\nLatin American"), "la-latin1", "latam", 0 ], + "kur" => [ N_("_: keyboard\nKurdish (arabic script)"), "us", "kur", 1 ], + "lat" => [ N_("_: keyboard\nLatin American"), "la-latin1", "latam", 0 ], # TODO: console map - "lao" => [ N_("_: keyboard\nLaotian"), "us", "la", 1 ], + "lao" => [ N_("_: keyboard\nLaotian"), "us", "la", 1 ], "lt" => [ N_("_: keyboard\nLithuanian AZERTY (old)"), "lt-latin7", "lt(lt_a)", 0 ], #- TODO: write a console kbd map for lt_new "lt_new" => [ N_("_: keyboard\nLithuanian AZERTY (new)"), "lt-latin7", "lt(std)", 0 ], @@ -254,37 +267,38 @@ arch() =~ /^sparc/ ? ( "lt_p" => [ N_("_: keyboard\nLithuanian \"phonetic\" QWERTY"), "ltp-latin7", "lt(phonetic)", 0 ], "lv" => [ N_("_: keyboard\nLatvian"), "lv-latin7", "lv", 0 ], "mal" => [ N_("_: keyboard\nMalayalam"), "us", "in(mal)", 1 ], -#"mao" => [ N_("_: keyboard\nMaori"), "us", "mao", 0 ], + "mao" => [ N_("_: keyboard\nMaori"), "us", "mao", 0 ], "mk" => [ N_("_: keyboard\nMacedonian"), "mk", "mkd", 1 ], "mm" => [ N_("_: keyboard\nMyanmar (Burmese)"), "us", "mm", 1 ], - "mng" => [ N_("_: keyboard\nMongolian (cyrillic)"), "us", "mn", 1 ], + "mn" => [ N_("_: keyboard\nMongolian (cyrillic)"), "us", "mn", 1 ], "mt" => [ N_("_: keyboard\nMaltese (UK)"), "mt", "mt", 0 ], "mt_us" => [ N_("_: keyboard\nMaltese (US)"), "mt_us", "mt(us)", 0 ], + "ng" => [ N_("_: keyboard\nNigerian"), "us", "ng", 0 ], "nl" => [ N_("_: keyboard\nDutch"), "nl-latin1", "nl", 0 ], "no" => [ N_("_: keyboard\nNorwegian"), "no-latin1", "no", 0 ], "ori" => [ N_("_: keyboard\nOriya"), "us", "in(ori)", 1 ], "pl" => [ N_("_: keyboard\nPolish (qwerty layout)"), "pl", "pl", 0 ], "pl2" => [ N_("_: keyboard\nPolish (qwertz layout)"), "pl-latin2", "pl(qwertz)", 0 ], # TODO: console map - "ps" => [ N_("_: keyboard\nPashto"), "us", "ps", 1 ], + "pus" => [ N_("_: keyboard\nPashto"), "us", "pus", 1 ], "pt" => [ N_("_: keyboard\nPortuguese"), "pt-latin1", "pt", 0 ], "qc" => [ N_("_: keyboard\nCanadian (Quebec)"), "qc-latin1", "ca", 0 ], "ro2" => [ N_("_: keyboard\nRomanian (qwertz)"), "ro2", "ro", 0 ], "ro" => [ N_("_: keyboard\nRomanian (qwerty)"), "ro", "ro(us)", 0 ], "ru" => [ N_("_: keyboard\nRussian"), "ru4", "ru(winkeys)", 1 ], "ru_yawerty" => [ N_("_: keyboard\nRussian (phonetic)"), "ru-yawerty", "ru(phonetic)", 1 ], - "sapmi" => [ N_("_: keyboard\nSaami (norwegian)"), "no-latin1", "no(smi)", 0 ], - "sapmi_sefi" => [ N_("_: keyboard\nSaami (swedish/finnish)"), "se-latin1", "se(smi)", 0 ], -# TODO: console map - "sd" => [ N_("_: keyboard\nSindhi"), "us", "sd(digits)", 1 ], "se" => [ N_("_: keyboard\nSwedish"), "se-latin1", "se", 0 ], "si" => [ N_("_: keyboard\nSlovenian"), "slovene", "si", 0 ], # TODO: console map "sin" => [ N_("_: keyboard\nSinhala"), "us", "lk", 1 ], "sk" => [ N_("_: keyboard\nSlovakian (QWERTZ)"), "sk-qwertz", "sk", 0 ], "sk_qwerty" => [ N_("_: keyboard\nSlovakian (QWERTY)"), "sk-qwerty", "sk(qwerty)", 0 ], + "smi" => [ N_("_: keyboard\nSaami (norwegian)"), "no-latin1", "no(smi)", 0 ], + "smi_sefi" => [ N_("_: keyboard\nSaami (swedish/finnish)"), "se-latin1", "se(smi)", 0 ], +# TODO: console map + "snd" => [ N_("_: keyboard\nSindhi"), "us", "snd(digits)", 1 ], # TODO: console map - "sr" => [ N_("_: keyboard\nSerbian (cyrillic)"), "sr", "srp(basic),srp(latin)", 1 ], + "srp" => [ N_("_: keyboard\nSerbian (cyrillic)"), "sr", "srp(basic),srp(latin)", 1 ], "syr" => [ N_("_: keyboard\nSyriac"), "us", "sy(syc)", 1 ], "syr_p" => [ N_("_: keyboard\nSyriac (phonetic)"), "us", "sy(syc_phonetic)", 1 ], "tel" => [ N_("_: keyboard\nTelugu"), "us", "in(tel)", 1 ], @@ -299,18 +313,18 @@ arch() =~ /^sparc/ ? ( "tifinagh" => [ N_("_: keyboard\nTifinagh (moroccan layout) (+latin/arabic)"), "fr-tifinagh", "fr,tifinagh(basic),ara(azerty)", 1 ], "tifinagh_p" => [ N_("_: keyboard\nTifinagh (phonetic) (+latin/arabic)"), "fr-tifinaghp", "fr,tifinagh(phonetic),ara(azerty)", 1 ], # TODO: console map - "tj" => [ N_("_: keyboard\nTajik"), "ru4", "tj", 1 ], + "tj" => [ N_("_: keyboard\nTajik"), "ru4", "tj", 1 ], # TODO: console map - "tk" => [ N_("_: keyboard\nTurkmen"), "us", "tk", 0 ], + "tm" => [ N_("_: keyboard\nTurkmen"), "us", "tm", 0 ], "tr_f" => [ N_("_: keyboard\nTurkish (traditional \"F\" model)"), "trf", "tr(f)", 0 ], "tr_q" => [ N_("_: keyboard\nTurkish (modern \"Q\" model)"), "tr_q-latin5", "tr", 0 ], #-"tw => [ N_("_: keyboard\nChineses bopomofo"), "tw", "tw", 1 ], "ua" => [ N_("_: keyboard\nUkrainian"), "ua", "ua", 1 ], - "uk" => [ N_("UK keyboard"), "uk-latin1", "gb", 0 ], # TODO: console map - "ur" => [ N_("_: keyboard\nUrdu keyboard"), "us", "ur", 1 ], + "urd" => [ N_("_: keyboard\nUrdu keyboard"), "us", "urd", 1 ], "us" => [ N_("US keyboard"), "us", "us", 0 ], "us_intl" => [ N_("US keyboard (international)"), "us-intl", "us(alt-intl)", 0 ], + "us3" => [ N_("ISO9995-3 (US keyboard with 3 levels per key)"), "us", "latin+level3(ralt_switch)", 0 ], "uz" => [ N_("_: keyboard\nUzbek (cyrillic)"), "uz", "uz", 1 ], # old XKB layout "vn" => [ N_("_: keyboard\nVietnamese \"numeric row\" QWERTY"), "vn-tcvn", "vn", 0 ], @@ -391,7 +405,7 @@ key to switch between the different keyboard layouts."))); sub loadkeys_files { my ($err) = @_; - my $archkbd = arch() =~ /^sparc/ ? "sun" : arch() =~ /i.86/ ? "i386" : arch() =~ /ppc/ ? "mac" : arch(); + my $archkbd = arch() =~ /^sparc/ ? "sun" : arch() =~ /i.86|x86_64/ ? "i386" : arch() =~ /ppc/ ? "mac" : arch(); my $p = "/usr/lib/kbd/keymaps/$archkbd"; my $post = ".kmap.gz"; my %trans = ("cz-latin2" => "cz-lat2"); @@ -495,7 +509,7 @@ sub builtin_loadkeys { sub parse_xkb_rules() { my $cat; my %l; - my $lst_file = "$::prefix/usr/X11R6/lib/X11/xkb/rules/xorg.lst"; + my $lst_file = "$::prefix/usr/share/X11/xkb/rules/xorg.lst"; foreach (cat_($lst_file)) { next if m!^\s*//! || m!^\s*$!; chomp; @@ -547,7 +561,7 @@ sub setxkbmap { sub setup_install { my ($keyboard) = @_; - return if arch() =~ /^sparc/; + return if arch() =~ /^sparc/ || $::local_install; #- Xpmac does not map keys quite right if (arch() =~ /ppc/ && !$::testing && $ENV{DISPLAY}) { @@ -569,7 +583,7 @@ sub setup_install { log::l("ERROR: can not load keymap"); } - if (-x "/usr/X11R6/bin/setxkbmap") { + if (-x "/usr/bin/setxkbmap") { setxkbmap($keyboard); } else { my $f = xmodmap_file($keyboard); @@ -603,8 +617,7 @@ sub configure_xorg { my ($keyboard) = @_; require Xconfig::default; - my $xfree_conf = Xconfig::xfree->read; - if (!is_empty_array_ref($xfree_conf)) { + if (my $xfree_conf = Xconfig::xfree->read) { Xconfig::default::config_keyboard($xfree_conf, $keyboard); $xfree_conf->write; } diff --git a/lib/mouse.pm b/lib/mouse.pm index e991514..7f8e056 100644 --- a/lib/mouse.pm +++ b/lib/mouse.pm @@ -15,7 +15,7 @@ use modules; use any; use log; -my @mouses_fields = qw(nbuttons MOUSETYPE XMOUSETYPE name EMULATEWHEEL); +my @mouses_fields = qw(nbuttons MOUSETYPE Protocol name EmulateWheel); my %mice = arch() =~ /^sparc/ ? @@ -32,9 +32,7 @@ my %mice = [ 5, 'ps/2', 'MouseManPlusPS/2', N_("Logitech MouseMan+") ], [ 5, 'imps2', 'IMPS/2', N_("Generic PS2 Wheel Mouse") ], [ 5, 'ps/2', 'GlidePointPS/2', N_("GlidePoint") ], - if_(c::kernel_version() !~ /^\Q2.6/, - [ 5, 'imps2', 'auto', N_("Automatic") ] - ), + [ 5, 'imps2', 'auto', N_("Automatic") ], '', [ 5, 'ps/2', 'ThinkingMousePS/2', N_("Kensington Thinking Mouse") ], [ 5, 'netmouse', 'NetMousePS/2', N_("Genius NetMouse") ], @@ -43,12 +41,12 @@ my %mice = ] ], 'USB' => - [ [ 'usbmouse' ], - [ [ 1, 'ps/2', 'IMPS/2', N_("1 button") ], - [ 2, 'ps/2', 'IMPS/2', N_("Generic 2 Button Mouse") ], - [ 3, 'ps/2', 'IMPS/2', N_("Generic") ], - [ 3, 'ps/2', 'IMPS/2', N_("Generic 3 Button Mouse with Wheel emulation"), 'wheel' ], - [ 5, 'ps/2', 'IMPS/2', N_("Wheel") ], + [ [ 'input/mice' ], + [ [ 1, 'ps/2', 'ExplorerPS/2', N_("1 button") ], + [ 2, 'ps/2', 'ExplorerPS/2', N_("Generic 2 Button Mouse") ], + [ 3, 'ps/2', 'ExplorerPS/2', N_("Generic") ], + [ 3, 'ps/2', 'ExplorerPS/2', N_("Generic 3 Button Mouse with Wheel emulation"), 'wheel' ], + [ 5, 'ps/2', 'ExplorerPS/2', N_("Wheel") ], [ 7, 'ps/2', 'ExplorerPS/2', N_("Microsoft Explorer") ], ] ], @@ -82,13 +80,11 @@ my %mice = [ 3, 'Busmouse', 'BusMouse', N_("3 buttons with Wheel emulation"), 'wheel' ], ] ], - if_(c::kernel_version() =~ /^\Q2.6/, N_("Universal") => [ [ 'input/mice' ], [ [ 7, 'ps/2', 'ExplorerPS/2', N_("Any PS/2 & USB mice") ], if_(detect_devices::is_xbox(), [ 5, 'ps/2', 'IMPS/2', N_("Microsoft Xbox Controller S") ]), ] ], - ), N_("none") => [ [ 'none' ], @@ -96,6 +92,26 @@ my %mice = ] ], ); +#- Logitech MX700 +#- +#- I: Bus=0003 Vendor=046d Product=c506 Version=1600 +#- N: Name="Logitech USB Receiver" +#- P: Phys=usb-0000:00:11.3-2/input0 +#- S: Sysfs=/class/input/input5 +#- H: Handlers=mouse2 ts2 event3 +#- B: EV=7 +#- B: KEY=ffff0000 0 0 0 0 0 0 0 0 +#- B: REL=103 +#- +#- T: Bus=05 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 4 Spd=1.5 MxCh= 0 +#- D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +#- P: Vendor=046d ProdID=c506 Rev=16.00 +#- S: Manufacturer=Logitech +#- S: Product=USB Receiver +#- C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 50mA +#- I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid +#- E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=10ms + sub xmouse2xId { #- xmousetypes must be sorted as found in /usr/include/X11/extensions/xf86misc.h @@ -154,7 +170,7 @@ sub raw2mouse { $raw or return; my %l; @l{@mouses_fields} = @$raw; - +{ %l, type => $type }; + +{ %l, type => $type, if_($l{nbuttons} < 3, Emulate3Buttons => 1) }; } sub fullnames() { @@ -175,17 +191,16 @@ sub fullnames() { sub fullname2mouse { my ($fname, %opts) = @_; my ($type, @l) = split '\|', $fname; - my $name = pop @l; - search: - $opts{device} ||= $mice{$type}[0][0]; + my $name = pop @l; #- ensure we get rid of "[Other]" + + if (my @devices = @{$mice{$type}[0]}) { + member($opts{device}, @devices) or delete $opts{device}; + $opts{device} ||= $devices[0]; + } foreach (@{$mice{$type}[1]}) { my $l = raw2mouse($type, $_); $name eq $l->{name} and return { %$l, %opts }; } - if ($name eq '1 Button' || $name eq '1 button') { - $name = "Generic 2 Button Mouse"; - goto search; - } die "$fname not found ($type, $name)"; } @@ -196,24 +211,17 @@ sub serial_port2text { sub read() { my %mouse = getVarsFromSh "$::prefix/etc/sysconfig/mouse"; - eval { add2hash_(\%mouse, fullname2mouse($mouse{FULLNAME})) }; - $mouse{nbuttons} ||= $mouse{XEMU3} eq "yes" ? 2 : $mouse{WHEEL} eq "yes" ? 5 : 3; - \%mouse; + eval { fullname2mouse($mouse{FULLNAME}, device => $mouse{device}) } || \%mouse; } sub write { my ($do_pkgs, $mouse) = @_; - local $mouse->{FULLNAME} = qq("$mouse->{type}|$mouse->{name}"); #-" - local $mouse->{XEMU3} = bool2yesno($mouse->{nbuttons} < 3); - local $mouse->{WHEEL} = bool2yesno($mouse->{nbuttons} > 3); - setVarsInSh("$::prefix/etc/sysconfig/mouse", $mouse, qw(MOUSETYPE XMOUSETYPE FULLNAME XEMU3 WHEEL device)); - any::devfssymlinkf($mouse, 'mouse'); - - #- we should be using input/mice directly instead of usbmouse, but legacy... - symlinkf 'input/mice', "$::prefix/dev/usbmouse" if $mouse->{device} eq "usbmouse"; - - any::devfssymlinkf($mouse->{auxmouse}, 'mouse1') if $mouse->{auxmouse}; + setVarsInSh("$::prefix/etc/sysconfig/mouse", { + device => $mouse->{device}, + MOUSETYPE => $mouse->{MOUSETYPE}, + FULLNAME => qq($mouse->{type}|$mouse->{name}), + }); various_xfree_conf($do_pkgs, $mouse); @@ -230,10 +238,7 @@ sub write { } } -sub probe_wacom_devices { - my ($modules_conf) = @_; - - $modules_conf->get_probeall("usb-interface") or return; +sub probe_usb_wacom_devices() { my (@l) = detect_devices::usbWacom() or return; log::l("found usb wacom $_->{driver} $_->{description} ($_->{type})") foreach @l; @@ -257,12 +262,12 @@ sub detect_serial() { if ($t->{CLASS} eq 'MOUSE') { $t->{MFG} ||= $t->{MANUFACTURER}; - $mouse = fullname2mouse("serial|Microsoft IntelliMouse") if $t->{MFG} eq 'MSH' && $t->{MODEL} eq '0001'; - $mouse = fullname2mouse("serial|Logitech MouseMan") if $t->{MFG} eq 'LGI' && $t->{MODEL} =~ /^80/; - $mouse = fullname2mouse("serial|Genius NetMouse") if $t->{MFG} eq 'KYE' && $t->{MODEL} eq '0003'; + my $name = 'Generic 2 Button Mouse'; + $name = 'Microsoft IntelliMouse' if $t->{MFG} eq 'MSH' && $t->{MODEL} eq '0001'; + $name = 'Logitech MouseMan' if $t->{MFG} eq 'LGI' && $t->{MODEL} =~ /^80/; + $name = 'Genius NetMouse' if $t->{MFG} eq 'KYE' && $t->{MODEL} eq '0003'; - $mouse ||= fullname2mouse("serial|Generic 2 Button Mouse"); #- generic by default. - $mouse->{device} = "ttyS$_"; + $mouse ||= fullname2mouse("serial|$name", device => "ttyS$_"); last; } elsif ($t->{CLASS} eq "PEN" || $t->{MANUFACTURER} eq "WAC") { push @wacom, "ttyS$_"; @@ -271,120 +276,116 @@ sub detect_serial() { $mouse, @wacom; } +sub detect_evdev_mice { + my (@mice) = @_; + + my $imwheel; + foreach (@mice) { + my @l = $_->{usb} && $_->{usb}{driver} =~ /^Mouse:(.*)/ ? split('\|', $1) : (); + foreach my $opt (@l) { + if ($opt eq 'evdev') { + $_->{want_evdev} = 1; + } elsif ($opt =~ /imwheel:(.*)/) { + $imwheel = $1; + } + } + if ($_->{HWHEEL}) { + $_->{want_evdev} = 1; + } elsif ($_->{SIDE}) { + $imwheel ||= 'generic'; + } + } + + my @evdev_mice = map { + #- we always use HWheelRelativeAxisButtons for evdev, it tells mice with no horizontal wheel to skip those buttons + #- that way we ensure 6 & 7 is always horizontal wheel + #- (cf patch skip-HWheelRelativeAxisButtons-even-if-unused in x11-driver-input-evdev) + { vendor => "0x$_->{vendor}", product => "0x$_->{id}", HWheelRelativeAxisButtons => "7 6" }; + } grep { $_->{want_evdev} } @mice; + + log::l("configuring mice with imwheel for thumb buttons (imwheel=$imwheel)") if $imwheel; + log::l("configuring mice for evdev (" . join(' ', map { "$_->{vendor}:$_->{product}" } @evdev_mice) . ")") if @evdev_mice; + + { imwheel => $imwheel, if_(@evdev_mice, evdev_mice => \@evdev_mice) }; +} + sub detect { my ($modules_conf) = @_; # let more USB tablets and touchscreens magically work at install time # through /dev/input/mice multiplexing: - modules::probe_category('input/tablet'); - modules::probe_category('input/touchscreen'); - - if (arch() =~ /^sparc/) { - return fullname2mouse("sunmouse|Sun - Mouse"); - } - if (arch() eq "ppc") { - return fullname2mouse(detect_devices::hasMousePS2("usbmouse") ? - "USB|1 button" : - # No need to search for an ADB mouse. If I did, the PPC kernel would - # find one whether or not I had one installed! So.. default to it. - "busmouse|1 button"); - } - - my @wacom = probe_wacom_devices($modules_conf); - - if (c::kernel_version() =~ /^\Q2.6/) { - $modules_conf->get_probeall("usb-interface") and eval { modules::load('usbhid') }; - if (cat_('/proc/bus/input/devices') =~ /^H: Handlers=mouse/m) { - if (detect_devices::is_xbox()) { - return fullname2mouse('Universal|Microsoft Xbox Controller S'); - } - my $univ_mouse = fullname2mouse('Universal|Any PS/2 & USB mice', wacom => \@wacom); - if (my ($synaptics_touchpad) = detect_devices::getSynapticsTouchpads()) { - $univ_mouse->{auxmouse} = { - name => N_("Synaptics Touchpad"), - device => 'input/mice', - XMOUSETYPE => 'auto-dev', - ALPS => $synaptics_touchpad->{description} =~ /ALPS/, - }; - } - return $univ_mouse; - } + detect_devices::probe_category('input/tablet'); + detect_devices::probe_category('input/touchscreen'); + + my @wacom = probe_usb_wacom_devices(); + + $modules_conf->get_probeall("usb-interface") and eval { modules::load('usbhid') }; + if (my @mice = grep { $_->{driver} =~ /^mouse/ } detect_devices::getInputDevices_and_usb()) { + my @synaptics = map { + { ALPS => $_->{ALPS} }; + } grep { $_->{Synaptics} || $_->{ALPS} } @mice; + + my $evdev_opts = detect_evdev_mice(@mice); + + my $fullname = detect_devices::is_xbox() ? + 'Universal|Microsoft Xbox Controller S' : + arch() eq "ppc" ? + 'USB|1 button' : + 'Universal|Any PS/2 & USB mice'; + + fullname2mouse($fullname, wacom => \@wacom, + synaptics => $synaptics[0], + if_($evdev_opts, %$evdev_opts)); + } elsif (arch() eq 'ppc') { + # No need to search for an ADB mouse. If I did, the PPC kernel would + # find one whether or not I had one installed! So.. default to it. + fullname2mouse("busmouse|1 button"); + } elsif (arch() =~ /^sparc/) { + fullname2mouse("sunmouse|Sun - Mouse"); } else { - my $ps2_mouse = detect_devices::hasMousePS2("psaux") && fullname2mouse("PS/2|Automatic", unsafe => 0); - - #- workaround for some special case were mouse is openable 1/2. - if (!$ps2_mouse) { - $ps2_mouse = detect_devices::hasMousePS2("psaux") && fullname2mouse("PS/2|Automatic", unsafe => 0); - $ps2_mouse and detect_devices::hasMousePS2("psaux"); #- fake another open in order for XFree to see the mouse. - } - - if ($modules_conf->get_probeall("usb-interface")) { - sleep 2; - if (my (@l) = detect_devices::usbMice()) { - log::l(join('', "found usb mouse $_->{driver} $_->{description} (", if_($_->{type}, $_->{type}), ")")) foreach @l; - if (eval { modules::load(qw(hid mousedev usbmouse)); detect_devices::tryOpen("usbmouse") }) { - return fullname2mouse($l[0]{driver} =~ /Mouse:(.*)/ ? $1 : "USB|Wheel", - if_($ps2_mouse, auxmouse => $ps2_mouse), #- for laptop, we kept the PS/2 as secondary (symbolic). - wacom => \@wacom); - - } - eval { modules::unload(qw(usbmouse mousedev hid)) }; - } + #- probe serial device to make sure a wacom has been detected. + eval { modules::load("serial") }; + my ($serial_mouse, @serial_wacom) = detect_serial(); + push @wacom, @serial_wacom; + if ($serial_mouse) { + { wacom => \@wacom, %$serial_mouse }; + } elsif (@wacom) { + #- in case only a wacom has been found, assume an inexistant mouse (necessary). + fullname2mouse('none|No mouse', wacom => \@wacom); } else { - log::l("no usb interface found for mice"); - } - if ($ps2_mouse) { - return { wacom => \@wacom, %$ps2_mouse }; + fullname2mouse('Universal|Any PS/2 & USB mice', unsafe => 1); } } - - #- probe serial device to make sure a wacom has been detected. - eval { modules::load("serial") }; - my ($serial_mouse, @serial_wacom) = detect_serial(); push @wacom, @serial_wacom; - if ($serial_mouse) { - { wacom => \@wacom, %$serial_mouse }; - } elsif (@wacom) { - #- in case only a wacom has been found, assume an inexistant mouse (necessary). - fullname2mouse('none|No mouse', wacom => \@wacom); - } elsif (c::kernel_version() =~ /^\Q2.6/) { - fullname2mouse('Universal|Any PS/2 & USB mice', unsafe => 1); - } else { - fullname2mouse("PS/2|Automatic", unsafe => 1); - } } sub load_modules { my ($mouse) = @_; my @l; - for ($mouse->{type}) { - /serial/ and @l = qw(serial); - /USB/ and @l = qw(hid mousedev usbmouse); - } - foreach (@{$mouse->{wacom}}) { - /ttyS/ and push @l, qw(serial); - /event/ and push @l, qw(wacom evdev); - } - if ($mouse->{auxmouse} && $mouse->{auxmouse}{name} eq N_("Synaptics Touchpad")) { - push @l, qw(evdev); - } + push @l, qw(hid mousedev usbmouse) if $mouse->{type} =~ /USB/; + push @l, qw(serial) if $mouse->{type} =~ /serial/ || any { /ttyS/ } @{$mouse->{wacom}}; + push @l, qw(wacom evdev) if any { /event/ } @{$mouse->{wacom}}; + push @l, qw(evdev) if $mouse->{synaptics} || $mouse->{evdev_mice}; + eval { modules::load(@l) }; } sub set_xfree_conf { my ($mouse, $xfree_conf, $b_keep_auxmouse_unchanged) = @_; - my ($synaptics, $mouse_) = partition { $_->{name} eq N_("Synaptics Touchpad") } ($mouse, if_($mouse->{auxmouse}, $mouse->{auxmouse})); my @mice = map { { - Protocol => $_->{XMOUSETYPE}, + Protocol => $_->{Protocol}, Device => "/dev/mouse", - if_($_->{nbuttons} > 3, ZAxisMapping => [ $_->{nbuttons} > 5 ? '6 7' : '4 5' ]), - if_($_->{nbuttons} < 3, Emulate3Buttons => undef, Emulate3Timeout => 50), - if_($_->{EMULATEWHEEL}, Emulate3Buttons => undef, Emulate3Timeout => 50, EmulateWheel => undef, EmulateWheelButton => 2), + if_($_->{Emulate3Buttons} || $_->{EmulateWheel}, Emulate3Buttons => undef, Emulate3Timeout => 50), + if_($_->{EmulateWheel}, EmulateWheel => undef, EmulateWheelButton => 2), }; - } @$mouse_; + } $mouse; + + devices::symlink_now_and_register($mouse, 'mouse'); - if (!$mouse->{auxmouse} && $b_keep_auxmouse_unchanged) { + if ($mouse->{evdev_mice}) { + push @mice, @{$mouse->{evdev_mice}}; + } elsif (!$mouse->{synaptics} && $b_keep_auxmouse_unchanged) { my (undef, @l) = $xfree_conf->get_mice; push @mice, @l; } @@ -395,34 +396,17 @@ sub set_xfree_conf { $xfree_conf->set_wacoms(map { { Device => "/dev/$_", USB => m|input/event| } } @wacoms); } - $synaptics and $xfree_conf->set_synaptics(map { { - Device => "/dev/$_->{device}", - Protocol => $_->{XMOUSETYPE}, + $xfree_conf->set_synaptics({ Primary => 0, - ALPS => $_->{ALPS}, - } } @$synaptics); + ALPS => $mouse->{synaptics}{ALPS}, + }) if $mouse->{synaptics}; } sub various_xfree_conf { my ($do_pkgs, $mouse) = @_; - { - my $f = "$::prefix/etc/X11/xinit.d/mouse_buttons"; - if ($mouse->{nbuttons} <= 5) { - unlink($f); - } else { - output_with_perm($f, 0755, "xmodmap -e 'pointer = 1 2 3 6 7 4 5'\n"); - } - } - { - my $f = "$::prefix/etc/X11/xinit.d/auxmouse_buttons"; - if (!$mouse->{auxmouse} || $mouse->{auxmouse}{nbuttons} <= 5) { - unlink($f); - } else { - $do_pkgs->install('xinput'); - output_with_perm($f, 0755, "xinput set-button-map Mouse2 1 2 3 6 7 4 5\n"); - } - } + #- we don't need this anymore. Remove it for upgrades + unlink("$::prefix/etc/X11/xinit.d/mouse_buttons"); { my $f = "$::prefix/etc/X11/xinit.d/xpad"; if ($mouse->{name} !~ /^Microsoft Xbox Controller/) { @@ -432,8 +416,20 @@ sub various_xfree_conf { } } - if (member(N_("Synaptics Touchpad"), $mouse->{name}, $mouse->{auxmouse} && $mouse->{auxmouse}{name})) { - $do_pkgs->install("synaptics"); + my @pkgs = ( + if_($mouse->{synaptics}, 'synaptics'), + if_($mouse->{evdev_mice}, 'x11-driver-input-evdev'), + if_($mouse->{imwheel}, 'imwheel'), + if_(@{$mouse->{wacom}}, 'linuxwacom'), + ); + $do_pkgs->install(@pkgs) if @pkgs; + + if ($mouse->{imwheel}) { + my $rc = "/etc/X11/imwheel/imwheelrc.$mouse->{imwheel}"; + eval { setVarsInSh("$::prefix/etc/X11/imwheel/startup.conf", { + IMWHEEL_START => 1, + IMWHEEL_PARAMS => join(' ', '-k', if_(-e "$::prefix$rc", '--rc', $rc)), + }) }; } } @@ -443,16 +439,15 @@ sub various_xfree_conf { #- $mouse input #- $mouse->{nbuttons} : number of buttons : integer #- $mouse->{device} : device of the mouse : string : ex 'psaux' -#- $mouse->{XMOUSETYPE} : type of the mouse for gpm : string : ex 'PS/2' +#- $mouse->{Protocol} : type of the mouse for X : string (eg 'PS/2') #- $mouse->{type} : type (generic ?) of the mouse : string : ex 'PS/2' #- $mouse->{name} : name of the mouse : string : ex 'Standard' #- $mouse->{MOUSETYPE} : type of the mouse : string : ex "ps/2" -#- $mouse->{XEMU3} : emulate 3rd button : string : 'yes' or 'no' sub write_conf { my ($do_pkgs, $modules_conf, $mouse, $b_keep_auxmouse_unchanged) = @_; &write($do_pkgs, $mouse); - $modules_conf->write if $mouse->{device} eq "usbmouse" && !$::testing; + $modules_conf->write if $mouse->{device} eq "input/mice" && !$::testing; eval { require Xconfig::xfree; @@ -465,10 +460,10 @@ sub write_conf { sub change_mouse_live { my ($mouse, $old) = @_; - my $xId = xmouse2xId($mouse->{XMOUSETYPE}); - $old->{device} ne $mouse->{device} || $xId != xmouse2xId($old->{XMOUSETYPE}) or return; + my $xId = xmouse2xId($mouse->{Protocol}); + $old->{device} ne $mouse->{device} || $xId != xmouse2xId($old->{Protocol}) or return; - log::l("telling X server to use another mouse ($mouse->{XMOUSETYPE}, $xId)"); + log::l("telling X server to use another mouse ($mouse->{Protocol}, $xId)"); eval { modules::load('serial') } if $mouse->{device} =~ /ttyS/; if (!$::testing) { @@ -476,7 +471,7 @@ sub change_mouse_live { symlinkf($mouse->{device}, "/dev/mouse"); eval { require xf86misc::main; - xf86misc::main::setMouseLive($ENV{DISPLAY}, $xId, $mouse->{nbuttons} < 3); + xf86misc::main::setMouseLive($ENV{DISPLAY}, $xId, $mouse->{Emulate3Buttons}); }; } 1; @@ -486,13 +481,13 @@ sub test_mouse_install { my ($mouse, $x_protocol_changed) = @_; require ugtk2; ugtk2->import(qw(:wrappers :create)); - my $w = ugtk2->new('', disallow_big_help => 1); + my $w = ugtk2->new(N("Testing the mouse"), disallow_big_help => 1); my $darea = Gtk2::DrawingArea->new; $darea->set_events([ 'button_press_mask', 'button_release_mask' ]); #$darea must be unrealized. gtkadd($w->{window}, gtkpack(my $vbox_grab = Gtk2::VBox->new(0, 0), $darea, - gtkset_sensitive(create_okcancel($w, undef, undef, 'edge'), 1) + gtkset_sensitive(create_okcancel($w, undef, '', 'edge'), 1) ), ); test_mouse($mouse, $darea, $x_protocol_changed); @@ -513,6 +508,48 @@ sub test_mouse_standalone { test_mouse($mouse, $darea); } +sub select { + my ($in, $mouse) = @_; + + my $prev = my $fullname = $mouse->{type} . '|' . $mouse->{name}; + + $in->ask_from_({ messages => N("Please choose your type of mouse."), + title => N("Mouse choice"), + interactive_help_id => 'selectMouse', + if_($mouse->{unsafe}, cancel => ''), + }, + [ { list => [ fullnames() ], separator => '|', val => \$fullname, + format => sub { join('|', map { translate($_) } split('\|', $_[0])) } } ]) or return; + + if ($fullname ne $prev) { + my $mouse_ = fullname2mouse($fullname, device => $mouse->{device}); + %$mouse = %$mouse_; + } + + if ($mouse->{nbuttons} < 3 && $::isStandalone) { + $mouse->{Emulate3Buttons} = $in->ask_yesorno('', N("Emulate third button?"), 1); + } + + if ($mouse->{type} eq 'serial') { + $in->ask_from_({ title => N("Mouse Port"), + messages => N("Please choose which serial port your mouse is connected to."), + interactive_help_id => 'selectSerialPort', + }, [ { list => [ serial_ports() ], format => \&serial_port2text, val => \$mouse->{device} } ]) or return &select; + } + + if (arch() =~ /ppc/ && $mouse->{nbuttons} == 1) { + #- set a sane default F11/F12 + $mouse->{button2_key} = 87; + $mouse->{button3_key} = 88; + $in->ask_from('', N("Buttons emulation"), + [ + { label => N("Button 2 Emulation"), val => \$mouse->{button2_key}, list => [ ppc_one_button_keys() ], format => \&ppc_one_button_key2text }, + { label => N("Button 3 Emulation"), val => \$mouse->{button3_key}, list => [ ppc_one_button_keys() ], format => \&ppc_one_button_key2text }, + ]) or return; + } + 1; +} + sub test_mouse { my ($mouse, $darea, $b_x_protocol_changed) = @_; @@ -530,7 +567,7 @@ sub test_mouse { down => 'arrow_down'); my %images = map { $_ => ugtk2::gtkcreate_pixbuf("$image_files{$_}.png") } keys %image_files; my $width = $images{mouse}->get_width; - my $height = round_up(min($images{mouse}->get_height, $::windowheight - 150), 6); + my $height = round_up($images{mouse}->get_height, 6); my $draw_text = sub { my ($t, $y) = @_; @@ -559,7 +596,7 @@ sub test_mouse { $draw_by_name->('mouse'); if ($::isInstall || 1) { $draw_text->(N("Please test the mouse"), 200); - if ($b_x_protocol_changed && $mouse->{nbuttons} > 3 && $mouse->{device} eq 'psaux' && member($mouse->{XMOUSETYPE}, 'IMPS/2', 'ExplorerPS/2')) { + if ($b_x_protocol_changed && $mouse->{nbuttons} > 3 && $mouse->{device} eq 'psaux' && member($mouse->{Protocol}, 'IMPS/2', 'ExplorerPS/2')) { $draw_text->(N("To activate the mouse,"), 240); $draw_text->(N("MOVE YOUR WHEEL!"), 260); } @@ -622,7 +659,7 @@ C is a perl module used by mousedrake to detect and configure the mouse. =head1 COPYRIGHT -Copyright (C) 2000-2002 Mandriva +Copyright (C) 2000-2006 Mandriva This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/xf86misc/.cvsignore b/lib/xf86misc/.cvsignore deleted file mode 100644 index 83a662f..0000000 --- a/lib/xf86misc/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -main.bs -main.c -pm_to_blib -blib -Makefile_c diff --git a/lib/xf86misc/Makefile b/lib/xf86misc/Makefile index 2d874b9..a645f67 100644 --- a/lib/xf86misc/Makefile +++ b/lib/xf86misc/Makefile @@ -3,7 +3,7 @@ main: %: %.xs test -e Makefile_c || perl Makefile.PL $(MAKE) -f Makefile_c LD_RUN_PATH= || $(MAKE) -f Makefile_c LD_RUN_PATH= - rm -f ../auto/xf86misc ; ln -s ../xf86misc/blib/arch/auto ../auto/xf86misc + rm -f ../../auto/xf86misc ; ln -s ../lib/xf86misc/blib/arch/auto ../../auto/xf86misc clean: test ! -e Makefile_c || $(MAKE) -f Makefile_c clean -- cgit v1.2.1