1 /*
2 ** 1999-12-23 - Hm, perhaps this is an unfortunate choice of module title. It might bloat,
3 ** or something. :) Anyway, the purpose of this module is to help handle
4 ** (toplevel) windows, specifically remembering their sizes and positions.
5 */
6
7 #include "gentoo.h"
8
9 #include <ctype.h>
10 #include <stdlib.h>
11
12 #include "guiutil.h"
13 #include "graphics/icon_gentoo_small.xpm"
14
15 #include "window.h"
16
17 /* ----------------------------------------------------------------------------------------- */
18
19 typedef struct
20 {
21 guint32 id; /* Unique identifier for this windata. */
22 WinType type; /* What type of window? */
23 gboolean persistent; /* Makes close() actually do a hide(). */
24 const gchar *title; /* Text for window's title bar. */
25 const gchar *label; /* Short descriptive label (like "main", "config" etc). */
26 gboolean pos_grab;
27 gboolean size_grab;
28 /* Data below here is stored in configuration file. */
29 gint x, y; /* Window's opening position. */
30 gint width, height; /* The desired size of this window. */
31 gboolean pos_use; /* Should we set use the recorded position? */
32 gboolean pos_update; /* Update recorded position when window closes? */
33 gboolean size_use; /* Use recorded size? */
34 gboolean size_update; /* Update recorded size with current size on close? */
35 } WinDef;
36
37 struct WinInfo
38 {
39 MainInfo *min; /* The handiness of this pointer cannot be overstated. */
40 GList *windows; /* List of WinDef:s as per above. There's no rush. */
41 gint border_width; /* User's idea of her window manager's border size. Hackish. */
42 gint border_height;
43 };
44
45 /* ----------------------------------------------------------------------------------------- */
46
47 static WinDef * window_find(const WinInfo *wi, guint32 id);
48
49 /* ----------------------------------------------------------------------------------------- */
50
win_wininfo_new(MainInfo * min)51 WinInfo * win_wininfo_new(MainInfo *min)
52 {
53 WinInfo *wi;
54
55 wi = g_malloc(sizeof *wi);
56 wi->min = min;
57 wi->windows = NULL;
58
59 return wi;
60 }
61
62 /* 1999-12-23 - Create a new WinInfo, initialized with the "default" (i.e., legacy) windows. */
win_wininfo_new_default(MainInfo * min)63 WinInfo * win_wininfo_new_default(MainInfo *min)
64 {
65 WinInfo *wi;
66
67 wi = win_wininfo_new(min);
68
69 /* This is what seems to be right on my stock GNOME desktop.
70 ** Mileage will vary, wildly.
71 */
72 win_borders_set(wi, 4, 24);
73
74 win_window_new(wi, WIN_MAIN, WIN_TYPE_SIMPLE_TOPLEVEL, FALSE, geteuid() == 0 ? "gentoo [root]" : "gentoo", "main");
75 win_window_pos_grab_set(wi, WIN_MAIN, TRUE);
76 win_window_size_set(wi, WIN_MAIN, 764, 932);
77 win_window_size_use_set(wi, WIN_MAIN, TRUE);
78 win_window_size_update_set(wi, WIN_MAIN, TRUE);
79 win_window_size_grab_set(wi, WIN_MAIN, TRUE);
80
81 win_window_new(wi, WIN_CONFIG, WIN_TYPE_COMPLEX_DIALOG, TRUE, _("Configure gentoo"), "config");
82 win_window_pos_use_set(wi, WIN_CONFIG, FALSE);
83 win_window_size_set(wi, WIN_CONFIG, -1, 464);
84 win_window_size_use_set(wi, WIN_CONFIG, TRUE);
85 win_window_size_update_set(wi, WIN_CONFIG, TRUE);
86
87 win_window_new(wi, WIN_TEXTVIEW, WIN_TYPE_SIMPLE_TOPLEVEL, FALSE, _("Text Viewer"), "textview");
88 win_window_pos_use_set(wi, WIN_TEXTVIEW, FALSE);
89 win_window_size_set(wi, WIN_TEXTVIEW, 640, 480);
90 win_window_size_use_set(wi, WIN_TEXTVIEW, TRUE);
91 win_window_size_update_set(wi, WIN_TEXTVIEW, TRUE);
92
93 win_window_new(wi, WIN_INFO, WIN_TYPE_SIMPLE_DIALOG, FALSE, "Info", "info");
94 win_window_size_set(wi, WIN_INFO, 320, 480);
95 win_window_size_use_set(wi, WIN_INFO, TRUE);
96 win_window_size_update_set(wi, WIN_INFO, TRUE);
97
98 return wi;
99 }
100
101 /* 1999-12-23 - Create a copy of <wi>, sharing no memory with it. */
win_wininfo_copy(const WinInfo * wi)102 WinInfo * win_wininfo_copy(const WinInfo *wi)
103 {
104 WinInfo *nwi;
105 WinDef *win;
106 GList *iter;
107
108 nwi = win_wininfo_new(wi->min);
109
110 for(iter = wi->windows; iter != NULL; iter = g_list_next(iter))
111 {
112 win = iter->data;
113
114 win_window_new(nwi, win->id, win->type, win->persistent,
115 win->title, win->label);
116 win_window_pos_grab_set(nwi, win->id, win->pos_grab);
117 win_window_pos_set(nwi, win->id, win->x, win->y);
118 win_window_pos_use_set(nwi, win->id, win->pos_use);
119 win_window_pos_update_set(nwi, win->id, win->pos_update);
120 win_window_size_grab_set(nwi, win->id, win->size_grab);
121 win_window_size_set(nwi, win->id, win->width, win->height);
122 win_window_size_use_set(nwi, win->id, win->size_use);
123 win_window_size_update_set(nwi, win->id, win->size_update);
124 }
125 nwi->border_width = wi->border_width;
126 nwi->border_height = wi->border_height;
127 return nwi;
128 }
129
win_wininfo_destroy(WinInfo * wi)130 void win_wininfo_destroy(WinInfo *wi)
131 {
132 GList *iter;
133
134 for(iter = wi->windows; iter != NULL; iter = g_list_next(iter))
135 g_free(iter->data);
136 g_list_free(wi->windows);
137 g_free(wi);
138 }
139
140 /* ----------------------------------------------------------------------------------------- */
141
142 enum
143 {
144 SUBFRAME_POSITION, SUBFRAME_SIZE
145 };
146
evt_boolean_clicked(GtkWidget * wid,gpointer user)147 static void evt_boolean_clicked(GtkWidget *wid, gpointer user)
148 {
149 gboolean *flag = user;
150 gboolean *modified;
151
152 *flag = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));
153 if((modified = g_object_get_data(G_OBJECT(wid), "modified")) != NULL)
154 *modified = TRUE;
155 }
156
evt_integer_changed(GtkAdjustment * adj,gpointer user)157 static void evt_integer_changed(GtkAdjustment *adj, gpointer user)
158 {
159 gint *value = user;
160 gboolean *modified;
161
162 *value = gtk_adjustment_get_value(adj);
163 if((modified = g_object_get_data(G_OBJECT(adj), "modified")) != NULL)
164 *modified = TRUE;
165 }
166
167 /* Grab position. We implicitly *know* that the window in question is the main
168 ** gentoo window, and therefore access it directly through the MainInfo. We
169 ** then put the grabbed position into the editing copy of the WinDef, and update
170 ** the spin buttons to match. Of course, we don't forget setting that pesky old
171 ** modified-flag, either. :) What would people think?
172 */
evt_pos_grab_clicked(GtkWidget * wid,gpointer user)173 static void evt_pos_grab_clicked(GtkWidget *wid, gpointer user)
174 {
175 MainInfo *min;
176 WinDef *wd = user;
177
178 min = g_object_get_data(G_OBJECT(wid), "min");
179 gdk_window_get_position(gtk_widget_get_window(min->gui->window), &wd->x, &wd->y);
180 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(wid), "spin1")), wd->x);
181 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(wid), "spin2")), wd->y);
182 *(gboolean *) g_object_get_data(G_OBJECT(wid), "modified") = TRUE;
183 }
184
185 /* Grab size. Works only for main gentoo window. See comment for pos_grab above. */
evt_size_grab_clicked(GtkWidget * wid,gpointer user)186 static void evt_size_grab_clicked(GtkWidget *wid, gpointer user)
187 {
188 MainInfo *min;
189 WinDef *wd = user;
190
191 min = g_object_get_data(G_OBJECT(wid), "min");
192 wd->width = gdk_window_get_width(gtk_widget_get_window(min->gui->window));
193 wd->height = gdk_window_get_height(gtk_widget_get_window(min->gui->window));
194 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(wid), "spin1")), wd->width);
195 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(wid), "spin2")), wd->height);
196 *(gboolean *) g_object_get_data(G_OBJECT(wid), "modified") = TRUE;
197 }
198
subframe_build(const WinInfo * wi,WinDef * win,gint type,gboolean * modified)199 static GtkWidget * subframe_build(const WinInfo *wi, WinDef *win, gint type, gboolean *modified)
200 {
201 const gchar *ltext[] =
202 { N_("Position"), N_("Size") }, *etext[] =
203 { N_("X"), N_("Y"), N_("Width"), N_("Height") };
204 GtkWidget *label, *frame, *cbtn, *vbox, *grid, *spin1, *spin2;
205 GtkAdjustment *adj;
206 gint val1 = 0, val2 = 0;
207
208 frame = gtk_frame_new(_(ltext[type]));
209 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
210 cbtn = gtk_check_button_new_with_label(_("Set on Open?"));
211 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbtn), (type == SUBFRAME_POSITION) ? win_window_pos_use_get(wi, win->id) : win_window_size_use_get(wi, win->id));
212 g_object_set_data(G_OBJECT(cbtn), "modified", modified);
213 g_signal_connect(G_OBJECT(cbtn), "clicked", G_CALLBACK(evt_boolean_clicked), (type == SUBFRAME_POSITION) ? &win->pos_use : &win->size_use);
214 gtk_box_pack_start(GTK_BOX(vbox), cbtn, FALSE, FALSE, 0);
215
216 cbtn = gtk_check_button_new_with_label(_("Update on Close?"));
217 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbtn), (type == SUBFRAME_POSITION) ? win_window_pos_update_get(wi, win->id) : win_window_size_update_get(wi, win->id));
218 g_object_set_data(G_OBJECT(cbtn), "modified", modified);
219 g_signal_connect(G_OBJECT(cbtn), "clicked", G_CALLBACK(evt_boolean_clicked), (type == SUBFRAME_POSITION) ? &win->pos_update : &win->size_update);
220 gtk_box_pack_start(GTK_BOX(vbox), cbtn, FALSE, FALSE, 0);
221
222 grid = gtk_grid_new();
223
224 if(type == SUBFRAME_POSITION)
225 win_window_pos_get(wi, win->id, &val1, &val2);
226 else
227 win_window_size_get(wi, win->id, &val1, &val2);
228
229 label = gtk_label_new(_(etext[2 * type]));
230 gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
231 adj = gtk_adjustment_new(val1, -1.0, 65535.0, 1.0, 25.0, 0.0);
232 spin1 = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0.0);
233 g_object_set_data(G_OBJECT(adj), "modified", modified);
234 g_signal_connect(G_OBJECT(adj), "value_changed", G_CALLBACK(evt_integer_changed), type == SUBFRAME_POSITION ? &win->x : &win->width);
235 gtk_widget_set_hexpand(spin1, TRUE);
236 gtk_widget_set_halign(spin1, GTK_ALIGN_FILL);
237 gtk_grid_attach(GTK_GRID(grid), spin1, 1, 0, 1, 1);
238 label = gtk_label_new(_(etext[2 * type + 1]));
239 gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
240 adj = gtk_adjustment_new(val2, -1.0, 65535.0, 1.0, 25.0, 0.0);
241 spin2 = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0.0);
242 g_object_set_data(G_OBJECT(adj), "modified", modified);
243 g_signal_connect(G_OBJECT(adj), "value_changed", G_CALLBACK(evt_integer_changed), type == SUBFRAME_POSITION ? &win->y : &win->height);
244 gtk_grid_attach(GTK_GRID(grid), spin2, 1, 1, 1, 1);
245 if((type == SUBFRAME_POSITION && win->pos_grab) || (type == SUBFRAME_SIZE && win->size_grab))
246 {
247 GtkWidget *grab;
248
249 grab = gtk_button_new_with_label(_("Grab"));
250
251 g_object_set_data(G_OBJECT(grab), "min", wi->min);
252 g_object_set_data(G_OBJECT(grab), "spin1", spin1);
253 g_object_set_data(G_OBJECT(grab), "spin2", spin2);
254 g_object_set_data(G_OBJECT(grab), "modified", modified);
255 g_signal_connect(G_OBJECT(grab), "clicked", type == SUBFRAME_POSITION ? G_CALLBACK(evt_pos_grab_clicked) : G_CALLBACK(evt_size_grab_clicked), win);
256 gtk_grid_attach(GTK_GRID(grid), grab, 2, 0, 1, 2);
257 }
258 gtk_box_pack_start(GTK_BOX(vbox), grid, FALSE, FALSE, 0);
259 gtk_container_add(GTK_CONTAINER(frame), vbox);
260
261 return frame;
262 }
263
win_wininfo_build(const WinInfo * wi,gboolean * modified)264 GtkWidget * win_wininfo_build(const WinInfo *wi, gboolean *modified)
265 {
266 GtkWidget *vbox, *frame, *hbox, *sframe;
267 GList *iter;
268 gchar tmp[64];
269 WinDef *win;
270
271 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
272
273 for(iter = wi->windows; iter != NULL; iter = g_list_next(iter))
274 {
275 win = iter->data;
276
277 g_snprintf(tmp, sizeof tmp, "%c%s", toupper(*win->label), win->label + 1);
278 frame = gtk_frame_new(tmp);
279 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
280 sframe = subframe_build(wi, win, SUBFRAME_POSITION, modified);
281 gtk_box_pack_start(GTK_BOX(hbox), sframe, TRUE, TRUE, 5);
282 sframe = subframe_build(wi, win, SUBFRAME_SIZE, modified);
283 gtk_box_pack_start(GTK_BOX(hbox), sframe, TRUE, TRUE, 5);
284 gtk_container_add(GTK_CONTAINER(frame), hbox);
285 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
286 }
287 return vbox;
288 }
289
290 /* ----------------------------------------------------------------------------------------- */
291
292 /* 2000-02-24 - Write WinInfo out to given file <out>, at its current location. */
win_wininfo_save(const WinInfo * wi,FILE * out)293 void win_wininfo_save(const WinInfo *wi, FILE *out)
294 {
295 GList *iter;
296 WinDef *wd;
297
298 xml_put_node_open(out, "Windows");
299 for(iter = wi->windows; iter != NULL; iter = g_list_next(iter))
300 {
301 wd = iter->data;
302
303 xml_put_node_open(out, "Window");
304 xml_put_uinteger(out, "id", wd->id);
305 xml_put_integer(out, "x", wd->x);
306 xml_put_integer(out, "y", wd->y);
307 xml_put_integer(out, "w", wd->width);
308 xml_put_integer(out, "h", wd->height);
309 xml_put_boolean(out, "pos_use", wd->pos_use);
310 xml_put_boolean(out, "pos_update", wd->pos_update);
311 xml_put_boolean(out, "size_use", wd->size_use);
312 xml_put_boolean(out, "size_update", wd->size_update);
313 xml_put_node_close(out, "Window");
314 }
315 /* This goes INSIDE <Windows>, since there is no outer structure. :| */
316 xml_put_node_open(out, "Borders");
317 xml_put_integer(out, "width", wi->border_width);
318 xml_put_integer(out, "height", wi->border_height);
319 xml_put_node_close(out, "Borders");
320 xml_put_node_close(out, "Windows");
321 }
322
window_load(const XmlNode * node,gpointer user)323 static void window_load(const XmlNode *node, gpointer user)
324 {
325 WinInfo *wi = user;
326
327 if(xml_node_has_name(node, "Window"))
328 {
329 guint32 id;
330
331 if(xml_get_uinteger(node, "id", &id))
332 {
333 WinDef *wd;
334
335 if((wd = window_find(wi, id)) != NULL)
336 {
337 xml_get_integer(node, "x", &wd->x);
338 xml_get_integer(node, "y", &wd->y);
339 xml_get_integer(node, "w", &wd->width);
340 xml_get_integer(node, "h", &wd->height);
341 xml_get_boolean(node, "pos_use", &wd->pos_use);
342 xml_get_boolean(node, "pos_update", &wd->pos_update);
343 xml_get_boolean(node, "size_use", &wd->size_use);
344 xml_get_boolean(node, "size_update", &wd->size_update);
345 }
346 }
347 }
348 else if(xml_node_has_name(node, "Borders"))
349 {
350 xml_get_integer(node, "width", &wi->border_width);
351 xml_get_integer(node, "height", &wi->border_height);
352 }
353 }
354
355 /* 2000-02-24 - Fill in <wi> with details for windows, loaded from <node>. */
win_wininfo_load(WinInfo * wi,const XmlNode * node)356 void win_wininfo_load(WinInfo *wi, const XmlNode *node)
357 {
358 /* Visit all children. Since the XML structure, for the usual raisins, is a bit
359 ** messed up, the Window elements are at the same level as the Borders.
360 */
361 xml_node_visit_children(node, window_load, wi);
362 }
363
364 /* ----------------------------------------------------------------------------------------- */
365
win_borders_set(WinInfo * wi,gint width,gint height)366 void win_borders_set(WinInfo *wi, gint width, gint height)
367 {
368 if(wi == NULL)
369 return;
370 wi->border_width = width;
371 wi->border_height = height;
372 }
373
win_borders_get(const WinInfo * wi,gint * width,gint * height)374 void win_borders_get(const WinInfo *wi, gint *width, gint *height)
375 {
376 if(wi == NULL)
377 return;
378 if(width != NULL)
379 *width = wi->border_width;
380 if(height != NULL)
381 *height = wi->border_height;
382 }
383
384 /* ----------------------------------------------------------------------------------------- */
385
win_window_new(WinInfo * wi,guint32 id,WinType type,gboolean persistent,const gchar * title,const gchar * label)386 void win_window_new(WinInfo *wi, guint32 id, WinType type, gboolean persistent, const gchar *title, const gchar *label)
387 {
388 WinDef *wd;
389
390 wd = g_malloc(sizeof *wd);
391 wd->id = id;
392 wd->type = type;
393 wd->persistent = persistent;
394 wd->title = title;
395 wd->label = label;
396 wd->pos_grab = FALSE;
397 wd->size_grab = FALSE;
398
399 wd->x = 32;
400 wd->y = 32;
401 wd->width = 32;
402 wd->height = 32;
403
404 wd->pos_use = FALSE;
405 wd->pos_update = FALSE;
406 wd->size_use = FALSE;
407 wd->size_update = TRUE;
408
409 wi->windows = g_list_append(wi->windows, wd);
410 }
411
window_find(const WinInfo * wi,guint32 id)412 static WinDef * window_find(const WinInfo *wi, guint32 id)
413 {
414 GList *iter;
415
416 if(wi == NULL)
417 return NULL;
418
419 for(iter = wi->windows; iter != NULL; iter = g_list_next(iter))
420 {
421 if(((WinDef *) iter->data)->id == id)
422 return iter->data;
423 }
424 return NULL;
425 }
426
win_window_pos_grab_set(const WinInfo * wi,guint32 id,gboolean grab)427 void win_window_pos_grab_set(const WinInfo *wi, guint32 id, gboolean grab)
428 {
429 WinDef *wd;
430
431 if((wd = window_find(wi, id)) != NULL)
432 wd->pos_grab = grab;
433 }
434
win_window_pos_set(const WinInfo * wi,guint32 id,gint x,gint y)435 void win_window_pos_set(const WinInfo *wi, guint32 id, gint x, gint y)
436 {
437 WinDef *wd;
438
439 if((wd = window_find(wi, id)) != NULL)
440 {
441 wd->x = x;
442 wd->y = y;
443 }
444 }
445
win_window_pos_get(const WinInfo * wi,guint32 id,gint * x,gint * y)446 gboolean win_window_pos_get(const WinInfo *wi, guint32 id, gint *x, gint *y)
447 {
448 WinDef *wd;
449
450 if((wd = window_find(wi, id)) != NULL)
451 {
452 if(x)
453 *x = wd->x;
454 if(y)
455 *y = wd->y;
456 return TRUE;
457 }
458 return FALSE;
459 }
460
win_window_pos_use_set(const WinInfo * wi,guint32 id,gboolean enabled)461 void win_window_pos_use_set(const WinInfo *wi, guint32 id, gboolean enabled)
462 {
463 WinDef *wd;
464
465 if((wd = window_find(wi, id)) != NULL)
466 wd->pos_use = enabled;
467 }
468
win_window_pos_use_get(const WinInfo * wi,guint32 id)469 gboolean win_window_pos_use_get(const WinInfo *wi, guint32 id)
470 {
471 WinDef *wd;
472
473 if((wd = window_find(wi, id)) != NULL)
474 return wd->pos_use;
475 return FALSE;
476 }
477
win_window_pos_update_set(const WinInfo * wi,guint32 id,gboolean enabled)478 void win_window_pos_update_set(const WinInfo *wi, guint32 id, gboolean enabled)
479 {
480 WinDef *wd;
481
482 if((wd = window_find(wi, id)) != NULL)
483 wd->pos_update = enabled;
484 }
485
win_window_pos_update_get(const WinInfo * wi,guint32 id)486 gboolean win_window_pos_update_get(const WinInfo *wi, guint32 id)
487 {
488 WinDef *wd;
489
490 if((wd = window_find(wi, id)) != NULL)
491 return wd->pos_update;
492 return FALSE;
493 }
494
win_window_size_grab_set(const WinInfo * wi,guint32 id,gboolean grab)495 void win_window_size_grab_set(const WinInfo *wi, guint32 id, gboolean grab)
496 {
497 WinDef *wd;
498
499 if((wd = window_find(wi, id)) != NULL)
500 wd->size_grab = grab;
501 }
502
win_window_size_set(const WinInfo * wi,guint32 id,gint width,gint height)503 void win_window_size_set(const WinInfo *wi, guint32 id, gint width, gint height)
504 {
505 WinDef *wd;
506
507 if((wd = window_find(wi, id)) != NULL)
508 {
509 wd->width = width;
510 wd->height = height;
511 }
512 }
513
win_window_size_get(const WinInfo * wi,guint32 id,gint * width,gint * height)514 gboolean win_window_size_get(const WinInfo *wi, guint32 id, gint *width,
515 gint *height)
516 {
517 WinDef *wd;
518
519 if((wd = window_find(wi, id)) != NULL)
520 {
521 if(width)
522 *width = wd->width;
523 if(height)
524 *height = wd->height;
525 return TRUE;
526 }
527 return FALSE;
528 }
529
win_window_size_use_set(const WinInfo * wi,guint32 id,gboolean enabled)530 void win_window_size_use_set(const WinInfo *wi, guint32 id, gboolean enabled)
531 {
532 WinDef *wd;
533
534 if((wd = window_find(wi, id)) != NULL)
535 wd->size_use = enabled;
536 }
537
win_window_size_use_get(const WinInfo * wi,guint32 id)538 gboolean win_window_size_use_get(const WinInfo *wi, guint32 id)
539 {
540 WinDef *wd;
541
542 if((wd = window_find(wi, id)) != NULL)
543 return wd->size_use;
544 return FALSE;
545 }
546
win_window_size_update_set(const WinInfo * wi,guint32 id,gboolean enabled)547 void win_window_size_update_set(const WinInfo *wi, guint32 id, gboolean enabled)
548 {
549 WinDef *wd;
550
551 if((wd = window_find(wi, id)) != NULL)
552 wd->size_update = enabled;
553 }
554
win_window_size_update_get(const WinInfo * wi,guint32 id)555 gboolean win_window_size_update_get(const WinInfo *wi, guint32 id)
556 {
557 WinDef *wd;
558
559 if((wd = window_find(wi, id)) != NULL)
560 return wd->size_update;
561 return FALSE;
562 }
563
564 /* ----------------------------------------------------------------------------------------- */
565
win_window_destroy(WinInfo * wi,guint32 id)566 void win_window_destroy(WinInfo *wi, guint32 id)
567 {
568 WinDef *wd;
569
570 if((wd = window_find(wi, id)) != NULL)
571 {
572 wi->windows = g_list_remove(wi->windows, wd);
573 g_free(wd);
574 }
575 }
576
577 /* ----------------------------------------------------------------------------------------- */
578
579 /* 2010-12-12 - Rewritten to not use deprecated (and crazy-seeming) GDK calls. */
window_set_icon(GtkWindow * win)580 static void window_set_icon(GtkWindow *win)
581 {
582 GdkPixbuf *pbuf;
583
584 if((pbuf = gdk_pixbuf_new_from_xpm_data(icon_gentoo_small_xpm)) != NULL)
585 {
586 gtk_window_set_default_icon(pbuf);
587 gtk_window_set_icon_name(win, PACKAGE);
588 g_object_unref(G_OBJECT(pbuf)); /* I believe GTK+ owns this, now. */
589 }
590 }
591
592 /* 1999-12-23 - Open the window described by <key> in <wi>. The window will not be shown yet. */
win_window_open(const WinInfo * wi,guint32 id)593 GtkWidget * win_window_open(const WinInfo *wi, guint32 id)
594 {
595 WinDef *wd;
596
597 if((wd = window_find(wi, id)) != NULL)
598 {
599 GtkWidget *wid = NULL;
600
601 switch (wd->type)
602 {
603 case WIN_TYPE_SIMPLE_TOPLEVEL:
604 case WIN_TYPE_SIMPLE_DIALOG:
605 wid = gtk_window_new(GTK_WINDOW_TOPLEVEL);
606 break;
607 case WIN_TYPE_SIMPLE_POPUP:
608 wid = gtk_window_new(GTK_WINDOW_POPUP);
609 break;
610 case WIN_TYPE_COMPLEX_DIALOG:
611 wid = win_dialog_open(wi->min->gui->window);
612 break;
613 }
614 g_object_set_data(G_OBJECT(wid), "wininfo", (gpointer) wi);
615 g_object_set_data(G_OBJECT(wid), "windef", (gpointer) wd);
616 if(!wd->pos_use)
617 gtk_window_set_position(GTK_WINDOW(wid), GTK_WIN_POS_MOUSE);
618 gtk_widget_realize(wid);
619 if(id == WIN_MAIN)
620 window_set_icon(GTK_WINDOW(wid));
621 else if(id != WIN_MAIN && id != WIN_TYPE_COMPLEX_DIALOG && wi->min->gui != NULL)
622 gtk_window_set_transient_for(GTK_WINDOW(wid), GTK_WINDOW(wi->min->gui->window));
623 if(wd->title != NULL)
624 win_window_set_title(wid, wd->title);
625 if(wd->label != NULL)
626 gtk_window_set_role(GTK_WINDOW(wid), wd->label);
627 return wid;
628 }
629 return NULL;
630 }
631
632 /* 2000-02-19 - Refresh link between <wi> and <window>. Handy after <wi> has been replaced
633 ** while window was open, as happens in the config window case.
634 */
win_window_relink(const WinInfo * wi,guint32 id,GtkWidget * window)635 void win_window_relink(const WinInfo *wi, guint32 id, GtkWidget *window)
636 {
637 WinDef *wd;
638
639 if((wd = window_find(wi, id)) != NULL)
640 {
641 g_object_set_data(G_OBJECT(window), "wininfo", (gpointer) wi);
642 g_object_set_data(G_OBJECT(window), "windef", wd);
643 }
644 }
645
646 /* 2002-08-10 - Set title of a window. Since it seems to break if locale is set, we simply
647 ** un-set the locale temporarily. Hopefully, noone sets window titles in inner
648 ** loops around here.
649 ** NOTE NOTE This works for *all* windows, not just those created through this module.
650 ** That might surprise, but it felt more sensical to stick it in here anyway.
651 */
win_window_set_title(GtkWidget * win,const gchar * title)652 void win_window_set_title(GtkWidget *win, const gchar *title)
653 {
654 gtk_widget_realize(win);
655 gtk_window_set_title(GTK_WINDOW(win), title);
656 }
657
658 /* 1999-12-23 - Use this rather than gtk_widget_show() when you want to the window to appear, since
659 ** this gives us a chance to set the window's size and position according to preference.
660 */
win_window_show(GtkWidget * window)661 void win_window_show(GtkWidget *window)
662 {
663 WinInfo *wi;
664 WinDef *wd;
665
666 if(gtk_widget_get_visible(window))
667 return;
668
669 wi = g_object_get_data(G_OBJECT(window), "wininfo");
670 wd = g_object_get_data(G_OBJECT(window), "windef");
671 if((wd != NULL) && wd->size_use && wd->width >= 0)
672 gtk_window_set_default_size(GTK_WINDOW(window), wd->width, wd->height);
673 /* For the main window, make sure to make it possible to shrink very much. */
674 if(wd != NULL && wd->id == WIN_MAIN)
675 {
676 GdkGeometry geo;
677
678 geo.min_width = 10;
679 geo.min_height = 10;
680 gtk_window_set_geometry_hints(GTK_WINDOW(window), window, &geo, GDK_HINT_MIN_SIZE);
681 }
682
683 /* This causes the window to appear at some more or less random position. We then reposition
684 ** it to the configured place. This is visually distracting, unattractive, and almost s*cks,
685 ** but unfortunately I haven't been able to figure out how to fix it. If you move the show()
686 ** call to below the if, it works, but not all the time. :( Tips welcome.
687 */
688 gtk_widget_show_all(window);
689
690 /* If user wants to set position, check where it ended up and move it home. */
691 if((wd != NULL) && wd->pos_use && wd->x >= 0)
692 {
693 gint cx, cy;
694
695 gtk_window_get_position(GTK_WINDOW(window), &cx, &cy);
696 if(wi != NULL) /* Any borders to adjust for? */
697 {
698 cx += wi->border_width;
699 cy += wi->border_height;
700 }
701 gtk_window_move(GTK_WINDOW(window), wd->x - cx, wd->y - cy);
702 gui_events_flush();
703 gtk_window_get_position(GTK_WINDOW(window), &cx, &cy);
704 }
705 }
706
707 /* 2000-03-04 - If <a_new> is different from *<a>, update *<a> to <a_new> and return TRUE, else
708 ** return FALSE. Likewise for <b>, whatever that would mean.
709 */
update_pair(gint * a,gint * b,gint a_new,gint b_new)710 static gboolean update_pair(gint *a, gint *b, gint a_new, gint b_new)
711 {
712 if((*a != a_new) || (*b != b_new))
713 {
714 *a = a_new;
715 *b = b_new;
716 return TRUE;
717 }
718 return FALSE;
719 }
720
721 /* 2000-03-18 - Do an update for the given window, changing the config as needed. Returns TRUE
722 ** if the config was indeed changed.
723 */
win_window_update(GtkWidget * win)724 gboolean win_window_update(GtkWidget *win)
725 {
726 WinDef *wd;
727
728 if((wd = g_object_get_data(G_OBJECT(win), "windef")) != NULL)
729 {
730 gboolean ret = FALSE;
731 gint ta, tb;
732
733 if(wd->pos_update)
734 {
735 gdk_window_get_root_origin(gtk_widget_get_window(win), &ta, &tb);
736 ret |= update_pair(&wd->x, &wd->y, ta, tb);
737 }
738 if(wd->size_update)
739 {
740 ta = gdk_window_get_width(gtk_widget_get_window(win));
741 tb = gdk_window_get_height(gtk_widget_get_window(win));
742 ret |= update_pair(&wd->width, &wd->height, ta, tb);
743 }
744 return ret;
745 }
746 return FALSE;
747 }
748
749 /* 1999-12-23 - Close the given window. Use this rather than a direct gtk_widget_destroy(), since
750 ** we need a chance to update the position and size fields if needed. Also, if the
751 ** window is classified as "persistent", we don't actually destroy it, but only hide
752 ** it. Returns TRUE if the config was changed, i.e. if one of the update flags were
753 ** set AND the relevant property actually had changed.
754 */
win_window_close(GtkWidget * win)755 gboolean win_window_close(GtkWidget *win)
756 {
757 WinDef *wd;
758
759 if((wd = g_object_get_data(G_OBJECT(win), "windef")) != NULL)
760 {
761 gboolean ret;
762
763 ret = win_window_update(win);
764 if(wd->persistent)
765 gtk_widget_hide(win);
766 else
767 gtk_widget_destroy(win);
768 return ret;
769 }
770 gtk_widget_destroy(win);
771 return FALSE;
772 }
773
774 /* ----------------------------------------------------------------------------------------- */
775
776 /* 2010-12-12 - New single way of opening a dialog, that tries to make sure it gets the proper
777 ** linkage to the main window. This shares the icon, among (possibly) other things.
778 */
win_dialog_open(GtkWidget * main_window)779 GtkWidget * win_dialog_open(GtkWidget *main_window)
780 {
781 GtkWidget *wid = gtk_dialog_new();
782
783 if(main_window != NULL)
784 gtk_window_set_transient_for(GTK_WINDOW(wid), GTK_WINDOW(main_window));
785
786 return wid;
787 }
788