From: martin rudalics <rudalics@gmx.at>
To: "Clément Pit--Claudel" <clement.pit@gmail.com>, emacs-devel@gnu.org
Subject: Re: Latest master broken on Cocoa/NS
Date: Fri, 15 Jul 2016 18:41:06 +0200 [thread overview]
Message-ID: <57891222.1060900@gmx.at> (raw)
In-Reply-To: <57890B53.4050402@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 347 bytes --]
> company-mode would benefit tremendously from such a thing.
Attached. mini-frame.diff is against master from this morning and
contains unrelated stuff which should not bother you. The entry point
is the function ‘make-mini-frame’. mini-frame.el has some functions to
show how it can be used. No NS support, obviously.
martin
[-- Attachment #2: mini-frame.diff --]
[-- Type: text/plain, Size: 49068 bytes --]
diff --git a/lisp/frame.el b/lisp/frame.el
index 09738d1..478cc2b 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -144,6 +144,13 @@ handle-focus-out
This function runs the hook `focus-out-hook'."
(interactive "e")
(run-hooks 'focus-out-hook))
+
+(defun handle-move-frame (event)
+ "Handle a move-frame event.
+This function runs the abnormal hook `move-frame-functions'."
+ (interactive "e")
+ (let ((frame (posn-window (event-start event))))
+ (run-hook-with-args 'move-frame-functions frame)))
\f
;;;; Arrangement of frames at startup
@@ -1483,6 +1490,90 @@ frame-monitor-attributes
for frames = (cdr (assq 'frames attributes))
if (memq frame frames) return attributes))
+(declare-function x-make-mini-frame "xfns.c" (&optional frame parameters))
+(declare-function w32-make-mini-frame "w32fns.c" (&optional frame parameters))
+
+(defun make-mini-frame (&optional frame parameters)
+ "Make a new mini-frame with FRAME as its parent.
+Optional argument FRAME must specify a live frame. If omitted,
+FRAME defaults to the selected frame. The mini-frame is made on
+the same display as FRAME. Return the new mini-frame, nil if its
+creation failed.
+
+PARAMETERS is a list of frame parameters. The 'child-window'
+parameter is special: If non-nil, the mini-frame becomes a
+\"child window\" of FRAME. This usually means that the
+mini-frame is clipped at the boundaries of FRAME and is moved,
+raised, and iconified together with FRAME. Usually, this also
+means that the position of the mini-frame in the Z-order
+\(stacking order) is always right above FRAME.
+
+'child-window' omitted or nil usually means that the application
+has to take full care of how to raise, move and iconify the
+mini-frame and how to maintain its place in the Z-order (stacking
+order) of frames on the display. On some platforms, such a
+mini-frame invariably appears on top of all other frames so you
+usually would like to hide it whenever its parent frame is not on
+top of the Z-order or does not have focus. On other platforms,
+such a mini-frame may appear right above FRAME as with a non-nil
+'child-window' parameter.
+
+The stacking order of mini-frames with the same parent is
+undefined regardless of whether a 'child-window' parameter has
+been specified or not. On many platforms, the stacking order of
+mini-frames with a non-nil 'child-window' parameter may be also
+undefined wrt control elements (like a scroll bar) which may
+appear under or over the mini-frame, depending on which of them
+has been drawn later.
+
+By default, mini-frames are drawn without any external borders, a
+title bar or the buttons to minimize, maximize or delete the
+frame. The 'border-width' parameter, which is usually not used
+on \"normal\" frames, can be used to draw a border around the
+mini-frame. On Windows, specifying a positive number as border
+width produces a one pixel wide external border. That border is
+also reported as \"external\" by `frame-geometry' which, on
+Windows, always returns value of zero for `border-width'. On
+both, X and Windows, the border drawn due to this parameter's
+setting is not within the native edges of the mini-frame.
+
+Other aspects of mini-frames are platform-dependent as well. For
+example, on Windows, the 'alpha' parameter may not work correctly
+when used together with a non-nil 'child-window' parameter. On
+X, mini-frames with a non-nil 'child-window' parameter may have
+to be explicitly redrawn when their parent frame is deiconified.
+
+The hooks `move-frame-functions', `focus-in-hook',
+`focus-out-hook', `window-configuration-change-hook', and
+‘window-size-change-functions' can be used to control size,
+placing and visibilty of a mini-frame when size, position or
+contents of its parent frame change."
+ (let* ((frame (window-normalize-frame frame))
+ (frame-type (framep-on-display frame)))
+ (cond
+ ((eq frame-type 'x)
+ (x-create-mini-frame frame parameters))
+ ((eq frame-type 'w32)
+ (w32-create-mini-frame frame parameters)))))
+
+(declare-function x-frame-list-z-order "xfns.c" (&optional display))
+(declare-function w32-frame-list-z-order "w32fns.c" (&optional display))
+
+(defun frame-list-z-order (&optional display)
+ "Return list of Emacs' frames, in Z (stacking) order.
+The optional argument DISPLAY specifies which display to poll.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Frames are listed from bottommost (first) to topmost (last).
+Return nil if DISPLAY contains no Emacs frame. Child frames are
+not listed by this function."
+ (let ((display (framep-on-display display)))
+ (cond
+ ((eq display 'x)
+ (x-frame-list-z-order display))
+ ((eq display 'w32)
+ (w32-frame-list-z-order display)))))
\f
;;;; Frame/display capabilities.
@@ -1882,14 +1973,14 @@ delete-other-frames
(interactive)
(unless frame
(setq frame (selected-frame)))
- (let* ((mini-frame (window-frame (minibuffer-window frame)))
- (frames (delq mini-frame (delq frame (frame-list)))))
+ (let* ((minibuffer-frame (window-frame (minibuffer-window frame)))
+ (frames (delq minibuffer-frame (delq frame (frame-list)))))
;; Only consider frames on the same terminal.
(dolist (frame (prog1 frames (setq frames nil)))
(if (eq (frame-terminal) (frame-terminal frame))
(push frame frames)))
;; Delete mon-minibuffer-only frames first, because `delete-frame'
- ;; signals an error when trying to delete a mini-frame that's
+ ;; signals an error when trying to delete a minibuffer-frame that's
;; still in use by another frame.
(dolist (frame frames)
(unless (eq (frame-parameter frame 'minibuffer) 'only)
diff --git a/src/frame.c b/src/frame.c
index 22143ab..9d86b07 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -81,11 +81,6 @@
{
f->buffer_predicate = val;
}
-static void
-fset_minibuffer_window (struct frame *f, Lisp_Object val)
-{
- f->minibuffer_window = val;
-}
struct frame *
decode_live_frame (register Lisp_Object frame)
@@ -418,9 +413,13 @@ struct frame *
sizes and any "new" settings for scroll bars, dividers, fringes and
margins (though the latter should have been processed already). */
min_windows_width
- = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
+ = (f->mini_frame
+ ? unit_width
+ : frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt));
min_windows_height
- = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
+ = (f->mini_frame
+ ? unit_height
+ : frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt));
if (inhibit >= 2 && inhibit <= 4)
/* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
@@ -636,6 +635,7 @@ struct frame *
f->inhibit_vertical_resize = false;
f->tool_bar_redisplayed = false;
f->tool_bar_resized = false;
+ f->mini_frame = false;
f->column_width = 1; /* !FRAME_WINDOW_P value. */
f->line_height = 1; /* !FRAME_WINDOW_P value. */
#ifdef HAVE_WINDOW_SYSTEM
@@ -1381,18 +1381,18 @@ of them (the selected terminal frame) is actually displayed.
It considers only frames on the same terminal as FRAME.
By default, skip minibuffer-only frames.
If omitted, FRAME defaults to the selected frame.
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
-If MINIFRAME is a window, include only its own frame
+If optional argument MINIBUF is nil, exclude minibuffer-only frames.
+If MINIBUF is a window, include only its own frame
and any frame now using that window as the minibuffer.
-If MINIFRAME is `visible', include all visible frames.
-If MINIFRAME is 0, include all visible and iconified frames.
+If MINIBUF is `visible', include all visible frames.
+If MINIBUF is 0, include all visible and iconified frames.
Otherwise, include all frames. */)
- (Lisp_Object frame, Lisp_Object miniframe)
+ (Lisp_Object frame, Lisp_Object minibuf)
{
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
- return next_frame (frame, miniframe);
+ return next_frame (frame, minibuf);
}
DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
@@ -1400,18 +1400,18 @@ of them (the selected terminal frame) is actually displayed.
It considers only frames on the same terminal as FRAME.
By default, skip minibuffer-only frames.
If omitted, FRAME defaults to the selected frame.
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
-If MINIFRAME is a window, include only its own frame
+If optional argument MINIBUF is nil, exclude minibuffer-only frames.
+If MINIBUF is a window, include only its own frame
and any frame now using that window as the minibuffer.
-If MINIFRAME is `visible', include all visible frames.
-If MINIFRAME is 0, include all visible and iconified frames.
+If MINIBUF is `visible', include all visible frames.
+If MINIBUF is 0, include all visible and iconified frames.
Otherwise, include all frames. */)
- (Lisp_Object frame, Lisp_Object miniframe)
+ (Lisp_Object frame, Lisp_Object minibuf)
{
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
- return prev_frame (frame, miniframe);
+ return prev_frame (frame, minibuf);
}
DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
@@ -1515,7 +1515,7 @@ of them (the selected terminal frame) is actually displayed.
struct frame *sf;
struct kboard *kb;
- int minibuffer_selected, is_tooltip_frame;
+ int minibuffer_selected, tip_or_mini_frame;
if (! FRAME_LIVE_P (f))
return Qnil;
@@ -1557,13 +1557,14 @@ of them (the selected terminal frame) is actually displayed.
}
}
- is_tooltip_frame = !NILP (Fframe_parameter (frame, Qtooltip));
+ tip_or_mini_frame
+ = (!NILP (Fframe_parameter (frame, Qtooltip))
+ || !NILP (Fframe_parameter (frame, Qmini_frame)));
- /* Run `delete-frame-functions' unless FORCE is `noelisp' or
- frame is a tooltip. FORCE is set to `noelisp' when handling
- a disconnect from the terminal, so we don't dare call Lisp
- code. */
- if (NILP (Vrun_hooks) || is_tooltip_frame)
+ /* Run `delete-frame-functions' unless FORCE is `noelisp' or FRAME is
+ a tip or mini-frame. FORCE is set to `noelisp' when handling a
+ disconnect from the terminal, so we don't dare call Lisp code. */
+ if (NILP (Vrun_hooks) || tip_or_mini_frame)
;
else if (EQ (force, Qnoelisp))
pending_funcalls
@@ -1815,7 +1816,7 @@ of them (the selected terminal frame) is actually displayed.
}
/* Cause frame titles to update--necessary if we now have just one frame. */
- if (!is_tooltip_frame)
+ if (!tip_or_mini_frame)
update_mode_lines = 15;
return Qnil;
@@ -4901,6 +4902,7 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.
DEFSYM (Qicon_left, "icon-left");
DEFSYM (Qicon_top, "icon-top");
DEFSYM (Qtooltip, "tooltip");
+ DEFSYM (Qmini_frame, "mini-frame");
DEFSYM (Quser_position, "user-position");
DEFSYM (Quser_size, "user-size");
DEFSYM (Qwindow_id, "window-id");
@@ -5138,6 +5140,11 @@ even if the end of the buffer is shown (i.e. overscrolling).
doc: /* Normal hook run when a frame loses input focus. */);
Vfocus_out_hook = Qnil;
+ DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
+ doc: /* Functions run after a frame was moved.
+The functions are run with one arg, the frame that moved. */);
+ Vmove_frame_functions = Qnil;
+
DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
doc: /* Functions run before deleting a frame.
The functions are run with one arg, the frame to be deleted.
diff --git a/src/frame.h b/src/frame.h
index 5e3ee68..16c5a92 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -342,6 +342,9 @@ struct frame
/* Non-zero if this frame's faces need to be recomputed. */
bool_bf face_change : 1;
+ /* True means this a mini-frame. */
+ bool_bf mini_frame : 1;
+
/* Bitfield area ends here. */
/* Number of lines (rounded up) of tool bar. REMOVE THIS */
@@ -515,6 +518,12 @@ struct frame
/* Most code should use these functions to set Lisp fields in struct frame. */
INLINE void
+fset_minibuffer_window (struct frame *f, Lisp_Object val)
+{
+ f->minibuffer_window = val;
+}
+
+INLINE void
fset_buffer_list (struct frame *f, Lisp_Object val)
{
f->buffer_list = val;
diff --git a/src/keyboard.c b/src/keyboard.c
index 653f527..e4b4fcd 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4048,6 +4048,14 @@ static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
kbd_fetch_ptr = event + 1;
}
#endif
+#if defined (HAVE_X11) || defined (HAVE_NTGUI)
+ else if (event->kind == MOVE_FRAME_EVENT)
+ {
+ /* Make an event (move-frame (FRAME)). */
+ obj = list2 (Qmove_frame, list1 (event->ie.frame_or_window));
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
#ifdef HAVE_XWIDGETS
else if (event->kind == XWIDGET_EVENT)
{
@@ -10936,6 +10944,7 @@ struct event_head
{SYMBOL_INDEX (Qfocus_in), SYMBOL_INDEX (Qfocus_in)},
{SYMBOL_INDEX (Qfocus_out), SYMBOL_INDEX (Qfocus_out)},
+ {SYMBOL_INDEX (Qmove_frame), SYMBOL_INDEX (Qmove_frame)},
{SYMBOL_INDEX (Qdelete_frame), SYMBOL_INDEX (Qdelete_frame)},
{SYMBOL_INDEX (Qiconify_frame), SYMBOL_INDEX (Qiconify_frame)},
{SYMBOL_INDEX (Qmake_frame_visible), SYMBOL_INDEX (Qmake_frame_visible)},
@@ -11108,6 +11117,7 @@ struct event_head
DEFSYM (Qswitch_frame, "switch-frame");
DEFSYM (Qfocus_in, "focus-in");
DEFSYM (Qfocus_out, "focus-out");
+ DEFSYM (Qmove_frame, "move-frame");
DEFSYM (Qdelete_frame, "delete-frame");
DEFSYM (Qiconify_frame, "iconify-frame");
DEFSYM (Qmake_frame_visible, "make-frame-visible");
@@ -11846,6 +11856,8 @@ shutdown when Emacs receives a fatal signal (e.g., a crash).
"handle-focus-in");
initial_define_lispy_key (Vspecial_event_map, "focus-out",
"handle-focus-out");
+ initial_define_lispy_key (Vspecial_event_map, "move-frame",
+ "handle-move-frame");
}
/* Mark the pointers in the kboard objects.
diff --git a/src/termhooks.h b/src/termhooks.h
index ff74d99..9829b50 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -202,6 +202,9 @@ enum event_kind
FOCUS_OUT_EVENT,
+ /* Generated when a frame is moved. */
+ MOVE_FRAME_EVENT,
+
/* Generated when mouse moves over window not currently selected. */
SELECT_WINDOW_EVENT,
diff --git a/src/w32fns.c b/src/w32fns.c
index d6b54d1..70e0ab3 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -345,7 +345,7 @@ struct frame *
static Lisp_Object unwind_create_frame (Lisp_Object);
static void unwind_create_tip_frame (Lisp_Object);
static void my_create_window (struct frame *);
-static void my_create_tip_window (struct frame *);
+static void my_create_tip_window (struct frame *, bool, Lisp_Object);
/* TODO: Native Input Method support; see x_create_im. */
void x_set_foreground_color (struct frame *, Lisp_Object, Lisp_Object);
@@ -5065,42 +5065,39 @@ struct frame *
messages for the tooltip. Creating tooltips indirectly also creates
deadlocks when tooltips are created for menu items. */
static void
-my_create_tip_window (struct frame *f)
+my_create_tip_window (struct frame *f, bool mini_frame, Lisp_Object owner)
{
RECT rect;
+ Window window;
rect.left = rect.top = 0;
rect.right = FRAME_PIXEL_WIDTH (f);
rect.bottom = FRAME_PIXEL_HEIGHT (f);
-
AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false);
- tip_window = FRAME_W32_WINDOW (f)
- = CreateWindow (EMACS_CLASS,
- f->namebuf,
- f->output_data.w32->dwStyle,
- f->left_pos,
- f->top_pos,
- rect.right - rect.left,
- rect.bottom - rect.top,
- FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
- NULL,
- hinst,
- NULL);
-
- if (tip_window)
+ if (window
+ = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle,
+ f->left_pos, f->top_pos,
+ rect.right - rect.left, rect.bottom - rect.top,
+ (FRAME_W32_WINDOW /* owner */
+ (mini_frame ? XFRAME (owner) : SELECTED_FRAME ())),
+ NULL, hinst, NULL))
{
- SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
- SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
- SetWindowLong (tip_window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
- SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
+ FRAME_W32_WINDOW (f) = window;
+ if (!mini_frame)
+ tip_window = FRAME_W32_WINDOW (f);
+
+ SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
+ SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
+ SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
+ SetWindowLong (window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
/* Tip frames have no scrollbars. */
- SetWindowLong (tip_window, WND_VSCROLLBAR_INDEX, 0);
- SetWindowLong (tip_window, WND_HSCROLLBAR_INDEX, 0);
+ SetWindowLong (window, WND_VSCROLLBAR_INDEX, 0);
+ SetWindowLong (window, WND_HSCROLLBAR_INDEX, 0);
/* Do this to discard the default setting specified by our parent. */
- ShowWindow (tip_window, SW_HIDE);
+ ShowWindow (window, SW_HIDE);
}
}
@@ -6515,7 +6512,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
/* Create a frame for a tooltip on the display described by DPYINFO.
- PARMS is a list of frame parameters. Value is the frame.
+ PARMS is a list of frame parameters. MINI_FRAME true means to create
+ a mini-frame. Value is the frame.
Note that functions called here, esp. x_default_parameter can
signal errors, for instance when a specified color name is
@@ -6523,7 +6521,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
when this happens. */
static Lisp_Object
-x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
+x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms, bool mini_frame, Lisp_Object owner)
{
struct frame *f;
Lisp_Object frame;
@@ -6558,7 +6556,10 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
f->wants_modeline = false;
XSETFRAME (frame, f);
- record_unwind_protect (unwind_create_tip_frame, frame);
+ if (mini_frame)
+ record_unwind_protect (do_unwind_create_frame, frame);
+ else
+ record_unwind_protect (unwind_create_tip_frame, frame);
/* By setting the output method, we're essentially saying that
the frame is live, as per FRAME_LIVE_P. If we get a signal
@@ -6606,7 +6607,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
that are needed to determine window geometry. */
x_default_font_parameter (f, parms);
- x_default_parameter (f, parms, Qborder_width, make_number (2),
+ x_default_parameter (f, parms, Qborder_width,
+ make_number (mini_frame ? 0 : 2),
"borderWidth", "BorderWidth", RES_TYPE_NUMBER);
/* This defaults to 2 in order to match xterm. We recognize either
internalBorderWidth or internalBorder (which is what xterm calls
@@ -6622,7 +6624,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
parms);
}
- x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
+ x_default_parameter (f, parms, Qinternal_border_width,
+ make_number (mini_frame ? 0 : 1),
"internalBorderWidth", "internalBorderWidth",
RES_TYPE_NUMBER);
/* Also do the stuff which must be set before the window exists. */
@@ -6642,7 +6645,29 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
init_iterator with a null face cache, which should not happen. */
init_frame_faces (f);
- f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
+ /* Handle `child-window' and `border-width' separately for
+ mini-frames. */
+ if (mini_frame)
+ {
+ Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
+
+ f->output_data.w32->dwStyle =
+ (!NILP (Fassq (Qchild_window, parms))) ? WS_CHILD : WS_POPUP;
+
+ /* Always disable input. */
+ f->output_data.w32->dwStyle =
+ f->output_data.w32->dwStyle | WS_DISABLED;
+
+ /* Have Windows draw a "thin-line border". `border-width' is
+ usually dismissed on Windows but for mini frames, if it's
+ non-zero, draw a standard thin border around the frame. */
+ if (NUMBERP (border_width) && (XINT (border_width) > 0))
+ f->output_data.w32->dwStyle =
+ f->output_data.w32->dwStyle | WS_BORDER;
+ }
+ else
+ f->output_data.w32->dwStyle = WS_DISABLED | WS_BORDER | WS_POPUP;
+
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
x_figure_window_size (f, parms, true, &x_width, &x_height);
@@ -6656,7 +6681,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
f->bottom_divider_width = 0;
block_input ();
- my_create_tip_window (f);
+ my_create_tip_window (f, mini_frame, owner);
unblock_input ();
x_make_gc (f);
@@ -6680,8 +6705,10 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
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)))
+ /* Add `mini-frame' or `tooltip' frame parameter's default value. */
+ if (mini_frame && NILP (Fframe_parameter (frame, Qmini_frame)))
+ Fmodify_frame_parameters (frame, Fcons (Fcons (Qmini_frame, Qt), Qnil));
+ if (!mini_frame && NILP (Fframe_parameter (frame, Qtooltip)))
Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
/* Set up faces after all frame parameters are known. This call
@@ -7060,7 +7087,7 @@ with offset DY added (default is -10).
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
struct frame *f; /* The value is unused. */
- if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
+ if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, false, Qnil)))
{
/* Creating the tip frame failed. */
unblock_input ();
@@ -7071,6 +7098,7 @@ with offset DY added (default is -10).
tip_f = XFRAME (tip_frame);
window = FRAME_ROOT_WINDOW (tip_f);
set_window_buffer (window, Fget_buffer_create (tip), false, false);
+
w = XWINDOW (window);
w->pseudo_window_p = true;
@@ -7179,6 +7207,89 @@ with offset DY added (default is -10).
{
return x_hide_tip (!tooltip_reuse_hidden_frame);
}
+
+
+DEFUN ("w32-create-mini-frame", Fw32_create_mini_frame, Sw32_create_mini_frame, 1, 2, 0,
+ doc: /* Create a mini-frame.
+FRAME is the frame where to attach this one to. PARAMETERS is an alist of
+frame paramaters.
+
+The following parameters are special:
+
+- 'child-window" makes the new frame a child window of FRAME. This has
+ a number of consequences. On Windows 'alpha' does not necessarily
+ work if this is set.
+
+- 'external-border' enables external border. */)
+ (Lisp_Object frame, Lisp_Object parameters)
+{
+ struct frame *f = decode_window_system_frame (frame);
+ Lisp_Object tip_frame;
+ ptrdiff_t count = SPECPDL_INDEX ();
+ long window_prompting = 0;
+
+ if (!FRAME_W32_P (f) || NILP (FRAME_MINIBUF_WINDOW(f)))
+ error ("Cannot create tip-like frame for non-GUI or minibuffer-less frame");
+
+ /* Make copy of frame parameters because the original is in pure
+ storage now. */
+ parameters = Fcopy_alist (parameters);
+
+ specbind (Qinhibit_redisplay, Qt);
+ block_input ();
+ if (!NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parameters, true, frame)))
+ {
+ struct frame *tip_f;
+ struct window *w;
+ int old_windows_or_buffers_changed = windows_or_buffers_changed;
+ Lisp_Object window, tem;
+ Lisp_Object visibility;
+ int x_width = 0, x_height = 0;
+
+ tip_f = XFRAME (tip_frame);
+ window = FRAME_ROOT_WINDOW (tip_f);
+ w = XWINDOW (window);
+ w->pseudo_window_p = true;
+
+ fset_minibuffer_window (tip_f, FRAME_MINIBUF_WINDOW (f));
+ FRAME_EXTERNAL_MENU_BAR (tip_f) = false;
+
+ window_prompting
+ = x_figure_window_size (tip_f, parameters, true, &x_width, &x_height);
+
+ tip_f->mini_frame = true;
+ /* Allow x_set_window_size, now. */
+ tip_f->can_x_set_window_size = true;
+
+ if (x_width > 0)
+ SET_FRAME_WIDTH (tip_f, x_width);
+ if (x_height > 0)
+ SET_FRAME_HEIGHT (tip_f, x_height);
+
+ adjust_frame_size (tip_f, FRAME_TEXT_WIDTH (tip_f), FRAME_TEXT_HEIGHT (tip_f),
+ 0, true, Qx_create_frame_2); /* NEW SYMBOL NEEDED */
+
+ visibility = x_get_arg (FRAME_DISPLAY_INFO (f), parameters,
+ Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+ if (EQ (visibility, Qunbound) || !NILP (visibility))
+ SET_FRAME_VISIBLE (tip_f, 1);
+
+ ShowWindow (FRAME_W32_WINDOW (tip_f),
+ (EQ (visibility, Qunbound) || !NILP (visibility))
+ ? SW_SHOWNOACTIVATE : SW_HIDE);
+
+ w->must_be_updated_p = true;
+ update_single_window (w);
+ windows_or_buffers_changed = old_windows_or_buffers_changed;
+
+ for (tem = parameters; CONSP (tem); tem = XCDR (tem))
+ if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+ fset_param_alist (tip_f, Fcons (XCAR (tem), tip_f->param_alist));
+ }
+
+ unblock_input ();
+ return unbind_to (count, tip_frame);
+}
\f
/***********************************************************************
File selection dialog
@@ -8563,6 +8674,58 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are
}
}
+static Lisp_Object
+w32_frame_list_z_order (struct w32_display_info *dpyinfo, HWND window, Lisp_Object frames)
+{
+ while (window)
+ {
+ HWND child;
+ struct frame *f = x_window_to_frame (dpyinfo, window);
+ Lisp_Object frame;
+
+ /* Process child windows first - they precede their parent in the
+ z-order. */
+ block_input ();
+ child = GetWindow (window, GW_CHILD);
+ unblock_input ();
+ if (child)
+ frames = w32_frame_list_z_order (dpyinfo, child, frames);
+
+ if (f)
+ {
+ XSETFRAME (frame, f);
+ frames = Fcons (frame, frames);
+ }
+
+ block_input ();
+ window = GetNextWindow (window, GW_HWNDNEXT);
+ unblock_input ();
+ }
+
+ return frames;
+}
+
+DEFUN ("w32-frame-list-z-order", Fw32_frame_list_z_order,
+ Sw32_frame_list_z_order, 0, 1, 0,
+ doc: /* Return list of Emacs' frames, in Z (stacking) order.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Frames are listed from bottommost (first) to topmost (last). Return
+nil if DISPLAY contains no Emacs frame. */)
+ (Lisp_Object display)
+{
+ struct w32_display_info *dpyinfo = check_x_display_info (display);
+ HWND window;
+
+ block_input ();
+ window = GetTopWindow (NULL);
+ unblock_input ();
+
+ return w32_frame_list_z_order (dpyinfo, window, Qnil);
+}
+
DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position,
Sw32_mouse_absolute_pixel_position, 0, 0, 0,
doc: /* Return absolute position of mouse cursor in pixels.
@@ -9709,6 +9872,41 @@ enum NI_Severity {
#endif /* WINDOWSNT && !HAVE_DBUS */
+/* XXXXXXXXXXXXXXXXXXXXX */
+#ifdef WINDOWSNT
+DEFUN ("w32-focus", Fw32_focus, Sw32_focus,
+ 0, 0, 0,
+ doc: /* Return t if the selected frame has focus. */)
+ (void)
+{
+ HWND focus_window;
+
+ block_input ();
+ focus_window = GetFocus ();
+ unblock_input ();
+
+ return focus_window == NULL ? Qnil : Qt;
+}
+
+DEFUN ("w32-foreground-window", Fw32_foreground_window, Sw32_foreground_window,
+ 0, 0, 0,
+ doc: /* Return frame of current foreground window, if it's ours. */)
+ (void)
+{
+ Lisp_Object frame;
+ struct frame *f;
+ struct w32_display_info *dpyinfo = &one_w32_display_info;
+
+ block_input ();
+ f = x_window_to_frame (dpyinfo, GetForegroundWindow ());
+ unblock_input ();
+ XSETFRAME (frame, f);
+
+ return frame;
+}
+
+#endif
+/* XXXXXXXXXXXXXXXXXXXXXXXX */
\f
/***********************************************************************
Initialization
@@ -9781,6 +9979,7 @@ enum NI_Severity {
DEFSYM (Qmm_size, "mm-size");
DEFSYM (Qframes, "frames");
DEFSYM (Qtip_frame, "tip-frame");
+ DEFSYM (Qchild_window, "child-window");
DEFSYM (Qassq_delete_all, "assq-delete-all");
DEFSYM (Qunicode_sip, "unicode-sip");
#if defined WINDOWSNT && !defined HAVE_DBUS
@@ -10094,6 +10293,15 @@ successive mouse move (or scroll bar drag) events before they are
This variable has effect only on Windows Vista and later. */);
w32_disable_new_uniscribe_apis = 0;
+ /* XXXXXXXXXXXXXX */
+ DEFVAR_BOOL ("w32-keyboard-hook-active",
+ w32_keyboard_hook_active,
+ doc: /* Non-nil means w32 hotkey registration is activated.
+Set this to nil to get the old behavior of hotkey handling; this should
+only be necessary if the default setting causes problems. */);
+ w32_keyboard_hook_active = true;
+ /* XXXXXXXXXXXXXX */
+
DEFVAR_LISP ("w32-tooltip-extra-pixels",
Vw32_tooltip_extra_pixels,
doc: /* Number of pixels added after tooltip text.
@@ -10134,6 +10342,7 @@ successive mouse move (or scroll bar drag) events before they are
defsubr (&Sx_display_list);
defsubr (&Sw32_frame_geometry);
defsubr (&Sw32_frame_edges);
+ defsubr (&Sw32_frame_list_z_order);
defsubr (&Sw32_mouse_absolute_pixel_position);
defsubr (&Sw32_set_mouse_absolute_pixel_position);
defsubr (&Sx_synchronize);
@@ -10159,6 +10368,10 @@ successive mouse move (or scroll bar drag) events before they are
#endif
#ifdef WINDOWSNT
+ /* XXXXXXXXXXXXXXX */
+ defsubr (&Sw32_focus);
+ defsubr (&Sw32_foreground_window);
+ /* XXXXXXXXXXXXXXX */
defsubr (&Sfile_system_info);
defsubr (&Sdefault_printer_name);
#endif
@@ -10166,6 +10379,7 @@ successive mouse move (or scroll bar drag) events before they are
defsubr (&Sset_message_beep);
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
+ defsubr (&Sw32_create_mini_frame);
tip_timer = Qnil;
staticpro (&tip_timer);
tip_frame = Qnil;
diff --git a/src/w32term.c b/src/w32term.c
index 5a11e2a..04c6178 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5015,7 +5015,11 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f && !FRAME_ICONIFIED_P (f))
- x_real_positions (f, &f->left_pos, &f->top_pos);
+ {
+ x_real_positions (f, &f->left_pos, &f->top_pos);
+ inev.kind = MOVE_FRAME_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
+ }
check_visibility = 1;
break;
@@ -6444,9 +6448,11 @@ struct xim_inst_t
frames that were truely hidden (using make-frame-invisible), so
we need it to avoid Bug#5482. It seems that iconified is only
set for minimized windows that are still visible, so use that to
- determine the appropriate flag to pass ShowWindow. */
+ determine the appropriate flag to pass to ShowWindow. */
my_show_window (f, FRAME_W32_WINDOW (f),
- FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL);
+ f->mini_frame ? SW_SHOWNOACTIVATE
+ : FRAME_ICONIFIED_P (f) ? SW_RESTORE
+ : SW_SHOWNORMAL);
}
/* Synchronize to ensure Emacs knows the frame is visible
@@ -6531,7 +6537,8 @@ struct xim_inst_t
x_set_bitmap_icon (f);
/* Simulate the user minimizing the frame. */
- SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
+/** SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0); **/
+ my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWMINNOACTIVE);
SET_FRAME_VISIBLE (f, 0);
SET_FRAME_ICONIFIED (f, true);
diff --git a/src/window.c b/src/window.c
index e123b89..2ff0dc5 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1896,6 +1896,115 @@ of the (first) text line, YPOS is negative.
return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
}
+DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0,
+ doc: /* Return pixel dimensions of WINDOW's lines.
+The return value is a list of the x- and y-coordinates of the lower
+right corner of the last character of each line. Return nil if the
+current glyph matrix of WINDOW is not up-to-date.
+
+Optional argument WINDOW specifies the window whose lines' dimensions
+shall be returned. Nil or omitted means to return the dimensions for
+the selected window.
+
+FIRST, if non-nil, specifies the first line whose dimensions shall be
+returned. If FIRST is nil and BODY is non-nil, start with the first
+text line of WINDOW. Otherwise, start with the first line of WINDOW.
+
+LAST, if non-nil, specifies the last line whose dimensions shall be
+returned. If LAST is nil and BODY is non-nil, the last line is the last
+line of the body (text area) of WINDOW. Otherwise, last is the last
+line of WINDOW.
+
+INVERSE, if non-nil, means that the y-pixel value returned should
+specify the number of pixels from the left corner of the last glyph of
+each line to the right edge (body edge if BODY is non-nil) of WINDOW.
+INVERSE nil means to count from the left edge (body edge if BODY is
+non-nil) of WINDOW.
+
+LEFT non-nil means to return the x- and y-coordinates of the lower left
+corner of the leftmost character on each line. This is the value that
+should be used for buffers that mostly display text from right to
+left. */)
+ (Lisp_Object window, Lisp_Object first, Lisp_Object last, Lisp_Object body, Lisp_Object inverse, Lisp_Object left)
+{
+ struct window *w = decode_live_window (window);
+ struct buffer *b;
+ struct glyph_row *row, *end_row;
+ int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
+ Lisp_Object rows = Qnil;
+ int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true);
+ int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+ int subtract = NILP (body) ? 0 : header_line_height;
+ bool invert = !NILP (inverse);
+ bool left_flag = !NILP (left);
+
+ if (noninteractive || w->pseudo_window_p)
+ return Qnil;
+
+ CHECK_BUFFER (w->contents);
+ b = XBUFFER (w->contents);
+
+ /* Fail if current matrix is not up-to-date. */
+ if (!w->window_end_valid
+ || windows_or_buffers_changed
+ || b->clip_changed
+ || b->prevent_redisplay_optimizations_p
+ || window_outdated (w))
+ return Qnil;
+
+ if (NILP (first))
+ row = MATRIX_ROW (w->current_matrix, 0);
+ else if (NUMBERP (first))
+ {
+ CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows);
+ row = MATRIX_ROW (w->current_matrix, XINT (first));
+ }
+ else if (!NILP (body))
+ row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ else
+ error ("Invalid specification of first line");
+
+ if (NILP (last))
+ end_row = MATRIX_ROW (w->current_matrix, w->current_matrix->nrows);
+ else if (NUMBERP (first))
+ {
+ CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows);
+ end_row = MATRIX_ROW (w->current_matrix, XINT (last));
+ }
+ else if (!NILP (body))
+ end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+ else
+ error ("Invalid specification of last line");
+
+ while (row <= end_row && row->enabled_p
+ && row->y + row->height < max_y)
+ {
+
+ if (left_flag)
+ {
+ struct glyph *glyph = row->glyphs[TEXT_AREA];
+
+ rows = Fcons (Fcons (make_number
+ (invert
+ ? glyph->pixel_width
+ : window_width - glyph->pixel_width),
+ make_number (row->y + row->height - subtract)),
+ rows);
+ }
+ else
+ rows = Fcons (Fcons (make_number
+ (invert
+ ? window_width - row->pixel_width
+ : row->pixel_width), /* maybe add left
+ margin here */
+ make_number (row->y + row->height - subtract)),
+ rows);
+ row++;
+ }
+
+ return Fnreverse (rows);
+}
+
DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
0, 1, 0,
doc: /* Return non-nil when WINDOW is dedicated to its buffer.
@@ -7571,6 +7680,7 @@ this value for parameters without read syntax (like windows or frames).
defsubr (&Sset_window_point);
defsubr (&Sset_window_start);
defsubr (&Swindow_dedicated_p);
+ defsubr (&Swindow_lines_pixel_dimensions);
defsubr (&Sset_window_dedicated_p);
defsubr (&Swindow_display_table);
defsubr (&Sset_window_display_table);
diff --git a/src/xdisp.c b/src/xdisp.c
index 14d6f8f..b31e77d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11367,10 +11367,15 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
struct frame *sf = SELECTED_FRAME ();
mini_window = FRAME_MINIBUF_WINDOW (sf);
+
+ /* Don't redisplay if the selected frame has no mini_window. This may
+ be the case for tooltip frames. */
+ if (NILP (mini_window))
+ return;
w = XWINDOW (mini_window);
f = XFRAME (WINDOW_FRAME (w));
- /* Don't display if frame is invisible or not yet initialized. */
+ /* Don't redisplay if frame is invisible or not yet initialized. */
if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
return;
@@ -11713,7 +11718,8 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
if ((FRAME_WINDOW_P (f)
|| FRAME_MINIBUF_ONLY_P (f)
|| f->explicit_name)
- && NILP (Fframe_parameter (frame, Qtooltip)))
+ && NILP (Fframe_parameter (frame, Qtooltip))
+ && NILP (Fframe_parameter (frame, Qmini_frame)))
{
/* Do we have more than one visible frame on this X display? */
Lisp_Object tail, other_frame, fmt;
diff --git a/src/xfns.c b/src/xfns.c
index 798dc49..2643f11 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4738,6 +4738,60 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are
: Qnative_edges));
}
+static Lisp_Object
+x_frame_list_z_order (Display* dpy, struct x_display_info *dpyinfo, Window window, Lisp_Object frames)
+{
+ Window root, parent, *children;
+ unsigned int nchildren;
+ int i;
+
+ block_input ();
+ if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
+ {
+ unblock_input ();
+ for (i = nchildren - 1; i >= 0; i--)
+ {
+ struct frame *f = x_window_to_frame (dpyinfo, children[i]);
+
+ /* Process child windows first - they precede their paarent
+ in the z-order. */
+ frames = x_frame_list_z_order (dpy, dpyinfo, children[i], frames);
+
+ if (f)
+ {
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+ frames = Fcons (frame, frames);
+ }
+ }
+
+ if (children) XFree ((char *)children);
+ }
+ else
+ unblock_input ();
+
+ return frames;
+}
+
+
+DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
+ Sx_frame_list_z_order, 0, 1, 0,
+ doc: /* Return list of Emacs' frames, in Z (stacking) order.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Frames are listed from bottommost (first) to topmost (last). Return
+nil if DISPLAY contains no Emacs frame. */)
+ (Lisp_Object display)
+{
+ struct x_display_info *dpyinfo = check_x_display_info (display);
+ Display *dpy = dpyinfo->display;
+
+ return x_frame_list_z_order (dpy, dpyinfo, dpyinfo->root_window, Qnil);
+}
+
DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
Sx_mouse_absolute_pixel_position, 0, 0, 0,
doc: /* Return absolute position of mouse cursor in pixels.
@@ -5355,7 +5409,7 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
when this happens. */
static Lisp_Object
-x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
+x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms, bool mini_frame, Lisp_Object owner)
{
struct frame *f;
Lisp_Object frame;
@@ -5381,7 +5435,10 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
f = make_frame (false);
f->wants_modeline = false;
XSETFRAME (frame, f);
- record_unwind_protect (unwind_create_tip_frame, frame);
+ if (mini_frame)
+ record_unwind_protect (do_unwind_create_frame, frame);
+ else
+ record_unwind_protect (unwind_create_tip_frame, frame);
f->terminal = dpyinfo->terminal;
@@ -5495,7 +5552,8 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
parms);
}
- x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
+ x_default_parameter (f, parms, Qinternal_border_width,
+ make_number (mini_frame ? 0 : 1),
"internalBorderWidth", "internalBorderWidth",
RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qright_divider_width, make_number (0),
@@ -5545,17 +5603,30 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
= f->output_data.x->text_cursor;
/* Arrange for getting MapNotify and UnmapNotify events. */
attrs.event_mask = StructureNotifyMask;
- tip_window
- = FRAME_X_WINDOW (f)
- = XCreateWindow (FRAME_X_DISPLAY (f),
- FRAME_DISPLAY_INFO (f)->root_window,
- /* x, y, width, height */
- 0, 0, 1, 1,
- /* Border. */
- f->border_width,
- CopyFromParent, InputOutput, CopyFromParent,
- mask, &attrs);
- XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
+ if (mini_frame && !NILP (Fassq (Qchild_window, parms)))
+ FRAME_X_WINDOW (f)
+ = (XCreateSimpleWindow
+ (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (XFRAME (owner)),
+ /* x, y, width, height */
+ f->left_pos, f->top_pos, 1, 1,
+ f->border_width,
+ CopyFromParent, CopyFromParent));
+ else
+ FRAME_X_WINDOW (f)
+ = (XCreateWindow
+ (FRAME_X_DISPLAY (f),
+ FRAME_DISPLAY_INFO (f)->root_window,
+ /* x, y, width, height */
+ f->left_pos, f->top_pos, 1, 1,
+ /* Border. */
+ f->border_width,
+ CopyFromParent, InputOutput, CopyFromParent,
+ mask, &attrs));
+
+ if (!mini_frame) tip_window = FRAME_X_WINDOW (f);
+
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
XA_ATOM, 32, PropModeReplace,
(unsigned char *)&type, 1);
@@ -6038,7 +6109,7 @@ with offset DY added (default is -10).
/* 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)))
+ if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, false, Qnil)))
/* Creating the tip frame failed. */
return unbind_to (count, Qnil);
}
@@ -6131,6 +6202,90 @@ with offset DY added (default is -10).
return x_hide_tip (!tooltip_reuse_hidden_frame);
}
+DEFUN ("x-create-mini-frame", Fx_create_mini_frame, Sx_create_mini_frame, 1, 2, 0,
+ doc: /* Create a mini-frame.
+FRAME is the frame where to attach this one to. PARAMETERS is an alist of
+frame paramaters.
+
+The following parameters are special:
+
+- 'child-window" makes the new frame a child window of FRAME. This has
+ a number of consequences. On Windows 'alpha' does not necessarily
+ work if this is set.
+
+- 'external-border' enables external border. */)
+ (Lisp_Object frame, Lisp_Object parameters)
+{
+ struct frame *f = decode_window_system_frame (frame);
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ Lisp_Object tip_frame;
+ ptrdiff_t count = SPECPDL_INDEX ();
+
+ if (!dpyinfo->terminal->name)
+ error ("Terminal is not live, can't create new frames on it");
+
+ if (NILP (FRAME_MINIBUF_WINDOW(f)))
+ error ("Cannot create tip-like frame for minibuffer-less frame");
+
+ /* Make copy of frame parameters because the original is in pure
+ storage now. */
+ parameters = Fcopy_alist (parameters);
+
+ specbind (Qinhibit_redisplay, Qt);
+ block_input ();
+ if (!NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parameters, true, frame)))
+ {
+ struct frame *tip_f;
+ struct window *w;
+ int old_windows_or_buffers_changed = windows_or_buffers_changed;
+ Lisp_Object window, tem;
+ Lisp_Object visibility;
+ int x_width = 0, x_height = 0;
+
+ tip_f = XFRAME (tip_frame);
+ window = FRAME_ROOT_WINDOW (tip_f);
+ w = XWINDOW (window);
+ w->pseudo_window_p = true;
+
+ fset_minibuffer_window (tip_f, FRAME_MINIBUF_WINDOW (f));
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+ FRAME_EXTERNAL_MENU_BAR (tip_f) = false;
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
+
+ x_figure_window_size (tip_f, parameters, true, &x_width, &x_height);
+
+ tip_f->mini_frame = true;
+ /* Allow x_set_window_size, now. */
+ tip_f->can_x_set_window_size = true;
+
+ if (x_width > 0)
+ SET_FRAME_WIDTH (tip_f, x_width);
+ if (x_height > 0)
+ SET_FRAME_HEIGHT (tip_f, x_height);
+
+ adjust_frame_size (tip_f, FRAME_TEXT_WIDTH (tip_f), FRAME_TEXT_HEIGHT (tip_f),
+ 0, true, Qx_create_frame_2); /* NEW SYMBOL NEEDED */
+
+ visibility = x_get_arg (FRAME_DISPLAY_INFO (f), parameters,
+ Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+ if (EQ (visibility, Qunbound) || !NILP (visibility))
+ SET_FRAME_VISIBLE (tip_f, 1);
+
+ /* Map tip-like frame. */
+ XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
+
+ w->must_be_updated_p = true;
+ update_single_window (w);
+ windows_or_buffers_changed = old_windows_or_buffers_changed;
+
+ for (tem = parameters; CONSP (tem); tem = XCDR (tem))
+ if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+ fset_param_alist (tip_f, Fcons (XCAR (tem), tip_f->param_alist));
+ }
+
+ unblock_input ();
+ return unbind_to (count, tip_frame);
+}
\f
/***********************************************************************
File selection dialog
@@ -6792,6 +6947,7 @@ FRAMES should be nil (the selected frame), a frame, or a list of
DEFSYM (Qcancel_timer, "cancel-timer");
DEFSYM (Qfont_parameter, "font-parameter");
DEFSYM (Qmono, "mono");
+ DEFSYM (Qchild_window, "child-window");
DEFSYM (Qassq_delete_all, "assq-delete-all");
#ifdef USE_CAIRO
@@ -6985,6 +7141,7 @@ FRAMES should be nil (the selected frame), a frame, or a list of
defsubr (&Sx_display_monitor_attributes_list);
defsubr (&Sx_frame_geometry);
defsubr (&Sx_frame_edges);
+ defsubr (&Sx_frame_list_z_order);
defsubr (&Sx_mouse_absolute_pixel_position);
defsubr (&Sx_set_mouse_absolute_pixel_position);
defsubr (&Sx_wm_set_size_hint);
@@ -6997,6 +7154,7 @@ FRAMES should be nil (the selected frame), a frame, or a list of
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
+ defsubr (&Sx_create_mini_frame);
tip_timer = Qnil;
staticpro (&tip_timer);
tip_frame = Qnil;
diff --git a/src/xterm.c b/src/xterm.c
index cd1d712..03d53c6 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -4252,7 +4252,7 @@ Status x_parse_color (struct frame *f, const char *color_name,
/* Return the Emacs frame-object corresponding to an X window.
It could be the frame's main window or an icon window. */
-static struct frame *
+struct frame *
x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
{
Lisp_Object tail, frame;
@@ -8476,7 +8476,20 @@ static void xembed_send_message (struct frame *f, Time,
if (FRAME_GTK_OUTER_WIDGET (f)
&& gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
#endif
- x_real_positions (f, &f->left_pos, &f->top_pos);
+
+
+ {
+ int old_left = f->left_pos;
+ int old_top = f->top_pos;
+
+ x_real_positions (f, &f->left_pos, &f->top_pos);
+
+ if (old_left != f->left_pos || old_top != f->top_pos)
+ {
+ inev.ie.kind = MOVE_FRAME_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ }
+ }
#ifdef HAVE_X_I18N
if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
diff --git a/src/xterm.h b/src/xterm.h
index 675a484..c61a339 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1086,6 +1086,7 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
extern void x_cr_draw_frame (cairo_t *, struct frame *);
extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
#endif
+extern struct frame *x_window_to_frame (struct x_display_info *, int);
INLINE int
x_display_pixel_height (struct x_display_info *dpyinfo)
[-- Attachment #3: mini-frame.el --]
[-- Type: application/emacs-lisp, Size: 13768 bytes --]
prev parent reply other threads:[~2016-07-15 16:41 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-12 21:47 Latest master broken on Cocoa/NS João Távora
2016-07-12 22:05 ` John Wiegley
2016-07-12 22:06 ` João Távora
2016-07-12 22:26 ` John Wiegley
2016-07-14 5:41 ` Dmitry Antipov
2016-07-14 6:26 ` John Wiegley
2016-07-15 6:41 ` Dmitry Antipov
2016-07-15 6:46 ` John Wiegley
2016-07-15 7:25 ` Eli Zaretskii
2016-07-15 7:28 ` martin rudalics
2016-07-15 8:02 ` Eli Zaretskii
2016-07-15 9:10 ` martin rudalics
2016-07-15 13:35 ` Stefan Monnier
2016-07-15 13:51 ` Clément Pit--Claudel
2016-07-15 14:09 ` Eli Zaretskii
2016-07-15 14:21 ` Clément Pit--Claudel
2016-07-15 14:25 ` Eli Zaretskii
2016-07-15 15:14 ` Clément Pit--Claudel
2016-07-15 16:04 ` Eli Zaretskii
2016-07-15 16:16 ` Clément Pit--Claudel
2016-07-15 17:37 ` Eli Zaretskii
2016-07-15 14:08 ` Dmitry Gutov
2016-07-15 15:20 ` martin rudalics
2016-07-15 16:12 ` Clément Pit--Claudel
2016-07-15 16:41 ` martin rudalics [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=57891222.1060900@gmx.at \
--to=rudalics@gmx.at \
--cc=clement.pit@gmail.com \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.