Skip to content

Commit 0bc35c4

Browse files
committed
v2.17.4
1 parent aaa9dc5 commit 0bc35c4

File tree

14 files changed

+167
-21
lines changed

14 files changed

+167
-21
lines changed

client/common/changelog.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2.17.4 (04/09/2025)
2+
All:
3+
* Improved highlight colours used in log viewer. #1213
4+
* Fixed resize bar may be cut off when update banner is shown. #1465
5+
* Fixed broken link in preferences. #1467
6+
7+
18
2.17.3 (22/08/2025)
29
All:
310
* Improved native window colours in accordance with OS theme. #1213

client/common/version/windscribe_version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#define WINDSCRIBE_MAJOR_VERSION 2
44
#define WINDSCRIBE_MINOR_VERSION 17
5-
#define WINDSCRIBE_BUILD_VERSION 3
5+
#define WINDSCRIBE_BUILD_VERSION 4
66

77
// only one of these should be enabled; neither -> stable
88
//#define WINDSCRIBE_IS_BETA

client/gui/connectwindow/networktrustbutton.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ void NetworkTrustButton::onHoverEnter()
171171
void NetworkTrustButton::onHoverLeave()
172172
{
173173
startAnAnimation(opacityAnimation_, animProgress_, 0.7, ANIMATION_SPEED_FAST);
174-
174+
175175
// Hide tooltip if it was shown
176176
if (isTextElided_) {
177177
TooltipController::instance().hideTooltip(TOOLTIP_ID_ELIDED_TEXT);

client/gui/locationswindow/widgetlocations/configfooterinfo.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ void ConfigFooterInfo::mouseReleaseEvent(QMouseEvent * /*event*/)
176176

177177
void ConfigFooterInfo::onIconOpacityChanged(const QVariant &value, int index)
178178
{
179-
WS_ASSERT(index >= 0 && index < NUM_ICONS);
179+
if (index < 0 || index >= NUM_ICONS) {
180+
WS_ASSERT(false);
181+
return;
182+
}
180183
iconButtons_[index].opacity = value.toDouble();
181184
update();
182185
}

client/gui/log/logviewerwindow.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ void LogViewerWindow::highlightBlocks()
145145
if (isColorHighlighting_) {
146146
RandomColor color;
147147
color.setSeed(hash);
148-
int c = color.generate(RandomColor::RandomHue, isDarkTheme_ ? RandomColor::Dark : RandomColor::Light);
148+
149+
// Get the text color for contrast calculation
150+
QColor textColor = textEdit_->palette().color(QPalette::Text);
151+
int textColorRgb = (textColor.red() << 16) | (textColor.green() << 8) | textColor.blue();
152+
153+
int c = color.generateWithContrast(textColorRgb, RandomColor::RandomHue,
154+
isDarkTheme_ ? RandomColor::Dark : RandomColor::Light);
149155
auto brush = QBrush(QColor(c));
150156
blockFormat.setBackground(brush);
151157
} else {
@@ -163,7 +169,8 @@ void LogViewerWindow::onWordWrapToggled(bool wordWrap)
163169
void LogViewerWindow::onOsThemeChanged(bool isDarkTheme)
164170
{
165171
isDarkTheme_ = isDarkTheme;
166-
highlightBlocks();
172+
// Delay to ensure palette has updated after theme change
173+
QTimer::singleShot(100, this, [this]() { highlightBlocks(); });
167174
}
168175

169176
} //namespace LogViewer

client/gui/log/randomcolor.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "randomcolor.h"
1111
#include <cassert>
12+
#include <cmath>
13+
#include <algorithm>
1214

1315
/**
1416
* The map is formed with the help of the following sources:
@@ -273,3 +275,113 @@ int RandomColor::HSBtoRGB( double h, double s, double v ) const
273275
// Scale r, g, b to [0; 255] and pack them into a number 0xRRGGBB
274276
return (int(r * 255) << 16) + (int(g * 255) << 8) + int(b * 255);
275277
}
278+
279+
int RandomColor::generateWithContrast( int textColor, Color color, Luminosity luminosity )
280+
{
281+
double textLuminance = calculateRelativeLuminance(textColor);
282+
double targetLuminance;
283+
284+
if (luminosity == Dark) {
285+
// Dark mode - need dark background: (textLum + 0.05) / (bgLum + 0.05) >= 4.5
286+
targetLuminance = (textLuminance + 0.05) / 4.5 - 0.05;
287+
targetLuminance = std::max(0.05, std::min(0.4, targetLuminance)); // Keep backgrounds reasonably dark
288+
} else {
289+
// Light mode - need bright background: (bgLum + 0.05) / (textLum + 0.05) >= 4.5
290+
double minRequired = (textLuminance + 0.05) * 4.5 - 0.05;
291+
targetLuminance = std::max(0.6, std::min(0.9, minRequired)); // Keep backgrounds reasonably bright but not blinding
292+
}
293+
294+
// Generate base hue and saturation
295+
const ColorInfo& info = (color == RandomHue) ? getColorInfo(randomWithin({0, 359})) : colorMap[color];
296+
const int h = randomWithin(info.hRange);
297+
const int s = pickSaturation(info, luminosity);
298+
299+
// Generate color with exact target luminance
300+
return generateColorWithTargetLuminance(h, s, targetLuminance);
301+
}
302+
303+
double RandomColor::calculateContrastRatio( int color1, int color2 )
304+
{
305+
double lum1 = calculateRelativeLuminance(color1);
306+
double lum2 = calculateRelativeLuminance(color2);
307+
308+
if (lum1 < lum2) {
309+
std::swap(lum1, lum2);
310+
}
311+
312+
return (lum1 + 0.05) / (lum2 + 0.05);
313+
}
314+
315+
double RandomColor::calculateRelativeLuminance( int rgbColor )
316+
{
317+
double r = ((rgbColor >> 16) & 0xFF) / 255.0;
318+
double g = ((rgbColor >> 8) & 0xFF) / 255.0;
319+
double b = (rgbColor & 0xFF) / 255.0;
320+
321+
r = sRGBtoLinear(r);
322+
g = sRGBtoLinear(g);
323+
b = sRGBtoLinear(b);
324+
325+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
326+
}
327+
328+
double RandomColor::sRGBtoLinear( double value )
329+
{
330+
if (value <= 0.03928) {
331+
return value / 12.92;
332+
} else {
333+
return pow((value + 0.055) / 1.055, 2.4);
334+
}
335+
}
336+
337+
double RandomColor::linearTosRGB( double value )
338+
{
339+
if (value <= 0.0031308) {
340+
return value * 12.92;
341+
} else {
342+
return 1.055 * pow(value, 1.0/2.4) - 0.055;
343+
}
344+
}
345+
346+
int RandomColor::generateColorWithTargetLuminance( int h, int s, double targetLuminance ) const
347+
{
348+
// Convert HSV to RGB to get the hue and saturation ratios
349+
double tempColor = HSBtoRGB(h, s, 50); // Use 50% brightness as baseline
350+
int tempR = (int(tempColor) >> 16) & 0xFF;
351+
int tempG = (int(tempColor) >> 8) & 0xFF;
352+
int tempB = int(tempColor) & 0xFF;
353+
354+
// Calculate the relative contributions of R, G, B to luminance
355+
// L = 0.2126*R + 0.7152*G + 0.0722*B (in linear space)
356+
// We need to find a scaling factor that achieves target luminance
357+
358+
// Binary search for the right brightness multiplier
359+
double minBrightness = 0.0;
360+
double maxBrightness = 1.0;
361+
362+
for (int i = 0; i < 20; ++i) { // 20 iterations gives us good precision
363+
double testBrightness = (minBrightness + maxBrightness) / 2.0;
364+
365+
// Scale the RGB values by brightness
366+
int r = std::min(255, (int)(tempR * testBrightness * 2.0)); // *2 because we used 50% baseline
367+
int g = std::min(255, (int)(tempG * testBrightness * 2.0));
368+
int b = std::min(255, (int)(tempB * testBrightness * 2.0));
369+
370+
int testColor = (r << 16) | (g << 8) | b;
371+
double actualLuminance = calculateRelativeLuminance(testColor);
372+
373+
if (actualLuminance < targetLuminance) {
374+
minBrightness = testBrightness;
375+
} else {
376+
maxBrightness = testBrightness;
377+
}
378+
}
379+
380+
// Generate final color with calculated brightness
381+
double finalBrightness = (minBrightness + maxBrightness) / 2.0;
382+
int r = std::min(255, (int)(tempR * finalBrightness * 2.0));
383+
int g = std::min(255, (int)(tempG * finalBrightness * 2.0));
384+
int b = std::min(255, (int)(tempB * finalBrightness * 2.0));
385+
386+
return (r << 16) | (g << 8) | b;
387+
}

client/gui/log/randomcolor.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ class RandomColor
131131
*/
132132
void setSeed( int seed );
133133

134+
/**
135+
* Generates a color that has sufficient contrast with the specified text color.
136+
* Returns a random color with at least 4.5:1 contrast ratio, in RGB format (0xRRGGBB).
137+
*/
138+
int generateWithContrast( int textColor, Color color = RandomHue, Luminosity luminosity = Normal );
139+
140+
/**
141+
* Calculates the contrast ratio between two RGB colors.
142+
* Returns a value >= 1.0, where higher values indicate better contrast.
143+
*/
144+
static double calculateContrastRatio( int color1, int color2 );
145+
134146
private:
135147
struct SBRange
136148
{
@@ -157,6 +169,11 @@ class RandomColor
157169
int randomWithin( const Range& );
158170
int HSBtoRGB( double h, double s, double b ) const;
159171

172+
static double calculateRelativeLuminance( int rgbColor );
173+
static double sRGBtoLinear( double value );
174+
static double linearTosRGB( double value );
175+
int generateColorWithTargetLuminance( int h, int s, double targetLuminance ) const;
176+
160177
static const std::vector<ColorInfo> colorMap;
161178
std::default_random_engine randomEngine;
162179
#ifdef RANDOMCOLOR_THREAD_SAFE

client/gui/mainwindowcontroller.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2904,7 +2904,7 @@ void MainWindowController::getGraphicsRegionWidthAndHeight(int &width, int &heig
29042904
for (auto w : windowSizeManager_->windows()) {
29052905
if (windowSizeManager_->isExclusivelyExpanded(w)) {
29062906
width = w->boundingRect().width();
2907-
height = w->boundingRect().height();
2907+
height = w->boundingRect().height() + w->y();
29082908
height += preferences_->appSkin() == APP_SKIN_VAN_GOGH ? (UPDATE_WIDGET_HEIGHT * updateWidgetAnimationProgress_)*G_SCALE : 0;
29092909
return;
29102910
}
@@ -2929,9 +2929,9 @@ void MainWindowController::getGraphicsRegionWidthAndHeight(int &width, int &heig
29292929
if (QGuiApplication::platformName() == "xcb") {
29302930
// For X11, as soon as a window starts animating, treat it as if the height were the full height.
29312931
// Otherwise, some items ping-pong between positions and the animation looks wrong.
2932-
height = windowSizeManager_->windowHeight(w)*G_SCALE;
2932+
height = windowSizeManager_->windowHeight(w)*G_SCALE + w->y();
29332933
} else {
2934-
height = w->boundingRect().height();
2934+
height = w->boundingRect().height() + w->y();
29352935
}
29362936
break;
29372937
}

client/gui/preferenceswindow/connectionwindow/connectionwindowitem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ void ConnectionWindowItem::onLanguageChanged()
347347
QString("https://%1/features/firewall").arg(HardcodedSettings::instance().windscribeServerUrl()));
348348
connectionModeGroup_->setTitle(tr("Connection Mode"));
349349
connectionModeGroup_->setDescription(tr("Automatically choose the VPN protocol, or select one manually. NOTE: \"Preferred Protocol\" will override this setting."),
350-
QString("https://%1/features/connection-mode").arg(HardcodedSettings::instance().windscribeServerUrl()));
350+
QString("https://%1/features/flexible-connectivity").arg(HardcodedSettings::instance().windscribeServerUrl()));
351351
packetSizeGroup_->setDescription(tr("Automatically determine the MTU for your connection, or manually override. This has no effect on TCP-based protocols."),
352352
QString("https://%1/features/packet-size").arg(HardcodedSettings::instance().windscribeServerUrl()));
353353
connectedDnsGroup_->setDescription(tr("Select the DNS server while connected to Windscribe."),

client/gui/sounds/soundmanager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
SoundManager::SoundManager(QObject *parent, Preferences *preferences)
1010
: QObject(parent), preferences_(preferences), audioEngineInitialized_(false), soundInitialized_(false), shouldLoop_(false), connectedEventQueued_(false)
1111
{
12-
initialize();
12+
initialize(); // NOLINT
1313
}
1414

1515
SoundManager::~SoundManager()

0 commit comments

Comments
 (0)