Merge pull request #1039 from joelmartinez/master
authorMiguel de Icaza <miguel@gnome.org>
Fri, 16 May 2014 16:13:53 +0000 (12:13 -0400)
committerMiguel de Icaza <miguel@gnome.org>
Fri, 16 May 2014 16:13:53 +0000 (12:13 -0400)
[monodoc] removed erroneous instance of 'FOO' string.

14 files changed:
configure.in
data/config.in
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Screen.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/SystemInformation.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Structs.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUICarbon.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms_test.dll.sources
mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ScreenTest.cs [new file with mode: 0644]

index 104908f858e6f3dc4aa2734e3b14085cddcdfcc2..93f228973c29898a64ce243d880a69d7be36b968 100644 (file)
@@ -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)
index cf457fc207bac9f58a5f335a5f8bc31aa45f629b..44fefc080276ca63a6080c5327fa6ce66034ce77 100644 (file)
@@ -16,6 +16,7 @@
        <dllmap dll="sqlite" target="@SQLITE@" os="!windows"/>
        <dllmap dll="sqlite3" target="@SQLITE3@" os="!windows"/>
        <dllmap dll="libX11" target="@X11@" os="!windows" />
+       <dllmap dll="libXinerama" target="@XINERAMA@" os="!windows" />
        <dllmap dll="libcairo-2.dll" target="libcairo.so.2" os="!windows"/>
        <dllmap dll="libcairo-2.dll" target="libcairo.2.dylib" os="osx"/>
        <dllmap dll="libcups" target="libcups.so.2" os="!windows"/>
index 14345a6a491f8feb2916a136d7de9ee7dd285108..fad6981b745964226a9ff363374068cfde4946ef 100644 (file)
@@ -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 ();
index 897bc75ea6b84ad6c6449e982e6a9df0238434d1..5b6ed663ee251300d8c4ac1396f8796004961a30 100644 (file)
@@ -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)]
index eeb4f80000b96c0abe129155c934f43dc56f92b7..7e8709b035aacc239eb5e361ae1ac50683a11200 100644 (file)
 //
 //
 
-// 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) {
index 95a677e2d778b685b7872e0c6857d1e1bc368a4e..6a10a9173584dc7f02507d75bfcc03013662c1c0 100644 (file)
@@ -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;
                        }
                }
        }
index f2dd4ca10f1e25ad6ad18450265e97fc25ecf825..cfac29e9bed8d18eda8fb460b4a87647b5ba3136 100644 (file)
@@ -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;
+       }
 }
index 89f91da939c0baf542260b71880a5ca72601da80..565569c43f27b82c6565cf5cc0b7222b04dbd4c7 100644 (file)
@@ -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;
index 18afe41221fbf888cac28d6393c84225ae3788ad..7a568b4c09ec7656cdfd3416b7ce566eaf1d649a 100644 (file)
@@ -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;
index b79b967566cf9eb257748c133b24bd562142b7e7..ff2427e069041443921e17fff29bb2903512acac 100644 (file)
@@ -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 {
index efc464d5d124bb11c44f58f23b742727b2c59bac..e541b1fdb97e8ac428e21922b014da5a404fed6f 100644 (file)
@@ -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;
index 2f3b9d85461287a98718c52431037c72e7d6c0f0..c25124033921bcc71ee367c0f780916bdca36f83 100644 (file)
@@ -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
        }
 }
index e14341db1a9f62588375b5e9dcbf84466e5f7dca..e9a833018a6d5e4e82a0718a12ab7cd4e9cc9bf4 100644 (file)
@@ -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 (file)
index 0000000..a5fcedb
--- /dev/null
@@ -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");
+               }
+       }
+}