-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
68 lines (59 loc) · 3.16 KB
/
Copy pathProgram.cs
File metadata and controls
68 lines (59 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System.Runtime.InteropServices;
using System.Windows.Forms;
using DisplayDefaults;
// WinExe has no console of its own; borrow the terminal's. Output lands after the shell
// prompt returns, which is ugly but readable.
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int processId);
if (args.Contains("--uninstall"))
{
AttachConsole(-1);
Console.WriteLine("Removed:");
Console.WriteLine(TrayApp.Uninstall());
Console.WriteLine();
Console.WriteLine("Exit the tray app if it is running, then delete the exe.");
return;
}
if (args.Contains("--selftest"))
{
AttachConsole(-1);
// Not Debug.Assert: that compiles out in Release, so the published exe would print
// "selftest ok" having checked nothing. CI builds Release.
static void Check(bool ok, string what)
{
if (ok) return;
Console.Error.WriteLine("FAIL: " + what);
Environment.Exit(1);
}
var seen = new HashSet<string>(new[] { "MON-A" }, StringComparer.OrdinalIgnoreCase);
Check(NewDisplayWatcher.Unseen(new[] { "MON-A", "MON-B" }, seen).Single() == "MON-B", "unseen monitor is detected");
Check(NewDisplayWatcher.Unseen(new[] { "MON-A" }, seen).Count == 0, "known monitor does not retrigger");
Check(NewDisplayWatcher.Unseen(new[] { "mon-a" }, seen).Count == 0, "identity is case-insensitive");
Check(NewDisplayWatcher.Unseen(Array.Empty<string>(), seen).Count == 0, "no monitors is not a new monitor");
// Primary 1920x1080 at the origin, new monitor 2560x1440. Left/Above must use the NEW
// monitor's size and Right/Below the primary's, or the two rectangles overlap; the
// deliberately different dimensions catch a swap.
Check(DisplayTopology.Offset(Placement.Right, 1920, 1080, 2560, 1440) == (1920, 0), "right of primary");
Check(DisplayTopology.Offset(Placement.Left, 1920, 1080, 2560, 1440) == (-2560, 0), "left by the new monitor's width");
Check(DisplayTopology.Offset(Placement.Above, 1920, 1080, 2560, 1440) == (0, -1440), "above by the new monitor's height");
Check(DisplayTopology.Offset(Placement.Below, 1920, 1080, 2560, 1440) == (0, 1080), "below the primary");
Check(DisplayTopology.Offset(Placement.Default, 1920, 1080, 2560, 1440) == (0, 0), "default moves nothing");
Console.WriteLine("selftest ok");
Console.WriteLine("attached monitors:");
foreach (var id in DisplayTopology.AttachedMonitorIds()) Console.WriteLine(" " + id);
return;
}
// Autostart plus a manual launch would otherwise give two tray icons and two watchers.
// Local\ scopes it to the logon session, which is the right scope for a per-user tray app.
// installer.iss declares the same name as AppMutex — change one and change the other.
using var single = new Mutex(initiallyOwned: true, @"Local\DisplayDefaults", out bool isFirstInstance);
if (!isFirstInstance)
{
// Silently exiting here looks like a broken launch, so say why.
MessageBox.Show(
"DisplayDefaults is already running. Look for the monitor icon in the notification area.",
"DisplayDefaults", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
ApplicationConfiguration.Initialize();
Application.Run(new TrayApp());