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:
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:
-- Gonzalo Garramuño
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) {Or, if you really want to eclipse specific events like FL_SHOW and FL_HIDE from the
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)
}
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);
$ ./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
..Guess I'd be curious if that prints unexpectedly negative values on the end user's
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
..
while (window->parent()) {
Fl::e_x += window->x();
Fl::e_y += window->y();
window = window->window();
}
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.
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
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.
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
@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.
-- Gonzalo Garramuño
On 2/10/21 1:41 AM, Gonzalo Garramuño wrote:
The raw screen values are those that Greg suggested.
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.