Merge branch 'wip/kill-menu' into 'master'

Use menus less

See merge request GNOME/gtk!1098
This commit is contained in:
Matthias Clasen 2019-09-16 22:10:02 +00:00
commit 87e7fa9917
15 changed files with 214 additions and 294 deletions

View File

@ -30,7 +30,6 @@
#endif
#include <gtk/gtkwidget.h>
#include <gtk/gtkmenu.h>
#include <gio/gio.h>
G_BEGIN_DECLS

View File

@ -51,8 +51,6 @@
#include "gtklabel.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtkpango.h"
#include "gtkpopover.h"
#include "gtkprivate.h"

View File

@ -36,7 +36,6 @@
#include <gtk/gtkeditable.h>
#include <gtk/gtkimcontext.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkentrybuffer.h>
#include <gtk/gtkentrycompletion.h>
#include <gtk/gtkimage.h>

View File

@ -26,8 +26,6 @@
#include "gtklabel.h"
#include "gtkmain.h"
#include "gtkprivate.h"
#include "gtkradiomenuitem.h"
#include "gtkseparatormenuitem.h"
#include "gtksettings.h"

View File

@ -23,7 +23,6 @@
#endif
#include <gtk/gtkimcontext.h>
#include <gtk/gtkmenushell.h>
G_BEGIN_DECLS

View File

