All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.openfin.desktop.win32.ExternalWindowObserver Maven / Gradle / Ivy

There is a newer version: 11.0.2
Show newest version
package com.openfin.desktop.win32;

import com.openfin.desktop.*;
import com.openfin.desktop.EventListener;
import com.openfin.desktop.Window;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import org.json.JSONObject;

import java.awt.*;
import java.net.URISyntaxException;
import java.util.*;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * Integrates a window outside of the desktop for interaction and control with the API.
 * An integrated window is controlled in the same way as an HTML window running in the desktop.
 * It can be controlled and queried by the API,
 * generate events that are subscribed to by addEventListener,
 * and join/merge groups with other windows for docking.
 *
 * Created by wche on 3/11/15.
 */
public class ExternalWindowObserver implements DesktopStateListener {
    private final static Logger logger = LoggerFactory.getLogger(ExternalWindowObserver.class.getName());
    private String appUuid;
    private String name;
    private DesktopConnection desktopConnection;
    private WinDef.HWND hwnd;
    private String hwndHex;
    private boolean registered = false;                   // True when this window has been successfully registered with the container.
    private AckListener registerListener;

    private boolean frameDisabled;
    private boolean handlinguserDisabledFrame;
    private boolean ignoreNextChange;
    private int subscribedSystemEvents;

    // Window messges
    public static final int WM_CAPTURECHANGED = 0x0215;
    public static final int WM_DESTROY = 0x0002;
    public static final int WM_ENTERSIZEMOVE = 0x0231;
    public static final int WM_ERASEBKGND = 0x0014;
    public static final int WM_EXITSIZEMOVE = 0x0232;
    public static final int WM_KEYDOWN = 0x0100;
    public static final int WM_KEYUP = 0x0101;
    public static final int WM_KILLFOCUS = 0x0008;
    public static final int WM_LBUTTONDOWN = 0x0201;
    public static final int WM_LBUTTONUP = 0x0202;
    public static final int WM_MOUSEMOVE = 0x0200;
    public static final int WM_MOVE = 0x0003;
    public static final int WM_MOVING = 0x0216;
    public static final int WM_NCLBUTTONDBLCLK = 0x00A3;
    public static final int WM_NCLBUTTONUP = 0x00A2;
    public static final int WM_NOTIFY = 0x4E;
    public static final int WM_SETFOCUS = 0x0007;
    public static final int WM_SIZING = 0x0214;
    public static final int WM_SYSCOMMAND = 0x0112;
    public static final int WM_WINDOWPOSCHANGED = 0x0047;
    public static final int WM_WINDOWPOSCHANGING = 0x0046;
    public static final int WM_PAINT = 0x000F;
    // System command messages
    public static final int SC_CLOSE = 0xF060;
    public static final int SC_MAXIMIZE = 0xF030;
    public static final int SC_MINIMIZE = 0xF020;
    public static final int SC_RESTORE = 0xF120;
    // SetWindowPosition
    public static final int SWP_HIDEWINDOW = 0x0080;
    public static final int SWP_NOMOVE = 0x0002;
    public static final int SWP_NOSIZE = 0x0001;
    public static final int SWP_SHOWWINDOW = 0x0040;

    // Payloads for event propagation to the container
    private JSONObject blurPayload;
    private JSONObject captureChangedPayload;
    private JSONObject destroyedPayload;
    private JSONObject enterSizeMovePayload;
    private JSONObject exitSizeMovePayload;
    private JSONObject focusPayload;
    private JSONObject movePayload;
    private JSONObject movingPayload;
    private JSONObject ncDoubleClickPayload;
    private JSONObject posChangedPayload;
    private JSONObject posChangingPayload;
    private JSONObject sizingPayload;
    private JSONObject sysCommandPayload;

