| Summary: | [SWT_AWT] Embedded SWT in AWT broken on Mac with Java 7 | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Christopher Deckers <chrriis> | ||||
| Component: | SWT | Assignee: | Platform-SWT-Inbox <platform-swt-inbox> | ||||
| Status: | CLOSED WONTFIX | QA Contact: | Lakshmi P Shanmugam <lshanmug> | ||||
| Severity: | blocker | ||||||
| Priority: | P3 | CC: | ahmadswaid, arunkumar.thondapu, christophe.cornu+eclipse, ciuste, dan.sonnemann, daniel_megert, djakone, egalvez, hcmc-up, joel.drigo, lethanhhoang705, lshanmug, mdaenzer, nikita, nvkaymanov, sandipsahoo789, Silenio_Quarti, snorthov, support, zandersmith | ||||
| Version: | 4.4 | Keywords: | helpwanted, triaged | ||||
| Target Milestone: | --- | ||||||
| Hardware: | Macintosh | ||||||
| OS: | Mac OS X | ||||||
| See Also: |
https://git.eclipse.org/r/155620 https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=30ad38d69b91bac02f587cec89b564c73a903bdb |
||||||
| Whiteboard: | |||||||
| Attachments: |
|
||||||
|
Description
Christopher Deckers
> final Shell shell = SWT_AWT.new_Shell(display, canvas_); My understanding is that this line no longer works starting with JDK1.7. AWT Team has apparently rewritten AWT on the Mac to use CALayer's and no more NSView's. As a result, Snippet337 fails with this stack trace on latest JDK1.8EA (click on AWT Button in snippet): JavaVM WARNING: JAWT_GetAWT must be called after loading a JVM Exception in thread "AppKit Thread" org.eclipse.swt.SWTException: Failed to execute runnable (java.lang.IllegalArgumentException: Argument not valid [peer not created]) at org.eclipse.swt.SWT.error(Unknown Source) at org.eclipse.swt.SWT.error(Unknown Source) at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Unknown Source) at org.eclipse.swt.widgets.Display.runAsyncMessages(Unknown Source) at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source) at Snippet337.main(Snippet337.java:77) Caused by: java.lang.IllegalArgumentException: Argument not valid [peer not created] at org.eclipse.swt.SWT.error(Unknown Source) at org.eclipse.swt.awt.SWT_AWT.new_Shell(Unknown Source) at Snippet337$1$1$1.run(Snippet337.java:43) at org.eclipse.swt.widgets.RunnableLock.run(Unknown Source) ... 4 more http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet337.java As you said, fix for bug 374199 is for a different scenario which was also broken by JDK1.7 on Mac. The patch allows us to run Snippet154 with JDK1.8EA. But AWT team reintroduced the functionality of CViewEmbeddedFrame backed by an NSView, but this doesn't address the issue of Canvas being now CALayer based. The rewrite of AWT on Mac has caused issues for other projects as well, and was discussed in a few places e.g. https://github.com/caprica/vlcj/issues/205 http://stackoverflow.com/questions/10584204/swt-browser-swing-integration-mac-jdk-1-7 A customer of ours needs a working browser in a swing component on macos with JRE 7 until end of june 2014. If we do not have a solution until june then we will need to use another solution omitting swt. In this issue I do not see a target milestone, so my question is obvious: Are there any plans how and when to proceed? Hi Mickael Danzer, I think you need to put SWT Browser component into SWING Component (as DJNative does) : this is the opposite of this problem, and fixed according to https://bugs.eclipse.org/bugs/show_bug.cgi?id=374199 (ie SWT R-4.3-201306052000) Like you, I couldn't wait the release of Eclipse RCP with this fixed SWT component, so I patched it in 3.8.2 myself. I started with the code on http://www.eclipse.org/articles/article.php?file=Article-Swing-SWT-Integration/index.html, then I patched the code according to https://bugs.eclipse.org/bugs/show_bug.cgi?id=374199. I added, in EmbeddedSwingComposite, a boolean constant, called MAC_PATCH (true means os.name is Mac OS X, and java.version starts with 1.7, or any other way to set the environment is OSX and Java7). I add this static block: private final static MAC_PATCH = System.getProperty("os.name").startsWith("Mac static { if ( MAC_PATCH ) { LOG.info("SWT_AWT Bridge: patching for Apple/Oracle MacOsX/JAVA7 bugs workaround" ); SWT_AWT.embeddedFrameClass="sun.lwawt.macosx.CViewEmbeddedFrame"; } } Then, I add the following code, after the frame creation: ... final Frame frame = SWT_AWT.new_Frame(this); // j'ai juste ajouté final à la ligne d'origine de createFrame if (MAC_PATCH) { // patch du bug tracker Eclipse 4.3.2 (<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=374199" target="_blank">https://bugs.eclipse.org/bugs/show_bug.cgi?id=374199</a>) final Composite parent = AbstractSWTSwingNGComposite.this; // When display is disposed the frame is disposed in AWT EventQueue. // Force main event loop to run to let the frame finish dispose. final Display display = parent.getDisplay(); display.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event event) { while (frame.isDisplayable() && !display.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } //Frame finished dispose, the listener can be removed if (!display.isDisposed()) { display.removeListener(SWT.Dispose, this); } } }); Listener listener = new Listener () { public void handleEvent (Event e) { switch (e.type) { case SWT.Dispose: getShell().removeListener (SWT.Activate, this); getShell().removeListener (SWT.FocusOut, this); break; case SWT.Activate: if (!parent.isFocusControl()) return; // case géré par l'implémentation de la classe parente : case SWT.FocusIn: EventQueue.invokeLater(new Runnable () { public void run () { if (frame.isActive()) return; try { Class clazz = frame.getClass(); Method method = clazz.getMethod("synthesizeWindowActivation", new Class[]{boolean.class}); if (method != null) method.invoke(frame, new Object[]{new Boolean(true)}); } catch (Throwable e) { LOG.error("SWT_AWT ERROR",e);} } } ); break; // case gérée par l'implémentation de la classe parente : case SWT.Deactivate: case SWT.FocusOut: EventQueue.invokeLater(new Runnable () { public void run () { if (!frame.isActive()) return; try { Class clazz = frame.getClass(); Method method = clazz.getMethod("synthesizeWindowActivation", new Class[]{boolean.class}); if (method != null) method.invoke(frame, new Object[]{new Boolean(false)}); } catch (Throwable e) { LOG.error("SWT_AWT ERROR",e); } } }); break; } } }; parent.addListener (SWT.Dispose, listener); parent.addListener (SWT.Activate, listener); parent.addListener (SWT.FocusOut, listener); // fin du patch du bug tracker Eclipse 4.3.2 // les lignes suivantes sont nécessaires pour que la gestion du focus fonctionne correctement !!! frame.setVisible(false); frame.setVisible(true); // autre partie reprise en partie du patch display.asyncExec(new Runnable() { @Override public void run() { if (parent.isDisposed()) return; final Rectangle clientArea = parent.getClientArea(); try { Method method = frame.getClass().getMethod("validateWithBounds", new Class[] {int.class, int.class, int.class, int.class}); if (method != null) method.invoke(frame, new Object[]{new Integer(clientArea.x), new Integer(clientArea.y), new Integer(clientArea.width), new Integer(clientArea.height)}); parent.setFocus(); if ( parent.isFocusControl() ) { // le validateWithBounds fait perdre le focus au composant SWT, ce qui fait perdre le focus au composant AWT // le fait de redonner le focus au compsant SWT ne redonne pas bizarrement le focus au composant AWT EventQueue.invokeLater(new Runnable () { public void run () { if (!frame.isActive()) return; // ce code redonne le focus à la frame AWT (un requestFocusInWindows est insuffisant, bizarrement try { Class clazz = frame.getClass(); Method method = clazz.getMethod("synthesizeWindowActivation", new Class[]{boolean.class}); if (method != null) method.invoke(frame, new Object[]{new Boolean(true)}); } catch (Throwable e) {LOG.error("SWT_AWT ERROR",e);} if ( awtContext.getSwingComponent()!=null ) { awtContext.getSwingComponent().requestFocusInWindow(); } } }); } } catch (Throwable e) { LOG.error("SWT_AWT ERROR",e); } } }); } awtContext = new AwtContext(frame); // ligne dans le code d'origine de createFrame ... This works fine on MacOSX Java 1.7 u51, except for the DND between AWT and SWT (see my bugtracker: https://bugs.eclipse.org/bugs/show_bug.cgi?id=428634). (In reply to Joël DRIGO from comment #3) Sorry, I made a mistake: my patch is for embedding AWT in SWT, not SWT in AWT. Please investigate for 4.4.1. I've investigated the issue. The problem happens with Oracle Java as it seems that AWT Canvas is no longer backed by a NSView. We should investigate further and see if we can find a way of embedding the shell NSView on a CALayer or something. We'll defer this for now and address it in 4.5. Between JDK6 and JDK7, the AWT implementation was changed to be lightweight and to use CALayers instead of NSViews as the underlying widget handle for AWT widgets. This meant that any native code that used NSViews and expected AWT to use NSViews was broken. There is no way to fix this easily. AWT would need to go back to NSViews (but it won't because the browser won't work) or SWT will need to go to CALayers (but it won't because native cocoa controls are all NSViews). It may be possible to fake up something by either toolkit creating an NSView to give to SWT but the results might not be pretty. (In reply to Steve Northover from comment #7) > Between JDK6 and JDK7, the AWT implementation was changed to be lightweight > and to use CALayers instead of NSViews as the underlying widget handle for > AWT widgets. This meant that any native code that used NSViews and expected > AWT to use NSViews was broken. > > There is no way to fix this easily. AWT would need to go back to NSViews > (but it won't because the browser won't work) or SWT will need to go to > CALayers (but it won't because native cocoa controls are all NSViews). > > It may be possible to fake up something by either toolkit creating an NSView > to give to SWT but the results might not be pretty. This is outside the capacity of the SWT team. Unless someone from the community steps up, we have to drop the support for that feature. Agree. It has been broken since JDK7 which is quite a long time. That's not a excuse, but it indicates that people have been able to function without this feature for a while. > it indicates that people have been able to function
> without this feature for a while.
I regularily have users of my library (which uses SWT to integrate native components in Swing) asking about the Mac integration, and I redirect them to this bug.
I also regularily have users who ask me if the issue improved.
And last but not least, I know some users who are still using Java 6 and really complain that it is not an option anymore; they don't know how to solve their problem.
I also acknowledge that it is not a trivial problem to solve...
@Steve People are not able to function without this feature, they're leaving. I'm planning to migrate away from Eclipse SWT since on Mac OS X I'm effectively stuck at Java 6 and when Apple drops it, I need an alternative. We have a product that has been using the SWT/AWT bridge, and at the moment I can verify that running under Java 6, on OS X, I have no problems. As soon as I run under Java 7, I get an issue whereby a java.awt.Frame does not layout properly; the Frame does not fill the composite it got created from! Are there any workarounds that are available? We will not be able to fix this in Eclipse 4.5. Resetting the target. Hi, I have exactly the same problem as Eddie #12 (by embedding an AWT Frame in a SWT Composite, using JDK > 6, the AWT Frame is not displayed or, after resizing the Editor, the AWT Frame is glitched, got wrong dimensions and the AWT events are also not detected. I'm really sorry, I don't really understand the original issue and if the behavior can be linked to it. Do you think it can ? or maybe someone could help me to find the right issue/bug ? Also maybe anyone have found a temporary workaround for this bug ? Thank you very much in advance for your help and please forgive me if I'm not really at the right location. (In reply to Djak Mising name from comment #14) > Hi, > I have exactly the same problem as Eddie #12 (by embedding an AWT Frame in a > SWT Composite, using JDK > 6, the AWT Frame is not displayed or, after > resizing the Editor, the AWT Frame is glitched, got wrong dimensions and the > AWT events are also not detected. > I'm really sorry, I don't really understand the original issue and if the > behavior can be linked to it. Do you think it can ? or maybe someone could > help me to find the right issue/bug ? > Also maybe anyone have found a temporary workaround for this bug ? > Thank you very much in advance for your help and please forgive me if I'm > not really at the right location. This bug tracks the problem with embedding SWT in AWT. But, you are embedding AWT in SWT which should work fine. Please open a separate bug for this issue. Also, you need to use Java 7 update 40 or later (due to Bug 374199). Please find some example snippets on how to use the SWT_AWT bridge here -- https://www.eclipse.org/swt/snippets/ under bullet Swing/AWT. Hi, thank you for your answer. After further investigation, I add this last comment to clarify my issue (comment #14) that is finally not linked to this one (and also doesn't seem to be linked to SWT). The problem is on some OS X configurations, Java 1.7/1.8 can not enable hardware acceleration, leading to a CPU usage reaching sometimes 80% when the layout resizing is done even when using only AWT code (no SWT code at all). The message in RCP console is "WARNING: GL pipe is running in software mode". The behavior is a few different when embedding AWT in SWT in an RCP application, it simply creates glitched components or does not create them at all and freezes the app. (I didn't found any solution at this moment for this, except stay in Java 1.6) Bug triaged, visit https://wiki.eclipse.org/SWT/Devel/Triage for more information Have the same problem. Voted. When will be solved this bug? I have the same problem described here. Any update how to solve it. New Gerrit change created: https://git.eclipse.org/r/155620 Gerrit change https://git.eclipse.org/r/155620 was merged to [master]. Commit: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=30ad38d69b91bac02f587cec89b564c73a903bdb Unfortunately, this can't be fixed. AWT internals have changed in Java 7 and the necessary API isn't available anymore. |