Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button stays hovered on touch monitor (Win) #1470

Open
sebasobotka opened this issue Nov 30, 2017 · 20 comments
Open

Button stays hovered on touch monitor (Win) #1470

sebasobotka opened this issue Nov 30, 2017 · 20 comments
Labels

Comments

@sebasobotka
Copy link

Button stays hovered when I touch it, using the mouse it works correctly. How can I prevent this behavior on Touch monitor (Win10)?

button4

@ocornut
Copy link
Owner

ocornut commented Nov 30, 2017

Does your code that binds the touch pad input as a mouse disable the mouse when the touch pad is released? You need to set io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX) to disable the mouse.

@sebasobotka
Copy link
Author

I was trying to set io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX) but no success.
I develop in openframeworks. Touch events are seen as mouse event. Everything works fine except that.

@ocornut
Copy link
Owner

ocornut commented Nov 30, 2017 via email

@sebasobotka
Copy link
Author

sebasobotka commented Dec 1, 2017

The mouse pos is -FLT_MAX but it doesn't affect.
This is my code:

if (ImGui::Button("refresh", ImVec2(200, 50))) {
		refresh();
	}
	io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
	cursor_pos = io.MousePos;
	ofLogNotice("cursor pos") << cursor_pos;

I tried also special addon in openframeworks which uses new WM_POINTER events to obtain more detailed information about the touch but then ImGui doesn't work anymore.

@ocornut
Copy link
Owner

ocornut commented Dec 1, 2017

io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
cursor_pos = io.MousePos;
ofLogNotice("cursor pos") << cursor_pos;

You can't just be printing a value that you just set and that wasn't used by imgui....

You need to set io.MousePos BEFORE calling NewFrame() in the openframeworks imgui backend..

And it needs to be set one frame AFTER the mouse button is released. So when the virtual mouse button is released, the position is still valid. Then it's not valid the next frame. You are trying to emulate a mouse with a touch screen this is one way to do it.

PS: Also you can use ImGui::Text() instead of ofLogNotice, this is what imgui is for :)

@ocornut
Copy link
Owner

ocornut commented Jan 7, 2018

@sebasobotka Have you solved this on your side?

@sebasobotka
Copy link
Author

Hi @ocornut,
I had to move my work to another project and it's still not solved. But it's on my list Todo.

@sebasobotka
Copy link
Author

I think I got it but one thing I would like to be sure.
I can set io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX) globally in the backend when the touchUp event occurs but then e.g. Combo stops working properly. I need to set MousePos exactly when button is triggered but I need do this for every button.

in backend
Gui::begin() - io.DeltaTime, io.MousePos are set -> ImGui::NewFrame();
Gui::end() -> ImGui::Render();

in main draw
gui.begin();
...
ImGui.widgets()
...
if (ImGui::Button("button")) {
    backend->mouseCursorPos.set(-FLT_MAX, -FLT_MAX);
}
gui.end();

Here is my version of the addon.

@ocornut
Copy link
Owner

ocornut commented Jan 25, 2018

@sebasobotka
I don't know why Combo would stop working and you don't really explain here how you are transforming your ofx inputs (touch inputs presumably) into io.MousePos so it's hard to make a guess.

  • As a basic rule you should only set io.MousePos before NewFrame() and never anywhere else.
  • On a touch screen, set io.MousePos + io.MouseDown[0] whenever the screen is touched.
  • Clear io.MouseDown[0] whenever the screen is not touched.
  • Clear the mouse position io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX) two frames after releasing the touch. This is because you want the release event to happen at the same position (e.g. on your buttons) to activate them.

If you never clear the mouse position you'll get the behavior you are reporting in the first post (button stays hovered, etc.).

@ocornut
Copy link
Owner

ocornut commented Jan 25, 2018

I can set io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX) globally in the backend when the touchUp event occurs

This is not what I meant in my Dec 1th message and in my last message I tried to clarify it. Set io.MousePos one frame AFTER your touchUp event.

@sebasobotka
Copy link
Author

sebasobotka commented Jan 25, 2018

All the rules are there. I shared my code. On Windows and openframeworks there are some issues with touches. You need to enable them. Then you can use some events like touchDown, touchUp etc. I modified the backend for using both mouse and touch events. io.MousePos is set only in one place, above is shown where gui.begin() and it's before NewFrame() What I am doing is preparing only value of ofVec2f mouseCursorPos with mouse position. The same is in mouse and touch events.

I don't understand how to set something one frame/ two frames after, do I need to check frame number and then set something?

--edit
I checked it. In openframeworks there is

update() 

and 

draw()

When button is triggered there is e.g. frame nr 455, then in update loop is 456 and so on...
Is it wrong to set some '''MyMousePos''' when button is clicked? Then in update loop there is nothing and then we are in draw loop, gui.begin() - here my position is set and that's all. I am one frame AFTER.

@ocornut
Copy link
Owner

ocornut commented Jan 25, 2018 via email

@sebasobotka
Copy link
Author

Yes, that's obvious. I complicated it to myself. I will check it.

@sebasobotka
Copy link
Author

Maybe I am doing something wrong or there is a bug somewhere (win touches / backend / imgui) but it doesn't work.

Here is clearing mouse pos one frame after - combo stops working, button still hovered:
oneframerot3

Here is two frames after - combo works, button still hovered:
twoframesrot2

Here is my approach which works:
myrot2

I am leaving it for now. We can close the issue.

@ocornut
Copy link
Owner

ocornut commented Jan 26, 2018 via email

@sebasobotka
Copy link
Author

Hi @ocornut .
Thanks for your help and suggestions. Maybe it's not visible well but I displayed io.MousePos on window title bar and also I printed current frame number in the logs.

But today with fresh mind ;) I got it! The frame counter needs to be set 3 frames to clear mouse position. When the touchUp event is triggered we are checking the counter in the same frame number and after ONE frame exactly we are clearing the mouse pos. The combo doesn't work and the button isn't triggered either. For counter = 3 everything works great!

Here is a log for counter = 2:

[notice ] Frame nr: 5713, touchDown
[notice ] Frame nr: 5721, touchUp
[notice ] Frame nr: 5722, mousePos: 125.137, 294.015, 2 frames after mouse clearing..
[notice ] Frame nr: 5722, mousePos: -3.40282e+38, -3.40282e+38, check mouse pos after clearing

Here is a log for counter = 3:

[notice ] Frame nr: 302, touchDown
[notice ] Frame nr: 307, touchUp
[notice ] Frame nr: 308, button method
[notice ] Frame nr: 309, mousePos: 108.858, 292.732, 2 frames after mouse clearing..
[notice ] Frame nr: 309, mousePos: -3.40282e+38, -3.40282e+38, check mouse pos after clearing

But I have another issue. What do I need to scroll combo area as shown below?
scrollfieldrot

@ocornut
Copy link
Owner

ocornut commented Jan 26, 2018

Thanks for your help and suggestions. Maybe it's not visible well but I displayed io.MousePos on window title

Good point. And you can see in your GIF above for "Here is two frames after - combo works, button still hovered:" than the mouse position is NOT being cleared, that's why the button is still hovered. It's not really a question of 2 frames vs 3 frames it is that you have a bug in your flow/logic which isn't clearing the value.

But I have another issue. What do I need to scroll combo area as shown below?

You probably want to emulate a mouse wheel event, aka set io.MouseWheel based on your vertical drag delta. you also need to lock io.MousePos to the starting touch position because mouse wheel event apply to the hovered window, not the focused window. This puts a little extra burden on your side, and most annoyingly the scrolled delta won't match the exact drag distance (because it's provided in arbitrary "mouse wheel units" whereas in the case of a two fingers drag you'll ideally want movement to be exactly 1-to-1, you may adjust the scale of the value you pass, to find a nice match, but it'll feel a little dodgy).

So I think it would be beneficial and make it easier for users on for touch device that I add a specific input, provided in in imgui/pixel coordinates, to trigger scrolling. You will however still need to make sure only the first touch sets io.MousePos, so when you'll drag two fingers outside the area the window keeps scrolling.

Enabling io.MouseDrawCursor. will probably be your best friend when debugging that.

TL;DR; You can follow instruction above, or wait until I add a new input and it'll become a little easier.

(PS: As a side question, any reason you didn't use e.g. ImGui::Text() to display that mouse position, instead of going through the effort of displaying it in the title bar?)

@sebasobotka
Copy link
Author

sebasobotka commented Jan 26, 2018

Good point. And you can see in your GIF above for "Here is two frames after - combo works, button still hovered:" than the mouse position is NOT being cleared, that's why the button is still hovered. It's not really a question of 2 frames vs 3 frames it is that you have a bug in your flow/logic which isn't clearing the value.

It's not visible well on my GIF but it was being cleared. But it doesn't matter today. Now I have a working version :)
2frames

But why it's a bug in my flow/logic? I would like to understand it. The touchUp event and method before NewFrame() are called in the same frame number so maybe it's a better idea to remember the frame number in touchUp event and check the difference later. I will check it later.

TL;DR; You can follow instruction above, or wait until I add a new input and it'll become a little easier.

I will wait for it ;) I have a lot of another work to do now. It's not crucial for me but it will be nice enhancement.

(PS: As a side question, any reason you didn't use e.g. ImGui::Text() to display that mouse position, instead of going through the effort of displaying it in the title bar?)

I am from openframeworks society and I have got some habits. It's easier sometimes to print something using OF methods than ImGui. For example in OF you have got different levels of logging and you can enable/disable them for different classes. Here is a documentation about it.
Displaying something in the title bar is not a big deal. It's only one method.

ofSetWindowTitle("imgui mouse pos x: " + ofToString(io.MousePos.x) + ",y: " + ofToString(io.MousePos.y));

Those were my debug information. But of course, when I would need to display something for user I will use ImGui::Text(). And once again, your work is great ! and I am a big fan of ImGui.

@ocornut
Copy link
Owner

ocornut commented Jan 26, 2018

It's not visible well on my GIF but it was being cleared.

Either that statement is contradicting the actual data either we are not talking about the same GIF. The last GIF where the bug is visible and value of MousePos is displayed, that value it is never -FLT_MAX:
https://user-images.githubusercontent.com/7688669/35421144-d1e2c044-0241-11e8-982f-42d7be54e6fe.gif
The button "get buffers" stays hovered and you can see the value MousePos not being cleared. The log is misleading as you can clear the value and set it again right after through another event. The only reliable indicator is the value of io.MousePos at the time of NewFrame and I am assuming that value is reflected in the title bar and updated every frame? Calling ofSetWindowTitle() or ImGui::Text("MousePos %f, %f", io.MousePos.x, io.MousePos.y); right after NewFrame() would at least guarantee we are seeing the right value and not some intermediate value that gets overwritten five lines later by another piece of code/event.

I think I'll need to provide a touch demo at some point for people to use (last time I did it was on the Vita, and my code on the Switch left the mouse cursor in the same place).

@sebasobotka
Copy link
Author

Believe me or not, this is the same movie but gif is compressed and some frames are reduced and it's not visible what I showed later. But You are right. Probably the mouse position was cleared and was overwritten later.

I think I'll need to provide a touch demo at some point for people to use (last time I did it was on the Vita, and my code on the Switch left the mouse cursor in the same place).

It would be nice to see how it should be done :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants