diff options
author | Andrew Niefer | 2010-01-08 22:02:37 +0000 |
---|---|---|
committer | Andrew Niefer | 2010-01-08 22:02:37 +0000 |
commit | 7de7957a64f90ba63698335bcfcb196b85e2b5d8 (patch) | |
tree | 4d31d82808f5da0b913188b20d4ff4bc0ce44a7f /bundles | |
parent | e3d16d962c54d7d7849b10294b0da0b7ceb9536c (diff) | |
download | rt.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')
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(>k, 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" |