mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
action: add If and ForEach actions
Add If and ForEach actions as described in OpenBox specification. Limitations: - If and ForEach cannot contain nested If and ForEach.
This commit is contained in:
parent
12f6a8975a
commit
22e3be40e5
4 changed files with 307 additions and 3 deletions
|
|
@ -148,6 +148,56 @@ Actions are used in menus and keyboard/mouse bindings.
|
||||||
*<action name="None" />*
|
*<action name="None" />*
|
||||||
If used as the only action for a binding: clear an earlier defined binding.
|
If used as the only action for a binding: clear an earlier defined binding.
|
||||||
|
|
||||||
|
# CONDITIONAL ACTIONS
|
||||||
|
|
||||||
|
Actions that execute other actions. Used in keyboard/mouse bindings.
|
||||||
|
|
||||||
|
*<action name="If">*
|
||||||
|
This action will execute one set of actions if the focused window
|
||||||
|
matches the criteria, or another if it does not.
|
||||||
|
|
||||||
|
The arguments are as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
<action name="If">
|
||||||
|
<query/>
|
||||||
|
<then><action/></then>
|
||||||
|
<else><action/></else>
|
||||||
|
</action>
|
||||||
|
```
|
||||||
|
|
||||||
|
*query*
|
||||||
|
Define a query with zero or more conditions. All conditions must
|
||||||
|
be evaluated as true in order for the window to match this
|
||||||
|
query. Multiple queries can be defined.
|
||||||
|
|
||||||
|
Pattern matching is done according to glob(7) and is
|
||||||
|
case-insensitive.
|
||||||
|
|
||||||
|
Conditions are as follows:
|
||||||
|
|
||||||
|
*identifier*
|
||||||
|
XDG shell app_id for Wayland clients, WM_CLASS for
|
||||||
|
XWayland clients.
|
||||||
|
|
||||||
|
*title*
|
||||||
|
XDG shell title for Wayland clients, WM_NAME for
|
||||||
|
XWayland clients.
|
||||||
|
|
||||||
|
This argument is optional.
|
||||||
|
|
||||||
|
*then*
|
||||||
|
A list of actions to be executed if the window matches any
|
||||||
|
query. This argument is optional.
|
||||||
|
|
||||||
|
*else*
|
||||||
|
A list of actions to be executed if the window does not match
|
||||||
|
any query. This argument is optional.
|
||||||
|
|
||||||
|
*<action name="ForEach">*
|
||||||
|
Identical to "If" action, but applies to all windows, not just the
|
||||||
|
focused one.
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
labwc(1), labwc-config(5), labwc-theme(5)
|
labwc(1), labwc-config(5), labwc-theme(5), glob(7)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@ struct action *action_create(const char *action_name);
|
||||||
bool action_is_valid(struct action *action);
|
bool action_is_valid(struct action *action);
|
||||||
|
|
||||||
void action_arg_add_str(struct action *action, const char *key, const char *value);
|
void action_arg_add_str(struct action *action, const char *key, const char *value);
|
||||||
|
void action_arg_add_actionlist(struct action *action, const char *key);
|
||||||
|
void action_arg_add_querylist(struct action *action, const char *key);
|
||||||
|
|
||||||
|
struct wl_list *action_get_actionlist(struct action *action, const char *key);
|
||||||
|
struct wl_list *action_get_querylist(struct action *action, const char *key);
|
||||||
|
|
||||||
void action_arg_from_xml_node(struct action *action, const char *nodename, const char *content);
|
void action_arg_from_xml_node(struct action *action, const char *nodename, const char *content);
|
||||||
|
|
||||||
|
|
|
||||||
128
src/action.c
128
src/action.c
|
|
@ -7,6 +7,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
|
#include "common/array-size.h"
|
||||||
#include "common/list.h"
|
#include "common/list.h"
|
||||||
#include "common/mem.h"
|
#include "common/mem.h"
|
||||||
#include "common/parse-bool.h"
|
#include "common/parse-bool.h"
|
||||||
|
|
@ -24,6 +25,8 @@ enum action_arg_type {
|
||||||
LAB_ACTION_ARG_STR = 0,
|
LAB_ACTION_ARG_STR = 0,
|
||||||
LAB_ACTION_ARG_BOOL,
|
LAB_ACTION_ARG_BOOL,
|
||||||
LAB_ACTION_ARG_INT,
|
LAB_ACTION_ARG_INT,
|
||||||
|
LAB_ACTION_ARG_QUERY_LIST,
|
||||||
|
LAB_ACTION_ARG_ACTION_LIST,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct action_arg {
|
struct action_arg {
|
||||||
|
|
@ -48,6 +51,11 @@ struct action_arg_int {
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct action_arg_list {
|
||||||
|
struct action_arg base;
|
||||||
|
struct wl_list value;
|
||||||
|
};
|
||||||
|
|
||||||
enum action_type {
|
enum action_type {
|
||||||
ACTION_TYPE_INVALID = 0,
|
ACTION_TYPE_INVALID = 0,
|
||||||
ACTION_TYPE_NONE,
|
ACTION_TYPE_NONE,
|
||||||
|
|
@ -82,6 +90,8 @@ enum action_type {
|
||||||
ACTION_TYPE_SNAP_TO_REGION,
|
ACTION_TYPE_SNAP_TO_REGION,
|
||||||
ACTION_TYPE_TOGGLE_KEYBINDS,
|
ACTION_TYPE_TOGGLE_KEYBINDS,
|
||||||
ACTION_TYPE_FOCUS_OUTPUT,
|
ACTION_TYPE_FOCUS_OUTPUT,
|
||||||
|
ACTION_TYPE_IF,
|
||||||
|
ACTION_TYPE_FOR_EACH,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *action_names[] = {
|
const char *action_names[] = {
|
||||||
|
|
@ -118,6 +128,8 @@ const char *action_names[] = {
|
||||||
"SnapToRegion",
|
"SnapToRegion",
|
||||||
"ToggleKeybinds",
|
"ToggleKeybinds",
|
||||||
"FocusOutput",
|
"FocusOutput",
|
||||||
|
"If",
|
||||||
|
"ForEach",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -158,6 +170,30 @@ action_arg_add_int(struct action *action, const char *key, int value)
|
||||||
wl_list_append(&action->args, &arg->base.link);
|
wl_list_append(&action->args, &arg->base.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
action_arg_add_list(struct action *action, const char *key, enum action_arg_type type)
|
||||||
|
{
|
||||||
|
assert(action);
|
||||||
|
assert(key);
|
||||||
|
struct action_arg_list *arg = znew(*arg);
|
||||||
|
arg->base.type = type;
|
||||||
|
arg->base.key = xstrdup(key);
|
||||||
|
wl_list_init(&arg->value);
|
||||||
|
wl_list_append(&action->args, &arg->base.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
action_arg_add_querylist(struct action *action, const char *key)
|
||||||
|
{
|
||||||
|
action_arg_add_list(action, key, LAB_ACTION_ARG_QUERY_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
action_arg_add_actionlist(struct action *action, const char *key)
|
||||||
|
{
|
||||||
|
action_arg_add_list(action, key, LAB_ACTION_ARG_ACTION_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
action_get_arg(struct action *action, const char *key, enum action_arg_type type)
|
action_get_arg(struct action *action, const char *key, enum action_arg_type type)
|
||||||
{
|
{
|
||||||
|
|
@ -193,6 +229,20 @@ action_get_int(struct action *action, const char *key, int default_value)
|
||||||
return arg ? arg->value : default_value;
|
return arg ? arg->value : default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wl_list *
|
||||||
|
action_get_querylist(struct action *action, const char *key)
|
||||||
|
{
|
||||||
|
struct action_arg_list *arg = action_get_arg(action, key, LAB_ACTION_ARG_QUERY_LIST);
|
||||||
|
return arg ? &arg->value : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_list *
|
||||||
|
action_get_actionlist(struct action *action, const char *key)
|
||||||
|
{
|
||||||
|
struct action_arg_list *arg = action_get_arg(action, key, LAB_ACTION_ARG_ACTION_LIST);
|
||||||
|
return arg ? &arg->value : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
action_arg_from_xml_node(struct action *action, const char *nodename, const char *content)
|
action_arg_from_xml_node(struct action *action, const char *nodename, const char *content)
|
||||||
{
|
{
|
||||||
|
|
@ -327,6 +377,20 @@ actions_contain_toggle_keybinds(struct wl_list *action_list)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
action_list_is_valid(struct wl_list *actions)
|
||||||
|
{
|
||||||
|
assert(actions);
|
||||||
|
|
||||||
|
struct action *action;
|
||||||
|
wl_list_for_each(action, actions, link) {
|
||||||
|
if (!action_is_valid(action)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Checks for *required* arguments */
|
/* Checks for *required* arguments */
|
||||||
bool
|
bool
|
||||||
action_is_valid(struct action *action)
|
action_is_valid(struct action *action)
|
||||||
|
|
@ -356,6 +420,19 @@ action_is_valid(struct action *action)
|
||||||
case ACTION_TYPE_FOCUS_OUTPUT:
|
case ACTION_TYPE_FOCUS_OUTPUT:
|
||||||
arg_name = "output";
|
arg_name = "output";
|
||||||
break;
|
break;
|
||||||
|
case ACTION_TYPE_IF:
|
||||||
|
case ACTION_TYPE_FOR_EACH:
|
||||||
|
; /* works around "a label can only be part of a statement" */
|
||||||
|
static const char * const branches[] = { "then", "else" };
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(branches); i++) {
|
||||||
|
struct wl_list *children = action_get_actionlist(action, branches[i]);
|
||||||
|
if (children && !action_list_is_valid(children)) {
|
||||||
|
wlr_log(WLR_ERROR, "Invalid action in %s '%s' branch",
|
||||||
|
action_names[action->type], branches[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
/* No arguments required */
|
/* No arguments required */
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -381,6 +458,15 @@ action_free(struct action *action)
|
||||||
if (arg->type == LAB_ACTION_ARG_STR) {
|
if (arg->type == LAB_ACTION_ARG_STR) {
|
||||||
struct action_arg_str *str_arg = (struct action_arg_str *)arg;
|
struct action_arg_str *str_arg = (struct action_arg_str *)arg;
|
||||||
zfree(str_arg->value);
|
zfree(str_arg->value);
|
||||||
|
} else if (arg->type == LAB_ACTION_ARG_ACTION_LIST) {
|
||||||
|
struct action_arg_list *list_arg = (struct action_arg_list *)arg;
|
||||||
|
action_list_free(&list_arg->value);
|
||||||
|
} else if (arg->type == LAB_ACTION_ARG_QUERY_LIST) {
|
||||||
|
struct action_arg_list *list_arg = (struct action_arg_list *)arg;
|
||||||
|
struct view_query *elm, *next;
|
||||||
|
wl_list_for_each_safe(elm, next, &list_arg->value, link) {
|
||||||
|
view_query_free(elm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
zfree(arg);
|
zfree(arg);
|
||||||
}
|
}
|
||||||
|
|
@ -466,6 +552,31 @@ view_for_action(struct view *activator, struct server *server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
run_if_action(struct view *view, struct server *server, struct action *action)
|
||||||
|
{
|
||||||
|
struct view_query *query;
|
||||||
|
struct wl_list *queries, *actions;
|
||||||
|
const char *branch = "then";
|
||||||
|
|
||||||
|
queries = action_get_querylist(action, "query");
|
||||||
|
if (queries) {
|
||||||
|
branch = "else";
|
||||||
|
/* All queries are OR'ed */
|
||||||
|
wl_list_for_each(query, queries, link) {
|
||||||
|
if (view_matches_query(view, query)) {
|
||||||
|
branch = "then";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actions = action_get_actionlist(action, branch);
|
||||||
|
if (actions) {
|
||||||
|
actions_run(view, server, actions, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
actions_run(struct view *activator, struct server *server,
|
actions_run(struct view *activator, struct server *server,
|
||||||
struct wl_list *actions, uint32_t resize_edges)
|
struct wl_list *actions, uint32_t resize_edges)
|
||||||
|
|
@ -693,6 +804,23 @@ actions_run(struct view *activator, struct server *server,
|
||||||
desktop_focus_output(output_from_name(server, output_name));
|
desktop_focus_output(output_from_name(server, output_name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ACTION_TYPE_IF:
|
||||||
|
if (view) {
|
||||||
|
run_if_action(view, server, action);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_TYPE_FOR_EACH:
|
||||||
|
{
|
||||||
|
struct wl_array views;
|
||||||
|
struct view **item;
|
||||||
|
wl_array_init(&views);
|
||||||
|
view_array_append(server, &views, LAB_VIEW_CRITERIA_NONE);
|
||||||
|
wl_array_for_each(item, &views) {
|
||||||
|
run_if_action(*item, server, action);
|
||||||
|
}
|
||||||
|
wl_array_release(&views);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ACTION_TYPE_INVALID:
|
case ACTION_TYPE_INVALID:
|
||||||
wlr_log(WLR_ERROR, "Not executing unknown action");
|
wlr_log(WLR_ERROR, "Not executing unknown action");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "config/rcxml.h"
|
#include "config/rcxml.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "regions.h"
|
#include "regions.h"
|
||||||
|
#include "view.h"
|
||||||
#include "window-rules.h"
|
#include "window-rules.h"
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
|
|
||||||
|
|
@ -37,6 +38,9 @@ static bool in_mousebind;
|
||||||
static bool in_libinput_category;
|
static bool in_libinput_category;
|
||||||
static bool in_window_switcher_field;
|
static bool in_window_switcher_field;
|
||||||
static bool in_window_rules;
|
static bool in_window_rules;
|
||||||
|
static bool in_action_query;
|
||||||
|
static bool in_action_then_branch;
|
||||||
|
static bool in_action_else_branch;
|
||||||
|
|
||||||
static struct usable_area_override *current_usable_area_override;
|
static struct usable_area_override *current_usable_area_override;
|
||||||
static struct keybind *current_keybind;
|
static struct keybind *current_keybind;
|
||||||
|
|
@ -49,6 +53,8 @@ static struct region *current_region;
|
||||||
static struct window_switcher_field *current_field;
|
static struct window_switcher_field *current_field;
|
||||||
static struct window_rule *current_window_rule;
|
static struct window_rule *current_window_rule;
|
||||||
static struct action *current_window_rule_action;
|
static struct action *current_window_rule_action;
|
||||||
|
static struct view_query *current_view_query;
|
||||||
|
static struct action *current_child_action;
|
||||||
|
|
||||||
enum font_place {
|
enum font_place {
|
||||||
FONT_PLACE_NONE = 0,
|
FONT_PLACE_NONE = 0,
|
||||||
|
|
@ -246,6 +252,79 @@ fill_region(char *nodename, char *content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_action_query(char *nodename, char *content, struct action *action)
|
||||||
|
{
|
||||||
|
string_truncate_at_pattern(nodename, ".keybind.keyboard");
|
||||||
|
string_truncate_at_pattern(nodename, ".mousebind.context.mouse");
|
||||||
|
|
||||||
|
if (!strcasecmp(nodename, "query.action")) {
|
||||||
|
current_view_query = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_truncate_at_pattern(nodename, ".query.action");
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current_view_query) {
|
||||||
|
struct wl_list *queries = action_get_querylist(action, "query");
|
||||||
|
if (!queries) {
|
||||||
|
action_arg_add_querylist(action, "query");
|
||||||
|
queries = action_get_querylist(action, "query");
|
||||||
|
}
|
||||||
|
current_view_query = znew(*current_view_query);
|
||||||
|
wl_list_append(queries, ¤t_view_query->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcasecmp(nodename, "identifier")) {
|
||||||
|
current_view_query->identifier = xstrdup(content);
|
||||||
|
} else if (!strcasecmp(nodename, "title")) {
|
||||||
|
current_view_query->title = xstrdup(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_child_action(char *nodename, char *content, struct action *parent,
|
||||||
|
const char *branch_name)
|
||||||
|
{
|
||||||
|
string_truncate_at_pattern(nodename, ".keybind.keyboard");
|
||||||
|
string_truncate_at_pattern(nodename, ".mousebind.context.mouse");
|
||||||
|
string_truncate_at_pattern(nodename, ".then.action");
|
||||||
|
string_truncate_at_pattern(nodename, ".else.action");
|
||||||
|
|
||||||
|
if (!strcasecmp(nodename, "action")) {
|
||||||
|
current_child_action = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_list *siblings = action_get_actionlist(parent, branch_name);
|
||||||
|
if (!siblings) {
|
||||||
|
action_arg_add_actionlist(parent, branch_name);
|
||||||
|
siblings = action_get_actionlist(parent, branch_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcasecmp(nodename, "name.action")) {
|
||||||
|
if (!strcasecmp(content, "If") || !strcasecmp(content, "ForEach")) {
|
||||||
|
wlr_log(WLR_ERROR, "action '%s' cannot be a child action", content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_child_action = action_create(content);
|
||||||
|
if (current_child_action) {
|
||||||
|
wl_list_append(siblings, ¤t_child_action->link);
|
||||||
|
}
|
||||||
|
} else if (!current_child_action) {
|
||||||
|
wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
|
||||||
|
"nodename: '%s' content: '%s'", nodename, content);
|
||||||
|
} else {
|
||||||
|
action_arg_from_xml_node(current_child_action, nodename, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_keybind(char *nodename, char *content)
|
fill_keybind(char *nodename, char *content)
|
||||||
{
|
{
|
||||||
|
|
@ -539,11 +618,33 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
fill_usable_area_override(nodename, content);
|
fill_usable_area_override(nodename, content);
|
||||||
}
|
}
|
||||||
if (in_keybind) {
|
if (in_keybind) {
|
||||||
|
if (in_action_query) {
|
||||||
|
fill_action_query(nodename, content,
|
||||||
|
current_keybind_action);
|
||||||
|
} else if (in_action_then_branch) {
|
||||||
|
fill_child_action(nodename, content,
|
||||||
|
current_keybind_action, "then");
|
||||||
|
} else if (in_action_else_branch) {
|
||||||
|
fill_child_action(nodename, content,
|
||||||
|
current_keybind_action, "else");
|
||||||
|
} else {
|
||||||
fill_keybind(nodename, content);
|
fill_keybind(nodename, content);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (in_mousebind) {
|
if (in_mousebind) {
|
||||||
|
if (in_action_query) {
|
||||||
|
fill_action_query(nodename, content,
|
||||||
|
current_mousebind_action);
|
||||||
|
} else if (in_action_then_branch) {
|
||||||
|
fill_child_action(nodename, content,
|
||||||
|
current_mousebind_action, "then");
|
||||||
|
} else if (in_action_else_branch) {
|
||||||
|
fill_child_action(nodename, content,
|
||||||
|
current_mousebind_action, "else");
|
||||||
|
} else {
|
||||||
fill_mousebind(nodename, content);
|
fill_mousebind(nodename, content);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (in_libinput_category) {
|
if (in_libinput_category) {
|
||||||
fill_libinput_category(nodename, content);
|
fill_libinput_category(nodename, content);
|
||||||
}
|
}
|
||||||
|
|
@ -771,6 +872,24 @@ xml_tree_walk(xmlNode *node)
|
||||||
in_window_rules = false;
|
in_window_rules = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcasecmp((char *)n->name, "query")) {
|
||||||
|
in_action_query = true;
|
||||||
|
traverse(n);
|
||||||
|
in_action_query = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcasecmp((char *)n->name, "then")) {
|
||||||
|
in_action_then_branch = true;
|
||||||
|
traverse(n);
|
||||||
|
in_action_then_branch = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcasecmp((char *)n->name, "else")) {
|
||||||
|
in_action_else_branch = true;
|
||||||
|
traverse(n);
|
||||||
|
in_action_else_branch = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
traverse(n);
|
traverse(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1366,6 +1485,8 @@ rcxml_finish(void)
|
||||||
current_mouse_context = NULL;
|
current_mouse_context = NULL;
|
||||||
current_keybind_action = NULL;
|
current_keybind_action = NULL;
|
||||||
current_mousebind_action = NULL;
|
current_mousebind_action = NULL;
|
||||||
|
current_child_action = NULL;
|
||||||
|
current_view_query = NULL;
|
||||||
current_region = NULL;
|
current_region = NULL;
|
||||||
current_field = NULL;
|
current_field = NULL;
|
||||||
current_window_rule = NULL;
|
current_window_rule = NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue