Skip to content

Commit

Permalink
8233955: VM crashes if more than one file are added to ClipboardConte…
Browse files Browse the repository at this point in the history
…nt via drag and drop

Reviewed-by: kcr, arapte
  • Loading branch information
Lukasz Kostyra authored and kevinrushforth committed May 30, 2023
1 parent 56fb71a commit afa71d4
Show file tree
Hide file tree
Showing 10 changed files with 435 additions and 82 deletions.
Expand Up @@ -28,15 +28,16 @@

@protocol GlassDragSourceDelegate <NSObject>

- (void)startDrag:(NSDragOperation)operation;
- (void)startDrag:(NSDragOperation)operation withItems:(NSArray<NSDraggingItem*>*)items;
- (void)draggingEnded;

@end

@interface GlassDragSource : NSObject

+ (void)setDelegate:(NSObject<GlassDragSourceDelegate>*)delegate;
+ (void)flushWithMask:(jint)mask;
+ (BOOL)isDelegateSet;
+ (void)flushWithMask:(jint)mask withItems:(NSArray<NSDraggingItem*>*)items;

+ (NSDragOperation)mapJavaMaskToNsOperation:(jint)mask;
+ (jint)mapNsOperationToJavaMaskExternal:(NSDragOperation)operation;
Expand Down
Expand Up @@ -49,7 +49,12 @@ + (void)setDelegate:(NSObject<GlassDragSourceDelegate>*)delegate
gDelegate = delegate; // notice, there is no retain
}

+ (void)flushWithMask:(jint)mask
+ (BOOL)isDelegateSet
{
return (gDelegate != nil);
}

+ (void)flushWithMask:(jint)mask withItems:(NSArray<NSDraggingItem*>*)items
{
LOG("GlassDragSource:flushWithMask: %d", mask);

Expand All @@ -59,12 +64,12 @@ + (void)flushWithMask:(jint)mask
NSDragOperation operation = [GlassDragSource mapJavaMaskToNsOperation:mask];
if (operation != NSDragOperationNone)
{
LOG("[gDelegate startDrag:operation]");
[gDelegate startDrag:operation];
LOG("[gDelegate startDrag:operation withItems:items] gDelegate %p", gDelegate);
[gDelegate startDrag:operation withItems:items];
}
else
{
LOG("[gDelegate startDrag:operation] NOT TAKEN!");
LOG("[gDelegate startDrag:operation withItems:items] NOT TAKEN!");
}
}
else
Expand Down
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/


#import <Cocoa/Cocoa.h>

@interface GlassDraggingSource : NSObject <NSDraggingSource>
{
@public
NSDragOperation dragOperation;

}

- (GlassDraggingSource*)initWithOperation:(NSDragOperation)operation;

- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint;
- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint;
- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation;

- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session;

@end
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

#import "common.h"
#include <AppKit/AppKit.h>
#import "GlassDraggingSource.h"
#import "GlassMacros.h"

//#define VERBOSE
#ifndef VERBOSE
#define LOG(MSG, ...)
#else
#define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
#endif


@implementation GlassDraggingSource

- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
// The Command key masks out every operation other than NSDragOperationGeneric. We want
// internal Move events to get through this filtering so we copy the Move bit into the
// Generic bit and treat Generic as a synonym for Move.
if (context == NSDraggingContextWithinApplication)
{
NSDragOperation result = self->dragOperation;
if (result & NSDragOperationMove)
result |= NSDragOperationGeneric;
return result;
}
return self->dragOperation;
}

- (GlassDraggingSource*)initWithOperation:(NSDragOperation)operation
{
dragOperation = operation;
return self;
}

- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint
{
}

- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint
{
}

- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
{
}

- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session
{
return NO;
}

@end
Expand Up @@ -760,7 +760,7 @@ static inline jobject createUTF(JNIEnv *env, NSString *data) {
seed = [pasteboard clearContents];

jsize itemCount = (*env)->GetArrayLength(env, jObjects);
//NSLog(@"Java_com_sun_glass_ui_mac_MacPasteboard__1putItems itemCount: %d", itemCount);
LOG(@"Java_com_sun_glass_ui_mac_MacPasteboard__1putItems itemCount: %d", itemCount);
if (itemCount > 0)
{
NSMutableArray *objects = [NSMutableArray arrayWithCapacity:(NSUInteger)itemCount];
Expand All @@ -775,12 +775,33 @@ static inline jobject createUTF(JNIEnv *env, NSString *data) {
}
}

// http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/PasteboardGuide106/Articles/pbCustom.html
[pasteboard writeObjects:objects];
// We perform a Drag-n-Drop only when our pasteboard is a DnD pasteboard
// and if drag delegate was set. The latter one is set when DnD operation
// came from a NSView (ex. mouse drag).
if ([[pasteboard name] isEqualToString:NSDragPboard] && [GlassDragSource isDelegateSet])
{
// DnD requires separate NSDragging* calls to work since macOS 10.7
// convert NSPasteboardItem-s array to NSDraggingItem-s
NSMutableArray<NSDraggingItem*> *dItems = [NSMutableArray<NSDraggingItem*> arrayWithCapacity:itemCount];
for (NSPasteboardItem* i in objects)
{
[dItems addObject:[[NSDraggingItem alloc] initWithPasteboardWriter:i]];
}

// New DnD API (macOS 10.7+) requires us to skip writing data to Pasteboard.
// It handles managing the pasteboard separately on its own.
[GlassDragSource flushWithMask:supportedActions withItems:dItems];

if (pasteboard == [NSPasteboard pasteboardWithName:NSDragPboard])
for (NSDraggingItem* i in dItems)
{
[i release];
}
}
else
{
[GlassDragSource flushWithMask:supportedActions];
// previous write to pasteboard for compatibility
// http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/PasteboardGuide106/Articles/pbCustom.html
[pasteboard writeObjects:objects];
}
}
}
Expand Down
Expand Up @@ -579,14 +579,6 @@ - (void)draggingExited:(id <NSDraggingInfo>)sender
[self->_delegate sendJavaDndEvent:sender type:com_sun_glass_events_DndEvent_EXIT];
}

- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
// Deprecated for 10.7
// use NSDraggingSession - (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
DNDLOG("draggingSourceOperationMaskForLocal");
return [self->_delegate draggingSourceOperationMaskForLocal:isLocal];
}

#pragma mark --- Callbacks

- (void)enterFullscreenWithAnimate:(BOOL)animate withKeepRatio:(BOOL)keepRatio withHideCursor:(BOOL)hideCursor
Expand Down
Expand Up @@ -29,6 +29,7 @@
#import "GlassHostView.h"
#import "GlassFullscreenWindow.h"
#import "GlassDragSource.h"
#import "GlassDraggingSource.h"
#import "GlassAccessible.h"

// Bit mask for tracking gesture begin / end
Expand Down Expand Up @@ -66,7 +67,7 @@ typedef enum GestureMaskType {
// The last processed key event
NSEvent *s_lastKeyEvent;

NSDragOperation dragOperation;
GlassDraggingSource *draggingSource;
NSInteger lastTrackingNumber;

@public
Expand Down Expand Up @@ -100,8 +101,7 @@ typedef enum GestureMaskType {

- (NSDragOperation)sendJavaDndEvent:(id <NSDraggingInfo>)info type:(jint)type;

- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
- (void)startDrag:(NSDragOperation)operation;
- (void)startDrag:(NSDragOperation)operation withItems:(NSArray<NSDraggingItem*>*)items;

- (BOOL)suppressMouseEnterExitOnMouseDown;

Expand Down

1 comment on commit afa71d4

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.