/* Implements a lightweight menubar widget.
Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994-1995, 1997, 1999-2011 Free Software Foundation, Inc.
+Copyright (C) 1994-1995, 1997, 1999-2016 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Created by devin@lucid.com */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <setjmp.h>
#include <lisp.h>
#include <stdio.h>
-#include <ctype.h>
#include <sys/types.h>
-#if (defined __sun) && !(defined SUNOS41)
-#define SUNOS41
-#include <X11/Xos.h>
-#undef SUNOS41
-#else
#include <X11/Xos.h>
-#endif
#include <X11/IntrinsicP.h>
#include <X11/ObjectP.h>
#include <X11/StringDefs.h>
#ifdef emacs
-/* Defined in xfns.c. When config.h defines `static' as empty, we get
- redefinition errors when gray_bitmap is included more than once, so
- we're referring to the one include in xfns.c here. */
-
-extern int gray_bitmap_width;
-extern int gray_bitmap_height;
-extern char *gray_bitmap_bits;
-
#include <xterm.h>
+#include "bitmaps/gray.xbm"
#else /* not emacs */
#include <X11/bitmaps/gray>
-#define gray_bitmap_width gray_width
-#define gray_bitmap_height gray_height
-#define gray_bitmap_bits gray_bits
#endif /* not emacs */
<KeyUp>: key()\n\
";
-/* FIXME: Space should toggle toggleable menu item but not remove the menu
+/* FIXME: Space should toggle togglable menu item but not remove the menu
so you can toggle the next one without entering the menu again. */
/* FIXME: Should ESC close one level of menu structure or the complete menu? */
/* FIXME: F10 should enter the menu, the first one in the menu-bar. */
-#define offset(field) XtOffset(XlwMenuWidget, field)
+#define offset(field) offsetof (XlwMenuRec, field)
static XtResource
xlwMenuResources[] =
{
static void Nothing(Widget w, XEvent *ev, String *params, Cardinal *num_params);
static int separator_height (enum menu_separator);
static void pop_up_menu (XlwMenuWidget, XButtonPressedEvent *);
-static void abort_gracefully (Widget w) NO_RETURN;
static XtActionsRec
xlwMenuActionsList [] =
/* Like abort, but remove grabs from widget W before. */
-static void
+static _Noreturn void
abort_gracefully (Widget w)
{
if (XtIsShell (XtParent (w)))
int complete_length =
strlen (resourced_name) + strlen (val->value) + 2;
complete_name = XtMalloc (complete_length);
- *complete_name = 0;
- strcat (complete_name, resourced_name);
- strcat (complete_name, " ");
- strcat (complete_name, val->value);
+ char *z = stpcpy (complete_name, resourced_name);
+ *z++ = ' ';
+ strcpy (z, val->value);
}
val->toolkit_data = complete_name;
{
if (val->enabled)
*hit_return = val;
- else
+ else
no_return = 1;
- if (mw->menu.inside_entry != val)
+ if (mw->menu.inside_entry != val)
{
if (mw->menu.inside_entry)
XtCallCallbackList ((Widget)mw, mw->menu.leave,
static void
create_pixmap_for_menu (window_state* ws, XlwMenuWidget mw)
{
- if (ws->pixmap != None)
+ if (ws->pixmap != None)
{
XFreePixmap (XtDisplay (ws->w), ws->pixmap);
ws->pixmap = None;
if (new_selection && !new_selection->enabled)
new_selection = NULL;
- /* Call callback when the hightlighted item changes. */
+ /* Call callback when the highlighted item changes. */
if (old_selection || new_selection)
XtCallCallbackList ((Widget)mw, mw->menu.highlight,
(XtPointer) new_selection);
if (mw->menu.horizontal && i == 1)
ws->y += mw->menu.margin;
+ /* WMs like Gnome 3 ignores requests to move windows. So we
+ must destroy the current one and create a new to get it to move. */
+ XtUnrealizeWidget (ws->w);
+ XtRealizeWidget (ws->w);
+ ws->window = XtWindow (ws->w);
+
size_menu (mw, i);
fit_to_screen (mw, ws, previous_ws, mw->menu.horizontal && i == 1);
create_pixmap_for_menu (ws, mw);
- XtMoveWidget (ws->w, ws->x, ws->y);
- XtPopup (ws->w, XtGrabNone);
- XtResizeWidget (ws->w, ws->width, ws->height,
- mw->core.border_width);
- XtResizeWindow (ws->w);
+ XtConfigureWidget (ws->w, ws->x, ws->y, ws->width, ws->height,
+ ws->w->core.border_width);
display_menu (mw, i, False, &selection_position, NULL, NULL);
+ XtPopup (ws->w, XtGrabNone);
}
/* unmap the menus that popped down */
}
}
- if (!inside)
+ if (!inside)
{
- if (mw->menu.inside_entry != NULL)
+ if (mw->menu.inside_entry != NULL)
XtCallCallbackList ((Widget)mw, mw->menu.leave,
(XtPointer) mw->menu.inside_entry);
mw->menu.inside_entry = NULL;
mw->menu.background_gc = (GC) -1;
}
+#ifndef emacs
#define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
? ((unsigned long) (x)) : ((unsigned long) (y)))
+#endif
static void
make_shadow_gcs (XlwMenuWidget mw)
1.2, 0x8000))
#else
XQueryColor (dpy, cmap, &topc);
- /* don't overflow/wrap! */
+ /* Don't overflow/wrap! */
topc.red = MINL (65535, topc.red * 1.2);
topc.green = MINL (65535, topc.green * 1.2);
topc.blue = MINL (65535, topc.blue * 1.2);
}
}
- if (!mw->menu.top_shadow_pixmap &&
- mw->menu.top_shadow_color == mw->core.background_pixel)
+ if (!mw->menu.top_shadow_pixmap
+ && mw->menu.top_shadow_color == mw->core.background_pixel)
{
mw->menu.top_shadow_pixmap = mw->menu.gray_pixmap;
if (mw->menu.free_top_shadow_color_p)
}
mw->menu.top_shadow_color = mw->menu.foreground;
}
- if (!mw->menu.bottom_shadow_pixmap &&
- mw->menu.bottom_shadow_color == mw->core.background_pixel)
+ if (!mw->menu.bottom_shadow_pixmap
+ && mw->menu.bottom_shadow_color == mw->core.background_pixel)
{
mw->menu.bottom_shadow_pixmap = mw->menu.gray_pixmap;
if (mw->menu.free_bottom_shadow_color_p)
if (fname && strcmp (fname, "none") != 0)
{
int screen = XScreenNumberOfScreen (mw->core.screen);
- int len = strlen (fname), i = len-1;
+ int len = strlen (fname), i = len - 1;
/* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
- while (i > 0 && isdigit (fname[i]))
+ while (i > 0 && '0' <= fname[i] && fname[i] <= '9')
--i;
if (fname[i] == ' ')
{
fname[i] = '-';
}
- mw->menu.font = XLoadQueryFont (XtDisplay (mw), fname);
- if (!mw->menu.font)
- {
- mw->menu.xft_font = XftFontOpenName (XtDisplay (mw), screen, fname);
- if (!mw->menu.xft_font)
- {
- fprintf (stderr, "Can't find font '%s'\n", fname);
- mw->menu.xft_font = getDefaultXftFont (mw);
- }
- }
+ mw->menu.xft_font = XftFontOpenName (XtDisplay (mw), screen, fname);
+ if (!mw->menu.xft_font)
+ mw->menu.xft_font = getDefaultXftFont (mw);
}
- if (fname != mw->menu.fontName) free (fname);
+ if (fname != mw->menu.fontName) xfree (fname);
return mw->menu.xft_font != 0;
}
static void
XlwMenuInitialize (Widget request, Widget w, ArgList args, Cardinal *num_args)
{
- /* Get the GCs and the widget size */
+ /* Get the GCs and the widget size. */
XlwMenuWidget mw = (XlwMenuWidget) w;
Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
Display* display = XtDisplay (mw);
-#if 0
- widget_value *tem = (widget_value *) XtMalloc (sizeof (widget_value));
-
- /* _XtCreate is freeing the object that was passed to us,
- so make a copy that we will actually keep. */
- memcpy (tem, mw->menu.contents, sizeof (widget_value));
- mw->menu.contents = tem;
-#endif
-
/* mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */
mw->menu.cursor = mw->menu.cursor_shape;
mw->menu.gray_pixmap
- = XCreatePixmapFromBitmapData (display, window, gray_bitmap_bits,
- gray_bitmap_width, gray_bitmap_height,
+ = XCreatePixmapFromBitmapData (display, window, gray_bits,
+ gray_width, gray_height,
(unsigned long)1, (unsigned long)0, 1);
#ifdef HAVE_XFT
if (!mw->menu.font)
{
mw->menu.font = XLoadQueryFont (display, "fixed");
- if (!mw->menu.font)
+ if (!mw->menu.font)
{
fprintf (stderr, "Menu font fixed not found, can't continue.\n");
abort ();
}
}
}
-
+
#ifdef HAVE_X_I18N
if (mw->menu.fontSet)
mw->menu.font_extents = XExtentsOfFontSet (mw->menu.fontSet);
#endif
-
+
make_drawing_gcs (mw);
make_shadow_gcs (mw);
/* Only the toplevel menubar/popup is a widget so it's the only one that
receives expose events through Xt. So we repaint all the other panes
- when receiving an Expose event. */
+ when receiving an Expose event. */
static void
XlwMenuRedisplay (Widget w, XEvent *ev, Region region)
{
release_drawing_gcs (mw);
release_shadow_gcs (mw);
- /* this doesn't come from the resource db but is created explicitly
- so we must free it ourselves. */
+ /* This doesn't come from the resource db but is created explicitly
+ so we must free it ourselves. */
XFreePixmap (XtDisplay (mw), mw->menu.gray_pixmap);
mw->menu.gray_pixmap = (Pixmap) -1;
-#if 0
- /* Do free mw->menu.contents because nowadays we copy it
- during initialization. */
- XtFree (mw->menu.contents);
-#endif
-
/* Don't free mw->menu.contents because that comes from our creator.
The `*_stack' elements are just pointers into `contents' so leave
- that alone too. But free the stacks themselves. */
+ that alone too. But free the stacks themselves. */
if (mw->menu.old_stack) XtFree ((char *) mw->menu.old_stack);
if (mw->menu.new_stack) XtFree ((char *) mw->menu.new_stack);
- /* Remember, you can't free anything that came from the resource
+ /* Original comment was:
+
+ Remember, you can't free anything that came from the resource
database. This includes:
mw->menu.cursor
mw->menu.top_shadow_pixmap
Also the color cells of top_shadow_color, bottom_shadow_color,
foreground, and button_foreground will never be freed until this
client exits. Nice, eh?
- */
+
+ But now I can free font without any visible glitches. */
+
+ if (mw->menu.font)
+ XFreeFont (XtDisplay (mw), mw->menu.font);
#ifdef HAVE_XFT
if (mw->menu.windows [0].xft_draw)
XftFontClose (XtDisplay (mw), mw->menu.xft_font);
#endif
- if (mw->menu.windows [0].pixmap != None)
+ if (mw->menu.windows [0].pixmap != None)
XFreePixmap (XtDisplay (mw), mw->menu.windows [0].pixmap);
- /* start from 1 because the one in slot 0 is w->core.window */
+ /* Start from 1 because the one in slot 0 is w->core.window. */
for (i = 1; i < mw->menu.windows_length; i++)
{
- if (mw->menu.windows [i].pixmap != None)
+ if (mw->menu.windows [i].pixmap != None)
XFreePixmap (XtDisplay (mw), mw->menu.windows [i].pixmap);
#ifdef HAVE_XFT
if (mw->menu.windows [i].xft_draw)
{
XlwMenuWidget oldmw = (XlwMenuWidget)current;
XlwMenuWidget newmw = (XlwMenuWidget)new;
- Boolean redisplay = False;
- int i;
+ Boolean do_redisplay = False;
if (newmw->menu.contents
&& newmw->menu.contents->contents
&& newmw->menu.contents->contents->change >= VISIBLE_CHANGE)
- redisplay = True;
+ do_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;
+ do_redisplay = True;
if (newmw->core.background_pixel != oldmw->core.background_pixel
|| newmw->menu.foreground != oldmw->menu.foreground
#endif
)
{
+ int i;
release_drawing_gcs (newmw);
make_drawing_gcs (newmw);
newmw->menu.bottom_shadow_color = -1;
make_shadow_gcs (newmw);
- redisplay = True;
+ do_redisplay = True;
if (XtIsRealized (current))
/* If the menu is currently displayed, change the display. */
XSetWindowBackground (XtDisplay (oldmw),
oldmw->menu.windows [i].window,
newmw->core.background_pixel);
- /* clear windows and generate expose events */
+ /* Clear windows and generate expose events. */
XClearArea (XtDisplay (oldmw), oldmw->menu.windows[i].window,
0, 0, 0, 0, True);
}
#ifdef HAVE_X_I18N
if (newmw->menu.fontSet != oldmw->menu.fontSet && newmw->menu.fontSet != NULL)
{
- redisplay = True;
+ do_redisplay = True;
newmw->menu.font_extents = XExtentsOfFontSet (newmw->menu.fontSet);
}
#endif
- return redisplay;
+ return do_redisplay;
}
static void
set_new_state (mw, val, level);
remap_menubar (mw);
- /* Sync with the display. Makes it feel better on X terms. */
+ /* Sync with the display. Makes it feel better on X terms. */
XSync (XtDisplay (mw), False);
}
int state = ev->state;
XMotionEvent oldev = *ev;
- /* allow motion events to be generated again */
+ /* Allow motion events to be generated again. */
if (ev->is_hint
&& XQueryPointer (XtDisplay (mw), ev->window,
&ev->root, &ev->subwindow,
releasing the button should always pop the menu down. */
next_release_must_exit = 1;
- /* notes the absolute position of the menubar window */
+ /* Notes the absolute position of the menubar window. */
mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x;
mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y;
- /* handles the down like a move, slots are compatible */
+ /* Handles the down like a move, slots are compatible. */
ev->xmotion.is_hint = 0;
handle_motion_event (mw, &ev->xmotion);
}
while (lw_separator_p (current->name, &separator, 0) || !current->enabled
|| (skip_titles && !current->call_data && !current->contents))
if (current->next)
- current=current->next;
+ current = current->next;
else
return NULL;
widget_value *current = item;
enum menu_separator separator;
- while (current->next && (current=current->next) &&
- (lw_separator_p (current->name, &separator, 0) || !current->enabled
- || (skip_titles && !current->call_data && !current->contents)))
+ while (current->next && (current = current->next)
+ && (lw_separator_p (current->name, &separator, 0) || !current->enabled
+ || (skip_titles && !current->call_data && !current->contents)))
;
if (current == item)
&& !current->contents))
{
if (current->next)
- current=current->next;
+ current = current->next;
if (current == item)
break;
widget_value *current = item;
widget_value *prev = item;
- while ((current=find_next_selectable (mw, current, skip_titles))
+ while ((current = find_next_selectable (mw, current, skip_titles))
!= item)
{
if (prev == current)
break;
- prev=current;
+ prev = current;
}
return prev;
< XtGetMultiClickTime (XtDisplay (w))))
return;
- /* pop down everything. */
+ /* Pop down everything. */
mw->menu.new_depth = 1;
remap_menubar (mw);
}
-\f/* Special code to pop-up a menu */
+\f/* Special code to pop-up a menu. */
static void
pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event)
{
mw->menu.popped_up = True;
if (XtIsShell (XtParent ((Widget)mw)))
{
+ /* fprintf (stderr, "Config %d %d\n", x, y); */
XtConfigureWidget (XtParent ((Widget)mw), x, y, w, h,
XtParent ((Widget)mw)->core.border_width);
XtPopup (XtParent ((Widget)mw), XtGrabExclusive);
display_menu (mw, 0, False, NULL, NULL, NULL);
mw->menu.windows [0].x = x + borderwidth;
mw->menu.windows [0].y = y + borderwidth;
- mw->menu.top_depth = 1; /* Popup menus don't have a bar so top is 1 */
+ mw->menu.top_depth = 1; /* Popup menus don't have a bar so top is 1. */
}
else
{
XtAddGrab ((Widget) mw, True, True);
- /* notes the absolute position of the menubar window */
+ /* Notes the absolute position of the menubar window. */
mw->menu.windows [0].x = ev->xmotion.x_root - ev->xmotion.x;
mw->menu.windows [0].y = ev->xmotion.y_root - ev->xmotion.y;
mw->menu.top_depth = 2;