feat: validate widget gesture actions in plugin manifests
This commit is contained in:
@@ -112,6 +112,17 @@ SETTING_OWNER_TYPES = ("widget", "panel", "desktop_widget", "launcher_provider")
|
||||
SETTING_TYPES = {"string", "string_list", "bool", "glyph", "select", "folder", "file", "int", "color"}
|
||||
PANEL_PLACEMENTS = {"attached", "floating"}
|
||||
PANEL_KEYBOARD_FOCUS = {"on_demand", "exclusive", "none"}
|
||||
WIDGET_GESTURES = {
|
||||
"left",
|
||||
"right",
|
||||
"middle",
|
||||
"back",
|
||||
"forward",
|
||||
"scroll_up",
|
||||
"scroll_down",
|
||||
"scroll_left",
|
||||
"scroll_right",
|
||||
}
|
||||
PANEL_POSITIONS = {
|
||||
"auto",
|
||||
"center",
|
||||
@@ -132,7 +143,7 @@ ROOT_FIELDS = set(ROOT_STRING_FIELDS) | set(ROOT_ARRAY_FIELDS) | set(ENTRY_TYPES
|
||||
}
|
||||
BASE_ENTRY_FIELDS = {"id", "entry"}
|
||||
ENTRY_FIELDS = {
|
||||
"widget": BASE_ENTRY_FIELDS | {"setting"},
|
||||
"widget": BASE_ENTRY_FIELDS | {"setting", "actions"},
|
||||
"panel": BASE_ENTRY_FIELDS
|
||||
| {
|
||||
"setting",
|
||||
@@ -778,6 +789,46 @@ class Validator:
|
||||
manifest_path, context, "capture_keys must be an array of key chord strings"
|
||||
)
|
||||
|
||||
def validate_widget_fields(
|
||||
self,
|
||||
manifest_path: Path,
|
||||
context: str,
|
||||
entry: dict[str, Any],
|
||||
plugin_api: Any,
|
||||
) -> None:
|
||||
if "actions" not in entry:
|
||||
return
|
||||
|
||||
if not is_int(plugin_api) or plugin_api < 14:
|
||||
self.add_context_error(manifest_path, context, "actions requires plugin_api >= 14")
|
||||
return
|
||||
|
||||
actions = entry["actions"]
|
||||
if not isinstance(actions, dict):
|
||||
self.add_context_error(
|
||||
manifest_path, context, "actions must be a table of gesture bindings"
|
||||
)
|
||||
return
|
||||
|
||||
for gesture, action in actions.items():
|
||||
if gesture not in WIDGET_GESTURES:
|
||||
valid = ", ".join(sorted(WIDGET_GESTURES))
|
||||
self.add_context_error(
|
||||
manifest_path, context, f"actions.{gesture} is not a gesture (expected one of: {valid})"
|
||||
)
|
||||
continue
|
||||
if not is_non_empty_string(action):
|
||||
self.add_context_error(
|
||||
manifest_path, context, f"actions.{gesture} must be a non-empty string"
|
||||
)
|
||||
continue
|
||||
# The shell resolves the verb against its live IPC registry, which is not available
|
||||
# here, so only the grammar is checked: "<verb> [args]", "exec <command>", or "none".
|
||||
if action.split()[0] == "exec" and len(action.split(maxsplit=1)) < 2:
|
||||
self.add_context_error(
|
||||
manifest_path, context, f"actions.{gesture}: exec needs a command line"
|
||||
)
|
||||
|
||||
def validate_entries(
|
||||
self,
|
||||
manifest_path: Path,
|
||||
@@ -825,6 +876,9 @@ class Validator:
|
||||
if entry_type == "panel":
|
||||
self.validate_panel_fields(manifest_path, context, entry, manifest.get("plugin_api"))
|
||||
|
||||
if entry_type == "widget":
|
||||
self.validate_widget_fields(manifest_path, context, entry, manifest.get("plugin_api"))
|
||||
|
||||
if entry_type in SETTING_OWNER_TYPES and "setting" in entry:
|
||||
self.validate_settings(
|
||||
manifest_path,
|
||||
|
||||
Reference in New Issue
Block a user