    /**
     * OpenFin window EventListener to listen for FrameDisable events
     */
    private EventListener frameDisableListener = new EventListener() {
        @Override
        public void eventReceived(ActionEvent actionEvent) {
            onWindowFrameDisabled();
        }
    };
    /**
     * OpenFin window EventListener to listen for FrameEnable events
     */
    private EventListener frameEnableListener = new EventListener() {
        @Override
        public void eventReceived(ActionEvent actionEvent) {
            onWindowFrameEnabled();
        }
    };

    /**
     *
     * Establishes a connection and registers
     * the window identified by hWnd with the Runtime.
     *
     * @param port The host that the desktop is running on
     * @param parentAppUuid The UUID of the application to create register this window as a child of
     * @param name The unique name for this window as a child window
     * @param window The HWND of the window to control/observe
     * @param listener AckListener for external registering
     * @throws DesktopException if registration fails
     */
    public ExternalWindowObserver(int port, String parentAppUuid, String name, java.awt.Window window, AckListener listener) throws DesktopException {
        logger.debug("init for " + name);
        this.appUuid = parentAppUuid;
        this.name = name;
        this.desktopConnection = new DesktopConnection(UUID.randomUUID().toString(), null, port);
        this.hwnd = new WinDef.HWND();
        this.hwnd.setPointer(Native.getWindowPointer(window));
        this.hwndHex = Long.toHexString(Native.getWindowID(window));
        this.registerListener = listener;
        this.subscribedSystemEvents = (SC_CLOSE | SC_MAXIMIZE | SC_MINIMIZE | SC_RESTORE);

        this.desktopConnection.connect(this);
    }

    /**
     * Get UUID of parent application
     * @return UUID
     */
    public String getAppUuid() {
        return this.appUuid;
    }

    /**
     * Get name of this window
     * @return name
     */
    public String getName() {
        return this.name;
    }

    /**
     *  deregisters the window with the desktop
     *
     * @throws DesktopException if errors are caught during cleanup
     */
    private void cleanup() throws DesktopException{
        logger.debug("cleaning up");
        try {
            final CountDownLatch deregisterLatch = new CountDownLatch(1);
            // Notify the desktop to remove this external window
            deregisterExternalWindow(new AckListener() {
                public void onSuccess(Ack ack) {
                    deregisterLatch.countDown();
                }

                public void onError(Ack ack) {
                    logger.error(String.format("Error registering external window %s", ack.getReason()));
                    deregisterLatch.countDown();
                }
            });
            deregisterLatch.await(5, TimeUnit.SECONDS);
            // Reset the normal WndProc
            WinMessageHelper.unhookWndProc(this.hwnd);
            // Ensure the deregister gets sent.
            this.desktopConnection.disconnect();
        } catch (Exception ex) {
            logger.info("Error cleaning up", ex);
        }
    }

    /**
     * Ensures this window is deregistered on disposal
     *
     * @throws DesktopException if errors are caught during cleanup
     */
    public void dispose() throws DesktopException{
        cleanup();
    }

    /**
     *
     * Triggered when a "frame-enabled" event is triggered for the registered external window.
     *
     */
    private void onWindowFrameEnabled() {
        logger.debug("window frame enabled " + name);
        this.frameDisabled = false;
    }

    /**
     *
     * Triggered when a "frame-disabled" event is triggered for the registered external window.
     *
     */
    private void onWindowFrameDisabled() {
        logger.debug("window frame disabled " + name);
        this.frameDisabled = true;
    }

    /**
     *
     * Notifies the desktop to track, control and observe events for this window
     *
     * @param callback AckListener for the request
     */
    private void registerExternalWindow(final AckListener callback) {
        logger.debug("registering " + name);
        JSONObject registerExternalWindowPayload = new JSONObject();
        registerExternalWindowPayload.put("topic", "application");
        registerExternalWindowPayload.put("uuid", this.appUuid);
        registerExternalWindowPayload.put("hwnd", this.hwndHex);
        registerExternalWindowPayload.put("name", this.name);

        AckListener subscribeToFrameSateChange = new AckListener() {
            @Override
            public void onSuccess(final Ack ack) {
                // this is on websocket io thread, need to run on another thread
                Thread thread = new Thread() {
                    public void run() {
                        // Subscribe to frame state change events
                        try {
                            Window wnd = Window.wrap(appUuid, name, desktopConnection);
                            DesktopUtils.addEventListener(wnd, "frame-disabled", frameDisableListener);
                            DesktopUtils.addEventListener(wnd, "frame-enabled", frameEnableListener);
                            DesktopUtils.successAck(callback, ack);
                        } catch (Exception ex) {
                            logger.error("Error registering external window", ex);
                            DesktopUtils.errorAckOnException(callback, ExternalWindowObserver.this, ex);
                        }
                    }
                };
                thread.setName(ExternalWindowObserver.class.getName() + ".registerExternalWindow");
                thread.start();
            }
            @Override
            public void onError(Ack ack) {
                logger.warn("Error registering external window " + ack.getReason());
                DesktopUtils.errorAck(callback, ack);
            }
        };
        this.desktopConnection.sendAction("register-external-window", registerExternalWindowPayload, subscribeToFrameSateChange, this);
    }

    /**
     * Notifies the desktop to stop all integration with this window, and remove it from the app
     *
     * @param callback AckListener for this request
     * @see com.openfin.desktop.AckListener
     *
     */
    private void deregisterExternalWindow(final AckListener callback) {
        if (this.registered) {
            logger.debug("deregistering " + name);
            this.registered = false;
            JSONObject deregisterExternalWindowPayload = new JSONObject();
            deregisterExternalWindowPayload.put("topic", "application");
            deregisterExternalWindowPayload.put("uuid", appUuid);
            deregisterExternalWindowPayload.put("hwnd", hwndHex);
            deregisterExternalWindowPayload.put("name", name);

            AckListener deSubscribeToFrameSateChange = new AckListener() {
                @Override
                public void onSuccess(Ack ack) {
                    // Subscribe to frame state change events
                    Window wnd = Window.wrap(appUuid, name, desktopConnection);
                    wnd.removeEventListener("frame-disabled", frameDisableListener, null);
                    wnd.removeEventListener("frame-enabled", frameEnableListener, null);
                    DesktopUtils.successAck(callback, ack);
                }
                @Override
                public void onError(Ack ack) {
                    logger.warn("Error deregistering external window " + ack.getReason());
                    DesktopUtils.errorAck(callback, ack);
                }
            };
            desktopConnection.sendAction("deregister-external-window", deregisterExternalWindowPayload, deSubscribeToFrameSateChange, this);
        }
    }

    /**
     * sendExternalWindowEvent
     *
     * @param payload The serialized WM message
     *
     */
    private void sendExternalWindowEvent(JSONObject payload) {
        if (this.registered) {
            if (logger.isDebugEnabled()) {
                logger.debug(payload.toString());
            }
            desktopConnection.sendAction("external-window-action", payload, null, this);
        }
    }

