]> code.delx.au - gnu-emacs/blobdiff - lwlib/xlwmenu.c
(motion_event_is_in_menu): Make x and y signed.
[gnu-emacs] / lwlib / xlwmenu.c
index 31773e1e00184f6451ee97327d700e0bc4640f98..c2aae8d0e61cbe07e5b1fad274cf08217af61495 100644 (file)
@@ -33,11 +33,43 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 static int pointer_grabbed;
 static XEvent menu_post_event;
 
+XFontStruct *xlwmenu_default_font;
+
 static char 
 xlwMenuTranslations [] = 
-"<BtnDown>:    start()\n\
-<Motion>:      drag()\n\
-<BtnUp>:       select()\n\
+"<BtnDown>:      start()\n\
+<Motion>:        drag()\n\
+<BtnUp>:         select()\n\
+<Key>Shift_L:     nothing()\n\
+<Key>Shift_R:     nothing()\n\
+<Key>Meta_L:      nothing()\n\
+<Key>Meta_R:      nothing()\n\
+<Key>Control_L:   nothing()\n\
+<Key>Control_R:   nothing()\n\
+<Key>Hyper_L:     nothing()\n\
+<Key>Hyper_R:     nothing()\n\
+<Key>Super_L:     nothing()\n\
+<Key>Super_R:     nothing()\n\
+<Key>Alt_L:       nothing()\n\
+<Key>Alt_R:       nothing()\n\
+<Key>Caps_Lock:   nothing()\n\
+<Key>Shift_Lock:  nothing()\n\
+<KeyUp>Shift_L:   nothing()\n\
+<KeyUp>Shift_R:   nothing()\n\
+<KeyUp>Meta_L:    nothing()\n\
+<KeyUp>Meta_R:    nothing()\n\
+<KeyUp>Control_L: nothing()\n\
+<KeyUp>Control_R: nothing()\n\
+<KeyUp>Hyper_L:   nothing()\n\
+<KeyUp>Hyper_R:   nothing()\n\
+<KeyUp>Super_L:   nothing()\n\
+<KeyUp>Super_R:   nothing()\n\
+<KeyUp>Alt_L:     nothing()\n\
+<KeyUp>Alt_R:     nothing()\n\
+<KeyUp>Caps_Lock: nothing()\n\
+<KeyUp>Shift_Lock:nothing()\n\
+<Key>:            key()\n\
+<KeyUp>:          key()\n\
 ";
 
 #define offset(field) XtOffset(XlwMenuWidget, field)
@@ -95,6 +127,8 @@ static void XlwMenuClassInitialize();
 static void Start();
 static void Drag();
 static void Select();
+static void Key();
+static void Nothing();
 
 static XtActionsRec 
 xlwMenuActionsList [] =
@@ -102,6 +136,8 @@ xlwMenuActionsList [] =
   {"start",            Start},
   {"drag",             Drag},
   {"select",           Select},
+  {"key",              Key},
+  {"nothing",          Nothing},
 };
 
 #define SuperClass ((CoreWidgetClass)&coreClassRec)
@@ -324,10 +360,10 @@ size_menu (mw, level)
      XlwMenuWidget mw;
      int level;
 {
-  int          label_width = 0;
+  unsigned int  label_width = 0;
   int          rest_width = 0;
   int          max_rest_width = 0;
-  int          height = 0;
+  unsigned int  height = 0;
   int          horizontal_p = mw->menu.horizontal && (level == 0);
   widget_value*        val;
   window_state*        ws;
@@ -484,8 +520,11 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
       width = ws->width - 2 * shadow;
     }
 
+#if 0
   /* see if it should be a button in the menubar */
   button_p = horizontal_p && val->call_data;
+#endif
+  button_p = 0;
 
   /* Only highlight an enabled item that has a callback. */
   if (highlighted_p)
@@ -516,10 +555,19 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p, just_compute
        }
       else 
        {
+         int x_offset = x + h_spacing + shadow;
          char* display_string = resource_widget_value (mw, val);
          draw_shadow_rectangle (mw, ws->window, x, y, width, height, True);
-         XDrawString (XtDisplay (mw), ws->window, text_gc,
-                      x + h_spacing + shadow,
+
+         /* Deal with centering a menu title. */
+         if (!horizontal_p && !val->contents && !val->call_data)
+           {
+             int l = string_width (mw, display_string);
+
+             if (width > l)
+               x_offset = (width - l) >> 1;
+           }
+          XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset,
                       y + v_spacing + shadow + font_ascent,
                       display_string, strlen (display_string));
          
@@ -730,8 +778,8 @@ fit_to_screen (mw, ws, previous_ws, horizontal_p)
      window_state* previous_ws;
      Boolean horizontal_p;
 {
-  int screen_width = WidthOfScreen (XtScreen (mw));
-  int screen_height = HeightOfScreen (XtScreen (mw));
+  unsigned int screen_width = WidthOfScreen (XtScreen (mw));
+  unsigned int screen_height = HeightOfScreen (XtScreen (mw));
 
   if (ws->x < 0)
     ws->x = 0;
@@ -741,6 +789,8 @@ fit_to_screen (mw, ws, previous_ws, horizontal_p)
        ws->x = previous_ws->x - ws->width;
       else
        ws->x = screen_width - ws->width;
+      if (ws->x < 0)
+        ws->x = 0;
     }
   if (ws->y < 0)
     ws->y = 0;
@@ -750,6 +800,8 @@ fit_to_screen (mw, ws, previous_ws, horizontal_p)
        ws->y = previous_ws->y - ws->height;
       else
        ws->y = screen_height - ws->height;
+      if (ws->y < 0) 
+        ws->y = 0;
     }
 }
 
