Example #1
0
void
OSXKeyState::getKeyMapForSpecialKeys(synergy::KeyMap& keyMap, SInt32 group) const
{
	// special keys are insensitive to modifers and none are dead keys
	synergy::KeyMap::KeyItem item;
	for (size_t i = 0; i < sizeof(s_controlKeys) /
								sizeof(s_controlKeys[0]); ++i) {
		const KeyEntry& entry = s_controlKeys[i];
		item.m_id        = entry.m_keyID;
		item.m_group     = group;
		item.m_button    = mapVirtualKeyToKeyButton(entry.m_virtualKey);
		item.m_required  = 0;
		item.m_sensitive = 0;
		item.m_dead      = false;
		item.m_client    = 0;
		synergy::KeyMap::initModifierKey(item);
		keyMap.addKeyEntry(item);

		if (item.m_lock) {
			// all locking keys are half duplex on OS X
			keyMap.addHalfDuplexButton(item.m_button);
		}
	}

	// note:  we don't special case the number pad keys.  querying the
	// mac keyboard returns the non-keypad version of those keys but
	// a KeyState always provides a mapping from keypad keys to
	// non-keypad keys so we'll be able to generate the characters
	// anyway.
}
Example #2
0
bool
OSXKeyState::getKeyMap(synergy::KeyMap& keyMap,
				SInt32 group, const KeyResource& r) const
{
	if (!r.isValid()) {
		return false;
	}

	// space for all possible modifier combinations
	std::vector<bool> modifiers(r.getNumModifierCombinations());

	// make space for the keys that any single button can synthesize
	std::vector<std::pair<KeyID, bool> > buttonKeys(r.getNumTables());

	// iterate over each button
	synergy::KeyMap::KeyItem item;
	for (UInt32 i = 0; i < r.getNumButtons(); ++i) {
		item.m_button = mapVirtualKeyToKeyButton(i);

		// the KeyIDs we've already handled
		std::set<KeyID> keys;

		// convert the entry in each table for this button to a KeyID
		for (UInt32 j = 0; j < r.getNumTables(); ++j) {
			buttonKeys[j].first  = r.getKey(j, i);
			buttonKeys[j].second = synergy::KeyMap::isDeadKey(buttonKeys[j].first);
		}

		// iterate over each character table
		for (UInt32 j = 0; j < r.getNumTables(); ++j) {
			// get the KeyID for the button/table
			KeyID id = buttonKeys[j].first;
			if (id == kKeyNone) {
				continue;
			}

			// if we've already handled the KeyID in the table then
			// move on to the next table
			if (keys.count(id) > 0) {
				continue;
			}
			keys.insert(id);

			// prepare item.  the client state is 1 for dead keys.
			item.m_id     = id;
			item.m_group  = group;
			item.m_dead   = buttonKeys[j].second;
			item.m_client = buttonKeys[j].second ? 1 : 0;
			synergy::KeyMap::initModifierKey(item);
			if (item.m_lock) {
				// all locking keys are half duplex on OS X
				keyMap.addHalfDuplexButton(i);
			}

			// collect the tables that map to the same KeyID.  we know it
			// can't be any earlier tables because of the check above.
			std::set<UInt8> tables;
			tables.insert(static_cast<UInt8>(j));
			for (UInt32 k = j + 1; k < r.getNumTables(); ++k) {
				if (buttonKeys[k].first == id) {
					tables.insert(static_cast<UInt8>(k));
				}
			}

			// collect the modifier combinations that map to any of the
			// tables we just collected
			for (UInt32 k = 0; k < r.getNumModifierCombinations(); ++k) {
				modifiers[k] = (tables.count(r.getTableForModifier(k)) > 0);
			}

			// figure out which modifiers the key is sensitive to.  the
			// key is insensitive to a modifier if for every modifier mask
			// with the modifier bit unset in the modifiers we also find
			// the same mask with the bit set.
			//
			// we ignore a few modifiers that we know aren't important
			// for generating characters.  in fact, we want to ignore any
			// characters generated by the control key.  we don't map
			// those and instead expect the control modifier plus a key.
			UInt32 sensitive = 0;
			for (UInt32 k = 0; (1u << k) <
								r.getNumModifierCombinations(); ++k) {
				UInt32 bit = (1u << k);
				if ((bit << 8) == cmdKey ||
					(bit << 8) == controlKey ||
					(bit << 8) == rightControlKey) {
					continue;
				}
				for (UInt32 m = 0; m < r.getNumModifierCombinations(); ++m) {
					if (modifiers[m] != modifiers[m ^ bit]) {
						sensitive |= bit;
						break;
					}
				}
			}

			// find each required modifier mask.  the key can be synthesized
			// using any of the masks.
			std::set<UInt32> required;
			for (UInt32 k = 0; k < r.getNumModifierCombinations(); ++k) {
				if ((k & sensitive) == k && modifiers[k & sensitive]) {
					required.insert(k);
				}
			}

			// now add a key entry for each key/required modifier pair.
			item.m_sensitive = mapModifiersFromOSX(sensitive << 8);
			for (std::set<UInt32>::iterator k = required.begin();
											k != required.end(); ++k) {
				item.m_required = mapModifiersFromOSX(*k << 8);
				// Quick and dirty workaround for #2765
				// #2765 could be due to a bug in the Apple CoreServices
				// Framework
				if (item.m_id == 0x20 && item.m_button == 0x7 &&
						item.m_group == 0) {
					item.m_button = 0x32;
					LOG((CLOG_WARN "Key button for 0x20 patched"));
				}

				keyMap.addKeyEntry(item);
			}
		}
	}

	return true;
}