Flash SWF inside CefSharp browser doesn't appear to register double click events

252 Views Asked by At

There is a lot of things to be considered here so I was just generally wondering if anyone has gotten a SWF flash file to fully work inside a CefSharp browser in WPF more specifically the double-click events for the flash SWF.

Right now everything appears to work for me except the double-click events. These appear to work fine in Chrome but not in CefSharp. I have tried hooking up to a few different versions of pepflash.dll but no dice.

Versions tried:

  • pepflashplayer32_30_0_0_113.dll
  • pepflashplayer32_29_0_0_171.dll
1

There are 1 best solutions below

1
Organis On

Something like that, I guess. I didn't check it so please forgive me for any typos. But in theory that should do the trick. As I said above the only other thing to do is to replace MouseEvent.DOUBLE_CLICK with the DoubleClick.DOUBLE_CLICK everywhere you listen to it and it will magically work. Probably.

package
{
    import flash.display.Stage;
    import flash.display.DisplayObject;

    import flash.events.MouseEvent;

    public class DoubleClick
    {
        // Don't occasionally set it to actual MouseEvent.DOUBLE_CLICK
        // because you'll get twice as many events on the platforms
        // where original MouseEvent.DOUBLE_CLICK actually works.
        static public const DOUBLE_CLICK:String = "custom.double";

        // How far the Mouse can click for the second time so that
        // it will still count as double click (in pixels).
        static public const distanceTreshold:int = 5;

        // How fast the second click has to happen for these two clicks
        // to still be considered a double click (in milliseconds).
        static public const timeoutTreshold:int = 500;

        static private var stage:Stage;

        // Call it to initialize the custom double click engine.
        static public function attachTo(target:Stage):void
        {
            stage = target;
            stage.addEventListener(MouseEvent.CLICK, onClick);

            Click.stage = stage;
        }

        static private var lastClick:Click;

        static private function onClick(e:MouseEvent):void
        {
            // Sanity check. If the event target is not attached to
            // the display list then it is pointless to proceed.
            if (!e.target.stage)
            {
                if (lastClick)
                {
                    lastClick.destroy();
                    lastClick = null;
                }

                return;
            }

            var aClick:Click = new Click(e.target as DisplayObject);

            if (!lastClick)
            {
                // If there was no previous clicks then just remember this one.
                lastClick = aClick;
            }
            else if (checkDouble(aClick))
            {
                // Yay! Double click seems to happen!
                dispatchDouble(aClick, e);
            }
            else
            {
                // If these two clicks don't qualify as double, just
                // forget the previous one and remember the new one.
                lastClick.destroy();
                lastClick = aClick;
            }
        }

        // Return true if the second click was fast enough and close enough.
        static private function checkDouble(click:Click):Boolean
        {
            if (Math.abs(click.x - lastClick.x) > distanceTreshold) return false;
            if (Math.abs(click.y - lastClick.y) > distanceTreshold) return false;

            if (click.time - lastClick.time > timeoutTreshold) return false;

            return true;
        }

        static private function dispatchDouble(click:Click, e:MouseEvent):void
        {
            // Get the bottommost display object as a
            // starting point for the double click event,
            // because between the first and second clicks
            // some other objects could appear or disappear
            // under the mouse, so the second click might not
            // actually be the second for the designated target.
            var aTarget:DisplayObject = lastClick.deepestCommon(click);

            // Compose the event.
            var anEvent:MouseEvent = new MouseEvent
            (
                DOUBLE_CLICK, // Event.type
                true,         // Event.bubbles
                false,        // Event.cancelable

                e.localX,     // Copies of original event properties.
                e.localY,
                e.relatedObject,
                e.ctrlKey,
                e.altKey,
                e.shiftKey,
                e.buttonDown,
                e.delta,
                e.commandKey,
                e.controlKey,

                2            // MouseEvent.clickCount
            );

            // Clean up things.
            lastClick.destroy();
            lastClick = null;

            click.destroy();

            // Emulate the double click event.
            aTarget.dispatchEvent(anEvent);
        }
    }
}

import flash.utils.getTimer;

import flash.display.Stage;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;

// This is basically a data structure to keep
// basic information about a single click.
internal class Click
{
    static public var stage:Stage;

    public var x:int;
    public var y:int;

    public var time:int;
    public var path:Array;

    public function Click(target:DisplayObject)
    {
        x = stage.mouseX;
        y = stage.mouseY;

        time = getTimer();
        path = [target];

        // Unwind the full path from stage to the target.
        var aParent:DisplayObjectContainer = target.parent;

        while (aParent)
        {
            path.unshift(aParent);
            aParent = aParent.parent;
        }

        // At this point the path should contain something like
        // [stage, .. , .. , .. , target.parent, target]
    }

    // Release the path Array.
    public function destroy():void
    {
        if (path)
        {
            path.length = 0;
            path = null;
        }
    }

    // Returns the deepest DisplayObject that
    // both click passed through along their ways.
    public function deepestCommon(click:Click):DisplayObject
    {
        // At very least they have stage as the common point.
        var result:DisplayObject = path[0];

        for (var i:int = 1; i < Math.min(path.length, click.path.length); i++)
        {
            if (path[i] != click.path[i]) break;

            result = path[i];
        }

        return result;
    }
}