JUCE as VST plugin.... keyboard focus


#1

The TrackPAD plugin that ModuLR and I have been working on operates fine under Tracktion and energyXT, but in Cubase and Live there are keyboard focus issues. I’ve not got either host to try with, (guess i should get some demos!) but apparently the hotkeys in cubase still ‘go off’ when trying to type in the plugin window, and live doesn’t pass the typed text to it at all.

any ideas as to why this might be before i bust my head open trying to fix it?


#2

hmm - could be any number of things… might be that these apps are using nasty hooks to grab the keys.

Did you make sure that the VST effKeysRequired setting is enabled for your plugin?


#3

:frowning: yeah that’s set alright. Live lets the plugin recieve mouse focus, even the scroll-wheel works on it. it just doesn’t recieve any keystrokes, and you can see them being recieved by the host.


#4

Do any other plugins manage to get keypresses in Live? It might be that it just intercepts all of them…


#5

well, it’s tricky to find a plug that doesn’t pop-up a windows style thing to type in, and i can imagine that kind of popup getting focus easily (i suppose). Reaktor lets you rename the pins in the interface itself tho, which shows that plugs are capable of recieving the keystrokes from within live.

i am completely stumped! should i need to do something with the effKeyDown bitsnbobs? i wouldn’t know how to pass a keystroke to the texteditor tho…

confused! :smiley:


#6

i’ve tried putting a SetFocus( (HWND) editorWindowPointer ) into the function that opens the editor window, but that doesn’t seem to have any effect. The fact that the mouse is working fine tho suggests that live is gobbling up the keystrokes for itself, but i literally haven’t a clue how i’d get around that. My searches just show things about putting in ‘hooks’ to the keyboard stream or something… but any examples are in pascal! so yeah i’m truly stumped there.


#7

I can’t think of any ideas here…

Does juce actually think it’s getting focus - e.g. if you have a TextEditor component, does the cursor flash in it?


#8

yeah, it sure does. flashing away as if all were normal. :cry: !


#9

damn. I’ll have to have a think about that one…


#10

I’ve the same problem too.

I’m using Bidule and AudioMulch.

I can’t get key focus on my text editor and sliders!

What is due to?


#11

i think the host is intercepting the keystrokes and making some kind of filtering by means of hooking the messages. on another framework (win) i’ve come up with installing a hook over the host ones by scanning parent windows and installing the hooks on the windows that’s blocking’em. in some hosts you can easily install a hook over the plugin editor window,
something like:

	namespace Hook
	{
		extern HHOOK hMsgFilterHook;
		extern LRESULT CALLBACK WndFilterProc(int nCode, WPARAM wParam, LPARAM lParam);
		extern BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam);
	};


HHOOK Hook::hMsgFilterHook = NULL;

//_____________________________________________________________________
BOOL CALLBACK Hook::EnumChildProc(HWND hwnd, LPARAM lParam)
{
	if (::GetWindowLong(hwnd, GWL_WNDPROC) == (LONG)YourClass::WndProc)
	{
		HWND *tmp = (HWND *)lParam;
		*tmp = hwnd;
		return FALSE;
	}
	return TRUE;
}

//_____________________________________________________________________
LRESULT CALLBACK Hook::WndFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode < HC_ACTION)
		return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);

	MSG *msg = (MSG *)lParam;
	HWND focus = ::GetFocus();
	HWND child = NULL;
	::EnumChildWindows(focus, Hook::EnumChildProc, (LPARAM)&child);

	if (child != NULL)
	{
		YourClass*obj = reinterpret_cast<YourClass*>(::GetWindowLong(child, GWL_USERDATA));
		switch (msg->message)
		{
			case WM_KEYDOWN:
			{
           // ... do processing of events as usual
				if (event.IsProcessed())
					return 1;
				else
					return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);
			}
			break;
			case WM_KEYUP:
			{
          // ... do processing of events as usual
				if (event.IsProcessed())
					return 1;
				else
					return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);
			}
			break;
			case WM_SYSKEYDOWN:
			{
          // ... do processing of events as usual
				if (event.IsProcessed())
					return 1;
				else
					return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);
			}
			break;
			case WM_SYSKEYUP:
			{
           // ... do processing of events as usual
				if (event.IsProcessed())
					return 1;
				else
					return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);
			}
			break;
			default:
				return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);
		}
	}
	else
		return ::CallNextHookEx(Hook::hMsgFilterHook, nCode, wParam, lParam);
}

then u can attach the hook in your window on its opening:

Hook::hMsgFilterHook = ::SetWindowsHookEx( WH_CALLWNDPROC, (HOOKPROC)Hook::WndFilterProc, NULL, ::GetWindowThreadProcessId((HWND)ptr, NULL)); YourClass::m_hookInstalled = true;

and killing on close

if (YourClass::m_hookInstalled == true && m_classRefCount == 1) ::UnhookWindowsHookEx(Hook::hMsgFilterHook);

in some weird hosts you need to transverse the parent windows starting from the one the host give you, and install the hook on that window… a bunch of

[code]HWND parent = (HWND)::GetWindowLong( (HWND)ptr, GWL_HWNDPARENT );
while( parent )
{
::GetWindowText( parent, name, 256 );

                    if ( strcmp(name,"flswrapper") == 0)
                        break;
                    else if ( strcmp(name,"cplugin") == 0)
                        break;

		parent = (HWND)::GetWindowLong( (HWND)parent, GWL_HWNDPARENT );
	}[/code]

isn’t so easy to find out…


#12