summaryrefslogtreecommitdiffstats
path: root/perl-install/Xconfigurator.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/Xconfigurator.pm')
-rw-r--r--perl-install/Xconfigurator.pm1403
1 files changed, 1403 insertions, 0 deletions
diff --git a/perl-install/Xconfigurator.pm b/perl-install/Xconfigurator.pm
new file mode 100644
index 000000000..37c689eff
--- /dev/null
+++ b/perl-install/Xconfigurator.pm
@@ -0,0 +1,1403 @@
+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 (<F>) {
+ if ($X->{card}{use_xf4}) {
+ if (/^\(EE\)/ && !/Disabling/ || /^Fatal\b/) {
+ my @msg = !/error/ && $_ ;
+ while (<F>) {
+ /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 (<F>) {
+ /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/zero";
+ open STDOUT, ">/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;