Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Miniwindows ➜ 1x1 hotspots

1x1 hotspots

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1  2 3  

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #15 on Tue 22 Dec 2009 02:00 AM (UTC)

Amended on Tue 22 Dec 2009 02:01 AM (UTC) by Twisol

Message
The issue is that, once a tooltip control is Activated, it (probably) needs to receive a mousemove event for the tooltip to show up. My proposed solution, assuming I'm even close to being correct, is to immediately Activate a hotspot's tooltip during WindowAddHotspot, and then limit the tooltip control's rect using CToolTipCtrl::SetToolRect(). That way, the tooltip would be alerted the moment you wander into a hotspot, rather than once you move around inside one.

EDIT: I think I am right; see [1] and [2].


[1] http://msdn.microsoft.com/en-us/library/6b4cb3a5(VS.80).aspx
Quote:
A "tool" is either a window, such as a child window or control, or an application-defined rectangular area within a window's client area. A tool tip is hidden most of the time, appearing only when the user puts the cursor on a tool and leaves it there for approximately one-half second.


[2] http://msdn.microsoft.com/en-us/library/6hh5zw0e(VS.80).aspx
CToolTipCtrl:SetToolRect()

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #16 on Tue 22 Dec 2009 02:46 AM (UTC)
Message
There is one tooltip control for the entire output window, not one per hotspot. After all, only one tooltip is visible at once.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #17 on Tue 22 Dec 2009 02:46 AM (UTC)

Amended on Tue 22 Dec 2009 02:48 AM (UTC) by Twisol

Message
Anyways, what do you think about the initial idea, adding a flag for WindowAddHotspot to allow hotspots to pick up on pixel-sensitive movement? It wouldn't affect hotspots prior to the change, and would be fully optional (more of an advanced feature, if you will). But just as you said, it's better to blit a whole image at once rather than its component pixels separately, and that's exactly what the flag would do.

EDIT: Good timing on the posting... replying again to respond.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #18 on Tue 22 Dec 2009 02:48 AM (UTC)
Message
I'm not sure I see the issue. You can have multiple CToolTipCtrl's and attach them all to the output window's HWND, and then use ::SetToolRect() to map the tooltip to a specific rectangle of the output window.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #19 on Tue 22 Dec 2009 04:04 AM (UTC)
Message
You could, but so far I haven't. I can see quite possibly, especially if you have a tooltip per pixel, dozens of tooltips popping up everywhere driving you mad, like confetti. The current design limits you to one tooltip at a time.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #20 on Tue 22 Dec 2009 04:09 AM (UTC)
Message
Twisol said:

Anyways, what do you think about the initial idea, adding a flag for WindowAddHotspot to allow hotspots to pick up on pixel-sensitive movement?


Ah yes, well I got distracted trying to see if there was a genuine bug.

You are right WoW uses Lua, however that is somewhat more coarse-grained than calling a Lua routine for every pixel the mouse wanders over. User functions are called for things like incoming messages (eg. battle damage) or the player clicking on a button, exactly like what you get now in MUSHclient with triggers and hotspots.

Your proposed change of getting a mouse-move message for every time the mouse moves, even by a pixel, would break the documented effect for mouse moves, that you get a mouse-move followed by a mouse-cancel event. Unless you also want a mouse-over cancel event for every pixel as well.

I can't help feeling you are trying a brute-force approach to a problem that should have a more elegant solution. Surely even nested hotspots can be accommodated by simply keeping them in a table, and finding the topmost one by a quick search?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #21 on Tue 22 Dec 2009 04:21 AM (UTC)

Amended on Tue 22 Dec 2009 04:41 AM (UTC) by Twisol

Message
Nick Gammon said:

You could, but so far I haven't. I can see quite possibly, especially if you have a tooltip per pixel, dozens of tooltips popping up everywhere driving you mad, like confetti. The current design limits you to one tooltip at a time.

That's fine, I was just proposing a possible fix. It's definitely not a major concern.


Nick Gammon said:
Your proposed change of getting a mouse-move message for every time the mouse moves, even by a pixel, would break the documented effect for mouse moves, that you get a mouse-move followed by a mouse-cancel event. Unless you also want a mouse-over cancel event for every pixel as well.

No, not really. The cancelmouseover would only occur when you leave the hotspot, as it is now, and that makes sense to me. The mouseover event just responds as the mouse moves over it.


