예제 #1
0
        protected virtual void OnNcMouseUp(NSEvent e)
        {
            var p      = driver.NativeToMonoScreen(Frame.Location);
            var lParam = (IntPtr)((p.Y << 16) | (int)(short)p.X);
            var wParam = (IntPtr)(e.ModifierFlags.ToWParam() | e.ButtonNumberToWParam());

            Application.SendMessage(ContentView.Handle, Msg.WM_NCLBUTTONUP.AdjustForButton(e), wParam, lParam);
        }
예제 #2
0
        internal void TranslateMouseUp(NSEvent e)
        {
            var msg = TranslateMouseCore(e, out bool client, MouseTarget());

            msg.message           = (client ? Msg.WM_LBUTTONUP : Msg.WM_NCLBUTTONUP) + MsgOffset4Button(e);
            msg.wParam            = (IntPtr)(e.ModifierFlags.ToWParam() | e.ButtonNumberToWParam());
            LastMouseDownMsg.hwnd = IntPtr.Zero;
            Application.SendMessage(ref msg);
        }
예제 #3
0
        internal void TranslateMouseDown(NSEvent e)
        {
            var msg = TranslateMouseCore(e, out bool client);

            msg.wParam = (IntPtr)(e.ModifiersToWParam() | e.ButtonNumberToWParam());
            // FIXME: Should be elsewhere
            if (e.ClickCount > 1)
            {
                msg.message = (client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK) + MsgOffset4Button(e);
            }
            else
            {
                msg.message      = (client ? Msg.WM_LBUTTONDOWN : Msg.WM_NCLBUTTONDOWN) + MsgOffset4Button(e);
                LastMouseDownMsg = msg;
            }
            Application.SendMessage(ref msg);
        }
예제 #4
0
        internal void TranslateMouseDown(NSEvent e)
        {
            var msg = TranslateMouseCore(e, out bool client);

            msg.wParam = (IntPtr)(e.ModifiersToWParam() | e.ButtonNumberToWParam());

            if (e.ClickCount > 1 && (e.ClickCount & 1) == 0 && prevMouseDown?.Type == e.Type)
            {
                msg.message = (client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK) + MsgOffset4Button(e);
            }
            else
            {
                msg.message      = (client ? Msg.WM_LBUTTONDOWN : Msg.WM_NCLBUTTONDOWN) + MsgOffset4Button(e);
                LastMouseDownMsg = msg;
            }

            prevMouseDown = e;
            Application.SendMessage(ref msg);
        }
