Re: [GTK] Suggestion: make panels graggable



On Mon, Oct 09, 2006 at 08:31:56PM -0600, Michael Torrie wrote:

> There is one major problem with getting GTK to do this anyways.
> That is that only widgets that receive events actually have X
> windows capable of receiving mouse events.  So to do this at the GTK
> level would involve some re-engineering of how GTK uses GDK windows
> (which wrap X windows).  It's just not worth it.  Also no other
> widget set does this either (not even normal Aqua windows).

On the contrary, I think that actually makes it much easier to
implement. If an un-interesting widget doesn't have its own X window
then the button motion events will be sent to the window underneath
the widget. This way you'd only have to listen for events on the
underlying window. Any events that shouldn't cause the window to be
moved would be conveniently processed by the covering widgets instead.

I've attached some code to demonstrate. You can move the window by
dragging the label or the gaps, but the buttons still work because
they have their own X windows. I'm sure it would be very easy to make
a hacked version of GTK that implements this within GtkWindow so that
it would work for all GTK applications.

- Neil
#include <gtk/gtk.h>

static gboolean moving = FALSE;
static gint base_pointer_x, base_pointer_y;
static gint base_window_x, base_window_y;

static gboolean
on_button_press (GtkWidget *window, GdkEventButton *event, gpointer user_data)
{
  moving = TRUE;
  base_pointer_x = event->x_root;
  base_pointer_y = event->y_root;
  gdk_window_get_position (window->window, &base_window_x, &base_window_y);

  return TRUE;
}

static gboolean
on_button_release (GtkWidget *window, GdkEventButton *event, gpointer user_data)
{
  moving = FALSE;

  return TRUE;
}

static gboolean
on_motion_notify (GtkWidget *window, GdkEventMotion *event, gpointer user_data)
{
  if (moving)
    gdk_window_move (window->window,
		     base_window_x + event->x_root - base_pointer_x,
		     base_window_y + event->y_root - base_pointer_y);
  
  return TRUE;
}

int
main (int argc, char **argv)
{
  GtkWidget *window, *button, *label, *box;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  g_signal_connect (G_OBJECT (window), "button-press-event",
		    G_CALLBACK (on_button_press), NULL);
  g_signal_connect (G_OBJECT (window), "button-release-event",
		    G_CALLBACK (on_button_release), NULL);
  g_signal_connect (G_OBJECT (window), "motion-notify-event",
		    G_CALLBACK (on_motion_notify), NULL);

  box = gtk_vbox_new (FALSE, 0);

  button = gtk_button_new_with_label ("A button");
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (box), button, TRUE, FALSE, 0);

  label = gtk_label_new ("A label");
  gtk_widget_show (label);
  gtk_box_pack_start (GTK_BOX (box), label, TRUE, FALSE, 0);

  button = gtk_button_new_with_label ("Another button");
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (box), button, TRUE, FALSE, 0);

  gtk_widget_show (box);
  gtk_container_add (GTK_CONTAINER (window), box);
  
  gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
  gtk_widget_show (window);

  gdk_window_set_events (window->window, gdk_window_get_events (window->window)
			 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
			 | GDK_BUTTON_MOTION_MASK);

  gtk_main ();

  return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]