]> git.eshelyaron.com Git - emacs.git/commitdiff
Stop cursor blink after blink-cursor-blinks (10), stop timers when not blinking.
authorJan Djärv <jan.h.d@swipnet.se>
Tue, 16 Jul 2013 11:41:06 +0000 (13:41 +0200)
committerJan Djärv <jan.h.d@swipnet.se>
Tue, 16 Jul 2013 11:41:06 +0000 (13:41 +0200)
* etc/NEWS: Document blink-cursor-blinks and blink timers stopped.

* lisp/frame.el (blink-cursor-blinks): New defcustom.
(blink-cursor-blinks-done): New defvar.
(blink-cursor-start): Set blink-cursor-blinks-done to 1.
(blink-cursor-timer-function): Check if number of blinks has been
done on X and NS.
(blink-cursor-suspend, blink-cursor-check): New defuns.

* src/frame.c (Fhandle_focus_in, Fhandle_focus_out): New functions.
(Fhandle_switch_frame): Call Fhandle_focus_in.
(syms_of_frame): defsubr handle-focus-in/out.

* src/keyboard.c (Qfocus_in, Qfocus_out): New static objects.
(make_lispy_focus_in, make_lispy_focus_out): Declare and define.
(kbd_buffer_get_event): For FOCUS_IN, make a focus_in event if no
switch frame event is made.  Check ! NILP (event->arg) if X11 (moved
from xterm.c). Make focus_out event for FOCUS_OUT_EVENT if NS or X11
and there is a focused frame.
(head_table): Add focus-in and focus-out.
(keys_of_keyboard): Add focus-in and focus-out to Vspecial_event_map,
bind to handle-focus-in/out.

* src/nsterm.m (windowDidResignKey): If this is the focused frame, generate
FOCUS_OUT_EVENT.

* src/termhooks.h (enum event_kind): Add FOCUS_OUT_EVENT.

* src/xterm.c (x_focus_changed): Always generate FOCUS_IN_EVENT.
Set event->arg to Qt if switch-event shall be generated.
Generate FOCUS_OUT_EVENT for FocusOut if this is the focused frame.

etc/ChangeLog
etc/NEWS
lisp/ChangeLog
lisp/frame.el
src/ChangeLog
src/frame.c
src/keyboard.c
src/nsterm.m
src/termhooks.h
src/xterm.c

index 02b13e12945891e72e66b5602479dd226604f1cc..d477f8e3d36e550e57a00df0c5d6bbb96ee88442 100644 (file)
@@ -1,3 +1,7 @@
+2013-07-16  Jan Djärv  <jan.h.d@swipnet.se>
+
+       * NEWS: Document blink-cursor-blinks and blink timers stopped.
+
 2013-07-13  Eli Zaretskii  <eliz@gnu.org>
 
        * NEWS: Document prefer-utf-8 and the new attributes
index 869277fa84dbbcf8d0174a7fbfc355716e7e2699..46aaf18513300a95966d5b933d2f8ccc520cf7f4 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -122,6 +122,11 @@ monitor, use the new functions above.  Similar notes also apply to
 Generic commands are interactive functions whose implementation can be
 selected among several alternatives, as a matter of user preference.
 
+** The blink cursor stops blinking after 10 blinks (default) on X and NS.
+You can change the default by customizing the variable blink-cursor-blinks.
+Also timers for blinking are stopped when no blinking is done, so Emacs does
+not consume CPU cycles.
+
 \f
 * Editing Changes in Emacs 24.4
 
index 5949dcdbd00fa6f0b682163d24af3e7ac247bb87..d1613283bb787a9c3a11846dd717c86b313b1e3c 100644 (file)
@@ -1,3 +1,12 @@
+2013-07-16  Jan Djärv  <jan.h.d@swipnet.se>
+
+       * frame.el (blink-cursor-blinks): New defcustom.
+       (blink-cursor-blinks-done): New defvar.
+       (blink-cursor-start): Set blink-cursor-blinks-done to 1.
+       (blink-cursor-timer-function): Check if number of blinks has been
+       done on X and NS.
+       (blink-cursor-suspend, blink-cursor-check): New defuns.
+
 2013-07-15  Glenn Morris  <rgm@gnu.org>
 
        * edmacro.el (edmacro-format-keys): Fix previous change.
index 3ac24a509a0c065c052ffdf5f345dad51d6f395a..a37d1189552d6387aab8f2c30915b9324a527013 100644 (file)
@@ -1671,6 +1671,16 @@ left untouched.  FRAME nil or omitted means use the selected frame."
   :type 'number
   :group 'cursor)
 
