1 /*
2 Copyright (C) 2004, 2005 Stephen Bach
3 This file is part of the Viewglob package.
4
5 Viewglob is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 Viewglob is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Viewglob; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include "common.h"
21 #include "string.h"
22 #include "x11-stuff.h"
23 #include "display-common.h"
24 #include "param-io.h"
25 #include "lscolors.h"
26
27 #include <gdk/gdkx.h>
28 #include <gdk/gdkkeysyms.h>
29
30 #include <X11/Xlib.h>
31 #include <X11/Xatom.h>
32
33 #include "fgetopt.h"
34
35 static void report_version(void);
36
37
prefs_init(struct prefs * v)38 void prefs_init(struct prefs* v) {
39 v->show_icons = TRUE;
40 v->jump_resize = TRUE;
41 v->font_size_modifier = 0;
42 }
43
44
parse_args(int argc,char ** argv,struct prefs * v)45 void parse_args(int argc, char** argv, struct prefs* v) {
46 gboolean in_loop = TRUE;
47
48 struct option long_options[] = {
49 { "font-size-modifier", 1, NULL, 'z' },
50 { "black", 1, NULL, '1' },
51 { "red", 1, NULL, '2' },
52 { "green", 1, NULL, '3' },
53 { "yellow", 1, NULL, '4' },
54 { "blue", 1, NULL, '5' },
55 { "magenta", 1, NULL, '6' },
56 { "cyan", 1, NULL, '7' },
57 { "white", 1, NULL, '8' },
58 { "jump-resize", 2, NULL, 'j' },
59 { "file-icons", 2, NULL, 'i' },
60 { "version", 0, NULL, 'V' },
61 };
62
63 GdkColor color_temp;
64
65 optind = 0;
66 while (in_loop) {
67 switch (fgetopt_long(argc, argv, "j::z:i::vV", long_options, NULL)) {
68
69 case -1:
70 in_loop = FALSE;
71 break;
72
73 /* Font size modifier */
74 case 'z':
75 v->font_size_modifier = CLAMP(atoi(optarg), -10, 10);
76 break;
77
78 /* Enable or disable icons */
79 case 'i':
80 if (!optarg || STREQ(optarg, "on"))
81 v->show_icons = TRUE;
82 else if (STREQ(optarg, "off"))
83 v->show_icons = FALSE;
84 break;
85
86 /* Enable or disable jump-resize */
87 case 'j':
88 if (!optarg || STREQ(optarg, "on"))
89 v->jump_resize = TRUE;
90 else if (STREQ(optarg, "off"))
91 v->jump_resize = FALSE;
92 break;
93
94 /* Colours */
95 case '1':
96 if (gdk_color_parse(optarg, &color_temp))
97 set_color(TCC_BLACK, &color_temp);
98 break;
99 case '2':
100 if (gdk_color_parse(optarg, &color_temp))
101 set_color(TCC_RED, &color_temp);
102 break;
103 case '3':
104 if (gdk_color_parse(optarg, &color_temp))
105 set_color(TCC_GREEN, &color_temp);
106 break;
107 case '4':
108 if (gdk_color_parse(optarg, &color_temp))
109 set_color(TCC_YELLOW, &color_temp);
110 break;
111 case '5':
112 if (gdk_color_parse(optarg, &color_temp))
113 set_color(TCC_BLUE, &color_temp);
114 break;
115 case '6':
116 if (gdk_color_parse(optarg, &color_temp))
117 set_color(TCC_MAGENTA, &color_temp);
118 break;
119 case '7':
120 if (gdk_color_parse(optarg, &color_temp))
121 set_color(TCC_CYAN, &color_temp);
122 break;
123 case '8':
124 if (gdk_color_parse(optarg, &color_temp))
125 set_color(TCC_WHITE, &color_temp);
126 break;
127
128 case 'v':
129 case 'V':
130 report_version();
131 break;
132
133 case ':':
134 g_warning("Option missing argument");
135 /*exit(EXIT_FAILURE);*/
136 break;
137
138 case '?':
139 default:
140 g_warning("Unknown option provided");
141 /*exit(EXIT_FAILURE);*/
142 break;
143 }
144 }
145 }
146
147
report_version(void)148 static void report_version(void) {
149 g_print("%s %s\n", g_get_prgname(), VERSION);
150 g_print("Released %s\n", VG_RELEASE_DATE);
151 exit(EXIT_SUCCESS);
152 }
153
154
155 /* Set the application icons. */
set_icons(void)156 void set_icons(void) {
157 #include "app_icons.h"
158
159 GList* icons = NULL;
160
161 /* Setup the application icons. */
162 icons = g_list_append(icons,
163 gdk_pixbuf_new_from_inline(-1, icon_16x16_inline, FALSE, NULL));
164 icons = g_list_append(icons,
165 gdk_pixbuf_new_from_inline(-1, icon_24x24_inline, FALSE, NULL));
166 icons = g_list_append(icons,
167 gdk_pixbuf_new_from_inline(-1, icon_32x32_inline, FALSE, NULL));
168 icons = g_list_append(icons,
169 gdk_pixbuf_new_from_inline(-1, icon_36x36_inline, FALSE, NULL));
170 gtk_window_set_default_icon_list(icons);
171 }
172
173
174 /* Send the id of the given window's X window to seer. */
write_xwindow_id(GtkWidget * gtk_window)175 void write_xwindow_id(GtkWidget* gtk_window) {
176
177 GdkWindow* gdk_window = gtk_window->window;
178 GString* xwindow_string = g_string_new(NULL);
179
180 if (gdk_window)
181 g_string_printf(xwindow_string, "%lu", GDK_WINDOW_XID(gdk_window));
182 else {
183 g_warning("Couldn't find an id for the display's window.");
184 xwindow_string = g_string_assign(xwindow_string, "0");
185 }
186
187 if (!put_param(STDOUT_FILENO, P_WIN_ID, xwindow_string->str)) {
188 g_critical("Couldn't write window ID to stdout");
189 exit(EXIT_FAILURE);
190 }
191
192 g_string_free(xwindow_string, TRUE);
193 }
194
195
refocus_wrapped(GtkWidget * display_win_gtk,gchar * term_win_str)196 void refocus_wrapped(GtkWidget* display_win_gtk, gchar* term_win_str) {
197 g_return_if_fail(display_win_gtk != NULL);
198 g_return_if_fail(term_win_str != NULL);
199 g_return_if_fail(display_win_gtk->window != NULL);
200
201 Display* Xdisplay;
202 Window display_win, term_win;
203
204 Xdisplay = GDK_DRAWABLE_XDISPLAY(display_win_gtk->window);
205 display_win = GDK_WINDOW_XID(display_win_gtk->window);
206 term_win = str_to_win(term_win_str);
207
208 if (display_win == 0 || term_win == 0)
209 return;
210
211 refocus(Xdisplay, display_win, term_win);
212 static int i = 0; i++;
213 g_warning("refocus %d", i);
214 }
215
216
raise_wrapped(GtkWidget * display_win_gtk,gchar * term_win_str)217 void raise_wrapped(GtkWidget* display_win_gtk, gchar* term_win_str) {
218
219 Display* Xdisplay;
220 Window display_win, term_win;
221
222 Xdisplay = GDK_DRAWABLE_XDISPLAY(display_win_gtk->window);
223 display_win = GDK_WINDOW_XID(display_win_gtk->window);
224 term_win = str_to_win(term_win_str);
225
226 if (display_win == 0 || term_win == 0)
227 return;
228
229 gint term_desktop = get_desktop(Xdisplay, term_win);
230 gint disp_desktop = get_desktop(Xdisplay, display_win);
231
232 if (term_desktop != -1 && disp_desktop != -1
233 && term_desktop != disp_desktop) {
234 window_to_desktop(Xdisplay, display_win, term_desktop);
235 }
236
237 static int i = 0; i++;
238 g_warning("raise %d", i);
239 /*raise_window(Xdisplay, display_win, term_win, TRUE);*/
240 //XMapRaised(Xdisplay, display_win);
241 XRaiseWindow(Xdisplay, display_win);
242 }
243
244
up_to_delimiter(gchar ** ptr,char c)245 gchar* up_to_delimiter(gchar** ptr, char c) {
246 gchar* start = *ptr;
247 while (**ptr != c)
248 (*ptr)++;
249
250 **ptr = '\0';
251 (*ptr)++;
252 return start;
253 }
254
255
256 /* Chooses a selection state based on the string's first char. */
map_selection_state(gchar c)257 FileSelection map_selection_state(gchar c) {
258 switch (c) {
259 case '-':
260 return FS_NO;
261 case '~':
262 return FS_MAYBE;
263 case '*':
264 return FS_YES;
265 default:
266 g_warning("Unexpected selection state \"%c\".", c);
267 return FS_NO;
268 }
269 }
270
271
272 /* Chooses a file type based on the string's first char. */
map_file_type(gchar c)273 FileType map_file_type(gchar c) {
274 switch (c) {
275 case 'r':
276 return FT_REGULAR;
277 case 'e':
278 return FT_EXECUTABLE;
279 case 'd':
280 return FT_DIRECTORY;
281 case 'y':
282 return FT_SYMLINK;
283 case 'b':
284 return FT_BLOCKDEV;
285 case 'c':
286 return FT_CHARDEV;
287 case 'f':
288 return FT_FIFO;
289 case 's':
290 return FT_SOCKET;
291 default:
292 g_warning("Unexpected file type \"%c\".", c);
293 return FT_REGULAR;
294 }
295 }
296
297
298 /* End the program. */
window_delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)299 gboolean window_delete_event(GtkWidget* widget, GdkEvent* event,
300 gpointer data) {
301 gtk_main_quit();
302 return FALSE;
303 }
304
305
306 /* A key has been pressed -- write it to stdout. */
window_key_press_event(GtkWidget * window,GdkEventKey * event,gpointer data)307 gboolean window_key_press_event(GtkWidget* window, GdkEventKey* event,
308 gpointer data) {
309
310 gsize bytes_written;
311 gchar* temp1;
312 gchar* temp2;
313
314 gboolean result = TRUE;
315
316 switch (event->keyval) {
317 case GDK_Home:
318 case GDK_Left:
319 case GDK_Up:
320 case GDK_Right:
321 case GDK_Down:
322 case GDK_Page_Up:
323 case GDK_Page_Down:
324 case GDK_End:
325 /* These keys we let the display interpret. */
326 result = FALSE;
327 break;
328
329 default:
330 /* The rest are passed to the terminal. */
331 temp1 = g_malloc(2);
332 *temp1 = event->keyval;
333 *(temp1 + 1) = '\0';
334
335 /* Convert out of utf8. */
336 temp2 = g_locale_from_utf8(temp1, -1, NULL, &bytes_written, NULL);
337
338 if (temp2) {
339 if (event->state & GDK_CONTROL_MASK) {
340 /* Control is being held. Determine if it's a control
341 key and convert. */
342 if (event->keyval >= 'a' && event->keyval <= 'z')
343 *temp2 -= 96;
344 else if (event->keyval >= '[' && event->keyval <= '_')
345 *temp2 -= 64;
346 else if (event->keyval == '@' || event->keyval == ' ')
347 /* This will go out empty, but vgseer is smart enough
348 to interpret a value length of 0 as a NUL
349 character. */
350 *temp2 = '\0';
351 }
352
353 if (!put_param(STDOUT_FILENO, P_KEY, temp2)) {
354 g_critical("Couldn't write key to stdout");
355 exit(EXIT_FAILURE);
356 }
357
358 g_free(temp2);
359 }
360 else
361 result = FALSE;
362
363 g_free(temp1);
364 break;
365 }
366
367 return result;
368 }
369
370