package Xconfigurator; # $Id$ use diagnostics; use strict; use vars qw($in $do_pkgs); use common; use log; use detect_devices; use run_program; use Xconfigurator_consts; use Xconfig; use any; use modules; my $tmpconfig = "/tmp/Xconfig"; my ($prefix); sub xtest { my ($display) = @_; $::isStandalone ? system("DISPLAY=$display /usr/X11R6/bin/xtest") == 0 : c::Xtest($display); } sub readCardsNames { my $file = "$ENV{SHARE_PATH}/ldetect-lst/CardsNames"; map { (split '=>')[0] } grep { !/^#/ } catMaybeCompressed($file); } sub cardName2RealName { my ($name) = @_; my $file = "$ENV{SHARE_PATH}/ldetect-lst/CardsNames"; foreach (catMaybeCompressed($file)) { chop; next if /^#/; my ($name_, $real) = split '=>'; return $real if $name eq $name_; } $name; } sub realName2CardName { my ($real) = @_; my $file = "$ENV{SHARE_PATH}/ldetect-lst/CardsNames"; foreach (catMaybeCompressed($file)) { chop; next if /^#/; my ($name, $real_) = split '=>'; return $name if $real eq $real_; } return; } sub updateCardAccordingName { my ($card, $name) = @_; my $cards = Xconfig::readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+"); Xconfig::add2card($card, $cards->{$name}); $card; } sub readMonitorsDB { my ($file) = @_; my (%monitors, %standard_monitors); my $F = common::openFileMaybeCompressed($file); local $_; my $lineno = 0; while (<$F>) { $lineno++; s/\s+$//; /^#/ and next; /^$/ and next; my @fields = qw(vendor type eisa hsyncrange vsyncrange dpms); my @l = split /\s*;\s*/; my %l; @l{@fields} = @l; if ($monitors{$l{type}}) { my $i; for ($i = 0; $monitors{"$l{type} ($i)"}; $i++) {} $l{type} = "$l{type} ($i)"; } $monitors{"$l{vendor}|$l{type}"} = \%l; } \%monitors; } sub keepOnlyLegalModes { my ($card, $monitor) = @_; my $mem = 1024 * ($card->{VideoRam} || ($card->{server} eq 'FBDev' ? 2048 : 32768)); #- limit to 2048x1536x64 my $hsync = max(split(/[,-]/, $monitor->{hsyncrange})); while (my ($depth, $res) = each %{$card->{depth}}) { @$res = grep { $mem >= product(@$_, $depth / 8) && $hsync >= ($Xconfigurator_consts::min_hsync4x_res{$_->[0]} || 0) && ($card->{server} ne 'FBDev' || (Xconfigurator_consts::bios_vga_modes($_->[0], $depth))[2] == $_->[1]) } @$res; delete $card->{depth}{$depth} if @$res == 0; } } sub cardConfigurationAuto() { my @c = grep { $_->{driver} =~ /(Card|Server|Driver):/ } detect_devices::probeall(); my @cards = map_index { my $card = { identifier => $_->{description} . (@c > 1 && " $::i"), busid => "PCI:$_->{pci_bus}:$_->{pci_device}:$_->{pci_function}", }; if ($_->{driver} =~ /Card:(.*)/) { updateCardAccordingName($card, $1) } elsif ($_->{driver} =~ /Server:(.*)/) { $card->{server} = $1 } elsif ($_->{driver} =~ /Driver:(.*)/) { $card->{driver} = $1 } else { internal_error() } $card; } @c; if (@cards >= 2 && $cards[0]{type} eq $cards[1]{type} && $cards[0]{type} eq 'Intel 830') { shift @cards; } #- take a default on sparc if nothing has been found. if (arch() =~ /^sparc/ && !@cards) { log::l("Using probe with /proc/fb as nothing has been found!"); local $_ = cat_("/proc/fb"); @cards = { server => /Mach64/ ? "Mach64" : /Permedia2/ ? "3DLabs" : "Sun24" }; } #- special case for multi head card using only one busid. @cards = map { if ($_->{MULTI_HEAD} && $_->{type} =~ /G[24]00/) { if ($ENV{MATROX_HAL}) { $_->{flags}{need_MATROX_HAL} = 1; } else { delete $_->{MULTI_HEAD}; } } map { {%$_} } ($_) x ($_->{MULTI_HEAD} || 1); } @cards; #- make sure no type are already used, duplicate both screen #- and rename type (because used as id). if (@cards > 1) { my $card = 1; foreach (@cards) { $_->{type} = "$_->{type} $card"; $card++; } } #- in case of only one cards, remove all busid reference, this will avoid #- need of change of it if the card is moved. #- on many PPC machines, card is on-board, busid is important, leave? if (@cards == 1 && arch() !~ /ppc/) { delete $cards[0]{busid}; } @cards; } sub install_server { my ($card, $cardOptions) = @_; my $prog = "/usr/X11R6/bin/" . ($card->{use_xf4} ? 'XFree86' : $card->{server} =~ /Sun(.*)/ ? "Xsun$1" : $card->{server} eq 'Xpmac' ? 'Xpmac' : "XF86_$card->{server}"); my @packages = (); -x "$prefix$prog" or push @packages, $card->{use_xf4} ? 'XFree86-server' : "XFree86-$card->{server}"; #- additional packages to install according available card. #- add XFree86-libs-DRI here if using DRI (future split of XFree86 TODO) if ($card->{DRI_GLX}) { push @packages, 'Glide_V5' if $card->{type} eq 'Voodoo5 (generic)'; push @packages, 'Glide_V3-DRI' if member($card->{type}, 'Voodoo3 (generic)', 'Voodoo Banshee (generic)'); push @packages, 'XFree86-glide-module' if $card->{type} =~ /Voodoo/; } if ($card->{UTAH_GLX}) { push @packages, 'Mesa'; } #- 3D acceleration configuration for XFree 4 using NVIDIA driver (TNT, TN2 and GeForce cards only). push @packages, @{$cardOptions->{allowNVIDIA_rpms}} if $card->{driver2} eq 'nvidia' && $cardOptions->{allowNVIDIA_rpms}; $do_pkgs->install(@packages) if @packages; -x "$prefix$prog" or die "server $card->{server} is not available (should be in $prefix$prog)"; #- 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/usr/X11R6/lib/modules/drivers/nvidia_drv.o" && -e "$prefix/usr/X11R6/lib/modules/extensions/libglx.so") { log::l("Using specific NVIDIA driver and GLX extensions"); $card->{driver} = 'nvidia'; } Xconfig::install_matrox_proprietary_hal($prefix) if $card->{flags}{need_MATROX_HAL}; $prog; } sub cardConfiguration { my ($card, $noauto, $cardOptions) = @_; $card ||= {}; updateCardAccordingName($card, $card->{type}) if $card->{type}; #- try to get info from given type undef $card->{type} unless $card->{server} || $card->{driver}; #- bad type as we can't find the server my @cards = cardConfigurationAuto(); if (@cards > 1 && ($noauto || !$card->{server})) {#} && !$::isEmbedded) { my (%single_heads, @choices, $tc); my $configure_multi_head = sub { add2hash($card, $cards[0]); #- assume good default. delete $card->{cards} if $noauto; $card->{cards} or $card->{cards} = \@cards; $card->{force_xf4} = 1; #- force XF4 in such case. $card->{Xinerama} = $_[0]; }; foreach (@cards) { if (!$_->{driver}) { log::l("found card \"$_->{identifier}\" not supported by XF4, disabling mutli-head support"); $configure_multi_head = undef; } #- if more than one card use the same BusID, we have to use screen. if ($single_heads{$_->{busid}}) { $single_heads{$_->{busid}}{screen} ||= 0; $_->{screen} = $single_heads{$_->{busid}}{screen} + 1; } $single_heads{$_->{busid}} = $_; } if ($configure_multi_head) { push @choices, { text => _("Configure all heads independently"), code => sub { $configure_multi_head->('') } }; push @choices, { text => _("Use Xinerama extension"), code => sub { $configure_multi_head->(1) } }; } foreach my $e (values %single_heads) { push @choices, { text => _("Configure only card \"%s\" (%s)", $e->{identifier}, $e->{busid}), code => sub { add2hash($card, $e); foreach (qw(cards screen Xinerama)) { delete $card->{$_} } } }; } $tc = $in->ask_from_listf(_("Multi-head configuration"), _("Your system support multiple head configuration. What do you want to do?"), sub { translate($_[0]{text}) }, \@choices) or return; #- no more die, CHECK with auto that return ''! $tc->{code} and $tc->{code}(); } else { #- only one head found, configure it as before. add2hash($card, $cards[0]) if !$noauto; delete $card->{cards}; delete $card->{Xinerama}; } $card->{server} = 'FBDev' unless !$cardOptions->{allowFB} || $card->{server} || $card->{driver} || $card->{type} || $noauto; my $currentRealName = realName2CardName($card->{type} || $cards[0]{type}) || 'Other|Unlisted'; $card->{type} = cardName2RealName($in->ask_from_treelist(_("Graphics card"), _("Select a graphics card"), '|', ['Other|Unlisted', readCardsNames()], $currentRealName)) or return unless $card->{type} || $card->{server} || $card->{driver}; updateCardAccordingName($card, $card->{type}) if $card->{type}; #- check to use XFree 4 or XFree 3.3. $card->{use_xf4} = $card->{driver}; $card->{force_xf4} ||= arch() =~ /ppc|ia64/; #- try to figure out ugly hack for PPC (recommend XF4 always so...) $card->{prefer_xf3} = !$card->{force_xf4} && $card->{type} =~ /NeoMagic /; #- take into account current environment in standalone to keep #- the XFree86 version. if ($::isStandalone) { readlink("$prefix/etc/X11/X") =~ /XFree86/ and $card->{prefer_xf3} = 0; readlink("$prefix/etc/X11/X") =~ /XF86_/ and $card->{prefer_xf3} = !$card->{force_xf4}; } #- manage X 3.3.6 or above 4.2.0 specific server or driver. if ($card->{type} eq 'Other|Unlisted') { undef $card->{type}; my @list = ('server', $cardOptions->{allowFB} ? @Xconfigurator_consts::allservers : @Xconfigurator_consts::allbutfbservers); my $default_server = if_(!$card->{use_xf4} || $card->{prefer_xf3}, $card->{server} || $cards[0]{server}) || 'server'; $card->{server} = $in->ask_from_list(_("X server"), _("Choose a X server"), \@list, $default_server) or return; if ($card->{server} eq 'server') { my $fake_card = {}; updateCardAccordingName($fake_card, $cards[0]{type}) if $cards[0]{type}; $card->{server} = $card->{prefer_xf3} = undef; $card->{use_xf4} = $card->{force_xf4} = 1; $card->{driver} = $in->ask_from_list(_("X driver"), _("Choose a X driver"), ($cardOptions->{allowFB} ? \@Xconfigurator_consts::alldrivers : \@Xconfigurator_consts::allbutfbdrivers), $card->{driver} || $fake_card->{driver} || $cards[0]{driver}) or return; } else { $card->{driver} = $card->{use_xf4} = $card->{force_xf4} = undef; $card->{prefer_xf3} = 1; } } foreach ($card, @{$card->{cards} || []}) { $_->{VideoRam} = 4096, delete $_->{depth} if $_->{driver} eq 'i810'; $_->{VideoRam} = 16384, delete $_->{depth} if $_->{Chipset} =~ /PERMEDIA/ && $_->{VideoRam} <= 1024; } if (availableRamMB() > 800 || arch() =~ /ppc/) { #- No 3D XFree 3.3 for PPC #- and no Utah GLX if more than 800 Mb (server, or kernel-enterprise, Utha GLX does not work with latest). $card->{UTAH_GLX} = $card->{UTAH_GLX_EXPERIMENTAL} = ''; } #- XFree version available, better to parse available package and get version from it. my ($xf4_ver, $xf3_ver) = ("4.2.0", "3.3.6"); #- basic installation, use of XFree 4.2 or XFree 3.3. my $xf3_tc = { text => _("XFree %s", $xf3_ver), code => sub { $card->{UTAH_GLX} = $card->{DRI_GLX} = ''; $card->{use_xf4} = ''; log::l("Using XFree $xf3_ver") } }; my $msg = _("Which configuration of XFree do you want to have?"); my @choices = $card->{use_xf4} ? (if_($card->{prefer_xf3}, $xf3_tc), if_(!$card->{prefer_xf3} || $::expert || $noauto, { text => _("XFree %s", $xf4_ver), code => sub { $card->{UTAH_GLX} = $card->{DRI_GLX} = ''; log::l("Using XFree $xf4_ver") } }), if_(!$card->{prefer_xf3} && !$card->{force_xf4} && ($::expert || $noauto), $xf3_tc)) : $xf3_tc; #- try to figure if 3D acceleration is supported #- by XFree 3.3 but not XFree 4 then ask user to keep XFree 3.3 ? if ($card->{UTAH_GLX} && !$card->{force_xf4}) { $msg = ($card->{use_xf4} && !$card->{DRI_GLX} && !$card->{prefer_xf3} ? _("Your card can have 3D hardware acceleration support but only with XFree %s. Your card is supported by XFree %s which may have a better support in 2D.", $xf3_ver, $xf4_ver) : _("Your card can have 3D hardware acceleration support with XFree %s.", $xf3_ver)) . "\n\n\n" . $msg; $::expert || $noauto or @choices = (); #- keep it by default here as it is the only choice available. unshift @choices, { text => _("XFree %s with 3D hardware acceleration", $xf3_ver), code => sub { $card->{use_xf4} = ''; log::l("Using XFree $xf3_ver with 3D hardware acceleration") } }; } #- an expert user may want to try to use an EXPERIMENTAL 3D acceleration. if ($::expert && $card->{use_xf4} && $card->{DRI_GLX_EXPERIMENTAL} && !$card->{Xinerama}) { $msg = _("Your card can have 3D hardware acceleration support with XFree %s, NOTE THIS IS EXPERIMENTAL SUPPORT AND MAY FREEZE YOUR COMPUTER.", $xf4_ver) . "\n\n\n" . $msg; push @choices, { text => _("XFree %s with EXPERIMENTAL 3D hardware acceleration", $xf4_ver), code => sub { $card->{DRI_GLX} = 'EXPERIMENTAL'; log::l("Using XFree $xf4_ver with EXPERIMENTAL 3D hardware acceleration") } }; } #- an expert user may want to try to use an EXPERIMENTAL 3D acceleration, currenlty #- this is with Utah GLX and so, it can provide a way of testing. if ($::expert && $card->{UTAH_GLX_EXPERIMENTAL} && !$card->{force_xf4}) { $msg = ($card->{use_xf4} && !$card->{DRI_GLX} && !$card->{prefer_xf3} ? _("Your card can have 3D hardware acceleration support but only with XFree %s, NOTE THIS IS EXPERIMENTAL SUPPORT AND MAY FREEZE YOUR COMPUTER. Your card is supported by XFree %s which may have a better support in 2D.", $xf3_ver, $xf4_ver) : _("Your card can have 3D hardware acceleration support with XFree %s, NOTE THIS IS EXPERIMENTAL SUPPORT AND MAY FREEZE YOUR COMPUTER.", $xf3_ver)) . "\n\n\n" . $msg; push @choices, { text => _("XFree %s with EXPERIMENTAL 3D hardware acceleration", $xf3_ver), code => sub { $card->{use_xf4} = ''; $card->{UTAH_GLX} = 'EXPERIMENTAL'; log::l("Using XFree $xf3_ver with EXPERIMENTAL 3D hardware acceleration") } }; } #- ask the expert or any user on second pass user to enable or not hardware acceleration support. if ($card->{use_xf4} && $card->{DRI_GLX} && !$card->{Xinerama}) { $msg = _("Your card can have 3D hardware acceleration support with XFree %s.", $xf4_ver) . "\n\n\n" . $msg; $::expert || $noauto or @choices = (); #- keep all user by default with XFree 4 including 3D acceleration. unshift @choices, { text => _("XFree %s with 3D hardware acceleration", $xf4_ver), code => sub { log::l("Using XFree $xf4_ver with 3D hardware acceleration") } }; } if (arch() =~ /ppc/) { #- not much choice for PPC - we only have XF4, and Xpmac from the installer @choices = { text => _("XFree %s", $xf4_ver), code => sub { $card->{use_xf4} = 1; log::l("Using XFree $xf4_ver") } }; push @choices, { text => _("Xpmac (installation display driver)"), code => sub { $card->{server} = "Xpmac"; $card->{use_xf4} = ''; }} if $ENV{DISPLAY}; } #- examine choice of user, beware the list MUST NOT BE REORDERED AS the first item should be the #- proposed one by DrakX. my $tc = $in->ask_from_listf(_("XFree configuration"), formatAlaTeX($msg), sub { translate($_[0]{text}) }, \@choices) or return; #- in case of class discarding, this can help ... $tc or $tc = $choices[0]; $tc->{code} and $tc->{code}(); $card->{prog} = install_server($card); #- check for Matrox G200 PCI cards, disable AGP in such cases, causes black screen else. if (member($card->{type}, 'Matrox Millennium 200', 'Matrox Millennium 200', 'Matrox Mystique') && $card->{identifier} !~ /AGP/) { log::l("disabling AGP mode for Matrox card, as it seems to be a PCI card"); log::l("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"; } delete $card->{depth}{32} if $card->{type} =~ /S3 Trio3D|SiS/; $card->{options}{sw_cursor} = 1 if $card->{type} =~ /S3 Trio3D|SiS 6326/; $card->{options_xf3}{power_saver} = 1; $card->{options_xf4}{DPMS} = 'on'; $card->{VideoRam} ||= $in->ask_from_listf_('', _("Select the memory size of your graphics card"), sub { $Xconfigurator_consts::VideoRams{$_[0]} }, [ sort keys %Xconfigurator_consts::VideoRams ]) || return if $card->{flags}{needVideoRam}; #- hack for ATI Mach64 cards where two options should be used if using Utah-GLX. if (member($card->{type}, 'ATI Mach64 Utah', 'ATI Rage Mobility')) { $card->{options_xf3}{no_font_cache} = $card->{UTAH_GLX}; $card->{options_xf3}{no_pixmap_cache} = $card->{UTAH_GLX}; } #- hack for SiS cards where an option should be used if using Utah-GLX. if (member($card->{type}, 'SiS 6326', 'SiS 630')) { $card->{options_xf3}{no_pixmap_cache} = $card->{UTAH_GLX}; } #- 3D acceleration configuration for XFree 4 using DRI, this is enabled by default #- but for some there is a need to specify VideoRam (else it won't run). if ($card->{DRI_GLX}) { $card->{flags}{needVideoRam} = 1 if $card->{identifier} =~ /Matrox.* G[245][05]0/; ($card->{flags}{needVideoRam}, $card->{VideoRam}) = (1, 16384) if member($card->{type}, 'Intel 810', 'Intel 815'); #- always enable (as a reminder for people using a better AGP mode to change it at their own risk). $card->{options_xf4}{AGPMode} = '1'; #- 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->{type}, 'ATI Rage 128', 'ATI Rage 128 Mobility')) { $card->{options_xf4}{UseCCEFor2D} = (detect_devices::matching_desc('Bt8[47][89]') || detect_devices::matching_desc('TV') || detect_devices::matching_desc('AG GMV1')) ? 'true' : 'false'; } } $card; } sub optionsConfiguration($) { my ($X) = @_; my @l; my %l; foreach (@Xconfigurator_consts::options) { if ($X->{card}{server} eq $_->[1] && $X->{card}{identifier} =~ /$_->[2]/) { my $options = 'options_' . ($X->{card}{server} eq 'XFree86' ? 'xf4' : 'xf3'); $X->{card}{$options}{$_->[0]} ||= 0; if (!$l{$_->[0]}) { push @l, { label => $_->[0], val => \$X->{card}{$options}{$_->[0]}, type => 'bool' }; $l{$_->[0]} = 1; } } } @l = @l[0..9] if @l > 9; #- reduce list size to 10 for display $in->ask_from('', _("Choose options for server"), \@l); } sub monitorConfiguration(;$$) { my $monitor = shift || {}; my $useFB = shift || 0; my $monitors = readMonitorsDB("$ENV{SHARE_PATH}/ldetect-lst/MonitorsDB"); if ($monitor->{EISA_ID}) { log::l("EISA_ID: $monitor->{EISA_ID}"); if (my ($mon) = grep { lc($_->{eisa}) eq $monitor->{EISA_ID} } values %$monitors) { add2hash($monitor, $mon); log::l("EISA_ID corresponds to: $monitor->{type}"); } } if ($monitor->{hsyncrange} && $monitor->{vsyncrange}) { add2hash($monitor, { type => "monitor1" }); return $monitor; } my $good_default = (arch() =~ /ppc/ ? 'Apple|' : 'Generic|') . translate($Xconfigurator_consts::good_default_monitor); $monitor->{type} ||= ($::auto_install ? $Xconfigurator_consts::low_default_monitor : $in->ask_from_treelist(_("Monitor"), _("Choose a monitor"), '|', ['Custom', keys %$monitors], $good_default)); if ($monitor->{type} eq 'Custom') { $in->ask_from('', _("The two critical parameters are the vertical refresh rate, which is the rate at which the whole screen is refreshed, and most importantly the horizontal sync rate, which is the rate at which scanlines are displayed. It is VERY IMPORTANT that you do not specify a monitor type with a sync range that is beyond the capabilities of your monitor: you may damage your monitor. If in doubt, choose a conservative setting."), [ { val => \$monitor->{hsyncrange}, list => \@Xconfigurator_consts::hsyncranges, label => _("Horizontal refresh rate"), not_edit => 0 }, { val => \$monitor->{vsyncrange}, list => \@Xconfigurator_consts::vsyncranges, label => _("Vertical refresh rate"), not_edit => 0 } ]); } else { add2hash($monitor, $monitors->{$monitor->{type}}); } add2hash($monitor, { type => "monitor1", manual => 1 }); } sub finalize_config { my ($X) = @_; $X->{monitor}{ModeLines_xf3} .= $Xconfigurator_consts::ModeLines_text_standard; $X->{monitor}{ModeLines_xf3} .= $Xconfigurator_consts::ModeLines_text_ext; $X->{monitor}{ModeLines} .= $Xconfigurator_consts::ModeLines_text_ext; #- clean up duplicated ModeLines foreach ($X->{monitor}{ModeLines}, $X->{monitor}{ModeLines_xf3}) { s/Modeline/ModeLine/g; #- normalize my @l = reverse split "\n"; my %seen; @l = grep { !/^\s*Mode[lL]ine\s+(\S+)\s+(\S+)\s+(.*)/ || !$seen{"$1 $2"}++; } @l; $_ = join("\n", reverse @l); } $X->{keyboard}{XkbModel} ||= arch() =~ /sparc/ ? 'sun' : $X->{keyboard}{XkbLayout} eq 'jp' ? 'jp106' : $X->{keyboard}{XkbLayout} eq 'br' ? 'abnt2' : 'pc105'; } sub check_config { my ($X) = @_; finalize_config($X); $X->{monitor}{hsyncrange} && $X->{monitor}{vsyncrange} or die _("Monitor not configured") . "\n"; $X->{card}{server} || $X->{card}{driver} or die _("Graphics card not configured yet") . "\n"; $X->{card}{depth} or die _("Resolutions not chosen yet") . "\n"; } #- needed for bad cards not restoring cleanly framebuffer, according to which version of XFree are used. sub check_bad_card { my ($card) = @_; my $bad_card = $card->{use_xf4} ? $card->{BAD_FB_RESTORE} : $card->{BAD_FB_RESTORE_XF3}; $bad_card ||= $card->{driver} eq 'i810' || $card->{driver} eq 'fbdev'; $bad_card ||= $card->{identifier} =~ /S3.*ViRGE/ if $::live; $bad_card ||= $card->{driver} eq 'nvidia' if !$::isStandalone; #- avoid testing during install at any price. log::l("the graphics card does not like X in framebuffer") if $bad_card; !$bad_card; } sub testFinalConfig { my ($X, $auto, $skiptest, $skip_badcard) = @_; my $f = "/etc/X11/XF86Config.test"; eval { write_XF86Config($X, $::testing ? $tmpconfig : "$prefix/$f") }; if (my $err = $@) { $in->ask_warn('', $err); return; } $skiptest || $X->{card}{server} =~ 'FBDev|Sun' and return 1; #- avoid testing with these. check_bad_card($X->{card}) or return 1; $in->ask_yesorno(_("Test of the configuration"), _("Do you want to test the configuration?"), 1) or return 1 if !$auto; unlink "$prefix/tmp/.X9-lock"; #- create a link from the non-prefixed /tmp/.X11-unix/X9 to the prefixed one #- that way, you can talk to :9 without doing a chroot #- but take care of non X11 install :-) if (-d "/tmp/.X11-unix") { symlinkf "$prefix/tmp/.X11-unix/X9", "/tmp/.X11-unix/X9" if $prefix; } else { symlinkf "$prefix/tmp/.X11-unix", "/tmp/.X11-unix" if $prefix; } #- restart_xfs; my $f_err = "$prefix/tmp/Xoutput"; my $pid; unless ($pid = fork) { system("xauth add :9 . `mcookie`"); open STDERR, ">$f_err"; chroot $prefix if $prefix; exec $X->{card}{prog}, if_($X->{card}{prog} !~ /Xsun/, "-xf86config", ($::testing ? $tmpconfig : $f) . ($X->{card}{use_xf4} && "-4")), ":9" or c::_exit(0); } do { sleep 1 } until xtest(":9") || waitpid($pid, c::WNOHANG()); my $b = before_leaving { unlink $f_err }; if (!xtest(":9")) { local $_; local *F; open F, $f_err; i: while () { if ($X->{card}{use_xf4}) { if (/^\(EE\)/ && !/Disabling/ || /^Fatal\b/) { my @msg = !/error/ && $_ ; while () { /reporting a problem/ and last; push @msg, $_; $in->ask_warn('', [ _("An error occurred:"), " ", @msg, _("\ntry to change some parameters") ]); return 0; } } } else { if (/\b(error|not supported)\b/i) { my @msg = !/error/ && $_ ; while () { /not fatal/ and last i; /^$/ and last; push @msg, $_; } $in->ask_warn('', [ _("An error occurred:"), " ", @msg, _("\ntry to change some parameters") ]); return 0; } } } } $::noShadow = 1; local *F; open F, "|perl 2>/dev/null" or die ''; print F "use lib qw(", join(' ', @INC), ");\n"; print F q{ require lang; use interactive_gtk; use my_gtk qw(:wrappers); $::isStandalone = 1; lang::bindtextdomain(); $ENV{DISPLAY} = ":9"; gtkset_background(200 * 257, 210 * 257, 210 * 257); my ($h, $w) = Gtk::Gdk::Window->new_foreign(Gtk::Gdk->ROOT_WINDOW)->get_size; $my_gtk::force_position = [ $w / 3, $h / 2.4 ]; $my_gtk::force_focus = 1; my $text = Gtk::Label->new; my $time = 8; Gtk->timeout_add(1000, sub { $text->set(_("Leaving in %d seconds", $time)); $time-- or Gtk->main_quit; 1; }); my $background = "/usr/share/pixmaps/backgrounds/linux-mandrake/XFdrake-image-test.jpg"; my $qiv = "/usr/bin/qiv"; -r "} . $prefix . q{/$background" && -x "} . $prefix . q{/$qiv" and system(($::testing ? "} . $prefix . q{" : "chroot } . $prefix . q{/ ") . "$qiv -y $background"); my $in = interactive_gtk->new; $in->exit($in->ask_yesorno('', [ _("Is this the correct setting?"), $text ], 0) ? 0 : 222); }; my $rc = close F; my $err = $?; unlink "/tmp/.X11-unix/X9" if $prefix; kill 2, $pid; $::noShadow = 0; $rc || $err == 222 << 8 or $in->ask_warn('', _("An error occurred, try to change some parameters")); $rc; } sub allowedDepth($) { my ($card) = @_; my %allowed_depth; if ($card->{UTAH_GLX} || $card->{DRI_GLX}) { $allowed_depth{16} = 1; #- this is the default. $card->{identifier} =~ /Voodoo 5/ and $allowed_depth{24} = undef; $card->{identifier} =~ /Matrox.* G[245][05]0/ and $allowed_depth{24} = undef; $card->{identifier} =~ /Rage 128/ and $allowed_depth{24} = undef; $card->{identifier} =~ /Radeon/ and $allowed_depth{24} = undef; } for ($card->{server}) { #- this should work by default, FBDev is allowed only if install currently uses it at 16bpp. /FBDev/ and $allowed_depth{16} = 1; #- Sun servers, Sun24 handles 24,8,2; Sun only 8 and 2; and SunMono only 2. /^Sun24$/ and @allowed_depth{qw(24 8 2)} = (1); /^Sun$/ and @allowed_depth{qw(8 2)} = (1); /^SunMono$/ and @allowed_depth{qw(2)} = (1); } return %allowed_depth && \%allowed_depth; #- no restriction if false is returned. } sub autoDefaultDepth($$) { my ($card, $x_res_wanted) = @_; my ($best, $depth); #- check for forced depth according to current environment. my $allowed_depth = allowedDepth($card); if ($allowed_depth) { foreach (keys %$allowed_depth) { $allowed_depth->{$_} and return $_; #- a default depth is given. } } while (my ($d, $r) = each %{$card->{depth}}) { $allowed_depth && ! exists $allowed_depth->{$d} and next; #- reject depth. $depth = max($depth || 0, $d); #- try to have resolution_wanted $best = max($best || 0, $d) if $r->[0][0] >= $x_res_wanted; $best = $card->{suggest_depth}, last if ($card->{suggest_depth} && $card->{suggest_x_res} && $r->[0][0] >= $card->{suggest_x_res}); } $best || $depth or die "no valid modes"; } sub autoDefaultResolution { # return "1024x768" if detect_devices::hasPCMCIA; if (arch() =~ /ppc/) { return "1024x768" if detect_devices::get_mac_model =~ /^PowerBook|^iMac/; } my ($size) = @_; $Xconfigurator_consts::monitorSize2resolution[round($size || 14)] || #- assume a small monitor (size is in inch) $Xconfigurator_consts::monitorSize2resolution[-1]; #- no corresponding resolution for this size. It means a big monitor, take biggest we have } sub chooseResolutionsGtk($$;$) { my ($card, $chosen_depth, $chosen_w) = @_; require my_gtk; my_gtk->import(qw(:helpers :wrappers)); my $W = my_gtk->new(_("Resolution")); my %txt2depth = reverse %Xconfigurator_consts::depths; my ($r, $depth_combo, %w2depth, %w2h, %w2widget, $pix_monitor, $pix_colors, $w2_combo); $w2_combo = new Gtk::Combo; my $best_w; my $allowed_depth = allowedDepth($card); my %allowed_depth; while (my ($depth, $res) = each %{$card->{depth}}) { $allowed_depth && ! exists $allowed_depth->{$depth} and next; #- reject depth. foreach (@$res) { ++$allowed_depth{$depth}; $w2h{$_->[0]} = $_->[1]; push @{$w2depth{$_->[0]}}, $depth; $best_w = max($_->[0], $best_w) if $_->[0] <= $chosen_w; } } $chosen_w = $best_w; $chosen_w ||= 640; #- safe guard ? my $set_depth = sub { $depth_combo->entry->set_text(translate($Xconfigurator_consts::depths{$chosen_depth})) }; #- the set function is usefull to toggle the CheckButton with the callback being ignored my $ignore; my $no_human; # is the w2_combo->entry changed by a human? my $set = sub { $ignore = 1; $_[0] and $_[0]->set_active(1); $ignore = 0 }; my %monitor; $monitor{$_} = [ gtkcreate_png("monitor-" . $_ . ".png") ] foreach (640, 800, 1024, 1280); $monitor{$_} = [ gtkcreate_png("monitor-" . 1024 . ".png") ] foreach (1152); #- add default icons for resolutions not taken into account (assume largest image available). $monitor{$_} ||= [ gtkcreate_png("monitor-" . 1280 . ".png") ] foreach map { (split 'x', $_)[0] } @Xconfigurator_consts::resolutions; my $pixmap_mo = new Gtk::Pixmap( $monitor{$chosen_w}[0] , $monitor{$chosen_w}[1] ); while (my ($w, $h) = each %w2h) { my $V = $w . "x" . $h; $w2widget{$w} = $r = new Gtk::RadioButton($r ? ($V, $r) : $V); if ($chosen_w == $w) { &$set($r); } $r->signal_connect("clicked" => sub { $ignore and return; $chosen_w = $w; $no_human=1; $w2_combo->entry->set_text($w . "x" . $w2h{$w}); if (!member($chosen_depth, @{$w2depth{$w}})) { $chosen_depth = max(@{$w2depth{$w}}); &$set_depth(); } }); } gtkadd($W->{window}, gtkpack_($W->create_box_with_title(_("Choose the resolution and the color depth"), "(" . ($card->{type} ? _("Graphics card: %s", $card->{type}) : _("XFree86 server: %s", $card->{server})) . ")" ), 1, gtkpack2(new Gtk::VBox(0,0), gtkpack2__(new Gtk::VBox(0, $::isEmbedded ? 15 : 0), if_($::isEmbedded, $pixmap_mo), if_(!$::isEmbedded, map {$w2widget{$_} } ikeys(%w2widget)), gtkpack2(new Gtk::HBox(0,0), create_packtable({ col_spacings => 5, row_spacings => 5}, [ if_($::isEmbedded,$w2_combo) , new Gtk::Label("")], [ $depth_combo = new Gtk::Combo, gtkadd(gtkset_shadow_type(new Gtk::Frame, 'etched_out'), $pix_colors = gtkpng ("colors")) ], ), ), ), ), 0, gtkadd($W->create_okcancel(_("Ok"), _("More")), $::isEmbedded ? gtksignal_connect(new Gtk::Button(_("Expert Mode")), clicked => sub { system ("XFdrake --expert") }) : gtksignal_connect(new Gtk::Button(_("Show all")), clicked => sub { $W->{retval} = 1; $chosen_w = 0; Gtk->main_quit })), )); $depth_combo->disable_activate; $depth_combo->set_use_arrows_always(1); $depth_combo->entry->set_editable(0); $depth_combo->set_popdown_strings(map { translate($Xconfigurator_consts::depths{$_}) } grep { $Xconfigurator_consts::allowed_depth{$_} } ikeys(%{$card->{depth}})); $depth_combo->entry->signal_connect(changed => sub { $chosen_depth = $txt2depth{untranslate($depth_combo->entry->get_text, keys %txt2depth)}; my $w = $card->{depth}{$chosen_depth}[0][0]; $chosen_w > $w and &$set($w2widget{$chosen_w = $w}); $pix_colors->set(gtkcreate_png( $chosen_depth >= 24 ? "colors.png" : $chosen_depth >= 15 ? "colors16.png" : "colors8.png")); }); if ($::isEmbedded) { $w2_combo->disable_activate; $w2_combo->set_use_arrows_always(1); $w2_combo->entry->set_editable(0); $w2_combo->set_popdown_strings(map { $_ . "x" . $w2h{$_} } keys %w2h); $w2_combo->entry->signal_connect(changed => sub { ($chosen_w) = $w2_combo->entry->get_text =~ /([^x]*)x.*/; $no_human ? $no_human=0 : $w2widget{$chosen_w}->set_active(1); $pixmap_mo->set($monitor{$chosen_w}[0], $monitor{$chosen_w}[1]); }); } &$set_depth(); $W->{ok}->grab_focus; if ($::isEmbedded) { $no_human=1; $w2_combo->entry->set_text($chosen_w . "x" . $w2h{$chosen_w}); } $W->main or return; ($chosen_depth, $chosen_w); } sub chooseResolutions($$;$) { goto &chooseResolutionsGtk if $in->isa('interactive_gtk'); my ($card, $chosen_depth, $chosen_w) = @_; my $best_w; my $allowed_depth = allowedDepth($card); local $_ = $in->ask_from_list(_("Resolutions"), "", [ map_each { if_(!$allowed_depth || exists $allowed_depth->{$::a}, map { "$_->[0]x$_->[1] ${main::a}bpp" } @$::b) } %{$card->{depth}} ]) or return; reverse /(\d+)x\S+ (\d+)/; } sub resolutionsConfiguration { my ($X, $auto) = @_; my $card = $X->{card}; #- For the vga16 server, no further configuration is required. if ($card->{server} eq "VGA16") { $card->{depth}{8} = [[ 640, 480 ]]; return; } elsif ($card->{server} =~ /Sun/) { $card->{depth}{2} = [[ 1152, 864 ]] if $card->{server} =~ /^(SunMono)$/; $card->{depth}{8} = [[ 1152, 864 ]] if $card->{server} =~ /^(SunMono|Sun)$/; $card->{depth}{24} = [[ 1152, 864 ]] if $card->{server} =~ /^(SunMono|Sun|Sun24)$/; $card->{default_x_res} = 1152; $X->{default_depth} = max(keys %{$card->{depth}}); return 1; #- aka we cannot test, assumed as good (should be). } if (is_empty_hash_ref($card->{depth})) { $card->{depth}{$_} = [ map { [ split "x" ] } @Xconfigurator_consts::resolutions ] foreach @Xconfigurator_consts::depths; } #- sort resolutions in each depth foreach (values %{$card->{depth}}) { my $i = 0; @$_ = grep { first($i != $_->[0], $i = $_->[0]) } sort { $b->[0] <=> $a->[0] } @$_; } #- remove unusable resolutions (based on the video memory size and the monitor hsync rate) keepOnlyLegalModes($card, $X->{monitor}); my $res = $X->{resolution_wanted} || $card->{suggest_x_res} || autoDefaultResolution($X->{monitor}{size}); my $x_res = first(split 'x', $res); #- take the first available resolution <= the wanted resolution eval { $x_res = max map { first(grep { $_->[0] <= $x_res } @$_)->[0] } values %{$card->{depth}} }; my $depth = eval { $X->{default_depth} || autoDefaultDepth($card, $x_res) }; $auto or ($depth, $x_res) = chooseResolutions($card, $depth, $x_res) or return; #- if nothing has been found for x_res, #- try to find if memory used by mode found match the memory available #- card, if this is the case for a relatively low resolution ( < 1024 ), #- there could be a problem. #- memory in KB is approximated by $x_res*$dpeth/14 which is little less #- than memory really used, (correct factor is 13.65333 for w/h ratio of 1.33333). if (!$x_res || $auto && ref($in) !~ /class_discard/ && ($x_res < 1024 && ($card->{VideoRam} / ($x_res * $depth / 14)) > 2)) { delete $card->{depth}; return resolutionsConfiguration($X); } #- needed in auto mode when all has been provided by the user $card->{depth}{$depth} or die "you selected an unusable depth"; #- remove all biggest resolution (keep the small ones for ctl-alt-+) #- otherwise there'll be a virtual screen :( $_ = [ grep { $_->[0] <= $x_res } @$_ ] foreach values %{$card->{depth}}; $card->{default_x_res} = $x_res; $card->{bios_vga_mode} = (Xconfigurator_consts::bios_vga_modes($x_res, $depth))[0]; #- for use with frame buffer. $X->{default_depth} = $depth; 1; } #- Create the XF86Config file. sub write_XF86Config { my ($X, $file) = @_; my $O; check_config($X); $::g_auto_install and return; local (*F, *G); open F, ">$file" or die "can't write XF86Config in $file: $!"; open G, ">$file-4" or die "can't write XF86Config in $file-4: $!"; print F $Xconfigurator_consts::XF86firstchunk_text; print G $Xconfigurator_consts::XF86firstchunk_text; #- Write keyboard section. $O = $X->{keyboard}; print F ' Section "Keyboard" Protocol "Standard" '; print G ' Section "InputDevice" Identifier "Keyboard1" Driver "Keyboard" '; print F qq( XkbDisable\n) if !$O->{XkbLayout}; print G qq( Option "XkbDisable"\n) if !$O->{XkbLayout}; print F qq( XkbModel "$O->{XkbModel}"\n); print G qq( Option "XkbModel" "$O->{XkbModel}"\n); print F qq( XkbLayout "$O->{XkbLayout}"\n); print G qq( Option "XkbLayout" "$O->{XkbLayout}"\n); print F join '', map { " $_\n" } @{$Xconfigurator_consts::XkbOptions{$O->{XkbLayout}} || []}; print G join '', map { /(\S+)(.*)/; qq( Option "$1" $2\n) } @{$Xconfigurator_consts::XkbOptions{$O->{XkbLayout}} || []}; print F "\nEndSection\n\n"; print G "\nEndSection\n\n"; #- Write pointer section. my $pointer = sub { my ($O, $id) = @_; print F $id > 1 ? qq(Section "XInput"\n) : qq(Section "Pointer"\n); $id > 1 and print F qq( SubSection "Mouse"\n); print G qq(Section "InputDevice"\n\n); $id > 1 and print F qq( DeviceName "Mouse$id"\n); print G qq( Identifier "Mouse$id"\n); print G qq( Driver "mouse"\n); print F ($id > 1 && " ") . qq( Protocol "$O->{XMOUSETYPE}"\n); print G qq( Option "Protocol" "$O->{XMOUSETYPE}"\n); print F ($id > 1 && " ") . qq( Device "/dev/$O->{device}"\n); print G qq( Option "Device" "/dev/$O->{device}"\n); print F " AlwaysCore\n" if $id > 1; #- this will enable the "wheel" or "knob" functionality if the mouse supports it print F ($id > 1 && " ") . " ZAxisMapping 4 5\n" if $O->{nbuttons} > 3; print F ($id > 1 && " ") . " ZAxisMapping 6 7\n" if $O->{nbuttons} > 5; print G qq( Option "ZAxisMapping" "4 5"\n) if $O->{nbuttons} > 3; print G qq( Option "ZAxisMapping" "6 7"\n) if $O->{nbuttons} > 5; print F "#" if $O->{nbuttons} >= 3; print G "#" if $O->{nbuttons} >= 3; print F ($id > 1 && " ") . qq( Emulate3Buttons\n); print G qq( Option "Emulate3Buttons"\n); print F "#" if $O->{nbuttons} >= 3; print G "#" if $O->{nbuttons} >= 3; print F ($id > 1 && " ") . qq( Emulate3Timeout 50\n\n); print G qq( Option "Emulate3Timeout" "50"\n\n); $id > 1 and print F qq( EndSubSection\n); print F "EndSection\n\n\n"; print G "EndSection\n\n\n"; }; $pointer->($X->{mouse}, 1); $pointer->($X->{mouse}{auxmouse}, 2) if $X->{mouse}{auxmouse}; #- write module section for version 3. if (@{$X->{wacom}} || $X->{card}{UTAH_GLX}) { print F qq(Section "Module"\n); print F qq( Load "xf86Wacom.so"\n) if @{$X->{wacom}}; print F qq( Load "glx-3.so"\n) if $X->{card}{UTAH_GLX}; #- glx.so may clash with server version 4. print F qq(EndSection\n\n); } #- write wacom device support. foreach (1 .. @{$X->{wacom}}) { my $dev = "/dev/" . $X->{wacom}[$_-1]; print F $dev =~ /input\/event/ ? qq( Section "XInput" SubSection "WacomStylus" Port "$dev" DeviceName "Stylus$_" USB AlwaysCore Mode Absolute EndSubSection SubSection "WacomCursor" Port "$dev" DeviceName "Cursor$_" USB AlwaysCore Mode Relative EndSubSection SubSection "WacomEraser" Port "$dev" DeviceName "Eraser$_" USB AlwaysCore Mode Absolute EndSubSection EndSection ) : qq( Section "XInput" SubSection "WacomStylus" Port "$dev" DeviceName "Stylus$_" AlwaysCore Mode Absolute EndSubSection SubSection "WacomCursor" Port "$dev" DeviceName "Sursor$_" AlwaysCore Mode Relative EndSubSection SubSection "WacomEraser" Port "$dev" DeviceName "Eraser$_" AlwaysCore Mode Absolute EndSubSection EndSection ); } foreach (1..@{$X->{wacom}}) { my $dev = "/dev/" . $X->{wacom}[$_-1]; print G $dev =~ m|input/event| ? qq( Section "InputDevice" Identifier "Stylus$_" Driver "wacom" Option "Type" "stylus" Option "Device" "$dev" Option "Mode" "Absolute" Option "USB" "on" EndSection Section "InputDevice" Identifier "Eraser$_" Driver "wacom" Option "Type" "eraser" Option "Device" "$dev" Option "Mode" "Absolute" Option "USB" "on" EndSection Section "InputDevice" Identifier "Cursor$_" Driver "wacom" Option "Type" "cursor" Option "Device" "$dev" Option "Mode" "Relative" Option "USB" "on" EndSection ) : qq( Section "InputDevice" Identifier "Stylus$_" Driver "wacom" Option "Type" "stylus" Option "Device" "$dev" Option "Mode" "Absolute" EndSection Section "InputDevice" Identifier "Eraser$_" Driver "wacom" Option "Type" "eraser" Option "Device" "$dev" Option "Mode" "Absolute" EndSection Section "InputDevice" Identifier "Cursor$_" Driver "wacom" Option "Type" "cursor" Option "Device" "$dev" Option "Mode" "Relative" EndSection ); } #- write modules section for version 4. print G qq( Section "Module" # This loads the DBE extension module. Load "dbe" ); if (!($X->{card}{DRI_GLX} && $X->{card}{driver} eq 'r128')) { print G qq( # This loads the Video for Linux module. Load "v4l" ); } #- For example, this loads the NVIDIA GLX extension module. #- When DRI_GLX_SPECIAL is set, DRI_GLX is also set if ($X->{card}{DRI_GLX_SPECIAL}) { print G $X->{card}{DRI_GLX_SPECIAL}; } elsif ($X->{card}{DRI_GLX}) { print G qq( Load "glx" Load "dri" ); } print G qq( Load "type1" Load "freetype" EndSection ); print G qq( Section "DRI" Mode 0666 EndSection ) if $X->{card}{DRI_GLX}; #- Write monitor section. $O = $X->{monitor}; print F qq(\nSection "Monitor"\n); print G qq(\nSection "Monitor"\n); print F qq( Identifier "$O->{type}"\n); print G qq( Identifier "$O->{type}"\n); print F qq( HorizSync $O->{hsyncrange}\n\n); print G qq( HorizSync $O->{hsyncrange}\n\n); print F qq( VertRefresh $O->{vsyncrange}\n\n); print G qq( VertRefresh $O->{vsyncrange}\n\n); print F $O->{ModeLines_xf3} if $O->{ModeLines_xf3}; print G $O->{ModeLines} if $O->{ModeLines}; print F "\nEndSection\n\n\n"; print G "\nEndSection\n\n\n"; foreach (2..@{$X->{card}{cards} || []}) { print G qq(Section "Monitor"\n); print G qq( Identifier "monitor$_"\n); print G qq( HorizSync $O->{hsyncrange}\n); print G qq( VertRefresh $O->{vsyncrange}\n); print G qq(EndSection\n\n\n); } #- Write Device section. $O = $X->{card}; print F $Xconfigurator_consts::devicesection_text; print F qq(Section "Device"\n); print F qq( Identifier "$O->{type}"\n); print F qq( Chipset "$O->{Chipset}"\n) if $O->{Chipset}; print F "#" if $O->{VideoRam} && !$O->{flags}{needVideoRam}; print F " VideoRam $O->{VideoRam}\n" if $O->{VideoRam}; print F map { " $_\n" } @{$O->{lines} || []}; #- Obsolete stuff, no existing card still need this print F qq( Ramdac "$O->{Ramdac}"\n) if $O->{Ramdac}; print F qq( Dacspeed "$O->{Dacspeed}"\n) if $O->{Dacspeed}; print F qq( Clockchip "$O->{Clockchip}"\n) if $O->{Clockchip}; print F qq( # Uncomment following option if you see a big white block # instead of the cursor! # Option "sw_cursor" ); my $p_xf3 = sub { my $l = $O->{$_[0]}; map { (!$l->{$_} && '#') . qq( Option "$_"\n) } keys %{$l || {}}; }; my $p_xf4 = sub { my $l = $O->{$_[0]}; map { (! defined $l->{$_} && '#') . qq( Option "$_" "$l->{$_}"\n) } keys %{$l || {}}; }; print F $p_xf3->('options'); print F $p_xf3->('options_xf3'); print F "EndSection\n\n\n"; #- configure all drivers here! foreach (@{$O->{cards} || [ $O ]}) { print G qq(Section "Device"\n); print G qq( Identifier "$_->{type}"\n); print G qq( Driver "$_->{driver}"\n); print G "#" if $_->{VideoRam} && !$_->{flags}{needVideoRam}; print G " VideoRam $_->{VideoRam}\n" if $_->{VideoRam}; print G map { " $_\n" } @{$_->{lines} || []}; #- Obsolete stuff, no existing card still need this print G qq( Ramdac "$_->{Ramdac}"\n) if $_->{Ramdac}; print G qq( Dacspeed "$_->{Dacspeed}"\n) if $_->{Dacspeed}; print G qq( Clockchip "$_->{clockchip}"\n) if $_->{clockchip}; print G qq( # Uncomment following option if you see a big white block # instead of the cursor! # Option "sw_cursor" ); print G $p_xf3->('options'); #- keep $O for these! print G $p_xf4->('options_xf4'); #- keep $O for these! print G qq( Screen $_->{screen}\n) if defined $_->{screen}; print G qq( BusID "$_->{busid}"\n) if $_->{busid}; if ((arch =~ /ppc/) && ($_->{driver} eq "r128")) { print G qq( Option "UseFBDev"\n); } print G "EndSection\n\n\n"; } my $subscreen = sub { my ($f, $server, $defdepth, $depths) = @_; print $f " DefaultColorDepth $defdepth\n" if $defdepth; foreach (ikeys(%$depths)) { my $m = $server ne "fbdev" ? join(" ", map { qq("$_->[0]x$_->[1]") } @{$depths->{$_}}) : qq("default"); #-" print $f qq( Subsection "Display"\n); print $f qq( Depth $_\n) if $_; print $f qq( Modes $m\n); print $f qq( ViewPort 0 0\n); print $f qq( EndSubsection\n); } print $f "EndSection\n"; }; my $screen = sub { my ($server, $defdepth, $device, $depths) = @_; print F qq( Section "Screen" Driver "$server" Device "$device" Monitor "$X->{monitor}{type}" ); #-" $subscreen->(*F, $server, $defdepth, $depths); }; &$screen("svga", $X->{default_depth}, $O->{type}, $O->{depth}) if $O->{server} eq 'SVGA'; &$screen("accel", $X->{default_depth}, $O->{type}, $O->{depth}) if $Xconfigurator_consts::serversdriver{$O->{server}} eq 'accel'; &$screen("fbdev", $X->{default_depth}, $O->{type}, $O->{depth}); &$screen("vga16", '', "Generic VGA", { '' => [[ 640, 480 ], [ 800, 600 ]]}); print G qq( Section "Screen" Identifier "screen1" Device "$O->{type}" Monitor "$X->{monitor}{type}" ); #- bpp 32 not handled by XF4 $subscreen->(*G, "svga", min($X->{default_depth}, 24), $O->{depth}); foreach (2..@{$O->{cards} || []}) { my $device = $O->{cards}[$_ - 1]{type}; print G qq( Section "Screen" Identifier "screen$_" Device "$device" Monitor "monitor$_" ); #- bpp 32 not handled by XF4 $subscreen->(*G, "svga", min($X->{default_depth}, 24), $O->{depth}); } print G qq( Section "ServerLayout" Identifier "layout1" Screen "screen1" ); foreach (2..@{$O->{cards} || []}) { my ($curr, $prev) = ($_, $_ - 1); print G qq( Screen "screen$curr" RightOf "screen$prev"\n); } print G '#' if defined $O->{Xinerama} && !$O->{Xinerama}; print G qq( Option "Xinerama" "on"\n) if defined $O->{Xinerama}; print G qq(\n InputDevice "Mouse1" "CorePointer"\n); print G qq(\n InputDevice "Mouse2" "SendCoreEvents"\n) if $X->{mouse}{auxmouse}; foreach (1..@{$X->{wacom}}) { print G qq( InputDevice "Stylus$_" "AlwaysCore" InputDevice "Eraser$_" "AlwaysCore" InputDevice "Cursor$_" "AlwaysCore" ); } print G qq( InputDevice "Keyboard1" "CoreKeyboard"\n); print G "\nEndSection\n\n"; close F; close G; } sub show_info { my ($X) = @_; $in->ask_warn('', Xconfig::info($X)); } #- Program entry point. sub main { ($prefix, my $X, $in, $do_pkgs, my $cardOptions) = @_; $X ||= {}; Xconfig::XF86check_link($prefix, ''); Xconfig::XF86check_link($prefix, '-4'); { my $w = $in->wait_message('', _("Preparing X-Window configuration"), 1); $X->{card} = cardConfiguration($X->{card}, $::noauto, $cardOptions); $X->{monitor} = monitorConfiguration($X->{monitor}, $X->{card}{server} eq 'FBDev'); } my $ok = resolutionsConfiguration($X, $::auto); $ok &&= testFinalConfig($X, $::auto, $X->{skiptest}, $::auto); my $quit; until ($ok || $quit) { ref($in) =~ /discard/ and die "automatic X configuration failed, ensure you give hsyncrange and vsyncrange with non-DDC aware videocards/monitors"; $in->set_help('configureXmain') if !$::isStandalone; my $f; $in->ask_from_( { title => 'XFdrake', messages => _("What do you want to do?"), cancel => '', }, [ { format => sub { $_[0][0] }, val => \$f, list => [ [ _("Change Monitor") => sub { $X->{monitor} = monitorConfiguration() } ], [ _("Change Graphics card") => sub { my $card = cardConfiguration('', 'noauto', $cardOptions); $card and $X->{card} = $card } ], if_($::expert, [ _("Change Server options") => sub { optionsConfiguration($X) } ]), [ _("Change Resolution") => sub { resolutionsConfiguration($X) } ], [ _("Show information") => sub { show_info($X) } ], [ _("Test again") => sub { $ok = testFinalConfig($X, 1) } ], [ _("Quit") => sub { $quit = 1 } ], ], } ]); $f->[1]->(); $in->kill; } if (!$ok) { $ok = $in->ask_yesorno('', _("Keep the changes? The current configuration is: %s", Xconfig::info($X))); } if ($ok) { if (!$::testing) { my $f = "$prefix/etc/X11/XF86Config"; if (-e "$f.test") { rename $f, "$f.old" or die "unable to make a backup of XF86Config"; rename "$f-4", "$f-4.old"; rename "$f.test", $f; rename "$f.test-4", "$f-4"; symlinkf "../..$X->{card}{prog}", "$prefix/etc/X11/X" if $X->{card}{server} !~ /Xpmac/; } } if (!$::isStandalone || $0 !~ /Xdrakres/) { $in->set_help('configureXxdm') if !$::isStandalone; my $run = exists $X->{xdm} ? $X->{xdm} : $::auto || $in->ask_yesorno(_("Graphical interface at startup"), _("I can setup your computer to automatically start the graphical interface (XFree) upon booting. Would you like XFree to start when you reboot?"), 1); any::runlevel($prefix, $run ? 5 : 3) if !$::testing; } if ($::isStandalone && $in->isa('interactive_gtk')) { if (my $wm = any::running_window_manager()) { if ($in->ask_okcancel('', _("Please relog into %s to activate the changes", ucfirst (lc $wm)), 1)) { fork and $in->exit; any::ask_window_manager_to_logout($wm); open STDIN, "/dev/null"; open STDERR, ">&STDERR"; c::setsid(); exec qw(perl -e), q{ my $wm = shift; for (my $nb = 30; $nb && `pidof "$wm"` > 0; $nb--) { sleep 1 } system("killall X ; killall -15 xdm gdm kdm prefdm") if !(`pidof "$wm"` > 0); }, $wm; } } else { $in->ask_warn('', _("Please log out and then use Ctrl-Alt-BackSpace")); } } } } 1;