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 Mon 21 Dec 2009 05:43 AM (UTC)

Amended on Mon 21 Dec 2009 06:11 AM (UTC) by Twisol

Message
I seem to be unable to create 1x1 hotspots, i.e. hotspots that only affect a single pixel. I'm trying to layer a window entirely in 1x1 hotspots for fine-tuned tracking of the mouse using the below code, and for testing purposes I'm using the hotspot's ID as the tooltip text. The problem is that no tooltip appears at all, no matter where I point the mouse.


for y = 0, self.height do
  for x = 0, self.width do
    local id = self.name .. "-h(" .. x .. "," .. y .. ")"
    check(WindowAddHotspot(self.name, id, x, y, x+1, y+1,
       "MWidget.View.hotspot_handlers.mouseover",
       "MWidget.View.hotspot_handlers.cancelmouseover",
       "MWidget.View.hotspot_handlers.mousedown",
       "MWidget.View.hotspot_handlers.cancelmousedown",
       "MWidget.View.hotspot_handlers.mouseup",
       id, 0, 0))
    check(WindowDragHandler(self.name, id,
       "MWidget.View.hotspot_handlers.dragmove",
       "MWidget.View.hotspot_handlers.dragrelease",
       0))
  end
end


If I make the hotspots 2x2 instead, and change the for-loops to have a step of 2 instead of the default of 1, everything works fine. 2x2 isn't sufficient for my purposes, though, and it seems odd that 1x1 wouldn't work - it seems perfectly valid.

Another issue is that this takes a long time to execute, taking around 2 seconds on a 184x299 window. I think it wouldn't be such a bad idea to start using the 'flags' parameter to WindowAddHotspot, allowing you to modify the behavior of a single hotspot to send mouseover events for every mouse movement within the area, rather than just crossing into it from the outside. That way, I could just use one large hotspot instead of hundreds of tiny ones.

For reference, the reason I am doing this is because it provides the most convenient and intuitive way to create an abstraction layer over MUSHclient hotspots, allowing each widget in my framework to manage its own set of Hotspot objects (even if the widget is a child (contained within) of another widget). This solves the issue of how to percolate hotspot changes from subwidgets up to the visible frame, because my abstraction layer (implemented by the set of generic handlers you see in the code above) can use the information available to them to travel down the tree of subwidgets to locate the appropriate Hotspot to trigger.

Of course, if anyone has any other ideas I'm all ears, but I've been thinking about this for quite a while and I think it's the most viable way to go about it. After all, I think Win32 sends mouse-movement messages to its windows for every twitch of the mouse, doesn't it? So there is definitely precedent. [1]

[1] http://msdn.microsoft.com/en-us/library/ms645616(VS.85).aspx


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

* 1x1 hotspots seem to be malfunctioning, though I could just be doing something wrong.
* Fine-tuned mouse movement notification within a given hotspot would make a great flag for the unused 'flags' parameter in WindowAddHotspot.

'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 #1 on Mon 21 Dec 2009 07:48 AM (UTC)

Amended on Mon 21 Dec 2009 07:51 AM (UTC) by Nick Gammon

Message
Twisol said:

Another issue is that this takes a long time to execute, taking around 2 seconds on a 184x299 window.


So it creates 55,016 hotspots in 2 seconds? And that is slow? That is 27,508 per second. Each hotspot causes memory allocations, and needs to be stored in a list.

Whilst there may be a bug in hotspots where you can't make a 1x1 pixel hotspot, I think you are abusing the concept here. Hotspots are supposed to be GUI elements, like buttons, not individual pixels.

Other parts of miniwindows documentation state that you should make, say, lines by calling a single function (WindowLine) rather than doing it individually for every pixel (WindowSetPixel) - this can reduce the number of function calls from thousands, to one.

- Nick Gammon

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

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #2 on Mon 21 Dec 2009 07:55 AM (UTC)
Message
Even if the bug wasn't there, you are asking for a Lua script to be called for every pixel that the mouse moves over a window. I think that would be slow too. The miniwindow mouse handlers are trying hard to abstract away a lot of that low-level stuff, so individual mouse moves are only relevant when they move to or from graphical elements (hotspots) like buttons.

- Nick Gammon

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

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #3 on Mon 21 Dec 2009 07:56 AM (UTC)

Amended on Mon 21 Dec 2009 07:58 AM (UTC) by Twisol

Message
Everything you just said is precisely why I suggested the modification to the 'flags' parameter in WindowAddHotspot. I fully admit that creating 55,016 hotspots is completely inefficient, and using just one that's pixel-sensitive - akin to using a line or an image rather than pixel blits - would be much more effective. I'm simply working with what I have, and suggesting improvements that would be useful. (It's important to note that such a change would be quite useful even outside my widget framework, by the way - as I said, Windows itself fires a WM_MOUSEMOVE on every movement per-pixel.)

'Soludra' on Achaea

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

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

Amended on Mon 21 Dec 2009 08:07 AM (UTC) by Twisol

Message
Nick Gammon said:
Even if the bug wasn't there, you are asking for a Lua script to be called for every pixel that the mouse moves over a window. I think that would be slow too.


Graphical games (like World of Warcraft, which also uses Lua) do far more intensive number-crunching per frame, so I don't see this as an issue unless you're doing really heavy things in the handlers. And the most likely place for heavy things to go would be mousedown (or mouseup), not mouseover.

Nick Gammon said:
The miniwindow mouse handlers are trying hard to abstract away a lot of that low-level stuff, so individual mouse moves are only relevant when they move to or from graphical elements (hotspots) like buttons.

The issue is that at a fundamental level, composition of images and composition of hotspots are very different things. It is very simple to redraw widgets and pass the finished buffer up to the parent widget, and so on. It is not so easy to do the same with hotspots, especially when they need to be able to be removed or modified. This approach is the only one I've come up with so far that seems both viable and intuitive.


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.

EDIT: Second sidenote. Yes, 2 seconds is very speedy considering the sheer amount of work being done, but it is incredibly slow compared to the rest of what I've done so far. In other words, it is a bottleneck with an, in my opinion, obvious and relatively easy solution.

'Soludra' on Achaea

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

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #5 on Mon 21 Dec 2009 08:15 AM (UTC)

Amended on Mon 21 Dec 2009 08:18 AM (UTC) by Twisol

Message
A cursory glance at the code in CMUSHView::Mouse_Move_Window suggests that maybe the following change might allow this functionality, though I am by no means certain.

      // if different hotspot from before or this hotspot is pixel-sensitive
      if (sHotspotId != mw->m_sMouseOverHotspot || (pHotspot->m_Flags | 1))
        {
        // this is our new one
        mw->m_sMouseOverHotspot = sHotspotId;
        Send_Mouse_Event_To_Plugin (mw->m_sCallbackPlugin, 
                                    pHotspot->m_sMouseOver, 
                                    sHotspotId);
        }
      }


1 is just an arbitrarily selected flag to mark it as pixel-sensitive.

(EDIT: It's late and I should head to bed, I'll check back in tomorrow. >_>)

'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 #6 on Mon 21 Dec 2009 07:35 PM (UTC)
Message
Twisol said:

I seem to be unable to create 1x1 hotspots, i.e. hotspots that only affect a single pixel.


I can create 1x1 hotspots OK, see this:

Template:saveplugin=Hotspot_bug_test To save and install the Hotspot_bug_test plugin do this:
  1. Copy between the lines below (to the Clipboard)
  2. Open a text editor (such as Notepad) and paste the plugin into it
  3. Save to disk on your PC, preferably in your plugins directory, as Hotspot_bug_test.xml
  4. Go to the MUSHclient File menu -> Plugins
  5. Click "Add"
  6. Choose the file Hotspot_bug_test.xml (which you just saved in step 3) as a plugin
  7. Click "Close"



<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Tuesday, December 22, 2009, 7:29 AM -->
<!-- MuClient version 4.45 -->

<!-- Plugin "Hotspot_bug_test" generated by Plugin Wizard -->

