Attached the patch to solve the cursors issues on Windows. The backend
only process the events inside the windows, so we should take cares when
the mouse leave/enter the window. As far as I can see, this patch solves
all the problems with the cursor. Let me know if you are agree with
these changes.
Germán
Index: Source/win32/WIN32Server.m
===================================================================
--- Source/win32/WIN32Server.m (revisión: 38408)
+++ Source/win32/WIN32Server.m (copia de trabajo)
@@ -49,6 +49,7 @@
#include <AppKit/NSTextField.h>
#include <AppKit/DPSOperators.h>
#include <GNUstepGUI/GSTheme.h>
+#include <GNUstepGUI/GSTrackingRect.h>
#include "win32/WIN32Server.h"
#include "win32/WIN32Geometry.h"
@@ -62,6 +63,12 @@
#include <math.h>
+// To update the cursor..
+static BOOL update_cursor = NO;
+static BOOL should_handle_cursor = NO;
+static NSCursor *current_cursor = nil;
+
+
// Forward declarations...
static unsigned int mask_for_keystate(BYTE *keyState);
@@ -135,6 +142,8 @@
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);
+static void remove_cursors();
+
BOOL CALLBACK LoadDisplayMonitorInfo(HMONITOR hMonitor,
HDC hdcMonitor,
LPRECT lprcMonitor,
@@ -1139,6 +1148,15 @@
switch (uMsg)
{
+ case WM_MOUSELEAVE:
+ {
+ /* If the cursor leave the window remove the GNUstep cursors and
+ * tell GNUstep that should stop handle the cursor.
+ */
+ remove_cursors();
+ should_handle_cursor = NO;
+ }
+ break;
case WM_SIZING:
return [self decodeWM_SIZINGParams: hwnd : wParam : lParam];
break;
@@ -1211,7 +1229,15 @@
else
[self decodeWM_KILLFOCUSParams: wParam : lParam : hwnd];
break;
- case WM_SETCURSOR:
+ case WM_SETCURSOR:
+ if (wParam == (int)hwnd)
+ {
+ // Check if GNUstep should handle the cursor.
+ if (should_handle_cursor)
+ {
+ flags._eventHandled = YES;
+ }
+ }
break;
case WM_QUERYOPEN:
[self decodeWM_QUERYOPENParams: wParam : lParam : hwnd];
@@ -1241,10 +1267,20 @@
break;
case WM_APP:
break;
- case WM_ENTERMENULOOP:
+ case WM_ENTERMENULOOP:
+ /* If the user open a native menu remove the GNUstep cursors and
+ * set an arrow cursor.
+ */
+ remove_cursors();
+ [[NSCursor arrowCursor] set];
+ break;
+ case WM_EXITMENULOOP:
+ /* Allow GNUstep handle the cursor and check if the cursor
+ * should be updated.
+ */
+ update_cursor = YES;
+ should_handle_cursor = YES;
break;
- case WM_EXITMENULOOP:
- break;
case WM_INITMENU:
break;
case WM_MENUSELECT:
@@ -1288,8 +1324,15 @@
NSDebugLLog(@"NSEvent", @"Got Message %s for %d", "NCHITTEST", hwnd);
break;
case WM_NCMOUSEMOVE: //MOUSE
- NSDebugLLog(@"NSEvent", @"Got Message %s for %d", "NCMOUSEMOVE", hwnd);
- break;
+ /* If the user move the mouse over a nonclient area, remove the
+ * GNUstep cursors and tell GNUstep that should stop handle the
+ * cursor. This could seems redundant, since we do this
+ * on WM_MOUSELEAVE, but ensures a correct behaviour.
+ */
+ NSDebugLLog(@"NSEvent", @"Got Message %s for %d", "NCMOUSEMOVE", hwnd);
+ remove_cursors();
+ should_handle_cursor = NO;
+ break;
case WM_NCLBUTTONDOWN: //MOUSE
NSDebugLLog(@"NSEvent", @"Got Message %s for %d", "NCLBUTTONDOWN", hwnd);
break;
@@ -2713,6 +2756,109 @@
}
// What about other modifiers?
+ /* Currently GNUstep only proccess events inside the windows (contentview).
+ * So we should check if this is the first movement inside the window.
+ * And should consider also the case when this is the last movement inside
+ * the window.
+ */
+ if (!should_handle_cursor)
+ {
+ /* If this is the first movement inside the window, tell GNUstep
+ * that should handle the cursor and that should check if the
+ * cursor needs be updated.
+ */
+ should_handle_cursor = YES;
+ update_cursor = YES;
+
+ /* If there are a previous cursor available (maybe a cursor that
+ * represent a tool) set it as the cursor. If not, set an arrow
+ * cursor (this is necessary because if the cursor is updated to,
+ * for example, an I Beam cursor, there will not be a default cursor
+ * to display when the user moves the mouse over, for example, an
+ * scrollbar).
+ */
+ if (current_cursor != nil)
+ {
+ [current_cursor set];
+ current_cursor = nil;
+ }
+ else
+ {
+ [[NSCursor arrowCursor] set];
+ }
+ }
+ else
+ {
+ /* If the cursor is not associated to a tracking rectangle, not in
+ * the push/pop stack, save this. We do this for the case when, for
+ * example, the user choose a tool in a Tools window which sets a
+ * cursor for the tool and this cursor should be preserved between
+ * different windows.
+ */
+ if ([NSCursor count] == 0 &&
+ ![current_cursor isEqual: [NSCursor currentCursor]])
+ {
+ ASSIGN(current_cursor, [NSCursor currentCursor]);
+ }
+ }
+
+ // Check if we need update the cursor.
+ if (update_cursor)
+ {
+ NSView *subview = nil;
+ NSWindow *gswin = GSWindowWithNumber((int)hwnd);
+
+ subview = [[gswin contentView] hitTest: eventLocation];
+
+ if (subview != nil && subview->_rFlags.valid_rects)
+ {
+ NSArray *tr = subview->_cursor_rects;
+ NSUInteger count = [tr count];
+
+ // Loop through cursor rectangles
+ if (count > 0)
+ {
+ GSTrackingRect *rects[count];
+ NSUInteger i;
+
+ [tr getObjects: rects];
+
+ for (i = 0; i < count; ++i)
+ {
+ GSTrackingRect *r = rects[i];
+ BOOL now;
+
+ if ([r isValid] == NO)
+ continue;
+
+ /*
+ * Check for presence of point in rectangle.
+ */
+ now = NSMouseInRect(eventLocation, r->rectangle, NO);
+
+ // Mouse inside
+ if (now)
+ {
+ NSEvent *e;
+
+ e = [NSEvent enterExitEventWithType: NSCursorUpdate
+ location: eventLocation
+ modifierFlags: eventFlags
+ timestamp: 0
+ windowNumber: (int)hwnd
+ context: gcontext
+ eventNumber: 0
+ trackingNumber: (int)YES
+ userData: (void*)r];
+ [GSCurrentServer() postEvent: e atStart: YES];
+ //NSLog(@"Add enter event %@ for view %@ rect %@", e, theView, NSStringFromRect(r->rectangle));
+ }
+ }
+ }
+ }
+ update_cursor = NO;
+ }
+
if (eventType == NSScrollWheel)
{
float delta = GET_WHEEL_DELTA_WPARAM(wParam) / 120.0;
@@ -2888,3 +3034,11 @@
return [ctxt windowEventProc: hwnd : uMsg : wParam : lParam];
}
+// This function just removes the cursors at push/pop stack.
+static void remove_cursors () {
+ int x;
+ for (x = 0; x < [NSCursor count]; x++)
+ {
+ [[NSCursor currentCursor] pop];
+ }
+}
_______________________________________________
Gnustep-dev mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/gnustep-dev