Jelajahi Sumber

Add GLFW_HOVERED for polling cursor hover state

This window attribute corresponds to the cursor enter/leave callback.

Fixes #1166.
Camilla Löwy 7 tahun lalu
induk
melakukan
ee9dffcd66
14 mengubah file dengan 83 tambahan dan 0 penghapusan
  1. 1 0
      README.md
  2. 10 0
      docs/input.dox
  3. 5 0
      docs/window.dox
  4. 1 0
      include/GLFW/glfw3.h
  5. 14 0
      src/cocoa_window.m
  6. 1 0
      src/internal.h
  7. 7 0
      src/mir_window.c
  8. 5 0
      src/null_window.c
  9. 5 0
      src/win32_window.c
  10. 2 0
      src/window.c
  11. 4 0
      src/wl_init.c
  12. 1 0
      src/wl_platform.h
  13. 5 0
      src/wl_window.c
  14. 22 0
      src/x11_window.c

+ 1 - 0
README.md

@@ -162,6 +162,7 @@ information on what to include when reporting a bug.
 - Added definition of `GLAPIENTRY` to public header
 - Added `GLFW_TRANSPARENT_FRAMEBUFFER` window hint and attribute for controlling
   per-pixel framebuffer transparency (#197,#663,#715,#723,#1078)
+- Added `GLFW_HOVERED` window attribute for polling cursor hover state (#1166)
 - Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
   (#749,#842)
 - Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)

+ 10 - 0
docs/input.dox

@@ -419,6 +419,16 @@ void cursor_enter_callback(GLFWwindow* window, int entered)
 }
 @endcode
 
+You can query whether the cursor is currently inside the client area of the
+window with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute.
+
+@code
+if (glfwGetWindowAttrib(window, GLFW_HOVERED))
+{
+    highlight_interface();
+}
+@endcode
+
 
 @subsection input_mouse_button Mouse button input
 

+ 5 - 0
docs/window.dox

@@ -1220,6 +1220,11 @@ See @ref window_iconify for details.
 __GLFW_MAXIMIZED__ indicates whether the specified window is maximized.  See
 @ref window_maximize for details.
 
+@anchor GLFW_HOVERED_attrib
+__GLFW_HOVERED__ indicates whether the cursor is currently directly over the
+client area of the window, with no other windows between.  See @ref cursor_enter
+for details.
+
 @anchor GLFW_VISIBLE_attrib
 __GLFW_VISIBLE__ indicates whether the specified window is visible.  See @ref
 window_hide for details.

+ 1 - 0
include/GLFW/glfw3.h

@@ -814,6 +814,7 @@ extern "C" {
  *  [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
  */
 #define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
+#define GLFW_HOVERED                0x0002000B
 
 /*! @brief Framebuffer bit depth hint.
  *

+ 14 - 0
src/cocoa_window.m

@@ -1488,6 +1488,20 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
     return [window->ns.object isZoomed];
 }
 
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    const NSPoint point = [NSEvent mouseLocation];
+
+    if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
+        [window->ns.object windowNumber])
+    {
+        return GLFW_FALSE;
+    }
+
+    return NSPointInRect(point,
+        [window->ns.object convertRectToScreen:[window->ns.view bounds]]);
+}
+
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
     return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];

+ 1 - 0
src/internal.h

@@ -690,6 +690,7 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window);
 int _glfwPlatformWindowIconified(_GLFWwindow* window);
 int _glfwPlatformWindowVisible(_GLFWwindow* window);
 int _glfwPlatformWindowMaximized(_GLFWwindow* window);
+int _glfwPlatformWindowHovered(_GLFWwindow* window);
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
 float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
 void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);

+ 7 - 0
src/mir_window.c

@@ -627,6 +627,13 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
     return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
 }
 
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+    return GLFW_FALSE;
+}
+
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
     _glfwInputError(GLFW_PLATFORM_ERROR,

+ 5 - 0
src/null_window.c

@@ -165,6 +165,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
     return GLFW_FALSE;
 }
 
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
     return GLFW_FALSE;

+ 5 - 0
src/win32_window.c

@@ -1578,6 +1578,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
     return IsZoomed(window->win32.handle);
 }
 
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    return cursorInClientArea(window);
+}
+
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
     return window->win32.transparent && _glfwIsCompositionEnabledWin32();

+ 2 - 0
src/window.c

@@ -785,6 +785,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
             return _glfwPlatformWindowVisible(window);
         case GLFW_MAXIMIZED:
             return _glfwPlatformWindowMaximized(window);
+        case GLFW_HOVERED:
+            return _glfwPlatformWindowHovered(window);
         case GLFW_TRANSPARENT_FRAMEBUFFER:
             return _glfwPlatformFramebufferTransparent(window);
         case GLFW_RESIZABLE:

+ 4 - 0
src/wl_init.c

@@ -54,6 +54,8 @@ static void pointerHandleEnter(void* data,
     _glfw.wl.pointerSerial = serial;
     _glfw.wl.pointerFocus = window;
 
+    window->wl.hovered = GLFW_TRUE;
+
     _glfwPlatformSetCursor(window, window->wl.currentCursor);
     _glfwInputCursorEnter(window, GLFW_TRUE);
 }
@@ -68,6 +70,8 @@ static void pointerHandleLeave(void* data,
     if (!window)
         return;
 
+    window->wl.hovered = GLFW_FALSE;
+
     _glfw.wl.pointerSerial = serial;
     _glfw.wl.pointerFocus = NULL;
     _glfwInputCursorEnter(window, GLFW_FALSE);

+ 1 - 0
src/wl_platform.h

@@ -117,6 +117,7 @@ typedef struct _GLFWwindowWayland
     int                         width, height;
     GLFWbool                    visible;
     GLFWbool                    maximized;
+    GLFWbool                    hovered;
     GLFWbool                    transparent;
     struct wl_surface*          surface;
     struct wl_egl_window*       native;

+ 5 - 0
src/wl_window.c

@@ -692,6 +692,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
     return window->wl.maximized;
 }
 
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    return window->wl.hovered;
+}
+
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
     return window->wl.transparent;

+ 22 - 0
src/x11_window.c

@@ -2453,6 +2453,28 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
     return maximized;
 }
 
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    Window w = _glfw.x11.root;
+    while (w)
+    {
+        Window root;
+        int rootX, rootY, childX, childY;
+        unsigned int mask;
+
+        if (!XQueryPointer(_glfw.x11.display, w,
+                           &root, &w, &rootX, &rootY, &childX, &childY, &mask))
+        {
+            return GLFW_FALSE;
+        }
+
+        if (w == window->x11.handle)
+            return GLFW_TRUE;
+    }
+
+    return GLFW_FALSE;
+}
+
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
     if (!window->x11.transparent)