Exemple #1
0
        /// <summary>
        /// Returns true if window matches.
        /// </summary>
        /// <param name="thc">This func uses the window handle (gets on demand) and WFCache.</param>
        internal bool Match(TriggerHookContext thc)
        {
            bool yes = false;
            var  w   = thc.Window;

            if (!w.Is0)
            {
                switch (o)
                {
                case AWnd.Finder f:
                    yes = f.IsMatch(w, thc);
                    break;

                case AWnd.Finder[] a:
                    foreach (var v in a)
                    {
                        if (yes = v.IsMatch(w, thc))
                        {
                            break;
                        }
                    }
                    break;
                }
            }
            return(yes ^ not);
        }
Exemple #2
0
        internal bool MatchScopeWindowAndFunc(TriggerHookContext thc)
        {
            try {
                for (int i = 0; i < 3; i++)
                {
                    if (i == 1)
                    {
                        if (scope != null)
                        {
                            thc.PerfStart();
                            bool ok = scope.Match(thc);
                            thc.PerfEnd(false, ref scope.perfTime);
                            if (!ok)
                            {
                                return(false);
                            }
                        }
                    }
                    else
                    {
                        var af = i == 0 ? _funcBefore : _funcAfter;
                        if (af != null)
                        {
                            foreach (var v in af)
                            {
                                thc.PerfStart();
                                bool ok = v.f(thc.args);
                                thc.PerfEnd(true, ref v.perfTime);
                                if (!ok)
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex) {
                AOutput.Write(ex);
                return(false);
            }
            return(true);

            //never mind: when same scope used several times (probably with different functions),
            //	should compare it once, and don't call 'before' functions again if did not match. Rare.
        }
Exemple #3
0
        internal void HookProcEdgeMove(EdgeMoveDetector_.Result d, TriggerHookContext thc)         //d not in
        {
            ESubtype subtype;
            byte     data, dataAnyPart;

            if (d.edgeEvent != 0)
            {
                subtype = ESubtype.Edge;
                data    = (byte)d.edgeEvent; dataAnyPart = (byte)d.edgeEventAnyPart;
            }
            else
            {
                subtype = ESubtype.Move;
                data    = (byte)d.moveEvent; dataAnyPart = (byte)d.moveEventAnyPart;
            }

            _HookProc2(thc, true, subtype, HookData.MouseEvent.Move, d.pt, data, dataAnyPart);
        }
Exemple #4
0
        /// <summary>
        /// Makes triggers alive.
        /// </summary>
        /// <remarks>
        /// This function monitors hotkeys, activated windows and other events. When an event matches an added trigger, launches the thrigger's action, which runs in other thread by default.
        /// Does not return immediately. Runs until this process is terminated or <see cref="Stop"/> called.
        /// </remarks>
        /// <example>See <see cref="ActionTriggers"/>.</example>
        /// <exception cref="InvalidOperationException">Already running.</exception>
        /// <exception cref="AuException">Something failed.</exception>
        public unsafe void Run()
        {
            //ADebug.PrintLoadedAssemblies(true, true, true);

            ThrowIfRunning_();

            //bool haveTriggers = false;
            HooksThread.UsedEvents hookEvents = 0;
            _windowTriggers = null;
            for (int i = 0; i < _t.Length; i++)
            {
                var t = _t[i];
                if (t == null || !t.HasTriggers)
                {
                    continue;
                }
                //haveTriggers = true;
                switch ((TriggerType)i)
                {
                case TriggerType.Hotkey: hookEvents |= HooksThread.UsedEvents.Keyboard; break;

                case TriggerType.Autotext: hookEvents |= HooksThread.UsedEvents.Keyboard | HooksThread.UsedEvents.Mouse; break;

                case TriggerType.Mouse: hookEvents |= (t as MouseTriggers).UsedHookEvents_; break;

                case TriggerType.Window: _windowTriggers = t as WindowTriggers; break;
                }
            }
            //AOutput.Write(haveTriggers, (uint)llHooks);
            //if(!haveTriggers) return; //no. The message loop may be used for toolbars etc.

            if (!s_wasRun)
            {
                s_wasRun = true;
                AWnd.More.RegisterWindowClass(c_cn);
            }
            _wMsg             = AWnd.More.CreateMessageOnlyWindow(_WndProc, c_cn);
            _mainThreadId     = AThread.NativeId;
            _winTimerPeriod   = 0;
            _winTimerLastTime = 0;

            if (hookEvents != 0)
            {
                //prevent big delay later on first LL hook event while hook proc waits
                if (!s_wasKM)
                {
                    s_wasKM = true;
                    ThreadPool.QueueUserWorkItem(_ => {
                        try {
                            //using var p1 = APerf.Create();
                            new AWnd.Finder("*a").IsMatch(AWnd.GetWnd.Root);               //if used window scopes etc
                            _ = AHookWin.LowLevelHooksTimeout;                             //slow JIT of registry functions
                            Util.AJit.Compile(typeof(ActionTriggers), nameof(_WndProc), nameof(_KeyMouseEvent));
                            Util.AJit.Compile(typeof(TriggerHookContext), nameof(TriggerHookContext.InitContext), nameof(TriggerHookContext.PerfEnd), nameof(TriggerHookContext.PerfWarn));
                            Util.AJit.Compile(typeof(ActionTrigger), nameof(ActionTrigger.MatchScopeWindowAndFunc));
                            Util.AJit.Compile(typeof(HotkeyTriggers), nameof(HotkeyTriggers.HookProc));
                            AutotextTriggers.JitCompile();
                            MouseTriggers.JitCompile();
                        }
                        catch (Exception ex) { ADebug.Print(ex); }
                    });
                }

                _thc = new TriggerHookContext(this);

                _ht = new HooksThread(hookEvents, _wMsg);
            }

            try {
                _evStop = Api.CreateEvent(false);
                _StartStopAll(true);
                IntPtr h = _evStop;
                _Wait(&h, 1);
            }
            finally {
                if (hookEvents != 0)
                {
                    _ht.Dispose(); _ht = null;
                }
                Api.DestroyWindow(_wMsg); _wMsg = default;
                Stopping?.Invoke(this, EventArgs.Empty);
                _evStop.Dispose();
                _StartStopAll(false);
                _mainThreadId = 0;
                _threads?.Dispose(); _threads = null;
            }

            void _StartStopAll(bool start)
            {
                foreach (var t in _t)
                {
                    if (t?.HasTriggers ?? false)
                    {
                        t.StartStop(start);
                    }
                }
            }
        }
Exemple #5
0
        bool _HookProc2(TriggerHookContext thc, bool isEdgeMove, ESubtype subtype, HookData.MouseEvent mEvent, POINT pt, byte data, byte dataAnyPart)
        {
            var mod = TrigUtil.GetModLR(out var modL, out var modR) | _eatMod;
            MouseTriggerArgs args = null;

g1:
            if (_d.TryGetValue(_DictKey(subtype, data), out var v))
            {
                if (!isEdgeMove)
                {
                    thc.UseWndFromPoint(pt);
                }
                for (; v != null; v = v.next)
                {
                    var x = v as MouseTrigger;
                    if ((mod & x.modMask) != x.modMasked)
                    {
                        continue;
                    }

                    switch (x.flags & (TMFlags.LeftMod | TMFlags.RightMod))
                    {
                    case TMFlags.LeftMod: if (modL != mod)
                        {
                            continue;
                        }
                        break;

                    case TMFlags.RightMod: if (modR != mod)
                        {
                            continue;
                        }
                        break;
                    }

                    if (isEdgeMove && x.screenIndex != TMScreen.Any)
                    {
                        var screen = x.screenIndex == TMScreen.OfActiveWindow
                                                        ? AScreen.Of(AWnd.Active)
                                                        : AScreen.Index((int)x.screenIndex);
                        if (!screen.Bounds.Contains(pt))
                        {
                            continue;
                        }
                    }

                    if (v.DisabledThisOrAll)
                    {
                        continue;
                    }

                    if (args == null)
                    {
                        thc.args = args = new MouseTriggerArgs(x, thc.Window, mod);                                  //may need for scope callbacks too
                    }
                    else
                    {
                        args.Trigger = x;
                    }

                    if (!x.MatchScopeWindowAndFunc(thc))
                    {
                        continue;
                    }

                    if (x.action == null)
                    {
                        _ResetUp();
                    }
                    else if (0 != (x.flags & TMFlags.ButtonModUp) && (mod != 0 || subtype == ESubtype.Click))
                    {
                        _upTrigger = x;
                        _upArgs    = args;
                        _upEvent   = subtype == ESubtype.Click ? mEvent : 0;
                        _upMod     = mod;
                    }
                    else
                    {
                        thc.trigger = x;
                        _ResetUp();
                    }

                    _eatMod = mod;
                    if (mod != 0)
                    {
                        _SetTempKeybHook();
                        if (thc.trigger != null)
                        {
                            thc.muteMod = TriggerActionThreads.c_modRelease;
                        }
                        else
                        {
                            ThreadPool.QueueUserWorkItem(_ => AKeys.Internal_.ReleaseModAndDisableModMenu());
                        }
                    }

                    //AOutput.Write(mEvent, pt, mod);
                    if (isEdgeMove || 0 != (x.flags & TMFlags.ShareEvent))
                    {
                        return(false);
                    }
                    if (subtype == ESubtype.Click)
                    {
                        _eatUp = mEvent;
                    }
                    return(true);
                }
            }
            if (dataAnyPart != 0)
            {
                data        = dataAnyPart;
                dataAnyPart = 0;
                goto g1;
            }
            return(false);
        }
Exemple #6
0
        internal bool HookProcClickWheel(HookData.Mouse k, TriggerHookContext thc)
        {
            //AOutput.Write(k.Event, k.pt);
            Debug.Assert(!k.IsInjectedByAu);             //server must ignore

            ESubtype subtype;
            byte     data;

            if (k.IsButton)
            {
                if (k.IsButtonUp)
                {
                    if (k.Event == _upEvent)
                    {
                        _upEvent = 0;
                        if (_upMod == 0 && _upTrigger != null)
                        {
                            thc.args    = _upArgs;
                            thc.trigger = _upTrigger;
                            _ResetUp();
                        }
                    }
                    if (k.Event == _eatUp)
                    {
                        _eatUp = 0;
                        return(true);
                        //To be safer, could return false if AMouse.IsPressed(k.Button), but then can interfere with the trigger action.
                    }
                    return(false);
                    //CONSIDER: _upTimeout.
                }
                if (k.Event == _eatUp)
                {
                    _eatUp = 0;
                }

                subtype = ESubtype.Click;
                TMClick b;
                switch (k.Event)
                {
                case HookData.MouseEvent.LeftButton: b = TMClick.Left; break;

                case HookData.MouseEvent.RightButton: b = TMClick.Right; break;

                case HookData.MouseEvent.MiddleButton: b = TMClick.Middle; break;

                case HookData.MouseEvent.X1Button: b = TMClick.X1; break;

                default: b = TMClick.X2; break;
                }
                data = (byte)b;
            }
            else                 //wheel
            {
                subtype = ESubtype.Wheel;
                TMWheel b;
                switch (k.Event)
                {
                case HookData.MouseEvent.WheelForward: b = TMWheel.Forward; break;

                case HookData.MouseEvent.WheelBackward: b = TMWheel.Backward; break;

                case HookData.MouseEvent.WheelLeft: b = TMWheel.Left; break;

                default: b = TMWheel.Right; break;
                }
                data = (byte)b;
            }

            return(_HookProc2(thc, false, subtype, k.Event, k.pt, data, 0));
        }
Exemple #7
0
 void _UpTriggered(TriggerHookContext thc)
 {
     thc.args    = _upArgs;
     thc.trigger = _upTrigger;
     _UpClear();
 }
Exemple #8
0
        internal bool HookProc(HookData.Keyboard k, TriggerHookContext thc)
        {
            //AOutput.Write(k.vkCode, !k.IsUp);
            Debug.Assert(!k.IsInjectedByAu);             //server must ignore

            KKey key = k.vkCode;
            KMod mod = thc.Mod;
            bool up  = k.IsUp;

            if (!up)
            {
                _UpClear();
            }

            if (thc.ModThis != 0)
            {
                if (_upTrigger != null && mod == 0 && _upKey == 0)
                {
                    _UpTriggered(thc);
                }
            }
            else if (up)
            {
                if (key == _upKey)
                {
                    _upKey = 0;
                    if (_upTrigger != null && mod == 0)
                    {
                        _UpTriggered(thc);
                    }
                }
                if (key == _eatUp)
                {
                    _eatUp = 0;
                    return(true);
                    //To be safer, could return false if AKeys.IsPressed(_eatUp), but then can interfere with the trigger action.
                }
                //CONSIDER: _upTimeout.
            }
            else
            {
                //if(key == _eatUp) _eatUp = 0;
                _eatUp = 0;

                if (_d.TryGetValue((int)key, out var v))
                {
                    HotkeyTriggerArgs args = null;
                    for (; v != null; v = v.next)
                    {
                        var x = v as HotkeyTrigger;
                        if ((mod & x.modMask) != x.modMasked)
                        {
                            continue;
                        }

                        switch (x.flags & (TKFlags.LeftMod | TKFlags.RightMod))
                        {
                        case TKFlags.LeftMod: if (thc.ModL != mod)
                            {
                                continue;
                            }
                            break;

                        case TKFlags.RightMod: if (thc.ModR != mod)
                            {
                                continue;
                            }
                            break;
                        }

                        if (v.DisabledThisOrAll)
                        {
                            continue;
                        }

                        if (args == null)
                        {
                            thc.args = args = new HotkeyTriggerArgs(x, thc.Window, key, mod);                                      //may need for scope callbacks too
                        }
                        else
                        {
                            args.Trigger = x;
                        }

                        if (!x.MatchScopeWindowAndFunc(thc))
                        {
                            continue;
                        }

                        if (x.action != null)
                        {
                            if (0 != (x.flags & TKFlags.KeyModUp))
                            {
                                _upTrigger = x;
                                _upArgs    = args;
                                _upKey     = key;
                            }
                            else
                            {
                                thc.trigger = x;
                            }
                        }

                        //AOutput.Write(key, mod);
                        if (0 != (x.flags & TKFlags.ShareEvent))
                        {
                            return(false);
                        }

                        if (thc.trigger == null)                          //KeyModUp or action==null
                        {
                            if (mod == KMod.Alt || mod == KMod.Win || mod == (KMod.Alt | KMod.Win))
                            {
                                //AOutput.Write("need Ctrl");
                                ThreadPool.QueueUserWorkItem(o => AKeys.Internal_.SendKey(KKey.Ctrl));                                 //disable Alt/Win menu
                            }
                        }
                        else if (mod != 0)
                        {
                            if (0 == (x.flags & TKFlags.NoModOff))
                            {
                                thc.muteMod = TriggerActionThreads.c_modRelease;
                            }
                            else if (mod == KMod.Alt || mod == KMod.Win || mod == (KMod.Alt | KMod.Win))
                            {
                                thc.muteMod = TriggerActionThreads.c_modCtrl;
                            }
                        }

                        _eatUp = key;
                        return(true);
                    }
                }
            }
            return(false);
        }