]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/gtkapp.c
Create OS X application bundles for PuTTY and pterm.
[PuTTY.git] / unix / gtkapp.c
1 /*
2  * gtkapp.c: a top-level front end to GUI PuTTY and pterm, using
3  * GtkApplication. Suitable for OS X. Currently unfinished.
4  *
5  * (You could run it on ordinary Linux GTK too, in principle, but I
6  * don't think it would be particularly useful to do so, even once
7  * it's fully working.)
8  */
9
10 /*
11
12 To build on OS X, you will need a build environment with GTK 3 and
13 gtk-mac-bundler, and also Halibut on the path (to build the man pages,
14 without which the standard Makefile will complain). Then, from a clean
15 checkout, do this:
16
17 ./mkfiles.pl -U --with-quartz
18 make -C icons icns
19 make -C doc
20 make
21
22 and you should get unix/PuTTY.app and unix/PTerm.app as output.
23
24 */
25
26 #include <assert.h>
27 #include <stdlib.h>
28
29 #include <unistd.h>
30
31 #include <gtk/gtk.h>
32
33 #define MAY_REFER_TO_GTK_IN_HEADERS
34
35 #include "putty.h"
36
37 char *x_get_default(const char *key) { return NULL; }
38
39 #if !GTK_CHECK_VERSION(3,0,0)
40 /* This front end only works in GTK 3. If that's not what we've got,
41  * it's easier to just turn this program into a trivial stub by ifdef
42  * in the source than it is to remove it in the makefile edifice. */
43 int main(int argc, char **argv)
44 {
45     fprintf(stderr, "launcher does nothing on non-OSX platforms\n");
46     return 1;
47 }
48 GtkWidget *make_gtk_toplevel_window(void *frontend) { return NULL; }
49 void launch_duplicate_session(Conf *conf) {}
50 void launch_new_session(void) {}
51 void launch_saved_session(const char *str) {}
52 #else /* GTK_CHECK_VERSION(3,0,0) */
53
54 static void startup(GApplication *app, gpointer user_data)
55 {
56     GMenu *menubar, *menu, *section;
57
58     menubar = g_menu_new();
59
60     menu = g_menu_new();
61     g_menu_append_submenu(menubar, "File", G_MENU_MODEL(menu));
62
63     section = g_menu_new();
64     g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
65     g_menu_append(section, "New Window", "app.newwin");
66
67     menu = g_menu_new();
68     g_menu_append_submenu(menubar, "Edit", G_MENU_MODEL(menu));
69
70     section = g_menu_new();
71     g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
72     g_menu_append(section, "Paste", "win.paste");
73
74     gtk_application_set_menubar(GTK_APPLICATION(app),
75                                 G_MENU_MODEL(menubar));
76 }
77
78 static void paste_cb(GSimpleAction *action,
79                      GVariant      *parameter,
80                      gpointer       user_data)
81 {
82     request_paste(user_data);
83 }
84
85 static const GActionEntry win_actions[] = {
86     { "paste", paste_cb },
87 };
88
89 static GtkApplication *app;
90 GtkWidget *make_gtk_toplevel_window(void *frontend)
91 {
92     GtkWidget *win = gtk_application_window_new(app);
93     g_action_map_add_action_entries(G_ACTION_MAP(win),
94                                     win_actions,
95                                     G_N_ELEMENTS(win_actions),
96                                     frontend);
97     return win;
98 }
99
100 extern int cfgbox(Conf *conf);
101
102 void launch_duplicate_session(Conf *conf)
103 {
104     assert(conf_launchable(conf));
105     new_session_window(conf, NULL);
106 }
107
108 void launch_new_session(void)
109 {
110     Conf *conf = conf_new();
111     do_defaults(NULL, conf);
112     if (conf_launchable(conf) || cfgbox(conf)) {
113         new_session_window(conf, NULL);
114     }
115 }
116
117 void launch_saved_session(const char *str)
118 {
119     Conf *conf = conf_new();
120     do_defaults(str, conf);
121     if (conf_launchable(conf) || cfgbox(conf)) {
122         new_session_window(conf, NULL);
123     }
124 }
125
126 void new_app_win(GtkApplication *app)
127 {
128     launch_new_session();
129 }
130
131 static void activate(GApplication *app,
132                      gpointer      user_data)
133 {
134     new_app_win(GTK_APPLICATION(app));
135 }
136
137 static void newwin_cb(GSimpleAction *action,
138                       GVariant      *parameter,
139                       gpointer       user_data)
140 {
141     new_app_win(GTK_APPLICATION(user_data));
142 }
143
144 static void quit_cb(GSimpleAction *action,
145                     GVariant      *parameter,
146                     gpointer       user_data)
147 {
148     g_application_quit(G_APPLICATION(user_data));
149 }
150
151 static const GActionEntry app_actions[] = {
152     { "newwin", newwin_cb },
153     { "quit", quit_cb },
154 };
155
156 int main(int argc, char **argv)
157 {
158     int status;
159
160     {
161         /* Call the function in ux{putty,pterm}.c to do app-type
162          * specific setup */
163         extern void setup(int);
164         setup(FALSE);     /* FALSE means we are not a one-session process */
165     }
166
167     if (argc > 1) {
168         extern char *pty_osx_envrestore_prefix;
169         pty_osx_envrestore_prefix = argv[--argc];
170     }
171
172     {
173         const char *home = getenv("HOME");
174         if (home) {
175             if (chdir(home)) {}
176         }
177     }
178
179     gtkcomm_setup();
180
181     app = gtk_application_new("org.tartarus.projects.putty.macputty",
182                               G_APPLICATION_FLAGS_NONE);
183     g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
184     g_signal_connect(app, "startup", G_CALLBACK(startup), NULL);
185     g_action_map_add_action_entries(G_ACTION_MAP(app),
186                                     app_actions,
187                                     G_N_ELEMENTS(app_actions),
188                                     app);
189
190     status = g_application_run(G_APPLICATION(app), argc, argv);
191     g_object_unref(app);
192
193     return status;
194 }
195
196 #endif /* GTK_CHECK_VERSION(3,0,0) */