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))) ;;;; 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))))) ;;;; 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); +} /*********************************************************************** 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 */ /*********************************************************************** 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); +} /*********************************************************************** 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)