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 +++++++++++++++--------- 9 files changed, 895 insertions(+), 391 deletions(-) create mode 100644 lib/Xconfig/plugins.pm (limited to 'lib/Xconfig') 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" -- cgit v1.2.1