Skip to content

Commit

Permalink
feat(bootstrap): set keyboard via setxkbmap
Browse files Browse the repository at this point in the history
  • Loading branch information
d-loose committed Apr 11, 2024
1 parent e115cfc commit b866c55
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
25 changes: 23 additions & 2 deletions packages/ubuntu_bootstrap/lib/services/keyboard_service.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:dbus/dbus.dart';
import 'package:gsettings/gsettings.dart';
import 'package:meta/meta.dart';
Expand All @@ -12,11 +14,15 @@ class SubiquityKeyboardService implements KeyboardService {
SubiquityKeyboardService(
this._subiquity, {
@visibleForTesting GSettings? inputSourceSettings,
}) : _inputSourceSettings = inputSourceSettings ??
createService<GSettings, String>('org.gnome.desktop.input-sources');
@visibleForTesting
Future<ProcessResult> Function(String, List<String>)? runProcess,
}) : _inputSourceSettings = inputSourceSettings ??
createService<GSettings, String>('org.gnome.desktop.input-sources'),
_runProcess = runProcess ?? Process.run;

final SubiquityClient _subiquity;
final GSettings _inputSourceSettings;
final Future<ProcessResult> Function(String, List<String>) _runProcess;

@override
Future<KeyboardSetup> getKeyboard() => _subiquity.getKeyboard();
Expand All @@ -28,6 +34,7 @@ class SubiquityKeyboardService implements KeyboardService {

@override
Future<void> setInputSource(KeyboardSetting setting, {String? user}) async {
await _setXkbInputSource(setting);
await _setGsettingsInputSource(setting);
return _subiquity.setInputSource(setting, user: user);
}
Expand Down Expand Up @@ -57,4 +64,18 @@ class SubiquityKeyboardService implements KeyboardService {
_log.error('Failed to set input source via gsettings', e);
}
}

Future<void> _setXkbInputSource(KeyboardSetting setting) async {
final result = await _runProcess(
'setxkbmap',
[
'-layout',
setting.layout,
if (setting.variant.isNotEmpty) ...['-variant', setting.variant],
],
);
if (result.exitCode != 0) {
_log.error('Failed to set input source via setxkbmap', result.stderr);
}
}
}
3 changes: 3 additions & 0 deletions packages/ubuntu_bootstrap/test/installer_wizard_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -501,6 +503,7 @@ extension on WidgetTester {
final keyboardService = SubiquityKeyboardService(
subiquityClient,
inputSourceSettings: inputSettings,
runProcess: (_, __) async => ProcessResult(0, 0, '', ''),
);
registerMockService<KeyboardService>(keyboardService);
when(keyboardService.getKeyboard()).thenAnswer((_) async => keyboardSetup);
Expand Down
29 changes: 29 additions & 0 deletions packages/ubuntu_bootstrap/test/services/keyboard_service_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:dbus/dbus.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
Expand All @@ -9,10 +11,15 @@ import '../test_utils.dart';

void main() {
late MockGSettings inputSourceSettings;
late MockProcess mockProcess;

setUp(() {
inputSourceSettings = MockGSettings();
when(inputSourceSettings.set(any, any)).thenAnswer((_) async {});

mockProcess = MockProcess();
when(mockProcess.run(any, any))
.thenAnswer((_) async => ProcessResult(0, 0, '', ''));
});

test('get keyboard', () async {
Expand All @@ -22,6 +29,7 @@ void main() {
final service = SubiquityKeyboardService(
client,
inputSourceSettings: inputSourceSettings,
runProcess: mockProcess.run,
);
expect(await service.getKeyboard(), equals(keyboardSetup));

Expand All @@ -35,6 +43,7 @@ void main() {
final service = SubiquityKeyboardService(
client,
inputSourceSettings: inputSourceSettings,
runProcess: mockProcess.run,
);
await service.setKeyboard(keyboardSetup.setting);

Expand All @@ -49,6 +58,7 @@ void main() {
final service = SubiquityKeyboardService(
client,
inputSourceSettings: inputSourceSettings,
runProcess: mockProcess.run,
);
await service.setInputSource(keyboardSetup.setting, user: 'ubuntu');

Expand All @@ -67,6 +77,11 @@ void main() {
],
),
)).called(1);

verify(mockProcess.run(
'setxkbmap',
['-layout', 'us', '-variant', 'altgr-intl'],
)).called(1);
});

test('get keyboard step', () async {
Expand All @@ -77,9 +92,23 @@ void main() {
final service = SubiquityKeyboardService(
client,
inputSourceSettings: inputSourceSettings,
runProcess: mockProcess.run,
);
await service.getKeyboardStep('1');

verify(client.getKeyboardStep('1')).called(1);
});
}

abstract class _Process {
Future<ProcessResult> run(String? executable, List<String>? arguments);
}

class MockProcess extends Mock implements _Process {
@override
Future<ProcessResult> run(String? executable, List<String>? arguments) =>
super.noSuchMethod(
Invocation.method(#run, [executable, arguments]),
returnValue: Future.value(ProcessResult(0, 0, '', '')),
) as Future<ProcessResult>;
}

0 comments on commit b866c55

Please sign in to comment.