Everything is possible just you need some creativity and hard work :)
I hope you know that Java can call native Windows API (this won't be very performance vise, but we have only this way), for this we could use JNA lib which will give us access to native shared libraries.
I have done some quick concept check this code only checks if active window fully covers java application window, but you can iterate over visible windows and calculate area too, JNA gives that access too.
For my demo project I was using these JNA dependencies:
compile("net.java.dev.jna", "jna", "4.5.0")
compile("net.java.dev.jna", "jna-platform", "4.5.0")
My main class:
package com.sauliuxx.inc;
import com.sauliuxx.inc.workers.ActiveWindowChecker;
import com.sun.jna.platform.win32.WinDef;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* The type App.
*/
public class App extends Frame implements ActionListener {
private final String title = "Demo123";
private Label sizeLabel;
private Label positionLabel;
private Label visibleLabel;
BlockingQueue<WinDef.RECT> q =
new LinkedBlockingQueue<>();
private App() {
this.setTitle(title);
this.setLayout(new BorderLayout());
this.setSize(500, 500);
Panel infoPanel = new Panel();
sizeLabel = new Label(this.getSize().height + " X " + this.getSize().width);
infoPanel.add(sizeLabel);
positionLabel = new Label("X: " + this.getLocation().getX() + " Y: " + this.getLocation().getY());
infoPanel.add(positionLabel);
visibleLabel = new Label(this.isVisible() ? "true" : "false");
infoPanel.add(visibleLabel);
this.add(infoPanel, BorderLayout.PAGE_END);
Timer timer = new Timer(250, this);
timer.start();
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent componentEvent) {
sizeLabel.setText(componentEvent.getComponent().getSize().height + " X " + componentEvent.getComponent().getSize().width);
}
@Override
public void componentMoved(ComponentEvent componentEvent) {
positionLabel.setText("X: " + componentEvent.getComponent().getLocation().getX() + " Y: " + componentEvent.getComponent().getLocation().getY());
}
@Override
public void componentShown(ComponentEvent componentEvent) {
visibleLabel.setText("true");
}
@Override
public void componentHidden(ComponentEvent componentEvent) {
visibleLabel.setText("false");
}
});
ActiveWindowChecker awcDeamon = new ActiveWindowChecker(q);
awcDeamon.setDaemon(true);
awcDeamon.start();
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
WinDef.RECT rect = null;
try {
rect = q.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (this.isActive()) {
System.out.println("action");
} else {
//System.out.println("rect = " + (rect != null ? rect : ""));
//System.out.println("frame = [(" + (int)this.getLocation().getX() + "," + (int)this.getLocation().getY() + ") (" + this.getSize().width + "," + this.getSize().height + ")]");
// x and y windows to compare top left point
int rxTop = rect == null ? 0: rect.left;
int ryTop = rect == null ? 0:rect.top;
int fxTop = (int) this.getLocation().getX();
int fyTop = (int) this.getLocation().getY();
// bottom right points
int rxBottom = rect == null ? 0: rect.right;
int ryBottom = rect == null ? 0: rect.bottom;
int fxBottom = fxTop + this.getSize().width;
int fyBottom = fyTop + this.getSize().height;
if ((rxTop >= fxTop || ryTop >= fyTop) || (rxBottom <= fxBottom || ryBottom <= fyBottom))
{
System.out.println("Not covered by active window.");
}
else{
System.out.println("Covered by active window.");
}
}
}
/**
* The entry point of application.
*
* @param args the input arguments
*/
public static void main(String... args) {
if (!System.getProperty("os.name").contains("Windows")) {
System.err.println("ERROR: Only implemented on Windows");
System.exit(1);
}
java.awt.EventQueue.invokeLater(() -> new App().setVisible(true));
}
}
My worker class:
package com.sauliuxx.inc.workers;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import java.util.concurrent.BlockingQueue;
/**
* The type Active window checker.
*/
public class ActiveWindowChecker extends Thread {
private static final int MAX_TITLE_LENGTH = 1024;
private final BlockingQueue<WinDef.RECT> queue;
/**
* Instantiates a new Active window checker.
*
* @param q the q
*/
public ActiveWindowChecker(BlockingQueue<WinDef.RECT> q) {
this.queue = q;
}
@Override
public void run() {
Exception ex = null;
while (ex == null) {
char[] buffer = new char[MAX_TITLE_LENGTH * 2];
WinDef.HWND hwnd = User32.INSTANCE.GetForegroundWindow();
User32.INSTANCE.GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH);
System.out.println("Active window title: " + Native.toString(buffer));
WinDef.RECT rect = new WinDef.RECT();
User32.INSTANCE.GetWindowRect(hwnd, rect);
try {
queue.put(rect);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
ex = e;
}
}
}
}