Nick Gammon said:
I can't help feeling you are trying a brute-force approach to a problem that should have a more elegant solution. Surely even nested hotspots can be accommodated by simply keeping them in a table, and finding the topmost one by a quick search?

I find this approach very elegant, personally, but we're allowed to disagree. The issue is that each widget needs some way to keep track of its hotspots, change their handlers, modify their location/size, and remove them if need be, and it is a bonus that the hotspots wouldn't lose their current mouse-state just by getting moved or resized. They would naturally get updated on the next mouse movement, of course, if it moved itself away from the mouse.

Taking this approach - decoupling the hotspots from the events - allows widgets to manage their own hotspots dynamically, without needing to run through complex operations just to make simple changes. I had spent around two or three days just trying to come up with a good design for hotspots, and all of them had some major drawbacks. When I came up with this design, I felt like it was a eureka moment; the only real drawback I could see was the inefficiency of creating so many 1x1 hotspots, which is what I am proposing a (simple) solution to. The layer of hotpixels would track the events, traverse the tree to locate potential callbacks, and execute callbacks when appropriate. The whole widget/hotspot tree can be changed dynamically, and the view need never know.

If you think you have a better solution, I am completely all ears! :) The source is also available on GitHub (now linked in my signature), if you want to look at it for a better idea of what's involved. I'll soon be pushing up a version using the 1x1 blanket of hotpixels, since that approach currently works, if you'd like to see exactly what I'm planning. Most of the infrastructure for the hotspot functionality is already in this version, actually, it's just not exposed.



EDIT: To note, by supplying the flag to enable pixel-sensitive mouse movement, you'd know exactly what would happen. I don't think the documentation issue is a valid concern because of this; just note that the pixel-precision has this behavior and it should be kept in mind while using it.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #22 on Tue 22 Dec 2009 06:04 AM (UTC)
Message
Twisol said:

EDIT: tl;dr summary, because I think I rambled a bit there:


I forgot to say, purely for humor you understand: TLDR

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #23 on Tue 22 Dec 2009 06:15 PM (UTC)
Message
I think that two issues have been somewhat conflated here:

1. Twisol wants per-pixel knowledge of where the mouse cursor currently is.

2. Twisol has a solution to this problem that abuses the notion of hotspots. (Twisol also believes he doesn't have much of a choice in the matter given the current API.)


I think that it's pretty clear that blanketing the entire window with 1x1 hotspots is not ideal for several reasons. So I don't think we should argue against the 1x1 method; we should be trying to establish if having per-pixel mouse control is a good idea or not.

First, note that most GUI frameworks send mouse movement events to the whole (sub-)window, with the coordinates as extra parameters. Applications can then deal with or ignore these messages as they see fit.

An argument given against per-pixel control was efficiency. Many applications do in fact track the mouse rather particularly. For example, many games change the cursor depending on what's under the mouse; many others track mouse movements in order to move the camera. So (in principle) tracking every mouse movement is not prohibitive.

I threw together a quick benchmark:


$ cat test.lua 

function do_something(x, y)
    return x * 2 + y
end
function do_something_else(x, y)
    return x * 3 + y
end

function HandleEvent(event)
    if event.type == "mouseover" then
        if event.x > 50 and event.y < 20 then
            do_something(x, y)
        else
            do_something_else(x, y)
        end
    end
end


for i = 1, 10000000 do
    x = math.random(1, 100)
    y = math.random(1, 100)
    HandleEvent({type = "mouseover", x = x, y = y})
end

$ time lua test.lua
lua test.lua  31.21s user 0.00s system 99% cpu 31.223 total
$ 

(This is on an Intel Celeron 2.4 GHz, running Debian. Not exactly a fast computer.)

This is obviously only an approximation of what happens for mouse events. Note that it takes ~30 seconds to run 10 million events. That's 0.000003 seconds, or 0.003 milliseconds, per event handling.

It can be empirically tested, but I wager that you probably won't be getting more than several thousand mouse events per second (if that many!). This means that we'd be spending a few milliseconds processing events at maximal "mouse moving bandwidth". That's probably acceptable.



For windows that do not need fine-grained control, it would suffice to create them with a flag set to false (which could be the default value for the parameter) -- in this case they would not generate the mouse events in the first place. So, miniwindows who don't care about mouse events will see no difference.



I think that having per-pixel mouse control is an important feature of any GUI toolkit. The fact that Twisol is trying to do his own stuff on top of this is kind of irrelevant in my opinion (it just happens that his work is exposing issues in the API). There are many reasons to have per-pixel control. One reason is that it makes some tasks much easier; imagine you have some sort of map that displays things. You could create a hotspot per thing, but this would require complex management (addition, removal, modification) of hotspots each time the 'things' changed. But if you could simply capture all pixels, you could look up which 'thing' is under the cursor at that point in time.



Perhaps one way to focus the discussion is to examine the objections to per-pixel control? The main ones I see are: "it's inefficient" (which I think has been addressed) and "it creates extra work" (which I think is true but unavoidable :P).

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #24 on Tue 22 Dec 2009 07:55 PM (UTC)

Amended on Tue 22 Dec 2009 08:06 PM (UTC) by Twisol

Message
Just to note briefly, I have just pushed a version of the framework with a working pixel-sensitive layer of 1x1 hotpixels. It's not even remotely close to being done, but it does work, and my Tic Tac Toe plugin is behaving very well (it uses hotspots extensively). I hope you will check it out!

EDIT: To briefly note, I'm only using the 1x1 layer because I have no other recourse. It's an odd workaround, to be sure, but that's all I've got.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #25 on Tue 22 Dec 2009 08:07 PM (UTC)
Message
OK, well if everyone insists. :)