    /**
     *
     *  Install delegates to send WM events to the desktop
     *
     */
    private void installMessageHandlers() {
        WindowProcCallback windowProcCallback = new WindowProcCallback() {
            @Override
            public boolean callback(WinDef.HWND hwnd, int msg, WinDef.WPARAM wp, Pointer lp) {
                boolean handled = false;
                try {
                    switch (msg) {
                        case WM_CAPTURECHANGED:
                            onCaptureChanged(hwnd, msg, wp, lp);
                            break;
                        case WM_DESTROY:
                            onWMDestroy(msg);
                            break;
                        case WM_ENTERSIZEMOVE:
                            onEnterSizeMove(msg);
                            break;
                        case WM_EXITSIZEMOVE:
                            onExitSizeMove(msg);
                            break;
                        case WM_KILLFOCUS:
                            onKillFocus(msg);
                            break;
                        case WM_MOVE:
                            onMove(msg, wp, lp);
                            break;
                        case WM_MOVING:
                            handled = onMoving(msg, wp, lp);
                            break;
                        case WM_NCLBUTTONDBLCLK:
                            onNcDoubleClick(msg, wp, lp);
                            break;
                        case WM_SETFOCUS:
                            onSetFocus(msg);
                            break;
                        case WM_SYSCOMMAND:
                            onSysCommand(msg, wp);
                            break;
                        case WM_WINDOWPOSCHANGED:
                            onWindowPosChanged(msg, wp, lp);
                            break;
                        case WM_WINDOWPOSCHANGING:
                            onWindowPosChanging(msg, wp, lp);
                            break;
                        case WM_SIZING:
                            handled = onSizing(msg, wp, lp);
                            break;
                    }
                } catch (Exception e) {
                    logger.error("Error processing callback", e);
                }
                return handled;
            }
        };
        try {
            WinMessageHelper.hookWndProc(hwnd, windowProcCallback);
            if (this.registerListener != null) {
                JSONObject msg = new JSONObject();
                msg.put("success", Boolean.TRUE);
                DesktopUtils.successAck(this.registerListener, new Ack(msg, this));
            }
        } catch (Throwable e) {
            JSONObject msg = new JSONObject();
            msg.put("success", Boolean.FALSE);
            DesktopUtils.errorAck(this.registerListener, new Ack(msg, this));
            logger.error("Error initializing", e);
        }
    }

    /**
     * Called in response to WM_CAPTURECHANGED
     *
     * @param hwnd A handle to the window
     * @param msg WM_CAPTURECHANGED
     * @param wp wParam of Windows message callback
     * @param lp lParam of Windows message callback
     */
    private void onCaptureChanged(WinDef.HWND hwnd, int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onCaptureChanged");
        if (this.captureChangedPayload == null) {
            this.captureChangedPayload = createBaseWMJSONObject(msg);
        }
        WinDef.HWND h = new WinDef.HWND(lp);
        this.captureChangedPayload.put( "lParam", Pointer.nativeValue(lp));
        sendExternalWindowEvent(this.captureChangedPayload);

        if (handlinguserDisabledFrame && !hwnd.equals(h)) {
            ignoreNextChange = true;
        }
    }

    /**
     * Called in response to WM_DESTROY
     *
     * @param msg WM_DESTROY
     */
    private void onWMDestroy(int msg) {
        try {
            logger.debug("onWMDestroy");
            sendExternalWindowEvent(createBaseWMJSONObject(msg));
            cleanup();
        } catch (DesktopException e) {
            logger.error("Error onWMDestroy", e);
        }
    }

    /**
     * Called in response to WM_ENTERSIZEMOVE
     *
     * @param msg WM_ENTERSIZEMOVE
     */
    private void onEnterSizeMove(int msg) {
        logger.debug("onEnterSizeMove");
        if (!handlinguserDisabledFrame && frameDisabled) {
            logger.debug("set handlinguserDisabledFrame true");
            handlinguserDisabledFrame = true;
        }
        if (enterSizeMovePayload == null) {
            enterSizeMovePayload = createBaseWMJSONObject(msg);
        }
        PointerInfo a = MouseInfo.getPointerInfo();
        Point b = a.getLocation();
        enterSizeMovePayload.put("mouseX", b.getX());
        enterSizeMovePayload.put("mouseY", b.getY());
        sendExternalWindowEvent(enterSizeMovePayload);
    }

    /**
     * Called in response to WM_EXITSIZEMOVE
     *
     * @param msg WM_EXITSIZEMOVE
     */
    private void onExitSizeMove(int msg) {
        logger.debug("onExitSizeMove");
        if (handlinguserDisabledFrame) {
            logger.debug("set handlinguserDisabledFrame false");
            handlinguserDisabledFrame = false;
        }
        if (exitSizeMovePayload == null) {
            exitSizeMovePayload = createBaseWMJSONObject(msg);
        }
        PointerInfo a = MouseInfo.getPointerInfo();
        Point b = a.getLocation();
        exitSizeMovePayload.put("mouseX", b.getX());
        exitSizeMovePayload.put("mouseY", b.getY());
        sendExternalWindowEvent(exitSizeMovePayload);
    }

