Articles

Stupid JS Trick #2: Dragging a Window Around

Welcome to the second installment of Stupid JS Tricks. If you missed the previous installment, you can take trip back in time to see us resize our patcher's interface. In this trick we will rise to a brave new challenge: to drag a window around on our screen without using the standard drag-able region provided on that window by the operating system.

Prior to our revealing of Andrew Pask's top-secret new formula for window dragging, the alternatives you have are:

  • sending coordinates to a thispatcher object in Max using the window size messages. If you've tried this, then you know the problem is that this puts a tremendous load on the system and does not function smoothly for dragging a window around (it was meant to change the size of a window not the position). If you do this, it is redrawing the window constantly.

  • using a custom extern, such as tap.windowdrag from the Tap.Tools collection. This external basically pulls the rug out from underneath Max and directly manipulates the window provided by the operating system. This technique is what applications such as current versions of radiaL do to move windows around the screen.

The method discussed here can allow you to create a custom look for your windows and let people move them around. This screenshot is from radiaL - an application for loop-based performances built using Max/MSP.

And now the drum roll please...

// windowdragger.js
// by Andrew Pask

var vrgb2 = [0.35,0.35,0.35,1.];
var last_x = 0;
var last_y = 0;

sketch.default2d();
draw();

// DRAWING ************************************************
function draw()
{
    var theta;
    var width = box.rect[2] - box.rect[0];

    with (sketch) {
        moveto(0,0);
        glclearcolor(vrgb2);
        glclear();
        glcolor(vrgb2);
        quad(0., 0., 0., 1., 0., 0., 1., 1., 0., 0., 1., 0.);
    }
}

// MOUSE EVENTS ************************************************
function onclick(x,y,but,cmd,shift,capslock,option,ctrl)
{
    // cache mouse position for tracking delta movements
    last_x = x;
    last_y = y;
}
onclick.local = 1; //private. 

function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
{
    var dx, dy;

    // calculate delta movements from onclick()
    dx = x - last_x;
    dy = y - last_y;

    if (dx || dy) {
        pos = this.patcher.wind.location;
        pos[0] += dx;
        pos[1] += dy;
        pos[2] += dx;
        pos[3] += dy;
        this.patcher.message("window", "size", pos[0], pos[1], pos[2], pos[3]);
        this.patcher.message("window", "exec");
    }
}
ondrag.local = 1; //private.

function onresize(w,h)
{
    draw();
    refresh();
}
onresize.local = 1; //private

For this to work, you need to load the Javascript file into JSUI (The JS object's user-interface cousin). This lets us draw a color for the drag-able region and process the mouse dragging. While we are sending messages to this.patcher, the result is a lot more direct than sending messages to a thispatcher object in a Max patch - and we get the smooth window-dragging love we are looking are for...

Toodles... and PS. If you really don't feel like typing all of that in, you can download it here!

by Timothy Place on May 15, 2006

Creative Commons License