Bug 343273 [Compatibility] Quick Access dialog opens on wrong monitor
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/quickaccess/SearchField.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/quickaccess/SearchField.java index 4270cac..697a0ad 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/quickaccess/SearchField.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/quickaccess/SearchField.java
@@ -23,6 +23,7 @@ import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.Geometry; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; @@ -33,6 +34,7 @@ import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; @@ -162,44 +164,73 @@ }); } - private void layoutShell() { - Composite parent = text.getParent(); - Rectangle tempBounds = parent.getBounds(); - Display display = text.getDisplay(); - Rectangle compBounds = display.map(parent, null, tempBounds); - for (Monitor monitor : display.getMonitors()) { - if (monitor.getBounds().contains(compBounds.x, compBounds.y)) { - Rectangle monitorBounds = monitor.getBounds(); - int width = Math.max(350, compBounds.width); - int height = 250; + /** + * This method was copy/pasted from JFace. + * + * @see org.eclipse.jface.window.Window#getClosestMonitor(Display, Point) + */ + private static Monitor getClosestMonitor(Display toSearch, Point toFind) { + int closest = Integer.MAX_VALUE; - if (compBounds.x + width > monitorBounds.width) { - compBounds.x = monitorBounds.width - width; - } + Monitor[] monitors = toSearch.getMonitors(); + Monitor result = monitors[0]; - if (compBounds.y + height > monitorBounds.height) { - compBounds.y = compBounds.y - tempBounds.height - height; - } + for (int idx = 0; idx < monitors.length; idx++) { + Monitor current = monitors[idx]; - shell.setBounds(compBounds.x, compBounds.y + compBounds.height, width, height); - shell.layout(); - return; + Rectangle clientArea = current.getClientArea(); + + if (clientArea.contains(toFind)) { + return current; + } + + int distance = Geometry.distanceSquared(Geometry.centerPoint(clientArea), toFind); + if (distance < closest) { + closest = distance; + result = current; } } - Rectangle monitorBounds = text.getMonitor().getBounds(); + return result; + } + + /** + * This method was copy/pasted from JFace. + * + * @see org.eclipse.jface.window.Window#getConstrainedShellBounds(Display, + * Rectangle) + */ + private Rectangle getConstrainedShellBounds(Display display, Rectangle preferredSize) { + Rectangle result = new Rectangle(preferredSize.x, preferredSize.y, preferredSize.width, + preferredSize.height); + + Monitor mon = getClosestMonitor(display, Geometry.centerPoint(result)); + + Rectangle bounds = mon.getClientArea(); + + if (result.height > bounds.height) { + result.height = bounds.height; + } + + if (result.width > bounds.width) { + result.width = bounds.width; + } + + result.x = Math.max(bounds.x, Math.min(result.x, bounds.x + bounds.width - result.width)); + result.y = Math.max(bounds.y, Math.min(result.y, bounds.y + bounds.height - result.height)); + + return result; + } + + void layoutShell() { + Display display = text.getDisplay(); + Composite parent = text.getParent(); + Rectangle tempBounds = parent.getBounds(); + Rectangle compBounds = display.map(parent, null, tempBounds); int width = Math.max(350, compBounds.width); int height = 250; - - if (compBounds.x + width > monitorBounds.width) { - compBounds.x = monitorBounds.width - width; - } - - if (compBounds.y + height > monitorBounds.height) { - compBounds.y = compBounds.y - tempBounds.height - height; - } - - shell.setBounds(compBounds.x, compBounds.y + compBounds.height, width, height); + shell.setBounds(getConstrainedShellBounds(display, new Rectangle(compBounds.x, compBounds.y + + compBounds.height, width, height))); shell.layout(); }