diff --git a/unix/KasmVNC/ConfigKey.pm b/unix/KasmVNC/ConfigKey.pm index f60fd63..b8ff425 100644 --- a/unix/KasmVNC/ConfigKey.pm +++ b/unix/KasmVNC/ConfigKey.pm @@ -32,13 +32,6 @@ sub validate { return if $self->isValueBlank(); - if ($self->{validator}) { - $self->resolveValidatorFromFunction() if (ref $self->{validator} eq "CODE"); - - $self->{validator}->validate($self); - return; - } - switch($self->{type}) { case INT { $self->validateInt(); @@ -47,6 +40,13 @@ sub validate { $self->validateBoolean(); } } + + if ($self->{validator}) { + $self->resolveValidatorFromFunction() if (ref $self->{validator} eq "CODE"); + + $self->{validator}->validate($self); + return; + } } sub resolveValidatorFromFunction { diff --git a/unix/kasmvnc_defaults.yaml b/unix/kasmvnc_defaults.yaml index afad666..0ed63ce 100644 --- a/unix/kasmvnc_defaults.yaml +++ b/unix/kasmvnc_defaults.yaml @@ -134,6 +134,10 @@ encoding: compare_framebuffer: auto zrle_zlib_level: auto hextile_improved_compression: true + scrolling: + detect_vertical_scrolling: false + detect_horizontal_scrolling: false + scroll_detect_threshold: 25% server: http: diff --git a/unix/vncserver b/unix/vncserver index 1ac99c8..7a9588f 100755 --- a/unix/vncserver +++ b/unix/vncserver @@ -1246,6 +1246,10 @@ sub DefineConfigToCLIConversion { pattern => qr/^(never|\d+)$/, errorMessage => "must be a number or 'never'" }); + my $percentValidator = KasmVNC::PatternValidator->new({ + pattern => qr/^(\d+%)$/, + errorMessage => "must be a number, followed by %" + }); my $allConfigKeysValidatorSub = sub { my @allConfigKeys = map { $_->configKeyNames() } @xvncOptions; @@ -1253,6 +1257,14 @@ sub DefineConfigToCLIConversion { allowedValues => [flatten(@allConfigKeys)] }) }; + my $deriveValueStripPercentSub = sub { + $self = shift; + + my $value = $self->configValue(); + $value =~ s/%$//; + + $value; + }; KasmVNC::CliOption::beforeIsActive(\&limitVncModeOptions); my $ipv4_regexp = '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}'; my $ipv6_regexp = '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))'; @@ -1999,20 +2011,10 @@ sub DefineConfigToCLIConversion { configKeys => [ KasmVNC::ConfigKey->new({ name => "encoding.video_encoding_mode.enter_video_encoding_mode.area_threshold", - validator => KasmVNC::PatternValidator->new({ - pattern => qr/^(\d+%)$/, - errorMessage => "must be a number, followed by %" - }), + validator => $percentValidator }) ], - deriveValueSub => sub { - $self = shift; - - my $value = $self->configValue(); - $value =~ s/%$//; - - $value; - } + deriveValueSub => $deriveValueStripPercentSub }), KasmVNC::CliOption->new({ name => 'VideoOutTime', @@ -2462,6 +2464,56 @@ sub DefineConfigToCLIConversion { }) ] }), + KasmVNC::CliOption->new({ + name => 'DetectScrolling', + configKeys => [ + KasmVNC::ConfigKey->new({ + name => "encoding.scrolling.detect_vertical_scrolling", + type => KasmVNC::ConfigKey::BOOLEAN + }) + ], + isActiveSub => sub { + $self = shift; + + my $value = $self->configValue(); + isPresent($value) && $value eq 'true'; + } + }), + KasmVNC::CliOption->new({ + name => 'DetectHorizontal', + configKeys => [ + KasmVNC::ConfigKey->new({ + name => "encoding.scrolling.detect_horizontal_scrolling", + type => KasmVNC::ConfigKey::BOOLEAN, + validator => KasmVNC::CallbackValidator->new({ + isValidCallback => sub { + my $value = shift; + + return 1 if $value eq "false"; + + ConfigValue("encoding.scrolling.detect_vertical_scrolling") eq "true"; + }, + errorMessage => "Detection of horizontal scrolling requires detection of vertical scrolling enabled" + }), + }) + ], + isActiveSub => sub { + $self = shift; + + my $value = $self->configValue(); + isPresent($value) && $value eq 'true'; + } + }), + KasmVNC::CliOption->new({ + name => 'ScrollDetectLimit', + configKeys => [ + KasmVNC::ConfigKey->new({ + name => "encoding.scrolling.scroll_detect_threshold", + validator => $percentValidator + }) + ], + deriveValueSub => $deriveValueStripPercentSub + }), ); %cliArgMap = map { ("-" . $_->{name}) => $_ } @xvncOptions; diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man index 206784c..2afd1fa 100644 --- a/unix/xserver/hw/vnc/Xvnc.man +++ b/unix/xserver/hw/vnc/Xvnc.man @@ -584,6 +584,23 @@ When this option is used, benchmarking results can be saved to a file specified .B -BenchmarkResults Save the benchmarking results to the specified file. Use this option together with \fB-Benchmark\fP to output the report to a custom file. +. +.TP +.B \-DetectScrolling +Try to detect scrolled sections in a changed area. + +Detect vertical scrolling on the screen and then use copyRects instead of +sending jpeg. A copy rect tells the client to copy a section of the screen and +paste it somewhere else. This significantly reduces bandwidth usage when someone +is scrolling down a page. +. +.TP +.B \-DetectHorizontal +With \fB-DetectScrolling\fP enabled, try to detect horizontal scrolls too, not just vertical. +. +.TP +.B \-ScrollDetectLimit +At least this % of the screen must change for scroll detection to happen, default 25. .SH USAGE WITH INETD By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched