]> Dogcows Code - chaz/openbox/blob - plugins/focus.c
add sloppy focus
[chaz/openbox] / plugins / focus.c
1 #include "../kernel/dispatch.h"
2 #include "../kernel/screen.h"
3 #include "../kernel/client.h"
4 #include "../kernel/focus.h"
5 #include "../kernel/stacking.h"
6 #include "../kernel/openbox.h"
7
8 static GSList **focus_order = NULL;
9
10 static void focus_fallback(guint desk, gboolean warp)
11 {
12 GSList *it;
13
14 for (it = focus_order[desk]; it != NULL; it = it->next)
15 if (client_focus(it->data)) {
16 if (warp) { /* XXX make this configurable */
17 Client *c = it->data;
18 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
19 c->area.width / 2, c->area.height / 2);
20 }
21 break;
22 }
23 }
24
25 static void events(ObEvent *e, void *foo)
26 {
27 guint i;
28 guint new, old;
29
30 switch (e->type) {
31 case Event_Client_Mapped:
32 /* focus new normal windows */
33 if (client_normal(e->data.c.client))
34 client_focus(e->data.c.client);
35 break;
36
37 case Event_Client_Destroy:
38 i = e->data.c.client->desktop;
39 focus_order[i] = g_slist_remove(focus_order[i], e->data.c.client);
40 break;
41
42 case Event_Ob_NumDesktops:
43 new = e->data.o.num[0];
44 old = e->data.o.num[1];
45 /* free our lists for the desktops which have disappeared */
46 for (i = new; i < old; ++i)
47 g_slist_free(focus_order[i]);
48 /* realloc the array */
49 focus_order = g_renew(GSList*, focus_order, new);
50 /* set the new lists to be empty */
51 for (i = old; i < new; ++i)
52 focus_order[i] = NULL;
53 break;
54
55 case Event_Client_Desktop:
56 old = e->data.c.num[1];
57 if (old != DESKTOP_ALL)
58 focus_order[old] = g_slist_remove(focus_order[old],
59 e->data.c.client);
60 else
61 for (i = 0; i < screen_num_desktops; ++i)
62 focus_order[i] = g_slist_remove(focus_order[i],
63 e->data.c.client);
64 break;
65
66 case Event_Ob_Desktop:
67 /* focus the next available target */
68 focus_fallback(e->data.o.num[0], TRUE);
69 break;
70
71 case Event_Client_Unfocus:
72 /* nothing is left with focus! */
73 if (focus_client == NULL)
74 /* focus the next available target */
75 focus_fallback(screen_desktop, FALSE);
76 break;
77
78 case Event_Client_Focus:
79 /* move to the top of the list */
80 focus_order[e->data.c.num[1]] =
81 g_slist_remove(focus_order[e->data.c.num[1]], e->data.c.client);
82 focus_order[e->data.c.num[1]] =
83 g_slist_prepend(focus_order[e->data.c.num[1]], e->data.c.client);
84 break;
85
86 case Event_X_EnterNotify:
87 if (e->data.x.client && client_normal(e->data.x.client))
88 client_focus(e->data.x.client);
89
90 default:
91 g_assert_not_reached();
92 }
93 }
94
95 void plugin_startup()
96 {
97 guint i;
98
99 dispatch_register(Event_Client_Mapped | Event_Client_Destroy |
100 Event_Ob_Desktop | Event_Ob_NumDesktops |
101 Event_Client_Focus | Event_Client_Unfocus |
102 Event_X_EnterNotify |
103 Event_Client_Desktop,
104 (EventHandler)events, NULL);
105
106 focus_order = g_new(GSList*, screen_num_desktops);
107 for (i = 0; i < screen_num_desktops; ++i)
108 focus_order[i] = NULL;
109 }
110
111 void plugin_shutdown()
112 {
113 guint i;
114
115 dispatch_register(0, (EventHandler)events, NULL);
116
117 for (i = 0; i < screen_num_desktops; ++i)
118 g_slist_free(focus_order[i]);
119 g_free(focus_order);
120 }
This page took 0.040788 seconds and 5 git commands to generate.