Adds "push to talk" functionality. The default shortcut for push to talk is "Shift Ctrl/Meta T". Native global shortcuts are now committed only for Mac. Windows and Linux coming soon. Patch provided by Hristo Terezov on dev (March 25, 2013, subject: "Re: [jitsi-dev] [PATCH] Push to talk"). Additionally this commit also removes the ppc command from the globalshortcut target.

cusax-fix
Yana Stamcheva 13 years ago
parent 39c1998b9f
commit 77b1249b45

@ -77,6 +77,7 @@ impl.keybinding.global.hangup.1=shift ctrl pressed H
impl.keybinding.global.answer_hangup.1=shift ctrl pressed P
impl.keybinding.global.contactlist.1=shift ctrl pressed L
impl.keybinding.global.mute.1=shift ctrl pressed M
impl.keybinding.global.push_to_talk.1=shift ctrl pressed T
# Default provisioning method
plugin.provisioning.IS_INITIAL_PROVISIONING_LINK=true

@ -1280,6 +1280,7 @@ plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primary shortcut
plugin.keybindings.globalchooser.SHORTCUT_SECOND=Second shortcut
plugin.keybindings.globalchooser.PRESS_BTN=Press to set shortcut
plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Waiting
plugin.keybindings.globalchooser.PUSH_TO_TALK=Push to talk
plugin.keybindings.globalchooser.ENABLE_SPECIAL=Enable special key detection
plugin.keybindings.PLUGIN_NAME=Keybindings
plugin.keybindings.CHAT=Chat

@ -709,8 +709,6 @@
<compilerarg value="x86_64" if="is.running.macos"/>
<compilerarg value="-arch" if="is.running.macos"/>
<compilerarg value="i386" if="is.running.macos"/>
<compilerarg value="-arch" if="is.running.macos"/>
<compilerarg value="ppc" if="is.running.macos"/>
<compilerarg value="-I/System/Library/Frameworks/JavaVM.framework/Headers"
if="is.running.macos"/>
@ -721,8 +719,6 @@
<linkerarg value="x86_64" if="is.running.macos"/>
<linkerarg value="-arch" if="is.running.macos"/>
<linkerarg value="i386" if="is.running.macos"/>
<linkerarg value="-arch" if="is.running.macos"/>
<linkerarg value="ppc" if="is.running.macos"/>
<linkerarg value="-framework" if="is.running.macos"/>
<linkerarg value="Foundation" if="is.running.macos"/>
<linkerarg value="-framework" if="is.running.macos"/>

