mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-22 01:02:16 -05:00
Keepass original source code version 2.30
This commit is contained in:
parent
36c1df19d4
commit
3585d4f61f
115
src/KeePassLib2Android/Native/NativeMethods.Unix.cs
Normal file
115
src/KeePassLib2Android/Native/NativeMethods.Unix.cs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
|
Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#if !KeePassUAP
|
||||||
|
using System.Windows.Forms;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace KeePassLib.Native
|
||||||
|
{
|
||||||
|
internal static partial class NativeMethods
|
||||||
|
{
|
||||||
|
#if (!KeePassLibSD && !KeePassUAP)
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct XClassHint
|
||||||
|
{
|
||||||
|
public IntPtr res_name;
|
||||||
|
public IntPtr res_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("libX11")]
|
||||||
|
private static extern int XSetClassHint(IntPtr display, IntPtr window, IntPtr class_hints);
|
||||||
|
|
||||||
|
private static Type m_tXplatUIX11 = null;
|
||||||
|
private static Type GetXplatUIX11Type(bool bThrowOnError)
|
||||||
|
{
|
||||||
|
if(m_tXplatUIX11 == null)
|
||||||
|
{
|
||||||
|
// CheckState is in System.Windows.Forms
|
||||||
|
string strTypeCS = typeof(CheckState).AssemblyQualifiedName;
|
||||||
|
string strTypeX11 = strTypeCS.Replace("CheckState", "XplatUIX11");
|
||||||
|
m_tXplatUIX11 = Type.GetType(strTypeX11, bThrowOnError, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_tXplatUIX11;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Type m_tHwnd = null;
|
||||||
|
private static Type GetHwndType(bool bThrowOnError)
|
||||||
|
{
|
||||||
|
if(m_tHwnd == null)
|
||||||
|
{
|
||||||
|
// CheckState is in System.Windows.Forms
|
||||||
|
string strTypeCS = typeof(CheckState).AssemblyQualifiedName;
|
||||||
|
string strTypeHwnd = strTypeCS.Replace("CheckState", "Hwnd");
|
||||||
|
m_tHwnd = Type.GetType(strTypeHwnd, bThrowOnError, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_tHwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SetWmClass(Form f, string strName, string strClass)
|
||||||
|
{
|
||||||
|
if(f == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
// The following crashes under Mac OS X (SIGSEGV in native code,
|
||||||
|
// not just an exception), thus skip it when we're on Mac OS X;
|
||||||
|
// https://sourceforge.net/projects/keepass/forums/forum/329221/topic/5860588
|
||||||
|
if(NativeLib.GetPlatformID() == PlatformID.MacOSX) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type tXplatUIX11 = GetXplatUIX11Type(true);
|
||||||
|
FieldInfo fiDisplayHandle = tXplatUIX11.GetField("DisplayHandle",
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
|
IntPtr hDisplay = (IntPtr)fiDisplayHandle.GetValue(null);
|
||||||
|
|
||||||
|
Type tHwnd = GetHwndType(true);
|
||||||
|
MethodInfo miObjectFromHandle = tHwnd.GetMethod("ObjectFromHandle",
|
||||||
|
BindingFlags.Public | BindingFlags.Static);
|
||||||
|
object oHwnd = miObjectFromHandle.Invoke(null, new object[] { f.Handle });
|
||||||
|
|
||||||
|
FieldInfo fiWholeWindow = tHwnd.GetField("whole_window",
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
IntPtr hWindow = (IntPtr)fiWholeWindow.GetValue(oHwnd);
|
||||||
|
|
||||||
|
XClassHint xch = new XClassHint();
|
||||||
|
xch.res_name = Marshal.StringToCoTaskMemAnsi(strName ?? string.Empty);
|
||||||
|
xch.res_class = Marshal.StringToCoTaskMemAnsi(strClass ?? string.Empty);
|
||||||
|
IntPtr pXch = Marshal.AllocCoTaskMem(Marshal.SizeOf(xch));
|
||||||
|
Marshal.StructureToPtr(xch, pXch, false);
|
||||||
|
|
||||||
|
XSetClassHint(hDisplay, hWindow, pXch);
|
||||||
|
|
||||||
|
Marshal.FreeCoTaskMem(pXch);
|
||||||
|
Marshal.FreeCoTaskMem(xch.res_name);
|
||||||
|
Marshal.FreeCoTaskMem(xch.res_class);
|
||||||
|
}
|
||||||
|
catch(Exception) { Debug.Assert(false); }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
403
src/KeePassLib2Android/Utility/MonoWorkarounds.cs
Normal file
403
src/KeePassLib2Android/Utility/MonoWorkarounds.cs
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
/*
|
||||||
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
|
Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
#if !KeePassUAP
|
||||||
|
using System.Windows.Forms;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using KeePassLib.Native;
|
||||||
|
|
||||||
|
namespace KeePassLib.Utility
|
||||||
|
{
|
||||||
|
public static class MonoWorkarounds
|
||||||
|
{
|
||||||
|
private static Dictionary<uint, bool> m_dForceReq = new Dictionary<uint, bool>();
|
||||||
|
|
||||||
|
private static bool? m_bReq = null;
|
||||||
|
public static bool IsRequired()
|
||||||
|
{
|
||||||
|
if(!m_bReq.HasValue) m_bReq = NativeLib.IsUnix();
|
||||||
|
return m_bReq.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1219:
|
||||||
|
// Mono prepends byte order mark (BOM) to StdIn.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1219/
|
||||||
|
// 1245:
|
||||||
|
// Key events not raised while Alt is down, and nav keys out of order.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1245/
|
||||||
|
// 1254:
|
||||||
|
// NumericUpDown bug: text is drawn below up/down buttons.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1254/
|
||||||
|
// 1354:
|
||||||
|
// Finalizer of NotifyIcon throws on Unity.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1354/
|
||||||
|
// 1358:
|
||||||
|
// FileDialog crashes when ~/.recently-used is invalid.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1358/
|
||||||
|
// 1366:
|
||||||
|
// Drawing bug when scrolling a RichTextBox.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1366/
|
||||||
|
// 1378:
|
||||||
|
// Mono doesn't implement Microsoft.Win32.SystemEvents events.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1378/
|
||||||
|
// https://github.com/mono/mono/blob/master/mcs/class/System/Microsoft.Win32/SystemEvents.cs
|
||||||
|
// 1418:
|
||||||
|
// Minimizing a form while loading it doesn't work.
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1418/
|
||||||
|
// 5795:
|
||||||
|
// Text in input field is incomplete.
|
||||||
|
// https://bugzilla.xamarin.com/show_bug.cgi?id=5795
|
||||||
|
// https://sourceforge.net/p/keepass/discussion/329220/thread/d23dc88b/
|
||||||
|
// 10163:
|
||||||
|
// WebRequest GetResponse call missing, breaks WebDAV due to no PUT.
|
||||||
|
// https://bugzilla.xamarin.com/show_bug.cgi?id=10163
|
||||||
|
// https://sourceforge.net/p/keepass/bugs/1117/
|
||||||
|
// https://sourceforge.net/p/keepass/discussion/329221/thread/9422258c/
|
||||||
|
// https://github.com/mono/mono/commit/8e67b8c2fc7cb66bff7816ebf7c1039fb8cfc43b
|
||||||
|
// https://bugzilla.xamarin.com/show_bug.cgi?id=1512
|
||||||
|
// https://sourceforge.net/p/keepass/patches/89/
|
||||||
|
// 12525:
|
||||||
|
// PictureBox not rendered when bitmap height >= control height.
|
||||||
|
// https://bugzilla.xamarin.com/show_bug.cgi?id=12525
|
||||||
|
// https://sourceforge.net/p/keepass/discussion/329220/thread/54f61e9a/
|
||||||
|
// 586901:
|
||||||
|
// RichTextBox doesn't handle Unicode string correctly.
|
||||||
|
// https://bugzilla.novell.com/show_bug.cgi?id=586901
|
||||||
|
// 620618:
|
||||||
|
// ListView column headers not drawn.
|
||||||
|
// https://bugzilla.novell.com/show_bug.cgi?id=620618
|
||||||
|
// 649266:
|
||||||
|
// Calling Control.Hide doesn't remove the application from taskbar.
|
||||||
|
// https://bugzilla.novell.com/show_bug.cgi?id=649266
|
||||||
|
// 686017:
|
||||||
|
// Minimum sizes must be enforced.
|
||||||
|
// http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=686017
|
||||||
|
// 801414:
|
||||||
|
// Mono recreates the main window incorrectly.
|
||||||
|
// https://bugs.launchpad.net/ubuntu/+source/keepass2/+bug/801414
|
||||||
|
// 891029:
|
||||||
|
// Increase tab control height, otherwise Mono throws exceptions.
|
||||||
|
// https://sourceforge.net/projects/keepass/forums/forum/329221/topic/4519750
|
||||||
|
// https://bugs.launchpad.net/ubuntu/+source/keepass2/+bug/891029
|
||||||
|
// 836428016:
|
||||||
|
// ListView group header selection unsupported.
|
||||||
|
// https://sourceforge.net/p/keepass/discussion/329221/thread/31dae0f0/
|
||||||
|
// 3574233558:
|
||||||
|
// Problems with minimizing windows, no content rendered.
|
||||||
|
// https://sourceforge.net/p/keepass/discussion/329220/thread/d50a79d6/
|
||||||
|
public static bool IsRequired(uint uBugID)
|
||||||
|
{
|
||||||
|
if(!MonoWorkarounds.IsRequired()) return false;
|
||||||
|
|
||||||
|
bool bForce;
|
||||||
|
if(m_dForceReq.TryGetValue(uBugID, out bForce)) return bForce;
|
||||||
|
|
||||||
|
ulong v = NativeLib.MonoVersion;
|
||||||
|
if(v != 0)
|
||||||
|
{
|
||||||
|
if(uBugID == 10163)
|
||||||
|
return (v >= 0x0002000B00000000UL); // >= 2.11
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void SetEnabled(string strIDs, bool bEnabled)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(strIDs)) return;
|
||||||
|
|
||||||
|
string[] vIDs = strIDs.Split(new char[] { ',' });
|
||||||
|
foreach(string strID in vIDs)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(strID)) continue;
|
||||||
|
|
||||||
|
uint uID;
|
||||||
|
if(StrUtil.TryParseUInt(strID.Trim(), out uID))
|
||||||
|
m_dForceReq[uID] = bEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !KeePassUAP
|
||||||
|
public static void ApplyTo(Form f)
|
||||||
|
{
|
||||||
|
if(!MonoWorkarounds.IsRequired()) return;
|
||||||
|
if(f == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
#if !KeePassLibSD
|
||||||
|
f.HandleCreated += MonoWorkarounds.OnFormHandleCreated;
|
||||||
|
SetWmClass(f);
|
||||||
|
|
||||||
|
ApplyToControlsRec(f.Controls, f, MonoWorkarounds.ApplyToControl);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Release(Form f)
|
||||||
|
{
|
||||||
|
if(!MonoWorkarounds.IsRequired()) return;
|
||||||
|
if(f == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
#if !KeePassLibSD
|
||||||
|
f.HandleCreated -= MonoWorkarounds.OnFormHandleCreated;
|
||||||
|
|
||||||
|
ApplyToControlsRec(f.Controls, f, MonoWorkarounds.ReleaseControl);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !KeePassLibSD
|
||||||
|
private delegate void MwaControlHandler(Control c, Form fContext);
|
||||||
|
|
||||||
|
private static void ApplyToControlsRec(Control.ControlCollection cc,
|
||||||
|
Form fContext, MwaControlHandler fn)
|
||||||
|
{
|
||||||
|
if(cc == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
foreach(Control c in cc)
|
||||||
|
{
|
||||||
|
fn(c, fContext);
|
||||||
|
ApplyToControlsRec(c.Controls, fContext, fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyToControl(Control c, Form fContext)
|
||||||
|
{
|
||||||
|
Button btn = (c as Button);
|
||||||
|
if(btn != null) ApplyToButton(btn, fContext);
|
||||||
|
|
||||||
|
NumericUpDown nc = (c as NumericUpDown);
|
||||||
|
if((nc != null) && MonoWorkarounds.IsRequired(1254))
|
||||||
|
{
|
||||||
|
if(nc.TextAlign == HorizontalAlignment.Right)
|
||||||
|
nc.TextAlign = HorizontalAlignment.Left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class MwaHandlerInfo
|
||||||
|
{
|
||||||
|
private readonly Delegate m_fnOrg; // May be null
|
||||||
|
public Delegate FunctionOriginal
|
||||||
|
{
|
||||||
|
get { return m_fnOrg; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Delegate m_fnOvr;
|
||||||
|
public Delegate FunctionOverride
|
||||||
|
{
|
||||||
|
get { return m_fnOvr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly DialogResult m_dr;
|
||||||
|
public DialogResult Result
|
||||||
|
{
|
||||||
|
get { return m_dr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Form m_fContext;
|
||||||
|
public Form FormContext
|
||||||
|
{
|
||||||
|
get { return m_fContext; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MwaHandlerInfo(Delegate fnOrg, Delegate fnOvr, DialogResult dr,
|
||||||
|
Form fContext)
|
||||||
|
{
|
||||||
|
m_fnOrg = fnOrg;
|
||||||
|
m_fnOvr = fnOvr;
|
||||||
|
m_dr = dr;
|
||||||
|
m_fContext = fContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EventHandlerList GetEventHandlers(Component c,
|
||||||
|
out object objClickEvent)
|
||||||
|
{
|
||||||
|
FieldInfo fi = typeof(Control).GetField("ClickEvent", // Mono
|
||||||
|
BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
|
if(fi == null)
|
||||||
|
fi = typeof(Control).GetField("EventClick", // .NET
|
||||||
|
BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
|
if(fi == null) { Debug.Assert(false); objClickEvent = null; return null; }
|
||||||
|
|
||||||
|
objClickEvent = fi.GetValue(null);
|
||||||
|
if(objClickEvent == null) { Debug.Assert(false); return null; }
|
||||||
|
|
||||||
|
PropertyInfo pi = typeof(Component).GetProperty("Events",
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
return (pi.GetValue(c, null) as EventHandlerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<object, MwaHandlerInfo> m_dictHandlers =
|
||||||
|
new Dictionary<object, MwaHandlerInfo>();
|
||||||
|
private static void ApplyToButton(Button btn, Form fContext)
|
||||||
|
{
|
||||||
|
DialogResult dr = btn.DialogResult;
|
||||||
|
if(dr == DialogResult.None) return; // No workaround required
|
||||||
|
|
||||||
|
object objClickEvent;
|
||||||
|
EventHandlerList ehl = GetEventHandlers(btn, out objClickEvent);
|
||||||
|
if(ehl == null) { Debug.Assert(false); return; }
|
||||||
|
Delegate fnClick = ehl[objClickEvent]; // May be null
|
||||||
|
|
||||||
|
EventHandler fnOvr = new EventHandler(MonoWorkarounds.OnButtonClick);
|
||||||
|
m_dictHandlers[btn] = new MwaHandlerInfo(fnClick, fnOvr, dr, fContext);
|
||||||
|
|
||||||
|
btn.DialogResult = DialogResult.None;
|
||||||
|
if(fnClick != null) ehl.RemoveHandler(objClickEvent, fnClick);
|
||||||
|
ehl[objClickEvent] = fnOvr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReleaseControl(Control c, Form fContext)
|
||||||
|
{
|
||||||
|
Button btn = (c as Button);
|
||||||
|
if(btn != null) ReleaseButton(btn, fContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReleaseButton(Button btn, Form fContext)
|
||||||
|
{
|
||||||
|
MwaHandlerInfo hi;
|
||||||
|
m_dictHandlers.TryGetValue(btn, out hi);
|
||||||
|
if(hi == null) return;
|
||||||
|
|
||||||
|
object objClickEvent;
|
||||||
|
EventHandlerList ehl = GetEventHandlers(btn, out objClickEvent);
|
||||||
|
if(ehl == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
ehl.RemoveHandler(objClickEvent, hi.FunctionOverride);
|
||||||
|
if(hi.FunctionOriginal != null)
|
||||||
|
ehl[objClickEvent] = hi.FunctionOriginal;
|
||||||
|
|
||||||
|
btn.DialogResult = hi.Result;
|
||||||
|
m_dictHandlers.Remove(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnButtonClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Button btn = (sender as Button);
|
||||||
|
if(btn == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
MwaHandlerInfo hi;
|
||||||
|
m_dictHandlers.TryGetValue(btn, out hi);
|
||||||
|
if(hi == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
Form f = hi.FormContext;
|
||||||
|
|
||||||
|
// Set current dialog result by setting the form's private
|
||||||
|
// variable; the DialogResult property can't be used,
|
||||||
|
// because it raises close events
|
||||||
|
FieldInfo fiRes = typeof(Form).GetField("dialog_result",
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
if(fiRes == null) { Debug.Assert(false); return; }
|
||||||
|
if(f != null) fiRes.SetValue(f, hi.Result);
|
||||||
|
|
||||||
|
if(hi.FunctionOriginal != null)
|
||||||
|
hi.FunctionOriginal.Method.Invoke(hi.FunctionOriginal.Target,
|
||||||
|
new object[] { btn, e });
|
||||||
|
|
||||||
|
// Raise close events, if the click event handler hasn't
|
||||||
|
// reset the dialog result
|
||||||
|
if((f != null) && (f.DialogResult == hi.Result))
|
||||||
|
f.DialogResult = hi.Result; // Raises close events
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetWmClass(Form f)
|
||||||
|
{
|
||||||
|
NativeMethods.SetWmClass(f, PwDefs.UnixName, PwDefs.ResClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnFormHandleCreated(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Form f = (sender as Form);
|
||||||
|
if(f == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
if(!f.IsHandleCreated) return; // Prevent infinite loop
|
||||||
|
|
||||||
|
SetWmClass(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the value of the private <c>shown_raised</c> member
|
||||||
|
/// variable of a form.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Previous <c>shown_raised</c> value.</returns>
|
||||||
|
internal static bool ExchangeFormShownRaised(Form f, bool bNewValue)
|
||||||
|
{
|
||||||
|
if(f == null) { Debug.Assert(false); return true; }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FieldInfo fi = typeof(Form).GetField("shown_raised",
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
if(fi == null) { Debug.Assert(false); return true; }
|
||||||
|
|
||||||
|
bool bPrevious = (bool)fi.GetValue(f);
|
||||||
|
|
||||||
|
fi.SetValue(f, bNewValue);
|
||||||
|
|
||||||
|
return bPrevious;
|
||||||
|
}
|
||||||
|
catch(Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensure that the file ~/.recently-used is valid (in order to
|
||||||
|
/// prevent Mono's FileDialog from crashing).
|
||||||
|
/// </summary>
|
||||||
|
internal static void EnsureRecentlyUsedValid()
|
||||||
|
{
|
||||||
|
if(!MonoWorkarounds.IsRequired(1358)) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string strFile = Environment.GetFolderPath(
|
||||||
|
Environment.SpecialFolder.Personal);
|
||||||
|
strFile = UrlUtil.EnsureTerminatingSeparator(strFile, false);
|
||||||
|
strFile += ".recently-used";
|
||||||
|
|
||||||
|
if(File.Exists(strFile))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Mono's WriteRecentlyUsedFiles method also loads the
|
||||||
|
// XML file using XmlDocument
|
||||||
|
XmlDocument xd = new XmlDocument();
|
||||||
|
xd.Load(strFile);
|
||||||
|
}
|
||||||
|
catch(Exception) // The XML file is invalid
|
||||||
|
{
|
||||||
|
File.Delete(strFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception) { Debug.Assert(false); }
|
||||||
|
}
|
||||||
|
#endif // !KeePassUAP
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user