/* * Copyright (C) 2011, 2018 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "WKFullKeyboardAccessWatcher.h" #if ENABLE(FULL_KEYBOARD_ACCESS) #import "WebProcessPool.h" #if PLATFORM(IOS_FAMILY) #import "AccessibilitySupportSPI.h" #endif #if PLATFORM(MAC) static NSString * const KeyboardUIModeDidChangeNotification = @"com.apple.KeyboardUIModeDidChange"; static const CFStringRef AppleKeyboardUIMode = CFSTR("AppleKeyboardUIMode"); #endif @implementation WKFullKeyboardAccessWatcher static inline BOOL platformIsFullKeyboardAccessEnabled() { BOOL fullKeyboardAccessEnabled = NO; #if PLATFORM(MAC) CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); Boolean keyExistsAndHasValidFormat; int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat); if (keyExistsAndHasValidFormat) { // The keyboard access mode has two bits: // Bit 0 is set if user can set the focus to menus, the dock, and various windows using the keyboard. // Bit 1 is set if controls other than text fields are included in the tab order (WebKit also always includes lists). fullKeyboardAccessEnabled = (mode & 0x2); } #elif PLATFORM(IOS_FAMILY) fullKeyboardAccessEnabled = _AXSFullKeyboardAccessEnabled(); #endif return fullKeyboardAccessEnabled; } - (void)notifyAllProcessPools { for (auto& processPool : WebKit::WebProcessPool::allProcessPools()) processPool->fullKeyboardAccessModeChanged(fullKeyboardAccessEnabled); } - (void)retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification { BOOL oldValue = fullKeyboardAccessEnabled; fullKeyboardAccessEnabled = platformIsFullKeyboardAccessEnabled(); if (fullKeyboardAccessEnabled != oldValue) [self notifyAllProcessPools]; } - (id)init { self = [super init]; if (!self) return nil; [self retrieveKeyboardUIModeFromPreferences:nil]; NSNotificationCenter *notificationCenter = nil; NSString *notitificationName = nil; #if PLATFORM(MAC) notificationCenter = [NSDistributedNotificationCenter defaultCenter]; notitificationName = KeyboardUIModeDidChangeNotification; #elif PLATFORM(IOS_FAMILY) notificationCenter = [NSNotificationCenter defaultCenter]; notitificationName = (NSString *)kAXSFullKeyboardAccessEnabledNotification; #endif if (notitificationName) [notificationCenter addObserver:self selector:@selector(retrieveKeyboardUIModeFromPreferences:) name:notitificationName object:nil]; return self; } + (BOOL)fullKeyboardAccessEnabled { static WKFullKeyboardAccessWatcher *watcher = [[WKFullKeyboardAccessWatcher alloc] init]; return watcher->fullKeyboardAccessEnabled; } @end #endif // ENABLE(FULL_KEYBOARD_ACCESS)