]> Dogcows Code - chaz/openbox/blob - plugins/placement/history.c
dont let windows be placed offscreen
[chaz/openbox] / plugins / placement / history.c
1 #include "kernel/openbox.h"
2 #include "kernel/dispatch.h"
3 #include "kernel/frame.h"
4 #include "kernel/client.h"
5 #include "kernel/screen.h"
6 #include <glib.h>
7 #include <string.h>
8 #ifdef HAVE_STDLIB_H
9 # include <stdlib.h>
10 #endif
11
12 struct HistoryItem {
13 char *name;
14 char *class;
15 char *role;
16 int x;
17 int y;
18 gboolean placed;
19 };
20
21 static GSList *history = NULL;
22 static char *history_path = NULL;
23
24 static struct HistoryItem *find_history(Client *c)
25 {
26 GSList *it;
27 struct HistoryItem *hi = NULL;
28
29 /* find the client */
30 for (it = history; it != NULL; it = it->next) {
31 hi = it->data;
32 g_assert(hi->name != NULL);
33 g_assert(hi->class != NULL);
34 g_assert(hi->role != NULL);
35 g_assert(c->name != NULL);
36 g_assert(c->class != NULL);
37 g_assert(c->role != NULL);
38 if (!strcmp(hi->name, c->name) &&
39 !strcmp(hi->class, c->class) &&
40 !strcmp(hi->role, c->role))
41 return hi;
42 }
43 return NULL;
44 }
45
46 gboolean place_history(Client *c)
47 {
48 struct HistoryItem *hi;
49 int x, y;
50
51 hi = find_history(c);
52
53 if (hi != NULL && !hi->placed) {
54 hi->placed = TRUE;
55 if (ob_state != State_Starting) {
56 x = hi->x;
57 y = hi->y;
58
59 /* make sure the window is on the display */
60 if (x >= screen_physical_size.width ||
61 y >= screen_physical_size.height ||
62 x + c->frame->area.width < 1 ||
63 y + c->frame->area.height < 1)
64 return FALSE;
65
66 frame_frame_gravity(c->frame, &x, &y); /* get where the client
67 should be */
68 client_configure(c, Corner_TopLeft, x, y,
69 c->area.width, c->area.height,
70 TRUE, TRUE);
71 }
72 return TRUE;
73 }
74
75 return FALSE;
76 }
77
78 static void strip_tabs(char *s)
79 {
80 while (*s != '\0') {
81 if (*s == '\t')
82 *s = ' ';
83 ++s;
84 }
85 }
86
87 static void set_history(Client *c)
88 {
89 struct HistoryItem *hi;
90
91 hi = find_history(c);
92
93 if (hi == NULL) {
94 hi = g_new(struct HistoryItem, 1);
95 history = g_slist_append(history, hi);
96 hi->name = g_strdup(c->name);
97 strip_tabs(hi->name);
98 hi->class = g_strdup(c->class);
99 strip_tabs(hi->class);
100 hi->role = g_strdup(c->role);
101 strip_tabs(hi->role);
102 }
103
104 hi->x = c->frame->area.x;
105 hi->y = c->frame->area.y;
106 hi->placed = FALSE;
107 }
108
109 static void event(ObEvent *e, void *foo)
110 {
111 g_assert(e->type == Event_Client_Destroy);
112
113 set_history(e->data.c.client);
114 }
115
116 static void save_history()
117 {
118 GError *err = NULL;
119 GIOChannel *io;
120 GString *buf;
121 GSList *it;
122 struct HistoryItem *hi;
123 gsize ret;
124
125 io = g_io_channel_new_file(history_path, "w", &err);
126 if (io != NULL) {
127 for (it = history; it != NULL; it = it->next) {
128 hi = it->data;
129 buf = g_string_sized_new(0);
130 buf=g_string_append(buf, hi->name);
131 g_string_append_c(buf, '\t');
132 buf=g_string_append(buf, hi->class);
133 g_string_append_c(buf, '\t');
134 buf=g_string_append(buf, hi->role);
135 g_string_append_c(buf, '\t');
136 g_string_append_printf(buf, "%d", hi->x);
137 buf=g_string_append_c(buf, '\t');
138 g_string_append_printf(buf, "%d", hi->y);
139 buf=g_string_append_c(buf, '\n');
140 if (g_io_channel_write_chars(io, buf->str, buf->len, &ret, &err) !=
141 G_IO_STATUS_NORMAL)
142 break;
143 g_string_free(buf, TRUE);
144 }
145 g_io_channel_unref(io);
146 }
147 }
148
149 static void load_history()
150 {
151 GError *err = NULL;
152 GIOChannel *io;
153 char *buf = NULL;
154 char *b, *c;
155 struct HistoryItem *hi = NULL;
156
157 io = g_io_channel_new_file(history_path, "r", &err);
158 if (io != NULL) {
159 while (g_io_channel_read_line(io, &buf, NULL, NULL, &err) ==
160 G_IO_STATUS_NORMAL) {
161 hi = g_new0(struct HistoryItem, 1);
162
163 b = buf;
164 if ((c = strchr(b, '\t')) == NULL) break;
165 *c = '\0';
166 hi->name = g_strdup(b);
167
168 b = c + 1;
169 if ((c = strchr(b, '\t')) == NULL) break;
170 *c = '\0';
171 hi->class = g_strdup(b);
172
173 b = c + 1;
174 if ((c = strchr(b, '\t')) == NULL) break;
175 *c = '\0';
176 hi->role = g_strdup(b);
177
178 b = c + 1;
179 if ((c = strchr(b, '\t')) == NULL) break;
180 *c = '\0';
181 hi->x = atoi(b);
182
183 b = c + 1;
184 if ((c = strchr(b, '\n')) == NULL) break;
185 *c = '\0';
186 hi->y = atoi(b);
187
188 hi->placed = FALSE;
189
190 g_free(buf);
191 buf = NULL;
192
193 history = g_slist_append(history, hi);
194 hi = NULL;
195 }
196 g_io_channel_unref(io);
197 }
198
199 g_free(buf);
200
201 if (hi != NULL) {
202 g_free(hi->name);
203 g_free(hi->class);
204 g_free(hi->role);
205 }
206 g_free(hi);
207 }
208
209 void history_startup()
210 {
211 char *path;
212
213 history = NULL;
214
215 path = g_build_filename(g_get_home_dir(), ".openbox", "history", NULL);
216 history_path = g_strdup_printf("%s.%d", path, ob_screen);
217 g_free(path);
218
219 load_history(); /* load from the historydb file */
220
221 dispatch_register(Event_Client_Destroy, (EventHandler)event, NULL);
222 }
223
224 void history_shutdown()
225 {
226 GSList *it;
227
228 save_history(); /* save to the historydb file */
229 for (it = history; it != NULL; it = it->next)
230 g_free(it->data);
231 g_slist_free(history);
232
233 dispatch_register(0, (EventHandler)event, NULL);
234
235 g_free(history_path);
236 }
This page took 0.048677 seconds and 5 git commands to generate.