Fl::event_x() and Fl::event_y() negative for FL_MOUSEWHEEL !!!???

127 views
Skip to first unread message

Gonzalo Garramuño

unread,
Feb 7, 2021, 12:06:48 PM2/7/21
to fltkg...@googlegroups.com

I have a problem in my program in that a user is getting negative values for Fl::event_x() and Fl::event_y() depending on where he has a smaller fltk gl window in the screen.
Thus, my program zooms incorrectly.  This is on Windows and I am unable to reproduce the problem on my machine with Windows 8.1.

The user has two monitors.  The primary display set to 100% and the secondary display set to 125%.  The primary screen is set to 1920x1200 and the secondary to 1920x1080.  Currently we are testing the primary display first.

Here's a video of the problem he has:

https://imgur.com/a/emlrpL1

and here's the logging of the coordinates I got from him (the first x,y= is the event_x() and event_y() as it comes from fltk ).  You will see that the two bottom and top right positions give negative values:

  1. Maximized:
  2. [opengl] mrv::GLEngine::reset_view_matrix(670) view pixels: 1920x1088
  3. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  4. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  5. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=1920x1088
  6. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=1004, 558

  7. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  8. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  9. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=1920x1088
  10. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=1002, 560

  11.  
  12. Top Left [gui] mrv::ImageView::fit_image(2341) >>>>>>>> FIT IMAGE
  13. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  14. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000 [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  15. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=295, 218

  16. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  17. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  18. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  19. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=303, 219

  20.  
  21. Top Right
  22. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  23. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  24. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  25. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=-941, 204

  26. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  27. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  28. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  29. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=-941, 204

  30.  
  31. Bottom Left
  32. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  33. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  34. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  35. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=311, -365

  36. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  37. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  38. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  39. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=311, -365

  40.  
  41. Bottom Right
  42. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  43. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  44. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  45. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=-956, -361

  46. [gui] mrv::ImageView::zoom_under_mouse(8882) 0 -------------------------------------------------------
  47. [gui] mrv::ImageView::zoom_under_mouse(8884) 1 screen=0 scale= 1.000000
  48. [gui] mrv::ImageView::zoom_under_mouse(8886) 2 WxH=640x501
  49. [gui] mrv::ImageView::zoom_under_mouse(8887) 3 x,y=-956, -361
-- 
Gonzalo Garramuño

lifeatt...@gmail.com

unread,
Feb 7, 2021, 5:47:54 PM2/7/21
to fltk.general
>I have a problem in my program in that a user is getting negative values for Fl::event_x() and Fl::event_y() depending on where he has a smaller fltk gl window in >the screen.

You don't tell us what version of FLTK is involved, nor do you show us any code. So it will be difficult to assist.

A negative Y position suggests the monitor scale/position is confusing the position calculations [yours or FLTK's]. Does the user experience the problem when their secondary display is disabled / disconnected?  When both monitors are at 100% scale?

Albrecht Schlosser

unread,
Feb 7, 2021, 6:08:05 PM2/7/21
to fltkg...@googlegroups.com
On 2/7/21 11:47 PM lifeatt...@gmail.com wrote:
> >I have a problem in my program in that a user is getting negative
> values for Fl::event_x() and Fl::event_y() depending on where he has a
> smaller fltk gl window in >the screen.
>
> You don't tell us what version of FLTK is involved, nor do you show us
> any code. So it will be difficult to assist.

... and I'd like to add that the OS is also a very important information
when we're talking about system specific things like mousewheel handling
and display scaling.

@Gonzalo: I also looked at the video you posted and I wonder how we
should be able to tell what the expected behavior would be and what the
unexpected behavior is. I have no idea.

Albrecht Schlosser

unread,
Feb 7, 2021, 6:28:31 PM2/7/21
to fltkg...@googlegroups.com
Forwarding this message to the group because Gonzalo sent it to my
personal mail address.

-------- Forwarded Message --------
Subject: Re: [fltk.general] Re: Fl::event_x() and Fl::event_y() negative
for FL_MOUSEWHEEL !!!???
Date: Sun, 7 Feb 2021 20:20:57 -0300
From: Gonzalo Garramuño <...>
To: Albrecht Schlosser <...>

El 07/02/2021 a las 20:08, Albrecht Schlosser escribió:
> On 2/7/21 11:47 PM lifeatt...@gmail.com wrote:
>>  >I have a problem in my program in that a user is getting negative
>> values for Fl::event_x() and Fl::event_y() depending on where he has
>> a smaller fltk gl window in >the screen.
>>
>> You don't tell us what version of FLTK is involved, nor do you show
>> us any code. So it will be difficult to assist.
>
> ... and I'd like to add that the OS is also a very important
> information when we're talking about system specific things like
> mousewheel handling and display scaling.
>
Ok.  It is version 1.4 git head.  It is Windows.
> @Gonzalo: I also looked at the video you posted and I wonder how we
> should be able to tell what the expected behavior would be and what
> the unexpected behavior is. I have no idea.
>
The video shows the user trying to zoom in/out to the mouse position in
different window positions.  The zooming should happen onto the location
of the cursor.  Only the full window and the top left window seem to
succeed.  The others derail the view quite significantly due to the
Fl::event_x() or Fl::event_y() ( or both ) being negative.

--
Gonzalo Garramuño

Gonzalo Garramuño

unread,
Feb 7, 2021, 6:32:41 PM2/7/21
to fltkg...@googlegroups.com

El 07/02/2021 a las 19:47, lifeatt...@gmail.com escribió:
>
> A negative Y position suggests the monitor scale/position is confusing
> the position calculations [yours or FLTK's]. Does the user experience
> the problem when their secondary display is disabled / disconnected? 
> When both monitors are at 100% scale?
>
Not sure.  He experiences the problem also on the second monitor but at
a 125% scale.  I'll have him disable the monitor and set its scale to 100%.

--
Gonzalo Garramuño

Anon Mouse

unread,
Feb 7, 2021, 7:13:28 PM2/7/21
to fltkg...@googlegroups.com
Looking at the FLTK 1.4 source code, it is not clear that Fl::event_x and Fl::event_y have been updated on WM_MOUSE*WHEEL events. I.e. if some other event occurs which modifies those globals, it is possible that they don't correspond to the mouse position when the WM_MOUSEWHEEL event occurs.

[FLTK internals experts may be able to say if I'm wrong - the code in question is FL_win32.cxx, method WndProc(): the WM_MOUSEWHEEL handling case, which does NOT call mouse_event() to update event_x/event_y.]

An experiment would be to have the user perform some other mouse event before using the mouse wheel. You know your application best as to what mouse event they can perform without changing behavior - left click, right click, etc.

I'm also unclear how GL impacts any of this, I'll poke further.

lifeatt...@gmail.com

unread,
Feb 7, 2021, 8:19:37 PM2/7/21
to fltk.general
>Looking at the FLTK 1.4 source code, it is not clear that Fl::event_x and Fl::event_y have been updated on WM_MOUSE*WHEEL events. 
Empirically I appear to be wrong. Modifying the gl_overlay sample to log mouse position to the console, the event_x/event_y values are updated.

I DO get negative mousewheel location values if I do my mousewheel scrolling outside the window with the handle() method. event_x/event_y values are relative to said window. Unlike other mouse events, I get mousewheel events even if the mouse pointer is outside the window.

lifeatt...@gmail.com

unread,
Feb 7, 2021, 8:56:54 PM2/7/21
to fltk.general
Wish I could edit a reply rather than posting another...

Those numbers in the logging look consistent with a calculation error. It appears as if the X/Y values have been calculated by subtracting the window X,Y from the mousewheel X,Y.

Take the upper right case. The Window is 640 wide and positioned so it has a X value of about 1250. Mousing in the middle of the window has an X value of about 300. 300 minus 1250 is -950 ...

Take the lower left case. The Window is 500 high and positioned so it has a Y value of about 500. Mousing in the middle of the window has a Y value of about 250. 250 minus 500 is -250 ...

Works fine in the upper left and full screen because the Window X,Y values would be around (0,0).

Mouse event values are relative to their window, NOT relative to the screen. So clicking in the middle of the window is at (e.g) (300,250) relative to the current image viewport.

I think I'm speculating too much in the absence of any real code ...

Gonzalo Garramuño

unread,
Feb 7, 2021, 9:15:39 PM2/7/21
to fltkg...@googlegroups.com

El 07/02/2021 a las 22:56, lifeatt...@gmail.com escribió:
>
> I think I'm speculating too much in the absence of any real code ...

Here's some sample code, albeit not much to go thru or comprehend:

int handle( int event )
{

// Standard handling code for all other events

    case FL_MOUSEWHEEL:
    {
            Fl_Gl_Window::handle( event );
            if ( Fl::event_dy() < 0.f )
            {
                zoom_under_mouse( _zoom * 2.0f,
                                  Fl::event_x(), Fl::event_y() );
            }
            else
            {
                zoom_under_mouse( _zoom * 0.5f,
                                  Fl::event_x(), Fl::event_y() );
            }
            return 1;
            break;
    }

}

void ImageView::zoom_under_mouse( float z, int x, int y )
{
    if ( !vr() && (z > kMaxZoom || z < kMinZoom) ) return;
    double mw = (double) w() / 2;
    double mh = (double) h() / 2;
    double offx = mw - x;
    double offy = mh - y;
    double xf = (double) x;
    double yf = (double) y;

    mrv::media fg = foreground();
    if ( ! fg ) {
        // no image, set zoom factor and exit
        zoom( z );
        return;
    }

    CMedia* img = fg->image();

    const mrv::Recti& dpw = img->display_window();

    int W = dpw.w();
    int H = dpw.h();

    float scale = Fl::screen_scale( window()->screen_num() );

    DBGM1( "0 -------------------------------------------------------" );
    DBGM1( "1 screen=" << window()->screen_num() << " scale= " << scale
           );

    DBGM1( "2 WxH=" << w() << "x" << h() );

    //
    // HERE's the printout of FLTK coords
    //

    DBGM1( "3 x,y=" << x << ", " << y );

    // This routine turns fltk coords into the image coords
    image_coordinates( img, xf, yf );

    // These are the image coordinates previous the zoom
    DBGM1( "4 xf,yf=" << xf << ", " << yf );
    DBGM1( "5 zoom=" << _zoom << " realzoom=" << _real_zoom );

    zoom( z );

    int w2 = W / 2;
    int h2 = H / 2;

    // These are the image offsets previous the zoom
    DBGM1( "6 xoff,yoff=" << xoffset << ", " << yoffset );

    xoffset = w2 - xf;
    yoffset = h2 - ( H - yf );
    xoffset -= (offx / _real_zoom)

    double ratio = 1.0f;
    if ( _showPixelRatio ) ratio = img->pixel_ratio();

    yoffset += (offy / _real_zoom * ratio);

    // HERE's the image offsets past the zoom
    DBGM1( "7 zoom=" << _zoom << " realzoom=" << _real_zoom );
    DBGM1( "8 xoff,yoff=" << xoffset << ", " << yoffset );

    mouseMove( x, y );
}


--
Gonzalo Garramuño

Albrecht Schlosser

unread,
Feb 8, 2021, 6:55:23 AM2/8/21
to fltkg...@googlegroups.com
On 2/8/21 1:13 AM Anon Mouse wrote:
> Looking at the FLTK 1.4 source code, it is not clear that Fl::event_x
> and Fl::event_y have been updated on WM_MOUSE*WHEEL events. I.e. if some
> other event occurs which modifies those globals, it is possible that
> they don't correspond to the mouse position when the WM_MOUSEWHEEL event
> occurs.

W/o looking at the code in question I'd say that you need to move the
mouse to a window/screen position before you can use the mousewheel at
that position. The mouse move would update the mouse coordinates, hence
it's not necessary to do so for WM_MOUSEWHEEL.

> [FLTK internals experts may be able to say if I'm wrong - the code in
> question is FL_win32.cxx, method WndProc(): the WM_MOUSEWHEEL handling
> case, which does NOT call mouse_event() to update event_x/event_y.]

Generally FLTK leaves all event_* variables as-is so they always refer
to the last event for which they *were* relevant. For instance, keyboard
events don't change mouse event variables and vice versa.

Albrecht Schlosser

unread,
Feb 8, 2021, 7:12:46 AM2/8/21
to fltkg...@googlegroups.com
On 2/8/21 2:19 AM lifeatt...@gmail.com wrote:
>
> I DO get negative mousewheel location values if I do my mousewheel
> scrolling outside the window with the handle() method. event_x/event_y
> values are relative to said window.

That sounds plausible, although ...

> Unlike other mouse events, I get
> mousewheel events even if the mouse pointer is outside the window.

... that's an interesting observation.

Where did you see these events? In FLTK's own event handling (in
Fl_win32.cxx) or in a handle() method of a window/widget?

If you don't get mouse move events (which *IS* plausible because the
mouse is outside the window) then I don't know how the update of the
mouse coordinates would be done. Of course, if your other observation is
true that mousewheel events don't update the mouse coordinates.

OTOH, if FLTK gets the mouse move event even if the mouse is outside the
window (which I doubt), updates the mouse coordinates internally but
doesn't send mouse events to any window because the mouse is outside all
windows, then this would also make sense. Puzzled...

Gonzalo Garramuño

unread,
Feb 8, 2021, 7:37:43 AM2/8/21
to fltkg...@googlegroups.com

El 08/02/2021 a las 08:55, Albrecht Schlosser escribió:
> On 2/8/21 1:13 AM Anon Mouse wrote:
>> Looking at the FLTK 1.4 source code, it is not clear that Fl::event_x
>> and Fl::event_y have been updated on WM_MOUSE*WHEEL events. I.e. if
>> some other event occurs which modifies those globals, it is possible
>> that they don't correspond to the mouse position when the
>> WM_MOUSEWHEEL event occurs.
>
> W/o looking at the code in question I'd say that you need to move the
> mouse to a window/screen position before you can use the mousewheel at
> that position. The mouse move would update the mouse coordinates,
> hence it's not necessary to do so for WM_MOUSEWHEEL.
>
Yes, my user does that.  He positions the cursor in the middle of the
window and then uses the mousewheel which reports wrong coordinates as
you saw.

--
Gonzalo Garramuño

Albrecht Schlosser

unread,
Feb 8, 2021, 10:08:43 AM2/8/21
to fltkg...@googlegroups.com
On 2/8/21 1:37 PM Gonzalo Garramuño wrote:
>
> El 08/02/2021 a las 08:55, Albrecht Schlosser escribió:
>>
>> W/o looking at the code in question I'd say that you need to move the
>> mouse to a window/screen position before you can use the mousewheel at
>> that position. The mouse move would update the mouse coordinates,
>> hence it's not necessary to do so for WM_MOUSEWHEEL.

I can confirm this with my demo program (below).

> Yes, my user does that.  He positions the cursor in the middle of the
> window and then uses the mousewheel which reports wrong coordinates as
> you saw.

Gonzalo, it's hard to follow your program and debug output. I decided to
create a new event handling test/demo program and committed this to Git
master. This demo is compatible with 1.3 and can be built standalone
(e.g. `fltk-config -g --use-gl --compile handle_events.cxx') or with the
normal FLTK library build.

Please use this demo for testing and report under which circumstances
you see invalid (negative) coordinates for FL_MOUSEWHEEL events. I could
not see such wrong coordinates (albeit only with one screen so far).

To get this demo, either update your local FLTK repo (git pull) or
download the demo directly from:

https://raw.githubusercontent.com/fltk/fltk/master/test/handle_events.cxx

Note 1: There is advice in the demo how to edit it to change the
Fl_Double_Window to an Fl_Gl_Window. In this case the Quit button is not
visible, however I can still see the same behavior.

Note 2: I didn't test a subwindow of type Fl_Gl_Window. In that case I
would expect the mouse coordinates to be relative to the subwindow.
Would be an interesting test case...

Note 3: Under Windows you may need to build the "Debug" version *and*
run the demo from a DOS (console) window. In my tests I used Visual
Studio and ran the demo directly from the IDE (Debug menu).

Note 4: Tested under Linux and with my MinGW cross-build under Linux,
using wine to run as well.

Note 5: I could see FL_SHORTCUT events reporting coordinates outside the
window (once the correct x/y and a second time the faulty x/y
coordinates). This is a case that needs to be investigated but it's
certainly not related.

@Kevin: I can't see FL_MOUSEWHEEL events outside the window (as expected
by me). Can you confirm this? Can you modify the demo to show what you
saw, i.e. FL_MOUSEWHEEL events with the mouse pointer outside the window?

lifeatt...@gmail.com

unread,
Feb 8, 2021, 11:13:41 AM2/8/21
to fltk.general

>W/o looking at the code in question I'd say that you need to move the
>mouse to a window/screen position before you can use the mousewheel at
>that position. The mouse move would update the mouse coordinates, hence
>it's not necessary to do so for WM_MOUSEWHEEL.

Yes, that makes sense.

>> Unlike other mouse events, I get
>> mousewheel events even if the mouse pointer is outside the window.

>Where did you see these events? In FLTK's own event handling (in
>Fl_win32.cxx) or in a handle() method of a window/widget?

I had modified the gl_overlay.cxx test example to do a printf() of
event_x/event_y on FL_PUSH and FL_MOUSEWHEEL events. This is in an
added handle() method in the Fl_Gl_Window overload.

Once the mouse cursor has left said window, FL_PUSH events are no
longer printed. But FL_MOUSEWHEEL events still are.

>OTOH, if FLTK gets the mouse move event even if the mouse is outside the
>window (which I doubt), updates the mouse coordinates internally but
>doesn't send mouse events to any window because the mouse is outside all
>windows, then this would also make sense. Puzzled...

I also believe WM_ mouse events are not reported to the window after the
cursor has left, but I'm going to have to confirm via MSDN.

>@Kevin: I can't see FL_MOUSEWHEEL events outside the window (as expected
>by me). Can you confirm this? Can you modify the demo to show what you
>saw, i.e. FL_MOUSEWHEEL events with the mouse pointer outside the window?

Yes, I'll give your and my variant another look.

One difference between my code and "handle_events.cxx" is that my handle()
event is on the Fl_Gl_Window sub-window, not the main window. I'll try 
an event handler on the main window as well. I'll post my code after that.

Gonzalo Garramuño

unread,
Feb 8, 2021, 11:38:11 AM2/8/21
to fltkg...@googlegroups.com

El 08/02/2021 a las 12:08, Albrecht Schlosser escribió:
> On 2/8/21 1:37 PM Gonzalo Garramuño wrote:
>>
>> El 08/02/2021 a las 08:55, Albrecht Schlosser escribió:
>>>
>>> W/o looking at the code in question I'd say that you need to move
>>> the mouse to a window/screen position before you can use the
>>> mousewheel at that position. The mouse move would update the mouse
>>> coordinates, hence it's not necessary to do so for WM_MOUSEWHEEL.
>
> I can confirm this with my demo program (below).

Thank you for the program, but I wrote my own.  See attached:

I cannot reproduce the wrong coordinates myself since it is a user of my
program that has the problem.  I will pass him the program and see what
he says.

--
Gonzalo Garramuño

mousewheel.cxx

Albrecht Schlosser

unread,
Feb 8, 2021, 11:42:00 AM2/8/21
to fltkg...@googlegroups.com
On 2/8/21 5:13 PM lifeatt...@gmail.com wrote:
>
> I had modified the gl_overlay.cxx test example to do a printf() of
> event_x/event_y on FL_PUSH and FL_MOUSEWHEEL events. This is in an
> added handle() method in the Fl_Gl_Window overload.
>
> Once the mouse cursor has left said window, FL_PUSH events are no
> longer printed. But FL_MOUSEWHEEL events still are.

OK, that makes sense, probably. It's possible that *FLTK* delegates the
FL_MOUSEWHEEL events to subwindows whereas FL_PUSH events are only
delivered to widgets that are below the mouse (pointer). I'm not sure at
all about that.

> I also believe WM_ mouse events are not reported to the window after the
> cursor has left, but I'm going to have to confirm via MSDN.

Yes, as said above, it's possible that FLTK forwards the FL_MOUSEWHEEL
events to subwindows.

> ... I'll give your and my variant another look.
>
> One difference between my code and "handle_events.cxx" is that my handle()
> event is on the Fl_Gl_Window sub-window, not the main window. I'll try
> an event handler on the main window as well. I'll post my code after that.

Looking forward to your results. Thanks a lot for your help.

lifeatt...@gmail.com

unread,
Feb 8, 2021, 11:55:17 AM2/8/21
to fltk.general
Gonzalo -
>Thank you for the program, but I wrote my own.  See attached:

Thank you for the code. My program is closer to yours than Albrecht's, as my handle() is in the Fl_Gl_Window "sub-window", not the main window class.

I could see from the video that your user appeared to have his mouse cursor in the middle of the (sub) window. Under normal circumstances this means event_x/event_y _should_ be positive. In my testing this has been consistently true, event with multi-monitors. The fact you cannot repro the issue either suggests something distinct about your user's setup.

Testing with your demo program by your user will hopefully answer many questions.
Kevin

Greg Ercolano

unread,
Feb 8, 2021, 12:08:35 PM2/8/21
to fltkg...@googlegroups.com

My only input to this thread; make sure your handle() methods are not eclipsing
important events from the parent class.

The programming pattern I see in mousewheel.cxx is not normal; the Fl_Gl_Window
is not seeing any events except the ones you explicitly pass down.

For instance it eclipses FL_SHOW and FL_HIDE from Fl_Gl_Window.
And the default: condition eclipses ALL other events not named in your case statement.
That in particluar is bad, because there may be FLTK events you don't know about that
the Fl_Gl_Window needs to consume to work correctly.

I would suggest you use an event handler() more like this, to ensure Fl_Gl_Window
gets to see ALL events, and then you can handle the ones you want after:

int handle(int event) {
    int ret = Fl_Gl_Window::handle(event);    // ensure *ALL* events get to Fl_Gl_Window
    switch (event) {
         case FL_FOCUS:
         case FL_UNFOCUS:
         case FL_ENTER:
         case FL_LEAVE:
         case FL_RELEASE:
         case FL_MOVE:
         case FL_DRAG:
         case FL_SHOW:
         case FL_HIDE:
               ret = 1;
                break;
         case FL_PUSH:
                std::cerr << "PUSH: " << X << ", " << Y << std::endl;
                ret = 1;
    }
    return ret;   // returns your changes, or if none, preserves Fl_Gl_Window's return value (IMPORTANT)
}

Or, if you really want to eclipse specific events like FL_SHOW and FL_HIDE from the
parent class, then you can use your code, but at least be sure the default: condition
passes all other events to the parent class, e.g.

    default: return Fl_Gl_Window::handle(event);
       
This may not mean much in the case of this program, but as a general rule it's important
to make sure when you create a handle() overload, you don't starve the parent class of
events it may need to operate correctly.

lifeatt...@gmail.com

unread,
Feb 8, 2021, 12:21:48 PM2/8/21
to fltk.general
A quick update before I start making code changes. TLDR: as far as I can see, FLTK is behaving completely correct and as expected and my confusion is all due to WM_MOUSEWHEEL magic.

>OK, that makes sense, probably. It's possible that *FLTK* delegates the
>FL_MOUSEWHEEL events to subwindows whereas FL_PUSH events are only
>delivered to widgets that are below the mouse (pointer). I'm not sure at
>all about that.

How I'm seeing negative event_x/event_y values for FL_MOUSEWHEEL is when the mouse cursor is outside the sub-window but inside the main window. The gl_overlay.cxx program is different from handle_events.cxx in that the sub-window does not occupy the full space of the main window.

With the mouse cursor sitting above the sub-window yet within the main window, the FL_MOUSEWHEEL event in the sub-window has a negative event_y value. For the main window, the event_y value is positive.

As I move the mouse cursor outside the *main* window, FLTK can no longer track the mouse and event_x/event_y are set to the _last_ position FLTK could know. If I scroll the mousewheel [without clicking!] then FL_MOUSEWHEEL events are received and event_x/event_y are still at the _last_ value. [Any implication I might have made that event_x/event_y was *changing* after leaving the FLTK main window was incorrect.]

WM_MOUSE* events are not sent to a window when the mouse is outside the window bounds. An app can "capture" the mouse to see mouse events outside the window, but FLTK is not doing this.

WM_MOUSEWHEEL is different as (from the docs):

Sent to the focus window when the mouse wheel is rotated.

As long as I have not clicked the mouse, the FLTK window still has focus. The mouse cursor is outside the window but the WM_MOUSEWHEEL event will be sent to the FLTK window.

My modified version of gl_overlay.cxx attached for reference.

gl_overlay.cxx

Gonzalo Garramuño

unread,
Feb 8, 2021, 3:03:19 PM2/8/21
to fltkg...@googlegroups.com

El 08/02/2021 a las 14:21, lifeatt...@gmail.com escribió:
> A quick update before I start making code changes. TLDR: as far as I
> can see, FLTK is behaving completely correct and as expected and my
> confusion is all due to WM_MOUSEWHEEL magic.
>
Ok.  I passed my program to my user and he reports that he gets negative
numbers on FL_MOUSEWHEEL on all positions of the window (640x480) but
the top left position. But he gets positive numbers on FL_PUSH everywhere.

--
Gonzalo Garramuño

lifeatt...@gmail.com

unread,
Feb 8, 2021, 3:09:01 PM2/8/21
to fltk.general
Well I've tried Albrecht's code in combo with mine and saw no issues, even on multi-monitor and various scaling factors.

> I passed my program to my user and he reports that he gets negative numbers on FL_MOUSEWHEEL

So which version of Windows (10? and what release) is your user have, and does he have some sort of exotic pointing device?

Ian MacArthur

unread,
Feb 8, 2021, 4:06:05 PM2/8/21
to fltkg...@googlegroups.com
A longshot maybe, but monitor layout may matter?

On my old work system (which, lockdown, I no longer access...) the secondary monitor was positioned to the left of the primary, and so all the window position coordinates on that monitor were negative. On the test rigs, they were set up the “other way”, i.e. secondary monitor to the right, and there the window co-ordinates were (of course) all positive...

So I wonder if the actual layout of the monitors is somehow affecting what Gonzalo’s user sees, in some way, and why Kevin does not see the same?

Greg Ercolano

unread,
Feb 8, 2021, 6:01:08 PM2/8/21
to fltkg...@googlegroups.com


On 2/8/21 8:41 AM, Albrecht Schlosser wrote:
On 2/8/21 5:13 PM lifeatt...@gmail.com wrote:

I had modified the gl_overlay.cxx test example to do a printf() of
event_x/event_y on FL_PUSH and FL_MOUSEWHEEL events. This is in an
added handle() method in the Fl_Gl_Window overload.

Once the mouse cursor has left said window, FL_PUSH events are no
longer printed. But FL_MOUSEWHEEL events still are.

OK, that makes sense, probably. It's possible that *FLTK* delegates the FL_MOUSEWHEEL events to subwindows whereas FL_PUSH events are only delivered to widgets that are below the mouse (pointer). I'm not sure at all about that.

I also believe WM_ mouse events are not reported to the window after the
cursor has left, but I'm going to have to confirm via MSDN.

Yes, as said above, it's possible that FLTK forwards the FL_MOUSEWHEEL events to subwindows.


    FWIW, if I make the following change to test/subwindow.cxx:

--- a/test/subwindow.cxx
+++ b/test/subwindow.cxx
@@ -82,6 +82,8 @@ int testwindow::handle(int e) {
 #ifdef DEBUG
   if (e != FL_MOVE) printf("%s : %s\n",label(),fl_eventnames[e]);
 #endif
+  if (e == FL_MOUSEWHEEL )
+    { printf("[%s] mousewheel event x/y= %d/%d\n", label(), Fl::event_x(), Fl::event_y()); }
   if (crsr!=FL_CURSOR_DEFAULT) {
     if (e == FL_ENTER)
       cursor(crsr);


    ..I can easily get negative values for the Fl::event_x()/y() values for the  'inner window'
    if my mouse is above and to the left of the inner subwindow while I roll the mouse, e.g.

$ ./subwindow
[outer] mousewheel event x/y= 69/79
[inner] mousewheel event x/y= -31/-21
[outer] mousewheel event x/y= 69/79
[inner] mousewheel event x/y= -31/-21

    I get this on linux too. Is this what we're talking about, or is it something else?
 

lifeatt...@gmail.com

unread,
Feb 8, 2021, 6:09:04 PM2/8/21
to fltk.general
>    ..I can easily get negative values for the Fl::event_x()/y() values for the  'inner window'
>    if my mouse is above and to the left of the inner subwindow while I roll the mouse, e.g.

That is consistent with the behavior I am seeing. The original issue is something else.

The OP, Gonzalo, is reporting his user has a different issue. His user is getting negative values on FL_MOUSEWHEEL when the mouse is positioned _within_ the sub-window. The degree and sign for the values varied depending on where the FLTK window was positioned on the user's screen.

The OP, Albrecht and I have been unable to repro the user-reported issue.

lifeatt...@gmail.com

unread,
Feb 8, 2021, 6:21:33 PM2/8/21
to fltk.general
>On my old work system (which, lockdown, I no longer access...) the secondary monitor was positioned to the left of the primary

Thanks Ian but I was thinking the same. I tried both situations: the secondary monitor "left" and "right" and in neither case did I see any change in behavior. 

I'm only partially approaching the user's setup as I tested on Windows 7 where I can only set one scale for all monitors. At least my monitors are also different resolutions. I think separate monitor scales requires Win10 but I want to hear from Gonzalo what the user is running.

Greg Ercolano

unread,
Feb 8, 2021, 7:29:28 PM2/8/21
to fltkg...@googlegroups.com
    Ah, thanks for that.

    So would it be worth printing the raw values from WIN32 during mouseswheel events,
    just to bypass FLTK's own code?

    For instance, inside Fl_win32.cxx's WndProc() function, adding the code in red just above
    the big switch() statement for all the WM_XXX event handlers:
..
  if (window) {

    if (uMsg == WM_MOUSEWHEEL)
      { printf("raw mousewheel screen x/y=%ld/%ld\n", (long)LOWORD(lParam), (long)HIWORD(lParam)); }

    switch (uMsg) {
      case WM_DPICHANGED: { // 0x02E0
..

    Guess I'd be curious if that prints unexpectedly negative values on the end user's
    machine.

    If those values look normal on either of the user's two screens, then the only other thing
    I think is influencing FLTK's Fl::e_x/e_y values are the window and subwindow x()/y() positions,
    based on my read of this little loop in the mouse_event() function of Fl_win32.cxx:

  while (window->parent()) {
    Fl::e_x += window->x();
    Fl::e_y += window->y();
    window = window->window();
  }

Greg Ercolano

unread,
Feb 8, 2021, 7:57:44 PM2/8/21
to fltkg...@googlegroups.com


On 2/8/21 4:29 PM, Greg Ercolano wrote:
    If those values look normal on either of the user's two screens, then the only other thing
    I think is influencing FLTK's Fl::e_x/e_y values are the window and subwindow x()/y() positions,
    based on my read of this little loop in the mouse_event() function of Fl_win32.cxx:

  while (window->parent()) {
    Fl::e_x += window->x();
    Fl::e_y += window->y();
    window = window->window();
  }

    Oh, and of course FLTK's new scale values are applied too, but I'm guessing the values for FLTK's
    scale aren't going negative, or ALL the x/y positions would be weird, not just the wheelmouse.

    The values Fl::event_x()/y() returns are the internal variables Fl::e_x/y, which aren't set in too
    many places in the Fl_win32.cxx code, making it maybe easy to track how they are modified
    by FLTK, in case there's a bug in how that's done.

    I believe all that is handled in the mouse_event() code (shown in green below, italics are my comments):

static int mouse_event(Fl_Window *window, int what, int button,
                       WPARAM wParam, LPARAM lParam) {
  static int px, py, pmx, pmy;
  POINT pt;
  float scale = Fl_Graphics_Driver::default_driver().scale();
  Fl::e_x = pt.x = (signed short)LOWORD(lParam);    <-- get raw x/y from WndProc()'s lParam
  Fl::e_y = pt.y = (signed short)HIWORD(lParam);
  Fl::e_x /= scale;                                 <-- apply FLTK scale
  Fl::e_y /= scale;
  ClientToScreen(fl_xid(window), &pt);
  Fl::e_x_root = pt.x / scale;
  Fl::e_y_root = pt.y / scale;
#ifdef USE_CAPTURE_MOUSE_WIN
  Fl_Window *mouse_window = window; // save "mouse window"
#endif
  while (window->parent()) {
    Fl::e_x += window->x();                         <-- apply FLTK subwindow offsets


    Fl::e_y += window->y();

    window = window->window();
  }
   ..

    I think that's the only places e_x/e_y are modified from the WIN32 raw values;
    they are set by WM_MOUSEMOVE, and looks like just FLTK scale and FLTK subwindow offsets are applied.
    If we suspect any of that code, it's easy enough to add printf()s to each interpolation.

Gonzalo Garramuño

unread,
Feb 8, 2021, 9:36:04 PM2/8/21
to fltkg...@googlegroups.com


El 08/02/2021 a las 21:29, Greg Ercolano escribió:
On 2/8/21 3:09 PM, lifeatt...@gmail.com wrote:
>    ..I can easily get negative values for the Fl::event_x()/y() values for the  'inner window'
>    if my mouse is above and to the left of the inner subwindow while I roll the mouse, e.g.

That is consistent with the behavior I am seeing. The original issue is something else.

The OP, Gonzalo, is reporting his user has a different issue. His user is getting negative values on FL_MOUSEWHEEL when the mouse is positioned _within_ the sub-window. The degree and sign for the values varied depending on where the FLTK window was positioned on the user's screen.

The OP, Albrecht and I have been unable to repro the user-reported issue.

Ok.  I delved into the WM_MOUSEWHEEL docs in the Windows API and found a gem that says the behavior as what my user is seeing.

Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates of the cursor position because these macros return incorrect results on systems with multiple monitors. Systems with multiple monitors can have negative x- and y- coordinates, and LOWORD and HIWORD treat the coordinates as unsigned quantities.

Albeit this is the opposite of what I wanted, I changed the code to the attached git diff.


-- 
Gonzalo Garramuño

diff.txt

Greg Ercolano

unread,
Feb 8, 2021, 10:05:42 PM2/8/21
to fltkg...@googlegroups.com


On 2/8/21 6:36 PM, Gonzalo Garramuño wrote:

Ok.  I delved into the WM_MOUSEWHEEL docs in the Windows API and found a gem that says the behavior as what my user is seeing.

Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates of the cursor position because these macros return incorrect results on systems with multiple monitors. Systems with multiple monitors can have negative x- and y- coordinates, and LOWORD and HIWORD treat the coordinates as unsigned quantities.

Albeit this is the opposite of what I wanted, I changed the code to the attached git diff.


    Great! So did this modification solve the user's problem?

    If so, let's make an issue for this so the devs can hash out the details, though what your diff
    suggests offhand looks pretty good to me..


Manolo

unread,
Feb 9, 2021, 2:39:54 AM2/9/21
to fltk.general
The current source code is :
Fl::e_x = pt.x = (signed short)LOWORD(lParam);
Fl::e_y = pt.y = (signed short)HIWORD(lParam);

The patch would change it as follows :
#if ( _WIN32_WINNT >= 0x0500 )
#  include <Windowsx.h>
#else
#  define GET_X_LPARAM (signed short) LOWORD
#  define GET_Y_LPARAM (signed short) HIWORD
#endif

Fl::e_x = pt.x = GET_X_LPARAM(lParam);
Fl::e_y = pt.y = GET_Y_LPARAM(lParam);


Consider that header windowsx.h defines these macros as follows :
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))

Therefore,  the patched code would assign exactly the same values to Fl::e_x and Fl::e_y as the current code.

Gonzalo Garramuño

unread,
Feb 9, 2021, 12:45:48 PM2/9/21
to fltkg...@googlegroups.com

Oh damn.  But the current code does not promote the values to an int, just a signed short.  I assume it gets promoted to an int on assignment.  However, since this is the recommended Microsoft way of reading the parameters, it allows them to change it at any time without breaking our code.

Also, the warning of Microsoft was saying that multiple screens may return negative screen values, which is what's happening to my user.  FLTK seems not to take care of the negative screen coordinates.

-- 
Gonzalo Garramuño

Ian MacArthur

unread,
Feb 9, 2021, 1:12:34 PM2/9/21
to fltkg...@googlegroups.com
On 9 Feb 2021, at 17:45, Gonzalo Garramuño wrote:
>
> El 09/02/2021 a las 04:39, Manolo escribió:
>> The current source code is :
>> Fl::e_x = pt.x = (signed short)LOWORD(lParam);
>> Fl::e_y = pt.y = (signed short)HIWORD(lParam);
>>
>> The patch would change it as follows :
>> #if ( _WIN32_WINNT >= 0x0500 )
>> # include <Windowsx.h>
>> #else
>> # define GET_X_LPARAM (signed short) LOWORD
>> # define GET_Y_LPARAM (signed short) HIWORD
>> #endif
>>
>> Fl::e_x = pt.x = GET_X_LPARAM(lParam);
>> Fl::e_y = pt.y = GET_Y_LPARAM(lParam);
>>
>>
>> Consider that header windowsx.h defines these macros as follows :
>> #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
>> #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
>>
>> Therefore, the patched code would assign exactly the same values to Fl::e_x and Fl::e_y as the current code.
>>
> Oh damn. But the current code does not promote the values to an int, just a signed short. I assume it gets promoted to an int on assignment.

It’s a C-style language, automatic type promotion is a (dangerous and confusing) given...
A signed short ought to be sign-extend to signed int on promotion.


> However, since this is the recommended Microsoft way of reading the parameters, it allows them to change it at any time without breaking our code.
>

It might be worth passing lparam into an explicitly unsigned value (I cannot recall if an LPARAM type, which is what we currently have, is a signed or unsigned type, but I think it is signed...)
If it is signed, it may be getting sign-extended when the LOWORD and HIWORD macros do whatever they do... If it were explicitly an unsigned type the compiler ought NOT to sign-extend it and *might* conceivably produce different results in that case...




> Also, the warning of Microsoft was saying that multiple screens may return negative screen values, which is what's happening to my user. FLTK seems not to take care of the negative screen coordinates.


There’s nothing to take care of, though, is there? For the majority of cases where that occurs (like mouse coordinates, say, on the “left-hand” screen) the negative values are correct; the mouse really is left of the origin, so the coordinates are negative. This is normal and necessary...



Gonzalo Garramuño

unread,
Feb 9, 2021, 1:15:39 PM2/9/21
to fltkg...@googlegroups.com

El 09/02/2021 a las 15:12, Ian MacArthur escribió:
> There’s nothing to take care of, though, is there? For the majority of cases where that occurs (like mouse coordinates, say, on the “left-hand” screen) the negative values are correct; the mouse really is left of the origin, so the coordinates are negative. This is normal and necessary...
Yes, but the user is seeing left coordinates on the right area of the
screen, which is no good.

--
Gonzalo Garramuño

Gonzalo Garramuño

unread,
Feb 9, 2021, 3:58:16 PM2/9/21
to fltkg...@googlegroups.com
I meant the user is seeing negative coordites on the right and bottom
area of the screen which is no good.

--
Gonzalo Garramuño

Gonzalo Garramuño

unread,
Feb 9, 2021, 3:59:38 PM2/9/21
to fltkg...@googlegroups.com

El 09/02/2021 a las 17:58, Gonzalo Garramuño escribió:
>
> El 09/02/2021 a las 15:15, Gonzalo Garramuño escribió:
>>
>> El 09/02/2021 a las 15:12, Ian MacArthur escribió:
>>> There’s nothing to take care of, though, is there? For the majority
>>> of cases where that occurs (like mouse coordinates, say, on the
>>> “left-hand” screen) the negative values are correct; the mouse
>>> really is left of the origin, so the coordinates are negative. This
>>> is normal and necessary...
> Damn my typos.  I meant the user is seeing negative coordinates on the

Albrecht Schlosser

unread,
Feb 9, 2021, 4:43:40 PM2/9/21
to fltkg...@googlegroups.com
There are two things we need to distinguish: absolute (i.e. "screen")
coordinates and relative (i.e. "window") coordinates. It's not clear to
me how Microsoft sends mouse coordinates to a window while the cursor is
*inside* this window but I suspect they are relative to the window. If
this is true, the coordinates sent by MS would always be positive as far
as FLTK is concerned.

There's another case we need to consider, as Kevin and Greg noted:
subwindows. Let's say we have a window (size 200x200) with a subwindow
at the bottom right quarter (100, 100, 100, 100) relative to the main
window.

Here's my theory (mostly tested with attached new version of
handle_events.cxx - note: quick and dirty hack alarm: there's a
substantial amount of *copied* code for the main class and the subwindow
class):

(1) When the mouse enters the subwindow Windows sends coordinates
relative to that subwindow.

(2) FLTK translates these coordinates to coordinates of the main window
using the code Greg found and posted. These coordinates still ought to
be positive.

(3) FLTK sends an FL_MOVE (or other) event to the main window. This
event is propagated to the subwindow because it's below the mouse. When
FLTK notices the event is inside a subwindow it translates the
coordinates back to the subwindow's view, hence FL_MOVE events (almost)
always have positive coordinates (there's an exception if you move the
mouse quickly outside a window).

(4) When the mouse pointer is *inside* the subwindow FL_MOUSEWHEEL
events are (in my tests) always "seen" by the subwindow as positive
coordinates relative to the subwindow.

(5) However(!): if you move the mouse pointer *outside* the subwindow
(i.e. left of it or above it) but still *inside* the main window
FL_MOUSEWHEEL events are still propagated to the subwindow and the
subwindow "sees" the *correct* mouse coordinates with negative values
(i.e. the mouse is at the left side or above of its own window
boundaries). This is something Kevin mentioned as well, so it's not new.

So, maybe point (5) is what Gonzalo's user is experiencing - if the
window / subwindow situation is similar.

But that's not all about it. ;-(

(6) If both screens have *different* scale factors screen coordinates
are *ambiguous* WRT the point of view of one or the other window. Then
this is all kinda weird.

Example: configuration of my Windows box is such that screen 0 is at the
right hand side and screen 1 at the left hand side. Both screens have
*positive* coordinates:

screen 0 = (1680, 0, 1680, 1050), scale = 100%
screen 1 = ( 0, 0, 1680, 1050), scale = 100%

If I change screen 0 (the right one) to 125% zoom I get:

screen 0 = (1344, 0, 1344, 840), scale = 125%
screen 1 = ( 0, 0, 1680, 1050), scale = 100%

The screens are still adjacent, but the right screen (0) "thinks" it's
at x = 1344 whereas the left screen (1) extends up to x = 1680 from its
own point of view.

This can yield some surprising effects where coordinate calculation is
definitely - say, at least - difficult.

Test program output examples and comments below each example:

[101, *subwin(100,100,100,100), screen 1, scale 100%] FL_MOUSEWHEEL
at ( -59, 37), dx = 0, dy = 1
[102, mainwin(1023,472,200,200), screen 1, scale 100%] FL_MOUSEWHEEL
at ( 41, 137), dx = 0, dy = 1

This is perfectly normal. The mouse is located left of the subwindow.


[184, *subwin(100,100,100,100), screen 1, scale 100%] FL_MOUSEWHEEL
at ( -51, -38), dx = 0, dy = 1
[185, mainwin(268,105,200,200), screen 1, scale 100%] FL_MOUSEWHEEL
at ( 49, 62), dx = 0, dy = 1

Again normal and correct behavior. The mouse pointer is located
somewhere in the left top quarter of the main window. The difference
between the x and y coordinates of main and subwindow are always exactly
100 which is fine.

[258, *subwin(125,125,100,100), screen 0, scale 125%] FL_MOUSEWHEEL
at ( -94, -29), dx = 0, dy = 1
[259, mainwin(1389,250,200,200), screen 0, scale 125%] FL_MOUSEWHEEL
at ( 31, 96), dx = 0, dy = 1

Still kinda normal but also "funny"(?): the entire main window is on the
right monitor (0) with scaling factor 125%. The main window still
"thinks" its width and height are both 200 (which means the subwindow is
still offset by 100/100 pixels) but the subwindow reports x/y delta
values of 125/125 according to its own screen zoom factor.

I'm not sure if this is all correct / optimal. Maybe something's going
awry in border cases - particularly if the main window is on screen 1
(left) and the subwindow is on screen 0 (right) where "on screen" means
that the window's largest part is on the respective monitor. In the test
program it's possible that this happens.

@Gonzalo: please feel free to use the new test program and forward it to
your user. We *need* to know their exact desktop / screen configuration
which the program prints at the start (maybe after some event logging).

It's also necessary to see the output of FL_MOUSEWHEEL events on your
user's desktop. The program can be configured to use a Fl_Double_Window
or Fl_Gl_Window as the subwindow so it should help in any case.
handle_events.cxx

Manolo

unread,
Feb 10, 2021, 4:26:58 AM2/10/21
to fltk.general
@Albrecht:
As you have seen, and as documented (see the doc of Fl_Window::screen_num(int screen_num)),
when screens have distinct scaling factor values, some ranges of screen coordinates can
pertain to 2 different screens. That ambiguity disappears if one considers both
an (x,y) couple and a screen number. Each window (and sub-window) "knows" at all time the
number of the screen it belongs to (exactly, the screen where the window center is located).
The API to get that number is Fl_Window::screen_num(). Furthermore, Fl_Window::screen_num()
applied to a subwindow returns the screen number of its top_window()
(see Fl_WinAPI_Window_Driver::screen_num() in src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx)

Conversions between FLTK screen coordinates (affected by the current screen scaling factor)
and raw screen coordinates (system-defined) are as follows:

from FLTK to raw for screen # n :
float s = Fl::screen_scale(n)
(x, y) --> (x * s, y * s)

from raw to FLTK for screen # n :
float s = Fl::screen_scale(n)
(x, y) --> (x / s, y / s)

Thus, the test program handle_events should be modified to report accurately
the screen number of each mouse event:

In function print_event of class app, these statements
    if (parent())
      screen_num = Fl::screen_num(x()+window()->x(), y()+window()->y(), w(), h());
    else
      screen_num = Fl::screen_num(x(), y(), w(), h());
should be replaced by
    screen_num = this->Fl_Window::screen_num();

In function print_event of class sub, these statements
    if (parent())
      screen_num = Fl::screen_num(x()+window()->x(), y()+window()->y(), w(), h());
    else
      screen_num = Fl::screen_num(x(), y(), w(), h());
should be replaced by
    screen_num = this->Fl_Window::screen_num();

With these changes, one sees that both parent and subwindow change screen together exactly when
the parent window center changes screen.

In file src/Fl_win32.cxx, the statement that updates the value returned by Fl_Window::screen_num()
when the center of a window changes screen is at line #1606.
The statement that sets the value returned by Fl_Window::screen_num() when a parent window
is created is at line #2036.

That said, there were 2 errors in file src/Fl_win32.cxx :

1) line #1013

float scale = Fl_Graphics_Driver::default_driver().scale();
should be changed into :
  float scale = Fl::screen_driver()->scale(window->screen_num());
to get the screen-specific scale factor value

2) a new condition is needed at the if () test of line #1600 to restrict operations
performed when the test condition is true to top windows only.

I have just committed these 2 changes (818a2ab).

Gonzalo Garramuño

unread,
Feb 10, 2021, 4:41:51 AM2/10/21
to fltkg...@googlegroups.com


El 10/02/2021 a las 06:26, Manolo escribió:
@Albrecht:
As you have seen, and as documented (see the doc of Fl_Window::screen_num(int screen_num)),
when screens have distinct scaling factor values, some ranges of screen coordinates can
pertain to 2 different screens. That ambiguity disappears if one considers both
an (x,y) couple and a screen number. Each window (and sub-window) "knows" at all time

Here's the result of running Albrecht's progam  on my user's machine.   And yes, his secondary display is a Wacom Cintiq 16.
The raw screen values are those that Greg suggested.

  1. Top Left
  2.  
  3. (...)
  4. [290, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 87, 71)
  5. [291, mainwin( 17, 48, 346, 288), screen 0, scale 100%] FL_MOVE at ( 260, 215)
  6. [292, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 86, 71)
  7. [293, mainwin( 17, 48, 346, 288), screen 0, scale 100%] FL_MOVE at ( 259, 215)
  8. raw screen x/y=276/263 unsigned=276/263
  9. [294, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at ( 242, 167), dx = 0, dy = -1
  10. raw screen x/y=276/263 unsigned=276/263
  11. [295, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at ( 242, 167), dx = 0, dy = 1
  12.  
  13.  
  14. Top Right
  15.  
  16. (...)
  17. [993, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 94, 69)
  18. [994, mainwin(1551, 57, 346, 288), screen 0, scale 100%] FL_MOVE at ( 267, 213)
  19. [995, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 93, 69)
  20. [996, mainwin(1551, 57, 346, 288), screen 0, scale 100%] FL_MOVE at ( 266, 213)
  21. raw screen x/y=1817/270 unsigned=1817/270
  22. [997, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at (-1285, 156), dx = 0, dy = -1
  23. raw screen x/y=1817/270 unsigned=1817/270
  24. [998, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at (-1285, 156), dx = 0, dy = 1
  25.  
  26.  
  27. Bottom Left
  28.  
  29. (...)
  30. [613, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 98, 78)
  31. [614, mainwin( 20, 858, 346, 288), screen 0, scale 100%] FL_MOVE at ( 271, 222)
  32. [615, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 99, 78)
  33. [616, mainwin( 20, 858, 346, 288), screen 0, scale 100%] FL_MOVE at ( 272, 222)
  34. raw screen x/y=292/1080 unsigned=292/1080
  35. [617, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at ( 252, -636), dx = 0, dy = -1
  36. raw screen x/y=292/1080 unsigned=292/1080
  37. [618, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at ( 252, -636), dx = 0, dy = 1
  38.  
  39.  
  40. Bottom Right
  41.  
  42. (...)
  43. [132, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 83, 65)
  44. [133, mainwin(1569, 865, 346, 288), screen 0, scale 100%] FL_MOVE at ( 256, 209)
  45. [134, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOVE at ( 83, 66)
  46. [135, mainwin(1569, 865, 346, 288), screen 0, scale 100%] FL_MOVE at ( 256, 210)
  47. raw screen x/y=1825/1075 unsigned=1825/1075
  48. [136, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at (-1313, -655), dx = 0, dy = -1
  49. raw screen x/y=1825/1075 unsigned=1825/1075
  50. [137, *subwin( 173, 144, 173, 144), screen 0, scale 100%] FL_MOUSEWHEEL at (-1313, -655), dx = 0, dy = 1
  51.  
-- 
Gonzalo Garramuño

Greg Ercolano

unread,
Feb 10, 2021, 5:28:41 AM2/10/21
to fltkg...@googlegroups.com

On 2/10/21 1:41 AM, Gonzalo Garramuño wrote:

The raw screen values are those that Greg suggested.


    Perhaps manolo's recent commit solved the problem.

    The raw screen values FLTK is receiving certainly look normal enough,
    ruling out a driver issue:

Top Left
raw screen x/y=276/263 unsigned=276/263

Top Right
raw screen x/y=1817/270  unsigned=1817/270

Bottom Left
raw screen x/y=292/1080  unsigned=292/1080

Bottom Right
raw screen x/y=1825/1075  unsigned=1825/1075


    However, during wheelmouse motion I /think/ FLTK is using the x/y values last calculated
    from the most recent WM_MOVEMOUSE event, presumably to save on recalculating the
    x/y's from WM_WHEELMOUSE.

    I say this because offhand, I don't see WM_WHEELMOUSE events invoking mouse_event(),
    which would make WM_WHEELMOUSE's lparam (x/y values) be ignored.

    So unless manolo's recent commit solves the problem, perhaps the WM_MOVEMOUSE's
    lparam and calculations should be checked carefully, as those are the ones effectively
    being used (I think?) during wheelmouse movement.

Gonzalo Garramuño

unread,
Feb 10, 2021, 5:51:55 AM2/10/21
to fltkg...@googlegroups.com
>  So which version of Windows (10? and what release) is your user
have, and does he have some sort of exotic pointing device?

He is using Windows 10 latest release.  He is also using a Wacom Cintiq
16 as a secondary device.

--
Gonzalo Garramuño

Reply all
Reply to author
Forward
0 new messages