~ubuntu-branches/ubuntu/precise/gnome-screenshot/precise

« back to all changes in this revision

Viewing changes to src/screenshot-application.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-02-06 19:16:06 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120206191606-b1v0isk0124peq59
Tags: 3.3.2-0ubuntu1
* New upstream version:
  - "unable to overwrite file, says the file already exist and close" 
    (lp: #871135)    
* debian/control.in:
  - drop vcs, using ~ubuntu-desktop/gnome-screenshot/ubuntu requires to 
    create a gnome-screenshot component on launchpad, we can use the
    standard lp:ubuntu location for a small source
* debian/copyright: fixed some small syntax issues, 
  thanks Didier for the review

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gnome-screenshot.c - Take a screenshot of the desktop
 
2
 *
 
3
 * Copyright (C) 2001 Jonathan Blandford <jrb@alum.mit.edu>
 
4
 * Copyright (C) 2006 Emmanuele Bassi <ebassi@gnome.org>
 
5
 * Copyright (C) 2008-2012 Cosimo Cecchi <cosimoc@gnome.org>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License as
 
9
 * published by the Free Software Foundation; either version 2 of the
 
10
 * License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
20
 * USA
 
21
 */
 
22
 
 
23
#include <config.h>
 
24
#include <gdk/gdkx.h>
 
25
#include <gdk/gdkkeysyms.h>
 
26
#include <fcntl.h>
 
27
#include <unistd.h>
 
28
#include <stdlib.h>
 
29
#include <locale.h>
 
30
#include <glib/gi18n.h>
 
31
#include <gio/gio.h>
 
32
 
 
33
#include "screenshot-application.h"
 
34
#include "screenshot-area-selection.h"
 
35
#include "screenshot-config.h"
 
36
#include "screenshot-filename-builder.h"
 
37
#include "screenshot-interactive-dialog.h"
 
38
#include "screenshot-shadow.h"
 
39
#include "screenshot-utils.h"
 
40
#include "screenshot-dialog.h"
 
41
 
 
42
#define SCREENSHOOTER_ICON "applets-screenshooter"
 
43
 
 
44
#define LAST_SAVE_DIRECTORY_KEY "last-save-directory"
 
45
 
 
46
G_DEFINE_TYPE (ScreenshotApplication, screenshot_application, GTK_TYPE_APPLICATION);
 
47
 
 
48
static ScreenshotApplication *_app_singleton = NULL;
 
49
 
 
50
static void screenshot_save_to_file (ScreenshotApplication *self);
 
51
 
 
52
struct _ScreenshotApplicationPriv {
 
53
  GDBusConnection *connection;
 
54
 
 
55
  gchar *icc_profile_base64;
 
56
  GdkPixbuf *screenshot;
 
57
 
 
58
  gchar *save_uri;
 
59
  gboolean should_overwrite;
 
60
 
 
61
  ScreenshotDialog *dialog;
 
62
};
 
63
 
 
64
static void
 
65
save_folder_to_settings (ScreenshotApplication *self)
 
66
{
 
67
  char *folder;
 
68
 
 
69
  folder = screenshot_dialog_get_folder (self->priv->dialog);
 
70
  g_settings_set_string (screenshot_config->settings,
 
71
                         LAST_SAVE_DIRECTORY_KEY, folder);
 
72
 
 
73
  g_free (folder);
 
74
}
 
75
 
 
76
static void
 
77
set_recent_entry (ScreenshotApplication *self)
 
78
{
 
79
  char *app_exec = NULL;
 
80
  GtkRecentManager *recent;
 
81
  GtkRecentData recent_data;
 
82
  GAppInfo *app;
 
83
  const char *exec_name = NULL;
 
84
  static char * groups[2] = { "Graphics", NULL };
 
85
 
 
86
  app = g_app_info_get_default_for_type ("image/png", TRUE);
 
87
 
 
88
  if (!app) {
 
89
    /* return early, as this would be an useless recent entry anyway. */
 
90
    return;
 
91
  }
 
92
 
 
93
  recent = gtk_recent_manager_get_default ();
 
94
  
 
95
  exec_name = g_app_info_get_executable (app);
 
96
  app_exec = g_strjoin (" ", exec_name, "%u", NULL);
 
97
 
 
98
  recent_data.display_name = NULL;
 
99
  recent_data.description = NULL;
 
100
  recent_data.mime_type = "image/png";
 
101
  recent_data.app_name = "GNOME Screenshot";
 
102
  recent_data.app_exec = app_exec;
 
103
  recent_data.groups = groups;
 
104
  recent_data.is_private = FALSE;
 
105
 
 
106
  gtk_recent_manager_add_full (recent, self->priv->save_uri, &recent_data);
 
107
 
 
108
  g_object_unref (app);
 
109
  g_free (app_exec);
 
110
}
 
111
 
 
112
static void
 
113
save_pixbuf_handle_success (ScreenshotApplication *self)
 
114
{
 
115
  set_recent_entry (self);
 
116
 
 
117
  if (screenshot_config->interactive)
 
118
    {
 
119
      ScreenshotDialog *dialog = self->priv->dialog;
 
120
 
 
121
      save_folder_to_settings (self);
 
122
      gtk_widget_destroy (screenshot_dialog_get_toplevel (dialog));
 
123
    }
 
124
  else
 
125
    {
 
126
      g_application_release (G_APPLICATION (self));
 
127
    }
 
128
}
 
129
 
 
130
static void
 
131
save_pixbuf_handle_error (ScreenshotApplication *self,
 
132
                          GError *error)
 
133
{
 
134
  if (screenshot_config->interactive)
 
135
    {
 
136
      ScreenshotDialog *dialog = self->priv->dialog;
 
137
      GtkWidget *toplevel = screenshot_dialog_get_toplevel (dialog);
 
138
 
 
139
      screenshot_dialog_set_busy (dialog, FALSE);
 
140
 
 
141
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS) &&
 
142
          !self->priv->should_overwrite)
 
143
        {
 
144
          gchar *folder = screenshot_dialog_get_folder (dialog);
 
145
          gchar *folder_name = g_path_get_basename (folder);
 
146
          gchar *file_name = screenshot_dialog_get_filename (dialog);
 
147
          gchar *detail = g_strdup_printf (_("A file named \"%s\" already exists in \"%s\""),
 
148
                                           file_name, folder_name);
 
149
          gint response;
 
150
                                             
 
151
          response = screenshot_show_dialog (GTK_WINDOW (toplevel),
 
152
                                             GTK_MESSAGE_WARNING,
 
153
                                             GTK_BUTTONS_YES_NO,
 
154
                                             _("Overwrite existing file?"),
 
155
                                             detail);
 
156
 
 
157
          g_free (folder);
 
158
          g_free (folder_name);
 
159
          g_free (file_name);
 
160
          g_free (detail);
 
161
 
 
162
          if (response == GTK_RESPONSE_YES)
 
163
            {
 
164
              self->priv->should_overwrite = TRUE;
 
165
              screenshot_save_to_file (self);
 
166
 
 
167
              return;
 
168
            }
 
169
        }
 
170
      else
 
171
        {
 
172
          screenshot_show_dialog (GTK_WINDOW (toplevel),
 
173
                                  GTK_MESSAGE_ERROR,
 
174
                                  GTK_BUTTONS_OK,
 
175
                                  _("Unable to capture a screenshot"),
 
176
                                  _("Error creating file. Please choose another location and retry."));
 
177
        }
 
178
 
 
179
      screenshot_dialog_focus_entry (dialog);
 
180
    }
 
