# Draw Shapes on the Screen directly without a proper window

**URL:** https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215
**Category:** Gallery
**Created:** [April 14, 2025, 4:03pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215 "2025-04-14T16:03:51Z")
**Posts on this page:** 17
**Page:** 2

<div class="post-metadata">

### Author: ![ProcessingOrg](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/processingorg/32/18341_2.png) [@ProcessingOrg](https://discourse.processing.org/u/ProcessingOrg)
#### Post date: [April 16, 2025, 9:49pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/24 "2025-04-16T21:49:11Z")

</div>

You might be interested to know there is a new library template 😃

> **[Processing Library Template](https://processing.github.io/processing-library-template/)**

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 16, 2025, 9:51pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/25 "2025-04-16T21:51:57Z")

</div>

You can click through it at opacity \< 0.05 on Mac (my demo).

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 6:24am UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/26 "2025-04-17T06:24:09Z")

</div>

It seems to be a well known issue with macos that this doesn’t properly work.  
There is e.g. a website where a .jar file is sold that supposedly will solve this problem. However there is actually nothing there as this problem has no proper solution…

I think I can make something similar if this code works properly:

```Java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.Ellipse2D;
import static java.awt.GraphicsDevice.WindowTranslucency.*;

class ShapedWindowDemo extends JFrame {
  ShapedWindowDemo() {
    super("ShapedWindow");
    setLayout(new GridBagLayout());

    // It is best practice to set the window's shape in
    // the componentResized method. Then, if the window
    // changes size, the shape will be correctly recalculated.
    addComponentListener(new ComponentAdapter() {
      // Give the window an elliptical shape.
      // If the window is resized, the shape is recalculated here.
      @Override
        void componentResized(ComponentEvent e) {
        setShape(new Ellipse2D.Double(0, 0, getWidth(), getHeight()));
      }
    }
    );
    setUndecorated(true);
    setSize(300, 200);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}
// Determine what the GraphicsDevice can support.
GraphicsEnvironment ge =
  GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
final boolean isTranslucencySupported =
  gd.isWindowTranslucencySupported(TRANSLUCENT);

//If shaped windows aren't supported, exit.
if (!gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT)) {
  System.err.println("Shaped windows are not supported");
  System.exit(0);
}

//If translucent windows aren't supported,
//create an opaque window.
if (!isTranslucencySupported) {
  System.out.println(
    "Translucency is not supported, creating an opaque window");
}
SwingUtilities.invokeLater(new Runnable() {
  @Override
    public void run() {
    ShapedWindowDemo sw = new ShapedWindowDemo();
    sw.getContentPane().setBackground(new Color(0,0,0));
    // Display the window.
    sw.setVisible(true);
  }
}
);
getSurface().setVisible(false);

```

This should just create an ellipse in the middle of the screen.  
When checking if this properly works please also try clicking near the edge of the ellipse to exclude the possibility that it internally makes an rectangular window that places the ellipse inside.

---

<div class="post-metadata">

### Author: ![sableraph](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sableraph/32/251_2.png) [@sableraph](https://discourse.processing.org/u/sableraph)
#### Post date: [April 17, 2025, 2:00pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/28 "2025-04-17T14:00:08Z")

</div>

> [@NumericPrime](#):
>
> I think I can make something similar if this code works properly:

I can’t seem to run this code by itself. Is it a complete Java project like the previous one?

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 17, 2025, 3:18pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/29 "2025-04-17T15:18:11Z")

</div>

Runs as is on my mac. Gives an elliptical black non-movable window which will not allow click throughs. My personal assessment is that Apple disallowed click throughs likely for a good reason (to keep users from unintended consequences).  
**Output:**

 ![o](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/6/3/63702056e770b20b9366ac495e97b63cc6af4ce0.png)

An alternate approach would be to create a ‘halo’ circle around an arrow cursor, but that won’t be easy either.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 5:58pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/30 "2025-04-17T17:58:35Z")

</div>

I’m actually working on something similar:

