Author: espectador
Date: Mon Mar 23 20:32:36 2015
New Revision: 38429
URL: http://svn.gna.org/viewcvs/gnustep?rev=38429&view=rev
Log:
Improvements to handle the cursor on MS Windows.
Modified:
libs/back/trunk/ChangeLog
libs/back/trunk/Source/win32/WIN32Server.m
Modified: libs/back/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/trunk/ChangeLog?rev=38429&r1=38428&r2=38429&view=diff
==============================================================================
--- libs/back/trunk/ChangeLog (original)
+++ libs/back/trunk/ChangeLog Mon Mar 23 20:32:36 2015
@@ -1,3 +1,14 @@
+2015-03-23 Germán Arias <[email protected]>
+
+ * Source/win32/WIN32Server.m (-windowEventProc:, -process_mouse_event:):
+ Add code to handle the case when the mouse leave the window, move over
+ a nonclient area, update the cursor or when the user open a
+ contextual menu. Also handle the first mouse movement inside the
+ window and save the cursor if we should preserve it between different
+ windows. Sometimes there is a problem with the cursor if the user
+ open a contextual menu after resize the window. But this seems
+ other issue.
+
2015-03-22 Fred Kiefer <[email protected]>
* Source/x11/XGServerEvent.m (-processEvent:): Reenable Richard's
Modified: libs/back/trunk/Source/win32/WIN32Server.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/trunk/Source/win32/WIN32Server.m?rev=38429&r1=38428&r2=38429&view=diff
==============================================================================
--- libs/back/trunk/Source/win32/WIN32Server.m (original)
+++ libs/back/trunk/Source/win32/WIN32Server.m Mon Mar 23 20:32:36 2015
@@ -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"
@@ -61,6 +62,12 @@
#endif
#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);
@@ -1139,6 +1146,27 @@
switch (uMsg)
{
+ case WM_MOUSELEAVE:
+ {
+ /* If the cursor leave the window remove the GNUstep cursors, send
+ * the appropriate message and tell GNUstep stop handling
+ * the cursor.
+ */
+ NSEvent *e;
+ [GSWindowWithNumber((int)hwnd) resetCursorRects];
+ e = [NSEvent otherEventWithType: NSAppKitDefined
+ location: NSMakePoint(-1,-1)
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: (int)hwnd
+ context: GSCurrentContext()
+ subtype: GSAppKitWindowLeave
+ data1: 0
+ data2: 0];
+ [GSCurrentServer() postEvent: e atStart: YES];
+ should_handle_cursor = NO;
+ }
+ break;
case WM_SIZING:
return [self decodeWM_SIZINGParams: hwnd : wParam : lParam];
break;
@@ -1211,7 +1239,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,9 +1277,29 @@
break;
case WM_APP:
break;
- case WM_ENTERMENULOOP:
- break;
- case WM_EXITMENULOOP:
+ case WM_ENTERMENULOOP:
+ /* If the user open a native contextual menu (a non GNUstep window)
+ * send the appropriate message and tell GNUstep stop handling
+ * the cursor.
+ */
+ if (wParam)
+ {
+ NSEvent *e;
+ [GSWindowWithNumber((int)hwnd) resetCursorRects];
+ e = [NSEvent otherEventWithType: NSAppKitDefined
+ location: NSMakePoint(-1,-1)
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: (int)hwnd
+ context: GSCurrentContext()
+ subtype: GSAppKitWindowLeave
+ data1: 0
+ data2: 0];
+ [GSCurrentServer() postEvent: e atStart: YES];
+ should_handle_cursor = NO;
+ }
+ break;
+ case WM_EXITMENULOOP:
break;
case WM_INITMENU:
break;
@@ -1288,8 +1344,12 @@
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, tell GNUstep
+ * that should stop handle the cursor.
+ */
+ NSDebugLLog(@"NSEvent", @"Got Message %s for %d", "NCMOUSEMOVE", hwnd);
+ should_handle_cursor = NO;
+ break;
case WM_NCLBUTTONDOWN: //MOUSE
NSDebugLLog(@"NSEvent", @"Got Message %s for %d", "NCLBUTTONDOWN",
hwnd);
break;
@@ -2712,6 +2772,109 @@
eventFlags |= NSHelpKeyMask;
}
// 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)
{
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs