moved class declarations other than the main form below the main form's declaration...
[deb_libcec.git] / src / LibCecTray / ui / CECTray.cs
index 6a04d62f2301da982ecb970cf78547c9031351bc..740033b386539f65670bf317872fbe0116c04fa1 100644 (file)
@@ -40,22 +40,11 @@ using LibCECTray.controller.applications;
 using LibCECTray.settings;
 using Microsoft.Win32;
 using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Threading;
 
 namespace LibCECTray.ui
 {
-  /// <summary>
-  /// The tab pages in this application
-  /// </summary>
-  internal enum ConfigTab
-  {
-    Configuration,
-    KeyConfiguration,
-    Tester,
-    Log,
-    WMC,
-    XBMC
-  }
-
   /// <summary>
   /// Main LibCecTray GUI
   /// </summary>
@@ -72,28 +61,91 @@ namespace LibCECTray.ui
                          else
                            OnShow();
                        };
-      SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(OnPowerModeChanged);
+
       SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
     }
 
     public void OnSessionEnding(object sender, SessionEndingEventArgs e)
     {
+      Controller.CECActions.SuppressUpdates = true;
       Controller.Close();
     }
 
-    public void OnPowerModeChanged(Object sender, PowerModeChangedEventArgs e)
+    #region Power state change window messages
+    private const int WM_POWERBROADCAST      = 0x0218;
+    private const int PBT_APMSUSPEND         = 0x0004;
+    private const int PBT_APMRESUMESUSPEND   = 0x0007;
+    private const int PBT_APMRESUMECRITICAL  = 0x0006;
+    private const int PBT_APMRESUMEAUTOMATIC = 0x0012;
+    private const int PBT_POWERSETTINGCHANGE = 0x8013;
+    private static Guid GUID_SYSTEM_AWAYMODE = new Guid("98a7f580-01f7-48aa-9c0f-44352c29e5c0");
+
+    [StructLayout(LayoutKind.Sequential, Pack = 4)]
+    internal struct POWERBROADCAST_SETTING
     {
-      switch (e.Mode)
+      public Guid PowerSetting;
+      public uint DataLength;
+      public byte Data;
+    }
+    #endregion
+
+    /// <summary>
+    /// Check for power state changes, and pass up when it's something we don't care about
+    /// </summary>
+    /// <param name="msg">The incoming window message</param>
+    protected override void WndProc(ref Message msg)
+    {
+      if (msg.Msg == WM_POWERBROADCAST)
       {
-        case PowerModes.Resume:
-          Controller.Initialise();
-          break;
-        case PowerModes.Suspend:
-          Controller.Close();
-          break;
-        case PowerModes.StatusChange:
-          break;
+        switch (msg.WParam.ToInt32())
+        {
+          case PBT_APMSUSPEND:
+            OnSleep();
+            return;
+
+          case PBT_APMRESUMESUSPEND:
+          case PBT_APMRESUMECRITICAL:
+          case PBT_APMRESUMEAUTOMATIC:
+            OnWake();
+            return;
+
+          case PBT_POWERSETTINGCHANGE:
+            {
+              POWERBROADCAST_SETTING pwr = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(msg.LParam, typeof(POWERBROADCAST_SETTING));
+              if (pwr.PowerSetting == GUID_SYSTEM_AWAYMODE && pwr.DataLength == Marshal.SizeOf(typeof(Int32)))
+              {
+                switch (pwr.Data)
+                {
+                  case 0:
+                    // do _not_ wake the pc when away mode is deactivated
+                    //OnWake();
+                    //return;
+                  case 1:
+                    OnSleep();
+                    return;
+                  default:
+                    break;
+                }
+              }
+            }
+            break;
+          default:
+            break;
+        }
       }
+
+      // pass up when not handled
+      base.WndProc(ref msg);
+    }
+
+    private void OnWake()
+    {
+      Controller.Initialise();
+    }
+
+    private void OnSleep()
+    {
+      Controller.Close();
     }
 
     public override sealed string Text
@@ -112,7 +164,9 @@ namespace LibCECTray.ui
       Hide();
       if (disposing)
       {
-        Controller.Close();
+        Controller.CECActions.SuppressUpdates = true;
+        AsyncDisconnect dc = new AsyncDisconnect(Controller);
+        (new Thread(dc.Process)).Start();
       }
       if (disposing && (components != null))
       {
@@ -529,4 +583,32 @@ namespace LibCECTray.ui
       Controller.DisplayDialog(appConfig, false);
     }
   }
+
+  /// <summary>
+  /// The tab pages in this application
+  /// </summary>
+  internal enum ConfigTab
+  {
+    Configuration,
+    KeyConfiguration,
+    Tester,
+    Log,
+    WMC,
+    XBMC
+  }
+
+  class AsyncDisconnect
+  {
+    public AsyncDisconnect(CECController controller)
+    {
+      _controller = controller;
+    }
+
+    public void Process()
+    {
+      _controller.Close();
+    }
+
+    private CECController _controller;
+  }
 }