Allow windows to be dragged by clicking on empty areas
Allow windows to be dragged by clicking on empty areas in menubars and toolbars. This is under theme control, via the GtkWidget::window-dragging style property. The idea is that it makes sense to turn this on if a theme makes the window frame and the menubar/toolbar appear visually contiguous. The main patch was written by Cody Russell, with a contribution by Ayan George. See bug 611313.
This commit is contained in:
@ -596,18 +596,45 @@ gtk_menu_shell_button_press (GtkWidget *widget,
|
|||||||
|
|
||||||
if (!menu_shell->active || !menu_shell->button)
|
if (!menu_shell->active || !menu_shell->button)
|
||||||
{
|
{
|
||||||
_gtk_menu_shell_activate (menu_shell);
|
gboolean initially_active = menu_shell->active;
|
||||||
|
|
||||||
menu_shell->button = event->button;
|
menu_shell->button = event->button;
|
||||||
|
|
||||||
if (menu_item && _gtk_menu_item_is_selectable (menu_item) &&
|
if (menu_item)
|
||||||
menu_item->parent == widget &&
|
|
||||||
menu_item != menu_shell->active_menu_item)
|
|
||||||
{
|
{
|
||||||
if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement == GTK_TOP_BOTTOM)
|
if (_gtk_menu_item_is_selectable (menu_item) &&
|
||||||
|
menu_item->parent == widget &&
|
||||||
|
menu_item != menu_shell->active_menu_item)
|
||||||
{
|
{
|
||||||
menu_shell->activate_time = event->time;
|
_gtk_menu_shell_activate (menu_shell);
|
||||||
gtk_menu_shell_select_item (menu_shell, menu_item);
|
menu_shell->button = event->button;
|
||||||
|
|
||||||
|
if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement == GTK_TOP_BOTTOM)
|
||||||
|
{
|
||||||
|
menu_shell->activate_time = event->time;
|
||||||
|
gtk_menu_shell_select_item (menu_shell, menu_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!initially_active)
|
||||||
|
{
|
||||||
|
gboolean window_drag = FALSE;
|
||||||
|
|
||||||
|
gtk_widget_style_get (widget,
|
||||||
|
"window-dragging", &window_drag,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (window_drag)
|
||||||
|
{
|
||||||
|
gtk_menu_shell_deactivate (menu_shell);
|
||||||
|
gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
|
||||||
|
event->button,
|
||||||
|
event->x_root,
|
||||||
|
event->y_root,
|
||||||
|
event->time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,11 +44,11 @@
|
|||||||
* Use gtk_separator_tool_item_new() to create a new #GtkSeparatorToolItem.
|
* Use gtk_separator_tool_item_new() to create a new #GtkSeparatorToolItem.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define MENU_ID "gtk-separator-tool-item-menu-id"
|
#define MENU_ID "gtk-separator-tool-item-menu-id"
|
||||||
|
|
||||||
struct _GtkSeparatorToolItemPrivate
|
struct _GtkSeparatorToolItemPrivate
|
||||||
{
|
{
|
||||||
|
GdkWindow *event_window;
|
||||||
guint draw : 1;
|
guint draw : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,20 +59,28 @@ enum {
|
|||||||
|
|
||||||
static gboolean gtk_separator_tool_item_create_menu_proxy (GtkToolItem *item);
|
static gboolean gtk_separator_tool_item_create_menu_proxy (GtkToolItem *item);
|
||||||
static void gtk_separator_tool_item_set_property (GObject *object,
|
static void gtk_separator_tool_item_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
static void gtk_separator_tool_item_get_property (GObject *object,
|
static void gtk_separator_tool_item_get_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
static void gtk_separator_tool_item_size_request (GtkWidget *widget,
|
static void gtk_separator_tool_item_size_request (GtkWidget *widget,
|
||||||
GtkRequisition *requisition);
|
GtkRequisition *requisition);
|
||||||
|
static void gtk_separator_tool_item_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation);
|
||||||
static gboolean gtk_separator_tool_item_expose (GtkWidget *widget,
|
static gboolean gtk_separator_tool_item_expose (GtkWidget *widget,
|
||||||
GdkEventExpose *event);
|
GdkEventExpose *event);
|
||||||
static void gtk_separator_tool_item_add (GtkContainer *container,
|
static void gtk_separator_tool_item_add (GtkContainer *container,
|
||||||
GtkWidget *child);
|
GtkWidget *child);
|
||||||
static gint get_space_size (GtkToolItem *tool_item);
|
static gint get_space_size (GtkToolItem *tool_item);
|
||||||
|
static void gtk_separator_tool_item_realize (GtkWidget *widget);
|
||||||
|
static void gtk_separator_tool_item_unrealize (GtkWidget *widget);
|
||||||
|
static void gtk_separator_tool_item_map (GtkWidget *widget);
|
||||||
|
static void gtk_separator_tool_item_unmap (GtkWidget *widget);
|
||||||
|
static gboolean gtk_separator_tool_item_button_event (GtkWidget *widget,
|
||||||
|
GdkEventButton *event);
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GtkSeparatorToolItem, gtk_separator_tool_item, GTK_TYPE_TOOL_ITEM)
|
G_DEFINE_TYPE (GtkSeparatorToolItem, gtk_separator_tool_item, GTK_TYPE_TOOL_ITEM)
|
||||||
@ -86,8 +94,8 @@ get_space_size (GtkToolItem *tool_item)
|
|||||||
if (GTK_IS_TOOLBAR (parent))
|
if (GTK_IS_TOOLBAR (parent))
|
||||||
{
|
{
|
||||||
gtk_widget_style_get (parent,
|
gtk_widget_style_get (parent,
|
||||||
"space-size", &space_size,
|
"space-size", &space_size,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return space_size;
|
return space_size;
|
||||||
@ -109,34 +117,45 @@ gtk_separator_tool_item_class_init (GtkSeparatorToolItemClass *class)
|
|||||||
object_class->set_property = gtk_separator_tool_item_set_property;
|
object_class->set_property = gtk_separator_tool_item_set_property;
|
||||||
object_class->get_property = gtk_separator_tool_item_get_property;
|
object_class->get_property = gtk_separator_tool_item_get_property;
|
||||||
widget_class->size_request = gtk_separator_tool_item_size_request;
|
widget_class->size_request = gtk_separator_tool_item_size_request;
|
||||||
|
widget_class->size_allocate = gtk_separator_tool_item_size_allocate;
|
||||||
widget_class->expose_event = gtk_separator_tool_item_expose;
|
widget_class->expose_event = gtk_separator_tool_item_expose;
|
||||||
|
widget_class->realize = gtk_separator_tool_item_realize;
|
||||||
|
widget_class->unrealize = gtk_separator_tool_item_unrealize;
|
||||||
|
widget_class->map = gtk_separator_tool_item_map;
|
||||||
|
widget_class->unmap = gtk_separator_tool_item_unmap;
|
||||||
|
widget_class->button_press_event = gtk_separator_tool_item_button_event;
|
||||||
|
widget_class->button_release_event = gtk_separator_tool_item_button_event;
|
||||||
|
|
||||||
toolitem_class->create_menu_proxy = gtk_separator_tool_item_create_menu_proxy;
|
toolitem_class->create_menu_proxy = gtk_separator_tool_item_create_menu_proxy;
|
||||||
|
|
||||||
container_class->add = gtk_separator_tool_item_add;
|
container_class->add = gtk_separator_tool_item_add;
|
||||||
|
|
||||||
g_object_class_install_property (object_class,
|
g_object_class_install_property (object_class,
|
||||||
PROP_DRAW,
|
PROP_DRAW,
|
||||||
g_param_spec_boolean ("draw",
|
g_param_spec_boolean ("draw",
|
||||||
P_("Draw"),
|
P_("Draw"),
|
||||||
P_("Whether the separator is drawn, or just blank"),
|
P_("Whether the separator is drawn, or just blank"),
|
||||||
TRUE,
|
TRUE,
|
||||||
GTK_PARAM_READWRITE));
|
GTK_PARAM_READWRITE));
|
||||||
|
|
||||||
|
|
||||||
g_type_class_add_private (object_class, sizeof (GtkSeparatorToolItemPrivate));
|
g_type_class_add_private (object_class, sizeof (GtkSeparatorToolItemPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_separator_tool_item_init (GtkSeparatorToolItem *separator_item)
|
gtk_separator_tool_item_init (GtkSeparatorToolItem *separator_item)
|
||||||
{
|
{
|
||||||
separator_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (separator_item,
|
separator_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (separator_item,
|
||||||
GTK_TYPE_SEPARATOR_TOOL_ITEM,
|
GTK_TYPE_SEPARATOR_TOOL_ITEM,
|
||||||
GtkSeparatorToolItemPrivate);
|
GtkSeparatorToolItemPrivate);
|
||||||
separator_item->priv->draw = TRUE;
|
separator_item->priv->draw = TRUE;
|
||||||
|
|
||||||
|
gtk_widget_set_has_window (GTK_WIDGET (separator_item), FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_separator_tool_item_add (GtkContainer *container,
|
gtk_separator_tool_item_add (GtkContainer *container,
|
||||||
GtkWidget *child)
|
GtkWidget *child)
|
||||||
{
|
{
|
||||||
g_warning ("attempt to add a child to an GtkSeparatorToolItem");
|
g_warning ("attempt to add a child to an GtkSeparatorToolItem");
|
||||||
}
|
}
|
||||||
@ -155,9 +174,9 @@ gtk_separator_tool_item_create_menu_proxy (GtkToolItem *item)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_separator_tool_item_set_property (GObject *object,
|
gtk_separator_tool_item_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GtkSeparatorToolItem *item = GTK_SEPARATOR_TOOL_ITEM (object);
|
GtkSeparatorToolItem *item = GTK_SEPARATOR_TOOL_ITEM (object);
|
||||||
|
|
||||||
@ -174,9 +193,9 @@ gtk_separator_tool_item_set_property (GObject *object,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_separator_tool_item_get_property (GObject *object,
|
gtk_separator_tool_item_get_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GtkSeparatorToolItem *item = GTK_SEPARATOR_TOOL_ITEM (object);
|
GtkSeparatorToolItem *item = GTK_SEPARATOR_TOOL_ITEM (object);
|
||||||
|
|
||||||
@ -193,7 +212,7 @@ gtk_separator_tool_item_get_property (GObject *object,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_separator_tool_item_size_request (GtkWidget *widget,
|
gtk_separator_tool_item_size_request (GtkWidget *widget,
|
||||||
GtkRequisition *requisition)
|
GtkRequisition *requisition)
|
||||||
{
|
{
|
||||||
GtkToolItem *item = GTK_TOOL_ITEM (widget);
|
GtkToolItem *item = GTK_TOOL_ITEM (widget);
|
||||||
GtkOrientation orientation = gtk_tool_item_get_orientation (item);
|
GtkOrientation orientation = gtk_tool_item_get_orientation (item);
|
||||||
@ -210,9 +229,119 @@ gtk_separator_tool_item_size_request (GtkWidget *widget,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_separator_tool_item_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
|
GtkSeparatorToolItemPrivate *priv = separator->priv;
|
||||||
|
|
||||||
|
widget->allocation = *allocation;
|
||||||
|
|
||||||
|
if (gtk_widget_get_realized (widget))
|
||||||
|
gdk_window_move_resize (priv->event_window,
|
||||||
|
widget->allocation.x,
|
||||||
|
widget->allocation.y,
|
||||||
|
widget->allocation.width,
|
||||||
|
widget->allocation.height);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_separator_tool_item_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
|
GtkSeparatorToolItemPrivate *priv = separator->priv;
|
||||||
|
GdkWindowAttr attributes;
|
||||||
|
gint attributes_mask;
|
||||||
|
|
||||||
|
gtk_widget_set_realized (widget, TRUE);
|
||||||
|
|
||||||
|
attributes.window_type = GDK_WINDOW_CHILD;
|
||||||
|
attributes.x = widget->allocation.x;
|
||||||
|
attributes.y = widget->allocation.y;
|
||||||
|
attributes.width = widget->allocation.width;
|
||||||
|
attributes.height = widget->allocation.height;
|
||||||
|
attributes.wclass = GDK_INPUT_ONLY;
|
||||||
|
attributes.visual = gtk_widget_get_visual (widget);
|
||||||
|
attributes.colormap = gtk_widget_get_colormap (widget);
|
||||||
|
attributes.event_mask = gtk_widget_get_events (widget) |
|
||||||
|
GDK_BUTTON_PRESS_MASK |
|
||||||
|
GDK_BUTTON_RELEASE_MASK;
|
||||||
|
attributes_mask = GDK_WA_X | GDK_WA_Y;
|
||||||
|
|
||||||
|
widget->window = gtk_widget_get_parent_window (widget);
|
||||||
|
g_object_ref (widget->window);
|
||||||
|
|
||||||
|
priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
|
||||||
|
&attributes, attributes_mask);
|
||||||
|
gdk_window_set_user_data (priv->event_window, widget);
|
||||||
|
|
||||||
|
widget->style = gtk_style_attach (widget->style, widget->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_separator_tool_item_unrealize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
|
GtkSeparatorToolItemPrivate *priv = separator->priv;
|
||||||
|
|
||||||
|
if (priv->event_window)
|
||||||
|
{
|
||||||
|
gdk_window_set_user_data (priv->event_window, NULL);
|
||||||
|
gdk_window_destroy (priv->event_window);
|
||||||
|
priv->event_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_separator_tool_item_parent_class)->unrealize (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_separator_tool_item_map (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
|
GtkSeparatorToolItemPrivate *priv = separator->priv;
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_separator_tool_item_parent_class)->map (widget);
|
||||||
|
|
||||||
|
if (priv->event_window)
|
||||||
|
gdk_window_show (priv->event_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_separator_tool_item_unmap (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
|
GtkSeparatorToolItemPrivate *priv = separator->priv;
|
||||||
|
|
||||||
|
if (priv->event_window)
|
||||||
|
gdk_window_hide (priv->event_window);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_separator_tool_item_parent_class)->unmap (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_separator_tool_item_button_event (GtkWidget *widget,
|
||||||
|
GdkEventButton *event)
|
||||||
|
{
|
||||||
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
|
GtkSeparatorToolItemPrivate *priv = separator->priv;
|
||||||
|
|
||||||
|
/* We want window dragging to work on empty toolbar areas,
|
||||||
|
* so we only eat button events on visible separators
|
||||||
|
*/
|
||||||
|
return priv->draw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFAULT_SPACE_SIZE 12
|
||||||
|
#define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
|
||||||
|
#define SPACE_LINE_DIVISION 10.0
|
||||||
|
#define SPACE_LINE_START 2.0
|
||||||
|
#define SPACE_LINE_END 8.0
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gtk_separator_tool_item_expose (GtkWidget *widget,
|
gtk_separator_tool_item_expose (GtkWidget *widget,
|
||||||
GdkEventExpose *event)
|
GdkEventExpose *event)
|
||||||
{
|
{
|
||||||
GtkToolbar *toolbar = NULL;
|
GtkToolbar *toolbar = NULL;
|
||||||
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
GtkSeparatorToolItem *separator = GTK_SEPARATOR_TOOL_ITEM (widget);
|
||||||
@ -221,10 +350,10 @@ gtk_separator_tool_item_expose (GtkWidget *widget,
|
|||||||
if (priv->draw)
|
if (priv->draw)
|
||||||
{
|
{
|
||||||
if (GTK_IS_TOOLBAR (widget->parent))
|
if (GTK_IS_TOOLBAR (widget->parent))
|
||||||
toolbar = GTK_TOOLBAR (widget->parent);
|
toolbar = GTK_TOOLBAR (widget->parent);
|
||||||
|
|
||||||
_gtk_toolbar_paint_space_line (widget, toolbar,
|
_gtk_toolbar_paint_space_line (widget, toolbar,
|
||||||
&(event->area), &widget->allocation);
|
&(event->area), &widget->allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -245,7 +374,7 @@ gtk_separator_tool_item_new (void)
|
|||||||
GtkToolItem *self;
|
GtkToolItem *self;
|
||||||
|
|
||||||
self = g_object_new (GTK_TYPE_SEPARATOR_TOOL_ITEM,
|
self = g_object_new (GTK_TYPE_SEPARATOR_TOOL_ITEM,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -282,7 +411,7 @@ gtk_separator_tool_item_get_draw (GtkSeparatorToolItem *item)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gtk_separator_tool_item_set_draw (GtkSeparatorToolItem *item,
|
gtk_separator_tool_item_set_draw (GtkSeparatorToolItem *item,
|
||||||
gboolean draw)
|
gboolean draw)
|
||||||
{
|
{
|
||||||
g_return_if_fail (GTK_IS_SEPARATOR_TOOL_ITEM (item));
|
g_return_if_fail (GTK_IS_SEPARATOR_TOOL_ITEM (item));
|
||||||
|
|
||||||
|
|||||||
@ -2630,6 +2630,8 @@ static gboolean
|
|||||||
gtk_toolbar_button_press (GtkWidget *toolbar,
|
gtk_toolbar_button_press (GtkWidget *toolbar,
|
||||||
GdkEventButton *event)
|
GdkEventButton *event)
|
||||||
{
|
{
|
||||||
|
GtkWidget *window;
|
||||||
|
|
||||||
if (event->button == 3)
|
if (event->button == 3)
|
||||||
{
|
{
|
||||||
gboolean return_value;
|
gboolean return_value;
|
||||||
@ -2641,6 +2643,28 @@ gtk_toolbar_button_press (GtkWidget *toolbar,
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window = gtk_widget_get_toplevel (toolbar);
|
||||||
|
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
gboolean window_drag = FALSE;
|
||||||
|
|
||||||
|
gtk_widget_style_get (toolbar,
|
||||||
|
"window-dragging", &window_drag,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (window_drag)
|
||||||
|
{
|
||||||
|
gtk_window_begin_move_drag (GTK_WINDOW (window),
|
||||||
|
event->button,
|
||||||
|
event->x_root,
|
||||||
|
event->y_root,
|
||||||
|
event->time);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2491,6 +2491,13 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
|||||||
0.0, 1.0, 0.04,
|
0.0, 1.0, 0.04,
|
||||||
GTK_PARAM_READABLE));
|
GTK_PARAM_READABLE));
|
||||||
|
|
||||||
|
gtk_widget_class_install_style_property (klass,
|
||||||
|
g_param_spec_boolean ("window-dragging",
|
||||||
|
P_("Window dragging"),
|
||||||
|
P_("Whether windows can be dragged by clicking on empty areas"),
|
||||||
|
FALSE,
|
||||||
|
GTK_PARAM_READWRITE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkWidget:draw-border:
|
* GtkWidget:draw-border:
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user