pidgin/pidginapplication.c

changeset 40553
892459990bb7
child 40555
0bf5825aab0a
equal deleted inserted replaced
40552:eb0f386cea6b 40553:892459990bb7
1 /*
2 * Pidgin - Internet Messenger
3 * Copyright (C) Pidgin Developers <devel@pidgin.im>
4 *
5 * Pidgin is the legal property of its developers, whose names are too numerous
6 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * source distribution.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <glib.h>
28 #include <glib/gi18n-lib.h>
29 #include <glib/gstdio.h>
30
31 #include <gplugin.h>
32 #include <purple.h>
33
34 #include "pidginapplication.h"
35
36 #include "gtkaccount.h"
37 #include "gtkblist.h"
38 #include "pidgincore.h"
39 #include "pidgindebug.h"
40
41 struct _PidginApplication {
42 GtkApplication parent;
43 };
44
45 /******************************************************************************
46 * Globals
47 *****************************************************************************/
48 static gchar *opt_config_dir_arg = NULL;
49 static gboolean opt_nologin = FALSE;
50
51 static GOptionEntry option_entries[] = {
52 {
53 "config", 'c', 0, G_OPTION_ARG_FILENAME, &opt_config_dir_arg,
54 N_("use DIR for config files"), N_("DIR")
55 }, {
56 "nologin", 'n', 0, G_OPTION_ARG_NONE, &opt_nologin,
57 N_("don't automatically login"), NULL
58 },
59 {
60 "version", 'v', 0, G_OPTION_ARG_NONE, NULL,
61 N_("display the current version and exit"), NULL
62 }, {
63 NULL
64 }
65 };
66
67 G_DEFINE_TYPE(PidginApplication, pidgin_application, GTK_TYPE_APPLICATION)
68
69 /******************************************************************************
70 * GApplication Implementation
71 *****************************************************************************/
72 static void
73 pidgin_application_startup(GApplication *application) {
74 GtkCssProvider *provider = NULL;
75 GError *error = NULL;
76 GList *active_accounts = NULL;
77 gchar *search_path = NULL;
78
79 G_APPLICATION_CLASS(pidgin_application_parent_class)->startup(application);
80
81 /* set a user-specified config directory */
82 if (opt_config_dir_arg != NULL) {
83 if (g_path_is_absolute(opt_config_dir_arg)) {
84 purple_util_set_user_dir(opt_config_dir_arg);
85 } else {
86 /* Make an absolute (if not canonical) path */
87 gchar *cwd = g_get_current_dir();
88 gchar *path = g_build_filename(cwd, opt_config_dir_arg, NULL);
89
90 purple_util_set_user_dir(path);
91
92 g_free(cwd);
93 g_free(path);
94 }
95 }
96
97 provider = gtk_css_provider_new();
98
99 search_path = g_build_filename(purple_config_dir(), "gtk-3.0.css", NULL);
100 gtk_css_provider_load_from_path(provider, search_path, &error);
101 if(error != NULL) {
102 purple_debug_error("gtk", "Unable to load custom gtk-3.0.css: %s\n",
103 error->message);
104 g_clear_error(&error);
105 } else {
106 GdkScreen *screen = gdk_screen_get_default();
107 gtk_style_context_add_provider_for_screen(screen,
108 GTK_STYLE_PROVIDER(provider),
109 GTK_STYLE_PROVIDER_PRIORITY_USER);
110 }
111
112 g_free(search_path);
113
114 #ifdef _WIN32
115 winpidgin_init();
116 #endif
117
118 purple_core_set_ui_ops(pidgin_core_get_ui_ops());
119
120 if(!purple_core_init(PIDGIN_UI)) {
121 fprintf(stderr,
122 _("Initialization of the libpurple core failed. Aborting!\n"
123 "Please report this!\n"));
124 g_abort();
125 }
126
127 if(g_getenv("PURPLE_PLUGINS_SKIP")) {
128 purple_debug_info("gtk",
129 "PURPLE_PLUGINS_SKIP environment variable "
130 "set, skipping normal Pidgin plugin paths");
131 } else {
132 search_path = g_build_filename(purple_data_dir(), "plugins", NULL);
133
134 if(!g_file_test(search_path, G_FILE_TEST_IS_DIR)) {
135 g_mkdir(search_path, S_IRUSR | S_IWUSR | S_IXUSR);
136 }
137
138 purple_plugins_add_search_path(search_path);
139 g_free(search_path);
140
141 purple_plugins_add_search_path(PIDGIN_LIBDIR);
142 }
143
144 purple_plugins_refresh();
145
146 /* load plugins we had when we quit */
147 purple_plugins_load_saved(PIDGIN_PREFS_ROOT "/plugins/loaded");
148
149 /* gk 20201008: this needs to be moved to the buddy list initialization. */
150 pidgin_blist_setup_sort_methods();
151
152 gtk_window_set_default_icon_name("pidgin");
153
154 g_free(opt_config_dir_arg);
155 opt_config_dir_arg = NULL;
156
157 /*
158 * We want to show the blist early in the init process so the
159 * user feels warm and fuzzy.
160 */
161 purple_blist_show();
162
163 if(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled")) {
164 pidgin_debug_window_show();
165 }
166
167 if(opt_nologin) {
168 /* Set all accounts to "offline" */
169 PurpleSavedStatus *saved_status;
170
171 /* If we've used this type+message before, lookup the transient status */
172 saved_status = purple_savedstatus_find_transient_by_type_and_message(
173 PURPLE_STATUS_OFFLINE, NULL);
174
175 /* If this type+message is unique then create a new transient saved status */
176 if(saved_status == NULL) {
177 saved_status = purple_savedstatus_new(NULL, PURPLE_STATUS_OFFLINE);
178 }
179
180 /* Set the status for each account */
181 purple_savedstatus_activate(saved_status);
182 } else {
183 /* Everything is good to go--sign on already */
184 if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status")) {
185 purple_savedstatus_activate(purple_savedstatus_get_startup());
186 }
187
188 purple_accounts_restore_current_statuses();
189 }
190
191 if((active_accounts = purple_accounts_get_all_active()) == NULL) {
192 pidgin_accounts_window_show();
193 } else {
194 g_list_free(active_accounts);
195 }
196
197 /* GTK clears the notification for us when opening the first window, but we
198 * may have launched with only a status icon, so clear it just in case.
199 */
200 gdk_notify_startup_complete();
201
202 #ifdef _WIN32
203 winpidgin_post_init();
204 #endif
205
206 /* TODO: Use GtkApplicationWindow or add a window instead */
207 g_application_hold(application);
208 }
209
210 static void
211 pidgin_application_activate(GApplication *application) {
212 PidginBuddyList *blist = pidgin_blist_get_default_gtk_blist();
213
214 if(blist != NULL && blist->window != NULL) {
215 gtk_window_present(GTK_WINDOW(blist->window));
216 }
217 }
218
219 static gint
220 pidgin_application_command_line(GApplication *application,
221 GApplicationCommandLine *cmdline)
222 {
223 gchar **argv = NULL;
224 gint argc = 0, i = 0;
225
226 argv = g_application_command_line_get_arguments(cmdline, &argc);
227
228 if(argc == 1) {
229 /* No arguments, just activate */
230 g_application_activate(application);
231 }
232
233 /* Start at 1 to skip the executable name */
234 for (i = 1; i < argc; i++) {
235 purple_got_protocol_handler_uri(argv[i]);
236 }
237
238 g_strfreev(argv);
239
240 return 0;
241 }
242
243 static gint
244 pidgin_application_handle_local_options(GApplication *application,
245 GVariantDict *options)
246 {
247 if (g_variant_dict_contains(options, "version")) {
248 printf("%s %s (libpurple %s)\n", PIDGIN_NAME, DISPLAY_VERSION,
249 purple_core_get_version());
250
251 return 0;
252 }
253
254 return -1;
255 }
256
257 /******************************************************************************
258 * GObject Implementation
259 *****************************************************************************/
260 static void
261 pidgin_application_init(PidginApplication *application) {
262 GApplication *gapp = G_APPLICATION(application);
263
264 g_application_add_main_option_entries(gapp, option_entries);
265 g_application_add_option_group(gapp, purple_get_option_group());
266 g_application_add_option_group(gapp, gplugin_get_option_group());
267 }
268
269 static void
270 pidgin_application_class_init(PidginApplicationClass *klass) {
271 GApplicationClass *app_class = G_APPLICATION_CLASS(klass);
272
273 app_class->startup = pidgin_application_startup;
274 app_class->activate = pidgin_application_activate;
275 app_class->command_line = pidgin_application_command_line;
276 app_class->handle_local_options = pidgin_application_handle_local_options;
277 }
278
279 /******************************************************************************
280 * Public API
281 *****************************************************************************/
282 GApplication *
283 pidgin_application_new(void) {
284 return g_object_new(
285 PIDGIN_TYPE_APPLICATION,
286 "flags", G_APPLICATION_CAN_OVERRIDE_APP_ID |
287 G_APPLICATION_HANDLES_COMMAND_LINE,
288 "register-session", TRUE,
289 NULL);
290 }

mercurial