+(defcustom blink-cursor-blinks 10
+  "How many times to blink before using a solid cursor on NS and X.
+Use 0 or negative value to blink forever."
+  :version "24.4"
+  :type 'integer
+  :group 'cursor)
+
+(defvar blink-cursor-blinks-done 1
+  "Number of blinks done since we started blinking on NS and X")
+
 (defvar blink-cursor-idle-timer nil
   "Timer started after `blink-cursor-delay' seconds of Emacs idle time.
 The function `blink-cursor-start' is called when the timer fires.")
@@ -1688,6 +1698,7 @@ command starts, by installing a pre-command hook."
   (when (null blink-cursor-timer)
     ;; Set up the timer first, so that if this signals an error,
     ;; blink-cursor-end is not added to pre-command-hook.
+    (setq blink-cursor-blinks-done 1)
     (setq blink-cursor-timer
          (run-with-timer blink-cursor-interval blink-cursor-interval
                          'blink-cursor-timer-function))
@@ -1696,7 +1707,15 @@ command starts, by installing a pre-command hook."
 
 (defun blink-cursor-timer-function ()
   "Timer function of timer `blink-cursor-timer'."
-  (internal-show-cursor nil (not (internal-show-cursor-p))))
+  (internal-show-cursor nil (not (internal-show-cursor-p)))
+  ;; Each blink is two calls to this function.
+  (when (memq window-system '(x ns))
+    (setq blink-cursor-blinks-done (1+ blink-cursor-blinks-done))
+    (when (and (> blink-cursor-blinks 0)
+              (<= (* 2 blink-cursor-blinks) blink-cursor-blinks-done))
+      (blink-cursor-suspend)
+      (add-hook 'post-command-hook 'blink-cursor-check))))
+
 
 (defun blink-cursor-end ()
   "Stop cursor blinking.
@@ -1709,6 +1728,29 @@ itself as a pre-command hook."
     (cancel-timer blink-cursor-timer)
     (setq blink-cursor-timer nil)))
 
+(defun blink-cursor-suspend ()
+  "Suspend cursor blinking on NS and X.
+This is called when no frame has focus and timers can be suspended.
+Timers are restarted by `blink-cursor-check', which is called when a
+frame receives focus."
+  (when (memq window-system '(x ns))
+    (blink-cursor-end)
+    (when blink-cursor-idle-timer
+      (cancel-timer blink-cursor-idle-timer)
+      (setq blink-cursor-idle-timer nil))))
+
+(defun blink-cursor-check ()
+  "Check if cursot blinking shall be restarted.
+This is done when a frame gets focus.  Blink timers may be stopped by
+`blink-cursor-suspend'."
+  (when (and blink-cursor-mode
+            (not blink-cursor-idle-timer))
+    (remove-hook 'post-command-hook 'blink-cursor-check)
+    (setq blink-cursor-idle-timer
+          (run-with-idle-timer blink-cursor-delay
+                               blink-cursor-delay
+                               'blink-cursor-start))))
+
 (define-obsolete-variable-alias 'blink-cursor 'blink-cursor-mode "22.1")
 
 (define-minor-mode blink-cursor-mode
index 4d819413b42a5534aa42ef7af1e5060fa6d1c065..7c3548c4f84340976c1ecfb7360b36cb2ad7b5d6 100644 (file)
@@ -1,3 +1,28 @@
+2013-07-16  Jan Djärv  <jan.h.d@swipnet.se>
+
+       * xterm.c (x_focus_changed): Always generate FOCUS_IN_EVENT.
+       Set event->arg to Qt if switch-event shall be generated.
+       Generate FOCUS_OUT_EVENT for FocusOut if this is the focused frame.
+
+       * termhooks.h (enum event_kind): Add FOCUS_OUT_EVENT.
+
+       * nsterm.m (windowDidResignKey): If this is the focused frame, generate
+       FOCUS_OUT_EVENT.
+
+       * keyboard.c (Qfocus_in, Qfocus_out): New static objects.
+       (make_lispy_focus_in, make_lispy_focus_out): Declare and define.
+       (kbd_buffer_get_event): For FOCUS_IN, make a focus_in event if no
+       switch frame event is made.  Check ! NILP (event->arg) if X11 (moved
+       from xterm.c). Make focus_out event for FOCUS_OUT_EVENT if NS or X11
+       and there is a focused frame.
+       (head_table): Add focus-in and focus-out.
+       (keys_of_keyboard): Add focus-in and focus-out to Vspecial_event_map,
+       bind to handle-focus-in/out.
+
+       * frame.c (Fhandle_focus_in, Fhandle_focus_out): New functions.
+       (Fhandle_switch_frame): Call Fhandle_focus_in.
+       (syms_of_frame): defsubr handle-focus-in/out.
+
 2013-07-16  Paul Eggert  <eggert@cs.ucla.edu>
 
        Fix porting bug to older POSIXish platforms (Bug#14862).
index f2cbfaa321f4e00d5b982bb0fdbe90715c31facc..5bd9f777755e5054777eed3dfd592b4608120527 100644 (file)
@@ -887,6 +887,26 @@ This function returns FRAME, or nil if FRAME has been deleted.  */)
   return do_switch_frame (frame, 1, 0, norecord);
 }
 
+DEFUN ("handle-focus-in", Fhandle_focus_in, Shandle_focus_in, 1, 1, "e",
+       doc: /* Handle a focus-in event.
+Focus in events are usually bound to this function.
+Focus in events occur when a frame has focus, but a switch-frame event
+is not generated.
+This function checks if blink-cursor timers should be turned on again.  */)
+  (Lisp_Object event)
+{
+  call0 (intern ("blink-cursor-check"));
+}
+
+DEFUN ("handle-focus-out", Fhandle_focus_out, Shandle_focus_out, 1, 1, "e",
+       doc: /* Handle a focus-out event.
+Focus out events are usually bound to this function.
+Focus out events occur when no frame has focus.
+This function checks if blink-cursor timers should be turned off.  */)
+  (Lisp_Object event)
+{
+  call0 (intern ("blink-cursor-suspend"));
+}
 
 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "e",
        doc: /* Handle a switch-frame event EVENT.
@@ -902,6 +922,7 @@ to that frame.  */)
   /* Preserve prefix arg that the command loop just cleared.  */
   kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
   Frun_hooks (1, &Qmouse_leave_buffer_hook);
+  Fhandle_focus_in (event); // switch-frame implies a focus in.
   return do_switch_frame (event, 0, 0, Qnil);
 }
 
@@ -4449,6 +4470,8 @@ automatically.  See also `mouse-autoselect-window'.  */);
   defsubr (&Swindow_system);
   defsubr (&Smake_terminal_frame);
   defsubr (&Shandle_switch_frame);
+  defsubr (&Shandle_focus_in);
+  defsubr (&Shandle_focus_out);
   defsubr (&Sselect_frame);
   defsubr (&Sselected_frame);
   defsubr (&Sframe_list);
index f6bc7f308e66a24d756b077d29e23994b0c45db4..5cdb87818caff39cbc331c6580298b2bfb87e229 100644 (file)
@@ -295,6 +295,7 @@ static struct input_event * volatile kbd_store_ptr;
 static Lisp_Object Qmouse_movement;
 static Lisp_Object Qscroll_bar_movement;
 Lisp_Object Qswitch_frame;
+static Lisp_Object Qfocus_in, Qfocus_out;
 static Lisp_Object Qdelete_frame;
 static Lisp_Object Qiconify_frame;
 static Lisp_Object Qmake_frame_visible;
@@ -420,6 +421,8 @@ static Lisp_Object modify_event_symbol (ptrdiff_t, int, Lisp_Object,
                                         Lisp_Object, const char *const *,
                                         Lisp_Object *, ptrdiff_t);
 static Lisp_Object make_lispy_switch_frame (Lisp_Object);
+static Lisp_Object make_lispy_focus_in (Lisp_Object);
+static Lisp_Object make_lispy_focus_out (Lisp_Object);
 static bool help_char_p (Lisp_Object);
 static void save_getcjmp (sys_jmp_buf);
 static void restore_getcjmp (sys_jmp_buf);
@@ -4061,17 +4064,45 @@ kbd_buffer_get_event (KBOARD **kbp,
             switch-frame event if necessary.  */
          Lisp_Object frame, focus;
 
-         frame = event->frame_or_window;
-         focus = FRAME_FOCUS_FRAME (XFRAME (frame));
-         if (FRAMEP (focus))
-           frame = focus;
+          frame = event->frame_or_window;
+          focus = FRAME_FOCUS_FRAME (XFRAME (frame));
+          if (FRAMEP (focus))
+            frame = focus;
 
-         if (!EQ (frame, internal_last_event_frame)
-             && !EQ (frame, selected_frame))
-           obj = make_lispy_switch_frame (frame);
-         internal_last_event_frame = frame;
-         kbd_fetch_ptr = event + 1;
-       }
+          if (
+#ifdef HAVE_X11
+              ! NILP (event->arg)
+              &&
+#endif
+              !EQ (frame, internal_last_event_frame)
+              && !EQ (frame, selected_frame))
+            obj = make_lispy_switch_frame (frame);
+          else
+            obj = make_lispy_focus_in (frame);
+
+          internal_last_event_frame = frame;
+          kbd_fetch_ptr = event + 1;
+        }
+      else if (event->kind == FOCUS_OUT_EVENT)
+        {
+#if defined(HAVE_NS) || defined (HAVE_X11)
+
+#ifdef HAVE_NS
+          struct ns_display_info *di;
+#else
+          struct x_display_info *di;
+#endif
+          Lisp_Object rest, frame = event->frame_or_window;
+          bool focused = false;
+
+          for (di = x_display_list; di && ! focused; di = di->next)
+            focused = di->x_highlight_frame != 0;
+
+          if (! focused) obj = make_lispy_focus_out (frame);
+#endif /* HAVE_NS || HAVE_X11 */
+
+          kbd_fetch_ptr = event + 1;
+        }
 #ifdef HAVE_DBUS
       else if (event->kind == DBUS_EVENT)
        {
@@ -6052,6 +6083,17 @@ make_lispy_switch_frame (Lisp_Object frame)
 {
   return list2 (Qswitch_frame, frame);
 }
+
+static Lisp_Object
+make_lispy_focus_in (Lisp_Object frame)
+{
+  return list2 (Qfocus_in, frame);
+}
+static Lisp_Object
+make_lispy_focus_out (Lisp_Object frame)
+{
+  return list2 (Qfocus_out, frame);
+}
 \f
 /* Manipulating modifiers.  */
 
@@ -10911,6 +10953,8 @@ static const struct event_head head_table[] = {
   {&Qmouse_movement,      "mouse-movement",      &Qmouse_movement},
   {&Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement},
   {&Qswitch_frame,        "switch-frame",        &Qswitch_frame},
+  {&Qfocus_in,            "focus-in",            &Qfocus_in},
+  {&Qfocus_out,           "focus-out",          &Qfocus_out},
   {&Qdelete_frame,        "delete-frame",        &Qdelete_frame},
   {&Qiconify_frame,       "iconify-frame",       &Qiconify_frame},
   {&Qmake_frame_visible,  "make-frame-visible",  &Qmake_frame_visible},
@@ -11725,6 +11769,10 @@ keys_of_keyboard (void)
   initial_define_lispy_key (Vspecial_event_map, "language-change",
                            "ignore");
 #endif
+  initial_define_lispy_key (Vspecial_event_map, "focus-in",
+                           "handle-focus-in");
+  initial_define_lispy_key (Vspecial_event_map, "focus-out",
+                           "handle-focus-out");
 }
 
 /* Mark the pointers in the kboard objects.
index 340ef3b00a235bc6a04ebae994a0f6c1b34c2aed..c91e68f37a9ad1a8607fcf4e24b98ca2b74b1373 100644 (file)
@@ -5746,9 +5746,10 @@ not_in_argv (NSString *arg)
 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
 {
   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
+  BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe;
   NSTRACE (windowDidResignKey);
 
-  if (dpyinfo->x_focus_frame == emacsframe)
+  if (is_focus_frame)
     dpyinfo->x_focus_frame = 0;
 
   ns_frame_rehighlight (emacsframe);
@@ -5761,10 +5762,10 @@ not_in_argv (NSString *arg)
       x_set_frame_alpha (emacsframe);
     }
 
-  if (emacs_event)
+  if (emacs_event && is_focus_frame)
     {
       [self deleteWorkingText];
-      emacs_event->kind = FOCUS_IN_EVENT;
+      emacs_event->kind = FOCUS_OUT_EVENT;
       EV_TRAILER ((id)nil);
     }
 }
index 0190478c254b949cf440ad1a9f95a5d6f60a921b..b49a7bc706bc8bc1fadf5f027cec8b00ad6a35e7 100644 (file)
@@ -172,6 +172,8 @@ enum event_kind
      `switch-frame' events in kbd_buffer_get_event, if necessary.  */
   FOCUS_IN_EVENT,
 
+  FOCUS_OUT_EVENT,
+
   /* Generated when mouse moves over window not currently selected.  */
   SELECT_WINDOW_EVENT,
 
index f1a18d3bf37a541ce34221d8c61aa26184fa1116..74e495e56454646d258cf1e11786191bfde1155c 100644 (file)
@@ -3439,9 +3439,15 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
               && CONSP (Vframe_list)
               && !NILP (XCDR (Vframe_list)))
             {
-              bufp->kind = FOCUS_IN_EVENT;
-              XSETFRAME (bufp->frame_or_window, frame);
+              bufp->arg = Qt;
             }
+          else
+            {
+              bufp->arg = Qnil;
+            }
+
+          bufp->kind = FOCUS_IN_EVENT;
+          XSETFRAME (bufp->frame_or_window, frame);
         }
 
       frame->output_data.x->focus_state |= state;
@@ -3459,6 +3465,9 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
         {
           dpyinfo->x_focus_event_frame = 0;
           x_new_focus_frame (dpyinfo, 0);
+
+          bufp->kind = FOCUS_OUT_EVENT;
+          XSETFRAME (bufp->frame_or_window, frame);
         }
 
 #ifdef HAVE_X_I18N