Skip to content

Instantly share code, notes, and snippets.

@SableRaf
Created May 20, 2026 13:49
Show Gist options
  • Select an option

  • Save SableRaf/da87706a48042db6328e6867a32a59c3 to your computer and use it in GitHub Desktop.

Select an option

Save SableRaf/da87706a48042db6328e6867a32a59c3 to your computer and use it in GitHub Desktop.
Span image accross displays
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.Rectangle;
ChildApplet[] children;
PShape pointer;
PImage img;
GraphicsDevice[] screens;
Rectangle virtualBounds;
int displayCount;
int childrenCreated = 0;
int frameDelay = 5;
void setup() {
size(400, 300, P2D);
pixelDensity(1);
pointer = createShape(ELLIPSE, 0, 0, 20, 20);
screens = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getScreenDevices();
displayCount = screens.length;
println("Found " + displayCount + " display(s)");
virtualBounds = getVirtualBounds(screens);
println("Virtual bounds: " + virtualBounds);
children = new ChildApplet[displayCount];
img = loadImage("heic0601a_6400x2400.jpg");
}
void draw() {
background(32);
fill(160);
textAlign(CENTER, CENTER);
text("MAIN window\n" + childrenCreated + " / " + displayCount + " children created",
width/2, height/2);
windowTitle(String.format("Main %6.2ffps", frameRate));
if (childrenCreated < displayCount && frameCount % frameDelay == 0) {
int targetDisplay = childrenCreated + 1;
children[childrenCreated] = new ChildApplet(targetDisplay, screens[childrenCreated].getDefaultConfiguration().getBounds());
childrenCreated++;
}
}
Rectangle getVirtualBounds(GraphicsDevice[] devices) {
Rectangle bounds = new Rectangle();
for (GraphicsDevice device : devices) {
bounds = bounds.union(device.getDefaultConfiguration().getBounds());
}
return bounds;
}
class ChildApplet extends PApplet {
int targetDisplay;
Rectangle screenBounds;
ChildApplet(int targetDisplay, Rectangle screenBounds) {
super();
this.targetDisplay = targetDisplay;
this.screenBounds = screenBounds;
PApplet.runSketch(new String[] { "ChildApplet" + targetDisplay }, this);
}
void settings() {
fullScreen(P2D, targetDisplay);
smooth(0);
println("Creating fullscreen window on display " + targetDisplay);
}
void setup() {
pixelDensity(1);
}
void draw() {
background(0);
drawImageAcrossDisplays(img);
windowTitle(String.format("Window display %d %6.2ffps", targetDisplay, frameRate));
}
void drawImageAcrossDisplays(PImage img) {
float virtualW = virtualBounds.width;
float virtualH = virtualBounds.height;
float imgRatio = img.width / (float) img.height;
float virtualRatio = virtualW / virtualH;
float drawW, drawH;
// object-fit: cover
if (imgRatio > virtualRatio) {
drawH = virtualH;
drawW = drawH * imgRatio;
} else {
drawW = virtualW;
drawH = drawW / imgRatio;
}
float drawX = virtualBounds.x + (virtualW - drawW) / 2.0;
float drawY = virtualBounds.y + (virtualH - drawH) / 2.0;
// Position this display inside the virtual desktop
float offsetX = screenBounds.x - drawX;
float offsetY = screenBounds.y - drawY;
image(img, -offsetX, -offsetY, drawW, drawH);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment