mssh-window.c 8.4 KB

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