Fix segfault after viewing same tag twice and doing a tag_prev_selected.
[awesome.git] / focus.c
blob8c6a405850aa1cd88a5f9cae9dc62e1b9ce22237
1 /*
2 * focus.c - focus management
4 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "tag.h"
23 #include "focus.h"
24 #include "client.h"
26 extern AwesomeConf globalconf;
28 static client_node_t *
29 focus_get_node_by_client(Client *c)
31 client_node_t *node;
33 for(node = globalconf.focus; node; node = node->next)
34 if(node->client == c)
35 return node;
37 return NULL;
40 void
41 focus_add_client(Client *c)
43 client_node_t *node;
45 /* if we don't find this node, create a new one */
46 if(!(node = focus_get_node_by_client(c)))
48 node = p_new(client_node_t, 1);
49 node->client = c;
51 else /* if we've got a node, detach it */
52 client_node_list_detach(&globalconf.focus, node);
54 client_node_list_push(&globalconf.focus, node);
57 void
58 focus_delete_client(Client *c)
60 client_node_t *node = focus_get_node_by_client(c);
62 if(node)
64 client_node_list_detach(&globalconf.focus, node);
65 p_delete(&node);
69 static Client *
70 focus_get_latest_client_for_tags(Tag **t, int nindex)
72 client_node_t *node;
73 Tag **tags;
74 int i = 0;
76 for(node = globalconf.focus; node; node = node->next)
77 if(node->client && !node->client->skip && node->client != globalconf.scratch.client)
78 for(tags = t; *tags; tags++)
79 if(is_client_tagged(node->client, *tags))
81 if(i == nindex)
82 return node->client;
83 else
84 i--;
87 return NULL;
90 Client *
91 focus_get_current_client(int screen)
93 Tag **curtags = tags_get_current(screen);
94 Client *sel = focus_get_latest_client_for_tags(curtags, 0);
95 p_delete(&curtags);
97 return sel;
100 /** Jump in focus history stack
101 * \param screen Screen ID
102 * \param arg Integer argument
103 * \ingroup ui_callback
105 void
106 uicb_focus_history(int screen, char *arg)
108 int i;
109 Tag **curtags;
110 Client *c;
112 if(arg)
114 i = atoi(arg);
116 if(i < 0)
118 curtags = tags_get_current(screen);
119 c = focus_get_latest_client_for_tags(curtags, i);
120 p_delete(&curtags);
121 if(c)
122 client_focus(c, screen, True);
127 void
128 uicb_focus_client_byname(int screen, char *arg)
130 Client *c;
131 Tag **curtags, **tag;
133 if(arg)
135 curtags = tags_get_current(screen);
136 if((c = client_get_byname(globalconf.clients, arg)))
137 for(tag = curtags; *tag; tag++)
138 if(is_client_tagged(c, *tag))
139 client_focus(c, screen, True);
140 p_delete(&curtags);
144 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80