diff options
author | Martin Rudalics <rudalics@gmx.at> | 2017-04-11 12:37:26 +0200 |
---|---|---|
committer | Martin Rudalics <rudalics@gmx.at> | 2017-04-11 12:37:26 +0200 |
commit | ea6c880aa68bcc8f0e388ecbd8c552392488b38f (patch) | |
tree | c4da212b292347d6668dc6283f8444fc795f6e2c | |
parent | 0eef8e9af7707b7bd01243033b9a48cb74fb8672 (diff) | |
download | emacs-ea6c880aa68bcc8f0e388ecbd8c552392488b38f.tar.gz |
Frame movement, focus and hook related changes
New hook `move-frame-functions'. Run `focus-in-hook'
after switching to frame that gets focus. Don't run
XMoveWindow for GTK.
* lisp/frame.el (handle-move-frame, frame-size-changed-p): New
functions.
* src/frame.c (do_switch_frame): Simplify code.
(Fhandle_switch_frame): Switch frame before running
`handle-focus-in'.
(Vfocus_in_hook, Vfocus_out_hook): Clarify doc-strings.
(Vmove_frame_functions): New hook variable.
* src/keyboard.c (kbd_buffer_get_event): Handle
MOVE_FRAME_EVENT. Handle SELECT_WINDOW_EVENT separately.
(head_table): Add Qmove_frame entry.
(syms_of_keyboard): Add Qmove_frame.
(keys_of_keyboard): Define key for `move-frame'.
* src/termhooks.h (event_kind): Add MOVE_FRAME_EVENT.
* src/w32term.c (w32_read_socket): Create MOVE_FRAME_EVENT.
* src/window.c (run_window_size_change_functions): Record size of
FRAME's minibuffer window too.
* src/xterm.c (handle_one_xevent): Create MOVE_FRAME_EVENT.
(x_set_offset): For GTK call gtk_widget_move instead of
XMoveWindow.
-rw-r--r-- | lisp/frame.el | 30 | ||||
-rw-r--r-- | src/frame.c | 37 | ||||
-rw-r--r-- | src/keyboard.c | 17 | ||||
-rw-r--r-- | src/termhooks.h | 3 | ||||
-rw-r--r-- | src/w32term.c | 6 | ||||
-rw-r--r-- | src/window.c | 9 | ||||
-rw-r--r-- | src/xterm.c | 24 |
7 files changed, 107 insertions, 19 deletions
diff --git a/lisp/frame.el b/lisp/frame.el index 0a35b715b3d..4768b5be002 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -144,6 +144,13 @@ Focus-out events occur when no frame has focus. 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,29 @@ keys and their meanings." for frames = (cdr (assq 'frames attributes)) if (memq frame frames) return attributes)) +(defun frame-size-changed-p (&optional frame) + "Return non-nil when the size of FRAME has changed. +More precisely, return non-nil when the inner width or height of +FRAME has changed since `window-size-change-functions' was run +for FRAME." + (let* ((frame (window-normalize-frame frame)) + (root (frame-root-window frame)) + (mini (minibuffer-window frame)) + (mini-height-before-size-change 0) + (mini-height 0)) + ;; FRAME's minibuffer window counts iff it's on FRAME and FRAME is + ;; not a minibuffer-only frame. + (when (and (eq (window-frame mini) frame) (not (eq mini root))) + (setq mini-height-before-size-change + (window-pixel-height-before-size-change mini)) + (setq mini-height (window-pixel-height mini))) + ;; Return non-nil when either the width of the root or the sum of + ;; the heights of root and minibuffer window changed. + (or (/= (window-pixel-width-before-size-change root) + (window-pixel-width root)) + (/= (+ (window-pixel-height-before-size-change root) + mini-height-before-size-change) + (+ (window-pixel-height root) mini-height))))) ;;;; Frame/display capabilities. diff --git a/src/frame.c b/src/frame.c index d873147fc8b..5f57d4a0c24 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1107,7 +1107,7 @@ affects all frames on the same terminal device. */) Lisp_Object do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord) { - struct frame *sf = SELECTED_FRAME (); + struct frame *sf = SELECTED_FRAME (), *f; /* If FRAME is a switch-frame event, extract the frame we should switch to. */ @@ -1120,10 +1120,10 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor a switch-frame event to arrive after a frame is no longer live, especially when deleting the initial frame during startup. */ CHECK_FRAME (frame); - if (! FRAME_LIVE_P (XFRAME (frame))) + f = XFRAME (frame); + if (!FRAME_LIVE_P (f)) return Qnil; - - if (sf == XFRAME (frame)) + else if (f == sf) return frame; /* If a frame's focus has been redirected toward the currently @@ -1156,11 +1156,11 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor #else /* ! 0 */ /* Instead, apply it only to the frame we're pointing to. */ #ifdef HAVE_WINDOW_SYSTEM - if (track && FRAME_WINDOW_P (XFRAME (frame))) + if (track && FRAME_WINDOW_P (f)) { Lisp_Object focus, xfocus; - xfocus = x_get_focus_frame (XFRAME (frame)); + xfocus = x_get_focus_frame (f); if (FRAMEP (xfocus)) { focus = FRAME_FOCUS_FRAME (XFRAME (xfocus)); @@ -1168,8 +1168,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor /* Redirect frame focus also when FRAME has its minibuffer window on the selected frame (see Bug#24500). */ || (NILP (focus) - && EQ (FRAME_MINIBUF_WINDOW (XFRAME (frame)), - sf->selected_window))) + && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window))) Fredirect_frame_focus (xfocus, frame); } } @@ -1179,9 +1178,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); - if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame))) + if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) { - struct frame *f = XFRAME (frame); struct tty_display_info *tty = FRAME_TTY (f); Lisp_Object top_frame = tty->top_frame; @@ -1209,7 +1207,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) last_nonminibuf_frame = XFRAME (selected_frame); - Fselect_window (XFRAME (frame)->selected_window, norecord); + Fselect_window (f->selected_window, norecord); /* We want to make sure that the next event generates a frame-switch event to the appropriate frame. This seems kludgy to me, but @@ -1253,12 +1251,15 @@ If EVENT is frame object, handle it as if it were a switch-frame event to that frame. */) (Lisp_Object event) { + Lisp_Object value; + /* Preserve prefix arg that the command loop just cleared. */ kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); run_hook (Qmouse_leave_buffer_hook); /* `switch-frame' implies a focus in. */ + value = do_switch_frame (event, 0, 0, Qnil); call1 (intern ("handle-focus-in"), event); - return do_switch_frame (event, 0, 0, Qnil); + return value; } DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, @@ -1709,8 +1710,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force) promise that the terminal of the frame must be valid until we have called the window-system-dependent frame destruction routine. */ - - { struct terminal *terminal; block_input (); @@ -5121,13 +5120,19 @@ The pointer becomes visible again when the mouse is moved. */); Vmake_pointer_invisible = Qt; DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook, - doc: /* Normal hook run when a frame gains input focus. */); + doc: /* Normal hook run when a frame gains input focus. +The frame gaining focus is selected at the time this hook is run. */); Vfocus_in_hook = Qnil; DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook, - doc: /* Normal hook run when a frame loses input focus. */); + doc: /* Normal hook run when all frames lost 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/keyboard.c b/src/keyboard.c index 2e0a813bb08..3e50142f7c1 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4056,6 +4056,14 @@ kbd_buffer_get_event (KBOARD **kbp, 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) { @@ -4068,6 +4076,11 @@ kbd_buffer_get_event (KBOARD **kbp, obj = make_lispy_event (&event->ie); kbd_fetch_ptr = event + 1; } + else if (event->kind == SELECT_WINDOW_EVENT) + { + obj = list2 (Qselect_window, list1 (event->ie.frame_or_window)); + kbd_fetch_ptr = event + 1; + } else { /* If this event is on a different frame, return a switch-frame this @@ -10977,6 +10990,7 @@ static const struct event_head head_table[] = { {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)}, @@ -11149,6 +11163,7 @@ syms_of_keyboard (void) 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"); @@ -11895,6 +11910,8 @@ keys_of_keyboard (void) "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 3b1b4959b1d..14ec397346a 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/w32term.c b/src/w32term.c index 81666f5bc47..31f0b4a2fa0 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -5038,7 +5038,11 @@ w32_read_socket (struct terminal *terminal, 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; diff --git a/src/window.c b/src/window.c index 95690443f8e..58c0c33cbb0 100644 --- a/src/window.c +++ b/src/window.c @@ -3314,6 +3314,9 @@ run_window_size_change_functions (Lisp_Object frame) Lisp_Object functions = Vwindow_size_change_functions; if (FRAME_WINDOW_CONFIGURATION_CHANGED (f) + /* Here we implicitly exclude the possibility that the height of + FRAME and its minibuffer window both change leaving the height + of FRAME's root window alone. */ || window_size_changed (r)) { while (CONSP (functions)) @@ -3324,6 +3327,12 @@ run_window_size_change_functions (Lisp_Object frame) } window_set_before_size_change_sizes (r); + + if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) + /* Record size of FRAME's minibuffer window too. */ + window_set_before_size_change_sizes + (XWINDOW (FRAME_MINIBUF_WINDOW (f))); + FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false; } } diff --git a/src/xterm.c b/src/xterm.c index 08ccac07005..1d14407aa43 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8614,7 +8614,22 @@ handle_one_xevent (struct x_display_info *dpyinfo, 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; + Lisp_Object frame = Qnil; + + XSETFRAME (frame, f); + + 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)) @@ -10088,8 +10103,13 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ modified_top += FRAME_X_OUTPUT (f)->move_offset_top; } +#ifdef USE_GTK + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + modified_left, modified_top); +#else XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - modified_left, modified_top); + modified_left, modified_top); +#endif x_sync_with_move (f, f->left_pos, f->top_pos, FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN); |