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
5 changes: 4 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ The [Unreleased] section contains changes which are not released yet. If you wan
- Support for **switching window focus during workflows execution**. This means that you can now add a focus-window action to your workflows which will switch the focus to a specific window. This opens up many new possibilities for workflows, for instance, copying things from app A to app B.
- Support for **navigating through the menu using the arrow keys**. Highlight items with the arrow keys and press <kbd>Enter</kbd> to select them.
- A **redesigned General-Settings dialog** with a completely new layout. All the options are still there, but they are now organized in categories which should make it easier to navigate through the settings.
- A new option to move the mouse pointer back to where it opened the menu after making a selection. Thanks to [@cocojojo5213](https://github.com/cocojojo5213) for contributing this feature!
- A new option to **trigger the center-click action of the menu on key release**. This is for advanced Turbo-Mode users who want to hide the menu if the shortcut key is released over the center of the menu.
- A new option to **move the mouse pointer back to where it opened the menu** after making a selection. Thanks to [@cocojojo5213](https://github.com/cocojojo5213) for contributing this feature!
- The option to **delete menu items by dragging them back into the preview footer area**. Thanks to [@ik2m](https://github.com/ik2m) for looking into this!
- New options in the menu-themes dialog to **disable the animation of menu items**. Thanks to [@Yavuz-Kagan-Yadigar](https://github.com/Yavuz-Kagan-Yadigar) for contributing this feature!
- Support for **stylus input on KDE Wayland**. The menu will now open at the position of the pen tip when you use a drawing tablet!
- A global option to **return the pointer to the menu opening position** after selecting a button.
- Some warning signs in the settings dialog which indicate that a potentially dangerous setting is enabled. For instance, if you enable the keep-focus option, a warning sign will show that this disables all keyboard input.
- Many translation updates: **Thanks to all the contributors!**

### :wrench: Changed
Expand All @@ -68,6 +70,7 @@ The [Unreleased] section contains changes which are not released yet. If you wan

### :fire: Removed

- Single-key turbo mode. This was not working reliably anyways as it relied on the key-repeat events which are only send by the OS after some delay. You can enable Hover mode instead which is more reliable and works very similar to the old single-key turbo mode.
- The preview button for menus. I think it's not super useful and there is not much space where it used to be.

## [Kando 2.3.1](https://github.com/kando-menu/kando/releases/tag/v2.3.1)
Expand Down
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default defineConfig([
rules: {
'react/boolean-prop-naming': [
'error',
{ rule: '^(is|has|do|use|hide|initial)[A-Z]([A-Za-z0-9]?)+' },
{ rule: '^(is|has|do|use|hide|initial|show)[A-Z]([A-Za-z0-9]?)+' },
],
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-require-imports': 'off',
Expand Down
9 changes: 7 additions & 2 deletions locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,14 @@
"menu-behavior": "Menu Behavior",
"windows-ink-workaround-info": "This enables a workaround for the issue where getting the stylus position is not possible with Windows Ink enabled. This introduces a delay of 100ms before opening the menu, so if you don't use a stylus, you can disable it to make the menu open faster.",
"windows-ink-workaround": "Windows-Ink workaround",
"keep-input-focus-info": "If enabled, the menu will not receive keyboard input focus when opened. This disables Turbo Mode, but it may be useful if you require that other applications remain focused while the menu is open.",
"keep-input-focus-info": "If enabled, the menu will not receive keyboard input focus when opened. This will prevent the menu from stealing focus from the active application, yet it will disable some features such as Turbo Mode and the ability to use the keyboard to select items.",
"keep-input-focus": "Keep active application focused",
"keep-input-focus-warning": "This disables some features such as Turbo Mode and the ability to use the keyboard to select items. Activate this only if you know what you are doing!",
"enable-marking-mode-info": "With Marking Mode enabled, you can select items by dragging the mouse over them.",
"enable-marking-mode": "Enable Marking Mode",
"enable-turbo-mode-info": "With Turbo Mode enabled, you can perform gestures as long as you hold down a modifier key such as Shift or Ctrl.",
"enable-turbo-mode": "Enable Turbo Mode",
"enable-turbo-mode-warning": "Disabled due to the 'Keep active application focused' option being enabled.",
"move-pointer-to-menu-center-info": "If checked, the mouse pointer will be moved to the center of a menu or submenu when necessary. This could be the case if a menu is opened too close to the edge of the screen or if a menu is opened in Centered Mode.",
"move-pointer-to-menu-center": "Move pointer to the menu center",
"return-pointer-after-selection-info": "After you make a selection, the mouse pointer will move back to where it was when the menu was opened.",
Expand Down Expand Up @@ -213,7 +215,10 @@
"backup-menus-note": "This will backup or restore all your menus at once. This includes all your configured shortcuts, menu layouts, and your menu collections.",
"backup-settings-note": "This will backup or restore Kando's settings, which include all your general settings and your menu-theme configuration.",
"settings-dialog-and-tray-icon": "Settings Dialog & Tray Icon",
"achievements": "Achievements"
"achievements": "Achievements",
"trigger-center-click-on-key-release-info": "This will trigger the center-click workflow when a key is released while hovering over the center of a menu.",
"trigger-center-click-on-key-release": "Trigger center-click workflow on key release",
"trigger-center-click-on-key-release-warning": "This option will instantly close the menu when you release the shortcut. Activate this only if you know what you are doing!"
},
"introduction-dialog": {
"slide1-title": "Kando offers a unique and efficient way for interacting with your computer.",
Expand Down
7 changes: 7 additions & 0 deletions src/common/settings-schemata/general-settings-v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ export const GENERAL_SETTINGS_SCHEMA_V1 = z.object({
/** If enabled, menus using the hover mode require a final click for selecting items. */
hoverModeNeedsConfirmation: z.boolean().default(false),

/**
* If enabled, the center-click-workflow will be executed when a key is released while
* hovering over the center of a menu. This can be used to hide the menu without
* selecting an item in turbo mode.
*/
triggerCenterClickOnKeyRelease: z.boolean().default(false),

/** Shorter gestures will not lead to selections. */
gestureMinStrokeLength: z.number().min(0).default(150),

Expand Down
26 changes: 20 additions & 6 deletions src/menu-renderer/input-methods/pointer-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ export class PointerInput extends InputMethod {
/** If set to true, the hover mode will only select final actions with a mouse click. */
public hoverModeNeedsConfirmation = false;

/**
* If enabled, pressing a key while hovering over the center of a menu will trigger the
* center-click workflow.
*/
public triggerCenterClickOnKeyRelease = false;

/**
* This is used to detect gestures in "Marking Mode" and "Turbo Mode". It is fed with
* motion events and emits a selection event if either the mouse pointer was stationary
Expand Down Expand Up @@ -315,12 +321,20 @@ export class PointerInput extends InputMethod {
if (!stillAnyModifierPressed) {
this.deferredTurboMode = false;

// Select the active item if turbo mode ended due to a key release. But do not
// trigger selections on the center item in turbo mode.
if (
this.buttonState === ButtonState.eDragged &&
math.getDistance(this.pointerPosition, this.centerPosition) > this.centerRadius
) {
// Only if triggerCenterClickOnKeyRelease is enabled, we trigger the center-click-
// workflow when a key is released while hovering over the center of a menu. Else,
// we do not trigger selections on the center item in turbo mode.
let triggerSelection = false;

if (this.triggerCenterClickOnKeyRelease) {
triggerSelection = true;
} else {
triggerSelection =
this.buttonState === ButtonState.eDragged &&
math.getDistance(this.pointerPosition, this.centerPosition) > this.centerRadius;
}

if (triggerSelection) {
this.gestureDetector.reset();
this.selectCallback(
this.pointerPosition,
Expand Down
6 changes: 4 additions & 2 deletions src/menu-renderer/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ export class Menu extends (EventEmitter as new () => TypedEventEmitter<MenuEvent
this.pointerInput.enableHoverMode = showMenuOptions.hoverMode;
this.pointerInput.hoverModeNeedsConfirmation =
this.settings.hoverModeNeedsConfirmation;
this.pointerInput.triggerCenterClickOnKeyRelease =
this.settings.triggerCenterClickOnKeyRelease;

this.root = root;
this.createRenderData(this.root, this.container);
Expand Down Expand Up @@ -313,6 +315,8 @@ export class Menu extends (EventEmitter as new () => TypedEventEmitter<MenuEvent
this.pointerInput.dragThreshold = this.settings.dragThreshold;
this.pointerInput.hoverModeNeedsConfirmation =
this.settings.hoverModeNeedsConfirmation;
this.pointerInput.triggerCenterClickOnKeyRelease =
this.settings.triggerCenterClickOnKeyRelease;

this.pointerInput.gestureDetector.minStrokeLength =
this.settings.gestureMinStrokeLength;
Expand Down Expand Up @@ -496,8 +500,6 @@ export class Menu extends (EventEmitter as new () => TypedEventEmitter<MenuEvent
selectionKeys.push(`num${i + 1}`);
}

console.log('selectionKeys', selectionKeys, eventKey);

if (selectionKeys.includes(eventKey)) {
this.emitSelectionEvent(child, SelectionSource.eKeyboard);
this.selectItem(child, this.getCenterItemPosition());
Expand Down
4 changes: 4 additions & 0 deletions src/settings-renderer/components/common/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type Props = {
/** Optional information to display next to the label. */
readonly info?: string;

/** Optional warning to display next to the widget. */
readonly warning?: string;

/** Whether the checkbox is disabled. Defaults to false. */
readonly isDisabled?: boolean;

Expand All @@ -45,6 +48,7 @@ export default function Checkbox(props: Props) {
<SettingsRow
isLabelClickable
info={props.info}
warning={props.warning}
isDisabled={props.isDisabled}
isFlipped={props.isFlipped}
label={props.label}>
Expand Down
9 changes: 9 additions & 0 deletions src/settings-renderer/components/common/InfoItem.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
.info {
color: $widget-normal;
font-size: 1.2em;
padding: 0 0.2em;

&:hover {
color: $widget-normal-hover;
Expand All @@ -22,4 +23,12 @@
position: relative;
top: 0.2em;
}

&.warning {
color: rgb(233, 144, 49);

&:hover {
color: rgb(236, 163, 85);
}
}
}
14 changes: 11 additions & 3 deletions src/settings-renderer/components/common/InfoItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@
// SPDX-License-Identifier: MIT

import React from 'react';
import { TbInfoSquareRoundedFilled } from 'react-icons/tb';
import classNames from 'classnames/bind';
import { TbInfoSquareRoundedFilled, TbAlertTriangleFilled } from 'react-icons/tb';

import * as classes from './InfoItem.module.scss';
const cx = classNames.bind(classes);

type Props = {
/** Text to display in the tooltip. */
readonly info: string;

/** If true, it will show a warning-sign instead of an info icon. */
readonly isWarning?: boolean;
};

/**
Expand All @@ -27,10 +32,13 @@ type Props = {
export default function InfoItem(props: Props) {
return (
<span
className={classes.info}
className={cx({
info: true,
warning: props.isWarning,
})}
data-tooltip-content={props.info}
data-tooltip-id="main-tooltip">
<TbInfoSquareRoundedFilled />
{props.isWarning ? <TbAlertTriangleFilled /> : <TbInfoSquareRoundedFilled />}
</span>
);
}
4 changes: 4 additions & 0 deletions src/settings-renderer/components/common/SettingsCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type Props<K extends keyof GeneralSettings> = {
/** Optional information to display next to the label. */
readonly info?: string;

/** Optional warning to display next to the widget. */
readonly warning?: string;

/** Whether the checkbox is disabled. Defaults to false. */
readonly isDisabled?: boolean;

Expand Down Expand Up @@ -54,6 +57,7 @@ export default function SettingsCheckbox<K extends BooleanKeys<GeneralSettings>>
return (
<Checkbox
info={props.info}
warning={props.warning}
initialValue={state}
isDisabled={props.isDisabled}
isFlipped={props.isFlipped}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

&.disabled {
opacity: 0.5;
pointer-events: none;
}

.widget {
Expand Down
7 changes: 7 additions & 0 deletions src/settings-renderer/components/common/SettingsRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type Props = {
/** Optional information to display next to the label. */
readonly info?: string;

/** Optional warning to display next to the widget. */
readonly warning?: string;

/**
* If set to true, the settings row will be wrapped inside a label element so that
* clicking the label will focus the widget. Defaults to false.
Expand Down Expand Up @@ -72,6 +75,10 @@ export default function SettingsRow(props: Props) {
);
}

if (props.warning) {
widgets.push(<InfoItem key="warning" isWarning info={props.warning} />);
}

if (props.children) {
widgets.push(
<div
Expand Down
32 changes: 32 additions & 0 deletions src/settings-renderer/components/dialogs/GeneralSettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export default function GeneralSettingsDialog() {
const setSettingsDialogVisible = useAppState((state) => state.setSettingsDialogVisible);
const soundThemes = useAppState((state) => state.soundThemes);
const [keepInputFocus] = useGeneralSetting('keepInputFocus');
const [triggerCenterClickOnKeyRelease] = useGeneralSetting(
'triggerCenterClickOnKeyRelease'
);
const backend = useAppState((state) => state.backendInfo);
const [activeCategory, setActiveCategory] = React.useState(0);
const [transitionDirection, setTransitionDirection] =
Expand Down Expand Up @@ -344,6 +347,11 @@ export default function GeneralSettingsDialog() {
settingsKey="enableMarkingMode"
/>
<SettingsCheckbox
warning={
keepInputFocus
? i18next.t('settings.general-settings-dialog.enable-turbo-mode-warning')
: undefined
}
info={i18next.t('settings.general-settings-dialog.enable-turbo-mode-info')}
isDisabled={keepInputFocus}
label={i18next.t('settings.general-settings-dialog.enable-turbo-mode')}
Expand All @@ -358,8 +366,32 @@ export default function GeneralSettingsDialog() {
)}
settingsKey="hoverModeNeedsConfirmation"
/>
<SettingsCheckbox
warning={
keepInputFocus
? i18next.t('settings.general-settings-dialog.enable-turbo-mode-warning')
: triggerCenterClickOnKeyRelease
? i18next.t(
'settings.general-settings-dialog.trigger-center-click-on-key-release-warning'
)
: undefined
}
info={i18next.t(
'settings.general-settings-dialog.trigger-center-click-on-key-release-info'
)}
isDisabled={keepInputFocus}
label={i18next.t(
'settings.general-settings-dialog.trigger-center-click-on-key-release'
)}
settingsKey="triggerCenterClickOnKeyRelease"
/>
<h1>{i18next.t('settings.general-settings-dialog.input-options')}</h1>
<SettingsCheckbox
warning={
keepInputFocus
? i18next.t('settings.general-settings-dialog.keep-input-focus-warning')
: undefined
}
info={i18next.t('settings.general-settings-dialog.keep-input-focus-info')}
label={i18next.t('settings.general-settings-dialog.keep-input-focus')}
settingsKey="keepInputFocus"
Expand Down
Loading
Loading