Mouse clicks during window resize
Pages: 1 2
Andy S (2979) 504 posts |
I’m working on a “zoom on window resize” feature for the Paint Bounty. The problem is, to make it work smoothly, I want to record information when the user first initiates (and / or finishes) the resize operation. The wimp_EOPEN event won’t tell me that because it’s issued repeatedly during a resize mouse drag. I tried checking the icon flags on a wimp_EBUT event but that never fires unless the mouse pointer is actually over the client area of the window. Is there an elegant way to respond to clicks on parts of the window outside the client area (in this case the resize button)? If no-one can suggest an event driven way to do this I’ll have to just constantly read the mouse state on idle. I’ve been thinking I may need some code like this anyway in the Sprite window as I think I’ll have a similar problem responding to keyboard shortcuts (The Sprite window doesn’t take a keyboard focus as it doesn’t accept text. The code already accepts wimp_EKEY but I’m not sure why as I can’t find a situation where that would fire. ). |
Rick Murray (539) 13840 posts |
FilterManager? |
Andy S (2979) 504 posts |
That’s pretty cool, thanks. I didn’t know about that. As I’m not altering default behaviour (just augmenting) I assume it doesn’t matter whether I use a Pre- or Post- Filter. So, if I call Filter_RegisterPreFilter, it says R3 is “Task handle of task to which filter is applied, or 0 for all tasks”. So if I passed it Paint’s task handle, would I get clicks on a window outside the client area (e.g. resize button, title bar) or are they handled by a different task (the Window Manager perhaps)? Edit: I know I’m being a bit lazy. I could try it myself with 0 for all tasks then do TaskManager_TaskNameFromHandle to answer my own question. :) I’m just trying to get my head round how, if the FilterManager just provides filters for events that the application would have been passed on Wimp_Poll, it can pick up other events that no application would normally see? At this stage I’m only taking your word for it Rick that it can. ;) |
Rick Murray (539) 13840 posts |
Honestly, I do not know. The only time I have seen FilterManager in use (and known about it) was an application on a cover disc way back when which placed a grey border around every window. You could drag the border to resize the window, like how Windows 3.1 did it. For pre/post, I does matter which. Pre is called when the application called Wimp_Poll but before anything has happened. For example, a random application may decide to mute being notified of Gaining/Losing Focus as this may not be something the application cares about, however if your filter depended upon seeing these events, you could fiddle the flags that the application is passing to Wimp_Poll in order to have those events returned (which you later pick up). I do not know if the application is ever notified for the negative icon handles that represent the window furniture, or if the Wimp does most of the work and passes on the request via events (open window, close window, etc). I guess the simplest method could be to write some code to write some status to DADebug or Reporter, and see what happens. |
Andy S (2979) 504 posts |
Thanks Rick. It doesn’t seem to crop up much in the RISC OS sources either. I’ll have a play with it. It’s an interesting thing to learn about, regardless of how it gets used. |
Steve Fryatt (216) 2105 posts |
The window can take focus; you would just set the caret to the work area. However, I think what you actually want to do in this case is to set the ‘hotkeys’ bit of the window flags so that the window gets passed any keypresses which go unclaimed by the application with input focus. Monitoring keypresses on idle polls would make it very likely that you’d end up taking keypresses which would end up with another application as well. |
Jeff Doggett (257) 234 posts |
Fat32Fs uses a pre filter to intercept clicks on the SCSIFiler icons. Hence the reason that is says to type *Filters to check that Fat32Fs has initialised correctly in the !Help file – which you’ve all read, of course. |
Steve Fryatt (216) 2105 posts |
I don’t think that filters will do what you want, because their purpose is to allow other things to snoop on Wimp_Poll events sent to an application. If the information doesn’t come in via an event, a filter can’t see it – to the extent that pre-filters need to un-mask any events that they’re interested in if the application has them masked off. If Paint can’t see the information via its Wimp_Poll, a filter won’t help. I’m not near a RISC OS box to check, but I think I’d start by looking into the following approach:
There’s some more logic to fill in, of course, but I think that’s where I’d be starting from… |
Andy S (2979) 504 posts |
The Wimp doesn’t send Null events during drag operations, so if you get one or more Open Window events, the next Null poll marks the end of the drag. Aha! That would do it, thanks Steve. I’m still probably going to have a go at filters anyway, just because they seem interesting and I have a hunch based on what Rick said about that cover disc demo that there might be some events handled by the Desktop / Window Manager itself that I can intercept for Paint. |
Steve Fryatt (216) 2105 posts |
There aren’t: filters just wrap around Wimp_Poll, so all you’ll see is what you can see normally. The point of filters is to allow third party modules to ‘patch’ other apps by modifying or reacting to their poll events. There’s no point an application filtering itself! |
Rick Murray (539) 13840 posts |
Which brings us back to the original question – how can an application be notified of a click on window furniture? |
Rick Murray (539) 13840 posts |
Maybe call Wimp_GetPointerInfo on an OpenWindow event to see if it’s a click on the resize bit of the window? Icon -9 I think…? |
Andy S (2979) 504 posts |
Maybe call Wimp_GetPointerInfo on an OpenWindow event to see if it’s a click on the resize bit of the window? Icon -9 I think…? I think there the mouse flags will be the same on every OpenWindow event received for the duration of the resize drag, but I’ll try not to speculate anymore until I’ve actually knuckled down and coded some of these ideas. |
Rick Murray (539) 13840 posts |
Yes. This seems to be almost the case. I patched a custom OpenWindow handler into Manga, which is as follows:
(I’m using DeskLib) It does not appear to report anything when the window is initially opened, which is odd, but nevermind. Dragging the adjust size icon slowly generates many lines like this: OpenWindow: icon is -9 in window 540637913 (button 4) However it is worth noting that there is a discrepancy between what you see on-screen and what actually happens. If you drag the adjust size icon quickly, then this will occur: OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -1 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -1 in window 540637913 (button 4) OpenWindow: icon is -1 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -1 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -12 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) (-1 is work area, -9 is adjust size button, -12 is scroll right arrow) Note also: OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -1 in window 540680121 (button 4) OpenWindow: icon is -1 in window 540680121 (button 4) OpenWindow: icon is -1 in window 540680121 (button 4) OpenWindow: icon is -1 in window 540680121 (button 4) OpenWindow: icon is -1 in window 540680121 (button 4) OpenWindow: icon is -1 in window 540680121 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) OpenWindow: icon is -9 in window 540637913 (button 4) All of the -1 work areas here are a different window. How can this be? Easy. You click on the adjust size button and drag it. What you see on-screen is the result of the OpenWindow requests sent to the Wimp. Prior to that, reading the mouse position may return entirely weird results because the resize drag is happening but the window hasn’t been repositioned. Now, there are two ways to deal with this. The first, logical, way would be to shift the button check until after the OpenWindow. That should then always return -9 as the window and pointer will match up. This is, of course, not a lot of help if you want to be aware of the state before doing the OpenWindow. Which leads on to idea #2. As long as the user is dragging the window around, the Wimp should be firing OpenWindow requests at you. If the user is dragging slowly, other events may occur (I was able to press F12, go to command line, and come back, while a resize drag was in progress – I just never let go of the mouse button). In this case, the Wimp may fire other events. I have not tested this (it would be difficult due to how DeskLib’s event handling takes care of a lot of the boring grunt work). However, should this be the case then the first OpenWindow request each time should always begin with a -9 icon. |
Rick Murray (539) 13840 posts | Yup. Putting the mouse check on the other side of the OpenWindow returns -9 every time. That's probably the simplest option, provided you don't necessarily need to know this before calling Wimp_OpenWindow. ;-) |
Andy S (2979) 504 posts |
I appreciate your help and taking the time to test this Rick, thanks. Unfortunately, -9 button 4 every time would still give no indication of which OpenWindow happened on initial mouse button down and which is the last one before mouse button up. It sounds like Steve’s suggestion about the null events could work though. |
Andy S (2979) 504 posts |
So, you could set up some logic that goes “if OpenWindow and button is -9 then it’s a drag” and simply assume a drag is happening until you get a non-OpenWindow message. I don’t think that would work reliably because A. other events could arrive during the drag or B. there may be a long period with no other events arriving. The only caveat I can see here is that if the user is slow, a resize across the screen may appear to you as a dozen individual resize events, rather than just the one? Yeah, for this zoom resize I want to consider the moment the user first presses the mouse button to the point they release as the drag (although zooming will be happening in between as multiple OpenWindow events are received during the drag). The reason it’s important to get a good start point is that if I just keep on adjusting the magnification based on the immediate (very small) changes in the window size, it starts to give rounding errors and also because hands can wobble it makes it jerky (as it locks the aspect ratio). By looking at the total change in size and the initial zoom level from when they started dragging, I should be able to get it much smoother and nicer. |
Rick Murray (539) 13840 posts |
Both the OpenWindow and the mouse info have a window handle. Just remember that?
Again – remember. It is likely to be a combination of factors, such as checking to see if the icon is -9 upon an OpenWindow (so you know the operation is a resize drag, rather than “being moved by dragging title bar” or whatever). This will give you the “start of resize” information. Voilà, start and end positions. [sounds actually pretty simple, so there must be a big lurking “but” in here someplace!] |
Andy S (2979) 504 posts |
Yeah, I’ve definitely got enough information here now to make this work one way or another (famous last words ;) ). For some reason I didn’t think about moving the window with the title bar causing an OpenWindow, good point. Although I think my code would already do nothing in that case as there’s no change in window size. |
Andy S (2979) 504 posts |
It’s funny, when I started it, I thought this drag resize to zoom lark would be one of the quick, 5 minute jobs. Hahahahhaaa! ;D Ah well, it’s a good test of WIMP knowledge. |
Will Ling (519) 98 posts |
Just some thoughts that may or may not help. I looked at this earlier and thought I’d probably start how Steve suggested, but there are still some issues.. I believe you’ll still get idle polls during the drag, unless you are also opening other windows as panes or attached toolboxes for example, in which case you just get a flood of opens and no idles. I guess your initial state could perhaps be captured on the last poll that’s not idle, redraw or open. |
Jeffrey Lee (213) 6048 posts |
I think it would be nice if there was a way of detecting when drag/resize operations start/stop, but I’m not sure if it’s actually needed in this case. As you’ve said, you can calculate the adjusted scale factors by keeping track of the original window size and the new window size. OS_SpriteOp works using fractional scale factors, so there’s never any need to bake them down to a lossy fixed-point form; you can just keep them in the fractional form. There’ll be a danger of numerical overflow if you need to combine one set of scale factors with another. But that can be managed by keeping track of three values: The original scale factors, the original window size, and the new window size. Use those values to calculate the new scale factor (with e.g. 64bit ints), then if the numbers are too large for the target (32bit) you can try factoring out the GCD, or just divide by some other value until you get something that fits. This may introduce some inaccuracy, but if you keep the three original values around for as long as possible (i.e. until the user manually modifies the scale factors) you won’t really have anything to worry about. |
Andy S (2979) 504 posts |
Yes, I could just always compare the new window size against the original window size to calculate the zoom level accurately. That wasn’t the only reason I wanted a start point for the zoom drag action though. It’s because I am snapping the window to the correct aspect ratio, so I need to tell over a long drag whether the user is trying to grow or shrink the window. If you imagine in one iteration of the drag, the horizontal size of the window increases, but the vertical size reduces by almost the same amount, when I maintain the aspect ratio I would discard the vertical change and enlarge the window based on the horizontal growth (which incidentally requires a further Open Window message). The next iteration, the user’s shaky hand might reduce the vertical size by a very slightly bigger amount, and BAM, the window shrinks much smaller. In the worst case this can look horribly flickery or at best jerky. The solution, I think, is to look at the change in size over a longer duration hence the need to know the window size and scale when they started the operation. Bear in mind also that even if we don’t actually lock the aspect ratio of the window, the above information still needs to be considered, because if one dimension grows while the other shrinks, a choice still needs to be made on whether to reduce or increase the magnification. |
Andy S (2979) 504 posts |
Just some thoughts that may or may not help. I looked at this earlier and thought I’d probably start how Steve suggested, but there are still some issues.. I believe you’ll still get idle polls during the drag That should be fine. When a resize happens I can enable null events, check the mouse button state on each null event but the first time it detects select and adjust have been released, the nulls can be stopped and the new window state can be recorded. |
Jeffrey Lee (213) 6048 posts |
I’d assume the idea is to make sure that the area of the sprite which was originally visible will remain visible at the new scale. So if you start with the full sprite visible, then the user drags the adjust size icon up and right to create a short and wide window, the view would zoom out because that’s the only way it can keep the full sprite visible. One difficulty you might run into – regardless of the approach you’re using to track drag start/end – is that the Wimp will try and limit the drag to the extents of the window’s work area. So you might have to make the work area really big (effectively infinite), and have “virtual” scroll bars instead of real ones. (There’s probably some way of doing this by nesting/layering windows ontop of each other) |
Pages: 1 2