Place embedded windows with panel orientation, used on startup
[window-docker.git] / main.c
blob325cc4056d0db9d423544f9186eff652bca23601
1 /*
2 * Window Docker
4 * Copyright (C) 2011 Nikita Zlobin <cook60020tmp@mail.ru>
6 **************************************************************************
7 * This file is part of Window Docker utility
8 **************************************************************************
10 * Window Docker is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * Window Docker is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Window Docker. If not, see <http://www.gnu.org/licenses/>
22 * or write to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <stdint.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdk.h>
30 #include <gdk/gdkx.h>
32 #include "main.h"
33 #include <stdlib.h>
35 static GError * error;
37 args_t args = {
38 .side = SIDE_NONE,
39 .sideStr = NULL,
40 .pos = 0.0,
41 .border = 1,
43 .autohiding = FALSE,
44 .show_delay = 0.1,
45 .hide_delay = 0.1,
47 .x = 0, .y = 0,
49 .last = NULL
52 PanelWindow * panel;
53 struct list_head win_info = LIST_HEAD_INIT (win_info);
54 #if 1
56 static gboolean
57 on_plug_removed (GtkSocket * socket, gpointer data)
58 { g_print ("Plug removed\n"); return TRUE; }
60 static
61 void fill_Panel (PanelWindow * panel)
63 GtkWidget * win;
64 GtkWidget * frame;
65 GtkWidget * hbox;
67 win = panelWindow_Container (panel);
69 frame = gtk_frame_new (NULL);
70 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
71 gtk_container_add (GTK_CONTAINER (win), frame);
73 switch (args.side)
75 case SIDE_NONE:
76 case SIDE_TOP:
77 case SIDE_BOTTOM:
78 case SIDE_OTHER:
79 hbox = gtk_hbox_new (FALSE, 0); break;
80 case SIDE_LEFT:
81 case SIDE_RIGHT:
82 hbox = gtk_vbox_new (FALSE, 0); break;
84 gtk_container_add (GTK_CONTAINER (frame), hbox);
86 panel->container = hbox;
89 static
90 gboolean add_window (PanelWindow * panel, GdkNativeWindow id)
92 __label__ failed;
93 g_print ("Grabbing window %lli\n", (long long)id);
95 GdkWindow * win;
96 win_info_t * win_info_new = malloc (sizeof (win_info_t));
98 GtkWidget * socket;
99 socket = gtk_socket_new ();
100 g_signal_connect (G_OBJECT (socket), "plug-removed", G_CALLBACK (on_plug_removed), NULL);
101 gtk_box_pack_start (GTK_BOX (panel->container), socket, FALSE, TRUE, 0);
103 win = gdk_window_foreign_new (id);
104 if (! win) {
105 g_print ("ERROR: Can't get info about specified window\n");
106 goto failed;
109 gdk_window_get_origin (win, & win_info_new->x, & win_info_new->y);
110 gdk_drawable_get_size (GDK_DRAWABLE (win), & win_info_new->w, & win_info_new->h);
111 g_object_unref (win);
113 gtk_widget_set_size_request (socket, win_info_new->w, win_info_new->h);
114 gtk_socket_add_id (GTK_SOCKET (socket), id);
115 gtk_widget_show (socket);
117 win = gtk_socket_get_plug_window (GTK_SOCKET (socket));
118 if (! win) {
119 g_print ("ERROR: Window was not embedded\n");
120 goto failed;
123 win_info_new->id = gtk_socket_get_id (GTK_SOCKET (socket)),
124 INIT_LIST_HEAD (& win_info_new->sibling);
125 list_add_tail (& win_info_new->sibling, & win_info);
127 gdk_window_reparent (win, gtk_widget_get_window (socket), 0, 0);
129 gdk_window_show (win);
130 gdk_flush ();
131 return TRUE;
133 failed:
134 free (win_info_new);
135 return FALSE;
138 static void grab_WIDs (char ** args)
140 __label__ useful_point, useless_point;
142 if (!args) return;
143 gboolean useless = TRUE;
145 void * w_add_label = && useless_point;
147 char ** arg = args;
148 for (; * arg; arg++)
150 intmax_t wid = str_toIntMax (*arg);
152 if (wid) goto * w_add_label;
153 continue;
155 useless_point:
156 if (add_window (panel, wid)) {
157 useless = FALSE;
158 w_add_label = && useful_point; }
159 continue;
161 useful_point:
162 add_window (panel, wid);
163 continue;
165 if (useless) gtk_main_quit ();
167 g_strfreev (args);
170 /* Callbacks */
172 static gboolean on_init (gpointer data)
174 grab_WIDs (args.last);
175 return FALSE;
178 void container_on_quit (GtkWidget * sock, gpointer data)
180 GdkWindow * pluged_win;
182 pluged_win = gtk_socket_get_plug_window (GTK_SOCKET (sock));
183 if (! pluged_win) return;
185 GdkNativeWindow id = gtk_socket_get_id (GTK_SOCKET (sock));
187 win_info_t * w_info = (win_info_t *)win_info.next;
188 while (1)
190 if (& w_info->sibling == & win_info) return;
191 if (w_info->id == id) break;
192 w_info = (win_info_t *)w_info->sibling.next;
194 GdkWindow * parent
195 = gdk_screen_get_root_window (gtk_widget_get_screen (panel->win));
197 gdk_window_reparent (pluged_win, parent, w_info->x, w_info->y);
198 gdk_window_resize (pluged_win, w_info->w, w_info->h);
199 gdk_window_show (pluged_win);
201 /* Compensate window auto-placing, used in most window managers */
202 gdk_window_move (pluged_win, w_info->x, w_info->y);
204 list_del (& w_info->sibling);
205 free (w_info);
208 static gboolean on_quit (gpointer data)
210 static gboolean used;
211 if (used) return 0;
213 gtk_container_foreach (GTK_CONTAINER (panel->container), container_on_quit, NULL);
215 used = TRUE;
216 return 0;
218 #endif
220 static
221 void init (PanelWindow * panel)
223 fill_Panel (panel);
225 if (args.side == SIDE_NONE) {
226 g_print ("floating\n");
227 panelWindow_Side_Set (panel, SIDE_NONE);
228 gtk_window_move (GTK_WINDOW (panelWindow_Container (panel)), args.x, args.y);
229 } else {
230 g_print ("docked\n");
231 panelWindow_Side_Set (panel, args.side);
233 panelWindow_AH_Toggle (panel, args.autohiding);
234 panelWindow_AH_ShowDuration_Set (panel, args.show_delay);
235 panelWindow_AH_HideDuration_Set (panel, args.hide_delay);
236 panelWindow_AH_Border_Set (panel, args.border);
237 panelWindow_Pos_Set (panel, args.pos);
239 gtk_widget_show_all (panel->win);
242 /* Command line parsing */
243 /* {{{ */
245 static GOptionEntry options[] = {
246 /*{ "config", 'c', 0, G_OPTION_ARG_FILENAME, & fileName,
247 "Use other file to load and save configuration", NULL }, */
249 { "x", 'x', 0, G_OPTION_ARG_INT, & args.x,
250 "X coordinate in floating mode",
251 "0" },
253 { "y", 'y', 0, G_OPTION_ARG_INT, & args.y,
254 "Y coordinate in floating mode",
255 "0" },
257 { "orientation", 'o', 0, G_OPTION_ARG_STRING, & args.sideStr,
258 "Docked panel side.",
259 "top, left, right, bottom" },
261 { "position", 'p', 0, G_OPTION_ARG_DOUBLE, & args.pos,
262 "Docked panel position.",
263 "0.0...1.0" },
265 { "border", 'b', 0, G_OPTION_ARG_INT, & args.border,
266 "Size of visible border in hidden state",
267 "0" },
269 { "autohiding", 'a', 0, G_OPTION_ARG_NONE, & args.autohiding,
270 "Automatically hide panel when mouse leaves it.",
271 NULL},
273 { "show-delay", 's', 0, G_OPTION_ARG_DOUBLE, & args.show_delay,
274 "Show delay in seconds.",
275 "0.1" },
277 { "hide-delay", 'h', 0, G_OPTION_ARG_DOUBLE, & args.hide_delay,
278 "Hide delay in seconds.",
279 "0.1" },
281 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, & args.last,
282 NULL, NULL },
283 NULL };
285 gboolean args_check (args_t * args)
287 if (! args->last) return FALSE;
289 if (args->sideStr) {
290 __label__ done;
292 if (strcmp (args->sideStr, "n") == 0 || strcmp (args->sideStr, "N") == 0 || strcmp (args->sideStr, "none") == 0)
293 { args->side = SIDE_NONE; goto done; };
295 if (strcmp (args->sideStr, "t") == 0 || strcmp (args->sideStr, "T") == 0 || strcmp (args->sideStr, "top") == 0)
296 { args->side = SIDE_TOP; goto done; };
298 if (strcmp (args->sideStr, "b") == 0 || strcmp (args->sideStr, "B") == 0 || strcmp (args->sideStr, "bottom") == 0)
299 { args->side = SIDE_BOTTOM; goto done; };
301 if (strcmp (args->sideStr, "l") == 0 || strcmp (args->sideStr, "L") == 0 || strcmp (args->sideStr, "left") == 0)
302 { args->side = SIDE_LEFT; goto done; };
304 if (strcmp (args->sideStr, "r") == 0 || strcmp (args->sideStr, "R") == 0 || strcmp (args->sideStr, "right") == 0)
305 { args->side = SIDE_RIGHT; goto done; };
307 args->side = SIDE_NONE;
308 done:;
309 } else args->side = SIDE_NONE;
311 return TRUE;
314 /* Command line parsing */
315 /* }}} */
317 /****************[ M A I N ]********************/
319 int main (int argc, char ** argv)
321 if (! gtk_init_with_args (&argc, &argv, "WID", options, NULL, & error)) {
322 g_print ("Could not initialize GTK: %s\n", error->message);
323 goto shutdown_0; }
325 if (! args_check (& args)) goto shutdown_0;
327 panel = panelWindow_Alloc ();
328 panelWindow_Init (panel);
330 /* TODO: Configuration storage */
332 init (panel);
334 g_signal_connect (G_OBJECT (panel->win), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
336 gtk_init_add ( on_init, NULL);
337 gtk_quit_add (0, on_quit, NULL);
339 sig_handler_init ();
341 gtk_main ();
343 shutdown_0: return 0;