Skip to content

Configuration guide

Alfredo Sequeida edited this page Feb 9, 2025 · 29 revisions

Hints comes with sensible defaults, meaning you don't have to configure anything to start using it, but gives you the ability to customize as you wish. The values shown in these configuration options are also the default values. The full default config can be found here assigned to the DEFAULT_CONFIG variable.

To configure hints create a file in /home/$USER/.config/hints/config.json. This file follows JSON syntax.

Hint options

To edit the style of a hint, edit the hints object. For example:

{
  "hints": {
    "hint_height": 30,
    "hint_width_padding": 10,
    "hint_font_size": 15,
    "hint_font_face": "Sans",
    "hint_font_r": 0,
    "hint_font_g": 0,
    "hint_font_b": 0,
    "hint_font_a": 1,
    "hint_pressed_font_r": 0.5,
    "hint_pressed_font_g": 0.5,
    "hint_pressed_font_b": 0.2,
    "hint_pressed_font_a": 1,
    "hint_upercase": true,
    "hint_background_r": 1,
    "hint_background_g": 1,
    "hint_background_b": 0.5,
    "hint_background_a": 0.6
  }
}

All of the options are documented below.

  • hint_height: The height of the hint shown
  • hint_width_padding: The width of a hint is set automatically to fit the characters in a hint. If you want to add extra padding so that the edges of a hint are not touching the characters in the hint, this option lets you do that.
  • hint_font_size: The size of the font for the hints. A combination of this option and the hint_height let you customize the size of the hint.
  • hint_font_face: The font face for the hint. You can use this option to set a custom font
  • hint_font_r: The amount of red the font color has (0-1).
  • hint_font_g: The amount of green the font color has (0-1).
  • hint_font_b: The amount of blue the font color has (0-1).
  • hint_font_a: The alpha/transparent amount to use for the font (0-1).
  • hint_pressed_font_r: The amount of red the font color has for every letter pressed in a hit (0-1).
  • hint_pressed_font_g: The amount of green the font color has every letter pressed in a hit (0-1).
  • hint_pressed_font_b: The amount of blue the font color has every letter pressed in a hit (0-1).
  • hint_pressed_font_a: The alpha/transparent amount to use for the font every letter pressed in a hit (0-1). Note that because pressed letters are written over the original hint, anything less than 1, will also show the original hint underneath.
  • hint_upercase: If the hints text should be uppercase or not.
  • hint_background_r: The amount of red the background color of a hint has (0-1).
  • hint_background_g: The amount of green the background color of a hint has (0-1).
  • hint_background_b: The amount of blue the background color of a hint has (0-1).
  • hint_background_a: The alpha/transparent amount to use for the hint background (0-1).

Alphabet

By default, hints comes optimized for QWERTY keyboard layouts, however if you are rocking something more exotic, you can configure the 'alphabet' used so that you stay on home row as much as possible (or not if you prefer that.).

{
  "alphabet": "asdfgqwertzxcvbhjklyuiopnm"
}

The order matters here and the alphabet you choose must follow the following rules:

  • Must not use numbers, because numbers are used for multi-clicks.
  • Must not repeat characters.

For your sanity, any invalid characters will be removed for you automatically, but if you don't see them in hints; this is why.

By grouping characters in a specific way, you can make hints that are made up of a specific group of characters more often. You can use this to your advantage by making sure the characters you want to type the most are in those left-most positions (as hints are created from the alphabet from left to right).

With the default setting, this means that the keys on the left half of the keyboard come first prioritizing the home row. To help you create your own alphabets, below is the breakdown of how the default alphabet is structured:

  • left home row: asdfg
  • then above the left home row: qwert
  • then below the left home row: zxcvb
  • now we do the right home row: hjkl
  • then above the right home row: yiuiop
  • and finally, below the right home row: nm

Mouse

For mouse navigation, the following options are available:

