Hide unavailable display scale options
This commit is contained in:
@@ -33,6 +33,55 @@ function cleanScale(scale, width, height) {
|
|||||||
return normalizeScale(scaleUnits / 120)
|
return normalizeScale(scaleUnits / 120)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchingScaleIndex(scales, currentScale, width, height) {
|
||||||
|
var current = Number(currentScale)
|
||||||
|
if (!Array.isArray(scales) || !isFinite(current)) return -1
|
||||||
|
|
||||||
|
var bestIndex = -1
|
||||||
|
var bestDistance = Infinity
|
||||||
|
var normalizedCurrent = normalizeScale(current)
|
||||||
|
for (var i = 0; i < scales.length; i++) {
|
||||||
|
if (cleanScale(scales[i], width, height) !== normalizedCurrent) continue
|
||||||
|
|
||||||
|
var distance = Math.abs(Number(scales[i]) - current)
|
||||||
|
if (distance < bestDistance) {
|
||||||
|
bestIndex = i
|
||||||
|
bestDistance = distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
function availableScales(scales, width, height) {
|
||||||
|
if (!Array.isArray(scales) || Number(width) <= 0 || Number(height) <= 0) return scales || []
|
||||||
|
|
||||||
|
var byEffectiveScale = {}
|
||||||
|
for (var i = 0; i < scales.length; i++) {
|
||||||
|
var requested = Number(scales[i])
|
||||||
|
var effective = Number(cleanScale(requested, width, height))
|
||||||
|
|
||||||
|
// Clean scales round upward. If the mode cannot reach the requested
|
||||||
|
// scale, cleanScale caps at its largest valid value and this preset is
|
||||||
|
// not actually available.
|
||||||
|
if (!isFinite(requested) || !isFinite(effective) || effective < requested) continue
|
||||||
|
|
||||||
|
var key = normalizeScale(effective)
|
||||||
|
var existing = byEffectiveScale[key]
|
||||||
|
if (!existing || Math.abs(requested - effective) < existing.distance) {
|
||||||
|
byEffectiveScale[key] = {
|
||||||
|
value: String(scales[i]),
|
||||||
|
index: i,
|
||||||
|
distance: Math.abs(requested - effective)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(byEffectiveScale)
|
||||||
|
.map(function(key) { return byEffectiveScale[key] })
|
||||||
|
.sort(function(a, b) { return a.index - b.index })
|
||||||
|
.map(function(candidate) { return candidate.value })
|
||||||
|
}
|
||||||
|
|
||||||
function brightnessName(percent) {
|
function brightnessName(percent) {
|
||||||
var p = Math.round(percent)
|
var p = Math.round(percent)
|
||||||
if (p >= 95) return "Sun blast"
|
if (p >= 95) return "Sun blast"
|
||||||
@@ -70,6 +119,8 @@ if (typeof module !== "undefined") {
|
|||||||
clampBrightness: clampBrightness,
|
clampBrightness: clampBrightness,
|
||||||
normalizeScale: normalizeScale,
|
normalizeScale: normalizeScale,
|
||||||
cleanScale: cleanScale,
|
cleanScale: cleanScale,
|
||||||
|
matchingScaleIndex: matchingScaleIndex,
|
||||||
|
availableScales: availableScales,
|
||||||
brightnessName: brightnessName,
|
brightnessName: brightnessName,
|
||||||
parseDisplays: parseDisplays
|
parseDisplays: parseDisplays
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,15 @@ Panel {
|
|||||||
// j/k walks each row.
|
// j/k walks each row.
|
||||||
// Mouse hover on a target updates root state via the components' `hovered`
|
// Mouse hover on a target updates root state via the components' `hovered`
|
||||||
// signal so keyboard cursor and pointer share one highlight.
|
// signal so keyboard cursor and pointer share one highlight.
|
||||||
readonly property var scaleValues: ["1", "1.25", "1.6", "2", "3", "4"]
|
readonly property var scalePresets: ["1", "1.25", "1.6", "2", "3", "4"]
|
||||||
|
readonly property var scaleValues: {
|
||||||
|
for (var i = 0; i < displays.length; i++) {
|
||||||
|
var display = displays[i]
|
||||||
|
if (display && display.focused)
|
||||||
|
return Model.availableScales(scalePresets, display.width, display.height)
|
||||||
|
}
|
||||||
|
return scalePresets
|
||||||
|
}
|
||||||
property string focusSection: "scale"
|
property string focusSection: "scale"
|
||||||
property int selectedIndex: 0
|
property int selectedIndex: 0
|
||||||
property bool cursorActive: false
|
property bool cursorActive: false
|
||||||
@@ -246,13 +254,13 @@ Panel {
|
|||||||
return Model.normalizeScale(scale)
|
return Model.normalizeScale(scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
function effectiveScale(scale) {
|
function activeScaleIndex() {
|
||||||
for (var i = 0; i < displays.length; i++) {
|
for (var i = 0; i < displays.length; i++) {
|
||||||
var display = displays[i]
|
var display = displays[i]
|
||||||
if (display && display.focused)
|
if (display && display.focused)
|
||||||
return Model.cleanScale(scale, display.width, display.height)
|
return Model.matchingScaleIndex(scaleValues, monitorScale, display.width, display.height)
|
||||||
}
|
}
|
||||||
return normalizeScale(scale)
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Playful mood-name for a given brightness percent. Bands intentionally
|
// Playful mood-name for a given brightness percent. Bands intentionally
|
||||||
@@ -342,6 +350,7 @@ Panel {
|
|||||||
|
|
||||||
onBrightnessAvailableChanged: clampCursor()
|
onBrightnessAvailableChanged: clampCursor()
|
||||||
onDisplaysChanged: clampCursor()
|
onDisplaysChanged: clampCursor()
|
||||||
|
onScaleValuesChanged: clampCursor()
|
||||||
onVisibleSectionsChanged: clampCursor()
|
onVisibleSectionsChanged: clampCursor()
|
||||||
|
|
||||||
// Only poll while the panel is open; the bar glyph tracks monitor count via
|
// Only poll while the panel is open; the bar glyph tracks monitor count via
|
||||||
@@ -780,7 +789,7 @@ Panel {
|
|||||||
verticalPadding: Style.spacing.controlPaddingY
|
verticalPadding: Style.spacing.controlPaddingY
|
||||||
bordered: true
|
bordered: true
|
||||||
|
|
||||||
active: root.normalizeScale(root.monitorScale) === root.effectiveScale(scaleValue)
|
active: root.activeScaleIndex() === scaleIndex
|
||||||
hasCursor: root.cursorActive && root.focusSection === "scale" && root.selectedIndex === scaleIndex
|
hasCursor: root.cursorActive && root.focusSection === "scale" && root.selectedIndex === scaleIndex
|
||||||
|
|
||||||
onClicked: root.setScale(scaleValue)
|
onClicked: root.setScale(scaleValue)
|
||||||
|
|||||||
@@ -18,6 +18,31 @@ assertEqual(monitor.cleanScale(3, 1280, 800), '3.2', 'monitor matches clean VM s
|
|||||||
assertEqual(monitor.cleanScale(1.25, 1280, 800), '1.25', 'monitor preserves an already clean scale')
|
assertEqual(monitor.cleanScale(1.25, 1280, 800), '1.25', 'monitor preserves an already clean scale')
|
||||||
assertEqual(monitor.cleanScale(1.25, 6016, 3384), '1.33', 'monitor matches clean physical display scale')
|
assertEqual(monitor.cleanScale(1.25, 6016, 3384), '1.33', 'monitor matches clean physical display scale')
|
||||||
assertEqual(monitor.cleanScale(1.6, 0, 800), '', 'monitor rejects a missing display mode')
|
assertEqual(monitor.cleanScale(1.6, 0, 800), '', 'monitor rejects a missing display mode')
|
||||||
|
assertEqual(
|
||||||
|
monitor.matchingScaleIndex(['1', '1.25', '1.6', '2', '3', '4'], 3.2, 1280, 800),
|
||||||
|
4,
|
||||||
|
'monitor selects requested 3x for effective VM scale'
|
||||||
|
)
|
||||||
|
assertEqual(
|
||||||
|
monitor.matchingScaleIndex(['1', '1.25', '1.6', '2', '3', '4'], 4, 4, 4),
|
||||||
|
5,
|
||||||
|
'monitor selects only the closest preset when clean scales collide'
|
||||||
|
)
|
||||||
|
assertDeepEqual(
|
||||||
|
monitor.availableScales(['1', '1.25', '1.6', '2', '3', '4'], 1280, 800),
|
||||||
|
['1', '1.25', '1.6', '2', '3', '4'],
|
||||||
|
'monitor keeps presets that produce unique reachable VM scales'
|
||||||
|
)
|
||||||
|
assertDeepEqual(
|
||||||
|
monitor.availableScales(['1', '1.25', '1.6', '2', '3', '4'], 5968, 3230),
|
||||||
|
['1', '2'],
|
||||||
|
'monitor hides presets the current mode cannot reach'
|
||||||
|
)
|
||||||
|
assertDeepEqual(
|
||||||
|
monitor.availableScales(['1', '1.25', '1.6', '2', '3', '4'], 0, 0),
|
||||||
|
['1', '1.25', '1.6', '2', '3', '4'],
|
||||||
|
'monitor keeps presets until display dimensions are known'
|
||||||
|
)
|
||||||
|
|
||||||
assertEqual(monitor.brightnessName(96), 'Sun blast', 'monitor names very bright displays')
|
assertEqual(monitor.brightnessName(96), 'Sun blast', 'monitor names very bright displays')
|
||||||
assertEqual(monitor.brightnessName(12), 'Candlelit', 'monitor names dim displays')
|
assertEqual(monitor.brightnessName(12), 'Candlelit', 'monitor names dim displays')
|
||||||
|
|||||||
Reference in New Issue
Block a user