<muclient>
<plugin
   name="Hotspot_bug_test"
   author="Nick Gammon"
   id="b40cc6e35092067ad28e5616"
   language="Lua"
   purpose="Tests a 1x1 hotspot"
   date_written="2009-12-22 07:22:57"
   requires="4.40"
   version="1.0"
   >

</plugin>


<!--  Script  -->


<script>
<![CDATA[
function mouseover (flags, hotspot_id)
  print ("in mouseover, flags=", flags, "hotspot_id=", hotspot_id)
end -- mouseover

function cancelmouseover (flags, hotspot_id)
  print ("in cancelmouseover, flags=", flags, "hotspot_id=", hotspot_id)
end -- mouseover

function mousedown (flags, hotspot_id)
  print ("in mousedown, flags=", flags, "hotspot_id=", hotspot_id)
end -- mousedown

function cancelmousedown  (flags, hotspot_id)
  print ("in cancelmousedown, flags=", flags, "hotspot_id=", hotspot_id)
end -- cancelmousedown

function mouseup  (flags, hotspot_id)
  print ("in mouseup, flags=", flags, "hotspot_id=", hotspot_id)
end -- mousedown

-- make window
win = GetPluginID ()  -- get a unique name
WindowCreate (win, 0, 0, 200, 200, 12, 0, ColourNameToRGB("white"))  -- create window

-- hotspot location
LeftA, TopA, RightA, BottomA = 10, 10, 11, 11

-- fill it
WindowRectOp (win, 2, LeftA, TopA, RightA, BottomA, ColourNameToRGB ("red"))

-- add hotspot
WindowAddHotspot(win, "hs1",  LeftA, TopA, RightA, BottomA, 
                 "mouseover", 
                 "cancelmouseover", 
                 "mousedown",
                 "cancelmousedown", 
                 "mouseup", 
                 "tooltip - hs1",
                 1, 0)

WindowShow (win,  true)  -- show it 


]]>
</script>


</muclient>


- Nick Gammon

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

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #7 on Mon 21 Dec 2009 07:43 PM (UTC)
Message
And in case it was the juxtaposition of the hotspots, this test creates an array of 100 x 100 of 1x1 hotspots, and that works OK too.

Template:saveplugin=Hotspot_bug_test2 To save and install the Hotspot_bug_test2 plugin do this:
  1. Copy between the lines below (to the Clipboard)
  2. Open a text editor (such as Notepad) and paste the plugin into it
  3. Save to disk on your PC, preferably in your plugins directory, as Hotspot_bug_test2.xml
  4. Go to the MUSHclient File menu -> Plugins
  5. Click "Add"
  6. Choose the file Hotspot_bug_test2.xml (which you just saved in step 3) as a plugin
  7. Click "Close"



<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Tuesday, December 22, 2009, 7:29 AM -->
<!-- MuClient version 4.45 -->

<!-- Plugin "Hotspot_bug_test2" generated by Plugin Wizard -->

<muclient>
<plugin
   name="Hotspot_bug_test2"
   author="Nick Gammon"
   id="5a796a8c2d3e5735d5cd1f2d"
   language="Lua"
   purpose="Tests 100 1x1 hotspots"
   date_written="2009-12-22 07:22:57"
   requires="4.40"
   version="1.0"
   >

</plugin>


<!--  Script  -->