181
  else
 
182
    {
 
183
      screenshot_play_sound_effect ("dialog-error", _("Unable to capture a screenshot"));
 
184
      g_application_release (G_APPLICATION (self));
 
185
    }
 
186
}
 
187
 
 
188
static void
 
189
save_pixbuf_ready_cb (GObject *source,
 
190
                      GAsyncResult *res,
 
191
                      gpointer user_data)
 
192
{
 
193
  GError *error = NULL;
 
194
  ScreenshotApplication *self = user_data;
 
195
 
 
196
  gdk_pixbuf_save_to_stream_finish (res, &error);
 
197
 
 
198
  if (error != NULL)
 
199
    {
 
200
      save_pixbuf_handle_error (self, error);
 
201
      g_error_free (error);
 
202
      return;
 
203
    }
 
204
 
 
205
  save_pixbuf_handle_success (self);
 
206
}
 
207
 
 
208
static void
 
209
save_file_create_ready_cb (GObject *source,
 
210
                           GAsyncResult *res,
 
211
                           gpointer user_data)
 
212
{
 
213
  ScreenshotApplication *self = user_data;
 
214
  GFileOutputStream *os;
 
215
  GError *error = NULL;
 
216
 
 
217
  if (self->priv->should_overwrite)
 
218
    os = g_file_replace_finish (G_FILE (source), res, &error);
 
219
  else
 
220
    os = g_file_create_finish (G_FILE (source), res, &error);
 
221
 
 
222
  if (error != NULL)
 
223
    {
 
224
      save_pixbuf_handle_error (self, error);
 
225
      g_error_free (error);
 
226
      return;
 
227
    }
 
228
 
 
229
  if (self->priv->icc_profile_base64 != NULL)
 
230
    gdk_pixbuf_save_to_stream_async (self->priv->screenshot,
 
231
                                     G_OUTPUT_STREAM (os),
 
232
                                     "png", NULL,
 
233
                                     save_pixbuf_ready_cb, self,
 
234
                                     "icc-profile", self->priv->icc_profile_base64,
 
235
                                     "tEXt::Software", "gnome-screenshot",
 
236
                                     NULL);
 
237
  else
 
238
    gdk_pixbuf_save_to_stream_async (self->priv->screenshot,
 
239
                                     G_OUTPUT_STREAM (os),
 
240
                                     "png", NULL,
 
241
                                     save_pixbuf_ready_cb, self,
 
242
                                     "tEXt::Software", "gnome-screenshot",
 
243
                                     NULL);
 
244
 
 
245
  g_object_unref (os);
 
246
}
 
247
 
 
248
static void
 
249
screenshot_save_to_file (ScreenshotApplication *self)
 
250
{
 
251
  GFile *target_file;
 
252
 
 
253
  if (self->priv->dialog != NULL)
 
254
    screenshot_dialog_set_busy (self->priv->dialog, TRUE);
 
255
 
 
256
  target_file = g_file_new_for_uri (self->priv->save_uri);
 
257
 
 
258
  if (self->priv->should_overwrite)
 
259
    {
 
260
      g_file_replace_async (target_file,
 
261
                            NULL, FALSE,
 
262
                            G_FILE_CREATE_NONE,
 
263
                            G_PRIORITY_DEFAULT,
 
264
                            NULL, 
 
265
                            save_file_create_ready_cb, self);
 
266
    }
 
267
  else
 
268
    {
 
269
      g_file_create_async (target_file,
 
270
                           G_FILE_CREATE_NONE,
 
271
                           G_PRIORITY_DEFAULT,
 
272
                           NULL,
 
273
                           save_file_create_ready_cb, self);
 
274
    }
 
275
 
 
276
  g_object_unref (target_file);
 
277
}
 
278
 
 
279
static void
 
280
screenshot_save_to_clipboard (ScreenshotApplication *self)
 
281
{
 
282
  GtkClipboard *clipboard;
 
283
 
 
284
  clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
 
285
                                             GDK_SELECTION_CLIPBOARD);
 
286
  gtk_clipboard_set_image (clipboard, self->priv->screenshot);
 
287
}
 
288
 
 
289
static void
 
290
screenshot_dialog_response_cb (GtkDialog *d,
 
291
                               gint response_id,
 
292
                               gpointer user_data)
 
