Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 135381 - [content assist] On multiple monitors, content assist can open windows which are partially off-screen
Summary: [content assist] On multiple monitors, content assist can open windows which ...
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Text (show other bugs)
Version: 3.2   Edit
Hardware: All All
: P3 normal with 2 votes (vote)
Target Milestone: 3.3 M1   Edit
Assignee: JDT-Text-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 50257 135518 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-04-06 16:09 EDT by Gordon Henriksen CLA
Modified: 2006-06-12 04:47 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Gordon Henriksen CLA 2006-04-06 16:09:49 EDT
When a screen is positioned lower than the one on which Eclipse is displayed, the Java content assist menu can open partially off-screen, as indicated by the "dotted" box falling outside of the main monitor in the ASCII art. It's still within the box bounding the two display rectangles (I presume), but the content is not fully on-screen, and the resize handle at the bottom right can't be grabbed.

+-------------------------+
|                         |
|      Eclipse here       |
|                         |+-----------------+
|           +---+         ||                 |
|           |   |         ||   Other stuff   |
+-------------------------+|                 |
            :   :          |                 |
            :...:          +-----------------+

My workarounds are to either:
1. Logically arrange all monitors along the same "baseline," making moving windows or the cursor between them somewhat distressing.
2. Make the content assist window very small (so that it does not extend beyond the monitor frame).

Environment is as follows:

Eclipse SDK
Version: 3.2.0
Build id: I20060307-1315

java version "1.5.0_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-84)
Java HotSpot(TM) Client VM (build 1.5.0_05-51, mixed mode, sharing)

Darwin MacBookPro.local 8.6.1 Darwin Kernel Version 8.6.1: Tue Mar  7 16:55:45 PST 2006; root:xnu-792.9.22.obj~1/RELEASE_I386 i386 i386
Comment 1 Gordon Henriksen CLA 2006-04-06 16:12:00 EDT
Actually, Content Assist happily opens underneath the Dock, too, which is almost as annoying. Not sure if that's fixable.
Comment 2 Gordon Henriksen CLA 2006-04-12 15:15:34 EDT
I just can't win! Here's a related bug that's biting me even with my workarounds:

+-------------------------+
|                         |
|                 +----++-|.........
|                 | CA || |JavaDoc :
|                 |    || |+--------------+
|                 |    || ||       |      |
|                 +----++-||-------+      |
|                         ||              |
+-------------------------++--------------+

Like Content Assist, the JavaDoc accessory window will open into the blank space between the monitors.

My new work-around is to physically rearrange my desk to put the main monitor on the right…
Comment 3 Sean Montgomery CLA 2006-04-13 13:51:38 EDT
I think the problem is that org.eclipse.swt.widgets.Display.getClientArea returns the smallest Rectangle that contains all of the monitors' display areas.  If two or more monitors are arranged as mentioned above, then there's obviously going to be some "dead zones".

One solution would be to create something like a getClientAreaRects method that returns a List of display Rectangles. Unfortunately there's a lot of code in org.eclipse.jface.text that assumes the total display area is a Rectangle, and most likely a lot of Platform UI does, too.  Maybe a committer can let us know if such a sizable rewrite is possible or probable?

Probably wouldn't hurt to submit a separate bug to Platform SWT for excluding the OS X dock from the display area, if there isn't already one.
Comment 4 Gordon Henriksen CLA 2006-04-13 14:06:40 EDT
The right fix in this case would probably be to to simply position the windows with respect to the client rectangle of the display on which Eclipse is "mostly on" (i.e., the screen with the largest surface area of Eclipse exposed). Or, to be really precise, the display with the text caret. By centralizing the display loop, the fix should be less disruptive to the effected callers of getClientArea—it's just adding a parameter (what widget or window is under consideration?), instead of rewriting every algorithm as a loop.

I'll file the dock bug separately.
Comment 5 Sean Montgomery CLA 2006-04-13 15:55:20 EDT
Uh oh, my procedural programming heritage shows its ugly face ;-)

In an OO way it does make more sense to have getClientArea determine the best Rectangle to return for whatever widget is passed in.  What the best Rectangle is will be tricky to figure out, though.

In content assist situations getClientArea is called so that the popups can use the available screen real estate to position themselves near but not over the area of interest.  But consider the two screen layout in the original submission: if the Eclipse window is centered in the left monitor you could easily choose the whole left monitor as the client area - but what if the content assist popup was anchored on the right?  There might be some cases where you'd really want to use the available space on the right monitor.

And what if, for whatever reason, the user had the Eclipse window span the two monitors? Then there's the multiple windows to consider - should Eclipse window A's popups be allowed to overlay Eclipse window B?  Should getClientArea be responsible?

I'm not just disagreeing, just doing some stream of consciousness analysis :-)
Comment 6 Dani Megert CLA 2006-04-13 16:29:24 EDT
Sean, I'm waiting for your patch ;-)
Comment 7 Gordon Henriksen CLA 2006-04-14 12:14:47 EDT
I would think that it would be much less disruptive to add an overload for the described getClientArea API. This overload could accept an area of concern. It could return the client area of the single screen containing the largest proportion of that area; if no such screen, then the main screen.

With small changes, code that uses getClientArea could be adapted to be more multi-monitor friendly by simply calculating an appropriate area before calling getClientArea. Content assist might tend to concern itself with the editor area, the exposed area of the current line, or the area of the text caret.

Eventually, the original getClientArea API could be deprecated.

The area of concern ultimately needs to be translated to display coordinates for the algorithm, but it could be specified indirectly, perhaps as a widget and an area of concern on that widget's surface.

This sort of change shouldn't break anything or require particularly massive algorithmic adjustments; the Content Assist window positioning code, in particular, necessarily already knows about the cursor location, so should have this information readily available.
Comment 8 Sean Montgomery CLA 2006-04-15 19:23:11 EDT
(In reply to comment #6)
> Sean, I'm waiting for your patch ;-)

Sorry Dani, I'm trying to fix 135841 right now ;-)

Comment 9 Gordon Henriksen CLA 2006-04-17 23:33:30 EDT
The secondary (JavaDoc) window seems to be sized and positioned here:

org.eclipse.jface.fieldassist.ContentProposalPopup$ContentProposalAdapter$InfoPopupDialog.adjustBounds()
in org.eclise.jface/src/org/eclipse/jface/fieldassist/ContentProposalAdapter.java:451

This routine completely ignores the size of the screen.
Comment 10 Gordon Henriksen CLA 2006-04-18 00:17:56 EDT
Okay, PopupWindows (both the aforementioned ContentProposalAdapter$ContentProposalPopup and its outer class ContentProposalAdapter$ContentProposalPopup$InfoPopupDialog) were apparently intended to handle this correctly.

Trace from line 931 of ContentProposalAdapter.java -> PopupWindow.open -> PopupWindow.constrainShellSize -> PopupWindow.getConstrainedShellBounds. And the same call sequence from 1744 of the same file.

getConstrainedShellBounds is the routine apparently of interest, but it seems to be written correctly to me: It finds the screen nearest the midpoint of the popup window's natural location, and clamps the window's bounds to that single screen. But this observably doesn't work, at least on the Mac.

Maybe SWT's Screen API is busted on Carbon? They don't look busted, but neither does getConstrainedShellBounds… I don't think I can figure this out without adding logging, or busting out Eclipse's debugger out on Eclipse itself.
Comment 11 Sean Montgomery CLA 2006-04-18 08:56:49 EDT
Hi Gordon
<snip>
> does getConstrainedShellBounds… I don't think I can figure this out without
> adding logging, or busting out Eclipse's debugger out on Eclipse itself.

It's pretty easy to debug Eclipse in Eclipse.  Just check out the relevant source packages from cvs as projects and pick Eclipse Application for the run configuration.

Forgive me if I'm stating the obvious :-)

Comment 12 Tom Hofmann CLA 2006-04-18 10:00:13 EDT
Just some background info:

Content assist does not typically use PopupDialogs.

There are really two shells that have to be sized and placed correctly:

A) the proposal popup (shows the table of proposals). The implementation is entirely private: CompletionProposalPopup in org.eclipse.jface.text.

The placement is managed by ContentAssistant::layoutProposalSelector().

B) the additional info popup that typically shows javadoc excerpts (usually to the right of the proposal popup). The control used is an IInformationControl implementation, but depends on the proposal for which the additional information is shown; typically it is a BrowserInformationControl for javadoc.

The placement is managed by AbstractInformationControlManager::computeInformationControlLocation().

--

Both implementations that do popup placement use subjectControl.getDisplay().getClientArea() to bound the popup to lie within the display bounds. This is wrong, as you noted, because the display's client area comprises all monitors.

The correct code would not use the display, but rather subjectControl.getMonitor().getClientArea(). This fixes two issues:

- the monitor is really just the "main" monitor of the subjectControl; if the subject control covers multiple monitors, the gravity center monitor is chosen.

- unlike Display::getClientArea(), Monitor::getClientArea() does not include the window manager's reserved area (e.g. the "Start" bar of Windows). See also bug 33659.
Comment 13 Tom Hofmann CLA 2006-04-19 11:53:24 EDT
the additional info popup is already reported in bug 50257.
Comment 14 Dani Megert CLA 2006-04-20 03:54:13 EDT
*** Bug 135518 has been marked as a duplicate of this bug. ***
Comment 15 Tom Hofmann CLA 2006-05-31 05:07:44 EDT
*** Bug 50257 has been marked as a duplicate of this bug. ***
Comment 16 Tom Hofmann CLA 2006-06-09 05:29:41 EDT
fixed in HEAD > 20060608