    /**
     * Called in response to WM_KILLFOCUS
     *
     * @param msg WM_KILLFOCUS
     */
    private void onKillFocus(int msg) {
        logger.debug("onKillFocus");
        sendExternalWindowEvent(createBaseWMJSONObject(msg));
    }

    /**
     * Called in response to WM_MOVE
     *
     * @param msg WM_MOVE
     * @param wp wParam of Windows message callback
     * @param lp lParam of Windows message callback
     */
    private void onMove(int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onMove ");
        if (this.movePayload == null) {
            this.movePayload = createBaseWMJSONObject(msg);
        }
        // numbers from lp are for client area.  They are NOT window location
        // WinDef.DWORD dword = new WinDef.DWORD(Pointer.nativeValue(lp));
        // logger.fine("onMove " + dword.getLow().intValue() + ":" + dword.getHigh().intValue());

        WinDef.RECT bounds = new WinDef.RECT();
        User32.INSTANCE.GetWindowRect(this.hwnd, bounds);
        movePayload.put("x", bounds.left);
        movePayload.put("y", bounds.top);
        sendExternalWindowEvent(movePayload);
    }

    /**
     * Called in response to WM_MOVING
     *
     * @param msg WM_MOVING
     * @param wp wParam of Windows message callback
     * @param lp lParam of Windows message callback
     */
    private boolean onMoving(int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onMoving");
        boolean handled = false;
        if (movingPayload == null) {
            this.movingPayload = createBaseWMJSONObject(msg);
        }

        WINDOWRECT movingBounds = new WINDOWRECT(lp);
        movingPayload.put("left", movingBounds.left);
        movingPayload.put("top", movingBounds.top);
        movingPayload.put("right", movingBounds.right);
        movingPayload.put("bottom", movingBounds.bottom);

        PointerInfo a = MouseInfo.getPointerInfo();
        Point b = a.getLocation();
        movingPayload.put("mouseX", b.getX());
        movingPayload.put("mouseY", b.getY());

        if (handlinguserDisabledFrame) {
            logger.debug("handling disabled frame");
            //Retrieve the current bounds
            WinDef.RECT currentBounds = new WinDef.RECT();
            User32.INSTANCE.GetWindowRect(this.hwnd, currentBounds);
            structureToPtr(currentBounds, lp);
            handled = true;
        }
        sendExternalWindowEvent(movingPayload);
        return handled;
    }

    /**
     * Called in response to WM_NCLBUTTONDBLCLK
     *
     * @param msg WM_NCLBUTTONDBLCLK
     * @param wp wParam of Windows message callback
     * @param lp lParam of Windows message callback
     */
    private void onNcDoubleClick(int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onNcDoubleClick");
        if (ncDoubleClickPayload == null) {
            this.ncDoubleClickPayload = createBaseWMJSONObject(msg);
        }
        ncDoubleClickPayload.put("wParam", wp.intValue());
        // getting data from lp throws exception sometimes
        // WinDef.POINT point = new WinDef.POINT(lp);
        // ncDoubleClickPayload.put("x", point.x);
        // ncDoubleClickPayload.put("y", point.y);
        WinDef.POINT mouse = new WinDef.POINT();
        WinMessageHelper.customUser32.GetCursorPos(mouse);
        ncDoubleClickPayload.put("x", mouse.x);
        ncDoubleClickPayload.put("y", mouse.y);
        sendExternalWindowEvent(ncDoubleClickPayload);
    }

    /**
     * Called in response to WM_SETFOCUS
     *
     * @param msg WM_SETFOCUS
     *
     */
    private void onSetFocus(int msg) {
        logger.debug("onSetFocus");
        if (this.focusPayload == null) {
            this.focusPayload = createBaseWMJSONObject(msg);
        }
        sendExternalWindowEvent(focusPayload);
    }