```Processing
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
BufferedImage bi;
  JWindow windows[]={createPartialWindow(), createPartialWindow(), createPartialWindow(), createPartialWindow()};
  JPanel panels[]=new JPanel[4];
  int exclusionZoneSize=2;
void setup() {
//Generates the image
  bi=new BufferedImage(displayWidth, displayHeight, BufferedImage.TYPE_INT_ARGB);
  Graphics2D g2=(Graphics2D) bi.getGraphics();
  g2.setColor(new Color(255,0,0,50));
  g2.fillRect(0,0,displayWidth, displayHeight);
  g2.setColor(new Color(0,0,0));
  g2.fillOval(90,90,20,20);
  for(int i=0;i<windows.length;i++) panels[i]=(JPanel) windows[i].getContentPane();
  new java.util.Timer().schedule(new java.util.TimerTask() {
    public void run() {
      System.exit(0);
    }
  }
  , 10000);
  windows[0].setLocation(0,0);
  for(int i=0;i<windows.length;i++) windows[i].setVisible(true);
}
void draw(){
  Point p=MouseInfo.getPointerInfo().getLocation();
//Aligns the four windows so that they cover the screen except a little part around the mouse.
  panels[0].setPreferredSize(new Dimension(p.x-1-exclusionZoneSize,p.y+exclusionZoneSize));
  windows[0].setSize(p.x-1-exclusionZoneSize,p.y+exclusionZoneSize);
  windows[1].setLocation(0,p.y+exclusionZoneSize);
  panels[1].setPreferredSize(new Dimension(displayWidth,displayHeight-(p.y+exclusionZoneSize)));
  windows[1].setSize(displayWidth,displayHeight-(p.y+exclusionZoneSize));
  windows[2].setLocation(p.x+exclusionZoneSize,0);
  panels[2].setPreferredSize(new Dimension(displayWidth-(p.x+exclusionZoneSize),p.y+exclusionZoneSize));
  windows[2].setSize(displayWidth-(p.x+exclusionZoneSize),p.y+exclusionZoneSize);
  windows[3].setLocation(p.x-1-exclusionZoneSize,0);
  panels[3].setPreferredSize(new Dimension(2*exclusionZoneSize+1,p.y-exclusionZoneSize));
  windows[3].setSize(2*exclusionZoneSize+1,p.y-exclusionZoneSize);
}

JWindow createPartialWindow() {
  JWindow jw=new JWindow();
  JPanel jp=new JPanel() {
    @Override
      public void paint(Graphics g) {
      //Renders the image
      Point location=new Point(0,0);
      SwingUtilities.convertPointToScreen(location, this);
      //println(location.x, location.y, getPreferredSize().width, getPreferredSize().height);
      g.drawImage(bi.getSubimage(location.x, location.y, getPreferredSize().width, getPreferredSize().height), 0, 0, null);
    }
  };
  jw.setBackground(new Color(0, 0, 0, 0));
  jp.setBackground(new Color(0, 0, 0, 0));
  jw.setAlwaysOnTop(true);
  jp.setOpaque(false);
  jw.setContentPane(jp);
  jw.getRootPane().putClientProperty("apply.awt.draggableWindowBackground", false);
  jw.pack();
  return jw;
}

```

As one can notice, this code is extreamly laggy but it would theoretically work.  
The next thing to try is to try and abuse the setShape command.  
To give it a Shape covering the screen but so happening to have hole exactly where the mouse is.

Can anyone test this code? Someone on StackOverflow commented that I should try using setShape and I wrote this code based on that comment.

