Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Niefer2010-01-08 22:02:37 +0000
committerAndrew Niefer2010-01-08 22:02:37 +0000
commit7de7957a64f90ba63698335bcfcb196b85e2b5d8 (patch)
tree4d31d82808f5da0b913188b20d4ff4bc0ce44a7f /bundles/org.eclipse.equinox.executable
parente3d16d962c54d7d7849b10294b0da0b7ceb9536c (diff)
downloadrt.equinox.framework-7de7957a64f90ba63698335bcfcb196b85e2b5d8.tar.gz
rt.equinox.framework-7de7957a64f90ba63698335bcfcb196b85e2b5d8.tar.xz
rt.equinox.framework-7de7957a64f90ba63698335bcfcb196b85e2b5d8.zip
bug 178927 - way to pass arguments from launcher to a running application instance
Diffstat (limited to 'bundles/org.eclipse.equinox.executable')
-rw-r--r--bundles/org.eclipse.equinox.executable/library/carbon/eclipseCarbon.c145
-rw-r--r--bundles/org.eclipse.equinox.executable/library/eclipse.c19
-rw-r--r--bundles/org.eclipse.equinox.executable/library/eclipseOS.h2
-rw-r--r--bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.c177
-rw-r--r--bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.h16
-rw-r--r--bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtkInit.c18
-rw-r--r--bundles/org.eclipse.equinox.executable/library/gtk/make_linux.mak4
-rw-r--r--bundles/org.eclipse.equinox.executable/library/gtk/make_solaris.mak2
-rw-r--r--bundles/org.eclipse.equinox.executable/library/make_version.mak2
-rw-r--r--bundles/org.eclipse.equinox.executable/library/motif/eclipseMotif.c6
-rw-r--r--bundles/org.eclipse.equinox.executable/library/win32/eclipseWin.c103
-rw-r--r--bundles/org.eclipse.equinox.executable/library/wpf/eclipseWpf.cpp4
12 files changed, 493 insertions, 5 deletions
diff --git a/bundles/org.eclipse.equinox.executable/library/carbon/eclipseCarbon.c b/bundles/org.eclipse.equinox.executable/library/carbon/eclipseCarbon.c
index e7dab0988..4dda540bf 100644
--- a/bundles/org.eclipse.equinox.executable/library/carbon/eclipseCarbon.c
+++ b/bundles/org.eclipse.equinox.executable/library/carbon/eclipseCarbon.c
@@ -99,17 +99,81 @@ static NSWindow* window = nil;
}
@end
+
+@interface AppleEventDelegate : NSObject
+- (void)handleOpenDocuments:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+@end
+@implementation AppleEventDelegate
+ NSTimer *timer;
+ NSMutableArray *files;
+
+- (void)handleOpenDocuments:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ int count = [event numberOfItems];
+ int index = 1;
+
+ if (!files) {
+ files = [NSMutableArray arrayWithCapacity:count];
+ [files retain];
+ }
+
+ for (index = 1; index<=count; index++) {
+ NSAppleEventDescriptor *desc = [event descriptorAtIndex:index];
+ if (desc) {
+ desc = [desc coerceToDescriptorType:typeFSRef];
+ CFURLRef url = CFURLCreateFromFSRef(kCFAllocatorDefault, [[desc data] bytes]);
+ if (url) {
+ NSString *pathName = (NSString *)CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ [files addObject:pathName];
+ [pathName release];
+ CFRelease(url);
+ }
+ }
+ }
+
+ if (!timer) {
+ timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
+ target: self
+ selector: @selector(handleTimer:)
+ userInfo: nil
+ repeats: YES];
+ }
+ [pool release];
+}
+- (void) handleTimer: (NSTimer *) timer {
+ NSObject *delegate = [[NSApplication sharedApplication] delegate];
+ if (delegate != NULL && [delegate respondsToSelector: @selector(application:openFiles:)]) {
+ [delegate performSelector:@selector(application:openFiles:) withObject:[NSApplication sharedApplication] withObject:files];
+ [files release];
+ [timer invalidate];
+ }
+}
+@end
#endif
static CFRunLoopRef loopRef = NULL;
static void * startThread(void * init);
static void runEventLoop(CFRunLoopRef ref);
static void dummyCallback(void * info) {}
+#ifndef COCOA
+static CFMutableArrayRef files;
+static EventHandlerRef appHandler;
+static int SWT_CLASS = 'SWT-';
+static int SWT_OPEN_FILE_KIND = 1;
+static int SWT_OPEN_FILE_PARAM = 'odoc';
+#endif
int main() {
return -1;
}
+void installAppleEventHandler();
+
+int reuseWorkbench(_TCHAR* filePath, int timeout) {
+ installAppleEventHandler();
+ return 0;
+}
+
#ifdef COCOA
/* Show the Splash Window
@@ -175,6 +239,8 @@ typedef CGImageRef (*CGImageSourceCreateImageAtIndex_FUNC)(CGImageSourceRef, siz
static CGImageSourceCreateWithURL_FUNC createWithURL = NULL;
static CGImageSourceCreateImageAtIndex_FUNC createAtIndex = NULL;
+static pascal OSErr openDocumentsProc(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
+
static OSStatus drawProc (EventHandlerCallRef eventHandlerCallRef, EventRef eventRef, void * data) {
int result = CallNextEventHandler(eventHandlerCallRef, eventRef);
if (image) {
@@ -209,6 +275,66 @@ void loadImageFns()
}
}
+static OSStatus appleEventProc(EventHandlerCallRef inCaller, EventRef theEvent, void* inRefcon) {
+ EventRecord eventRecord;
+ Boolean release = false;
+ EventQueueRef queue;
+
+ queue = GetCurrentEventQueue();
+ if (IsEventInQueue (queue, theEvent)) {
+ RetainEvent (theEvent);
+ release = true;
+ RemoveEventFromQueue (queue, theEvent);
+ }
+ ConvertEventRefToEventRecord (theEvent, &eventRecord);
+ AEProcessAppleEvent (&eventRecord);
+ if (release) ReleaseEvent (theEvent);
+ return noErr;
+}
+
+static void timerProc(EventLoopTimerRef timer, void *userData) {
+ EventTargetRef target = GetApplicationEventTarget();
+ CFIndex count = CFArrayGetCount (files);
+ int i;
+ for (i=0; i<count; i++) {
+ CFStringRef file = (CFStringRef) CFArrayGetValueAtIndex(files, i);
+ EventRef event = NULL;
+ CreateEvent (NULL, SWT_CLASS, SWT_OPEN_FILE_KIND, 0, kEventAttributeNone, &event);
+ SetEventParameter (event, SWT_OPEN_FILE_PARAM, typeCFStringRef, sizeof(file), &file);
+ OSStatus status = SendEventToEventTarget(event, target);
+ ReleaseEvent(event);
+ if (status == eventNotHandledErr) return;
+ }
+ CFRelease(files);
+ RemoveEventLoopTimer(timer);
+ RemoveEventHandler(appHandler);
+ AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(openDocumentsProc), false);
+}
+
+static pascal OSErr openDocumentsProc(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon) {
+ AEDescList docList;
+ FSRef theFSRef;
+ long index;
+ long count = 0;
+
+ AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
+ AECountItems(&docList, &count);
+ for(index = 1; index <= count; index++) {
+ AEGetNthPtr(&docList, index, typeFSRef, NULL, NULL, &theFSRef, sizeof(FSRef), NULL);
+ CFURLRef url = CFURLCreateFromFSRef(kCFAllocatorDefault, &theFSRef);
+ CFStringRef pathName = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ if (!files) {
+ files = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
+ InstallEventLoopTimer(GetMainEventLoop(), 1, 1, NewEventLoopTimerUPP(timerProc), NULL, NULL);
+ }
+ CFArrayAppendValue(files, pathName);
+ CFRelease(pathName);
+ CFRelease(url);
+ }
+ AEDisposeDesc(&docList);
+ return noErr;
+}
+
/* Show the Splash Window
*
* Create the splash window, load the bitmap and display the splash window.
@@ -305,6 +431,25 @@ void dispatchMessages() {
}
#endif
+void installAppleEventHandler() {
+#ifdef COCOA
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ AppleEventDelegate *appleEventDelegate = [[AppleEventDelegate alloc] init];
+ [NSApplication sharedApplication];
+ NSAppleEventManager *manager = [NSAppleEventManager sharedAppleEventManager];
+ [manager setEventHandler:appleEventDelegate
+ andSelector:@selector(handleOpenDocuments:withReplyEvent:)
+ forEventClass:kCoreEventClass
+ andEventID:kAEOpenDocuments];
+// [appleEventDelegate release];
+ [pool release];
+#else
+ EventTypeSpec kEvents[] = { {kEventClassAppleEvent, kEventAppleEvent} };
+ InstallApplicationEventHandler(NewEventHandlerUPP(appleEventProc), GetEventTypeCount(kEvents), kEvents, 0, &appHandler);
+ AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(openDocumentsProc), 0, false);
+#endif
+}
+
jlong getSplashHandle() {
return (jlong)window;
}
diff --git a/bundles/org.eclipse.equinox.executable/library/eclipse.c b/bundles/org.eclipse.equinox.executable/library/eclipse.c
index 98a9d5d7b..61e99be5c 100644
--- a/bundles/org.eclipse.equinox.executable/library/eclipse.c
+++ b/bundles/org.eclipse.equinox.executable/library/eclipse.c
@@ -227,6 +227,8 @@ home directory.");
#define CLASSPATH _T_ECLIPSE("-classpath")
#define JAR _T_ECLIPSE("-jar")
+#define OPENFILE _T_ECLIPSE("--launcher.openFile")
+#define TIMEOUT _T_ECLIPSE("--launcher.timeout")
#define LIBRARY _T_ECLIPSE("--launcher.library")
#define SUPRESSERRORS _T_ECLIPSE("--launcher.suppressErrors")
#define INI _T_ECLIPSE("--launcher.ini")
@@ -257,6 +259,8 @@ static _TCHAR * startupArg = NULL; /* path of the startup.jar the user want
static _TCHAR* vmName = NULL; /* Java VM that the user wants to run */
static _TCHAR* name = NULL; /* program name */
static _TCHAR* permGen = NULL; /* perm gen size for sun */
+static _TCHAR* filePath = NULL; /* file to open */
+static _TCHAR* timeoutString = NULL; /* timeout value for opening a file */
/* variables for ee options */
static _TCHAR* eeExecutable = NULL;
@@ -301,6 +305,8 @@ static Option options[] = {
{ VM, &vmName, 0, 2 },
{ NAME, &name, 0, 2 },
{ PERM_GEN, &permGen, 0, 2 },
+ { OPENFILE, &filePath, 0, 2 },
+ { TIMEOUT, &timeoutString, 0, 2 },
{ WS, &wsArg, 0, 2 } };
static int optionsSize = (sizeof(options) / sizeof(options[0]));
@@ -371,6 +377,19 @@ JNIEXPORT int run(int argc, _TCHAR* argv[], _TCHAR* vmArgs[])
/* Initialize official program name */
officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName();
+ /* try to open the specified file in an already running eclipse */
+ /* on Mac we are only registering an event handler here, always do this */
+#ifndef MACOSX
+ if (filePath != NULL)
+#endif
+ {
+ int timeout = 60;
+ if (timeoutString != NULL)
+ _stscanf(timeoutString, _T_ECLIPSE("%d"), &timeout);
+ if (reuseWorkbench(filePath, timeout) > 0)
+ return 0;
+ }
+
#ifdef MACOSX
/* Most platforms, we will initialize the window system later before trying to do any
* graphics. On Mac, we need it initialized to get the dock icon properly, so always do
diff --git a/bundles/org.eclipse.equinox.executable/library/eclipseOS.h b/bundles/org.eclipse.equinox.executable/library/eclipseOS.h
index 5c81dfcb4..eeff21d05 100644
--- a/bundles/org.eclipse.equinox.executable/library/eclipseOS.h
+++ b/bundles/org.eclipse.equinox.executable/library/eclipseOS.h
@@ -115,5 +115,7 @@ extern int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib );
/* an array of paths that will need to be on the search path to load the vm shared library */
extern _TCHAR ** getVMLibrarySearchPath(_TCHAR * vmLibrary);
+extern int reuseWorkbench(_TCHAR* filePath, int timeout);
+
#endif /* ECLIPSE_OS_H */
diff --git a/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.c b/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.c
index 003ddd310..aa6db1db2 100644
--- a/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.c
+++ b/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.c
@@ -32,6 +32,8 @@
#include <stdlib.h>
#include <string.h>
#include <locale.h>
+#include <semaphore.h>
+#include <fcntl.h>
/* Global Variables */
char* defaultVM = "java";
@@ -47,10 +49,183 @@ static GtkWidget* shellHandle = 0;
static GdkPixbuf* pixbuf = 0;
static GtkWidget* image = 0;
+static sem_t* mutex;
+static Atom appWindowAtom, launcherWindowAtom;
+static char* openFilePath = NULL; /* the file we want to open */
+static int openFileTimeout = 60; /* number of seconds to wait before timeout */
+
+static struct sigaction quitAction;
+static struct sigaction intAction;
+
/* Local functions */
-static void log_handler(const gchar* domain, GLogLevelFlags flags, const gchar* msg, gpointer data) {
+static void catch_signal(int sig) {
+ //catch signals, free the lock, reinstall the original
+ //signal handlers and reraise the signal.
+ sem_post(mutex);
+ sem_close(mutex);
+ sigaction(SIGINT, &intAction, NULL);
+ sigaction(SIGQUIT, &intAction, NULL);
+ raise(sig);
+}
+
+typedef int (*LockFunc)();
+int executeWithLock(char *name, LockFunc func) {
+ int result = -1;
+ int lock = -1;
+ struct sigaction action;
+
+ mutex = sem_open(name, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 1);
+ if (mutex == SEM_FAILED) {
+ //create failed. Probably lock is already created so try opening the existing lock.
+ mutex = sem_open(name, 0);
+ }
+ if (mutex == SEM_FAILED)
+ return -1; //this is an error.
+
+ // install signal handler to free the lock if something bad happens.
+ // sem_t is not freed automatically when a process ends.
+ action.sa_handler = catch_signal;
+ sigaction(SIGINT, &action, &intAction);
+ sigaction(SIGQUIT, &action, &quitAction);
+
+ while ((lock = sem_trywait(mutex)) != 0) {
+ if (errno == EAGAIN) {
+ //couldn't acquire lock, sleep a bit and try again
+ sleep(1);
+ if (--openFileTimeout > 0)
+ continue;
+ }
+ break;
+ }
+
+ if (lock == 0)
+ result = func();
+
+ sem_post(mutex);
+ sem_close(mutex);
+
+ //reinstall the original signal handlers
+ sigaction(SIGINT, &intAction, NULL);
+ sigaction(SIGQUIT, &quitAction, NULL);
+ return result;
+}
+
+static void log_handler(const gchar* domain, GLogLevelFlags flags, const gchar* msg, gpointer data) {
/* nothing */
}
+
+/* Create the mutex name string, with optional suffix. Caller should free the memory when finished */
+static char * createMutexName(char * suffix) {
+ char * prefix = _T_ECLIPSE("SWT_Window_");
+ char * result = malloc((_tcslen(prefix) + _tcslen(getOfficialName()) + (suffix != NULL ? _tcslen(suffix) : 0) + 1) * sizeof(char));
+ if (suffix != NULL)
+ _stprintf(result, _T_ECLIPSE("%s%s%s"), prefix, getOfficialName(), suffix);
+ else
+ _stprintf(result, _T_ECLIPSE("%s%s"), prefix, getOfficialName());
+ return result;
+}
+
+static int setAppWindowPropertyFn() {
+ Window appWindow;
+ GdkWindow *propWindow;
+ GdkAtom propAtom;
+ char *propVal;
+
+ //Look for the SWT window. If it's there, set a property on it.
+ appWindow = gtk.XGetSelectionOwner(gtk_GDK_DISPLAY, appWindowAtom);
+ //appWindow = XGetSelectionOwner(GDK_DISPLAY(), appWindowAtom);
+ if (appWindow) {
+ propAtom = gtk.gdk_atom_intern("org.eclipse.swt.filePath.message", FALSE);
+ //append a colon delimiter in case more than one file gets appended to the app windows property.
+ propVal = malloc((_tcslen(openFilePath) + 2) * sizeof(char));
+ _stprintf(propVal, _T_ECLIPSE("%s%s"), openFilePath, ":");
+
+ propWindow = gtk.gdk_window_foreign_new(appWindow);
+ if (propWindow != NULL) {
+ gtk.gdk_property_change(propWindow, propAtom, propAtom, 8, GDK_PROP_MODE_APPEND, (guchar *) propVal, _tcslen(propVal));
+ free(propVal);
+ return 1;
+ } //else the window got destroyed between XGetSelectionOwner and here (?)
+ }
+ return 0;
+}
+
+/* set the Application window property by executing _setWindowPropertyFn within a semaphore */
+int setAppWindowProperty() {
+ int result;
+ char * mutexName = createMutexName(NULL);
+ result = executeWithLock(mutexName, setAppWindowPropertyFn);
+ gtk.XSync(gtk_GDK_DISPLAY, False);
+ free(mutexName);
+ return result;
+}
+
+/* timer callback function to call setAppWindowProperty */
+static gboolean setAppWindowTimerProc(gpointer data) {
+ //try to set the app window property. If unsuccessful return true to reschedule the timer.
+ openFileTimeout--;
+ return !setAppWindowProperty() && openFileTimeout > 0;
+}
+
+int createLauncherWindow() {
+ Window window, launcherWindow;
+ //check if a launcher window exists. If none exists, we know we are the first and we should be launching the app.
+ window = gtk.XGetSelectionOwner(gtk_GDK_DISPLAY, launcherWindowAtom);
+ if (window == 0) {
+ //create a launcher window that other processes can find.
+ launcherWindow = gtk.XCreateWindow(gtk_GDK_DISPLAY, gtk.XRootWindow(gtk_GDK_DISPLAY, gtk.XDefaultScreen(gtk_GDK_DISPLAY)), -10, -10, 1,
+ 1, 0, 0, InputOnly, CopyFromParent, (unsigned long) 0, (XSetWindowAttributes *) NULL);
+ //for some reason Set and Get are both necessary. Set alone does nothing.
+ gtk.XSetSelectionOwner(gtk_GDK_DISPLAY, launcherWindowAtom, launcherWindow, CurrentTime);
+ gtk.XGetSelectionOwner(gtk_GDK_DISPLAY, launcherWindowAtom);
+ //add a timeout to set the property on the apps window once the app is launched.
+ gtk.g_timeout_add(1000, setAppWindowTimerProc, 0);
+ return 0;
+ }
+ return 1;
+}
+
+int reuseWorkbench(char* filePath, int timeout) {
+ char *appName, *launcherName;
+ int result = 0;
+
+ if (initWindowSystem(&initialArgc, initialArgv, 1) != 0)
+ return -1;
+
+ openFileTimeout = timeout;
+ openFilePath = filePath;
+
+ //App name is defined in SWT as well. Values must be consistent.
+ appName = createMutexName(NULL);
+ appWindowAtom = gtk.XInternAtom(gtk_GDK_DISPLAY, appName, FALSE);
+ free(appName);
+
+ //check if app is already running. Just set property if it is.
+ if (setAppWindowProperty())
+ return 1;
+
+ /* app is not running, create a launcher window to act as a mutex so we don't need to keep the semaphore locked */
+ launcherName = createMutexName(_T_ECLIPSE("_Launcher"));
+ launcherWindowAtom = gtk.XInternAtom(gtk_GDK_DISPLAY, launcherName, FALSE);
+ result = executeWithLock(launcherName, createLauncherWindow);
+ free(launcherName);
+
+ if (result == 1) {
+ //The app is already being launched in another process. Set the property on that app window and exit
+ while (openFileTimeout > 0) {
+ if (setAppWindowProperty() > 0)
+ return 1; //success
+ else {
+ openFileTimeout--;
+ sleep(1);
+ }
+ }
+ //timed out trying to set the app property
+ result = 0;
+ }
+ return result;
+}
+
/* Create and Display the Splash Window */
int showSplash( const char* featureImage )
{
diff --git a/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.h b/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.h
index 280e6476b..c78ceaa38 100644
--- a/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.h
+++ b/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtk.h
@@ -13,6 +13,7 @@
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk/gdkx.h>
struct GTK_PTRS {
short not_initialized;
@@ -43,6 +44,8 @@ struct GTK_PTRS {
gboolean (*g_main_context_iteration) (GMainContext*, gboolean);
void (*g_object_unref) (gpointer);
GObject* (*g_object_new) (GType, const gchar*, ...);
+ guint (*g_timeout_add) (guint, GSourceFunc, gpointer);
+
#ifdef SOLARIS
GString* (*g_string_insert_c) (GString *, gssize, gchar);
#endif
@@ -51,8 +54,21 @@ struct GTK_PTRS {
int (*gdk_pixbuf_get_width) (const GdkPixbuf*);
int (*gdk_pixbuf_get_height) (const GdkPixbuf*);
void (*gdk_set_program_class) (const char*);
+ GdkWindow* (*gdk_window_foreign_new) (GdkNativeWindow);
+ void (*gdk_property_change) (GdkWindow*, GdkAtom, GdkAtom, gint, GdkPropMode, const guchar*, gint);
+ GdkAtom (*gdk_atom_intern) (const gchar*, gboolean);
+
+ Window (*XGetSelectionOwner) (Display*, Atom);
+ void (*XSetSelectionOwner) (Display*, Atom, Window, Time);
+ Window (*XCreateWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*);
+ void (*XSync) (Display*, Bool);
+ int (*XDefaultScreen) (Display*);
+ Window (*XRootWindow) (Display*, int);
+ Atom (*XInternAtom) (Display*, _Xconst char*, Bool );
+ Display **gdk_display;
};
+#define gtk_GDK_DISPLAY *(gtk.gdk_display)
extern struct GTK_PTRS gtk;
#define FN_TABLE_ENTRY(fn) { (void**)& gtk.fn, #fn }
diff --git a/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtkInit.c b/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtkInit.c
index bb09a2792..c6f888cd1 100644
--- a/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtkInit.c
+++ b/bundles/org.eclipse.equinox.executable/library/gtk/eclipseGtkInit.c
@@ -44,6 +44,10 @@ static FN_TABLE gtkFunctions[] = { FN_TABLE_ENTRY(gtk_adjustment_new),
};
/* functions from libgdk-x11-2.0 */
static FN_TABLE gdkFunctions[] = { FN_TABLE_ENTRY(gdk_set_program_class),
+ FN_TABLE_ENTRY(gdk_property_change),
+ FN_TABLE_ENTRY(gdk_atom_intern),
+ FN_TABLE_ENTRY(gdk_window_foreign_new),
+ FN_TABLE_ENTRY(gdk_display), /* not a function */
{ NULL, NULL }
};
/* functions from libgdk_pixbuf-2.0 */
@@ -57,12 +61,24 @@ static FN_TABLE gobjFunctions[] = { FN_TABLE_ENTRY(g_log_set_handler),
FN_TABLE_ENTRY(g_log_remove_handler),
FN_TABLE_ENTRY(g_main_context_iteration),
FN_TABLE_ENTRY(g_object_unref),
+ FN_TABLE_ENTRY(g_timeout_add),
#ifdef SOLARIS
FN_TABLE_ENTRY(g_string_insert_c),
#endif
{ NULL, NULL }
};
+/* functions from libX11 */
+static FN_TABLE x11Functions[] = { FN_TABLE_ENTRY(XGetSelectionOwner),
+ FN_TABLE_ENTRY(XSetSelectionOwner),
+ FN_TABLE_ENTRY(XCreateWindow),
+ FN_TABLE_ENTRY(XSync),
+ FN_TABLE_ENTRY(XRootWindow),
+ FN_TABLE_ENTRY(XDefaultScreen),
+ FN_TABLE_ENTRY(XInternAtom),
+ { NULL, NULL }
+ };
+
static int loadGtkSymbols( void * library, FN_TABLE * table) {
int i = 0;
@@ -82,6 +98,7 @@ int loadGtk() {
void * gdkLib = dlopen(GDK_LIB, RTLD_LAZY);
void * pixLib = dlopen(PIXBUF_LIB, RTLD_LAZY);
void * gtkLib = dlopen(GTK_LIB, RTLD_LAZY);
+ void * x11Lib = dlopen(X11_LIB, RTLD_LAZY);
/* initialize ptr struct to 0's */
memset(&gtk, 0, sizeof(struct GTK_PTRS));
@@ -90,6 +107,7 @@ int loadGtk() {
if ( gdkLib == NULL || loadGtkSymbols(gdkLib, gdkFunctions) != 0) return -1;
if ( pixLib == NULL || loadGtkSymbols(pixLib, pixFunctions) != 0) return -1;
if ( objLib == NULL || loadGtkSymbols(objLib, gobjFunctions) != 0) return -1;
+ if ( x11Lib == NULL || loadGtkSymbols(x11Lib, x11Functions) != 0) return -1;
return 0;
}
diff --git a/bundles/org.eclipse.equinox.executable/library/gtk/make_linux.mak b/bundles/org.eclipse.equinox.executable/library/gtk/make_linux.mak
index f7e6b9e57..b276cf814 100644
--- a/bundles/org.eclipse.equinox.executable/library/gtk/make_linux.mak
+++ b/bundles/org.eclipse.equinox.executable/library/gtk/make_linux.mak
@@ -41,9 +41,9 @@ DLL_OBJS = eclipse.o eclipseGtk.o eclipseUtil.o eclipseJNI.o eclipseMozilla.o ec
EXEC = $(PROGRAM_OUTPUT)
DLL = $(PROGRAM_LIBRARY)
-#LIBS = `pkg-config --libs-only-L gtk+-2.0` -lgtk-x11-2.0 -lgdk_pixbuf-2.0 -lgobject-2.0 -lgdk-x11-2.0 -lpthread -ldl
+#LIBS = `pkg-config --libs-only-L gtk+-2.0` -lgtk-x11-2.0 -lgdk_pixbuf-2.0 -lgobject-2.0 -lgdk-x11-2.0 -lpthread -ldl -lX11
LIBS = -lpthread -ldl
-GTK_LIBS = -DGTK_LIB="\"libgtk-x11-2.0.so.0\"" -DGDK_LIB="\"libgdk-x11-2.0.so.0\"" -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so.0\"" -DGOBJ_LIB="\"libgobject-2.0.so.0\""
+GTK_LIBS = -DGTK_LIB="\"libgtk-x11-2.0.so.0\"" -DGDK_LIB="\"libgdk-x11-2.0.so.0\"" -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so.0\"" -DGOBJ_LIB="\"libgobject-2.0.so.0\"" -DX11_LIB="\"libX11.so.6\""
LFLAGS = ${M_ARCH} -shared -fpic -Wl,--export-dynamic
CFLAGS = ${M_ARCH} -g -s -Wall\
-fpic \
diff --git a/bundles/org.eclipse.equinox.executable/library/gtk/make_solaris.mak b/bundles/org.eclipse.equinox.executable/library/gtk/make_solaris.mak
index 2833e20a2..39fd23f80 100644
--- a/bundles/org.eclipse.equinox.executable/library/gtk/make_solaris.mak
+++ b/bundles/org.eclipse.equinox.executable/library/gtk/make_solaris.mak
@@ -43,7 +43,7 @@ EXEC = $(PROGRAM_OUTPUT)
DLL = $(PROGRAM_LIBRARY)
#LIBS = `pkg-config --libs-only-L gtk+-2.0` -lgtk-x11-2.0 -lgdk_pixbuf-2.0 -lgobject-2.0 -lgdk-x11-2.0 -lglib-2.0 -lthread -ldl -lc
LIBS = -lthread -ldl -lc
-GTK_LIBS = -DGTK_LIB="\"libgtk-x11-2.0.so.0\"" -DGDK_LIB="\"libgdk-x11-2.0.so.0\"" -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so.0\"" -DGOBJ_LIB="\"libgobject-2.0.so.0\""
+GTK_LIBS = -DGTK_LIB="\"libgtk-x11-2.0.so.0\"" -DGDK_LIB="\"libgdk-x11-2.0.so.0\"" -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so.0\"" -DGOBJ_LIB="\"libgobject-2.0.so.0\"" -DX11_LIB="\"libX11.so.6\""
LFLAGS = -G
CFLAGS = $(OPTFLAG) \
-DSOLARIS \
diff --git a/bundles/org.eclipse.equinox.executable/library/make_version.mak b/bundles/org.eclipse.equinox.executable/library/make_version.mak
index b7b51d64c..9bb6eac17 100644
--- a/bundles/org.eclipse.equinox.executable/library/make_version.mak
+++ b/bundles/org.eclipse.equinox.executable/library/make_version.mak
@@ -10,5 +10,5 @@
#*******************************************************************************
maj_ver=1
-min_ver=304
+min_ver=305
LIB_VERSION = $(maj_ver)$(min_ver)
diff --git a/bundles/org.eclipse.equinox.executable/library/motif/eclipseMotif.c b/bundles/org.eclipse.equinox.executable/library/motif/eclipseMotif.c
index d69fa8a60..5762adb08 100644
--- a/bundles/org.eclipse.equinox.executable/library/motif/eclipseMotif.c
+++ b/bundles/org.eclipse.equinox.executable/library/motif/eclipseMotif.c
@@ -329,3 +329,9 @@ JavaResults* launchJavaVM( char* args[] )
/* Return the exit code from the JVM. */
return jvmResults;
}
+
+int reuseWorkbench(_TCHAR* filePath, int timeout) {
+ /* not yet implemented on motif */
+ return -1;
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.executable/library/win32/eclipseWin.c b/bundles/org.eclipse.equinox.executable/library/win32/eclipseWin.c
index 1c035ebed..bd17eb462 100644
--- a/bundles/org.eclipse.equinox.executable/library/win32/eclipseWin.c
+++ b/bundles/org.eclipse.equinox.executable/library/win32/eclipseWin.c
@@ -14,6 +14,7 @@
#include "eclipseUtil.h"
#include "eclipseCommon.h"
#include "eclipseJNI.h"
+#include "eclipseShm.h"
#include <windows.h>
#include <commctrl.h>
@@ -35,6 +36,14 @@ _TCHAR* consoleVM = _T("java.exe");
_TCHAR* vmLibrary = _T("jvm.dll");
_TCHAR* shippedVMDir = _T("jre\\bin\\");
+/* Define local variables for communicating with running eclipse instance. */
+static HANDLE mutex;
+static UINT findWindowTimeout = 1000;
+static UINT_PTR findWindowTimerId = 97;
+static UINT timerCount = 0;
+static UINT openFileTimeout = 60;
+static _TCHAR* openFilePath;
+
/* Define the window system arguments for the Java VM. */
static _TCHAR* argVM[] = { NULL };
@@ -44,6 +53,7 @@ static JavaResults* jvmResults = NULL;
static UINT jvmExitTimeout = 100;
static UINT_PTR jvmExitTimerId = 99;
+static void CALLBACK findWindowProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime);
static void CALLBACK detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime );
static _TCHAR* checkVMRegistryKey(HKEY jrekey, _TCHAR* subKeyName);
static void adjustSearchPath( _TCHAR * vmLibrary );
@@ -69,6 +79,99 @@ typedef struct {
#define COMPANY_NAME_KEY _T_ECLIPSE("\\StringFileInfo\\%04x%04x\\CompanyName")
#define SUN_MICROSYSTEMS _T_ECLIPSE("Sun Microsystems")
+static void sendOpenFileMessage(HWND window) {
+ _TCHAR* id;
+ UINT msg;
+ int size = (_tcslen(openFilePath) + 1) * sizeof(_TCHAR);
+ DWORD wParam;
+#ifdef WIN64
+ DWORDLONG lParam;
+#else
+ DWORD lParam;
+#endif
+ createSharedData(&id, size);
+ setSharedData(id, openFilePath);
+ msg = RegisterWindowMessage(_T("SWT_FILEOPEN"));
+ _stscanf(id, _T_ECLIPSE("%lx_%lx"), &wParam, &lParam);
+
+ /* SendMessage does not return until the message has been processed */
+ SendMessage(window, msg, wParam, lParam);
+ destroySharedData(id);
+}
+
+static HWND findSWTMessageWindow() {
+ HWND window = NULL;
+ _TCHAR *windowTitle, *windowPrefix, *name;
+
+ windowPrefix = _T("SWT_Window_");
+ name = getOfficialName();
+ windowTitle = malloc((_tcslen(windowPrefix) + _tcslen(name) + 1) * sizeof(_TCHAR));
+ _stprintf(windowTitle, _T_ECLIPSE("%s%s"), windowPrefix, name);
+ window = FindWindow(NULL, windowTitle);
+ free(windowTitle);
+ return window;
+}
+
+static void CALLBACK findWindowProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime) {
+ HWND window = findSWTMessageWindow();
+ if (window != NULL) {
+ sendOpenFileMessage(window);
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+ KillTimer(hwnd, findWindowTimerId);
+ return;
+ }
+
+ /* no window yet, set timer to try again later */
+ if (timerCount++ >= openFileTimeout) {
+ KillTimer(hwnd, findWindowTimerId);
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+ }
+}
+
+/* return > 0 if we successfully send a message to another eclipse instance */
+int reuseWorkbench(_TCHAR* filePath, int timeout) {
+ _TCHAR* mutexPrefix = _T("SWT_Mutex_");
+ _TCHAR* mutexName, *name;
+ DWORD lock;
+ HWND window = NULL;
+
+ /* store for later */
+ openFilePath = filePath;
+ openFileTimeout = timeout;
+
+ name = getOfficialName();
+ mutexName = malloc((_tcslen(mutexPrefix) + _tcslen(name) + 1) * sizeof(_TCHAR));
+ _stprintf(mutexName, _T_ECLIPSE("%s%s"), mutexPrefix, name);
+ mutex = CreateMutex(NULL, FALSE, mutexName);
+ free(mutexName);
+ if (mutex == NULL) return -1;
+
+ //wait for timeout seconds
+ lock = WaitForSingleObject(mutex, timeout * 1000);
+ if (lock != WAIT_OBJECT_0) {
+ /* failed to get the lock before timeout, We won't be reusing an existing eclipse. */
+ CloseHandle(mutex);
+ return 0;
+ }
+
+ /* we have the mutex, look for the SWT window */
+ window = findSWTMessageWindow();
+ if (window != NULL) {
+ sendOpenFileMessage(window);
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+ return 1; /* success! */
+ }
+
+ /* no window, set a timer to look again later */
+ if (initWindowSystem(0, NULL, 0) == 0)
+ SetTimer( topWindow, findWindowTimerId, findWindowTimeout, findWindowProc );
+
+ return 0;
+}
+
/* Show the Splash Window
*
* Open the bitmap, insert into the splash window and display it.
diff --git a/bundles/org.eclipse.equinox.executable/library/wpf/eclipseWpf.cpp b/bundles/org.eclipse.equinox.executable/library/wpf/eclipseWpf.cpp
index 6118bcbb9..f4878e35c 100644
--- a/bundles/org.eclipse.equinox.executable/library/wpf/eclipseWpf.cpp
+++ b/bundles/org.eclipse.equinox.executable/library/wpf/eclipseWpf.cpp
@@ -554,4 +554,8 @@ int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib ) {
return result;
}
+int reuseWorkbench(_TCHAR* filePath, int timeout) {
+ /* not implemented for WPF */
+ return -1;
+}
} // extern "C"

Back to the top