From: Miguel de Icaza Date: Fri, 16 May 2014 16:13:53 +0000 (-0400) Subject: Merge pull request #1039 from joelmartinez/master X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=89e0b257d4d71f4b87fad023495c86652c4ac332;hp=4de2bc52c54f8dd127471ec329b89cafc330333a;p=mono.git Merge pull request #1039 from joelmartinez/master [monodoc] removed erroneous instance of 'FOO' string. --- diff --git a/configure.in b/configure.in index 104908f858e..93f228973c2 100644 --- a/configure.in +++ b/configure.in @@ -2507,6 +2507,7 @@ INTL="libc.so.6" SQLITE="libsqlite.so.0" SQLITE3="libsqlite3.so.0" X11="libX11.so" +XINERAMA="libXinerama.so" sizeof_register="SIZEOF_VOID_P" @@ -2995,6 +2996,18 @@ case "$host" in AC_MSG_WARN([Could not find X development libs. Do you have the -devel package installed? Assuming libX11.so.6...]); X11=libX11.so.6 fi + AC_MSG_CHECKING(for the soname of libXinerama.so) + for i in $x_libraries $dlsearch_path; do + for r in 1 2 3; do + if test -f $i/libXinerama.so.$r; then + XINERAMA=libXinerama.so.$r + AC_MSG_RESULT($XINERAMA) + fi + done + done + if test "x$XINERAMA" = "xlibXinerama.so"; then + AC_MSG_WARN([Could not find Xinerama development libs. Support for multiple monitors might not work...]); + fi ;; esac @@ -3344,6 +3357,7 @@ AC_SUBST(INTL) AC_SUBST(SQLITE) AC_SUBST(SQLITE3) AC_SUBST(X11) +AC_SUBST(XINERAMA) AC_DEFINE_UNQUOTED(ARCHITECTURE,"$arch_target",[The architecture this is running on]) AC_SUBST(arch_target) AC_SUBST(CFLAGS) diff --git a/data/config.in b/data/config.in index cf457fc207b..44fefc08027 100644 --- a/data/config.in +++ b/data/config.in @@ -16,6 +16,7 @@ + diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs index 14345a6a491..fad6981b745 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs @@ -2768,6 +2768,10 @@ namespace System.Windows.Forms HighlightedIndex = owner.SelectedIndex; CalcListBoxArea (); + // If the listbox would extend below the screen, move it above the textbox. + Rectangle scrn_rect = Screen.FromControl (owner).Bounds; + if (this.Location.Y + this.Height >= scrn_rect.Bottom) + this.Location = new Point (this.Location.X, this.Location.Y - (this.Height + owner.TextArea.Height)); Show (); Refresh (); diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs index 897bc75ea6b..5b6ed663ee2 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs @@ -1872,9 +1872,8 @@ namespace System.Windows.Forms { } protected void CenterToScreen() { - Size DisplaySize; - int w; - int h; + int w; + int h; // MS creates the handle here. if (TopLevel) { @@ -1894,8 +1893,14 @@ namespace System.Windows.Forms { h = DefaultSize.Height; } - XplatUI.GetDisplaySize(out DisplaySize); - this.Location = new Point(DisplaySize.Width / 2 - w / 2, DisplaySize.Height / 2 - h / 2); + Rectangle workingArea; + if (Owner == null) { + workingArea = Screen.FromPoint (MousePosition).WorkingArea; + } else { + workingArea = Screen.FromControl (Owner).WorkingArea; + } + this.Location = new Point (workingArea.Left + workingArea.Width / 2 - w / 2, + workingArea.Top + workingArea.Height / 2 - h / 2); } [EditorBrowsable(EditorBrowsableState.Advanced)] diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Screen.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Screen.cs index eeb4f80000b..7e8709b035a 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Screen.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Screen.cs @@ -24,21 +24,13 @@ // // -// NOTE: We made a concious decision to have only a single 'screen' -// due to the differences in platforms. On Win32 we could gather -// all information, but not for X11 (and possibly Mac). So for now -// we'll stick with a single screen, but the functions are still -// written to support multiple screens, simply beef up the all_screens -// assignment to get multiples -// To support multiples, we need to use GetMonitorInfo API on Win32 - using System; using System.Drawing; namespace System.Windows.Forms { public class Screen { #region Local Variables - private static Screen[] all_screens = { new Screen(true, "Mono MWF Primary Display", SystemInformation.VirtualScreen, SystemInformation.WorkingArea) }; + private static Screen[] all_screens; private bool primary; private Rectangle bounds; private Rectangle workarea; @@ -47,12 +39,28 @@ namespace System.Windows.Forms { #endregion // Local Variables #region Constructors - private Screen() { + static Screen () + { + try { + all_screens = XplatUI.AllScreens; + } + catch (Exception e) { + Console.WriteLine ("{0} trying to get all screens: {1}", e.GetType (), e.Message); + } + + if (all_screens == null || all_screens.Length == 0) { + // just use a default one + all_screens = new[] { new Screen(true, "Mono MWF Primary Display", + XplatUI.VirtualScreen, XplatUI.WorkingArea) }; + } + } + + internal Screen() { this.primary = true; - this.bounds = SystemInformation.WorkingArea; + this.bounds = XplatUI.WorkingArea; } - private Screen(bool primary, string name, Rectangle bounds, Rectangle workarea) { + internal Screen(bool primary, string name, Rectangle bounds, Rectangle workarea) { this.primary = primary; this.name = name; this.bounds = bounds; @@ -133,7 +141,33 @@ namespace System.Windows.Forms { } public static Screen FromRectangle(Rectangle rect) { - return Screen.FromPoint(new Point(rect.Left, rect.Top)); + Screen bestScrn = null; + int closest = Int32.MaxValue; + foreach (Screen scrn in Screen.AllScreens) { + Rectangle rcBounds = scrn.Bounds; + int distance = 0; + if (rect.Left > rcBounds.Right) + distance += rect.Left - rcBounds.Right; + else if (rcBounds.Left > rect.Left) + distance += rcBounds.Left - rect.Left; + if (rcBounds.Left > rect.Right) + distance += rcBounds.Left - rect.Right; + else if (rect.Right > rcBounds.Right) + distance += rect.Right - rcBounds.Right; + if (rect.Top > rcBounds.Bottom) + distance += rect.Top - rcBounds.Bottom; + else if (rcBounds.Top > rect.Top) + distance += rcBounds.Top - rect.Top; + if (rcBounds.Top > rect.Bottom) + distance += rcBounds.Top - rect.Bottom; + else if (rect.Bottom > rcBounds.Bottom) + distance += rect.Bottom - rcBounds.Bottom; + if (distance < closest) { + bestScrn = scrn; + closest = distance; + } + } + return bestScrn; } public static Rectangle GetBounds(Control ctl) { diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/SystemInformation.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/SystemInformation.cs index 95a677e2d77..6a10a917358 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/SystemInformation.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/SystemInformation.cs @@ -385,7 +385,7 @@ namespace System.Windows.Forms public static int MonitorCount { get { - return 1; // Why bother... + return Screen.AllScreens.Length; } } @@ -479,13 +479,15 @@ namespace System.Windows.Forms public static Size PrimaryMonitorMaximizedWindowSize { get { - return new Size(WorkingArea.Width, WorkingArea.Height); + var workingArea = Screen.PrimaryScreen.WorkingArea; + return new Size (workingArea.Width, workingArea.Height); } } public static Size PrimaryMonitorSize { get { - return new Size(WorkingArea.Width, WorkingArea.Height); + var bounds = Screen.PrimaryScreen.Bounds; + return new Size (bounds.Width, bounds.Height); } } @@ -593,13 +595,16 @@ namespace System.Windows.Forms public static Rectangle VirtualScreen { get { - return XplatUI.VirtualScreen; + var rect = new Rectangle (); + foreach (var screen in Screen.AllScreens) + rect = Rectangle.Union (rect, screen.Bounds); + return rect; } } public static Rectangle WorkingArea { get { - return XplatUI.WorkingArea; + return Screen.PrimaryScreen.WorkingArea; } } } diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs index f2dd4ca10f1..cfac29e9bed 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs @@ -1808,4 +1808,14 @@ namespace System.Windows.Forms { public const string XNSpotLocation = "spotLocation"; public const string XNFontSet = "fontSet"; } + + [StructLayout (LayoutKind.Sequential)] + internal struct XineramaScreenInfo + { + public int screen_number; + public short x_org; + public short y_org; + public short width; + public short height; + } } diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs index 89f91da939c..565569c43f2 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs @@ -427,6 +427,12 @@ namespace System.Windows.Forms { } } + public static Screen[] AllScreens { + get { + return driver.AllScreens; + } + } + public static bool ThemesEnabled { get { return XplatUI.driver.ThemesEnabled; diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUICarbon.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUICarbon.cs index 18afe41221f..7a568b4c09e 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUICarbon.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUICarbon.cs @@ -2261,6 +2261,14 @@ namespace System.Windows.Forms { return new Rectangle ((int)bounds.origin.x, (int)bounds.origin.y, (int)bounds.size.width, (int)bounds.size.height); } } + + [MonoTODO] + internal override Screen[] AllScreens { + get { + return null; + } + } + internal override bool ThemesEnabled { get { return XplatUICarbon.themes_enabled; diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs index b79b967566c..ff2427e0690 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs @@ -248,6 +248,7 @@ namespace System.Windows.Forms { internal abstract bool MouseWheelPresent { get; } internal abstract Rectangle VirtualScreen { get; } internal abstract Rectangle WorkingArea { get; } + internal abstract Screen[] AllScreens { get; } internal abstract bool ThemesEnabled { get; } internal virtual bool RequiresPositiveClientAreaSize { diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs index efc464d5d12..e541b1fdb97 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs @@ -1505,6 +1505,14 @@ namespace System.Windows.Forms { } } + [MonoTODO] + internal override Screen[] AllScreens { + get { + // To support multiples, we need to use GetMonitorInfo API on Win32 + return null; + } + } + internal override bool ThemesEnabled { get { return XplatUIWin32.themes_enabled; diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs index 2f3b9d85461..c2512403392 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs @@ -2594,6 +2594,28 @@ namespace System.Windows.Forms { } } + internal override Screen[] AllScreens { + get { + if (!XineramaIsActive (DisplayHandle)) + return null; + int nScreens; + IntPtr xineramaScreens = XineramaQueryScreens (DisplayHandle, out nScreens); + var screens = new Screen [nScreens]; + IntPtr current = xineramaScreens; + for (int i = 0; i < nScreens; i++) { + var screen = (XineramaScreenInfo)Marshal.PtrToStructure (current, + typeof (XineramaScreenInfo)); + var screenRect = new Rectangle (screen.x_org, screen.y_org, screen.width, + screen.height); + var name = string.Format ("Display {0}", screen.screen_number); + screens [i] = new Screen (i == 0, name, screenRect, screenRect); + current = (IntPtr)( (ulong)current + (ulong)Marshal.SizeOf(typeof (XineramaScreenInfo))); + } + XFree (xineramaScreens); + return screens; + } + } + internal override bool ThemesEnabled { get { return XplatUIX11.themes_enabled; @@ -7236,6 +7258,34 @@ namespace System.Windows.Forms { } #endregion +#region Xinerama imports + [DllImport ("libXinerama", EntryPoint="XineramaQueryScreens")] + extern static IntPtr _XineramaQueryScreens (IntPtr display, out int number); + internal static IntPtr XineramaQueryScreens (IntPtr display, out int number) + { + DebugHelper.TraceWriteLine ("XineramaQueryScreens"); + return _XineramaQueryScreens (display, out number); + } + + [DllImport ("libXinerama", EntryPoint="XineramaIsActive")] + extern static bool _XineramaIsActive (IntPtr display); + static bool XineramaNotInstalled; + + internal static bool XineramaIsActive (IntPtr display) + { + DebugHelper.TraceWriteLine ("XineramaIsActive"); + + if (XineramaNotInstalled) + return false; + try { + return _XineramaIsActive (display); + } catch (DllNotFoundException) { + // Xinerama isn't installed + XineramaNotInstalled = true; + return false; + } + } +#endregion #else //no TRACE defined @@ -7606,6 +7656,29 @@ namespace System.Windows.Forms { internal extern static void gtk_clipboard_set_text (IntPtr clipboard, string text, int len); #endregion + +#region Xinerama imports + [DllImport ("libXinerama")] + internal extern static IntPtr XineramaQueryScreens (IntPtr display, out int number); + + [DllImport ("libXinerama", EntryPoint = "XineramaIsActive")] + extern static bool _XineramaIsActive (IntPtr display); + static bool XineramaNotInstalled; + + internal static bool XineramaIsActive (IntPtr display) + { + if (XineramaNotInstalled) + return false; + try { + return _XineramaIsActive (display); + } catch (DllNotFoundException) { + // Xinerama isn't installed + XineramaNotInstalled = true; + return false; + } + } +#endregion + #endif } } diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms_test.dll.sources b/mcs/class/Managed.Windows.Forms/System.Windows.Forms_test.dll.sources index e14341db1a9..e9a833018a6 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms_test.dll.sources +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms_test.dll.sources @@ -131,6 +131,7 @@ System.Windows.Forms/RichTextBoxTest.cs System.Windows.Forms/SaveFileDialogTest.cs System.Windows.Forms/ScrollableControlTest.cs System.Windows.Forms/ScrollBarTest.cs +System.Windows.Forms/ScreenTest.cs System.Windows.Forms/SelectionRangeTest.cs System.Windows.Forms/SendKeysTest.cs System.Windows.Forms/SplitterTest.cs diff --git a/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ScreenTest.cs b/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ScreenTest.cs new file mode 100644 index 00000000000..a5fcedba86f --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ScreenTest.cs @@ -0,0 +1,106 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2012 SIL International (http://sil.org) +// +// Authors: +// Stephen McConnel (stephen_mcconnel@sil.org) +// + +using System; +using System.Drawing; +using System.Windows.Forms; +using NUnit.Framework; + +namespace MonoTests.System.Windows.Forms +{ + [TestFixture] + public class ScreenTest + { + [TestFixtureSetUp] + public void FixtureSetup () + { + // If there is only one screen, then FromRectangle always returns that screen, + // so this test would not test anything (and would fail on the second Assert + // below). + int screenCount = Screen.AllScreens.Length; + if (screenCount == 1) + Assert.Ignore ("These tests require at least 2 screens"); + } + + static Rectangle GetLowestScreenBounds () + { + Rectangle lowestScreenBounds = new Rectangle (int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue); + foreach (Screen scrn in Screen.AllScreens) { + if (scrn.Bounds.X < lowestScreenBounds.X || scrn.Bounds.Y < lowestScreenBounds.Y) + lowestScreenBounds = scrn.Bounds; + } + return lowestScreenBounds; + } + + [Test] + public void FromRectangleTest_ContainedWithinLowestScreen () + { + var lowestScreenBounds = GetLowestScreenBounds (); + + // If a rectangle is contained within the lowest screen, then the lowest screen + // should be found for that rectangle. + Rectangle testRect1 = new Rectangle (lowestScreenBounds.X + lowestScreenBounds.Width / 4, + lowestScreenBounds.Width / 2, + lowestScreenBounds.Y + lowestScreenBounds.Height / 4, + lowestScreenBounds.Height / 2); + Screen scrn1 = Screen.FromRectangle (testRect1); + Assert.AreEqual (lowestScreenBounds, scrn1.Bounds, + "Wrong screen was found for rectangle contained in the first screen"); + } + + [Test] + public void FromRectangleTest_SlightOverlapWithLowestScreen () + { + var lowestScreenBounds = GetLowestScreenBounds (); + + // If a rectangle overlaps only slightly within the lowest screen, then the lowest screen + // should not be found for that rectangle. (This is where the original implementation + // fails.) + Rectangle testRect2 = new Rectangle (lowestScreenBounds.X + lowestScreenBounds.Width - 15, + lowestScreenBounds.Width / 2, + lowestScreenBounds.Y + lowestScreenBounds.Height - 15, + lowestScreenBounds.Height / 2); + Screen scrn2 = Screen.FromRectangle (testRect2); + Assert.AreNotEqual (lowestScreenBounds, scrn2.Bounds, + "Wrong screen was found for rectangle slightly overlapping the first screen"); + } + + [Test] + public void FromRectangleTest_MostlyOverlapWithLowestScreen () + { + var lowestScreenBounds = GetLowestScreenBounds (); + + // If a rectangle overlaps mostly within the lowest screen, then the lowest screen + // should be found for that rectangle. + Rectangle testRect3 = new Rectangle (lowestScreenBounds.X + (lowestScreenBounds.Width / 2) + 15, + lowestScreenBounds.Width / 2, + lowestScreenBounds.Y + (lowestScreenBounds.Height / 2) + 15, + lowestScreenBounds.Height / 2); + Screen scrn3 = Screen.FromRectangle (testRect3); + Assert.AreEqual (lowestScreenBounds, scrn3.Bounds, + "Wrong screen was found for rectangle mostly overlapping the first screen"); + } + } +}