void SwizzleNSApplicationAccessibilitySetter() { // Swizzle accessibilitySetValue:forAttribute: so that we can detect when VoiceOver gets enabled var nsApplicationClassHandle = Class.GetHandle("NSApplication"); // This happens if GtkMac is loaded before XamMac if (nsApplicationClassHandle == IntPtr.Zero) { return; } var accessibilitySetValueForAttributeSelector = Selector.GetHandle("accessibilitySetValue:forAttribute:"); var accessibilitySetValueForAttributeMethod = class_getInstanceMethod(nsApplicationClassHandle, accessibilitySetValueForAttributeSelector); originalAccessibilitySetValueForAttributeMethod = method_getImplementation(accessibilitySetValueForAttributeMethod); var block = new BlockLiteral(); SwizzledAccessibilitySetValueForAttributeDelegate d = accessibilitySetValueForAttribute; block.SetupBlock(d, null); var imp = imp_implementationWithBlock(ref block); method_setImplementation(accessibilitySetValueForAttributeMethod, imp); accessibilityInUse = CFPreferences.GetAppBooleanValue("voiceOverOnOffKey", "com.apple.universalaccess"); a11yHelperInitialized = true; }
void SetValue(string key, IntPtr value) { using (var cfKey = new CFString(key)) { CFPreferences.SetValue( cfKey.Handle, value, applicationId.Handle, CFPreferences.kCFPreferencesCurrentUser, CFPreferences.kCFPreferencesAnyHost); CFPreferences.Synchronize( applicationId.Handle, CFPreferences.kCFPreferencesCurrentUser, CFPreferences.kCFPreferencesAnyHost); } }
public void PlaySoundEffect(SoundEffect effect, EffectMode mode) { if (mode == EffectMode.Off || effect == SoundEffect.None) { return; } if (mode == EffectMode.Default && Forms9Patch.Settings.SoundEffectMode != EffectMode.On) { if (Forms9Patch.Settings.SoundEffectMode == EffectMode.Default) { // this no longer works and there doesn't appear to be a way to detect if keyclicks is on //var type = CFPreferences.CurrentApplication; CFPreferences.AppSynchronize("/var/mobile/Library/Preferences/com.apple.preferences.sounds"); if (!CFPreferences.GetAppBooleanValue("keyboard", "/var/mobile/Library/Preferences/com.apple.preferences.sounds")) { return; } } else // Forms9Patch.Settings.SoundEffectMode == EffectMode.Off { return; } } switch (effect) { case SoundEffect.KeyClick: click.PlaySystemSound(); break; case SoundEffect.Return: modifier.PlaySystemSound(); break; case SoundEffect.Delete: delete.PlaySystemSound(); break; } }
/// <summary> /// Feedback the specified effect and mode. /// </summary> /// <param name="effect">Effect.</param> /// <param name="mode">Mode.</param> public void Feedback(HapticEffect effect, KeyClicks mode = KeyClicks.Default) { var soundEnabled = (mode & KeyClicks.On) > 0; if (mode == KeyClicks.Default) { soundEnabled = (Forms9Patch.Settings.KeyClicks & KeyClicks.On) > 0; if (Forms9Patch.Settings.KeyClicks == KeyClicks.Default) { // this no longer works and there doesn't appear to be a way to detect if keyclicks is on //var type = CFPreferences.CurrentApplication; CFPreferences.AppSynchronize("/var/mobile/Library/Preferences/com.apple.preferences.sounds"); soundEnabled = CFPreferences.GetAppBooleanValue("keyboard", "/var/mobile/Library/Preferences/com.apple.preferences.sounds"); } } if (soundEnabled) { switch (effect) { case HapticEffect.None: break; case HapticEffect.KeyClick: click.PlaySystemSoundAsync(); break; case HapticEffect.Return: modifier.PlaySystemSoundAsync(); break; case HapticEffect.Delete: delete.PlaySystemSoundAsync(); break; } } }
protected override IReadOnlyList <string> GetKeys() => CFArray.FromCFStringArray(CFPreferences.CopyKeyList( applicationId.Handle, CFPreferences.kCFPreferencesCurrentUser, CFPreferences.kCFPreferencesAnyHost)) ?? (IReadOnlyList <string>)Array.Empty <string> ();
protected override bool StorageTryGetValue( string key, Type valueType, TypeCode valueTypeCode, out object value) { using (var cfKey = new CFString(key)) { var valuePtr = CFPreferences.CopyValue( cfKey.Handle, applicationId.Handle, CFPreferences.kCFPreferencesCurrentUser, CFPreferences.kCFPreferencesAnyHost); if (valuePtr == IntPtr.Zero) { value = null; return(false); } var typeId = CoreFoundation.CFGetTypeID(valuePtr); if (typeId == CoreFoundation.CFTypeID.CFBoolean) { value = CFBoolean.ToBoolean(valuePtr); return(true); } if (typeId == CoreFoundation.CFTypeID.CFString) { using (var cfString = new CFString(valuePtr)) value = cfString.ToString(); return(true); } if (typeId == CoreFoundation.CFTypeID.CFNumber) { using (var cfNumber = new CFNumber(valuePtr)) { switch (cfNumber.Type) { case CFNumberType.SInt8: case CFNumberType.Char: value = valueTypeCode == TypeCode.Byte ? cfNumber.ToByte() : (object)cfNumber.ToSByte(); return(true); case CFNumberType.SInt16: case CFNumberType.Short: value = valueTypeCode == TypeCode.UInt16 ? cfNumber.ToUInt16() : (object)cfNumber.ToInt16(); return(true); case CFNumberType.SInt32: case CFNumberType.Int: case CFNumberType.Long: value = valueTypeCode == TypeCode.UInt32 ? cfNumber.ToUInt32() : (object)cfNumber.ToInt32(); return(true); case CFNumberType.SInt64: case CFNumberType.LongLong: case CFNumberType.CFIndex: case CFNumberType.NSInteger: value = valueTypeCode == TypeCode.UInt64 ? cfNumber.ToUInt64() : (object)cfNumber.ToInt64(); return(true); case CFNumberType.Float32: case CFNumberType.Float: value = cfNumber.ToSingle(); return(true); case CFNumberType.Float64: case CFNumberType.Double: case CFNumberType.CGFloat: value = cfNumber.ToDouble(); return(true); } } } if (typeId == CoreFoundation.CFTypeID.CFArray) { try { value = CFArray .FromCFStringArray(valuePtr) ?.ToArray(); return(value != null); } catch { value = null; return(false); } } value = null; return(false); } }