@ -26,6 +26,7 @@
#include "gtkmenubuttonprivate.h"
#include "gtkbox.h"
#include "gtkmenu.h"
#include "gtkpopover.h"
#include "gtkmain.h"
#include "gtksizerequest.h"
#include "gtkbuildable.h"
@ -103,7 +104,8 @@ enum
enum
{
PROP_0,
PROP_MENU
PROP_MENU,
PROP_POPOVER
};
static gint signals[LAST_SIGNAL];
@ -210,6 +212,10 @@ gtk_menu_tool_button_set_property (GObject *object,
gtk_menu_tool_button_set_menu (button, g_value_get_object (value));
break;
case PROP_POPOVER:
gtk_menu_tool_button_set_popover (button, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -230,6 +236,10 @@ gtk_menu_tool_button_get_property (GObject *object,
g_value_set_object (value, gtk_menu_button_get_popup (GTK_MENU_BUTTON (button->priv->arrow_button)));
break;
case PROP_POPOVER:
g_value_set_object (value, gtk_menu_button_get_popover (GTK_MENU_BUTTON (button->priv->arrow_button)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -279,6 +289,13 @@ gtk_menu_tool_button_class_init (GtkMenuToolButtonClass *klass)
P_("The dropdown menu"),
GTK_TYPE_MENU,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_POPOVER,
g_param_spec_object ("popover",
P_("Popover"),
P_("The dropdown popover"),
GTK_TYPE_POPOVER,
GTK_PARAM_READWRITE));
}
static void
@ -324,6 +341,9 @@ gtk_menu_tool_button_buildable_add_child (GtkBuildable *buildable,
if (type && strcmp (type, "menu") == 0)
gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (buildable),
GTK_WIDGET (child));
else if (type && strcmp (type, "popover") == 0)
gtk_menu_tool_button_set_popover (GTK_MENU_TOOL_BUTTON (buildable),
GTK_WIDGET (child));
else
parent_buildable_iface->add_child (buildable, builder, child, type);
}
@ -419,6 +439,38 @@ gtk_menu_tool_button_get_menu (GtkMenuToolButton *button)
return GTK_WIDGET (ret);
}
void
gtk_menu_tool_button_set_popover (GtkMenuToolButton *button,
GtkWidget *popover)
{
GtkMenuToolButtonPrivate *priv;
g_return_if_fail (GTK_IS_MENU_TOOL_BUTTON (button));
g_return_if_fail (GTK_IS_POPOVER (popover) || popover == NULL);
priv = button->priv;
gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->arrow_button), popover);
gtk_menu_button_set_create_popup_func (GTK_MENU_BUTTON (priv->arrow_button),
_show_menu_emit, NULL, NULL);
g_object_notify (G_OBJECT (button), "popover");
}
GtkWidget *
gtk_menu_tool_button_get_popover (GtkMenuToolButton *button)
{
GtkPopover *ret;
g_return_val_if_fail (GTK_IS_MENU_TOOL_BUTTON (button), NULL);
ret = gtk_menu_button_get_popover (GTK_MENU_BUTTON (button->priv->arrow_button));
if (!ret)
return NULL;
return GTK_WIDGET (ret);
}
/**
* gtk_menu_tool_button_set_arrow_tooltip_text:
* @button: a #GtkMenuToolButton

View File

@ -24,7 +24,6 @@
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkmenu.h>
#include <gtk/gtktoolbutton.h>
G_BEGIN_DECLS
@ -47,6 +46,11 @@ void gtk_menu_tool_button_set_menu (GtkMenuToolButton *button,
GDK_AVAILABLE_IN_ALL
GtkWidget *gtk_menu_tool_button_get_menu (GtkMenuToolButton *button);
GDK_AVAILABLE_IN_ALL
void gtk_menu_tool_button_set_popover (GtkMenuToolButton *button,
GtkWidget *popover);
GDK_AVAILABLE_IN_ALL
GtkWidget *gtk_menu_tool_button_get_popover (GtkMenuToolButton *button);
GDK_AVAILABLE_IN_ALL
void gtk_menu_tool_button_set_arrow_tooltip_text (GtkMenuToolButton *button,
const gchar *text);
GDK_AVAILABLE_IN_ALL

View File

@ -43,8 +43,7 @@
#include "gtklabel.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtkpopovermenu.h"
#include "gtkorientable.h"
#include "gtksizerequest.h"
#include "gtkstylecontextprivate.h"
@ -237,6 +236,7 @@ struct _GtkNotebookPrivate
GtkWidget *action_widget[N_ACTION_WIDGETS];
GtkWidget *dnd_child;
GtkWidget *menu;
GtkWidget *menu_box;
GtkWidget *stack_widget;
GtkWidget *header_widget;
@ -807,8 +807,6 @@ static void gtk_notebook_menu_item_recreate (GtkNotebook *notebook,
GList *list);
static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
gpointer data);
static void gtk_notebook_menu_detacher (GtkWidget *widget,
GtkMenu *menu);
static void gtk_notebook_update_tab_pos (GtkNotebook *notebook);
@ -2501,7 +2499,14 @@ gtk_notebook_gesture_pressed (GtkGestureClick *gesture,
if (in_tabs (notebook, x, y) && priv->menu && gdk_event_triggers_context_menu (event))
{
gtk_menu_popup_at_pointer (GTK_MENU (priv->menu), event);
GdkRectangle rect;
rect.x = x;
rect.y = y;
rect.width = 1;
rect.height = 1;
gtk_popover_set_pointing_to (GTK_POPOVER (priv->menu), &rect);
gtk_popover_popup (GTK_POPOVER (priv->menu));
return;
}
@ -5592,14 +5597,14 @@ gtk_notebook_menu_switch_page (GtkWidget *widget,
{
GtkNotebookPrivate *priv;
GtkNotebook *notebook;
GtkWidget *parent;
GList *children;
guint page_num;
parent = gtk_widget_get_parent (widget);
notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget (GTK_MENU (parent)));
notebook = GTK_NOTEBOOK (gtk_widget_get_ancestor (widget, GTK_TYPE_NOTEBOOK));
priv = notebook->priv;
gtk_popover_popdown (GTK_POPOVER (priv->menu));
if (priv->cur_page == page)
return;
@ -5623,7 +5628,6 @@ gtk_notebook_menu_switch_page (GtkWidget *widget,
* gtk_notebook_menu_item_create
* gtk_notebook_menu_item_recreate
* gtk_notebook_menu_label_unparent
* gtk_notebook_menu_detacher
*/
static void
gtk_notebook_menu_item_create (GtkNotebook *notebook,
@ -5643,15 +5647,14 @@ gtk_notebook_menu_item_create (GtkNotebook *notebook,
gtk_widget_set_valign (page->menu_label, GTK_ALIGN_CENTER);
}
gtk_widget_show (page->menu_label);
menu_item = gtk_menu_item_new ();
menu_item = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (menu_item), GTK_RELIEF_NONE);
gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
gtk_menu_shell_insert (GTK_MENU_SHELL (priv->menu), menu_item,
g_list_index (priv->children, page));
g_signal_connect (menu_item, "activate",
gtk_container_add (GTK_CONTAINER (priv->menu_box), menu_item);
g_signal_connect (menu_item, "clicked",
G_CALLBACK (gtk_notebook_menu_switch_page), page);
if (gtk_widget_get_visible (page->child))
gtk_widget_show (menu_item);
if (!gtk_widget_get_visible (page->child))
gtk_widget_hide (menu_item);
}
static void
@ -5675,18 +5678,6 @@ gtk_notebook_menu_label_unparent (GtkWidget *widget,
_gtk_bin_set_child (GTK_BIN (widget), NULL);
}
static void
gtk_notebook_menu_detacher (GtkWidget *widget,
GtkMenu *menu)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
g_return_if_fail (priv->menu == (GtkWidget*) menu);
priv->menu = NULL;
}
/* Public GtkNotebook Page Insert/Remove Methods :
*
* gtk_notebook_append_page
@ -6531,9 +6522,10 @@ gtk_notebook_popup_enable (GtkNotebook *notebook)
if (priv->menu)
return;
priv->menu = gtk_menu_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (priv->menu),
GTK_STYLE_CLASS_CONTEXT_MENU);
priv->menu = gtk_popover_menu_new (priv->tabs_widget);
priv->menu_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_popover_menu_add_submenu (GTK_POPOVER_MENU (priv->menu), priv->menu_box, "main");
for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
list;
@ -6541,9 +6533,6 @@ gtk_notebook_popup_enable (GtkNotebook *notebook)
gtk_notebook_menu_item_create (notebook, list->data);
gtk_notebook_update_labels (notebook);
gtk_menu_attach_to_widget (GTK_MENU (priv->menu),
GTK_WIDGET (notebook),
gtk_notebook_menu_detacher);
g_object_notify_by_pspec (G_OBJECT (notebook), properties[PROP_ENABLE_POPUP]);
}
@ -6566,9 +6555,11 @@ gtk_notebook_popup_disable (GtkNotebook *notebook)
if (!priv->menu)
return;
gtk_container_foreach (GTK_CONTAINER (priv->menu),
gtk_container_foreach (GTK_CONTAINER (priv->menu_box),
(GtkCallback) gtk_notebook_menu_label_unparent, NULL);
gtk_widget_destroy (priv->menu);
priv->menu = NULL;
priv->menu_box = NULL;
g_object_notify_by_pspec (G_OBJECT (notebook), properties[PROP_ENABLE_POPUP]);
}

View File

@ -49,8 +49,6 @@
#include "gtkmagnifierprivate.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtkpango.h"
#include "gtkpopovermenu.h"
#include "gtkprivate.h"

View File

@ -29,7 +29,6 @@
#include "gtktextbuffer.h"
#include "gtktextlayoutprivate.h"
#include "gtkmenuitem.h"
#include "gtkintl.h"
#define DRAG_ICON_MAX_WIDTH 250
@ -37,110 +36,6 @@
#define DRAG_ICON_MAX_LINES 7
#define ELLIPSIS_CHARACTER "\xe2\x80\xa6"
typedef struct _GtkUnicodeMenuEntry GtkUnicodeMenuEntry;
typedef struct _GtkTextUtilCallbackInfo GtkTextUtilCallbackInfo;
struct _GtkUnicodeMenuEntry {
const char *label;
gunichar ch;
};
struct _GtkTextUtilCallbackInfo
{
GtkTextUtilCharChosenFunc func;
gpointer data;
};
static const GtkUnicodeMenuEntry bidi_menu_entries[] = {
{ N_("LRM _Left-to-right mark"), 0x200E },
{ N_("RLM _Right-to-left mark"), 0x200F },
{ N_("LRE Left-to-right _embedding"), 0x202A },
{ N_("RLE Right-to-left e_mbedding"), 0x202B },
{ N_("LRO Left-to-right _override"), 0x202D },
{ N_("RLO Right-to-left o_verride"), 0x202E },
{ N_("PDF _Pop directional formatting"), 0x202C },
{ N_("ZWS _Zero width space"), 0x200B },
{ N_("ZWJ Zero width _joiner"), 0x200D },
{ N_("ZWNJ Zero width _non-joiner"), 0x200C }
};
static GtkTextUtilCallbackInfo *
callback_info_new (GtkTextUtilCharChosenFunc func,
gpointer data)
{
GtkTextUtilCallbackInfo *info;
info = g_slice_new (GtkTextUtilCallbackInfo);
info->func = func;
info->data = data;
return info;
}
static void
callback_info_free (GtkTextUtilCallbackInfo *info)
{
g_slice_free (GtkTextUtilCallbackInfo, info);
}
static void
activate_cb (GtkWidget *menu_item,
gpointer data)
{
GtkUnicodeMenuEntry *entry;
GtkTextUtilCallbackInfo *info = data;
char buf[7];
entry = g_object_get_data (G_OBJECT (menu_item), "gtk-unicode-menu-entry");
buf[g_unichar_to_utf8 (entry->ch, buf)] = '\0';
(* info->func) (buf, info->data);
}
/*
* _gtk_text_util_append_special_char_menuitems
* @menushell: a #GtkMenuShell
* @callback: call this when an item is chosen
* @data: data for callback
*
* Add menuitems for various bidi control characters to a menu;
* the menuitems, when selected, will call the given function
* with the chosen character.
*
* This function is private/internal in GTK 2.0, the functionality may
* become public sometime, but it probably needs more thought first.
* e.g. maybe there should be a way to just get the list of items,
* instead of requiring the menu items to be created.
*/
void
_gtk_text_util_append_special_char_menuitems (GtkMenuShell *menushell,
GtkTextUtilCharChosenFunc func,
gpointer data)
{
int i;
for (i = 0; i < G_N_ELEMENTS (bidi_menu_entries); i++)
{
GtkWidget *menuitem;
GtkTextUtilCallbackInfo *info;
info = callback_info_new (func, data);
menuitem = gtk_menu_item_new_with_mnemonic (_(bidi_menu_entries[i].label));
g_object_set_data (G_OBJECT (menuitem), I_("gtk-unicode-menu-entry"),
(gpointer)&bidi_menu_entries[i]);
g_signal_connect_data (menuitem, "activate",
G_CALLBACK (activate_cb),
info, (GClosureNotify) callback_info_free, 0);
gtk_widget_show (menuitem);
gtk_menu_shell_append (menushell, menuitem);
}
}
static void
append_n_lines (GString *str, const gchar *text, GSList *lines, gint n_lines)
{

View File

@ -31,13 +31,6 @@ G_BEGIN_DECLS
* GtkTextView and GtkEntry
*/
typedef void (* GtkTextUtilCharChosenFunc) (const char *text,
gpointer data);
void _gtk_text_util_append_special_char_menuitems (GtkMenuShell *menushell,
GtkTextUtilCharChosenFunc func,
gpointer data);
GdkPaintable * gtk_text_util_create_drag_icon (GtkWidget *widget,
gchar *text,
gssize len);

View File

@ -36,8 +36,6 @@
#include "gtkintl.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtkrenderbackgroundprivate.h"
#include "gtkseparatormenuitem.h"
#include "gtksettings.h"

View File

@ -32,7 +32,6 @@
#include <gtk/gtkcontainer.h>
#include <gtk/gtkimcontext.h>
#include <gtk/gtktextbuffer.h>
#include <gtk/gtkmenu.h>
G_BEGIN_DECLS

View File

@ -45,10 +45,14 @@
#include "gtklabel.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkorientable.h"
#include "gtkorientableprivate.h"
#include "gtkprivate.h"
#include "gtkpopovermenu.h"
#include "gtkmodelbutton.h"
#include "gtkseparator.h"
#include "gtkradiomenuitem.h"
#include "gtkcheckmenuitem.h"
#include "gtkradiobutton.h"
#include "gtkradiotoolbutton.h"
#include "gtkseparatormenuitem.h"
@ -132,7 +136,8 @@ struct _GtkToolbarClass
struct _GtkToolbarPrivate
{
GtkMenu *menu;
GtkWidget *menu;
GtkWidget *menu_box;
GtkSettings *settings;
GtkToolbarStyle style;
@ -429,6 +434,7 @@ gtk_toolbar_class_init (GtkToolbarClass *klass)
NULL,
G_TYPE_NONE, 1,
GTK_TYPE_TOOLBAR_STYLE);
/**
* GtkToolbar::popup-context-menu:
* @toolbar: the #GtkToolbar which emitted the signal
@ -1108,77 +1114,97 @@ menu_deactivated (GtkWidget *menu,
}
static void
menu_detached (GtkWidget *widget,
GtkMenu *menu)
button_clicked (GtkWidget *button,
GtkWidget *item)
{
GtkToolbar *toolbar = GTK_TOOLBAR (widget);
GtkToolbarPrivate *priv = toolbar->priv;
priv->menu = NULL;
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
if (GTK_IS_TOOL_BUTTON (item))
g_signal_emit_by_name (_gtk_tool_button_get_button (GTK_TOOL_BUTTON (item)), "clicked");
}
static void
rebuild_menu (GtkToolbar *toolbar)
{
GtkToolbarPrivate *priv = toolbar->priv;
GList *list, *children;
GList *list;
if (!priv->menu)
{
priv->menu = GTK_MENU (gtk_menu_new ());
gtk_menu_attach_to_widget (priv->menu,
GTK_WIDGET (toolbar),
menu_detached);
priv->menu = gtk_popover_menu_new (priv->arrow_button);
priv->menu_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_popover_menu_add_submenu (GTK_POPOVER_MENU (priv->menu), priv->menu_box, "main");
g_signal_connect (priv->menu, "deactivate",
g_signal_connect (priv->menu, "closed",
G_CALLBACK (menu_deactivated), toolbar);
}
gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
gtk_container_foreach (GTK_CONTAINER (priv->menu_box), remove_item, NULL);
for (list = priv->content; list != NULL; list = list->next)
{
ToolbarContent *content = list->data;
if (toolbar_content_get_state (content) == OVERFLOWN &&
!toolbar_content_is_placeholder (content))
{
GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content);
if (menu_item)
{
GtkWidget *button, *widget;
const char *text;
GtkButtonRole role;
gboolean active;
g_assert (GTK_IS_MENU_ITEM (menu_item));
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
text = gtk_menu_item_get_label (GTK_MENU_ITEM (menu_item));
if (text == NULL)
{
GtkWidget *box, *child;
box = gtk_bin_get_child (GTK_BIN (menu_item));
for (child = gtk_widget_get_first_child (box);
child;
child = gtk_widget_get_next_sibling (child))
{
if (GTK_IS_LABEL (child))
{
text = gtk_label_get_label (GTK_LABEL (child));
break;
}
}
}
if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item))
{
gtk_container_add (GTK_CONTAINER (priv->menu_box), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
continue;
}
else if (GTK_IS_RADIO_MENU_ITEM (menu_item))
role = GTK_BUTTON_ROLE_RADIO;
else if (GTK_IS_CHECK_MENU_ITEM (menu_item))
role = GTK_BUTTON_ROLE_CHECK;
else
role = GTK_BUTTON_ROLE_NORMAL;
if (GTK_IS_CHECK_MENU_ITEM (menu_item))
active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item));
else
active = FALSE;
button = gtk_model_button_new ();
g_object_set (button,
"text", text,
"role", role,
"active", active,
NULL);
widget = toolbar_content_get_widget (content);
g_signal_connect (button, "clicked",
G_CALLBACK (button_clicked), widget);
gtk_container_add (GTK_CONTAINER (priv->menu_box), button);
}
}
}
/* Remove leading and trailing separator items */
children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
list = children;
while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
{
GtkWidget *child = list->data;
gtk_container_remove (GTK_CONTAINER (priv->menu), child);
list = list->next;
}
g_list_free (children);
/* Regenerate the list of children so we don't try to remove items twice */
children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
list = g_list_last (children);
while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
{
GtkWidget *child = list->data;
gtk_container_remove (GTK_CONTAINER (priv->menu), child);
list = list->prev;
}
g_list_free (children);
priv->need_rebuild = FALSE;
}
@ -2124,52 +2150,10 @@ show_menu (GtkToolbar *toolbar,
GdkEventButton *event)
{
GtkToolbarPrivate *priv = toolbar->priv;
GtkRequisition minimum_size;
rebuild_menu (toolbar);
gtk_widget_show (GTK_WIDGET (priv->menu));
switch (priv->orientation)
{
case GTK_ORIENTATION_HORIZONTAL:
gtk_widget_get_preferred_size (priv->arrow_button, &minimum_size, NULL);
g_object_set (priv->menu,
"anchor-hints", (GDK_ANCHOR_FLIP_Y |
GDK_ANCHOR_SLIDE |
GDK_ANCHOR_RESIZE),
"menu-type-hint", GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU,
"rect-anchor-dx", -minimum_size.width,
NULL);
gtk_menu_popup_at_widget (priv->menu,
priv->arrow_button,
GDK_GRAVITY_SOUTH_EAST,
GDK_GRAVITY_NORTH_WEST,
(GdkEvent *) event);
break;
case GTK_ORIENTATION_VERTICAL:
g_object_set (priv->menu,
"anchor-hints", (GDK_ANCHOR_FLIP_X |
GDK_ANCHOR_SLIDE |
GDK_ANCHOR_RESIZE),
NULL);
gtk_menu_popup_at_widget (priv->menu,
priv->arrow_button,
GDK_GRAVITY_NORTH_EAST,
GDK_GRAVITY_NORTH_WEST,
(GdkEvent *) event);
break;
default:
g_assert_not_reached ();
break;
}
gtk_popover_popup (GTK_POPOVER (priv->menu));
}
static void

