DragAFile
James Lampard (51) 120 posts |
Hi All, I’m in the process of writing a new module called DragAFile designed to complement the existing DragASprite/DragAnObject. An early alpha version with example is available from download at http://www4.webng.com/resurgam/drag.zip When you drag a file with this module the filename appears underneath. I believe the RO Select filer already does this. With this new module, potentially all programs can use it for saves too. Another advantage is that it automates things that many applications get wrong. 1. It checks the CMOS byte to see if you want Wimp_DragBox rectangle drags instead. 2. It centres the sprite on the mouse pointer (Actually offset up by 20 os units otherwise the pointer obscures the filename) 3. It allows you to drag the pointer to the bottom of the screen to bring the iconbar to the front. Amazingly some applications still get this wrong and specify the bounding box to apply to the sprite box rather than the pointer. It truncates the displayed leafname if you choose something stupidly long. As some users will prefer to stick with DragASprite style drags, this will be configurable. Interface: A cross between DragASprite_Start and OS_File 10 DragAFile_Start On Entry: R0 =flags, currently 0 for future expansion R1 =pointer to path (leaf name will be used for plinth) R2 =filetype number(directory =4096 application =8192) (if >&7FFF assumed to be pointer to string) Pretty simple huh, and certainly easier than using DragASprite/Object directly. On Exit: All registers preserved. DragAFile_Stop No entry registers I may have also discovered a bug, when using the example “DO_DRAG5” program. I’ve found after bringing the iconbar to the front by touching to bottom of the screen with the pointer that dragging the directory off the iconbar can cause screen corruption when the iconbar vanishes. Is this a bug with DragAnObject, presumably to do with the iconbar being re-drawn in the wrong order? I’ve found in the code for Wimp_DragBox that setting 0 in all of the parentbox co-ords limits the pointer to the screen, without having to go to the trouble of finding out the screen size and then modifiying it by half the dragbox width. The trouble is I can’t find this anywhere. It’s not documented in the PRMs, nor volume 5a or the Nested window docs or the RO4 docs. Is this okay to use? It’s implemented back to at least Window Manager 3.16 (30 Apr 1992) ie the RISC OS 3.11 version. No other programs seem to use this feature. For example RISCOSLib manually calculates the size correctly. Conversely Toolbox get’s it wrong only allowing the box to be dragged to the edge. |
Steve Revill (20) 1361 posts |
This all looks good to me. I’ll have a play with it some time and tell you what I think. Plus, when I have some time I’ll look into the Wimp_DragBox question. |
James Lampard (51) 120 posts |
I’ve slightly extended DragAFile recently and a new version is available from http://www4.webng.com/resurgam/hide/drag2.zip I’ve made it more configurable with 2 system variables added. DragAFile$Options is a numeric variable. Bits 0-3 configure how DragAFile will do file drags.
If the DragASprite CMOS bit is clear it will always use Wimp_DragBox and will ignore the variable. Bit 4-31 of DragAFile$Options is passed to DragASprite/DragAnObject You can thus configure if solid drags are used, or a drop shadow. DragAFile$Colours is a sting variable The validation string defining the colour of the leafname plinth which defaults to CFFFFFF/777777
Wimp_DragBox is not a massive problem, because I’m now conditionally assembling; so you can easily produce versions that do/don’t pass 0 to Wimp_DragBox. What is a bit worrying is that I’m sometimes ripping chunks out of windows. This shows the iconbar brought to the front over a zap window. (By touching the bottom of the screen with the pointer) After dragging the iconbar returns to it’s position in the stack – but the drag has ripped a large chunk out of the iconbar and the window. |
Fred Graute (114) 645 posts |
Thanks for that. I’ve modified the Pinboard to use DragAFile when dragging single icons around and it seems to work fine. The only minor problem is that the flags that were passed to DragASprite aren’t passed on by DragAFile so the icon is always centered around the pointer. Would it be possible to alter DragAFile such that flags in R0 are always passed to DragASprite/DragAnObject and that the flags for DragAFile itself passed in R5?
Don’t have an answer to this but I have seen it with various applications so it’s not down to your system or a specific application. |
James Lampard (51) 120 posts |
I’d rather not, the whole idea of DragAFile is that it works out the sprite positioning based on the pointer position. Currently no co-ords are required to be passed. My inspiration for DragAFile was from playing with the Pinboard sources. My intention was that for clients that require subtle positioning (like the pinboard) after the Drag completes they would call an extra swi DragAFile_Position maybe, which would ‘fix’ the returned co-ordinates at the end of the drag. For the pinboard the position of the centre of the top of the ‘virtual rectangle’ that contains the icon should be enough to re-position the icon. |
Colin (129) 41 posts |
I must admit I don’t like the dragging of text when dragging a file. I always feel that the sprite is the object I’m dragging not the name. If this gets used I’d like a global configure option to switch it off or better still it should be switched off by default. |
James Lampard (51) 120 posts |
It IS switched off by default. It has to be because the majority of programs won’t use DragAFile, and having different drags from some apps will be confusing. As I wrote above: DragAFile$Options is a numeric variable. Bits 0-3 configure how DragAFile will do file drags.
DragAFile$Options could obviously be set by a configure plug in. |
Colin (129) 41 posts |
Sorry I had assumed that as you had used bits that they also went in the flags word of dragafile_start. As you are using a module why not use *commands instead of system variables then you can have help associated with the options. You should have a flag for dragafile_start so that you can tell it that if the text+sprite option is used you drag a small sprite with the text to the right (instead of a large sprite with text below). I can think of situations where I definitely wouldn’t want text+sprite – dragging a folder to a directory to get it’s location for example (whereas just dragging a sprite always works). So a flag in dragafile_start to force text+sprite off would be useful. You don’t want to reconsider this do you? Text + sprite dragging is hideous you only have to use windows for 10 mins to figure that out – the text just gets in the way. Sorry that’s my last moan about it :) |
James Lampard (51) 120 posts |
I considered this initially – this is what most of the configure plugins use. I decided to use a variable in case another piece of software wanted to do it’s own implementation – it could then also read DragAFile$Options. Using variables isn’t unprecedented – Paint/Edit/Draw do it. It also makes the module simpler – we just read DragAFile$Options whenever the swi is called. As it would be set by a configure plug-in, most users will never be aware of it, so I don’t think there’s much point to help messages.
I could implement this. I think a flag in DragAFile$Options would be better.
Or you could just call DragASprite in these circumstances? The module isn’t intended to replace DragASprite/DragAnObject completely
It’s configurable, the default is to use DragASprite with just the Sprite. If you don’t like it don’t use it. The advantage of pushing all file drags through a single module is that things can be changed. It’s already possible to configure DragASprite/Object and solid/transparent drags. Anyway here’s an update on the window bug: To investigate this further I’ve produced a hacked version of DragAnObject 0.03 (23 Apr 1996) – the RISC OS 4.02 version using ARMalyser. This hacked version saves the produced sprites into the CSD. In PRM5a in the documentation for DragAnObject_Start it says the bounding box minx,miny are inclusive but maxx,maxy are exclusive (Exactly the same as DragASprite). Internally DragAnObject uses SpriteOp &10 (get sprite from user co-ords) with this all the co-ord’s are inclusive. So your object will always be one pixel bigger than you intended, not a problem normally unless your trying to centre on it. Will fixing this break any existing software? I’ve tried using DragASprite with really big sprites – no corruption of windows. I’ve tried taking the ‘final’ sprite produced by DragAnObject, loading it into the wimp pool and then using it with DragASprite – In this case there is no corruption of windows. In the light of this I’m really sure it’s something the DragAnObject does. |
Colin (129) 41 posts |
That’s because paint/edit/draw aren’t modules and can give help via the help file. Modules give help via the module help system.
The point is if it was used in the filer for example then you would want large icon with text below in large icon mode and small icon with text to the right in small icon mode. Which one you get depends on the filer window’s mode not on a global option so you need to tell dragafile_start which one to use. If you don’t have the global option for text set then you always get the large icon.
So a dragafile module can’t drag a file – why make an exception? |
James Lampard (51) 120 posts |
If your dragging a DIRECTORY as YOU SAID to find it’s location then YOU ARE NOT DRAGGING A FILE. ARRGHH! |
James Lampard (51) 120 posts |
I apologise for that little outburst… now I’ve taken a couple of aspirin and had a lie down I’ll deal with the rest:
I could be specious and point out that on my system Paint/Edit/Draw are modules – but I won’t. What I will say is that DragAFile$Options is a numeric variable you have to alter it at the bit level. I can’t see any user really wanting to do this – surely it’s better handled automatically by a configure plug-in. Another advantage of using a variable is you can change the variable even if the module isn’t loaded – removing the need to load it on boot on older OSes.
Ah I see what you mean. I’m not going to implement this yet – not until I know what the bug in DragAnObject is and if it’s fixable. I’m now thinking that the value passed in R0 could be ORRed with DragAFile$Options to allow for stuff like this. I would like to say that the Idea of DragAFile was mainly to be used in SaveAs windows and also in the filer/pinboard. I don’t think it’s unreasonable that other dragging operations continue to use DragASprite. |
Colin (129) 41 posts |
To quote your own original specification.
That makes it designed for dragging directories. There’s no need to shout. It’s best that I say no more. |
James Lampard (51) 120 posts |
Yes but your not ‘copying a directory’ or ‘creating a directory’ occasions when you would need to drag a directory with a filename. If ‘dragging a folder to a directory to get it’s location’ you don’t need a leafname so why not just continue to use DragASprite? The whole point of DragAFile is to drag files with leafnames. You can configure it to look like a DragASprite drag if you want – but it’s not designed to do everything. |
James Lampard (51) 120 posts |
I’ve come up with a clever heuristic to automatically convert suitable “DragASprite from a save window” calls to DragAFile. I’ve done this by hacking DragASprite and inserting a small “wedge” into DragASprite_Start which calls a new swi DragAFile_Hack. The upshot of this is that most programs can benefit from drags with leafnames without being re-written. This new version is available from http://www4.webng.com/resurgam/hide/drag3.zip To try this out just load the following:
And then drag from the savebox of almost any program. Changes to API DragAFile$Options: An extra bit is added; Bit 31 =if set check DragASprite_Start calls to see if it’s coming from a Save window, and if so convert it into a DragAFile_Start call. DragASprite_Start: An extra bit is added to the flags word R0; Bit 31 =if set don’t call DragAFile_Hack (DragAFile_Start uses this to prevent an infinite loop, and new applications could for non-file drags) |
James Lampard (51) 120 posts |
I’ve been doing some work in DragASprite and I think I’m close to finding the Ripping window bug. So hopefully DragAFile will start to move forward shortly. |
Steve Revill (20) 1361 posts |
Hi James. Don’t forget to include a copy of the Castle license terms with any distribution you make of stuff from the published RISC OS sources. It doesn’t apply to your own code, of course, but does to the Castle components (such as DragASprite). Ta. :) |
James Lampard (51) 120 posts |
I’m pretty sure I’ve done this with all the stuff available from: http://www4.webng.com/resurgam/ROOL/index.htm Is there anything I’ve forgotten? |
Steve Revill (20) 1361 posts |
The only thing I looked at was the archive linked to by a post jut above mine in this thread: http://www4.webng.com/resurgam/hide/drag3.zip but good to hear that the other stuff had this covered. |
James Lampard (51) 120 posts |
Finally here is my explanation of the ripping window bug. I found it by using a disassembly of Doggysoft’s re-written DragASprite module (where it doesn’t occur), and also by noticing that it never struck in EX0 EY0 modes. In a typical file sprite of 68×68, the sprite needs to be expanded by 8 OS units in each direction for the drop shadow. The drop shadow hangs both below and to the right. The section to the right has no effect on the positioning of the sprite but the one below requires the sprite to be appear 8 os units lower on the screen than it would otherwise. In order to handle this DragASprite has two variables to tell it where to plot the sprite in relation to the drag box. In the case of the 68×68 sprite these are set to: bl_offset_x =0 bl_offset_y =&FFFFFFF8 or -8 (The bl_offsets’ are also used to deal with the left/centre/right bottom/centre/top positioning of the sprite in the dragbox) This is the typical bug-free drag. DragAFile uses DragAnObject, and as mentioned in an earlier post always adds 1 extra pixel to the requested sprite. Having an odd number of pixels is a pre-requisite for this bug. As it throws out the calculations, now: bl_offset_x =&FFFFFFFF or -1 bl_offset_y =&FFFFFFF7 or -9 These skewed values are stored away before calling Wimp_DragBox The unplot,plot and move routines in s.Drag called by Wimp_DragBox, try to fix this by rounding down to os units after adding bl_offsets’ to the drag box. But it’s now equivalent to a bl_offset_y of -10 and a bl_offset_x of -2 I’ll admit I don’t fully understand how this is causing the corrupted areas onscreen. Internally there are three sprites fg, bg0 and bg1. (fg is the sprite you’re dragging and bg0/1 are copies of the background) I also don’t understand how DragASprite swaps between bg0 and bg1 during the drag. It’s something to do with graphics windows. When the sprites are created in s.StartUp they all are of the same size and in the normal drag they all stay that way. In the bugged case just bg0 becomes one pixel bigger in both x and y dimensions when the drag begins. I’ve managed to seemingly cure this bug by rounding up the bl_offsets before calling Wimp_DragBox I’m also thinking of changing the code that grabs bg0/1 from the screen to use the existing sprite size defined in s.StartUp. I propose the following API change to DragAnObject: DragAnObjectR0 (flags)
|
Ben Avison (25) 445 posts |
I’m not intimately familiar with these modules, but what you’re describing sounds like a bugfix that you’d always want enabled, so I don’t understand why you’d ever want it turned off. If so, I don’t see the need to add a flag to change the behaviour – just make the change unconditional. Or have I misunderstood somehow – can you explain under what conditions you’d want to set or clear bit 19? |
James Lampard (51) 120 posts |
It’s two separate bugs, the one in DragAnObject where an extra pixel is added is relatively minor (although it does guarantee the much more serious bug in DragASprite occurring) once DragASprite is fixed it will work with either case. In DragAFile I added a fudge factor to make up for extra pixel and centre the object under the pointer, other clients may also be doing this and I wouldn’t want to break them. |
Steve Revill (20) 1361 posts |
We’d welcome a submission which fixes the bugs in both modules from the sound of it. :) |
James Lampard (51) 120 posts |
Here’s the latest version of DragAFile with a fixed version of DragASprite included. http://www4.webng.com/resurgam/ROOL/Test/DRAG4.ZIP Anyone want to test it? I haven’t included a fixed version of DragAnObject yet because that would stop the bug dead before it gets a chance to cause the DragASprite bug. |