{
  "mouse_move_left": "h",
  "mouse_move_right": "l",
  "mouse_move_up": "k",
  "mouse_move_down": "j",
  "mouse_scroll_left": "h",
  "mouse_scroll_right": "l",
  "mouse_scroll_up": "k",
  "mouse_scroll_down": "j",
  "mouse_move_pixel": 10,
  "mouse_move_pixel_sensitivity": 10,
  "mouse_move_rampup_time": 0.5,
  "mouse_scroll_pixel": 5,
  "mouse_scroll_pixel_sensitivity": 5,
  "mouse_scroll_rampup_time": 0.5
}
  • mouse_move_left: Key used to move the mouse left while dragging.
  • mouse_move_right: Key used to move the mouse right while dragging.
  • mouse_move_up: Key used to move the mouse up while dragging.
  • mouse_move_down: Key used to move the mouse down while dragging.
  • mouse_scroll_left: Key used to scroll left in scroll mode.
  • mouse_scroll_right: Key used to scroll right in scroll mode.
  • mouse_scroll_up: Key used to scroll up in scroll mode.
  • mouse_scroll_down: Key used to scroll down in scroll mode.
  • mouse_move_pixel: The amount of pixels to move when moving the mouse.
  • mouse_move_pixel_sensitivity: The amount of pixels to increase moving by after mouse_move_rampup_time. This helps move the mouse faster after mouse_move_rampup_time has been reached.
  • mouse_move_rampup_time: The amount of time (in seconds) to wait before increasing the pixels to move the mouse set by mouse_move_pixel_sensitivity.
  • mouse_scroll_pixel: The amount of pixels to scroll.
  • mouse_scroll_pixel_sensitivity: The amount of pixels to increase scrolling by after mouse_scroll_rampup_time. This helps scroll faster after mouse_scoll_rampup_time has been reached.
  • mouse_scroll_rampup_time: The amount of time (in seconds) to wait before increasing the pixels to scroll by.

Keys

{
  "exit_key": 65307,
  "hover_modifier": 4,
  "grab_modifier": 8
}

The key constants are available here. You will need to click on the constant you are interested in to see the numerical value. The modifier values are available here.

  • exit_key: The key used to quit hints. This stops showing hints/moving the mouse/scrolling/etc. The default value is the ESC key.
  • hover_modifier: The modifier to use for hovering on a hint (without clicking). The default value is the Ctrl key.
  • grab_modifier: The modifier to use for grabbing an element on a hint. After the element has been grabbed, it can be moved with the values for mouse_move_[left/right/up/down]. See the Mouse configuration for more information. The default value is the Alt key.

Backends

Hints uses different backends to gather hints for GUI elements (buttons, text, images ,etc).

{
  "backends": {
    "enable": ["atspi", "opencv"]
  }
}

To enable a backend, you can add it to the enable array under backends. The order matters here. The leftmost backend in the array will be used first. If that backend does not yield any results, the following backend will be used until all backends have been exhausted. If you want to see which backend is being used, you can run hints in a shell like sleep 1; hints -v. The sleep will allow you time to move to the window you want to draw hints for. In the debug statements you can see what the current backend being used is:

2024-12-26 22:41:20,313 - hints.hints - DEBUG - Attempting to get accessible children using the 'atspi' backend.

Below are descriptions of how the backends work:

  • atspi - Uses Atspi to gather accessible elements using assistive technology functionality. To use this backend, you must enable accessibility as well as setup any application specific requirements.
  • opencv - Uses OpenCV to screenshot the active window and uses computer vision to find elements. Note that unlike the atspi backend, opencv cannot filter out what it gathers. This is why you might see an application crowded with hints (when previous backends fail to get hints). As such, this should be used as a fallback backend towards the end of the array.

Atspi Backend

{
  "backends": {
    "atspi": {
      "application_rules": {
        "default": {
          "states": [24, 25, 30],
          "states_match_type": 1,
          "attributes": {},
          "attributes_match_type": 1,
          "roles": [
            39, 85, 25, 23, 34, 63, 31, 38, 121, 49, 55, 116, 83, 73, 123, 110,
            20, 122
          ],
          "roles_match_type": 3
        }
      }
    }
  }
}

The Atspi backend can be configured to only gather hints for a specific combination of States and Roles. These values must be entered in their constant form (as numbers). Here is where you can find those values:

  • States
  • Roles
  • MatchTypes
  • Attributes are objects with key value pair mappings. For example, if the application you are configuring is a web application, an element might have html attributes, so you could for example exclude h1 elements:
{
  "backends": {
    "atspi": {
      "application_rules": {
        "default": {
          "states": [24, 25, 30],
          "states_match_type": 1,
          "attributes": { "tag": "h1" },
          "attributes_match_type": 3,
          "roles": [],
          "match_type": 1,
          "attributes": {},
          "attributes_match_type": 1,
          "roles": [],
          "roles_match_type": 1
        }
      }
    }
  }
}

How do I know what states/roles/attributes to use?

