|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Wed Jul 18, 2012 3:09 pm Post subject: rambling enquiry about full_mouse_input and callback_reason |
|
|
Some years ago, I wrestled with full_mouse_input in a %gr region. At the time I was much less adept in dealing with Clearwin than I am now, and indeed, I was inter alia attempting to do things that Paul didn’t actually fix until a later version of FTN95 than I was at that time using (notably popup menus in v5.50). I recall some helpful advice given on the forum (by John Campbell among others) about fmi.
I swore (a lot!) at the time that I would never use fmi ever again, but like an alcoholic returning to the bottle, I have attempted a couple of times subsequently to use it, as there is a limit to what one can do with simple clicks and key modifiers. Indeed, the fact that one gets single mouse clicks along with double mouse clicks means that the usefulness of the single click is limited because if one ever wants to respond to a double click the single click can only be associated with something that you don’t mind being invoked en route to the double click. This makes a program idiosyncratic compared to other windows applications as a single left click is then effectively neutered.
However, without fmi, the system is very reliable, and single clicks are detected and responded to very accurately. In my most recent excursion into the minefield of fmi, I discover that code that works well without it, such as:
Code: | CBR = CLEARWIN_STRING@('CALLBACK_REASON')
IF (CBR .EQ. 'MOUSE_LEFT_CLICK') THEN
Do something
ELSE IF (CBR .EQ. 'MOUSE_RIGHT_CLICK') THEN
Do something else
ENDIF |
occasionally misses a click with fmi enabled. This leads the user to a set of activities, such as removing fluff from the mouse or clearing other filth from its working parts, peering at the red light etc., never suspecting the true problem.
On deep reflection, it occurs to me that the original advice from John Campbell, which in effect was to quickly inspect the state of the mouse buttons and mouse coordinates at every invocation of the callback probably means handling the mouse as one did in DOS, interrupt at a time, and not relying on the above ‘callback reason’ approach. In the course of program development, that means abandoning (or at least further complicating) code that one had working satisfactorily. For me, it created a ‘slough of despond’ as I was under the impression for some reason that SET_GRAPHICS_SELECTION@ only worked with fmi. However, I find that this is not actually the case, and I wonder if something changed while I was not looking! I live in hope that eventually popup menus and scroll wheel handling will also not require fmi.
In my graphics callback routine, it would greatly simplify matters if the callback reason was set to something like ‘area_selected’ or ‘elastic_line_drawn’ as presumably one would never get a single or double click callback if SET_GRAPHICS_SELECTION@ was set to mode 1 or 2. (There appears not to be an ‘ENQUIRE_IF_GRAPHICS_AREA_SELECTION_IS_ENABLED@’ option, and at present I am keeping track of whether or not these modes are enabled using an inelegant approach with a COMMON block). Or have I missed something in the depths of FTN95.CHM?
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Wed Jul 18, 2012 3:44 pm Post subject: |
|
|
Eddie,
I probably do not have to much to add to your comments.
My latest approach to coding FMI is to set up a look up table of possible responses using " call call_back_statistics (reason, 1)". I inspect this at the end of a run to see the possible call back responses that occur. There are a few I didn't expect.
Code: | integer*4 function exit_func()
!
call call_back_statistics (' ', -1)
!
call close_output_window
!
exit_func = 0
end function exit_func
|
Also, as I write to the screen (OUTPUT) and to files, I struggle with clashing writes with multiple call-backs and also delays in being ready to write (hence I don't report the first call-back or some of the moves.)
The other key is to skip the MOUSE_MOVE reporting until sufficient movement has occurred, say 20 pixels.
I still have not solved all these problems completely, especially the multiple writes.
The following code is the first few lines of my standard callback handling.
Code: | integer*4 function mouse_back_func()
!
! Callback to respond to %gr callback
! reports the call back reason
!
include <clearwin.ins>
include <JDC_menu.ins>
include 'crtcom.ins'
!
integer*4 :: num_callback = 0
integer*4 :: xs,ys, mf
integer*4 :: xm = 0
integer*4 :: ym = 0
character reason*30
logical use_1, use_98
!
reason = clearwin_string@ ('CALLBACK_REASON')
call get_mouse_info@ (xs, ys, mf)
!
num_callback = num_callback + 1
use_1 = num_callback > 1
use_98 = num_callback > 1
!
if (use_98) then
write (98,*) ' '
write (98,*) 'mouse_back_func Callback : ',reason, num_callback, xs, ys, ptr_RGB_Address
end if
!
call call_back_statistics (reason, 1)
!
if ( reason == 'RESIZE') then
...
subroutine call_back_statistics (reason, call_id)
!
character reason*(*)
integer*4 call_id, i
!
integer*4, save :: num_type = 0
integer*4, save :: num_calls(2,10)
character, save :: reasons(10)*30
!
if ( call_id < 1) then
! write ( *,2000) ' Callback Statistics'
write (98,2000) ' Callback Statistics'
do i = 1, num_type
! write ( *,2001) i, reasons(i), num_calls(:,i)
write (98,2001) i, reasons(i), num_calls(:,i)
end do
2000 format (/a)
2001 format (i4,2x,a,2i10)
else
do i = 1,num_type
if (reason == reasons(i)) exit
end do
if ( i > 10) i = 10
if ( i > num_type ) then
num_type = i
reasons(i) = reason
num_calls(:,i) = 0
num_calls(call_id,i) = 1
else
num_calls(call_id,i) = num_calls(call_id,i) + 1
end if
end if
!
end subroutine call_back_statistics
! |
|
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Wed Jul 18, 2012 4:25 pm Post subject: |
|
|
John,
There's a lot to think about here! My immediate problem is to zoom in on a not very sophisticated map. Without FMI, and just using left_click to zoom in a step, right-click to zoom out, a good choice of step sizes and a limit on both zooming in and out gives me a nice effect. As my graphic is always centred in the screen, I tried a SHIFT or CTRL combo with a click to choose a new centre point. Alas, that causes an ugly jump, and my experience of other windows programs makes me yearn to be able to pan the screen view.
At that point, I contemplated scroll bars - but I dislike them for the whole of a screen-filling %gr. Maybe I should have a click-and-drag panning - but that would seem to require FMI. The logical thing for me was to use box_select, and rescale and re-centre based on that - but until I tried it earlier, I was under the impression that it required FMI as well (I'm sure it used to). It doesn't, but what it does seem to need is a way to know whether box_select is enabled, and to be able to turn it off so that simple clicks can be detected. (A mechanism for this is to select an appropriate toolbar button to swtich the process on and off, but for me, the fewer the big mouse movements and clicking on this and that, the better).
I'm fascinated by the idea of unexpected callback reasons ("There are a few I didn't expect.") How many of them are undocumented callback reasons?
Eddie
[edit]PS to Paul: could the area selection outline be a different colour, and/or the area be filled with a light tint with transparency? E
[second edit]PPS ... and wouldn't it be great if there was a mode 4 for SET_GRAPHICS_SELECTION@ in which nothing was drawn, but the start and finish coordinates of a "click and drag" operation was reported, to facilitate panning of the sort usually done with a 'hand' cursor? E |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Jul 19, 2012 1:26 am Post subject: |
|
|
Eddie,
My call_back_statistics is a recent work in progress.
Call_id can have a value
-1: echo statistics as end of run
1: mouse interrupt
2: mousewheel interrupt
I was thinking of storing a list of callbacks, using num_callback as the count and including cpu_clock@ as an indicator of spacing.
The main surprises I had was with resize and mouse wheel interrupts, where there were more interrupts than I expected. Also the few initial interrupts, before the program is "up and running" cause a few problems.
My blowup approach is also a work in progress (over many years), as I have a number of ideas but not the time to implement.
I do blowups with set_graphics_selection@ : mode=1. It has worked ok in the past.
I am wanting a better zoom and pan. I am thinking of using the mouse wheel to zoom in and out. To review the expanded image, I would create a virtual screen of the full object, then pan around by grabing the screen with the mouse down and draging the virtual screen over the real screen. (H:10,240xV:7,680x4colour_bytes = 300mb, hence the interest in large DIB images). Would work well for a 2D image, but needs more for rolling a 3D image.
I have a 3D roll by draging the mouse about the centre, updating with a wire diagram with the mouse down then a full rendered image when the mouse is released. I developed this over 10 years ago, so faster graphics might have meant that I could update with the rendered image, but the size of problem I have has also increased from about 50k polygons to about 20m.
With the latest problems, I don't select roll very often but do a lot of panning.
I also recently developed a lookup window; a small .1 x .1 screen in the bottom left with an edge line image. I click in this window to select a blow up view location. Works with large images and big zoom.
My call-back handler must know what viewing mode is in use: pan, blowup, rotate, porthole, wobble, lookup or other. Other is to inquire info about selected objects on the screen, so I need to know when all the other options are turned off.
Porthole is another interesting option, where I click on the full view and display a 10x blowup at that point in a .3 x .3 window in the top left. By dragging the mouse, the porthole updates in real time, with a much smaller active model.
As I'm the only user of the software, I don't have problems with tricky users who confuse the interrupt handler. I'd expect that coping with other users is another level of complexity.
I could send you my mouse.f95 if you would like to see some ideas that work for me. I'm sure there are many alternative approaches that work better. Always looking for advice on better ways to manage this. It's surprisingly easy to code some of these options, you just need to have a good idea and a way of managing the update.
John |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Thu Jul 19, 2012 8:19 am Post subject: |
|
|
I have noted this correspondence but the best I can do at the moment is to make and note to investigate when time allows. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Jul 19, 2012 9:16 am Post subject: |
|
|
I will update the callback log to include the list order and elapse times.
I will try to document the first few call-backs and identify what they relate to.
Once the program starts up, I find that recalling what I did to get the call backs is difficult, but I think the first few are of interest.
I recall that if resize is enabled, there is a resize interrupt issued as the program starts. Caused me some problems, as my status variables had not been initialised. I'll investigate and provide ore reliable advice.
John |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Sat Jul 21, 2012 10:30 am Post subject: |
|
|
John,
As always, thanks for the ideas. Fortran programming for me is far from being my main business, and I am often reluctant to dive in too deeply, especially to shark-infested waters (like fmi)! When I have digested this I've return to the topic with my thoughts.
In the meantime, perhaps Paul will consider my suggestion for a mode 4 as it looks to me as though it would be easy to derive from modes 1 and 2, and would be of considerable use when programming panning when not using fmi.
Regards
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Mon Jul 23, 2012 3:34 pm Post subject: |
|
|
Eddie,
I changed the log to store the interrupt reason and the elapse time when it occured. I also included some extra "interrupts", to log key events, as type 3.
the listing of the log, omitting repeated moves is: Code: | Callback listing
No elapse Reason Type
1 0.01398 saplot_first_call 3
2 0.01804 Saplot_Menus 3
3 0.02086 RESIZE 1
4 0.03177 plot_setup_func 3
5 0.03178 set_Window_Size 3
6 38.94277 MOUSE_MOVE 1
160 46.98982 MOUSE_LEFT_CLICK 1
161 47.06987 MOUSE_MOVE 1
202 47.82175 MOUSE_LEFT_RELEASE 1
203 48.08970 MOUSE_MOVE 1
320 59.68949 RESIZE 1
321 59.72217 set_Window_Size 3
322 59.76936 RESIZE 1
323 59.77966 set_Window_Size 3
324 59.80108 RESIZE 1
325 59.81080 set_Window_Size 3
326 59.83377 RESIZE 1
327 59.84348 set_Window_Size 3
328 59.86597 RESIZE 1
329 59.87586 set_Window_Size 3
...
362 60.83729 MOUSE_MOVE 1
457 71.03359 RESIZE 1
458 71.03384 MOUSE_MOVE 1
459 71.09745 set_Window_Size 3
460 71.39687 MOUSE_MOVE 1
804 85.70849 MOUSE_LEFT_CLICK 1
805 85.74657 MOUSE_MOVE 1
843 86.42045 MOUSE_LEFT_RELEASE 1
844 86.89241 MOUSE_MOVE 1
Callback Statistics
1 saplot_first_call 0 0 1
2 Saplot_Menus 0 0 1
3 RESIZE 23 0 0
4 plot_setup_func 0 0 1
5 set_Window_Size 0 0 23
6 MOUSE_MOVE 827 0 0
7 MOUSE_LEFT_CLICK 2 0 0
8 MOUSE_LEFT_RELEASE 2 0 0
|
Note there is a RESIZE interrupt (3) at startup, before the ('%sc&', plot_setup_func) (4) has occurred. This is generated by the program startup and not user initiated.
There is a big delay from interupt 5 to 6, as the program reads the 750 mb data file. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Mon Jul 23, 2012 3:40 pm Post subject: |
|
|
The revised call back loging routine is: Code: | subroutine call_back_statistics (reason, call_id)
!
character reason*(*)
integer*4 call_id
!
integer*4, parameter :: num_log = 5000
character, save :: reason_log(num_log)*30
real*8, save :: reason_sec(num_log)
integer*2, save :: reason_id(num_log)
integer*4, save :: log_count = 0
!
integer*4 num_type, i, k, id
integer*4 num_calls(3,15)
character reasons(15)*30
!
if ( call_id < 1) then ! generate statistics of run
!
write (98,2000) ' Callback listing'
num_type = 0
num_calls = 0
do k = 1,log_count
if (.not. (k>1 .and. reason_log(k)==reason_log(k-1)) ) &
write (98,2002) k, reason_sec(k), reason_log(k), reason_id(k)
!
id = reason_id(k) ; if (id<1) id = 3 ; if (id>3) id = 3
do i = 1,num_type
if (reason_log(k) == reasons(i)) exit
end do
if ( i > 15) i = 15
if ( i > num_type ) then
num_type = i
reasons(i) = reason_log(k)
end if
num_calls(id,i) = num_calls(id,i) + 1
end do
!
write (98,2000) ' Callback Statistics'
do i = 1, num_type
write (98,2001) i, reasons(i), num_calls(:,i)
end do
2000 format (/a)
2001 format (i4,2x,a,3i10)
2002 format (i0,f10.5,1x,a,i3)
!
else ! store call-back in list
!
if (log_count < num_log) log_count = log_count+1
reason_log(log_count) = reason
reason_id(log_count) = call_id
call ELAPSE_SECOND (reason_sec(log_count))
end if
!
end subroutine call_back_statistics |
|
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Mon Jul 23, 2012 7:28 pm Post subject: |
|
|
John,
Taking 40 seconds to load the file! It is probably a good job you are your main user, or you would be programming something to keep them busy while the 40 seconds ticks by.
Thanks for your suggestions / code. When I get a spare hour or two I will revisit the hell of fmi ...
I've been drawing icons. As thumbs up and thumbs down have defeated my limited artistic abilities I've settled on smilies ...
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Jul 26, 2012 2:04 am Post subject: |
|
|
Paul,
This is the first time I have been able to clearly document the effect of multiple interrupts and probably why I am getting the "write over write error"
You will note that the first 5 interrupts I have identified are :
Code: | No elapse Reason Type
1 0.01398 saplot_first_call 3 ! false interrupt as first executable line of code
2 0.01804 Saplot_Menus 3 ! false interrupt at first %mn
3 0.02086 RESIZE 1 ! real interrupt as resize is enabled
4 0.03177 plot_setup_func 3 ! false interrupt as first %sc start
5 0.03178 set_Window_Size 3 ! false interrupt during RESIZE response |
Interrupt 4 shows that %sc initialisation is being implemented while the response to the RESIZE interrupt is taking place. I presume these could be multiple threads and both groups of code can be updating the same variables.
It might not be a good thing to try, but is it possible to lock an interrupt response, so that other associated theads do not conflict. It would make the code easier to debug.
At present these two threads can conflict for I/O, where both are reporting a status u[pdate to my unit 98 log file.
I now have a better idea why the program is going wrong at startup. It does not always happen as it changes on different PC's where the relative run times of the threads change, resulting in different clashes.
Not sure what the best response to this is.
John
PS : Further to this post, I'm not sure why I use %sc at all.
I use %sc to call a variable initialisation set of routines.
Altertatively, I could call the initilisation code before any winio@ calls. Is the purpose of %sc to enable code to be run that uses routines that assume that the menu system is in place ?
I am not sure if with WINAPP if I should do a lot of computation before any winio@ calls.
What is your understanding of the timing restrictions of a startup approach ?
I'm probably making this more complex than it needs to be ! |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Jul 26, 2012 2:34 am Post subject: |
|
|
Not sure now, as Set_Widow_Size can be called from either RESIZE or %SC, although I had assumed that RESIZE response occurred after %SC.
The startup code I use is:
Code: | program test ! latest \PHPA_post_Dredge\saplot.new
!
use ceasap_variables
!
include <clearwin.ins>
include <JDC_menu.ins>
include 'sapcom.ins'
include 'plotcom.ins'
include 'srcom.ins'
!
integer*4 :: i, hwnd
integer*4 mouse_back_func, plot_setup_func, OnMouseWheel
external mouse_back_func, plot_setup_func, OnMouseWheel
!
integer*4, parameter :: WM_MOUSEWHEEL = Z'020A'
!
character build_stamp*30
logical full_screen
!
call call_back_statistics ('saplot_first_call', 3)
!
full_screen = .false. ! .true.
!
! Initialise for no greyed options
!
call crtstart ! this is called again in plot_setup_func ??
!
include 'build.ins'
caption ='GHD STRUCTURES SUITE : FEA MODEL : Build date '//build_stamp
!
i = winio@ ('%ca@&', caption)
!
if (full_screen) then
i = winio@ ('%ww[no_border,maximise]&')
else
i = winio@ ('%ww[no_border]&')
end if
!
i = winio@ ('%sc&', plot_setup_func) ! call saplot setup function
i = winio@ ('%pv&')
!
i = winio@ ('%`^gr[grey, user_resize, rgb_colours, full_mouse_input, user_surface]&', &
1024, 768, & ! screen dimension when not maximised
ptr_RGB_Address, & ! screen address for rgb surface ( not sure of the order ? )
w_handle, & ! ` window handle defined in crtstart
mouse_back_func) ! ^ call back function for mouse and resize
!
i = winio@ ('%mg&', WM_MOUSEWHEEL, OnMouseWheel) ! mousewheel response
!
call Saplot_Menus
!
i = winio@ ('%hw', hwnd) ! return the handle of the current window.
!
end program test
integer*4 function plot_setup_func()
!
! Initialise structure info
!
use ceasap_variables
!
! include <clearwin.ins>
include <JDC_menu.ins>
include 'sapcom.ins'
include 'plotcom.ins'
include 'srcom.ins'
!
integer*4 open_func, Rotate_isoZ_func, option_update_plot, i, ilc, iauto
external open_func, Rotate_isoZ_func, option_update_plot
real*8 fc
!
call call_back_statistics ('plot_setup_func', 3)
!
call crtstart
!
call set_Window_Size
!
! Initilaise SAP binary file I/O
call initbf
!
.... |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 Location: Salford, UK
|
Posted: Thu Jul 26, 2012 7:48 am Post subject: |
|
|
John
I am not able to respond to this in detail at the moment but here are a few random comments.
My understanding is that we have to think in terms of a single thread but this serves a message queue that is fed by SendMessage and PostMessage calls. The difference being that SendMessage waits for a return whilst PostMessage does not. In addition ClearWin+ can also peek a message before taking it out of the queue and processing it.
Messages can only be added to the end of the queue and processed one at a time. So the question in the end is what is the order in which the messages are sent.
Regarding %sc, I think that this is equivalent to the message WM_INITDIALOG and thus provides information whilst the window is being created by the API and before it is displayed. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Jul 26, 2012 8:46 am Post subject: |
|
|
Paul,
Thanks for your response.
Based on your single thread comment, am I wrong in thinking that the first RESIZE interrupt from
winio@ ('%`^gr[grey, user_resize, rgb_colours, full_mouse_input, user_surface]&', &
could conflict with %sc ?
IN the past I have had an error that a write event has occurred while another routine has itself performed I/O ( sorry I can't recall the exact message)
I assumed this was due to a seperate thread for the interrupts.
If it is not then I will have to look for another reason and a search as to how to clean it up.
John |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Wed Aug 01, 2012 1:16 am Post subject: |
|
|
Paul,
I have been thinking about the problem of the relative timing of the start-up events.
%gr initiates the window state and in the example I have provided, initiates the mouse response and also the resize response.
To initialise the program settings, I call some routines before any winio@ routines (eg crtstart) and also use %sc for some other routines (via my routine plot_setup_function).
It would appear that I should change the structure of this so that I initialise all data structures not related to the %gr window before the first winio@ call and include in plot_setup_function those data structures which depend on %gr.
Also as RESIZE is initiated before the %sc response, I should check that it can work at this time, although the RESIZE response does require some of the window dimensions to be initialised. (Not being aware that this could occur has caused problems recently.)
I think the answer to this problem is to be aware of the potential timing of these events, as I suspect there is not much that can (or should) be changed.
My understanding of the mouse, resize, mouse wheel or menu interrupts is that they are separate "threads" that act independently of each other. It is important to try and minimise the coded response time so that they do not conflict. My question before is can we queue these interrupts up so that they are processed one at a time. I have had the impression that especially with MOUSE_MOVE interrupts that they do not wait for the last interrupt to be completed, which is typically found with fmi.
I would welcome your comments on any of these thoughts.
John |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|