@@ -796,7 +848,7 @@ remap_menubar (mw)
     old_stack [i] = new_stack [i];
   mw->menu.old_depth = new_depth;
 
-  /* refresh the last seletion */
+  /* refresh the last selection */
   selection_position.x = 0;
   selection_position.y = 0;
   display_menu (mw, last_same, new_selection == old_selection,
@@ -1046,15 +1098,13 @@ release_shadow_gcs (mw)
 }
 
 static void
-XlwMenuInitialize (request, new, args, num_args)
+XlwMenuInitialize (request, mw, args, num_args)
      Widget request;
-     Widget new;
+     XlwMenuWidget mw;
      ArgList args;
      Cardinal *num_args;
 {
   /* Get the GCs and the widget size */
-  XlwMenuWidget mw = (XlwMenuWidget)new;
-  
   XSetWindowAttributes xswa;
   int mask;
   
@@ -1073,10 +1123,17 @@ XlwMenuInitialize (request, new, args, num_args)
 /*  mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */
   mw->menu.cursor = mw->menu.cursor_shape;
   
-  mw->menu.gray_pixmap = XCreatePixmapFromBitmapData (display, window,
-                                                     gray_bits, gray_width,
-                                                     gray_height, 1, 0, 1);
+  mw->menu.gray_pixmap
+    = XCreatePixmapFromBitmapData (display, window, gray_bits,
+                                  gray_width, gray_height,
+                                  (unsigned long)1, (unsigned long)0, 1);
   
+  /* I don't understand why this ends up 0 sometimes,
+     but it does.  This kludge works around it.
+     Can anyone find a real fix?   -- rms.  */
+  if (mw->menu.font == 0)
+    mw->menu.font = xlwmenu_default_font;
+
   make_drawing_gcs (mw);
   make_shadow_gcs (mw);
   
@@ -1228,6 +1285,11 @@ XlwMenuSetValues (current, request, new)
       && newmw->menu.contents->contents
       && newmw->menu.contents->contents->change >= VISIBLE_CHANGE)
     redisplay = True;
+  /* Do redisplay if the contents are entirely eliminated.  */
+  if (newmw->menu.contents
+      && newmw->menu.contents->contents == 0
+      && newmw->menu.contents->change >= VISIBLE_CHANGE)
+    redisplay = True;
 
   if (newmw->core.background_pixel != oldmw->core.background_pixel
       || newmw->menu.foreground != oldmw->menu.foreground
@@ -1351,10 +1413,54 @@ Drag (w, ev, params, num_params)
      Cardinal *num_params;
 {
   XlwMenuWidget mw = (XlwMenuWidget)w;
-  handle_motion_event (mw, &ev->xmotion);
+  if (mw->menu.popped_up)
+    handle_motion_event (mw, &ev->xmotion);
 }
 
-static void 
+/* Do nothing.
+   This is how we handle presses and releases of modifier keys.  */
+static void
+Nothing (w, ev, params, num_params)
+     Widget w;
+     XEvent *ev;
+     String *params;
+     Cardinal *num_params;
+{
+}
+
+/* Handle key press and release events while menu is popped up.
+   Our action is to get rid of the menu.  */
+static void
+Key (w, ev, params, num_params)
+     Widget w;
+     XEvent *ev;
+     String *params;
+     Cardinal *num_params;
+{
+  XlwMenuWidget mw = (XlwMenuWidget)w;
+
+  /* Pop down everything.  */
+  mw->menu.new_depth = 1;
+  remap_menubar (mw);
+
+  if (mw->menu.popped_up)
+    {
+      mw->menu.popped_up = False;
+      XtUngrabPointer ((Widget)mw, ev->xmotion.time);
+      if (XtIsShell (XtParent ((Widget) mw)))
+       XtPopdown (XtParent ((Widget) mw));
+      else
+       {
+         XtRemoveGrab ((Widget) mw);
+         display_menu (mw, 0, False, NULL, NULL, NULL, NULL, NULL);
+       }
+    }
+
+  /* callback */
+  XtCallCallbackList ((Widget)mw, mw->menu.select, (XtPointer)0);
+}
+
+static void
 Select (w, ev, params, num_params)
      Widget w;
      XEvent *ev;
@@ -1408,6 +1514,7 @@ pop_up_menu (mw, event)
   int          h;
   int          borderwidth = mw->menu.shadow_thickness;
   Screen*      screen = XtScreen (mw);
+  Display       *display = XtDisplay (mw);
 
   next_release_must_exit = 0;
 
@@ -1452,7 +1559,7 @@ pop_up_menu (mw, event)
     }
 
 #ifdef emacs
-  x_catch_errors ();
+  x_catch_errors (display);
 #endif
   XtGrabPointer ((Widget)mw, False,
                 (PointerMotionMask
@@ -1464,12 +1571,12 @@ pop_up_menu (mw, event)
                 event->time);
   pointer_grabbed = 1;
 #ifdef emacs
-  if (x_had_errors_p ())
+  if (x_had_errors_p (display))
     {
       pointer_grabbed = 0;
       XtUngrabPointer ((Widget)mw, event->time);
     }
-  x_uncatch_errors ();
+  x_uncatch_errors (display);
 #endif
 
   handle_motion_event (mw, (XMotionEvent*)event);