Skip to content

Commit e77ac04

Browse files
committed
feat(YaruWindowControl): follow system settings
Fixes #532
1 parent ca0e8ee commit e77ac04

File tree

5 files changed

+202
-67
lines changed

5 files changed

+202
-67
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
const kSchemaInterface = 'org.gnome.desktop.interface';
2+
const kSchemeWmPreferences = 'org.gnome.desktop.wm.preferences';
23
const kAccentColorKey = 'accent-color';
4+
const kButtonLayoutKey = 'button-layout';

lib/src/settings/inherited_theme.dart

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,33 +142,41 @@ class YaruTheme extends StatefulWidget {
142142
class _YaruThemeState extends State<YaruTheme> {
143143
YaruVariant? _variant;
144144
YaruSettings? _settings;
145-
StreamSubscription<String?>? _themeNameSubscription;
146-
StreamSubscription<String?>? _accentColorSubScription;
145+
final Map<String, List<String>?> _customTitleButtonLayout = {
146+
'left': null,
147+
'right': null,
148+
};
149+
StreamSubscription<String?>? _themeNameSub;
150+
StreamSubscription<String?>? _accentColorSub;
151+
StreamSubscription<String?>? _buttonLayoutSub;
147152

148153
@override
149154
void initState() {
150155
super.initState();
151-
if (widget.data.variant == null && canDetectVariant()) {
156+
if (canDetectGnome()) {
152157
_settings = widget._settings ?? YaruSettings();
153158
_settings?.init();
154-
_variant = resolveAccentColorVariant(_settings?.getAccentColor()) ??
155-
resolveGtkThemeVariant(_settings?.getThemeName());
156-
_accentColorSubScription ??=
157-
_settings!.accentColorChanged.listen(updateVariant);
158-
_themeNameSubscription ??=
159-
_settings!.themeNameChanged.listen(updateVariant);
159+
if (widget.data.variant == null) {
160+
_variant = resolveAccentColorVariant(_settings?.getAccentColor()) ??
161+
resolveGtkThemeVariant(_settings?.getThemeName());
162+
_accentColorSub ??= _settings!.accentColorChanged.listen(updateVariant);
163+
_themeNameSub ??= _settings!.themeNameChanged.listen(updateVariant);
164+
_buttonLayoutSub ??=
165+
_settings!.buttonLayoutChanged.listen(updateButtonLayout);
166+
}
160167
}
161168
}
162169

163170
@override
164171
void dispose() {
165-
_themeNameSubscription?.cancel();
166-
_accentColorSubScription?.cancel();
172+
_themeNameSub?.cancel();
173+
_accentColorSub?.cancel();
174+
_buttonLayoutSub?.cancel();
167175
_settings?.dispose();
168176
super.dispose();
169177
}
170178

171-
bool canDetectVariant() {
179+
bool canDetectGnome() {
172180
return !kIsWeb &&
173181
widget._platform.isLinux &&
174182
!widget._platform.environment.containsKey('FLUTTER_TEST');
@@ -221,7 +229,7 @@ class _YaruThemeState extends State<YaruTheme> {
221229
};
222230

223231
void updateVariant([String? value]) {
224-
assert(canDetectVariant());
232+
assert(canDetectGnome());
225233
final gtkThemeName = value ?? _settings?.getThemeName();
226234
final accentColor = value ?? _settings?.getAccentColor();
227235
setState(
@@ -230,6 +238,24 @@ class _YaruThemeState extends State<YaruTheme> {
230238
);
231239
}
232240

241+
void updateButtonLayout([String? value]) {
242+
assert(canDetectGnome());
243+
final buttonLayout = value ?? _settings?.getButtonLayout();
244+
245+
final buttons = buttonLayout?.split(':');
246+
247+
setState(() {
248+
_customTitleButtonLayout.update(
249+
'left',
250+
(value) => buttons?.firstOrNull?.split(',') ?? <String>[],
251+
);
252+
_customTitleButtonLayout.update(
253+
'right',
254+
(value) => buttons?.lastOrNull?.split(',') ?? [],
255+
);
256+
});
257+
}
258+
233259
ThemeMode resolveMode() {
234260
final mode = widget.data.themeMode ?? ThemeMode.system;
235261
if (mode == ThemeMode.system) {
@@ -246,6 +272,8 @@ class _YaruThemeState extends State<YaruTheme> {
246272
highContrast:
247273
widget.data.highContrast ?? MediaQuery.highContrastOf(context),
248274
themeMode: resolveMode(),
275+
customTitleButtonLayout:
276+
widget.data.customTitleButtonLayout ?? _customTitleButtonLayout,
249277
);
250278
}
251279

@@ -262,7 +290,7 @@ class _YaruThemeState extends State<YaruTheme> {
262290

263291
@override
264292
Widget build(BuildContext context) {
265-
if (_settings != null && _themeNameSubscription == null) {
293+
if (_settings != null && _themeNameSub == null) {
266294
return const SizedBox.shrink(); // #231
267295
}
268296
final data = resolveData();
@@ -287,11 +315,14 @@ class YaruThemeData with Diagnosticable {
287315
this.pageTransitionsTheme,
288316
this.useMaterial3,
289317
this.visualDensity,
318+
this.customTitleButtonLayout,
290319
});
291320

292321
/// Specifies the theme variant.
293322
final YaruVariant? variant;
294323

324+
final Map<String, List<String>?>? customTitleButtonLayout;
325+
295326
/// Whether to use high contrast colors.
296327
final bool? highContrast;
297328

@@ -328,6 +359,7 @@ class YaruThemeData with Diagnosticable {
328359
PageTransitionsTheme? pageTransitionsTheme,
329360
bool? useMaterial3,
330361
VisualDensity? visualDensity,
362+
Map<String, List<String>?>? customTitleButtonLayout,
331363
}) {
332364
return YaruThemeData(
333365
variant: variant ?? this.variant,
@@ -337,6 +369,8 @@ class YaruThemeData with Diagnosticable {
337369
pageTransitionsTheme: pageTransitionsTheme ?? this.pageTransitionsTheme,
338370
useMaterial3: useMaterial3 ?? this.useMaterial3,
339371
visualDensity: visualDensity ?? this.visualDensity,
372+
customTitleButtonLayout:
373+
customTitleButtonLayout ?? this.customTitleButtonLayout,
340374
);
341375
}
342376

@@ -351,6 +385,9 @@ class YaruThemeData with Diagnosticable {
351385
.add(DiagnosticsProperty('pageTransitionsTheme', pageTransitionsTheme));
352386
properties.add(DiagnosticsProperty('useMaterial3', useMaterial3));
353387
properties.add(DiagnosticsProperty('visualDensity', visualDensity));
388+
properties.add(
389+
DiagnosticsProperty('customTitleButtonLayout', customTitleButtonLayout),
390+
);
354391
}
355392

356393
@override
@@ -364,7 +401,8 @@ class YaruThemeData with Diagnosticable {
364401
iterableEquals(other.extensions, extensions) &&
365402
other.pageTransitionsTheme == pageTransitionsTheme &&
366403
other.useMaterial3 == useMaterial3 &&
367-
other.visualDensity == visualDensity;
404+
other.visualDensity == visualDensity &&
405+
other.customTitleButtonLayout == customTitleButtonLayout;
368406
}
369407

370408
@override
@@ -377,6 +415,7 @@ class YaruThemeData with Diagnosticable {
377415
pageTransitionsTheme,
378416
useMaterial3,
379417
visualDensity,
418+
customTitleButtonLayout,
380419
);
381420
}
382421
}

lib/src/settings/yaru_settings.dart

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ abstract class YaruSettings {
1111

1212
String? getThemeName();
1313
String? getAccentColor();
14+
String? getButtonLayout();
1415
Stream<String?> get themeNameChanged;
1516
Stream<String?> get accentColorChanged;
17+
Stream<String?> get buttonLayoutChanged;
1618
void init();
1719
Future<void> dispose();
1820
}
@@ -27,7 +29,8 @@ class YaruGtkSettings extends YaruSettings {
2729

2830
final GtkSettings _gtkSettings;
2931
final GSettingsService _gSettingsService;
30-
GnomeSettings? _gSettings;
32+
GnomeSettings? _interfaceSettings;
33+
GnomeSettings? _wmPrefSettings;
3134

3235
@override
3336
String? getThemeName() => _gtkSettings.getProperty(kGtkThemeName) as String?;
@@ -40,20 +43,32 @@ class YaruGtkSettings extends YaruSettings {
4043
@override
4144
Stream<String?> get accentColorChanged => _accentColorController.stream;
4245

46+
final _buttonLayoutController = StreamController<String?>.broadcast();
47+
@override
48+
Stream<String?> get buttonLayoutChanged => _buttonLayoutController.stream;
49+
4350
@override
4451
void init() {
45-
_gSettings ??= _gSettingsService.lookup(kSchemaInterface);
46-
_gSettings?.addListener(
52+
_interfaceSettings ??= _gSettingsService.lookup(kSchemaInterface);
53+
_interfaceSettings?.addListener(
4754
() => _accentColorController.add(getAccentColor()),
4855
);
56+
_wmPrefSettings ??= _gSettingsService.lookup(kSchemeWmPreferences);
57+
_wmPrefSettings?.addListener(
58+
() => _buttonLayoutController.add(getButtonLayout()),
59+
);
4960
}
5061

5162
@override
5263
Future<void> dispose() async {
5364
await _accentColorController.close();
65+
await _buttonLayoutController.close();
5466
await _gSettingsService.dispose();
5567
}
5668

5769
@override
58-
String? getAccentColor() => _gSettings?.stringValue(kAccentColorKey);
70+
String? getAccentColor() => _interfaceSettings?.stringValue(kAccentColorKey);
71+
72+
@override
73+
String? getButtonLayout() => _wmPrefSettings?.stringValue(kButtonLayoutKey);
5974
}

0 commit comments

Comments
 (0)