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.
35 static GError
* error
;
53 struct list_head win_info
= LIST_HEAD_INIT (win_info
);
57 on_plug_removed (GtkSocket
* socket
, gpointer data
)
58 { g_print ("Plug removed\n"); return TRUE
; }
61 void fill_Panel (PanelWindow
* panel
)
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
);
79 hbox
= gtk_hbox_new (FALSE
, 0); break;
82 hbox
= gtk_vbox_new (FALSE
, 0); break;
84 gtk_container_add (GTK_CONTAINER (frame
), hbox
);
86 panel
->container
= hbox
;
90 gboolean
add_window (PanelWindow
* panel
, GdkNativeWindow id
)
93 g_print ("Grabbing window %lli\n", (long long)id
);
96 win_info_t
* win_info_new
= malloc (sizeof (win_info_t
));
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
);
105 g_print ("ERROR: Can't get info about specified window\n");
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
));
119 g_print ("ERROR: Window was not embedded\n");
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
);
138 static void grab_WIDs (char ** args
)
140 __label__ useful_point
, useless_point
;
143 gboolean useless
= TRUE
;
145 void * w_add_label
= && useless_point
;
150 intmax_t wid
= str_toIntMax (*arg
);
152 if (wid
) goto * w_add_label
;
156 if (add_window (panel
, wid
)) {
158 w_add_label
= && useful_point
; }
162 add_window (panel
, wid
);
165 if (useless
) gtk_main_quit ();
172 static gboolean
on_init (gpointer data
)
174 grab_WIDs (args
.last
);
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
;
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
;
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
);
208 static gboolean
on_quit (gpointer data
)
210 static gboolean used
;
213 gtk_container_foreach (GTK_CONTAINER (panel
->container
), container_on_quit
, NULL
);
221 void init (PanelWindow
* 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
);
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 */
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",
253 { "y", 'y', 0, G_OPTION_ARG_INT
, & args
.y
,
254 "Y coordinate in floating mode",
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.",
265 { "border", 'b', 0, G_OPTION_ARG_INT
, & args
.border
,
266 "Size of visible border in hidden state",
269 { "autohiding", 'a', 0, G_OPTION_ARG_NONE
, & args
.autohiding
,
270 "Automatically hide panel when mouse leaves it.",
273 { "show-delay", 's', 0, G_OPTION_ARG_DOUBLE
, & args
.show_delay
,
274 "Show delay in seconds.",
277 { "hide-delay", 'h', 0, G_OPTION_ARG_DOUBLE
, & args
.hide_delay
,
278 "Hide delay in seconds.",
281 { G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_STRING_ARRAY
, & args
.last
,
285 gboolean
args_check (args_t
* args
)
287 if (! args
->last
) return FALSE
;
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
;
309 } else args
->side
= SIDE_NONE
;
314 /* Command line parsing */
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
);
325 if (! args_check (& args
)) goto shutdown_0
;
327 panel
= panelWindow_Alloc ();
328 panelWindow_Init (panel
);
330 /* TODO: Configuration storage */
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
);
343 shutdown_0
: return 0;