Commit 18c26d81 authored by Jan Djärv's avatar Jan Djärv

Stop cursor blink after blink-cursor-blinks (10), stop timers when not blinking.

* 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.
parent c7ddc792
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
......
......@@ -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.
* Editing Changes in Emacs 24.4
......
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.
......
......@@ -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
......
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).
......
......@@ -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);
......
......@@ -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);
}
/* 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.
......
......@@ -5746,9 +5746,10 @@ - (void)windowDidResignKey: (NSNotification *)notification
/* 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 @@ - (void)windowDidResignKey: (NSNotification *)notification
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);
}
}
......
......@@ -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,
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment