Hello All-

I'm having some trouble with dragging a floating, decoration-less
window around the screen. I have written a small (tried to keep it
under 100 lines but failed) app that demonstrates the problem.

The main window simply contains a button. When the user clicks on the
button, the button reparents itself to a floating window and the user
can then drag the window around the screen. The problem is that, after
the user clicks the button but BEFORE they let go of the mouse button,
the dragging doesn't seem to behave quite right. If the mouse is moved
slowly enough, it works fine, but at a certain speed the floating
window will stop tracking it. The strange thing is that if the user
lets go and clicks on the button again, the dragging will work
perfectly, no matter what the speed. It basically just doesn't seem to
be receiving the mouse events properly after the reparent.

I tried looking through the C source for HandleBox, but couldn't find
what makes it not behave this way. My source code is attached. Any
help would be greatly appreciated.

Thanks.

-Andy
using System;

namespace FloatDraggingTest
{
        /// <summary>
        /// Main window.
        /// </summary>
        class MainWindow : Gtk.Window
        {
                /// <summary>
                /// Application entry point.
                /// </summary>
                public static void Main(string[] args)
                {
                        Gtk.Application.Init();
                        MainWindow win = new MainWindow();
                        win.ShowAll();
                        Gtk.Application.Run();
                }


                /// <summary>
                /// Main window default constructor.
                /// </summary>
                public MainWindow()
                        : base(Gtk.WindowType.Toplevel)
                {
                        floatWidget = new FloatWidget("Click Me");
                        Add(floatWidget);

                        DeleteEvent += OnDeleteEvent;
                }

                /// <summary>
                /// Called when the window is deleted, stops the application.
                /// </summary>
                /// <param name="o"></param>
                /// <param name="args"></param>
                void OnDeleteEvent(object o, Gtk.DeleteEventArgs args)
                {
                        Gtk.Application.Quit();
                }


                private FloatWidget floatWidget;

        }


        /// <summary>
        /// A widget that you can grab and drag around.
        /// </summary>
        class FloatWidget : Gtk.Button
        {

                /// <summary>
                /// Default constructor.
                /// </summary>
                /// <param name="text"> Text to display on the widget.</param>
                public FloatWidget(string text)
                        : base(new Gtk.Label(text))
                {
                        // create the float window
                        floatWindow = new Gtk.Window(Gtk.WindowType.Toplevel);
                        floatWindow.Decorated = false;

                        AddEvents((int)Gdk.EventMask.AllEventsMask); // add all 
events
                }

                private Gtk.Window floatWindow;

                private bool grabbed = false;

                private Gdk.Point grabPoint;

                protected override bool OnButtonPressEvent(Gdk.EventButton evnt)
                {
                        grabbed = true;
                        int grabX, grabY;
                        GetPointer(out grabX, out grabY);
                        grabPoint = new Gdk.Point(grabX, grabY);
                        return true;
                }

                protected override bool OnButtonReleaseEvent(Gdk.EventButton 
evnt)
                {
                        grabbed = false;
                        return true;
                }

                protected override bool OnMotionNotifyEvent(Gdk.EventMotion 
evnt)
                {
                        if (grabbed) // the window has been grabbed
                        {
                                if (Parent != floatWindow) // it isn't floating 
yet, float it
                                {
                                        Reparent(floatWindow);
                                        floatWindow.ShowAll();
                                }
                                MoveToCursor();
                        }

                        return true;
                }

                protected override bool OnLeaveNotifyEvent(Gdk.EventCrossing 
evnt)
                {
                        if (grabbed)
                                MoveToCursor();
                        return true;
                }

                /// <summary>
                /// Moves the floating window to the cursor.
                /// </summary>
                protected void MoveToCursor()
                {
                        int cursorX, cursorY, windowX, windowY;
                        GetPointer(out cursorX, out cursorY);
                        GdkWindow.GetPosition(out windowX, out windowY);
                        floatWindow.GdkWindow.Move(windowX + cursorX - 
grabPoint.X, windowY + cursorY - grabPoint.Y);
                        Display.Sync();
                }

        }


}
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list

Reply via email to