libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.91k stars 1.83k forks source link

Can't receive WM_MOUSEWHEEL on windows7 sp1 #8722

Closed sandsc closed 3 months ago

sandsc commented 10 months ago

Creating a sdl window with avaloniaui NativeControlHost, and embed this control in avalonia parent control, found that WM_MOUSEWHEEL can't receive when mouse wheel is rotated on mouse device, however, strangely WM_MOUSEWHEEL can still received when use laptop's touch pad. But on Windows 10, everything works fine。 MSDN docs on WM_MOUSEWHEEL:

Sent to the focus window when the mouse wheel is rotated. The DefWindowProc function propagates the message to the window's parent. There should be no internal forwarding of the message, since DefWindowProc propagates it up the parent chain until it finds a window that processes it.

So I add following code to set focus when mouse click on window, then WM_MOUSEWHEEL generated either by touchpad or mouse device can be receive correctly.

 case WM_RBUTTONUP:
 case WM_MBUTTONUP:
 case WM_XBUTTONUP:
 case WM_LBUTTONDOWN:
 case WM_LBUTTONDBLCLK:
 case WM_RBUTTONDOWN:
 case WM_RBUTTONDBLCLK:
 case WM_MBUTTONDOWN:
 case WM_MBUTTONDBLCLK:
 case WM_XBUTTONDOWN:
 case WM_XBUTTONDBLCLK:

 {
     if (!IsWindows10OrGreater()) {
         SetFocus(data->hwnd);
     }
     SDL_Mouse *mouse = SDL_GetMouse();
     if (!mouse->relative_mode || mouse->relative_mode_warp) {
         if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
             lParam != data->last_pointer_update) {
             WIN_CheckWParamMouseButtons(wParam, data, 0);
         }
     }
 } break;

I'm not sure if this is a bug or if I'm using it the wrong way.

slouken commented 10 months ago

Does this fix anything?

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index 89e05cd50..05f65ccdf 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -620,6 +620,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
                 SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, 0, 0, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
             }
         }
+        returnCode = 0;
     } break;

     case WM_LBUTTONUP:
@@ -642,6 +643,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
                 WIN_CheckWParamMouseButtons(wParam, data, 0);
             }
         }
+        returnCode = 0;
     } break;

     case WM_INPUT:
@@ -766,6 +768,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         } else {
             SDL_SendMouseWheel(WIN_GetEventTimestamp(), data->window, 0, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL);
         }
+        returnCode = 0;
     } break;

     case WM_MOUSELEAVE:
slouken commented 10 months ago

We're releasing SDL 2.30 soon and haven't heard back, so I'm going ahead and moving this to the next milestone.

sandsc commented 3 months ago

This bug is reappeared on latest commit, still need to add following code to gets MouseWheel event on Windows7.

 case WM_LBUTTONUP:
  case WM_RBUTTONUP:
  case WM_MBUTTONUP:
  case WM_XBUTTONUP:
  case WM_LBUTTONDOWN:
  case WM_LBUTTONDBLCLK:
  case WM_RBUTTONDOWN:
  case WM_RBUTTONDBLCLK:
  case WM_MBUTTONDOWN:
  case WM_MBUTTONDBLCLK:
  case WM_XBUTTONDOWN:
  case WM_XBUTTONDBLCLK:
  {
      if (!IsWindows10OrGreater()) {
          SetFocus(data->hwnd);
      }
      /* SDL_Mouse *mouse = SDL_GetMouse(); */
      if (!data->videodata->raw_mouse_enabled) {
          if (GetMouseMessageSource((ULONG)GetMessageExtraInfo()) != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
              lParam != data->last_pointer_update) {
              WIN_CheckWParamMouseButtons(WIN_GetEventTimestamp(), wParam, data, SDL_GLOBAL_MOUSE_ID);
          }
      }
  } break;
slouken commented 3 months ago

I'm wondering if this is an issue with the embedded control rather than SDL?

Can you reproduce this with testwm --info event?

sandsc commented 3 months ago

I'm wondering if this is an issue with the embedded control rather than SDL?

Can you reproduce this with testwm --info event?

Yes, you are right, I add follow code in testwm’s event loop.

   if (event.type == SDL_EVENT_MOUSE_WHEEL) {
       SDL_Window *window = SDL_GetMouseFocus();
       if (window) {
           SDL_Log("Window %u, mouse wheel move, x: %f,y: %f\n",
                   SDL_GetWindowID(window),
                   event.wheel.x,
                   event.wheel.y);
       }
   }

When I scroll mouse wheel, I can get mouse wheel events on windows 7.
image

btw, I found an new bug while I was testing with testwm app, when I toggled full screen with ctrl+enter, the app crashed for access violation. image image

slouken commented 3 months ago

I'm wondering if this is an issue with the embedded control rather than SDL? Can you reproduce this with testwm --info event?

Yes, you are right, I add follow code in testwm’s event loop. ... When I scroll mouse wheel, I can get mouse wheel events on windows 7.

Maybe you just need to give the SDL window focus when the hosting control gains focus?

btw, I found an new bug while I was testing with testwm app, when I toggled full screen with ctrl+enter, the app crashed for access violation.

Can you update to the latest SDL code? I believe this is already fixed. Line 1145 is now SDL_UpdateFullscreenDisplayModes()

sandsc commented 3 months ago

Maybe you just need to give the SDL window focus when the hosting control gains focus?

I'm wondering why it doesn't work only on windows7? There may be some platform differences in the mechanism about control getting focus.

Can you update to the latest SDL code? I believe this is already fixed. Line 1145 is now SDL_UpdateFullscreenDisplayModes()

And yes, this is already fixed on latest code.

I'm now manually setting the control focus on the windows7 platform to fix this, thanks for the reply, I'll close this issue for now.