emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master ea6c880: Frame movement, focus and hook related cha


From: Martin Rudalics
Subject: [Emacs-diffs] master ea6c880: Frame movement, focus and hook related changes
Date: Tue, 11 Apr 2017 06:41:12 -0400 (EDT)

branch: master
commit ea6c880aa68bcc8f0e388ecbd8c552392488b38f
Author: Martin Rudalics <address@hidden>
Commit: Martin Rudalics <address@hidden>

    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.
---
 lisp/frame.el   | 30 ++++++++++++++++++++++++++++++
 src/frame.c     | 37 +++++++++++++++++++++----------------
 src/keyboard.c  | 17 +++++++++++++++++
 src/termhooks.h |  3 +++
 src/w32term.c   |  6 +++++-
 src/window.c    |  9 +++++++++
 src/xterm.c     | 24 ++++++++++++++++++++++--
 7 files changed, 107 insertions(+), 19 deletions(-)

diff --git a/lisp/frame.el b/lisp/frame.el
index 0a35b71..4768b5b 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 d873147..5f57d4a 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 2e0a813..3e50142 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 3b1b495..14ec397 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 81666f5..31f0b4a 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 9569044..58c0c33 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 08ccac0..1d14407 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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]