Commit aa1859f5 authored by Jan D's avatar Jan D

Use Gtk+ tooltips by default for Gtk+ Emacs.

* lisp/cus-start.el (x-gtk-use-system-tooltips): New variable.

* src/gtkutil.c (hierarchy_ch_cb, qttip_cb, xg_prepare_tooltip)
(xg_show_tooltip, xg_hide_tooltip, xg_free_frame_widgets): New
functions.
(xg_create_frame_widgets): Set ttip_* to 0.  Set a dummy tooltip
text so qttip_cb is called.  Connect query-tooltip to qttip_cb.
Remove code that is commented out.

* src/gtkutil.h (xg_free_frame_widgets, xg_prepare_tooltip)
(xg_show_tooltip, xg_hide_tooltip): Declare.

* src/xfns.c (x_gtk_use_system_tooltips): New variable.
(Fx_show_tip): If USE_GTK and x_gtk_use_system_tooltips, call
new gtkutil tooltip functions to show the tooltip.
(Fx_hide_tip): Call xg_hide_tooltip.
(syms_of_xfns): Defvar x-gtk-use-system-tooltips.

* src/xterm.c (x_clear_frame): Check FRAME_GTK_WIDGET (f) before
calling gtk_widget_queue_draw.
(x_free_frame_resources): Call xg_free_frame_widgets.