293
{
 
294
  ScreenshotApplication *self = user_data;
 
295
 
 
296
  switch (response_id)
 
297
    {
 
298
    case GTK_RESPONSE_HELP:
 
299
      screenshot_display_help (GTK_WINDOW (d));
 
300
      break;
 
301
    case GTK_RESPONSE_OK:
 
302
      /* update to the new URI */
 
303
      g_free (self->priv->save_uri);
 
304
      self->priv->save_uri = screenshot_dialog_get_uri (self->priv->dialog);
 
305
      screenshot_save_to_file (self);
 
306
      break;
 
307
    case SCREENSHOT_RESPONSE_COPY:
 
308
      screenshot_save_to_clipboard (self);
 
309
      break;
 
310
    default:
 
311
      gtk_widget_destroy (GTK_WIDGET (d));
 
312
      break;
 
313
    }
 
314
}
 
315
 
 
316
static void
 
317
build_filename_ready_cb (GObject *source,
 
318
                         GAsyncResult *res,
 
319
                         gpointer user_data)
 
320
{
 
321
  ScreenshotApplication *self = user_data;
 
322
  GtkWidget *toplevel;
 
323
  ScreenshotDialog *dialog;
 
324
  gchar *save_uri;
 
325
  GError *error = NULL;
 
326
 
 
327
  self->priv->save_uri = screenshot_build_filename_finish (res, &error);
 
328
 
 
329
  /* now release the application */
 
330
  g_application_release (G_APPLICATION (self));
 
331
 
 
332
  if (error != NULL)
 
333
    {
 
334
      g_critical ("Impossible to find a valid location to save the screenshot: %s",
 
335
                  error->message);
 
336
      g_error_free (error);
 
337
 
 
338
      if (screenshot_config->interactive)
 
339
        screenshot_show_dialog (NULL,
 
340
                                GTK_MESSAGE_ERROR,
 
341
                                GTK_BUTTONS_OK,
 
342
                                _("Unable to capture a screenshot"),
 
343
                                _("Error creating file"));
 
344
      else
 
345
        screenshot_play_sound_effect ("dialog-error", _("Unable to capture a screenshot"));
 
346
 
 
347
      return;
 
348
    }
 
349
 
 
350
  screenshot_play_sound_effect ("screen-capture", _("Screenshot taken"));
 
351
 
 
352
  if (screenshot_config->interactive)
 
353
    {
 
354
      self->priv->dialog = screenshot_dialog_new (self->priv->screenshot, self->priv->save_uri);
 
355
      toplevel = screenshot_dialog_get_toplevel (self->priv->dialog);
 
356
      gtk_widget_show (toplevel);
 
357
 
 
358
      gtk_application_add_window (GTK_APPLICATION (self), GTK_WINDOW (toplevel));
 
359
  
 
360
      g_signal_connect (toplevel,
 
361
                        "response",
 
362
                        G_CALLBACK (screenshot_dialog_response_cb),
 
363
                        self);
 
364
    }
 
365
  else
 
366
    {
 
367
      g_application_hold (G_APPLICATION (self));
 
368
      screenshot_save_to_file (self);
 
369
    }
 
370
}
 
371
 
 
372
static void
 
373
finish_prepare_screenshot (ScreenshotApplication *self,
 
374
                           GdkRectangle *rectangle)
 
375
{
 
376
  GdkPixbuf *screenshot;
 
377
 
 
378
  screenshot = screenshot_get_pixbuf (rectangle);
 
379
 
 
380
  if (screenshot == NULL)
 
381
    {
 
382
      g_critical ("Unable to capture a screenshot of any window");
 
383
 
 
384
      if (screenshot_config->interactive)
 
385
        screenshot_show_dialog (NULL,
 
386
                                GTK_MESSAGE_ERROR,
 
387
                                GTK_BUTTONS_OK,
 
388
                                _("Unable to capture a screenshot"),
 
389
                                _("All possible methods failed"));
 
390
      else
 
391
        screenshot_play_sound_effect ("dialog-error", _("Unable to capture a screenshot"));
 
392
 
 
393
      g_application_release (G_APPLICATION (self));
 
394
 
 
395
      return;
 
396
    }
 
397
 
 
398
  if (screenshot_config->take_window_shot)
 
399
    {
 
400
      switch (screenshot_config->border_effect[0])
 
401
        {
 
402
        case 's': /* shadow */
 
403
          screenshot_add_shadow (&screenshot);
 
404
          break;
 
405
        case 'b': /* border */
 
406
          screenshot_add_border (&screenshot);
 
407
          break;
 
408
        case 'n': /* none */
 
409
        default:
 
410
          break;
 
411
        }
 
412
    }
 
413
 
 
414
  self->priv->screenshot = screenshot;
 
415
 
 
416
  if (screenshot_config->copy_to_clipboard)
 
417
    {
 
418
      screenshot_save_to_clipboard (self);
 
419
      screenshot_play_sound_effect ("screen-capture", _("Screenshot taken"));
 
420
 
 
421
      g_application_release (G_APPLICATION (self));
 
422
 
 
423
      return;
 
424
    }
 
425
 
 
426
  /* FIXME: apply the ICC profile according to the preferences.
 
427
   * org.gnome.ColorManager.GetProfileForWindow() does not exist anymore,
 
428
   * so we probably need to fetch the color profile of the screen where
 
429
   * the area/window was.
 
430
   *
 
431
   * screenshot_ensure_icc_profile (window);
 
432
   */
 
433
  screenshot_build_filename_async (build_filename_ready_cb, self);
 
434
}
 