View File

@ -60,6 +60,9 @@
#include "gtkmenushellprivate.h"
#include "gtkpointerfocusprivate.h"
#include "gtkpopoverprivate.h"
#include "gtkpopovermenu.h"
#include "gtkmodelbutton.h"
#include "gtkseparator.h"
#include "gtkprivate.h"
#include "gtkroot.h"
#include "gtknative.h"
@ -6569,12 +6572,12 @@ _gtk_window_unset_focus_and_default (GtkWindow *window,
}
static void
popup_menu_detach (GtkWidget *widget,
GtkMenu *menu)
popup_menu_closed (GtkPopover *popover,
GtkWindow *widget)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (GTK_WINDOW (widget));
priv->popup_menu = NULL;
g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
}
static GdkSurfaceState
@ -6670,6 +6673,7 @@ ontop_window_clicked (GtkMenuItem *menuitem,
GtkWindow *window = (GtkWindow *)user_data;
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
gtk_popover_popdown (GTK_POPOVER (priv->popup_menu));
gtk_window_set_keep_above (window, !priv->above_initially);
}
@ -6690,6 +6694,7 @@ gtk_window_do_popup_fallback (GtkWindow *window,
GtkWidget *menuitem;
GdkSurfaceState state;
gboolean maximized, iconified;
GtkWidget *box;
if (priv->popup_menu)
gtk_widget_destroy (priv->popup_menu);
@ -6699,16 +6704,14 @@ gtk_window_do_popup_fallback (GtkWindow *window,
iconified = (state & GDK_SURFACE_STATE_ICONIFIED) == GDK_SURFACE_STATE_ICONIFIED;
maximized = priv->maximized && !iconified;
priv->popup_menu = gtk_menu_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (priv->popup_menu),
GTK_STYLE_CLASS_CONTEXT_MENU);
priv->popup_menu = gtk_popover_menu_new (priv->title_box);
gtk_menu_attach_to_widget (GTK_MENU (priv->popup_menu),
GTK_WIDGET (window),
popup_menu_detach);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_popover_menu_add_submenu (GTK_POPOVER_MENU (priv->popup_menu), box, "main");
menuitem = gtk_model_button_new ();
g_object_set (menuitem, "text", _("Restore"), NULL);
menuitem = gtk_menu_item_new_with_label (_("Restore"));
gtk_widget_show (menuitem);
/* "Restore" means "Unmaximize" or "Unminimize"
* (yes, some WMs allow window menu to be shown for minimized windows).
* Not restorable:
@ -6721,70 +6724,80 @@ gtk_window_do_popup_fallback (GtkWindow *window,
(!iconified && !priv->resizable) ||
priv->type_hint != GDK_SURFACE_TYPE_HINT_NORMAL)
gtk_widget_set_sensitive (menuitem, FALSE);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (restore_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_model_button_new ();
g_object_set (menuitem, "text", _("Move"), NULL);
menuitem = gtk_menu_item_new_with_label (_("Move"));
gtk_widget_show (menuitem);
if (maximized || iconified)
gtk_widget_set_sensitive (menuitem, FALSE);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (move_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_model_button_new ();
g_object_set (menuitem, "text", _("Resize"), NULL);
menuitem = gtk_menu_item_new_with_label (_("Resize"));
gtk_widget_show (menuitem);
if (!priv->resizable || maximized || iconified)
gtk_widget_set_sensitive (menuitem, FALSE);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (resize_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_model_button_new ();
g_object_set (menuitem, "text", _("Minimize"), NULL);
menuitem = gtk_menu_item_new_with_label (_("Minimize"));
gtk_widget_show (menuitem);
if (iconified ||
priv->type_hint != GDK_SURFACE_TYPE_HINT_NORMAL)
gtk_widget_set_sensitive (menuitem, FALSE);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (minimize_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_model_button_new ();
g_object_set (menuitem, "text", _("Maximize"), NULL);
menuitem = gtk_menu_item_new_with_label (_("Maximize"));
gtk_widget_show (menuitem);
if (maximized ||
!priv->resizable ||
priv->type_hint != GDK_SURFACE_TYPE_HINT_NORMAL)
gtk_widget_set_sensitive (menuitem, FALSE);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (maximize_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_separator_menu_item_new ();
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
menuitem = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_model_button_new ();
g_object_set (menuitem,
"text", _("Always on Top"),
"role", GTK_BUTTON_ROLE_CHECK,
"active", priv->above_initially,
NULL);
menuitem = gtk_check_menu_item_new_with_label (_("Always on Top"));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), priv->above_initially);
if (maximized)
gtk_widget_set_sensitive (menuitem, FALSE);
gtk_widget_show (menuitem);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (ontop_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_separator_menu_item_new ();
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
menuitem = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (box), menuitem);
menuitem = gtk_model_button_new ();
g_object_set (menuitem, "text", _("Close"), NULL);
menuitem = gtk_menu_item_new_with_label (_("Close"));
gtk_widget_show (menuitem);
if (!priv->deletable)
gtk_widget_set_sensitive (menuitem, FALSE);
g_signal_connect (G_OBJECT (menuitem), "activate",
g_signal_connect (G_OBJECT (menuitem), "clicked",
G_CALLBACK (close_window_clicked), window);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), (GdkEvent *) event);
gtk_container_add (GTK_CONTAINER (box), menuitem);
g_signal_connect (priv->popup_menu, "closed",
G_CALLBACK (popup_menu_closed), window);
gtk_popover_popup (GTK_POPOVER (priv->popup_menu));
}
static void