```Processing
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
BufferedImage bi;
  JWindow windows[]={createPartialWindow(), createPartialWindow(), createPartialWindow(), createPartialWindow()};
  JPanel panels[]=new JPanel[4];
  int exclusionZoneSize=2;
void setup() {
  bi=new BufferedImage(displayWidth, displayHeight, BufferedImage.TYPE_INT_ARGB);
  Graphics2D g2=(Graphics2D) bi.getGraphics();
  g2.setColor(new Color(255,0,0,50));
  g2.fillRect(0,0,displayWidth, displayHeight);
  g2.setColor(new Color(0,0,0));
  g2.fillOval(90,90,20,20);
  for(int i=0;i<windows.length;i++) panels[i]=(JPanel) windows[i].getContentPane();
  new java.util.Timer().schedule(new java.util.TimerTask() {
    public void run() {
      System.exit(0);
    }
  }
  , 10000);
  windows[0].setLocation(0,0);
  windows[0].setVisible(true);
}
void draw(){
  Point p=MouseInfo.getPointerInfo().getLocation();
  Rectangle window=new Rectangle(0,0,displayWidth,displayHeight);
  Rectangle windown=new Rectangle(p.x-exclusionZoneSize,p.y-exclusionZoneSize,exclusionZoneSize<<1|1,exclusionZoneSize<<1|1);
  Area a=new Area(window);
  a.subtract(new Area(windown));
  panels[0].setPreferredSize(new Dimension(displayWidth,displayHeight));
  windows[0].setSize(new Dimension(displayWidth,displayHeight));
  windows[0].setShape(a);
}

JWindow createPartialWindow() {
  JWindow jw=new JWindow();
  JPanel jp=new JPanel() {
    @Override
      public void paint(Graphics g) {
        println("Repainting");
      //Graphics2D g2=(Graphics2D)g;
      //g2.fillOval(40, 40, 20, 20);
      Point location=new Point(0,0);
      SwingUtilities.convertPointToScreen(location, this);
      println(location.x, location.y, getPreferredSize().width, getPreferredSize().height);
      g.drawImage(bi.getSubimage(location.x, location.y, getPreferredSize().width, getPreferredSize().height), 0, 0, null);
    }
  };
  jw.setBackground(new Color(0, 0, 0, 0));
  jp.setBackground(new Color(0, 0, 0, 0));
  jw.setAlwaysOnTop(true);
  jp.setOpaque(false);
  jw.setContentPane(jp);
  jw.getRootPane().putClientProperty("apply.awt.draggableWindowBackground", false);
  jw.pack();
  return jw;
}

```

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 17, 2025, 6:38pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/31 "2025-04-17T18:38:29Z")

</div>

Unable to run second demo on mac.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 6:40pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/32 "2025-04-17T18:40:34Z")

</div>

Do you get any error message? Does the program just do nothing?

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 17, 2025, 6:44pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/33 "2025-04-17T18:44:52Z")

</div>

This is part of it (much longer); copy to clipboard doesn’t work on mac:

 ![t](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/8/0/802518fc402109a1dc7fca94183cb71dacb87276.jpeg)

All that shows is the postage stamp size default Processing window which is empty.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 6:47pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/34 "2025-04-17T18:47:30Z")

</div>

This is the weirdest point where this program could fail.  
Try replacing:

```auto
g.drawImage(bi.getSubimage(location.x, location.y, getPreferredSize().width, getPreferredSize().height), 0, 0, null);

```

with

```auto
g.drawImage(bi, 0, 0, null);

```

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 17, 2025, 7:20pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/35 "2025-04-17T19:20:59Z")

</div>

> [@NumericPrime](#):
>
> `g.drawImage(bi, 0, 0, null);`

Now it runs without error. Get a beautiful transparent red sheen to my entire screen which is dispatched by the timer. Still have the default Processing window which should be easy to get rid of.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 7:22pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/36 "2025-04-17T19:22:42Z")

</div>

Is it now “click through”? if so I can now update the library to (hopefully) properly function on Mac.

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 17, 2025, 7:25pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/37 "2025-04-17T19:25:06Z")

</div>

Still not “click through” at any point, including the black dot.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 7:30pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/38 "2025-04-17T19:30:49Z")

</div>

Could you try to increase the exclusionZoneSize variable? When the program runs is there a blank square following the mouse?

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [April 17, 2025, 7:36pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/39 "2025-04-17T19:36:02Z")

</div>

Increased exclusionZoneSize from 2 to 200; still no click through in the ‘zone’.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 17, 2025, 7:43pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/40 "2025-04-17T19:43:25Z")

</div>

Thats troubleing. It seems that MacOS does create a rectangle around the window in which one can’t click through. So if I wish to fix it I’d probably go down the path of trying to make the four-window solution less laggy.

---

<div class="post-metadata">

### Author: ![NumericPrime](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/numericprime/32/16318_2.png) [@NumericPrime](https://discourse.processing.org/u/NumericPrime)
#### Post date: [April 20, 2025, 4:16pm UTC](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215/41 "2025-04-20T16:16:08Z")

</div>

I may have a potential patch for the problem on Mac implemented in a new version of the library. Since it does glich the graphics when quickly moving your mouse it is a toggle option. However my code should check if the OS is MacOS.

This is the current version of the library:

