Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const SETTINGS_GSCHEMA_PATH = `/${SETTINGS_GSCHEMA.replaceAll('.', '/')}/`;
export const MAXIMIZED_BEHAVIOR = 'maximized-behavior';
export const STYLE_TRIGGER = 'style-trigger';
export const PROXIMITY_DISTANCE = 'proximity-distance';
export const PROXIMITY_TRANSITION = 'proximity-transition';
export const GRADIENT_DIRECTION = 'gradient-direction';
export const MAXIMIZED_GRADIENT_DIRECTION = 'maximized-gradient-direction';
export const COLORS = 'colors';
Expand All @@ -29,6 +30,7 @@ export const getConfig = settings => {
const maximizedBehavior = settings.get_string(MAXIMIZED_BEHAVIOR);
const styleTrigger = settings.get_string(STYLE_TRIGGER);
const proximityDistance = settings.get_int(PROXIMITY_DISTANCE);
const proximityTransition = settings.get_boolean(PROXIMITY_TRANSITION);
const colors = settings.get_value(COLORS).deep_unpack();
const gradientDirection = settings.get_string(GRADIENT_DIRECTION);
const maximizedColors = settings.get_value(MAXIMIZED_COLORS).deep_unpack();
Expand All @@ -38,6 +40,7 @@ export const getConfig = settings => {
maximizedBehavior,
styleTrigger,
proximityDistance,
proximityTransition,
gradientDirection,
colors: {
start: colors[0],
Expand Down Expand Up @@ -84,6 +87,13 @@ export const setProximityDistance = (settings, value) => {
settings.set_int(PROXIMITY_DISTANCE, value);
};

export const getProximityTransition = settings =>
settings.get_boolean(PROXIMITY_TRANSITION);

export const setProximityTransition = (settings, value) => {
settings.set_boolean(PROXIMITY_TRANSITION, value);
};

/**
* Gets the gradient direction setting
*
Expand Down Expand Up @@ -178,6 +188,7 @@ export const attachSettingsListeners = (settings, listener) => {
MAXIMIZED_BEHAVIOR,
STYLE_TRIGGER,
PROXIMITY_DISTANCE,
PROXIMITY_TRANSITION,
COLORS,
MAXIMIZED_COLORS,
MAXIMIZED_GRADIENT_DIRECTION
Expand Down
69 changes: 69 additions & 0 deletions src/effects/discreteEffect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {
finishOriginalThemeTransition,
removeGradientTransition,
scrubAlternateGradient,
scrubOriginalTheme,
setGradientTransition,
toggleGradient
} from '../gradient.js';
import { MAXIMIZED_BEHAVIOR } from '../constants.js';
import { blendEffectStrength } from './effectStrength.js';


export default class DiscreteEffect {
constructor(triggeredBehavior) {
this.triggeredBehavior = triggeredBehavior;
}

apply(effectStrength) {
if (effectStrength === 0 || this.triggeredBehavior === MAXIMIZED_BEHAVIOR.KEEP_GRADIENT) {
toggleGradient(true, false);
setGradientTransition(0);
return;
}

if (this.triggeredBehavior === MAXIMIZED_BEHAVIOR.KEEP_THEME) {
toggleGradient(false);
return;
}

toggleGradient(true, false);
setGradientTransition(1);
}

scrub(startEffectStrength, endEffectStrength, progress) {
const effectStrength = blendEffectStrength(
Number(startEffectStrength > 0),
Number(endEffectStrength > 0),
progress
);

if (this.triggeredBehavior === MAXIMIZED_BEHAVIOR.KEEP_THEME) {
toggleGradient(false);
scrubOriginalTheme(effectStrength);
return;
}

toggleGradient(true, false);
if (this.triggeredBehavior === MAXIMIZED_BEHAVIOR.APPLY_STYLE)
scrubAlternateGradient(effectStrength);
}

settle(effectStrength) {
if (this.triggeredBehavior === MAXIMIZED_BEHAVIOR.KEEP_THEME) {
const showGradient = effectStrength === 0;
toggleGradient(showGradient, false);
finishOriginalThemeTransition(showGradient);
return;
}

toggleGradient(true, false);
if (this.triggeredBehavior === MAXIMIZED_BEHAVIOR.APPLY_STYLE)
scrubAlternateGradient(Number(effectStrength > 0));
}

destroy() {
removeGradientTransition();
toggleGradient(false);
}
}
2 changes: 2 additions & 0 deletions src/effects/effectStrength.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const blendEffectStrength = (startStrength, endStrength, progress) =>
startStrength + (endStrength - startStrength) * progress;
34 changes: 34 additions & 0 deletions src/effects/progressiveEffect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
removeGradientTransition,
scrubAlternateGradient,
setGradientTransition,
toggleGradient
} from '../gradient.js';
import { blendEffectStrength } from './effectStrength.js';

export default class ProgressiveEffect {
apply(effectStrength) {
toggleGradient(true, false);
setGradientTransition(effectStrength);
}

scrub(startEffectStrength, endEffectStrength, progress) {
const effectStrength = blendEffectStrength(
startEffectStrength,
endEffectStrength,
progress
);
toggleGradient(true, false);
scrubAlternateGradient(effectStrength);
}

settle(effectStrength) {
toggleGradient(true, false);
scrubAlternateGradient(effectStrength);
}

destroy() {
removeGradientTransition();
toggleGradient(false);
}
}
5 changes: 5 additions & 0 deletions src/events/behaviours/maximizedWindows.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ const { VERTICAL, BOTH } = Meta.MaximizeFlags;
// Detects windows that occupy the full monitor or are vertically maximized.
// This behaviour deliberately avoids layout and position-change dependencies.
export default class MaximizedWindows {
// TODO: Handle tiled windows and monitor-sized windows that were not snapped.
matches(window) {
if (window.is_monitor_sized() || window.is_screen_sized())
return true;

return [BOTH, VERTICAL].includes(window.get_maximize_flags());
}

getEffectStrength(windows) {
return Number(windows.some(window => this.matches(window)));
}

// Maximization changes window size; moving an unmaximized window is irrelevant.
attachWindowEvents(eventManager, window, updateState) {
eventManager.attachWindowEventOnce('size-changed', window, updateState);
Expand Down
21 changes: 16 additions & 5 deletions src/events/behaviours/proximityWindows.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,32 @@ import { layoutManager, panel } from 'resource:///org/gnome/shell/ui/main.js';

import { getProximityDistance } from '../../config.js';

const calculateProgress = (windowDistance, proximityDistance) =>
proximityDistance === 0
? Number(windowDistance <= 0)
: Math.max(0, Math.min(1, 1 - windowDistance / proximityDistance));

// Keeps all panel-layout dependencies inside the proximity behaviour.
export default class ProximityWindows {
constructor(settings) {
this.settings = settings;
}

matches(window) {
getEffectStrength(windows) {
const { primaryMonitor } = layoutManager;
if (!primaryMonitor)
return false;
return 0;

// Include a small tolerance below the panel to avoid an exact-edge requirement.
const distance = getProximityDistance(this.settings);
const panelBottom = primaryMonitor.y + panel.get_height() + distance;
return window.get_frame_rect().y <= panelBottom;
const panelBottom = primaryMonitor.y + panel.get_height();

return windows.reduce((effectStrength, window) => {
const windowDistance = window.get_frame_rect().y - panelBottom;
return Math.max(
effectStrength,
calculateProgress(windowDistance, distance)
);
}, 0);
}

// Proximity can change when a window moves, resizes, or changes workspace.
Expand Down
43 changes: 30 additions & 13 deletions src/events/states.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
const eqSet = (as, bs) => {
if (as.size !== bs.size)
return false;

for (const a of as)
{ if (!bs.has(a))
return false; }


return true;
};

export const areSameState = (state1, state2) => {
if ([state1, state2].includes(null))
return false;
if (state1.inOverview !== state2.inOverview)
return false;
if (state1.effectStrength !== state2.effectStrength)
return false;
if ([state1.currentWorkspace, state2.currentWorkspace].includes(undefined))
return false;
if (state1.currentWorkspace.index() !== state2.currentWorkspace.index())
return false;

return eqSet(state1.triggerWindows, state2.triggerWindows);
return true;
};

export const getWorkspaceTransition = (workspaces, snapPoints, progress) => {
if (workspaces.length === 0 || workspaces.length !== snapPoints.length)
return null;

const lastIndex = snapPoints.length - 1;
const endIndex = snapPoints.findIndex(point => point >= progress);

if (endIndex <= 0) {
const index = endIndex === 0 ? 0 : lastIndex;
return {
startWorkspace: workspaces[index],
endWorkspace: workspaces[index],
progress: 0
};
}

const startIndex = endIndex - 1;
const distance = snapPoints[endIndex] - snapPoints[startIndex];
return {
startWorkspace: workspaces[startIndex],
endWorkspace: workspaces[endIndex],
progress: distance === 0
? 0
: (progress - snapPoints[startIndex]) / distance
};
};
Loading
Loading