2008-07-11 09:40:09 +00:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-17 22:28:01 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2008-07-11 09:40:09 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-17 22:28:01 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2008-07-11 09:40:09 +00:00
|
|
|
* (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
|
2009-01-17 22:28:01 +00:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2008-07-11 09:40:09 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2012-05-16 22:58:18 +02:00
|
|
|
#include <gegl.h>
|
2008-07-13 19:49:32 +00:00
|
|
|
#include <gtk/gtk.h>
|
2008-07-11 09:40:09 +00:00
|
|
|
|
2008-07-11 12:40:41 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2012-05-16 22:58:18 +02:00
|
|
|
#ifdef GDK_WINDOWING_QUARTZ
|
|
|
|
#include <Carbon/Carbon.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#endif
|
|
|
|
|
2008-07-13 19:49:32 +00:00
|
|
|
#include "gui/gui-types.h"
|
2008-07-11 09:40:09 +00:00
|
|
|
|
|
|
|
#include "core/gimp.h"
|
2008-07-13 19:49:32 +00:00
|
|
|
#include "core/gimpcontainer.h"
|
2008-07-11 09:40:09 +00:00
|
|
|
|
2008-07-13 19:49:32 +00:00
|
|
|
#include "display/gimpdisplay.h"
|
2008-07-11 09:40:09 +00:00
|
|
|
|
2012-05-16 22:58:18 +02:00
|
|
|
#include "file/file-open.h"
|
|
|
|
|
2008-07-13 19:49:32 +00:00
|
|
|
#include "gimpdbusservice.h"
|
2008-07-11 09:40:09 +00:00
|
|
|
#include "gui-unique.h"
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef G_OS_WIN32
|
2013-05-24 23:25:47 +02:00
|
|
|
|
2008-10-17 12:03:08 +00:00
|
|
|
static void gui_unique_win32_init (Gimp *gimp);
|
|
|
|
static void gui_unique_win32_exit (void);
|
2008-07-11 10:31:27 +00:00
|
|
|
|
2013-05-24 23:25:47 +02:00
|
|
|
static Gimp *unique_gimp = NULL;
|
|
|
|
static HWND proxy_window = NULL;
|
|
|
|
|
2013-05-26 17:02:20 +02:00
|
|
|
#elif defined (GDK_WINDOWING_QUARTZ)
|
2008-07-11 09:40:09 +00:00
|
|
|
|
2012-05-16 22:58:18 +02:00
|
|
|
static void gui_unique_mac_init (Gimp *gimp);
|
|
|
|
static void gui_unique_mac_exit (void);
|
|
|
|
|
2013-05-24 23:25:47 +02:00
|
|
|
static Gimp *unique_gimp = NULL;
|
|
|
|
AEEventHandlerUPP open_document_callback_proc;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static void gui_dbus_service_init (Gimp *gimp);
|
|
|
|
static void gui_dbus_service_exit (void);
|
|
|
|
|
|
|
|
static GDBusObjectManagerServer *dbus_manager = NULL;
|
|
|
|
static guint dbus_name_id = 0;
|
|
|
|
|
2012-05-16 22:58:18 +02:00
|
|
|
#endif
|
|
|
|
|
2008-07-11 09:40:09 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
gui_unique_init (Gimp *gimp)
|
|
|
|
{
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
gui_unique_win32_init (gimp);
|
2013-05-26 17:02:20 +02:00
|
|
|
#elif defined (GDK_WINDOWING_QUARTZ)
|
2012-05-16 22:58:18 +02:00
|
|
|
gui_unique_mac_init (gimp);
|
2013-05-24 23:25:47 +02:00
|
|
|
#else
|
|
|
|
gui_dbus_service_init (gimp);
|
2012-05-16 22:58:18 +02:00
|
|
|
#endif
|
2008-07-11 09:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gui_unique_exit (void)
|
|
|
|
{
|
2008-09-10 19:25:54 +00:00
|
|
|
#ifdef G_OS_WIN32
|
2008-07-11 11:32:50 +00:00
|
|
|
gui_unique_win32_exit ();
|
2013-05-26 17:02:20 +02:00
|
|
|
#elif defined (GDK_WINDOWING_QUARTZ)
|
2012-05-16 22:58:18 +02:00
|
|
|
gui_unique_mac_exit ();
|
2013-05-24 23:25:47 +02:00
|
|
|
#else
|
|
|
|
gui_dbus_service_exit ();
|
2012-05-16 22:58:18 +02:00
|
|
|
#endif
|
2008-07-11 09:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
2008-07-11 13:56:07 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gchar *name;
|
|
|
|
gboolean as_new;
|
|
|
|
} IdleOpenData;
|
|
|
|
|
|
|
|
static IdleOpenData *
|
|
|
|
idle_open_data_new (const gchar *name,
|
2008-07-13 19:04:38 +00:00
|
|
|
gint len,
|
2008-09-10 20:01:45 +00:00
|
|
|
gboolean as_new)
|
2008-07-11 13:56:07 +00:00
|
|
|
{
|
2008-07-13 19:04:38 +00:00
|
|
|
IdleOpenData *data = g_slice_new0 (IdleOpenData);
|
2008-07-11 13:56:07 +00:00
|
|
|
|
2008-07-13 19:04:38 +00:00
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
data->name = g_strdup (name);
|
|
|
|
data->as_new = as_new;
|
|
|
|
}
|
2008-07-11 13:56:07 +00:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
idle_open_data_free (IdleOpenData *data)
|
|
|
|
{
|
|
|
|
g_free (data->name);
|
|
|
|
g_slice_free (IdleOpenData, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gui_unique_win32_idle_open (IdleOpenData *data)
|
|
|
|
{
|
2008-09-25 08:56:58 +00:00
|
|
|
/* We want to be called again later in case that GIMP is not fully
|
|
|
|
* started yet.
|
|
|
|
*/
|
|
|
|
if (! gimp_is_restored (unique_gimp))
|
|
|
|
return TRUE;
|
|
|
|
|
2008-07-13 19:04:38 +00:00
|
|
|
if (data->name)
|
|
|
|
{
|
|
|
|
file_open_from_command_line (unique_gimp, data->name, data->as_new);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-07-13 19:49:32 +00:00
|
|
|
/* raise the first display */
|
|
|
|
GimpObject *display;
|
2008-07-13 19:04:38 +00:00
|
|
|
|
2008-07-13 19:49:32 +00:00
|
|
|
display = gimp_container_get_first_child (unique_gimp->displays);
|
|
|
|
|
2009-10-04 19:56:39 +02:00
|
|
|
gimp_display_shell_present (gimp_display_get_shell (GIMP_DISPLAY (display)));
|
2008-07-13 19:04:38 +00:00
|
|
|
}
|
2008-07-11 13:56:07 +00:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-09-10 19:25:54 +00:00
|
|
|
static LRESULT CALLBACK
|
2008-07-11 10:31:27 +00:00
|
|
|
gui_unique_win32_message_handler (HWND hWnd,
|
2008-09-10 20:01:45 +00:00
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2008-07-11 10:31:27 +00:00
|
|
|
{
|
|
|
|
switch (uMsg)
|
|
|
|
{
|
|
|
|
case WM_COPYDATA:
|
2008-07-13 19:04:38 +00:00
|
|
|
if (unique_gimp)
|
|
|
|
{
|
|
|
|
COPYDATASTRUCT *copydata = (COPYDATASTRUCT *) lParam;
|
|
|
|
GSource *source;
|
|
|
|
GClosure *closure;
|
|
|
|
IdleOpenData *data;
|
|
|
|
|
|
|
|
data = idle_open_data_new (copydata->lpData,
|
|
|
|
copydata->cbData,
|
|
|
|
copydata->dwData != 0);
|
|
|
|
|
|
|
|
closure = g_cclosure_new (G_CALLBACK (gui_unique_win32_idle_open),
|
|
|
|
data,
|
|
|
|
(GClosureNotify) idle_open_data_free);
|
|
|
|
|
|
|
|
g_object_watch_closure (unique_gimp, closure);
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
2008-09-25 08:56:58 +00:00
|
|
|
g_source_set_priority (source, G_PRIORITY_LOW);
|
2008-07-13 19:04:38 +00:00
|
|
|
g_source_set_closure (source, closure);
|
|
|
|
g_source_attach (source, NULL);
|
|
|
|
g_source_unref (source);
|
|
|
|
}
|
2008-07-11 10:31:27 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return DefWindowProcW (hWnd, uMsg, wParam, lParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-11 09:40:09 +00:00
|
|
|
static void
|
|
|
|
gui_unique_win32_init (Gimp *gimp)
|
|
|
|
{
|
2008-07-11 10:31:27 +00:00
|
|
|
WNDCLASSW wc;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
g_return_if_fail (unique_gimp == NULL);
|
|
|
|
|
|
|
|
unique_gimp = gimp;
|
|
|
|
|
|
|
|
/* register window class for proxy window */
|
|
|
|
memset (&wc, 0, sizeof (wc));
|
2008-07-11 09:40:09 +00:00
|
|
|
|
2008-07-11 10:31:27 +00:00
|
|
|
wc.hInstance = GetModuleHandle (NULL);
|
|
|
|
wc.lpfnWndProc = gui_unique_win32_message_handler;
|
|
|
|
wc.lpszClassName = GIMP_UNIQUE_WIN32_WINDOW_CLASS;
|
|
|
|
|
|
|
|
RegisterClassW (&wc);
|
|
|
|
|
2008-09-10 20:00:53 +00:00
|
|
|
proxy_window = CreateWindowExW (0,
|
2008-09-10 20:01:45 +00:00
|
|
|
GIMP_UNIQUE_WIN32_WINDOW_CLASS,
|
|
|
|
GIMP_UNIQUE_WIN32_WINDOW_NAME,
|
|
|
|
WS_POPUP, 0, 0, 1, 1, NULL, NULL, wc.hInstance, NULL);
|
2008-07-11 10:31:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_unique_win32_exit (void)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (unique_gimp));
|
|
|
|
|
|
|
|
unique_gimp = NULL;
|
2008-09-10 20:00:53 +00:00
|
|
|
|
|
|
|
DestroyWindow (proxy_window);
|
2008-07-11 09:40:09 +00:00
|
|
|
}
|
|
|
|
|
2013-05-26 17:02:20 +02:00
|
|
|
#elif defined (GDK_WINDOWING_QUARTZ)
|
2012-05-16 22:58:18 +02:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gui_unique_mac_idle_open (gchar *data)
|
|
|
|
{
|
|
|
|
/* We want to be called again later in case that GIMP is not fully
|
|
|
|
* started yet.
|
|
|
|
*/
|
|
|
|
if (! gimp_is_restored (unique_gimp))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (data)
|
|
|
|
{
|
|
|
|
file_open_from_command_line (unique_gimp, data, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the kAEOpenDocuments Apple events. This will register
|
|
|
|
* an idle source callback for each filename in the event.
|
|
|
|
*/
|
|
|
|
static pascal OSErr
|
|
|
|
gui_unique_mac_open_documents (const AppleEvent *inAppleEvent,
|
|
|
|
AppleEvent *outAppleEvent,
|
|
|
|
long handlerRefcon)
|
|
|
|
{
|
|
|
|
OSStatus status;
|
|
|
|
AEDescList documents;
|
|
|
|
gchar path[MAXPATHLEN];
|
|
|
|
|
|
|
|
status = AEGetParamDesc (inAppleEvent,
|
|
|
|
keyDirectObject, typeAEList,
|
|
|
|
&documents);
|
|
|
|
if (status == noErr)
|
|
|
|
{
|
|
|
|
long count = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
AECountItems (&documents, &count);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
FSRef ref;
|
|
|
|
gchar *callback_path;
|
|
|
|
GSource *source;
|
|
|
|
GClosure *closure;
|
|
|
|
|
|
|
|
status = AEGetNthPtr (&documents, i + 1, typeFSRef,
|
|
|
|
0, 0, &ref, sizeof (ref),
|
|
|
|
0);
|
|
|
|
if (status != noErr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
FSRefMakePath (&ref, (UInt8 *) path, MAXPATHLEN);
|
|
|
|
|
|
|
|
callback_path = g_strdup (path);
|
|
|
|
|
|
|
|
closure = g_cclosure_new (G_CALLBACK (gui_unique_mac_idle_open),
|
|
|
|
(gpointer) callback_path,
|
|
|
|
(GClosureNotify) g_free);
|
|
|
|
|
|
|
|
g_object_watch_closure (G_OBJECT (unique_gimp), closure);
|
|
|
|
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
g_source_set_priority (source, G_PRIORITY_LOW);
|
|
|
|
g_source_set_closure (source, closure);
|
|
|
|
g_source_attach (source, NULL);
|
|
|
|
g_source_unref (source);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_unique_mac_init (Gimp *gimp)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
g_return_if_fail (unique_gimp == NULL);
|
|
|
|
|
|
|
|
unique_gimp = gimp;
|
|
|
|
|
|
|
|
open_document_callback_proc = NewAEEventHandlerUPP(gui_unique_mac_open_documents);
|
|
|
|
|
|
|
|
AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
|
|
|
|
open_document_callback_proc,
|
|
|
|
0L, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_unique_mac_exit (void)
|
|
|
|
{
|
|
|
|
unique_gimp = NULL;
|
|
|
|
|
|
|
|
AERemoveEventHandler (kCoreEventClass, kAEOpenDocuments,
|
|
|
|
open_document_callback_proc, TRUE);
|
|
|
|
|
|
|
|
DisposeAEEventHandlerUPP(open_document_callback_proc);
|
|
|
|
}
|
|
|
|
|
2013-05-24 23:25:47 +02:00
|
|
|
#else
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_dbus_bus_acquired (GDBusConnection *connection,
|
|
|
|
const gchar *name,
|
|
|
|
Gimp *gimp)
|
|
|
|
{
|
|
|
|
GDBusObjectSkeleton *object;
|
|
|
|
GObject *service;
|
|
|
|
|
|
|
|
/* this should use GIMP_DBUS_SERVICE_PATH, but that's historically wrong */
|
|
|
|
dbus_manager = g_dbus_object_manager_server_new ("/org/gimp/GIMP");
|
|
|
|
|
|
|
|
object = g_dbus_object_skeleton_new (GIMP_DBUS_INTERFACE_PATH);
|
|
|
|
|
|
|
|
service = gimp_dbus_service_new (gimp);
|
|
|
|
g_dbus_object_skeleton_add_interface (object,
|
|
|
|
G_DBUS_INTERFACE_SKELETON (service));
|
|
|
|
g_object_unref (service);
|
|
|
|
|
|
|
|
g_dbus_object_manager_server_export (dbus_manager, object);
|
|
|
|
g_object_unref (object);
|
|
|
|
|
|
|
|
g_dbus_object_manager_server_set_connection (dbus_manager, connection);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_dbus_name_acquired (GDBusConnection *connection,
|
|
|
|
const gchar *name,
|
|
|
|
Gimp *gimp)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_dbus_name_lost (GDBusConnection *connection,
|
|
|
|
const gchar *name,
|
|
|
|
Gimp *gimp)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_dbus_service_init (Gimp *gimp)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
g_return_if_fail (dbus_name_id == 0);
|
|
|
|
|
|
|
|
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
|
|
|
GIMP_DBUS_SERVICE_NAME,
|
|
|
|
G_BUS_NAME_OWNER_FLAGS_NONE,
|
|
|
|
(GBusAcquiredCallback) gui_dbus_bus_acquired,
|
|
|
|
(GBusNameAcquiredCallback) gui_dbus_name_acquired,
|
|
|
|
(GBusNameLostCallback) gui_dbus_name_lost,
|
|
|
|
gimp, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gui_dbus_service_exit (void)
|
|
|
|
{
|
|
|
|
g_bus_unown_name (dbus_name_id);
|
|
|
|
g_object_unref (dbus_manager);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|