Windows Event Dispatch modified to permit multiple instances (required for multiple, simultaneous system tray instances on windows)
This commit is contained in:
parent
41fe221e3c
commit
2a69b70803
@ -26,6 +26,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -33,12 +34,13 @@ import org.slf4j.LoggerFactory;
|
|||||||
import com.sun.jna.WString;
|
import com.sun.jna.WString;
|
||||||
import com.sun.jna.platform.win32.WinUser;
|
import com.sun.jna.platform.win32.WinUser;
|
||||||
|
|
||||||
@SuppressWarnings({"Convert2Lambda", "UnusedAssignment", "Convert2Diamond", "FieldCanBeLocal"})
|
@SuppressWarnings({"Convert2Lambda", "UnusedAssignment", "Convert2Diamond", "FieldCanBeLocal", "unused"})
|
||||||
public
|
public
|
||||||
class WindowsEventDispatch implements Runnable {
|
class WindowsEventDispatch implements Runnable {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(WindowsEventDispatch.class);
|
private static final Logger logger = LoggerFactory.getLogger(WindowsEventDispatch.class);
|
||||||
|
|
||||||
private static final String NAME = "WindowsEventDispatch";
|
private static final String NAME = "WindowsEventDispatch_";
|
||||||
|
private static final AtomicInteger COUNT = new AtomicInteger(0);
|
||||||
|
|
||||||
public static final int WM_TASKBARCREATED = User32.RegisterWindowMessage(new WString("TaskbarCreated"));
|
public static final int WM_TASKBARCREATED = User32.RegisterWindowMessage(new WString("TaskbarCreated"));
|
||||||
public static final int WM_COMMAND = 0x0111;
|
public static final int WM_COMMAND = 0x0111;
|
||||||
@ -49,12 +51,10 @@ class WindowsEventDispatch implements Runnable {
|
|||||||
public static final int MF_POPUP = 0x00000010;
|
public static final int MF_POPUP = 0x00000010;
|
||||||
|
|
||||||
|
|
||||||
private static final WindowsEventDispatch edt = new WindowsEventDispatch();
|
private final String name = NAME + COUNT.getAndIncrement();
|
||||||
private final static Map<Integer, List<Listener>> messageIDs = new HashMap<Integer, List<Listener>>();
|
private final Map<Integer, List<Listener>> messageIDs = new HashMap<Integer, List<Listener>>();
|
||||||
|
|
||||||
private static final Object lock = new Object();
|
|
||||||
private static int referenceCount = 0;
|
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
private Thread dispatchThread;
|
private Thread dispatchThread;
|
||||||
|
|
||||||
@ -70,61 +70,55 @@ class WindowsEventDispatch implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static
|
public static
|
||||||
void start() {
|
WindowsEventDispatch start() {
|
||||||
synchronized (lock) {
|
WindowsEventDispatch edt = new WindowsEventDispatch();
|
||||||
int ref = referenceCount++;
|
|
||||||
|
|
||||||
if (ref == 0) {
|
synchronized (edt.lock) {
|
||||||
edt.start_();
|
edt.start_();
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// wait for the dispatch thread to start
|
// wait for the dispatch thread to start if we aren't started yet, but requested it
|
||||||
lock.wait();
|
edt.lock.wait();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return edt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static
|
public
|
||||||
void stop() {
|
|
||||||
synchronized (lock) {
|
|
||||||
if (--referenceCount == 0) {
|
|
||||||
edt.stop_();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static
|
|
||||||
HWND get() {
|
HWND get() {
|
||||||
return edt.hWnd;
|
return hWnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// always from inside lock!
|
// always from inside lock!
|
||||||
private
|
private
|
||||||
void start_() {
|
void start_() {
|
||||||
dispatchThread = new Thread(this, NAME);
|
dispatchThread = new Thread(this, name);
|
||||||
dispatchThread.start();
|
dispatchThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// always from inside lock!
|
public void
|
||||||
private void
|
stop() {
|
||||||
stop_() {
|
synchronized (lock) {
|
||||||
User32.SendMessage(hWnd, WM_QUIT, new WPARAM(0), new LPARAM(0));
|
if (hWnd != null) {
|
||||||
|
User32.PostMessage(hWnd, WM_QUIT, new WPARAM(0), new LPARAM(0));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// wait for the dispatch thread to quit (but only if we are not on the dispatch thread)
|
// wait for the dispatch thread to quit (but only if we are not on the dispatch thread)
|
||||||
if (!Thread.currentThread().equals(dispatchThread)) {
|
if (!Thread.currentThread().equals(dispatchThread)) {
|
||||||
dispatchThread.join();
|
dispatchThread.join();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("Java8MapApi")
|
@SuppressWarnings("Java8MapApi")
|
||||||
public static
|
public
|
||||||
void addListener(final int messageId, final Listener listener) {
|
void addListener(final int messageId, final Listener listener) {
|
||||||
synchronized (messageIDs) {
|
synchronized (messageIDs) {
|
||||||
List<Listener> listeners = messageIDs.get(messageId);
|
List<Listener> listeners = messageIDs.get(messageId);
|
||||||
@ -136,7 +130,8 @@ class WindowsEventDispatch implements Runnable {
|
|||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static
|
|
||||||
|
public
|
||||||
void removeListener(final Listener listener) {
|
void removeListener(final Listener listener) {
|
||||||
synchronized (messageIDs) {
|
synchronized (messageIDs) {
|
||||||
for (Map.Entry<Integer, List<Listener>> entry : messageIDs.entrySet()) {
|
for (Map.Entry<Integer, List<Listener>> entry : messageIDs.entrySet()) {
|
||||||
@ -180,7 +175,7 @@ class WindowsEventDispatch implements Runnable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
hWnd = User32.CreateWindowEx(0, "STATIC", NAME, 0, 0, 0, 0, 0, null, null, null,
|
hWnd = User32.CreateWindowEx(0, "STATIC", name, 0, 0, 0, 0, 0, null, null, null,
|
||||||
null);
|
null);
|
||||||
if (hWnd == null) {
|
if (hWnd == null) {
|
||||||
throw new GetLastErrorException();
|
throw new GetLastErrorException();
|
||||||
|
Loading…
Reference in New Issue
Block a user