GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#define FOF_NO_CONNECTED_ELEMENTS 0x2000
#endif
-void syms_of_w32fns (void);
-void globals_of_w32fns (void);
-
-extern void free_frame_menubar (struct frame *);
extern int w32_console_toggle_lock_key (int, Lisp_Object);
extern void w32_menu_display_help (HWND, HMENU, UINT, UINT);
extern void w32_free_menu_strings (HWND);
extern const char *map_w32_filename (const char *, const char **);
-extern char * w32_strerror (int error_no);
#ifndef IDC_HAND
#define IDC_HAND MAKEINTRESOURCE(32649)
static int w32_unicode_gui;
/* From w32menu.c */
-extern HMENU current_popup_menu;
int menubar_in_use = 0;
/* From w32uniscribe.c */
void x_set_icon_type (struct frame *, Lisp_Object, Lisp_Object);
void x_set_icon_name (struct frame *, Lisp_Object, Lisp_Object);
void x_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
-void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
-void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
-void x_set_internal_border_width (struct frame *f, Lisp_Object, Lisp_Object);
\f
/* Store the screen positions of frame F into XPTR and YPTR.
/* The default colors for the w32 color map */
typedef struct colormap_t
{
- char *name;
+ const char *name;
COLORREF colorref;
} colormap_t;
NULL, NULL, (LPBYTE)color_buffer, &color_size)
== ERROR_SUCCESS)
{
- int r, g, b;
+ unsigned r, g, b;
if (sscanf (color_buffer, " %u %u %u", &r, &g, &b) == 3)
*system_colors = Fcons (Fcons (build_string (full_name_buffer),
make_number (RGB (r, g, b))),
If F is not a color screen, return DEF (default) regardless of what
ARG says. */
-int
+static int
x_decode_color (struct frame *f, Lisp_Object arg, int def)
{
XColor cdef;
Note that this does not fully take effect if done before
F has a window. */
-void
+static void
x_set_border_pixel (struct frame *f, int pix)
{
#endif
}
\f
-void
+static void
x_clear_under_internal_border (struct frame *f)
{
int border = FRAME_INTERNAL_BORDER_WIDTH (f);
suggesting a new name, which lisp code should override; if
F->explicit_name is set, ignore the new name; otherwise, set it. */
-void
+static void
x_set_name (struct frame *f, Lisp_Object name, bool explicit)
{
/* Make sure that requests from lisp code override requests from
\f
/* Subroutines for creating a frame. */
+Cursor w32_load_cursor (LPCTSTR);
+
Cursor
w32_load_cursor (LPCTSTR name)
{
post_msg (wmsg);
}
+#ifdef WINDOWSNT
/* The Windows keyboard hook callback. */
static LRESULT CALLBACK
funhook (int code, WPARAM w, LPARAM l)
can prevent this by setting the
w32-pass-[lr]window-to-system variable to
NIL. */
- if (hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system) ||
- hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))
+ if (hs->vkCode == (VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) ||
+ (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
{
/* Not prevented - Simulate the keypress to the system. */
memset (inputs, 0, sizeof (inputs));
/* Some other key was pressed while a captured Win key is down.
This is either an Emacs registered hotkey combination, or a
system hotkey. */
- if (kbdhook.lwindown && kbdhook.lwin_hooked[hs->vkCode] ||
- kbdhook.rwindown && kbdhook.rwin_hooked[hs->vkCode])
+ if ((kbdhook.lwindown && kbdhook.lwin_hooked[hs->vkCode]) ||
+ (kbdhook.rwindown && kbdhook.rwin_hooked[hs->vkCode]))
{
/* Hooked Win-x combination, do not pass the keypress to Windows. */
kbdhook.suppress_lone = 1;
kbdhook.hook = NULL;
}
}
+#endif /* WINDOWSNT */
/* Mark a specific key combination as hooked, preventing it to be
handled by the system. */
-void
+static void
hook_w32_key (int hook, int modifier, int vkey)
{
char *tbl = NULL;
leaves the Win key(s) "down" from the hook's point of view - the
keyup event is never seen. Thus, this function must be called when
the system is locked. */
-void
+static void
reset_w32_kbdhook_state (void)
{
kbdhook.lwindown = 0;
/* Convert between the modifier bits W32 uses and the modifier bits
Emacs uses. */
+unsigned int w32_key_to_modifier (int);
unsigned int
w32_key_to_modifier (int key)
return mods;
}
+unsigned int map_keypad_keys (unsigned int, unsigned int);
+
unsigned int
map_keypad_keys (unsigned int virt_key, unsigned int extended)
{
PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
}
+DWORD WINAPI w32_msg_worker (void *);
+
DWORD WINAPI
w32_msg_worker (void *arg)
{
Be ready to treat the case when this delivers WM_(SYS)DEADCHAR. */
static int after_deadkey = -1;
-int
+static int
deliver_wm_chars (int do_translate, HWND hwnd, UINT msg, UINT wParam,
UINT lParam, int legacy_alt_meta)
{
SHORT r = VkKeyScanW (*b), bitmap = 0x1FF;
FPRINTF_WM_CHARS((stderr, "VkKeyScanW %#06x %#04x\n", (int)r,
- wParam));
+ wParam));
if ((r & 0xFF) == wParam)
bitmap = r>>8; /* *b is reachable via simple interface */
+ else
+ {
+ /* VkKeyScanW() (essentially) returns the FIRST key with
+ the specified character; so here the pressed key is the
+ SECONDARY key producing the character.
+
+ Essentially, we have no information about the "role" of
+ modifiers on this key: which contribute into the
+ produced character (so "are consumed"), and which are
+ "extra" (must attache to bindable events).
+
+ The default above would consume ALL modifiers, so the
+ character is reported "as is". However, on many layouts
+ the ordering of the keys (in the layout table) is not
+ thought out well, so the "secondary" keys are often those
+ which the users would prefer to use with Alt-CHAR.
+ (Moreover - with e.g. Czech-QWERTY - the ASCII
+ punctuation is accessible from two equally [nu]preferable
+ AltGr-keys.)
+
+ SO: Heuristic: if the reported char is ASCII, AND Meta
+ modifier is a candidate, behave as if Meta is present
+ (fallback to the legacy branch; bug#23251).
+
+ (This would break layouts
+ - delivering ASCII characters
+ - on SECONDARY keys
+ - with not Shift/AltGr-like modifier combinations.
+ All 3 conditions together must be pretty exotic
+ cases - and a workaround exists: use "primary" keys!) */
+ if (*b < 0x80
+ && (wmsg.dwModifiers
+ & (alt_modifier | meta_modifier
+ | super_modifier | hyper_modifier)))
+ return 0;
+ }
if (*type_CtrlAlt == 'a') /* Simple Alt seen */
{
if ((bitmap & ~1) == 0) /* 1: KBDSHIFT */
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
goto dflt;
+#ifdef WINDOWSNT
case WM_CREATE:
setup_w32_kbdhook ();
goto dflt;
+#endif
case WM_DESTROY:
+#ifdef WINDOWSNT
remove_w32_kbdhook ();
+#endif
CoUninitialize ();
return 0;
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
return 0;
+ case WM_ENDSESSION:
+ my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+ /* If we return, the process will be terminated immediately. */
+ sleep (1000);
+
case WM_WINDOWPOSCHANGING:
/* Don't restrict the sizing of any kind of frames. If the window
manager doesn't, there's no reason to do it ourselves. */
if (!STRINGP (font))
{
int i;
- static char *names[]
+ static const char *names[]
= { "Courier New-10",
"-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
"-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
{
/* Remember the explicit font parameter, so we can re-apply it after
we've applied the `default' face settings. */
- x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
+ x_set_frame_parameters (f, Fcons (Fcons (Qfont_parameter, font_param),
+ Qnil));
}
x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
}
else if (! NILP (visibility))
x_make_frame_visible (f);
else
- /* Must have been Qnil. */
- ;
+ {
+ /* Must have been Qnil. */
+ ;
+ }
}
/* Initialize `default-minibuffer-frame' in case this is the first
DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
doc: /* Internal function called by `color-defined-p', which see.
-(Note that the Nextstep version of this function ignores FRAME.) */)
+\(Note that the Nextstep version of this function ignores FRAME.) */)
(Lisp_Object color, Lisp_Object frame)
{
XColor foo;
DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
doc: /* Return the "vendor ID" string of the GUI software on TERMINAL.
-(Labeling every distributor as a "vendor" embodies the false assumption
+\(Labeling every distributor as a "vendor" embodies the false assumption
that operating systems cannot be developed and distributed noncommercially.)
For GNU and Unix systems, this queries the X server software; for
return sound;
}
+#if 0 /* unused */
int
x_screen_planes (register struct frame *f)
{
return FRAME_DISPLAY_INFO (f)->n_planes;
}
+#endif
\f
/* Return the display structure for the display named NAME.
Open a new connection if necessary. */
Optional second arg XRM-STRING is a string of resources in xrdb format.
If the optional third arg MUST-SUCCEED is non-nil,
terminate Emacs if we can't open the connection.
-(In the Nextstep version, the last two arguments are currently ignored.) */)
+\(In the Nextstep version, the last two arguments are currently ignored.) */)
(Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
{
char *xrm_option;
Tool tips
***********************************************************************/
-static Lisp_Object x_create_tip_frame (struct w32_display_info *,
- Lisp_Object, Lisp_Object);
static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
Lisp_Object, int, int, int *, int *);
/* Create a frame for a tooltip on the display described by DPYINFO.
- PARMS is a list of frame parameters. TEXT is the string to
- display in the tip frame. Value is the frame.
+ PARMS is a list of frame parameters. Value is the frame.
Note that functions called here, esp. x_default_parameter can
signal errors, for instance when a specified color name is
when this happens. */
static Lisp_Object
-x_create_tip_frame (struct w32_display_info *dpyinfo,
- Lisp_Object parms, Lisp_Object text)
+x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
{
struct frame *f;
Lisp_Object frame;
ptrdiff_t count = SPECPDL_INDEX ();
struct kboard *kb;
bool face_change_before = face_change;
- Lisp_Object buffer;
- struct buffer *old_buffer;
int x_width = 0, x_height = 0;
/* Use this general default value to start with until we know if
frame = Qnil;
/* Make a frame without minibuffer nor mode-line. */
f = make_frame (false);
- f->wants_modeline = 0;
+ f->wants_modeline = false;
XSETFRAME (frame, f);
- AUTO_STRING (tip, " *tip*");
- buffer = Fget_buffer_create (tip);
- /* Use set_window_buffer instead of Fset_window_buffer (see
- discussion of bug#11984, bug#12025, bug#12026). */
- set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
- old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (buffer));
- bset_truncate_lines (current_buffer, Qnil);
- specbind (Qinhibit_read_only, Qt);
- specbind (Qinhibit_modification_hooks, Qt);
- Ferase_buffer ();
- Finsert (1, &text);
- set_buffer_internal_1 (old_buffer);
-
record_unwind_protect (unwind_create_tip_frame, frame);
/* By setting the output method, we're essentially saying that
{
fset_name (f, name);
f->explicit_name = true;
- /* use the frame's title when getting resources for this frame. */
+ /* Use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
+
x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
"internalBorderWidth", "internalBorderWidth",
RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qright_divider_width, make_number (0),
- NULL, NULL, RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
- NULL, NULL, RES_TYPE_NUMBER);
-
/* Also do the stuff which must be set before the window exists. */
x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
"foreground", "Foreground", RES_TYPE_STRING);
f->fringe_cols = 0;
f->left_fringe_width = 0;
f->right_fringe_width = 0;
+ /* No dividers on tip frame. */
+ f->right_divider_width = 0;
+ f->bottom_divider_width = 0;
block_input ();
my_create_tip_window (f);
SET_FRAME_LINES (f, 0);
adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame);
-
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
Lisp_Object fg = Fframe_parameter (frame, Qforeground_color);
Lisp_Object colors = Qnil;
- /* Set tip_frame here, so that */
- tip_frame = frame;
call2 (Qface_set_after_frame_default, frame, Qnil);
if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
*root_x = min_x;
}
+/* Hide tooltip. Delete its frame if DELETE is true. */
+static Lisp_Object
+x_hide_tip (bool delete)
+{
+ if (!NILP (tip_timer))
+ {
+ call1 (Qcancel_timer, tip_timer);
+ tip_timer = Qnil;
+ }
+
+ if (NILP (tip_frame)
+ || (!delete && FRAMEP (tip_frame)
+ && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
+ return Qnil;
+ else
+ {
+ ptrdiff_t count;
+ Lisp_Object was_open = Qnil;
+
+ count = SPECPDL_INDEX ();
+ specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
+
+ if (FRAMEP (tip_frame))
+ {
+ if (delete)
+ {
+ delete_frame (tip_frame, Qnil);
+ tip_frame = Qnil;
+ }
+ else
+ x_make_frame_invisible (XFRAME (tip_frame));
+
+ was_open = Qt;
+ }
+ else
+ tip_frame = Qnil;
+
+ return unbind_to (count, was_open);
+ }
+}
+
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
Text larger than the specified size is clipped. */)
(Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
{
- struct frame *f;
+ struct frame *tip_f;
struct window *w;
int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
- int i, width, height;
- bool seen_reversed_p;
+ int width, height;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t count = SPECPDL_INDEX ();
+ ptrdiff_t count_1;
+ Lisp_Object window, size;
specbind (Qinhibit_redisplay, Qt);
CHECK_STRING (string);
- f = decode_window_system_frame (frame);
+ decode_window_system_frame (frame);
if (NILP (timeout))
timeout = make_number (5);
else
if (NILP (last_show_tip_args))
last_show_tip_args = Fmake_vector (make_number (3), Qnil);
- if (!NILP (tip_frame))
+ if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
{
Lisp_Object last_string = AREF (last_show_tip_args, 0);
Lisp_Object last_frame = AREF (last_show_tip_args, 1);
Lisp_Object last_parms = AREF (last_show_tip_args, 2);
- if (EQ (frame, last_frame)
- && !NILP (Fequal (last_string, string))
+ if (FRAME_VISIBLE_P (XFRAME (tip_frame))
+ && EQ (frame, last_frame)
+ && !NILP (Fequal_including_properties (last_string, string))
&& !NILP (Fequal (last_parms, parms)))
{
- struct frame *f = XFRAME (tip_frame);
-
/* Only DX and DY have changed. */
+ tip_f = XFRAME (tip_frame);
if (!NILP (tip_timer))
{
Lisp_Object timer = tip_timer;
+
tip_timer = Qnil;
call1 (Qcancel_timer, timer);
}
block_input ();
- compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
- FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
+ compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
+ FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
/* Put tooltip in topmost group and in position. */
- SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
+ SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST,
root_x, root_y, 0, 0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
/* Ensure tooltip is on top of other topmost windows (eg menus). */
- SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
+ SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE
| SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+ /* Let redisplay know that we have made the frame visible already. */
+ SET_FRAME_VISIBLE (tip_f, 1);
+ ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE);
unblock_input ();
+
goto start_timer;
}
- }
+ else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame))
+ {
+ bool delete = false;
+ Lisp_Object tail, elt, parm, last;
- /* Hide a previous tip, if any. */
- Fx_hide_tip ();
+ /* Check if every parameter in PARMS has the same value in
+ last_parms. This may destruct last_parms which, however,
+ will be recreated below. */
+ for (tail = parms; CONSP (tail); tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ parm = Fcar (elt);
+ /* The left, top, right and bottom parameters are handled
+ by compute_tip_xy so they can be ignored here. */
+ if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
+ && !EQ (parm, Qright) && !EQ (parm, Qbottom))
+ {
+ last = Fassq (parm, last_parms);
+ if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
+ {
+ /* We lost, delete the old tooltip. */
+ delete = true;
+ break;
+ }
+ else
+ last_parms = call2 (Qassq_delete_all, parm, last_parms);
+ }
+ else
+ last_parms = call2 (Qassq_delete_all, parm, last_parms);
+ }
+
+ /* Now check if there's a parameter left in last_parms with a
+ non-nil value. */
+ for (tail = last_parms; CONSP (tail); tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ parm = Fcar (elt);
+ if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
+ && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
+ {
+ /* We lost, delete the old tooltip. */
+ delete = true;
+ break;
+ }
+ }
+
+ x_hide_tip (delete);
+ }
+ else
+ x_hide_tip (true);
+ }
+ else
+ x_hide_tip (true);
ASET (last_show_tip_args, 0, string);
ASET (last_show_tip_args, 1, frame);
ASET (last_show_tip_args, 2, parms);
- /* Add default values to frame parameters. */
- if (NILP (Fassq (Qname, parms)))
- parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
- if (NILP (Fassq (Qinternal_border_width, parms)))
- parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
- if (NILP (Fassq (Qright_divider_width, parms)))
- parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms);
- if (NILP (Fassq (Qbottom_divider_width, parms)))
- parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms);
- if (NILP (Fassq (Qborder_width, parms)))
- parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
- if (NILP (Fassq (Qborder_color, parms)))
- parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
- if (NILP (Fassq (Qbackground_color, parms)))
- parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
- parms);
-
/* Block input until the tip has been fully drawn, to avoid crashes
when drawing tips in menus. */
block_input ();
- /* Create a frame for the tooltip, and record it in the global
- variable tip_frame. */
- frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string);
- f = XFRAME (frame);
+ if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
+ {
+ /* Add default values to frame parameters. */
+ if (NILP (Fassq (Qname, parms)))
+ parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
+ if (NILP (Fassq (Qborder_width, parms)))
+ parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
+ if (NILP (Fassq (Qborder_color, parms)))
+ parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
+ if (NILP (Fassq (Qbackground_color, parms)))
+ parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
+ parms);
+
+ /* Create a frame for the tooltip, and record it in the global
+ variable tip_frame. */
+ if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
+ {
+ /* Creating the tip frame failed. */
+ unblock_input ();
+ return unbind_to (count, Qnil);
+ }
+ }
- /* Set up the frame's root window. */
- w = XWINDOW (FRAME_ROOT_WINDOW (f));
+ tip_f = XFRAME (tip_frame);
+ window = FRAME_ROOT_WINDOW (tip_f);
+ AUTO_STRING (tip, " *tip*");
+ set_window_buffer (window, Fget_buffer_create (tip), false, false);
+ w = XWINDOW (window);
+ w->pseudo_window_p = true;
+
+ /* Set up the frame's root window. Note: The following code does not
+ try to size the window or its frame correctly. Its only purpose is
+ to make the subsequent text size calculations work. The right
+ sizes should get installed when the toolkit gets back to us. */
w->left_col = 0;
w->top_line = 0;
w->pixel_left = 0;
w->pixel_top = 0;
if (CONSP (Vx_max_tooltip_size)
- && INTEGERP (XCAR (Vx_max_tooltip_size))
- && XINT (XCAR (Vx_max_tooltip_size)) > 0
- && INTEGERP (XCDR (Vx_max_tooltip_size))
- && XINT (XCDR (Vx_max_tooltip_size)) > 0)
+ && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
+ && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
{
w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size));
w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size));
w->total_lines = 40;
}
- w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f);
- w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f);
-
- FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
- adjust_frame_glyphs (f);
- w->pseudo_window_p = true;
+ w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
+ w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
+ FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w);
+ adjust_frame_glyphs (tip_f);
- /* Display the tooltip text in a temporary buffer. */
+ /* Insert STRING into the root window's buffer and fit the frame to
+ the buffer. */
+ count_1 = SPECPDL_INDEX ();
old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents));
+ set_buffer_internal_1 (XBUFFER (w->contents));
bset_truncate_lines (current_buffer, Qnil);
+ specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
+ specbind (Qinhibit_point_motion_hooks, Qt);
+ Ferase_buffer ();
+ Finsert (1, &string);
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
- try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
-
- /* Compute width and height of the tooltip. */
- width = height = 0;
- seen_reversed_p = false;
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- {
- struct glyph_row *row = &w->desired_matrix->rows[i];
- struct glyph *last;
- int row_width;
-
- /* Stop at the first empty row at the end. */
- if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
- break;
-
- /* Let the row go over the full width of the frame. */
- row->full_width_p = true;
-
- row_width = row->pixel_width;
- if (row->used[TEXT_AREA])
- {
- if (!row->reversed_p)
- {
- /* There's a glyph at the end of rows that is used to
- place the cursor there. Don't include the width of
- this glyph. */
- last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (NILP (last->object))
- row_width -= last->pixel_width;
- }
- else
- {
- /* There could be a stretch glyph at the beginning of R2L
- rows that is produced by extend_face_to_end_of_line.
- Don't count that glyph. */
- struct glyph *g = row->glyphs[TEXT_AREA];
-
- if (g->type == STRETCH_GLYPH && NILP (g->object))
- {
- row_width -= g->pixel_width;
- seen_reversed_p = true;
- }
- }
- }
-
- height += row->height;
- width = max (width, row_width);
- }
-
- /* If we've seen partial-length R2L rows, we need to re-adjust the
- tool-tip frame width and redisplay it again, to avoid over-wide
- tips due to the stretch glyph that extends R2L lines to full
- width of the frame. */
- if (seen_reversed_p)
- {
- /* PXW: Why do we do the pixel-to-cols conversion only if
- seen_reversed_p holds? Don't we have to set other fields of
- the window/frame structure?
-
- w->total_cols and FRAME_TOTAL_COLS want the width in columns,
- not in pixels. */
- w->pixel_width = width;
- width /= WINDOW_FRAME_COLUMN_WIDTH (w);
- w->total_cols = width;
- FRAME_TOTAL_COLS (f) = width;
- SET_FRAME_WIDTH (f, width);
- adjust_frame_glyphs (f);
- w->pseudo_window_p = 1;
- clear_glyph_matrix (w->desired_matrix);
- clear_glyph_matrix (w->current_matrix);
- try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
- width = height = 0;
- /* Recompute width and height of the tooltip. */
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- {
- struct glyph_row *row = &w->desired_matrix->rows[i];
- struct glyph *last;
- int row_width;
-
- if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
- break;
- row->full_width_p = true;
- row_width = row->pixel_width;
- if (row->used[TEXT_AREA] && !row->reversed_p)
- {
- last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (NILP (last->object))
- row_width -= last->pixel_width;
- }
-
- height += row->height;
- width = max (width, row_width);
- }
- }
-
- /* Add the frame's internal border to the width and height the w32
- window should have. */
- height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
- width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
-
- /* Move the tooltip window where the mouse pointer is. Resize and
- show it.
-
- PXW: This should use the frame's pixel coordinates. */
- compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
-
+ try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
+ /* Calculate size of tooltip window. */
+ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
+ make_number (w->pixel_height), Qnil);
+ /* Add the frame's internal border to calculated size. */
+ width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+ height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+ /* Calculate position of tooltip frame. */
+ compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
+
+ /* Show tooltip frame. */
{
- /* Adjust Window size to take border into account. */
RECT rect;
+ int pad = (NUMBERP (Vw32_tooltip_extra_pixels)
+ ? max (0, XINT (Vw32_tooltip_extra_pixels))
+ : FRAME_COLUMN_WIDTH (tip_f));
+
rect.left = rect.top = 0;
rect.right = width;
rect.bottom = height;
- AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false);
-
- /* Position and size tooltip, and put it in the topmost group.
- The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a
- peculiarity of w32 display: without it, some fonts cause the
- last character of the tip to be truncated or wrapped around to
- the next line. */
- SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
+ AdjustWindowRect (&rect, tip_f->output_data.w32->dwStyle,
+ FRAME_EXTERNAL_MENU_BAR (tip_f));
+
+ /* Position and size tooltip and put it in the topmost group. */
+ SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST,
root_x, root_y,
- rect.right - rect.left + FRAME_COLUMN_WIDTH (f),
+ rect.right - rect.left + pad,
rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER);
/* Ensure tooltip is on top of other topmost windows (eg menus). */
- SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
+ SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE
| SWP_NOACTIVATE | SWP_NOOWNERZORDER);
/* Let redisplay know that we have made the frame visible already. */
- SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_VISIBLE (tip_f, 1);
- ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
+ ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE);
}
- /* Draw into the window. */
w->must_be_updated_p = true;
update_single_window (w);
-
- unblock_input ();
-
- /* Restore original current buffer. */
set_buffer_internal_1 (old_buffer);
+ unbind_to (count_1, Qnil);
+ unblock_input ();
windows_or_buffers_changed = old_windows_or_buffers_changed;
start_timer:
Value is t if tooltip was open, nil otherwise. */)
(void)
{
- ptrdiff_t count;
- Lisp_Object deleted, frame, timer;
-
- /* Return quickly if nothing to do. */
- if (NILP (tip_timer) && NILP (tip_frame))
- return Qnil;
-
- frame = tip_frame;
- timer = tip_timer;
- tip_frame = tip_timer = deleted = Qnil;
-
- count = SPECPDL_INDEX ();
- specbind (Qinhibit_redisplay, Qt);
- specbind (Qinhibit_quit, Qt);
-
- if (!NILP (timer))
- call1 (Qcancel_timer, timer);
-
- if (FRAMEP (frame))
- {
- delete_frame (frame, Qnil);
- deleted = Qt;
- }
-
- return unbind_to (count, deleted);
+ return x_hide_tip (!tooltip_reuse_hidden_frame);
}
\f
/***********************************************************************
/* Alphanumerics map to themselves. */
if (key[1] == 0)
{
- if (key[0] >= 'A' && key[0] <= 'Z' ||
- key[0] >= '0' && key[0] <= '9')
+ if ((key[0] >= 'A' && key[0] <= 'Z')
+ || (key[0] >= '0' && key[0] <= '9'))
return key[0];
if (key[0] >= 'a' && key[0] <= 'z')
return toupper(key[0]);
Sw32_set_mouse_absolute_pixel_position, 2, 2, 0,
doc: /* Move mouse pointer to absolute pixel position (X, Y).
The coordinates X and Y are interpreted in pixels relative to a position
-(0, 0) of the selected frame's display. */)
+\(0, 0) of the selected frame's display. */)
(Lisp_Object x, Lisp_Object y)
{
UINT trail_num = 0;
else
{
long m;
- float h;
+ double h;
char buffer[16];
snprintf (buffer, 16, "%ld", seconds_left);
seconds = build_string (buffer);
/* For convenience when debugging. (You cannot call GetLastError
directly from GDB: it will crash, because it uses the __stdcall
calling convention, not the _cdecl convention assumed by GDB.) */
+DWORD w32_last_error (void);
+
DWORD
w32_last_error (void)
{
EMACS_INT retval;
char *icon, *tip, *title, *msg;
enum NI_Severity severity;
- unsigned timeout;
+ unsigned timeout = 0;
if (nargs == 0)
return Qnil;
if (STRINGP (lres))
icon = SSDATA (ENCODE_FILE (Fexpand_file_name (lres, Qnil)));
else
- icon = "";
+ icon = (char *)"";
/* Tip. */
lres = Fplist_get (arg_plist, QCtip);
if (STRINGP (lres))
tip = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
else
- tip = "Emacs notification";
+ tip = (char *)"Emacs notification";
/* Severity. */
lres = Fplist_get (arg_plist, QClevel);
if (STRINGP (lres))
title = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
else
- title = "";
+ title = (char *)"";
/* Notification body text. */
lres = Fplist_get (arg_plist, QCbody);
if (STRINGP (lres))
msg = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
else
- msg = "";
+ msg = (char *)"";
/* Do it! */
retval = add_tray_notification (f, icon, tip, severity, timeout, title, msg);
DEFSYM (Qctrl, "ctrl");
DEFSYM (Qcontrol, "control");
DEFSYM (Qshift, "shift");
- DEFSYM (Qfont_param, "font-parameter");
+ DEFSYM (Qfont_parameter, "font-parameter");
DEFSYM (Qgeometry, "geometry");
DEFSYM (Qworkarea, "workarea");
DEFSYM (Qmm_size, "mm-size");
DEFSYM (Qframes, "frames");
DEFSYM (Qtip_frame, "tip-frame");
+ DEFSYM (Qassq_delete_all, "assq-delete-all");
DEFSYM (Qunicode_sip, "unicode-sip");
#if defined WINDOWSNT && !defined HAVE_DBUS
DEFSYM (QCicon, ":icon");
#endif
/* Symbols used elsewhere, but only in MS-Windows-specific code. */
- DEFSYM (Qgnutls_dll, "gnutls");
- DEFSYM (Qlibxml2_dll, "libxml2");
+ DEFSYM (Qgnutls, "gnutls");
+ DEFSYM (Qlibxml2, "libxml2");
DEFSYM (Qserif, "serif");
- DEFSYM (Qzlib_dll, "zlib");
+ DEFSYM (Qzlib, "zlib");
Fput (Qundefined_color, Qerror_conditions,
listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
This variable has effect only on Windows Vista and later. */);
w32_disable_new_uniscribe_apis = 0;
+ DEFVAR_LISP ("w32-tooltip-extra-pixels",
+ Vw32_tooltip_extra_pixels,
+ doc: /* Number of pixels added after tooltip text.
+On Windows some fonts may cause the last character of a tooltip be
+truncated or wrapped around to the next line. Adding some extra space
+at the end of the toooltip works around this problem.
+
+This variable specifies the number of pixels that shall be added. The
+default value t means to add the width of one canonical character of the
+tip frame. */);
+ Vw32_tooltip_extra_pixels = Qt;
+
#if 0 /* TODO: Port to W32 */
defsubr (&Sx_change_window_property);
defsubr (&Sx_delete_window_property);
#define BACKTRACE_LIMIT_MAX 62
-int
+static int
w32_backtrace (void **buffer, int limit)
{
static CaptureStackBackTrace_proc s_pfn_CaptureStackBackTrace = NULL;