package Xconfigurator; # $Id$ use diagnostics; use strict; use vars qw($in $install @window_managers @depths @monitorSize2resolution @hsyncranges %min_hsync4wres @vsyncranges %depths @resolutions %serversdriver @svgaservers @accelservers @allbutfbservers @allservers %vgamodes %videomemory @ramdac_name @ramdac_id @clockchip_name @clockchip_id %keymap_translate %standard_monitors $XF86firstchunk_text $keyboardsection_start $keyboardsection_start_v4 $keyboardsection_part2 $keyboardsection_part3 $keyboardsection_part3_v4 $keyboardsection_end $pointersection_text $monitorsection_text1 $monitorsection_text2 $monitorsection_text3 $monitorsection_text4 $modelines_text_Trident_TG_96xx $modelines_text $devicesection_text $devicesection_text_v4 $screensection_text1 %lines @options %xkb_options $good_default_monitor $low_default_monitor $layoutsection_v4 $modelines_text_apple); use common qw(:common :file :functional :system); use log; use detect_devices; use run_program; use Xconfigurator_consts; use any; use modules; use my_gtk qw(:helpers :wrappers); my $tmpconfig = "/tmp/Xconfig"; my ($prefix, %monitors, %standard_monitors_); sub xtest { my ($display) = @_; $::isStandalone ? system("DISPLAY=$display /usr/X11R6/bin/xtest") == 0 : c::Xtest($display); } sub getVGAMode($) { $_[0]->{card}{vga_mode} || $vgamodes{"640x480x16"}; } sub readCardsDB { my ($file) = @_; my ($card, %cards); my $F = common::openFileMaybeCompressed($file); my ($lineno, $cmd, $val) = 0; my $fs = { LINE => sub { push @{$card->{lines}}, $val unless $val eq "VideoRam" }, NAME => sub { $cards{$card->{type}} = $card if $card; $card = { type => $val }; }, SEE => sub { my $c = $cards{$val} or die "Error in database, invalid reference $val at line $lineno"; push @{$card->{lines}}, @{$c->{lines} || []}; add2hash($card->{flags}, $c->{flags}); add2hash($card, $c); }, CHIPSET => sub { $card->{chipset} = $val; $card->{flags}{needChipset} = 1 if $val eq 'GeForce DDR'; $card->{flags}{needVideoRam} = 1 if member($val, qw(mgag10 mgag200 RIVA128 SiS6326)); }, SERVER => sub { $card->{server} = $val; }, DRIVER => sub { $card->{driver} = $val; }, RAMDAC => sub { $card->{ramdac} = $val; }, DACSPEED => sub { $card->{dacspeed} = $val; }, CLOCKCHIP => sub { $card->{clockchip} = $val; $card->{flags}{noclockprobe} = 1; }, NOCLOCKPROBE => sub { $card->{flags}{noclockprobe} = 1 }, UNSUPPORTED => sub { $card->{flags}{unsupported} = 1 }, COMMENT => sub {}, }; local $_; while (<$F>) { $lineno++; s/\s+$//; /^#/ and next; /^$/ and next; /^END/ and last; ($cmd, $val) = /(\S+)\s*(.*)/ or next; #log::l("bad line $lineno ($_)"), next; my $f = $fs->{$cmd}; $f ? $f->() : log::l("unknown line $lineno ($_)"); } \%cards; } 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 updateCardAccordingName { my ($card, $name) = @_; my $cards = readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+"); add2hash($card->{flags}, $cards->{$name}{flags}); add2hash($card, $cards->{$name}); $card; } sub readMonitorsDB { my ($file) = @_; %monitors and return; 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); my @l = split /\s*;\s*/; @l == @fields or log::l("bad line $lineno ($_)"), next; 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; } while (my ($k, $v) = each %standard_monitors) { $monitors{'Generic|' . translate($k)} = $standard_monitors_{$k} = { hsyncrange => $v->[1], vsyncrange => $v->[2] }; } } sub keepOnlyLegalModes { my ($card, $monitor) = @_; my $mem = 1024 * ($card->{memory} || ($card->{server} eq 'FBDev' ? 2048 : 99999)); my $hsync = max(split(/[,-]/, $monitor->{hsyncrange})); while (my ($depth, $res) = each %{$card->{depth}}) { @$res = grep { $mem >= product(@$_, $depth / 8) && $hsync >= ($min_hsync4wres{$_->[0]} || 0) && ($card->{server} ne 'FBDev' || $vgamodes{"$_->[0]x$_->[1]x$depth"}) } @$res; delete $card->{depth}{$depth} if @$res == 0; } } sub cardConfigurationAuto() { my @cards; if (my @c = grep { $_->{driver} =~ /(Card|Server):/ } detect_devices::probeall(1)) { foreach my $i (0..$#c) { local $_ = $c[$i]->{driver}; my $card = { identifier => ($c[$i]{description} . (@c > 1 && " $i")) }; $card->{type} = $1 if /Card:(.*)/; $card->{server} = $1 if /Server:(.*)/; $card->{flags}{needVideoRam} &&= /86c368/; $card->{busid} = "PCI:$c[$i]{pci_bus}:$c[$i]{pci_device}:$c[$i]{pci_function}"; push @{$card->{lines}}, @{$lines{$card->{identifier}} || []}; push @cards, $card; } } #- 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"); if (/Mach64/) { push @cards, { server => "Mach64" } } elsif (/Permedia2/) { push @cards, { server => "3DLabs" } } else { push @cards, { server => "Sun24" } } } #- special case for dual head card using only one busid. @cards = map { my $dup = $_->{identifier} =~ /MGA G450/ ? 2 : 1; if ($dup > 1) { my @result; my $orig = $_; foreach (1..$dup) { my $card = {}; add2hash($card, $orig); push @result, $card; } @result; } else { ($_); } } @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) { updateCardAccordingName($_, $_->{type}) if $_->{type}; $_->{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? @cards == 1 and delete $cards[0]{busid} if arch() !~ /ppc/; @cards; } 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}; #- 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) { unless ($_->{driver} && !$_->{flags}{unsupported}) { 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 independantly"), code => sub { $configure_multi_head->('') } }; push @choices, { text => _("Use Xinerama extension"), code => sub { $configure_multi_head->(1) } }; } foreach (values %single_heads) { push @choices, { text => _("Configure only card \"%s\" (%s)", $_->{identifier}, $_->{busid}), code => sub { add2hash($card, $_); delete $card->{cards}; delete $card->{Xinerama} } }; } $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]) unless $card->{server} || $noauto; delete $card->{cards}; delete $card->{Xinerama}; } $card->{server} = 'FBDev' unless !$cardOptions->{allowFB} || $card->{server} || $card->{type} || $noauto; $card->{type} = cardName2RealName($in->ask_from_treelist(_("Graphic card"), _("Select a graphic card"), '|', ['Other|Unlisted', readCardsNames()])) unless $card->{type} || $card->{server}; undef $card->{type}, $card->{server} = $in->ask_from_list(_("X server"), _("Choose a X server"), $cardOptions->{allowFB} ? \@allservers : \@allbutfbservers ) or return if $card->{type} eq 'Other|Unlisted'; updateCardAccordingName($card, $card->{type}) if $card->{type}; add2hash($card, { vendor => "Unknown", board => "Unknown" }); foreach ($card, @{$card->{cards} || []}) { $_->{memory} = 4096, delete $_->{depth} if $_->{driver} eq 'i810'; $_->{memory} = 16384, delete $_->{depth} if $_->{chipset} =~ /PERMEDIA/ && $_->{memory} <= 1024; } #- 3D acceleration configuration for XFree 3.3 using Utah-GLX. $card->{Utah_glx} = ($card->{identifier} =~ /Matrox.* G[24][05]0/ || #- 8bpp does not work. $card->{identifier} =~ /Riva.*128/ || $card->{identifier} =~ /Rage X[CL]/ || $card->{identifier} =~ /3D Rage (?:LT|Pro)/); #- NOT WORKING $card->{type} =~ /Intel 810/); $card->{Utah_glx} = '' if arch() =~ /ppc/; #- No #D XFree 3.3 for PPC #- 3D acceleration configuration for XFree 3.3 using Utah-GLX but EXPERIMENTAL that may freeze the machine (FOR INFO NOT USED). $card->{Utah_glx_EXPERIMENTAL} = ($card->{type} =~ /RIVA TNT/ || #- all RIVA/GeForce comes from NVIDIA and may freeze (gltron). #$card->{type} =~ /RIVA128/ || $card->{type} =~ /GeForce 256/ || $card->{type} =~ /S3 Savage3D/ || #- only this one is evoluting (expect a stable release ?) #- $card->{type} =~ /S3 ViRGE/ || #- 15bits only $card->{identifier} =~ /Rage Mobility (?:P\/M|L) / || $card->{type} =~ /SiS/); #- 3D acceleration configuration for XFree 4.0 using DRI. $card->{DRI_glx} = ($card->{identifier} =~ /Voodoo [35]/ || $card->{identifier} =~ /Voodoo Banshee/ || #- 16bit only $card->{identifier} =~ /Matrox.* G[24][05]0/ || #- prefer 16bit (24bit not well tested according to DRI) $card->{identifier} =~ /8281[05].* CGC/ || #- 16bits (Intel 810 & 815). #$card->{identifier} =~ /Radeon / || #- 16bits preferable ? $card->{identifier} =~ /Rage 128/); #- 16 and 32 bits, prefer 16bit as no DMA. #- 3D acceleration configuration for XFree 4.0 using DRI but EXPERIMENTAL that may freeze the machine (FOR INFO NOT USED). $card->{DRI_glx_EXPERIMENTAL} = ($card->{identifier} =~ /SiS.*6C?326/ || #- prefer 16bit, other ? $card->{identifier} =~ /SiS.*6C?236/ || $card->{identifier} =~ /SiS.*630/ || $card->{identifier} =~ /Radeon /); #- 16bits preferable ? #- 3D acceleration configuration for XFree 4.0 using NVIDIA driver (TNT, TN2 and GeForce cards only). $card->{NVIDIA_glx} = $cardOptions->{allowNVIDIA_rpms} && ($card->{type} =~ /RIVA TNT/ || $card->{type} =~ /GeForce/); #- check to use XFree 4.0 or XFree 3.3. $card->{use_xf4} = $card->{driver} && !$card->{flags}{unsupported}; $card->{force_xf4} = arch() =~ /ppc/; #- try to figure out ugly hack for PPC (recommend XF4 always so...) $card->{prefer_xf3} = !$card->{force_xf4} && ($card->{type} =~ /RIVA TNT/ || $card->{type} =~ /RIVA128/ || $card->{type} =~ /GeForce/ || $card->{type} =~ /SiS / && $card->{type} !~ /SiS 6326/ || $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}; } #- basic installation, use of XFree 4.0 or XFree 3.3. my ($xf4_ver, $xf3_ver) = ("4.0.3", "3.3.6"); my $xf3_tc = { text => _("XFree %s", $xf3_ver), code => sub { $card->{Utah_glx} = $card->{DRI_glx} = $card->{NVIDIA_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), #- hack for Matrox driver where there are undefined reference if no DRI! if_($card->{identifier} !~ /Matrox.* G[24][05]0/ && (!$card->{prefer_xf3} || $::expert), { text => _("XFree %s", $xf4_ver), code => sub { $card->{Utah_glx} = $card->{DRI_glx} = $card->{NVIDIA_glx} = ''; log::l("Using XFree $xf4_ver") } }), if_(!$card->{prefer_xf3} && $::expert, $xf3_tc)) : $xf3_tc; #- try to figure if 3D acceleration is supported #- by XFree 3.3 but not XFree 4.0 then ask user to keep XFree 3.3 ? if ($card->{Utah_glx}) { $msg = ($card->{use_xf4} && !($card->{DRI_glx} || $card->{NVIDIA_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 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}) { $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}) { $msg = ($card->{use_xf4} && !($card->{DRI_glx} || $card->{NVIDIA_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 user to enable or not hardware acceleration support. if ($card->{use_xf4} && ($card->{DRI_glx} || $card->{NVIDIA_glx})) { $msg = _("Your card can have 3D hardware acceleration support with XFree %s.", $xf4_ver) . "\n\n\n" . $msg; $::expert or @choices = (); #- keep all user by default with XFree 4.0 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") } }; } #- 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} = "/usr/X11R6/bin/" . ($card->{use_xf4} ? 'XFree86' : $card->{server} =~ /Sun (.*)/x ? "Xsun$1" : "XF86_$card->{server}"); #- additional packages to install according available card. #- add XFree86-libs-DRI here if using DRI (future split of XFree86 TODO) my @l = (); if ($card->{DRI_glx}) { push @l, 'Glide_V5' if $card->{identifier} =~ /Voodoo 5/; push @l, 'Glide_V3-DRI' if $card->{identifier} =~ /Voodoo (3|Banshee)/; push @l, 'XFree86-glide-module' if $card->{identifier} =~ /Voodoo/; } elsif ($card->{NVIDIA_glx}) { push @l, @{$cardOptions->{allowNVIDIA_rpms}}; } if ($card->{Utah_glx}) { push @l, 'Mesa' if !$card->{use_xf4}; } -x "$prefix$card->{prog}" or $install && $install->($card->{use_xf4} ? 'XFree86-server' : "XFree86-$card->{server}", @l); -x "$prefix$card->{prog}" or die "server $card->{server} is not available (should be in $prefix$card->{prog})"; #- make sure everything is correct at this point, packages have really been installed #- and driver and GLX extension is present. if ($card->{NVIDIA_glx} && !$card->{DRI_glx} && (-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'; } else { $card->{NVIDIA_glx} = ''; } delete $card->{depth}{32} if $card->{type} =~ /S3 Trio3D|SiS/; $card->{options}{sw_cursor} = 1 if $card->{type} =~ /S3 Trio3D|SiS 6326/; unless ($card->{type}) { $card->{flags}{noclockprobe} = member($card->{server}, qw(I128 S3 S3V Mach64)); } $card->{options_xf3}{power_saver} = 1; $card->{options_xf4}{DPMS} = 1; $card->{flags}{needVideoRam} and $card->{memory} ||= $videomemory{$in->ask_from_list_('', _("Select the memory size of your graphic card"), [ sort { $videomemory{$a} <=> $videomemory{$b} } keys %videomemory]) || return}; #- hack for ATI Mach64 cards where two options should be used if using Utah-GLX. if ($card->{identifier} =~ /Rage X[CL]/ || $card->{identifier} =~ /Rage Mobility (?:P\/M|L) / || $card->{identifier} =~ /3D Rage (?:LT|Pro)/) { $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 ($card->{type} =~ /SiS /) { $card->{options_xf3}{no_pixmap_cache} = $card->{Utah_glx}; } #- 3D acceleration configuration for XFree 4.0 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->{identifier} =~ /Matrox.* G[24]00/ and $card->{flags}{needVideoRam} = 'fakeVideoRam'; $card->{identifier} =~ /8281[05].* CGC/ and ($card->{flags}{needVideoRam}, $card->{memory}) = ('fakeVideoRam', 16384); } if (!$::isStandalone && $card->{driver} eq 'i810') { require modules; eval { modules::load("agpgart"); }; } $card; } sub optionsConfiguration($) { my ($o) = @_; my @l; my %l; foreach (@options) { if ($o->{card}{server} eq $_->[1] && $o->{card}{identifier} =~ /$_->[2]/) { my $options = 'options_' . ($o->{card}{server} eq 'XFree86' ? 'xf4' : 'xf3'); $o->{card}{$options}{$_->[0]} ||= 0; unless ($l{$_->[0]}) { push @l, { label => $_->[0], val => \$o->{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_entries_refH('', _("Choose options for server"), \@l); } sub monitorConfiguration(;$$) { my $monitor = shift || {}; my $useFB = shift || 0; if ($monitor->{hsyncrange} && $monitor->{vsyncrange}) { add2hash($monitor, { type => "monitor1", vendor => "Unknown", model => "Unknown" }); return $monitor; } readMonitorsDB("$ENV{SHARE_PATH}/ldetect-lst/MonitorsDB"); my $good_default = (arch() =~ /ppc/ ? 'Apple|' : 'Generic|') . translate($good_default_monitor); $monitor->{type} ||= ($::auto_install ? $low_default_monitor : $in->ask_from_treelist(_("Monitor"), _("Choose a monitor"), '|', ['Custom', keys %monitors], $good_default)); if ($monitor->{type} eq 'Custom') { $in->ask_from_entries_refH('', _("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 => \@hsyncranges, label => _("Horizontal refresh rate") }, { val => \$monitor->{vsyncrange}, list => \@vsyncranges, label => _("Vertical refresh rate") }]); } else { add2hash($monitor, $monitors{$monitor->{type}} || $standard_monitors_{$monitor->{type}}); } add2hash($monitor, { type => "Unknown", vendor => "Unknown", model => "Unknown", manual => 1 }); } sub testConfig($) { my ($o) = @_; my ($resolutions, $clocklines); write_XF86Config($o, $tmpconfig); unlink "/tmp/.X9-lock"; #- restart_xfs; my $f = $tmpconfig . ($o->{card}{use_xf4} && "-4"); local *F; open F, "$prefix$o->{card}{prog} :9 -probeonly -pn -xf86config $f 2>&1 |"; local $_; while () { $o->{card}{memory} ||= $2 if /(videoram|Video RAM):\s*(\d*)/; # look for clocks push @$clocklines, $1 if /clocks: (.*)/ && !/(pixel |num)clocks:/; push @$resolutions, [ $1, $2 ] if /: Mode "(\d+)x(\d+)": mode clock/; print; } close F or die "X probeonly failed"; ($resolutions, $clocklines); } sub testFinalConfig { my ($o, $auto, $skiptest, $skip_badcard) = @_; $o->{monitor}{hsyncrange} && $o->{monitor}{vsyncrange} or $in->ask_warn('', _("Monitor not configured")), return; $o->{card}{server} || $o->{card}{driver} or $in->ask_warn('', _("Graphic card not configured yet")), return; $o->{card}{depth} or $in->ask_warn('', _("Resolutions not chosen yet")), return; my $f = "/etc/X11/XF86Config.test"; write_XF86Config($o, $::testing ? $tmpconfig : "$prefix/$f"); $skiptest || $o->{card}{server} =~ 'FBDev|Sun' and return 1; #- avoid testing with these. #- needed for bad cards not restoring cleanly framebuffer my $bad_card = $o->{card}{identifier} =~ /i740|ViRGE/; $bad_card ||= $o->{card}{identifier} =~ /Rage Mobility (?:P\/M|L) / || $o->{card}{identifier} =~ /3D Rage LT/; $bad_card ||= $o->{card}{use_xf4}; #- TODO obsoleted to check, when using fbdev of XFree 4.0! log::l("the graphic card does not like X in framebuffer") if $bad_card; my $verybad_card = $o->{card}{driver} eq 'i810'; $verybad_card and return 1; my $mesg = _("Do you want to test the configuration?"); my $def = 1; if ($bad_card && !$::isStandalone) { $skip_badcard and return 1; $mesg = $mesg . "\n" . _("Warning: testing this graphic card may freeze your computer"); $def = 0; } $auto && $def or $in->ask_yesorno(_("Test of the configuration"), $mesg, $def) or return 1; 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) { open STDERR, ">$f_err"; chroot $prefix if $prefix; exec $o->{card}{prog}, if_($o->{card}{prog} !~ /Xsun/, "-xf86config", ($::testing ? $tmpconfig : $f) . ($o->{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 }; unless (xtest(":9")) { local $_; local *F; open F, $f_err; i: while () { 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 has occurred:"), " ", @msg, _("\ntry to change some parameters") ]); return 0; } } } local *F; open F, "|perl 2>/dev/null" or die ''; print F "use lib qw(", join(' ', @INC), ");\n"; print F q{ use interactive_gtk; use my_gtk qw(:wrappers); $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; $rc || $err == 222 << 8 or $in->ask_warn('', _("An error has occurred, try to change some parameters")); $rc; } sub autoDefaultDepth($$) { my ($card, $wres_wanted) = @_; my ($best, $depth); return 16 if $card->{Utah_glx} || $card->{DRI_glx}; #- assume 16bit as most of them need 16. for ($card->{server}) { /FBDev/ and return 16; #- this should work by default, FBDev is allowed only if install currently uses it at 16bpp. /Sun24/ and return 24; /SunMono/ and return 2; /Sun/ and return 8; } while (my ($d, $r) = each %{$card->{depth}}) { $depth = max($depth || 0, $d); #- try to have resolution_wanted $best = max($best || 0, $d) if $r->[0][0] >= $wres_wanted; $best = $card->{suggest_depth}, last if ($card->{suggest_depth} && $card->{suggest_wres} && $r->[0][0] >= $card->{suggest_wres}); } $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) = @_; $monitorSize2resolution[round($size || 14)] || #- assume a small monitor (size is in inch) $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(:wrappers)); my $W = my_gtk->new(_("Resolution")); my %txt2depth = reverse %depths; my ($r, $depth_combo, %w2depth, %w2h, %w2widget, $pix_monitor, $pix_colors, $w2_combo); $w2_combo = new Gtk::Combo; my $best_w; while (my ($depth, $res) = each %{$card->{depth}}) { foreach (@$res) { $w2h{$_->[0]} = $_->[1]; push @{$w2depth{$_->[0]}}, $depth; $best_w = max($_->[0], $best_w) if $_->[0] <= $chosen_w; } } $chosen_w = $best_w; my $set_depth = sub { $depth_combo->entry->set_text(translate($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]->set_active(1); $ignore = 0; }; my %monitor; $monitor{$_} = [ gtkcreate_png("monitor-" . $_ . ".png") ] foreach (640, 800, 1024, 1280); $monitor{1152} = [ gtkcreate_png("monitor-" . 1024 . ".png") ]; $monitor{1600} = [ gtkcreate_png("monitor-" . 1280 . ".png") ]; my $pixmap_m = 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}); unless (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} ? _("Graphic 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_m), 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, $::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($depths{$_}) } 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_m->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 ref($in) =~ /gtk/; my ($card, $chosen_depth, $chosen_w) = @_; my $best_w; local $_ = $in->ask_from_list(_("Resolutions"), "", [ map_each { map { "$_->[0]x$_->[1] ${main::a}bpp" } @$::b } %{$card->{depth}} ]) or return; reverse /(\d+)x\S+ (\d+)/; } sub resolutionsConfiguration { my ($o, $auto) = @_; my $card = $o->{card}; #- For the mono and vga16 server, no further configuration is required. if (member($card->{server}, "Mono", "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_wres} = 1152; $o->{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" ] } @resolutions ] foreach @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, $o->{monitor}); my $res = $o->{resolution_wanted} || $card->{suggest_wres} || autoDefaultResolution($o->{monitor}{size}); my $wres = first(split 'x', $res); #- take the first available resolution <= the wanted resolution $wres = max map { first(grep { $_->[0] <= $wres } @$_)->[0] } values %{$card->{depth}}; my $depth = eval { $o->{default_depth} || autoDefaultDepth($card, $wres) }; $auto or ($depth, $wres) = chooseResolutions($card, $depth, $wres) or return; unless ($wres) { delete $card->{depth}; return resolutionsConfiguration($o); } #- 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] <= $wres } @$_ ] foreach values %{$card->{depth}}; $card->{default_wres} = $wres; $card->{vga_mode} = $vgamodes{"${wres}xx$depth"} || $vgamodes{"${res}x$depth"}; #- for use with frame buffer. $o->{default_depth} = $depth; 1; } #- Create the XF86Config file. sub write_XF86Config { my ($o, $file) = @_; my $O; 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 $XF86firstchunk_text; print G $XF86firstchunk_text; #- Write keyboard section. $O = $o->{keyboard}; print F $keyboardsection_start; print G $keyboardsection_start_v4; print F qq( XkbDisable\n) unless $O->{xkb_keymap}; print G qq( Option "XkbDisable"\n) unless $O->{xkb_keymap}; print F $keyboardsection_part3; print G $keyboardsection_part3_v4; $O->{xkb_model} ||= arch() =~ /ppc/ ? 'macintosh' : arch() =~ /sparc/ ? 'sun' : $O->{xkb_keymap} eq 'br' ? 'abnt2' : 'pc105'; print F qq( XkbModel "$O->{xkb_model}"\n); print G qq( Option "XkbModel" "$O->{xkb_model}"\n); print F qq( XkbLayout "$O->{xkb_keymap}"\n); print G qq( Option "XkbLayout" "$O->{xkb_keymap}"\n); print F join '', map { " $_\n" } @{$xkb_options{$O->{xkb_keymap}} || []}; print G join '', map { /(\S+)(.*)/; qq( Option "$1" $2\n) } @{$xkb_options{$O->{xkb_keymap}} || []}; print F $keyboardsection_end; print G $keyboardsection_end; #- 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); #- 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 "#" unless $O->{nbuttons} < 3; print G "#" unless $O->{nbuttons} < 3; print F ($id > 1 && " ") . qq( Emulate3Buttons\n); print G qq( Option "Emulate3Buttons"\n); print F "#" unless $O->{nbuttons} < 3; print G "#" unless $O->{nbuttons} < 3; print F ($id > 1 && " ") . qq( Emulate3Timeout 50\n\n); print G qq( Option "Emulate3Timeout" "50"\n\n); print F "# ChordMiddle is an option for some 3-button Logitech mice\n\n"; print G "# ChordMiddle is an option for some 3-button Logitech mice\n\n"; print F "#" unless $O->{chordmiddle}; print G "#" unless $O->{chordmiddle}; print F ($id > 1 && " ") . qq( ChordMiddle\n\n); print G qq( Option "ChordMiddle"\n\n); print F ($id > 1 && " ") . " ClearDTR\n" if $O->{cleardtrrts}; print F ($id > 1 && " ") . " ClearRTS\n\n" if $O->{cleardtrrts}; $id > 1 and print F qq( EndSubSection\n); print F "EndSection\n\n\n"; print G "EndSection\n\n\n"; }; print F $pointersection_text; print G $pointersection_text; $pointer->($o->{mouse}, 1); $o->{mouse}{auxmouse} and $pointer->($o->{mouse}{auxmouse}, 2); #- write module section for version 3. if (@{$o->{wacom}} || $o->{card}{Utah_glx}) { print F qq(Section "Module" ); print F qq( Load "xf86Wacom.so"\n) if @{$o->{wacom}}; print F qq( Load "glx-3.so"\n) if $o->{card}{Utah_glx}; #- glx.so may clash with server version 4. print F qq(EndSection ); } #- write wacom device support. foreach (@{$o->{wacom}}) { my $dev = "/dev/" . $o->{wacom}[$_-1]; print F $dev =~ /input\/event/ ? qq( Section "XInput" SubSection "WacomStylus" DeviceName "Stylus$_" Port "$dev" USB AlwaysCore Mode Absolute EndSubSection SubSection "WacomCursor" DeviceName "Cursor$_" Port "$dev" USB AlwaysCore Mode Relative EndSubSection SubSection "WacomEraser" DeviceName "Eraser$_" Port "$dev" USB AlwaysCore Mode Absolute EndSubSection EndSection ) : qq( Section "XInput" SubSection "WacomStylus" DeviceName "Stylus$_" Port "$dev" AlwaysCore Mode Absolute EndSubSection SubSection "WacomCursor" DeviceName "Sursor$_" Port "$dev" AlwaysCore Mode Relative EndSubSection SubSection "WacomEraser" DeviceName "Eraser$_" Port "$dev" AlwaysCore Mode Absolute EndSubSection EndSection ); } foreach (1..@{$o->{wacom}}) { my $dev = "/dev/" . $o->{wacom}[$_-1]; print G $dev =~ /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 ($o->{card}{DRI_glx}) { print G qq( Load "glx" Load "dri" ); } elsif ($o->{card}{NVIDIA_glx}) { print G qq( # This loads the NVIDIA GLX extension module. # IT IS IMPORTANT TO KEEP NAME AS FULL PATH TO libglx.so ELSE # IT WILL LOAD XFree86 glx module and the server will crash. Load "/usr/X11R6/lib/modules/extensions/libglx.so" ); } print G qq( # This loads the miscellaneous extensions module, and disables # initialisation of the XFree86-DGA extension within that module. SubSection "extmod" #Option "omit xfree86-dga" EndSubSection # This loads the Type1 and FreeType font modules Load "type1" Load "freetype" EndSection ); print G qq( Section "DRI" Mode 0666 EndSection ) if $o->{card}{DRI_glx}; #- Write monitor section. $O = $o->{monitor}; print F $monitorsection_text1; print G $monitorsection_text1; print F qq( Identifier "$O->{type}"\n); print G qq( Identifier "$O->{type}"\n); print G qq( UseModes "Mac Modes"\n) if arch() =~ /ppc/; print F qq( VendorName "$O->{vendor}"\n); print G qq( VendorName "$O->{vendor}"\n); print F qq( ModelName "$O->{model}"\n\n); print G qq( ModelName "$O->{model}"\n\n); print F $monitorsection_text2; print G $monitorsection_text2; print F qq( HorizSync $O->{hsyncrange}\n\n); print G qq( HorizSync $O->{hsyncrange}\n\n); print F $monitorsection_text3; print G $monitorsection_text3; print F qq( VertRefresh $O->{vsyncrange}\n\n); print G qq( VertRefresh $O->{vsyncrange}\n\n); print F $monitorsection_text4; print F ($O->{modelines} || '') . ($o->{card}{type} eq "TG 96" ? $modelines_text_Trident_TG_96xx : $modelines_text); print F "\nEndSection\n\n\n"; print G "\nEndSection\n\n\n"; print G $modelines_text_apple if arch() =~ /ppc/; foreach (2..@{$o->{card}{cards} || []}) { print G qq(Section "Monitor"\n); print G qq( Identifier "monitor$_"\n); print G qq( VendorName "$O->{vendor}"\n); print G qq( ModelName "$O->{model}"\n\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 = $o->{card}; print F $devicesection_text; print G $devicesection_text_v4; print F qq(Section "Device"\n); print F qq( Identifier "$O->{type}"\n); print F qq( VendorName "$O->{vendor}"\n); print F qq( BoardName "$O->{board}"\n); print F "#" if $O->{chipset} && !$O->{flags}{needChipset}; print F qq( Chipset "$O->{chipset}"\n) if $O->{chipset}; print F "#" if $O->{memory} && !$O->{flags}{needVideoRam}; print F " VideoRam $O->{memory}\n" if $O->{memory}; print F map { " $_\n" } @{$O->{lines} || []}; print F qq( Ramdac "$O->{ramdac}"\n) if $O->{ramdac}; print F qq( Dacspeed "$O->{dacspeed}"\n) if $O->{dacspeed}; if ($O->{clockchip}) { print F qq( Clockchip "$O->{clockchip}"\n); } else { print F " # Clock lines\n"; print F " Clocks $_\n" foreach (@{$O->{clocklines}}); } print F qq( # Uncomment following option if you see a big white block # instead of the cursor! # Option "sw_cursor" ); my $p = sub { my $l = $O->{$_[0]}; map { (!$l->{$_} && '#') . qq( Option "$_"\n) } keys %{$l || {}}; }; print F $p->('options'); print F $p->('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( VendorName "$_->{vendor}"\n); print G qq( BoardName "$_->{board}"\n); print G qq( Driver "$_->{driver}"\n); print G "#" if $_->{memory} && !$_->{flags}{needVideoRam}; print G " VideoRam $_->{memory}\n" if $_->{memory}; print G map { " $_\n" } @{$_->{lines} || []}; print G qq( Ramdac "$_->{ramdac}"\n) if $_->{ramdac}; print G qq( Dacspeed "$_->{dacspeed}"\n) if $_->{dacspeed}; if ($_->{clockchip}) { print G qq( Clockchip "$_->{clockchip}"\n); } else { print G " # Clock lines\n"; print G " Clocks $_\n" foreach (@{$_->{clocklines}}); } print G qq( # Uncomment following option if you see a big white block # instead of the cursor! # Option "sw_cursor" ); print G $p->('options'); #- keep $O for these! print G $p->('options_xf4'); #- keep $O for these! print G qq( Screen $_->{screen}\n) if defined $_->{screen}; print G qq( BusID "$_->{busid}"\n) if $_->{busid}; print G "EndSection\n\n\n"; } #- Write Screen sections. print F $screensection_text1, "\n"; print G $screensection_text1, "\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 "$o->{monitor}{type}" ); #-" $subscreen->(*F, $server, $defdepth, $depths); }; #- SVGA screen section. print F qq( # The Colour SVGA server ); if (member($O->{server}, @svgaservers)) { &$screen("svga", $o->{default_depth}, $O->{type}, $O->{depth}); } else { &$screen("svga", '', "Generic VGA", { 8 => [[ 320, 200 ]] }); } &$screen("vga16", '', (member($O->{server}, "Mono", "VGA16") ? $O->{type} : "Generic VGA"), { '' => [[ 640, 480 ], [ 800, 600 ]]}); &$screen("vga2", '', (member($O->{server}, "Mono", "VGA16") ? $O->{type} : "Generic VGA"), { '' => [[ 640, 480 ], [ 800, 600 ]]}); &$screen("accel", $o->{default_depth}, $O->{type}, $O->{depth}); &$screen("fbdev", $o->{default_depth}, $O->{type}, $O->{depth}); print G qq( Section "Screen" Identifier "screen1" Device "$O->{type}" Monitor "$o->{monitor}{type}" ); #- bpp 32 not handled by XF4 $subscreen->(*G, "svga", min($o->{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($o->{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 ' InputDevice "Mouse1" "CorePointer" '; $o->{mouse}{auxmouse} and print G ' InputDevice "Mouse2" "SendCoreEvents" '; foreach (1..@{$o->{wacom}}) { print G qq( InputDevice "Stylus$_" "AlwaysCore" InputDevice "Eraser$_" "AlwaysCore" InputDevice "Cursor$_" "AlwaysCore" ); } print G ' InputDevice "Keyboard1" "CoreKeyboard" EndSection '; #-" close F; close G; } sub XF86check_link { my ($ext) = @_; my $f = "$prefix/etc/X11/XF86Config$ext"; touch($f); my $l = "$prefix/usr/X11R6/lib/X11/XF86Config$ext"; if (-e $l && (stat($f))[1] != (stat($l))[1]) { #- compare the inode, must be the sames -e $l and unlink($l) || die "can't remove bad $l"; symlinkf "../../../../etc/X11/XF86Config$ext", $l; } } sub info { my ($o) = @_; my $info; $info .= _("Keyboard layout: %s\n", $o->{keyboard}{xkb_keymap}); $info .= _("Mouse type: %s\n", $o->{mouse}{XMOUSETYPE}); $info .= _("Mouse device: %s\n", $o->{mouse}{device}) if $::expert; $info .= _("Monitor: %s\n", $o->{monitor}{type}); $info .= _("Monitor HorizSync: %s\n", $o->{monitor}{hsyncrange}) if $::expert; $info .= _("Monitor VertRefresh: %s\n", $o->{monitor}{vsyncrange}) if $::expert; $info .= _("Graphic card: %s\n", $o->{card}{type}); $info .= _("Graphic memory: %s kB\n", $o->{card}{memory}) if $o->{card}{memory}; if ($o->{default_depth} and my $depth = $o->{card}{depth}{$o->{default_depth}}) { $info .= _("Color depth: %s\n", translate($depths{$o->{default_depth}})); $info .= _("Resolution: %s\n", join "x", @{$depth->[0]}) if $depth && !is_empty_array_ref($depth->[0]); } $info .= _("XFree86 server: %s\n", $o->{card}{server}) if $o->{card}{server}; $info .= _("XFree86 driver: %s\n", $o->{card}{driver}) if $o->{card}{driver}; $info; } sub show_info { my ($o) = @_; $in->ask_warn('', info($o)); } #- Program entry point. sub main { my ($o, $cardOptions); ($prefix, $o, $in, $cardOptions, $install) = @_; $o ||= {}; XF86check_link(''); XF86check_link('-4'); { my $w = $in->wait_message('', _("Preparing X-Window configuration"), 1); $o->{card} = cardConfiguration($o->{card}, $::noauto, $cardOptions); $o->{monitor} = monitorConfiguration($o->{monitor}, $o->{card}{server} eq 'FBDev'); } my $ok = resolutionsConfiguration($o, $::auto); $ok &&= testFinalConfig($o, $::auto, $o->{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') unless $::isStandalone; my $f; $in->ask_from_entries_refH_powered( { title => 'XFdrake', messages => _("What do you want to do?"), cancel => '', }, [ { format => sub { $_[0][0] }, val => \$f, list => [ [ _("Change Monitor") => sub { $o->{monitor} = monitorConfiguration() } ], [ _("Change Graphic card") => sub { $o->{card} = cardConfiguration('', 'noauto', $cardOptions) } ], if_($::expert, [ _("Change Server options") => sub { optionsConfiguration($o) } ]), [ _("Change Resolution") => sub { resolutionsConfiguration($o) } ], [ _("Show information") => sub { show_info($o) } ], [ _("Test again") => sub { $ok = testFinalConfig($o, 1) } ], [ _("Quit") => sub { $quit = 1 } ], ], } ]); $f->[1]->(); $in->kill; } if (!$ok) { $ok = $in->ask_yesorno('', _("Keep the changes? Current configuration is: %s", info($o))); } if ($ok) { unless ($::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 "../..$o->{card}{prog}", "$prefix/etc/X11/X"; } } if ($::isStandalone && $0 =~ /Xdrakres/) { my $found; foreach (@window_managers) { if (`pidof "$_"` > 0) { if ($in->ask_okcancel('', _("Please relog into %s to activate the changes", ucfirst $_), 1)) { fork and $in->exit; system("kwmcom logout") if /kwm/; system("dcop kdesktop default logout") if /kwin/; system("save-session --kill") if /gnome-session/; system("killall -QUIT icewm") if /icewm/; 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") unless `pidof "$wm"` > 0; }, $_; } $found = 1; last; } } $in->ask_warn('', _("Please log out and then use Ctrl-Alt-BackSpace")) unless $found; } else { $in->set_help('configureXxdm') unless $::isStandalone; my $run = exists $o->{xdm} ? $o->{xdm} : $::auto || $in->ask_yesorno(_("X at startup"), _("I can set up your computer to automatically start X upon booting. Would you like X to start when you reboot?"), 1); any::runlevel($prefix, $run ? 5 : 3) unless $::testing; } run_program::rooted($prefix, "chkconfig", "--del", "gpm") if $o->{mouse}{device} =~ /ttyS/ && !$::isStandalone; } } 1;