435
 
 
436
static void
 
437
rectangle_found_cb (GdkRectangle *rectangle,
 
438
                    gpointer user_data)
 
439
{
 
440
  ScreenshotApplication *self = user_data;
 
441
 
 
442
  if (rectangle != NULL)
 
443
    finish_prepare_screenshot (self, rectangle);
 
444
  else
 
445
    /* user dismissed the rectangle with Esc, no error; just quit */
 
446
    g_application_release (G_APPLICATION (self));
 
447
}
 
448
 
 
449
static gboolean
 
450
prepare_screenshot_timeout (gpointer user_data)
 
451
{
 
452
  ScreenshotApplication *self = user_data;
 
453
 
 
454
  if (screenshot_config->take_area_shot)
 
455
    screenshot_select_area_async (rectangle_found_cb, self);
 
456
  else
 
457
    finish_prepare_screenshot (self, NULL);
 
458
 
 
459
  screenshot_save_config ();
 
460
 
 
461
  return FALSE;
 
462
}
 
463
 
 
464
static void
 
465
screenshot_start (ScreenshotApplication *self)
 
466
{
 
467
  guint delay = screenshot_config->delay * 1000;
 
468
 
 
469
  /* hold the GApplication while doing the async screenshot op */
 
470
  g_application_hold (G_APPLICATION (self));
 
471
 
 
472
  /* HACK: give time to the dialog to actually disappear.
 
473
   * We don't have any way to tell when the compositor has finished 
 
474
   * re-drawing.
 
475
   */
 
476
  if (delay == 0 && screenshot_config->interactive)
 
477
    delay = 200;
 
478
 
 
479
  if (delay > 0)
 
480
    g_timeout_add (delay,
 
481
                   prepare_screenshot_timeout,
 
482
                   self);
 
483
  else
 
484
    g_idle_add (prepare_screenshot_timeout, self);
 
485
}
 
486
 
 
487
static gboolean
 
488
screenshot_application_local_command_line (GApplication *app,
 
489
                                           gchar ***arguments,
 
490
                                           gint *exit_status)
 