> **[Release Useful Renderers 0.2 · NumericPrime/UsefulProcessingRenderers](https://github.com/NumericPrime/UsefulProcessingRenderers/releases/tag/v0.2.0)**
>
> Provided a potential patch for the glitch on MacOS. It has currently the issue that it glitches out the graphics a little especially when moving the mouse quickly.

You are more than welcome to test it:

This is an example from the library to test this feature on.

> **Example code**
>
> ```auto
> /*In this example the sketch will paint the screen black except for a circle around the cursor.*/
> 
> import usefulrenderers.*;
> import usefulrenderers.overlay.*;
> 
> void setup() {
> //Activates the overlay renderer that allows painting on the screen directly.
> fullScreen(UsefulRenderers.OVERLAY);
> }
> void draw() {
> //Paints the background black
> background(0);
> //Colors the pixel to be drawn transparent
> fill(0, 0, 0, 0);
> ellipse(mouseX, mouseY, 150, 150);
> }
> void keyPressed() {
> if (key==ESC)exit();
> }
> 
> //If you are on mac and the windows aren't click through try adding this line:
> //static{UsefulRenderers.MACWorkaround=true;}
> 
> ```

If you want to tinker around with fixing the glitchy graphics:  
The work-around is based on the following code:

> **Code**
>
> ```auto
> import javax.swing.*;
> import java.awt.*;
> import java.awt.image.*;
> import java.awt.geom.*;
> BufferedImage bi;
> JWindow windows[]={createPartialWindow(), createPartialWindow(), createPartialWindow(), createPartialWindow()};
> JPanel panels[]=new JPanel[4];
> void setup() {
> //Generates the image
> bi=new BufferedImage(displayWidth, displayHeight, BufferedImage.TYPE_INT_ARGB);
> Graphics2D g2=(Graphics2D) bi.getGraphics();
> g2.setColor(new Color(255, 0, 0, 50));
> g2.fillRect(0, 0, displayWidth, displayHeight);
> g2.setColor(new Color(0, 0, 0));
> g2.fillOval(90, 90, 20, 20);
> for (int i=0; i<windows.length; i++) panels[i]=(JPanel) windows[i].getContentPane();
> new java.util.Timer().schedule(new java.util.TimerTask() {
> public void run() {
> System.exit(0);
> }
> }
> , 10000);
> for (int i=0; i<windows.length; i++) windows[i].setLocation(0,0);
> for (int i=0; i<windows.length; i++) windows[i].setVisible(true);
> for (int i=0; i<windows.length; i++)panels[i].setPreferredSize(new Dimension(displayWidth, displayHeight));
> for (int i=0; i<windows.length; i++)windows[i].setSize(new Dimension(displayWidth, displayHeight));
> }
> volatile int pending=0;
> void draw() {
> Point p=MouseInfo.getPointerInfo().getLocation();
> //Aligns the four windows so that they cover the screen except for the pixel the mouse lies over
> windows[0].setShape(new Rectangle(0, 0, p.x, p.y+1));
> windows[1].setShape(new Rectangle(0, p.y+1, displayWidth, displayHeight-p.y));
> windows[2].setShape(new Rectangle(p.x+1, 0, displayWidth-p.x, p.y+1));
> windows[3].setShape(new Rectangle(p.x, 0, 1, p.y-1));
> //Waits until all windows are repainted
> while (pending>0) {
> while (pending>0);
> delay(1);
> }
> println(frameRate);
> }
> 
> JWindow createPartialWindow() {
> JWindow jw=new JWindow();
> JPanel jp=new JPanel() {
> @Override
> public void paint(Graphics g) {
> pending++;
> //Renders the image
> g.drawImage(bi, 0, 0, null);
> pending--;
> }
> };
> jw.setBackground(new Color(0, 0, 0, 0));
> jw.setLayout(null);
> jp.setBackground(new Color(0, 0, 0, 0));
> jw.setAlwaysOnTop(true);
> jp.setOpaque(false);
> jw.setContentPane(jp);
> jw.getRootPane().putClientProperty("apply.awt.draggableWindowBackground", false);
> jw.pack();
> return jw;
> }
> 
> ```

Any improvement made to this code can probably also be made to the library.

[Previous page](https://discourse.processing.org/t/draw-shapes-on-the-screen-directly-without-a-proper-window/46215.md?page=1)
