mssh-window.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <gconf/gconf-client.h>
  4. #include <gdk/gdkkeysyms.h>
  5. #include "mssh-terminal.h"
  6. #include "mssh-pref.h"
  7. #include "mssh-gconf.h"
  8. #include "mssh-window.h"
  9. #include "config.h"
  10. static void mssh_window_sendhost(GtkWidget *widget, gpointer data);
  11. static void mssh_window_destroy(GtkWidget *widget, gpointer data);
  12. static void mssh_window_pref(GtkWidget *widget, gpointer data);
  13. static gboolean mssh_window_key_press(GtkWidget *widget,
  14. GdkEventKey *event, gpointer data);
  15. static gboolean mssh_window_entry_focused(GtkWidget *widget,
  16. GtkDirectionType dir, gpointer data);
  17. static gboolean mssh_window_session_close(gpointer data);
  18. static void mssh_window_session_closed(MSSHTerminal *terminal,
  19. gpointer data);
  20. static void mssh_window_session_focused(MSSHTerminal *terminal,
  21. gpointer data);
  22. static void mssh_window_insert(GtkWidget *widget, gchar *new_text,
  23. gint new_text_length, gint *position, gpointer data);
  24. static void mssh_window_add_session(MSSHWindow *window, char *hostname);
  25. static void mssh_window_init(MSSHWindow* window);
  26. static void mssh_window_class_init(MSSHWindowClass *klass);
  27. G_DEFINE_TYPE(MSSHWindow, mssh_window, GTK_TYPE_WINDOW)
  28. struct WinTermPair
  29. {
  30. MSSHWindow *window;
  31. MSSHTerminal *terminal;
  32. };
  33. GtkWidget* mssh_window_new(void)
  34. {
  35. return g_object_new(MSSH_TYPE_WINDOW, NULL);
  36. }
  37. static void mssh_window_sendhost(GtkWidget *widget, gpointer data)
  38. {
  39. int i;
  40. MSSHWindow *window = MSSH_WINDOW(data);
  41. for(i = 0; i < window->terminals->len; i++)
  42. {
  43. mssh_terminal_send_host(g_array_index(window->terminals,
  44. MSSHTerminal*, i));
  45. }
  46. }
  47. static void mssh_window_destroy(GtkWidget *widget, gpointer data)
  48. {
  49. int i;
  50. MSSHWindow *window = MSSH_WINDOW(data);
  51. if(window->terminals->len > 0)
  52. {
  53. GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window),
  54. GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
  55. GTK_BUTTONS_YES_NO, "%s, %s",
  56. "You still have open sessions",
  57. "are you sure you wish to quit?");
  58. if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES)
  59. {
  60. for(i = 0; i < window->terminals->len; i++)
  61. {
  62. mssh_terminal_destroy(g_array_index(window->terminals,
  63. MSSHTerminal*, i));
  64. }
  65. g_array_free(window->terminals, TRUE);
  66. gtk_main_quit();
  67. }
  68. gtk_widget_destroy(dialog);
  69. }
  70. else
  71. {
  72. gtk_main_quit();
  73. }
  74. }
  75. static void mssh_window_pref(GtkWidget *widget, gpointer data)
  76. {
  77. MSSHWindow *window = MSSH_WINDOW(data);
  78. GtkWidget *pref = mssh_pref_new();
  79. gtk_window_set_transient_for(GTK_WINDOW(pref), GTK_WINDOW(window));
  80. gtk_window_set_modal(GTK_WINDOW(pref), TRUE);
  81. gtk_window_set_position(GTK_WINDOW(pref),
  82. GTK_WIN_POS_CENTER_ON_PARENT);
  83. gtk_widget_show_all(pref);
  84. }
  85. static void mssh_window_insert(GtkWidget *widget, gchar *new_text,
  86. gint new_text_length, gint *position, gpointer data)
  87. {
  88. int i;
  89. MSSHWindow *window = MSSH_WINDOW(data);
  90. for(i = 0; i < window->terminals->len; i++)
  91. {
  92. mssh_terminal_send_string(g_array_index(window->terminals,
  93. MSSHTerminal*, i), new_text);
  94. }
  95. g_signal_stop_emission_by_name(G_OBJECT(widget), "insert-text");
  96. }
  97. static gboolean mssh_window_key_press(GtkWidget *widget,
  98. GdkEventKey *event, gpointer data)
  99. {
  100. int i;
  101. MSSHWindow *window = MSSH_WINDOW(data);
  102. for(i = 0; i < window->terminals->len; i++)
  103. {
  104. mssh_terminal_send_data(g_array_index(window->terminals,
  105. MSSHTerminal*, i), event);
  106. }
  107. return TRUE;
  108. }
  109. static gboolean mssh_window_entry_focused(GtkWidget *widget,
  110. GtkDirectionType dir, gpointer data)
  111. {
  112. MSSHWindow *window = MSSH_WINDOW(data);
  113. gtk_window_set_title(GTK_WINDOW(window), PACKAGE_NAME" - All");
  114. return FALSE;
  115. }
  116. static gboolean mssh_window_session_close(gpointer data)
  117. {
  118. int i, idx = -1;
  119. struct WinTermPair *data_pair = (struct WinTermPair*)data;
  120. for(i = 0; i < data_pair->window->terminals->len; i++)
  121. {
  122. if(data_pair->terminal == g_array_index(
  123. data_pair->window->terminals, MSSHTerminal*, i))
  124. {
  125. idx = i;
  126. break;
  127. }
  128. }
  129. if(idx == -1)
  130. {
  131. fprintf(stderr,
  132. "mssh: Fatal Error: Can't find terminal to remove!\n");
  133. }
  134. else
  135. {
  136. gtk_widget_destroy(data_pair->terminal->menu_item);
  137. gtk_container_remove(GTK_CONTAINER(data_pair->window->table),
  138. GTK_WIDGET(data_pair->terminal));
  139. g_array_remove_index(data_pair->window->terminals, idx);
  140. mssh_window_relayout(data_pair->window);
  141. }
  142. free(data_pair);
  143. return FALSE;
  144. }
  145. static void mssh_window_session_closed(MSSHTerminal *terminal,
  146. gpointer data)
  147. {
  148. struct WinTermPair *data_pair = malloc(sizeof(struct WinTermPair));
  149. data_pair->terminal = terminal;
  150. data_pair->window = MSSH_WINDOW(data);
  151. g_timeout_add_seconds(2, mssh_window_session_close, data_pair);
  152. }
  153. static void mssh_window_session_focused(MSSHTerminal *terminal,
  154. gpointer data)
  155. {
  156. char *title;
  157. size_t len;
  158. MSSHWindow *window = MSSH_WINDOW(data);
  159. len = strlen(PACKAGE_NAME" - ") + strlen(terminal->hostname) + 1;
  160. title = malloc(len);
  161. snprintf(title, len, PACKAGE_NAME" - %s", terminal->hostname);
  162. gtk_window_set_title(GTK_WINDOW(window), title);
  163. free(title);
  164. }
  165. void mssh_window_relayout(MSSHWindow *window)
  166. {
  167. GConfClient *client;
  168. GConfEntry *entry;
  169. int i, len = window->terminals->len, cols = window->columns;
  170. for(i = 0; i < len; i++)
  171. {
  172. MSSHTerminal *terminal = g_array_index(window->terminals,
  173. MSSHTerminal*, i);
  174. g_object_ref(terminal);
  175. if(GTK_WIDGET(terminal)->parent == GTK_WIDGET(window->table))
  176. {
  177. gtk_container_remove(GTK_CONTAINER(window->table),
  178. GTK_WIDGET(terminal));
  179. }
  180. gtk_table_attach(GTK_TABLE(window->table), GTK_WIDGET(terminal),
  181. (i % cols), (i == len - 1) ? cols : (i % cols) + 1, i / cols,
  182. (i / cols) + 1,
  183. GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1);
  184. g_object_unref(terminal);
  185. if(!terminal->started)
  186. {
  187. mssh_terminal_start_session(terminal, window->env);
  188. terminal->started = 1;
  189. }
  190. }
  191. if(len > 0)
  192. {
  193. gtk_table_resize(GTK_TABLE(window->table), ((len + 1) / cols),
  194. cols);
  195. }
  196. client = gconf_client_get_default();
  197. gtk_widget_show_all(GTK_WIDGET(window));
  198. entry = gconf_client_get_entry(client, MSSH_GCONF_KEY_FONT, NULL,
  199. TRUE, NULL);
  200. mssh_gconf_notify_font(client, 0, entry, window);
  201. entry = gconf_client_get_entry(client, MSSH_GCONF_KEY_FG_COLOUR, NULL,
  202. TRUE, NULL);
  203. mssh_gconf_notify_fg_colour(client, 0, entry, window);
  204. entry = gconf_client_get_entry(client, MSSH_GCONF_KEY_BG_COLOUR, NULL,
  205. TRUE, NULL);
  206. mssh_gconf_notify_bg_colour(client, 0, entry, window);
  207. }
  208. static void mssh_window_add_session(MSSHWindow *window, char *hostname)
  209. {
  210. MSSHTerminal *terminal = MSSH_TERMINAL(mssh_terminal_new());
  211. g_array_append_val(window->terminals, terminal);
  212. g_signal_connect(G_OBJECT(terminal), "session-closed",
  213. G_CALLBACK(mssh_window_session_closed), window);
  214. g_signal_connect(G_OBJECT(terminal), "session-focused",
  215. G_CALLBACK(mssh_window_session_focused), window);
  216. mssh_terminal_init_session(terminal, hostname);
  217. gtk_menu_shell_append(GTK_MENU_SHELL(window->server_menu),
  218. terminal->menu_item);
  219. }
  220. static void mssh_window_init(MSSHWindow* window)
  221. {
  222. GConfClient *client;
  223. GtkAccelGroup *accel_group = gtk_accel_group_new();
  224. GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
  225. GtkWidget *entry = gtk_entry_new();
  226. GtkWidget *menu_bar = gtk_menu_bar_new();
  227. GtkWidget *file_menu = gtk_menu_new();
  228. GtkWidget *edit_menu = gtk_menu_new();
  229. GtkWidget *file_item = gtk_menu_item_new_with_label("File");
  230. GtkWidget *edit_item = gtk_menu_item_new_with_label("Edit");
  231. GtkWidget *server_item = gtk_menu_item_new_with_label("Servers");
  232. GtkWidget *file_quit = gtk_image_menu_item_new_from_stock(
  233. GTK_STOCK_QUIT, NULL);
  234. GtkWidget *file_sendhost = gtk_image_menu_item_new_with_label(
  235. "Send hostname");
  236. GtkWidget *file_add = gtk_image_menu_item_new_with_label(
  237. "Add session");
  238. GtkWidget *edit_pref = gtk_image_menu_item_new_from_stock(
  239. GTK_STOCK_PREFERENCES, NULL);
  240. window->server_menu = gtk_menu_new();
  241. window->terminals = g_array_new(FALSE, TRUE, sizeof(MSSHTerminal*));
  242. gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item), file_menu);
  243. gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_item), edit_menu);
  244. gtk_menu_item_set_submenu(GTK_MENU_ITEM(server_item),
  245. window->server_menu);
  246. gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), file_add);
  247. gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), file_sendhost);
  248. gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), file_quit);
  249. gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), edit_pref);
  250. g_signal_connect(G_OBJECT(file_sendhost), "activate",
  251. G_CALLBACK(mssh_window_sendhost), window);
  252. g_signal_connect(G_OBJECT(file_quit), "activate",
  253. G_CALLBACK(mssh_window_destroy), window);
  254. g_signal_connect(G_OBJECT(edit_pref), "activate",
  255. G_CALLBACK(mssh_window_pref), window);
  256. gtk_widget_add_accelerator(file_quit, "activate", accel_group,
  257. GDK_W, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
  258. gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
  259. gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), file_item);
  260. gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), edit_item);
  261. gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), server_item);
  262. g_signal_connect(G_OBJECT(entry), "key-press-event",
  263. G_CALLBACK(mssh_window_key_press), window);
  264. g_signal_connect(G_OBJECT(entry), "insert-text",
  265. G_CALLBACK(mssh_window_insert), window);
  266. g_signal_connect(G_OBJECT(entry), "focus-in-event",
  267. G_CALLBACK(mssh_window_entry_focused), window);
  268. gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, TRUE, 0);
  269. gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, TRUE, 2);
  270. window->table = gtk_table_new(1, 1, TRUE);
  271. gtk_box_pack_start(GTK_BOX(vbox), window->table, TRUE, TRUE, 0);
  272. gtk_container_add(GTK_CONTAINER(window), vbox);
  273. gtk_widget_set_size_request(GTK_WIDGET(window), 1024, 768);
  274. gtk_window_set_title(GTK_WINDOW(window), PACKAGE_NAME);
  275. client = gconf_client_get_default();
  276. gconf_client_add_dir(client, MSSH_GCONF_PATH,
  277. GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
  278. gconf_client_notify_add(client, MSSH_GCONF_KEY_FONT,
  279. mssh_gconf_notify_font, window, NULL, NULL);
  280. gconf_client_notify_add(client, MSSH_GCONF_KEY_FG_COLOUR,
  281. mssh_gconf_notify_fg_colour, window, NULL, NULL);
  282. gconf_client_notify_add(client, MSSH_GCONF_KEY_BG_COLOUR,
  283. mssh_gconf_notify_bg_colour, window, NULL, NULL);
  284. gconf_client_notify_add(client, MSSH_GCONF_KEY_COLUMNS,
  285. mssh_gconf_notify_columns, window, NULL, NULL);
  286. gconf_client_notify(client, MSSH_GCONF_KEY_COLUMNS);
  287. }
  288. void mssh_window_start_session(MSSHWindow* window, char **env, int nhosts,
  289. char **servers)
  290. {
  291. int i, j, k;
  292. int rows = (nhosts / 2) + (nhosts % 2);
  293. window->env = env;
  294. for(i = 0; i < rows; i++)
  295. {
  296. for(j = 0; j < 2; j++)
  297. {
  298. k = j + i*2;
  299. if(k < nhosts)
  300. {
  301. mssh_window_add_session(window, servers[k]);
  302. }
  303. }
  304. }
  305. mssh_window_relayout(window);
  306. }
  307. static void mssh_window_class_init(MSSHWindowClass *klass)
  308. {
  309. }