diff options
Diffstat (limited to 'lib/Xconfig/xfree.pm')
-rw-r--r-- | lib/Xconfig/xfree.pm | 207 |
1 files changed, 131 insertions, 76 deletions
diff --git a/lib/Xconfig/xfree.pm b/lib/Xconfig/xfree.pm index 5cba3ee..1e5eaaa 100644 --- a/lib/Xconfig/xfree.pm +++ b/lib/Xconfig/xfree.pm @@ -1,5 +1,7 @@ package Xconfig::xfree; # $Id$ +my ($Revision) = '$Revision$' =~ /(\d+)/; + use diagnostics; use strict; @@ -8,8 +10,8 @@ use Xconfig::parse; #- mostly internal only sub new { - my ($class, $val) = @_; - bless $val, $class; + my ($class, $raw) = @_; + @$raw && bless { raw => $raw }, $class; } sub _conf_files() { @@ -22,11 +24,14 @@ sub _conf_files() { sub read_and_prepare_write { my ($class) = @_; my $file = find { -f $_ } _conf_files(); - my $raw_X = $class->new(Xconfig::parse::read_XF86Config($file)); + my $raw_X = $class->new(Xconfig::parse::read_XF86Config($file)) or return; my $before = $raw_X->prepare_write; - if (my ($Keyboard) = $raw_X->get_InputDevices('Keyboard')) { - $Keyboard->{Driver}{val} = 'keyboard'; + if (my ($keyboard) = $raw_X->get_InputDevices('keyboard')) { + $keyboard->{Driver}{val} = 'kbd'; + } + if (my ($keyboard) = $raw_X->get_InputDevices('Keyboard')) { + $keyboard->{Driver}{val} = 'kbd'; } #- ugly hack to fix empty ModeLine lines, XFdrake seems to generate some, but where??? @@ -56,35 +61,60 @@ sub write { #- keep it for old programs still using this name symlink basename($file), "$::prefix/etc/X11/XF86Config"; } - Xconfig::parse::write_XF86Config($raw_X, $file); + set_Revision($raw_X); + Xconfig::parse::write_XF86Config($raw_X->{raw}, $file); } sub prepare_write { my ($raw_X) = @_; - join('', Xconfig::parse::prepare_write_XF86Config($raw_X)); + set_Revision($raw_X); + join('', Xconfig::parse::prepare_write_XF86Config($raw_X->{raw})); } sub empty_config { my ($class) = @_; $class->new(Xconfig::parse::read_XF86Config_from_string(our $default_header)); } +my $mark = '# File generated by XFdrake'; +sub get_Revision { + my ($raw_X) = @_; + my $first = $raw_X->{raw}[0]; + $first->{pre_comment} =~ /^\Q$mark\E \(rev (\d+)\)/ && $1; +} +sub set_Revision { + my ($raw_X) = @_; + my $first = $raw_X->{raw}[0]; + my $first_comment = $first->{pre_comment}; + + my $was_there = $first_comment =~ s/^\Q$mark\E.*\n//; + $first->{pre_comment} = "$mark (rev $Revision)\n" . ($was_there ? '' : "\n") . $first_comment; +} + ################################################################################ # keyboard ##################################################################### ################################################################################ my @keyboard_fields = qw(XkbLayout XkbModel XkbDisable XkbOptions XkbCompat); sub get_keyboard { my ($raw_X) = @_; - my $raw_kbd = first(map { $raw_X->get_InputDevices($_) } 'keyboard', 'kbd') or die "no keyboard section"; + my $raw_kbd = _raw_get_keyboard($raw_X) or die "no keyboard section"; raw_export_section($raw_kbd, \@keyboard_fields); } sub set_keyboard { my ($raw_X, $kbd) = @_; - my $raw_kbd = first(map { $raw_X->get_InputDevices($_) } 'keyboard', 'kbd') || _new_keyboard_section($raw_X); + my $raw_kbd = _raw_get_keyboard($raw_X) || _new_keyboard_section($raw_X); raw_import_section($raw_kbd, $kbd); _set_Option('keyboard', $raw_kbd, keys %$kbd); } +sub _raw_get_keyboard { + my ($raw_X) = @_; + first($raw_X->get_Sections('InputDevice', sub { + my ($entry) = @_; + my $Driver = val($entry->{Driver}); + $Driver eq 'kbd' || $Driver eq 'evdev' && val($entry->{XkbLayout}); + })); +} sub _new_keyboard_section { my ($raw_X) = @_; - my $raw_kbd = { Identifier => { val => 'Keyboard1' }, Driver => { val => 'keyboard' } }; + my $raw_kbd = { Identifier => { val => 'Keyboard1' }, Driver => { val => 'kbd' } }; $raw_X->add_Section('InputDevice', $raw_kbd); my $layout = get_ServerLayout($raw_X)->{InputDevice} ||= []; @@ -97,38 +127,44 @@ sub _new_keyboard_section { ################################################################################ # mouse ######################################################################## ################################################################################ -#- example: { Protocol => 'IMPS/2', Device => '/dev/psaux', Emulate3Buttons => undef, Emulate3Timeout => 50, ZAxisMapping => [ '4 5', '6 7' ] } -my @mouse_fields = qw(Protocol Device ZAxisMapping Emulate3Buttons Emulate3Timeout); #-); +#- example mouse: { Protocol => 'IMPS/2', Device => '/dev/psaux', Emulate3Buttons => undef, Emulate3Timeout => 50, ZAxisMapping => [ '4 5', '6 7' ] } +#- example evdev: { vendor => '0x045e', product => '0x008c' } +my @mouse_fields = qw(Protocol Device ZAxisMapping Emulate3Buttons Emulate3Timeout vendor product); #-); sub get_mice { my ($raw_X) = @_; - my @raw_mice = $raw_X->get_InputDevices('mouse'); + my @raw_mice = $raw_X->get_Sections('InputDevice', \&_is_mouse); map { raw_export_section($_, \@mouse_fields) } @raw_mice; } sub set_mice { my ($raw_X, @mice) = @_; - my @raw_mice = _new_mouse_sections($raw_X, int @mice); + my @raw_mice = _new_mouse_sections($raw_X, map { $_->{Protocol} ? 'mouse' : 'evdev' } @mice); mapn { my ($raw_mouse, $mouse) = @_; raw_import_section($raw_mouse, $mouse); _set_Option('mouse', $raw_mouse, keys %$mouse); } \@raw_mice, \@mice; } +sub _is_mouse { + my ($entry) = @_; + my $Driver = val($entry->{Driver}); + $Driver eq 'mouse' || $Driver eq 'evdev' && !val($entry->{XkbLayout}); +} sub _new_mouse_sections { - my ($raw_X, $nb_new) = @_; - $raw_X->remove_InputDevices('mouse'); + my ($raw_X, @Drivers) = @_; + $raw_X->remove_Section('InputDevice', \&_is_mouse); my $layout = get_ServerLayout($raw_X)->{InputDevice} ||= []; @$layout = grep { $_->{val} !~ /^"Mouse/ } @$layout; - $nb_new or return; + @Drivers or return; - my @l = map { - my $h = { Identifier => { val => "Mouse$_" }, Driver => { val => 'mouse' } }; + my @l = map_index { + my $h = { Identifier => { val => 'Mouse' . ($::i + 1) }, Driver => { val => $_ } }; $raw_X->add_Section('InputDevice', $h); - } (1 .. $nb_new); + } @Drivers; push @$layout, { val => qq("Mouse1" "CorePointer") }; - push @$layout, { val => qq("Mouse$_" "SendCoreEvents") } foreach 2 .. $nb_new; + push @$layout, { val => qq("Mouse$_" "SendCoreEvents") } foreach 2 .. @Drivers; @l; } @@ -139,30 +175,40 @@ sub _new_mouse_sections { ################################################################################ sub get_resolution { my ($raw_X, $o_Screen) = @_; + first(get_resolutions($raw_X, $o_Screen)); +} +sub get_resolutions { + my ($raw_X, $o_Screen) = @_; my $Screen = $o_Screen || $raw_X->get_default_screen or return {}; my $depth = val($Screen->{DefaultColorDepth} || $Screen->{DefaultDepth}); my $Display = find { !$depth || val($_->{l}{Depth}) eq $depth } @{$Screen->{Display} || []} or return {}; - $Display->{l}{Virtual} && val($Display->{l}{Virtual}) =~ /(\d+)\s+(\d+)/ or - val($Display->{l}{Modes}) =~ /(\d+)x(\d+)/ or return {}; - { X => $1, Y => $2, Depth => val($Display->{l}{Depth}) }; + my $s = val($Display->{l}{Virtual} || $Display->{l}{Modes}); + my @l; + while ($s =~ /(\d+)(x|\s+)(\d+)/g) { + push @l, { X => $1, Y => $3, Depth => val($Display->{l}{Depth}) }; + } + @l; } -sub set_resolution { - my ($raw_X, $resolution, $o_Screen_) = @_; +sub set_resolutions { + my ($raw_X, $resolutions, $o_Screen) = @_; - foreach my $Screen ($o_Screen_ ? $o_Screen_ : $raw_X->get_Sections('Screen')) { + foreach my $Screen ($o_Screen ? $o_Screen : $raw_X->get_Sections('Screen')) { $Screen ||= $raw_X->get_default_screen or internal_error('no screen'); - my $Mode_name = (any { $_->{l}{Modes} } @{$Screen->{Display} || []}) ? 'Modes' : 'Virtual'; - my $Mode = sprintf($Mode_name eq 'Modes' ? '"%dx%d"' : '%d %d', @$resolution{'X', 'Y'}); + #- if the existing config is using Virtual, keep Virtual, otherwise default to Modes + my $Mode_name = (any { $_->{l}{Virtual} } @{$Screen->{Display} || []}) ? 'Virtual' : 'Modes'; + + my @l = $Mode_name eq 'Modes' ? @$resolutions : first(@$resolutions); + my @Modes = map { sprintf($Mode_name eq 'Modes' ? '"%dx%d"' : '%d %d', @$_{'X', 'Y'}) } @l; delete $Screen->{DefaultDepth}; - $Screen->{DefaultColorDepth} = { val => $resolution->{Depth} eq '32' ? 24 : $resolution->{Depth} }; + $Screen->{DefaultColorDepth} = { val => $resolutions->[0]{Depth} eq '32' ? 24 : $resolutions->[0]{Depth} }; $Screen->{Display} = [ map { - { l => { Depth => { val => $_ }, $Mode_name => { val => $Mode } } }; + { l => { Depth => { val => $_ }, $Mode_name => { val => join(' ', @Modes) } } }; } 8, 15, 16, 24 ]; } - add_gtf_ModeLines($raw_X, $resolution); + add_gtf_ModeLines($raw_X, $resolutions); } @@ -250,7 +296,6 @@ sub set_synaptics { @$layout = grep { $_->{val} !~ /^"SynapticsMouse/ } @$layout; @synaptics or return; - add_load_module($raw_X, "synaptics"); each_index { my $synaptics_mouse = $_; @@ -261,9 +306,7 @@ sub set_synaptics { Driver => { val => "synaptics" }, }; my %opts = ( - Device => $synaptics_mouse->{Device}, - Protocol => $synaptics_mouse->{Protocol}, - $synaptics_mouse->{ALPS} ? ( + if_($synaptics_mouse->{ALPS}, #- from /usr/share/doc/synaptics-0.14.0/README.alps #- and http://qa.mandrakesoft.com/show_bug.cgi?id=14512 LeftEdge => 120, @@ -272,9 +315,7 @@ sub set_synaptics { BottomEdge => 650, FingerLow => 14, FingerHigh => 15, - MaxTapTime => 180, MaxTapMove => 110, - EmulateMidButtonTime => 75, VertScrollDelta => 20, HorizScrollDelta => 20, MinSpeed => '0.8', @@ -284,24 +325,9 @@ sub set_synaptics { EdgeMotionMaxSpeed => 200, UpDownScrolling => 1, CircularScrolling => 1, - CircScrollDelta => '0.1', CircScrollTrigger => 2, UpDownScrolling => 0, - ) : ( - #- from /usr/share/doc/synaptics-0.14.0/INSTALL - LeftEdge => 1700, - RightEdge => 5300, - TopEdge => 1700, - BottomEdge => 4200, - FingerLow => 25, - FingerHigh => 30, - MaxTapTime => 180, - MaxTapMove => 220, - VertScrollDelta => 100, - MinSpeed => '0.09', - MaxSpeed => '0.18', - AccelFactor => '0.0015', - ), + ), #- use default driver options for non-ALPS SHMConfig => "on", ); while (my ($k, $v) = each %opts) { @@ -356,21 +382,24 @@ sub default_ModeLine() { } sub add_gtf_ModeLines { - my ($raw_X, $resolution) = @_; + my ($raw_X, $resolutions) = @_; my $banner = 'modeline generated by gtf(1) [handled by XFdrake]'; - my $res = $resolution->{X} . 'x' . $resolution->{Y}; + my $res = $resolutions->[0]{X} . 'x' . $resolutions->[0]{Y}; my @to_add; if ($res ne '1280x1024' && ($res eq '1400x1050' || $res eq '1152x864' || $Xconfig::xfree::resolution2ratio{$res} ne '4/3')) { - @to_add = map { + @to_add = map { + my $resolution = $_; + map { my $s = run_program::rooted_get_stdout($::prefix, 'gtf', $resolution->{X}, $resolution->{Y}, $_); if (my ($name, $val) = $s =~ /ModeLine\s*"(.*)"(.*)/i) { chomp $val; $name =~ s/\.00//; #- nicer that way { val => qq("${name}"$val), pre_comment => "# $banner\n" }; } else { () } - } reverse(sort_numbers(@Xconfig::xfree::vfreqs)); + } reverse(sort_numbers(@Xconfig::xfree::vfreqs)); + } @$resolutions; } $raw_X->set_monitors(map { @@ -465,6 +494,28 @@ sub set_load_module { } +################################################################################ +# ModulePath ################################################################### +################################################################################ +sub get_ModulePaths { + my ($raw_X) = @_; + my $raw_Files = $raw_X->get_Section('Files') or return; + my $Files = raw_export_section($raw_Files, ['ModulePath']); + @{$Files->{ModulePath} || []}; +} +sub add_ModulePath { + my ($raw_X, $ModulePath) = @_; + my $raw_Files = $raw_X->get_Section('Files') || $raw_X->add_Section('Files', {}); + + push @{$raw_Files->{ModulePath}}, { val => $ModulePath } if !member($ModulePath, $raw_X->get_ModulePaths); +} +sub remove_ModulePath { + my ($raw_X, $ModulePath) = @_; + my $raw_Files = $raw_X->get_Section('Files') or return; + my @l = grep { $_->{val} ne $ModulePath && $_->{val} ne "$ModulePath/" } @{$raw_Files->{ModulePath}}; + $raw_Files->{ModulePath} = \@l; +} + #-############################################################################## #- helpers #-############################################################################## @@ -483,7 +534,7 @@ sub get_InputDevices { } sub remove_InputDevices { my ($raw_X, $Driver) = @_; - $raw_X->remove_Section('InputDevice', sub { val($_[0]{Driver}) ne $Driver }); + $raw_X->remove_Section('InputDevice', sub { val($_[0]{Driver}) eq $Driver }); } sub get_ServerLayout { @@ -524,23 +575,25 @@ sub add_Section { my %order = map_index { { lc($_) => $::i } } @suggested_ordering; my $e = { name => $Section, l => $h }; my $added; - @$raw_X = map { + my $raw = $raw_X->{raw}; + @$raw = map { if ($order{lc $_->{name}} > $order{lc $Section} && !$added) { $added = 1; ($e, $_); } else { $_ } - } @$raw_X; - push @$raw_X, $e if !$added; + } @$raw; + push @$raw, $e if !$added; $h; } sub remove_Section { my ($raw_X, $Section, $o_when) = @_; - @$raw_X = grep { $_->{name} ne $Section || $o_when && $o_when->($_->{l}) } @$raw_X; + my $raw = $raw_X->{raw}; + @$raw = grep { $_->{name} ne $Section || $o_when && !$o_when->($_->{l}) } @$raw; $raw_X; } sub get_Sections { my ($raw_X, $Section, $o_when) = @_; - map { if_(lc($_->{name}) eq lc($Section) && (!$o_when || $o_when->($_->{l})), $_->{l}) } @$raw_X; + map { if_(lc($_->{name}) eq lc($Section) && (!$o_when || $o_when->($_->{l})), $_->{l}) } @{$raw_X->{raw}}; } sub get_Section { my ($raw_X, $Section, $o_when) = @_; @@ -564,7 +617,7 @@ sub val { sub ModeLine_from_string { my ($s) = @_; my $raw_X_for_ModeLine = Xconfig::parse::read_XF86Config_from_string($s); - get_Section($raw_X_for_ModeLine, 'Monitor')->{ModeLine}; + get_Section(Xconfig::xfree->new($raw_X_for_ModeLine), 'Monitor')->{ModeLine}; } @@ -591,7 +644,7 @@ our %ratio2resolutions = ( # 1.25 '5/4' => [ qw(640x512 720x576 1280x1024 1800x1440) ], - # SXGA=1280x1024 QSXGA=2560x2048 + # SXGA=1280x1024 QSXGA=2560x2048, HSXGA=5120x4096 # 1.33 '4/3' => [ @@ -599,21 +652,24 @@ our %ratio2resolutions = ( 1024x768 1152x864 1280x960 1400x1050 1600x1200 1920x1440 2048x1536), # 768x576 1792x1344 1856x1392 # DBLSCAN: 400x300 416x312 512x384 576x432 700x525 896x672 928x696 960x720 - ], # VGA=640x480, SVGA=800x600, XGA=1024x768, SXGA+=1400x1050, UXGA=1600x1200, QXGA=2048x1536 QSXGA+=2800x2100, QUXGA=3200x2400 + ], # VGA=640x480, SVGA=800x600, XGA=1024x768, SXGA+=1400x1050, + # UXGA=1600x1200, QXGA=2048x1536 QSXGA+=2800x2100, QUXGA=3200x2400, + # HUXGA=6400x4800 # 1.5 '3/2' => [ qw(360x240 720x480 1152x768) ], # 576x384 (DBLSCAN of 1152x768) # 1.6 - '16/10' => [ qw(1280x800 1440x900 1600x1000 1680x1050 1920x1200) ], # 320x200 640x400 960x600 2560x1600 - # WSXGA+=1680x1050, WUXGA=1920x1200, WQUXGA=3840x2400 + '16/10' => [ qw(1280x800 1440x900 1600x1000 1680x1050 1920x1200 2560x1600) ], # 320x200 640x400 960x600 3840x2400 + # WSXGA+=1680x1050, WUXGA=1920x1200, WQXGA=2560x1600, WQUXGA=3840x2400, WHUXGA=7680x4800 # 1.67 '15/9' => [ qw(1280x768) ], # 800x480 # WXGA=1280x768 or ??? (should be 1366x768) # 1.78 - '16/9' => [ qw(1280x720 1600x900 1920x1080) ], # 960x540 1024x576 + '16/9' => [ qw(1280x720 1600x900 1920x1080) ], # 960x540 1024x576 1360x765 + # UHDTV=7680x4320 # now more weird things @@ -628,7 +684,8 @@ our %ratio2resolutions = ( # '17/12' => [ qw(544x384) ] , # 1.56 - # '25/16' => [ qw(1600x1024) ], # WSXGA, (DBLSCAN 800x512) + # '25/16' => [ qw(1600x1024 3200x2048 6400x4096) ], # (DBLSCAN 800x512) + # WSXGA=1600x1024, WQSXGA=3200x2048, WHSXGA=6400x4096 # 1.707 # '128/75' => [ qw(1024x600) ], @@ -677,18 +734,16 @@ foreach my $ratio (keys %ratio2resolutions) { } our $default_header = <<'END'; -# File generated by XFdrake. - # ********************************************************************** # Refer to the xorg.conf man page for details about the format of # this file. # ********************************************************************** Section "Files" - # Multiple FontPath entries are allowed (they are concatenated together) - # By default, Mandrake 6.0 and later now use a font server independent of - # the X server to render fonts. + # font server independent of the X server to render fonts. FontPath "unix/:-1" + # minimal fonts to allow X to run without xfs + FontPath "/usr/share/fonts/misc:unscaled" EndSection Section "ServerFlags" |