<script>
<![CDATA[
function mouseover (flags, hotspot_id)
  print ("in mouseover, flags=", flags, "hotspot_id=", hotspot_id)
end -- mouseover

function cancelmouseover (flags, hotspot_id)
  print ("in cancelmouseover, flags=", flags, "hotspot_id=", hotspot_id)
end -- mouseover

function mousedown (flags, hotspot_id)
  print ("in mousedown, flags=", flags, "hotspot_id=", hotspot_id)
end -- mousedown

function cancelmousedown  (flags, hotspot_id)
  print ("in cancelmousedown, flags=", flags, "hotspot_id=", hotspot_id)
end -- cancelmousedown

function mouseup  (flags, hotspot_id)
  print ("in mouseup, flags=", flags, "hotspot_id=", hotspot_id)
end -- mousedown

-- make window
win = GetPluginID ()  -- get a unique name
WindowCreate (win, 0, 0, 200, 200, 12, 0, ColourNameToRGB("white"))  -- create window

for y = 0, 99 do
  for x = 0, 99 do
  
  -- hotspot location
  local LeftA, TopA, RightA, BottomA = x, y, x + 1, y + 1
  local id = string.format ("x=%i, y=%i", x, y)
  
  -- fill it
  WindowRectOp (win, 2, LeftA, TopA, RightA, BottomA, 
                bit.bor (
                  bit.shl (math.random (0, 255), 16),
                  bit.shl (math.random (0, 255), 8),
                           math.random (0, 255)))
                  
                
  
  -- add hotspot
  WindowAddHotspot(win, id,  LeftA, TopA, RightA, BottomA, 
                   "mouseover", 
                   "cancelmouseover", 
                   "mousedown",
                   "cancelmousedown", 
                   "mouseup", 
                   "tooltip " ..  id,
                   1, 0)
  
  end -- for x
  
end -- for  y


WindowShow (win,  true)  -- show it 


]]>
</script>


</muclient>

- Nick Gammon

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

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #8 on Mon 21 Dec 2009 07:44 PM (UTC)
Message
The events appear to work fine. The tooltip doesn't. So, I suppose this is more of a tooltip-event issue...

Since I'm not planning on using the tooltip parameter except for testing, I guess it's a non-issue for me personally. However, I still think that using one high-sensitivity hotspot beats using 55016 hotpixels. ;)

'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 #9 on Mon 21 Dec 2009 07:48 PM (UTC)

Amended on Mon 21 Dec 2009 07:49 PM (UTC) by Nick Gammon

Message
Twisol said:

The events appear to work fine. The tooltip doesn't. So, I suppose this is more of a tooltip-event issue.


I don't seem to be able to get tooltips at all, so I agree there seems to be a problem there.

- Nick Gammon

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

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #10 on Mon 21 Dec 2009 09:16 PM (UTC)
Message
I am getting very variable results with the tooltip text, not only with 1x1 hotspots. There seems to be something strange going on there.

- Nick Gammon

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

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #11 on Tue 22 Dec 2009 01:41 AM (UTC)
Message
After extensive investigation I am coming to the conclusion that the tooltip code is somehow responsible for this. MUSHclient activates the tooltip when you move onto a different hotspot from before, however I think the tooltip code only shows the tooltip if you move *inside* the tooltip area, and then stop moving. Thus, it is impossible in a 1x1 pixel hotspot for it to be activated (by moving onto the pixel) and then move around *inside* that pixel for the the tooltip display to be activated - since by definition moving around would move you outside that pixel.

So basically this is an artifact of having tiny hotspots, which I may say you wouldn't use in practice anyway.

- Nick Gammon

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

Posted by Nick Gammon   Australia  (23,062 posts)  Bio   Forum Administrator
Date Reply #12 on Tue 22 Dec 2009 01:43 AM (UTC)
Message
Your original report was a bit misleading:

Twisol said:

I seem to be unable to create 1x1 hotspots, i.e. hotspots that only affect a single pixel.


You can indeed create 1x1 hotspots, as you agree yourself:

Twisol said:

The events appear to work fine. The tooltip doesn't.


- Nick Gammon

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

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

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

Message
At the time, I didn't know it was just the tooltips; I really did think it was the actual hotspot. Your later two plugin examples set me straight. My apologies if I wasn't clear in the second post you quoted.

As to the tooltip thing... interesting. Will that tidbit be added to the docs? ;)


EDIT: This may be a stupid question, but what happens if you enable the tooltip on every hotspot that provides one? Would the tooltip float up no matter where you hover, or would it only appear over the hotspot? It seems like maybe some of the CToolTipCtrl members could be used to limit the area the tooltip hovers over (::SetToolRect?), but this is my first exposure to the tooltip class and I'm just shooting in the dark.

'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 #14 on Tue 22 Dec 2009 01:57 AM (UTC)
Message
Don't really understand the question, and not sure about the answer, as the CToolTipCtrl control seems a bit obscure anyway.

- 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 1, subject is 3 pages long: 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.