Fix menus resizing dynamically while they are popped up or torn off.

Fri Aug  2 18:00:46 2002  Owen Taylor  <otaylor@redhat.com>

        * gtk/gtkmenu.c: Fix menus resizing dynamically while
        they are popped up or torn off. (#78949)
This commit is contained in:
Owen Taylor 2002-08-02 22:03:23 +00:00 committed by Owen Taylor
parent 934f1cc499
commit 786b3e298f
7 changed files with 122 additions and 25 deletions

View File

@ -1,3 +1,8 @@
Fri Aug 2 18:00:46 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmenu.c: Fix menus resizing dynamically while
they are popped up or torn off. (#78949)
Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com> Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkregion-generic.c: Comprehensively add * gdk/gdkregion-generic.c: Comprehensively add

View File

@ -1,3 +1,8 @@
Fri Aug 2 18:00:46 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmenu.c: Fix menus resizing dynamically while
they are popped up or torn off. (#78949)
Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com> Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkregion-generic.c: Comprehensively add * gdk/gdkregion-generic.c: Comprehensively add

View File

@ -1,3 +1,8 @@
Fri Aug 2 18:00:46 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmenu.c: Fix menus resizing dynamically while
they are popped up or torn off. (#78949)
Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com> Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkregion-generic.c: Comprehensively add * gdk/gdkregion-generic.c: Comprehensively add

View File

@ -1,3 +1,8 @@
Fri Aug 2 18:00:46 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmenu.c: Fix menus resizing dynamically while
they are popped up or torn off. (#78949)
Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com> Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkregion-generic.c: Comprehensively add * gdk/gdkregion-generic.c: Comprehensively add

View File

@ -1,3 +1,8 @@
Fri Aug 2 18:00:46 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmenu.c: Fix menus resizing dynamically while
they are popped up or torn off. (#78949)
Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com> Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkregion-generic.c: Comprehensively add * gdk/gdkregion-generic.c: Comprehensively add

View File

@ -1,3 +1,8 @@
Fri Aug 2 18:00:46 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmenu.c: Fix menus resizing dynamically while
they are popped up or torn off. (#78949)
Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com> Fri Aug 2 16:38:34 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkregion-generic.c: Comprehensively add * gdk/gdkregion-generic.c: Comprehensively add

View File

@ -53,6 +53,7 @@
#define MENU_SCROLL_TIMEOUT2 50 #define MENU_SCROLL_TIMEOUT2 50
typedef struct _GtkMenuAttachData GtkMenuAttachData; typedef struct _GtkMenuAttachData GtkMenuAttachData;
typedef struct _GtkMenuPrivate GtkMenuPrivate;
struct _GtkMenuAttachData struct _GtkMenuAttachData
{ {
@ -60,6 +61,13 @@ struct _GtkMenuAttachData
GtkMenuDetachFunc detacher; GtkMenuDetachFunc detacher;
}; };
struct _GtkMenuPrivate
{
gboolean have_position;
gint x;
gint y;
};
enum { enum {
PROP_0, PROP_0,
PROP_TEAROFF_TITLE PROP_TEAROFF_TITLE
@ -147,6 +155,29 @@ static void _gtk_menu_refresh_accel_paths (GtkMenu *menu,
static GtkMenuShellClass *parent_class = NULL; static GtkMenuShellClass *parent_class = NULL;
static const gchar *attach_data_key = "gtk-menu-attach-data"; static const gchar *attach_data_key = "gtk-menu-attach-data";
GtkMenuPrivate *
gtk_menu_get_private (GtkMenu *menu)
{
GtkMenuPrivate *private;
static GQuark private_quark = 0;
if (!private_quark)
private_quark = g_quark_from_static_string ("gtk-menu-private");
private = g_object_get_qdata (G_OBJECT (menu), private_quark);
if (!private)
{
private = g_new0 (GtkMenuPrivate, 1);
private->have_position = FALSE;
g_object_set_qdata_full (G_OBJECT (menu), private_quark,
private, (GDestroyNotify) g_free);
}
return private;
}
GtkType GtkType
gtk_menu_get_type (void) gtk_menu_get_type (void)
{ {
@ -336,6 +367,22 @@ gtk_menu_window_event (GtkWidget *window,
return handled; return handled;
} }
static void
gtk_menu_window_size_request (GtkWidget *window,
GtkRequisition *requisition,
GtkMenu *menu)
{
GtkMenuPrivate *private = gtk_menu_get_private (menu);
if (private->have_position)
{
gint screen_height = gdk_screen_height ();
if (private->y + requisition->height > screen_height)
requisition->height = screen_height - private->y;
}
}
static void static void
gtk_menu_init (GtkMenu *menu) gtk_menu_init (GtkMenu *menu)
{ {
@ -351,6 +398,7 @@ gtk_menu_init (GtkMenu *menu)
"child", menu, "child", menu,
NULL), NULL),
"signal::event", gtk_menu_window_event, menu, "signal::event", gtk_menu_window_event, menu,
"signal::size_request", gtk_menu_window_size_request, menu,
"signal::destroy", gtk_widget_destroyed, &menu->toplevel, "signal::destroy", gtk_widget_destroyed, &menu->toplevel,
NULL); NULL);
gtk_window_set_policy (GTK_WINDOW (menu->toplevel), gtk_window_set_policy (GTK_WINDOW (menu->toplevel),
@ -807,16 +855,20 @@ gtk_menu_popup (GtkMenu *menu,
void void
gtk_menu_popdown (GtkMenu *menu) gtk_menu_popdown (GtkMenu *menu)
{ {
GtkMenuPrivate *private;
GtkMenuShell *menu_shell; GtkMenuShell *menu_shell;
g_return_if_fail (GTK_IS_MENU (menu)); g_return_if_fail (GTK_IS_MENU (menu));
menu_shell = GTK_MENU_SHELL (menu); menu_shell = GTK_MENU_SHELL (menu);
private = gtk_menu_get_private (menu);
menu_shell->parent_menu_shell = NULL; menu_shell->parent_menu_shell = NULL;
menu_shell->active = FALSE; menu_shell->active = FALSE;
menu_shell->ignore_enter = FALSE; menu_shell->ignore_enter = FALSE;
private->have_position = FALSE;
gtk_menu_stop_scrolling (menu); gtk_menu_stop_scrolling (menu);
gtk_menu_stop_navigating_submenu (menu); gtk_menu_stop_navigating_submenu (menu);
@ -837,11 +889,7 @@ gtk_menu_popdown (GtkMenu *menu)
if (menu->torn_off) if (menu->torn_off)
{ {
gint width, height; gtk_widget_set_usize (menu->tearoff_window, -1, -1);
gdk_window_get_size (menu->tearoff_window->window, &width, &height);
gtk_widget_set_usize (menu->tearoff_window,
-1,
height);
if (GTK_BIN (menu->toplevel)->child) if (GTK_BIN (menu->toplevel)->child)
{ {
@ -1067,6 +1115,7 @@ gtk_menu_set_tearoff_hints (GtkMenu *menu,
geometry_hints.min_height = 0; geometry_hints.min_height = 0;
geometry_hints.max_height = GTK_WIDGET (menu)->requisition.height; geometry_hints.max_height = GTK_WIDGET (menu)->requisition.height;
gtk_window_set_geometry_hints (GTK_WINDOW (menu->tearoff_window), gtk_window_set_geometry_hints (GTK_WINDOW (menu->tearoff_window),
NULL, NULL,
&geometry_hints, &geometry_hints,
@ -1487,11 +1536,9 @@ gtk_menu_size_request (GtkWidget *widget,
menu->toggle_size = max_toggle_size; menu->toggle_size = max_toggle_size;
/* If the requested width was different than the allocated width, we need to change /* Don't resize the tearoff if it is not active, because it won't redraw (it is only a background pixmap).
* the geometry hints for the tear off window so that the window can actually be resized.
* Don't resize the tearoff if it is not active, because it won't redraw (it is only a background pixmap).
*/ */
if ((requisition->width != GTK_WIDGET (menu)->allocation.width) && menu->tearoff_active) if (menu->tearoff_active)
gtk_menu_set_tearoff_hints (menu, requisition->width); gtk_menu_set_tearoff_hints (menu, requisition->width);
} }
@ -1521,6 +1568,9 @@ gtk_menu_size_allocate (GtkWidget *widget,
width = MAX (1, allocation->width - x * 2); width = MAX (1, allocation->width - x * 2);
height = MAX (1, allocation->height - y * 2); height = MAX (1, allocation->height - y * 2);
if (menu_shell->active)
gtk_menu_scroll_to (menu, menu->scroll_offset);
if (menu->upper_arrow_visible && !menu->tearoff_active) if (menu->upper_arrow_visible && !menu->tearoff_active)
{ {
y += MENU_SCROLL_ARROW_HEIGHT; y += MENU_SCROLL_ARROW_HEIGHT;
@ -1588,7 +1638,6 @@ gtk_menu_size_allocate (GtkWidget *widget,
{ {
gtk_widget_hide (menu->tearoff_scrollbar); gtk_widget_hide (menu->tearoff_scrollbar);
gtk_menu_set_tearoff_hints (menu, allocation->width); gtk_menu_set_tearoff_hints (menu, allocation->width);
gtk_widget_set_usize (menu->tearoff_window, -1, allocation->height);
gtk_menu_scroll_to (menu, 0); gtk_menu_scroll_to (menu, 0);
} }
@ -1614,7 +1663,6 @@ gtk_menu_size_allocate (GtkWidget *widget,
{ {
gtk_widget_show (menu->tearoff_scrollbar); gtk_widget_show (menu->tearoff_scrollbar);
gtk_menu_set_tearoff_hints (menu, allocation->width); gtk_menu_set_tearoff_hints (menu, allocation->width);
gtk_widget_set_usize (menu->tearoff_window, -1, allocation->height);
} }
} }
} }
@ -2311,6 +2359,7 @@ gtk_menu_position (GtkMenu *menu)
{ {
GtkWidget *widget; GtkWidget *widget;
GtkRequisition requisition; GtkRequisition requisition;
GtkMenuPrivate *private;
gint x, y; gint x, y;
gint scroll_offset; gint scroll_offset;
gint menu_height; gint menu_height;
@ -2384,9 +2433,22 @@ gtk_menu_position (GtkMenu *menu)
gtk_window_move (GTK_WINDOW (GTK_MENU_SHELL (menu)->active ? menu->toplevel : menu->tearoff_window), gtk_window_move (GTK_WINDOW (GTK_MENU_SHELL (menu)->active ? menu->toplevel : menu->tearoff_window),
x, y); x, y);
gtk_widget_set_usize (GTK_MENU_SHELL (menu)->active ?
menu->toplevel : menu->tearoff_hbox, if (GTK_MENU_SHELL (menu)->active)
-1, requisition.height); {
private = gtk_menu_get_private (menu);
private->have_position = TRUE;
private->x = x;
private->y = y;
gtk_widget_queue_resize (menu->toplevel);
}
else
{
gtk_window_resize (GTK_WINDOW (menu->tearoff_window),
requisition.width, requisition.height);
}
menu->scroll_offset = scroll_offset; menu->scroll_offset = scroll_offset;
} }
@ -2422,17 +2484,21 @@ gtk_menu_scroll_to (GtkMenu *menu,
gtk_adjustment_value_changed (menu->tearoff_adjustment); gtk_adjustment_value_changed (menu->tearoff_adjustment);
} }
/* Scroll the menu: */
gdk_window_move (menu->bin_window, 0, -offset);
/* Move/resize the viewport according to arrows: */ /* Move/resize the viewport according to arrows: */
gdk_window_get_size (widget->window, &view_width, &view_height); view_width = widget->allocation.width;
view_height = widget->allocation.height;
border_width = GTK_CONTAINER (menu)->border_width; border_width = GTK_CONTAINER (menu)->border_width;
view_width -= (border_width + widget->style->xthickness) * 2; view_width -= (border_width + widget->style->xthickness) * 2;
view_height -= (border_width + widget->style->ythickness) * 2; view_height -= (border_width + widget->style->ythickness) * 2;
menu_height = widget->requisition.height - (border_width + widget->style->ythickness) * 2; menu_height = widget->requisition.height - (border_width + widget->style->ythickness) * 2;
offset = CLAMP (offset, 0, menu_height - view_height);
/* Scroll the menu: */
if (GTK_WIDGET_REALIZED (menu))
gdk_window_move (menu->bin_window, 0, -offset);
x = border_width + widget->style->xthickness; x = border_width + widget->style->xthickness;
y = border_width + widget->style->ythickness; y = border_width + widget->style->ythickness;
@ -2474,6 +2540,7 @@ gtk_menu_scroll_to (GtkMenu *menu,
y += MENU_SCROLL_ARROW_HEIGHT; y += MENU_SCROLL_ARROW_HEIGHT;
} }
if (GTK_WIDGET_REALIZED (menu))
gdk_window_move_resize (menu->view_window, gdk_window_move_resize (menu->view_window,
x, x,
y, y,