]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/gtk+/gtk+-2.6.4-1.osso7/gtkmenu.c.diff
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / gtk+ / gtk+-2.6.4-1.osso7 / gtkmenu.c.diff
1 --- gtk+-2.6.4/gtk/gtkmenu.c    2005-03-01 08:28:56.000000000 +0200
2 +++ gtk+-2.6.4/gtk/gtkmenu.c    2005-04-06 16:19:36.921925376 +0300
3 @@ -24,10 +24,16 @@
4   * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
5   */
6  
7 +/* Modified for Nokia Oyj during 2002-2005. See CHANGES file for list
8 + * of changes.
9 + */
10 +
11  #define GTK_MENU_INTERNALS
12  
13  #include <config.h>
14  #include <string.h> /* memset */
15 +#include <math.h>
16 +#include <stdlib.h>
17  #include "gdk/gdkkeysyms.h"
18  #include "gtkalias.h"
19  #include "gtkaccellabel.h"
20 @@ -44,7 +50,11 @@
21  #include "gtkvscrollbar.h"
22  #include "gtksettings.h"
23  #include "gtkintl.h"
24 +#include "gtkcombobox.h"
25  
26 +/* Hildon : We need this to figure out if menu should have
27 + * corners etc. */
28 +#include "gtkmenubar.h"
29  
30  #define MENU_ITEM_CLASS(w)   GTK_MENU_ITEM_GET_CLASS (w)
31  
32 @@ -55,16 +65,43 @@
33                                          * extends below the submenu
34                                          */
35  
36 +/* HILDON:
37 + * Urgh, nasty thing to hard-code things like these :p
38 + * One should really do some rewriting here...
39 + */
40 +
41  #define MENU_SCROLL_STEP1 8
42  #define MENU_SCROLL_STEP2 15
43 -#define MENU_SCROLL_ARROW_HEIGHT 16
44 -#define MENU_SCROLL_FAST_ZONE 8
45 +#define MENU_SCROLL_ARROW_HEIGHT 20 /* This used to be: 23; This hard-coding should be
46 +                                    * changed. Add arrow_height style property into 
47 +                                    * commongtkrc and read it from there everywhere 
48 +                                    * where a reference to MENU_SCROLL_ARROW_HEIGHT
49 +                                    * is made.
50 +                                     * If these changes are made, please modify also
51 +                                    * gtkcombobox.c.
52 +                                    */
53 +#define MENU_SCROLL_FAST_ZONE MENU_SCROLL_ARROW_HEIGHT /* Was originally 8 */
54  #define MENU_SCROLL_TIMEOUT1 50
55  #define MENU_SCROLL_TIMEOUT2 20
56  
57  #define ATTACH_INFO_KEY "gtk-menu-child-attach-info-key"
58  #define ATTACHED_MENUS "gtk-attached-menus"
59  
60 +/* HILDON: */
61 +#define HILDON_MENU_NAME_SHARP "menu_with_corners"
62
63 +/* needed to allow different themeing for first level menus */
64 +#define HILDON_MENU_NAME_ROUND_FIRST_LEVEL "menu_without_corners_first_level"
65 +#define HILDON_MENU_NAME_ROUND "menu_without_corners"
66 +#define HILDON_MENU_NAME_FORCE_SHARP "menu_force_with_corners"
67 +#define HILDON_MENU_NAME_FORCE_ROUND "menu_force_without_corners"
68 +
69 +/* maximum sizes for menus when attached to comboboxes */
70 +#define HILDON_MENU_COMBO_MAX_WIDTH 406
71 +#define HILDON_MENU_COMBO_MIN_WIDTH 66
72 +#define HILDON_MENU_COMBO_MAX_HEIGHT 305
73 +#define HILDON_MENU_COMBO_MIN_HEIGHT 70
74 +
75  typedef struct _GtkMenuAttachData      GtkMenuAttachData;
76  typedef struct _GtkMenuPrivate         GtkMenuPrivate;
77  
78 @@ -92,6 +129,15 @@
79    gboolean have_layout;
80    gint n_rows;
81    gint n_columns;
82 +  
83 +  /* Arrow states */
84 +  GtkStateType lower_arrow_state;
85 +  GtkStateType upper_arrow_state;
86 +
87 +  /* For context menu behavior */
88 +  gboolean context_menu;
89 +  int popup_pointer_x;
90 +  int popup_pointer_y;
91  };
92  
93  typedef struct
94 @@ -108,6 +154,7 @@
95  
96  enum {
97    MOVE_SCROLL,
98 +  CLOSE_CURRENT,
99    LAST_SIGNAL
100  };
101  
102 @@ -191,7 +238,8 @@
103  static void     gtk_menu_handle_scrolling  (GtkMenu          *menu,
104                                             gint              event_x,
105                                             gint              event_y,
106 -                                           gboolean          enter);
107 +                                           gboolean          enter,
108 +                                            gboolean          motion);
109  static void     gtk_menu_set_tearoff_hints (GtkMenu          *menu,
110                                             gint             width);
111  static void     gtk_menu_style_set         (GtkWidget        *widget,
112 @@ -232,6 +280,9 @@
113                                                    guint      signal_id);
114  static void _gtk_menu_refresh_accel_paths (GtkMenu *menu,
115                                            gboolean group_changed);
116 +static gboolean gtk_menu_check_name (GtkWidget *widget);
117 +
118 +static void _gtk_menu_close_current (GtkMenu *menu);
119  
120  static GtkMenuShellClass *parent_class = NULL;
121  static const gchar       attach_data_key[] = "gtk-menu-attach-data";
122 @@ -496,7 +547,6 @@
123    widget_class->hide_all = gtk_menu_hide_all;
124    widget_class->enter_notify_event = gtk_menu_enter_notify;
125    widget_class->leave_notify_event = gtk_menu_leave_notify;
126 -  widget_class->motion_notify_event = gtk_menu_motion_notify;
127    widget_class->style_set = gtk_menu_style_set;
128    widget_class->focus = gtk_menu_focus;
129    widget_class->can_activate_accel = gtk_menu_real_can_activate_accel;
130 @@ -521,6 +571,15 @@
131                              _gtk_marshal_VOID__ENUM,
132                              G_TYPE_NONE, 1,
133                              GTK_TYPE_SCROLL_TYPE);
134 +
135 +  menu_signals[CLOSE_CURRENT] =
136 +    _gtk_binding_signal_new ("close_current",
137 +                            G_OBJECT_CLASS_TYPE (object_class),
138 +                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
139 +                            G_CALLBACK (_gtk_menu_close_current),
140 +                            NULL, NULL,
141 +                            _gtk_marshal_VOID__VOID,
142 +                            G_TYPE_NONE, 0);
143    
144    g_object_class_install_property (gobject_class,
145                                     PROP_TEAROFF_TITLE,
146 @@ -606,6 +665,11 @@
147                                                                 G_PARAM_READWRITE));
148  
149    binding_set = gtk_binding_set_by_class (class);
150 +  /* Hildon : We moved handling of escape-key here because we need it to
151 +   * work like closing a submenu, not closing all the menus. */
152 +  gtk_binding_entry_add_signal (binding_set,
153 +                               GDK_Escape, 0,
154 +                               "close_current", 0);
155    gtk_binding_entry_add_signal (binding_set,
156                                 GDK_Up, 0,
157                                 "move_current", 1,
158 @@ -709,6 +773,25 @@
159                                                    DEFAULT_POPDOWN_DELAY,
160                                                    G_PARAM_READWRITE));
161                                                    
162 +  /* Hildon addition : border width was 
163 +     replaced with horizontal-padding and
164 +     vertical-padding (which already is an style
165 +     property for GtkMenu). */
166 +  gtk_widget_class_install_style_property (widget_class,
167 +                                          g_param_spec_int ("horizontal-padding",
168 +                                                            P_("Horizontal Padding"),
169 +                                                            P_("Extra space at the left and right edges of the menu"),
170 +                                                            0,
171 +                                                            G_MAXINT,
172 +                                                            0, /* 1, */
173 +                                                            G_PARAM_READABLE));
174 +
175 +  gtk_widget_class_install_style_property (widget_class,
176 +                                          g_param_spec_boolean ("double_arrows",
177 +                                                                P_("Double Arrows"),
178 +                                                                P_("When scrolling, always show both arrows."),
179 +                                                                FALSE,
180 +                                                                G_PARAM_READABLE));
181  }
182  
183  
184 @@ -884,13 +967,14 @@
185    menu->toggle_size = 0;
186  
187    menu->toplevel = g_object_connect (g_object_new (GTK_TYPE_WINDOW,
188 -                                                  "type", GTK_WINDOW_POPUP,
189 -                                                  "child", menu,
190 -                                                  NULL),
191 +                                    "type", GTK_WINDOW_POPUP,
192 +                                    "child", menu,
193 +                                     NULL),
194                                      "signal::event", gtk_menu_window_event, menu,
195                                      "signal::size_request", gtk_menu_window_size_request, menu,
196                                      "signal::destroy", gtk_widget_destroyed, &menu->toplevel,
197                                      NULL);
198 +
199    gtk_window_set_resizable (GTK_WINDOW (menu->toplevel), FALSE);
200    gtk_window_set_mnemonic_modifier (GTK_WINDOW (menu->toplevel), 0);
201  
202 @@ -919,6 +1003,15 @@
203    menu->lower_arrow_visible = FALSE;
204    menu->upper_arrow_prelight = FALSE;
205    menu->lower_arrow_prelight = FALSE;
206 +  
207 +  /* <Hildon> */
208 +  priv->upper_arrow_state = GTK_STATE_NORMAL;
209 +  priv->lower_arrow_state = GTK_STATE_NORMAL;
210 +
211 +  priv->context_menu = FALSE;
212 +  priv->popup_pointer_x = -1;
213 +  priv->popup_pointer_y = -1;
214 +  /* </hildon */
215  
216    priv->have_layout = FALSE;
217  }
218 @@ -1220,7 +1313,8 @@
219  
220  static gboolean
221  popup_grab_on_window (GdkWindow *window,
222 -                     guint32    activate_time)
223 +                     guint32    activate_time,
224 +                     gboolean   grab_keyboard)
225  {
226    if ((gdk_pointer_grab (window, TRUE,
227                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
228 @@ -1228,7 +1322,8 @@
229                          GDK_POINTER_MOTION_MASK,
230                          NULL, NULL, activate_time) == 0))
231      {
232 -      if (gdk_keyboard_grab (window, TRUE,
233 +      if (!grab_keyboard ||
234 +                     gdk_keyboard_grab (window, TRUE,
235                              activate_time) == 0)
236         return TRUE;
237        else
238 @@ -1282,6 +1377,7 @@
239    GtkWidget *parent;
240    GdkEvent *current_event;
241    GtkMenuShell *menu_shell;
242 +  gboolean grab_keyboard;
243    GtkMenuPrivate *priv = gtk_menu_get_private (menu);
244  
245    g_return_if_fail (GTK_IS_MENU (menu));
246 @@ -1333,10 +1429,28 @@
247     * probably could just leave the grab on the other window, with a
248     * little reorganization of the code in gtkmenu*).
249     */
250 +
251 +  grab_keyboard = gtk_menu_shell_get_take_focus (menu_shell);
252 +  gtk_window_set_accept_focus (GTK_WINDOW (menu->toplevel), grab_keyboard);
253 +  
254    if (xgrab_shell && xgrab_shell != widget)
255      {
256 -      if (popup_grab_on_window (xgrab_shell->window, activate_time))
257 +      if (popup_grab_on_window (xgrab_shell->window, activate_time, grab_keyboard))
258         GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
259 +
260 +      /* HILDON: 
261 +       * Check wheter parent is GtkMenuBar. If so,
262 +       * then we need sharp upper corners for this menu.
263 +       */
264 +      if (gtk_menu_check_name (widget))
265 +        {
266 +         if (GTK_IS_MENU_BAR (parent_menu_shell))
267 +           gtk_widget_set_name (widget, HILDON_MENU_NAME_SHARP);
268 +         else if (GTK_IS_MENU (parent_menu_shell))
269 +           gtk_widget_set_name( widget, HILDON_MENU_NAME_ROUND);
270 +         else
271 +           gtk_widget_set_name (widget, HILDON_MENU_NAME_ROUND_FIRST_LEVEL);
272 +        }
273      }
274    else
275      {
276 @@ -1344,8 +1458,14 @@
277  
278        xgrab_shell = widget;
279        transfer_window = menu_grab_transfer_window_get (menu);
280 -      if (popup_grab_on_window (transfer_window, activate_time))
281 +      if (popup_grab_on_window (transfer_window, activate_time, grab_keyboard))
282         GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
283 +
284 +      /* HILDON: 
285 +       * We want this menu to have round corners (Used by default) 
286 +       */
287 +      if (gtk_menu_check_name (widget))
288 +       gtk_widget_set_name (widget, HILDON_MENU_NAME_ROUND_FIRST_LEVEL);
289      }
290  
291    if (!GTK_MENU_SHELL (xgrab_shell)->have_xgrab)
292 @@ -1409,6 +1529,23 @@
293  
294    /* Position the menu, possibly changing the size request
295     */
296 +  if (GTK_IS_COMBO_BOX (gtk_menu_get_attach_widget (menu)))
297 +    {
298 +      /* Hildon - limit the size if the menu is attached to a ComboBox */
299 +      GtkRequisition req;
300 +      gint width, height;
301 +      
302 +      gtk_widget_set_size_request (widget, -1, -1);
303 +      gtk_widget_size_request (widget, &req);
304 +        
305 +      width = MAX (MIN (req.width, HILDON_MENU_COMBO_MAX_WIDTH),
306 +                   HILDON_MENU_COMBO_MIN_WIDTH);
307 +      height = MAX (MIN (req.height, HILDON_MENU_COMBO_MAX_HEIGHT),
308 +                   HILDON_MENU_COMBO_MIN_HEIGHT);
309 +        
310 +      gtk_widget_set_size_request (widget, width, height);
311 +   }
312 +
313    gtk_menu_position (menu);
314  
315    /* Compute the size of the toplevel and realize it so we
316 @@ -1430,13 +1567,29 @@
317  
318    gtk_menu_scroll_to (menu, menu->scroll_offset);
319  
320 +  if (priv->context_menu)
321 +    {
322 +      /* Save position of the pointer during popup */
323 +      /* currently not-multihead safe */
324 +      GdkScreen *screen;
325 +      GdkDisplay *display;
326 +      
327 +      screen = gtk_widget_get_screen (widget);
328 +      display = gdk_screen_get_display (screen);
329 +  
330 +      gdk_display_get_pointer (display, NULL,
331 +                               &priv->popup_pointer_x,
332 +                               &priv->popup_pointer_y,
333 +                               NULL);
334 +    }
335 +
336    /* Once everything is set up correctly, map the toplevel window on
337       the screen.
338     */
339    gtk_widget_show (menu->toplevel);
340  
341    if (xgrab_shell == widget)
342 -    popup_grab_on_window (widget->window, activate_time); /* Should always succeed */
343 +    popup_grab_on_window (widget->window, activate_time, grab_keyboard); /* Should always succeed */
344    gtk_grab_add (GTK_WIDGET (menu));
345  }
346  
347 @@ -1996,6 +2149,7 @@
348    GtkWidget *child;
349    GList *children;
350    guint vertical_padding;
351 +  guint horizontal_padding;
352    
353    g_return_if_fail (GTK_IS_MENU (widget));
354  
355 @@ -2025,9 +2179,10 @@
356  
357    gtk_widget_style_get (GTK_WIDGET (menu),
358                         "vertical-padding", &vertical_padding,
359 +                       "horizontal-padding", &horizontal_padding,
360                         NULL);
361    
362 -  attributes.x = border_width + widget->style->xthickness;
363 +  attributes.x = border_width + widget->style->xthickness + horizontal_padding;
364    attributes.y = border_width + widget->style->ythickness + vertical_padding;
365    attributes.width = MAX (1, widget->allocation.width - attributes.x * 2);
366    attributes.height = MAX (1, widget->allocation.height - attributes.y * 2);
367 @@ -2040,11 +2195,14 @@
368    if (menu->lower_arrow_visible)
369      attributes.height -= MENU_SCROLL_ARROW_HEIGHT;
370  
371 +  attributes.window_type = GDK_WINDOW_CHILD;
372 +
373    menu->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
374    gdk_window_set_user_data (menu->view_window, menu);
375  
376    attributes.x = 0;
377    attributes.y = 0;
378 +  attributes.width = MAX (1, widget->requisition.width - (border_width + widget->style->xthickness + horizontal_padding) * 2);
379    attributes.height = MAX (1, widget->requisition.height - (border_width + widget->style->ythickness + vertical_padding) * 2);
380    
381    menu->bin_window = gdk_window_new (menu->view_window, &attributes, attributes_mask);
382 @@ -2164,6 +2322,10 @@
383    guint vertical_padding;
384    GtkRequisition child_requisition;
385    GtkMenuPrivate *priv;
386 +  guint horizontal_padding;
387 +  GdkScreen *screen;
388 +  GdkRectangle monitor;
389 +  gint monitor_num;
390    
391    g_return_if_fail (GTK_IS_MENU (widget));
392    g_return_if_fail (requisition != NULL);
393 @@ -2182,6 +2344,16 @@
394    priv->heights = g_new0 (guint, gtk_menu_get_n_rows (menu));
395    priv->heights_length = gtk_menu_get_n_rows (menu);
396  
397 +/* Hildon addition to find out the monitor width */
398 +   screen = gtk_widget_get_screen (widget);
399 +   if (widget->window != NULL)
400 +     monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
401 +   else
402 +     monitor_num = 0;
403 +   if (monitor_num < 0)
404 +     monitor_num = 0;
405 +   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
406 +
407    children = menu_shell->children;
408    while (children)
409      {
410 @@ -2223,15 +2395,18 @@
411  
412    requisition->width += max_toggle_size + max_accel_width;
413    requisition->width *= gtk_menu_get_n_columns (menu);
414 -  requisition->width += (GTK_CONTAINER (menu)->border_width +
415 -                        widget->style->xthickness) * 2;
416  
417    gtk_widget_style_get (GTK_WIDGET (menu),
418 +                       "horizontal-padding", &horizontal_padding,
419                         "vertical-padding", &vertical_padding,
420                         NULL);
421 +  requisition->width += (GTK_CONTAINER (menu)->border_width + horizontal_padding +
422 +                        widget->style->xthickness) * 2;
423    requisition->height += (GTK_CONTAINER (menu)->border_width + vertical_padding +
424                           widget->style->ythickness) * 2;
425    
426 +/* Hildon addition to not make the menu too wide for the screen. */
427 +  requisition->width = MIN (requisition->width, monitor.width);
428    menu->toggle_size = max_toggle_size;
429  
430    /* Don't resize the tearoff if it is not active, because it won't redraw (it is only a background pixmap).
431 @@ -2253,6 +2428,7 @@
432    GList *children;
433    gint x, y;
434    gint width, height;
435 +  guint horizontal_padding;
436    guint vertical_padding;
437  
438    g_return_if_fail (GTK_IS_MENU (widget));
439 @@ -2266,10 +2442,11 @@
440    gtk_widget_get_child_requisition (GTK_WIDGET (menu), &child_requisition);
441  
442    gtk_widget_style_get (GTK_WIDGET (menu),
443 +                       "horizontal-padding", &horizontal_padding,
444                         "vertical-padding", &vertical_padding,
445                         NULL);
446    
447 -  x = GTK_CONTAINER (menu)->border_width + widget->style->xthickness;
448 +  x = GTK_CONTAINER (menu)->border_width + widget->style->xthickness + horizontal_padding;
449    y = GTK_CONTAINER (menu)->border_width + widget->style->ythickness + vertical_padding;
450  
451    width = MAX (1, allocation->width - x * 2);
452 @@ -2407,27 +2584,32 @@
453                 GdkEventExpose *event)
454  {
455    GtkMenu *menu;
456 -  gint width, height;
457 -  gint border_x, border_y;
458 -  guint vertical_padding;
459    
460    g_return_if_fail (GTK_IS_MENU (widget));
461  
462    menu = GTK_MENU (widget);
463  
464 -  gtk_widget_style_get (GTK_WIDGET (menu),
465 -                       "vertical-padding", &vertical_padding,
466 -                       NULL);
467 -  
468 -  border_x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
469 -  border_y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness + vertical_padding;
470 -  gdk_drawable_get_size (widget->window, &width, &height);
471 -
472    if (event->window == widget->window)
473      {
474 +      gint width, height;
475 +      gint border_x, border_y;
476 +      guint vertical_padding;
477 +      guint horizontal_padding;
478 +      GtkMenuPrivate *priv;
479        gint arrow_space = MENU_SCROLL_ARROW_HEIGHT - 2 * widget->style->ythickness;
480        gint arrow_size = 0.7 * arrow_space;
481         
482 +      priv = gtk_menu_get_private (menu);
483 +
484 +      gtk_widget_style_get (GTK_WIDGET (menu),
485 +                           "vertical-padding", &vertical_padding,
486 +                           "horizontal-padding", &horizontal_padding,
487 +                           NULL);
488 +  
489 +      border_x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness + horizontal_padding;
490 +      border_y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness + vertical_padding;
491 +      gdk_drawable_get_size (widget->window, &width, &height);
492 +
493        gtk_paint_box (widget->style,
494                      widget->window,
495                      GTK_STATE_NORMAL,
496 @@ -2436,21 +2618,9 @@
497                      0, 0, -1, -1);
498        if (menu->upper_arrow_visible && !menu->tearoff_active)
499         {
500 -         gtk_paint_box (widget->style,
501 -                        widget->window,
502 -                        menu->upper_arrow_prelight ?
503 -                        GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
504 -                        GTK_SHADOW_OUT,
505 -                        NULL, widget, "menu",
506 -                        border_x,
507 -                        border_y,
508 -                        width - 2 * border_x,
509 -                        MENU_SCROLL_ARROW_HEIGHT);
510 -         
511           gtk_paint_arrow (widget->style,
512                            widget->window,
513 -                          menu->upper_arrow_prelight ?
514 -                          GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
515 +                          priv->upper_arrow_state,
516                            GTK_SHADOW_OUT,
517                            NULL, widget, "menu_scroll_arrow_up",
518                            GTK_ARROW_UP,
519 @@ -2462,21 +2632,9 @@
520    
521        if (menu->lower_arrow_visible && !menu->tearoff_active)
522         {
523 -         gtk_paint_box (widget->style,
524 -                        widget->window,
525 -                        menu->lower_arrow_prelight ?
526 -                        GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
527 -                        GTK_SHADOW_OUT,
528 -                        NULL, widget, "menu",
529 -                        border_x,
530 -                        height - border_y - MENU_SCROLL_ARROW_HEIGHT,
531 -                        width - 2*border_x,
532 -                        MENU_SCROLL_ARROW_HEIGHT);
533 -         
534           gtk_paint_arrow (widget->style,
535                            widget->window,
536 -                          menu->lower_arrow_prelight ?
537 -                          GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
538 +                          priv->lower_arrow_state,
539                            GTK_SHADOW_OUT,
540                            NULL, widget, "menu_scroll_arrow_down",
541                            GTK_ARROW_DOWN,
542 @@ -2516,18 +2674,82 @@
543    GTK_WIDGET_CLASS (parent_class)->show (widget);
544  }
545  
546 +static GtkWidget *
547 +find_active_menu_item (GdkEventButton *event)
548 +{
549 +  GtkWidget *menu_item;
550 +      
551 +  menu_item = gtk_get_event_widget ((GdkEvent*) event);
552 +  while (menu_item && !GTK_IS_MENU_ITEM (menu_item))
553 +    menu_item = menu_item->parent;
554 +
555 +  return menu_item;
556 +}
557 +
558 +static gboolean
559 +pointer_in_menu_tree (GtkWidget *widget)
560 +{
561 +  GtkMenuShell *mshell;
562 +  int width, height, x, y;
563 +  
564 +  mshell = GTK_MENU_SHELL (widget);
565 +
566 +  gdk_window_get_pointer (widget->window, &x, &y, NULL);
567 +  gdk_drawable_get_size (widget->window, &width, &height);
568 +
569 +  if ((x <= width) && (x >= 0) && (y <= height) && (y >= 0))
570 +    return TRUE;
571 +
572 +  if ((mshell->parent_menu_shell != NULL) &&
573 +      GTK_IS_MENU (mshell->parent_menu_shell))
574 +    return pointer_in_menu_tree (mshell->parent_menu_shell);
575 +
576 +  return FALSE;
577 +}
578 +
579 +static int
580 +distance_traveled (GtkWidget *widget)
581 +{
582 +  GtkMenuPrivate *priv;
583 +  GdkScreen *screen;
584 +  GdkDisplay *display;
585 +  int x, y, dx, dy;
586 +
587 +  priv = gtk_menu_get_private (GTK_MENU (widget));
588 +    
589 +  screen = gtk_widget_get_screen (widget);
590 +  display = gdk_screen_get_display (screen);
591 +  
592 +  gdk_display_get_pointer (display, NULL, &x, &y, NULL);
593 +
594 +  dx = (priv->popup_pointer_x - x);
595 +  dy = (priv->popup_pointer_y - y);
596 +
597 +  return abs ((int) sqrt ((double) (dx * dx + dy * dy)));
598 +}
599 +
600  static gboolean
601  gtk_menu_button_press (GtkWidget      *widget,
602 -                        GdkEventButton *event)
603 +                       GdkEventButton *event)
604  {
605 -  /* Don't pop down the menu for releases over scroll arrows
606 -   */
607 -  if (GTK_IS_MENU (widget))
608 +  GtkWidget *menu_item;
609 +
610 +  menu_item = find_active_menu_item (event);
611 +  if (menu_item == NULL)
612      {
613        GtkMenu *menu = GTK_MENU (widget);
614  
615 -      if (menu->upper_arrow_prelight ||  menu->lower_arrow_prelight)
616 -       return TRUE;
617 +      if (menu->upper_arrow_prelight || menu->lower_arrow_prelight)
618 +        {
619 +         gtk_menu_handle_scrolling (GTK_MENU (widget), event->x_root, event->y_root, TRUE, FALSE);
620 +
621 +         return TRUE;
622 +       }
623 +
624 +      /* Don't pass down to menu shell if a non-menuitem part
625 +       * of the menu was clicked. */
626 +      if (pointer_in_menu_tree (widget))
627 +        return TRUE;
628      }
629  
630    return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
631 @@ -2537,14 +2759,44 @@
632  gtk_menu_button_release (GtkWidget      *widget,
633                          GdkEventButton *event)
634  {
635 -  /* Don't pop down the menu for releases over scroll arrows
636 -   */
637 -  if (GTK_IS_MENU (widget))
638 +  GtkMenuPrivate *priv;
639 +  GtkWidget *menu_item;
640 +
641 +  priv = gtk_menu_get_private (GTK_MENU (widget));
642 +
643 +  menu_item = find_active_menu_item (event);
644 +  if (menu_item == NULL)
645      {
646        GtkMenu *menu = GTK_MENU (widget);
647  
648 -      if (menu->upper_arrow_prelight ||  menu->lower_arrow_prelight)
649 -       return TRUE;
650 +      if (menu->upper_arrow_prelight || menu->lower_arrow_prelight)
651 +        {
652 +         gtk_menu_handle_scrolling (GTK_MENU (widget), event->x_root, event->y_root, FALSE, FALSE);
653 +
654 +         return TRUE;
655 +        }
656 +
657 +      if (priv->context_menu &&
658 +          (priv->popup_pointer_x >= 0) &&
659 +          (priv->popup_pointer_y >= 0))
660 +        {
661 +          int distance;
662 +
663 +          distance = distance_traveled (widget);
664 +
665 +          priv->popup_pointer_x = -1;
666 +          priv->popup_pointer_y = -1;
667 +          
668 +          /* Don't popdown if we traveled less than 20px since popup point,
669 +           * as per the specs. */
670 +          if (distance < 20)
671 +            return TRUE;
672 +        }
673 +
674 +      /* Don't pass down to menu shell if a non-menuitem part
675 +       * of the menu was clicked. */
676 +      if (pointer_in_menu_tree (widget))
677 +        return TRUE;
678      }
679  
680    return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
681 @@ -2765,7 +3017,7 @@
682    gboolean need_enter;
683  
684    if (GTK_IS_MENU (widget))
685 -    gtk_menu_handle_scrolling (GTK_MENU (widget), event->x_root, event->y_root, TRUE);
686 +    gtk_menu_handle_scrolling (GTK_MENU (widget), event->x_root, event->y_root, TRUE, TRUE);
687  
688    /* We received the event for one of two reasons:
689     *
690 @@ -2779,7 +3031,27 @@
691    menu_item = gtk_get_event_widget ((GdkEvent*) event);
692    if (!menu_item || !GTK_IS_MENU_ITEM (menu_item) ||
693        !GTK_IS_MENU (menu_item->parent))
694 -    return FALSE;
695 +    {
696 +      GtkMenuPrivate *priv;
697 +      
698 +      priv = gtk_menu_get_private (GTK_MENU (widget));
699 +      
700 +      if (priv->context_menu)
701 +        {
702 +          /* Context menu mode. If we dragged out of the menu,
703 +           * close the menu, as by the specs. */
704 +          if (!pointer_in_menu_tree (widget) && 
705 +              (distance_traveled (widget) >= 20) &&
706 +              (event->state & GDK_BUTTON1_MASK))
707 +            {
708 +              gtk_menu_deactivate (GTK_MENU_SHELL (widget));
709 +
710 +              return TRUE;
711 +            }
712 +        }
713 +      
714 +      return FALSE;
715 +    }
716  
717    menu_shell = GTK_MENU_SHELL (menu_item->parent);
718    menu = GTK_MENU (menu_shell);
719 @@ -2795,6 +3067,11 @@
720     */
721    if (gtk_menu_navigating_submenu (menu, event->x_root, event->y_root))
722      return TRUE; 
723 +/* HILDON MOD.
724 + * Close the submenus that are two levels down from the currently selected.
725 + * This ensures that the focus is correct all the time.*/
726 +  if (GTK_MENU_ITEM(menu_item)->submenu != NULL)
727 +        gtk_menu_shell_deselect (GTK_MENU_SHELL(&(GTK_MENU(GTK_MENU_ITEM(menu_item)->submenu)->menu_shell)));
728  
729    /* Make sure we pop down if we enter a non-selectable menu item, so we
730     * don't show a submenu when the cursor is outside the stay-up triangle.
731 @@ -2828,6 +3105,7 @@
732           send_event->crossing.y_root = event->y_root;
733           send_event->crossing.x = event->x;
734           send_event->crossing.y = event->y;
735 +          send_event->crossing.state = event->state;
736  
737           /* We send the event to 'widget', the currently active menu,
738            * instead of 'menu', the menu that the pointer is in. This
739 @@ -2852,17 +3130,24 @@
740    GtkWidget *widget;
741    gint offset;
742    gint view_width, view_height;
743 +  gboolean double_arrows;
744  
745    widget = GTK_WIDGET (menu);
746    offset = menu->scroll_offset + step;
747  
748 +  /* get double_arrows style property */
749 +  gtk_widget_style_get (widget,
750 +                       "double_arrows", &double_arrows,
751 +                       NULL);
752 +
753    /* If we scroll upward and the non-visible top part
754     * is smaller than the scroll arrow it would be
755     * pretty stupid to show the arrow and taking more
756     * screen space than just scrolling to the top.
757     */
758 -  if ((step < 0) && (offset < MENU_SCROLL_ARROW_HEIGHT))
759 -    offset = 0;
760 +  if (!double_arrows)
761 +    if ((step < 0) && (offset < MENU_SCROLL_ARROW_HEIGHT))
762 +      offset = 0;
763  
764    /* Don't scroll over the top if we weren't before: */
765    if ((menu->scroll_offset >= 0) && (offset < 0))
766 @@ -2874,6 +3159,12 @@
767    if (menu->scroll_offset > 0)
768      view_height -= MENU_SCROLL_ARROW_HEIGHT;
769    
770 +  /* When both arrows are always shown, reduce
771 +   * view height even more.
772 +   */
773 +  if (double_arrows)
774 +    view_height -= MENU_SCROLL_ARROW_HEIGHT;
775 +
776    if ((menu->scroll_offset + view_height <= widget->requisition.height) &&
777        (offset + view_height > widget->requisition.height))
778      offset = widget->requisition.height - view_height;
779 @@ -2922,18 +3213,21 @@
780  gtk_menu_handle_scrolling (GtkMenu *menu,
781                            gint x,
782                            gint y,
783 -                          gboolean enter)
784 +                          gboolean enter,
785 +                           gboolean motion)
786  {
787    GtkMenuShell *menu_shell;
788 +  GtkMenuPrivate *priv;
789    gint width, height;
790    gint border;
791    GdkRectangle rect;
792 -  gboolean in_arrow;
793    gboolean scroll_fast = FALSE;
794    guint vertical_padding;
795    gint top_x, top_y;
796    gint win_x, win_y;
797  
798 +  priv = gtk_menu_get_private (menu);
799 +
800    menu_shell = GTK_MENU_SHELL (menu);
801  
802    gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height);
803 @@ -2946,10 +3240,11 @@
804      GTK_WIDGET (menu)->style->ythickness + vertical_padding;
805  
806    gdk_window_get_position (menu->toplevel->window, &top_x, &top_y);
807 +  x -= top_x;
808 +  y -= top_y;
809 +
810    gdk_window_get_position (GTK_WIDGET (menu)->window, &win_x, &win_y);
811 -  win_x += top_x;
812 -  win_y += top_y;
813 -  
814 +
815    if (menu->upper_arrow_visible && !menu->tearoff_active)
816      {
817        rect.x = win_x;
818 @@ -2957,35 +3252,49 @@
819        rect.width = width;
820        rect.height = MENU_SCROLL_ARROW_HEIGHT + border;
821        
822 -      in_arrow = FALSE;
823 +      menu->upper_arrow_prelight = FALSE;
824        if ((x >= rect.x) && (x < rect.x + rect.width) &&
825           (y >= rect.y) && (y < rect.y + rect.height))
826 -       {
827 -         in_arrow = TRUE;
828 -         scroll_fast = (y < rect.y + MENU_SCROLL_FAST_ZONE);
829 -       }
830 -       
831 -      if (enter && in_arrow &&
832 -         (!menu->upper_arrow_prelight || menu->scroll_fast != scroll_fast))
833 -       {
834 -         menu->upper_arrow_prelight = TRUE;
835 -         menu->scroll_fast = scroll_fast;
836 -         gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
837 -         
838 -         /* Deselect the active item so that any submenus are poped down */
839 -         gtk_menu_shell_deselect (menu_shell);
840 +        menu->upper_arrow_prelight = TRUE;
841  
842 -         gtk_menu_remove_scroll_timeout (menu);
843 -         menu->scroll_step = (scroll_fast) ? -MENU_SCROLL_STEP2 : -MENU_SCROLL_STEP1;
844 -         menu->timeout_id = g_timeout_add ((scroll_fast) ? MENU_SCROLL_TIMEOUT2 : MENU_SCROLL_TIMEOUT1,
845 -                                           gtk_menu_scroll_timeout,
846 -                                           menu);
847 -       }
848 -      else if (!enter && !in_arrow && menu->upper_arrow_prelight)
849 +      if (priv->upper_arrow_state != GTK_STATE_INSENSITIVE)
850         {
851 -         gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
852 -         
853 -         gtk_menu_stop_scrolling (menu);
854 +         if (enter && menu->upper_arrow_prelight &&
855 +             (menu->timeout_id == 0 || menu->scroll_fast != scroll_fast))
856 +           {
857 +             menu->scroll_fast = scroll_fast;
858 +             
859 +             /* Deselect the active item so that any submenus are poped down */
860 +             gtk_menu_shell_deselect (menu_shell);
861 +
862 +             gtk_menu_remove_scroll_timeout (menu);
863 +             menu->scroll_step = (scroll_fast) ? -MENU_SCROLL_STEP2 : -MENU_SCROLL_STEP1;
864 +
865 +             if (!motion)
866 +               {
867 +                 /* Only do stuff on click. */
868 +                 GtkSettings *settings;
869 +                 guint timeout;
870 +                 
871 +                 settings = gtk_settings_get_default ();
872 +                 g_object_get (settings, "gtk-update-timeout", &timeout, NULL);
873 +
874 +                 menu->timeout_id = g_timeout_add (timeout / 2, gtk_menu_scroll_timeout, menu);
875 +
876 +                 priv->upper_arrow_state = GTK_STATE_ACTIVE;
877 +               }
878 +
879 +             gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
880 +           }
881 +         else if (!enter)
882 +           {
883 +             gtk_menu_stop_scrolling (menu);
884 +
885 +             priv->upper_arrow_state = menu->upper_arrow_prelight ?
886 +                                           GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
887 +
888 +             gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
889 +           }
890         }
891      }
892    
893 @@ -2996,36 +3305,50 @@
894        rect.width = width;
895        rect.height = MENU_SCROLL_ARROW_HEIGHT + border;
896  
897 -      in_arrow = FALSE;
898 +      menu->lower_arrow_prelight = FALSE;
899        if ((x >= rect.x) && (x < rect.x + rect.width) &&
900           (y >= rect.y) && (y < rect.y + rect.height))
901 -       {
902 -         in_arrow = TRUE;
903 -         scroll_fast = (y > rect.y + rect.height - MENU_SCROLL_FAST_ZONE);
904 -       }
905 +        menu->lower_arrow_prelight = TRUE;
906  
907 -      if (enter && in_arrow &&
908 -         (!menu->lower_arrow_prelight || menu->scroll_fast != scroll_fast))
909 +      if (priv->lower_arrow_state != GTK_STATE_INSENSITIVE)
910         {
911 -         menu->lower_arrow_prelight = TRUE;
912 -         menu->scroll_fast = scroll_fast;
913 -         gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
914 +         if (enter && menu->lower_arrow_prelight &&
915 +             (menu->timeout_id == 0 || menu->scroll_fast != scroll_fast))
916 +           {
917 +             menu->scroll_fast = scroll_fast;
918  
919 -         /* Deselect the active item so that any submenus are poped down */
920 -         gtk_menu_shell_deselect (menu_shell);
921 +             /* Deselect the active item so that any submenus are poped down */
922 +             gtk_menu_shell_deselect (menu_shell);
923  
924 -         gtk_menu_remove_scroll_timeout (menu);
925 -         menu->scroll_step = (scroll_fast) ? MENU_SCROLL_STEP2 : MENU_SCROLL_STEP1;
926 -         menu->timeout_id = g_timeout_add ((scroll_fast) ? MENU_SCROLL_TIMEOUT2 : MENU_SCROLL_TIMEOUT1,
927 -                                           gtk_menu_scroll_timeout,
928 -                                           menu);
929 -       }
930 -      else if (!enter && !in_arrow && menu->lower_arrow_prelight)
931 -       {
932 -         gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
933 -         
934 -         gtk_menu_stop_scrolling (menu);
935 -       }
936 +             gtk_menu_remove_scroll_timeout (menu);
937 +             menu->scroll_step = (scroll_fast) ? MENU_SCROLL_STEP2 : MENU_SCROLL_STEP1;
938 +
939 +             if (!motion)
940 +               { 
941 +                 /* Only do stuff on click. */
942 +                 GtkSettings *settings;
943 +                 guint timeout;
944 +                 
945 +                 settings = gtk_settings_get_default ();
946 +                 g_object_get (settings, "gtk-update-timeout", &timeout, NULL);
947 +
948 +                 menu->timeout_id = g_timeout_add (timeout / 2, gtk_menu_scroll_timeout, menu);
949 +
950 +                 priv->lower_arrow_state = GTK_STATE_ACTIVE;
951 +               }
952 +
953 +             gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
954 +           }
955 +         else if (!enter)
956 +           {
957 +             gtk_menu_stop_scrolling (menu);
958 +             
959 +             priv->lower_arrow_state = menu->lower_arrow_prelight ?
960 +                                           GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
961 +
962 +             gdk_window_invalidate_rect (GTK_WIDGET (menu)->window, &rect, FALSE);
963 +           }
964 +        }
965      }
966  }
967  
968 @@ -3041,7 +3364,7 @@
969        GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
970  
971        if (!menu_shell->ignore_enter)
972 -       gtk_menu_handle_scrolling (GTK_MENU (widget), event->x_root, event->y_root, TRUE);
973 +       gtk_menu_handle_scrolling (GTK_MENU (widget), event->x_root, event->y_root, TRUE, TRUE);
974      }
975  
976    if (menu_item && GTK_IS_MENU_ITEM (menu_item))
977 @@ -3106,7 +3429,7 @@
978    if (gtk_menu_navigating_submenu (menu, event->x_root, event->y_root))
979      return TRUE; 
980  
981 -  gtk_menu_handle_scrolling (menu, event->x_root, event->y_root, FALSE);
982 +  gtk_menu_handle_scrolling (menu, event->x_root, event->y_root, FALSE, TRUE);
983    
984    event_widget = gtk_get_event_widget ((GdkEvent*) event);
985    
986 @@ -3611,7 +3934,13 @@
987                          requisition.width, requisition.height);
988      }
989    
990 -  menu->scroll_offset = scroll_offset;
991 +  /* Hildon hack for menu in comboboxes:
992 +   * in case the menu in attached to a ComboBox, the scroll_offset is
993 +   * calculated in the positioning function so we dont't overwrite it
994 +   * with the value calculated above (in this function) */
995 +  if ( !GTK_IS_COMBO_BOX(gtk_menu_get_attach_widget(menu)) )
996 +      menu->scroll_offset = scroll_offset;
997 +  
998  }
999  
1000  static void
1001 @@ -3628,9 +3957,6 @@
1002  gtk_menu_stop_scrolling (GtkMenu *menu)
1003  {
1004    gtk_menu_remove_scroll_timeout (menu);
1005 -
1006 -  menu->upper_arrow_prelight = FALSE;
1007 -  menu->lower_arrow_prelight = FALSE;
1008  }
1009  
1010  static void
1011 @@ -3644,6 +3970,8 @@
1012    gboolean last_visible;
1013    gint menu_height;
1014    guint vertical_padding;
1015 +  guint horizontal_padding;
1016 +  gboolean double_arrows;
1017  
1018    widget = GTK_WIDGET (menu);
1019  
1020 @@ -3663,19 +3991,93 @@
1021  
1022    gtk_widget_style_get (GTK_WIDGET (menu),
1023                         "vertical-padding", &vertical_padding,
1024 +                       "horizontal-padding", &horizontal_padding,
1025 +                       "double_arrows", &double_arrows,
1026                         NULL);
1027    
1028    border_width = GTK_CONTAINER (menu)->border_width;
1029 -  view_width -= (border_width + widget->style->xthickness) * 2;
1030 +  view_width -= (border_width + widget->style->xthickness + horizontal_padding) * 2;
1031    view_height -= (border_width + widget->style->ythickness + vertical_padding) * 2;
1032    menu_height = widget->requisition.height -
1033        (border_width + widget->style->ythickness + vertical_padding) * 2;
1034  
1035 -  x = border_width + widget->style->xthickness;
1036 +  x = border_width + widget->style->xthickness + horizontal_padding;
1037    y = border_width + widget->style->ythickness + vertical_padding;
1038  
1039 +  if (double_arrows && !menu->tearoff_active && (view_height < menu_height))
1040 +  {
1041 +    GtkMenuPrivate *priv;
1042 +    GtkStateType upper_arrow_previous_state, lower_arrow_previous_state;
1043 +    
1044 +    priv = gtk_menu_get_private (menu);
1045 +    
1046 +    upper_arrow_previous_state = priv->upper_arrow_state;
1047 +    lower_arrow_previous_state = priv->lower_arrow_state;
1048 +    
1049 +    if (!menu->upper_arrow_visible || !menu->lower_arrow_visible)
1050 +      gtk_widget_queue_draw (GTK_WIDGET (menu));
1051 +    
1052 +    view_height -= 2*MENU_SCROLL_ARROW_HEIGHT;
1053 +    y += MENU_SCROLL_ARROW_HEIGHT;
1054 +
1055 +    menu->upper_arrow_visible = menu->lower_arrow_visible = TRUE;    
1056 +    if (priv->upper_arrow_state == GTK_STATE_INSENSITIVE)
1057 +      {
1058 +        priv->upper_arrow_state = menu->upper_arrow_prelight ?
1059 +                                    GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
1060 +      }
1061 +    if (priv->lower_arrow_state == GTK_STATE_INSENSITIVE)
1062 +      {
1063 +        priv->lower_arrow_state = menu->lower_arrow_prelight ?
1064 +                                    GTK_STATE_PRELIGHT : GTK_STATE_NORMAL;
1065 +      }
1066 +
1067 +    if (offset <= 0) 
1068 +    {
1069 +      offset = 0;
1070 +      priv->upper_arrow_state = GTK_STATE_INSENSITIVE;
1071 +    }
1072 +    if (offset >= menu_height - view_height)
1073 +    { 
1074 +      offset = menu_height - view_height;
1075 +      priv->lower_arrow_state = GTK_STATE_INSENSITIVE;
1076 +    }
1077 +    
1078 +    if ((priv->upper_arrow_state != upper_arrow_previous_state) ||
1079 +        (priv->lower_arrow_state != lower_arrow_previous_state))
1080 +      gtk_widget_queue_draw (GTK_WIDGET (menu));
1081 +    
1082 +    if (upper_arrow_previous_state != GTK_STATE_INSENSITIVE &&
1083 +       priv->upper_arrow_state == GTK_STATE_INSENSITIVE)
1084 +      {
1085 +       /* If we hid the upper arrow, possibly remove timeout */
1086 +       if (menu->scroll_step < 0)
1087 +         {
1088 +           gtk_menu_stop_scrolling (menu);
1089 +           gtk_widget_queue_draw (GTK_WIDGET (menu));
1090 +         }
1091 +      }
1092 +
1093 +    if (lower_arrow_previous_state != GTK_STATE_INSENSITIVE &&
1094 +       priv->lower_arrow_state == GTK_STATE_INSENSITIVE)
1095 +      {
1096 +       /* If we hid the lower arrow, possibly remove timeout */
1097 +       if (menu->scroll_step > 0)
1098 +         {
1099 +           gtk_menu_stop_scrolling (menu);
1100 +           gtk_widget_queue_draw (GTK_WIDGET (menu));
1101 +         }
1102 +      }
1103 +  }
1104 +  else
1105    if (!menu->tearoff_active)
1106      {
1107 +      if (offset <= 0) 
1108 +        offset = 0;
1109 +
1110 +      if (offset >= menu_height - view_height)
1111 +        offset = menu_height - view_height;
1112 +
1113        last_visible = menu->upper_arrow_visible;
1114        menu->upper_arrow_visible = offset > 0;
1115        
1116 @@ -3685,8 +4087,6 @@
1117        if ( (last_visible != menu->upper_arrow_visible) &&
1118            !menu->upper_arrow_visible)
1119         {
1120 -         menu->upper_arrow_prelight = FALSE;
1121 -         
1122           /* If we hid the upper arrow, possibly remove timeout */
1123           if (menu->scroll_step < 0)
1124             {
1125 @@ -3704,8 +4104,6 @@
1126        if ( (last_visible != menu->lower_arrow_visible) &&
1127            !menu->lower_arrow_visible)
1128         {
1129 -         menu->lower_arrow_prelight = FALSE;
1130 -         
1131           /* If we hid the lower arrow, possibly remove timeout */
1132           if (menu->scroll_step > 0)
1133             {
1134 @@ -3792,12 +4190,14 @@
1135                             &child_offset, &child_height, &last_child))
1136      {
1137        guint vertical_padding;
1138 +      gboolean double_arrows;
1139        
1140        y = menu->scroll_offset;
1141        gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height);
1142  
1143        gtk_widget_style_get (GTK_WIDGET (menu),
1144                             "vertical-padding", &vertical_padding,
1145 +                           "double_arrows", &double_arrows,
1146                             NULL);
1147                             
1148        height -= 2*GTK_CONTAINER (menu)->border_width + 2*GTK_WIDGET (menu)->style->ythickness + 2*vertical_padding;
1149 @@ -3820,11 +4220,11 @@
1150           if (child_offset + child_height > y + height - arrow_height)
1151             {
1152               arrow_height = 0;
1153 -             if (!last_child && !menu->tearoff_active)
1154 +             if ((!last_child && !menu->tearoff_active) || (double_arrows))
1155                 arrow_height += MENU_SCROLL_ARROW_HEIGHT;
1156               
1157               y = child_offset + child_height - height + arrow_height;
1158 -             if ((y > 0) && !menu->tearoff_active)
1159 +             if (((y > 0) && !menu->tearoff_active) || (double_arrows))
1160                 {
1161                   /* Need upper arrow */
1162                   arrow_height += MENU_SCROLL_ARROW_HEIGHT;
1163 @@ -4374,3 +4774,60 @@
1164    return list;
1165  }
1166  
1167 +/* Little help function for making some sanity tests on this menu.
1168 + * Checks that given widget really is a menu and that it has no name 
1169 + * assigned to it yet.
1170 + * Names used to do hildon theming:
1171 + * HILDON_MENU_NAME_SHARP for menu with sharp upper corners
1172 + * HILDON_MENU_NAME_ROUND for menu with round corners
1173 + */
1174 +static gboolean 
1175 +gtk_menu_check_name (GtkWidget *widget) 
1176 +{
1177 +  gboolean legal_name = FALSE;
1178 +  gchar **tmp = NULL;
1179 +  const gchar *name = NULL;
1180 +  static gchar *menu_names[] = { "GtkMenu",
1181 +                                HILDON_MENU_NAME_SHARP,
1182 +                                HILDON_MENU_NAME_ROUND,
1183 +                                HILDON_MENU_NAME_ROUND_FIRST_LEVEL,
1184 +                                NULL };
1185 +  if (GTK_IS_MENU (widget) &&
1186 +       (name = gtk_widget_get_name (widget)))
1187 +    {
1188 +      if (!g_ascii_strcasecmp (name, HILDON_MENU_NAME_FORCE_SHARP) || !g_ascii_strcasecmp (name, HILDON_MENU_NAME_FORCE_ROUND))
1189 +       return FALSE;
1190 +      for (tmp = menu_names; *tmp; tmp++) 
1191 +        if (!g_ascii_strcasecmp (name, *tmp ))
1192 +         {
1193 +           legal_name = TRUE;
1194 +           break;
1195 +          }
1196 +    }
1197 +
1198 +  return legal_name;
1199 +}
1200 +
1201 +/* A function called when esc-key is pressed. */
1202 +static void
1203 +_gtk_menu_close_current (GtkMenu * menu)
1204 +{
1205 +  GtkMenuShell * shell = GTK_MENU_SHELL (menu);
1206 +  
1207 +  /* Check is a submenu of current menu item is visible.
1208 +   * If it is, close that first. */
1209 +  if (shell->active_menu_item && (GTK_MENU_ITEM (shell->active_menu_item)->submenu) && GTK_WIDGET_VISIBLE (GTK_MENU_ITEM (shell->active_menu_item)->submenu))
1210 +    gtk_menu_popdown (GTK_MENU (GTK_MENU_ITEM (shell->active_menu_item)->submenu));
1211 +  else
1212 +    gtk_menu_popdown (menu);
1213 +
1214 +}
1215 +
1216 +/* Hildon function to make context menus behave according to spec */
1217 +void
1218 +_gtk_menu_enable_context_menu_behavior (GtkMenu *menu)
1219 +{
1220 +  GtkMenuPrivate *priv = gtk_menu_get_private (menu);
1221 +
1222 +  priv->context_menu = TRUE;
1223 +}