mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-23 04:51:44 +00:00
95cd081d13
2008-09-25 Sven Neumann <sven@gimp.org> * app/core/gimp.[ch]: added a 'restored' flag to the Gimp object and set it in gimp_real_restore(). Added method gimp_is_restored(). * app/gui/gui.c: call gui_unique_init() in gui_init() instead of that later in gui_restore_after_callback(). By doing so we start our DBus service (or message proxy window on Win32) much earlier in the start process, thus reducing the time frame where two instances of gimp can be launched. * app/gui/gui-unique.c * app/gui/gimpdbusservice.c: wait handling the queued file-open requests until gimp is fully restored. * app/gui/splash.c (splash_update): only run one iteration of the main loop. Doing it in a while loop can cause us to get stuck if the gimp-unique service already added an idle handler. svn path=/trunk/; revision=27049
269 lines
7.1 KiB
C
269 lines
7.1 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* GimpDBusService
|
|
* Copyright (C) 2007, 2008 Sven Neumann <sven@gimp.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#if HAVE_DBUS_GLIB
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <dbus/dbus-glib.h>
|
|
|
|
#include "gui-types.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpcontainer.h"
|
|
|
|
#include "file/file-open.h"
|
|
|
|
#include "display/gimpdisplay.h"
|
|
|
|
#include "gimpdbusservice.h"
|
|
#include "gimpdbusservice-glue.h"
|
|
|
|
|
|
typedef struct
|
|
{
|
|
gchar *uri;
|
|
gboolean as_new;
|
|
} OpenData;
|
|
|
|
|
|
static void gimp_dbus_service_class_init (GimpDBusServiceClass *klass);
|
|
|
|
static void gimp_dbus_service_init (GimpDBusService *service);
|
|
static void gimp_dbus_service_dispose (GObject *object);
|
|
static void gimp_dbus_service_finalize (GObject *object);
|
|
|
|
static gboolean gimp_dbus_service_queue_open (GimpDBusService *service,
|
|
const gchar *uri,
|
|
gboolean as_new);
|
|
|
|
static gboolean gimp_dbus_service_open_idle (GimpDBusService *service);
|
|
static OpenData * gimp_dbus_service_open_data_new (GimpDBusService *service,
|
|
const gchar *uri,
|
|
gboolean as_new);
|
|
static void gimp_dbus_service_open_data_free (OpenData *data);
|
|
|
|
|
|
G_DEFINE_TYPE (GimpDBusService, gimp_dbus_service, G_TYPE_OBJECT)
|
|
|
|
#define parent_class gimp_dbus_service_parent_class
|
|
|
|
|
|
static void
|
|
gimp_dbus_service_class_init (GimpDBusServiceClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->dispose = gimp_dbus_service_dispose;
|
|
object_class->finalize = gimp_dbus_service_finalize;
|
|
|
|
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
|
|
&dbus_glib_gimp_object_info);
|
|
}
|
|
|
|
static void
|
|
gimp_dbus_service_init (GimpDBusService *service)
|
|
{
|
|
service->queue = g_queue_new ();
|
|
}
|
|
|
|
GObject *
|
|
gimp_dbus_service_new (Gimp *gimp)
|
|
{
|
|
GimpDBusService *service;
|
|
|
|
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
|
|
|
|
service = g_object_new (GIMP_TYPE_DBUS_SERVICE, NULL);
|
|
|
|
service->gimp = gimp;
|
|
|
|
return G_OBJECT (service);
|
|
}
|
|
|
|
static void
|
|
gimp_dbus_service_dispose (GObject *object)
|
|
{
|
|
GimpDBusService *service = GIMP_DBUS_SERVICE (object);
|
|
|
|
if (service->source)
|
|
{
|
|
g_source_remove (g_source_get_id (service->source));
|
|
service->source = NULL;
|
|
}
|
|
|
|
while (! g_queue_is_empty (service->queue))
|
|
{
|
|
gimp_dbus_service_open_data_free (g_queue_pop_head (service->queue));
|
|
}
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gimp_dbus_service_finalize (GObject *object)
|
|
{
|
|
GimpDBusService *service = GIMP_DBUS_SERVICE (object);
|
|
|
|
if (service->queue)
|
|
{
|
|
g_queue_free (service->queue);
|
|
service->queue = NULL;
|
|
}
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
gboolean
|
|
gimp_dbus_service_open (GimpDBusService *service,
|
|
const gchar *uri,
|
|
gboolean *success,
|
|
GError **dbus_error)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_DBUS_SERVICE (service), FALSE);
|
|
g_return_val_if_fail (uri != NULL, FALSE);
|
|
g_return_val_if_fail (success != NULL, FALSE);
|
|
|
|
*success = gimp_dbus_service_queue_open (service, uri, FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gimp_dbus_service_open_as_new (GimpDBusService *service,
|
|
const gchar *uri,
|
|
gboolean *success,
|
|
GError **dbus_error)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_DBUS_SERVICE (service), FALSE);
|
|
g_return_val_if_fail (uri != NULL, FALSE);
|
|
g_return_val_if_fail (success != NULL, FALSE);
|
|
|
|
*success = gimp_dbus_service_queue_open (service, uri, TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gimp_dbus_service_activate (GimpDBusService *service,
|
|
GError **dbus_error)
|
|
{
|
|
GimpObject *display;
|
|
|
|
g_return_val_if_fail (GIMP_IS_DBUS_SERVICE (service), FALSE);
|
|
|
|
/* We want to be called again later in case that GIMP is not fully
|
|
* started yet.
|
|
*/
|
|
if (! gimp_is_restored (service->gimp))
|
|
return TRUE;
|
|
|
|
display = gimp_container_get_first_child (service->gimp->displays);
|
|
|
|
if (display)
|
|
gtk_window_present (GTK_WINDOW (GIMP_DISPLAY (display)->shell));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Adds a request to open a file to the end of the queue and
|
|
* starts an idle source if it is not already running.
|
|
*/
|
|
static gboolean
|
|
gimp_dbus_service_queue_open (GimpDBusService *service,
|
|
const gchar *uri,
|
|
gboolean as_new)
|
|
{
|
|
g_queue_push_tail (service->queue,
|
|
gimp_dbus_service_open_data_new (service, uri, as_new));
|
|
|
|
if (! service->source)
|
|
{
|
|
service->source = g_idle_source_new ();
|
|
|
|
g_source_set_priority (service->source, G_PRIORITY_LOW);
|
|
g_source_set_callback (service->source,
|
|
(GSourceFunc) gimp_dbus_service_open_idle, service,
|
|
NULL);
|
|
g_source_attach (service->source, NULL);
|
|
g_source_unref (service->source);
|
|
}
|
|
|
|
/* The call always succeeds as it is handled in one way or another.
|
|
* Even presenting an error message is considered success ;-)
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Idle callback that removes the first request from the queue and
|
|
* handles it. If there are no more requests, the idle source is
|
|
* removed.
|
|
*/
|
|
static gboolean
|
|
gimp_dbus_service_open_idle (GimpDBusService *service)
|
|
{
|
|
OpenData *data;
|
|
|
|
if (! service->gimp->restored)
|
|
return TRUE;
|
|
|
|
data = g_queue_pop_tail (service->queue);
|
|
|
|
if (data)
|
|
{
|
|
file_open_from_command_line (service->gimp, data->uri, data->as_new);
|
|
|
|
gimp_dbus_service_open_data_free (data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
service->source = NULL;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static OpenData *
|
|
gimp_dbus_service_open_data_new (GimpDBusService *service,
|
|
const gchar *uri,
|
|
gboolean as_new)
|
|
{
|
|
OpenData *data = g_slice_new (OpenData);
|
|
|
|
data->uri = g_strdup (uri);
|
|
data->as_new = as_new;
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
gimp_dbus_service_open_data_free (OpenData *data)
|
|
{
|
|
g_free (data->uri);
|
|
g_slice_free (OpenData, data);
|
|
}
|
|
|
|
|
|
#endif /* HAVE_DBUS_GLIB */
|