diff --git a/CMakeLists.txt b/CMakeLists.txt index 522aaf76..57f4d16b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,6 +181,9 @@ if (_GLFW_COCOA_NSGL) ${OPENGL_gl_LIBRARY} ${IOKIT_FRAMEWORK} ${CORE_FOUNDATION_FRAMEWORK}) + + set(GLFW_PKG_DEPS "") + set(GLFW_PKG_LIBS "-framework Cocoa -framework OpenGL -framework IOKit -framework CoreFoundation") endif() #-------------------------------------------------------------------- @@ -202,29 +205,34 @@ if (GLFW_BUILD_TESTS) endif() #-------------------------------------------------------------------- -# Create shared configuration header +# Create generated files #-------------------------------------------------------------------- +configure_file(${GLFW_SOURCE_DIR}/docs/Doxyfile.in + ${GLFW_BINARY_DIR}/docs/Doxyfile @ONLY) + configure_file(${GLFW_SOURCE_DIR}/src/config.h.in ${GLFW_BINARY_DIR}/src/config.h @ONLY) #-------------------------------------------------------------------- -# Install standard files +# Install header and documentation +# The src directory's CMakeLists.txt file installs the library #-------------------------------------------------------------------- - install(DIRECTORY include/GL DESTINATION include FILES_MATCHING PATTERN glfw3.h) install(FILES COPYING.txt readme.html DESTINATION share/doc/glfw-${GLFW_VERSION_FULL}) -# The src directory's CMakeLists.txt file installs the library +#-------------------------------------------------------------------- +# Create and install pkg-config file on supported platforms +#-------------------------------------------------------------------- +if (_GLFW_X11_GLX OR _GLFW_COCOA_NSGL) + configure_file(${GLFW_SOURCE_DIR}/src/libglfw.pc.in + ${GLFW_BINARY_DIR}/src/libglfw.pc @ONLY) -#-------------------------------------------------------------------- -# -- Documentation generation -#-------------------------------------------------------------------- -configure_file("${GLFW_SOURCE_DIR}/docs/Doxyfile.in" - "${GLFW_BINARY_DIR}/docs/Doxyfile" - @ONLY) + install(FILES ${GLFW_BINARY_DIR}/src/libglfw.pc + DESTINATION lib/pkgconfig) +endif() #-------------------------------------------------------------------- # Uninstall operation diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index e6c9fc35..73c7bb09 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -487,6 +487,7 @@ typedef void (* GLFWwindowfocusfun)(GLFWwindow,int); typedef void (* GLFWwindowiconifyfun)(GLFWwindow,int); typedef void (* GLFWmousebuttonfun)(GLFWwindow,int,int); typedef void (* GLFWmouseposfun)(GLFWwindow,int,int); +typedef void (* GLFWcursorenterfun)(GLFWwindow,int); typedef void (* GLFWscrollfun)(GLFWwindow,int,int); typedef void (* GLFWkeyfun)(GLFWwindow,int,int); typedef void (* GLFWcharfun)(GLFWwindow,int); @@ -571,6 +572,7 @@ GLFWAPI void glfwSetKeyCallback(GLFWkeyfun cbfun); GLFWAPI void glfwSetCharCallback(GLFWcharfun cbfun); GLFWAPI void glfwSetMouseButtonCallback(GLFWmousebuttonfun cbfun); GLFWAPI void glfwSetMousePosCallback(GLFWmouseposfun cbfun); +GLFWAPI void glfwSetCursorEnterCallback(GLFWcursorenterfun cbfun); GLFWAPI void glfwSetScrollCallback(GLFWscrollfun cbfun); /* Joystick input */ diff --git a/readme.html b/readme.html index f631acd7..d8f22094 100644 --- a/readme.html +++ b/readme.html @@ -846,6 +846,9 @@ their skills. Special thanks go out to:</p> <li>Ralph Eastwood, for the initial design and implementation of the gamma correction API</li> + <li>GeO4d, for the implementation of cursor enter/leave notifications on + Win32.</li> + <li>Gerald Franz, who made GLFW compile under IRIX, and supplied patches for the X11 keyboard translation routine</li> @@ -877,7 +880,8 @@ their skills. Special thanks go out to:</p> <li>Tristam MacDonald, for his bug reports and feedback on the Cocoa port</li> - <li>Hans 'Hanmac' Mackowiak, for adding UTF-8 window title support on X11 and + <li>Hans 'Hanmac' Mackowiak, for the initial implementation of cursor + enter/leave callbacks on X11, adding UTF-8 window title support on X11 and a fix for the Xkb support</li> <li>David Medlock, for doing the initial Lua port</li> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8276faa3..235e8650 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,11 +1,4 @@ -if (_GLFW_X11_GLX) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libglfw.pc.cmake - ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc - DESTINATION lib/pkgconfig) -endif() - include_directories(${GLFW_SOURCE_DIR}/src ${GLFW_BINARY_DIR}/src ${glfw_INCLUDE_DIRS}) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 98c220ed..5cd7ee3e 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -292,6 +292,7 @@ static int convertMacKeyCode(unsigned int macKeyCode) @interface GLFWContentView : NSView { _GLFWwindow* window; + NSTrackingArea* trackingArea; } - (id)initWithGlfwWindow:(_GLFWwindow *)initWindow; @@ -304,11 +305,22 @@ static int convertMacKeyCode(unsigned int macKeyCode) { self = [super init]; if (self != nil) + { window = initWindow; + trackingArea = nil; + + [self updateTrackingAreas]; + } return self; } +-(void)dealloc +{ + [trackingArea release]; + [super dealloc]; +} + - (BOOL)isOpaque { return YES; @@ -384,6 +396,36 @@ static int convertMacKeyCode(unsigned int macKeyCode) _glfwInputMouseClick(window, [event buttonNumber], GLFW_RELEASE); } +- (void)mouseExited:(NSEvent *)event +{ + _glfwInputCursorEnter(window, GL_FALSE); +} + +- (void)mouseEntered:(NSEvent *)event +{ + _glfwInputCursorEnter(window, GL_TRUE); +} + +- (void)updateTrackingAreas +{ + if (trackingArea != nil) + { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | + NSTrackingActiveAlways | + NSTrackingInVisibleRect; + + trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] + options:options + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; +} + - (void)keyDown:(NSEvent *)event { NSUInteger i, length; diff --git a/src/input.c b/src/input.c index ded88712..1074ded5 100644 --- a/src/input.c +++ b/src/input.c @@ -262,6 +262,17 @@ void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y) } +//======================================================================== +// Register cursor enter/leave events +//======================================================================== + +void _glfwInputCursorEnter(_GLFWwindow* window, int entered) +{ + if (_glfwLibrary.cursorEnterCallback) + _glfwLibrary.cursorEnterCallback(window, entered); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// @@ -557,6 +568,22 @@ GLFWAPI void glfwSetMousePosCallback(GLFWmouseposfun cbfun) } +//======================================================================== +// Set callback function for cursor enter/leave events +//======================================================================== + +GLFWAPI void glfwSetCursorEnterCallback(GLFWcursorenterfun cbfun) +{ + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return; + } + + _glfwLibrary.cursorEnterCallback = cbfun; +} + + //======================================================================== // Set callback function for scroll events //======================================================================== diff --git a/src/internal.h b/src/internal.h index 83ab78ba..d7c8f5ad 100644 --- a/src/internal.h +++ b/src/internal.h @@ -237,6 +237,7 @@ struct _GLFWlibrary GLFWwindowiconifyfun windowIconifyCallback; GLFWmousebuttonfun mouseButtonCallback; GLFWmouseposfun mousePosCallback; + GLFWcursorenterfun cursorEnterCallback; GLFWscrollfun scrollCallback; GLFWkeyfun keyCallback; GLFWcharfun charCallback; @@ -349,6 +350,7 @@ void _glfwInputChar(_GLFWwindow* window, int character); void _glfwInputScroll(_GLFWwindow* window, int x, int y); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action); void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y); +void _glfwInputCursorEnter(_GLFWwindow* window, int entered); // OpenGL context helpers (opengl.c) int _glfwStringInExtensionString(const char* string, const GLubyte* extensions); diff --git a/src/libglfw.pc.cmake b/src/libglfw.pc.in similarity index 91% rename from src/libglfw.pc.cmake rename to src/libglfw.pc.in index f83ad126..be6275aa 100644 --- a/src/libglfw.pc.cmake +++ b/src/libglfw.pc.in @@ -5,7 +5,7 @@ libdir=${exec_prefix}/lib Name: GLFW Description: A portable library for OpenGL, window and input -Version: 3.0.0 +Version: @GLFW_VERSION_FULL@ URL: http://www.glfw.org/ Requires.private: @GLFW_PKG_DEPS@ Libs: -L${libdir} -lglfw diff --git a/src/win32_platform.h b/src/win32_platform.h index 0f6362c1..63a372d7 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -270,6 +270,7 @@ typedef struct _GLFWwindowWin32 // Various platform specific internal variables int desiredRefreshRate; // Desired vertical monitor refresh rate GLboolean cursorCentered; + GLboolean cursorInside; int oldMouseX, oldMouseY; } _GLFWwindowWin32; diff --git a/src/win32_window.c b/src/win32_window.c index dd25c3ce..d73e73c3 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -997,6 +997,26 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, _glfwInputCursorMotion(window, x, y); } + if (!window->Win32.cursorInside) + { + TRACKMOUSEEVENT tme; + ZeroMemory(&tme, sizeof(tme)); + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = window->Win32.handle; + TrackMouseEvent(&tme); + + window->Win32.cursorInside = GL_TRUE; + _glfwInputCursorEnter(window, GL_TRUE); + } + + return 0; + } + + case WM_MOUSELEAVE: + { + window->Win32.cursorInside = GL_FALSE; + _glfwInputCursorEnter(window, GL_FALSE); return 0; } diff --git a/src/x11_window.c b/src/x11_window.c index db630b10..8959a193 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -685,7 +685,8 @@ static GLboolean createWindow(_GLFWwindow* window, wa.border_pixel = 0; wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | - ExposureMask | FocusChangeMask | VisibilityChangeMask; + ExposureMask | FocusChangeMask | VisibilityChangeMask | + EnterWindowMask | LeaveWindowMask; if (wndconfig->mode == GLFW_WINDOWED) { @@ -1186,6 +1187,40 @@ static void processSingleEvent(void) break; } + case EnterNotify: + { + // The mouse cursor enters the Window + window = findWindow(event.xcrossing.window); + if (window == NULL) + { + fprintf(stderr, "Cannot find GLFW window structure for EnterNotify event\n"); + return; + } + + if (window->cursorMode == GLFW_CURSOR_HIDDEN) + hideMouseCursor(window); + + _glfwInputCursorEnter(window, GL_TRUE); + break; + } + + case LeaveNotify: + { + // The mouse cursor leave the Window + window = findWindow(event.xcrossing.window); + if (window == NULL) + { + fprintf(stderr, "Cannot find GLFW window structure for LeaveNotify event\n"); + return; + } + + if (window->cursorMode == GLFW_CURSOR_HIDDEN) + showMouseCursor(window); + + _glfwInputCursorEnter(window, GL_FALSE); + break; + } + case MotionNotify: { // The mouse cursor was moved diff --git a/tests/events.c b/tests/events.c index 5603258b..3bf2ca6c 100644 --- a/tests/events.c +++ b/tests/events.c @@ -275,6 +275,14 @@ static void mouse_position_callback(GLFWwindow window, int x, int y) printf("%08x at %0.3f: Mouse position: %i %i\n", counter++, glfwGetTime(), x, y); } +static void cursor_enter_callback(GLFWwindow window, int entered) +{ + printf("%08x at %0.3f: Cursor %s window\n", + counter++, + glfwGetTime(), + entered ? "entered" : "left"); +} + static void scroll_callback(GLFWwindow window, int x, int y) { printf("%08x at %0.3f: Scroll: %i %i\n", counter++, glfwGetTime(), x, y); @@ -354,6 +362,7 @@ int main(void) glfwSetWindowIconifyCallback(window_iconify_callback); glfwSetMouseButtonCallback(mouse_button_callback); glfwSetMousePosCallback(mouse_position_callback); + glfwSetCursorEnterCallback(cursor_enter_callback); glfwSetScrollCallback(scroll_callback); glfwSetKeyCallback(key_callback); glfwSetCharCallback(char_callback);