[squeak-dev] The Inbox: Morphic-ct.2007.mcz

commits at source.squeak.org commits at source.squeak.org
Fri Jun 10 12:15:11 UTC 2022

A new version of Morphic was added to project The Inbox:

==================== Summary ====================

Name: Morphic-ct.2007
Author: ct
Time: 10 June 2022, 2:15:05.904912 pm
UUID: 6866f2c9-f8c2-3f40-b1e5-c57b6dcc5d17
Ancestors: Morphic-mt.2005

Proposal to fix invocation of Squeak from command line on macOS with positional arguments. Closes https://github.com/squeak-smalltalk/squeak-object-memory/issues/20.

As the number of situations in which VMs on different platforms abuse dragDrop events to transport other kind of information into the image is larger than I originally assumed, it seems no longer appropriate to me to focus on a single edge case (singleton VM - even though it seems to be the only one that works cross-platform) in HandMorph>>#generateDropFilesEvent:. Instead, this proposed patch rewrites that method to simulate a missing dragEnter event first so that the regular drop logic can be continued afterwards.

This still needs to be tested on different platforms: Linux/X11, macOS, maybe SqueakJS or TruffleSqueak. On Windows, it seems to work. Your help for testing would be welcome!

=============== Diff against Morphic-mt.2005 ===============

Item was changed:
  ----- Method: HandMorph>>generateDropFilesEvent: (in category 'private events') -----
+ generateDropFilesEvent: evtBuf
- generateDropFilesEvent: evtBuf 
  	"Generate the appropriate mouse event for the given raw event buffer."
  	| position buttons modifiers stamp numFiles dragType |
  	stamp := evtBuf second.
  	stamp = 0 ifTrue: [stamp := Time eventMillisecondClock].
  	dragType := evtBuf third.
  	position := evtBuf fourth @ evtBuf fifth.
  	buttons := MouseEvent redButton. "hacked because necessary for correct mouseMoveDragging handling"
  	modifiers := evtBuf sixth.
  	buttons := buttons bitOr: (modifiers bitShift: MouseEvent numButtons).
  	numFiles := evtBuf seventh.
  	dragType caseOf: {
  		[1] -> [ "dragEnter"
  			externalDropMorph := TransferMorph new
  				dragTransferType: #filesAndDirectories;
  				source: self;
  				passenger: (numFiles = 0 "Usually, numFiles and drop paths are delivered on dragDrop only. Still reserving this possibility for able host implementations."
  					ifTrue: [self flag: #vmCapabilityMissing. 'Unknown host content' translated]
  					ifFalse: [FileDirectory dropFilesAndDirectories: numFiles]);
  			"During the drag operation, the host system is responsible for displaying the cursor."
  			self grabMorph: externalDropMorph.
  			self showTemporaryCursor: Cursor blank.
  			externalDropMorph bottomRight: self topLeft. "Southeast area of the cursor is blocked by drawings from the source application. Display our drop morph at the opposite corner of the cursor." ].
  		[2] -> [ "dragMove"
  			^ MouseMoveEvent new 
  				setType: #mouseMove
  				startPoint: self position
  				endPoint: position
  				trail: "{self position. position}"(self mouseDragTrailFrom: evtBuf)
  				buttons: buttons
  				hand: self
  				stamp: stamp ].
  		[3]  -> [ "dragLeave"
  			externalDropMorph ifNotNil: #abandon.
  			externalDropMorph := nil.
  			self showTemporaryCursor: nil ].
  		[4] -> [ "dragDrop"
  			| oldButtons event |
+ 			externalDropMorph ifNil: [
+ 				self flag: #forLater.
+ 				"dragDrop has been sent without prior dragging. Currently, there are several edge cases where VMs generate these incomplete drop events:
+ 					* The VM is configured as singleton application and has been invoked again with a new image file (aka #launchDrop, runAsSingleInstance on Unix, or RunSingleApp on Windows).
+ 					* macOS: The VM is started from the command line with a positional argument after the image file.
+ 					* macOS: An external device (USB drive, headphones, ...) has been plugged in.
+ 				In the future, we should discuss to refine these messages by the VM and handle them specifically here (e.g., for the singleton mode, load the new image or display an adequate message). For now, we fake the missing dragEnter event here to create the missing externalDropMorph and then handle the dragDrop event normally."
+ 				self generateDropFilesEvent:
+ 					(evtBuf copy
+ 						at: 3 "dragType" put: 1 "dragEnter";
+ 						yourself).
+ 				position := self world center "artifical dragDrop events have no positional semantics"].
  			oldButtons := lastEventBuffer fifth
  				bitOr: (lastEventBuffer sixth bitShift: MouseEvent numButtons).
  			event := MouseButtonEvent new 
  				setType: #mouseUp
  				position: position
  				which: (oldButtons bitXor: buttons)
  				buttons: buttons
  				nClicks: 0
  				hand: self
  				stamp: stamp.
- 			externalDropMorph ifNil: [
- 				"dragDrop has been sent without prior dragging. This happens when the VM is configured as singleton application and has been invoked again with a new image file (aka #launchDrop, runAsSingleInstance on Unix, or RunSingleApp on Windows)."
- 				self flag: #forLater. "ct: When we decouple event generation from Morphic, we will probably need to introduce a separate SystemLaunchEvent class for this event. See http://forum.world.st/Changeset-Enhanced-integration-of-drag-n-drop-from-host-tp5123857p5124332.html."
- 				Project current
- 					launchSystemFiles: (FileDirectory dropFilesAndDirectories: numFiles)
- 					event: event.
- 				^ nil].
  			self showTemporaryCursor: nil.
  			externalDropMorph passenger isString ifTrue: [
  				self flag: #vmCapabilityMissing. "See above."
  				externalDropMorph passenger: (FileDirectory dropFilesAndDirectories: numFiles)].
  			externalDropMorph := nil.
  			(Smalltalk classNamed: #DropFilesEvent) ifNotNil: [:eventClass |
  				| classicEvent |
  				"Generate classic DropFilesEvent, providing backward compatibility."
  				classicEvent := eventClass new
  					setPosition: position
  					contents: numFiles
  					hand: self.
  				self processEvent: classicEvent.
  				classicEvent wasHandled ifTrue: [^ nil]].
  			^ event ].
  		[5] -> [ "drag request"
  			"For dnd out. Not properly implemented at the moment."
  			self shouldBeImplemented] }.
  	^ nil!

Item was removed:
- ----- Method: MorphicProject>>launchSystemFiles:event: (in category 'utilities') -----
- launchSystemFiles: fileStreams event: genericMorphicEvent
- 	"Handle a number of files the singleton VM was invoked with again."
- 	self flag: #todo. "Do something more useful with the image here, e. g. tell the VM to load it."
- 	self inform: ('Cannot start a second instance of Squeak\with the image "{1}"\because the VM is configured as singleton application.' translated withCRs format: {fileStreams first localName}).!

More information about the Squeak-dev mailing list