mirror of
https://github.com/tmux/tmux.git
synced 2026-08-03 14:08:59 +00:00
Add event payload and use it.
This commit is contained in:
@@ -159,6 +159,7 @@ dist_tmux_SOURCES = \
|
||||
control-notify.c \
|
||||
control.c \
|
||||
environ.c \
|
||||
events-payload.c \
|
||||
events.c \
|
||||
file.c \
|
||||
format.c \
|
||||
|
||||
@@ -85,8 +85,8 @@ static enum cmd_retval cmd_wait_for_lock(struct cmdq_item *, const char *,
|
||||
static enum cmd_retval cmd_wait_for_unlock(struct cmdq_item *, const char *,
|
||||
struct wait_channel *);
|
||||
static enum cmd_retval cmd_wait_for_event(struct cmdq_item *, const char *);
|
||||
static void cmd_wait_for_event_cb(const char *, void *,
|
||||
struct events_type *, void *);
|
||||
static void cmd_wait_for_event_cb(const char *,
|
||||
struct event_payload *, void *);
|
||||
|
||||
static struct wait_channel *cmd_wait_for_add(const char *);
|
||||
static void cmd_wait_for_remove(struct wait_channel *);
|
||||
@@ -158,8 +158,8 @@ cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_wait_for_event_cb(__unused const char *name, __unused void *data,
|
||||
__unused struct events_type *type, void *item_data)
|
||||
cmd_wait_for_event_cb(__unused const char *name,
|
||||
__unused struct event_payload *ep, void *item_data)
|
||||
{
|
||||
struct wait_event_item *wei = item_data;
|
||||
|
||||
|
||||
139
control-notify.c
139
control-notify.c
@@ -31,33 +31,48 @@
|
||||
|
||||
/* Notify control clients that pane mode changed. */
|
||||
static void
|
||||
control_pane_mode_changed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_pane_mode_changed_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct window_pane *wp;
|
||||
struct client *c;
|
||||
char *value;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
control_write(c, "%%pane-mode-changed %%%u", ne->pane);
|
||||
wp = event_payload_get_pane(ep, "pane");
|
||||
if (wp != NULL) {
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
control_write(c, "%%pane-mode-changed %%%u", wp->id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
value = event_payload_print(ep, "pane");
|
||||
if (value == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
control_write(c, "%%pane-mode-changed %s", value);
|
||||
}
|
||||
free(value);
|
||||
}
|
||||
|
||||
/* Notify control clients that window layout changed. */
|
||||
static void
|
||||
control_window_layout_changed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_window_layout_changed_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *c;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window *w = ne->window;
|
||||
struct window *w = event_payload_get_window(ep, "window");
|
||||
const char *template;
|
||||
char *cp;
|
||||
|
||||
if (w == NULL)
|
||||
return;
|
||||
|
||||
template = "%layout-change #{window_id} #{window_layout} "
|
||||
"#{window_visible_layout} #{window_raw_flags}";
|
||||
|
||||
@@ -83,14 +98,13 @@ control_window_layout_changed_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that window pane changed. */
|
||||
static void
|
||||
control_window_pane_changed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_window_pane_changed_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *c;
|
||||
struct window *w = ne->window;
|
||||
struct window *w = event_payload_get_window(ep, "window");
|
||||
|
||||
if (w->active == NULL)
|
||||
if (w == NULL || w->active == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
@@ -103,14 +117,15 @@ control_window_pane_changed_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a window was unlinked. */
|
||||
static void
|
||||
control_window_unlinked_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_window_unlinked_cb(__unused const char *name, struct event_payload *ep,
|
||||
__unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *c;
|
||||
struct session *cs;
|
||||
struct window *w = ne->window;
|
||||
struct window *w = event_payload_get_window(ep, "window");
|
||||
|
||||
if (w == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||
continue;
|
||||
@@ -125,14 +140,15 @@ control_window_unlinked_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a window was linked. */
|
||||
static void
|
||||
control_window_linked_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_window_linked_cb(__unused const char *name, struct event_payload *ep,
|
||||
__unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *c;
|
||||
struct session *cs;
|
||||
struct window *w = ne->window;
|
||||
struct window *w = event_payload_get_window(ep, "window");
|
||||
|
||||
if (w == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||
continue;
|
||||
@@ -147,14 +163,15 @@ control_window_linked_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a window was renamed. */
|
||||
static void
|
||||
control_window_renamed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_window_renamed_cb(__unused const char *name, struct event_payload *ep,
|
||||
__unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *c;
|
||||
struct session *cs;
|
||||
struct window *w = ne->window;
|
||||
struct window *w = event_payload_get_window(ep, "window");
|
||||
|
||||
if (w == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||
continue;
|
||||
@@ -172,15 +189,14 @@ control_window_renamed_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a client changed session. */
|
||||
static void
|
||||
control_client_session_changed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_client_session_changed_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *cc = ne->client;
|
||||
struct client *cc = event_payload_get_client(ep, "client");
|
||||
struct client *c;
|
||||
struct session *s;
|
||||
|
||||
if (cc->session == NULL)
|
||||
if (cc == NULL || cc->session == NULL)
|
||||
return;
|
||||
s = cc->session;
|
||||
|
||||
@@ -200,13 +216,14 @@ control_client_session_changed_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a client detached. */
|
||||
static void
|
||||
control_client_detached_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_client_detached_cb(__unused const char *name, struct event_payload *ep,
|
||||
__unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct client *cc = ne->client;
|
||||
struct client *cc = event_payload_get_client(ep, "client");
|
||||
struct client *c;
|
||||
|
||||
if (cc == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
control_write(c, "%%client-detached %s", cc->name);
|
||||
@@ -215,13 +232,14 @@ control_client_detached_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a session was renamed. */
|
||||
static void
|
||||
control_session_renamed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_session_renamed_cb(__unused const char *name, struct event_payload *ep,
|
||||
__unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct session *s = ne->session;
|
||||
struct session *s = event_payload_get_session(ep, "session");
|
||||
struct client *c;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
@@ -232,8 +250,8 @@ control_session_renamed_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that sessions changed. */
|
||||
static void
|
||||
control_session_created_cb(__unused const char *name, __unused void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_session_created_cb(__unused const char *name,
|
||||
__unused struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct client *c;
|
||||
|
||||
@@ -247,8 +265,8 @@ control_session_created_cb(__unused const char *name, __unused void *data,
|
||||
|
||||
/* Notify control clients that sessions changed. */
|
||||
static void
|
||||
control_session_closed_cb(__unused const char *name, __unused void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_session_closed_cb(__unused const char *name,
|
||||
__unused struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct client *c;
|
||||
|
||||
@@ -262,11 +280,10 @@ control_session_closed_cb(__unused const char *name, __unused void *data,
|
||||
|
||||
/* Notify control clients that the current window changed. */
|
||||
static void
|
||||
control_session_window_changed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_session_window_changed_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct session *s = ne->session;
|
||||
struct session *s = event_payload_get_session(ep, "session");
|
||||
struct client *c;
|
||||
|
||||
/*
|
||||
@@ -274,7 +291,7 @@ control_session_window_changed_cb(__unused const char *name, void *data,
|
||||
* session has been destroyed (which sets curw to NULL) but is kept
|
||||
* alive by the notification's reference. Skip the notification.
|
||||
*/
|
||||
if (s->curw == NULL)
|
||||
if (s == NULL || s->curw == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
@@ -288,33 +305,37 @@ control_session_window_changed_cb(__unused const char *name, void *data,
|
||||
|
||||
/* Notify control clients that a paste buffer changed. */
|
||||
static void
|
||||
control_paste_buffer_changed_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_paste_buffer_changed_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
const char *pbname = event_payload_get_string(ep, "paste_buffer");
|
||||
struct client *c;
|
||||
|
||||
if (pbname == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
control_write(c, "%%paste-buffer-changed %s", ne->pbname);
|
||||
control_write(c, "%%paste-buffer-changed %s", pbname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify control clients that a paste buffer was deleted. */
|
||||
static void
|
||||
control_paste_buffer_deleted_cb(__unused const char *name, void *data,
|
||||
__unused struct events_type *type, __unused void *sink_data)
|
||||
control_paste_buffer_deleted_cb(__unused const char *name,
|
||||
struct event_payload *ep, __unused void *sink_data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
const char *pbname = event_payload_get_string(ep, "paste_buffer");
|
||||
struct client *c;
|
||||
|
||||
if (pbname == NULL)
|
||||
return;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
control_write(c, "%%paste-buffer-deleted %s", ne->pbname);
|
||||
control_write(c, "%%paste-buffer-deleted %s", pbname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
506
events-payload.c
Normal file
506
events-payload.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <event.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* Event payload item. */
|
||||
struct event_payload_item {
|
||||
char *name;
|
||||
enum event_payload_type type;
|
||||
|
||||
union {
|
||||
char *string;
|
||||
time_t time;
|
||||
struct client *client;
|
||||
struct session *session;
|
||||
struct window *window;
|
||||
u_int pane;
|
||||
struct {
|
||||
u_int session;
|
||||
u_int window;
|
||||
int idx;
|
||||
} winlink;
|
||||
struct {
|
||||
void *ptr;
|
||||
event_payload_free_cb free_cb;
|
||||
event_payload_print_cb print_cb;
|
||||
} pointer;
|
||||
};
|
||||
|
||||
RB_ENTRY(event_payload_item) entry;
|
||||
};
|
||||
|
||||
static int
|
||||
event_payload_cmp(struct event_payload_item *epi1,
|
||||
struct event_payload_item *epi2)
|
||||
{
|
||||
return (strcmp(epi1->name, epi2->name));
|
||||
}
|
||||
RB_HEAD(event_payload, event_payload_item);
|
||||
RB_GENERATE_STATIC(event_payload, event_payload_item, entry, event_payload_cmp);
|
||||
|
||||
/* Find an item. */
|
||||
static struct event_payload_item *
|
||||
event_payload_find(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item find = { .name = (char *)name };
|
||||
|
||||
return (RB_FIND(event_payload, ep, &find));
|
||||
}
|
||||
|
||||
/* Free the value in an item. */
|
||||
static void
|
||||
event_payload_free_value(struct event_payload_item *epi)
|
||||
{
|
||||
switch (epi->type) {
|
||||
case EVENT_PAYLOAD_STRING:
|
||||
free(epi->string);
|
||||
break;
|
||||
case EVENT_PAYLOAD_CLIENT:
|
||||
if (epi->client != NULL)
|
||||
server_client_unref(epi->client);
|
||||
break;
|
||||
case EVENT_PAYLOAD_SESSION:
|
||||
if (epi->session != NULL)
|
||||
session_remove_ref(epi->session, __func__);
|
||||
break;
|
||||
case EVENT_PAYLOAD_WINDOW:
|
||||
if (epi->window != NULL)
|
||||
window_remove_ref(epi->window, __func__);
|
||||
break;
|
||||
case EVENT_PAYLOAD_POINTER:
|
||||
if (epi->pointer.free_cb != NULL)
|
||||
epi->pointer.free_cb(epi->pointer.ptr);
|
||||
break;
|
||||
case EVENT_PAYLOAD_TIME:
|
||||
case EVENT_PAYLOAD_PANE:
|
||||
case EVENT_PAYLOAD_WINLINK:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set an item. */
|
||||
static void
|
||||
event_payload_set_item(struct event_payload *ep, const char *name,
|
||||
struct event_payload_item *new)
|
||||
{
|
||||
struct event_payload_item *old;
|
||||
|
||||
new->name = xstrdup(name);
|
||||
old = RB_INSERT(event_payload, ep, new);
|
||||
if (old != NULL) {
|
||||
RB_REMOVE(event_payload, ep, old);
|
||||
event_payload_free_value(old);
|
||||
free(old->name);
|
||||
free(old);
|
||||
RB_INSERT(event_payload, ep, new);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create an event payload. */
|
||||
struct event_payload *
|
||||
event_payload_create(void)
|
||||
{
|
||||
struct event_payload *ep;
|
||||
|
||||
ep = xcalloc(1, sizeof *ep);
|
||||
RB_INIT(ep);
|
||||
return (ep);
|
||||
}
|
||||
|
||||
/* Free an event payload. */
|
||||
void
|
||||
event_payload_free(struct event_payload *ep)
|
||||
{
|
||||
struct event_payload_item *epi, *epi1;
|
||||
|
||||
if (ep != NULL) {
|
||||
RB_FOREACH_SAFE(epi, event_payload, ep, epi1) {
|
||||
RB_REMOVE(event_payload, ep, epi);
|
||||
event_payload_free_value(epi);
|
||||
free(epi->name);
|
||||
free(epi);
|
||||
}
|
||||
free(ep);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set a string item. */
|
||||
void
|
||||
event_payload_set_string(struct event_payload *ep, const char *name,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_STRING;
|
||||
xvasprintf(&epi->string, fmt, ap);
|
||||
event_payload_set_item(ep, name, epi);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Set a time item. */
|
||||
void
|
||||
event_payload_set_time(struct event_payload *ep, const char *name,
|
||||
time_t value)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_TIME;
|
||||
epi->time = value;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Set a client item. */
|
||||
void
|
||||
event_payload_set_client(struct event_payload *ep, const char *name,
|
||||
struct client *c)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
if (c != NULL)
|
||||
c->references++;
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_CLIENT;
|
||||
epi->client = c;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Set a session item. */
|
||||
void
|
||||
event_payload_set_session(struct event_payload *ep, const char *name,
|
||||
struct session *s)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
if (s != NULL)
|
||||
session_add_ref(s, __func__);
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_SESSION;
|
||||
epi->session = s;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Set a window item. */
|
||||
void
|
||||
event_payload_set_window(struct event_payload *ep, const char *name,
|
||||
struct window *w)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
if (w != NULL)
|
||||
window_add_ref(w, __func__);
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_WINDOW;
|
||||
epi->window = w;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Set a pane item. */
|
||||
void
|
||||
event_payload_set_pane(struct event_payload *ep, const char *name,
|
||||
struct window_pane *wp)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_PANE;
|
||||
epi->pane = wp->id;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Set a winlink item. */
|
||||
void
|
||||
event_payload_set_winlink(struct event_payload *ep, const char *name,
|
||||
struct winlink *wl)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_WINLINK;
|
||||
epi->winlink.session = wl->session->id;
|
||||
epi->winlink.window = wl->window->id;
|
||||
epi->winlink.idx = wl->idx;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Set a pointer item. */
|
||||
void
|
||||
event_payload_set_pointer(struct event_payload *ep, const char *name,
|
||||
void *ptr, event_payload_free_cb free_cb, event_payload_print_cb print_cb)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = xcalloc(1, sizeof *epi);
|
||||
epi->type = EVENT_PAYLOAD_POINTER;
|
||||
epi->pointer.ptr = ptr;
|
||||
epi->pointer.free_cb = free_cb;
|
||||
epi->pointer.print_cb = print_cb;
|
||||
event_payload_set_item(ep, name, epi);
|
||||
}
|
||||
|
||||
/* Get a string item. */
|
||||
const char *
|
||||
event_payload_get_string(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_STRING)
|
||||
return (NULL);
|
||||
return (epi->string);
|
||||
}
|
||||
|
||||
/* Print a payload item. */
|
||||
static void
|
||||
event_payload_add_item(struct event_payload_item *epi, struct evbuffer *evb)
|
||||
{
|
||||
switch (epi->type) {
|
||||
case EVENT_PAYLOAD_STRING:
|
||||
evbuffer_add_printf(evb, "%s", epi->string);
|
||||
break;
|
||||
case EVENT_PAYLOAD_TIME:
|
||||
evbuffer_add_printf(evb, "%lld", (long long)epi->time);
|
||||
break;
|
||||
case EVENT_PAYLOAD_CLIENT:
|
||||
if (epi->client != NULL)
|
||||
evbuffer_add_printf(evb, "%s", epi->client->name);
|
||||
break;
|
||||
case EVENT_PAYLOAD_SESSION:
|
||||
if (epi->session != NULL)
|
||||
evbuffer_add_printf(evb, "$%u", epi->session->id);
|
||||
break;
|
||||
case EVENT_PAYLOAD_WINDOW:
|
||||
if (epi->window != NULL)
|
||||
evbuffer_add_printf(evb, "@%u", epi->window->id);
|
||||
break;
|
||||
case EVENT_PAYLOAD_PANE:
|
||||
evbuffer_add_printf(evb, "%%%u", epi->pane);
|
||||
break;
|
||||
case EVENT_PAYLOAD_WINLINK:
|
||||
evbuffer_add_printf(evb, "$%u:%d", epi->winlink.session,
|
||||
epi->winlink.idx);
|
||||
break;
|
||||
case EVENT_PAYLOAD_POINTER:
|
||||
if (epi->pointer.print_cb != NULL)
|
||||
epi->pointer.print_cb(epi->pointer.ptr, evb);
|
||||
else
|
||||
evbuffer_add_printf(evb, "%p", epi->pointer.ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a payload item. */
|
||||
char *
|
||||
event_payload_item_print(struct event_payload_item *epi)
|
||||
{
|
||||
struct evbuffer *evb;
|
||||
char *value = NULL;
|
||||
size_t size;
|
||||
|
||||
evb = evbuffer_new();
|
||||
if (evb == NULL)
|
||||
fatalx("out of memory");
|
||||
event_payload_add_item(epi, evb);
|
||||
if ((size = EVBUFFER_LENGTH(evb)) != 0)
|
||||
value = xmemdup(EVBUFFER_DATA(evb), size);
|
||||
else
|
||||
value = xstrdup("");
|
||||
evbuffer_free(evb);
|
||||
return (value);
|
||||
}
|
||||
|
||||
/* Print an item value. */
|
||||
char *
|
||||
event_payload_print(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL)
|
||||
return (NULL);
|
||||
return (event_payload_item_print(epi));
|
||||
}
|
||||
|
||||
/* Get the first payload item. */
|
||||
struct event_payload_item *
|
||||
event_payload_first(struct event_payload *ep)
|
||||
{
|
||||
return (RB_MIN(event_payload, ep));
|
||||
}
|
||||
|
||||
/* Get the next payload item. */
|
||||
struct event_payload_item *
|
||||
event_payload_next(struct event_payload_item *epi)
|
||||
{
|
||||
return (RB_NEXT(event_payload, , epi));
|
||||
}
|
||||
|
||||
/* Get a payload item name. */
|
||||
const char *
|
||||
event_payload_item_name(struct event_payload_item *epi)
|
||||
{
|
||||
return (epi->name);
|
||||
}
|
||||
|
||||
/* Get a payload item type. */
|
||||
enum event_payload_type
|
||||
event_payload_item_type(struct event_payload_item *epi)
|
||||
{
|
||||
return (epi->type);
|
||||
}
|
||||
|
||||
/* Log a payload. */
|
||||
void
|
||||
event_payload_log(struct event_payload *ep, const char *fmt, ...)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
struct evbuffer *evb;
|
||||
va_list ap;
|
||||
char *prefix;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&prefix, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
evb = evbuffer_new();
|
||||
if (evb == NULL)
|
||||
fatalx("out of memory");
|
||||
if (ep != NULL) {
|
||||
RB_FOREACH(epi, event_payload, ep) {
|
||||
if (EVBUFFER_LENGTH(evb) != 0)
|
||||
evbuffer_add_printf(evb, ", ");
|
||||
evbuffer_add_printf(evb, "%s=", epi->name);
|
||||
event_payload_add_item(epi, evb);
|
||||
}
|
||||
}
|
||||
log_debug("%s%.*s", prefix, (int)EVBUFFER_LENGTH(evb),
|
||||
(char *)EVBUFFER_DATA(evb));
|
||||
evbuffer_free(evb);
|
||||
free(prefix);
|
||||
}
|
||||
|
||||
/* Get a time item. */
|
||||
int
|
||||
event_payload_get_time(struct event_payload *ep, const char *name,
|
||||
time_t *value)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_TIME)
|
||||
return (0);
|
||||
*value = epi->time;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get a client item. */
|
||||
struct client *
|
||||
event_payload_get_client(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_CLIENT)
|
||||
return (NULL);
|
||||
return (epi->client);
|
||||
}
|
||||
|
||||
/* Get a session item. */
|
||||
struct session *
|
||||
event_payload_get_session(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_SESSION)
|
||||
return (NULL);
|
||||
return (epi->session);
|
||||
}
|
||||
|
||||
/* Get a window item. */
|
||||
struct window *
|
||||
event_payload_get_window(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_WINDOW)
|
||||
return (NULL);
|
||||
return (epi->window);
|
||||
}
|
||||
|
||||
/* Get a pane item. */
|
||||
struct window_pane *
|
||||
event_payload_get_pane(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_PANE)
|
||||
return (NULL);
|
||||
return (window_pane_find_by_id(epi->pane));
|
||||
}
|
||||
|
||||
/* Get a winlink item. */
|
||||
struct winlink *
|
||||
event_payload_get_winlink(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_WINLINK)
|
||||
return (NULL);
|
||||
s = session_find_by_id(epi->winlink.session);
|
||||
if (s == NULL)
|
||||
return (NULL);
|
||||
wl = winlink_find_by_index(&s->windows, epi->winlink.idx);
|
||||
if (wl == NULL || wl->window->id != epi->winlink.window)
|
||||
return (NULL);
|
||||
return (wl);
|
||||
}
|
||||
|
||||
/* Get a pointer item. */
|
||||
void *
|
||||
event_payload_get_pointer(struct event_payload *ep, const char *name)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
|
||||
epi = event_payload_find(ep, name);
|
||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_POINTER)
|
||||
return (NULL);
|
||||
return (epi->pointer.ptr);
|
||||
}
|
||||
49
events.c
49
events.c
@@ -26,9 +26,6 @@
|
||||
/* Event type metadata. */
|
||||
struct events_type {
|
||||
char *name;
|
||||
events_add_formats_cb add_formats_cb;
|
||||
events_find_state_cb find_state_cb;
|
||||
events_get_client_cb get_client_cb;
|
||||
|
||||
RB_ENTRY(events_type) entry;
|
||||
};
|
||||
@@ -96,23 +93,15 @@ events_free_dead(void)
|
||||
|
||||
/* Add an event type. */
|
||||
int
|
||||
events_add_event(const char *name, events_add_formats_cb add_formats_cb,
|
||||
events_find_state_cb find_state_cb, events_get_client_cb get_client_cb)
|
||||
events_add_event(const char *name)
|
||||
{
|
||||
struct events_type *et;
|
||||
|
||||
if ((et = events_find_type(name)) != NULL) {
|
||||
et->add_formats_cb = add_formats_cb;
|
||||
et->find_state_cb = find_state_cb;
|
||||
et->get_client_cb = get_client_cb;
|
||||
if ((et = events_find_type(name)) != NULL)
|
||||
return (0);
|
||||
}
|
||||
|
||||
et = xcalloc(1, sizeof *et);
|
||||
et->name = xstrdup(name);
|
||||
et->add_formats_cb = add_formats_cb;
|
||||
et->find_state_cb = find_state_cb;
|
||||
et->get_client_cb = get_client_cb;
|
||||
RB_INSERT(events_types, &events_types, et);
|
||||
return (0);
|
||||
}
|
||||
@@ -147,45 +136,21 @@ events_remove_sink(struct events_sink *es)
|
||||
|
||||
/* Fire an event. */
|
||||
void
|
||||
events_fire(const char *name, void *data)
|
||||
events_fire(const char *name, struct event_payload *ep)
|
||||
{
|
||||
struct events_type *et = events_find_type(name);
|
||||
struct events_sink *es;
|
||||
u_int generation = events_generation;
|
||||
|
||||
event_payload_log(ep, "%s: %s: ", __func__, name);
|
||||
|
||||
events_dispatching++;
|
||||
TAILQ_FOREACH(es, &events_sinks, entry) {
|
||||
if (es->dead || es->generation > generation)
|
||||
continue;
|
||||
if (strcmp(es->name, name) == 0)
|
||||
es->cb(name, data, et, es->data);
|
||||
es->cb(name, ep, es->data);
|
||||
}
|
||||
if (--events_dispatching == 0)
|
||||
events_free_dead();
|
||||
}
|
||||
|
||||
/* Add event formats. */
|
||||
void
|
||||
events_add_formats(struct events_type *et, void *data, struct format_tree *ft)
|
||||
{
|
||||
if (et != NULL && et->add_formats_cb != NULL)
|
||||
et->add_formats_cb(data, ft);
|
||||
}
|
||||
|
||||
/* Find event state. */
|
||||
int
|
||||
events_find_state(struct events_type *et, void *data, struct cmd_find_state *fs)
|
||||
{
|
||||
if (et == NULL || et->find_state_cb == NULL)
|
||||
return (0);
|
||||
return (et->find_state_cb(data, fs));
|
||||
}
|
||||
|
||||
/* Get event client. */
|
||||
struct client *
|
||||
events_get_client(struct events_type *et, void *data)
|
||||
{
|
||||
if (et == NULL || et->get_client_cb == NULL)
|
||||
return (NULL);
|
||||
return (et->get_client_cb(data));
|
||||
event_payload_free(ep);
|
||||
}
|
||||
|
||||
354
hooks.c
354
hooks.c
@@ -37,10 +37,14 @@ struct hook_monitor {
|
||||
char *format;
|
||||
};
|
||||
|
||||
/* Hook monitor event data passed through events_fire. */
|
||||
struct hook_monitor_event {
|
||||
struct hook_monitor *hm;
|
||||
struct monitor_change *change;
|
||||
/* Hook command data built from an event payload. */
|
||||
struct hooks_data {
|
||||
const char *name;
|
||||
struct cmd_find_state fs;
|
||||
struct format_tree *formats;
|
||||
struct options *oo;
|
||||
struct client *client;
|
||||
int expand;
|
||||
};
|
||||
|
||||
/* Hook event sink registered for a notify event name. */
|
||||
@@ -49,12 +53,12 @@ struct hooks_event {
|
||||
struct events_sink *sink;
|
||||
TAILQ_ENTRY(hooks_event) entry;
|
||||
};
|
||||
static TAILQ_HEAD(, hooks_event) hooks_events =
|
||||
TAILQ_HEAD_INITIALIZER(hooks_events);
|
||||
TAILQ_HEAD(hooks_events, hooks_event);
|
||||
static struct hooks_events hooks_events = TAILQ_HEAD_INITIALIZER(hooks_events);
|
||||
|
||||
/* Insert one hook command list. */
|
||||
static struct cmdq_item *
|
||||
hooks_insert_one(struct cmdq_item *item, struct notify_entry *ne,
|
||||
hooks_insert_one(struct cmdq_item *item, struct hooks_data *hd,
|
||||
struct cmd_list *cmdlist, struct cmdq_state *state)
|
||||
{
|
||||
struct cmdq_item *new_item;
|
||||
@@ -64,7 +68,7 @@ hooks_insert_one(struct cmdq_item *item, struct notify_entry *ne,
|
||||
return (item);
|
||||
if (log_get_level() != 0) {
|
||||
s = cmd_list_print(cmdlist, 0);
|
||||
log_debug("%s: hook %s is: %s", __func__, ne->name, s);
|
||||
log_debug("%s: hook %s is: %s", __func__, hd->name, s);
|
||||
free(s);
|
||||
}
|
||||
new_item = cmdq_get_command(cmdlist, state);
|
||||
@@ -75,19 +79,19 @@ hooks_insert_one(struct cmdq_item *item, struct notify_entry *ne,
|
||||
|
||||
/* Parse a hook command. */
|
||||
static struct cmd_parse_result *
|
||||
hooks_parse(struct notify_entry *ne, struct cmd_find_state *fs,
|
||||
hooks_parse(struct hooks_data *hd, struct cmd_find_state *fs,
|
||||
const char *value)
|
||||
{
|
||||
struct cmd_parse_result *pr;
|
||||
struct format_tree *ft;
|
||||
char *expanded;
|
||||
|
||||
if (!ne->expand)
|
||||
if (!hd->expand)
|
||||
return (cmd_parse_from_string(value, NULL));
|
||||
|
||||
ft = format_create_defaults(NULL, ne->client, fs->s, fs->wl, fs->wp);
|
||||
if (ne->formats != NULL)
|
||||
format_merge(ft, ne->formats);
|
||||
ft = format_create_defaults(NULL, hd->client, fs->s, fs->wl, fs->wp);
|
||||
if (hd->formats != NULL)
|
||||
format_merge(ft, hd->formats);
|
||||
expanded = format_expand(ft, value);
|
||||
format_free(ft);
|
||||
|
||||
@@ -98,7 +102,7 @@ hooks_parse(struct notify_entry *ne, struct cmd_find_state *fs,
|
||||
|
||||
/* Insert commands for a hook. */
|
||||
static void
|
||||
hooks_insert(struct cmdq_item *item, struct notify_entry *ne)
|
||||
hooks_insert(struct cmdq_item *item, struct hooks_data *hd)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct options *oo;
|
||||
@@ -109,72 +113,72 @@ hooks_insert(struct cmdq_item *item, struct notify_entry *ne)
|
||||
const char *value;
|
||||
struct cmd_parse_result *pr;
|
||||
|
||||
log_debug("%s: inserting hook %s", __func__, ne->name);
|
||||
log_debug("%s: inserting hook %s", __func__, hd->name);
|
||||
|
||||
cmd_find_clear_state(&fs, 0);
|
||||
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
|
||||
if (cmd_find_empty_state(&hd->fs) || !cmd_find_valid_state(&hd->fs))
|
||||
cmd_find_from_nothing(&fs, 0);
|
||||
else
|
||||
cmd_find_copy_state(&fs, &ne->fs);
|
||||
cmd_find_copy_state(&fs, &hd->fs);
|
||||
|
||||
if (ne->oo != NULL) {
|
||||
oo = ne->oo;
|
||||
o = options_get_only(oo, ne->name);
|
||||
if (hd->oo != NULL) {
|
||||
oo = hd->oo;
|
||||
o = options_get_only(oo, hd->name);
|
||||
} else {
|
||||
if (fs.s == NULL)
|
||||
oo = global_s_options;
|
||||
else
|
||||
oo = fs.s->options;
|
||||
o = options_get(oo, ne->name);
|
||||
o = options_get(oo, hd->name);
|
||||
if (o == NULL && fs.wp != NULL) {
|
||||
oo = fs.wp->options;
|
||||
o = options_get(oo, ne->name);
|
||||
o = options_get(oo, hd->name);
|
||||
}
|
||||
if (o == NULL && fs.wl != NULL) {
|
||||
oo = fs.wl->window->options;
|
||||
o = options_get(oo, ne->name);
|
||||
o = options_get(oo, hd->name);
|
||||
}
|
||||
}
|
||||
if (o == NULL) {
|
||||
log_debug("%s: hook %s not found", __func__, ne->name);
|
||||
log_debug("%s: hook %s not found", __func__, hd->name);
|
||||
return;
|
||||
}
|
||||
|
||||
state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS);
|
||||
cmdq_add_formats(state, ne->formats);
|
||||
cmdq_add_formats(state, hd->formats);
|
||||
|
||||
if (*ne->name == '@') {
|
||||
value = options_get_string(oo, ne->name);
|
||||
pr = hooks_parse(ne, &fs, value);
|
||||
if (*hd->name == '@') {
|
||||
value = options_get_string(oo, hd->name);
|
||||
pr = hooks_parse(hd, &fs, value);
|
||||
switch (pr->status) {
|
||||
case CMD_PARSE_ERROR:
|
||||
log_debug("%s: can't parse hook %s: %s", __func__,
|
||||
ne->name, pr->error);
|
||||
hd->name, pr->error);
|
||||
free(pr->error);
|
||||
break;
|
||||
case CMD_PARSE_SUCCESS:
|
||||
hooks_insert_one(item, ne, pr->cmdlist, state);
|
||||
hooks_insert_one(item, hd, pr->cmdlist, state);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
a = options_array_first(o);
|
||||
while (a != NULL) {
|
||||
if (ne->expand) {
|
||||
if (hd->expand) {
|
||||
value = options_array_item_value(a)->string;
|
||||
pr = hooks_parse(ne, &fs, value);
|
||||
pr = hooks_parse(hd, &fs, value);
|
||||
switch (pr->status) {
|
||||
case CMD_PARSE_ERROR:
|
||||
if (pr->error != NULL)
|
||||
cmdq_error(item, "%s", pr->error);
|
||||
break;
|
||||
case CMD_PARSE_SUCCESS:
|
||||
item = hooks_insert_one(item, ne,
|
||||
item = hooks_insert_one(item, hd,
|
||||
pr->cmdlist, state);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cmdlist = options_array_item_value(a)->cmdlist;
|
||||
item = hooks_insert_one(item, ne, cmdlist,
|
||||
item = hooks_insert_one(item, hd, cmdlist,
|
||||
state);
|
||||
}
|
||||
a = options_array_next(a);
|
||||
@@ -184,46 +188,155 @@ hooks_insert(struct cmdq_item *item, struct notify_entry *ne)
|
||||
cmdq_free_state(state);
|
||||
}
|
||||
|
||||
/* Add payload formats for a hook. */
|
||||
static void
|
||||
hooks_add_formats(struct format_tree *ft, const char *name,
|
||||
struct event_payload *ep)
|
||||
{
|
||||
struct event_payload_item *epi;
|
||||
struct client *c;
|
||||
struct session *s;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
char *fname, *value;
|
||||
const char *key;
|
||||
const char *svalue;
|
||||
|
||||
epi = event_payload_first(ep);
|
||||
while (epi != NULL) {
|
||||
key = event_payload_item_name(epi);
|
||||
if (*key != '_') {
|
||||
value = event_payload_item_print(epi);
|
||||
xasprintf(&fname, "hook_%s", key);
|
||||
format_add(ft, fname, "%s", value);
|
||||
free(fname);
|
||||
free(value);
|
||||
}
|
||||
epi = event_payload_next(epi);
|
||||
}
|
||||
|
||||
format_add(ft, "hook", "%s", name);
|
||||
|
||||
c = event_payload_get_client(ep, "client");
|
||||
if (c != NULL)
|
||||
format_add(ft, "hook_client", "%s", c->name);
|
||||
s = event_payload_get_session(ep, "session");
|
||||
if (s != NULL) {
|
||||
format_add(ft, "hook_session", "$%u", s->id);
|
||||
format_add(ft, "hook_session_name", "%s", s->name);
|
||||
}
|
||||
w = event_payload_get_window(ep, "window");
|
||||
if (w != NULL) {
|
||||
format_add(ft, "hook_window", "@%u", w->id);
|
||||
format_add(ft, "hook_window_name", "%s", w->name);
|
||||
}
|
||||
wp = event_payload_get_pane(ep, "pane");
|
||||
if (wp != NULL)
|
||||
format_add(ft, "hook_pane", "%%%u", wp->id);
|
||||
else {
|
||||
value = event_payload_print(ep, "pane");
|
||||
if (value != NULL) {
|
||||
format_add(ft, "hook_pane", "%s", value);
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
svalue = event_payload_get_string(ep, "value");
|
||||
if (svalue != NULL)
|
||||
format_add(ft, "hook_value", "%s", svalue);
|
||||
svalue = event_payload_get_string(ep, "last");
|
||||
if (svalue != NULL)
|
||||
format_add(ft, "hook_last", "%s", svalue);
|
||||
}
|
||||
|
||||
/* Find the best target state for a hook payload. */
|
||||
static void
|
||||
hooks_find_state(struct event_payload *ep, struct cmd_find_state *fs)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
struct winlink *wl;
|
||||
struct window *w;
|
||||
struct session *s;
|
||||
struct client *c;
|
||||
struct hook_monitor *hm;
|
||||
|
||||
wp = event_payload_get_pane(ep, "pane");
|
||||
if (wp != NULL && cmd_find_from_pane(fs, wp, 0) == 0)
|
||||
return;
|
||||
|
||||
wl = event_payload_get_winlink(ep, "winlink");
|
||||
if (wl != NULL) {
|
||||
if (wp != NULL && wp->window == wl->window) {
|
||||
cmd_find_from_winlink_pane(fs, wl, wp, 0);
|
||||
return;
|
||||
}
|
||||
cmd_find_from_winlink(fs, wl, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
s = event_payload_get_session(ep, "session");
|
||||
w = event_payload_get_window(ep, "window");
|
||||
if (s != NULL && w != NULL &&
|
||||
cmd_find_from_session_window(fs, s, w, 0) == 0)
|
||||
return;
|
||||
|
||||
if (w != NULL && cmd_find_from_window(fs, w, 0) == 0)
|
||||
return;
|
||||
|
||||
if (s != NULL && session_alive(s)) {
|
||||
cmd_find_from_session(fs, s, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
c = event_payload_get_client(ep, "client");
|
||||
if (c != NULL && cmd_find_from_client(fs, c, 0) == 0)
|
||||
return;
|
||||
|
||||
hm = event_payload_get_pointer(ep, "_hook_monitor");
|
||||
if (hm != NULL && !cmd_find_empty_state(&hm->fs) &&
|
||||
cmd_find_valid_state(&hm->fs)) {
|
||||
cmd_find_copy_state(fs, &hm->fs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_find_from_nothing(fs, 0) != 0)
|
||||
cmd_find_clear_state(fs, 0);
|
||||
}
|
||||
|
||||
/* Insert commands for a hook event. */
|
||||
static void
|
||||
hooks_insert_event(struct cmdq_item *item, const char *name,
|
||||
struct events_type *type, void *data, struct options *oo, int expand)
|
||||
struct event_payload *ep, struct options *oo, int expand)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct notify_entry ne;
|
||||
struct hooks_data hd;
|
||||
struct format_tree *ft;
|
||||
struct client *c;
|
||||
|
||||
if (item != NULL && (cmdq_get_flags(item) & CMDQ_STATE_NOHOOKS))
|
||||
return;
|
||||
|
||||
cmd_find_clear_state(&fs, 0);
|
||||
if (!events_find_state(type, data, &fs) ||
|
||||
cmd_find_empty_state(&fs) || !cmd_find_valid_state(&fs))
|
||||
cmd_find_from_nothing(&fs, 0);
|
||||
|
||||
c = events_get_client(type, data);
|
||||
c = event_payload_get_client(ep, "client");
|
||||
ft = format_create(c, item, FORMAT_NONE, FORMAT_NOJOBS);
|
||||
events_add_formats(type, data, ft);
|
||||
hooks_add_formats(ft, name, ep);
|
||||
format_log_debug(ft, __func__);
|
||||
|
||||
memset(&ne, 0, sizeof ne);
|
||||
ne.name = name;
|
||||
cmd_find_copy_state(&ne.fs, &fs);
|
||||
ne.formats = ft;
|
||||
ne.oo = oo;
|
||||
ne.client = c;
|
||||
ne.expand = expand;
|
||||
memset(&hd, 0, sizeof hd);
|
||||
hd.name = name;
|
||||
hooks_find_state(ep, &hd.fs);
|
||||
hd.formats = ft;
|
||||
hd.oo = oo;
|
||||
hd.client = c;
|
||||
hd.expand = expand;
|
||||
|
||||
hooks_insert(item, &ne);
|
||||
hooks_insert(item, &hd);
|
||||
format_free(ft);
|
||||
}
|
||||
|
||||
/* Handle an event for hooks. */
|
||||
static void
|
||||
hooks_event_cb(const char *name, void *data, struct events_type *type,
|
||||
hooks_event_cb(const char *name, struct event_payload *ep,
|
||||
__unused void *sink_data)
|
||||
{
|
||||
hooks_insert_event(cmdq_running(NULL), name, type, data, NULL, 0);
|
||||
hooks_insert_event(cmdq_running(NULL), name, ep, NULL, 0);
|
||||
}
|
||||
|
||||
/* Add a hook event sink. */
|
||||
@@ -248,80 +361,18 @@ void
|
||||
hooks_run(struct cmdq_item *item, const char *name)
|
||||
{
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct notify_entry ne;
|
||||
struct hooks_data hd = { 0 };
|
||||
|
||||
memset(&ne, 0, sizeof ne);
|
||||
hd.name = name;
|
||||
cmd_find_copy_state(&hd.fs, target);
|
||||
hd.client = cmdq_get_client(item);
|
||||
|
||||
ne.name = name;
|
||||
cmd_find_copy_state(&ne.fs, target);
|
||||
hd.formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
|
||||
format_add(hd.formats, "hook", "%s", name);
|
||||
format_log_debug(hd.formats, __func__);
|
||||
|
||||
ne.client = cmdq_get_client(item);
|
||||
ne.session = target->s;
|
||||
ne.window = target->w;
|
||||
ne.pane = (target->wp != NULL ? (int)target->wp->id : -1);
|
||||
|
||||
ne.formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
|
||||
format_add(ne.formats, "hook", "%s", name);
|
||||
format_log_debug(ne.formats, __func__);
|
||||
|
||||
hooks_insert(item, &ne);
|
||||
format_free(ne.formats);
|
||||
}
|
||||
|
||||
/* Add formats for a hook monitor event. */
|
||||
static void
|
||||
hooks_monitor_event_add_formats(void *data, struct format_tree *ft)
|
||||
{
|
||||
struct hook_monitor_event *hme = data;
|
||||
struct monitor_change *change = hme->change;
|
||||
struct window *w;
|
||||
|
||||
format_add(ft, "hook", "%s", change->name);
|
||||
format_add(ft, "hook_value", "%s",
|
||||
change->value == NULL ? "" : change->value);
|
||||
format_add(ft, "hook_last", "%s",
|
||||
change->last == NULL ? "" : change->last);
|
||||
if (change->s != NULL) {
|
||||
format_add(ft, "hook_session", "$%u", change->s->id);
|
||||
format_add(ft, "hook_session_name", "%s", change->s->name);
|
||||
}
|
||||
if (change->wl != NULL) {
|
||||
w = change->wl->window;
|
||||
format_add(ft, "hook_window", "@%u", w->id);
|
||||
format_add(ft, "hook_window_name", "%s", w->name);
|
||||
format_add(ft, "hook_window_index", "%d", change->wl->idx);
|
||||
}
|
||||
if (change->wp != NULL)
|
||||
format_add(ft, "hook_pane", "%%%u", change->wp->id);
|
||||
}
|
||||
|
||||
/* Find state for a hook monitor event. */
|
||||
static int
|
||||
hooks_monitor_event_find_state(void *data, struct cmd_find_state *fs)
|
||||
{
|
||||
struct hook_monitor_event *hme = data;
|
||||
struct hook_monitor *hm = hme->hm;
|
||||
struct monitor_change *change = hme->change;
|
||||
|
||||
if (change->wp != NULL && change->wl != NULL)
|
||||
cmd_find_from_winlink_pane(fs, change->wl, change->wp, 0);
|
||||
else if (change->wl != NULL)
|
||||
cmd_find_from_winlink(fs, change->wl, 0);
|
||||
else if (change->s != NULL)
|
||||
cmd_find_from_session(fs, change->s, 0);
|
||||
else
|
||||
cmd_find_copy_state(fs, &hm->fs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get client for a hook monitor event. */
|
||||
static struct client *
|
||||
hooks_monitor_event_get_client(void *data)
|
||||
{
|
||||
struct hook_monitor_event *hme = data;
|
||||
struct monitor_change *change = hme->change;
|
||||
|
||||
return (change->c);
|
||||
hooks_insert(item, &hd);
|
||||
format_free(hd.formats);
|
||||
}
|
||||
|
||||
/* Free a hook monitor. */
|
||||
@@ -356,27 +407,55 @@ hooks_monitor_remove(struct options *oo, const char *name)
|
||||
|
||||
/* Handle a hook monitor event. */
|
||||
static void
|
||||
hooks_monitor_hook_cb(const char *name, void *data, struct events_type *type,
|
||||
hooks_monitor_hook_cb(const char *name, struct event_payload *ep,
|
||||
void *sink_data)
|
||||
{
|
||||
struct hook_monitor_event *hme = data;
|
||||
struct hook_monitor *hm = sink_data;
|
||||
struct hook_monitor *hm = sink_data;
|
||||
|
||||
if (hme->hm != hm)
|
||||
return;
|
||||
|
||||
hooks_insert_event(cmdq_running(NULL), name, type, data, hm->oo, 1);
|
||||
if (event_payload_get_pointer(ep, "_hook_monitor") == hm)
|
||||
hooks_insert_event(cmdq_running(NULL), name, ep, hm->oo, 1);
|
||||
}
|
||||
|
||||
/* Fire a hook monitor event. */
|
||||
static void
|
||||
hooks_monitor_cb(struct monitor_change *change, void *data)
|
||||
{
|
||||
struct hook_monitor_event hme;
|
||||
struct event_payload *ep;
|
||||
struct winlink *wl = change->wl;
|
||||
struct window_pane *wp = change->wp;
|
||||
|
||||
hme.hm = data;
|
||||
hme.change = change;
|
||||
events_fire(change->name, &hme);
|
||||
ep = event_payload_create();
|
||||
event_payload_set_pointer(ep, "_hook_monitor", data, NULL, NULL);
|
||||
|
||||
if (change->value != NULL)
|
||||
event_payload_set_string(ep, "value", "%s", change->value);
|
||||
else
|
||||
event_payload_set_string(ep, "value", "%s", "");
|
||||
if (change->last != NULL)
|
||||
event_payload_set_string(ep, "last", "%s", change->last);
|
||||
else
|
||||
event_payload_set_string(ep, "last", "%s", "");
|
||||
|
||||
if (change->c != NULL)
|
||||
event_payload_set_client(ep, "client", change->c);
|
||||
if (change->s != NULL)
|
||||
event_payload_set_session(ep, "session", change->s);
|
||||
if (wl != NULL) {
|
||||
if (change->s == NULL)
|
||||
event_payload_set_session(ep, "session",
|
||||
wl->session);
|
||||
event_payload_set_window(ep, "window", wl->window);
|
||||
event_payload_set_string(ep, "window_index", "%d",
|
||||
wl->idx);
|
||||
event_payload_set_winlink(ep, "winlink", wl);
|
||||
}
|
||||
if (wp != NULL) {
|
||||
event_payload_set_pane(ep, "pane", wp);
|
||||
if (wl == NULL)
|
||||
event_payload_set_window(ep, "window", wp->window);
|
||||
}
|
||||
|
||||
events_fire(change->name, ep);
|
||||
}
|
||||
|
||||
/* Add a hook monitor. */
|
||||
@@ -400,8 +479,7 @@ hooks_monitor_add(__unused struct cmdq_item *item, struct options *oo,
|
||||
hm->id = id;
|
||||
hm->format = xstrdup(format);
|
||||
hm->set = monitor_create_session(s, hooks_monitor_cb, hm);
|
||||
events_add_event(name, hooks_monitor_event_add_formats,
|
||||
hooks_monitor_event_find_state, hooks_monitor_event_get_client);
|
||||
events_add_event(name);
|
||||
hm->sink = events_add_sink(name, hooks_monitor_hook_cb, hm);
|
||||
options_set_monitor_data(o, hm);
|
||||
monitor_add(hm->set, name, type, id, format, 0);
|
||||
|
||||
183
notify.c
183
notify.c
@@ -23,127 +23,46 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* Add formats for a notify event. */
|
||||
static void
|
||||
notify_add_formats(void *data, struct format_tree *ft)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
|
||||
if (ne->formats != NULL)
|
||||
format_merge(ft, ne->formats);
|
||||
}
|
||||
|
||||
/* Find state for a notify event. */
|
||||
static int
|
||||
notify_find_state(void *data, struct cmd_find_state *fs)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
|
||||
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
|
||||
return (0);
|
||||
cmd_find_copy_state(fs, &ne->fs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get client for a notify event. */
|
||||
static struct client *
|
||||
notify_get_client(void *data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
|
||||
return (ne->client);
|
||||
}
|
||||
|
||||
/* Build a notify event type. */
|
||||
static void
|
||||
notify_build_event(const char *name)
|
||||
{
|
||||
events_add_event(name, notify_add_formats, notify_find_state,
|
||||
notify_get_client);
|
||||
hooks_add_event(name);
|
||||
}
|
||||
/* Queued notify event. */
|
||||
struct notify_event {
|
||||
char *name;
|
||||
struct event_payload *payload;
|
||||
};
|
||||
|
||||
/* Fire a queued notify event. */
|
||||
static enum cmd_retval
|
||||
notify_callback(__unused struct cmdq_item *item, void *data)
|
||||
{
|
||||
struct notify_entry *ne = data;
|
||||
struct notify_event *ne = data;
|
||||
|
||||
log_debug("%s: %s", __func__, ne->name);
|
||||
|
||||
notify_build_event(ne->name);
|
||||
events_fire(ne->name, ne);
|
||||
events_add_event(ne->name);
|
||||
hooks_add_event(ne->name);
|
||||
events_fire(ne->name, ne->payload);
|
||||
ne->payload = NULL;
|
||||
|
||||
if (ne->client != NULL)
|
||||
server_client_unref(ne->client);
|
||||
if (ne->session != NULL)
|
||||
session_remove_ref(ne->session, __func__);
|
||||
if (ne->window != NULL)
|
||||
window_remove_ref(ne->window, __func__);
|
||||
|
||||
if (ne->fs.s != NULL)
|
||||
session_remove_ref(ne->fs.s, __func__);
|
||||
|
||||
format_free(ne->formats);
|
||||
free((void *)ne->name);
|
||||
free((void *)ne->pbname);
|
||||
free(ne->name);
|
||||
free(ne);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* Queue a notify event. */
|
||||
static void
|
||||
notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
|
||||
struct session *s, struct window *w, struct window_pane *wp,
|
||||
const char *pbname)
|
||||
notify_add(const char *name, struct event_payload *ep)
|
||||
{
|
||||
struct notify_entry *ne;
|
||||
struct notify_event *ne;
|
||||
struct cmdq_item *item;
|
||||
|
||||
item = cmdq_running(NULL);
|
||||
if (item != NULL && (cmdq_get_flags(item) & CMDQ_STATE_NOHOOKS))
|
||||
if (item != NULL && (cmdq_get_flags(item) & CMDQ_STATE_NOHOOKS)) {
|
||||
event_payload_free(ep);
|
||||
return;
|
||||
}
|
||||
|
||||
ne = xcalloc(1, sizeof *ne);
|
||||
ne->name = xstrdup(name);
|
||||
|
||||
ne->client = c;
|
||||
ne->session = s;
|
||||
ne->window = w;
|
||||
ne->pane = (wp != NULL ? (int)wp->id : -1);
|
||||
ne->pbname = (pbname != NULL ? xstrdup(pbname) : NULL);
|
||||
|
||||
ne->formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
|
||||
format_add(ne->formats, "hook", "%s", name);
|
||||
if (c != NULL)
|
||||
format_add(ne->formats, "hook_client", "%s", c->name);
|
||||
if (s != NULL) {
|
||||
format_add(ne->formats, "hook_session", "$%u", s->id);
|
||||
format_add(ne->formats, "hook_session_name", "%s", s->name);
|
||||
}
|
||||
if (w != NULL) {
|
||||
format_add(ne->formats, "hook_window", "@%u", w->id);
|
||||
format_add(ne->formats, "hook_window_name", "%s", w->name);
|
||||
}
|
||||
if (wp != NULL) {
|
||||
format_add(ne->formats, "hook_pane", "%%%d", wp->id);
|
||||
format_add(ne->formats, "hook_window", "@%u", wp->window->id);
|
||||
format_add(ne->formats, "hook_window_name", "%s",
|
||||
wp->window->name);
|
||||
}
|
||||
format_log_debug(ne->formats, __func__);
|
||||
|
||||
if (c != NULL)
|
||||
c->references++;
|
||||
if (s != NULL)
|
||||
session_add_ref(s, __func__);
|
||||
if (w != NULL)
|
||||
window_add_ref(w, __func__);
|
||||
|
||||
cmd_find_copy_state(&ne->fs, fs);
|
||||
if (ne->fs.s != NULL) /* cmd_find_valid_state needs session */
|
||||
session_add_ref(ne->fs.s, __func__);
|
||||
ne->payload = ep;
|
||||
|
||||
cmdq_append(NULL, cmdq_get_callback(notify_callback, ne));
|
||||
}
|
||||
@@ -151,71 +70,79 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
|
||||
void
|
||||
notify_client(const char *name, struct client *c)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
cmd_find_from_client(&fs, c, 0);
|
||||
notify_add(name, &fs, c, NULL, NULL, NULL, NULL);
|
||||
ep = event_payload_create();
|
||||
event_payload_set_client(ep, "client", c);
|
||||
notify_add(name, ep);
|
||||
}
|
||||
|
||||
void
|
||||
notify_session(const char *name, struct session *s)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
if (session_alive(s))
|
||||
cmd_find_from_session(&fs, s, 0);
|
||||
else
|
||||
cmd_find_from_nothing(&fs, 0);
|
||||
notify_add(name, &fs, NULL, s, NULL, NULL, NULL);
|
||||
ep = event_payload_create();
|
||||
event_payload_set_session(ep, "session", s);
|
||||
notify_add(name, ep);
|
||||
}
|
||||
|
||||
void
|
||||
notify_winlink(const char *name, struct winlink *wl)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
cmd_find_from_winlink(&fs, wl, 0);
|
||||
notify_add(name, &fs, NULL, wl->session, wl->window, NULL, NULL);
|
||||
ep = event_payload_create();
|
||||
event_payload_set_session(ep, "session", wl->session);
|
||||
event_payload_set_window(ep, "window", wl->window);
|
||||
event_payload_set_string(ep, "window_index", "%d", wl->idx);
|
||||
/* XXX winlink is not refcounted; store session/window IDs and index. */
|
||||
event_payload_set_winlink(ep, "winlink", wl);
|
||||
notify_add(name, ep);
|
||||
}
|
||||
|
||||
void
|
||||
notify_session_window(const char *name, struct session *s, struct window *w)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
cmd_find_from_session_window(&fs, s, w, 0);
|
||||
notify_add(name, &fs, NULL, s, w, NULL, NULL);
|
||||
ep = event_payload_create();
|
||||
event_payload_set_session(ep, "session", s);
|
||||
event_payload_set_window(ep, "window", w);
|
||||
notify_add(name, ep);
|
||||
}
|
||||
|
||||
void
|
||||
notify_window(const char *name, struct window *w)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
cmd_find_from_window(&fs, w, 0);
|
||||
notify_add(name, &fs, NULL, NULL, w, NULL, NULL);
|
||||
ep = event_payload_create();
|
||||
event_payload_set_window(ep, "window", w);
|
||||
notify_add(name, ep);
|
||||
}
|
||||
|
||||
void
|
||||
notify_pane(const char *name, struct window_pane *wp)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
cmd_find_from_pane(&fs, wp, 0);
|
||||
notify_add(name, &fs, NULL, NULL, NULL, wp, NULL);
|
||||
ep = event_payload_create();
|
||||
/* XXX window_pane is not refcounted; store pane ID for now. */
|
||||
event_payload_set_pane(ep, "pane", wp);
|
||||
event_payload_set_window(ep, "window", wp->window);
|
||||
notify_add(name, ep);
|
||||
}
|
||||
|
||||
void
|
||||
notify_paste_buffer(const char *pbname, int deleted)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct event_payload *ep;
|
||||
|
||||
cmd_find_clear_state(&fs, 0);
|
||||
if (deleted) {
|
||||
notify_add("paste-buffer-deleted", &fs, NULL, NULL, NULL,
|
||||
NULL, pbname);
|
||||
} else {
|
||||
notify_add("paste-buffer-changed", &fs, NULL, NULL, NULL,
|
||||
NULL, pbname);
|
||||
}
|
||||
ep = event_payload_create();
|
||||
event_payload_set_string(ep, "paste_buffer", "%s", pbname);
|
||||
if (deleted)
|
||||
notify_add("paste-buffer-deleted", ep);
|
||||
else
|
||||
notify_add("paste-buffer-changed", ep);
|
||||
}
|
||||
|
||||
101
tmux.h
101
tmux.h
@@ -49,8 +49,9 @@ struct cmdq_state;
|
||||
struct cmds;
|
||||
struct control_state;
|
||||
struct environ;
|
||||
struct event_payload;
|
||||
struct event_payload_item;
|
||||
struct events_sink;
|
||||
struct events_type;
|
||||
struct format_job_tree;
|
||||
struct format_tree;
|
||||
struct hyperlinks_uri;
|
||||
@@ -2338,27 +2339,22 @@ struct monitor_change {
|
||||
};
|
||||
typedef void (*monitor_cb)(struct monitor_change *, void *);
|
||||
|
||||
/* Events. */
|
||||
typedef void (*events_cb)(const char *, void *, struct events_type *, void *);
|
||||
typedef void (*events_add_formats_cb)(void *, struct format_tree *);
|
||||
typedef int (*events_find_state_cb)(void *, struct cmd_find_state *);
|
||||
typedef struct client *(*events_get_client_cb)(void *);
|
||||
|
||||
/* Data passed by notify producers to event sinks. */
|
||||
struct notify_entry {
|
||||
const char *name;
|
||||
struct cmd_find_state fs;
|
||||
struct format_tree *formats;
|
||||
struct options *oo;
|
||||
|
||||
struct client *client;
|
||||
struct session *session;
|
||||
struct window *window;
|
||||
int pane;
|
||||
const char *pbname;
|
||||
int expand;
|
||||
/* Event payload type. */
|
||||
enum event_payload_type {
|
||||
EVENT_PAYLOAD_STRING,
|
||||
EVENT_PAYLOAD_TIME,
|
||||
EVENT_PAYLOAD_CLIENT,
|
||||
EVENT_PAYLOAD_SESSION,
|
||||
EVENT_PAYLOAD_WINDOW,
|
||||
EVENT_PAYLOAD_PANE,
|
||||
EVENT_PAYLOAD_WINLINK,
|
||||
EVENT_PAYLOAD_POINTER
|
||||
};
|
||||
|
||||
/* Event payload callbacks. */
|
||||
typedef void (*event_payload_free_cb)(void *);
|
||||
typedef void (*event_payload_print_cb)(void *, struct evbuffer *);
|
||||
|
||||
/* Key binding and key table. */
|
||||
struct key_binding {
|
||||
key_code key;
|
||||
@@ -2668,25 +2664,62 @@ char *format_grid_hyperlink(struct grid *, u_int, u_int,
|
||||
struct screen *);
|
||||
char *format_grid_line(struct grid *, u_int);
|
||||
|
||||
/* events-payload.c */
|
||||
struct event_payload *event_payload_create(void);
|
||||
void event_payload_free(struct event_payload *);
|
||||
void printflike(2, 3) event_payload_log(struct event_payload *, const char *,
|
||||
...);
|
||||
char *event_payload_item_print(struct event_payload_item *);
|
||||
void printflike(3, 4) event_payload_set_string(struct event_payload *,
|
||||
const char *, const char *, ...);
|
||||
void event_payload_set_time(struct event_payload *, const char *, time_t);
|
||||
void event_payload_set_client(struct event_payload *, const char *,
|
||||
struct client *);
|
||||
void event_payload_set_session(struct event_payload *, const char *,
|
||||
struct session *);
|
||||
void event_payload_set_window(struct event_payload *, const char *,
|
||||
struct window *);
|
||||
void event_payload_set_pane(struct event_payload *, const char *,
|
||||
struct window_pane *);
|
||||
void event_payload_set_winlink(struct event_payload *, const char *,
|
||||
struct winlink *);
|
||||
void event_payload_set_pointer(struct event_payload *, const char *,
|
||||
void *, event_payload_free_cb, event_payload_print_cb);
|
||||
const char *event_payload_get_string(struct event_payload *,
|
||||
const char *);
|
||||
char *event_payload_print(struct event_payload *, const char *);
|
||||
struct event_payload_item *event_payload_first(struct event_payload *);
|
||||
struct event_payload_item *event_payload_next(struct event_payload_item *);
|
||||
const char *event_payload_item_name(struct event_payload_item *);
|
||||
enum event_payload_type event_payload_item_type(struct event_payload_item *);
|
||||
int event_payload_get_time(struct event_payload *, const char *,
|
||||
time_t *);
|
||||
struct client *event_payload_get_client(struct event_payload *,
|
||||
const char *);
|
||||
struct session *event_payload_get_session(struct event_payload *,
|
||||
const char *);
|
||||
struct window *event_payload_get_window(struct event_payload *,
|
||||
const char *);
|
||||
struct window_pane *event_payload_get_pane(struct event_payload *,
|
||||
const char *);
|
||||
struct winlink *event_payload_get_winlink(struct event_payload *,
|
||||
const char *);
|
||||
void *event_payload_get_pointer(struct event_payload *,
|
||||
const char *);
|
||||
|
||||
/* events.c */
|
||||
int events_add_event(const char *, events_add_formats_cb,
|
||||
events_find_state_cb, events_get_client_cb);
|
||||
typedef void (*events_cb)(const char *, struct event_payload *, void *);
|
||||
int events_add_event(const char *);
|
||||
struct events_sink *events_add_sink(const char *, events_cb, void *);
|
||||
void events_remove_sink(struct events_sink *);
|
||||
void events_fire(const char *, void *);
|
||||
void events_add_formats(struct events_type *, void *,
|
||||
struct format_tree *);
|
||||
int events_find_state(struct events_type *, void *,
|
||||
struct cmd_find_state *);
|
||||
struct client *events_get_client(struct events_type *, void *);
|
||||
void events_fire(const char *, struct event_payload *);
|
||||
|
||||
/* format-draw.c */
|
||||
void format_draw(struct screen_write_ctx *,
|
||||
const struct grid_cell *, u_int, const char *,
|
||||
struct style_ranges *, int);
|
||||
u_int format_width(const char *);
|
||||
char *format_trim_left(const char *, u_int);
|
||||
char *format_trim_right(const char *, u_int);
|
||||
void format_draw(struct screen_write_ctx *, const struct grid_cell *,
|
||||
u_int, const char *, struct style_ranges *, int);
|
||||
u_int format_width(const char *);
|
||||
char *format_trim_left(const char *, u_int);
|
||||
char *format_trim_right(const char *, u_int);
|
||||
|
||||
/* hooks.c */
|
||||
void hooks_add_event(const char *);
|
||||
|
||||
Reference in New Issue
Block a user