focus new windows and focus windows on workspace change
[dana/openbox.git] / plugins / focus.c
1 #include "../kernel/dispatch.h"
2 #include "../kernel/screen.h"
3 #include "../kernel/client.h"
4 #include "../kernel/stacking.h"
5
6 static GSList **focus_order = NULL;
7
8 static void events(ObEvent *e, void *foo)
9 {
10     guint i;
11     guint new, old;
12     GSList *it;
13
14     switch (e->type) {
15     case Event_Client_Mapped:
16         /* focus new normal windows */
17         if (client_normal(e->data.c.client))
18             client_focus(e->data.c.client);
19         break;
20
21     case Event_Ob_NumDesktops:
22         new = e->data.o.num[0];
23         old = e->data.o.num[1];
24         /* free our lists for the desktops which have disappeared */
25         for (i = new; i < old; ++i)
26             g_slist_free(focus_order[i]);
27         /* realloc the array */
28         focus_order = g_renew(GSList*, focus_order, new);
29         /* set the new lists to be empty */
30         for (i = old; i < new; ++i)
31             focus_order[i] = NULL;
32         break;
33
34     case Event_Client_Desktop:
35         old = e->data.c.num[1];
36         if (old != DESKTOP_ALL)
37             focus_order[old] = g_slist_remove(focus_order[old],
38                                               e->data.c.client);
39         else
40             for (i = 0; i < screen_num_desktops; ++i)
41                 focus_order[i] = g_slist_remove(focus_order[i],
42                                                 e->data.c.client);
43         break;
44
45     case Event_Ob_Desktop:
46         for (it = focus_order[e->data.o.num[0]]; it != NULL; it = it->next)
47             if (client_focus(it->data))
48                 break;
49         break;
50
51     case Event_Client_Focus:
52         /* move to the top of the list */
53         focus_order[e->data.c.num[1]] =
54         g_slist_remove(focus_order[e->data.c.num[1]], e->data.c.client);
55         focus_order[e->data.c.num[1]] =
56         g_slist_prepend(focus_order[e->data.c.num[1]], e->data.c.client);
57         break;
58
59     default:
60         g_assert_not_reached();
61     }
62 }
63
64 void plugin_startup()
65 {
66     guint i;
67
68     dispatch_register(Event_Client_Mapped | Event_Ob_Desktop |
69                       Event_Ob_NumDesktops | Event_Client_Focus |
70                       Event_Client_Desktop, (EventHandler)events, NULL);
71
72     focus_order = g_new(GSList*, screen_num_desktops);
73     for (i = 0; i < screen_num_desktops; ++i)
74         focus_order[i] = NULL;
75 }
76
77 void plugin_shutdown()
78 {
79     guint i;
80
81     dispatch_register(0, (EventHandler)events, NULL);
82
83     for (i = 0; i < screen_num_desktops; ++i)
84         g_slist_free(focus_order[i]);
85     g_free(focus_order);
86 }