Skip to content

Commit

Permalink
customization: Display key combination in dropdown
Browse files Browse the repository at this point in the history
When a button is remapped with a keyEvent, calculate the key combination
from the keyEvent and display it in the dropdown menu.

Screenshot: https://screenshot.googleplex.com/4X4EFhneibaZCMn

Bug: b/241965717
Test: Verified on DUT and browser_tests.
Change-Id: I7c5aa377d8b1a52b1d6d4c3b897e5e45bb0a06df
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4791313
Reviewed-by: David Padlipsky <dpad@google.com>
Commit-Queue: Yuhan Yang <yyhyyh@google.com>
Cr-Commit-Position: refs/heads/main@{#1186789}
  • Loading branch information
yuhan202 authored and Chromium LUCI CQ committed Aug 22, 2023
1 parent 7801c2a commit 799d520
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
</option>
</template>
<option id="keyCombination" value="[[keyCombinationOptionValue_]]">
$i18n{keyCombinationOptionLabel}
[[keyCombinationLabel_]]
</option>
</select>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,55 @@ import {microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer
import {cast} from '../assert_extras.js';

import {getTemplate} from './customize_button_row.html.js';
import {ActionChoice, ButtonRemapping} from './input_device_settings_types.js';
import {ActionChoice, ButtonRemapping, KeyEvent} from './input_device_settings_types.js';

const NO_REMAPPING_OPTION_LABEL = 'none';
const KEY_COMBINATION_OPTION_LABEL = 'key combination';

/**
* Bit mask of modifiers.
* Ordering is according to UX, but values match EventFlags in
* ui/events/event_constants.h.
*/
enum Modifier {
NONE = 0,
CONTROL = 1 << 2,
SHIFT = 1 << 1,
ALT = 1 << 3,
META = 1 << 4,
}

/**
* Map the modifier keys to the bit value. Currently the modifiers only
* contains the following four.
*/
const modifierBitMaskToString: Map<number, string> = new Map([
[Modifier.CONTROL, 'ctrl'],
[Modifier.SHIFT, 'shift'],
[Modifier.ALT, 'alt'],
[Modifier.META, 'meta'],
]);

function concateKeyString(firstStr: string, secondStr: string): string {
return firstStr.length === 0 ? secondStr : firstStr.concat(` + ${secondStr}`);
}

/**
* Converts a keyEvent to a string representing all the modifiers and the vkey.
*/
function getKeyCombinationLabel(keyEvent: KeyEvent): string {
let combinationLabel = '';
modifierBitMaskToString.forEach((modifierName: string, bitValue: number) => {
if ((keyEvent.modifiers & bitValue) !== 0) {
combinationLabel = concateKeyString(combinationLabel, modifierName);
}
});
if (keyEvent.keyDisplay !== undefined && keyEvent.keyDisplay.length !== 0) {
combinationLabel = concateKeyString(combinationLabel, keyEvent.keyDisplay);
}
return combinationLabel;
}

const CustomizeButtonRowElementBase = I18nMixin(PolymerElement);

export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
Expand Down Expand Up @@ -78,8 +122,12 @@ export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
reflectToAttribute: true,
},

keyCombinationLabel_: {
type: String,
},

/**
* The value of the "None" item.
* The value of the "None" item in dropdown menu.
*/
noRemappingOptionValue_: {
type: String,
Expand All @@ -88,7 +136,7 @@ export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
},

/**
* The value of the "Key combination" item.
* The value of the "Key combination" item in dropdown menu.
*/
keyCombinationOptionValue_: {
type: String,
Expand All @@ -101,7 +149,7 @@ export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
static get observers(): string[] {
return [
'onSettingsChanged(fakePref_.*)',
'initializeCustomizeKey(buttonRemappingList, remappingIndex)',
'initializeCustomizeKey(buttonRemappingList.*, remappingIndex)',
];
}

Expand All @@ -113,6 +161,7 @@ export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
private fakePref_: chrome.settingsPrivate.PrefObject;
private noRemappingOptionValue_: string;
private keyCombinationOptionValue_: string;
private keyCombinationLabel_: string;

/**
* Populate dropdown menu choices.
Expand All @@ -133,26 +182,25 @@ export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
}

/**
* Initialize the button remapping content and set up fake pref.
* Populate the button remapping action according to the existing settings.
*/
private initializeCustomizeKey(): void {
if (!this.buttonRemappingList ||
!this.buttonRemappingList[this.remappingIndex]) {
return;
}
this.buttonRemapping_ = this.buttonRemappingList[this.remappingIndex];
this.setUpButtonMapTargets_();
private setUpRemappingActions_(): void {
const dropdown = cast(
this.shadowRoot!.querySelector('#remappingActionDropdown'),
HTMLSelectElement);

// Set the dropdown option label to default 'Key combination'.
this.keyCombinationLabel_ = this.i18n('keyCombinationOptionLabel');

// For accelerator actions, the remappingAction.action value is number.
// TODO(yyhyyh@): Add the case when remappingAction is none or Keyboard
// events.
const action = this.buttonRemapping_.remappingAction!.action;
const action = this.buttonRemapping_.remappingAction?.action;
const keyEvent = this.buttonRemapping_.remappingAction?.keyEvent;
if (action !== undefined && !isNaN(action)) {
const originalAction =
this.buttonRemapping_.remappingAction!.action!.toString();
const dropdown = cast(
this.shadowRoot!.querySelector('#remappingActionDropdown'),
HTMLSelectElement);


// Initialize fakePref with the tablet settings mapping.
this.set('fakePref_.value', originalAction);
Expand All @@ -166,9 +214,30 @@ export class CustomizeButtonRowElement extends CustomizeButtonRowElementBase {
dropdown.value =
option === undefined ? NO_REMAPPING_OPTION_LABEL : originalAction;
});
} else if (keyEvent) {
this.set('fakePref_.value', KEY_COMBINATION_OPTION_LABEL);
this.keyCombinationLabel_ = getKeyCombinationLabel(keyEvent) ??
this.i18n('keyCombinationOptionLabel');

microTask.run(() => {
dropdown.value = KEY_COMBINATION_OPTION_LABEL;
});
}
}

/**
* Initialize the button remapping content and set up fake pref.
*/
private initializeCustomizeKey(): void {
if (!this.buttonRemappingList ||
!this.buttonRemappingList[this.remappingIndex]) {
return;
}
this.buttonRemapping_ = this.buttonRemappingList[this.remappingIndex];
this.setUpButtonMapTargets_();
this.setUpRemappingActions_();
}

/**
* Update device settings whenever the pref changes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ suite('<customize-button-row>', () => {
expectedRemapping!.remappingAction?.action!.toString());

// Change buttonRemapping data to display.
customizeButtonRow.set('remappingIndex', 1);
customizeButtonRow.set(
'buttonRemappingList',
fakeGraphicsTablets[1]!.settings.tabletButtonRemappings);
customizeButtonRow.set('remappingIndex', 1);
await flushTasks();
expectedRemapping =
fakeGraphicsTablets[1]!.settings.tabletButtonRemappings[1];
Expand All @@ -77,4 +77,26 @@ suite('<customize-button-row>', () => {
getSelectedValue(),
expectedRemapping!.remappingAction?.action!.toString());
});

test('Initialize key combination string', async () => {
await initializeCustomizeButtonRow();
customizeButtonRow.set(
'buttonRemappingList',
fakeGraphicsTablets[0]!.settings.penButtonRemappings);
customizeButtonRow.set('remappingIndex', 0);
await flushTasks();

assertEquals(getSelectedValue(), 'key combination');
assertEquals(customizeButtonRow.get('keyCombinationLabel_'), 'ctrl + z');

// Switch to another button remapping.
customizeButtonRow.set(
'buttonRemappingList',
fakeGraphicsTablets[1]!.settings.penButtonRemappings);
customizeButtonRow.set('remappingIndex', 1);
await flushTasks();

assertEquals(getSelectedValue(), 'key combination');
assertEquals(customizeButtonRow.get('keyCombinationLabel_'), 'ctrl + v');
});
});

0 comments on commit 799d520

Please sign in to comment.