    /**
     * Called in response to WM_SYSCOMMAND
     *
     * @param msg WM_SYSCOMMAND
     *
     */
    private void onSysCommand(int msg, WinDef.WPARAM wp) {
        logger.debug("onSysCommand");
        if (sysCommandPayload == null) {
            this.sysCommandPayload = createBaseWMJSONObject(msg);
        }
        // Only send events we are interested in
        if ((wp.intValue() & subscribedSystemEvents) > 0) {
            sysCommandPayload.put("wParam", wp.intValue());
            sendExternalWindowEvent(sysCommandPayload);
        }
    }

    /**
     * Called in response to WM_WINDOWPOSCHANGED
     *
     * @param msg WM_WINDOWPOSCHANGED
     * @param wp wParam of Windows message callback
     * @param lp lParam of Windows message callback
     */
    private void onWindowPosChanged(int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onWindowPosChanged ");
        if (posChangedPayload == null) {
            this.posChangedPayload = createBaseWMJSONObject(msg);
        }
        WINDOWPOS changeInfo = new WINDOWPOS(lp);
        posChangedPayload.put("hwnd", toHWNDHex(changeInfo.hwnd));
        if (changeInfo.hwndInsertAfter != null) {
            posChangedPayload.put("hwndInsertAfter", toHWNDHex(changeInfo.hwndInsertAfter));
        }
        posChangedPayload.put("x", changeInfo.x);
        posChangedPayload.put("y", changeInfo.y);
        posChangedPayload.put("cx", changeInfo.cx);
        posChangedPayload.put("cy", changeInfo.cy);
        posChangedPayload.put("flags", changeInfo.flags);
        sendExternalWindowEvent(posChangedPayload);
    }

    /**
     * Called in response to WM_WINDOWPOSCHANGING
     *
     * @param msg WM_WINDOWPOSCHANGING
     * @param wp wParam of Windows message callback
     * @param lp lParam of Windows message callback
     */
    private void onWindowPosChanging(int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onWindowPosChanging ");
        if (this.posChangingPayload == null) {
            this.posChangingPayload = createBaseWMJSONObject(msg);
        }
        WINDOWPOS changeInfo = new WINDOWPOS(lp);
        posChangingPayload.put("hwnd", toHWNDHex(changeInfo.hwnd));
        if (changeInfo.hwndInsertAfter != null) {
            posChangingPayload.put("hwndInsertAfter", toHWNDHex(changeInfo.hwndInsertAfter));
        }
        posChangingPayload.put("x", changeInfo.x);
        posChangingPayload.put("y", changeInfo.y);
        posChangingPayload.put("cx", changeInfo.cx);
        posChangingPayload.put("cy", changeInfo.cy);
        posChangingPayload.put("flags", changeInfo.flags);

        // Moving allowed
        boolean isMoving = (changeInfo.flags & SWP_NOMOVE) == 0;
        // Sizing allowed
        boolean isSizing = (changeInfo.flags & SWP_NOSIZE) == 0;
        // Delegate to desktop if this is a move/size and handling a disabled user frame
        if ((isMoving || isSizing)) {
            if (handlinguserDisabledFrame && ignoreNextChange) {
                logger.debug("prevent pos changing");
                changeInfo.flags |= (SWP_NOMOVE | SWP_NOSIZE);
                // Copy the flag change to lParam unmanaged memory.
                // Prevents changes
                structureToPtr(changeInfo, lp);
            }
            ignoreNextChange = false;
        }
        sendExternalWindowEvent(posChangingPayload);
    }

