Applied patch 1547642, key broadcasting. Modified the patch to conform
to style guidelines. Also enhanced it to allow binding hot keys to not only toggling broadcasting but also turning it on or off, resized the hot key dialog to accommodate the keyboard broadcasting option, changed the configuration string for the keyboard broadcasting option, and added documentation. This change does not include the VS8 fix included in the patch.
This commit is contained in:
parent
d001ca488a
commit
b728885e25
|
@ -925,6 +925,8 @@ CInputFilter::CAction*
|
|||
CHotkeyOptions::CActionDialog::s_action = NULL;
|
||||
CInputFilter::CAction*
|
||||
CHotkeyOptions::CActionDialog::s_lastGoodAction = NULL;
|
||||
std::set<CString>
|
||||
CHotkeyOptions::CActionDialog::s_screens;
|
||||
WNDPROC CHotkeyOptions::CActionDialog::s_editWndProc = NULL;
|
||||
|
||||
bool
|
||||
|
@ -995,11 +997,21 @@ CHotkeyOptions::CActionDialog::doInit(HWND hwnd)
|
|||
// fill lock modes
|
||||
child = getItem(hwnd, IDC_HOTKEY_ACTION_LOCK_LIST);
|
||||
SendMessage(child, CB_ADDSTRING, 0,
|
||||
(LPARAM)getString(IDS_LOCK_MODE_OFF).c_str());
|
||||
(LPARAM)getString(IDS_MODE_OFF).c_str());
|
||||
SendMessage(child, CB_ADDSTRING, 0,
|
||||
(LPARAM)getString(IDS_LOCK_MODE_ON).c_str());
|
||||
(LPARAM)getString(IDS_MODE_ON).c_str());
|
||||
SendMessage(child, CB_ADDSTRING, 0,
|
||||
(LPARAM)getString(IDS_LOCK_MODE_TOGGLE).c_str());
|
||||
(LPARAM)getString(IDS_MODE_TOGGLE).c_str());
|
||||
SendMessage(child, CB_SETCURSEL, 0, 0);
|
||||
|
||||
// fill keyboard broadcast modes
|
||||
child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST);
|
||||
SendMessage(child, CB_ADDSTRING, 0,
|
||||
(LPARAM)getString(IDS_MODE_OFF).c_str());
|
||||
SendMessage(child, CB_ADDSTRING, 0,
|
||||
(LPARAM)getString(IDS_MODE_ON).c_str());
|
||||
SendMessage(child, CB_ADDSTRING, 0,
|
||||
(LPARAM)getString(IDS_MODE_TOGGLE).c_str());
|
||||
SendMessage(child, CB_SETCURSEL, 0, 0);
|
||||
|
||||
// select when
|
||||
|
@ -1011,6 +1023,9 @@ CHotkeyOptions::CActionDialog::doInit(HWND hwnd)
|
|||
}
|
||||
setItemChecked(child, true);
|
||||
|
||||
// no screens by default
|
||||
s_screens.clear();
|
||||
|
||||
// select mode
|
||||
child = NULL;
|
||||
CInputFilter::CKeystrokeAction* keyAction =
|
||||
|
@ -1023,6 +1038,8 @@ CHotkeyOptions::CActionDialog::doInit(HWND hwnd)
|
|||
dynamic_cast<CInputFilter::CSwitchToScreenAction*>(s_action);
|
||||
CInputFilter::CSwitchInDirectionAction* switchInAction =
|
||||
dynamic_cast<CInputFilter::CSwitchInDirectionAction*>(s_action);
|
||||
CInputFilter::CKeyboardBroadcastAction* keyboardBroadcastAction=
|
||||
dynamic_cast<CInputFilter::CKeyboardBroadcastAction*>(s_action);
|
||||
if (keyAction != NULL) {
|
||||
if (dynamic_cast<CKeystrokeDownUpAction*>(s_action) != NULL) {
|
||||
child = getItem(hwnd, IDC_HOTKEY_ACTION_DOWNUP);
|
||||
|
@ -1066,6 +1083,14 @@ CHotkeyOptions::CActionDialog::doInit(HWND hwnd)
|
|||
switchInAction->getDirection() - kLeft, 0);
|
||||
child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN);
|
||||
}
|
||||
else if (keyboardBroadcastAction != NULL) {
|
||||
// Save the screens we're broadcasting to
|
||||
s_screens = keyboardBroadcastAction->getScreens();
|
||||
|
||||
child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST);
|
||||
SendMessage(child, CB_SETCURSEL, keyboardBroadcastAction->getMode(), 0);
|
||||
child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST);
|
||||
}
|
||||
if (child != NULL) {
|
||||
setItemChecked(child, true);
|
||||
}
|
||||
|
@ -1111,12 +1136,18 @@ CHotkeyOptions::CActionDialog::updateControls(HWND hwnd)
|
|||
else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_LOCK))) {
|
||||
mode = 4;
|
||||
}
|
||||
else if (isItemChecked(getItem(hwnd,
|
||||
IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST))) {
|
||||
mode = 5;
|
||||
}
|
||||
|
||||
// enable/disable all mode specific controls
|
||||
enableItem(hwnd, IDC_HOTKEY_ACTION_HOTKEY, mode == 1);
|
||||
enableItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO_LIST, mode == 2);
|
||||
enableItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN_LIST, mode == 3);
|
||||
enableItem(hwnd, IDC_HOTKEY_ACTION_LOCK_LIST, mode == 4);
|
||||
enableItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST, mode == 5);
|
||||
enableItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS, mode == 5);
|
||||
|
||||
// can only set screens in key actions
|
||||
CInputFilter::CKeystrokeAction* keyAction =
|
||||
|
@ -1306,6 +1337,18 @@ CHotkeyOptions::CActionDialog::onSwitchInAction(HWND hwnd)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CHotkeyOptions::CActionDialog::onKeyboardBroadcastAction(HWND hwnd)
|
||||
{
|
||||
HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST);
|
||||
LRESULT index = SendMessage(child, CB_GETCURSEL, 0, 0);
|
||||
if (index != CB_ERR) {
|
||||
delete s_action;
|
||||
s_action = new CInputFilter::CKeyboardBroadcastAction(
|
||||
(CInputFilter::CKeyboardBroadcastAction::Mode)index, s_screens);
|
||||
}
|
||||
}
|
||||
|
||||
KeyID
|
||||
CHotkeyOptions::CActionDialog::getChar(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -1509,6 +1552,11 @@ CHotkeyOptions::CActionDialog::dlgProc(HWND hwnd,
|
|||
updateControls(hwnd);
|
||||
return TRUE;
|
||||
|
||||
case IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST:
|
||||
onKeyboardBroadcastAction(hwnd);
|
||||
updateControls(hwnd);
|
||||
return TRUE;
|
||||
|
||||
case IDC_HOTKEY_ACTION_LOCK_LIST:
|
||||
switch (HIWORD(wParam)) {
|
||||
case LBN_SELCHANGE:
|
||||
|
@ -1533,11 +1581,37 @@ CHotkeyOptions::CActionDialog::dlgProc(HWND hwnd,
|
|||
}
|
||||
break;
|
||||
|
||||
case IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST:
|
||||
switch (HIWORD(wParam)) {
|
||||
case LBN_SELCHANGE:
|
||||
onKeyboardBroadcastAction(hwnd);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_HOTKEY_ACTION_SCREENS:
|
||||
CScreensDialog::doModal(hwnd, s_config,
|
||||
dynamic_cast<CInputFilter::CKeystrokeAction*>(s_action));
|
||||
fillHotkey(hwnd);
|
||||
return TRUE;
|
||||
|
||||
case IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS: {
|
||||
// convert screens to form that CScreenDialog::doModal() wants
|
||||
IPlatformScreen::CKeyInfo* tmpInfo =
|
||||
IPlatformScreen::CKeyInfo::alloc(0, 0, 0, 1, s_screens);
|
||||
CInputFilter::CKeystrokeAction tmpAction(tmpInfo, true);
|
||||
|
||||
// get the screens
|
||||
CScreensDialog::doModal(hwnd, s_config, &tmpAction);
|
||||
|
||||
// convert screens back
|
||||
IPlatformScreen::CKeyInfo::split(
|
||||
tmpAction.getInfo()->m_screens, s_screens);
|
||||
|
||||
// update
|
||||
onKeyboardBroadcastAction(hwnd);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ private:
|
|||
static void onLockAction(HWND hwnd);
|
||||
static void onSwitchToAction(HWND hwnd);
|
||||
static void onSwitchInAction(HWND hwnd);
|
||||
static void onKeyboardBroadcastAction(HWND hwnd);
|
||||
|
||||
static KeyID getChar(WPARAM wParam, LPARAM lParam);
|
||||
static KeyModifierMask
|
||||
|
@ -176,6 +177,7 @@ private:
|
|||
s_action;
|
||||
static CInputFilter::CAction*
|
||||
s_lastGoodAction;
|
||||
static std::set<CString> s_screens;
|
||||
static WNDPROC s_editWndProc;
|
||||
};
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@ BEGIN
|
|||
PUSHBUTTON "Cancel",IDCANCEL,126,37,50,14
|
||||
END
|
||||
|
||||
IDD_HOTKEY_ACTION DIALOG DISCARDABLE 0, 0, 183, 202
|
||||
IDD_HOTKEY_ACTION DIALOG DISCARDABLE 0, 0, 183, 218
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Action"
|
||||
FONT 8, "MS Sans Serif"
|
||||
|
@ -356,6 +356,9 @@ BEGIN
|
|||
"Button",BS_AUTORADIOBUTTON,7,101,77,10
|
||||
CONTROL "Lock Cursor to Screen:",IDC_HOTKEY_ACTION_LOCK,"Button",
|
||||
BS_AUTORADIOBUTTON,7,117,89,10
|
||||
CONTROL "Keyboard broadcasting:",
|
||||
IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST,"Button",
|
||||
BS_AUTORADIOBUTTON,7,133,89,10
|
||||
LTEXT "&Hot key or mouse button:",IDC_STATIC,7,55,80,8
|
||||
EDITTEXT IDC_HOTKEY_ACTION_HOTKEY,7,67,152,12,ES_WANTRETURN
|
||||
PUSHBUTTON "...",IDC_HOTKEY_ACTION_SCREENS,162,67,14,12
|
||||
|
@ -365,13 +368,17 @@ BEGIN
|
|||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_HOTKEY_ACTION_LOCK_LIST,106,115,70,58,
|
||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Action takes place &when:",IDC_STATIC,7,137,81,8
|
||||
COMBOBOX IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST,106,131,53,58,
|
||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "...",IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS,
|
||||
162,131,14,12
|
||||
LTEXT "Action takes place &when:",IDC_STATIC,7,153,81,8
|
||||
CONTROL "Hot key is pressed",IDC_HOTKEY_ACTION_ON_ACTIVATE,
|
||||
"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,149,74,10
|
||||
"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,165,74,10
|
||||
CONTROL "Hot key is released",IDC_HOTKEY_ACTION_ON_DEACTIVATE,
|
||||
"Button",BS_AUTORADIOBUTTON,7,161,76,10
|
||||
DEFPUSHBUTTON "OK",IDOK,70,181,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,126,181,50,14
|
||||
"Button",BS_AUTORADIOBUTTON,7,177,76,10
|
||||
DEFPUSHBUTTON "OK",IDOK,70,197,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,126,197,50,14
|
||||
END
|
||||
|
||||
IDD_HOTKEY_SCREENS DIALOG DISCARDABLE 0, 0, 237, 79
|
||||
|
@ -586,9 +593,9 @@ BEGIN
|
|||
IDS_AUTOSTART_SAVE_FAILED "Failed to save autostart configuration: %{1}"
|
||||
IDS_LOAD_FAILED "Failed to load configuration."
|
||||
IDS_CONFIG_CHANGED "Configuration changed on disk. Reload?"
|
||||
IDS_LOCK_MODE_OFF "off"
|
||||
IDS_LOCK_MODE_ON "on"
|
||||
IDS_LOCK_MODE_TOGGLE "toggle"
|
||||
IDS_MODE_OFF "off"
|
||||
IDS_MODE_ON "on"
|
||||
IDS_MODE_TOGGLE "toggle"
|
||||
IDS_ALL_SCREENS "All Screens"
|
||||
IDS_ACTIVE_SCREEN "Active Screen"
|
||||
END
|
||||
|
|
|
@ -59,9 +59,9 @@
|
|||
#define IDS_AUTOSTART_SAVE_FAILED 54
|
||||
#define IDS_LOAD_FAILED 55
|
||||
#define IDS_CONFIG_CHANGED 56
|
||||
#define IDS_LOCK_MODE_OFF 57
|
||||
#define IDS_LOCK_MODE_ON 58
|
||||
#define IDS_LOCK_MODE_TOGGLE 59
|
||||
#define IDS_MODE_OFF 57
|
||||
#define IDS_MODE_ON 58
|
||||
#define IDS_MODE_TOGGLE 59
|
||||
#define IDS_ALL_SCREENS 60
|
||||
#define IDS_ACTIVE_SCREEN 61
|
||||
#define IDD_MAIN 101
|
||||
|
@ -169,6 +169,9 @@
|
|||
#define IDC_HOTKEY_SCREENS_DST 1096
|
||||
#define IDC_HOTKEY_SCREENS_ADD 1097
|
||||
#define IDC_HOTKEY_SCREENS_REMOVE 1098
|
||||
#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST 1099
|
||||
#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST 1100
|
||||
#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS 1101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
@ -177,7 +180,7 @@
|
|||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 116
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1098
|
||||
#define _APS_NEXT_CONTROL_VALUE 1102
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -406,6 +406,8 @@ Allowed individual actions are:
|
|||
<span class="arg">screens</span> lists the screen or screens to
|
||||
direct the event to, regardless of the active screen. If not
|
||||
given then the event is directed to the active screen only.
|
||||
(Due to a bug, keys cannot be directed to the server while on a
|
||||
client screen.)
|
||||
</p><p>
|
||||
<span class="code">keyDown</span> synthesizes a key press and
|
||||
<span class="code">keyUp</span> synthesizes a key release.
|
||||
|
@ -458,6 +460,30 @@ Allowed individual actions are:
|
|||
<span class="code">right</span>, <span class="code">up</span> or
|
||||
<span class="code">down</span>.
|
||||
</p><p>
|
||||
<li><a name="keyboardBroadcast"></a><span class="code">keyboardBroadcast(<span class="arg">mode</span>[,<span class="arg">screens</span>])</span>
|
||||
</p><p>
|
||||
Turns broadcasting of keystrokes to multiple screens on and off. When
|
||||
turned on all key presses and releases are sent to all of the screens
|
||||
listed in <span class="arg">screens</span>. If not given, empty or
|
||||
<span class="code">*</span> then keystrokes are broadcast to all screens.
|
||||
(However, due to a bug, keys cannot be sent to the server while on a
|
||||
client screen.)
|
||||
</p><p>
|
||||
<span class="arg">mode</span> can be <span class="code">off</span>
|
||||
to turn broadcasting off, <span class="code">on</span> to turn it
|
||||
on, or <span class="code">toggle</span> to toggle the current
|
||||
state. The default is <span class="code">toggle</span>.
|
||||
</p><p>
|
||||
<span class="arg">screens</span> is either <span class="code">*</span>
|
||||
to indicate all screens or a colon (:) separated list of screen
|
||||
names. (Note that the screen name must have already been encountered
|
||||
in the configuration file so you'll probably want to put actions at
|
||||
the bottom of the file.)
|
||||
</p><p>
|
||||
Multiple <span class="code">keyboardBroadcast</span> actions may be
|
||||
configured with different <span class="arg">screens</span>. The most
|
||||
recently performed action defines the screens to broadcast to.
|
||||
</p><p>
|
||||
</ul>
|
||||
</p><p>
|
||||
Examples:
|
||||
|
|
|
@ -1203,6 +1203,36 @@ CConfig::parseAction(CConfigReadContext& s,
|
|||
action = new CInputFilter::CLockCursorToScreenAction(mode);
|
||||
}
|
||||
|
||||
else if (name == "keyboardBroadcast") {
|
||||
if (args.size() > 2) {
|
||||
throw XConfigRead(s, "syntax for action: keyboardBroadcast([{off|on|toggle}[,screens]])");
|
||||
}
|
||||
|
||||
CInputFilter::CKeyboardBroadcastAction::Mode mode =
|
||||
CInputFilter::CKeyboardBroadcastAction::kToggle;
|
||||
if (args.size() >= 1) {
|
||||
if (args[0] == "off") {
|
||||
mode = CInputFilter::CKeyboardBroadcastAction::kOff;
|
||||
}
|
||||
else if (args[0] == "on") {
|
||||
mode = CInputFilter::CKeyboardBroadcastAction::kOn;
|
||||
}
|
||||
else if (args[0] == "toggle") {
|
||||
mode = CInputFilter::CKeyboardBroadcastAction::kToggle;
|
||||
}
|
||||
else {
|
||||
throw XConfigRead(s, "syntax for action: keyboardBroadcast([{off|on|toggle}[,screens]])");
|
||||
}
|
||||
}
|
||||
|
||||
std::set<CString> screens;
|
||||
if (args.size() >= 2) {
|
||||
parseScreens(s, args[1], screens);
|
||||
}
|
||||
|
||||
action = new CInputFilter::CKeyboardBroadcastAction(mode, screens);
|
||||
}
|
||||
|
||||
else {
|
||||
throw XConfigRead(s, "unknown action argument \"%{1}\"", name);
|
||||
}
|
||||
|
|
|
@ -268,13 +268,12 @@ CInputFilter::CAction::~CAction()
|
|||
// do nothing
|
||||
}
|
||||
|
||||
CInputFilter::CLockCursorToScreenAction::CLockCursorToScreenAction(Mode mode):
|
||||
CInputFilter::CLockCursorToScreenAction::CLockCursorToScreenAction(Mode mode) :
|
||||
m_mode(mode)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
CInputFilter::CLockCursorToScreenAction::Mode
|
||||
CInputFilter::CLockCursorToScreenAction::getMode() const
|
||||
{
|
||||
|
@ -400,6 +399,74 @@ CInputFilter::CSwitchInDirectionAction::perform(const CEvent& event)
|
|||
CEvent::kDeliverImmediately));
|
||||
}
|
||||
|
||||
CInputFilter::CKeyboardBroadcastAction::CKeyboardBroadcastAction(Mode mode) :
|
||||
m_mode(mode)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CInputFilter::CKeyboardBroadcastAction::CKeyboardBroadcastAction(
|
||||
Mode mode,
|
||||
const std::set<CString>& screens) :
|
||||
m_mode(mode),
|
||||
m_screens(IKeyState::CKeyInfo::join(screens))
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CInputFilter::CKeyboardBroadcastAction::Mode
|
||||
CInputFilter::CKeyboardBroadcastAction::getMode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
std::set<CString>
|
||||
CInputFilter::CKeyboardBroadcastAction::getScreens() const
|
||||
{
|
||||
std::set<CString> screens;
|
||||
IKeyState::CKeyInfo::split(m_screens.c_str(), screens);
|
||||
return screens;
|
||||
}
|
||||
|
||||
CInputFilter::CAction*
|
||||
CInputFilter::CKeyboardBroadcastAction::clone() const
|
||||
{
|
||||
return new CKeyboardBroadcastAction(*this);
|
||||
}
|
||||
|
||||
CString
|
||||
CInputFilter::CKeyboardBroadcastAction::format() const
|
||||
{
|
||||
static const char* s_mode[] = { "off", "on", "toggle" };
|
||||
static const char* s_name = "keyboardBroadcast";
|
||||
|
||||
if (m_screens.empty() || m_screens[0] == '*') {
|
||||
return CStringUtil::print("%s(%s)", s_name, s_mode[m_mode]);
|
||||
}
|
||||
else {
|
||||
return CStringUtil::print("%s(%s,%.*s)", s_name, s_mode[m_mode],
|
||||
m_screens.size() - 2,
|
||||
m_screens.c_str() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CInputFilter::CKeyboardBroadcastAction::perform(const CEvent& event)
|
||||
{
|
||||
static const CServer::CKeyboardBroadcastInfo::State s_state[] = {
|
||||
CServer::CKeyboardBroadcastInfo::kOff,
|
||||
CServer::CKeyboardBroadcastInfo::kOn,
|
||||
CServer::CKeyboardBroadcastInfo::kToggle
|
||||
};
|
||||
|
||||
// send event
|
||||
CServer::CKeyboardBroadcastInfo* info =
|
||||
CServer::CKeyboardBroadcastInfo::alloc(s_state[m_mode], m_screens);
|
||||
EVENTQUEUE->addEvent(CEvent(CServer::getKeyboardBroadcastEvent(),
|
||||
event.getTarget(), info,
|
||||
CEvent::kDeliverImmediately));
|
||||
}
|
||||
|
||||
CInputFilter::CKeystrokeAction::CKeystrokeAction(
|
||||
IPlatformScreen::CKeyInfo* info, bool press) :
|
||||
m_keyInfo(info),
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "IPlatformScreen.h"
|
||||
#include "CString.h"
|
||||
#include "stdmap.h"
|
||||
#include "stdset.h"
|
||||
|
||||
class CPrimaryClient;
|
||||
class CEvent;
|
||||
|
@ -173,6 +174,27 @@ public:
|
|||
EDirection m_direction;
|
||||
};
|
||||
|
||||
// CKeyboardBroadcastAction
|
||||
class CKeyboardBroadcastAction : public CAction {
|
||||
public:
|
||||
enum Mode { kOff, kOn, kToggle };
|
||||
|
||||
CKeyboardBroadcastAction(Mode = kToggle);
|
||||
CKeyboardBroadcastAction(Mode, const std::set<CString>& screens);
|
||||
|
||||
Mode getMode() const;
|
||||
std::set<CString> getScreens() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
private:
|
||||
Mode m_mode;
|
||||
CString m_screens;
|
||||
};
|
||||
|
||||
// CKeystrokeAction
|
||||
class CKeystrokeAction : public CAction {
|
||||
public:
|
||||
|
|
|
@ -39,6 +39,7 @@ CEvent::Type CServer::s_connectedEvent = CEvent::kUnknown;
|
|||
CEvent::Type CServer::s_disconnectedEvent = CEvent::kUnknown;
|
||||
CEvent::Type CServer::s_switchToScreen = CEvent::kUnknown;
|
||||
CEvent::Type CServer::s_switchInDirection = CEvent::kUnknown;
|
||||
CEvent::Type CServer::s_keyboardBroadcast = CEvent::kUnknown;
|
||||
CEvent::Type CServer::s_lockCursorToScreen = CEvent::kUnknown;
|
||||
|
||||
CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient) :
|
||||
|
@ -61,6 +62,7 @@ CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient) :
|
|||
m_switchTwoTapArmed(false),
|
||||
m_switchTwoTapZone(3),
|
||||
m_relativeMoves(false),
|
||||
m_keyboardBroadcasting(false),
|
||||
m_lockedToScreen(false)
|
||||
{
|
||||
// must have a primary client and it must have a canonical name
|
||||
|
@ -133,6 +135,10 @@ CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient) :
|
|||
m_inputFilter,
|
||||
new TMethodEventJob<CServer>(this,
|
||||
&CServer::handleSwitchInDirectionEvent));
|
||||
EVENTQUEUE->adoptHandler(getKeyboardBroadcastEvent(),
|
||||
m_inputFilter,
|
||||
new TMethodEventJob<CServer>(this,
|
||||
&CServer::handleKeyboardBroadcastEvent));
|
||||
EVENTQUEUE->adoptHandler(getLockCursorToScreenEvent(),
|
||||
m_inputFilter,
|
||||
new TMethodEventJob<CServer>(this,
|
||||
|
@ -355,6 +361,13 @@ CServer::getSwitchInDirectionEvent()
|
|||
"CServer::switchInDirection");
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CServer::getKeyboardBroadcastEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_keyboardBroadcast,
|
||||
"CServer:keyboardBroadcast");
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CServer::getLockCursorToScreenEvent()
|
||||
{
|
||||
|
@ -1364,6 +1377,37 @@ CServer::handleSwitchInDirectionEvent(const CEvent& event, void*)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServer::handleKeyboardBroadcastEvent(const CEvent& event, void*)
|
||||
{
|
||||
CKeyboardBroadcastInfo* info = (CKeyboardBroadcastInfo*)event.getData();
|
||||
|
||||
// choose new state
|
||||
bool newState;
|
||||
switch (info->m_state) {
|
||||
case CKeyboardBroadcastInfo::kOff:
|
||||
newState = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
case CKeyboardBroadcastInfo::kOn:
|
||||
newState = true;
|
||||
break;
|
||||
|
||||
case CKeyboardBroadcastInfo::kToggle:
|
||||
newState = !m_keyboardBroadcasting;
|
||||
break;
|
||||
}
|
||||
|
||||
// enter new state
|
||||
if (newState != m_keyboardBroadcasting ||
|
||||
info->m_screens != m_keyboardBroadcastingScreens) {
|
||||
m_keyboardBroadcasting = newState;
|
||||
m_keyboardBroadcastingScreens = info->m_screens;
|
||||
LOG((CLOG_DEBUG "keyboard broadcasting %s: %s", m_keyboardBroadcasting ? "on" : "off", m_keyboardBroadcastingScreens.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServer::handleLockCursorToScreenEvent(const CEvent& event, void*)
|
||||
{
|
||||
|
@ -1513,10 +1557,17 @@ CServer::onKeyDown(KeyID id, KeyModifierMask mask, KeyButton button,
|
|||
assert(m_active != NULL);
|
||||
|
||||
// relay
|
||||
if (IKeyState::CKeyInfo::isDefault(screens)) {
|
||||
if (!m_keyboardBroadcasting ||
|
||||
(screens && IKeyState::CKeyInfo::isDefault(screens))) {
|
||||
m_active->keyDown(id, mask, button);
|
||||
}
|
||||
else {
|
||||
if (!screens && m_keyboardBroadcasting) {
|
||||
screens = m_keyboardBroadcastingScreens.c_str();
|
||||
if (IKeyState::CKeyInfo::isDefault(screens)) {
|
||||
screens = "*";
|
||||
}
|
||||
}
|
||||
for (CClientList::const_iterator index = m_clients.begin();
|
||||
index != m_clients.end(); ++index) {
|
||||
if (IKeyState::CKeyInfo::contains(screens, index->first)) {
|
||||
|
@ -1534,10 +1585,17 @@ CServer::onKeyUp(KeyID id, KeyModifierMask mask, KeyButton button,
|
|||
assert(m_active != NULL);
|
||||
|
||||
// relay
|
||||
if (IKeyState::CKeyInfo::isDefault(screens)) {
|
||||
if (!m_keyboardBroadcasting ||
|
||||
(screens && IKeyState::CKeyInfo::isDefault(screens))) {
|
||||
m_active->keyUp(id, mask, button);
|
||||
}
|
||||
else {
|
||||
if (!screens && m_keyboardBroadcasting) {
|
||||
screens = m_keyboardBroadcastingScreens.c_str();
|
||||
if (IKeyState::CKeyInfo::isDefault(screens)) {
|
||||
screens = "*";
|
||||
}
|
||||
}
|
||||
for (CClientList::const_iterator index = m_clients.begin();
|
||||
index != m_clients.end(); ++index) {
|
||||
if (IKeyState::CKeyInfo::contains(screens, index->first)) {
|
||||
|
@ -2090,3 +2148,29 @@ CServer::CScreenConnectedInfo::alloc(const CString& screen)
|
|||
strcpy(info->m_screen, screen.c_str());
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CServer::CKeyboardBroadcastInfo
|
||||
//
|
||||
|
||||
CServer::CKeyboardBroadcastInfo*
|
||||
CServer::CKeyboardBroadcastInfo::alloc(State state)
|
||||
{
|
||||
CKeyboardBroadcastInfo* info =
|
||||
(CKeyboardBroadcastInfo*)malloc(sizeof(CKeyboardBroadcastInfo));
|
||||
info->m_state = state;
|
||||
info->m_screens[0] = '\0';
|
||||
return info;
|
||||
}
|
||||
|
||||
CServer::CKeyboardBroadcastInfo*
|
||||
CServer::CKeyboardBroadcastInfo::alloc(State state, const CString& screens)
|
||||
{
|
||||
CKeyboardBroadcastInfo* info =
|
||||
(CKeyboardBroadcastInfo*)malloc(sizeof(CKeyboardBroadcastInfo) +
|
||||
screens.size());
|
||||
info->m_state = state;
|
||||
strcpy(info->m_screens, screens.c_str());
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,20 @@ public:
|
|||
char m_screen[1];
|
||||
};
|
||||
|
||||
//! Keyboard broadcast data
|
||||
class CKeyboardBroadcastInfo {
|
||||
public:
|
||||
enum State { kOff, kOn, kToggle };
|
||||
|
||||
static CKeyboardBroadcastInfo* alloc(State state = kToggle);
|
||||
static CKeyboardBroadcastInfo* alloc(State state,
|
||||
const CString& screens);
|
||||
|
||||
public:
|
||||
State m_state;
|
||||
char m_screens[1];
|
||||
};
|
||||
|
||||
/*!
|
||||
Start the server with the configuration \p config and the primary
|
||||
client (local screen) \p primaryClient. The client retains
|
||||
|
@ -166,6 +180,14 @@ public:
|
|||
*/
|
||||
static CEvent::Type getSwitchInDirectionEvent();
|
||||
|
||||
//! Get keyboard broadcast event type
|
||||
/*!
|
||||
Returns the keyboard broadcast event type. The server responds
|
||||
to this by turning on keyboard broadcasting or turning it off. The
|
||||
event data is a \c CKeyboardBroadcastInfo*.
|
||||
*/
|
||||
static CEvent::Type getKeyboardBroadcastEvent();
|
||||
|
||||
//! Get lock cursor event type
|
||||
/*!
|
||||
Returns the lock cursor event type. The server responds to this
|
||||
|
@ -304,6 +326,7 @@ private:
|
|||
void handleClientCloseTimeout(const CEvent&, void*);
|
||||
void handleSwitchToScreenEvent(const CEvent&, void*);
|
||||
void handleSwitchInDirectionEvent(const CEvent&, void*);
|
||||
void handleKeyboardBroadcastEvent(const CEvent&,void*);
|
||||
void handleLockCursorToScreenEvent(const CEvent&, void*);
|
||||
void handleFakeInputBeginEvent(const CEvent&, void*);
|
||||
void handleFakeInputEndEvent(const CEvent&, void*);
|
||||
|
@ -421,6 +444,11 @@ private:
|
|||
// relative mouse move option
|
||||
bool m_relativeMoves;
|
||||
|
||||
// flag whether or not we have broadcasting enabled and the screens to
|
||||
// which we should send broadcasted keys.
|
||||
bool m_keyboardBroadcasting;
|
||||
CString m_keyboardBroadcastingScreens;
|
||||
|
||||
// screen locking (former scroll lock)
|
||||
bool m_lockedToScreen;
|
||||
|
||||
|
@ -429,6 +457,7 @@ private:
|
|||
static CEvent::Type s_disconnectedEvent;
|
||||
static CEvent::Type s_switchToScreen;
|
||||
static CEvent::Type s_switchInDirection;
|
||||
static CEvent::Type s_keyboardBroadcast;
|
||||
static CEvent::Type s_lockCursorToScreen;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,12 +53,13 @@ IKeyState::CKeyInfo*
|
|||
IKeyState::CKeyInfo::alloc(KeyID id,
|
||||
KeyModifierMask mask, KeyButton button, SInt32 count)
|
||||
{
|
||||
CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo));
|
||||
info->m_key = id;
|
||||
info->m_mask = mask;
|
||||
info->m_button = button;
|
||||
info->m_count = count;
|
||||
info->m_screens[0] = '\0';
|
||||
CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo));
|
||||
info->m_key = id;
|
||||
info->m_mask = mask;
|
||||
info->m_button = button;
|
||||
info->m_count = count;
|
||||
info->m_screens = NULL;
|
||||
info->m_screensBuffer[0] = '\0';
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -67,44 +68,30 @@ IKeyState::CKeyInfo::alloc(KeyID id,
|
|||
KeyModifierMask mask, KeyButton button, SInt32 count,
|
||||
const std::set<CString>& destinations)
|
||||
{
|
||||
// collect destinations into a string. names are surrounded by ':'
|
||||
// which makes searching easy later. the string is empty if there
|
||||
// are no destinations and "*" means all destinations.
|
||||
CString screens;
|
||||
for (std::set<CString>::const_iterator i = destinations.begin();
|
||||
i != destinations.end(); ++i) {
|
||||
if (*i == "*") {
|
||||
screens = "*";
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (screens.empty()) {
|
||||
screens = ":";
|
||||
}
|
||||
screens += *i;
|
||||
screens += ":";
|
||||
}
|
||||
}
|
||||
CString screens = join(destinations);
|
||||
|
||||
// build structure
|
||||
CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo) + screens.size());
|
||||
info->m_key = id;
|
||||
info->m_mask = mask;
|
||||
info->m_button = button;
|
||||
info->m_count = count;
|
||||
strcpy(info->m_screens, screens.c_str());
|
||||
CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo) + screens.size());
|
||||
info->m_key = id;
|
||||
info->m_mask = mask;
|
||||
info->m_button = button;
|
||||
info->m_count = count;
|
||||
info->m_screens = info->m_screensBuffer;
|
||||
strcpy(info->m_screensBuffer, screens.c_str());
|
||||
return info;
|
||||
}
|
||||
|
||||
IKeyState::CKeyInfo*
|
||||
IKeyState::CKeyInfo::alloc(const CKeyInfo& x)
|
||||
{
|
||||
CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo) + strlen(x.m_screens));
|
||||
info->m_key = x.m_key;
|
||||
info->m_mask = x.m_mask;
|
||||
info->m_button = x.m_button;
|
||||
info->m_count = x.m_count;
|
||||
strcpy(info->m_screens, x.m_screens);
|
||||
CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo) +
|
||||
strlen(x.m_screensBuffer));
|
||||
info->m_key = x.m_key;
|
||||
info->m_mask = x.m_mask;
|
||||
info->m_button = x.m_button;
|
||||
info->m_count = x.m_count;
|
||||
info->m_screens = x.m_screens ? info->m_screensBuffer : NULL;
|
||||
strcpy(info->m_screensBuffer, x.m_screensBuffer);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -141,7 +128,31 @@ IKeyState::CKeyInfo::equal(const CKeyInfo* a, const CKeyInfo* b)
|
|||
a->m_mask == b->m_mask &&
|
||||
a->m_button == b->m_button &&
|
||||
a->m_count == b->m_count &&
|
||||
strcmp(a->m_screens, b->m_screens) == 0);
|
||||
strcmp(a->m_screensBuffer, b->m_screensBuffer) == 0);
|
||||
}
|
||||
|
||||
CString
|
||||
IKeyState::CKeyInfo::join(const std::set<CString>& destinations)
|
||||
{
|
||||
// collect destinations into a string. names are surrounded by ':'
|
||||
// which makes searching easy. the string is empty if there are no
|
||||
// destinations and "*" means all destinations.
|
||||
CString screens;
|
||||
for (std::set<CString>::const_iterator i = destinations.begin();
|
||||
i != destinations.end(); ++i) {
|
||||
if (*i == "*") {
|
||||
screens = "*";
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (screens.empty()) {
|
||||
screens = ":";
|
||||
}
|
||||
screens += *i;
|
||||
screens += ":";
|
||||
}
|
||||
}
|
||||
return screens;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
static bool isDefault(const char* screens);
|
||||
static bool contains(const char* screens, const CString& name);
|
||||
static bool equal(const CKeyInfo*, const CKeyInfo*);
|
||||
static CString join(const std::set<CString>& destinations);
|
||||
static void split(const char* screens, std::set<CString>&);
|
||||
|
||||
public:
|
||||
|
@ -50,7 +51,8 @@ public:
|
|||
KeyModifierMask m_mask;
|
||||
KeyButton m_button;
|
||||
SInt32 m_count;
|
||||
char m_screens[1];
|
||||
char* m_screens;
|
||||
char m_screensBuffer[1];
|
||||
};
|
||||
|
||||
typedef std::set<KeyButton> KeyButtonSet;
|
||||
|
|
Loading…
Reference in New Issue