[monodoc] removed erroneous instance of 'FOO' string.
SQLITE="libsqlite.so.0"
SQLITE3="libsqlite3.so.0"
X11="libX11.so"
+XINERAMA="libXinerama.so"
sizeof_register="SIZEOF_VOID_P"
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
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)
<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"/>
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 ();
}
protected void CenterToScreen() {
- Size DisplaySize;
- int w;
- int h;
+ int w;
+ int h;
// MS creates the handle here.
if (TopLevel) {
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)]
//
//
-// 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;
#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;
}
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) {
public static int MonitorCount {
get {
- return 1; // Why bother...
+ return Screen.AllScreens.Length;
}
}
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);
}
}
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;
}
}
}
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;
+ }
}
}
}
+ public static Screen[] AllScreens {
+ get {
+ return driver.AllScreens;
+ }
+ }
+
public static bool ThemesEnabled {
get {
return XplatUI.driver.ThemesEnabled;
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;
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 {
}
}
+ [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;
}
}
+ 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;
}
#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
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
}
}
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
--- /dev/null
+// 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");
+ }
+ }
+}