diff --git a/Source/Terminals.Common/Configuration/FavoriteConfigurationElement.cs b/Source/Terminals.Common/Configuration/FavoriteConfigurationElement.cs
index b7880e25..4f7483a3 100644
--- a/Source/Terminals.Common/Configuration/FavoriteConfigurationElement.cs
+++ b/Source/Terminals.Common/Configuration/FavoriteConfigurationElement.cs
@@ -297,20 +297,21 @@ public Int32 IdleTimeout
get
{
Int32 val = (Int32)this["idleTimeout"];
- if (val > 600)
- val = 600;
+ if (val > 240)
+ val = 240;
- if (val < 10)
- val = 10;
+ // 0 means the idle timeout is disabled (never disconnect), so keep it as is.
+ if (val < 0)
+ val = 0;
return val;
}
set
{
- if (value > 240)
+ if (value > 240)
value = 240;
- if (value < 0)
+ if (value < 0)
value = 0;
this["idleTimeout"] = value;
diff --git a/Source/Terminals.Plugins.Rdp/RdpExtendedSettingsControl.Designer.cs b/Source/Terminals.Plugins.Rdp/RdpExtendedSettingsControl.Designer.cs
index 64d9dcde..e4e47817 100644
--- a/Source/Terminals.Plugins.Rdp/RdpExtendedSettingsControl.Designer.cs
+++ b/Source/Terminals.Plugins.Rdp/RdpExtendedSettingsControl.Designer.cs
@@ -122,9 +122,9 @@ private void InitializeComponent()
this.label26.AutoSize = true;
this.label26.Location = new System.Drawing.Point(239, 167);
this.label26.Name = "label26";
- this.label26.Size = new System.Drawing.Size(68, 13);
+ this.label26.Size = new System.Drawing.Size(116, 13);
this.label26.TabIndex = 33;
- this.label26.Text = "Idle Timeout:";
+ this.label26.Text = "Idle Timeout (0=off):";
//
// IdleTimeoutMinutesTextBox
//
diff --git a/Source/Terminals.Plugins.Rdp/RdpTimeOutOptions.cs b/Source/Terminals.Plugins.Rdp/RdpTimeOutOptions.cs
index f1915c66..43553856 100644
--- a/Source/Terminals.Plugins.Rdp/RdpTimeOutOptions.cs
+++ b/Source/Terminals.Plugins.Rdp/RdpTimeOutOptions.cs
@@ -55,17 +55,19 @@ public Int32 ConnectionTimeout
private int idleTimeout = 240;
///
- /// Gets or sets the value in range 10 - 600, default is 240
+ /// Gets or sets the idle timeout in minutes. Valid range is 10 - 240, default is 240.
+ /// A value of 0 disables the idle timeout, so the session is never disconnected for
+ /// being idle (maps to MsRdpClient AdvancedSettings.MinutesToIdleTimeout = 0).
///
public Int32 IdleTimeout
{
get
{
- return CorrectValueToInterval(10, 240, idleTimeout);
+ return idleTimeout <= 0 ? 0 : CorrectValueToInterval(10, 240, idleTimeout);
}
set
{
- idleTimeout = CorrectValueToInterval(10, 240, value);
+ idleTimeout = value <= 0 ? 0 : CorrectValueToInterval(10, 240, value);
}
}
diff --git a/Source/Tests/Configuration/FavoriteConfigurationElementTests.cs b/Source/Tests/Configuration/FavoriteConfigurationElementTests.cs
index 172e5eb1..8ab936c5 100644
--- a/Source/Tests/Configuration/FavoriteConfigurationElementTests.cs
+++ b/Source/Tests/Configuration/FavoriteConfigurationElementTests.cs
@@ -110,6 +110,38 @@ public void WithCredential_ResolveUserName_ReturnsCredentialUserName()
Assert.AreEqual(EXPECTED_USER, favoriteSecurity.ResolveUserName(), "UserName is primary resolved from Credential.");
}
+ [TestMethod]
+ public void IdleTimeoutZero_SetGet_StaysZeroToDisableTimeout()
+ {
+ FavoriteConfigurationElement favorite = this.CreateFavorite();
+ favorite.IdleTimeout = 0;
+ Assert.AreEqual(0, favorite.IdleTimeout, "0 means the idle timeout is disabled and must survive a set/get round-trip (issue #225).");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutNegative_SetGet_NormalizedToZero()
+ {
+ FavoriteConfigurationElement favorite = this.CreateFavorite();
+ favorite.IdleTimeout = -1;
+ Assert.AreEqual(0, favorite.IdleTimeout, "Negative idle timeout is normalized to 0 (disabled), not forced up to the old minimum of 10.");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutAboveMaximum_SetGet_ClampedToMaximum()
+ {
+ FavoriteConfigurationElement favorite = this.CreateFavorite();
+ favorite.IdleTimeout = 1000;
+ Assert.AreEqual(240, favorite.IdleTimeout, "Idle timeout is clamped to the MsRdpClient maximum of 240 minutes.");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutWithinRange_SetGet_KeepsValue()
+ {
+ FavoriteConfigurationElement favorite = this.CreateFavorite();
+ favorite.IdleTimeout = 120;
+ Assert.AreEqual(120, favorite.IdleTimeout, "A valid idle timeout has to be preserved.");
+ }
+
private FavoriteConfigurationSecurity CreateFavoriteConfigurationSecurity()
{
FavoriteConfigurationElement favorite = this.CreteFavoriteWithCredential();
diff --git a/Source/Tests/Connections/RdpTimeOutOptionsTests.cs b/Source/Tests/Connections/RdpTimeOutOptionsTests.cs
new file mode 100644
index 00000000..edc1c8d5
--- /dev/null
+++ b/Source/Tests/Connections/RdpTimeOutOptionsTests.cs
@@ -0,0 +1,56 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Terminals.Data;
+
+namespace Tests.Connections
+{
+ ///
+ /// Tests for issue #225: it has to be possible to disable the RDP idle timeout
+ /// (never disconnect an idle session) by setting it to 0. Previously any value
+ /// below 10 was forced up to 10, so 0 and -1 silently became 10.
+ ///
+ [TestClass]
+ public class RdpTimeOutOptionsTests
+ {
+ [TestMethod]
+ public void IdleTimeoutZero_SetGet_StaysZeroToDisableTimeout()
+ {
+ var options = new RdpTimeOutOptions { IdleTimeout = 0 };
+ Assert.AreEqual(0, options.IdleTimeout, "0 disables the idle timeout and must not be forced up to the minimum.");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutNegative_SetGet_NormalizedToZero()
+ {
+ var options = new RdpTimeOutOptions { IdleTimeout = -5 };
+ Assert.AreEqual(0, options.IdleTimeout, "A negative idle timeout is normalized to 0 (disabled).");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutBelowMinimumButPositive_SetGet_ClampedToMinimum()
+ {
+ var options = new RdpTimeOutOptions { IdleTimeout = 5 };
+ Assert.AreEqual(10, options.IdleTimeout, "A positive value below the minimum is still clamped to 10; only 0 disables the timeout.");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutAboveMaximum_SetGet_ClampedToMaximum()
+ {
+ var options = new RdpTimeOutOptions { IdleTimeout = 1000 };
+ Assert.AreEqual(240, options.IdleTimeout, "Idle timeout is clamped to the MsRdpClient maximum of 240 minutes.");
+ }
+
+ [TestMethod]
+ public void IdleTimeoutWithinRange_SetGet_KeepsValue()
+ {
+ var options = new RdpTimeOutOptions { IdleTimeout = 120 };
+ Assert.AreEqual(120, options.IdleTimeout, "A valid idle timeout has to be preserved.");
+ }
+
+ [TestMethod]
+ public void DefaultIdleTimeout_IsTwoHundredForty()
+ {
+ var options = new RdpTimeOutOptions();
+ Assert.AreEqual(240, options.IdleTimeout, "The default idle timeout is unchanged at 240 minutes.");
+ }
+ }
+}
diff --git a/Source/Tests/Tests.csproj b/Source/Tests/Tests.csproj
index 4c76e091..875e9fb0 100644
--- a/Source/Tests/Tests.csproj
+++ b/Source/Tests/Tests.csproj
@@ -131,6 +131,7 @@
+
Component