    /**
     * Called in response to WM_SIZING
     *
     * @param msg WM_SIZING
     * @param wp wParam of Windows message callback
     */
    private boolean onSizing(int msg, WinDef.WPARAM wp, Pointer lp) {
        logger.debug("onSizing");
        boolean handled = false;
        if (sizingPayload == null) {
            sizingPayload = createBaseWMJSONObject(msg);
        }
        sizingPayload.put("wParam", wp.intValue());

        WINDOWRECT changeInfo = new WINDOWRECT(lp);
        sizingPayload.put("left", changeInfo.left);
        sizingPayload.put("top", changeInfo.top);
        sizingPayload.put("right", changeInfo.right);
        sizingPayload.put("bottom", changeInfo.bottom);

        WinDef.POINT mouse = new WinDef.POINT();
        WinMessageHelper.customUser32.GetCursorPos(mouse);
        sizingPayload.put("mouseX", mouse.x);
        sizingPayload.put("mouseY", mouse.y);
        if (handlinguserDisabledFrame) {
            //Retrieve the current bounds
            WinDef.RECT currentBounds = new WinDef.RECT();
            User32.INSTANCE.GetWindowRect(this.hwnd, currentBounds);
            // Copy the current bounds struct to lParam unmanaged memory.
            // Prevents changes
            structureToPtr(currentBounds, lp);
            handled = true;
        }
        sendExternalWindowEvent(sizingPayload);
        return handled;
    }

    /**
     * Create base JSONObject for all message types
     * @param msg message type
     * @return JSONObject
     */
    private JSONObject createBaseWMJSONObject(int msg) {
        JSONObject payload = new JSONObject();
        payload.put("uuid", appUuid);
        payload.put("name", name);
        payload.put("type", msg);
        return payload;
    }

    /**
     * Convert HWND to hex
     * @param hwnd HWND
     * @return hex string
     */
    private String toHWNDHex(WinDef.HWND hwnd) {
        return Long.toHexString(Pointer.nativeValue(hwnd.getPointer()));
    }

    private void structureToPtr(Structure struture, Pointer pointer) {
        byte[] buffer = new byte[struture.size()];
        struture.getPointer().read(0, buffer, 0, struture.size());
        pointer.write(0, buffer, 0, struture.size());

    }

    /**
     * DesktopStateListener.onReady
     */
    @Override
    public void onReady() {
        registerExternalWindow(new AckListener() {
            @Override
            public void onSuccess(Ack ack) {
                registered = true;
                installMessageHandlers();
            }
            @Override
            public void onError(Ack ack) {
                DesktopUtils.errorAck(registerListener, ack);
            }
        });
    }


    /**
     * DesktopStateListener.onClose
     *
     */
    @Override
    public void onClose(String error) {

    }

    /**
     * DesktopStateListener.onError
     *
     * @param reason Error message
     */
    @Override
    public void onError(String reason) {

    }

    /**
     * DesktopStateListener.onMessage
     *
     * @param message Message text
     */
    @Override
    public void onMessage(String message) {

    }

    /**
     * DesktopStateListener.onOutgoingMessage
     *
     * @param message Message text
     */
    @Override
    public void onOutgoingMessage(String message) {

    }

    /**
     * Structure of WindowPos
     */
    public static class WINDOWPOS extends Structure {
        public WinDef.HWND hwnd;
        public WinDef.HWND hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public int flags;

        public WINDOWPOS(Pointer memory) {
            super(memory);
            read();
        }

        @Override
        protected List getFieldOrder() {
            String[] aa = {"hwnd", "hwndInsertAfter", "x", "y", "cx", "cy", "flags"};
            return Arrays.asList(aa);
        }
    }

    public static class WINDOWRECT extends Structure {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public WINDOWRECT(Pointer memory) {
            super(memory);
            read();
        }

        protected List getFieldOrder() {
            return Arrays.asList(new String[] { "left", "top", "right", "bottom" });
        }

        public Rectangle toRectangle() {
            return new Rectangle(left, top, right - left, bottom - top);
        }

        public String toString() {
            return "[(" + left + "," + top + ")(" + right + "," + bottom + ")]";
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy