Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 77174

Summary: Reparenting support on MacOS X
Product: [Eclipse Project] Platform Reporter: Alexey Maslov <amaslov>
Component: SWTAssignee: Silenio Quarti <Silenio_Quarti>
Status: RESOLVED FIXED QA Contact:
Severity: enhancement    
Priority: P3 CC: aramis, bill, bradleyjames, Dominique.Buenzli, eclipse, emoffatt, fredwulff, mg_list, oli, rszhang, Silenio_Quarti, snorthov, sxenos, wuhaijie
Version: 3.1Keywords: helpwanted
Target Milestone: 3.3 M6   
Hardware: Macintosh   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:
Bug Depends on:    
Bug Blocks: 56793, 70050    
Attachments:
Description Flags
patch for Control.java
none
Second iteration of a proposed patch
none
Third iteration of the patch - with Webkit fix none

Description Alexey Maslov CLA 2004-10-28 06:06:16 EDT
Currenly reparenting is not supported on MacOS X/Carbon implementation.
Comment 1 Steve Northover CLA 2004-10-28 10:36:10 EDT
This is a bunch of work and tricky to get right on this platform.  Use of 
eparenting is generally considered bad UI design (there are notable 
exceptions).  Can you rewrite your code to avoid Control.setParent()?
Comment 2 Alexey Maslov CLA 2004-10-29 09:20:12 EDT
  Avoiding setParent() is pretty hard as we have designed our own framework on
top of SWT that's pretty close to Swing in terms of parent/child relationship
design. Each  container has add() method to add children.
  Maybe our design is wrong? Please, explain why 'use of reparenting considered
bad design'? And what are 'notable exceptions'?
Comment 3 Steve Northover CLA 2004-10-29 15:14:23 EDT
First let's look at the add() method.  Given that a control can only have a 
single parent, what happens when the control is added in 2 different parents?  
Given that a control can't be drawn or really used without a parent, when does 
it ever make sense to create a control and then never give it a parent?  So, 
the fact that the parent must be included in the constructor (a restriction 
imposed by most native window systems), while somewhat strange, is key in the 
design of SWT.  So, controls should always have parents.

If you allow reparenting, what this means is that anybody anywhere inside SWT 
or in client code, who stores the parent of a control in a field can have that 
parent changed.  This leads to incredibly sublte bugs (Windows has a bunch 
involving hover help and the tool bar).

One notable exception is the "tear off" case where you want to move a widget 
hierarchy to a new shell.  Even then, it is safer to destroy and recreate the 
widgets.  The reason you might not want to do this is performance and the fact 
that it might not be possible to create the new widget hierarchy with exactly 
the same attributes as the old.  Eclipse uses Control.setParent() for "tear 
off" controls.

So, I would suggest strongly that rather than fighting fundamental design 
decisions of a library, that they be embraced.  This is exactly what SWT did 
with Windows in exactly this case.  The CreateWindowEx() Windows API needs the 
parent so SWT needs the parent.

Hope this helps.
Comment 4 Alexey Maslov CLA 2004-11-02 14:12:35 EST
First of all, thank you for detailed explanations.
From technical viewpoint I completely agree with you. But from design viewpoint
passing parent into children has some deficiencies. You are probably aware of
them so I will try to be brief.
1. Under such approach children become partly responsible for parent-child
relationship management. In our framework we would have to add to root hierarchy
class some code to add itself to parent. It is not very good.
2. Because we have to pass parent to each child the dependencies between classes
are growing.
3. In practice it makes quite complicated the situation when you have to place
child control to one or another parent depending on child's internal state.
Although I have to admit that such a situation is not very common in practice.

  Now about the add() method. It seems quite logical to me to have a convention
that adding control to another parent removes it from its original parent. I do
not think that storing reference to parent in child would be much of a problem
if the whole framework was build on the add() methaphor. Then child controls
would not have to know about its parent at all. Such a mistakes would be as rare
as for ordinary objects. 
  And after all sometimes you have to reparent controls ("tear off" case). BTW,
how do you do it in Eclipse on Mac OS X?

  So, I agree that if you pass parents into children than framework
implementation is simpler. But I think that the most important thing is the
client API even if the implementation is more complicated. In our framework we
initially create controls with invisible parent window. And on add they are
being assigned valid parent. This makes client code cleaner. Just compare:

1. SWT design
  Shell shell = new Shell();
  new Button(shell);

2. Our framework design 
  Shell shell = new Shell();
  shell.add(new Button());

  Not much of a difference but the code is simpler and easier to maintain.

  In any case, thank you for great framework! We have already forgot about Swing
slowdowns.
Comment 5 Steve Northover CLA 2004-11-02 15:59:19 EST
When you add() an object to a collection, does it remove it from another 
collection it might be in?  Is there any case where you would create a control 
and never add() it to a parent?  If not, why not just pass around the parent 
control and combine the steps?  Not sure how this causes any problems.

From org.eclipse.swt, "The SWT component is designed to provide efficient, 
portable access to the user-interface facilities of the operating systems on 
which it is implemented.".  That is number one for us, more important than 
having and elegant API. So, I strongly urge you to embrace the toolkit rather 
than fighting it.  In the end, your code will be faster and you'll have less 
to debug and ... thanks for using SWT!
Comment 6 Steve Northover CLA 2005-03-29 20:45:19 EST
*** Bug 89051 has been marked as a duplicate of this bug. ***
Comment 7 Stefan Xenos CLA 2005-04-18 15:43:55 EDT
A gentleman from apple was inquiring about this in bug 56793.
Comment 8 Steve Northover CLA 2005-04-18 15:58:38 EDT
Thanks.  Send him over!
Comment 9 Todd Brackett CLA 2005-04-18 16:23:10 EDT
Hi Steve.  Should this be re-tagged as a Mac bug?
Comment 10 Steve Northover CLA 2005-04-18 18:17:37 EDT
Yup.
Comment 11 Andre Weinand CLA 2005-05-30 06:47:32 EDT
Created attachment 21955 [details]
patch for Control.java

This patch is my (naive) attempt to get reparenting working on MacOS X by using
the EmbedControl API.
However, my hack is incomplete since I didn't try to get the required menu
reparenting right.
Comment 12 Todd Brackett CLA 2005-06-22 17:52:00 EDT
Thanks, Andre.  I've asked engineering to take a look at your patch.  We'll be in touch.
Comment 13 Todd Brackett CLA 2005-07-15 17:07:38 EDT
Andre, engineering reports that your use of the EmbedControl API looks fine; the use of that API doesn't 
look like a "hack" at all.

Is there anything else you need?
Comment 14 Dan Phifer CLA 2006-02-07 22:57:19 EST
Is anything happening with this bug?  Is the suggested patch a start?
Comment 15 Steve Northover CLA 2006-05-09 15:19:51 EDT
This fell off a cliff for 3.2.  The patch is a good start.
Comment 16 Dominique Buenzli CLA 2006-06-23 02:59:47 EDT
Will this be resolved in 3.2 final ?
Comment 17 Steve Northover CLA 2006-06-23 13:42:37 EDT
No.  We are long past making any code changes for 3.2.
Comment 18 Kim Horne CLA 2006-09-27 14:01:37 EDT
And 3.3?
Comment 19 Eric Moffatt CLA 2006-10-05 12:49:58 EDT
I'm interested in this too since the new min/max story works best when Fast View behaviour can be supported (which requires reparenting).
Comment 20 Dominique Buenzli CLA 2006-10-12 11:50:35 EDT
Yes this feature is very important for my application too, someone could give us some update about this ?
Thanks in advance.
Comment 21 Dominique Buenzli CLA 2007-01-17 16:45:49 EST
Any chance we could see this in 3.3 final ?
Comment 22 Dominique Buenzli CLA 2007-01-17 16:46:04 EST
Any chance we could see this in 3.3 final ?
Comment 23 Steve Northover CLA 2007-01-18 12:38:47 EST
We are unlikely to have time to work on this for R3.3.  If someone from the community wants to take a stab at it, we'd be happy to talk to them about it.
Comment 24 Fred Wulff CLA 2007-01-24 13:54:18 EST
This functionality is useful for a project that I'm working on, so I'm going to look into implementing support for it.

I corresponded with Steve via email, and here's what he had to say:

"It's a detailed job.  First of all, you need to find the operating system call that reparents the underlying operating system control.  Then, you need to write the code that traverses the widget that was reparented and fixes up any fields or operating system state that we have in Java to know about the new parent.  This involves fixing popup menus etc.  On Windows and GTK, where reparenting is supported, you can see the code pattern we use to do this (a recursive descent with arguments).  The Mac code pattern should be similar."
Comment 25 Fred Wulff CLA 2007-01-30 10:43:03 EST
Created attachment 57800 [details]
Second iteration of a proposed patch

Okay, here's my first run at a patch. Generally, it looks like the Mac should be pretty easy. Tool tips appear to transfer just fine with their components without any modification. The Webkit-based Browser class used by the Javadoc view in Eclipse doesn't detach gracefully, I'm going to look into it, but any suggestions would be appreciated. Also, at the moment I'm not doing anything to set up the menu bar for the reparented window. Looking at a couple of Apple applications, it seems like the menu bar stays static for pretty much everything within the app (including modal dialogs, etc.), it just greys out unavailable options. Any opinions on what the behavior should be, and if we are transferring menus in some respect, at what level we should be doing it (e.g. reparenting vs. a client thereof)?
Comment 26 Silenio Quarti CLA 2007-01-30 11:02:17 EST
>The Webkit-based Browser class used by the Javadoc view in Eclipse >doesn'tdetach gracefully

The Browser webViewHandle is not a child of the Browser handle for some reason I don't remember right now. It is a child of the root control. Look for the code below. You need to reparent it yourself when moving to a different window. Note that there are some callbacks hooked in the Shell that need to be transfer too.

int[] contentView = new int[1];
OS.HIViewFindByID(OS.HIViewGetRoot(window), OS.kHIViewWindowContentID(), contentView);
OS.HIViewAddSubview(contentView[0], webViewHandle);
Comment 27 Dominique Buenzli CLA 2007-01-30 16:57:15 EST
Great. Thank you very much for your patch. If it is usefull for you, can you please quickly explain how I can apply and test this patch on my computer. I download the patch and then ?
I am using Eclipse 3.2.1 for Mac OS X, Intel Mac OS X 10.4.8 with latest java from Apple

Keep up the good work. Thanks again
Comment 28 Fred Wulff CLA 2007-01-30 23:49:12 EST
Created attachment 57888 [details]
Third iteration of the patch - with Webkit fix

I've updated the patch with code to deal with reparenting the Webkit control and its listeners. I'm still not doing anything menu-wise. That's it in terms of bugs that I've found playing around. Still not sure what to do in terms of menus, though.
Comment 29 Fred Wulff CLA 2007-02-04 02:07:29 EST
Steve asked me to remind him that the latest patch seems to be functional on my end. Could anybody else in the community who is perhaps less swamped, and has a CVS build set up on the Mac test it and corroborate that it works? Also, he asked for the community to nicely make some noise, so...erm, nicely make some noise, I suppose :).
Comment 30 Eric Moffatt CLA 2007-02-05 00:03:43 EST
From my perspective reparenting menus is less interesting than reparenting higher order structures (Views...) since they're low in embedded state and, in eclipse in particular, can be re-created on demand from internal caches.

The problem with the destroy/re-create style of reparenting is in the transfer of  the previous control's state information over to the newly created control. This can be fiarly involved for more complex controls such as the Package Explorer (current scroll settings, which sub-trees are open, which -listeners- have to be rehooked...). One of the major advantages of 'true' reparenting is that it removes the onus for this type of code from our clients...
Comment 31 Fred Wulff CLA 2007-02-05 00:31:06 EST
Eric,

I think you may be misunderstanding what exactly is being added. Carbon has native support for reparenting (although it's apparently called embedding in Carbon-ese),  SWT just hasn't been using it, and this is what this patch corrects. Any talk of menus in specific has just been in regards to context menus (which I believe have proved problematic on other platforms, but seem to transfer gracefully under Carbon) or in regards to the question of what to do with the application menu at the top of the screen under OS X, which SWT treats as being associated with a particular shell (much like the menus operate in Windows or GTK), but which most OS X applications treat as being associated with the application directly.
Comment 32 Silenio Quarti CLA 2007-02-20 12:01:03 EST
Fixed > 20070220.

Thanks for the help.
Comment 33 ivar vasara CLA 2007-02-20 12:22:38 EST
Awesome ! Thank you Fred Wulff and everyone for your work on this.. 
Comment 34 Dan Phifer CLA 2007-02-21 07:46:19 EST
Great!  I've applied the patch to my RCP app and it works flawlessly!  I think Mac people using multiple monitors will consider this a big improvement.  Well done.

Is it too late for 3.3? 
Comment 35 Steve Northover CLA 2007-02-21 07:57:22 EST
It's in 3.3.  The patch (while worthy) had a bunch of problems (internal methods became public breaking portability, missing cases etc.) so we couldn't really use it.  The idea was right though.  Thanks Fred!
Comment 36 Dominique Buenzli CLA 2007-02-21 16:07:02 EST
Hi,
Glad to hear that ! Thanks everyone, but... I am not able to make it work yet. 
Is it in build I20070220-1330 ?
Comment 37 Silenio Quarti CLA 2007-02-21 17:07:27 EST
(In reply to comment #36)
> Hi,
> Glad to hear that ! Thanks everyone, but... I am not able to make it work yet. 
> Is it in build I20070220-1330 ?

No, it is going to be in the next integration build (or a nighty greater than 20070220).
Comment 38 Fabian Steeg CLA 2007-03-03 21:33:45 EST
I just checked this out in the latest integration build. Awesome! Many thanks for this!