(emacs-uptime): Move here from time-date.el.
[bpt/emacs.git] / lwlib / xlwmenu.c
index 7b35f0c..6316b13 100644 (file)
@@ -1,6 +1,7 @@
 /* Implements a lightweight menubar widget.
-   Copyright (C) 1992 Lucid, Inc.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+Copyright (C) 1992 Lucid, Inc.
+Copyright (C) 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+  2005, 2006, 2007, 2008  Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
@@ -53,21 +54,8 @@ extern int gray_bitmap_width;
 extern int gray_bitmap_height;
 extern char *gray_bitmap_bits;
 
-/* Defined in xterm.c.  */
-extern int x_alloc_nearest_color_for_widget __P ((Widget, Colormap, XColor*));
-extern int x_alloc_lighter_color_for_widget __P ((Widget, Display*, Colormap,
-                                                 unsigned long *,
-                                                 double, int));
-extern int x_catch_errors __P ((Display*));
-extern void x_uncatch_errors P_ ((Display *, int));
-extern int x_had_errors_p __P ((Display*));
-extern void x_clear_errors __P ((Display*));
-extern unsigned long x_copy_dpy_color __P ((Display *, Colormap,
-                                           unsigned long));
-
-/* Defined in xfaces.c.  */
-extern void x_free_dpy_colors __P ((Display *, Screen *, Colormap,
-                                   unsigned long *pixels, int npixels));
+#include "xterm.h"
+
 #else /* not emacs */
 
 #include <X11/bitmaps/gray>
@@ -174,6 +162,10 @@ xlwMenuResources[] =
      offset(menu.select), XtRCallback, (XtPointer)NULL},
   {XtNhighlightCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
      offset(menu.highlight), XtRCallback, (XtPointer)NULL},
+  {XtNenterCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
+     offset(menu.enter), XtRCallback, (XtPointer)NULL},
+  {XtNleaveCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
+     offset(menu.leave), XtRCallback, (XtPointer)NULL},
   {XtNmenu, XtCMenu, XtRPointer, sizeof(XtPointer),
      offset(menu.contents), XtRImmediate, (XtPointer)NULL},
   {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
@@ -352,7 +344,7 @@ make_old_stack_space (mw, n)
 }
 
 \f/* Size code */
-int
+static int
 string_width (mw, s)
      XlwMenuWidget mw;
      char *s;
@@ -1199,8 +1191,17 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
        {
          if (val->enabled)
            *hit_return = val;
-         else
-           no_return = 1;
+         else 
+            no_return = 1;
+          if (mw->menu.inside_entry != val) 
+            {
+              if (mw->menu.inside_entry)
+                XtCallCallbackList ((Widget)mw, mw->menu.leave,
+                                    (XtPointer) mw->menu.inside_entry);
+              mw->menu.inside_entry = val;
+              XtCallCallbackList ((Widget)mw, mw->menu.enter,
+                                  (XtPointer) mw->menu.inside_entry);
+            }
        }
 
       if (horizontal_p)
@@ -1465,7 +1466,7 @@ motion_event_is_in_menu (mw, ev, level, relative_pos)
   relative_pos->x = ev->x_root - x;
   relative_pos->y = ev->y_root - y;
   return (x - shadow < ev->x_root && ev->x_root < x + ws->width
-         && y - shadow < ev->y_root && ev->y_root < y + ws->height);
+          && y - shadow < ev->y_root && ev->y_root < y + ws->height);
 }
 
 static Boolean
@@ -1478,6 +1479,7 @@ map_event_to_widget_value (mw, ev, val, level)
   int          i;
   XPoint       relative_pos;
   window_state*        ws;
+  int inside = 0;
 
   *val = NULL;
 
@@ -1487,6 +1489,7 @@ map_event_to_widget_value (mw, ev, val, level)
       ws = &mw->menu.windows [i];
       if (ws && motion_event_is_in_menu (mw, ev, i, &relative_pos))
        {
+          inside = 1;
          display_menu (mw, i, True, NULL, &relative_pos, val, NULL, NULL);
 
          if (*val)
@@ -1496,6 +1499,15 @@ map_event_to_widget_value (mw, ev, val, level)
            }
        }
     }
+
+  if (!inside) 
+    {
+      if (mw->menu.inside_entry != NULL) 
+        XtCallCallbackList ((Widget)mw, mw->menu.leave,
+                            (XtPointer) mw->menu.inside_entry);
+      mw->menu.inside_entry = NULL;
+    }
+
   return False;
 }
 
@@ -1825,7 +1837,6 @@ XlwMenuRealize (w, valueMask, attributes)
   XlwMenuWidget mw = (XlwMenuWidget)w;
   XSetWindowAttributes xswa;
   int mask;
-  int count;
 
   (*xlwMenuWidgetClass->core_class.superclass->core_class.realize)
     (w, valueMask, attributes);
@@ -1837,11 +1848,11 @@ XlwMenuRealize (w, valueMask, attributes)
      frame on a display.  I can not find their reason, but they are
      annoying so for now let's ignore any errors here.  -- lorentey  */
 #ifdef emacs
-  count = x_catch_errors (XtDisplay (w));
+  x_catch_errors (XtDisplay (w));
 #endif
   XChangeWindowAttributes (XtDisplay (w), XtWindow (w), mask, &xswa);
 #ifdef emacs
-  x_uncatch_errors (XtDisplay (w), count);
+  x_uncatch_errors ();
 #endif
 
   mw->menu.windows [0].window = XtWindow (w);
@@ -2098,6 +2109,7 @@ Start (w, ev, params, num_params)
       mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y;
 
       /* handles the down like a move, slots are compatible */
+      ev->xmotion.is_hint = 0;
       handle_motion_event (mw, &ev->xmotion);
     }
 }
@@ -2435,10 +2447,10 @@ pop_up_menu (mw, event)
   int          borderwidth = mw->menu.shadow_thickness;
   Screen*      screen = XtScreen (mw);
   Display       *display = XtDisplay (mw);
-  int count;
 
   next_release_must_exit = 0;
 
+  mw->menu.inside_entry = NULL;
   XtCallCallbackList ((Widget)mw, mw->menu.open, NULL);
 
   if (XtIsShell (XtParent ((Widget)mw)))
@@ -2482,7 +2494,7 @@ pop_up_menu (mw, event)
     }
 
 #ifdef emacs
-  count = x_catch_errors (display);
+  x_catch_errors (display);
 #endif
   if (XtGrabPointer ((Widget)mw, False,
                      (PointerMotionMask
@@ -2510,9 +2522,10 @@ pop_up_menu (mw, event)
       pointer_grabbed = 0;
       XtUngrabPointer ((Widget)mw, event->time);
     }
-  x_uncatch_errors (display, count);
+  x_uncatch_errors ();
 #endif
 
+  ((XMotionEvent*)event)->is_hint = 0;
   handle_motion_event (mw, (XMotionEvent*)event);
 }