mirror of
https://github.com/ZuneDev/ZuneShell.dll.git
synced 2026-07-27 13:11:51 -07:00
583 lines
21 KiB
C#
583 lines
21 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: ZuneUI.WindowSnapSimulator
|
|
// Assembly: ZuneShell, Version=4.7.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
|
|
// MVID: FC8028F3-A47B-4FB4-B35B-11D1752D8264
|
|
// Assembly location: C:\Program Files\Zune\ZuneShell.dll
|
|
|
|
using Microsoft.Iris;
|
|
using Microsoft.Zune.Util;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
|
|
namespace ZuneUI
|
|
{
|
|
public class WindowSnapSimulator : SingletonModelItem<WindowSnapSimulator>
|
|
{
|
|
private const float c_hotspotPercentage = 0.015f;
|
|
private Window _window;
|
|
private bool _isInitialized;
|
|
private List<Monitor> _monitors;
|
|
private IHotspot _currentHotspot;
|
|
private bool _isSnapping;
|
|
|
|
public void Phase3Init() => this.Initialize();
|
|
|
|
private void Initialize()
|
|
{
|
|
if (this.IsInitialized)
|
|
return;
|
|
this.InitializeMonitors();
|
|
this._window = Application.Window;
|
|
this._window.PropertyChanged += new PropertyChangedEventHandler(this.OnWindowPropertyChanged);
|
|
Win7ShellManager.Instance.OnMonitorChange += new MonitorChangeHandler(this.OnMonitorChangeDetected);
|
|
if (OSVersion.IsWin7())
|
|
Win7ShellManager.Instance.OnWindowPositionKeyPress += new WindowPositionKeyPressHandler(this.OnWin7KeypressDetected);
|
|
Shell defaultInstance = (Shell)ZuneShell.DefaultInstance;
|
|
if (defaultInstance.NormalWindowSize == null)
|
|
defaultInstance.NormalWindowSize = new Size(this._window.ClientSize.Width, this._window.ClientSize.Height);
|
|
if (defaultInstance.NormalWindowPosition == null)
|
|
defaultInstance.NormalWindowPosition = new Point(this._window.Position.X, this._window.Position.Y);
|
|
this.IsInitialized = true;
|
|
this.UpdateIsSnapping();
|
|
}
|
|
|
|
private void InitializeMonitors()
|
|
{
|
|
this._monitors = new List<Monitor>();
|
|
foreach (MonitorSize detectMonitor in new MonitorDetector().DetectMonitors())
|
|
{
|
|
Monitor monitor = new Monitor(detectMonitor);
|
|
int width = Math.Max((monitor.Right - monitor.Left + 1) / 2, Shell.MinimumWindowWidth);
|
|
int height = Math.Max(monitor.Bottom - monitor.Top + 1, Shell.MinimumWindowHeight);
|
|
monitor.LeftSnap.Position = new WindowPosition(monitor.Left, monitor.Top);
|
|
monitor.LeftSnap.Size = new WindowSize(width, height);
|
|
monitor.RightSnap.Position = new WindowPosition(monitor.Right - width, monitor.Top);
|
|
monitor.RightSnap.Size = new WindowSize(width, height);
|
|
this._monitors.Add(monitor);
|
|
}
|
|
this._monitors.Sort();
|
|
foreach (Monitor monitor in this._monitors)
|
|
monitor.InitializeHotspots(this._monitors, 0.015f);
|
|
}
|
|
|
|
public bool IsSnapping
|
|
{
|
|
get => this._isSnapping;
|
|
private set
|
|
{
|
|
if (this._isSnapping == value)
|
|
return;
|
|
this._isSnapping = value;
|
|
this.FirePropertyChanged(nameof(IsSnapping));
|
|
}
|
|
}
|
|
|
|
private bool IsInitialized
|
|
{
|
|
get => this._isInitialized;
|
|
set => this._isInitialized = value;
|
|
}
|
|
|
|
public void ShiftUp()
|
|
{
|
|
if (!this.IsInitialized || this._window.WindowState != WindowState.Normal)
|
|
return;
|
|
if (this.IsSnapping)
|
|
this.Unsnap(this.GetWindowMonitor());
|
|
this._window.WindowState = WindowState.Maximized;
|
|
}
|
|
|
|
public void ShiftDown()
|
|
{
|
|
if (!this.IsInitialized)
|
|
return;
|
|
switch (this._window.WindowState)
|
|
{
|
|
case WindowState.Normal:
|
|
if (this.IsSnapping)
|
|
{
|
|
this.Unsnap();
|
|
break;
|
|
}
|
|
this._window.WindowState = WindowState.Minimized;
|
|
break;
|
|
case WindowState.Maximized:
|
|
this._window.WindowState = WindowState.Normal;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ShiftLeft()
|
|
{
|
|
if (!this.IsInitialized)
|
|
return;
|
|
if (this._window.WindowState == WindowState.Maximized)
|
|
this._window.WindowState = WindowState.Normal;
|
|
Monitor windowMonitor = this.GetWindowMonitor();
|
|
switch (this.GetWindowSnappedness(windowMonitor))
|
|
{
|
|
case WindowSnappedness.Unsnapped:
|
|
this.Snap(windowMonitor.LeftSnap);
|
|
break;
|
|
case WindowSnappedness.Left:
|
|
this.Snap(this.FindPreviousMonitor(windowMonitor).RightSnap);
|
|
break;
|
|
case WindowSnappedness.Right:
|
|
this.Unsnap(windowMonitor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ShiftRight()
|
|
{
|
|
if (!this.IsInitialized)
|
|
return;
|
|
if (this._window.WindowState == WindowState.Maximized)
|
|
this._window.WindowState = WindowState.Normal;
|
|
Monitor windowMonitor = this.GetWindowMonitor();
|
|
switch (this.GetWindowSnappedness(windowMonitor))
|
|
{
|
|
case WindowSnappedness.Unsnapped:
|
|
this.Snap(windowMonitor.RightSnap);
|
|
break;
|
|
case WindowSnappedness.Left:
|
|
this.Unsnap(windowMonitor);
|
|
break;
|
|
case WindowSnappedness.Right:
|
|
this.Snap(this.FindNextMonitor(windowMonitor).LeftSnap);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ShiftMonitorLeft()
|
|
{
|
|
if (!this.IsInitialized)
|
|
return;
|
|
Monitor windowMonitor = this.GetWindowMonitor();
|
|
WindowSnappedness windowSnappedness = this.GetWindowSnappedness(windowMonitor);
|
|
Monitor destinationMonitor = null;
|
|
if (!OSVersion.IsWin7())
|
|
destinationMonitor = this.FindPreviousMonitor(windowMonitor);
|
|
switch (windowSnappedness)
|
|
{
|
|
case WindowSnappedness.Unsnapped:
|
|
if (OSVersion.IsWin7())
|
|
break;
|
|
this.MoveWindowToMonitor(windowMonitor, this._window.Position, destinationMonitor);
|
|
break;
|
|
case WindowSnappedness.Left:
|
|
if (OSVersion.IsWin7())
|
|
{
|
|
this.Snap(windowMonitor.LeftSnap);
|
|
break;
|
|
}
|
|
this.Snap(destinationMonitor.LeftSnap);
|
|
break;
|
|
case WindowSnappedness.Right:
|
|
if (OSVersion.IsWin7())
|
|
{
|
|
this.Snap(windowMonitor.RightSnap);
|
|
break;
|
|
}
|
|
this.Snap(destinationMonitor.RightSnap);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ShiftMonitorRight()
|
|
{
|
|
if (!this.IsInitialized)
|
|
return;
|
|
Monitor windowMonitor = this.GetWindowMonitor();
|
|
WindowSnappedness windowSnappedness = this.GetWindowSnappedness(windowMonitor);
|
|
Monitor destinationMonitor = null;
|
|
if (!OSVersion.IsWin7())
|
|
destinationMonitor = this.FindNextMonitor(windowMonitor);
|
|
switch (windowSnappedness)
|
|
{
|
|
case WindowSnappedness.Unsnapped:
|
|
if (OSVersion.IsWin7())
|
|
break;
|
|
this.MoveWindowToMonitor(windowMonitor, this._window.Position, destinationMonitor);
|
|
break;
|
|
case WindowSnappedness.Left:
|
|
if (OSVersion.IsWin7())
|
|
{
|
|
this.Snap(windowMonitor.LeftSnap);
|
|
break;
|
|
}
|
|
this.Snap(destinationMonitor.LeftSnap);
|
|
break;
|
|
case WindowSnappedness.Right:
|
|
if (OSVersion.IsWin7())
|
|
{
|
|
this.Snap(windowMonitor.RightSnap);
|
|
break;
|
|
}
|
|
this.Snap(destinationMonitor.RightSnap);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void Unsnap()
|
|
{
|
|
if (!this.IsSnapping || !this.IsInitialized)
|
|
return;
|
|
this.Unsnap(this.GetWindowMonitor());
|
|
}
|
|
|
|
public void DragBegun()
|
|
{
|
|
if (this.IsInitialized)
|
|
{
|
|
int x = 0;
|
|
int y = 0;
|
|
MousePosition.GetCursorScreenPosition(out x, out y);
|
|
this._currentHotspot = this.GetWindowMonitor(x, y).GetHotspotForCursor(x, y);
|
|
}
|
|
else
|
|
this._currentHotspot = null;
|
|
}
|
|
|
|
public bool ReactToDrag()
|
|
{
|
|
IHotspot hotspot = null;
|
|
if (this.IsInitialized)
|
|
{
|
|
int x = 0;
|
|
int y = 0;
|
|
MousePosition.GetCursorScreenPosition(out x, out y);
|
|
hotspot = this.GetWindowMonitor(x, y).GetHotspotForCursor(x, y);
|
|
if (hotspot != this._currentHotspot)
|
|
{
|
|
if (this.IsSnapping)
|
|
this.Unsnap();
|
|
if (this._window.WindowState == WindowState.Maximized)
|
|
this._window.WindowState = WindowState.Normal;
|
|
this._currentHotspot = hotspot;
|
|
hotspot?.Snap();
|
|
}
|
|
}
|
|
return hotspot != null;
|
|
}
|
|
|
|
public void DragEnded() => this._currentHotspot = null;
|
|
|
|
public void SetWindowPosition(int left, int top, int width, int height)
|
|
{
|
|
this.Initialize();
|
|
Monitor windowMonitor = this.GetWindowMonitor(left + width / 2, top + height / 2);
|
|
if (windowMonitor != null)
|
|
{
|
|
if (width > windowMonitor.Right - windowMonitor.Left)
|
|
width = windowMonitor.Right - windowMonitor.Left;
|
|
if (height > windowMonitor.Bottom - windowMonitor.Top)
|
|
height = windowMonitor.Bottom - windowMonitor.Top;
|
|
if (left < windowMonitor.Left)
|
|
left = windowMonitor.Left;
|
|
else if (left + width > windowMonitor.Right)
|
|
left = windowMonitor.Right - width;
|
|
if (top < windowMonitor.Top)
|
|
top = windowMonitor.Top;
|
|
else if (top + height > windowMonitor.Bottom)
|
|
top = windowMonitor.Bottom - height;
|
|
}
|
|
this._window.Position = new WindowPosition(left, top);
|
|
this._window.ClientSize = new WindowSize(width, height);
|
|
}
|
|
|
|
private void Snap(WindowPlacement placement)
|
|
{
|
|
if (!this.IsInitialized)
|
|
return;
|
|
this._window.Position = placement.Position;
|
|
this._window.ClientSize = placement.Size;
|
|
}
|
|
|
|
private void Unsnap(Monitor monitor)
|
|
{
|
|
if (!this.IsSnapping || !this.IsInitialized)
|
|
return;
|
|
Shell defaultInstance = (Shell)ZuneShell.DefaultInstance;
|
|
WindowPosition windowPosition = new WindowPosition(defaultInstance.NormalWindowPosition.X, defaultInstance.NormalWindowPosition.Y);
|
|
WindowSize size = new WindowSize(defaultInstance.NormalWindowSize.Width, defaultInstance.NormalWindowSize.Height);
|
|
Monitor windowMonitor = this.GetWindowMonitor(windowPosition, size);
|
|
if (monitor == windowMonitor)
|
|
this._window.Position = windowPosition;
|
|
else
|
|
this.MoveWindowToMonitor(windowMonitor, windowPosition, monitor);
|
|
this._window.ClientSize = size;
|
|
}
|
|
|
|
private void MoveWindowToMonitor(
|
|
Monitor currentMonitor,
|
|
WindowPosition currentPosition,
|
|
Monitor destinationMonitor)
|
|
{
|
|
int num1 = destinationMonitor.Left - currentMonitor.Left;
|
|
int num2 = destinationMonitor.Top - currentMonitor.Top;
|
|
this._window.Position = new WindowPosition(currentPosition.X + num1, currentPosition.Y + num2);
|
|
}
|
|
|
|
private Monitor FindNextMonitor(
|
|
Monitor monitor)
|
|
{
|
|
int index = this._monitors.IndexOf(monitor) + 1;
|
|
if (index >= this._monitors.Count)
|
|
index = 0;
|
|
return this._monitors[index];
|
|
}
|
|
|
|
private Monitor FindPreviousMonitor(
|
|
Monitor monitor)
|
|
{
|
|
int index = this._monitors.IndexOf(monitor) - 1;
|
|
if (index < 0)
|
|
index = this._monitors.Count - 1;
|
|
return this._monitors[index];
|
|
}
|
|
|
|
private WindowSnappedness GetWindowSnappedness(
|
|
Monitor monitor)
|
|
{
|
|
WindowSnappedness windowSnappedness = WindowSnappedness.Ineligible;
|
|
if (this.IsInitialized && this._window.WindowState != WindowState.Maximized && this._window.WindowState != WindowState.Minimized)
|
|
windowSnappedness = !(this._window.Position == monitor.LeftSnap.Position) || !(this._window.ClientSize == monitor.LeftSnap.Size) ? (!(this._window.Position == monitor.RightSnap.Position) || !(this._window.ClientSize == monitor.RightSnap.Size) ? WindowSnappedness.Unsnapped : WindowSnappedness.Right) : WindowSnappedness.Left;
|
|
return windowSnappedness;
|
|
}
|
|
|
|
private Monitor GetWindowMonitor() => this.GetWindowMonitor(this._window.Position, this._window.ClientSize);
|
|
|
|
private Monitor GetWindowMonitor(
|
|
WindowPlacement placement)
|
|
{
|
|
return this.GetWindowMonitor(placement.Position, placement.Size);
|
|
}
|
|
|
|
private Monitor GetWindowMonitor(
|
|
WindowPosition position,
|
|
WindowSize size)
|
|
{
|
|
return this.GetWindowMonitor(position.X + size.Width / 2, position.Y + size.Height / 2);
|
|
}
|
|
|
|
private Monitor GetWindowMonitor(int x, int y)
|
|
{
|
|
Monitor monitor1 = null;
|
|
if (this.IsInitialized)
|
|
{
|
|
if (this._monitors.Count > 1)
|
|
{
|
|
int num1 = int.MaxValue;
|
|
foreach (Monitor monitor2 in this._monitors)
|
|
{
|
|
int num2 = 0;
|
|
int num3 = 0;
|
|
if (x < monitor2.Left)
|
|
num2 = monitor2.Left - x;
|
|
else if (x > monitor2.Right)
|
|
num2 = x - monitor2.Right;
|
|
if (y < monitor2.Top)
|
|
num3 = monitor2.Top - y;
|
|
else if (y > monitor2.Bottom)
|
|
num3 = y - monitor2.Bottom;
|
|
int num4 = num2 + num3;
|
|
if (num4 < num1)
|
|
{
|
|
monitor1 = monitor2;
|
|
num1 = num4;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
monitor1 = this._monitors[0];
|
|
}
|
|
return monitor1;
|
|
}
|
|
|
|
private void UpdateIsSnapping()
|
|
{
|
|
bool flag = false;
|
|
if (this._window.WindowState == WindowState.Normal)
|
|
{
|
|
switch (this.GetWindowSnappedness(this.GetWindowMonitor()))
|
|
{
|
|
case WindowSnappedness.Left:
|
|
case WindowSnappedness.Right:
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
this.IsSnapping = flag;
|
|
}
|
|
|
|
private void OnWindowPropertyChanged(object sender, PropertyChangedEventArgs args)
|
|
{
|
|
if (!(args.PropertyName == "Position") && !(args.PropertyName == "ClientSize") && !(args.PropertyName == "WindowState"))
|
|
return;
|
|
this.UpdateIsSnapping();
|
|
}
|
|
|
|
private void OnWin7KeypressDetected(WindowPositionKeys key) => Application.DeferredInvoke(delegate
|
|
{
|
|
switch (key)
|
|
{
|
|
case WindowPositionKeys.eWindowPositionKeyLeft:
|
|
this.ShiftLeft();
|
|
break;
|
|
case WindowPositionKeys.eWindowPositionKeyRight:
|
|
this.ShiftRight();
|
|
break;
|
|
case WindowPositionKeys.eWindowPositionKeyDown:
|
|
if (this._window.WindowState != WindowState.Maximized)
|
|
break;
|
|
this.ShiftDown();
|
|
break;
|
|
case WindowPositionKeys.eWindowPositionKeyShiftLeft:
|
|
this.ShiftMonitorLeft();
|
|
break;
|
|
case WindowPositionKeys.eWindowPositionKeyShiftRight:
|
|
this.ShiftMonitorRight();
|
|
break;
|
|
}
|
|
}, null);
|
|
|
|
private void OnMonitorChangeDetected() => Application.DeferredInvoke(delegate
|
|
{
|
|
this.Unsnap();
|
|
this.InitializeMonitors();
|
|
}, null);
|
|
|
|
private enum WindowSnappedness
|
|
{
|
|
Unsnapped,
|
|
Left,
|
|
Right,
|
|
Ineligible,
|
|
}
|
|
|
|
private class WindowPlacement
|
|
{
|
|
private WindowPosition _position;
|
|
private WindowSize _size;
|
|
|
|
public WindowPosition Position
|
|
{
|
|
get => this._position;
|
|
set => this._position = value;
|
|
}
|
|
|
|
public WindowSize Size
|
|
{
|
|
get => this._size;
|
|
set => this._size = value;
|
|
}
|
|
}
|
|
|
|
private class Monitor : IComparable<Monitor>
|
|
{
|
|
private MonitorSize _dimensions;
|
|
private WindowPlacement _leftSnap;
|
|
private WindowPlacement _rightSnap;
|
|
private int _hotspotSize;
|
|
private IHotspot _topHotspot;
|
|
private IHotspot _leftHotspot;
|
|
private IHotspot _rightHotspot;
|
|
|
|
public Monitor(MonitorSize dimensions)
|
|
{
|
|
this._dimensions = dimensions;
|
|
this.LeftSnap = new WindowPlacement();
|
|
this.RightSnap = new WindowPlacement();
|
|
}
|
|
|
|
public int Left => this._dimensions.WorkArea.Left;
|
|
|
|
public int Right => this._dimensions.WorkArea.Right;
|
|
|
|
public int Top => this._dimensions.WorkArea.Top;
|
|
|
|
public int Bottom => this._dimensions.WorkArea.Bottom;
|
|
|
|
public WindowPlacement LeftSnap
|
|
{
|
|
get => this._leftSnap;
|
|
private set => this._leftSnap = value;
|
|
}
|
|
|
|
public WindowPlacement RightSnap
|
|
{
|
|
get => this._rightSnap;
|
|
private set => this._rightSnap = value;
|
|
}
|
|
|
|
public void InitializeHotspots(
|
|
List<Monitor> monitorList,
|
|
float hotspotSizePercentage)
|
|
{
|
|
this._hotspotSize = (int)((this.Right - this.Left + 1 + (this.Bottom - this.Top + 1)) / 2 * (double)hotspotSizePercentage);
|
|
bool flag1 = true;
|
|
bool flag2 = true;
|
|
bool flag3 = true;
|
|
foreach (Monitor monitor in monitorList)
|
|
{
|
|
RECT totalArea = monitor._dimensions.TotalArea;
|
|
if (totalArea.Top + 1 == this.Top)
|
|
flag1 = false;
|
|
if (totalArea.Right + 1 == this.Left)
|
|
flag2 = false;
|
|
if (totalArea.Left - 1 == this.Right)
|
|
flag3 = false;
|
|
}
|
|
if (flag1)
|
|
this._topHotspot = new MaximizeHotspot();
|
|
if (flag2)
|
|
this._leftHotspot = new PlacementHotspot(this.LeftSnap);
|
|
if (!flag3)
|
|
return;
|
|
this._rightHotspot = new PlacementHotspot(this.RightSnap);
|
|
}
|
|
|
|
public IHotspot GetHotspotForCursor(
|
|
int cursorX,
|
|
int cursorY)
|
|
{
|
|
IHotspot hotspot = null;
|
|
if (cursorY <= this.Top + this._hotspotSize && this._topHotspot != null)
|
|
hotspot = this._topHotspot;
|
|
else if (cursorX <= this.Left + this._hotspotSize)
|
|
hotspot = this._leftHotspot;
|
|
else if (cursorX >= this.Right - this._hotspotSize)
|
|
hotspot = this._rightHotspot;
|
|
return hotspot;
|
|
}
|
|
|
|
public int CompareTo(Monitor other)
|
|
{
|
|
int num = this.Top.CompareTo(other.Top);
|
|
return num == 0 ? this.Left.CompareTo(other.Left) : num;
|
|
}
|
|
}
|
|
|
|
private interface IHotspot
|
|
{
|
|
void Snap();
|
|
}
|
|
|
|
private class MaximizeHotspot : IHotspot
|
|
{
|
|
public void Snap() => Instance.ShiftUp();
|
|
}
|
|
|
|
private class PlacementHotspot : IHotspot
|
|
{
|
|
private WindowPlacement _placement;
|
|
|
|
public PlacementHotspot(WindowPlacement placement) => this._placement = placement;
|
|
|
|
public void Snap() => Instance.Snap(this._placement);
|
|
}
|
|
}
|
|
}
|