@ -29,7 +29,6 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
- (id) object { return nil; }
- (unsigned short) keyCode { return 0; }
- (NSUInteger) modifierFlags { return 0; }
#if NS_BLOCKS_AVAILABLE
- (DDHotKeyTask) task { return nil; }
#endif
@ -72,6 +71,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
NSUInteger modifierFlags;
UInt32 hotKeyID;
NSValue * hotKeyRef;
BOOL isOnKeyRelease;
}
@property (nonatomic, retain) id target;
@ -81,6 +81,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
@property (nonatomic) NSUInteger modifierFlags;
@property (nonatomic) UInt32 hotKeyID;
@property (nonatomic, retain) NSValue * hotKeyRef;
@property (nonatomic) BOOL isOnKeyRelease;
#if NS_BLOCKS_AVAILABLE
@property (nonatomic, copy) DDHotKeyTask task;
@ -94,7 +95,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
@implementation _DDHotKey
@synthesize target, action, object, keyCode, modifierFlags, hotKeyID, hotKeyRef;
@synthesize target, action, object, keyCode, modifierFlags, hotKeyID, hotKeyRef, isOnKeyRelease;
#if NS_BLOCKS_AVAILABLE
@synthesize task;
#endif
@ -167,10 +168,9 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
if (self == [DDHotKeyCenter class] && _registeredHotKeys == nil) {
_registeredHotKeys = [[NSMutableSet alloc] init];
_nextHotKeyID = 1;
EventTypeSpec eventSpec;
eventSpec.eventClass = kEventClassKeyboard;
eventSpec.eventKind = kEventHotKeyReleased;
InstallApplicationEventHandler(&dd_hotKeyHandler, 1, &eventSpec, NULL, NULL);
EventTypeSpec eventSpec[2] = {{kEventClassKeyboard, kEventHotKeyPressed},
{kEventClassKeyboard, kEventHotKeyReleased}};
InstallApplicationEventHandler(&dd_hotKeyHandler, 2, &eventSpec, NULL, NULL);
}
}
@ -184,7 +184,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
}
#if NS_BLOCKS_AVAILABLE
- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task {
- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task inIsOnKeyRelease:(BOOL)keyRelease {
//we can't add a new hotkey if something already has this combo
if ([self hasRegisteredHotKeyWithKeyCode:keyCode modifierFlags:flags]) { return NO; }
@ -192,6 +192,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
[newHotKey setTask:task];
[newHotKey setKeyCode:keyCode];
[newHotKey setModifierFlags:flags];
[newHotKey setIsOnKeyRelease:keyRelease];
BOOL success = [newHotKey registerHotKey];
if (success) {
@ -203,7 +204,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
}
#endif
- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags target:(id)target action:(SEL)action object:(id)object {
- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags target:(id)target action:(SEL)action object:(id)object inIsOnKeyRelease:(BOOL)keyRelease {
//we can't add a new hotkey if something already has this combo
if ([self hasRegisteredHotKeyWithKeyCode:keyCode modifierFlags:flags]) { return NO; }
@ -214,6 +215,7 @@ NSString* dd_stringifyModifierFlags(NSUInteger flags);
[newHotKey setObject:object];
[newHotKey setKeyCode:keyCode];
[newHotKey setModifierFlags:flags];
[newHotKey setIsOnKeyRelease:keyRelease];
BOOL success = [newHotKey registerHotKey];
if (success) {
@ -275,11 +277,24 @@ OSStatus dd_hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, vo
NSSet * matchingHotKeys = [_registeredHotKeys filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"hotKeyID = %u", keyID]];
if ([matchingHotKeys count] > 1) { NSLog(@"ERROR!"); }
_DDHotKey * matchingHotKey = [matchingHotKeys anyObject];
if(![matchingHotKey isOnKeyRelease] && GetEventKind(theEvent) == kEventHotKeyReleased)
{
return noErr;
}
NSEvent * event = [NSEvent eventWithEventRef:theEvent];
NSEvent * keyEvent = [NSEvent keyEventWithType:NSKeyUp
NSEventType type;
if(GetEventKind(theEvent) == kEventHotKeyReleased)
{
type = NSKeyUp;
}
else
{
type = NSKeyDown;
}
NSEvent * keyEvent = [NSEvent keyEventWithType:type
location:[event locationInWindow]
modifierFlags:[event modifierFlags]
modifierFlags:[matchingHotKey modifierFlags]
timestamp:[event timestamp]
windowNumber:-1
context:nil

@ -34,6 +34,7 @@ class keystrok
int vkcode; /**< Virtual keycode. */
int modifiers; /**< Modifiers (ALT, CTLR, ...). */
int active; /**< If the hotkey is active. */
bool onrelease; /**< If the java should be notified on release. */
};
/**
@ -659,7 +660,7 @@ static int JavaUserDefinedModifiersToX11(int modifiers)
* \param keycode keycode
* \param modifiers modifiers used (SHIFT, CTRL, ALT, LOGO)
*/
static void notify(struct keyboard_hook* keyboard, jint keycode, jint modifiers)
static void notify(struct keyboard_hook* keyboard, jint keycode, jint modifiers, jboolean on_key_release)
{
JNIEnv *jniEnv = NULL;
jclass delegateClass = NULL;
@ -680,11 +681,11 @@ static void notify(struct keyboard_hook* keyboard, jint keycode, jint modifiers)
{
jmethodID methodid = NULL;
methodid = jniEnv->GetMethodID(delegateClass, "receiveKey", "(II)V");
methodid = jniEnv->GetMethodID(delegateClass, "receiveKey", "(IIZ)V");
if(methodid)
{
jniEnv->CallVoidMethod(keyboard->delegate, methodid, keycode, modifiers);
jniEnv->CallVoidMethod(keyboard->delegate, methodid, keycode, modifiers, on_key_release);
}
}
jniEnv->ExceptionClear();
@ -698,8 +699,7 @@ static void notify(struct keyboard_hook* keyboard, jint keycode, jint modifiers)
static void* x11_event_loop_thread(void* arg)
{
struct keyboard_hook* keyboard = (struct keyboard_hook*)arg;
XSelectInput(keyboard->display, keyboard->root, KeyPressMask);
XSelectInput(keyboard->display, keyboard->root, KeyPressMask | KeyReleaseMask);
while(keyboard->running)
{
@ -709,9 +709,14 @@ static void* x11_event_loop_thread(void* arg)
switch (ev.type)
{
case KeyPress:
case KeyRelease:
for(std::list<keystrok>::iterator it = keyboard->keystrokes.begin() ; it != keyboard->keystrokes.end() ; ++it)
{
keystrok& ks = (*it);
if(ev.type == KeyRelease && !ks.onrelease)
{
continue;
}
XKeyEvent* keyEvent = (XKeyEvent*)&ev.xkey;
unsigned long keycode = -1;
//XKeycodeToKeysym(keyboard->display, keyEvent->keycode, 1);
@ -723,7 +728,7 @@ static void* x11_event_loop_thread(void* arg)
if(ks.vkcode == keycode && ks.modifiers == modifiers)
{
notify(keyboard, ks.vkcode, ks.modifiers);
notify(keyboard, ks.vkcode, ks.modifiers, (ev.type == KeyRelease));
}
}
@ -736,7 +741,7 @@ static void* x11_event_loop_thread(void* arg)
for(std::list<keystrok>::iterator it = keyboard->keystrokes.begin() ; it != keyboard->keystrokes.end() ; ++it)
{
keystrok& ks = (*it);
if(ks.active == 0)
{
/* hotkey to add */
@ -752,7 +757,6 @@ static void* x11_event_loop_thread(void* arg)
continue;
}
int x11Modifiers = JavaUserDefinedModifiersToX11(ks.modifiers);
ks.active = 1;
if(XGrabKey(keyboard->display, x11Keycode, x11Modifiers, keyboard->root, False, GrabModeAsync, GrabModeAsync) > 1)
{
@ -786,7 +790,6 @@ JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Nativ
(JNIEnv* jniEnv, jclass clazz)
{
struct keyboard_hook* keyboard = NULL;
(void)jniEnv;
(void)clazz;
@ -879,20 +882,19 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
}
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerShortcut
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jint modifiers)
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jint modifiers, jboolean is_on_key_release)
{
struct keyboard_hook* keyboard = (struct keyboard_hook*)ptr;
(void)jniEnv;
(void)clazz;
if(keyboard)
{
keystrok ks;
ks.vkcode = keycode;
ks.modifiers = modifiers;
ks.active = 0;
ks.onrelease = is_on_key_release;
keyboard->keystrokes.push_back(ks);
return JNI_TRUE;
@ -923,7 +925,7 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
}
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerSpecial
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode)
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jboolean is_on_key_release)
{
(void)jniEnv;
(void)clazz;

@ -44,6 +44,31 @@ class keystrok
int modifiers; /**< Modifiers (ALT, CTLR, ...). */
int id; /**< ID. */
int active; /**< If the hotkey is active. */
bool is_on_key_release; /**< If java object delegate should be notified
when the hotkey is released. */
};
/**
* \class keystroke_special
* \brief keystroke class for special keystrokes.
*/
class keystroke_special
{
public:
int keycode; /**< Keycode. */
bool is_on_key_release; /**< If java object delegate should be notified
when the hotkey is released. */
};
/**
* \class hotkey_release
* \brief stores information about hotkey that will be realesed.
*/
class hotkey_release
{
public:
std::list<DWORD> vkcodes; /**< Virtual keycode that is pressed. */
int java_keycode; /**< keycode of the hotkey that is pressed. */
int java_modifiers; /**< modifiers (ALT, CTLR, ...) of the hotkey that is pressed. */
};
/**
@ -61,8 +86,10 @@ class keyboard_hook
HWND hwnd; /**< Handle of the window that will receive event. */
int hotkey_next_id; /**< Next ID to use for a new hotkey. */
std::list<keystrok> keystrokes; /**< List of keystrokes registered. */
std::list<int> specials; /**< List of special keystrokes registered. */
std::list<keystroke_special> specials; /**< List of special keystrokes registered. */
bool detect; /**< If we are in detection mode. */
hotkey_release hk_release; /**< hotkey that is pressed and it will notify
the java object delegate on release. */
};
/**
@ -732,12 +759,53 @@ static int convertJavaUserDefinedModifiersToWindows(int modifiers)
return winModifiers;
}
/**
* \brief Sets the current pressed hotkey in g_keyboard_hook.
* \param modifiers modifiers of the hotkey
* \param keycode keycode of the hotkey
* \param java_modifiers original modifiers which were used to call notify function
* \param java_keycode original keycode which wes used to call notify function
*/
static void setHotkeyRealese(int modifiers, DWORD keycode, int java_modifiers, int java_keycode)
{
hotkey_release *hk_release = &(g_keyboard_hook.hk_release);
if(modifiers & MOD_CONTROL)
{
/* CTRL */
hk_release->vkcodes.push_back(VK_RCONTROL);
hk_release->vkcodes.push_back(VK_CONTROL);
}
if(modifiers & MOD_ALT)
{
/* ALT */
hk_release->vkcodes.push_back(VK_MENU);
}
if(modifiers & MOD_SHIFT)
{
/* SHIFT */
hk_release->vkcodes.push_back(VK_SHIFT);
hk_release->vkcodes.push_back(VK_LSHIFT);
hk_release->vkcodes.push_back(VK_RSHIFT);
}
if(modifiers & MOD_WIN)
{
/* LOGO */
hk_release->vkcodes.push_back(VK_LWIN);
hk_release->vkcodes.push_back(VK_RWIN);
}
hk_release->vkcodes.push_back(keycode);
hk_release->java_modifiers = java_modifiers;
hk_release->java_keycode = java_keycode;
}
/**
* \brief Notify Java side about key pressed (keycode + modifiers).
* \param keycode keycode
* \param modifiers modifiers used (SHIFT, CTRL, ALT, LOGO)
* \param on_key_release true - if the hotkey is released
*/
static void notify(jint keycode, jint modifiers)
static void notify(jint keycode, jint modifiers, jboolean on_key_release)
{
JNIEnv *jniEnv = NULL;
jclass delegateClass = NULL;
@ -751,18 +819,16 @@ static void notify(jint keycode, jint modifiers)
{
return;
}
delegateClass = jniEnv->GetObjectClass(g_keyboard_hook.delegate);
if(delegateClass)
{
jmethodID methodid = NULL;
methodid = jniEnv->GetMethodID(delegateClass, "receiveKey", "(II)V");
methodid = jniEnv->GetMethodID(delegateClass, "receiveKey", "(IIZ)V");
if(methodid)
{
jniEnv->CallVoidMethod(g_keyboard_hook.delegate, methodid, keycode, modifiers);
jniEnv->CallVoidMethod(g_keyboard_hook.delegate, methodid, keycode, modifiers, on_key_release);
}
}
jniEnv->ExceptionClear();
@ -776,49 +842,53 @@ static void notify(jint keycode, jint modifiers)
*/
HRESULT callback(UINT msg, WPARAM wParam, LPARAM lParam)
{
keyboard_hook* keyboard = &g_keyboard_hook;
for(std::list<keystrok>::iterator it = keyboard->keystrokes.begin() ; it != keyboard->keystrokes.end() ; ++it)
if(msg == WM_HOTKEY)
{
keystrok& ks = (*it);
if(ks.active == 0)
keyboard_hook* keyboard = &g_keyboard_hook;
if(keyboard->hwnd)
{
/* hotkey to add */
ks.active = 1;
if(!RegisterHotKey(keyboard->hwnd, ks.id, ks.modifiers, ks.vkcode))
{
fprintf(stderr, "[LOOP] Problem with RegisterHotKey: %d\n", GetLastError());fflush(stderr);
ks.active = -1;
}
}
else if(ks.active == -1)
{
/* hotkey to remove */
if(!UnregisterHotKey(keyboard->hwnd, ks.id))
{
//fprintf(stderr, "[LOOP] Error when UnregisterHotKey: %d\n", GetLastError());fflush(stderr);
}
it = keyboard->keystrokes.erase(it)--;
for(std::list<keystrok>::iterator it = keyboard->keystrokes.begin() ; it != keyboard->keystrokes.end() ; ++it)
{
keystrok& ks = (*it);
if(ks.active == 0)
{
/* hotkey to add */
ks.active = 1;
if(!RegisterHotKey(keyboard->hwnd, ks.id, ks.modifiers | MOD_NOREPEAT, ks.vkcode))
{
fprintf(stderr, "[LOOP] Problem with RegisterHotKey: %d\n", GetLastError());fflush(stderr);
ks.active = -1;
}
}
else if(ks.active == -1)
{
/* hotkey to remove */
if(!UnregisterHotKey(keyboard->hwnd, ks.id))
{
//fprintf(stderr, "[LOOP] Error when UnregisterHotKey: %d\n", GetLastError());fflush(stderr);
}
it = keyboard->keystrokes.erase(it)--;
}
}
}
}
if(msg == WM_HOTKEY)
{
for(std::list<keystrok>::iterator it = g_keyboard_hook.keystrokes.begin() ; it != g_keyboard_hook.keystrokes.end() ; ++it)
{
keystrok ks = (*it);
/* check via hotkey id */
if(ks.id == wParam)
{
int javaModifiers = 0;
int javaKeycode = 0;
javaKeycode = convertWindowsKeycodeToJava(HIWORD(lParam)); //ks.vkcode);
javaModifiers = convertWindowsModifiersToJavaUserDefined(ks.modifiers);
notify(javaKeycode, javaModifiers);
notify(javaKeycode, javaModifiers, false);
if(ks.is_on_key_release)
{
setHotkeyRealese(ks.modifiers, ks.vkcode, javaModifiers, javaKeycode);
}
return 0;
}
}
@ -852,7 +922,6 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
static void RegisterWindowClassW(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
memset(&wcex, 0x00, sizeof(WNDCLASSEXW));
wcex.cbSize = sizeof(WNDCLASSEXW);
wcex.style = CS_HREDRAW | CS_VREDRAW;
@ -883,27 +952,50 @@ static void RegisterWindowClassW(HINSTANCE hInstance)
*/
LRESULT CALLBACK keyHandler(int nCode, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT* kbd = (KBDLLHOOKSTRUCT*)lParam;
int pressed = wParam == WM_KEYDOWN;
if(pressed && kbd->vkCode > 160)
{
if(g_keyboard_hook.detect)
{
notify(kbd->vkCode, 16367);
notify(kbd->vkCode, 16367, false);
}
else
{
for(std::list<int>::const_iterator it = g_keyboard_hook.specials.begin() ; it != g_keyboard_hook.specials.end() ; ++it)
for(std::list<keystroke_special>::const_iterator it = g_keyboard_hook.specials.begin() ; it != g_keyboard_hook.specials.end() ; ++it)
{
if((*it)== kbd->vkCode)
if(it->keycode == kbd->vkCode)
{
notify((*it), 16367);
notify(it->keycode, 16367, false);
if(it->is_on_key_release)
{
setHotkeyRealese(0, it->keycode, 16367, it->keycode);
}
break;
}
}
}
}
if(!pressed)
{
hotkey_release* hk = &(g_keyboard_hook.hk_release);
for(
std::list<DWORD>::iterator it = hk->vkcodes.begin() ;
it != hk->vkcodes.end() ;
++it
)
{
if((*it) == kbd->vkCode)
{
notify(hk->java_keycode, hk->java_modifiers, true);
hk->vkcodes.clear();
break;
}
}
}
return CallNextHookEx(g_keyboard_hook.hook, nCode, wParam, lParam);
}
@ -935,6 +1027,7 @@ static unsigned WINAPI CreateWndThreadW(LPVOID pThreadParam)
MSG msg;
keyboard->hwnd = hWnd;
PostMessage(keyboard->hwnd, WM_HOTKEY, 0, 0);
while(GetMessageW(&msg, hWnd, 0, 0))
{
@ -1005,11 +1098,10 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
}
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerShortcut
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jint modifiers)
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jint modifiers, jboolean is_on_key_release)
{
keyboard_hook* keyboard = (keyboard_hook*)ptr;
if(keyboard && keyboard->hwnd)
if(keyboard)
{
int winModifiers = 0;
int winKeycode = 0;
@ -1022,9 +1114,14 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Na
ks.modifiers = winModifiers;
ks.id = keyboard->hotkey_next_id;
ks.active = 0;
ks.is_on_key_release = is_on_key_release;
keyboard->keystrokes.push_back(ks);
keyboard->hotkey_next_id++;
PostMessage(keyboard->hwnd, WM_HOTKEY, 0, 0);
if(keyboard->hwnd)
{
PostMessage(keyboard->hwnd, WM_HOTKEY, 0, 0);
return true;
}
return true;
}
return false;
@ -1056,13 +1153,16 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
}
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerSpecial
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode)
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jboolean is_on_key_release)
{
struct keyboard_hook* keyboard = (struct keyboard_hook*)ptr;
if(keyboard && keyboard->hook != NULL)
{
keyboard->specials.push_back((int)keycode);
keystroke_special kss;
kss.keycode = keycode;
kss.is_on_key_release = is_on_key_release;
keyboard->specials.push_back(kss);
return JNI_TRUE;
}
return JNI_FALSE;
@ -1075,10 +1175,10 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
if(keyboard)
{
for(std::list<int>::iterator it = keyboard->specials.begin() ;
for(std::list<keystroke_special>::iterator it = keyboard->specials.begin() ;
it != keyboard->specials.end() ; ++it)
{
if((*it) == keycode)
if(it->keycode == keycode)
{
keyboard->specials.erase(it);
return;

@ -42,10 +42,10 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
/*
* Class: net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook
* Method: registerShortcut
* Signature: (JII)Z
* Signature: (JIIZ)Z
*/
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerShortcut
(JNIEnv *, jclass, jlong, jint, jint);
(JNIEnv *, jclass, jlong, jint, jint, jboolean);
/*
* Class: net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook
@ -58,10 +58,10 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
/*
* Class: net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook
* Method: registerSpecial
* Signature: (JI)Z
* Signature: (JIZ)Z
*/
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerSpecial
(JNIEnv *, jclass, jlong, jint);
(JNIEnv *, jclass, jlong, jint, jboolean);
/*
* Class: net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook

@ -717,7 +717,7 @@ static int convertMacModifiersToJavaUserDefined(int modifiers)
@end
@implementation KeyboardHook
-(void) notify:(int) keyCode inModifiers:(int)modifiers;
-(void) notify:(int) keyCode inModifiers:(int)modifiers inReleased:(BOOL)released;
{
jobject delegate;
JNIEnv* jniEnv = NULL;
@ -736,10 +736,10 @@ static int convertMacModifiersToJavaUserDefined(int modifiers)
{
jmethodID methodid = NULL;
methodid = (*jniEnv)->GetMethodID(jniEnv, delegateClass,"receiveKey", "(II)V");
methodid = (*jniEnv)->GetMethodID(jniEnv, delegateClass,"receiveKey", "(IIZ)V");
if(methodid)
{
(*jniEnv)->CallVoidMethod(jniEnv, delegate, methodid, keyCode, modifiers);
(*jniEnv)->CallVoidMethod(jniEnv, delegate, methodid, keyCode, modifiers, released);
}
}
(*jniEnv)->ExceptionClear(jniEnv);
@ -779,7 +779,7 @@ static int convertMacModifiersToJavaUserDefined(int modifiers)
javaKeycode = convertMacKeycodeToJava(keycode);
javaModifiers = convertMacModifiersToJavaUserDefined(modifiers);
[self notify:javaKeycode inModifiers:javaModifiers];
[self notify:javaKeycode inModifiers:javaModifiers inReleased:([hotKeyEvent type] == NSKeyUp)];
}
- (id)init
@ -798,7 +798,7 @@ static int convertMacModifiersToJavaUserDefined(int modifiers)
[super dealloc];
}
- (int) registerKey:(int)keycode inModifiers:(int)modifiers
- (int) registerKey:(int)keycode inModifiers:(int)modifiers inIsOnKeyRelease:(BOOL)isOnKeyRelease
{
NSAutoreleasePool* autoreleasePool = NULL;
DDHotKeyCenter* c = NULL;
@ -813,7 +813,7 @@ static int convertMacModifiersToJavaUserDefined(int modifiers)
};
*/
if(![c registerHotKeyWithKeyCode:keycode modifierFlags:(modifiers) target:self action:@selector(hotkeyAction:inObject:) object:nil])
if(![c registerHotKeyWithKeyCode:keycode modifierFlags:(modifiers) target:self action:@selector(hotkeyAction:inObject:) object:nil inIsOnKeyRelease:isOnKeyRelease ])
{
[c release];
[autoreleasePool release];
@ -892,7 +892,7 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
}
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerShortcut
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jint modifiers)
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jint modifiers, jboolean is_on_key_release)
{
KeyboardHook* keyboard = (KeyboardHook*)ptr;
@ -908,7 +908,7 @@ JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Na
return JNI_FALSE;
}
if([keyboard registerKey:macKeycode inModifiers:macModifiers])
if([keyboard registerKey:macKeycode inModifiers:macModifiers inIsOnKeyRelease: is_on_key_release])
{
return JNI_TRUE;
}
@ -939,7 +939,7 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_globalshortcut_Native
}
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_globalshortcut_NativeKeyboardHook_registerSpecial
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode)
(JNIEnv* jniEnv, jclass clazz, jlong ptr, jint keycode, jboolean is_on_key_release)
{
(void)jniEnv;
(void)clazz;

@ -65,6 +65,11 @@ private enum CallAction
*/
private boolean mute = true;
/**
* Push to talk state action.
*/
private boolean ptt_pressed = false;
/**
* Initializes a new <tt>CallShortcut</tt> instance.
*/
@ -83,7 +88,6 @@ public void shortcutReceived(GlobalShortcutEvent evt)
{
AWTKeyStroke keystroke = evt.getKeyStroke();
GlobalKeybindingSet set = keybindingsService.getGlobalBindings();
for(Map.Entry<String, List<AWTKeyStroke>> entry
: set.getBindings().entrySet())
{
@ -93,7 +97,6 @@ public void shortcutReceived(GlobalShortcutEvent evt)
continue;
String entryKey = entry.getKey();
if(entryKey.equals("answer") &&
keystroke.getKeyCode() == ks.getKeyCode() &&
keystroke.getModifiers() == ks.getModifiers())
@ -146,16 +149,7 @@ else if(entryKey.equals("mute") &&
{
try
{
synchronized(incomingCalls)
{
for(Call c : incomingCalls)
handleMute(c);
}
synchronized(answeredCalls)
{
for(Call c : answeredCalls)
handleMute(c);
}
handleAllCallsMute(mute);
}
finally
{
@ -164,10 +158,44 @@ else if(entryKey.equals("mute") &&
mute = !mute;
}
}
else if(entryKey.equals("push_to_talk") &&
keystroke.getKeyCode() == ks.getKeyCode() &&
keystroke.getModifiers() == ks.getModifiers() &&
evt.isReleased() == ptt_pressed
)
{
try
{
handleAllCallsMute(ptt_pressed);
}
finally
{
ptt_pressed = !ptt_pressed;
}
}
}
}
}
/**
* Sets the mute state for all calls.
*
* @param mute the state to be set
*/
private void handleAllCallsMute(boolean mute)
{
synchronized(incomingCalls)
{
for(Call c : incomingCalls)
handleMute(c, mute);
}
synchronized(answeredCalls)
{
for(Call c : answeredCalls)
handleMute(c, mute);
}
}
/**
* This method is called by a protocol provider whenever an incoming call is
* received.
@ -243,8 +271,9 @@ private static void removeCall(Call call, List<Call> calls)
* {@link #mute}.
*
* @param call the <tt>Call</tt> to set the mute state of
* @param mute indicates if the current state is mute or unmute
*/
private void handleMute(Call call)
private void handleMute(Call call, boolean mute)
{
// handle only established call
if(call.getCallState() != CallState.CALL_IN_PROGRESS)
@ -264,6 +293,7 @@ private void handleMute(Call call)
}
}
/**
* Answers or puts on/off hold the given call.
*

@ -114,42 +114,26 @@ public void registerShortcut(GlobalShortcutListener listener,
return;
}
if(keystrokes != null)
if(keystrokes == null)
{
if(keyStroke.getModifiers() != SPECIAL_KEY_MODIFIERS)
{
ok = keyboardHook.registerShortcut(keyStroke.getKeyCode(),
getModifiers(keyStroke));
}
else
{
ok = keyboardHook.registerSpecial(keyStroke.getKeyCode());
}
if(ok && add)
{
keystrokes.add(keyStroke);
}
keystrokes = new ArrayList<AWTKeyStroke>();
}
if(keyStroke.getModifiers() != SPECIAL_KEY_MODIFIERS)
{
ok = keyboardHook.registerShortcut(keyStroke.getKeyCode(),
getModifiers(keyStroke), keyStroke.isOnKeyRelease());
}
else
{
keystrokes = new ArrayList<AWTKeyStroke>();
if(keyStroke.getModifiers() != SPECIAL_KEY_MODIFIERS)
{
ok = keyboardHook.registerShortcut(keyStroke.getKeyCode(),
getModifiers(keyStroke));
}
else
{
ok = keyboardHook.registerSpecial(keyStroke.getKeyCode());
}
if(ok && add)
{
keystrokes.add(keyStroke);
}
ok = keyboardHook.registerSpecial(keyStroke.getKeyCode(),
keyStroke.isOnKeyRelease());
}
if(ok && add)
{
keystrokes.add(keyStroke);
}
if(add)
mapActions.put(listener, keystrokes);
@ -267,8 +251,10 @@ public void stop()
*
* @param keycode keycode received
* @param modifiers modifiers received (ALT or CTRL + letter, ...)
* @param isOnKeyRelease this parameter is true if the shortcut is released
*/
public synchronized void receiveKey(int keycode, int modifiers)
public synchronized void receiveKey(int keycode, int modifiers,
boolean onRelease)
{
if(keyboardHook.isSpecialKeyDetection())
{
@ -281,7 +267,7 @@ public synchronized void receiveKey(int keycode, int modifiers)
}
GlobalShortcutEvent evt = new GlobalShortcutEvent(
specialKeyDetected);
specialKeyDetected, onRelease);
List<GlobalShortcutListener> copyListeners =
new ArrayList<GlobalShortcutListener>(specialKeyNotifiers);
@ -293,7 +279,6 @@ public synchronized void receiveKey(int keycode, int modifiers)
// if special key detection is enabled, disable all other shortcuts
return;
}
synchronized(mapActions)
{
// compare keycode/modifiers to keystroke
@ -310,7 +295,8 @@ public synchronized void receiveKey(int keycode, int modifiers)
l.getModifiers() == modifiers)))
{
// notify corresponding listeners
GlobalShortcutEvent evt = new GlobalShortcutEvent(l);
GlobalShortcutEvent evt = new GlobalShortcutEvent(
l, onRelease);
entry.getKey().shortcutReceived(evt);
return;
}
@ -377,11 +363,23 @@ public synchronized void reloadGlobalShortcuts()
if(entry.getKey().equals("answer") ||
entry.getKey().equals("hangup") ||
entry.getKey().equals("answer_hangup") ||
entry.getKey().equals("mute"))
entry.getKey().equals("mute") ||
entry.getKey().equals("push_to_talk"))
{
for(AWTKeyStroke e : entry.getValue())
{
registerShortcut(callShortcut, e);
if(entry.getKey().equals("push_to_talk"))
{
if(e != null)
registerShortcut(callShortcut,
AWTKeyStroke.getAWTKeyStroke(
e.getKeyCode(), e.getModifiers(), true));
}
else
{
registerShortcut(callShortcut, e);
}
}
}
else if(entry.getKey().equals("contactlist"))

@ -86,13 +86,15 @@ public synchronized void setDelegate(NativeKeyboardHookDelegate delegate)
*
* @param keycode keycode of the shortcut
* @param modifiers modifiers (CTRL, ALT, ...)
* @param isOnKeyRelease this parameter should be true if when the shortcut
* is released an action should be performed.
* @return true if success, false otherwise
*/
public synchronized boolean registerShortcut(int keycode,
int modifiers)
int modifiers, boolean isOnKeyRelease)
{
if(ptr != 0)
return registerShortcut(ptr, keycode, modifiers);
return registerShortcut(ptr, keycode, modifiers, isOnKeyRelease);
return false;
}
@ -114,12 +116,15 @@ public synchronized void unregisterShortcut(int keycode,
* Register a special key shortcut (for example key coming from headset).
*
* @param keycode keycode of the shortcut
* @param isOnKeyRelease this parameter should be true if when the shortcut
* is released an action should be performed.
* @return true if success, false otherwise
*/
public synchronized boolean registerSpecial(int keycode)
public synchronized boolean registerSpecial(int keycode,
boolean isOnKeyRelease)
{
if(ptr != 0)
return registerSpecial(ptr, keycode);
return registerSpecial(ptr, keycode, isOnKeyRelease);
return false;
}
@ -195,10 +200,12 @@ private static native void setDelegate(long ptr,
* @param ptr native pointer
* @param keycode keycode of the shortcut
* @param modifiers modifiers (CTRL, ALT, ...)
* @param isOnKeyRelease this parameter should be true if when the shortcut
* is released an action should be performed.
* @return true if registration is successful, false otherwise
*/
private static native boolean registerShortcut(long ptr, int keycode,
int modifiers);
int modifiers, boolean isOnKeyRelease);
/**
* Native method to unregister a shortcut.
@ -216,9 +223,12 @@ private static native void unregisterShortcut(long ptr, int keycode,
*
* @param ptr native pointer
* @param keycode keycode of the shortcut
* @param isOnKeyRelease this parameter should be true if when the shortcut
* is released an action should be performed.
* @return true if registration is successful, false otherwise
*/
private static native boolean registerSpecial(long ptr, int keycode);
private static native boolean registerSpecial(long ptr, int keycode,
boolean isOnKeyRelease);
/**
* Native method to unregister a special key shortcut (for example key

@ -39,6 +39,7 @@ public interface NativeKeyboardHookDelegate
*
* @param keycode keycode received
* @param modifiers modifiers received (ALT or CTRL + letter, ...)
* @param onRelease this parameter is true if the shortcut is released
*/
public void receiveKey(int keycode, int modifiers);
public void receiveKey(int keycode, int modifiers, boolean onRelease);
}

@ -338,7 +338,7 @@ public Map<String, List<AWTKeyStroke>> getGlobalShortcutFromConfiguration()
String propName = null;
String propName2 = null;
String names[] = new String[]{"answer", "hangup", "answer_hangup",
"contactlist", "mute"};
"contactlist", "mute", "push_to_talk"};
Object configured = configService.getProperty(
"net.java.sip.communicator.impl.keybinding.global.configured");
@ -396,7 +396,6 @@ public Map<String, List<AWTKeyStroke>> getGlobalShortcutFromConfiguration()
}
gBindings.put(name, kss);
}
return gBindings;
}

