4

I have an object I want to drag around the screen with the mouse in Processing. I set acquired to true on mouse down over the object, and to false on mouse up, thus:

void mousePressed() {
  if (overThing()) {
    acquired = true;
  }
}

void mouseReleased() {
  acquired = false;
}

I then query acquired in my update(), and drag the object if it is true.

void update() {
  \\ other stuff...
  if (acquired) {
    \\ drag thing code ...
  }
}

This all works fine in Processing. mouseReleased() gets called whether I release the mouse inside or outside the active window.

However, when I move the code to Chrome, using processing.js (v1.4.8), mouseReleased() is not called if I release the mouse outside the canvas (whether the mouse is still over the web page, or outside the browser window). So when I return the (now unclicked) mouse to the canvas, the object is still getting dragged around.

I tried including a test of mousePressed in update(), but that also returns true in these circumstances.

Any help on what I need to do to make mouse state changes outside the canvas visible with processing.js?

2 Answers2

2

I don't know about Processing specifically, but releasing mouse buttons outside a widget is a common issue in GUI development.

I suspect that you have no way of knowing the precise time when the mouse is released outside the widget, but you do have two options:

  1. Set acquired = false in mouseOut(), as @Kevin suggests.

  2. I assume there is some type of mouseEntered() method in Processing, and also some way of knowing if the mouse button is currently pressed (either a global variable, or an event object passed to mouseEntered()). You can catch the mouse entered event, check if the mouse has been released, and set acquired = false then.

Like so:

void mouseEntered() {
  if (mouse button is pressed) {
    acquired = false;
  }
}

Edit: From your comments, @Susan, it seems like there is a bug in processing.js, where mousePressed is not set to false if the mouse button is released outside the canvas. One thing pointing to this being a bug is that the mouse movement example on the processing website also shows this behaviour.

Depending upon how much control you have over the website this is going on, and how much effort you want to go to, you could fix the bug yourself by writing some javascript (separate from your processing code):

  1. Define a mouseUp() event on the page <body>, to catch all mouse release events on the page.
  2. In the mouseUp() event, check if the event comes from your Processing control. (There is probably an event object passed to the mouseUp() function, and you might have to give your Processing control an ID to identify it)
  3. If the event doesn't come from your Processing control, then fire a mouseUp event yourself, on the Processing control. This should (hopefully!) trigger a mouse event inside your Processing code.
  4. I'm not sure what Processing will make of the mouse (x,y) position being outside its control when it handles the event you send it. You might want to set a flag on the event object (assuming you can add extra data to the event object) to say "don't use the (x,y) position of this event - it's outside the control".

Edit2: It was easier than I thought! Here is the JavaScript code to detect the mouse being released outside of the Processing canvas and send the mouseReleased event to the canvas. I've tested it on the mouse movement example from the Processing website, and it fixes the bug. It uses jQuery (although it could be re-written to not use jQuery), and it assumes your Processing canvas has the ID "processingCanvas":

$(':not(processingCanvas)').mouseup(function(){
  Processing.getInstanceById('processingCanvas').mouseReleased();
});

To use this code, include it anywhere in your page (in a JavaScript file or in <script> tags) and make sure you have the jQuery library included before this code.

The Processing object allows JavaScript to call any functions defined in your Processing code. Here I've used it to call Processing's built in mouseReleased() function, but if you wanted to call a custom function to handle the mouse-released-outside state differently, then you could.

Adam Nellis
  • 1,500
  • 1
  • 16
  • 23
  • Thanks Adam. But when I bring the mouse back onto the canvas, it says `mousePressed == true`, whether or not it's been released off canvas. It seems like the underlying system doesn't get the event. – Susan Stepney May 18 '15 at 20:27
  • Ok - I understand now - I think it's a bug in processing.js - I've updated my answer with a possible workaround for the bug. – Adam Nellis May 19 '15 at 15:03
1

You should use the mouseOut() function to detect when the mouse leaves the sketch:

void mouseOut() {
  acquired = false;
}

More info in the reference here.

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
  • Thanks. But I want to set `acquired` to `false` on `mouseReleased`, rather than when the mouse leaves the canvas. So if I _don't_ release the mouse off canvas, when I bring the mouse back onto the canvas, the object continues to be dragged. Is there a way to do that? (When I bring the mouse back onto the canvas, it says `mousePressed == true`, whether or not it's been released off canvas.) – Susan Stepney May 16 '15 at 14:28