[gimp/nielsdg/fix-context-menus: 2/3] app: Popup menu at rect in GimpEditor
- From: Niels De Graef <nielsdg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/nielsdg/fix-context-menus: 2/3] app: Popup menu at rect in GimpEditor
- Date: Tue, 7 Dec 2021 23:09:46 +0000 (UTC)
commit bdab4fce4112a401f9c4f4d4c662a548a44c3451
Author: Niels De Graef <nielsdegraef gmail com>
Date: Wed Dec 8 00:09:08 2021 +0100
app: Popup menu at rect in GimpEditor
Rather than trying to fix up our own heuristics using a
`GtkMenuPositionFunc`, use whatever GTK provides to position given a
specific rectangle, which also has the benefit of nicely integrating
with GDK backends such as Wayland. Another advantage is that we can use
GdkGravity to center the popup.
Since GTK 3, GtkWidget also gained a "popup-menu" signal, which we
can/should use instead of rolling our own context signals.
app/widgets/gimpcolormapeditor.c | 49 ++++++++++++++++---
app/widgets/gimpcolormapselection.c | 42 ++++++++++------
app/widgets/gimpcolormapselection.h | 5 ++
app/widgets/gimpcontainereditor.c | 37 ++------------
app/widgets/gimpcontainereditor.h | 2 -
app/widgets/gimpcontainericonview.c | 98 +++++++++++++++----------------------
app/widgets/gimpcontainertreeview.c | 72 +++++++--------------------
app/widgets/gimpcontainerview.c | 44 -----------------
app/widgets/gimpcontainerview.h | 7 ---
app/widgets/gimpeditor.c | 22 +++++++++
app/widgets/gimpeditor.h | 6 +++
app/widgets/gimpitemtreeview.c | 15 ------
app/widgets/gimppaletteeditor.c | 54 +++++++++++++++-----
app/widgets/gimppaletteview.c | 47 +++++++++++++-----
app/widgets/gimppaletteview.h | 6 +++
app/widgets/gimpuimanager.c | 40 +++++++++++++++
app/widgets/gimpuimanager.h | 9 ++++
17 files changed, 294 insertions(+), 261 deletions(-)
---
diff --git a/app/widgets/gimpcolormapeditor.c b/app/widgets/gimpcolormapeditor.c
index 8a2152822a..c27f5af97f 100644
--- a/app/widgets/gimpcolormapeditor.c
+++ b/app/widgets/gimpcolormapeditor.c
@@ -58,7 +58,11 @@ static void gimp_colormap_editor_color_update (GimpColorDialog *dialog
GimpColorDialogState state,
GimpColormapEditor *editor);
-static void gimp_colormap_editor_entry_popup (GimpEditor *editor);
+static gboolean gimp_colormap_editor_entry_button_press (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data);
+static gboolean gimp_colormap_editor_entry_popup (GtkWidget *widget,
+ gpointer user_data);
static void gimp_colormap_editor_color_clicked (GimpColormapEditor *editor,
GimpPaletteEntry *entry,
GdkModifierType state);
@@ -177,15 +181,18 @@ gimp_colormap_editor_set_context (GimpDocked *docked,
gtk_box_pack_start (GTK_BOX (editor), editor->selection, TRUE, TRUE, 0);
gtk_widget_show (editor->selection);
- g_signal_connect_swapped (editor->selection, "color-context",
- G_CALLBACK (gimp_colormap_editor_entry_popup),
- editor);
g_signal_connect_swapped (editor->selection, "color-clicked",
G_CALLBACK (gimp_colormap_editor_color_clicked),
editor);
g_signal_connect_swapped (editor->selection, "color-activated",
G_CALLBACK (gimp_colormap_editor_edit_color),
editor);
+ g_signal_connect (editor->selection, "button-press-event",
+ G_CALLBACK (gimp_colormap_editor_entry_button_press),
+ editor);
+ g_signal_connect (editor->selection, "popup-menu",
+ G_CALLBACK (gimp_colormap_editor_entry_popup),
+ editor);
}
}
@@ -361,10 +368,38 @@ gimp_colormap_editor_color_update (GimpColorDialog *dialog,
}
}
-static void
-gimp_colormap_editor_entry_popup (GimpEditor *editor)
+static gboolean
+gimp_colormap_editor_entry_button_press (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ if (gdk_event_triggers_context_menu (event))
+ {
+ gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (user_data), event);
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+gimp_colormap_editor_entry_popup (GtkWidget *widget,
+ gpointer user_data)
{
- gimp_editor_popup_menu (editor, NULL, NULL);
+ GimpColormapEditor *editor = GIMP_COLORMAP_EDITOR (user_data);
+ GimpColormapSelection *selection = GIMP_COLORMAP_SELECTION (widget);
+ GimpPaletteEntry *selected;
+ GdkRectangle rect;
+
+ selected = gimp_colormap_selection_get_selected_entry (selection);
+ if (!selected)
+ return GDK_EVENT_PROPAGATE;
+
+ gimp_colormap_selection_get_entry_rect (selection, selected, &rect);
+ return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (editor),
+ gtk_widget_get_window (widget),
+ &rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
+ NULL);
}
static void
diff --git a/app/widgets/gimpcolormapselection.c b/app/widgets/gimpcolormapselection.c
index 7d582fac0c..9705a3dad6 100644
--- a/app/widgets/gimpcolormapselection.c
+++ b/app/widgets/gimpcolormapselection.c
@@ -106,9 +106,6 @@ static void gimp_colormap_selection_entry_selected (GimpPaletteView *vi
static void gimp_colormap_selection_entry_activated (GimpPaletteView *view,
GimpPaletteEntry *entry,
GimpColormapSelection *selection);
-static void gimp_colormap_selection_entry_context (GimpPaletteView *view,
- GimpPaletteEntry *entry,
- GimpColormapSelection *selection);
static void gimp_colormap_selection_color_dropped (GimpPaletteView *view,
GimpPaletteEntry *entry,
const GimpRGB *color,
@@ -215,9 +212,6 @@ gimp_colormap_selection_init (GimpColormapSelection *selection)
g_signal_connect (selection->view, "entry-activated",
G_CALLBACK (gimp_colormap_selection_entry_activated),
selection);
- g_signal_connect (selection->view, "entry-context",
- G_CALLBACK (gimp_colormap_selection_entry_context),
- selection);
g_signal_connect (selection->view, "color-dropped",
G_CALLBACK (gimp_colormap_selection_color_dropped),
selection);
@@ -471,6 +465,32 @@ gimp_colormap_selection_max_index (GimpColormapSelection *selection)
return MAX (0, gimp_image_get_colormap_size (image) - 1);
}
+GimpPaletteEntry *
+gimp_colormap_selection_get_selected_entry (GimpColormapSelection *selection)
+{
+ g_return_val_if_fail (GIMP_IS_COLORMAP_SELECTION (selection), NULL);
+
+ return gimp_palette_view_get_selected_entry (GIMP_PALETTE_VIEW (selection->view));
+}
+
+void
+gimp_colormap_selection_get_entry_rect (GimpColormapSelection *selection,
+ GimpPaletteEntry *entry,
+ GdkRectangle *rect)
+{
+ GtkAllocation allocation;
+
+ g_return_if_fail (GIMP_IS_COLORMAP_SELECTION (selection));
+ g_return_if_fail (entry);
+ g_return_if_fail (rect);
+
+ gimp_palette_view_get_entry_rect (GIMP_PALETTE_VIEW (selection->view),
+ entry, rect);
+ gtk_widget_get_allocation (GTK_WIDGET (selection), &allocation);
+ /* rect->x += allocation.x; */
+ /* rect->y += allocation.y; */
+}
+
/* private functions */
@@ -603,16 +623,6 @@ gimp_colormap_selection_entry_activated (GimpPaletteView *view,
g_signal_emit (selection, signals[COLOR_ACTIVATED], 0, entry);
}
-static void
-gimp_colormap_selection_entry_context (GimpPaletteView *view,
- GimpPaletteEntry *entry,
- GimpColormapSelection *selection)
-{
- gimp_colormap_selection_set_index (selection, entry->position, NULL);
-
- g_signal_emit (selection, signals[COLOR_CONTEXT], 0, entry);
-}
-
static void
gimp_colormap_selection_color_dropped (GimpPaletteView *view,
GimpPaletteEntry *entry,
diff --git a/app/widgets/gimpcolormapselection.h b/app/widgets/gimpcolormapselection.h
index e524d1b42f..8553d96e26 100644
--- a/app/widgets/gimpcolormapselection.h
+++ b/app/widgets/gimpcolormapselection.h
@@ -76,6 +76,11 @@ gboolean gimp_colormap_selection_set_index (GimpColormapSelection *selection
gint gimp_colormap_selection_max_index (GimpColormapSelection *selection);
+GimpPaletteEntry * gimp_colormap_selection_get_selected_entry (GimpColormapSelection *selection);
+
+void gimp_colormap_selection_get_entry_rect (GimpColormapSelection *selection,
+ GimpPaletteEntry *entry,
+ GdkRectangle *rect);
#endif /* __GIMP_COLORMAP_SELECTION_H__ */
diff --git a/app/widgets/gimpcontainereditor.c b/app/widgets/gimpcontainereditor.c
index cbfe1d037b..ae5f59277c 100644
--- a/app/widgets/gimpcontainereditor.c
+++ b/app/widgets/gimpcontainereditor.c
@@ -93,12 +93,6 @@ static void gimp_container_editor_activate_item (GtkWidget *widge
GimpViewable *viewable,
gpointer insert_data,
GimpContainerEditor *editor);
-static void gimp_container_editor_context_item (GtkWidget *widget,
- GimpViewable *viewable,
- gpointer insert_data,
- GimpContainerEditor *editor);
-static void gimp_container_editor_real_context_item(GimpContainerEditor *editor,
- GimpViewable *viewable);
static GtkWidget * gimp_container_editor_get_preview (GimpDocked *docked,
GimpContext *context,
@@ -136,7 +130,6 @@ gimp_container_editor_class_init (GimpContainerEditorClass *klass)
klass->select_item = NULL;
klass->activate_item = NULL;
- klass->context_item = gimp_container_editor_real_context_item;
g_object_class_install_property (object_class, PROP_VIEW_TYPE,
g_param_spec_enum ("view-type",
@@ -288,9 +281,9 @@ gimp_container_editor_constructed (GObject *object)
g_signal_connect_object (editor->view, "activate-item",
G_CALLBACK (gimp_container_editor_activate_item),
editor, 0);
- g_signal_connect_object (editor->view, "context-item",
- G_CALLBACK (gimp_container_editor_context_item),
- editor, 0);
+ /* g_signal_connect_object (editor->view, "context-item", XXX maybe listen to popup-menu? */
+ /* G_CALLBACK (gimp_container_editor_context_item), */
+ /* editor, 0); */
{
GimpObject *object = gimp_context_get_by_type (editor->priv->context,
@@ -461,30 +454,6 @@ gimp_container_editor_activate_item (GtkWidget *widget,
klass->activate_item (editor, viewable);
}
-static void
-gimp_container_editor_context_item (GtkWidget *widget,
- GimpViewable *viewable,
- gpointer insert_data,
- GimpContainerEditor *editor)
-{
- GimpContainerEditorClass *klass = GIMP_CONTAINER_EDITOR_GET_CLASS (editor);
-
- if (klass->context_item)
- klass->context_item (editor, viewable);
-}
-
-static void
-gimp_container_editor_real_context_item (GimpContainerEditor *editor,
- GimpViewable *viewable)
-{
- GimpContainer *container = gimp_container_view_get_container (editor->view);
-
- if (viewable && gimp_container_have (container, GIMP_OBJECT (viewable)))
- {
- gimp_editor_popup_menu (GIMP_EDITOR (editor->view), NULL, NULL);
- }
-}
-
static GtkWidget *
gimp_container_editor_get_preview (GimpDocked *docked,
GimpContext *context,
diff --git a/app/widgets/gimpcontainereditor.h b/app/widgets/gimpcontainereditor.h
index 728d604e30..3d16dc4de2 100644
--- a/app/widgets/gimpcontainereditor.h
+++ b/app/widgets/gimpcontainereditor.h
@@ -50,8 +50,6 @@ struct _GimpContainerEditorClass
GimpViewable *object);
void (* activate_item) (GimpContainerEditor *editor,
GimpViewable *object);
- void (* context_item) (GimpContainerEditor *editor,
- GimpViewable *object);
};
diff --git a/app/widgets/gimpcontainericonview.c b/app/widgets/gimpcontainericonview.c
index ecc89176a6..c0e9d0c221 100644
--- a/app/widgets/gimpcontainericonview.c
+++ b/app/widgets/gimpcontainericonview.c
@@ -241,68 +241,25 @@ gimp_container_icon_view_unmap (GtkWidget *widget)
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}
-static void
-gimp_container_icon_view_menu_position (GtkMenu *menu,
- gint *x,
- gint *y,
- gpointer data)
+static gboolean
+gimp_container_icon_view_popup_menu (GtkWidget *widget)
{
- GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (data);
- GtkWidget *widget = GTK_WIDGET (icon_view->view);
- GtkAllocation allocation;
-#if 0
- GtkTreeIter selected_iter;
-#endif
-
- gtk_widget_get_allocation (widget, &allocation);
-
- gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
-
- if (! gtk_widget_get_has_window (widget))
- {
- *x += allocation.x;
- *y += allocation.y;
- }
-
-#if 0
- if (gimp_container_icon_view_get_selected_single (icon_view, &selected_iter))
- {
- GtkTreePath *path;
- GdkRectangle cell_rect;
- gint center;
-
- path = gtk_tree_model_get_path (icon_view->model, &selected_iter);
- gtk_icon_view_get_cell_area (icon_view->view, path,
- icon_view->main_column, &cell_rect);
- gtk_tree_path_free (path);
-
- center = cell_rect.y + cell_rect.height / 2;
- center = CLAMP (center, 0, allocation.height);
+ GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (widget);
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GdkRectangle rect;
- *x += allocation.width / 2;
- *y += center;
- }
- else
-#endif
- {
- GtkStyleContext *style = gtk_widget_get_style_context (widget);
- GtkBorder border;
-
- gtk_style_context_get_border (style, 0, &border);
-
- *x += border.left;
- *y += border.top;
- }
+ if (!gimp_container_icon_view_get_selected_single (icon_view, &iter))
+ return FALSE;
- gimp_menu_position (menu, x, y);
-}
+ path = gtk_tree_model_get_path (icon_view->model, &iter);
+ gtk_icon_view_get_cell_rect (icon_view->view, path, NULL, &rect);
+ gtk_tree_path_free (path);
-static gboolean
-gimp_container_icon_view_popup_menu (GtkWidget *widget)
-{
- return gimp_editor_popup_menu (GIMP_EDITOR (widget),
- gimp_container_icon_view_menu_position,
- widget);
+ return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (widget),
+ gtk_widget_get_window (GTK_WIDGET (icon_view->view)),
+ &rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
+ NULL);
}
GtkWidget *
@@ -638,7 +595,8 @@ gimp_container_icon_view_button_press (GtkWidget *widget,
GdkEventButton *bevent,
GimpContainerIconView *icon_view)
{
- GtkTreePath *path;
+ GimpContainerView *container_view = GIMP_CONTAINER_VIEW (icon_view);
+ GtkTreePath *path;
icon_view->priv->dnd_renderer = NULL;
@@ -658,10 +616,32 @@ gimp_container_icon_view_button_press (GtkWidget *widget,
icon_view->priv->dnd_renderer = renderer;
+ if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
+ {
+ /* If the clicked item is not selected, it becomes the new
+ * selection. Otherwise, we use the current selection. This
+ * allows to not break multiple selection when right-clicking.
+ */
+ if (! gimp_container_view_is_item_selected (container_view, renderer->viewable))
+ gimp_container_view_item_selected (container_view, renderer->viewable);
+ /* Show the context menu. */
+ if (gimp_container_view_get_container (container_view))
+ gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view), (GdkEvent *) bevent);
+ }
+
g_object_unref (renderer);
gtk_tree_path_free (path);
}
+ else
+ {
+ if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
+ {
+ gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view), (GdkEvent *) bevent);
+ }
+
+ return TRUE;
+ }
return FALSE;
}
diff --git a/app/widgets/gimpcontainertreeview.c b/app/widgets/gimpcontainertreeview.c
index af1c335a4d..dd8c57d282 100644
--- a/app/widgets/gimpcontainertreeview.c
+++ b/app/widgets/gimpcontainertreeview.c
@@ -420,64 +420,26 @@ gimp_container_tree_view_unmap (GtkWidget *widget)
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}
-static void
-gimp_container_tree_view_menu_position (GtkMenu *menu,
- gint *x,
- gint *y,
- gpointer data)
+static gboolean
+gimp_container_tree_view_popup_menu (GtkWidget *widget)
{
- GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (data);
- GtkWidget *widget = GTK_WIDGET (tree_view->view);
- GtkAllocation allocation;
- GtkTreeIter selected_iter;
-
- gtk_widget_get_allocation (widget, &allocation);
-
- gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
-
- if (! gtk_widget_get_has_window (widget))
- {
- *x += allocation.x;
- *y += allocation.y;
- }
-
- if (gimp_container_tree_view_get_selected_single (tree_view, &selected_iter))
- {
- GtkTreePath *path;
- GdkRectangle cell_rect;
- gint center;
-
- path = gtk_tree_model_get_path (tree_view->model, &selected_iter);
- gtk_tree_view_get_cell_area (tree_view->view, path,
- tree_view->main_column, &cell_rect);
- gtk_tree_path_free (path);
-
- center = cell_rect.y + cell_rect.height / 2;
- center = CLAMP (center, 0, allocation.height);
-
- *x += allocation.width / 2;
- *y += center;
- }
- else
- {
- GtkStyleContext *style = gtk_widget_get_style_context (widget);
- GtkBorder border;
-
- gtk_style_context_get_border (style, 0, &border);
+ GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (widget);
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GdkRectangle rect;
- *x += border.left;
- *y += border.top;
- }
+ if (!gimp_container_tree_view_get_selected_single (tree_view, &iter))
+ return FALSE;
- gimp_menu_position (menu, x, y);
-}
+ path = gtk_tree_model_get_path (tree_view->model, &iter);
+ gtk_tree_view_get_cell_area (tree_view->view, path,
+ tree_view->main_column, &rect);
+ gtk_tree_path_free (path);
-static gboolean
-gimp_container_tree_view_popup_menu (GtkWidget *widget)
-{
- return gimp_editor_popup_menu (GIMP_EDITOR (widget),
- gimp_container_tree_view_menu_position,
- widget);
+ return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (widget),
+ gtk_tree_view_get_bin_window (tree_view->view),
+ &rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
+ NULL);
}
GtkWidget *
@@ -1484,7 +1446,7 @@ gimp_container_tree_view_button (GtkWidget *widget,
gimp_container_view_item_selected (container_view, renderer->viewable);
/* Show the context menu. */
if (gimp_container_view_get_container (container_view))
- gimp_container_view_item_context (container_view, renderer->viewable);
+ gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (tree_view), (GdkEvent *) bevent);
}
else if (bevent->button == 1)
{
diff --git a/app/widgets/gimpcontainerview.c b/app/widgets/gimpcontainerview.c
index e6bbed0e4d..eac2c20020 100644
--- a/app/widgets/gimpcontainerview.c
+++ b/app/widgets/gimpcontainerview.c
@@ -48,7 +48,6 @@ enum
SELECT_ITEM,
SELECT_ITEMS,
ACTIVATE_ITEM,
- CONTEXT_ITEM,
LAST_SIGNAL
};
@@ -191,21 +190,9 @@ gimp_container_view_default_init (GimpContainerViewInterface *iface)
GIMP_TYPE_OBJECT,
G_TYPE_POINTER);
- view_signals[CONTEXT_ITEM] =
- g_signal_new ("context-item",
- G_TYPE_FROM_INTERFACE (iface),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GimpContainerViewInterface, context_item),
- NULL, NULL,
- gimp_marshal_VOID__OBJECT_POINTER,
- G_TYPE_NONE, 2,
- GIMP_TYPE_OBJECT,
- G_TYPE_POINTER);
-
iface->select_item = NULL;
iface->select_items = NULL;
iface->activate_item = NULL;
- iface->context_item = NULL;
iface->set_container = gimp_container_view_real_set_container;
iface->set_context = gimp_container_view_real_set_context;
@@ -709,27 +696,6 @@ gimp_container_view_activate_item (GimpContainerView *view,
viewable, insert_data);
}
-void
-gimp_container_view_context_item (GimpContainerView *view,
- GimpViewable *viewable)
-{
- GimpContainerViewPrivate *private;
- gpointer insert_data;
-
- g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
- g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
-
- private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
-
- if (gimp_container_frozen (private->container))
- return;
-
- insert_data = g_hash_table_lookup (private->item_hash, viewable);
-
- g_signal_emit (view, view_signals[CONTEXT_ITEM], 0,
- viewable, insert_data);
-}
-
gpointer
gimp_container_view_lookup (GimpContainerView *view,
GimpViewable *viewable)
@@ -975,16 +941,6 @@ gimp_container_view_item_activated (GimpContainerView *view,
gimp_container_view_activate_item (view, viewable);
}
-void
-gimp_container_view_item_context (GimpContainerView *view,
- GimpViewable *viewable)
-{
- g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
- g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
-
- gimp_container_view_context_item (view, viewable);
-}
-
void
gimp_container_view_set_property (GObject *object,
guint property_id,
diff --git a/app/widgets/gimpcontainerview.h b/app/widgets/gimpcontainerview.h
index 0b5ad9ba01..3094710ac0 100644
--- a/app/widgets/gimpcontainerview.h
+++ b/app/widgets/gimpcontainerview.h
@@ -54,9 +54,6 @@ struct _GimpContainerViewInterface
void (* activate_item) (GimpContainerView *view,
GimpViewable *object,
gpointer insert_data);
- void (* context_item) (GimpContainerView *view,
- GimpViewable *object,
- gpointer insert_data);
/* virtual functions */
void (* set_container) (GimpContainerView *view,
@@ -133,8 +130,6 @@ gboolean gimp_container_view_select_item (GimpContainerView *v
GimpViewable *viewable);
void gimp_container_view_activate_item (GimpContainerView *view,
GimpViewable *viewable);
-void gimp_container_view_context_item (GimpContainerView *view,
- GimpViewable *viewable);
gint gimp_container_view_get_selected (GimpContainerView *view,
GList **items,
GList **items_data);
@@ -156,8 +151,6 @@ gboolean gimp_container_view_multi_selected (GimpContainerView *v
GList *paths);
void gimp_container_view_item_activated (GimpContainerView *view,
GimpViewable *item);
-void gimp_container_view_item_context (GimpContainerView *view,
- GimpViewable *item);
/* convenience functions */
diff --git a/app/widgets/gimpeditor.c b/app/widgets/gimpeditor.c
index c84cd5718e..a70ddccc3a 100644
--- a/app/widgets/gimpeditor.c
+++ b/app/widgets/gimpeditor.c
@@ -482,6 +482,28 @@ gimp_editor_popup_menu_at_pointer (GimpEditor *editor,
return FALSE;
}
+gboolean
+gimp_editor_popup_menu_at_rect (GimpEditor *editor,
+ GdkWindow *window,
+ const GdkRectangle *rect,
+ GdkGravity rect_anchor,
+ GdkGravity menu_anchor,
+ const GdkEvent *trigger_event)
+{
+ g_return_val_if_fail (GIMP_IS_EDITOR (editor), FALSE);
+
+ if (editor->priv->ui_manager && editor->priv->ui_path)
+ {
+ gimp_ui_manager_update (editor->priv->ui_manager, editor->priv->popup_data);
+ gimp_ui_manager_ui_popup_at_rect (editor->priv->ui_manager, editor->priv->ui_path,
+ window, rect, rect_anchor, menu_anchor,
+ trigger_event, NULL, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
GtkWidget *
gimp_editor_add_button (GimpEditor *editor,
const gchar *icon_name,
diff --git a/app/widgets/gimpeditor.h b/app/widgets/gimpeditor.h
index 8ebcf12428..66225941e0 100644
--- a/app/widgets/gimpeditor.h
+++ b/app/widgets/gimpeditor.h
@@ -60,6 +60,12 @@ gboolean gimp_editor_popup_menu (GimpEditor *editor,
gpointer position_data);
gboolean gimp_editor_popup_menu_at_pointer (GimpEditor *editor,
const GdkEvent *trigger_event);
+gboolean gimp_editor_popup_menu_at_rect (GimpEditor *editor,
+ GdkWindow *window,
+ const GdkRectangle *rect,
+ GdkGravity rect_anchor,
+ GdkGravity menu_anchor,
+ const GdkEvent *trigger_event);
GtkWidget * gimp_editor_add_button (GimpEditor *editor,
const gchar *icon_name,
diff --git a/app/widgets/gimpitemtreeview.c b/app/widgets/gimpitemtreeview.c
index 5f163db569..8850fe380a 100644
--- a/app/widgets/gimpitemtreeview.c
+++ b/app/widgets/gimpitemtreeview.c
@@ -134,9 +134,6 @@ static gboolean gimp_item_tree_view_select_items (GimpContainerView *view,
static void gimp_item_tree_view_activate_item (GimpContainerView *view,
GimpViewable *item,
gpointer insert_data);
-static void gimp_item_tree_view_context_item (GimpContainerView *view,
- GimpViewable *item,
- gpointer insert_data);
static gboolean gimp_item_tree_view_drop_possible (GimpContainerTreeView *view,
GimpDndType src_type,
@@ -307,7 +304,6 @@ gimp_item_tree_view_view_iface_init (GimpContainerViewInterface *iface)
iface->select_item = gimp_item_tree_view_select_item;
iface->select_items = gimp_item_tree_view_select_items;
iface->activate_item = gimp_item_tree_view_activate_item;
- iface->context_item = gimp_item_tree_view_context_item;
}
static void
@@ -1182,17 +1178,6 @@ gimp_item_tree_view_activate_item (GimpContainerView *view,
}
}
-static void
-gimp_item_tree_view_context_item (GimpContainerView *view,
- GimpViewable *item,
- gpointer insert_data)
-{
- if (parent_view_iface->context_item)
- parent_view_iface->context_item (view, item, insert_data);
-
- gimp_editor_popup_menu (GIMP_EDITOR (view), NULL, NULL);
-}
-
static gboolean
gimp_item_tree_view_drop_possible (GimpContainerTreeView *tree_view,
GimpDndType src_type,
diff --git a/app/widgets/gimppaletteeditor.c b/app/widgets/gimppaletteeditor.c
index 6abee86f45..2335dad337 100644
--- a/app/widgets/gimppaletteeditor.c
+++ b/app/widgets/gimppaletteeditor.c
@@ -106,9 +106,11 @@ static void palette_editor_entry_selected (GimpPaletteView *view,
static void palette_editor_entry_activated (GimpPaletteView *view,
GimpPaletteEntry *entry,
GimpPaletteEditor *editor);
-static void palette_editor_entry_context (GimpPaletteView *view,
- GimpPaletteEntry *entry,
- GimpPaletteEditor *editor);
+static gboolean palette_editor_button_press_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data);
+static gboolean palette_editor_popup_menu (GtkWidget *widget,
+ gpointer user_data);
static void palette_editor_color_dropped (GimpPaletteView *view,
GimpPaletteEntry *entry,
const GimpRGB *color,
@@ -219,12 +221,15 @@ gimp_palette_editor_init (GimpPaletteEditor *editor)
g_signal_connect (editor->view, "entry-activated",
G_CALLBACK (palette_editor_entry_activated),
editor);
- g_signal_connect (editor->view, "entry-context",
- G_CALLBACK (palette_editor_entry_context),
- editor);
g_signal_connect (editor->view, "color-dropped",
G_CALLBACK (palette_editor_color_dropped),
editor);
+ g_signal_connect (editor->view, "button-press-event",
+ G_CALLBACK (palette_editor_button_press_event),
+ editor);
+ g_signal_connect (editor->view, "popup-menu",
+ G_CALLBACK (palette_editor_popup_menu),
+ editor);
gimp_dnd_viewable_dest_add (editor->view,
GIMP_TYPE_PALETTE,
@@ -825,12 +830,39 @@ palette_editor_entry_activated (GimpPaletteView *view,
}
}
-static void
-palette_editor_entry_context (GimpPaletteView *view,
- GimpPaletteEntry *entry,
- GimpPaletteEditor *editor)
+static gboolean
+palette_editor_button_press_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (user_data);
+
+ if (gdk_event_triggers_context_menu (event))
+ {
+ gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (editor), event);
+ return GDK_EVENT_STOP;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+palette_editor_popup_menu (GtkWidget *widget,
+ gpointer user_data)
{
- gimp_editor_popup_menu (GIMP_EDITOR (editor), NULL, NULL);
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (user_data);
+ GimpPaletteEntry *selected;
+ GdkRectangle rect;
+
+ selected = gimp_palette_view_get_selected_entry (GIMP_PALETTE_VIEW (editor->view));
+ if (!selected)
+ return GDK_EVENT_PROPAGATE;
+
+ gimp_palette_view_get_entry_rect (GIMP_PALETTE_VIEW (editor->view), selected, &rect);
+ return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (editor),
+ gtk_widget_get_window (GTK_WIDGET (editor->view)),
+ &rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
+ NULL);
}
static void
diff --git a/app/widgets/gimppaletteview.c b/app/widgets/gimppaletteview.c
index 6b10d05056..ee6168c99f 100644
--- a/app/widgets/gimppaletteview.c
+++ b/app/widgets/gimppaletteview.c
@@ -42,7 +42,6 @@ enum
ENTRY_CLICKED,
ENTRY_SELECTED,
ENTRY_ACTIVATED,
- ENTRY_CONTEXT,
COLOR_DROPPED,
LAST_SIGNAL
};
@@ -119,15 +118,6 @@ gimp_palette_view_class_init (GimpPaletteViewClass *klass)
G_TYPE_NONE, 1,
G_TYPE_POINTER);
- view_signals[ENTRY_CONTEXT] =
- g_signal_new ("entry-context",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GimpPaletteViewClass, entry_context),
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-
view_signals[COLOR_DROPPED] =
g_signal_new ("color-dropped",
G_TYPE_FROM_CLASS (klass),
@@ -226,7 +216,9 @@ gimp_palette_view_button_press (GtkWidget *widget,
if (entry != view->selected)
gimp_palette_view_select_entry (view, entry);
- g_signal_emit (view, view_signals[ENTRY_CONTEXT], 0, entry);
+ /* Usually the menu is provided by a GimpEditor.
+ * Make sure it's also run by returning FALSE here */
+ return FALSE;
}
else if (bevent->button == 1)
{
@@ -404,6 +396,39 @@ gimp_palette_view_select_entry (GimpPaletteView *view,
g_signal_emit (view, view_signals[ENTRY_SELECTED], 0, view->selected);
}
+GimpPaletteEntry *
+gimp_palette_view_get_selected_entry (GimpPaletteView *view)
+{
+ g_return_val_if_fail (GIMP_IS_PALETTE_VIEW (view), NULL);
+
+ return view->selected;
+}
+
+void
+gimp_palette_view_get_entry_rect (GimpPaletteView *view,
+ GimpPaletteEntry *entry,
+ GdkRectangle *rect)
+{
+ GimpViewRendererPalette *renderer;
+ GtkAllocation allocation;
+ gint row, col;
+
+ g_return_if_fail (GIMP_IS_PALETTE_VIEW (view));
+ g_return_if_fail (entry);
+ g_return_if_fail (rect);
+
+ gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
+
+ renderer = GIMP_VIEW_RENDERER_PALETTE (GIMP_VIEW (view)->renderer);
+ row = entry->position / renderer->columns;
+ col = entry->position % renderer->columns;
+
+ rect->x = allocation.x + col * renderer->cell_width;
+ rect->y = allocation.y + row * renderer->cell_height;
+ rect->width = renderer->cell_width;
+ rect->height = renderer->cell_height;
+}
+
/* private functions */
diff --git a/app/widgets/gimppaletteview.h b/app/widgets/gimppaletteview.h
index 68de628fc6..9c215e43e5 100644
--- a/app/widgets/gimppaletteview.h
+++ b/app/widgets/gimppaletteview.h
@@ -66,5 +66,11 @@ GType gimp_palette_view_get_type (void) G_GNUC_CONST;
void gimp_palette_view_select_entry (GimpPaletteView *view,
GimpPaletteEntry *entry);
+GimpPaletteEntry * gimp_palette_view_get_selected_entry (GimpPaletteView *view);
+
+void gimp_palette_view_get_entry_rect (GimpPaletteView *view,
+ GimpPaletteEntry *entry,
+ GdkRectangle *rect);
+
#endif /* __GIMP_PALETTE_VIEW_H__ */
diff --git a/app/widgets/gimpuimanager.c b/app/widgets/gimpuimanager.c
index be7cd4ad46..c3300cb87d 100644
--- a/app/widgets/gimpuimanager.c
+++ b/app/widgets/gimpuimanager.c
@@ -801,6 +801,46 @@ gimp_ui_manager_ui_popup_at_pointer (GimpUIManager *manager,
gtk_menu_popup_at_pointer (GTK_MENU (menu), trigger_event);
}
+void
+gimp_ui_manager_ui_popup_at_rect (GimpUIManager *manager,
+ const gchar *ui_path,
+ GdkWindow *window,
+ const GdkRectangle *rect,
+ GdkGravity rect_anchor,
+ GdkGravity menu_anchor,
+ const GdkEvent *trigger_event,
+ GDestroyNotify popdown_func,
+ gpointer popdown_data)
+{
+ GtkWidget *menu;
+
+ g_return_if_fail (GIMP_IS_UI_MANAGER (manager));
+ g_return_if_fail (ui_path != NULL);
+
+ menu = gimp_ui_manager_get_widget (manager, ui_path);
+
+ if (GTK_IS_MENU_ITEM (menu))
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu));
+
+ if (! menu)
+ return;
+
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ if (popdown_func && popdown_data)
+ {
+ g_object_set_data_full (G_OBJECT (manager), "popdown-data",
+ popdown_data, popdown_func);
+ g_signal_connect (menu, "selection-done",
+ G_CALLBACK (gimp_ui_manager_delete_popdown_data),
+ manager);
+ }
+
+ gtk_menu_popup_at_rect (GTK_MENU (menu), window,
+ rect, rect_anchor, menu_anchor,
+ trigger_event);
+}
+
/* private functions */
diff --git a/app/widgets/gimpuimanager.h b/app/widgets/gimpuimanager.h
index 6c508d283b..b1b64384ac 100644
--- a/app/widgets/gimpuimanager.h
+++ b/app/widgets/gimpuimanager.h
@@ -148,6 +148,15 @@ void gimp_ui_manager_ui_popup_at_pointer
const GdkEvent *trigger_event,
GDestroyNotify popdown_func,
gpointer popdown_data);
+void gimp_ui_manager_ui_popup_at_rect (GimpUIManager *manager,
+ const gchar *ui_path,
+ GdkWindow *window,
+ const GdkRectangle *rect,
+ GdkGravity rect_anchor,
+ GdkGravity menu_anchor,
+ const GdkEvent *trigger_event,
+ GDestroyNotify popdown_func,
+ gpointer popdown_data);
#endif /* __GIMP_UI_MANAGER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]