Hints comes with a way to see what states/roles are available if you launch the application from a terminal with the -v flag like this sleep 1; hints -v. Notice the sleep 1. This allows you to wait for 1 second after running the command to switch to the window you want to see information for. You will see something like this (starting from the bottom of the output):

2024-12-26 22:53:32,789 - hints.backends.atspi - DEBUG - Accessible element matched. Name: , ID: 156
2024-12-26 22:53:32,789 - hints.backends.atspi - DEBUG - role: <enum ATSPI_ROLE_CANVAS of type Atspi.Role>
2024-12-26 22:53:32,789 - hints.backends.atspi - DEBUG - states: [<enum ATSPI_STATE_ENABLED of type Atspi.StateType>, <enum ATSPI_STATE_SENSITIVE of type Atspi.StateType>, <enum ATSPI_STATE_SHOWING of type Atspi.StateType>, <enum ATSPI_STATE_VISIBLE of type Atspi.StateType>]
2024-12-26 22:53:32,789 - hints.backends.atspi - DEBUG - Finished gathering hints for 'discord'. Toolkit: Chromium v:1.0
2024-12-26 22:53:32,789 - hints.hints - DEBUG - Gathering hints took 0.057098 seconds
2024-12-26 22:53:32,789 - hints.hints - DEBUG - Gathered 12 hints

Notice the name of the application in the third line from the bottom (discord in this case). This name must match the name used when creating the rule in your JSON config file.

This feature is meant for a quick glance at what is happening. For more complicated applications/configurations, install accerciser. Accerciser gives you a view into the accessible elements of an application showing you a nice tree view of the entire application with State, Role, and attribute information.

Scale factor:

If you are using a custom scale factor within the application or have a HiDPI display with a dpi value that is not the default, you can set the scale factor.

{
  "backends": {
    "atspi": {
      "application_rules": {
        "default": {
          "scale_factor": 1
        }
      }
    }
  }
}

So if your dpi or scale factor is doubled, you can set scale_factor to 2.

How Do I set rules on a per-application basis?

The hope is that the defaults give you good hint coverage so that you don't get too many unnecessary hints while still getting the hints that are relevant for GUI interactions. However, not all applications are built the same and sometimes you might want to change the rules for a specific application. To do this, edit your config file; adding an entry for the application you want to add a rule for.

For example, lets say you notice that you are not getting hints for some specific elements in discord. A good place to start might be to just remove all rules for discord specifically:

{
  "backends": {
    "atspi": {
      "application_rules": {
        "discord": {
          "states": [],
          "states_match_type": 1,
          "attributes": {},
          "attributes_match_type": 1,
          "roles": [],
          "roles_match_type": 1
        }
      }
    },
    "opencv": {
      "application_rules": {
        "nheko": {
          "kernel_size": 5
        }
      }
    }
  }
}

Note: You can also set application rules for other backends like the openvc backend as shown above.

Notice how the discord application name (see here to find out what the application name is) is mentioned and there are no states, roles, or attributes set and all match types are set to 1, which is represents ATSPI_Collection_MATCH_ALL. This will show hints for all possible elements (which might be too many depending on the application and could get overwhelming).

You can then start adding states, roles, or attributes depending on what elements you want hints to exist for.

How do I change the rules for all applications?

To change the rules for all applications override the default match rule in your config for the backend you want to change the defaults for. This allows you to set your own rules or none at all if that's what you prefer.

OpenCV Backend

The opencv backend has some options to control the number of hints you get on your screen. These options are as follow:

  • kernel_size: This is the option you will want to use the most to change the number of hints you get. This is a positive integer that controls the size of the Kernel used for edge dilation. Essentially, it controls how thick edges are. So a larger number will lead to thicker edges increasing the possibility of elements joining together and giving you less hints. A smaller number will lead to thinner edges causing elements to separate more and giving you more hints. Here is a table to explain the same thing with less words:
Kernel Number Elements Are Number of Hints
Larger grouped closer together Less
Smaller further apart More

This can be done for all applications:

{
  "backends": {
    "opencv": {
      "application_rules": {
        "default": { "kernel_size": 6 }
      }
    }
  }
}

or on a per application basis:

{
  "backends": {
    "opencv": {
      "application_rules": {
        "org.gnome.Nautilus": { "kernel_size": 6 },
        "baobab": { "kernel_size": 5 }
      }
    }
  }
}

(see here to find out what the application name is)