491
{
 
492
  gboolean clipboard_arg = FALSE;
 
493
  gboolean window_arg = FALSE;
 
494
  gboolean area_arg = FALSE;
 
495
  gboolean include_border_arg = FALSE;
 
496
  gboolean disable_border_arg = FALSE;
 
497
  gboolean interactive_arg = FALSE;
 
498
  gchar *border_effect_arg = NULL;
 
499
  guint delay_arg = 0;
 
500
  const GOptionEntry entries[] = {
 
501
    { "clipboard", 'c', 0, G_OPTION_ARG_NONE, &clipboard_arg, N_("Send the grab directly to the clipboard"), NULL },
 
502
    { "window", 'w', 0, G_OPTION_ARG_NONE, &window_arg, N_("Grab a window instead of the entire screen"), NULL },
 
503
    { "area", 'a', 0, G_OPTION_ARG_NONE, &area_arg, N_("Grab an area of the screen instead of the entire screen"), NULL },
 
504
    { "include-border", 'b', 0, G_OPTION_ARG_NONE, &include_border_arg, N_("Include the window border with the screenshot"), NULL },
 
505
    { "remove-border", 'B', 0, G_OPTION_ARG_NONE, &disable_border_arg, N_("Remove the window border from the screenshot"), NULL },
 
506
    { "delay", 'd', 0, G_OPTION_ARG_INT, &delay_arg, N_("Take screenshot after specified delay [in seconds]"), N_("seconds") },
 
507
    { "border-effect", 'e', 0, G_OPTION_ARG_STRING, &border_effect_arg, N_("Effect to add to the border (shadow, border or none)"), N_("effect") },
 
508
    { "interactive", 'i', 0, G_OPTION_ARG_NONE, &interactive_arg, N_("Interactively set options"), NULL },
 
509
    { NULL },
 
510
  };
 
511
 
 
512
  GOptionContext *context;
 
513
  GError *error = NULL;
 
514
  gint argc = 0;
 
515
  gchar **argv = NULL;
 
516
  gboolean res;
 
517
 
 
518
  *exit_status = EXIT_SUCCESS;
 
519
  argv = *arguments;
 
520
  argc = g_strv_length (argv);
 
521
 
 
522
  context = g_option_context_new (_("Take a picture of the screen"));
 
523
  g_option_context_add_main_entries (context, entries, NULL);
 
524
  g_option_context_add_group (context, gtk_get_option_group (TRUE));
 
525
 
 
526
  if (!g_option_context_parse (context, &argc, &argv, &error))
 
527
    {
 
528
      g_critical ("Unable to parse arguments: %s", error->message);
 
529
      g_error_free (error);
 
530
 
 
531
      *exit_status = EXIT_FAILURE;
 
532
      goto out;
 
533
    }
 
534
 
 
535
  res = screenshot_load_config (clipboard_arg,
 
536
                                window_arg,
 
537
                                area_arg,
 
538
                                include_border_arg,
 
539
                                disable_border_arg,
 
540
                                border_effect_arg,
 
541
                                delay_arg,
 
542
                                interactive_arg);
 
543
 
 
544
  if (!res)
 
545
    {
 
546
      *exit_status = EXIT_FAILURE;
 
547
      goto out;
 
548
    }
 
549
 
 
550
  if (!g_application_register (app, NULL, &error)) 
 
551
    {
 
552
      g_printerr ("Could not register the application: %s\n", error->message);
 
553
      g_error_free (error);
 
554
 
 
555
      *exit_status = EXIT_FAILURE;
 
556
    }
 
557
 
 
558
 out:
 
559
  g_option_context_free (context);
 
560
 
 
561
  return TRUE;  
 
562
}
 
563
 
 
564
static void
 
565
register_screenshooter_icon (GtkIconFactory * factory)
 
566
{
 
567
  GtkIconSource *source;
 
568
  GtkIconSet *icon_set;
 
569
 
 
570
  source = gtk_icon_source_new ();
 
571
  gtk_icon_source_set_icon_name (source, SCREENSHOOTER_ICON);
 
572
 
 
573
  icon_set = gtk_icon_set_new ();
 
574
  gtk_icon_set_add_source (icon_set, source);
 
575
 
 
576
  gtk_icon_factory_add (factory, SCREENSHOOTER_ICON, icon_set);
 
577
  gtk_icon_set_unref (icon_set);
 
578
  gtk_icon_source_free (source);
 
579
}
 
580
 
 
581
static void
 
582
screenshooter_init_stock_icons (void)
 
583
{
 
584
  GtkIconFactory *factory;
 
585
 
 
586
  factory = gtk_icon_factory_new ();
 
587
  gtk_icon_factory_add_default (factory);
 
588
 
 
589
  register_screenshooter_icon (factory);
 
590
  g_object_unref (factory);
 
591
}
 
592
 
 
593
static void
 
594
interactive_dialog_response_cb (GtkWidget *d,
 
595
                                gint response,
 
596
                                gpointer user_data)
 
597
{
 
598
  ScreenshotApplication *self = user_data;
 
599
 
 
600
  gtk_widget_destroy (d);
 
601
 
 
602
  switch (response)
 
603
    {
 
604
    case GTK_RESPONSE_DELETE_EVENT:
 
605
    case GTK_RESPONSE_CANCEL:
 
606
      break;
 
607
    case GTK_RESPONSE_OK:
 
608
      screenshot_start (self);
 
609
      break;
 
610
    default:
 
611
      g_assert_not_reached ();
 
612
      break;
 
613
    }
 
614
}
 
615
 
 
616
static ScreenshotApplication *
 
617
get_singleton (void)
 
618
{
 
619
  if (_app_singleton == NULL)
 
620
    _app_singleton = g_object_new (SCREENSHOT_TYPE_APPLICATION, 
 
621
                                   "application-id", "org.gnome.Screenshot",
 
622
                                   NULL);
 
623
 
 
624
  return _app_singleton;
 
625
}
 
626
 
 
627
static void
 
628
screenshot_application_startup (GApplication *app)
 
629
{
 
630
  ScreenshotApplication *self = SCREENSHOT_APPLICATION (app);
 
631
  GError *error = NULL;
 
632
 
 
633
  G_APPLICATION_CLASS (screenshot_application_parent_class)->startup (app);
 
634
 
 
635
  gtk_window_set_default_icon_name (SCREENSHOOTER_ICON);
 
636
  screenshooter_init_stock_icons ();
 
637
 
 
638
  self->priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 
639
 
 
640
  if (error != NULL)
 
641
    {
 
642
      g_critical ("Unable to connect to the session bus: %s",
 
643
                  error->message);
 
644
      g_error_free (error);
 
645
 
 
646
      return;
 
647
    }
 
648
 
 
649
  /* interactive mode: trigger the dialog and wait for the response */
 
650
  if (screenshot_config->interactive)
 
651
    {
 
652
      GtkWidget *dialog;
 
653
 
 
654
      dialog = screenshot_interactive_dialog_new ();
 
655
      gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (dialog));
 
656
      gtk_widget_show (dialog);
 
657
      g_signal_connect (dialog, "response",
 
658
                        G_CALLBACK (interactive_dialog_response_cb), self);
 
659
    }
 
660
  else
 
661
    {
 
662
      screenshot_start (self);
 
663
    }
 
664
}
 
665
 
 
666
static void
 
667
screenshot_application_finalize (GObject *object)
 
668
{
 
669
  ScreenshotApplication *self = SCREENSHOT_APPLICATION (object);
 
670
 
 
671
  g_clear_object (&self->priv->connection);
 
672
  g_clear_object (&self->priv->screenshot);
 
673
  g_free (self->priv->icc_profile_base64);
 
674
  g_free (self->priv->save_uri);
 
675
 
 
676
  G_OBJECT_CLASS (screenshot_application_parent_class)->finalize (object);
 
677
}
 
678
 
 
679
static void
 
680
screenshot_application_class_init (ScreenshotApplicationClass *klass)
 
681
{
 
682
  GObjectClass *oclass = G_OBJECT_CLASS (klass);
 
683
  GApplicationClass *aclass = G_APPLICATION_CLASS (klass);
 
684
 
 
685
  oclass->finalize = screenshot_application_finalize;
 
686
 
 
687
  aclass->local_command_line = screenshot_application_local_command_line;
 
688
  aclass->startup = screenshot_application_startup;
 
689
 
 
690
  g_type_class_add_private (klass, sizeof (ScreenshotApplicationPriv));
 
691
}
 
692
 
 
693
static void
 
694
screenshot_application_init (ScreenshotApplication *self)
 
695
{
 
696
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SCREENSHOT_TYPE_APPLICATION,
 
697
                                            ScreenshotApplicationPriv);
 
698
}
 
699
 
 
700
GDBusConnection *
 
701
screenshot_application_get_session_bus (void)
 
702
{
 
703
  ScreenshotApplication *self = get_singleton ();
 
704
  return self->priv->connection;
 
705
}
 
706
 
 
707
ScreenshotApplication *
 
708
screenshot_application_get (void)
 
709
{
 
710
  return get_singleton ();
 
711
}