예제 #5
0
        void TranslateMouseEvent(NSEvent e)
        {
            var  clientView = view as IClientView;
            bool client     = clientView == null;

            var nspoint        = view.ConvertPointFromView(e.LocationInWindow, null);
            var localMonoPoint = driver.NativeToMonoFramed(nspoint, view);

            if ((clientView != null && clientView.ClientBounds.ToRectangle().Contains(localMonoPoint)) ||
                driver.Grab.Hwnd != IntPtr.Zero)
            {
                client            = true;
                localMonoPoint.X -= (int)clientView.ClientBounds.X;
                localMonoPoint.Y -= (int)clientView.ClientBounds.Y;
            }

            MSG msg = new MSG();

            msg.hwnd   = view.Handle;
            msg.lParam = (IntPtr)(localMonoPoint.Y << 16 | (localMonoPoint.X & 0xFFFF));
            if (e.Window == null)
            {
                msg.pt = driver.NativeToMonoScreen(NSEvent.CurrentMouseLocation).ToPOINT();
            }
            else
            {
                msg.pt = driver.NativeToMonoScreen(e.Window.ConvertBaseToScreen(e.LocationInWindow)).ToPOINT();
            }
            msg.refobject = view;

            switch (e.Type)
            {
            case NSEventType.LeftMouseDown:
            case NSEventType.RightMouseDown:
            case NSEventType.OtherMouseDown:
                // FIXME: Should be elsewhere
                if (e.ClickCount > 1)
                {
                    msg.message = (client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK) + MsgOffset4Button(e);
                }
                else
                {
                    msg.message = (client ? Msg.WM_LBUTTONDOWN : Msg.WM_NCLBUTTONDOWN) + MsgOffset4Button(e);
                }
                msg.wParam = (IntPtr)(e.ModifiersToWParam() | e.ButtonNumberToWParam());
                break;

            case NSEventType.LeftMouseUp:
            case NSEventType.RightMouseUp:
            case NSEventType.OtherMouseUp:
                msg.message = (client ? Msg.WM_LBUTTONUP : Msg.WM_NCLBUTTONUP) + MsgOffset4Button(e);
                msg.wParam  = (IntPtr)(e.ModifierFlags.ToWParam() | e.ButtonNumberToWParam());
                break;

            case NSEventType.MouseMoved:
                msg.wParam  = (IntPtr)(e.ModifierFlags.ToWParam());
                msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE);
                break;

            case NSEventType.LeftMouseDragged:
                msg.wParam  = (IntPtr)(e.ModifierFlags.ToWParam() | (uint)MsgButtons.MK_LBUTTON);
                msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE);
                break;

            case NSEventType.RightMouseDragged:
                msg.wParam  = (IntPtr)(e.ModifierFlags.ToWParam() | (uint)MsgButtons.MK_RBUTTON);
                msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE);
                break;

            case NSEventType.OtherMouseDragged:
                msg.wParam  = (IntPtr)(e.ModifierFlags.ToWParam() | (uint)MsgButtons.MK_MBUTTON);
                msg.message = (client ? Msg.WM_MOUSEMOVE : Msg.WM_NCMOUSEMOVE);
                break;

            case NSEventType.ScrollWheel:
                bool horizontal = e.ScrollingDeltaY == 0 && e.ScrollingDeltaX != 0;
                int  delta      = ScaleAndQuantizeDelta((float)(horizontal ? e.ScrollingDeltaX : e.ScrollingDeltaY), e.HasPreciseScrollingDeltas);
                if (delta == 0)
                {
                    return;
                }

                if (e.Phase == NSEventPhase.None && e.MomentumPhase == NSEventPhase.None || e.Phase == NSEventPhase.Changed || e.MomentumPhase == NSEventPhase.Changed)
                {
                    msg.message = Msg.WM_MOUSEWHEEL;
                    msg.wParam  = (IntPtr)(e.ModifiersToWParam());
                    msg.wParam  = (IntPtr)(((int)msg.wParam & 0xFFFF) | (delta << 16));
                    msg.lParam  = (IntPtr)((msg.pt.x & 0xFFFF) | (msg.pt.y << 16));
                    break;
                }
                return;

            case NSEventType.MouseEntered:
            case NSEventType.MouseExited:
                // We use overlapping track rectanges on every control, so the Entered/Exited events
                // are sent not only to the top-level visible view, but also to its superviews.
                // This has to be converted to the the model where only the top-level control receives
                // the messages.
                //
                // The conversion is by performing the hit test. Note that e.LocationInWindow is NOT
                // updated by the time the tracking events are received and thus e.Window.
                // MouseLocationOutsideOfEventStream has to be used instead.
                //
                // The Exited event has to be handled the same way as the entered event to cover the
                // following scenario:
                //  ___________________________
                // | Panel                     |
                // |  ______________           |
                // | |    Button    |          |
                //
                // When you move the mouse over the Button you will receive the Entered event for
                // it. At the same time the Panel already had Entered called for its own tracking area.
                // Now moving the mouse away from the Button into the Panel area will cause an
                // Exited event on the Button's tracking rectangle, but it will NOT generate any
                // Entered event. In the System.Windows.Forms world we want to receive WM_MOUSELEAVE
                // on the Button and WM_MOUSE_ENTERED on the Panel.
                //
                // Further reading:
                // https://stackoverflow.com/questions/9986267/mouse-enter-exit-events-on-partially-hidden-nsviews

                var newMouseView       = e.Window?.ContentView.HitTest(e.LocationInWindow) ?? e.Window?.ContentView.Superview?.HitTest(e.LocationInWindow);
                var newMouseViewHandle = newMouseView is MonoView ? newMouseView.Handle : IntPtr.Zero;

#if DEBUG_MOUSE_ENTER_EXIT
                {
                    // DEBUG
                    Console.Write(e.Type == NSEventType.MouseEntered ? "ENTER " : "EXIT ");
                    if (newMouseView != null)
                    {
                        Console.Write("NEW: " + DebugUtility.ControlInfo(newMouseView));
                    }
                    else
                    {
                        Console.Write("NO NEW");
                    }
                }
#endif

                if (newMouseViewHandle == driver.LastEnteredHwnd)
                {
                    return;
                }

                // Keep track of the last entered window during grab, but don't send messages. The
                // messages are sent by XplatUICocoa.GrabWindow and XplatUICocoa.UngrabWindow when
                // the grabbing state is entered/exited.
                if (driver.Grab.Hwnd != IntPtr.Zero)
                {
                    driver.LastEnteredHwnd = newMouseViewHandle;
                    return;
                }

                msg.wParam = (IntPtr)(e.ModifiersToWParam() | Mac.Extensions.ButtonMaskToWParam(NSEvent.CurrentPressedMouseButtons));
                // First notify the old window that mouse left it
                if (driver.LastEnteredHwnd != IntPtr.Zero)
                {
                    msg.hwnd               = driver.LastEnteredHwnd;
                    msg.message            = Msg.WM_MOUSELEAVE;
                    driver.LastEnteredHwnd = IntPtr.Zero;
                    Application.SendMessage(ref msg);
                }
                // And then notify the new window that mouse entered it
                if (newMouseViewHandle != IntPtr.Zero)
                {
                    msg.hwnd               = newMouseViewHandle;
                    msg.message            = Msg.WM_MOUSE_ENTER;
                    driver.LastEnteredHwnd = newMouseViewHandle;
                    Application.SendMessage(ref msg);
                }
                return;

            //case NSEventType.TabletPoint:
            //case NSEventType.TabletProximity:
            default:
                return;
            }

            Application.SendMessage(ref msg);
        }