@ -212,6 +212,11 @@ else if(key.equals("mute"))
desc = Resources.getString(
"plugin.keybindings.globalchooser.MUTE_CALLS");
}
else if(key.equals("push_to_talk"))
{
desc = Resources.getString(
"plugin.keybindings.globalchooser.PUSH_TO_TALK");
}
else
continue;
@ -267,6 +272,11 @@ else if(entry.getAction().equals(Resources.getString(
{
desc = "mute";
}
else if(entry.getAction().equals(Resources.getString(
"plugin.keybindings.globalchooser.PUSH_TO_TALK")))
{
desc = "push_to_talk";
}
else
continue;

@ -20,6 +20,13 @@ public class GlobalShortcutEvent
*/
private final AWTKeyStroke keyStroke;
/**
* Shows the event type:
* pressed is false
* released is true
*/
private final boolean isReleased;
/**
* Initializes a new <tt>GlobalShortcutEvent</tt>.
*
@ -28,6 +35,20 @@ public class GlobalShortcutEvent
public GlobalShortcutEvent(AWTKeyStroke keyStroke)
{
this.keyStroke = keyStroke;
isReleased = false;
}
/**
* Initializes a new <tt>GlobalShortcutEvent</tt>.
*
* @param keyStroke keystroke
* @param isRelease if the event is for release this parameter is true
* else this parameter is false
*/
public GlobalShortcutEvent(AWTKeyStroke keyStroke, boolean isReleased)
{
this.keyStroke = keyStroke;
this.isReleased = isReleased;
}
/**
@ -39,4 +60,14 @@ public AWTKeyStroke getKeyStroke()
{
return keyStroke;
}
/**
* Returns isReleased.
*
* @return release flag of the event
*/
public boolean isReleased()
{
return this.isReleased;
}
}

Loading…
Cancel
Save