* src/xterm.h (struct x_output): Add ttip_widget, ttip_window and
ttip_lbl.
parent 6e051c0a
......@@ -104,6 +104,9 @@ The frame-parameter tool-bar-position controls this. It takes the values
top, left, tight or bottom. The Options => Show/Hide menu has entries
for this.
** Emacs uses GTK tooltips by default if built with GTK. You can turn that
off by customizing x-gtk-use-system-tooltips.
** Lucid menus and dialogs can display antialiased fonts if Emacs is built
with Xft.
......
2010-08-01 Jan Djärv <jan.h.d@swipnet.se>
* cus-start.el (x-gtk-use-system-tooltips): New variable.
2010-08-01 Chong Yidong <cyd@stupidchicken.com>
* emacs-lisp/package.el (package--list-packages): Fix column
......
......@@ -358,6 +358,7 @@ since it could result in memory overflow and make Emacs crash."
(x-gtk-show-hidden-files menu boolean "22.1")
(x-gtk-file-dialog-help-text menu boolean "22.1")
(x-gtk-whole-detached-tool-bar x boolean "22.1")
(x-gtk-use-system-tooltips tooltip boolean "23.3")
;; xterm.c
(x-use-underline-position-properties display boolean "22.1")
(x-underline-at-descent-line display boolean "22.1")
......
2010-08-01 Jan Djärv <jan.h.d@swipnet.se>
* xterm.h (struct x_output): Add ttip_widget, ttip_window and
ttip_lbl.
* xterm.c (x_clear_frame): Check FRAME_GTK_WIDGET (f) before
calling gtk_widget_queue_draw.
(x_free_frame_resources): Call xg_free_frame_widgets.
* xfns.c (x_gtk_use_system_tooltips): New variable.
(Fx_show_tip): If USE_GTK and x_gtk_use_system_tooltips, call
new gtkutil tooltip functions to show the tooltip.
(Fx_hide_tip): Call xg_hide_tooltip.
(syms_of_xfns): Defvar x-gtk-use-system-tooltips.
* gtkutil.h (xg_free_frame_widgets, xg_prepare_tooltip)
(xg_show_tooltip, xg_hide_tooltip): Declare.
* gtkutil.c (hierarchy_ch_cb, qttip_cb, xg_prepare_tooltip)
(xg_show_tooltip, xg_hide_tooltip, xg_free_frame_widgets): New
functions.
(xg_create_frame_widgets): Set ttip_* to 0. Set a dummy tooltip
text so qttip_cb is called. Connect query-tooltip to qttip_cb.
Remove code that is commented out.
2010-08-01 Stefan Monnier <monnier@iro.umontreal.ca>
* keymap.c (Fdefine_key, Flookup_key): Say what event is invalid.
......
......@@ -506,6 +506,161 @@ get_utf8_string (char *str)
}
/***********************************************************************
Tooltips
***********************************************************************/
/* Gtk+ calls this callback when the parent of our tooltip dummy changes.
We use that to pop down the tooltip. This happens if Gtk+ for some
reason wants to change or hide the tooltip. */
static void
hierarchy_ch_cb (GtkWidget *widget,
GtkWidget *previous_toplevel,
gpointer user_data)
{
FRAME_PTR f = (FRAME_PTR) user_data;
struct x_output *x = f->output_data.x;
GtkWidget *top = gtk_widget_get_toplevel (x->ttip_lbl);
if (! top || ! GTK_IS_WINDOW (top))
gtk_widget_hide (previous_toplevel);
}
/* Callback called when Gtk+ thinks a tooltip should be displayed.
We use it to get the tooltip window and the tooltip widget so
we can manipulate the ourselves.
Return FALSE ensures that the tooltip is not shown. */
static gboolean
qttip_cb (GtkWidget *widget,
gint xpos,
gint ypos,
gboolean keyboard_mode,
GtkTooltip *tooltip,
gpointer user_data)
{
FRAME_PTR f = (FRAME_PTR) user_data;
struct x_output *x = f->output_data.x;
if (x->ttip_widget == NULL)
{
g_object_set (G_OBJECT (widget), "has-tooltip", FALSE, NULL);
x->ttip_widget = tooltip;
g_object_ref (G_OBJECT (tooltip));
x->ttip_lbl = gtk_label_new ("");
g_object_ref (G_OBJECT (x->ttip_lbl));
gtk_tooltip_set_custom (tooltip, x->ttip_lbl);
x->ttip_window = GTK_WINDOW (gtk_widget_get_toplevel (x->ttip_lbl));
/* Realize so we can safely get screen later on. */
gtk_widget_realize (GTK_WIDGET (x->ttip_window));
gtk_widget_realize (x->ttip_lbl);
g_signal_connect (x->ttip_lbl, "hierarchy-changed",
G_CALLBACK (hierarchy_ch_cb), f);
}
return FALSE;
}
/* Prepare a tooltip to be shown, i.e. calculate WIDTH and HEIGHT.
Return zero if no system tooltip available, non-zero otherwise. */
int
xg_prepare_tooltip (FRAME_PTR f,
Lisp_Object string,
int *width,
int *height)
{
struct x_output *x = f->output_data.x;
GtkWidget *widget;
GdkWindow *gwin;
GdkScreen *screen;
GtkSettings *settings;
gboolean tt_enabled = TRUE;
GtkRequisition req;
Lisp_Object encoded_string;
if (!x->ttip_lbl) return 0;
BLOCK_INPUT;
encoded_string = ENCODE_UTF_8 (string);
widget = GTK_WIDGET (x->ttip_lbl);
gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window));
screen = gdk_drawable_get_screen (gwin);
settings = gtk_settings_get_for_screen (screen);
g_object_get (settings, "gtk-enable-tooltips", &tt_enabled, NULL);
if (tt_enabled)
{
g_object_set (settings, "gtk-enable-tooltips", FALSE, NULL);
/* Record that we disabled it so it can be enabled again. */
g_object_set_data (G_OBJECT (x->ttip_window), "restore-tt",
(gpointer)f);
}
/* Prevent Gtk+ from hiding tooltip on mouse move and such. */
g_object_set_data (G_OBJECT
(gtk_widget_get_display (GTK_WIDGET (x->ttip_window))),
"gdk-display-current-tooltip", NULL);
/* Put out dummy widget in so we can get callbacks for unrealize and
hierarchy-changed. */
gtk_tooltip_set_custom (x->ttip_widget, widget);
gtk_tooltip_set_text (x->ttip_widget, SDATA (encoded_string));
gtk_widget_size_request (GTK_WIDGET (x->ttip_window), &req);
if (width) *width = req.width;
if (height) *height = req.height;
UNBLOCK_INPUT;
return 1;
}
/* Show the tooltip at ROOT_X and ROOT_Y.
xg_prepare_tooltip must have been called before this function. */
void
xg_show_tooltip (FRAME_PTR f, int root_x, int root_y)
{
struct x_output *x = f->output_data.x;
if (x->ttip_window)
{
BLOCK_INPUT;
gtk_window_move (x->ttip_window, root_x, root_y);
gtk_widget_show_all (GTK_WIDGET (x->ttip_window));
UNBLOCK_INPUT;
}
}
/* Hide tooltip if shown. Do nothing if not shown.
Return non-zero if tip was hidden, non-ero if not (i.e. not using
system tooltips). */
int
xg_hide_tooltip (FRAME_PTR f)
{
int ret = 0;
if (f->output_data.x->ttip_window)
{
GtkWindow *win = f->output_data.x->ttip_window;
BLOCK_INPUT;
gtk_widget_hide (GTK_WIDGET (win));
if (g_object_get_data (G_OBJECT (win), "restore-tt"))
{
GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win));
GdkScreen *screen = gdk_drawable_get_screen (gwin);
GtkSettings *settings = gtk_settings_get_for_screen (screen);
g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
}
UNBLOCK_INPUT;
ret = 1;
}
return ret;
}
/***********************************************************************
General functions for creating widgets, resizing, events, e.t.c.
......@@ -847,17 +1002,34 @@ xg_create_frame_widgets (FRAME_PTR f)
style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>");
gtk_widget_modify_style (wfixed, style);
/* GTK does not set any border, and they look bad with GTK. */
/* That they look bad is no excuse for imposing this here. --Stef
It should be done by providing the proper default in Fx_create_Frame.
f->border_width = 0;
f->internal_border_width = 0; */
/* Steal a tool tip window we can move ourselves. */
f->output_data.x->ttip_widget = 0;
f->output_data.x->ttip_lbl = 0;
f->output_data.x->ttip_window = 0;
gtk_widget_set_tooltip_text (wtop, "Dummy text");
g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
UNBLOCK_INPUT;
return 1;
}
void
xg_free_frame_widgets (FRAME_PTR f)
{
if (FRAME_GTK_OUTER_WIDGET (f))
{
struct x_output *x = f->output_data.x;
gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
FRAME_GTK_OUTER_WIDGET (f) = 0;
if (x->ttip_lbl)
gtk_widget_destroy (x->ttip_lbl);
if (x->ttip_widget)
g_object_unref (G_OBJECT (x->ttip_widget));
}
}
/* Set the normal size hints for the window manager, for frame F.
FLAGS is the flags word to use--or 0 meaning preserve the flags
that the window now has.
......
......@@ -194,6 +194,7 @@ extern void xg_display_close (Display *dpy);
extern GdkCursor * xg_create_default_cursor (Display *dpy);
extern int xg_create_frame_widgets (FRAME_PTR f);
extern void xg_free_frame_widgets (FRAME_PTR f);
extern void x_wm_set_size_hint (FRAME_PTR f,
long flags,
int user_position);
......@@ -203,6 +204,14 @@ extern void xg_set_frame_icon (FRAME_PTR f,
Pixmap icon_pixmap,
Pixmap icon_mask);
extern int xg_prepare_tooltip (FRAME_PTR f,
Lisp_Object string,
int *width,
int *height);
extern void xg_show_tooltip (FRAME_PTR f, int root_x, int root_y);
extern int xg_hide_tooltip (FRAME_PTR f);
/* Mark all callback data that are Lisp_object:s during GC. */
extern void xg_mark_data (void);
......
......@@ -161,6 +161,10 @@ int x_gtk_file_dialog_help_text;
int x_gtk_whole_detached_tool_bar;
/* If non-zero, use Gtk+ tooltips. */
static int x_gtk_use_system_tooltips;
/* The background and shape of the mouse pointer, and shape when not
over text or in the modeline. */
......@@ -4610,7 +4614,9 @@ unwind_create_tip_frame (Lisp_Object frame)
when this happens. */
static Lisp_Object
x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms, Lisp_Object text)
x_create_tip_frame (struct x_display_info *dpyinfo,
Lisp_Object parms,
Lisp_Object text)
{
struct frame *f;
Lisp_Object frame, tem;
......@@ -5037,6 +5043,27 @@ Text larger than the specified size is clipped. */)
else
CHECK_NUMBER (dy);
#ifdef USE_GTK
if (x_gtk_use_system_tooltips)
{
int ok;
/* Hide a previous tip, if any. */
Fx_hide_tip ();
BLOCK_INPUT;
if ((ok = xg_prepare_tooltip (f, string, &width, &height)) != 0)
{
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
xg_show_tooltip (f, root_x, root_y);
/* This is used in Fx_hide_tip. */
XSETFRAME (tip_frame, f);
}
UNBLOCK_INPUT;
if (ok) goto start_timer;
}
#endif /* USE_GTK */
if (NILP (last_show_tip_args))
last_show_tip_args = Fmake_vector (make_number (3), Qnil);
......@@ -5197,6 +5224,7 @@ Value is t if tooltip was open, nil otherwise. */)
int count;
Lisp_Object deleted, frame, timer;
struct gcpro gcpro1, gcpro2;
struct frame *f;
/* Return quickly if nothing to do. */
if (NILP (tip_timer) && NILP (tip_frame))
......@@ -5214,6 +5242,14 @@ Value is t if tooltip was open, nil otherwise. */)
if (!NILP (timer))
call1 (Qcancel_timer, timer);
#ifdef USE_GTK
/* When using system tooltip, tip_frame is the Emacs frame on which
the tip is shown. */
f = XFRAME (frame);
if (xg_hide_tooltip (f))
frame = Qnil;
#endif
if (FRAMEP (frame))
{
delete_frame (frame, Qnil);
......@@ -5224,8 +5260,9 @@ Value is t if tooltip was open, nil otherwise. */)
redisplay procedure is not called when a tip frame over menu
items is unmapped. Redisplay the menu manually... */
{
struct frame *f = SELECTED_FRAME ();
Widget w = f->output_data.x->menubar_widget;
Widget w;
f = SELECTED_FRAME ();
w = f->output_data.x->menubar_widget;
if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
&& w != NULL)
......@@ -5894,6 +5931,12 @@ The default is to just show an arrow and pressing on that arrow shows
the tool bar buttons. */);
x_gtk_whole_detached_tool_bar = 0;
DEFVAR_BOOL ("x-gtk-use-system-tooltips", &x_gtk_use_system_tooltips,
doc: /* *If non-nil with a Gtk+ built Emacs, the Gtk+ toolip is used.
Otherwise use Emacs own tooltip implementation.
When using Gtk+ tooltips, the tooltip face is not used. */);
x_gtk_use_system_tooltips = 1;
Fprovide (intern_c_string ("x"), Qnil);
#ifdef USE_X_TOOLKIT
......
......@@ -2842,7 +2842,8 @@ x_clear_frame (struct frame *f)
#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
/* Make sure scroll bars are redrawn. As they aren't redrawn by
redisplay, do it here. */
gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
if (FRAME_GTK_WIDGET (f))
gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
#endif
XFlush (FRAME_X_DISPLAY (f));
......@@ -9278,14 +9279,7 @@ x_free_frame_resources (struct frame *f)
#else /* !USE_X_TOOLKIT */
#ifdef USE_GTK
/* In the GTK version, tooltips are normal X
frames. We must check and free both types. */
if (FRAME_GTK_OUTER_WIDGET (f))
{
gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
FRAME_GTK_OUTER_WIDGET (f) = 0;
}
xg_free_frame_widgets (f);
#endif /* USE_GTK */
if (FRAME_X_WINDOW (f))
......
......@@ -502,6 +502,10 @@ struct x_output
/* The last size hints set. */
GdkGeometry size_hints;
long hint_flags;
GtkTooltip *ttip_widget;
GtkWidget *ttip_lbl;
GtkWindow *ttip_window;
#endif
/* If >=0, a bitmap index. The indicated bitmap is used for the
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment