tomboy r2221 - in trunk: . Tomboy



Author: sharm
Date: Tue Oct 14 09:42:35 2008
New Revision: 2221
URL: http://svn.gnome.org/viewvc/tomboy?rev=2221&view=rev

Log:
* Tomboy/ManagedWinapi.EventDispatchingNativeWindow.cs:
* Tomboy/ManagedWinapi.Hoteky.cs: Importing easy-to-use keybinding code
from the ManagedWinapi project (Windows-only, LGPL V2.1 or later).

* Tomboy/WindowsKeybinder.cs: Implementation of IKeybinder for Windows.

* Tomboy/WindowsFactory.cs: Use WindowsKeybinder instead of NullKeybinder.

* Tomboy/Tomboy.cs: Work around GetGeometry bug for WIN32.

* Tomboy.csproj: Added new files and System.Windows.Forms dependency

Added:
   trunk/Tomboy/ManagedWinapi.EventDispatchingNativeWindow.cs   (contents, props changed)
   trunk/Tomboy/ManagedWinapi.Hotkey.cs   (contents, props changed)
   trunk/Tomboy/WindowsKeybinder.cs   (contents, props changed)
Modified:
   trunk/ChangeLog
   trunk/Tomboy.csproj
   trunk/Tomboy/Tomboy.cs
   trunk/Tomboy/WindowsFactory.cs

Modified: trunk/Tomboy.csproj
==============================================================================
--- trunk/Tomboy.csproj	(original)
+++ trunk/Tomboy.csproj	Tue Oct 14 09:42:35 2008
@@ -89,6 +89,7 @@
       <HintPath>winbin\Mono.Posix.dll</HintPath>
     </Reference>
     <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml" />
     <Reference Include="glib-sharp, Version=2.10.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <Reference Include="System" />
@@ -100,6 +101,10 @@
     <Compile Include="Tomboy\Contrast.cs" />
     <Compile Include="Tomboy\Defines.WIN32.cs" />
     <Compile Include="Tomboy\Logger.cs" />
+    <Compile Include="Tomboy\ManagedWinapi.EventDispatchingNativeWindow.cs" />
+    <Compile Include="Tomboy\ManagedWinapi.Hotkey.cs">
+      <SubType>Component</SubType>
+    </Compile>
     <Compile Include="Tomboy\Note.cs" />
     <Compile Include="Tomboy\NoteBuffer.cs" />
     <Compile Include="Tomboy\NoteManager.cs" />
@@ -117,6 +122,7 @@
     <Compile Include="Tomboy\Tag.cs" />
     <Compile Include="Tomboy\TagButton.cs" />
     <Compile Include="Tomboy\WindowsFactory.cs" />
+    <Compile Include="Tomboy\WindowsKeybinder.cs" />
     <Compile Include="Tomboy\WrapBox.cs" />
     <Compile Include="Tomboy\PreferencesDialog.cs" />
     <Compile Include="Tomboy\NoteEditor.cs" />

Added: trunk/Tomboy/ManagedWinapi.EventDispatchingNativeWindow.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/ManagedWinapi.EventDispatchingNativeWindow.cs	Tue Oct 14 09:42:35 2008
@@ -0,0 +1,93 @@
+/*
+ * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to 
+ * access native API by managed code. http://mwinapi.sourceforge.net/
+ * Copyright (C) 2006 Michael Schierl
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING. if not, visit
+ * http://www.gnu.org/licenses/lgpl.html or write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+
+namespace ManagedWinapi.Windows
+{
+
+    /// <summary>
+    /// Called by an EventDispatchingNativeWindow when a window message is received
+    /// </summary>
+    /// <param name="m">The message to handle.</param>
+    /// <param name="handled">Whether the event has already been handled. If this value is true, the handler
+    /// should return immediately. It may set the value to true to indicate that no others 
+    /// should handle it. If the event is not handled by any handler, it is passed to the
+    /// default WindowProc.</param>
+    public delegate void WndProcEventHandler(ref Message m, ref bool handled);
+
+    /// <summary>
+    /// A Win32 native window that delegates window messages to handlers. So several
+    /// components can use the same native window to save "USER resources". This class
+    /// is useful when writing your own components.
+    /// </summary>
+    public class EventDispatchingNativeWindow : NativeWindow
+    {
+
+        private static Object myLock = new Object();
+        private static EventDispatchingNativeWindow _instance;
+
+        /// <summary>
+        /// A global instance which can be used by components that do not need
+        /// their own window.
+        /// </summary>
+        public static EventDispatchingNativeWindow Instance
+        {
+            get
+            {
+                lock (myLock)
+                {
+                    if (_instance == null)
+                        _instance = new EventDispatchingNativeWindow();
+                    return _instance;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Attach your event handlers here.
+        /// </summary>
+        public event WndProcEventHandler EventHandler;
+
+        /// <summary>
+        /// Create your own event dispatching window.
+        /// </summary>
+        public EventDispatchingNativeWindow()
+        {
+            CreateHandle(new CreateParams());
+        }
+
+        /// <summary>
+        /// Parse messages passed to this window and send them to the event handlers.
+        /// </summary>
+        /// <param name="m">A System.Windows.Forms.Message that is associated with the 
+        /// current Windows message.</param>
+        protected override void WndProc(ref Message m)
+        {
+            bool handled = false;
+            if (EventHandler != null)
+                EventHandler(ref m, ref handled);
+            if (!handled)
+                base.WndProc(ref m);
+        }
+    }
+}

Added: trunk/Tomboy/ManagedWinapi.Hotkey.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/ManagedWinapi.Hotkey.cs	Tue Oct 14 09:42:35 2008
@@ -0,0 +1,206 @@
+/*
+ * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to 
+ * access native API by managed code. http://mwinapi.sourceforge.net/
+ * Copyright (C) 2006 Michael Schierl
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING. if not, visit
+ * http://www.gnu.org/licenses/lgpl.html or write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+using ManagedWinapi.Windows;
+
+namespace ManagedWinapi
+{
+
+    /// <summary>
+    /// Specifies a component that creates a global keyboard hotkey.
+    /// </summary>
+    [DefaultEvent("HotkeyPressed")]
+    public class Hotkey : Component
+    {
+
+        /// <summary>
+        /// Occurs when the hotkey is pressed.
+        /// </summary>
+        public event EventHandler HotkeyPressed;
+
+        private static Object myStaticLock = new Object();
+        private static int hotkeyCounter = 0xA000;
+
+        private int hotkeyIndex;
+        private bool isDisposed = false, isEnabled = false, isRegistered = false;
+        private Keys _keyCode;
+        private bool _ctrl, _alt, _shift, _windows;
+        private readonly IntPtr hWnd;
+
+        /// <summary>
+        /// Initializes a new instance of this class with the specified container.
+        /// </summary>
+        /// <param name="container">The container to add it to.</param>
+        public Hotkey(IContainer container) : this()
+        {
+            container.Add(this);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of this class.
+        /// </summary>
+        public Hotkey() 
+        {
+            EventDispatchingNativeWindow.Instance.EventHandler += nw_EventHandler;
+            lock(myStaticLock) 
+            {
+                hotkeyIndex = ++hotkeyCounter;
+            }
+            hWnd = EventDispatchingNativeWindow.Instance.Handle;
+        }
+
+        /// <summary>
+        /// Enables the hotkey. When the hotkey is enabled, pressing it causes a
+        /// <c>HotkeyPressed</c> event instead of being handled by the active 
+        /// application.
+        /// </summary>
+        public bool Enabled
+        {
+            get
+            {
+                return isEnabled;
+            }
+            set
+            {
+                isEnabled = value;
+                updateHotkey(false);
+            }
+        }
+
+        /// <summary>
+        /// The key code of the hotkey.
+        /// </summary>
+        public Keys KeyCode
+        {
+            get
+            {
+                return _keyCode;
+            }
+
+            set
+            {
+                _keyCode = value;
+                updateHotkey(true);
+            }
+        }
+
+        /// <summary>
+        /// Whether the shortcut includes the Control modifier.
+        /// </summary>
+        public bool Ctrl {
+            get { return _ctrl; }
+            set {_ctrl = value; updateHotkey(true);}
+        }
+
+        /// <summary>
+        /// Whether this shortcut includes the Alt modifier.
+        /// </summary>
+        public bool Alt {
+            get { return _alt; }
+            set {_alt = value; updateHotkey(true);}
+        }     
+   
+        /// <summary>
+        /// Whether this shortcut includes the shift modifier.
+        /// </summary>
+        public bool Shift {
+            get { return _shift; }
+            set {_shift = value; updateHotkey(true);}
+        }
+        
+        /// <summary>
+        /// Whether this shortcut includes the Windows key modifier. The windows key
+        /// is an addition by Microsoft to the keyboard layout. It is located between
+        /// Control and Alt and depicts a Windows flag.
+        /// </summary>
+        public bool WindowsKey {
+            get { return _windows; }
+            set {_windows = value; updateHotkey(true);}
+        }
+
+        void nw_EventHandler(ref Message m, ref bool handled)
+        {
+            if (handled) return;
+            if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == hotkeyIndex)
+            {
+                if (HotkeyPressed != null)
+                    HotkeyPressed(this, EventArgs.Empty);
+                handled = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the System.ComponentModel.Component.
+        /// </summary>
+        /// <param name="disposing">Whether to dispose managed resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            isDisposed = true;
+            updateHotkey(false);
+            EventDispatchingNativeWindow.Instance.EventHandler -= nw_EventHandler;
+            base.Dispose(disposing);
+        }
+
+        private void updateHotkey(bool reregister)
+        {
+            bool shouldBeRegistered = isEnabled && !isDisposed && !DesignMode;
+            if (isRegistered && (!shouldBeRegistered || reregister))
+            {
+                // unregister hotkey
+                UnregisterHotKey(hWnd, hotkeyIndex);
+                isRegistered = false;
+            }
+            if (!isRegistered && shouldBeRegistered)
+            {
+                // register hotkey
+                bool success = RegisterHotKey(hWnd, hotkeyIndex, 
+                    (_shift ? MOD_SHIFT : 0) + (_ctrl ? MOD_CONTROL : 0) +
+                    (_alt ? MOD_ALT : 0) + (_windows ? MOD_WIN : 0), (int)_keyCode);
+                if (!success) throw new HotkeyAlreadyInUseException();
+                isRegistered = true;
+            }
+        }
+
+        #region PInvoke Declarations
+
+        [DllImport("user32.dll", SetLastError=true)]
+        private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
+        [DllImport("user32.dll", SetLastError=true)]
+        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+        private static readonly int MOD_ALT = 0x0001,
+            MOD_CONTROL = 0x0002, MOD_SHIFT = 0x0004, MOD_WIN = 0x0008;
+
+        private static readonly int WM_HOTKEY = 0x0312;
+
+        #endregion
+    }
+
+    /// <summary>
+    /// The exception is thrown when a hotkey should be registered that
+    /// has already been registered by another application.
+    /// </summary>
+    public class HotkeyAlreadyInUseException : Exception { }
+}

Modified: trunk/Tomboy/Tomboy.cs
==============================================================================
--- trunk/Tomboy/Tomboy.cs	(original)
+++ trunk/Tomboy/Tomboy.cs	Tue Oct 14 09:42:35 2008
@@ -249,9 +249,13 @@
 		{
 			Gdk.Screen screen = null;
 			if (tray_icon != null) {
+#if WIN32
+				screen = tray_icon.Tray.TomboyTrayMenu.Screen;
+#else
 				Gdk.Rectangle area;
 				Gtk.Orientation orientation;
 				tray_icon.GetGeometry (out screen, out area, out orientation);
+#endif
 			}
 			GuiUtils.ShowHelp("tomboy.xml", null,
 			                  screen,

Modified: trunk/Tomboy/WindowsFactory.cs
==============================================================================
--- trunk/Tomboy/WindowsFactory.cs	(original)
+++ trunk/Tomboy/WindowsFactory.cs	Tue Oct 14 09:42:35 2008
@@ -25,7 +25,7 @@
 
 		public IKeybinder CreateKeybinder ()
 		{
-			return new NullKeybinder ();
+			return new WindowsKeybinder ();
 		}
 	}
 }
\ No newline at end of file

Added: trunk/Tomboy/WindowsKeybinder.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/WindowsKeybinder.cs	Tue Oct 14 09:42:35 2008
@@ -0,0 +1,124 @@
+ïusing System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+
+using ManagedWinapi;
+
+namespace Tomboy
+{
+	public class WindowsKeybinder : IKeybinder
+	{
+		#region Private Members
+
+		private Dictionary<string, Hotkey> bindings;
+
+		#endregion
+
+		#region Constructor
+
+		public WindowsKeybinder ()
+		{
+			bindings = new Dictionary<string, Hotkey> ();
+		}
+
+		#endregion
+
+		#region IKeybinder Members
+
+		public void Bind (string keystring, EventHandler handler)
+		{
+			Hotkey hotkey = ParseHotkey (keystring);
+			if (hotkey == null)
+				return;
+
+			hotkey.HotkeyPressed += handler;
+			hotkey.Enabled = true;
+
+			bindings [keystring] = hotkey;
+		}
+
+		public void Unbind (string keystring)
+		{
+			Hotkey hotkey;
+			if (bindings.TryGetValue (keystring, out hotkey)) {
+				hotkey.Enabled = false;
+				bindings.Remove (keystring);
+			}
+		}
+
+		public void UnbindAll ()
+		{
+			foreach (string keystring in bindings.Keys)
+				Unbind (keystring);
+		}
+
+		public bool GetAccelKeys (string prefs_path, out uint keyval, out Gdk.ModifierType mods)
+		{
+			keyval = 0;
+			mods = 0;
+
+			try {
+				string keystring = (string) Preferences.Get (prefs_path);
+
+				if (string.IsNullOrEmpty (keystring) ||
+					keystring == "disabled")
+					return false;
+
+				Hotkey hotkey = ParseHotkey (keystring);
+				if (hotkey == null)
+					return false;
+
+				keyval = (uint) (Gdk.Key) Enum.Parse (
+					typeof (Gdk.Key),
+					hotkey.KeyCode.ToString ());
+				if (hotkey.Alt)
+					mods |= Gdk.ModifierType.MetaMask;
+				if (hotkey.Ctrl)
+					mods |= Gdk.ModifierType.ControlMask;
+				if (hotkey.WindowsKey)
+					mods |= Gdk.ModifierType.SuperMask;
+				if (hotkey.Shift)
+					mods |= Gdk.ModifierType.ShiftMask;
+
+				return true;
+			} catch {
+				return false;
+			}
+		}
+
+		#endregion
+
+		#region Private Methods
+
+		private Hotkey ParseHotkey (string keystring)
+		{
+			keystring = keystring.ToUpper ();
+
+			// TODO: Really, is this the same behavior as XKeybinder?
+			if (string.IsNullOrEmpty (keystring) ||
+				bindings.ContainsKey (keystring))
+				return null;
+
+			Regex bindingExp = new Regex (
+				"^(<((ALT)|(CTRL)|(SUPER)|(WIN)|(SHIFT))>)+((F(([1-9])|(1[0-2])))|[A-Z])$");
+
+			if (bindingExp.Matches (keystring).Count == 0)
+				return null;
+
+			Hotkey hotkey = new Hotkey ();
+			hotkey.KeyCode = (Keys) Enum.Parse (
+				typeof (Keys),
+				keystring.Substring (keystring.LastIndexOf (">") + 1));
+			hotkey.Alt = keystring.Contains ("<ALT>");
+			hotkey.Ctrl = keystring.Contains ("<CTRL>");
+			hotkey.Shift = keystring.Contains ("<SHIFT>");
+			hotkey.WindowsKey = keystring.Contains ("<SUPER>") ||
+				keystring.Contains ("<WIN>");
+
+			return hotkey;
+		}
+
+		#endregion
+	}
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]