This is the bug/patch tracker for Rockbox. Click here for more information.
Quick links: Bugs · Patches · Rockbox frontpage
FS#11903 - Android does not handle keypresses correctly - potential fix but I can't java
Attached to Project:
Rockbox
Opened by Benjamin Brown (BenjaminBrown) - Monday, 24 January 2011, 12:37 GMT+2
Opened by Benjamin Brown (BenjaminBrown) - Monday, 24 January 2011, 12:37 GMT+2
|
DetailsI've hunted this down here is what I found out.
from http://developer.android.com/reference/android/view/KeyEvent.Callback.html -------------------------------------------------------------------------------------------------------------------- public abstract boolean onKeyDown (int keyCode, KeyEvent event) Since: API Level 1 Called when a key down event has occurred. If you return true, you can first call KeyEvent.startTracking() to have the framework track the event through its onKeyUp(int, KeyEvent) and also call your onKeyLongPress(int, KeyEvent) if it occurs. -------------------------------------------------------------------------------------------------------------------- We need to return true and call KeyEvent.startTracking() from /android/src/org/rockbox/RockboxFramebuffer.java then set the interrupt flag from /firmware/target/hosted/button-android.c and find out what is passed back after a key release and handle that. I may not be a great programmer but this looks like the ticket to removing the BUTTON_REL work around from /firmware/target/hosted/android/app/button-application.c |
This task depends upon
{
event.startTracking();
buttonHandler(keyCode, true);
return true;
}
I'm still a dork,
this still does nothing except compile what am I missiing?
This patch fixes up the logic handler for key events in firmware/target/hosted/android/button-android.c and removes an unneeded function as well as removes the |BUTTON_REL work around from firmware/target/hosted/android/app/button-application.c
My kasiar's DPAD is behaving nicely with the patch and even gets long press repeats through to the button handlers.
I need to know if it effected any other button functions on other devices like ones with scroll wheels and navigation balls, before its ready for commit.
unsigned button = 0;
unsigned last_btns = 0;
be better?
Good news is that this bug is crushed.
from http://www3.ntu.edu.sg/home/ehchua/programming/android/Android_2D.html
but still a ways to go. I could really use a hand on this java.
tested on my side scroll wheel and dpad.
todo:
there are no long key press events
some times two key presses are need to change direction.
patches:
BUG_MISSING_BETTER_button-android.c.patch
BUG_MISSING_RockboxFramebuffer.java.patch
BUG_MISSING_fixed.button-application.c.patch
button = key_to_button(keycode);
if (!button)
{
button = key_to_button(keycode);
}
I still think the queue_post() call you add is wrong. Also please note that multimedia buttons need some special handling.
This one works much better.
I did notice that when entering the plugins menu two different key presses were needed to "wake up"? the buttons. last key presses are stored some where I guess. I removed last_btns from this patch is that needed some where else?
I did not have this issue on the settings menu I don't think it is a bug in this code but one in the "list plugins funtion" what ever file that may be in, but of course I'm always wrong just ask my wife.
A. has a scroll wheel you know for doing scrollie stuff
B. has touch screen for that all important touch screen interface and
C. every freakin button imaginable! It has to many really.
let me count 1 2 3 oh you know what just pull up android-event.h and I think every thing less than 84 or less just let me know.
I did try
if (!state)
queue_post(&button_queue, "BUTTON_REL", 0);
button = !button;
return true;
which, I thought, should have worked and I tried |BUTTON_REL as well with no quotes.
Unless someone knows why, I can't get rid of |BUTTON_REL from button-application.c.
So as it is right now these patches work but still contain the original work around. tested with my dpad and scroll wheel.
works better with last_btns rather than queue_post() hmm now I can remove |BUTTON_REL
this patch
http://www.rockbox.org/tracker/task/11903?getfile=23212
and the following work best so far and without the work around.
be right back
either way it does the same thing and I feel changing the values of android-keyevents.h to be wrong if this the way it was downloaded.
feel free to test sorry about all the trouble I can cause :)
Do any other android phones have volume up/down that is not mapped to the left/right soft keys?
I don't really care cause I never want to look at java again but I will :)
So I decided to keep it, as it is now my pet.
this patch is IT hopefully :)
I did not need to add requestFocus() to the constructor.
It works without it, I'm sure you don't want extra cruft in there so I left it out. cheers.
Designing this patch according to your hacked phone is not the way to go I'm afraid.
queue_post(&button_queue, button|BUTTON_REL, 0);
Instead of trying to rewrite the logic that was there before, I understand and I will. but it was hard to follow.
that last patch really works great trust me :) no bull
I know you hate looking at my ugly monkey shit code but it's the first time I programmed since I wrote a 3dcube like program way way way back in the day, and java is so new to me its not even funny. Just look at the first post ^
Anyway as always it's your call of course.
I found most of this at http://blog.7touchgroup.com/tag/keyevent-starttracking/ since action.c locks waiting for release events a nicer way to track them must be necessary I'm gonna try this instead of just onKeyUp or onKeyDown
public boolean dispatchKeyEvent(KeyEvent event)
{
// Tell the framework to start tracking this event.
getKeyDispatcherState().startTracking(event, this);
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0)
{
getKeyDispatcherState().handleDownEvent(event);
keyCode = event.getKeyCode()
return buttonHandler(keyCode, true);
}
else if (event.getAction() == KeyEvent.ACTION_UP && event.getRepeatCount() == 0)
{
getKeyDispatcherState().handleUpEvent(event);
keyCode = event.getKeyCode()
return buttonHandler(keyCode, false);
}
return super.dispatchKeyEvent(event);
}
I'll submit another patch only after I get the hang of java and write the right code to get this done or if I write a patch to split the Aaap port into dpad and track ball android targets. cheers
{
return buttonHandler(keyCode, true);
}
Doesn't this return immediately after being called and get called again directly afterwards, if the button event is still active. So it sends rapid key presses, can a "do while loop" work sort of better. I see where you coded around this, but it doesn't make sense to do this if we can make java send one keydown event then wait until the key is released, and then send one keyup event. This is maybe not a real "bug" but if I can find away to handle this better I'll jump on in.
none working example of my idea.
http://forum.xda-developers.com/
sorry just my way of thinking about it, no offense intended mate.
What I meant, was that since android is open source, there will be some one else who comes a long the way, with another legacy device running android.
And is going to come in here and do the same thing I did. Except they probably won't read the wiki let alone the source code, and they definitely would never consider a patch.
So until rockbox is android 2.0. How about a legacy option for those poor souls with legacy devices?
I'll send a patch sometime. ;)
Now time to put android on the tilt II and see what happens when I run rockbox.
But I do say, you must have a vividly twisted mind to come up that one.
I know the "why" it's coded this way, maybe not the "how" did you come up with that, but it is brilliant only looking for button releases.
The startTracking() call is api 2.0 and up, but handles the interrupt line differently than the existing code. Making it hard for me to just drop it in and walk away. If we used starttracking it would mostly insure rockbox worked smoothly on any device as long as it was 2.0 compliant.
So by excluding phones below 2.0 we can actually open up the door to their hardware as long as they can upgrade to 2.0 and up. Actually 2.3 runs much faster.
Warning for those who travel this way, DO NOT open the box Thomas Martitz so kindly wrapped around the most hideous demon one could conceive of, and just use this last patch if you can.
How does this one feel on a track/optical android? My wheel is worn out so I can't tell, it never really works reliably.
If onKeyDown is evaluated true button_handler is called and the keypress is sent to rockbox for processing. On the next tick if onKeyDown is still true another keypress is sent. thus multiple key presses are sent.
But if an onKeyup event is detected button_handler is called only once. This is what Kugel looked for and used evil evil code to go back in time a see which key was pressed before hand, dragging down the frame buffer while it did that.
My way fixes the assumption that only one onKeyDown event is sent and stops sending them after the first one. I maybe foolsh but I'm not stupid. Commit this, it is good code kugel, I stepped through the registers on my white board to figure it out.
Test it bud, it works better this way.
It's out of my hands until some body tests it on a track pad/ball.
What this patch does:
rewrites the input code (sorry kugel) in order to remove a work around.
fixes:
widgets work
buttons work for plugins again
frambuffer seems faster
It "should" work on every android out there - needs testers
It is 1.5 API compliant
It will act the same for track pads/balls, but fix the problem with dpads.
Its ready buddy trust me.
please guy, trust the sage old programmer who had to learn java, to get rockbox working on his android ;) please
I'm Sorry
Truce?
works nice over here now, how about you?
It might not be from this patch I'll dig in tomorrow.. again, and see what I dig up.
First, it is supposed to be a virtual hardware construct, so that the virtual hardware looks like real hardware.
In real hardware you cannot split a one bit interrupt into two or more path ways.
By splicing the interrupt, in button-application, it basically hooked the output line, from the gpio, directly up to three individual virtual chips, sort of.
The media, key, and dpad buttons can all go in one matrix, and should. That is how real "non-virtual" hardware operates.
This caused most of the trouble.
I'll pull multimedia_to_button out to the side and see what I can bring back.
from
http://developer.android.com/reference/android/view/MotionEvent.html
look just right
That leaves multimedia_keys exposed to rockbox. And put in a dispatchTrackballEvent and see if works for track pads too, not just balls.
Ok this has one interrupt, with multimedia keys on the side.
I duplicated onTouchEvent for onTrackballEvent, but still pass it off to touchhandler. This is wrong, it needs it's own handler, but I don't have this hardware so I can't really see what happens.
{
switch (me.getAction())
{
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_MOVE:
}
return false;
}
might work better
If I assign one of the many buttons on this phone to lets say, BUTTON_MULTIMEDIA_PREV it should change to the previous track, no matter what is happening in rockbox. Like if I was changing something on the lcd setting screen and pressed it.
I'm gonna try this if it works does that mean it auto-magically fixed itself? (O_o) that.... would be awesome
this is related to the missing track ball events
android-developers@googlegroups.com/msg31548.html"> http://www.mail-archive.com/android-developers@googlegroups.com/msg31548.html
This is It! this page talks about the problem at detail Thomas I found it!
Trackball events are handled by the onTrackBallEvent() callback. If you don’t add this callback to your application, trackball events fall through to key press events. You can use the onKeyUp() or onKeyDown() event handler callbacks, or implement the OnKeyListenerand onKey() listener callback to intercept trackball motion events.)
and this other bit
(On trackballs, the pointer coordinates specify relative movements as X/Y deltas. A trackball gesture consists of a sequence of movements described by motion events with ACTION_MOVE interspersed with occasional ACTION_DOWN or ACTION_UP motion events when the trackball button is pressed or released)
when the deltas add up to 1 you get a button press!! missing BUTTON_REL!!! do you see it yet?
this talks about the deltas
I can't sleep now :)
I hope you see it, if not I will try harder to .....say......things
Things go in my head real easy
---->(o,o)-------?
but they don't comeback out so clearly.
but it's in there you can find it.
I need sleep so, tomorrow then.
The RockboxFramebuffer view is not receiving scroll events, because
(Trackball events are handled by the onTrackBallEvent() callback. If you don’t add this callback to your application, trackball events fall through to key press events. You can use the onKeyUp() or onKeyDown() event handler callbacks, or implement the OnKeyListenerand onKey() listener callback to intercept trackball motion events.)
But we did not see those events because
(Event Listeners are must more specific. They “listen” for an event generated on a View or ViewGroup. You must register the listener for a View or Viewgroup with the appropriate setOnxxxListener(). The event is then “triggered” when one of the input types is activated. The callback that is launched depends on which View or ViewGroup has focus.)
we know how it supposed to work
(On trackballs, the pointer coordinates specify relative movements as X/Y deltas. A trackball gesture consists of a sequence of movements described by motion events with ACTION_MOVE interspersed with occasional ACTION_DOWN or ACTION_UP motion events when the trackball button is pressed or released)
But they look like they are missing BUTTON_REL lastly because
(The relative movement of the trackball since the last event can be retrieve with MotionEvent.getX() and MotionEvent.getY(). These are normalized so that a movement of 1 corresponds to the user pressing one DPAD key (so they will often be fractional values, representing the more fine-grained movement information available from a trackball))
and we get only one dpad event for every delta = 1
These two links:
http://developer.motorola.com/docstools/library/Basics_of_Event_Management/
http://developer.android.com/reference/android/view/View.html#onTrackballEvent%28android.view.MotionEvent%29
Ah this code implements setOnTrackballListener. It should be easy peasy now
I did notice the view is removed and reattached to the framebuffer, at RockboxActivity.java:110-114
Seems like the source of the trouble.
It looks like trying to add setOnTrackballListener() and registering the view/viewgroup in the manifest, is the last effort available. Before trying to hurt myself coming up with another layer of work around.