Added LRU (Least Recently Used) semantics to Group switch mode.

This commit is contained in:
Lorenz Cuno Klopfenstein 2010-07-01 14:06:50 +02:00
parent 0f28a47328
commit bcdca91f27

View file

@ -20,9 +20,16 @@ namespace OnTopReplica.MessagePumpProcessors {
uint _hookMsgId;
bool _active = false;
IList<WindowHandle> _handles;
List<WindowHandleWrapper> _lruHandles;
/// <summary>
/// Enables group switch mode.
/// </summary>
/// <param name="handles">List of window handles to track.</param>
public void EnableGroupMode(IList<WindowHandle> handles) {
if (handles == null || handles.Count == 0)
return;
//Enable new hook
if (!_active) {
if (!HookMethods.RegisterShellHookWindow(Form.Handle)) {
@ -32,10 +39,28 @@ namespace OnTopReplica.MessagePumpProcessors {
}
//Okey dokey, will now track handles
_handles = handles;
TrackHandles(handles);
_active = true;
}
/// <summary>
/// Initializes the LRU sorted list of window handles.
/// </summary>
private void TrackHandles(IList<WindowHandle> handles) {
_lruHandles = new List<WindowHandleWrapper>(handles.Count);
var now = DateTime.Now;
foreach(var h in handles){
_lruHandles.Add(new WindowHandleWrapper {
WindowHandle = h,
LastTimeUsed = now
});
}
}
/// <summary>
/// Disables group switch mode.
/// </summary>
public void Disable() {
if (!_active)
return;
@ -43,9 +68,13 @@ namespace OnTopReplica.MessagePumpProcessors {
if (!HookMethods.DeregisterShellHookWindow(Form.Handle))
Console.Error.WriteLine("Failed to deregister shell hook window.");
_lruHandles = null;
_active = false;
}
/// <summary>
/// Processes the message pump.
/// </summary>
public override void Process(Message msg) {
if (_active && msg.Msg == _hookMsgId) {
int hookCode = msg.WParam.ToInt32();
@ -59,17 +88,18 @@ namespace OnTopReplica.MessagePumpProcessors {
}
private void HandleForegroundWindowChange(IntPtr activeWindow) {
int iActive = -1;
for (int i = 0; i < _handles.Count; ++i) {
if (_handles[i].Handle == activeWindow)
iActive = i;
}
#if DEBUG
Console.Write("New active window (h {0}). ", activeWindow);
#endif
if (iActive < 0) {
//Seek window in tracked handles
WindowHandleWrapper activated = null;
foreach (var i in _lruHandles) {
if (i.WindowHandle.Handle == activeWindow)
activated = i;
}
if (activated == null) {
#if DEBUG
//new foreground window is not tracked
Console.WriteLine("Active window is not tracked.");
@ -77,16 +107,18 @@ namespace OnTopReplica.MessagePumpProcessors {
return;
}
//Get new handle to clone
int iNewToClone = (iActive + 1) % _handles.Count;
//Update tracked handle
activated.LastTimeUsed = DateTime.Now;
_lruHandles.Sort(new LruDateTimeComparer());
//Get least recently used
var next = _lruHandles[0];
#if DEBUG
Console.WriteLine("Tracked as {0}. Switching to {1}.", iActive, iNewToClone);
Console.WriteLine("Tracked. Switching to {0} (last use: {1}).", next.WindowHandle.Title, next.LastTimeUsed);
#endif
//TODO: use real least-recently-used semantics
Form.SetThumbnail(_handles[iNewToClone], null);
Form.SetThumbnail(next.WindowHandle, null);
}
protected override void Shutdown() {
@ -102,6 +134,26 @@ namespace OnTopReplica.MessagePumpProcessors {
}
}
#region List sorting stuff
class WindowHandleWrapper {
public WindowHandle WindowHandle { get; set; }
public DateTime LastTimeUsed { get; set; }
}
class LruDateTimeComparer : IComparer<WindowHandleWrapper> {
#region IComparer<WindowHandleWrapper> Members
public int Compare(WindowHandleWrapper x, WindowHandleWrapper y) {
return x.LastTimeUsed.CompareTo(y.LastTimeUsed);
}
#endregion
}
#endregion
}
}