I have added a new plugin callback to version 4.45. This detects mouse movement in the output window. For example:


function OnPluginMouseMoved (x, y, unused)
  TraceOut ("mouse move: x=", x, ", y=", y)
end -- function OnPluginMouseMoved


Tests seem to show that with continuous movement of the mouse you get about 60 calls per second. Using the example code above I didn't notice any particular slowing down of the client.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #26 on Tue 22 Dec 2009 08:16 PM (UTC)

Amended on Tue 22 Dec 2009 08:18 PM (UTC) by Twisol

Message
Not to be like "give them an inch, they take a mile" or anything - I appreciate that you're doing this at all - but I really, really don't think this is the best solution. In relation to the framework (as an example), it requires that either (a) the user write an OnPluginMouseMoved themselves and pass it along to an overall framework callback, or (b) the framework write one itself, thus rendering it wholly unavailable to the user if they want to do anything different with it.

Doing it this way would require not only that code be written to discern which hotspot to execute, but also which -window- to check in the first place! Further, it's wholly decoupled from the miniwindow system, which is really the only place this would make any sense. Finally, because there is no sense of 'which window is being moused over', you could have two windows on top of eachother, both created in separate plugins, both moused over at some point, and both of them doing something in response to the mouseover, even though only one is on top. This wholly breaks expected behavior, and is the largest issue with this approach.

I would honestly like to know why you're averse to adding a flag to WindowAddHotspot. Is there an issue with it I'm unaware of?

EDIT: note the "both created in separate plugins" bit, I forgot that part.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #27 on Tue 22 Dec 2009 08:20 PM (UTC)

Amended on Tue 22 Dec 2009 08:25 PM (UTC) by Nick Gammon

Message
Well, given that you seem to want cursor movements only for a particular hotspot, why is that? I assumed from your earlier posts that you were trying to detect movements in general, and then farm them out to a particular "control" or whatever it is.

I mean, if there is an OK button, why is it exciting to know the mouse has moved around inside it?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #28 on Tue 22 Dec 2009 08:24 PM (UTC)

Amended on Tue 22 Dec 2009 08:25 PM (UTC) by Nick Gammon

Message
Twisol said:

As a sidenote, if someone wanted to create a custom 'cursor'-like graphic when hovering over a minwindow, how would they do it? This is competely apart from my widget framework. You would need either a layer of 1x1 hotpixels, or a single high-sensitivity hotspot.


I have added a new selector to SetCursor, namely -1 for "no cursor".

Combined with OnPluginMouseMoved, you could hide the normal cursor, and then move around another miniwindow, which could be your graphical cursor. This is one of the reasons I added the "ignore mouse" (8) parameter to miniwindow creation a while back. Such a "cursor" window would not want to get mouse clicks, or it would be impossible to click on the underlying window.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #29 on Tue 22 Dec 2009 08:26 PM (UTC)
Message
Twisol said:

(b) the framework write one itself, thus rendering it wholly unavailable to the user if they want to do anything different with it.


Why? They can't "do anything" with it. It just tells them where the mouse is. All plugins will get it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


96,639 views.

This is page 2, subject is 3 pages long:  [Previous page]  1  2 3  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.