Merge pull request #341 from TingPing/lastact
Add last activity keybinding from fedora
This commit is contained in:
commit
0213f21a46
|
@ -77,6 +77,24 @@ GSList *usermenu_list = 0;
|
||||||
GSList *urlhandler_list = 0;
|
GSList *urlhandler_list = 0;
|
||||||
GSList *tabmenu_list = 0;
|
GSList *tabmenu_list = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This array contains 5 double linked lists, one for each priority in the
|
||||||
|
* "interesting session" queue ("channel" stands for everything but
|
||||||
|
* SESS_DIALOG):
|
||||||
|
*
|
||||||
|
* [0] queries with hilight
|
||||||
|
* [1] queries
|
||||||
|
* [2] channels with hilight
|
||||||
|
* [3] channels with dialogue
|
||||||
|
* [4] channels with other data
|
||||||
|
*
|
||||||
|
* Each time activity happens the corresponding session is put at the
|
||||||
|
* beginning of one of the lists. The aim is to be able to switch to the
|
||||||
|
* session with the most important/recent activity.
|
||||||
|
*/
|
||||||
|
GList *sess_list_by_lastact[5] = {NULL, NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
|
|
||||||
static int in_hexchat_exit = FALSE;
|
static int in_hexchat_exit = FALSE;
|
||||||
int hexchat_is_quitting = FALSE;
|
int hexchat_is_quitting = FALSE;
|
||||||
/* command-line args */
|
/* command-line args */
|
||||||
|
@ -103,6 +121,79 @@ SSL_CTX *ctx = NULL;
|
||||||
pxProxyFactory *libproxy_factory;
|
pxProxyFactory *libproxy_factory;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the priority queue of the "interesting sessions"
|
||||||
|
* (sess_list_by_lastact).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
lastact_update(session *sess)
|
||||||
|
{
|
||||||
|
int oldidx = sess->lastact_idx;
|
||||||
|
int newidx = LACT_NONE;
|
||||||
|
int dia = (sess->type == SESS_DIALOG);
|
||||||
|
|
||||||
|
if (sess->nick_said)
|
||||||
|
newidx = dia? LACT_QUERY_HI: LACT_CHAN_HI;
|
||||||
|
else if (sess->msg_said)
|
||||||
|
newidx = dia? LACT_QUERY: LACT_CHAN;
|
||||||
|
else if (sess->new_data)
|
||||||
|
newidx = dia? LACT_QUERY: LACT_CHAN_DATA;
|
||||||
|
|
||||||
|
/* If already first at the right position, just return */
|
||||||
|
if (oldidx == newidx &&
|
||||||
|
(newidx == LACT_NONE || g_list_index(sess_list_by_lastact[newidx], sess) == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Remove from the old position */
|
||||||
|
if (oldidx != LACT_NONE)
|
||||||
|
sess_list_by_lastact[oldidx] = g_list_remove(sess_list_by_lastact[oldidx], sess);
|
||||||
|
|
||||||
|
/* Add at the new position */
|
||||||
|
sess->lastact_idx = newidx;
|
||||||
|
if (newidx != LACT_NONE)
|
||||||
|
sess_list_by_lastact[newidx] = g_list_prepend(sess_list_by_lastact[newidx], sess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the first session from the priority queue of sessions with recent
|
||||||
|
* activity. Return NULL if no such session can be found.
|
||||||
|
*
|
||||||
|
* If filter is specified, skip a session if filter(session) returns 0. This
|
||||||
|
* can be used for UI-specific needs, e.g. in fe-gtk we want to filter out
|
||||||
|
* detached sessions.
|
||||||
|
*/
|
||||||
|
session *
|
||||||
|
lastact_getfirst(int (*filter) (session *sess))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
session *sess = NULL;
|
||||||
|
GList *curitem;
|
||||||
|
|
||||||
|
/* 5 is the number of priority classes LACT_ */
|
||||||
|
for (i = 0; i < 5 && !sess; i++)
|
||||||
|
{
|
||||||
|
curitem = sess_list_by_lastact[i];
|
||||||
|
while (curitem && !sess)
|
||||||
|
{
|
||||||
|
sess = g_list_nth_data(curitem, 0);
|
||||||
|
if (!sess || (filter && !filter(sess)))
|
||||||
|
{
|
||||||
|
sess = NULL;
|
||||||
|
curitem = g_list_next(curitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sess)
|
||||||
|
{
|
||||||
|
sess_list_by_lastact[i] = g_list_remove(sess_list_by_lastact[i], sess);
|
||||||
|
sess->lastact_idx = LACT_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sess;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
is_session (session * sess)
|
is_session (session * sess)
|
||||||
{
|
{
|
||||||
|
@ -372,6 +463,8 @@ session_new (server *serv, char *from, int type, int focus)
|
||||||
sess->text_logging = SET_DEFAULT;
|
sess->text_logging = SET_DEFAULT;
|
||||||
sess->text_scrollback = SET_DEFAULT;
|
sess->text_scrollback = SET_DEFAULT;
|
||||||
|
|
||||||
|
sess->lastact_idx = LACT_NONE;
|
||||||
|
|
||||||
if (from != NULL)
|
if (from != NULL)
|
||||||
safe_strcpy (sess->channel, from, CHANLEN);
|
safe_strcpy (sess->channel, from, CHANLEN);
|
||||||
|
|
||||||
|
@ -489,6 +582,7 @@ session_free (session *killsess)
|
||||||
server *killserv = killsess->server;
|
server *killserv = killsess->server;
|
||||||
session *sess;
|
session *sess;
|
||||||
GSList *list;
|
GSList *list;
|
||||||
|
int oldidx;
|
||||||
|
|
||||||
plugin_emit_dummy_print (killsess, "Close Context");
|
plugin_emit_dummy_print (killsess, "Close Context");
|
||||||
|
|
||||||
|
@ -525,6 +619,10 @@ session_free (session *killsess)
|
||||||
if (killsess->type == SESS_CHANNEL)
|
if (killsess->type == SESS_CHANNEL)
|
||||||
userlist_free (killsess);
|
userlist_free (killsess);
|
||||||
|
|
||||||
|
oldidx = killsess->lastact_idx;
|
||||||
|
if (oldidx != LACT_NONE)
|
||||||
|
sess_list_by_lastact[oldidx] = g_list_remove(sess_list_by_lastact[oldidx], killsess);
|
||||||
|
|
||||||
exec_notify_kill (killsess);
|
exec_notify_kill (killsess);
|
||||||
|
|
||||||
log_close (killsess);
|
log_close (killsess);
|
||||||
|
|
|
@ -350,6 +350,15 @@ struct hexchatprefs
|
||||||
#define SET_ON 1
|
#define SET_ON 1
|
||||||
#define SET_DEFAULT 2 /* use global setting */
|
#define SET_DEFAULT 2 /* use global setting */
|
||||||
|
|
||||||
|
/* Priorities in the "interesting sessions" priority queue
|
||||||
|
* (see xchat.c:sess_list_by_lastact) */
|
||||||
|
#define LACT_NONE -1 /* no queues */
|
||||||
|
#define LACT_QUERY_HI 0 /* query with hilight */
|
||||||
|
#define LACT_QUERY 1 /* query with messages */
|
||||||
|
#define LACT_CHAN_HI 2 /* channel with hilight */
|
||||||
|
#define LACT_CHAN 3 /* channel with messages */
|
||||||
|
#define LACT_CHAN_DATA 4 /* channel with other data */
|
||||||
|
|
||||||
/* Moved from fe-gtk for use in outbound.c as well -- */
|
/* Moved from fe-gtk for use in outbound.c as well -- */
|
||||||
typedef enum gtk_xtext_search_flags_e {
|
typedef enum gtk_xtext_search_flags_e {
|
||||||
case_match = 1,
|
case_match = 1,
|
||||||
|
@ -408,6 +417,9 @@ typedef struct session
|
||||||
|
|
||||||
int type; /* SESS_* */
|
int type; /* SESS_* */
|
||||||
|
|
||||||
|
int lastact_idx; /* the sess_list_by_lastact[] index of the list we're in.
|
||||||
|
* For valid values, see defines of LACT_*. */
|
||||||
|
|
||||||
int new_data:1; /* new data avail? (purple tab) */
|
int new_data:1; /* new data avail? (purple tab) */
|
||||||
int nick_said:1; /* your nick mentioned? (blue tab) */
|
int nick_said:1; /* your nick mentioned? (blue tab) */
|
||||||
int msg_said:1; /* new msg available? (red tab) */
|
int msg_said:1; /* new msg available? (red tab) */
|
||||||
|
|
|
@ -25,10 +25,13 @@ extern GSList *ignore_list;
|
||||||
extern GSList *usermenu_list;
|
extern GSList *usermenu_list;
|
||||||
extern GSList *urlhandler_list;
|
extern GSList *urlhandler_list;
|
||||||
extern GSList *tabmenu_list;
|
extern GSList *tabmenu_list;
|
||||||
|
extern GList *sess_list_by_lastact[];
|
||||||
|
|
||||||
session * find_channel (server *serv, char *chan);
|
session * find_channel (server *serv, char *chan);
|
||||||
session * find_dialog (server *serv, char *nick);
|
session * find_dialog (server *serv, char *nick);
|
||||||
session * new_ircwindow (server *serv, char *name, int type, int focus);
|
session * new_ircwindow (server *serv, char *name, int type, int focus);
|
||||||
|
void lastact_update (session * sess);
|
||||||
|
session * lastact_getfirst (int (*filter) (session *sess));
|
||||||
int is_session (session * sess);
|
int is_session (session * sess);
|
||||||
void session_free (session *killsess);
|
void session_free (session *killsess);
|
||||||
void lag_check (void);
|
void lag_check (void);
|
||||||
|
|
|
@ -301,7 +301,10 @@ is_hilight (char *from, char *text, session *sess, server *serv)
|
||||||
{
|
{
|
||||||
g_free (text);
|
g_free (text);
|
||||||
if (sess != current_tab)
|
if (sess != current_tab)
|
||||||
|
{
|
||||||
sess->nick_said = TRUE;
|
sess->nick_said = TRUE;
|
||||||
|
lastact_update (sess);
|
||||||
|
}
|
||||||
fe_set_hilight (sess);
|
fe_set_hilight (sess);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -364,6 +367,7 @@ inbound_action (session *sess, char *chan, char *from, char *ip, char *text, int
|
||||||
sess->msg_said = TRUE;
|
sess->msg_said = TRUE;
|
||||||
sess->new_data = FALSE;
|
sess->new_data = FALSE;
|
||||||
}
|
}
|
||||||
|
lastact_update (sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
user = userlist_find (sess, from);
|
user = userlist_find (sess, from);
|
||||||
|
@ -421,6 +425,7 @@ inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text
|
||||||
{
|
{
|
||||||
sess->msg_said = TRUE;
|
sess->msg_said = TRUE;
|
||||||
sess->new_data = FALSE;
|
sess->new_data = FALSE;
|
||||||
|
lastact_update (sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
user = userlist_find (sess, from);
|
user = userlist_find (sess, from);
|
||||||
|
|
|
@ -674,6 +674,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp)
|
||||||
sess->gui->is_tab && !sess->nick_said && stamp == 0)
|
sess->gui->is_tab && !sess->nick_said && stamp == 0)
|
||||||
{
|
{
|
||||||
sess->new_data = TRUE;
|
sess->new_data = TRUE;
|
||||||
|
lastact_update (sess);
|
||||||
if (sess->msg_said)
|
if (sess->msg_said)
|
||||||
fe_set_tab_color (sess, 2);
|
fe_set_tab_color (sess, 2);
|
||||||
else
|
else
|
||||||
|
|
|
@ -159,9 +159,9 @@ static struct key_binding *keys_root = NULL;
|
||||||
static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
|
static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = {
|
||||||
|
|
||||||
{key_action_handle_command, "Run Command",
|
{key_action_handle_command, "Run Command",
|
||||||
N_("The \002Run Command\002 action runs the data in Data 1 as if it has been typed into the entry box where you pressed the key sequence. Thus it can contain text (which will be sent to the channel/person), commands or user commands. When run all \002\\n\002 characters in Data 1 are used to deliminate seperate commands so it is possible to run more than one command. If you want a \002\\\002 in the actual text run then enter \002\\\\\002")},
|
N_("The \002Run Command\002 action runs the data in Data 1 as if it had been typed into the entry box where you pressed the key sequence. Thus it can contain text (which will be sent to the channel/person), commands or user commands. When run all \002\\n\002 characters in Data 1 are used to deliminate seperate commands so it is possible to run more than one command. If you want a \002\\\002 in the actual text run then enter \002\\\\\002")},
|
||||||
{key_action_page_switch, "Change Page",
|
{key_action_page_switch, "Change Page",
|
||||||
N_("The \002Change Page\002 command switches between pages in the notebook. Set Data 1 to the page you want to switch to. If Data 2 is set to anything then the switch will be relative to the current position")},
|
N_("The \002Change Page\002 command switches between pages in the notebook. Set Data 1 to the page you want to switch to. If Data 2 is set to anything then the switch will be relative to the current position. Set Data 1 to auto to switch to the page with the most recent and important activity (queries first, then channels with hilight, channels with dialogue, channels with other data)")},
|
||||||
{key_action_insert, "Insert in Buffer",
|
{key_action_insert, "Insert in Buffer",
|
||||||
N_("The \002Insert in Buffer\002 command will insert the contents of Data 1 into the entry where the key sequence was pressed at the current cursor position")},
|
N_("The \002Insert in Buffer\002 command will insert the contents of Data 1 into the entry where the key sequence was pressed at the current cursor position")},
|
||||||
{key_action_scroll_page, "Scroll Page",
|
{key_action_scroll_page, "Scroll Page",
|
||||||
|
@ -405,6 +405,7 @@ key_load_defaults ()
|
||||||
"A\n3\nChange Page\nD1:3\nD2!\n\n"\
|
"A\n3\nChange Page\nD1:3\nD2!\n\n"\
|
||||||
"A\n2\nChange Page\nD1:2\nD2!\n\n"\
|
"A\n2\nChange Page\nD1:2\nD2!\n\n"\
|
||||||
"A\n1\nChange Page\nD1:1\nD2!\n\n"\
|
"A\n1\nChange Page\nD1:1\nD2!\n\n"\
|
||||||
|
"A\ngrave\nChange Page\nD1:auto\nD2!\n\n"\
|
||||||
"C\no\nInsert in Buffer\nD1:\nD2!\n\n"\
|
"C\no\nInsert in Buffer\nD1:\nD2!\n\n"\
|
||||||
"C\nb\nInsert in Buffer\nD1:\nD2!\n\n"\
|
"C\nb\nInsert in Buffer\nD1:\nD2!\n\n"\
|
||||||
"C\nk\nInsert in Buffer\nD1:\nD2!\n\n"\
|
"C\nk\nInsert in Buffer\nD1:\nD2!\n\n"\
|
||||||
|
@ -1199,10 +1200,25 @@ key_action_handle_command (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the given session is inside the main window. This predicate
|
||||||
|
* is passed to lastact_getfirst() as a way to filter out detached sessions.
|
||||||
|
* XXX: Consider moving this in a different file?
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
session_check_is_tab(session *sess)
|
||||||
|
{
|
||||||
|
if (!sess || !sess->gui)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return (sess->gui->is_tab);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
key_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
key_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
||||||
char *d2, struct session *sess)
|
char *d2, struct session *sess)
|
||||||
{
|
{
|
||||||
|
session *newsess;
|
||||||
int len, i, num;
|
int len, i, num;
|
||||||
|
|
||||||
if (!d1)
|
if (!d1)
|
||||||
|
@ -1212,6 +1228,30 @@ key_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1,
|
||||||
if (!len)
|
if (!len)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (strcasecmp(d1, "auto") == 0)
|
||||||
|
{
|
||||||
|
/* Auto switch makes no sense in detached sessions */
|
||||||
|
if (!sess->gui->is_tab)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Obtain a session with recent activity */
|
||||||
|
newsess = lastact_getfirst(session_check_is_tab);
|
||||||
|
|
||||||
|
if (newsess)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Only sessions in the current window should be considered (i.e.
|
||||||
|
* we don't want to move the focus on a different window). This
|
||||||
|
* call could, in theory, do this, but we checked before that
|
||||||
|
* newsess->gui->is_tab and sess->gui->is_tab.
|
||||||
|
*/
|
||||||
|
mg_bring_tofront_sess(newsess);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (d1[i] < '0' || d1[i] > '9')
|
if (d1[i] < '0' || d1[i] > '9')
|
||||||
|
|
|
@ -307,6 +307,7 @@ fe_set_tab_color (struct session *sess, int col)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
lastact_update (sess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,6 +605,7 @@ mg_focus (session *sess)
|
||||||
sess->nick_said = FALSE;
|
sess->nick_said = FALSE;
|
||||||
sess->msg_said = FALSE;
|
sess->msg_said = FALSE;
|
||||||
sess->new_data = FALSE;
|
sess->new_data = FALSE;
|
||||||
|
lastact_update (sess);
|
||||||
/* when called via mg_changui_new, is_tab might be true, but
|
/* when called via mg_changui_new, is_tab might be true, but
|
||||||
sess->res->tab is still NULL. */
|
sess->res->tab is still NULL. */
|
||||||
if (sess->res->tab)
|
if (sess->res->tab)
|
||||||
|
|
Loading…
Reference in New Issue